/
proc
/
1387184
/
task
/
1387184
/
root
/
home
/
henzagold
/
branch
/
export
/
File Upload :
llllll
Current File: //proc/1387184/task/1387184/root/home/henzagold/branch/export/14.js
((typeof self !== 'undefined' ? self : this)["webpackJsonp"] = (typeof self !== 'undefined' ? self : this)["webpackJsonp"] || []).push([[14],{ /***/ "./node_modules/@babel/runtime/helpers/esm/classCallCheck.js": /*!*******************************************************************!*\ !*** ./node_modules/@babel/runtime/helpers/esm/classCallCheck.js ***! \*******************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _classCallCheck; });\nfunction _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY2xhc3NDYWxsQ2hlY2suanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY2xhc3NDYWxsQ2hlY2suanM/ZDRlYyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7XG4gIGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTtcbiAgfVxufSJdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/classCallCheck.js\n"); /***/ }), /***/ "./node_modules/@babel/runtime/helpers/esm/createClass.js": /*!****************************************************************!*\ !*** ./node_modules/@babel/runtime/helpers/esm/createClass.js ***! \****************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _createClass; });\nfunction _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n Object.defineProperty(Constructor, \"prototype\", {\n writable: false\n });\n return Constructor;\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY3JlYXRlQ2xhc3MuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vY3JlYXRlQ2xhc3MuanM/YmVlMiJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBfZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldO1xuICAgIGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTtcbiAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7XG4gICAgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7XG4gIH1cbn1cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHtcbiAgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7XG4gIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KENvbnN0cnVjdG9yLCBcInByb3RvdHlwZVwiLCB7XG4gICAgd3JpdGFibGU6IGZhbHNlXG4gIH0pO1xuICByZXR1cm4gQ29uc3RydWN0b3I7XG59Il0sIm1hcHBpbmdzIjoiQUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/@babel/runtime/helpers/esm/createClass.js\n"); /***/ }), /***/ "./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js": /*!***************************************************************************!*\ !*** ./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js ***! \***************************************************************************/ /*! exports provided: AbstractHeaderCellCtrl, AgAbstractField, AgAngleSelect, AgCheckbox, AgColorPicker, AgDialog, AgGroupComponent, AgInputNumberField, AgInputRange, AgInputTextArea, AgInputTextField, AgMenuItemComponent, AgMenuList, AgMenuPanel, AgPanel, AgPromise, AgPromiseStatus, AgRadioButton, AgSelect, AgSlider, AgStackComponentsRegistry, AgToggleButton, AlignedGridsService, AllCommunityModules, AnimateShowChangeCellRenderer, AnimateSlideCellRenderer, AnimationFrameService, AutoScrollService, AutoWidthCalculator, Autowired, BarColumnLabelPlacement, BaseComponentWrapper, BaseCreator, BaseGridSerializingSession, Bean, BeanStub, Beans, BodyDropPivotTarget, BodyDropTarget, CHART_TOOLBAR_ALLOW_LIST, CHART_TOOL_PANEL_ALLOW_LIST, CHART_TOOL_PANEL_MENU_OPTIONS, CellComp, CellCtrl, CellNavigationService, CellPositionUtils, CellRangeType, ChangedPath, CheckboxSelectionComponent, ClientSideRowModelModule, ClientSideRowModelSteps, ColDefUtil, Color, Column, ColumnApi, ColumnFactory, ColumnGroup, ColumnKeyCreator, ColumnModel, ColumnUtils, Component, ComponentUtil, Constants, Context, CssClassApplier, CssClassManager, CsvCreator, CsvExportModule, CtrlsService, CustomTooltipFeature, DEFAULT_CHART_GROUPS, DateFilter, DisplayedGroupCreator, Downloader, DragAndDropService, DragService, DragSourceType, Environment, EventService, Events, ExcelFactoryMode, ExpressionService, FilterManager, FloatingFilterMapper, FocusService, Grid, GridApi, GridBodyComp, GridBodyCtrl, GridComp, GridCoreCreator, GridCtrl, GridHeaderComp, GridHeaderCtrl, GridOptionsWrapper, GridSerializer, GroupCellRenderer, GroupCellRendererCtrl, GroupInstanceIdCreator, HeaderCellCtrl, HeaderFilterCellComp, HeaderFilterCellCtrl, HeaderGroupCellCtrl, HeaderNavigationDirection, HeaderNavigationService, HeaderPositionUtils, HeaderRowComp, HeaderRowContainerComp, HeaderRowContainerCtrl, HeaderRowCtrl, HeaderRowType, HorizontalDirection, HorizontalResizeService, InfiniteRowModelModule, KeyCode, LargeTextCellEditor, LayoutCssClasses, Logger, LoggerFactory, ManagedFocusFeature, ModuleNames, ModuleRegistry, MouseEventService, MoveColumnFeature, NavigationService, NumberFilter, NumberSequence, Optional, PaginationProxy, PinnedRowModel, PopupComponent, PopupEditorWrapper, PopupSelectCellEditor, PopupService, PopupTextCellEditor, PositionableFeature, PostConstruct, PreConstruct, PreDestroy, PropertyKeys, ProvidedColumnGroup, ProvidedFilter, Qualifier, QuerySelector, RefSelector, ResizeObserverService, RowAnimationCssClasses, RowContainerComp, RowContainerCtrl, RowContainerName, RowContainerType, RowCtrl, RowHighlightPosition, RowNode, RowNodeBlock, RowNodeBlockLoader, RowNodeSorter, RowPositionUtils, RowRenderer, RowType, ScalarFilter, ScrollVisibleService, SelectCellEditor, SelectableService, SelectionHandleType, SelectionService, ServerSideTransactionResultStatus, SetLeftFeature, SimpleFilter, SortController, SortIndicatorComp, StandardMenuFactory, StylingService, TabGuardComp, TabGuardCtrl, TabbedLayout, TemplateService, TextCellEditor, TextFilter, TextFloatingFilter, Timer, TouchListener, UserComponentFactory, UserComponentRegistry, ValueCache, ValueFormatterService, ValueService, VanillaFrameworkOverrides, VerticalDirection, VirtualList, XmlFactory, ZipContainer, _, defaultGroupComparator, getRowContainerTypeForName, simpleHttpRequest, stringToArray */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AbstractHeaderCellCtrl\", function() { return AbstractHeaderCellCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgAbstractField\", function() { return AgAbstractField; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgAngleSelect\", function() { return AgAngleSelect; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgCheckbox\", function() { return AgCheckbox; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgColorPicker\", function() { return AgColorPicker; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgDialog\", function() { return AgDialog; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgGroupComponent\", function() { return AgGroupComponent; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgInputNumberField\", function() { return AgInputNumberField; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgInputRange\", function() { return AgInputRange; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgInputTextArea\", function() { return AgInputTextArea; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgInputTextField\", function() { return AgInputTextField; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgMenuItemComponent\", function() { return AgMenuItemComponent; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgMenuList\", function() { return AgMenuList; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgMenuPanel\", function() { return AgMenuPanel; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgPanel\", function() { return AgPanel; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgPromise\", function() { return AgPromise; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgPromiseStatus\", function() { return AgPromiseStatus; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgRadioButton\", function() { return AgRadioButton; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgSelect\", function() { return AgSelect; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgSlider\", function() { return AgSlider; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgStackComponentsRegistry\", function() { return AgStackComponentsRegistry; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgToggleButton\", function() { return AgToggleButton; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AlignedGridsService\", function() { return AlignedGridsService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AllCommunityModules\", function() { return AllCommunityModules; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AnimateShowChangeCellRenderer\", function() { return AnimateShowChangeCellRenderer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AnimateSlideCellRenderer\", function() { return AnimateSlideCellRenderer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AnimationFrameService\", function() { return AnimationFrameService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AutoScrollService\", function() { return AutoScrollService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AutoWidthCalculator\", function() { return AutoWidthCalculator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Autowired\", function() { return Autowired; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BarColumnLabelPlacement\", function() { return BarColumnLabelPlacement; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BaseComponentWrapper\", function() { return BaseComponentWrapper; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BaseCreator\", function() { return BaseCreator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BaseGridSerializingSession\", function() { return BaseGridSerializingSession; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Bean\", function() { return Bean; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BeanStub\", function() { return BeanStub; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Beans\", function() { return Beans; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BodyDropPivotTarget\", function() { return BodyDropPivotTarget; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"BodyDropTarget\", function() { return BodyDropTarget; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CHART_TOOLBAR_ALLOW_LIST\", function() { return CHART_TOOLBAR_ALLOW_LIST; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CHART_TOOL_PANEL_ALLOW_LIST\", function() { return CHART_TOOL_PANEL_ALLOW_LIST; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CHART_TOOL_PANEL_MENU_OPTIONS\", function() { return CHART_TOOL_PANEL_MENU_OPTIONS; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CellComp\", function() { return CellComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CellCtrl\", function() { return CellCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CellNavigationService\", function() { return CellNavigationService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CellPositionUtils\", function() { return CellPositionUtils; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CellRangeType\", function() { return CellRangeType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ChangedPath\", function() { return ChangedPath; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CheckboxSelectionComponent\", function() { return CheckboxSelectionComponent; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ClientSideRowModelModule\", function() { return ClientSideRowModelModule; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ClientSideRowModelSteps\", function() { return ClientSideRowModelSteps; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColDefUtil\", function() { return ColDefUtil; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Color\", function() { return Color; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Column\", function() { return Column; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColumnApi\", function() { return ColumnApi; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColumnFactory\", function() { return ColumnFactory; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColumnGroup\", function() { return ColumnGroup; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColumnKeyCreator\", function() { return ColumnKeyCreator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColumnModel\", function() { return ColumnModel; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ColumnUtils\", function() { return ColumnUtils; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Component\", function() { return Component; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ComponentUtil\", function() { return ComponentUtil; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Constants\", function() { return Constants; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Context\", function() { return Context; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CssClassApplier\", function() { return CssClassApplier; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CssClassManager\", function() { return CssClassManager; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CsvCreator\", function() { return CsvCreator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CsvExportModule\", function() { return CsvExportModule; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CtrlsService\", function() { return CtrlsService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CustomTooltipFeature\", function() { return CustomTooltipFeature; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"DEFAULT_CHART_GROUPS\", function() { return DEFAULT_CHART_GROUPS; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"DateFilter\", function() { return DateFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"DisplayedGroupCreator\", function() { return DisplayedGroupCreator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Downloader\", function() { return Downloader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"DragAndDropService\", function() { return DragAndDropService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"DragService\", function() { return DragService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"DragSourceType\", function() { return DragSourceType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Environment\", function() { return Environment; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"EventService\", function() { return EventService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Events\", function() { return Events; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ExcelFactoryMode\", function() { return ExcelFactoryMode; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ExpressionService\", function() { return ExpressionService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"FilterManager\", function() { return FilterManager; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"FloatingFilterMapper\", function() { return FloatingFilterMapper; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"FocusService\", function() { return FocusService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Grid\", function() { return Grid; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridApi\", function() { return GridApi; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridBodyComp\", function() { return GridBodyComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridBodyCtrl\", function() { return GridBodyCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridComp\", function() { return GridComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridCoreCreator\", function() { return GridCoreCreator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridCtrl\", function() { return GridCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridHeaderComp\", function() { return GridHeaderComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridHeaderCtrl\", function() { return GridHeaderCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridOptionsWrapper\", function() { return GridOptionsWrapper; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GridSerializer\", function() { return GridSerializer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GroupCellRenderer\", function() { return GroupCellRenderer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GroupCellRendererCtrl\", function() { return GroupCellRendererCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"GroupInstanceIdCreator\", function() { return GroupInstanceIdCreator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderCellCtrl\", function() { return HeaderCellCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderFilterCellComp\", function() { return HeaderFilterCellComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderFilterCellCtrl\", function() { return HeaderFilterCellCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderGroupCellCtrl\", function() { return HeaderGroupCellCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderNavigationDirection\", function() { return HeaderNavigationDirection; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderNavigationService\", function() { return HeaderNavigationService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderPositionUtils\", function() { return HeaderPositionUtils; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderRowComp\", function() { return HeaderRowComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderRowContainerComp\", function() { return HeaderRowContainerComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderRowContainerCtrl\", function() { return HeaderRowContainerCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderRowCtrl\", function() { return HeaderRowCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HeaderRowType\", function() { return HeaderRowType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HorizontalDirection\", function() { return HorizontalDirection; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"HorizontalResizeService\", function() { return HorizontalResizeService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"InfiniteRowModelModule\", function() { return InfiniteRowModelModule; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"KeyCode\", function() { return KeyCode; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"LargeTextCellEditor\", function() { return LargeTextCellEditor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"LayoutCssClasses\", function() { return LayoutCssClasses; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Logger\", function() { return Logger; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"LoggerFactory\", function() { return LoggerFactory; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ManagedFocusFeature\", function() { return ManagedFocusFeature; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ModuleNames\", function() { return ModuleNames; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ModuleRegistry\", function() { return ModuleRegistry; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MouseEventService\", function() { return MouseEventService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MoveColumnFeature\", function() { return MoveColumnFeature; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"NavigationService\", function() { return NavigationService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"NumberFilter\", function() { return NumberFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"NumberSequence\", function() { return NumberSequence; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Optional\", function() { return Optional; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PaginationProxy\", function() { return PaginationProxy; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PinnedRowModel\", function() { return PinnedRowModel; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PopupComponent\", function() { return PopupComponent; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PopupEditorWrapper\", function() { return PopupEditorWrapper; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PopupSelectCellEditor\", function() { return PopupSelectCellEditor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PopupService\", function() { return PopupService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PopupTextCellEditor\", function() { return PopupTextCellEditor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PositionableFeature\", function() { return PositionableFeature; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PostConstruct\", function() { return PostConstruct; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PreConstruct\", function() { return PreConstruct; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PreDestroy\", function() { return PreDestroy; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PropertyKeys\", function() { return PropertyKeys; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ProvidedColumnGroup\", function() { return ProvidedColumnGroup; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ProvidedFilter\", function() { return ProvidedFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Qualifier\", function() { return Qualifier; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"QuerySelector\", function() { return QuerySelector; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RefSelector\", function() { return RefSelector; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ResizeObserverService\", function() { return ResizeObserverService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowAnimationCssClasses\", function() { return RowAnimationCssClasses; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowContainerComp\", function() { return RowContainerComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowContainerCtrl\", function() { return RowContainerCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowContainerName\", function() { return RowContainerName; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowContainerType\", function() { return RowContainerType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowCtrl\", function() { return RowCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowHighlightPosition\", function() { return RowHighlightPosition; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowNode\", function() { return RowNode; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowNodeBlock\", function() { return RowNodeBlock; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowNodeBlockLoader\", function() { return RowNodeBlockLoader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowNodeSorter\", function() { return RowNodeSorter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowPositionUtils\", function() { return RowPositionUtils; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowRenderer\", function() { return RowRenderer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RowType\", function() { return RowType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ScalarFilter\", function() { return ScalarFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ScrollVisibleService\", function() { return ScrollVisibleService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SelectCellEditor\", function() { return SelectCellEditor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SelectableService\", function() { return SelectableService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SelectionHandleType\", function() { return SelectionHandleType; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SelectionService\", function() { return SelectionService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ServerSideTransactionResultStatus\", function() { return ServerSideTransactionResultStatus; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SetLeftFeature\", function() { return SetLeftFeature; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SimpleFilter\", function() { return SimpleFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SortController\", function() { return SortController; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"SortIndicatorComp\", function() { return SortIndicatorComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"StandardMenuFactory\", function() { return StandardMenuFactory; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"StylingService\", function() { return StylingService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TabGuardComp\", function() { return TabGuardComp; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TabGuardCtrl\", function() { return TabGuardCtrl; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TabbedLayout\", function() { return TabbedLayout; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TemplateService\", function() { return TemplateService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TextCellEditor\", function() { return TextCellEditor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TextFilter\", function() { return TextFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TextFloatingFilter\", function() { return TextFloatingFilter; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Timer\", function() { return Timer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"TouchListener\", function() { return TouchListener; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"UserComponentFactory\", function() { return UserComponentFactory; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"UserComponentRegistry\", function() { return UserComponentRegistry; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ValueCache\", function() { return ValueCache; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ValueFormatterService\", function() { return ValueFormatterService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ValueService\", function() { return ValueService; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VanillaFrameworkOverrides\", function() { return VanillaFrameworkOverrides; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VerticalDirection\", function() { return VerticalDirection; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VirtualList\", function() { return VirtualList; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"XmlFactory\", function() { return XmlFactory; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ZipContainer\", function() { return ZipContainer; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"_\", function() { return _; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultGroupComparator\", function() { return defaultGroupComparator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getRowContainerTypeForName\", function() { return getRowContainerTypeForName; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"simpleHttpRequest\", function() { return simpleHttpRequest; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"stringToArray\", function() { return stringToArray; });\n/**\n * @ag-grid-community/all-modules - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/**\n * If value is undefined, null or blank, returns null, otherwise returns the value\n * @param {T} value\n * @returns {T | null}\n */\nfunction makeNull(value) {\n if (value == null || value === '') {\n return null;\n }\n return value;\n}\nfunction exists(value, allowEmptyString) {\n if (allowEmptyString === void 0) { allowEmptyString = false; }\n return value != null && (value !== '' || allowEmptyString);\n}\nfunction missing(value) {\n return !exists(value);\n}\nfunction missingOrEmpty(value) {\n return value == null || value.length === 0;\n}\nfunction toStringOrNull(value) {\n return value != null && typeof value.toString === 'function' ? value.toString() : null;\n}\n// for parsing html attributes, where we want empty strings and missing attributes to be undefined\nfunction attrToNumber(value) {\n if (value === undefined) {\n // undefined or empty means ignore the value\n return;\n }\n if (value === null || value === '') {\n // null or blank means clear\n return null;\n }\n if (typeof value === 'number') {\n return isNaN(value) ? undefined : value;\n }\n var valueParsed = parseInt(value, 10);\n return isNaN(valueParsed) ? undefined : valueParsed;\n}\n// for parsing html attributes, where we want empty strings and missing attributes to be undefined\nfunction attrToBoolean(value) {\n if (value === undefined) {\n // undefined or empty means ignore the value\n return;\n }\n if (value === null || value === '') {\n // null means clear\n return false;\n }\n if (typeof value === 'boolean') {\n // if simple boolean, return the boolean\n return value;\n }\n // if equal to the string 'true' (ignoring case) then return true\n return (/true/i).test(value);\n}\n// for parsing html attributes, where we want empty strings and missing attributes to be undefined\nfunction attrToString(value) {\n if (value == null || value === '') {\n return;\n }\n return value;\n}\n/** @deprecated */\nfunction referenceCompare(left, right) {\n if (left == null && right == null) {\n return true;\n }\n if (left == null && right != null) {\n return false;\n }\n if (left != null && right == null) {\n return false;\n }\n return left === right;\n}\nfunction jsonEquals(val1, val2) {\n var val1Json = val1 ? JSON.stringify(val1) : null;\n var val2Json = val2 ? JSON.stringify(val2) : null;\n return val1Json === val2Json;\n}\nfunction defaultComparator(valueA, valueB, accentedCompare) {\n if (accentedCompare === void 0) { accentedCompare = false; }\n var valueAMissing = valueA == null;\n var valueBMissing = valueB == null;\n // this is for aggregations sum and avg, where the result can be a number that is wrapped.\n // if we didn't do this, then the toString() value would be used, which would result in\n // the strings getting used instead of the numbers.\n if (valueA && valueA.toNumber) {\n valueA = valueA.toNumber();\n }\n if (valueB && valueB.toNumber) {\n valueB = valueB.toNumber();\n }\n if (valueAMissing && valueBMissing) {\n return 0;\n }\n if (valueAMissing) {\n return -1;\n }\n if (valueBMissing) {\n return 1;\n }\n function doQuickCompare(a, b) {\n return (a > b ? 1 : (a < b ? -1 : 0));\n }\n if (typeof valueA !== 'string') {\n return doQuickCompare(valueA, valueB);\n }\n if (!accentedCompare) {\n return doQuickCompare(valueA, valueB);\n }\n try {\n // using local compare also allows chinese comparisons\n return valueA.localeCompare(valueB);\n }\n catch (e) {\n // if something wrong with localeCompare, eg not supported\n // by browser, then just continue with the quick one\n return doQuickCompare(valueA, valueB);\n }\n}\nfunction values(object) {\n if (object instanceof Set || object instanceof Map) {\n var arr_1 = [];\n object.forEach(function (value) { return arr_1.push(value); });\n return arr_1;\n }\n return Object.values(object);\n}\n\nvar GenericUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n makeNull: makeNull,\n exists: exists,\n missing: missing,\n missingOrEmpty: missingOrEmpty,\n toStringOrNull: toStringOrNull,\n attrToNumber: attrToNumber,\n attrToBoolean: attrToBoolean,\n attrToString: attrToString,\n referenceCompare: referenceCompare,\n jsonEquals: jsonEquals,\n defaultComparator: defaultComparator,\n values: values\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar ColumnKeyCreator = /** @class */ (function () {\n function ColumnKeyCreator() {\n this.existingKeys = {};\n }\n ColumnKeyCreator.prototype.addExistingKeys = function (keys) {\n for (var i = 0; i < keys.length; i++) {\n this.existingKeys[keys[i]] = true;\n }\n };\n ColumnKeyCreator.prototype.getUniqueKey = function (colId, colField) {\n // in case user passed in number for colId, convert to string\n colId = toStringOrNull(colId);\n var count = 0;\n while (true) {\n var idToTry = void 0;\n if (colId) {\n idToTry = colId;\n if (count !== 0) {\n idToTry += '_' + count;\n }\n }\n else if (colField) {\n idToTry = colField;\n if (count !== 0) {\n idToTry += '_' + count;\n }\n }\n else {\n idToTry = '' + count;\n }\n if (!this.existingKeys[idToTry]) {\n this.existingKeys[idToTry] = true;\n return idToTry;\n }\n count++;\n }\n };\n return ColumnKeyCreator;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction iterateObject(object, callback) {\n if (object == null) {\n return;\n }\n if (Array.isArray(object)) {\n object.forEach(function (value, index) { return callback(\"\" + index, value); });\n }\n else {\n Object.keys(object).forEach(function (key) { return callback(key, object[key]); });\n }\n}\nfunction cloneObject(object) {\n var copy = {};\n var keys = Object.keys(object);\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n var value = object[key];\n copy[key] = value;\n }\n return copy;\n}\nfunction deepCloneObject(object) {\n return JSON.parse(JSON.stringify(object));\n}\n// returns copy of an object, doing a deep clone of any objects with that object.\n// this is used for eg creating copies of Column Definitions, where we want to\n// deep copy all objects, but do not want to deep copy functions (eg when user provides\n// a function or class for colDef.cellRenderer)\nfunction deepCloneDefinition(object, keysToSkip) {\n if (!object) {\n return;\n }\n var obj = object;\n var res = {};\n Object.keys(obj).forEach(function (key) {\n if (keysToSkip && keysToSkip.indexOf(key) >= 0) {\n return;\n }\n var value = obj[key];\n // 'simple object' means a bunch of key/value pairs, eg {filter: 'myFilter'}. it does\n // NOT include the following:\n // 1) arrays\n // 2) functions or classes (eg ColumnAPI instance)\n var sourceIsSimpleObject = isNonNullObject(value) && value.constructor === Object;\n if (sourceIsSimpleObject) {\n res[key] = deepCloneDefinition(value);\n }\n else {\n res[key] = value;\n }\n });\n return res;\n}\nfunction getProperty(object, key) {\n return object[key];\n}\nfunction setProperty(object, key, value) {\n object[key] = value;\n}\n/**\n * Will copy the specified properties from `source` into the equivalent properties on `target`, ignoring properties with\n * a value of `undefined`.\n */\nfunction copyPropertiesIfPresent(source, target) {\n var properties = [];\n for (var _i = 2; _i < arguments.length; _i++) {\n properties[_i - 2] = arguments[_i];\n }\n properties.forEach(function (p) { return copyPropertyIfPresent(source, target, p); });\n}\n/**\n * Will copy the specified property from `source` into the equivalent property on `target`, unless the property has a\n * value of `undefined`. If a transformation is provided, it will be applied to the value before being set on `target`.\n */\nfunction copyPropertyIfPresent(source, target, property, transform) {\n var value = getProperty(source, property);\n if (value !== undefined) {\n setProperty(target, property, transform ? transform(value) : value);\n }\n}\nfunction getAllKeysInObjects(objects) {\n var allValues = {};\n objects.filter(function (obj) { return obj != null; }).forEach(function (obj) {\n Object.keys(obj).forEach(function (key) { return allValues[key] = null; });\n });\n return Object.keys(allValues);\n}\nfunction getAllValuesInObject(obj) {\n if (!obj) {\n return [];\n }\n var anyObject = Object;\n if (typeof anyObject.values === 'function') {\n return anyObject.values(obj);\n }\n var ret = [];\n for (var key in obj) {\n if (obj.hasOwnProperty(key) && obj.propertyIsEnumerable(key)) {\n ret.push(obj[key]);\n }\n }\n return ret;\n}\nfunction mergeDeep(dest, source, copyUndefined, makeCopyOfSimpleObjects) {\n if (copyUndefined === void 0) { copyUndefined = true; }\n if (makeCopyOfSimpleObjects === void 0) { makeCopyOfSimpleObjects = false; }\n if (!exists(source)) {\n return;\n }\n iterateObject(source, function (key, sourceValue) {\n var destValue = dest[key];\n if (destValue === sourceValue) {\n return;\n }\n // when creating params, we don't want to just copy objects over. otherwise merging ColDefs (eg DefaultColDef\n // and Column Types) would result in params getting shared between objects.\n // by putting an empty value into destValue first, it means we end up copying over values from\n // the source object, rather than just copying in the source object in it's entirety.\n if (makeCopyOfSimpleObjects) {\n var objectIsDueToBeCopied = destValue == null && sourceValue != null;\n if (objectIsDueToBeCopied) {\n // 'simple object' means a bunch of key/value pairs, eg {filter: 'myFilter'}, as opposed\n // to a Class instance (such as ColumnAPI instance).\n var sourceIsSimpleObject = typeof sourceValue === 'object' && sourceValue.constructor === Object;\n var dontCopy = sourceIsSimpleObject;\n if (dontCopy) {\n destValue = {};\n dest[key] = destValue;\n }\n }\n }\n if (isNonNullObject(sourceValue) && isNonNullObject(destValue) && !Array.isArray(destValue)) {\n mergeDeep(destValue, sourceValue, copyUndefined, makeCopyOfSimpleObjects);\n }\n else if (copyUndefined || sourceValue !== undefined) {\n dest[key] = sourceValue;\n }\n });\n}\nfunction missingOrEmptyObject(value) {\n return missing(value) || Object.keys(value).length === 0;\n}\nfunction get(source, expression, defaultValue) {\n if (source == null) {\n return defaultValue;\n }\n var keys = expression.split('.');\n var objectToRead = source;\n while (keys.length > 1) {\n objectToRead = objectToRead[keys.shift()];\n if (objectToRead == null) {\n return defaultValue;\n }\n }\n var value = objectToRead[keys[0]];\n return value != null ? value : defaultValue;\n}\nfunction set(target, expression, value) {\n if (target == null) {\n return;\n }\n var keys = expression.split('.');\n var objectToUpdate = target;\n while (keys.length > 1) {\n objectToUpdate = objectToUpdate[keys.shift()];\n if (objectToUpdate == null) {\n return;\n }\n }\n objectToUpdate[keys[0]] = value;\n}\nfunction deepFreeze(object) {\n Object.freeze(object);\n values(object).forEach(function (v) {\n if (isNonNullObject(v) || typeof v === 'function') {\n deepFreeze(v);\n }\n });\n return object;\n}\nfunction getValueUsingField(data, field, fieldContainsDots) {\n if (!field || !data) {\n return;\n }\n // if no '.', then it's not a deep value\n if (!fieldContainsDots) {\n return data[field];\n }\n // otherwise it is a deep value, so need to dig for it\n var fields = field.split('.');\n var currentObject = data;\n for (var i = 0; i < fields.length; i++) {\n if (currentObject == null) {\n return undefined;\n }\n currentObject = currentObject[fields[i]];\n }\n return currentObject;\n}\n// used by ColumnAPI and GridAPI to remove all references, so keeping grid in memory resulting in a\n// memory leak if user is not disposing of the GridAPI or ColumnApi references\nfunction removeAllReferences(obj, objectName) {\n Object.keys(obj).forEach(function (key) {\n var value = obj[key];\n // we want to replace all the @autowired services, which are objects. any simple types (boolean, string etc)\n // we don't care about\n if (typeof value === 'object') {\n obj[key] = undefined;\n }\n });\n var proto = Object.getPrototypeOf(obj);\n var properties = {};\n Object.keys(proto).forEach(function (key) {\n var value = proto[key];\n // leave all basic types - this is needed for GridAPI to leave the \"destroyed: boolean\" attribute alone\n if (typeof value === 'function') {\n var func = function () {\n console.warn(\"AG Grid: \" + objectName + \" function \" + key + \"() cannot be called as the grid has been destroyed.\\n Please don't call grid API functions on destroyed grids - as a matter of fact you shouldn't\\n be keeping the API reference, your application has a memory leak! Remove the API reference\\n when the grid is destroyed.\");\n };\n properties[key] = { value: func, writable: true };\n }\n });\n Object.defineProperties(obj, properties);\n}\nfunction isNonNullObject(value) {\n return typeof value === 'object' && value !== null;\n}\n\nvar ObjectUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n iterateObject: iterateObject,\n cloneObject: cloneObject,\n deepCloneObject: deepCloneObject,\n deepCloneDefinition: deepCloneDefinition,\n getProperty: getProperty,\n setProperty: setProperty,\n copyPropertiesIfPresent: copyPropertiesIfPresent,\n copyPropertyIfPresent: copyPropertyIfPresent,\n getAllKeysInObjects: getAllKeysInObjects,\n getAllValuesInObject: getAllValuesInObject,\n mergeDeep: mergeDeep,\n missingOrEmptyObject: missingOrEmptyObject,\n get: get,\n set: set,\n deepFreeze: deepFreeze,\n getValueUsingField: getValueUsingField,\n removeAllReferences: removeAllReferences,\n isNonNullObject: isNonNullObject\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar doOnceFlags = {};\n/**\n * If the key was passed before, then doesn't execute the func\n * @param {Function} func\n * @param {string} key\n */\nfunction doOnce(func, key) {\n if (doOnceFlags[key]) {\n return;\n }\n func();\n doOnceFlags[key] = true;\n}\nfunction getFunctionName(funcConstructor) {\n // for every other browser in the world\n if (funcConstructor.name) {\n return funcConstructor.name;\n }\n // for the pestilence that is ie11\n var matches = /function\\s+([^\\(]+)/.exec(funcConstructor.toString());\n return matches && matches.length === 2 ? matches[1].trim() : null;\n}\nfunction isFunction(val) {\n return !!(val && val.constructor && val.call && val.apply);\n}\nfunction executeInAWhile(funcs) {\n executeAfter(funcs, 400);\n}\nvar executeNextVMTurnFuncs = [];\nvar executeNextVMTurnPending = false;\nfunction executeNextVMTurn(func) {\n executeNextVMTurnFuncs.push(func);\n if (executeNextVMTurnPending) {\n return;\n }\n executeNextVMTurnPending = true;\n window.setTimeout(function () {\n var funcsCopy = executeNextVMTurnFuncs.slice();\n executeNextVMTurnFuncs.length = 0;\n executeNextVMTurnPending = false;\n funcsCopy.forEach(function (func) { return func(); });\n }, 0);\n}\nfunction executeAfter(funcs, milliseconds) {\n if (milliseconds === void 0) { milliseconds = 0; }\n if (funcs.length > 0) {\n window.setTimeout(function () { return funcs.forEach(function (func) { return func(); }); }, milliseconds);\n }\n}\n/**\n * from https://stackoverflow.com/questions/24004791/can-someone-explain-the-debounce-function-in-javascript\n * @param {Function} func The function to be debounced\n * @param {number} wait The time in ms to debounce\n * @param {boolean} immediate If it should run immediately or wait for the initial debounce delay\n * @return {Function} The debounced function\n */\nfunction debounce(func, wait, immediate) {\n if (immediate === void 0) { immediate = false; }\n // 'private' variable for instance\n // The returned function will be able to reference this due to closure.\n // Each call to the returned function will share this common timer.\n var timeout;\n // Calling debounce returns a new anonymous function\n return function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n // reference the context and args for the setTimeout function\n var context = this;\n // Should the function be called now? If immediate is true\n // and not already in a timeout then the answer is: Yes\n var callNow = immediate && !timeout;\n // This is the basic debounce behaviour where you can call this\n // function several times, but it will only execute once\n // [before or after imposing a delay].\n // Each time the returned function is called, the timer starts over.\n window.clearTimeout(timeout);\n // Set the new timeout\n timeout = window.setTimeout(function () {\n // Inside the timeout function, clear the timeout variable\n // which will let the next execution run when in 'immediate' mode\n timeout = null;\n // Check if the function already ran with the immediate flag\n if (!immediate) {\n // Call the original function with apply\n // apply lets you define the 'this' object as well as the arguments\n // (both captured before setTimeout)\n func.apply(context, args);\n }\n }, wait);\n // Immediate mode and no wait timer? Execute the function..\n if (callNow) {\n func.apply(context, args);\n }\n };\n}\n/**\n * @param {Function} func The function to be throttled\n * @param {number} wait The time in ms to throttle\n * @return {Function} The throttled function\n */\nfunction throttle(func, wait) {\n var previousCall = 0;\n return function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var context = this;\n var currentCall = new Date().getTime();\n if (currentCall - previousCall < wait) {\n return;\n }\n previousCall = currentCall;\n func.apply(context, args);\n };\n}\nfunction waitUntil(condition, callback, timeout, timeoutMessage) {\n if (timeout === void 0) { timeout = 100; }\n var timeStamp = new Date().getTime();\n var interval = null;\n var executed = false;\n var internalCallback = function () {\n var reachedTimeout = ((new Date().getTime()) - timeStamp) > timeout;\n if (condition() || reachedTimeout) {\n callback();\n executed = true;\n if (interval != null) {\n window.clearInterval(interval);\n interval = null;\n }\n if (reachedTimeout && timeoutMessage) {\n console.warn(timeoutMessage);\n }\n }\n };\n internalCallback();\n if (!executed) {\n interval = window.setInterval(internalCallback, 10);\n }\n}\nfunction compose() {\n var fns = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n fns[_i] = arguments[_i];\n }\n return function (arg) { return fns.reduce(function (composed, f) { return f(composed); }, arg); };\n}\nfunction callIfPresent(func) {\n if (func) {\n func();\n }\n}\nvar noop = function () { return; };\n\nvar FunctionUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n doOnce: doOnce,\n getFunctionName: getFunctionName,\n isFunction: isFunction,\n executeInAWhile: executeInAWhile,\n executeNextVMTurn: executeNextVMTurn,\n executeAfter: executeAfter,\n debounce: debounce,\n throttle: throttle,\n waitUntil: waitUntil,\n compose: compose,\n callIfPresent: callIfPresent,\n noop: noop\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar Context = /** @class */ (function () {\n function Context(params, logger) {\n this.beanWrappers = {};\n this.destroyed = false;\n if (!params || !params.beanClasses) {\n return;\n }\n this.contextParams = params;\n this.logger = logger;\n this.logger.log(\">> creating ag-Application Context\");\n this.createBeans();\n var beanInstances = this.getBeanInstances();\n this.wireBeans(beanInstances);\n this.logger.log(\">> ag-Application Context ready - component is alive\");\n }\n Context.prototype.getBeanInstances = function () {\n return values(this.beanWrappers).map(function (beanEntry) { return beanEntry.beanInstance; });\n };\n Context.prototype.createBean = function (bean, afterPreCreateCallback) {\n if (!bean) {\n throw Error(\"Can't wire to bean since it is null\");\n }\n this.wireBeans([bean], afterPreCreateCallback);\n return bean;\n };\n Context.prototype.wireBeans = function (beanInstances, afterPreCreateCallback) {\n this.autoWireBeans(beanInstances);\n this.methodWireBeans(beanInstances);\n this.callLifeCycleMethods(beanInstances, 'preConstructMethods');\n // the callback sets the attributes, so the component has access to attributes\n // before postConstruct methods in the component are executed\n if (exists(afterPreCreateCallback)) {\n beanInstances.forEach(afterPreCreateCallback);\n }\n this.callLifeCycleMethods(beanInstances, 'postConstructMethods');\n };\n Context.prototype.createBeans = function () {\n var _this = this;\n // register all normal beans\n this.contextParams.beanClasses.forEach(this.createBeanWrapper.bind(this));\n // register override beans, these will overwrite beans above of same name\n // instantiate all beans - overridden beans will be left out\n iterateObject(this.beanWrappers, function (key, beanEntry) {\n var constructorParamsMeta;\n if (beanEntry.bean.__agBeanMetaData && beanEntry.bean.__agBeanMetaData.autowireMethods && beanEntry.bean.__agBeanMetaData.autowireMethods.agConstructor) {\n constructorParamsMeta = beanEntry.bean.__agBeanMetaData.autowireMethods.agConstructor;\n }\n var constructorParams = _this.getBeansForParameters(constructorParamsMeta, beanEntry.bean.name);\n var newInstance = applyToConstructor(beanEntry.bean, constructorParams);\n beanEntry.beanInstance = newInstance;\n });\n var createdBeanNames = Object.keys(this.beanWrappers).join(', ');\n this.logger.log(\"created beans: \" + createdBeanNames);\n };\n // tslint:disable-next-line\n Context.prototype.createBeanWrapper = function (BeanClass) {\n var metaData = BeanClass.__agBeanMetaData;\n if (!metaData) {\n var beanName = void 0;\n if (BeanClass.prototype.constructor) {\n beanName = getFunctionName(BeanClass.prototype.constructor);\n }\n else {\n beanName = \"\" + BeanClass;\n }\n console.error(\"Context item \" + beanName + \" is not a bean\");\n return;\n }\n var beanEntry = {\n bean: BeanClass,\n beanInstance: null,\n beanName: metaData.beanName\n };\n this.beanWrappers[metaData.beanName] = beanEntry;\n };\n Context.prototype.autoWireBeans = function (beanInstances) {\n var _this = this;\n beanInstances.forEach(function (beanInstance) {\n _this.forEachMetaDataInHierarchy(beanInstance, function (metaData, beanName) {\n var attributes = metaData.agClassAttributes;\n if (!attributes) {\n return;\n }\n attributes.forEach(function (attribute) {\n var otherBean = _this.lookupBeanInstance(beanName, attribute.beanName, attribute.optional);\n beanInstance[attribute.attributeName] = otherBean;\n });\n });\n });\n };\n Context.prototype.methodWireBeans = function (beanInstances) {\n var _this = this;\n beanInstances.forEach(function (beanInstance) {\n _this.forEachMetaDataInHierarchy(beanInstance, function (metaData, beanName) {\n iterateObject(metaData.autowireMethods, function (methodName, wireParams) {\n // skip constructor, as this is dealt with elsewhere\n if (methodName === \"agConstructor\") {\n return;\n }\n var initParams = _this.getBeansForParameters(wireParams, beanName);\n beanInstance[methodName].apply(beanInstance, initParams);\n });\n });\n });\n };\n Context.prototype.forEachMetaDataInHierarchy = function (beanInstance, callback) {\n var prototype = Object.getPrototypeOf(beanInstance);\n while (prototype != null) {\n var constructor = prototype.constructor;\n if (constructor.hasOwnProperty('__agBeanMetaData')) {\n var metaData = constructor.__agBeanMetaData;\n var beanName = this.getBeanName(constructor);\n callback(metaData, beanName);\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n };\n Context.prototype.getBeanName = function (constructor) {\n if (constructor.__agBeanMetaData && constructor.__agBeanMetaData.beanName) {\n return constructor.__agBeanMetaData.beanName;\n }\n var constructorString = constructor.toString();\n var beanName = constructorString.substring(9, constructorString.indexOf(\"(\"));\n return beanName;\n };\n Context.prototype.getBeansForParameters = function (parameters, beanName) {\n var _this = this;\n var beansList = [];\n if (parameters) {\n iterateObject(parameters, function (paramIndex, otherBeanName) {\n var otherBean = _this.lookupBeanInstance(beanName, otherBeanName);\n beansList[Number(paramIndex)] = otherBean;\n });\n }\n return beansList;\n };\n Context.prototype.lookupBeanInstance = function (wiringBean, beanName, optional) {\n if (optional === void 0) { optional = false; }\n if (beanName === \"context\") {\n return this;\n }\n if (this.contextParams.providedBeanInstances && this.contextParams.providedBeanInstances.hasOwnProperty(beanName)) {\n return this.contextParams.providedBeanInstances[beanName];\n }\n var beanEntry = this.beanWrappers[beanName];\n if (beanEntry) {\n return beanEntry.beanInstance;\n }\n if (!optional) {\n console.error(\"AG Grid: unable to find bean reference \" + beanName + \" while initialising \" + wiringBean);\n }\n return null;\n };\n Context.prototype.callLifeCycleMethods = function (beanInstances, lifeCycleMethod) {\n var _this = this;\n beanInstances.forEach(function (beanInstance) { return _this.callLifeCycleMethodsOnBean(beanInstance, lifeCycleMethod); });\n };\n Context.prototype.callLifeCycleMethodsOnBean = function (beanInstance, lifeCycleMethod, methodToIgnore) {\n // putting all methods into a map removes duplicates\n var allMethods = {};\n // dump methods from each level of the metadata hierarchy\n this.forEachMetaDataInHierarchy(beanInstance, function (metaData) {\n var methods = metaData[lifeCycleMethod];\n if (methods) {\n methods.forEach(function (methodName) {\n if (methodName != methodToIgnore) {\n allMethods[methodName] = true;\n }\n });\n }\n });\n var allMethodsList = Object.keys(allMethods);\n allMethodsList.forEach(function (methodName) { return beanInstance[methodName](); });\n };\n Context.prototype.getBean = function (name) {\n return this.lookupBeanInstance(\"getBean\", name, true);\n };\n Context.prototype.destroy = function () {\n if (this.destroyed) {\n return;\n }\n this.logger.log(\">> Shutting down ag-Application Context\");\n var beanInstances = this.getBeanInstances();\n this.destroyBeans(beanInstances);\n this.contextParams.providedBeanInstances = null;\n this.destroyed = true;\n this.logger.log(\">> ag-Application Context shut down - component is dead\");\n };\n Context.prototype.destroyBean = function (bean) {\n if (!bean) {\n return;\n }\n this.destroyBeans([bean]);\n };\n Context.prototype.destroyBeans = function (beans) {\n var _this = this;\n if (!beans) {\n return [];\n }\n beans.forEach(function (bean) {\n _this.callLifeCycleMethodsOnBean(bean, 'preDestroyMethods', 'destroy');\n // call destroy() explicitly if it exists\n var beanAny = bean;\n if (typeof beanAny.destroy === 'function') {\n beanAny.destroy();\n }\n });\n return [];\n };\n return Context;\n}());\n// taken from: http://stackoverflow.com/questions/3362471/how-can-i-call-a-javascript-constructor-using-call-or-apply\n// allows calling 'apply' on a constructor\nfunction applyToConstructor(constructor, argArray) {\n var args = [null].concat(argArray);\n var factoryFunction = constructor.bind.apply(constructor, args);\n return new factoryFunction();\n}\nfunction PreConstruct(target, methodName, descriptor) {\n var props = getOrCreateProps$1(target.constructor);\n if (!props.preConstructMethods) {\n props.preConstructMethods = [];\n }\n props.preConstructMethods.push(methodName);\n}\nfunction PostConstruct(target, methodName, descriptor) {\n var props = getOrCreateProps$1(target.constructor);\n if (!props.postConstructMethods) {\n props.postConstructMethods = [];\n }\n props.postConstructMethods.push(methodName);\n}\nfunction PreDestroy(target, methodName, descriptor) {\n var props = getOrCreateProps$1(target.constructor);\n if (!props.preDestroyMethods) {\n props.preDestroyMethods = [];\n }\n props.preDestroyMethods.push(methodName);\n}\nfunction Bean(beanName) {\n return function (classConstructor) {\n var props = getOrCreateProps$1(classConstructor);\n props.beanName = beanName;\n };\n}\nfunction Autowired(name) {\n return function (target, propertyKey, descriptor) {\n autowiredFunc(target, name, false, target, propertyKey, null);\n };\n}\nfunction Optional(name) {\n return function (target, propertyKey, descriptor) {\n autowiredFunc(target, name, true, target, propertyKey, null);\n };\n}\nfunction autowiredFunc(target, name, optional, classPrototype, methodOrAttributeName, index) {\n if (name === null) {\n console.error(\"AG Grid: Autowired name should not be null\");\n return;\n }\n if (typeof index === \"number\") {\n console.error(\"AG Grid: Autowired should be on an attribute\");\n return;\n }\n // it's an attribute on the class\n var props = getOrCreateProps$1(target.constructor);\n if (!props.agClassAttributes) {\n props.agClassAttributes = [];\n }\n props.agClassAttributes.push({\n attributeName: methodOrAttributeName,\n beanName: name,\n optional: optional\n });\n}\nfunction Qualifier(name) {\n return function (classPrototype, methodOrAttributeName, index) {\n var constructor = typeof classPrototype == \"function\" ? classPrototype : classPrototype.constructor;\n var props;\n if (typeof index === \"number\") {\n // it's a parameter on a method\n var methodName = void 0;\n if (methodOrAttributeName) {\n props = getOrCreateProps$1(constructor);\n methodName = methodOrAttributeName;\n }\n else {\n props = getOrCreateProps$1(constructor);\n methodName = \"agConstructor\";\n }\n if (!props.autowireMethods) {\n props.autowireMethods = {};\n }\n if (!props.autowireMethods[methodName]) {\n props.autowireMethods[methodName] = {};\n }\n props.autowireMethods[methodName][index] = name;\n }\n };\n}\nfunction getOrCreateProps$1(target) {\n if (!target.hasOwnProperty(\"__agBeanMetaData\")) {\n target.__agBeanMetaData = {};\n }\n return target.__agBeanMetaData;\n}\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __assign$i = (undefined && undefined.__assign) || function () {\n __assign$i = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$i.apply(this, arguments);\n};\nvar __decorate$2A = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$a = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar EventService = /** @class */ (function () {\n function EventService() {\n this.allSyncListeners = new Map();\n this.allAsyncListeners = new Map();\n this.globalSyncListeners = new Set();\n this.globalAsyncListeners = new Set();\n this.asyncFunctionsQueue = [];\n this.scheduled = false;\n // using an object performs better than a Set for the number of different events we have\n this.firedEvents = {};\n }\n // because this class is used both inside the context and outside the context, we do not\n // use autowired attributes, as that would be confusing, as sometimes the attributes\n // would be wired, and sometimes not.\n //\n // the global event servers used by AG Grid is autowired by the context once, and this\n // setBeans method gets called once.\n //\n // the times when this class is used outside of the context (eg RowNode has an instance of this\n // class) then it is not a bean, and this setBeans method is not called.\n EventService.prototype.setBeans = function (loggerFactory, gridOptionsWrapper, frameworkOverrides, globalEventListener) {\n if (globalEventListener === void 0) { globalEventListener = null; }\n this.frameworkOverrides = frameworkOverrides;\n this.gridOptionsWrapper = gridOptionsWrapper;\n if (globalEventListener) {\n var async = gridOptionsWrapper.useAsyncEvents();\n this.addGlobalListener(globalEventListener, async);\n }\n };\n EventService.prototype.getListeners = function (eventType, async, autoCreateListenerCollection) {\n var listenerMap = async ? this.allAsyncListeners : this.allSyncListeners;\n var listeners = listenerMap.get(eventType);\n // Note: 'autoCreateListenerCollection' should only be 'true' if a listener is about to be added. For instance\n // getListeners() is also called during event dispatch even though no listeners are added. This measure protects\n // against 'memory bloat' as empty collections will prevent the RowNode's event service from being removed after\n // the RowComp is destroyed, see noRegisteredListenersExist() below.\n if (!listeners && autoCreateListenerCollection) {\n listeners = new Set();\n listenerMap.set(eventType, listeners);\n }\n return listeners;\n };\n EventService.prototype.noRegisteredListenersExist = function () {\n return this.allSyncListeners.size === 0 && this.allAsyncListeners.size === 0 &&\n this.globalSyncListeners.size === 0 && this.globalAsyncListeners.size === 0;\n };\n EventService.prototype.addEventListener = function (eventType, listener, async) {\n if (async === void 0) { async = false; }\n this.getListeners(eventType, async, true).add(listener);\n };\n EventService.prototype.removeEventListener = function (eventType, listener, async) {\n if (async === void 0) { async = false; }\n var listeners = this.getListeners(eventType, async, false);\n if (!listeners) {\n return;\n }\n listeners.delete(listener);\n if (listeners.size === 0) {\n var listenerMap = async ? this.allAsyncListeners : this.allSyncListeners;\n listenerMap.delete(eventType);\n }\n };\n EventService.prototype.addGlobalListener = function (listener, async) {\n if (async === void 0) { async = false; }\n (async ? this.globalAsyncListeners : this.globalSyncListeners).add(listener);\n };\n EventService.prototype.removeGlobalListener = function (listener, async) {\n if (async === void 0) { async = false; }\n (async ? this.globalAsyncListeners : this.globalSyncListeners).delete(listener);\n };\n EventService.prototype.dispatchEvent = function (event) {\n var agEvent = event;\n if (this.gridOptionsWrapper) {\n // Apply common properties to all dispatched events if this event service has had its beans set with gridOptionsWrapper.\n // Note there are multiple instances of EventService that are used local to components which do not set gridOptionsWrapper. \n agEvent = __assign$i(__assign$i({}, event), { api: this.gridOptionsWrapper.getApi(), columnApi: this.gridOptionsWrapper.getColumnApi(), context: this.gridOptionsWrapper.getContext() });\n }\n this.dispatchToListeners(agEvent, true);\n this.dispatchToListeners(agEvent, false);\n this.firedEvents[agEvent.type] = true;\n };\n EventService.prototype.dispatchEventOnce = function (event) {\n if (!this.firedEvents[event.type]) {\n this.dispatchEvent(event);\n }\n };\n EventService.prototype.dispatchToListeners = function (event, async) {\n var _this = this;\n var eventType = event.type;\n var processEventListeners = function (listeners) { return listeners.forEach(function (listener) {\n if (async) {\n _this.dispatchAsync(function () { return listener(event); });\n }\n else {\n listener(event);\n }\n }); };\n var listeners = this.getListeners(eventType, async, false);\n if (listeners) {\n processEventListeners(listeners);\n }\n var globalListeners = async ? this.globalAsyncListeners : this.globalSyncListeners;\n globalListeners.forEach(function (listener) {\n if (async) {\n _this.dispatchAsync(function () { return _this.frameworkOverrides.dispatchEvent(eventType, function () { return listener(eventType, event); }, true); });\n }\n else {\n _this.frameworkOverrides.dispatchEvent(eventType, function () { return listener(eventType, event); }, true);\n }\n });\n };\n // this gets called inside the grid's thread, for each event that it\n // wants to set async. the grid then batches the events into one setTimeout()\n // because setTimeout() is an expensive operation. ideally we would have\n // each event in it's own setTimeout(), but we batch for performance.\n EventService.prototype.dispatchAsync = function (func) {\n // add to the queue for executing later in the next VM turn\n this.asyncFunctionsQueue.push(func);\n // check if timeout is already scheduled. the first time the grid calls\n // this within it's thread turn, this should be false, so it will schedule\n // the 'flush queue' method the first time it comes here. then the flag is\n // set to 'true' so it will know it's already scheduled for subsequent calls.\n if (!this.scheduled) {\n // if not scheduled, schedule one\n window.setTimeout(this.flushAsyncQueue.bind(this), 0);\n // mark that it is scheduled\n this.scheduled = true;\n }\n };\n // this happens in the next VM turn only, and empties the queue of events\n EventService.prototype.flushAsyncQueue = function () {\n this.scheduled = false;\n // we take a copy, because the event listener could be using\n // the grid, which would cause more events, which would be potentially\n // added to the queue, so safe to take a copy, the new events will\n // get executed in a later VM turn rather than risk updating the\n // queue as we are flushing it.\n var queueCopy = this.asyncFunctionsQueue.slice();\n this.asyncFunctionsQueue = [];\n // execute the queue\n queueCopy.forEach(function (func) { return func(); });\n };\n __decorate$2A([\n __param$a(0, Qualifier('loggerFactory')),\n __param$a(1, Qualifier('gridOptionsWrapper')),\n __param$a(2, Qualifier('frameworkOverrides')),\n __param$a(3, Qualifier('globalEventListener'))\n ], EventService.prototype, \"setBeans\", null);\n EventService = __decorate$2A([\n Bean('eventService')\n ], EventService);\n return EventService;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar Constants = /** @class */ (function () {\n function Constants() {\n }\n Constants.ROW_BUFFER_SIZE = 10;\n Constants.LAYOUT_INTERVAL = 500;\n Constants.BATCH_WAIT_MILLIS = 50;\n Constants.EXPORT_TYPE_DRAG_COPY = 'dragCopy';\n Constants.EXPORT_TYPE_CLIPBOARD = 'clipboard';\n Constants.EXPORT_TYPE_EXCEL = 'excel';\n Constants.EXPORT_TYPE_CSV = 'csv';\n Constants.ROW_MODEL_TYPE_INFINITE = 'infinite';\n Constants.ROW_MODEL_TYPE_VIEWPORT = 'viewport';\n Constants.ROW_MODEL_TYPE_CLIENT_SIDE = 'clientSide';\n Constants.ROW_MODEL_TYPE_SERVER_SIDE = 'serverSide';\n Constants.ALWAYS = 'always';\n Constants.ONLY_WHEN_GROUPING = 'onlyWhenGrouping';\n Constants.PINNED_TOP = 'top';\n Constants.PINNED_BOTTOM = 'bottom';\n Constants.DOM_LAYOUT_NORMAL = 'normal';\n Constants.DOM_LAYOUT_PRINT = 'print';\n Constants.DOM_LAYOUT_AUTO_HEIGHT = 'autoHeight';\n Constants.GROUP_AUTO_COLUMN_ID = 'ag-Grid-AutoColumn';\n Constants.SOURCE_PASTE = 'paste';\n Constants.PINNED_RIGHT = 'right';\n Constants.PINNED_LEFT = 'left';\n Constants.SORT_ASC = 'asc';\n Constants.SORT_DESC = 'desc';\n Constants.INPUT_SELECTOR = 'input, select, button, textarea';\n Constants.FOCUSABLE_SELECTOR = '[tabindex], input, select, button, textarea';\n Constants.FOCUSABLE_EXCLUDE = '.ag-hidden, .ag-hidden *, [disabled], .ag-disabled, .ag-disabled *';\n return Constants;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar ModuleNames;\n(function (ModuleNames) {\n // when using modules, user references this\n ModuleNames[\"CommunityCoreModule\"] = \"@ag-grid-community/core\";\n // when not using modules, user references this\n ModuleNames[\"CommunityAllModules\"] = \"@ag-grid-community/all\";\n // community modules\n ModuleNames[\"InfiniteRowModelModule\"] = \"@ag-grid-community/infinite-row-model\";\n ModuleNames[\"ClientSideRowModelModule\"] = \"@ag-grid-community/client-side-row-model\";\n ModuleNames[\"CsvExportModule\"] = \"@ag-grid-community/csv-export\";\n // enterprise core - users never import on this, but other enterprise modules do\n ModuleNames[\"EnterpriseCoreModule\"] = \"@ag-grid-enterprise/core\";\n // when not using modules, user references this\n ModuleNames[\"EnterpriseAllModules\"] = \"@ag-grid-enterprise/all\";\n // enterprise modules\n ModuleNames[\"RowGroupingModule\"] = \"@ag-grid-enterprise/row-grouping\";\n ModuleNames[\"ColumnToolPanelModule\"] = \"@ag-grid-enterprise/column-tool-panel\";\n ModuleNames[\"FiltersToolPanelModule\"] = \"@ag-grid-enterprise/filter-tool-panel\";\n ModuleNames[\"MenuModule\"] = \"@ag-grid-enterprise/menu\";\n ModuleNames[\"SetFilterModule\"] = \"@ag-grid-enterprise/set-filter\";\n ModuleNames[\"MultiFilterModule\"] = \"@ag-grid-enterprise/multi-filter\";\n ModuleNames[\"StatusBarModule\"] = \"@ag-grid-enterprise/status-bar\";\n ModuleNames[\"SideBarModule\"] = \"@ag-grid-enterprise/side-bar\";\n ModuleNames[\"RangeSelectionModule\"] = \"@ag-grid-enterprise/range-selection\";\n ModuleNames[\"MasterDetailModule\"] = \"@ag-grid-enterprise/master-detail\";\n ModuleNames[\"RichSelectModule\"] = \"@ag-grid-enterprise/rich-select\";\n ModuleNames[\"GridChartsModule\"] = \"@ag-grid-enterprise/charts\";\n ModuleNames[\"ViewportRowModelModule\"] = \"@ag-grid-enterprise/viewport-row-model\";\n ModuleNames[\"ServerSideRowModelModule\"] = \"@ag-grid-enterprise/server-side-row-model\";\n ModuleNames[\"ExcelExportModule\"] = \"@ag-grid-enterprise/excel-export\";\n ModuleNames[\"ClipboardModule\"] = \"@ag-grid-enterprise/clipboard\";\n ModuleNames[\"SparklinesModule\"] = \"@ag-grid-enterprise/sparklines\";\n // framework wrappers currently don't provide beans, comps etc, so no need to be modules,\n // however i argue they should be as in theory they 'could' provide beans etc\n ModuleNames[\"AngularModule\"] = \"@ag-grid-community/angular\";\n ModuleNames[\"ReactModule\"] = \"@ag-grid-community/react\";\n ModuleNames[\"VueModule\"] = \"@ag-grid-community/vue\";\n ModuleNames[\"PolymerModule\"] = \"@ag-grid-community/polymer\";\n // and then this, which is definitely not a grid module, as it should not have any dependency\n // on the grid (ie shouldn't even reference the Module interface)\n // ChartsModule = \"@ag-grid-community/charts-core\",\n})(ModuleNames || (ModuleNames = {}));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar ModuleRegistry = /** @class */ (function () {\n function ModuleRegistry() {\n }\n ModuleRegistry.register = function (module, moduleBased) {\n if (moduleBased === void 0) { moduleBased = true; }\n ModuleRegistry.modulesMap[module.moduleName] = module;\n if (ModuleRegistry.moduleBased === undefined) {\n ModuleRegistry.moduleBased = moduleBased;\n }\n else {\n if (ModuleRegistry.moduleBased !== moduleBased) {\n doOnce(function () {\n console.warn(\"AG Grid: You are mixing modules (i.e. @ag-grid-community/core) and packages (ag-grid-community) - you can only use one or the other of these mechanisms.\");\n console.warn('Please see https://www.ag-grid.com/javascript-grid/packages-modules/ for more information.');\n }, 'ModulePackageCheck');\n }\n }\n };\n // noinspection JSUnusedGlobalSymbols\n ModuleRegistry.registerModules = function (modules, moduleBased) {\n if (moduleBased === void 0) { moduleBased = true; }\n if (!modules) {\n return;\n }\n modules.forEach(function (module) { return ModuleRegistry.register(module, moduleBased); });\n };\n ModuleRegistry.assertRegistered = function (moduleName, reason) {\n if (this.isRegistered(moduleName)) {\n return true;\n }\n var warningKey = reason + moduleName;\n var warningMessage;\n if (ModuleRegistry.moduleBased) {\n warningMessage = \"AG Grid: unable to use \" + reason + \" as module \" + moduleName + \" is not present. Please see: https://www.ag-grid.com/javascript-grid/modules/\";\n }\n else {\n warningMessage = \"AG Grid: unable to use \" + reason + \" as package 'ag-grid-enterprise' is not present. Please see: https://www.ag-grid.com/javascript-grid/packages/\";\n }\n doOnce(function () {\n console.warn(warningMessage);\n }, warningKey);\n return false;\n };\n ModuleRegistry.isRegistered = function (moduleName) {\n return !!ModuleRegistry.modulesMap[moduleName];\n };\n ModuleRegistry.getRegisteredModules = function () {\n return values(ModuleRegistry.modulesMap);\n };\n ModuleRegistry.isPackageBased = function () {\n return !ModuleRegistry.moduleBased;\n };\n // having in a map a) removes duplicates and b) allows fast lookup\n ModuleRegistry.modulesMap = {};\n return ModuleRegistry;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$2z = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar instanceIdSequence$4 = 0;\n// Wrapper around a user provide column definition. The grid treats the column definition as ready only.\n// This class contains all the runtime information about a column, plus some logic (the definition has no logic).\n// This class implements both interfaces ColumnGroupChild and ProvidedColumnGroupChild as the class can\n// appear as a child of either the original tree or the displayed tree. However the relevant group classes\n// for each type only implements one, as each group can only appear in it's associated tree (eg ProvidedColumnGroup\n// can only appear in OriginalColumn tree).\nvar Column = /** @class */ (function () {\n function Column(colDef, userProvidedColDef, colId, primary) {\n // used by React (and possibly other frameworks) as key for rendering\n this.instanceId = instanceIdSequence$4++;\n // The measured height of this column's header when autoHeaderHeight is enabled\n this.autoHeaderHeight = null;\n this.moving = false;\n this.menuVisible = false;\n this.filterActive = false;\n this.eventService = new EventService();\n this.rowGroupActive = false;\n this.pivotActive = false;\n this.aggregationActive = false;\n this.colDef = colDef;\n this.userProvidedColDef = userProvidedColDef;\n this.colId = colId;\n this.primary = primary;\n this.setState(colDef);\n }\n Column.prototype.getInstanceId = function () {\n return this.instanceId;\n };\n Column.prototype.setState = function (colDef) {\n // sort\n if (colDef.sort !== undefined) {\n if (colDef.sort === Constants.SORT_ASC || colDef.sort === Constants.SORT_DESC) {\n this.sort = colDef.sort;\n }\n }\n else {\n if (colDef.initialSort === Constants.SORT_ASC || colDef.initialSort === Constants.SORT_DESC) {\n this.sort = colDef.initialSort;\n }\n }\n // sortIndex\n var sortIndex = attrToNumber(colDef.sortIndex);\n var initialSortIndex = attrToNumber(colDef.initialSortIndex);\n if (sortIndex !== undefined) {\n if (sortIndex !== null) {\n this.sortIndex = sortIndex;\n }\n }\n else {\n if (initialSortIndex !== null) {\n this.sortIndex = initialSortIndex;\n }\n }\n // hide\n var hide = attrToBoolean(colDef.hide);\n var initialHide = attrToBoolean(colDef.initialHide);\n if (hide !== undefined) {\n this.visible = !hide;\n }\n else {\n this.visible = !initialHide;\n }\n // pinned\n if (colDef.pinned !== undefined) {\n this.setPinned(colDef.pinned);\n }\n else {\n this.setPinned(colDef.initialPinned);\n }\n // flex\n var flex = attrToNumber(colDef.flex);\n var initialFlex = attrToNumber(colDef.initialFlex);\n if (flex !== undefined) {\n this.flex = flex;\n }\n else if (initialFlex !== undefined) {\n this.flex = initialFlex;\n }\n };\n // gets called when user provides an alternative colDef, eg\n Column.prototype.setColDef = function (colDef, userProvidedColDef) {\n this.colDef = colDef;\n this.userProvidedColDef = userProvidedColDef;\n this.initMinAndMaxWidths();\n this.initDotNotation();\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_COL_DEF_CHANGED, \"api\"));\n };\n /**\n * Returns the column definition provided by the application.\n * This may not be correct, as items can be superseded by default column options.\n * However it's useful for comparison, eg to know which application column definition matches that column.\n */\n Column.prototype.getUserProvidedColDef = function () {\n return this.userProvidedColDef;\n };\n Column.prototype.setParent = function (parent) {\n this.parent = parent;\n };\n /** Returns the parent column group, if column grouping is active. */\n Column.prototype.getParent = function () {\n return this.parent;\n };\n Column.prototype.setOriginalParent = function (originalParent) {\n this.originalParent = originalParent;\n };\n Column.prototype.getOriginalParent = function () {\n return this.originalParent;\n };\n // this is done after constructor as it uses gridOptionsWrapper\n Column.prototype.initialise = function () {\n this.initMinAndMaxWidths();\n this.resetActualWidth('gridInitializing');\n this.initDotNotation();\n this.validate();\n };\n Column.prototype.initDotNotation = function () {\n var suppressDotNotation = this.gridOptionsWrapper.isSuppressFieldDotNotation();\n this.fieldContainsDots = exists(this.colDef.field) && this.colDef.field.indexOf('.') >= 0 && !suppressDotNotation;\n this.tooltipFieldContainsDots = exists(this.colDef.tooltipField) && this.colDef.tooltipField.indexOf('.') >= 0 && !suppressDotNotation;\n };\n Column.prototype.initMinAndMaxWidths = function () {\n var colDef = this.colDef;\n this.minWidth = this.columnUtils.calculateColMinWidth(colDef);\n this.maxWidth = this.columnUtils.calculateColMaxWidth(colDef);\n };\n Column.prototype.resetActualWidth = function (source) {\n if (source === void 0) { source = 'api'; }\n var initialWidth = this.columnUtils.calculateColInitialWidth(this.colDef);\n this.setActualWidth(initialWidth, source, true);\n };\n Column.prototype.isEmptyGroup = function () {\n return false;\n };\n Column.prototype.isRowGroupDisplayed = function (colId) {\n if (missing(this.colDef) || missing(this.colDef.showRowGroup)) {\n return false;\n }\n var showingAllGroups = this.colDef.showRowGroup === true;\n var showingThisGroup = this.colDef.showRowGroup === colId;\n return showingAllGroups || showingThisGroup;\n };\n /** Returns `true` if column is a primary column, `false` if secondary. Secondary columns are used for pivoting. */\n Column.prototype.isPrimary = function () {\n return this.primary;\n };\n /** Returns `true` if column filtering is allowed. */\n Column.prototype.isFilterAllowed = function () {\n // filter defined means it's a string, class or true.\n // if its false, null or undefined then it's false.\n var filterDefined = !!this.colDef.filter || !!this.colDef.filterFramework;\n return filterDefined;\n };\n Column.prototype.isFieldContainsDots = function () {\n return this.fieldContainsDots;\n };\n Column.prototype.isTooltipFieldContainsDots = function () {\n return this.tooltipFieldContainsDots;\n };\n Column.prototype.validate = function () {\n var colDefAny = this.colDef;\n function warnOnce(msg, key, obj) {\n doOnce(function () {\n if (obj) {\n console.warn(msg, obj);\n }\n else {\n doOnce(function () { return console.warn(msg); }, key);\n }\n }, key);\n }\n var usingCSRM = this.gridOptionsWrapper.isRowModelDefault();\n if (usingCSRM && !ModuleRegistry.isRegistered(ModuleNames.RowGroupingModule)) {\n var rowGroupingItems = ['enableRowGroup', 'rowGroup', 'rowGroupIndex', 'enablePivot', 'enableValue', 'pivot', 'pivotIndex', 'aggFunc'];\n rowGroupingItems.forEach(function (item) {\n if (exists(colDefAny[item])) {\n if (ModuleRegistry.isPackageBased()) {\n warnOnce(\"AG Grid: \" + item + \" is only valid in ag-grid-enterprise, your column definition should not have \" + item, 'ColumnRowGroupingMissing' + item);\n }\n else {\n warnOnce(\"AG Grid: \" + item + \" is only valid with AG Grid Enterprise Module \" + ModuleNames.RowGroupingModule + \" - your column definition should not have \" + item, 'ColumnRowGroupingMissing' + item);\n }\n }\n });\n }\n if (!ModuleRegistry.isRegistered(ModuleNames.RichSelectModule)) {\n if (this.colDef.cellEditor === 'agRichSelect' || this.colDef.cellEditor === 'agRichSelectCellEditor') {\n if (ModuleRegistry.isPackageBased()) {\n warnOnce(\"AG Grid: \" + this.colDef.cellEditor + \" can only be used with ag-grid-enterprise\", 'ColumnRichSelectMissing');\n }\n else {\n warnOnce(\"AG Grid: \" + this.colDef.cellEditor + \" can only be used with AG Grid Enterprise Module \" + ModuleNames.RichSelectModule, 'ColumnRichSelectMissing');\n }\n }\n }\n if (this.gridOptionsWrapper.isTreeData()) {\n var itemsNotAllowedWithTreeData = ['rowGroup', 'rowGroupIndex', 'pivot', 'pivotIndex'];\n itemsNotAllowedWithTreeData.forEach(function (item) {\n if (exists(colDefAny[item])) {\n warnOnce(\"AG Grid: \" + item + \" is not possible when doing tree data, your column definition should not have \" + item, 'TreeDataCannotRowGroup');\n }\n });\n }\n if (exists(this.colDef.width) && typeof this.colDef.width !== 'number') {\n warnOnce('AG Grid: colDef.width should be a number, not ' + typeof this.colDef.width, 'ColumnCheck_asdfawef');\n }\n if (colDefAny.pinnedRowCellRenderer) {\n warnOnce('AG Grid: pinnedRowCellRenderer no longer exists, use cellRendererSelector if you want a different Cell Renderer for pinned rows. Check params.node.rowPinned. This was an unfortunate (but necessary) change we had to do to allow future plans we have of re-skinng the data grid in frameworks such as React, Angular and Vue. See https://www.ag-grid.com/javascript-grid/cell-rendering/#many-renderers-one-column', 'colDef.pinnedRowCellRenderer-deprecated');\n }\n if (colDefAny.pinnedRowCellRendererParams) {\n warnOnce('AG Grid: pinnedRowCellRenderer no longer exists, use cellRendererSelector if you want a different Cell Renderer for pinned rows. Check params.node.rowPinned. This was an unfortunate (but necessary) change we had to do to allow future plans we have of re-skinng the data grid in frameworks such as React, Angular and Vue. See https://www.ag-grid.com/javascript-grid/cell-rendering/#many-renderers-one-column', 'colDef.pinnedRowCellRenderer-deprecated');\n }\n if (colDefAny.pinnedRowCellRendererFramework) {\n warnOnce('AG Grid: pinnedRowCellRenderer no longer exists, use cellRendererSelector if you want a different Cell Renderer for pinned rows. Check params.node.rowPinned. This was an unfortunate (but necessary) change we had to do to allow future plans we have of re-skinng the data grid in frameworks such as React, Angular and Vue. See https://www.ag-grid.com/javascript-grid/cell-rendering/#many-renderers-one-column', 'colDef.pinnedRowCellRenderer-deprecated');\n }\n if (colDefAny.pinnedRowValueGetter) {\n warnOnce('AG Grid: pinnedRowCellRenderer is deprecated, use cellRendererSelector if you want a different Cell Renderer for pinned rows. Check params.node.rowPinned. This was an unfortunate (but necessary) change we had to do to allow future plans we have of re-skinng the data grid in frameworks such as React, Angular and Vue.', 'colDef.pinnedRowCellRenderer-deprecated');\n }\n };\n /** Add an event listener to the column. */\n Column.prototype.addEventListener = function (eventType, listener) {\n this.eventService.addEventListener(eventType, listener);\n };\n /** Remove event listener from the column. */\n Column.prototype.removeEventListener = function (eventType, listener) {\n this.eventService.removeEventListener(eventType, listener);\n };\n Column.prototype.createColumnFunctionCallbackParams = function (rowNode) {\n return {\n node: rowNode,\n data: rowNode.data,\n column: this,\n colDef: this.colDef,\n context: this.gridOptionsWrapper.getContext(),\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi()\n };\n };\n Column.prototype.isSuppressNavigable = function (rowNode) {\n // if boolean set, then just use it\n if (typeof this.colDef.suppressNavigable === 'boolean') {\n return this.colDef.suppressNavigable;\n }\n // if function, then call the function to find out\n if (typeof this.colDef.suppressNavigable === 'function') {\n var params = this.createColumnFunctionCallbackParams(rowNode);\n var userFunc = this.colDef.suppressNavigable;\n return userFunc(params);\n }\n return false;\n };\n Column.prototype.isCellEditable = function (rowNode) {\n // only allow editing of groups if the user has this option enabled\n if (rowNode.group && !this.gridOptionsWrapper.isEnableGroupEdit()) {\n return false;\n }\n return this.isColumnFunc(rowNode, this.colDef.editable);\n };\n Column.prototype.isSuppressFillHandle = function () {\n return !!attrToBoolean(this.colDef.suppressFillHandle);\n };\n Column.prototype.isAutoHeight = function () {\n return !!attrToBoolean(this.colDef.autoHeight);\n };\n Column.prototype.isAutoHeaderHeight = function () {\n return !!attrToBoolean(this.colDef.autoHeaderHeight);\n };\n Column.prototype.isRowDrag = function (rowNode) {\n return this.isColumnFunc(rowNode, this.colDef.rowDrag);\n };\n Column.prototype.isDndSource = function (rowNode) {\n return this.isColumnFunc(rowNode, this.colDef.dndSource);\n };\n Column.prototype.isCellCheckboxSelection = function (rowNode) {\n return this.isColumnFunc(rowNode, this.colDef.checkboxSelection);\n };\n Column.prototype.isSuppressPaste = function (rowNode) {\n return this.isColumnFunc(rowNode, this.colDef ? this.colDef.suppressPaste : null);\n };\n Column.prototype.isResizable = function () {\n return !!attrToBoolean(this.colDef.resizable);\n };\n Column.prototype.isColumnFunc = function (rowNode, value) {\n // if boolean set, then just use it\n if (typeof value === 'boolean') {\n return value;\n }\n // if function, then call the function to find out\n if (typeof value === 'function') {\n var params = this.createColumnFunctionCallbackParams(rowNode);\n var editableFunc = value;\n return editableFunc(params);\n }\n return false;\n };\n Column.prototype.setMoving = function (moving, source) {\n if (source === void 0) { source = \"api\"; }\n this.moving = moving;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_MOVING_CHANGED, source));\n };\n Column.prototype.createColumnEvent = function (type, source) {\n return {\n type: type,\n column: this,\n columns: [this],\n source: source,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n };\n Column.prototype.isMoving = function () {\n return this.moving;\n };\n /** If sorting is active, returns the sort direction e.g. `'asc'` or `'desc'`. */\n Column.prototype.getSort = function () {\n return this.sort;\n };\n Column.prototype.setSort = function (sort, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.sort !== sort) {\n this.sort = sort;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_SORT_CHANGED, source));\n }\n };\n Column.prototype.setMenuVisible = function (visible, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.menuVisible !== visible) {\n this.menuVisible = visible;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_MENU_VISIBLE_CHANGED, source));\n }\n };\n Column.prototype.isMenuVisible = function () {\n return this.menuVisible;\n };\n Column.prototype.isSortAscending = function () {\n return this.sort === Constants.SORT_ASC;\n };\n Column.prototype.isSortDescending = function () {\n return this.sort === Constants.SORT_DESC;\n };\n Column.prototype.isSortNone = function () {\n return missing(this.sort);\n };\n Column.prototype.isSorting = function () {\n return exists(this.sort);\n };\n Column.prototype.getSortIndex = function () {\n return this.sortIndex;\n };\n Column.prototype.setSortIndex = function (sortOrder) {\n this.sortIndex = sortOrder;\n };\n Column.prototype.setAggFunc = function (aggFunc) {\n this.aggFunc = aggFunc;\n };\n /** If aggregation is set for the column, returns the aggregation function. */\n Column.prototype.getAggFunc = function () {\n return this.aggFunc;\n };\n Column.prototype.getLeft = function () {\n return this.left;\n };\n Column.prototype.getOldLeft = function () {\n return this.oldLeft;\n };\n Column.prototype.getRight = function () {\n return this.left + this.actualWidth;\n };\n Column.prototype.setLeft = function (left, source) {\n if (source === void 0) { source = \"api\"; }\n this.oldLeft = this.left;\n if (this.left !== left) {\n this.left = left;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_LEFT_CHANGED, source));\n }\n };\n /** Returns `true` if filter is active on the column. */\n Column.prototype.isFilterActive = function () {\n return this.filterActive;\n };\n // additionalEventAttributes is used by provided simple floating filter, so it can add 'floatingFilter=true' to the event\n Column.prototype.setFilterActive = function (active, source, additionalEventAttributes) {\n if (source === void 0) { source = \"api\"; }\n if (this.filterActive !== active) {\n this.filterActive = active;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_FILTER_ACTIVE_CHANGED, source));\n }\n var filterChangedEvent = this.createColumnEvent(Column.EVENT_FILTER_CHANGED, source);\n if (additionalEventAttributes) {\n mergeDeep(filterChangedEvent, additionalEventAttributes);\n }\n this.eventService.dispatchEvent(filterChangedEvent);\n };\n Column.prototype.setPinned = function (pinned) {\n if (pinned === true || pinned === Constants.PINNED_LEFT) {\n this.pinned = Constants.PINNED_LEFT;\n }\n else if (pinned === Constants.PINNED_RIGHT) {\n this.pinned = Constants.PINNED_RIGHT;\n }\n else {\n this.pinned = null;\n }\n };\n Column.prototype.setFirstRightPinned = function (firstRightPinned, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.firstRightPinned !== firstRightPinned) {\n this.firstRightPinned = firstRightPinned;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_FIRST_RIGHT_PINNED_CHANGED, source));\n }\n };\n Column.prototype.setLastLeftPinned = function (lastLeftPinned, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.lastLeftPinned !== lastLeftPinned) {\n this.lastLeftPinned = lastLeftPinned;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_LAST_LEFT_PINNED_CHANGED, source));\n }\n };\n Column.prototype.isFirstRightPinned = function () {\n return this.firstRightPinned;\n };\n Column.prototype.isLastLeftPinned = function () {\n return this.lastLeftPinned;\n };\n Column.prototype.isPinned = function () {\n return this.pinned === Constants.PINNED_LEFT || this.pinned === Constants.PINNED_RIGHT;\n };\n Column.prototype.isPinnedLeft = function () {\n return this.pinned === Constants.PINNED_LEFT;\n };\n Column.prototype.isPinnedRight = function () {\n return this.pinned === Constants.PINNED_RIGHT;\n };\n Column.prototype.getPinned = function () {\n return this.pinned;\n };\n Column.prototype.setVisible = function (visible, source) {\n if (source === void 0) { source = \"api\"; }\n var newValue = visible === true;\n if (this.visible !== newValue) {\n this.visible = newValue;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_VISIBLE_CHANGED, source));\n }\n };\n Column.prototype.isVisible = function () {\n return this.visible;\n };\n /** Returns the column definition for this column.\n * The column definition will be the result of merging the application provided column definition with any provided defaults\n * (e.g. `defaultColDef` grid option, or column types.\n *\n * Equivalent: `getDefinition` */\n Column.prototype.getColDef = function () {\n return this.colDef;\n };\n Column.prototype.getColumnGroupShow = function () {\n return this.colDef.columnGroupShow;\n };\n /**\n * Returns the unique ID for the column.\n *\n * Equivalent: `getId`, `getUniqueId` */\n Column.prototype.getColId = function () {\n return this.colId;\n };\n /**\n * Returns the unique ID for the column.\n *\n * Equivalent: `getColId`, `getUniqueId` */\n Column.prototype.getId = function () {\n return this.getColId();\n };\n /**\n * Returns the unique ID for the column.\n *\n * Equivalent: `getColId`, `getId` */\n Column.prototype.getUniqueId = function () {\n return this.getId();\n };\n Column.prototype.getDefinition = function () {\n return this.colDef;\n };\n /** Returns the current width of the column. If the column is resized, the actual width is the new size. */\n Column.prototype.getActualWidth = function () {\n return this.actualWidth;\n };\n Column.prototype.getAutoHeaderHeight = function () {\n return this.autoHeaderHeight;\n };\n /** Returns true if the header height has changed */\n Column.prototype.setAutoHeaderHeight = function (height) {\n var changed = height !== this.autoHeaderHeight;\n this.autoHeaderHeight = height;\n return changed;\n };\n Column.prototype.createBaseColDefParams = function (rowNode) {\n var params = {\n node: rowNode,\n data: rowNode.data,\n colDef: this.colDef,\n column: this,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n return params;\n };\n Column.prototype.getColSpan = function (rowNode) {\n if (missing(this.colDef.colSpan)) {\n return 1;\n }\n var params = this.createBaseColDefParams(rowNode);\n var colSpan = this.colDef.colSpan(params);\n // colSpan must be number equal to or greater than 1\n return Math.max(colSpan, 1);\n };\n Column.prototype.getRowSpan = function (rowNode) {\n if (missing(this.colDef.rowSpan)) {\n return 1;\n }\n var params = this.createBaseColDefParams(rowNode);\n var rowSpan = this.colDef.rowSpan(params);\n // rowSpan must be number equal to or greater than 1\n return Math.max(rowSpan, 1);\n };\n Column.prototype.setActualWidth = function (actualWidth, source, silent) {\n if (source === void 0) { source = \"api\"; }\n if (silent === void 0) { silent = false; }\n if (this.minWidth != null) {\n actualWidth = Math.max(actualWidth, this.minWidth);\n }\n if (this.maxWidth != null) {\n actualWidth = Math.min(actualWidth, this.maxWidth);\n }\n if (this.actualWidth !== actualWidth) {\n // disable flex for this column if it was manually resized.\n this.actualWidth = actualWidth;\n if (this.flex && source !== 'flex' && source !== 'gridInitializing') {\n this.flex = null;\n }\n if (!silent) {\n this.fireColumnWidthChangedEvent(source);\n }\n }\n };\n Column.prototype.fireColumnWidthChangedEvent = function (source) {\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_WIDTH_CHANGED, source));\n };\n Column.prototype.isGreaterThanMax = function (width) {\n if (this.maxWidth != null) {\n return width > this.maxWidth;\n }\n return false;\n };\n Column.prototype.getMinWidth = function () {\n return this.minWidth;\n };\n Column.prototype.getMaxWidth = function () {\n return this.maxWidth;\n };\n Column.prototype.getFlex = function () {\n return this.flex || 0;\n };\n // this method should only be used by the columnModel to\n // change flex when required by the setColumnState method.\n Column.prototype.setFlex = function (flex) {\n if (this.flex !== flex) {\n this.flex = flex;\n }\n };\n Column.prototype.setMinimum = function (source) {\n if (source === void 0) { source = \"api\"; }\n if (exists(this.minWidth)) {\n this.setActualWidth(this.minWidth, source);\n }\n };\n Column.prototype.setRowGroupActive = function (rowGroup, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.rowGroupActive !== rowGroup) {\n this.rowGroupActive = rowGroup;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_ROW_GROUP_CHANGED, source));\n }\n };\n /** Returns `true` if row group is currently active for this column. */\n Column.prototype.isRowGroupActive = function () {\n return this.rowGroupActive;\n };\n Column.prototype.setPivotActive = function (pivot, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.pivotActive !== pivot) {\n this.pivotActive = pivot;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_PIVOT_CHANGED, source));\n }\n };\n /** Returns `true` if pivot is currently active for this column. */\n Column.prototype.isPivotActive = function () {\n return this.pivotActive;\n };\n Column.prototype.isAnyFunctionActive = function () {\n return this.isPivotActive() || this.isRowGroupActive() || this.isValueActive();\n };\n Column.prototype.isAnyFunctionAllowed = function () {\n return this.isAllowPivot() || this.isAllowRowGroup() || this.isAllowValue();\n };\n Column.prototype.setValueActive = function (value, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.aggregationActive !== value) {\n this.aggregationActive = value;\n this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_VALUE_CHANGED, source));\n }\n };\n /** Returns `true` if value (aggregation) is currently active for this column. */\n Column.prototype.isValueActive = function () {\n return this.aggregationActive;\n };\n Column.prototype.isAllowPivot = function () {\n return this.colDef.enablePivot === true;\n };\n Column.prototype.isAllowValue = function () {\n return this.colDef.enableValue === true;\n };\n Column.prototype.isAllowRowGroup = function () {\n return this.colDef.enableRowGroup === true;\n };\n Column.prototype.getMenuTabs = function (defaultValues) {\n var menuTabs = this.getColDef().menuTabs;\n if (menuTabs == null) {\n menuTabs = defaultValues;\n }\n return menuTabs;\n };\n // this used to be needed, as previous version of ag-grid had lockPosition as column state,\n // so couldn't depend on colDef version.\n Column.prototype.isLockPosition = function () {\n console.warn('AG Grid: since v21, col.isLockPosition() should not be used, please use col.getColDef().lockPosition instead.');\n return this.colDef ? !!this.colDef.lockPosition : false;\n };\n // this used to be needed, as previous version of ag-grid had lockVisible as column state,\n // so couldn't depend on colDef version.\n Column.prototype.isLockVisible = function () {\n console.warn('AG Grid: since v21, col.isLockVisible() should not be used, please use col.getColDef().lockVisible instead.');\n return this.colDef ? !!this.colDef.lockVisible : false;\n };\n // this used to be needed, as previous version of ag-grid had lockPinned as column state,\n // so couldn't depend on colDef version.\n Column.prototype.isLockPinned = function () {\n console.warn('AG Grid: since v21, col.isLockPinned() should not be used, please use col.getColDef().lockPinned instead.');\n return this.colDef ? !!this.colDef.lockPinned : false;\n };\n // + renderedHeaderCell - for making header cell transparent when moving\n Column.EVENT_MOVING_CHANGED = 'movingChanged';\n // + renderedCell - changing left position\n Column.EVENT_LEFT_CHANGED = 'leftChanged';\n // + renderedCell - changing width\n Column.EVENT_WIDTH_CHANGED = 'widthChanged';\n // + renderedCell - for changing pinned classes\n Column.EVENT_LAST_LEFT_PINNED_CHANGED = 'lastLeftPinnedChanged';\n Column.EVENT_FIRST_RIGHT_PINNED_CHANGED = 'firstRightPinnedChanged';\n // + renderedColumn - for changing visibility icon\n Column.EVENT_VISIBLE_CHANGED = 'visibleChanged';\n // + every time the filter changes, used in the floating filters\n Column.EVENT_FILTER_CHANGED = 'filterChanged';\n // + renderedHeaderCell - marks the header with filter icon\n Column.EVENT_FILTER_ACTIVE_CHANGED = 'filterActiveChanged';\n // + renderedHeaderCell - marks the header with sort icon\n Column.EVENT_SORT_CHANGED = 'sortChanged';\n // + renderedHeaderCell - marks the header with sort icon\n Column.EVENT_COL_DEF_CHANGED = 'colDefChanged';\n Column.EVENT_MENU_VISIBLE_CHANGED = 'menuVisibleChanged';\n // + toolpanel, for gui updates\n Column.EVENT_ROW_GROUP_CHANGED = 'columnRowGroupChanged';\n // + toolpanel, for gui updates\n Column.EVENT_PIVOT_CHANGED = 'columnPivotChanged';\n // + toolpanel, for gui updates\n Column.EVENT_VALUE_CHANGED = 'columnValueChanged';\n __decorate$2z([\n Autowired('gridOptionsWrapper')\n ], Column.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$2z([\n Autowired('columnUtils')\n ], Column.prototype, \"columnUtils\", void 0);\n __decorate$2z([\n PostConstruct\n ], Column.prototype, \"initialise\", null);\n return Column;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction firstExistingValue() {\n var values = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n values[_i] = arguments[_i];\n }\n for (var i = 0; i < values.length; i++) {\n var value = values[i];\n if (exists(value)) {\n return value;\n }\n }\n return null;\n}\nfunction existsAndNotEmpty(value) {\n return value != null && value.length > 0;\n}\nfunction last(arr) {\n if (!arr || !arr.length) {\n return;\n }\n return arr[arr.length - 1];\n}\nfunction areEqual(a, b, comparator) {\n if (a == null && b == null) {\n return true;\n }\n return a != null &&\n b != null &&\n a.length === b.length &&\n a.every(function (value, index) { return comparator ? comparator(value, b[index]) : b[index] === value; });\n}\n/** @deprecated */\nfunction compareArrays(array1, array2) {\n return areEqual(array1, array2);\n}\n/** @deprecated */\nfunction shallowCompare(arr1, arr2) {\n return areEqual(arr1, arr2);\n}\nfunction sortNumerically(array) {\n return array.sort(function (a, b) { return a - b; });\n}\nfunction removeRepeatsFromArray(array, object) {\n if (!array) {\n return;\n }\n for (var index = array.length - 2; index >= 0; index--) {\n var thisOneMatches = array[index] === object;\n var nextOneMatches = array[index + 1] === object;\n if (thisOneMatches && nextOneMatches) {\n array.splice(index + 1, 1);\n }\n }\n}\nfunction removeFromArray(array, object) {\n var index = array.indexOf(object);\n if (index >= 0) {\n array.splice(index, 1);\n }\n}\nfunction removeAllFromArray(array, toRemove) {\n toRemove.forEach(function (item) { return removeFromArray(array, item); });\n}\nfunction insertIntoArray(array, object, toIndex) {\n array.splice(toIndex, 0, object);\n}\nfunction insertArrayIntoArray(dest, src, toIndex) {\n if (dest == null || src == null) {\n return;\n }\n // put items in backwards, otherwise inserted items end up in reverse order\n for (var i = src.length - 1; i >= 0; i--) {\n var item = src[i];\n insertIntoArray(dest, item, toIndex);\n }\n}\nfunction moveInArray(array, objectsToMove, toIndex) {\n // first take out items from the array\n removeAllFromArray(array, objectsToMove);\n // now add the objects, in same order as provided to us, that means we start at the end\n // as the objects will be pushed to the right as they are inserted\n objectsToMove.slice().reverse().forEach(function (obj) { return insertIntoArray(array, obj, toIndex); });\n}\nfunction includes(array, value) {\n return array.indexOf(value) > -1;\n}\nfunction flatten(arrayOfArrays) {\n return [].concat.apply([], arrayOfArrays);\n}\nfunction pushAll(target, source) {\n if (source == null || target == null) {\n return;\n }\n source.forEach(function (value) { return target.push(value); });\n}\nfunction toStrings(array) {\n return array.map(toStringOrNull);\n}\nfunction forEachReverse(list, action) {\n if (list == null) {\n return;\n }\n for (var i = list.length - 1; i >= 0; i--) {\n action(list[i], i);\n }\n}\n\nvar ArrayUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n firstExistingValue: firstExistingValue,\n existsAndNotEmpty: existsAndNotEmpty,\n last: last,\n areEqual: areEqual,\n compareArrays: compareArrays,\n shallowCompare: shallowCompare,\n sortNumerically: sortNumerically,\n removeRepeatsFromArray: removeRepeatsFromArray,\n removeFromArray: removeFromArray,\n removeAllFromArray: removeAllFromArray,\n insertIntoArray: insertIntoArray,\n insertArrayIntoArray: insertArrayIntoArray,\n moveInArray: moveInArray,\n includes: includes,\n flatten: flatten,\n pushAll: pushAll,\n toStrings: toStrings,\n forEachReverse: forEachReverse\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$2y = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ColumnGroup = /** @class */ (function () {\n function ColumnGroup(providedColumnGroup, groupId, instanceId, pinned) {\n // depends on the open/closed state of the group, only displaying columns are stored here\n this.displayedChildren = [];\n this.localEventService = new EventService();\n this.groupId = groupId;\n this.instanceId = instanceId;\n this.providedColumnGroup = providedColumnGroup;\n this.pinned = pinned;\n }\n // this is static, a it is used outside of this class\n ColumnGroup.createUniqueId = function (groupId, instanceId) {\n return groupId + '_' + instanceId;\n };\n // as the user is adding and removing columns, the groups are recalculated.\n // this reset clears out all children, ready for children to be added again\n ColumnGroup.prototype.reset = function () {\n this.parent = null;\n this.children = null;\n this.displayedChildren = null;\n };\n ColumnGroup.prototype.getParent = function () {\n return this.parent;\n };\n ColumnGroup.prototype.setParent = function (parent) {\n this.parent = parent;\n };\n ColumnGroup.prototype.getUniqueId = function () {\n return ColumnGroup.createUniqueId(this.groupId, this.instanceId);\n };\n ColumnGroup.prototype.isEmptyGroup = function () {\n return this.displayedChildren.length === 0;\n };\n ColumnGroup.prototype.isMoving = function () {\n var allLeafColumns = this.getProvidedColumnGroup().getLeafColumns();\n if (!allLeafColumns || allLeafColumns.length === 0) {\n return false;\n }\n return allLeafColumns.every(function (col) { return col.isMoving(); });\n };\n ColumnGroup.prototype.checkLeft = function () {\n // first get all children to setLeft, as it impacts our decision below\n this.displayedChildren.forEach(function (child) {\n if (child instanceof ColumnGroup) {\n child.checkLeft();\n }\n });\n // set our left based on first displayed column\n if (this.displayedChildren.length > 0) {\n if (this.gridOptionsWrapper.isEnableRtl()) {\n var lastChild = last(this.displayedChildren);\n var lastChildLeft = lastChild.getLeft();\n this.setLeft(lastChildLeft);\n }\n else {\n var firstChildLeft = this.displayedChildren[0].getLeft();\n this.setLeft(firstChildLeft);\n }\n }\n else {\n // this should never happen, as if we have no displayed columns, then\n // this groups should not even exist.\n this.setLeft(null);\n }\n };\n ColumnGroup.prototype.getLeft = function () {\n return this.left;\n };\n ColumnGroup.prototype.getOldLeft = function () {\n return this.oldLeft;\n };\n ColumnGroup.prototype.setLeft = function (left) {\n this.oldLeft = left;\n if (this.left !== left) {\n this.left = left;\n this.localEventService.dispatchEvent(this.createAgEvent(ColumnGroup.EVENT_LEFT_CHANGED));\n }\n };\n ColumnGroup.prototype.getPinned = function () {\n return this.pinned;\n };\n ColumnGroup.prototype.createAgEvent = function (type) {\n return { type: type };\n };\n ColumnGroup.prototype.addEventListener = function (eventType, listener) {\n this.localEventService.addEventListener(eventType, listener);\n };\n ColumnGroup.prototype.removeEventListener = function (eventType, listener) {\n this.localEventService.removeEventListener(eventType, listener);\n };\n ColumnGroup.prototype.getGroupId = function () {\n return this.groupId;\n };\n ColumnGroup.prototype.getInstanceId = function () {\n return this.instanceId;\n };\n ColumnGroup.prototype.isChildInThisGroupDeepSearch = function (wantedChild) {\n var result = false;\n this.children.forEach(function (foundChild) {\n if (wantedChild === foundChild) {\n result = true;\n }\n if (foundChild instanceof ColumnGroup) {\n if (foundChild.isChildInThisGroupDeepSearch(wantedChild)) {\n result = true;\n }\n }\n });\n return result;\n };\n ColumnGroup.prototype.getActualWidth = function () {\n var groupActualWidth = 0;\n if (this.displayedChildren) {\n this.displayedChildren.forEach(function (child) {\n groupActualWidth += child.getActualWidth();\n });\n }\n return groupActualWidth;\n };\n ColumnGroup.prototype.isResizable = function () {\n if (!this.displayedChildren) {\n return false;\n }\n // if at least one child is resizable, then the group is resizable\n var result = false;\n this.displayedChildren.forEach(function (child) {\n if (child.isResizable()) {\n result = true;\n }\n });\n return result;\n };\n ColumnGroup.prototype.getMinWidth = function () {\n var result = 0;\n this.displayedChildren.forEach(function (groupChild) {\n result += groupChild.getMinWidth() || 0;\n });\n return result;\n };\n ColumnGroup.prototype.addChild = function (child) {\n if (!this.children) {\n this.children = [];\n }\n this.children.push(child);\n };\n ColumnGroup.prototype.getDisplayedChildren = function () {\n return this.displayedChildren;\n };\n ColumnGroup.prototype.getLeafColumns = function () {\n var result = [];\n this.addLeafColumns(result);\n return result;\n };\n ColumnGroup.prototype.getDisplayedLeafColumns = function () {\n var result = [];\n this.addDisplayedLeafColumns(result);\n return result;\n };\n // why two methods here doing the same thing?\n ColumnGroup.prototype.getDefinition = function () {\n return this.providedColumnGroup.getColGroupDef();\n };\n ColumnGroup.prototype.getColGroupDef = function () {\n return this.providedColumnGroup.getColGroupDef();\n };\n ColumnGroup.prototype.isPadding = function () {\n return this.providedColumnGroup.isPadding();\n };\n ColumnGroup.prototype.isExpandable = function () {\n return this.providedColumnGroup.isExpandable();\n };\n ColumnGroup.prototype.isExpanded = function () {\n return this.providedColumnGroup.isExpanded();\n };\n ColumnGroup.prototype.setExpanded = function (expanded) {\n this.providedColumnGroup.setExpanded(expanded);\n };\n ColumnGroup.prototype.addDisplayedLeafColumns = function (leafColumns) {\n this.displayedChildren.forEach(function (child) {\n if (child instanceof Column) {\n leafColumns.push(child);\n }\n else if (child instanceof ColumnGroup) {\n child.addDisplayedLeafColumns(leafColumns);\n }\n });\n };\n ColumnGroup.prototype.addLeafColumns = function (leafColumns) {\n this.children.forEach(function (child) {\n if (child instanceof Column) {\n leafColumns.push(child);\n }\n else if (child instanceof ColumnGroup) {\n child.addLeafColumns(leafColumns);\n }\n });\n };\n ColumnGroup.prototype.getChildren = function () {\n return this.children;\n };\n ColumnGroup.prototype.getColumnGroupShow = function () {\n return this.providedColumnGroup.getColumnGroupShow();\n };\n ColumnGroup.prototype.getProvidedColumnGroup = function () {\n return this.providedColumnGroup;\n };\n /** @deprecated getOriginalColumnGroup is deprecated, use getOriginalColumnGroup. */\n ColumnGroup.prototype.getOriginalColumnGroup = function () {\n console.warn('AG Grid: columnGroup.getOriginalColumnGroup() is deprecated due to a method rename, use columnGroup.getProvidedColumnGroup() instead');\n return this.getProvidedColumnGroup();\n };\n ColumnGroup.prototype.getPaddingLevel = function () {\n var parent = this.getParent();\n if (!this.isPadding() || !parent || !parent.isPadding()) {\n return 0;\n }\n return 1 + parent.getPaddingLevel();\n };\n ColumnGroup.prototype.calculateDisplayedColumns = function () {\n var _this = this;\n // clear out last time we calculated\n this.displayedChildren = [];\n // find the column group that is controlling expandable. this is relevant when we have padding (empty)\n // groups, where the expandable is actually the first parent that is not a padding group.\n var parentWithExpansion = this;\n while (parentWithExpansion != null && parentWithExpansion.isPadding()) {\n parentWithExpansion = parentWithExpansion.getParent();\n }\n var isExpandable = parentWithExpansion ? parentWithExpansion.providedColumnGroup.isExpandable() : false;\n // it not expandable, everything is visible\n if (!isExpandable) {\n this.displayedChildren = this.children;\n this.localEventService.dispatchEvent(this.createAgEvent(ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED));\n return;\n }\n // Add cols based on columnGroupShow\n // Note - the below also adds padding groups, these are always added because they never have\n // colDef.columnGroupShow set.\n this.children.forEach(function (child) {\n // never add empty groups\n var emptyGroup = child instanceof ColumnGroup && (!child.displayedChildren || !child.displayedChildren.length);\n if (emptyGroup) {\n return;\n }\n var headerGroupShow = child.getColumnGroupShow();\n switch (headerGroupShow) {\n case ColumnGroup.HEADER_GROUP_SHOW_OPEN:\n // when set to open, only show col if group is open\n if (parentWithExpansion.providedColumnGroup.isExpanded()) {\n _this.displayedChildren.push(child);\n }\n break;\n case ColumnGroup.HEADER_GROUP_SHOW_CLOSED:\n // when set to open, only show col if group is open\n if (!parentWithExpansion.providedColumnGroup.isExpanded()) {\n _this.displayedChildren.push(child);\n }\n break;\n default:\n _this.displayedChildren.push(child);\n break;\n }\n });\n this.localEventService.dispatchEvent(this.createAgEvent(ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED));\n };\n ColumnGroup.HEADER_GROUP_SHOW_OPEN = 'open';\n ColumnGroup.HEADER_GROUP_SHOW_CLOSED = 'closed';\n ColumnGroup.EVENT_LEFT_CHANGED = 'leftChanged';\n ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED = 'displayedChildrenChanged';\n __decorate$2y([\n Autowired('gridOptionsWrapper')\n ], ColumnGroup.prototype, \"gridOptionsWrapper\", void 0);\n return ColumnGroup;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar ProvidedColumnGroup = /** @class */ (function () {\n function ProvidedColumnGroup(colGroupDef, groupId, padding, level) {\n this.localEventService = new EventService();\n this.expandable = false;\n this.colGroupDef = colGroupDef;\n this.groupId = groupId;\n this.expanded = !!colGroupDef && !!colGroupDef.openByDefault;\n this.padding = padding;\n this.level = level;\n }\n ProvidedColumnGroup.prototype.setOriginalParent = function (originalParent) {\n this.originalParent = originalParent;\n };\n ProvidedColumnGroup.prototype.getOriginalParent = function () {\n return this.originalParent;\n };\n ProvidedColumnGroup.prototype.getLevel = function () {\n return this.level;\n };\n ProvidedColumnGroup.prototype.isVisible = function () {\n // return true if at least one child is visible\n if (this.children) {\n return this.children.some(function (child) { return child.isVisible(); });\n }\n return false;\n };\n ProvidedColumnGroup.prototype.isPadding = function () {\n return this.padding;\n };\n ProvidedColumnGroup.prototype.setExpanded = function (expanded) {\n this.expanded = expanded === undefined ? false : expanded;\n var event = {\n type: ProvidedColumnGroup.EVENT_EXPANDED_CHANGED\n };\n this.localEventService.dispatchEvent(event);\n };\n ProvidedColumnGroup.prototype.isExpandable = function () {\n return this.expandable;\n };\n ProvidedColumnGroup.prototype.isExpanded = function () {\n return this.expanded;\n };\n ProvidedColumnGroup.prototype.getGroupId = function () {\n return this.groupId;\n };\n ProvidedColumnGroup.prototype.getId = function () {\n return this.getGroupId();\n };\n ProvidedColumnGroup.prototype.setChildren = function (children) {\n this.children = children;\n };\n ProvidedColumnGroup.prototype.getChildren = function () {\n return this.children;\n };\n ProvidedColumnGroup.prototype.getColGroupDef = function () {\n return this.colGroupDef;\n };\n ProvidedColumnGroup.prototype.getLeafColumns = function () {\n var result = [];\n this.addLeafColumns(result);\n return result;\n };\n ProvidedColumnGroup.prototype.addLeafColumns = function (leafColumns) {\n if (!this.children) {\n return;\n }\n this.children.forEach(function (child) {\n if (child instanceof Column) {\n leafColumns.push(child);\n }\n else if (child instanceof ProvidedColumnGroup) {\n child.addLeafColumns(leafColumns);\n }\n });\n };\n ProvidedColumnGroup.prototype.getColumnGroupShow = function () {\n var colGroupDef = this.colGroupDef;\n if (!colGroupDef) {\n return;\n }\n return colGroupDef.columnGroupShow;\n };\n // need to check that this group has at least one col showing when both expanded and contracted.\n // if not, then we don't allow expanding and contracting on this group\n ProvidedColumnGroup.prototype.setupExpandable = function () {\n var _this = this;\n this.setExpandable();\n // note - we should be removing this event listener\n this.getLeafColumns().forEach(function (col) { return col.addEventListener(Column.EVENT_VISIBLE_CHANGED, _this.onColumnVisibilityChanged.bind(_this)); });\n };\n ProvidedColumnGroup.prototype.setExpandable = function () {\n if (this.isPadding()) {\n return;\n }\n // want to make sure the group doesn't disappear when it's open\n var atLeastOneShowingWhenOpen = false;\n // want to make sure the group doesn't disappear when it's closed\n var atLeastOneShowingWhenClosed = false;\n // want to make sure the group has something to show / hide\n var atLeastOneChangeable = false;\n var children = this.findChildrenRemovingPadding();\n for (var i = 0, j = children.length; i < j; i++) {\n var abstractColumn = children[i];\n if (!abstractColumn.isVisible()) {\n continue;\n }\n // if the abstractColumn is a grid generated group, there will be no colDef\n var headerGroupShow = abstractColumn.getColumnGroupShow();\n if (headerGroupShow === ColumnGroup.HEADER_GROUP_SHOW_OPEN) {\n atLeastOneShowingWhenOpen = true;\n atLeastOneChangeable = true;\n }\n else if (headerGroupShow === ColumnGroup.HEADER_GROUP_SHOW_CLOSED) {\n atLeastOneShowingWhenClosed = true;\n atLeastOneChangeable = true;\n }\n else {\n atLeastOneShowingWhenOpen = true;\n atLeastOneShowingWhenClosed = true;\n }\n }\n var expandable = atLeastOneShowingWhenOpen && atLeastOneShowingWhenClosed && atLeastOneChangeable;\n if (this.expandable !== expandable) {\n this.expandable = expandable;\n var event_1 = {\n type: ProvidedColumnGroup.EVENT_EXPANDABLE_CHANGED\n };\n this.localEventService.dispatchEvent(event_1);\n }\n };\n ProvidedColumnGroup.prototype.findChildrenRemovingPadding = function () {\n var res = [];\n var process = function (items) {\n items.forEach(function (item) {\n // if padding, we add this children instead of the padding\n var skipBecausePadding = item instanceof ProvidedColumnGroup && item.isPadding();\n if (skipBecausePadding) {\n process(item.children);\n }\n else {\n res.push(item);\n }\n });\n };\n process(this.children);\n return res;\n };\n ProvidedColumnGroup.prototype.onColumnVisibilityChanged = function () {\n this.setExpandable();\n };\n ProvidedColumnGroup.prototype.addEventListener = function (eventType, listener) {\n this.localEventService.addEventListener(eventType, listener);\n };\n ProvidedColumnGroup.prototype.removeEventListener = function (eventType, listener) {\n this.localEventService.removeEventListener(eventType, listener);\n };\n ProvidedColumnGroup.EVENT_EXPANDED_CHANGED = 'expandedChanged';\n ProvidedColumnGroup.EVENT_EXPANDABLE_CHANGED = 'expandableChanged';\n return ProvidedColumnGroup;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar DefaultColumnTypes = {\n numericColumn: {\n headerClass: 'ag-right-aligned-header',\n cellClass: 'ag-right-aligned-cell'\n },\n rightAligned: {\n headerClass: 'ag-right-aligned-header',\n cellClass: 'ag-right-aligned-cell'\n }\n};\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar AG_GRID_STOP_PROPAGATION = '__ag_Grid_Stop_Propagation';\nvar PASSIVE_EVENTS$1 = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\nvar supports = {};\n/**\n * a user once raised an issue - they said that when you opened a popup (eg context menu)\n * and then clicked on a selection checkbox, the popup wasn't closed. this is because the\n * popup listens for clicks on the body, however ag-grid WAS stopping propagation on the\n * checkbox clicks (so the rows didn't pick them up as row selection selection clicks).\n * to get around this, we have a pattern to stop propagation for the purposes of AG Grid,\n * but we still let the event pass back to the body.\n * @param {Event} event\n */\nfunction stopPropagationForAgGrid(event) {\n event[AG_GRID_STOP_PROPAGATION] = true;\n}\nfunction isStopPropagationForAgGrid(event) {\n return event[AG_GRID_STOP_PROPAGATION] === true;\n}\nvar isEventSupported = (function () {\n var tags = {\n select: 'input',\n change: 'input',\n submit: 'form',\n reset: 'form',\n error: 'img',\n load: 'img',\n abort: 'img'\n };\n var eventChecker = function (eventName) {\n if (typeof supports[eventName] === 'boolean') {\n return supports[eventName];\n }\n var el = document.createElement(tags[eventName] || 'div');\n eventName = 'on' + eventName;\n return supports[eventName] = (eventName in el);\n };\n return eventChecker;\n})();\nfunction getCtrlForEvent(gridOptionsWrapper, event, type) {\n var sourceElement = event.target;\n while (sourceElement) {\n var renderedComp = gridOptionsWrapper.getDomData(sourceElement, type);\n if (renderedComp) {\n return renderedComp;\n }\n sourceElement = sourceElement.parentElement;\n }\n return null;\n}\n/**\n * @deprecated\n * Adds all type of change listeners to an element, intended to be a text field\n * @param {HTMLElement} element\n * @param {EventListener} listener\n */\nfunction addChangeListener(element, listener) {\n element.addEventListener('changed', listener);\n element.addEventListener('paste', listener);\n element.addEventListener('input', listener);\n}\nfunction isElementInEventPath(element, event) {\n if (!event || !element) {\n return false;\n }\n return getEventPath(event).indexOf(element) >= 0;\n}\nfunction createEventPath(event) {\n var res = [];\n var pointer = event.target;\n while (pointer) {\n res.push(pointer);\n pointer = pointer.parentElement;\n }\n return res;\n}\n/**\n * firefox doesn't have event.path set, or any alternative to it, so we hack\n * it in. this is needed as it's to late to work out the path when the item is\n * removed from the dom. used by MouseEventService, where it works out if a click\n * was from the current grid, or a detail grid (master / detail).\n * @param {Event} event\n */\nfunction addAgGridEventPath(event) {\n event.__agGridEventPath = getEventPath(event);\n}\n/**\n * Gets the path for an Event.\n * https://stackoverflow.com/questions/39245488/event-path-undefined-with-firefox-and-vue-js\n * https://developer.mozilla.org/en-US/docs/Web/API/Event\n * @param {Event} event\n * @returns {EventTarget[]}\n */\nfunction getEventPath(event) {\n var eventNoType = event;\n if (eventNoType.path) {\n // Chrome supports path\n return eventNoType.path;\n }\n if (eventNoType.composedPath) {\n // Firefox supports composePath\n return eventNoType.composedPath();\n }\n if (eventNoType.__agGridEventPath) {\n // Firefox supports composePath\n return eventNoType.__agGridEventPath;\n }\n // and finally, if none of the above worked,\n // we create the path ourselves\n return createEventPath(event);\n}\nfunction addSafePassiveEventListener(frameworkOverrides, eElement, event, listener) {\n var isPassive = includes(PASSIVE_EVENTS$1, event);\n var options = isPassive ? { passive: true } : undefined;\n // this check is here for certain scenarios where I believe the user must be destroying\n // the grid somehow but continuing for it to be used\n if (frameworkOverrides && frameworkOverrides.addEventListener) {\n frameworkOverrides.addEventListener(eElement, event, listener, options);\n }\n}\n\nvar EventUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n stopPropagationForAgGrid: stopPropagationForAgGrid,\n isStopPropagationForAgGrid: isStopPropagationForAgGrid,\n isEventSupported: isEventSupported,\n getCtrlForEvent: getCtrlForEvent,\n addChangeListener: addChangeListener,\n isElementInEventPath: isElementInEventPath,\n createEventPath: createEventPath,\n addAgGridEventPath: addAgGridEventPath,\n getEventPath: getEventPath,\n addSafePassiveEventListener: addSafePassiveEventListener\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$2x = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar BeanStub = /** @class */ (function () {\n function BeanStub() {\n var _this = this;\n this.destroyFunctions = [];\n this.destroyed = false;\n // for vue 3 - prevents Vue from trying to make this (and obviously any sub classes) from being reactive\n // prevents vue from creating proxies for created objects and prevents identity related issues\n this.__v_skip = true;\n this.isAlive = function () { return !_this.destroyed; };\n }\n // this was a test constructor niall built, when active, it prints after 5 seconds all beans/components that are\n // not destroyed. to use, create a new grid, then api.destroy() before 5 seconds. then anything that gets printed\n // points to a bean or component that was not properly disposed of.\n // constructor() {\n // setTimeout(()=> {\n // if (this.isAlive()) {\n // let prototype: any = Object.getPrototypeOf(this);\n // const constructor: any = prototype.constructor;\n // const constructorString = constructor.toString();\n // const beanName = constructorString.substring(9, constructorString.indexOf(\"(\"));\n // console.log('is alive ' + beanName);\n // }\n // }, 5000);\n // }\n // CellComp and GridComp and override this because they get the FrameworkOverrides from the Beans bean\n BeanStub.prototype.getFrameworkOverrides = function () {\n return this.frameworkOverrides;\n };\n BeanStub.prototype.getContext = function () {\n return this.context;\n };\n BeanStub.prototype.destroy = function () {\n // let prototype: any = Object.getPrototypeOf(this);\n // const constructor: any = prototype.constructor;\n // const constructorString = constructor.toString();\n // const beanName = constructorString.substring(9, constructorString.indexOf(\"(\"));\n this.destroyFunctions.forEach(function (func) { return func(); });\n this.destroyFunctions.length = 0;\n this.destroyed = true;\n this.dispatchEvent({ type: BeanStub.EVENT_DESTROYED });\n };\n BeanStub.prototype.addEventListener = function (eventType, listener) {\n if (!this.localEventService) {\n this.localEventService = new EventService();\n }\n this.localEventService.addEventListener(eventType, listener);\n };\n BeanStub.prototype.removeEventListener = function (eventType, listener) {\n if (this.localEventService) {\n this.localEventService.removeEventListener(eventType, listener);\n }\n };\n BeanStub.prototype.dispatchEventAsync = function (event) {\n var _this = this;\n window.setTimeout(function () { return _this.dispatchEvent(event); }, 0);\n };\n BeanStub.prototype.dispatchEvent = function (event) {\n if (this.localEventService) {\n this.localEventService.dispatchEvent(event);\n }\n };\n BeanStub.prototype.addManagedListener = function (object, event, listener) {\n var _this = this;\n if (this.destroyed) {\n return;\n }\n if (object instanceof HTMLElement) {\n addSafePassiveEventListener(this.getFrameworkOverrides(), object, event, listener);\n }\n else {\n object.addEventListener(event, listener);\n }\n var destroyFunc = function () {\n object.removeEventListener(event, listener);\n _this.destroyFunctions = _this.destroyFunctions.filter(function (fn) { return fn !== destroyFunc; });\n return null;\n };\n this.destroyFunctions.push(destroyFunc);\n return destroyFunc;\n };\n BeanStub.prototype.addDestroyFunc = function (func) {\n // if we are already destroyed, we execute the func now\n if (this.isAlive()) {\n this.destroyFunctions.push(func);\n }\n else {\n func();\n }\n };\n BeanStub.prototype.createManagedBean = function (bean, context) {\n var res = this.createBean(bean, context);\n this.addDestroyFunc(this.destroyBean.bind(this, bean, context));\n return res;\n };\n BeanStub.prototype.createBean = function (bean, context, afterPreCreateCallback) {\n return (context || this.getContext()).createBean(bean, afterPreCreateCallback);\n };\n BeanStub.prototype.destroyBean = function (bean, context) {\n return (context || this.getContext()).destroyBean(bean);\n };\n BeanStub.prototype.destroyBeans = function (beans, context) {\n var _this = this;\n if (beans) {\n beans.forEach(function (bean) { return _this.destroyBean(bean, context); });\n }\n return [];\n };\n BeanStub.EVENT_DESTROYED = 'destroyed';\n __decorate$2x([\n Autowired('frameworkOverrides')\n ], BeanStub.prototype, \"frameworkOverrides\", void 0);\n __decorate$2x([\n Autowired('context')\n ], BeanStub.prototype, \"context\", void 0);\n __decorate$2x([\n Autowired('eventService')\n ], BeanStub.prototype, \"eventService\", void 0);\n __decorate$2x([\n Autowired('gridOptionsWrapper')\n ], BeanStub.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$2x([\n PreDestroy\n ], BeanStub.prototype, \"destroy\", null);\n return BeanStub;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2U = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2w = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$9 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\n// takes ColDefs and ColGroupDefs and turns them into Columns and OriginalGroups\nvar ColumnFactory = /** @class */ (function (_super) {\n __extends$2U(ColumnFactory, _super);\n function ColumnFactory() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ColumnFactory.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('ColumnFactory');\n };\n ColumnFactory.prototype.createColumnTree = function (defs, primaryColumns, existingTree) {\n // column key creator dishes out unique column id's in a deterministic way,\n // so if we have two grids (that could be master/slave) with same column definitions,\n // then this ensures the two grids use identical id's.\n var columnKeyCreator = new ColumnKeyCreator();\n var _a = this.extractExistingTreeData(existingTree), existingCols = _a.existingCols, existingGroups = _a.existingGroups, existingColKeys = _a.existingColKeys;\n columnKeyCreator.addExistingKeys(existingColKeys);\n // create am unbalanced tree that maps the provided definitions\n var unbalancedTree = this.recursivelyCreateColumns(defs, 0, primaryColumns, existingCols, columnKeyCreator, existingGroups);\n var treeDept = this.findMaxDept(unbalancedTree, 0);\n this.logger.log('Number of levels for grouped columns is ' + treeDept);\n var columnTree = this.balanceColumnTree(unbalancedTree, 0, treeDept, columnKeyCreator);\n var deptFirstCallback = function (child, parent) {\n if (child instanceof ProvidedColumnGroup) {\n child.setupExpandable();\n }\n // we set the original parents at the end, rather than when we go along, as balancing the tree\n // adds extra levels into the tree. so we can only set parents when balancing is done.\n child.setOriginalParent(parent);\n };\n this.columnUtils.depthFirstOriginalTreeSearch(null, columnTree, deptFirstCallback);\n return {\n columnTree: columnTree,\n treeDept: treeDept\n };\n };\n ColumnFactory.prototype.extractExistingTreeData = function (existingTree) {\n var existingCols = [];\n var existingGroups = [];\n var existingColKeys = [];\n if (existingTree) {\n this.columnUtils.depthFirstOriginalTreeSearch(null, existingTree, function (item) {\n if (item instanceof ProvidedColumnGroup) {\n var group = item;\n existingGroups.push(group);\n }\n else {\n var col = item;\n existingColKeys.push(col.getId());\n existingCols.push(col);\n }\n });\n }\n return { existingCols: existingCols, existingGroups: existingGroups, existingColKeys: existingColKeys };\n };\n ColumnFactory.prototype.createForAutoGroups = function (autoGroupCols, gridBalancedTree) {\n var _this = this;\n return autoGroupCols.map(function (col) { return _this.createAutoGroupTreeItem(gridBalancedTree, col); });\n };\n ColumnFactory.prototype.createAutoGroupTreeItem = function (balancedColumnTree, column) {\n var dept = this.findDepth(balancedColumnTree);\n // at the end, this will be the top of the tree item.\n var nextChild = column;\n for (var i = dept - 1; i >= 0; i--) {\n var autoGroup = new ProvidedColumnGroup(null, \"FAKE_PATH_\" + column.getId() + \"}_\" + i, true, i);\n this.context.createBean(autoGroup);\n autoGroup.setChildren([nextChild]);\n nextChild.setOriginalParent(autoGroup);\n nextChild = autoGroup;\n }\n // at this point, the nextChild is the top most item in the tree\n return nextChild;\n };\n ColumnFactory.prototype.findDepth = function (balancedColumnTree) {\n var dept = 0;\n var pointer = balancedColumnTree;\n while (pointer && pointer[0] && pointer[0] instanceof ProvidedColumnGroup) {\n dept++;\n pointer = pointer[0].getChildren();\n }\n return dept;\n };\n ColumnFactory.prototype.balanceColumnTree = function (unbalancedTree, currentDept, columnDept, columnKeyCreator) {\n var result = [];\n // go through each child, for groups, recurse a level deeper,\n // for columns we need to pad\n for (var i = 0; i < unbalancedTree.length; i++) {\n var child = unbalancedTree[i];\n if (child instanceof ProvidedColumnGroup) {\n // child is a group, all we do is go to the next level of recursion\n var originalGroup = child;\n var newChildren = this.balanceColumnTree(originalGroup.getChildren(), currentDept + 1, columnDept, columnKeyCreator);\n originalGroup.setChildren(newChildren);\n result.push(originalGroup);\n }\n else {\n // child is a column - so here we add in the padded column groups if needed\n var firstPaddedGroup = void 0;\n var currentPaddedGroup = void 0;\n // this for loop will NOT run any loops if no padded column groups are needed\n for (var j = columnDept - 1; j >= currentDept; j--) {\n var newColId = columnKeyCreator.getUniqueKey(null, null);\n var colGroupDefMerged = this.createMergedColGroupDef(null);\n var paddedGroup = new ProvidedColumnGroup(colGroupDefMerged, newColId, true, currentDept);\n this.context.createBean(paddedGroup);\n if (currentPaddedGroup) {\n currentPaddedGroup.setChildren([paddedGroup]);\n }\n currentPaddedGroup = paddedGroup;\n if (!firstPaddedGroup) {\n firstPaddedGroup = currentPaddedGroup;\n }\n }\n // likewise this if statement will not run if no padded groups\n if (firstPaddedGroup && currentPaddedGroup) {\n result.push(firstPaddedGroup);\n var hasGroups = unbalancedTree.some(function (leaf) { return leaf instanceof ProvidedColumnGroup; });\n if (hasGroups) {\n currentPaddedGroup.setChildren([child]);\n continue;\n }\n else {\n currentPaddedGroup.setChildren(unbalancedTree);\n break;\n }\n }\n result.push(child);\n }\n }\n return result;\n };\n ColumnFactory.prototype.findMaxDept = function (treeChildren, dept) {\n var maxDeptThisLevel = dept;\n for (var i = 0; i < treeChildren.length; i++) {\n var abstractColumn = treeChildren[i];\n if (abstractColumn instanceof ProvidedColumnGroup) {\n var originalGroup = abstractColumn;\n var newDept = this.findMaxDept(originalGroup.getChildren(), dept + 1);\n if (maxDeptThisLevel < newDept) {\n maxDeptThisLevel = newDept;\n }\n }\n }\n return maxDeptThisLevel;\n };\n ColumnFactory.prototype.recursivelyCreateColumns = function (defs, level, primaryColumns, existingColsCopy, columnKeyCreator, existingGroups) {\n var _this = this;\n return (defs || []).map(function (def) {\n if (_this.isColumnGroup(def)) {\n return _this.createColumnGroup(primaryColumns, def, level, existingColsCopy, columnKeyCreator, existingGroups);\n }\n else {\n return _this.createColumn(primaryColumns, def, existingColsCopy, columnKeyCreator);\n }\n });\n };\n ColumnFactory.prototype.createColumnGroup = function (primaryColumns, colGroupDef, level, existingColumns, columnKeyCreator, existingGroups) {\n var colGroupDefMerged = this.createMergedColGroupDef(colGroupDef);\n var groupId = columnKeyCreator.getUniqueKey(colGroupDefMerged.groupId || null, null);\n var providedGroup = new ProvidedColumnGroup(colGroupDefMerged, groupId, false, level);\n this.context.createBean(providedGroup);\n var existingGroup = this.findExistingGroup(colGroupDef, existingGroups);\n // make sure we remove, so if user provided duplicate id, then we don't have more than\n // one column instance for colDef with common id\n if (existingGroup) {\n removeFromArray(existingGroups, existingGroup);\n }\n if (existingGroup && existingGroup.isExpanded()) {\n providedGroup.setExpanded(true);\n }\n var children = this.recursivelyCreateColumns(colGroupDefMerged.children, level + 1, primaryColumns, existingColumns, columnKeyCreator, existingGroups);\n providedGroup.setChildren(children);\n return providedGroup;\n };\n ColumnFactory.prototype.createMergedColGroupDef = function (colGroupDef) {\n var colGroupDefMerged = {};\n Object.assign(colGroupDefMerged, this.gridOptionsWrapper.getDefaultColGroupDef());\n Object.assign(colGroupDefMerged, colGroupDef);\n this.checkForDeprecatedItems(colGroupDefMerged);\n return colGroupDefMerged;\n };\n ColumnFactory.prototype.createColumn = function (primaryColumns, colDef, existingColsCopy, columnKeyCreator) {\n var colDefMerged = this.mergeColDefs(colDef);\n this.checkForDeprecatedItems(colDefMerged);\n // see if column already exists\n var column = this.findExistingColumn(colDef, existingColsCopy);\n // make sure we remove, so if user provided duplicate id, then we don't have more than\n // one column instance for colDef with common id\n if (existingColsCopy && column) {\n removeFromArray(existingColsCopy, column);\n }\n if (!column) {\n // no existing column, need to create one\n var colId = columnKeyCreator.getUniqueKey(colDefMerged.colId, colDefMerged.field);\n column = new Column(colDefMerged, colDef, colId, primaryColumns);\n this.context.createBean(column);\n }\n else {\n column.setColDef(colDefMerged, colDef);\n this.applyColumnState(column, colDefMerged);\n }\n return column;\n };\n ColumnFactory.prototype.applyColumnState = function (column, colDef) {\n // flex\n var flex = attrToNumber(colDef.flex);\n if (flex !== undefined) {\n column.setFlex(flex);\n }\n // width - we only set width if column is not flexing\n var noFlexThisCol = column.getFlex() <= 0;\n if (noFlexThisCol) {\n // both null and undefined means we skip, as it's not possible to 'clear' width (a column must have a width)\n var width = attrToNumber(colDef.width);\n if (width != null) {\n column.setActualWidth(width);\n }\n else {\n // otherwise set the width again, in case min or max width has changed,\n // and width needs to be adjusted.\n var widthBeforeUpdate = column.getActualWidth();\n column.setActualWidth(widthBeforeUpdate);\n }\n }\n // sort - anything but undefined will set sort, thus null or empty string will clear the sort\n if (colDef.sort !== undefined) {\n if (colDef.sort == Constants.SORT_ASC || colDef.sort == Constants.SORT_DESC) {\n column.setSort(colDef.sort);\n }\n else {\n column.setSort(undefined);\n }\n }\n // sorted at - anything but undefined, thus null will clear the sortIndex\n var sortIndex = attrToNumber(colDef.sortIndex);\n if (sortIndex !== undefined) {\n column.setSortIndex(sortIndex);\n }\n // hide - anything but undefined, thus null will clear the hide\n var hide = attrToBoolean(colDef.hide);\n if (hide !== undefined) {\n column.setVisible(!hide);\n }\n // pinned - anything but undefined, thus null or empty string will remove pinned\n if (colDef.pinned !== undefined) {\n column.setPinned(colDef.pinned);\n }\n };\n ColumnFactory.prototype.findExistingColumn = function (newColDef, existingColsCopy) {\n return (existingColsCopy || []).find(function (existingCol) {\n var existingColDef = existingCol.getUserProvidedColDef();\n if (!existingColDef) {\n return false;\n }\n var newHasId = newColDef.colId != null;\n var newHasField = newColDef.field != null;\n if (newHasId) {\n return existingCol.getId() === newColDef.colId;\n }\n if (newHasField) {\n return existingColDef.field === newColDef.field;\n }\n // if no id or field present, then try object equivalence.\n if (existingColDef === newColDef) {\n return true;\n }\n return false;\n });\n };\n ColumnFactory.prototype.findExistingGroup = function (newGroupDef, existingGroups) {\n return existingGroups.find(function (existingGroup) {\n var existingDef = existingGroup.getColGroupDef();\n if (!existingDef) {\n return false;\n }\n var newHasId = newGroupDef.groupId != null;\n if (newHasId) {\n return existingGroup.getId() === newGroupDef.groupId;\n }\n return false;\n });\n };\n ColumnFactory.prototype.mergeColDefs = function (colDef) {\n // start with empty merged definition\n var colDefMerged = {};\n // merge properties from default column definitions\n var defaultColDef = this.gridOptionsWrapper.getDefaultColDef();\n mergeDeep(colDefMerged, defaultColDef, false, true);\n // merge properties from column type properties\n var columnType = colDef.type;\n if (!columnType) {\n columnType = defaultColDef && defaultColDef.type;\n }\n // if type of both colDef and defaultColDef, then colDef gets preference\n if (columnType) {\n this.assignColumnTypes(columnType, colDefMerged);\n }\n // merge properties from column definitions\n mergeDeep(colDefMerged, colDef, false, true);\n var autoGroupColDef = this.gridOptionsWrapper.getAutoGroupColumnDef();\n var isSortingCoupled = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n if (colDef.rowGroup && autoGroupColDef && isSortingCoupled) {\n // override the sort for row group columns where the autoGroupColDef defines these values.\n mergeDeep(colDefMerged, { sort: autoGroupColDef.sort, initialSort: autoGroupColDef.initialSort }, false, true);\n }\n return colDefMerged;\n };\n ColumnFactory.prototype.assignColumnTypes = function (type, colDefMerged) {\n var typeKeys = [];\n if (type instanceof Array) {\n var invalidArray = type.some(function (a) { return typeof a !== 'string'; });\n if (invalidArray) {\n console.warn(\"AG Grid: if colDef.type is supplied an array it should be of type 'string[]'\");\n }\n else {\n typeKeys = type;\n }\n }\n else if (typeof type === 'string') {\n typeKeys = type.split(',');\n }\n else {\n console.warn(\"AG Grid: colDef.type should be of type 'string' | 'string[]'\");\n return;\n }\n // merge user defined with default column types\n var allColumnTypes = Object.assign({}, DefaultColumnTypes);\n var userTypes = this.gridOptionsWrapper.getColumnTypes() || {};\n iterateObject(userTypes, function (key, value) {\n if (key in allColumnTypes) {\n console.warn(\"AG Grid: the column type '\" + key + \"' is a default column type and cannot be overridden.\");\n }\n else {\n allColumnTypes[key] = value;\n }\n });\n typeKeys.forEach(function (t) {\n var typeColDef = allColumnTypes[t.trim()];\n if (typeColDef) {\n mergeDeep(colDefMerged, typeColDef, false, true);\n }\n else {\n console.warn(\"AG Grid: colDef.type '\" + t + \"' does not correspond to defined gridOptions.columnTypes\");\n }\n });\n };\n ColumnFactory.prototype.checkForDeprecatedItems = function (colDef) {\n if (colDef) {\n var colDefNoType = colDef; // take out the type, so we can access attributes not defined in the type\n if (colDefNoType.group !== undefined) {\n console.warn('AG Grid: colDef.group is invalid, please check documentation on how to do grouping as it changed in version 3');\n }\n if (colDefNoType.headerGroup !== undefined) {\n console.warn('AG Grid: colDef.headerGroup is invalid, please check documentation on how to do grouping as it changed in version 3');\n }\n if (colDefNoType.headerGroupShow !== undefined) {\n console.warn('AG Grid: colDef.headerGroupShow is invalid, should be columnGroupShow, please check documentation on how to do grouping as it changed in version 3');\n }\n if (colDefNoType.suppressRowGroup !== undefined) {\n console.warn('AG Grid: colDef.suppressRowGroup is deprecated, please use colDef.type instead');\n }\n if (colDefNoType.suppressAggregation !== undefined) {\n console.warn('AG Grid: colDef.suppressAggregation is deprecated, please use colDef.type instead');\n }\n if (colDefNoType.suppressRowGroup || colDefNoType.suppressAggregation) {\n console.warn('AG Grid: colDef.suppressAggregation and colDef.suppressRowGroup are deprecated, use allowRowGroup, allowPivot and allowValue instead');\n }\n if (colDefNoType.displayName) {\n console.warn(\"AG Grid: Found displayName \" + colDefNoType.displayName + \", please use headerName instead, displayName is deprecated.\");\n colDefNoType.headerName = colDefNoType.displayName;\n }\n }\n };\n // if object has children, we assume it's a group\n ColumnFactory.prototype.isColumnGroup = function (abstractColDef) {\n return abstractColDef.children !== undefined;\n };\n __decorate$2w([\n Autowired('columnUtils')\n ], ColumnFactory.prototype, \"columnUtils\", void 0);\n __decorate$2w([\n __param$9(0, Qualifier('loggerFactory'))\n ], ColumnFactory.prototype, \"setBeans\", null);\n ColumnFactory = __decorate$2w([\n Bean('columnFactory')\n ], ColumnFactory);\n return ColumnFactory;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar Events = /** @class */ (function () {\n function Events() {\n }\n /** Everything has changed with the columns. Either complete new set of columns set, or user called setState() */\n /** @deprecated - grid no longer uses this, and setSate() also fires individual events */\n Events.EVENT_COLUMN_EVERYTHING_CHANGED = 'columnEverythingChanged';\n /** User has set in new columns. */\n Events.EVENT_NEW_COLUMNS_LOADED = 'newColumnsLoaded';\n /** The pivot mode flag was changed */\n Events.EVENT_COLUMN_PIVOT_MODE_CHANGED = 'columnPivotModeChanged';\n /** A row group column was added, removed or order changed. */\n Events.EVENT_COLUMN_ROW_GROUP_CHANGED = 'columnRowGroupChanged';\n /** expandAll / collapseAll was called from the api. */\n Events.EVENT_EXPAND_COLLAPSE_ALL = 'expandOrCollapseAll';\n /** A pivot column was added, removed or order changed. */\n Events.EVENT_COLUMN_PIVOT_CHANGED = 'columnPivotChanged';\n /** The list of grid columns has changed. */\n Events.EVENT_GRID_COLUMNS_CHANGED = 'gridColumnsChanged';\n /** A value column was added, removed or agg function was changed. */\n Events.EVENT_COLUMN_VALUE_CHANGED = 'columnValueChanged';\n /** A column was moved */\n Events.EVENT_COLUMN_MOVED = 'columnMoved';\n /** One or more columns was shown / hidden */\n Events.EVENT_COLUMN_VISIBLE = 'columnVisible';\n /** One or more columns was pinned / unpinned*/\n Events.EVENT_COLUMN_PINNED = 'columnPinned';\n /** A column group was opened / closed */\n Events.EVENT_COLUMN_GROUP_OPENED = 'columnGroupOpened';\n /** One or more columns was resized. If just one, the column in the event is set. */\n Events.EVENT_COLUMN_RESIZED = 'columnResized';\n /** The list of displayed columns has changed, can result from columns open / close, column move, pivot, group, etc */\n Events.EVENT_DISPLAYED_COLUMNS_CHANGED = 'displayedColumnsChanged';\n /** The list of virtual columns has changed, results from viewport changing */\n Events.EVENT_VIRTUAL_COLUMNS_CHANGED = 'virtualColumnsChanged';\n /** Async Transactions Executed */\n Events.EVENT_ASYNC_TRANSACTIONS_FLUSHED = 'asyncTransactionsFlushed';\n /** A row group was opened / closed */\n Events.EVENT_ROW_GROUP_OPENED = 'rowGroupOpened';\n /** @deprecated use EVENT_ROW_DATA_UPDATED instead */\n Events.EVENT_ROW_DATA_CHANGED = 'rowDataChanged';\n /** The client has updated data for the grid */\n Events.EVENT_ROW_DATA_UPDATED = 'rowDataUpdated';\n /** The client has set new floating data into the grid */\n Events.EVENT_PINNED_ROW_DATA_CHANGED = 'pinnedRowDataChanged';\n /** Range selection has changed */\n Events.EVENT_RANGE_SELECTION_CHANGED = 'rangeSelectionChanged';\n /** Chart was created */\n Events.EVENT_CHART_CREATED = 'chartCreated';\n /** Chart Range selection has changed */\n Events.EVENT_CHART_RANGE_SELECTION_CHANGED = 'chartRangeSelectionChanged';\n /** Chart Options have changed */\n Events.EVENT_CHART_OPTIONS_CHANGED = 'chartOptionsChanged';\n /** Chart was destroyed */\n Events.EVENT_CHART_DESTROYED = 'chartDestroyed';\n /** For when the tool panel is shown / hidden */\n Events.EVENT_TOOL_PANEL_VISIBLE_CHANGED = 'toolPanelVisibleChanged';\n Events.EVENT_TOOL_PANEL_SIZE_CHANGED = 'toolPanelSizeChanged';\n Events.EVENT_COLUMN_PANEL_ITEM_DRAG_START = 'columnPanelItemDragStart';\n Events.EVENT_COLUMN_PANEL_ITEM_DRAG_END = 'columnPanelItemDragEnd';\n /** Model was updated - grid updates the drawn rows when this happens */\n Events.EVENT_MODEL_UPDATED = 'modelUpdated';\n Events.EVENT_PASTE_START = 'pasteStart';\n Events.EVENT_PASTE_END = 'pasteEnd';\n Events.EVENT_FILL_START = 'fillStart';\n Events.EVENT_FILL_END = 'fillEnd';\n Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_START = 'keyShortcutChangedCellStart';\n Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_END = 'keyShortcutChangedCellEnd';\n Events.EVENT_CELL_CLICKED = 'cellClicked';\n Events.EVENT_CELL_DOUBLE_CLICKED = 'cellDoubleClicked';\n Events.EVENT_CELL_MOUSE_DOWN = 'cellMouseDown';\n Events.EVENT_CELL_CONTEXT_MENU = 'cellContextMenu';\n Events.EVENT_CELL_VALUE_CHANGED = 'cellValueChanged';\n Events.EVENT_CELL_EDIT_REQUEST = 'cellEditRequest';\n Events.EVENT_ROW_VALUE_CHANGED = 'rowValueChanged';\n Events.EVENT_CELL_FOCUSED = 'cellFocused';\n Events.EVENT_FULL_WIDTH_ROW_FOCUSED = 'fullWidthRowFocused';\n Events.EVENT_ROW_SELECTED = 'rowSelected';\n Events.EVENT_SELECTION_CHANGED = 'selectionChanged';\n Events.EVENT_CELL_KEY_DOWN = 'cellKeyDown';\n Events.EVENT_CELL_KEY_PRESS = 'cellKeyPress';\n Events.EVENT_CELL_MOUSE_OVER = 'cellMouseOver';\n Events.EVENT_CELL_MOUSE_OUT = 'cellMouseOut';\n /** 2 events for filtering. The grid LISTENS for filterChanged and afterFilterChanged */\n Events.EVENT_FILTER_CHANGED = 'filterChanged';\n /** Filter was change but not applied. Only useful if apply buttons are used in filters. */\n Events.EVENT_FILTER_MODIFIED = 'filterModified';\n Events.EVENT_FILTER_OPENED = 'filterOpened';\n Events.EVENT_SORT_CHANGED = 'sortChanged';\n /** A row was removed from the dom, for any reason. Use to clean up resources (if any) used by the row. */\n Events.EVENT_VIRTUAL_ROW_REMOVED = 'virtualRowRemoved';\n Events.EVENT_ROW_CLICKED = 'rowClicked';\n Events.EVENT_ROW_DOUBLE_CLICKED = 'rowDoubleClicked';\n /** Gets called once after the grid has finished initialising. */\n Events.EVENT_GRID_READY = 'gridReady';\n /** Width of height of the main grid div has changed. Grid listens for this and does layout of grid if it's\n * changed, so always filling the space it was given. */\n Events.EVENT_GRID_SIZE_CHANGED = 'gridSizeChanged';\n /** The indexes of the rows rendered has changed, eg user has scrolled to a new vertical position. */\n Events.EVENT_VIEWPORT_CHANGED = 'viewportChanged';\n /* The width of the scrollbar has been calculated */\n Events.EVENT_SCROLLBAR_WIDTH_CHANGED = 'scrollbarWidthChanged';\n /** Rows were rendered for the first time (ie on async data load). */\n Events.EVENT_FIRST_DATA_RENDERED = 'firstDataRendered';\n /** A column drag has started, either resizing a column or moving a column. */\n Events.EVENT_DRAG_STARTED = 'dragStarted';\n /** A column drag has stopped */\n Events.EVENT_DRAG_STOPPED = 'dragStopped';\n Events.EVENT_CHECKBOX_CHANGED = 'checkboxChanged';\n Events.EVENT_ROW_EDITING_STARTED = 'rowEditingStarted';\n Events.EVENT_ROW_EDITING_STOPPED = 'rowEditingStopped';\n Events.EVENT_CELL_EDITING_STARTED = 'cellEditingStarted';\n Events.EVENT_CELL_EDITING_STOPPED = 'cellEditingStopped';\n /** Main body of grid has scrolled, either horizontally or vertically */\n Events.EVENT_BODY_SCROLL = 'bodyScroll';\n /** Main body of the grid has stopped scrolling, either horizontally or vertically */\n Events.EVENT_BODY_SCROLL_END = 'bodyScrollEnd';\n Events.EVENT_HEIGHT_SCALE_CHANGED = 'heightScaleChanged';\n /** The displayed page for pagination has changed. For example the data was filtered or sorted,\n * or the user has moved to a different page. */\n Events.EVENT_PAGINATION_CHANGED = 'paginationChanged';\n /** Only used by React, Angular, Web Components and VueJS AG Grid components\n * (not used if doing plain JavaScript). If the grid receives changes due\n * to bound properties, this event fires after the grid has finished processing the change. */\n Events.EVENT_COMPONENT_STATE_CHANGED = 'componentStateChanged';\n /***************************** INTERNAL EVENTS: START ******************************************* */\n /** Please remember to add to ComponentUtil.EXCLUDED_INTERNAL_EVENTS to not have these events exposed to framework components. */\n /** All items from here down are used internally by the grid, not intended for external use. */\n // not documented, either experimental, or we just don't want users using an depending on them\n Events.EVENT_BODY_HEIGHT_CHANGED = 'bodyHeightChanged';\n Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED = 'displayedColumnsWidthChanged';\n Events.EVENT_SCROLL_VISIBILITY_CHANGED = 'scrollVisibilityChanged';\n Events.EVENT_COLUMN_HOVER_CHANGED = 'columnHoverChanged';\n Events.EVENT_FLASH_CELLS = 'flashCells';\n Events.EVENT_PAGINATION_PIXEL_OFFSET_CHANGED = 'paginationPixelOffsetChanged';\n Events.EVENT_DISPLAYED_ROWS_CHANGED = 'displayedRowsChanged';\n Events.EVENT_LEFT_PINNED_WIDTH_CHANGED = 'leftPinnedWidthChanged';\n Events.EVENT_RIGHT_PINNED_WIDTH_CHANGED = 'rightPinnedWidthChanged';\n Events.EVENT_ROW_CONTAINER_HEIGHT_CHANGED = 'rowContainerHeightChanged';\n Events.EVENT_HEADER_HEIGHT_CHANGED = 'headerHeightChanged';\n Events.EVENT_COLUMN_HEADER_HEIGHT_CHANGED = 'columnHeaderHeightChanged';\n Events.EVENT_ROW_DRAG_ENTER = 'rowDragEnter';\n Events.EVENT_ROW_DRAG_MOVE = 'rowDragMove';\n Events.EVENT_ROW_DRAG_LEAVE = 'rowDragLeave';\n Events.EVENT_ROW_DRAG_END = 'rowDragEnd';\n // primarily for charts\n Events.EVENT_POPUP_TO_FRONT = 'popupToFront';\n // these are used for server side group and agg - only used by CS with Viewport Row Model - intention is\n // to design these better around server side functions and then release to general public when fully working with\n // all the row models.\n Events.EVENT_COLUMN_ROW_GROUP_CHANGE_REQUEST = 'columnRowGroupChangeRequest';\n Events.EVENT_COLUMN_PIVOT_CHANGE_REQUEST = 'columnPivotChangeRequest';\n Events.EVENT_COLUMN_VALUE_CHANGE_REQUEST = 'columnValueChangeRequest';\n Events.EVENT_COLUMN_AGG_FUNC_CHANGE_REQUEST = 'columnAggFuncChangeRequest';\n Events.EVENT_KEYBOARD_FOCUS = 'keyboardFocus';\n Events.EVENT_MOUSE_FOCUS = 'mouseFocus';\n Events.EVENT_STORE_UPDATED = 'storeUpdated';\n return Events;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n// class returns unique instance id's for columns.\n// eg, the following calls (in this order) will result in:\n//\n// getInstanceIdForKey('country') => 0\n// getInstanceIdForKey('country') => 1\n// getInstanceIdForKey('country') => 2\n// getInstanceIdForKey('country') => 3\n// getInstanceIdForKey('age') => 0\n// getInstanceIdForKey('age') => 1\n// getInstanceIdForKey('country') => 4\nvar GroupInstanceIdCreator = /** @class */ (function () {\n function GroupInstanceIdCreator() {\n // this map contains keys to numbers, so we remember what the last call was\n this.existingIds = {};\n }\n GroupInstanceIdCreator.prototype.getInstanceIdForKey = function (key) {\n var lastResult = this.existingIds[key];\n var result;\n if (typeof lastResult !== 'number') {\n // first time this key\n result = 0;\n }\n else {\n result = lastResult + 1;\n }\n this.existingIds[key] = result;\n return result;\n };\n return GroupInstanceIdCreator;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar reUnescapedHtml = /[&<>\"']/g;\n/**\n * HTML Escapes.\n */\nvar HTML_ESCAPES = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n};\n/**\n * It encodes any string in UTF-8 format\n * taken from https://github.com/mathiasbynens/utf8.js\n * @param {string} s\n * @returns {string}\n */\nfunction utf8_encode(s) {\n var stringFromCharCode = String.fromCharCode;\n function ucs2decode(string) {\n var output = [];\n if (!string) {\n return [];\n }\n var len = string.length;\n var counter = 0;\n var value;\n var extra;\n while (counter < len) {\n value = string.charCodeAt(counter++);\n if (value >= 0xD800 && value <= 0xDBFF && counter < len) {\n // high surrogate, and there is a next character\n extra = string.charCodeAt(counter++);\n if ((extra & 0xFC00) == 0xDC00) { // low surrogate\n output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);\n }\n else {\n // unmatched surrogate; only append this code unit, in case the next\n // code unit is the high surrogate of a surrogate pair\n output.push(value);\n counter--;\n }\n }\n else {\n output.push(value);\n }\n }\n return output;\n }\n function checkScalarValue(point) {\n if (point >= 0xD800 && point <= 0xDFFF) {\n throw Error('Lone surrogate U+' + point.toString(16).toUpperCase() +\n ' is not a scalar value');\n }\n }\n function createByte(point, shift) {\n return stringFromCharCode(((point >> shift) & 0x3F) | 0x80);\n }\n function encodeCodePoint(point) {\n if ((point >= 0 && point <= 31 && point !== 10)) {\n var convertedCode = point.toString(16).toUpperCase();\n var paddedCode = convertedCode.padStart(4, '0');\n return \"_x\" + paddedCode + \"_\";\n }\n if ((point & 0xFFFFFF80) == 0) { // 1-byte sequence\n return stringFromCharCode(point);\n }\n var symbol = '';\n if ((point & 0xFFFFF800) == 0) { // 2-byte sequence\n symbol = stringFromCharCode(((point >> 6) & 0x1F) | 0xC0);\n }\n else if ((point & 0xFFFF0000) == 0) { // 3-byte sequence\n checkScalarValue(point);\n symbol = stringFromCharCode(((point >> 12) & 0x0F) | 0xE0);\n symbol += createByte(point, 6);\n }\n else if ((point & 0xFFE00000) == 0) { // 4-byte sequence\n symbol = stringFromCharCode(((point >> 18) & 0x07) | 0xF0);\n symbol += createByte(point, 12);\n symbol += createByte(point, 6);\n }\n symbol += stringFromCharCode((point & 0x3F) | 0x80);\n return symbol;\n }\n var codePoints = ucs2decode(s);\n var length = codePoints.length;\n var index = -1;\n var codePoint;\n var byteString = '';\n while (++index < length) {\n codePoint = codePoints[index];\n byteString += encodeCodePoint(codePoint);\n }\n return byteString;\n}\n/**\n * Converts a camelCase string into hyphenated string\n * from https://gist.github.com/youssman/745578062609e8acac9f\n * @param {string} str\n * @return {string}\n */\nfunction camelCaseToHyphen(str) {\n if (str === null || str === undefined) {\n return null;\n }\n return str.replace(/([A-Z])/g, function (g) { return '-' + g[0].toLowerCase(); });\n}\n/**\n * Converts a hyphenated string into camelCase string\n * from https://stackoverflow.com/questions/6660977/convert-hyphens-to-camel-case-camelcase\n * @param {string} str\n * @return {string}\n */\nfunction hyphenToCamelCase(str) {\n if (str === null || str === undefined) {\n return null;\n }\n return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });\n}\nfunction capitalise(str) {\n return str[0].toUpperCase() + str.substr(1).toLowerCase();\n}\nfunction escapeString(toEscape, skipEscapingHtmlChars) {\n if (toEscape == null) {\n return null;\n }\n // we call toString() twice, in case value is an object, where user provides\n // a toString() method, and first call to toString() returns back something other\n // than a string (eg a number to render)\n var stringResult = toEscape.toString().toString();\n if (skipEscapingHtmlChars) {\n return stringResult;\n }\n // in react we don't need to escape html characters, as it's done by the framework\n return stringResult.replace(reUnescapedHtml, function (chr) { return HTML_ESCAPES[chr]; });\n}\n/**\n * Converts a camelCase string into regular text\n * from: https://stackoverflow.com/questions/15369566/putting-space-in-camel-case-string-using-regular-expression\n * @param {string} camelCase\n * @return {string}\n */\nfunction camelCaseToHumanText(camelCase) {\n if (!camelCase || camelCase == null) {\n return null;\n }\n var rex = /([A-Z])([A-Z])([a-z])|([a-z])([A-Z])/g;\n var words = camelCase.replace(rex, '$1$4 $2$3$5').replace('.', ' ').split(' ');\n return words.map(function (word) { return word.substring(0, 1).toUpperCase() + ((word.length > 1) ? word.substring(1, word.length) : ''); }).join(' ');\n}\n\nvar StringUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n utf8_encode: utf8_encode,\n camelCaseToHyphen: camelCaseToHyphen,\n hyphenToCamelCase: hyphenToCamelCase,\n capitalise: capitalise,\n escapeString: escapeString,\n camelCaseToHumanText: camelCaseToHumanText\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction convertToMap(arr) {\n var map = new Map();\n arr.forEach(function (pair) { return map.set(pair[0], pair[1]); });\n return map;\n}\n// handy for organising a list into a map, where each item is mapped by an attribute, eg mapping Columns by ID\nfunction mapById(arr, callback) {\n var map = new Map();\n arr.forEach(function (item) { return map.set(callback(item), item); });\n return map;\n}\nfunction keys(map) {\n var arr = [];\n map.forEach(function (_, key) { return arr.push(key); });\n return arr;\n}\n\nvar MapUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n convertToMap: convertToMap,\n mapById: mapById,\n keys: keys\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __read$p = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$j = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$p(arguments[i]));\n return ar;\n};\nvar ColDefUtil = /** @class */ (function () {\n function ColDefUtil() {\n }\n ColDefUtil.STRING_PROPERTIES = [\n 'headerName',\n 'columnGroupShow',\n 'headerClass',\n 'toolPanelClass',\n 'headerValueGetter',\n 'pivotKeys',\n 'groupId',\n 'colId',\n 'sort',\n 'initialSort',\n 'field',\n 'type',\n 'tooltipComponent',\n 'tooltipField',\n 'headerTooltip',\n 'cellClass',\n 'showRowGroup',\n 'filter',\n 'initialAggFunc',\n 'defaultAggFunc',\n 'aggFunc',\n 'pinned',\n 'initialPinned',\n 'chartDataType',\n 'cellEditorPopupPosition'\n ];\n ColDefUtil.OBJECT_PROPERTIES = [\n 'headerGroupComponent',\n 'headerGroupComponentFramework',\n 'headerGroupComponentParams',\n 'cellStyle',\n 'cellRenderer',\n 'cellRendererParams',\n 'cellRendererFramework',\n 'cellEditor',\n 'cellEditorFramework',\n 'cellEditorParams',\n 'pinnedRowCellRendererFramework',\n 'pinnedRowCellRendererParams',\n 'filterFramework',\n 'filterParams',\n 'pivotValueColumn',\n 'headerComponent',\n 'headerComponentFramework',\n 'headerComponentParams',\n 'floatingFilterComponent',\n 'floatingFilterComponentParams',\n 'floatingFilterComponentFramework',\n 'floatingFilterFramework',\n 'tooltipComponent',\n 'tooltipComponentParams',\n 'tooltipComponentFramework',\n 'refData',\n 'columnsMenuParams'\n ];\n ColDefUtil.ARRAY_PROPERTIES = [\n 'children',\n 'sortingOrder',\n 'allowedAggFuncs',\n 'menuTabs',\n 'pivotTotalColumnIds',\n 'cellClassRules',\n 'icons'\n ];\n ColDefUtil.NUMBER_PROPERTIES = [\n 'sortedAt',\n 'sortIndex',\n 'initialSortIndex',\n 'flex',\n 'initialFlex',\n 'width',\n 'initialWidth',\n 'minWidth',\n 'maxWidth',\n 'rowGroupIndex',\n 'initialRowGroupIndex',\n 'pivotIndex',\n 'initialPivotIndex'\n ];\n ColDefUtil.BOOLEAN_PROPERTIES = [\n 'suppressCellFlash',\n 'suppressColumnsToolPanel',\n 'suppressFiltersToolPanel',\n 'openByDefault',\n 'marryChildren',\n 'hide',\n 'initialHide',\n 'rowGroup',\n 'initialRowGroup',\n 'pivot',\n 'initialPivot',\n 'checkboxSelection',\n 'showDisabledCheckboxes',\n 'headerCheckboxSelection',\n 'headerCheckboxSelectionFilteredOnly',\n 'suppressMenu',\n 'suppressMovable',\n 'lockPosition',\n 'lockVisible',\n 'lockPinned',\n 'unSortIcon',\n 'suppressSizeToFit',\n 'suppressAutoSize',\n 'enableRowGroup',\n 'enablePivot',\n 'enableValue',\n 'editable',\n 'suppressPaste',\n 'suppressNavigable',\n 'enableCellChangeFlash',\n 'rowDrag',\n 'dndSource',\n 'autoHeight',\n 'wrapText',\n 'sortable',\n 'resizable',\n 'singleClickEdit',\n 'floatingFilter',\n 'cellEditorPopup',\n 'suppressFillHandle',\n 'wrapHeaderText',\n 'autoHeaderHeight'\n ];\n ColDefUtil.FUNCTION_PROPERTIES = [\n 'dndSourceOnRowDrag',\n 'valueGetter',\n 'valueSetter',\n 'filterValueGetter',\n 'keyCreator',\n 'pinnedRowCellRenderer',\n 'valueFormatter',\n 'pinnedRowValueFormatter',\n 'valueParser',\n 'comparator',\n 'equals',\n 'pivotComparator',\n 'suppressKeyboardEvent',\n 'suppressHeaderKeyboardEvent',\n 'colSpan',\n 'rowSpan',\n 'getQuickFilterText',\n 'newValueHandler',\n 'onCellValueChanged',\n 'onCellClicked',\n 'onCellDoubleClicked',\n 'onCellContextMenu',\n 'rowDragText',\n 'tooltipValueGetter',\n 'tooltipComponent',\n 'tooltipComponentFramework',\n 'cellRendererSelector',\n 'cellEditorSelector'\n ];\n ColDefUtil.ALL_PROPERTIES = __spread$j(ColDefUtil.ARRAY_PROPERTIES, ColDefUtil.OBJECT_PROPERTIES, ColDefUtil.STRING_PROPERTIES, ColDefUtil.NUMBER_PROPERTIES, ColDefUtil.FUNCTION_PROPERTIES, ColDefUtil.BOOLEAN_PROPERTIES);\n // used when doing property checks - this causes noise when using frameworks which can add their own fw specific\n // properties to colDefs, gridOptions etc\n ColDefUtil.FRAMEWORK_PROPERTIES = [\n '__ob__',\n '__v_skip',\n '__metadata__',\n 'mappedColumnProperties',\n 'hasChildColumns',\n 'toColDef',\n 'createColDefFromGridColumn'\n ];\n return ColDefUtil;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __read$o = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$i = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$o(arguments[i]));\n return ar;\n};\n/**\n * These keys are used for validating properties supplied on a gridOptions object, and for code generation.\n * If you change the properties on the gridOptions interface, you *must* update this file as well to be consistent.\n */\nvar PropertyKeys = /** @class */ (function () {\n function PropertyKeys() {\n }\n PropertyKeys.STRING_PROPERTIES = [\n 'sortingOrder', 'rowClass', 'rowSelection', 'overlayLoadingTemplate', 'overlayNoRowsTemplate',\n 'quickFilterText', 'rowModelType', 'editType', 'domLayout', 'clipboardDelimiter', 'rowGroupPanelShow',\n 'multiSortKey', 'pivotColumnGroupTotals', 'pivotRowTotals', 'pivotPanelShow', 'fillHandleDirection',\n 'serverSideStoreType', 'groupDisplayType', 'treeDataDisplayType'\n ];\n PropertyKeys.OBJECT_PROPERTIES = [\n 'components', 'frameworkComponents', 'rowStyle', 'context', 'autoGroupColumnDef', 'localeText', 'icons',\n 'datasource', 'serverSideDatasource', 'viewportDatasource', 'groupRowRendererParams', 'aggFuncs', 'fullWidthCellRendererParams',\n 'defaultColGroupDef', 'defaultColDef', 'defaultExportParams', 'defaultCsvExportParams', 'defaultExcelExportParams', 'columnTypes',\n 'rowClassRules', 'detailCellRendererParams', 'loadingCellRendererParams', 'loadingOverlayComponentParams',\n 'noRowsOverlayComponentParams', 'popupParent', 'colResizeDefault', 'statusBar', 'sideBar', 'chartThemeOverrides',\n 'customChartThemes', 'chartToolPanelsDef'\n ];\n PropertyKeys.ARRAY_PROPERTIES = [\n 'alignedGrids', 'rowData', 'columnDefs', 'excelStyles', 'pinnedTopRowData', 'pinnedBottomRowData', 'chartThemes'\n ];\n PropertyKeys.NUMBER_PROPERTIES = [\n 'rowHeight', 'detailRowHeight', 'rowBuffer', 'colWidth', 'headerHeight', 'groupHeaderHeight', 'floatingFiltersHeight',\n 'pivotHeaderHeight', 'pivotGroupHeaderHeight', 'groupDefaultExpanded', 'minColWidth', 'maxColWidth', 'viewportRowModelPageSize',\n 'viewportRowModelBufferSize', 'autoSizePadding', 'maxBlocksInCache', 'maxConcurrentDatasourceRequests', 'tooltipShowDelay',\n 'tooltipHideDelay', 'cacheOverflowSize', 'paginationPageSize', 'cacheBlockSize', 'infiniteInitialRowCount', 'serverSideInitialRowCount', 'scrollbarWidth',\n 'batchUpdateWaitMillis', 'asyncTransactionWaitMillis', 'blockLoadDebounceMillis', 'keepDetailRowsCount',\n 'undoRedoCellEditingLimit', 'cellFlashDelay', 'cellFadeDelay', 'tabIndex'\n ];\n PropertyKeys.BOOLEAN_PROPERTIES = [\n 'suppressMakeColumnVisibleAfterUnGroup', 'suppressRowClickSelection', 'suppressCellSelection', 'suppressCellFocus', 'suppressHorizontalScroll',\n 'alwaysShowHorizontalScroll', 'alwaysShowVerticalScroll', 'debug', 'enableBrowserTooltips', 'enableCellExpressions',\n 'angularCompileRows', 'angularCompileFilters', 'groupSuppressAutoColumn', 'groupSelectsChildren', 'groupIncludeFooter',\n 'groupIncludeTotalFooter', 'groupUseEntireRow', 'groupSuppressBlankHeader', 'suppressMenuHide', 'suppressRowDeselection',\n 'unSortIcon', 'suppressMultiSort', 'alwaysMultiSort', 'singleClickEdit', 'suppressLoadingOverlay', 'suppressNoRowsOverlay', 'suppressAutoSize',\n 'skipHeaderOnAutoSize', 'suppressParentsInRowNodes', 'suppressColumnMoveAnimation', 'suppressMovableColumns',\n 'suppressFieldDotNotation', 'enableRangeSelection', 'enableRangeHandle', 'enableFillHandle', 'suppressClearOnFillReduction',\n 'deltaSort', 'suppressTouch', 'suppressAsyncEvents', 'allowContextMenuWithControlKey', 'suppressContextMenu',\n 'rememberGroupStateWhenNewData', 'enableCellChangeFlash', 'suppressDragLeaveHidesColumns', 'suppressRowGroupHidesColumns', 'suppressMiddleClickScrolls',\n 'suppressPreventDefaultOnMouseWheel', 'suppressCopyRowsToClipboard', 'copyHeadersToClipboard', 'copyGroupHeadersToClipboard',\n 'pivotMode', 'suppressAggFuncInHeader', 'suppressColumnVirtualisation', 'suppressAggAtRootLevel', 'suppressFocusAfterRefresh',\n 'functionsPassive', 'functionsReadOnly', 'animateRows', 'groupSelectsFiltered', 'groupRemoveSingleChildren',\n 'groupRemoveLowestSingleChildren', 'enableRtl', 'suppressClickEdit', 'rowDragEntireRow', 'rowDragManaged', 'suppressRowDrag',\n 'suppressMoveWhenRowDragging', 'rowDragMultiRow', 'enableGroupEdit', 'embedFullWidthRows', 'deprecatedEmbedFullWidthRows',\n 'suppressPaginationPanel', 'groupHideOpenParents', 'groupMultiAutoColumn', 'pagination',\n 'stopEditingWhenGridLosesFocus', 'paginationAutoPageSize', 'suppressScrollOnNewData', 'suppressScrollWhenPopupsAreOpen',\n 'purgeClosedRowNodes', 'cacheQuickFilter', 'deltaRowDataMode', 'ensureDomOrder', 'accentedSort', 'suppressChangeDetection',\n 'valueCache', 'valueCacheNeverExpires', 'aggregateOnlyChangedColumns', 'suppressAnimationFrame', 'suppressExcelExport',\n 'suppressCsvExport', 'treeData', 'masterDetail', 'suppressMultiRangeSelection', 'enterMovesDownAfterEdit', 'enterMovesDown',\n 'suppressPropertyNamesCheck', 'rowMultiSelectWithClick', 'suppressEnterpriseResetOnNewColumns',\n 'suppressRowHoverHighlight', 'suppressRowTransform', 'suppressClipboardPaste', 'suppressLastEmptyLineOnPaste',\n 'suppressSetColumnStateEvents', 'suppressColumnStateEvents', 'enableCharts', 'enableChartToolPanelsButton', 'deltaColumnMode',\n 'suppressMaintainUnsortedOrder', 'enableCellTextSelection', 'suppressBrowserResizeObserver', 'suppressMaxRenderedRowRestriction',\n 'excludeChildrenWhenTreeDataFiltering', 'tooltipMouseTrack', 'keepDetailRows', 'paginateChildRows', 'preventDefaultOnContextMenu',\n 'undoRedoCellEditing', 'allowDragFromColumnsToolPanel', 'immutableData', 'immutableColumns', 'pivotSuppressAutoColumn',\n 'suppressExpandablePivotGroups', 'applyColumnDefOrder', 'debounceVerticalScrollbar', 'detailRowAutoHeight',\n 'serverSideFilteringAlwaysResets', 'serverSideSortingAlwaysResets', 'serverSideSortAllLevels', 'serverSideFilterAllLevels',\n 'serverSideSortOnServer', 'serverSideFilterOnServer', 'suppressAggFilteredOnly', 'showOpenedGroup', 'suppressClipboardApi',\n 'suppressModelUpdateAfterUpdateTransaction', 'stopEditingWhenCellsLoseFocus', 'maintainColumnOrder', 'groupMaintainOrder',\n 'columnHoverHighlight', 'reactUi', 'suppressReactUi', 'readOnlyEdit', 'suppressRowVirtualisation', 'enableCellEditingOnBackspace',\n 'resetRowDataOnUpdate', 'removePivotHeaderRowWhenSingleValueColumn', 'suppressCopySingleCellRanges',\n 'groupRowsSticky', 'serverSideInfiniteScroll', 'rowGroupPanelSuppressSort',\n ];\n /** You do not need to include event callbacks in this list, as they are generated automatically. */\n PropertyKeys.FUNCTION_PROPERTIES = [\n 'localeTextFunc', 'getLocaleText', 'groupRowInnerRenderer', 'groupRowInnerRendererFramework', 'groupRowRenderer', 'groupRowRendererFramework',\n 'isExternalFilterPresent', 'getRowHeight', 'doesExternalFilterPass', 'getRowClass', 'getRowStyle', 'getContextMenuItems', 'getMainMenuItems',\n 'processRowPostCreate', 'processCellForClipboard', 'groupRowAggNodes', 'getGroupRowAgg', 'getRowNodeId', 'isFullWidthCell', 'isFullWidthRow',\n 'fullWidthCellRenderer', 'fullWidthCellRendererFramework', 'processSecondaryColDef', 'processSecondaryColGroupDef', 'processPivotResultColDef',\n 'processPivotResultColGroupDef', 'getBusinessKeyForNode', 'sendToClipboard', 'navigateToNextHeader', 'tabToNextHeader', 'navigateToNextCell',\n 'tabToNextCell', 'processCellFromClipboard', 'getDocument', 'postProcessPopup', 'getChildCount', 'getDataPath', 'loadingCellRenderer',\n 'loadingCellRendererFramework', 'loadingOverlayComponent', 'loadingOverlayComponentFramework', 'noRowsOverlayComponent', 'noRowsOverlayComponentFramework',\n 'detailCellRenderer', 'detailCellRendererFramework', 'isRowMaster', 'isRowSelectable', 'postSort', 'postSortRows', 'processHeaderForClipboard',\n 'processGroupHeaderForClipboard', 'paginationNumberFormatter', 'processDataFromClipboard', 'getServerSideGroupKey', 'isServerSideGroup', 'suppressKeyboardEvent',\n 'createChartContainer', 'getChartToolbarItems', 'fillOperation', 'isApplyServerSideTransaction', 'getServerSideStoreParams', 'getServerSideGroupLevelParams',\n 'isServerSideGroupOpenByDefault', 'isGroupOpenByDefault', 'defaultGroupSortComparator', 'defaultGroupOrderComparator', 'initialGroupOrderComparator',\n 'loadingCellRendererSelector', 'getRowId', 'groupAggFiltering', 'rowDragText'\n ];\n PropertyKeys.ALL_PROPERTIES = __spread$i(PropertyKeys.ARRAY_PROPERTIES, PropertyKeys.OBJECT_PROPERTIES, PropertyKeys.STRING_PROPERTIES, PropertyKeys.NUMBER_PROPERTIES, PropertyKeys.FUNCTION_PROPERTIES, PropertyKeys.BOOLEAN_PROPERTIES);\n /**\n * Used when performing property checks. This avoids noise caused when using frameworks, which can add their own\n * framework-specific properties to colDefs, gridOptions etc.\n */\n PropertyKeys.FRAMEWORK_PROPERTIES = [\n '__ob__', '__v_skip', '__metadata__', 'mappedColumnProperties', 'hasChildColumns', 'toColDef', 'createColDefFromGridColumn'\n ];\n return PropertyKeys;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __assign$h = (undefined && undefined.__assign) || function () {\n __assign$h = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$h.apply(this, arguments);\n};\nvar __read$n = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$h = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$n(arguments[i]));\n return ar;\n};\nvar ComponentUtil = /** @class */ (function () {\n function ComponentUtil() {\n }\n ComponentUtil.getEventCallbacks = function () {\n if (!ComponentUtil.EVENT_CALLBACKS) {\n ComponentUtil.EVENT_CALLBACKS = ComponentUtil.EVENTS.map(function (event) { return ComponentUtil.getCallbackForEvent(event); });\n }\n return ComponentUtil.EVENT_CALLBACKS;\n };\n ComponentUtil.copyAttributesToGridOptions = function (gridOptions, component, skipEventDeprecationCheck) {\n // create empty grid options if none were passed\n if (typeof gridOptions !== 'object') {\n gridOptions = {};\n }\n // to allow array style lookup in TypeScript, take type away from 'this' and 'gridOptions'\n var pGridOptions = gridOptions;\n var keyExists = function (key) { return typeof component[key] !== 'undefined'; };\n // if groupAggFiltering exists and isn't a function, handle as a boolean.\n if (keyExists('groupAggFiltering') && typeof component.groupAggFiltering !== 'function') {\n pGridOptions.groupAggFiltering = ComponentUtil.toBoolean(component.groupAggFiltering);\n delete component.groupAggFiltering;\n }\n // add in all the simple properties\n __spread$h(ComponentUtil.ARRAY_PROPERTIES, ComponentUtil.STRING_PROPERTIES, ComponentUtil.OBJECT_PROPERTIES, ComponentUtil.FUNCTION_PROPERTIES, ComponentUtil.getEventCallbacks()).filter(keyExists)\n .forEach(function (key) { return pGridOptions[key] = component[key]; });\n ComponentUtil.BOOLEAN_PROPERTIES\n .filter(keyExists)\n .forEach(function (key) { return pGridOptions[key] = ComponentUtil.toBoolean(component[key]); });\n ComponentUtil.NUMBER_PROPERTIES\n .filter(keyExists)\n .forEach(function (key) { return pGridOptions[key] = ComponentUtil.toNumber(component[key]); });\n return gridOptions;\n };\n ComponentUtil.getCallbackForEvent = function (eventName) {\n if (!eventName || eventName.length < 2) {\n return eventName;\n }\n return 'on' + eventName[0].toUpperCase() + eventName.substr(1);\n };\n ComponentUtil.processOnChange = function (changes, gridOptions, api, columnApi) {\n if (!changes) {\n return;\n }\n var changesToApply = __assign$h({}, changes);\n // to allow array style lookup in TypeScript, take type away from 'this' and 'gridOptions'\n var pGridOptions = gridOptions;\n var keyExists = function (key) { return changesToApply[key]; };\n // if groupAggFiltering exists and isn't a function, handle as a boolean.\n if (keyExists('groupAggFiltering')) {\n if (typeof changesToApply.groupAggFiltering === 'function') {\n pGridOptions.groupAggFiltering = changesToApply.groupAggFiltering;\n }\n else {\n pGridOptions.groupAggFiltering = ComponentUtil.toBoolean(changesToApply.groupAggFiltering);\n }\n delete changesToApply.groupAggFiltering;\n }\n if (keyExists('groupDisplayType')) {\n if (typeof changesToApply.groupDisplayType.currentValue === 'string') {\n api.setGroupDisplayType(changesToApply.groupDisplayType.currentValue);\n delete changesToApply.groupDisplayType;\n }\n }\n // we need to do this before the generic handling, otherwise value gets set before we\n // try to set it, and the grid then doesn't refresh the rows as it doesn't see any change.\n // also it's possible we use the generic code setXXX below and put it up there instead,\n // cover all cases.\n if (changesToApply.rowClass) {\n api.setRowClass(changesToApply.rowClass.currentValue);\n delete changesToApply.rowClass;\n }\n // check if any change for the simple types, and if so, then just copy in the new value\n __spread$h(ComponentUtil.ARRAY_PROPERTIES, ComponentUtil.OBJECT_PROPERTIES, ComponentUtil.STRING_PROPERTIES, ComponentUtil.getEventCallbacks()).filter(keyExists)\n .forEach(function (key) { return pGridOptions[key] = changesToApply[key].currentValue; });\n ComponentUtil.BOOLEAN_PROPERTIES\n .filter(keyExists)\n .forEach(function (key) { return pGridOptions[key] = ComponentUtil.toBoolean(changesToApply[key].currentValue); });\n ComponentUtil.NUMBER_PROPERTIES\n .filter(keyExists)\n .forEach(function (key) { return pGridOptions[key] = ComponentUtil.toNumber(changesToApply[key].currentValue); });\n if (changesToApply.enableCellTextSelection) {\n api.setEnableCellTextSelection(ComponentUtil.toBoolean(changesToApply.enableCellTextSelection.currentValue));\n delete changesToApply.enableCellTextSelection;\n }\n if (changesToApply.quickFilterText) {\n api.setQuickFilter(changesToApply.quickFilterText.currentValue);\n delete changesToApply.quickFilterText;\n }\n if (changesToApply.autoGroupColumnDef) {\n api.setAutoGroupColumnDef(changesToApply.autoGroupColumnDef.currentValue, \"gridOptionsChanged\");\n delete changesToApply.autoGroupColumnDef;\n }\n if (changesToApply.columnDefs) {\n api.setColumnDefs(changesToApply.columnDefs.currentValue, \"gridOptionsChanged\");\n delete changesToApply.columnDefs;\n }\n if (changesToApply.defaultColDef) {\n api.setDefaultColDef(changesToApply.defaultColDef.currentValue, \"gridOptionsChanged\");\n delete changesToApply.defaultColDef;\n }\n if (changesToApply.paginationPageSize) {\n api.paginationSetPageSize(ComponentUtil.toNumber(changesToApply.paginationPageSize.currentValue));\n delete changesToApply.paginationPageSize;\n }\n if (changesToApply.pivotMode) {\n columnApi.setPivotMode(ComponentUtil.toBoolean(changesToApply.pivotMode.currentValue));\n delete changesToApply.pivotMode;\n }\n if (changesToApply.groupRemoveSingleChildren) {\n api.setGroupRemoveSingleChildren(ComponentUtil.toBoolean(changesToApply.groupRemoveSingleChildren.currentValue));\n delete changesToApply.groupRemoveSingleChildren;\n }\n if (changesToApply.suppressRowDrag) {\n api.setSuppressRowDrag(ComponentUtil.toBoolean(changesToApply.suppressRowDrag.currentValue));\n delete changesToApply.suppressRowDrag;\n }\n if (changesToApply.suppressMoveWhenRowDragging) {\n api.setSuppressMoveWhenRowDragging(ComponentUtil.toBoolean(changesToApply.suppressMoveWhenRowDragging.currentValue));\n delete changesToApply.suppressMoveWhenRowDragging;\n }\n if (changesToApply.suppressRowClickSelection) {\n api.setSuppressRowClickSelection(ComponentUtil.toBoolean(changesToApply.suppressRowClickSelection.currentValue));\n delete changesToApply.suppressRowClickSelection;\n }\n if (changesToApply.suppressClipboardPaste) {\n api.setSuppressClipboardPaste(ComponentUtil.toBoolean(changesToApply.suppressClipboardPaste.currentValue));\n delete changesToApply.suppressClipboardPaste;\n }\n if (changesToApply.headerHeight) {\n api.setHeaderHeight(ComponentUtil.toNumber(changesToApply.headerHeight.currentValue));\n delete changesToApply.headerHeight;\n }\n // any remaining properties can be set in a generic way\n // ie the setter takes the form of setXXX and the argument requires no formatting/translation first\n var dynamicApi = api;\n Object.keys(changesToApply)\n .forEach(function (property) {\n var setterName = \"set\" + property.charAt(0).toUpperCase() + property.substring(1);\n if (dynamicApi[setterName]) {\n dynamicApi[setterName](changes[property].currentValue);\n }\n });\n // copy changes into an event for dispatch\n var event = {\n type: Events.EVENT_COMPONENT_STATE_CHANGED\n };\n iterateObject(changes, function (key, value) {\n event[key] = value;\n });\n api.dispatchEvent(event);\n };\n ComponentUtil.toBoolean = function (value) {\n if (typeof value === 'boolean') {\n return value;\n }\n if (typeof value === 'string') {\n // for boolean, compare to empty String to allow attributes appearing with\n // no value to be treated as 'true'\n return value.toUpperCase() === 'TRUE' || value == '';\n }\n return false;\n };\n ComponentUtil.toNumber = function (value) {\n if (typeof value === 'number') {\n return value;\n }\n if (typeof value === 'string') {\n return Number(value);\n }\n };\n // all the events are populated in here AFTER this class (at the bottom of the file).\n ComponentUtil.EVENTS = [];\n // events that are available for use by users of AG Grid and so should be documented\n ComponentUtil.PUBLIC_EVENTS = [];\n // events that are internal to AG Grid and should not be exposed to users via documentation or generated framework components\n ComponentUtil.EXCLUDED_INTERNAL_EVENTS = [];\n ComponentUtil.STRING_PROPERTIES = PropertyKeys.STRING_PROPERTIES;\n ComponentUtil.OBJECT_PROPERTIES = PropertyKeys.OBJECT_PROPERTIES;\n ComponentUtil.ARRAY_PROPERTIES = PropertyKeys.ARRAY_PROPERTIES;\n ComponentUtil.NUMBER_PROPERTIES = PropertyKeys.NUMBER_PROPERTIES;\n ComponentUtil.BOOLEAN_PROPERTIES = PropertyKeys.BOOLEAN_PROPERTIES;\n ComponentUtil.FUNCTION_PROPERTIES = PropertyKeys.FUNCTION_PROPERTIES;\n ComponentUtil.ALL_PROPERTIES = PropertyKeys.ALL_PROPERTIES;\n return ComponentUtil;\n}());\nComponentUtil.EVENTS = values(Events);\n/** Exclude the following internal events from code generation to prevent exposing these events via framework components */\nComponentUtil.EXCLUDED_INTERNAL_EVENTS = [\n Events.EVENT_SCROLLBAR_WIDTH_CHANGED,\n Events.EVENT_CHECKBOX_CHANGED,\n Events.EVENT_HEIGHT_SCALE_CHANGED,\n Events.EVENT_BODY_HEIGHT_CHANGED,\n Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED,\n Events.EVENT_SCROLL_VISIBILITY_CHANGED,\n Events.EVENT_COLUMN_HOVER_CHANGED,\n Events.EVENT_FLASH_CELLS,\n Events.EVENT_PAGINATION_PIXEL_OFFSET_CHANGED,\n Events.EVENT_DISPLAYED_ROWS_CHANGED,\n Events.EVENT_LEFT_PINNED_WIDTH_CHANGED,\n Events.EVENT_RIGHT_PINNED_WIDTH_CHANGED,\n Events.EVENT_ROW_CONTAINER_HEIGHT_CHANGED,\n Events.EVENT_POPUP_TO_FRONT,\n Events.EVENT_KEYBOARD_FOCUS,\n Events.EVENT_MOUSE_FOCUS,\n Events.EVENT_STORE_UPDATED,\n Events.EVENT_COLUMN_PANEL_ITEM_DRAG_START,\n Events.EVENT_COLUMN_PANEL_ITEM_DRAG_END,\n Events.EVENT_FILL_START,\n Events.EVENT_FILL_END,\n Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_START,\n Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_END,\n Events.EVENT_FULL_WIDTH_ROW_FOCUSED,\n Events.EVENT_HEADER_HEIGHT_CHANGED,\n Events.EVENT_COLUMN_HEADER_HEIGHT_CHANGED\n];\n/** EVENTS that should be exposed via code generation for the framework components. */\nComponentUtil.PUBLIC_EVENTS = ComponentUtil.EVENTS.filter(function (e) { return !includes(ComponentUtil.EXCLUDED_INTERNAL_EVENTS, e); });\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar SideBarDefParser = /** @class */ (function () {\n function SideBarDefParser() {\n }\n SideBarDefParser.parse = function (toParse) {\n if (!toParse) {\n return null;\n }\n if (toParse === true) {\n return {\n toolPanels: [\n SideBarDefParser.DEFAULT_COLUMN_COMP,\n SideBarDefParser.DEFAULT_FILTER_COMP,\n ],\n defaultToolPanel: 'columns'\n };\n }\n if (typeof toParse === 'string') {\n return SideBarDefParser.parse([toParse]);\n }\n if (Array.isArray(toParse)) {\n var comps_1 = [];\n toParse.forEach(function (key) {\n var lookupResult = SideBarDefParser.DEFAULT_BY_KEY[key];\n if (!lookupResult) {\n console.warn(\"AG Grid: the key \" + key + \" is not a valid key for specifying a tool panel, valid keys are: \" + Object.keys(SideBarDefParser.DEFAULT_BY_KEY).join(','));\n return;\n }\n comps_1.push(lookupResult);\n });\n if (comps_1.length === 0) {\n return null;\n }\n return {\n toolPanels: comps_1,\n defaultToolPanel: comps_1[0].id\n };\n }\n var result = {\n toolPanels: SideBarDefParser.parseComponents(toParse.toolPanels),\n defaultToolPanel: toParse.defaultToolPanel,\n hiddenByDefault: toParse.hiddenByDefault,\n position: toParse.position\n };\n return result;\n };\n SideBarDefParser.parseComponents = function (from) {\n var result = [];\n if (!from) {\n return result;\n }\n from.forEach(function (it) {\n var toAdd = null;\n if (typeof it === 'string') {\n var lookupResult = SideBarDefParser.DEFAULT_BY_KEY[it];\n if (!lookupResult) {\n console.warn(\"AG Grid: the key \" + it + \" is not a valid key for specifying a tool panel, valid keys are: \" + Object.keys(SideBarDefParser.DEFAULT_BY_KEY).join(','));\n return;\n }\n toAdd = lookupResult;\n }\n else {\n toAdd = it;\n }\n result.push(toAdd);\n });\n return result;\n };\n SideBarDefParser.DEFAULT_COLUMN_COMP = {\n id: 'columns',\n labelDefault: 'Columns',\n labelKey: 'columns',\n iconKey: 'columns',\n toolPanel: 'agColumnsToolPanel',\n };\n SideBarDefParser.DEFAULT_FILTER_COMP = {\n id: 'filters',\n labelDefault: 'Filters',\n labelKey: 'filters',\n iconKey: 'filter',\n toolPanel: 'agFiltersToolPanel',\n };\n SideBarDefParser.DEFAULT_BY_KEY = {\n columns: SideBarDefParser.DEFAULT_COLUMN_COMP,\n filters: SideBarDefParser.DEFAULT_FILTER_COMP\n };\n return SideBarDefParser;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __values$5 = (undefined && undefined.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\n/**\n * These variables are lazy loaded, as otherwise they try and get initialised when we are loading\n * unit tests and we don't have references to window or document in the unit tests\n * from http://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser\n */\nvar isSafari;\nvar isIE;\nvar isEdge;\nvar isChrome;\nvar isFirefox;\nvar isMacOs;\nvar isIOS;\nvar invisibleScrollbar;\nvar browserScrollbarWidth;\nvar browserInfo;\n/**\n * from https://stackoverflow.com/a/16938481/1388233\n */\nfunction getBrowserInfo() {\n if (browserInfo) {\n return browserInfo;\n }\n var userAgent = navigator.userAgent;\n var match = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || [];\n var tem;\n var version;\n if (/trident/i.test(match[1])) {\n tem = /\\brv[ :]+(\\d+)/g.exec(userAgent) || [];\n version = tem[1] != null ? parseFloat(tem[1]) : 0;\n return {\n name: 'IE',\n version: version\n };\n }\n if (match[1] === 'Chrome') {\n tem = userAgent.match(/\\bOPR|Edge\\/(\\d+)/);\n if (tem != null) {\n version = tem[1] != null ? parseFloat(tem[1]) : 0;\n return {\n name: 'Opera',\n version: version\n };\n }\n }\n match = match[2] ? [match[1], match[2]] : [navigator.appName, navigator.appVersion, '-?'];\n tem = userAgent.match(/version\\/(\\d+)/i);\n if (tem != null) {\n match.splice(1, 1, tem[1]);\n }\n var name = match[0];\n version = match[1] != null ? parseFloat(match[1]) : 0;\n browserInfo = { name: name, version: version };\n return browserInfo;\n}\nfunction isBrowserIE() {\n if (isIE === undefined) {\n isIE = /*@cc_on!@*/ !!document.documentMode; // At least IE6\n }\n return isIE;\n}\nfunction isBrowserEdge() {\n if (isEdge === undefined) {\n isEdge = !isBrowserIE() && !!window.StyleMedia;\n }\n return isEdge;\n}\nfunction isBrowserSafari() {\n if (isSafari === undefined) {\n // taken from https://stackoverflow.com/a/23522755/1388233\n isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n }\n return isSafari;\n}\nfunction isBrowserChrome() {\n if (isChrome === undefined) {\n var win = window;\n isChrome = (!!win.chrome && (!!win.chrome.webstore || !!win.chrome.runtime)) ||\n (/Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor));\n }\n return isChrome;\n}\nfunction isBrowserFirefox() {\n if (isFirefox === undefined) {\n var win = window;\n isFirefox = typeof win.InstallTrigger !== 'undefined';\n }\n return isFirefox;\n}\nfunction isMacOsUserAgent() {\n if (isMacOs === undefined) {\n isMacOs = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\n }\n return isMacOs;\n}\nfunction isIOSUserAgent() {\n if (isIOS === undefined) {\n // taken from https://stackoverflow.com/a/58064481/1388233\n isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||\n // eslint-disable-next-line\n (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&\n // @ts-ignore\n !window.MSStream;\n }\n return isIOS;\n}\nfunction browserSupportsPreventScroll() {\n // all browsers except safari support focus({ preventScroll: true }).\n // this feature was added on Safari 15+\n return !isBrowserSafari() || getBrowserInfo().version >= 15;\n}\nfunction getTabIndex(el) {\n if (!el) {\n return null;\n }\n var numberTabIndex = el.tabIndex;\n var tabIndex = el.getAttribute('tabIndex');\n if (numberTabIndex === -1 && (tabIndex === null || (tabIndex === '' && !isBrowserFirefox()))) {\n return null;\n }\n return numberTabIndex.toString();\n}\nfunction getMaxDivHeight() {\n if (!document.body) {\n return -1;\n }\n var res = 1000000;\n // FF reports the height back but still renders blank after ~6M px\n var testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? 6000000 : 1000000000;\n var div = document.createElement('div');\n document.body.appendChild(div);\n while (true) {\n var test = res * 2;\n div.style.height = test + 'px';\n if (test > testUpTo || div.clientHeight !== test) {\n break;\n }\n else {\n res = test;\n }\n }\n document.body.removeChild(div);\n return res;\n}\nfunction getScrollbarWidth() {\n if (browserScrollbarWidth == null) {\n initScrollbarWidthAndVisibility();\n }\n return browserScrollbarWidth;\n}\nfunction initScrollbarWidthAndVisibility() {\n var body = document.body;\n var div = document.createElement('div');\n div.style.width = div.style.height = '100px';\n div.style.opacity = '0';\n div.style.overflow = 'scroll';\n div.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps\n div.style.position = 'absolute';\n body.appendChild(div);\n var width = div.offsetWidth - div.clientWidth;\n // if width is 0 and client width is 0, means the DOM isn't ready\n if (width === 0 && div.clientWidth === 0) {\n width = null;\n }\n // remove div\n if (div.parentNode) {\n div.parentNode.removeChild(div);\n }\n if (width != null) {\n browserScrollbarWidth = width;\n invisibleScrollbar = width === 0;\n }\n}\nfunction isInvisibleScrollbar() {\n if (invisibleScrollbar == null) {\n initScrollbarWidthAndVisibility();\n }\n return invisibleScrollbar;\n}\n/** @deprecated */\nfunction hasOverflowScrolling() {\n var e_1, _a;\n var prefixes = ['webkit', 'moz', 'o', 'ms'];\n var div = document.createElement('div');\n var body = document.getElementsByTagName('body')[0];\n var found = false;\n var p;\n body.appendChild(div);\n div.setAttribute('style', prefixes.map(function (prefix) { return \"-\" + prefix + \"-overflow-scrolling: touch\"; }).concat('overflow-scrolling: touch').join(';'));\n var computedStyle = window.getComputedStyle(div);\n if (computedStyle.overflowScrolling === 'touch') {\n found = true;\n }\n if (!found) {\n try {\n for (var prefixes_1 = __values$5(prefixes), prefixes_1_1 = prefixes_1.next(); !prefixes_1_1.done; prefixes_1_1 = prefixes_1.next()) {\n p = prefixes_1_1.value;\n if (computedStyle[p + \"OverflowScrolling\"] === 'touch') {\n found = true;\n break;\n }\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (prefixes_1_1 && !prefixes_1_1.done && (_a = prefixes_1.return)) _a.call(prefixes_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n }\n if (div.parentNode) {\n div.parentNode.removeChild(div);\n }\n return found;\n}\n/**\n * Gets the document body width\n * from: http://stackoverflow.com/questions/1038727/how-to-get-browser-width-using-javascript-code\n * @returns {number}\n */\nfunction getBodyWidth() {\n if (document.body) {\n return document.body.clientWidth;\n }\n if (window.innerHeight) {\n return window.innerWidth;\n }\n if (document.documentElement && document.documentElement.clientWidth) {\n return document.documentElement.clientWidth;\n }\n return -1;\n}\n/**\n * Gets the body height\n * from: http://stackoverflow.com/questions/1038727/how-to-get-browser-width-using-javascript-code\n * @returns {number}\n */\nfunction getBodyHeight() {\n if (document.body) {\n return document.body.clientHeight;\n }\n if (window.innerHeight) {\n return window.innerHeight;\n }\n if (document.documentElement && document.documentElement.clientHeight) {\n return document.documentElement.clientHeight;\n }\n return -1;\n}\n\nvar BrowserUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n getBrowserInfo: getBrowserInfo,\n isBrowserEdge: isBrowserEdge,\n isBrowserSafari: isBrowserSafari,\n isBrowserChrome: isBrowserChrome,\n isBrowserFirefox: isBrowserFirefox,\n isMacOsUserAgent: isMacOsUserAgent,\n isIOSUserAgent: isIOSUserAgent,\n browserSupportsPreventScroll: browserSupportsPreventScroll,\n getTabIndex: getTabIndex,\n getMaxDivHeight: getMaxDivHeight,\n getScrollbarWidth: getScrollbarWidth,\n isInvisibleScrollbar: isInvisibleScrollbar,\n hasOverflowScrolling: hasOverflowScrolling,\n getBodyWidth: getBodyWidth,\n getBodyHeight: getBodyHeight\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction fuzzyCheckStrings(inputValues, validValues, allSuggestions) {\n var fuzzyMatches = {};\n var invalidInputs = inputValues.filter(function (inputValue) {\n return !validValues.some(function (validValue) { return validValue === inputValue; });\n });\n if (invalidInputs.length > 0) {\n invalidInputs.forEach(function (invalidInput) {\n return fuzzyMatches[invalidInput] = fuzzySuggestions(invalidInput, allSuggestions);\n });\n }\n return fuzzyMatches;\n}\n/**\n *\n * @param {String} inputValue The value to be compared against a list of strings\n * @param allSuggestions The list of strings to be compared against\n * @param hideIrrelevant By default, fuzzy suggestions will just sort the allSuggestions list, set this to true\n * to filter out the irrelevant values\n * @param weighted Set this to true, to make letters matched in the order they were typed have priority in the results.\n */\nfunction fuzzySuggestions(inputValue, allSuggestions, hideIrrelevant, weighted) {\n var search = weighted ? string_weighted_distances : string_distances;\n var thisSuggestions = allSuggestions.map(function (text) { return ({\n value: text,\n relevance: search(inputValue.toLowerCase(), text.toLocaleLowerCase())\n }); });\n thisSuggestions.sort(function (a, b) { return b.relevance - a.relevance; });\n if (hideIrrelevant) {\n thisSuggestions = thisSuggestions.filter(function (suggestion) { return suggestion.relevance !== 0; });\n }\n return thisSuggestions.map(function (suggestion) { return suggestion.value; });\n}\n/**\n * Algorithm to do fuzzy search\n * from https://stackoverflow.com/questions/23305000/javascript-fuzzy-search-that-makes-sense\n * @param {string} from\n * @return {[]}\n */\nfunction get_bigrams(from) {\n var s = from.toLowerCase();\n var v = new Array(s.length - 1);\n var i;\n var j;\n var ref;\n for (i = j = 0, ref = v.length; j <= ref; i = j += 1) {\n v[i] = s.slice(i, i + 2);\n }\n return v;\n}\nfunction string_distances(str1, str2) {\n if (str1.length === 0 && str2.length === 0) {\n return 0;\n }\n var pairs1 = get_bigrams(str1);\n var pairs2 = get_bigrams(str2);\n var union = pairs1.length + pairs2.length;\n var hit_count = 0;\n var j;\n var len;\n for (j = 0, len = pairs1.length; j < len; j++) {\n var x = pairs1[j];\n var k = void 0;\n var len1 = void 0;\n for (k = 0, len1 = pairs2.length; k < len1; k++) {\n var y = pairs2[k];\n if (x === y) {\n hit_count++;\n }\n }\n }\n return hit_count > 0 ? (2 * hit_count) / union : 0;\n}\nfunction string_weighted_distances(str1, str2) {\n var a = str1.replace(/\\s/g, '');\n var b = str2.replace(/\\s/g, '');\n var weight = 0;\n var lastIndex = 0;\n for (var i = 0; i < a.length; i++) {\n var idx = b.indexOf(a[i], lastIndex);\n if (idx === -1) {\n continue;\n }\n lastIndex = idx;\n weight += (100 - (lastIndex * 100 / 10000) * 100);\n }\n return weight;\n}\n\nvar FuzzyMatchUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n fuzzyCheckStrings: fuzzyCheckStrings,\n fuzzySuggestions: fuzzySuggestions,\n get_bigrams: get_bigrams,\n string_distances: string_distances,\n string_weighted_distances: string_weighted_distances\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction padStartWidthZeros(value, totalStringSize) {\n return value.toString().padStart(totalStringSize, '0');\n}\nfunction createArrayOfNumbers(first, last) {\n var result = [];\n for (var i = first; i <= last; i++) {\n result.push(i);\n }\n return result;\n}\n/**\n * Check if a value is numeric\n * from http://stackoverflow.com/questions/9716468/is-there-any-function-like-isnumeric-in-javascript-to-validate-numbers\n * @param {any} value\n * @return {boolean}\n */\nfunction isNumeric(value) {\n return value !== '' && !isNaN(parseFloat(value)) && isFinite(value);\n}\nfunction cleanNumber(value) {\n if (typeof value === 'string') {\n value = parseInt(value, 10);\n }\n if (typeof value === 'number') {\n return Math.floor(value);\n }\n return null;\n}\nfunction decToHex(number, bytes) {\n var hex = '';\n for (var i = 0; i < bytes; i++) {\n hex += String.fromCharCode(number & 0xff);\n number >>>= 8;\n }\n return hex;\n}\nfunction formatNumberTwoDecimalPlacesAndCommas(value, thousandSeparator, decimalSeparator) {\n if (typeof value !== 'number') {\n return '';\n }\n return formatNumberCommas(Math.round(value * 100) / 100, thousandSeparator, decimalSeparator);\n}\n/**\n * the native method number.toLocaleString(undefined, {minimumFractionDigits: 0})\n * puts in decimal places in IE, so we use this method instead\n * from: http://blog.tompawlak.org/number-currency-formatting-javascript\n * @param {number} value\n * @returns {string}\n */\nfunction formatNumberCommas(value, thousandSeparator, decimalSeparator) {\n if (typeof value !== 'number') {\n return '';\n }\n return value.toString().replace('.', decimalSeparator).replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, \"$1\" + thousandSeparator);\n}\nfunction sum(values) {\n return values == null ? null : values.reduce(function (total, value) { return total + value; }, 0);\n}\n\nvar NumberUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n padStartWidthZeros: padStartWidthZeros,\n createArrayOfNumbers: createArrayOfNumbers,\n isNumeric: isNumeric,\n cleanNumber: cleanNumber,\n decToHex: decToHex,\n formatNumberTwoDecimalPlacesAndCommas: formatNumberTwoDecimalPlacesAndCommas,\n formatNumberCommas: formatNumberCommas,\n sum: sum\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __assign$g = (undefined && undefined.__assign) || function () {\n __assign$g = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$g.apply(this, arguments);\n};\nvar __decorate$2v = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$8 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __read$m = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$g = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$m(arguments[i]));\n return ar;\n};\nvar DEFAULT_ROW_HEIGHT = 25;\nvar DEFAULT_DETAIL_ROW_HEIGHT = 300;\nvar DEFAULT_VIEWPORT_ROW_MODEL_PAGE_SIZE = 5;\nvar DEFAULT_VIEWPORT_ROW_MODEL_BUFFER_SIZE = 5;\nvar DEFAULT_KEEP_DETAIL_ROW_COUNT = 10;\nfunction isTrue(value) {\n return value === true || value === 'true';\n}\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (typeof value == 'string') {\n return parseInt(value, 10);\n }\n}\nfunction zeroOrGreater(value, defaultValue) {\n if (value >= 0) {\n return value;\n }\n // zero gets returned if number is missing or the wrong type\n return defaultValue;\n}\nfunction oneOrGreater(value, defaultValue) {\n var valueNumber = parseInt(value, 10);\n if (isNumeric(valueNumber) && valueNumber > 0) {\n return valueNumber;\n }\n return defaultValue;\n}\nvar GridOptionsWrapper = /** @class */ (function () {\n function GridOptionsWrapper() {\n this.propertyEventService = new EventService();\n this.domDataKey = '__AG_' + Math.random().toString();\n this.destroyed = false;\n }\n GridOptionsWrapper_1 = GridOptionsWrapper;\n GridOptionsWrapper.prototype.agWire = function (gridApi, columnApi) {\n this.gridOptions.api = gridApi;\n this.gridOptions.columnApi = columnApi;\n this.checkForDeprecated();\n this.checkForViolations();\n };\n GridOptionsWrapper.prototype.destroy = function () {\n // need to remove these, as we don't own the lifecycle of the gridOptions, we need to\n // remove the references in case the user keeps the grid options, we want the rest\n // of the grid to be picked up by the garbage collector\n this.gridOptions.api = null;\n this.gridOptions.columnApi = null;\n this.destroyed = true;\n };\n GridOptionsWrapper.prototype.init = function () {\n var _this = this;\n if (this.gridOptions.suppressPropertyNamesCheck !== true) {\n this.checkGridOptionsProperties();\n this.checkColumnDefProperties();\n }\n // parse side bar options into correct format\n if (this.gridOptions.sideBar != null) {\n this.gridOptions.sideBar = SideBarDefParser.parse(this.gridOptions.sideBar);\n }\n var async = this.useAsyncEvents();\n this.eventService.addGlobalListener(this.globalEventHandler.bind(this), async);\n if (this.isGroupSelectsChildren() && this.isSuppressParentsInRowNodes()) {\n console.warn(\"AG Grid: 'groupSelectsChildren' does not work with 'suppressParentsInRowNodes', this selection method needs the part in rowNode to work\");\n }\n if (this.isGroupSelectsChildren()) {\n if (!this.isRowSelectionMulti()) {\n console.warn(\"AG Grid: rowSelection must be 'multiple' for groupSelectsChildren to make sense\");\n }\n if (this.isRowModelServerSide()) {\n console.warn('AG Grid: group selects children is NOT support for Server Side Row Model. ' +\n 'This is because the rows are lazy loaded, so selecting a group is not possible as' +\n 'the grid has no way of knowing what the children are.');\n }\n }\n if (this.isGroupRemoveSingleChildren() && this.isGroupHideOpenParents()) {\n console.warn(\"AG Grid: groupRemoveSingleChildren and groupHideOpenParents do not work with each other, you need to pick one. And don't ask us how to use these together on our support forum either, you will get the same answer!\");\n }\n if (this.isRowModelServerSide()) {\n var msg = function (prop) { return \"AG Grid: '\" + prop + \"' is not supported on the Server-Side Row Model\"; };\n if (exists(this.gridOptions.groupDefaultExpanded)) {\n console.warn(msg('groupDefaultExpanded'));\n }\n if (exists(this.gridOptions.groupDefaultExpanded)) {\n console.warn(msg('groupIncludeFooter'));\n }\n if (exists(this.gridOptions.groupDefaultExpanded)) {\n console.warn(msg('groupIncludeTotalFooter'));\n }\n }\n if (isTrue(this.gridOptions.enableRangeSelection)) {\n ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'enableRangeSelection');\n }\n else if (this.isEnableRangeHandle() || this.isEnableFillHandle()) {\n console.warn(\"AG Grid: 'enableRangeHandle' or 'enableFillHandle' will not work unless 'enableRangeSelection' is set to true\");\n }\n if (this.isGroupRowsSticky()) {\n if (this.isGroupHideOpenParents()) {\n console.warn(\"AG Grid: groupRowsSticky and groupHideOpenParents do not work with each other, you need to pick one.\");\n }\n if (this.isMasterDetail()) {\n console.warn(\"AG Grid: groupRowsSticky and masterDetail do not work with each other, you need to pick one.\");\n }\n if (this.isPagination()) {\n console.warn(\"AG Grid: groupRowsSticky and pagination do not work with each other, you need to pick one.\");\n }\n }\n var warnOfDeprecaredIcon = function (name) {\n if (_this.gridOptions.icons && _this.gridOptions.icons[name]) {\n console.warn(\"gridOptions.icons.\" + name + \" is no longer supported. For information on how to style checkboxes and radio buttons, see https://www.ag-grid.com/javascript-grid-icons/\");\n }\n };\n warnOfDeprecaredIcon('radioButtonOff');\n warnOfDeprecaredIcon('radioButtonOn');\n warnOfDeprecaredIcon('checkboxChecked');\n warnOfDeprecaredIcon('checkboxUnchecked');\n warnOfDeprecaredIcon('checkboxIndeterminate');\n // sets an initial calculation for the scrollbar width\n this.getScrollbarWidth();\n };\n GridOptionsWrapper.prototype.checkColumnDefProperties = function () {\n var _this = this;\n if (this.gridOptions.columnDefs == null) {\n return;\n }\n this.gridOptions.columnDefs.forEach(function (colDef) {\n var userProperties = Object.getOwnPropertyNames(colDef);\n var validProperties = __spread$g(ColDefUtil.ALL_PROPERTIES, ColDefUtil.FRAMEWORK_PROPERTIES);\n _this.checkProperties(userProperties, validProperties, validProperties, 'colDef', 'https://www.ag-grid.com/javascript-grid-column-properties/');\n });\n };\n GridOptionsWrapper.prototype.checkGridOptionsProperties = function () {\n var userProperties = Object.getOwnPropertyNames(this.gridOptions);\n var validProperties = __spread$g(PropertyKeys.ALL_PROPERTIES, PropertyKeys.FRAMEWORK_PROPERTIES, values(Events).map(function (event) { return ComponentUtil.getCallbackForEvent(event); }));\n var validPropertiesAndExceptions = __spread$g(validProperties, ['api', 'columnApi']);\n this.checkProperties(userProperties, validPropertiesAndExceptions, validProperties, 'gridOptions', 'https://www.ag-grid.com/javascript-data-grid/grid-options/');\n };\n GridOptionsWrapper.prototype.checkProperties = function (userProperties, validPropertiesAndExceptions, validProperties, containerName, docsUrl) {\n var invalidProperties = fuzzyCheckStrings(userProperties, validPropertiesAndExceptions, validProperties);\n iterateObject(invalidProperties, function (key, value) {\n console.warn(\"ag-grid: invalid \" + containerName + \" property '\" + key + \"' did you mean any of these: \" + value.slice(0, 8).join(\", \"));\n });\n if (Object.keys(invalidProperties).length > 0) {\n console.warn(\"ag-grid: to see all the valid \" + containerName + \" properties please check: \" + docsUrl);\n }\n };\n /**\n * Wrap the user callback and attach the api, columnApi and context to the params object on the way through.\n * @param callback User provided callback\n * @returns Wrapped callback where the params object not require api, columnApi and context\n */\n GridOptionsWrapper.prototype.mergeGridCommonParams = function (callback) {\n var _this = this;\n if (callback) {\n var wrapped = function (callbackParams) {\n var mergedParams = __assign$g(__assign$g({}, callbackParams), { api: _this.getApi(), columnApi: _this.getColumnApi(), context: _this.getContext() });\n return callback(mergedParams);\n };\n return wrapped;\n }\n return callback;\n };\n GridOptionsWrapper.prototype.getDomDataKey = function () {\n return this.domDataKey;\n };\n // returns the dom data, or undefined if not found\n GridOptionsWrapper.prototype.getDomData = function (element, key) {\n var domData = element[this.getDomDataKey()];\n return domData ? domData[key] : undefined;\n };\n GridOptionsWrapper.prototype.setDomData = function (element, key, value) {\n var domDataKey = this.getDomDataKey();\n var domData = element[domDataKey];\n if (missing(domData)) {\n domData = {};\n element[domDataKey] = domData;\n }\n domData[key] = value;\n };\n GridOptionsWrapper.prototype.isRowSelection = function () {\n return this.gridOptions.rowSelection === 'single' || this.gridOptions.rowSelection === 'multiple';\n };\n GridOptionsWrapper.prototype.isSuppressRowDeselection = function () {\n return isTrue(this.gridOptions.suppressRowDeselection);\n };\n GridOptionsWrapper.prototype.isRowSelectionMulti = function () {\n return this.gridOptions.rowSelection === 'multiple';\n };\n GridOptionsWrapper.prototype.isRowMultiSelectWithClick = function () {\n return isTrue(this.gridOptions.rowMultiSelectWithClick);\n };\n GridOptionsWrapper.prototype.getContext = function () {\n return this.gridOptions.context;\n };\n GridOptionsWrapper.prototype.isPivotMode = function () {\n return isTrue(this.gridOptions.pivotMode);\n };\n GridOptionsWrapper.prototype.isSuppressExpandablePivotGroups = function () {\n return isTrue(this.gridOptions.suppressExpandablePivotGroups);\n };\n GridOptionsWrapper.prototype.getPivotColumnGroupTotals = function () {\n return this.gridOptions.pivotColumnGroupTotals;\n };\n GridOptionsWrapper.prototype.getPivotRowTotals = function () {\n return this.gridOptions.pivotRowTotals;\n };\n GridOptionsWrapper.prototype.isRowModelInfinite = function () {\n return this.gridOptions.rowModelType === Constants.ROW_MODEL_TYPE_INFINITE;\n };\n GridOptionsWrapper.prototype.isRowModelViewport = function () {\n return this.gridOptions.rowModelType === Constants.ROW_MODEL_TYPE_VIEWPORT;\n };\n GridOptionsWrapper.prototype.isRowModelServerSide = function () {\n return this.gridOptions.rowModelType === Constants.ROW_MODEL_TYPE_SERVER_SIDE;\n };\n GridOptionsWrapper.prototype.isRowModelDefault = function () {\n return (missing(this.gridOptions.rowModelType) ||\n this.gridOptions.rowModelType === Constants.ROW_MODEL_TYPE_CLIENT_SIDE);\n };\n GridOptionsWrapper.prototype.isFullRowEdit = function () {\n return this.gridOptions.editType === 'fullRow';\n };\n GridOptionsWrapper.prototype.isSuppressFocusAfterRefresh = function () {\n return isTrue(this.gridOptions.suppressFocusAfterRefresh);\n };\n GridOptionsWrapper.prototype.isSuppressBrowserResizeObserver = function () {\n return isTrue(this.gridOptions.suppressBrowserResizeObserver);\n };\n GridOptionsWrapper.prototype.isSuppressMaintainUnsortedOrder = function () {\n return isTrue(this.gridOptions.suppressMaintainUnsortedOrder);\n };\n GridOptionsWrapper.prototype.isSuppressClearOnFillReduction = function () {\n return isTrue(this.gridOptions.suppressClearOnFillReduction);\n };\n GridOptionsWrapper.prototype.isShowToolPanel = function () {\n return isTrue(this.gridOptions.sideBar && Array.isArray(this.getSideBar().toolPanels));\n };\n GridOptionsWrapper.prototype.getSideBar = function () {\n return this.gridOptions.sideBar;\n };\n GridOptionsWrapper.prototype.isSuppressTouch = function () {\n return isTrue(this.gridOptions.suppressTouch);\n };\n GridOptionsWrapper.prototype.isMaintainColumnOrder = function () {\n return isTrue(this.gridOptions.maintainColumnOrder);\n };\n GridOptionsWrapper.prototype.isSuppressRowTransform = function () {\n return isTrue(this.gridOptions.suppressRowTransform);\n };\n GridOptionsWrapper.prototype.isSuppressColumnStateEvents = function () {\n return isTrue(this.gridOptions.suppressColumnStateEvents);\n };\n GridOptionsWrapper.prototype.isAllowDragFromColumnsToolPanel = function () {\n return isTrue(this.gridOptions.allowDragFromColumnsToolPanel);\n };\n GridOptionsWrapper.prototype.useAsyncEvents = function () {\n return !isTrue(this.gridOptions.suppressAsyncEvents);\n };\n GridOptionsWrapper.prototype.isEnableCellChangeFlash = function () {\n return isTrue(this.gridOptions.enableCellChangeFlash);\n };\n GridOptionsWrapper.prototype.getCellFlashDelay = function () {\n return this.gridOptions.cellFlashDelay || 500;\n };\n GridOptionsWrapper.prototype.getCellFadeDelay = function () {\n return this.gridOptions.cellFadeDelay || 1000;\n };\n GridOptionsWrapper.prototype.isGroupSelectsChildren = function () {\n return isTrue(this.gridOptions.groupSelectsChildren);\n };\n GridOptionsWrapper.prototype.isSuppressRowHoverHighlight = function () {\n return isTrue(this.gridOptions.suppressRowHoverHighlight);\n };\n GridOptionsWrapper.prototype.isColumnHoverHighlight = function () {\n return isTrue(this.gridOptions.columnHoverHighlight);\n };\n GridOptionsWrapper.prototype.isGroupSelectsFiltered = function () {\n return isTrue(this.gridOptions.groupSelectsFiltered);\n };\n GridOptionsWrapper.prototype.isGroupHideOpenParents = function () {\n return isTrue(this.gridOptions.groupHideOpenParents);\n };\n GridOptionsWrapper.prototype.isGroupMaintainOrder = function () {\n return isTrue(this.gridOptions.groupMaintainOrder);\n };\n GridOptionsWrapper.prototype.getAutoGroupColumnDef = function () {\n return this.gridOptions.autoGroupColumnDef;\n };\n GridOptionsWrapper.prototype.isColumnsSortingCoupledToGroup = function () {\n var _a;\n var autoGroupColumnDef = this.getAutoGroupColumnDef();\n var isClientSideRowModel = this.isRowModelDefault();\n return isClientSideRowModel && !((_a = autoGroupColumnDef) === null || _a === void 0 ? void 0 : _a.comparator);\n };\n GridOptionsWrapper.prototype.isGroupMultiAutoColumn = function () {\n if (this.gridOptions.groupDisplayType) {\n return this.matchesGroupDisplayType('multipleColumns', this.gridOptions.groupDisplayType);\n }\n // if we are doing hideOpenParents we also show multiple columns, otherwise hideOpenParents would not work\n return isTrue(this.gridOptions.groupHideOpenParents);\n };\n GridOptionsWrapper.prototype.isGroupUseEntireRow = function (pivotMode) {\n // we never allow groupUseEntireRow if in pivot mode, otherwise we won't see the pivot values.\n if (pivotMode) {\n return false;\n }\n return this.gridOptions.groupDisplayType ?\n this.matchesGroupDisplayType('groupRows', this.gridOptions.groupDisplayType) : false;\n };\n GridOptionsWrapper.prototype.isRowGroupPanelSuppressSort = function () {\n return isTrue(this.gridOptions.rowGroupPanelSuppressSort);\n };\n GridOptionsWrapper.prototype.isGroupRowsSticky = function () {\n return isTrue(this.gridOptions.groupRowsSticky);\n };\n GridOptionsWrapper.prototype.isGroupSuppressAutoColumn = function () {\n var isCustomRowGroups = this.gridOptions.groupDisplayType ?\n this.matchesGroupDisplayType('custom', this.gridOptions.groupDisplayType) : false;\n if (isCustomRowGroups) {\n return true;\n }\n return this.gridOptions.treeDataDisplayType ?\n this.matchesTreeDataDisplayType('custom', this.gridOptions.treeDataDisplayType) : false;\n };\n GridOptionsWrapper.prototype.isGroupRemoveSingleChildren = function () {\n return isTrue(this.gridOptions.groupRemoveSingleChildren);\n };\n GridOptionsWrapper.prototype.isGroupRemoveLowestSingleChildren = function () {\n return isTrue(this.gridOptions.groupRemoveLowestSingleChildren);\n };\n GridOptionsWrapper.prototype.isGroupIncludeFooter = function () {\n return isTrue(this.gridOptions.groupIncludeFooter);\n };\n GridOptionsWrapper.prototype.isGroupIncludeTotalFooter = function () {\n return isTrue(this.gridOptions.groupIncludeTotalFooter);\n };\n GridOptionsWrapper.prototype.isGroupSuppressBlankHeader = function () {\n return isTrue(this.gridOptions.groupSuppressBlankHeader);\n };\n GridOptionsWrapper.prototype.isSuppressRowClickSelection = function () {\n return isTrue(this.gridOptions.suppressRowClickSelection);\n };\n GridOptionsWrapper.prototype.isSuppressCellFocus = function () {\n return isTrue(this.gridOptions.suppressCellFocus);\n };\n GridOptionsWrapper.prototype.isSuppressMultiSort = function () {\n return isTrue(this.gridOptions.suppressMultiSort);\n };\n GridOptionsWrapper.prototype.isAlwaysMultiSort = function () {\n return isTrue(this.gridOptions.alwaysMultiSort);\n };\n GridOptionsWrapper.prototype.isMultiSortKeyCtrl = function () {\n return this.gridOptions.multiSortKey === 'ctrl';\n };\n GridOptionsWrapper.prototype.isPivotSuppressAutoColumn = function () {\n return isTrue(this.gridOptions.pivotSuppressAutoColumn);\n };\n GridOptionsWrapper.prototype.isSuppressDragLeaveHidesColumns = function () {\n return isTrue(this.gridOptions.suppressDragLeaveHidesColumns);\n };\n GridOptionsWrapper.prototype.isSuppressRowGroupHidesColumns = function () {\n return isTrue(this.gridOptions.suppressRowGroupHidesColumns);\n };\n GridOptionsWrapper.prototype.isSuppressScrollOnNewData = function () {\n return isTrue(this.gridOptions.suppressScrollOnNewData);\n };\n GridOptionsWrapper.prototype.isSuppressScrollWhenPopupsAreOpen = function () {\n return isTrue(this.gridOptions.suppressScrollWhenPopupsAreOpen);\n };\n GridOptionsWrapper.prototype.isRowDragEntireRow = function () {\n return isTrue(this.gridOptions.rowDragEntireRow);\n };\n GridOptionsWrapper.prototype.getRowDragText = function (column) {\n if (column) {\n var colDef = column.getColDef();\n if (colDef.rowDragText) {\n return colDef.rowDragText;\n }\n }\n return this.gridOptions.rowDragText;\n };\n GridOptionsWrapper.prototype.isSuppressRowDrag = function () {\n return isTrue(this.gridOptions.suppressRowDrag);\n };\n GridOptionsWrapper.prototype.isRowDragManaged = function () {\n return isTrue(this.gridOptions.rowDragManaged);\n };\n GridOptionsWrapper.prototype.isSuppressMoveWhenRowDragging = function () {\n return isTrue(this.gridOptions.suppressMoveWhenRowDragging);\n };\n GridOptionsWrapper.prototype.isRowDragMultiRow = function () {\n return isTrue(this.gridOptions.rowDragMultiRow);\n };\n // returns either 'print', 'autoHeight' or 'normal' (normal is the default)\n GridOptionsWrapper.prototype.getDomLayout = function () {\n var domLayout = this.gridOptions.domLayout || Constants.DOM_LAYOUT_NORMAL;\n var validLayouts = [\n Constants.DOM_LAYOUT_PRINT,\n Constants.DOM_LAYOUT_AUTO_HEIGHT,\n Constants.DOM_LAYOUT_NORMAL\n ];\n if (validLayouts.indexOf(domLayout) === -1) {\n doOnce(function () {\n return console.warn(\"AG Grid: \" + domLayout + \" is not valid for DOM Layout, valid values are \" + Constants.DOM_LAYOUT_NORMAL + \", \" + Constants.DOM_LAYOUT_AUTO_HEIGHT + \" and \" + Constants.DOM_LAYOUT_PRINT);\n }, 'warn about dom layout values');\n return Constants.DOM_LAYOUT_NORMAL;\n }\n return domLayout;\n };\n GridOptionsWrapper.prototype.isSuppressHorizontalScroll = function () {\n return isTrue(this.gridOptions.suppressHorizontalScroll);\n };\n GridOptionsWrapper.prototype.isSuppressMaxRenderedRowRestriction = function () {\n return isTrue(this.gridOptions.suppressMaxRenderedRowRestriction);\n };\n GridOptionsWrapper.prototype.isExcludeChildrenWhenTreeDataFiltering = function () {\n return isTrue(this.gridOptions.excludeChildrenWhenTreeDataFiltering);\n };\n GridOptionsWrapper.prototype.isAlwaysShowHorizontalScroll = function () {\n return isTrue(this.gridOptions.alwaysShowHorizontalScroll);\n };\n GridOptionsWrapper.prototype.isAlwaysShowVerticalScroll = function () {\n return isTrue(this.gridOptions.alwaysShowVerticalScroll);\n };\n GridOptionsWrapper.prototype.isDebounceVerticalScrollbar = function () {\n return isTrue(this.gridOptions.debounceVerticalScrollbar);\n };\n GridOptionsWrapper.prototype.isSuppressLoadingOverlay = function () {\n return isTrue(this.gridOptions.suppressLoadingOverlay);\n };\n GridOptionsWrapper.prototype.isSuppressNoRowsOverlay = function () {\n return isTrue(this.gridOptions.suppressNoRowsOverlay);\n };\n GridOptionsWrapper.prototype.isSuppressFieldDotNotation = function () {\n return isTrue(this.gridOptions.suppressFieldDotNotation);\n };\n GridOptionsWrapper.prototype.getPinnedTopRowData = function () {\n return this.gridOptions.pinnedTopRowData;\n };\n GridOptionsWrapper.prototype.getPinnedBottomRowData = function () {\n return this.gridOptions.pinnedBottomRowData;\n };\n GridOptionsWrapper.prototype.isFunctionsPassive = function () {\n return isTrue(this.gridOptions.functionsPassive);\n };\n GridOptionsWrapper.prototype.isSuppressChangeDetection = function () {\n return isTrue(this.gridOptions.suppressChangeDetection);\n };\n GridOptionsWrapper.prototype.isSuppressAnimationFrame = function () {\n return isTrue(this.gridOptions.suppressAnimationFrame);\n };\n GridOptionsWrapper.prototype.getQuickFilterText = function () {\n return this.gridOptions.quickFilterText;\n };\n GridOptionsWrapper.prototype.isCacheQuickFilter = function () {\n return isTrue(this.gridOptions.cacheQuickFilter);\n };\n GridOptionsWrapper.prototype.isUnSortIcon = function () {\n return isTrue(this.gridOptions.unSortIcon);\n };\n GridOptionsWrapper.prototype.isSuppressMenuHide = function () {\n return isTrue(this.gridOptions.suppressMenuHide);\n };\n GridOptionsWrapper.prototype.isEnterMovesDownAfterEdit = function () {\n return isTrue(this.gridOptions.enterMovesDownAfterEdit);\n };\n GridOptionsWrapper.prototype.isEnterMovesDown = function () {\n return isTrue(this.gridOptions.enterMovesDown);\n };\n GridOptionsWrapper.prototype.isUndoRedoCellEditing = function () {\n return isTrue(this.gridOptions.undoRedoCellEditing);\n };\n GridOptionsWrapper.prototype.getUndoRedoCellEditingLimit = function () {\n return toNumber(this.gridOptions.undoRedoCellEditingLimit);\n };\n GridOptionsWrapper.prototype.isEnableCellEditingOnBackspace = function () {\n return isTrue(this.gridOptions.enableCellEditingOnBackspace);\n };\n GridOptionsWrapper.prototype.getRowStyle = function () {\n return this.gridOptions.rowStyle;\n };\n GridOptionsWrapper.prototype.getRowClass = function () {\n return this.gridOptions.rowClass;\n };\n GridOptionsWrapper.prototype.getRowStyleFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.getRowStyle);\n };\n GridOptionsWrapper.prototype.getRowClassFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.getRowClass);\n };\n GridOptionsWrapper.prototype.rowClassRules = function () {\n return this.gridOptions.rowClassRules;\n };\n GridOptionsWrapper.prototype.isServerSideInfiniteScroll = function () {\n return isTrue(this.gridOptions.serverSideInfiniteScroll);\n };\n GridOptionsWrapper.prototype.getServerSideGroupLevelParamsFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.getServerSideGroupLevelParams);\n };\n GridOptionsWrapper.prototype.getCreateChartContainerFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.createChartContainer);\n };\n GridOptionsWrapper.prototype.getPopupParent = function () {\n return this.gridOptions.popupParent;\n };\n GridOptionsWrapper.prototype.getBlockLoadDebounceMillis = function () {\n return this.gridOptions.blockLoadDebounceMillis;\n };\n GridOptionsWrapper.prototype.getPostProcessPopupFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.postProcessPopup);\n };\n GridOptionsWrapper.prototype.getPaginationNumberFormatterFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.paginationNumberFormatter);\n };\n GridOptionsWrapper.prototype.getChildCountFunc = function () {\n return this.gridOptions.getChildCount;\n };\n GridOptionsWrapper.prototype.getIsApplyServerSideTransactionFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.isApplyServerSideTransaction);\n };\n GridOptionsWrapper.prototype.getInitialGroupOrderComparator = function () {\n var _a = this.gridOptions, initialGroupOrderComparator = _a.initialGroupOrderComparator, defaultGroupOrderComparator = _a.defaultGroupOrderComparator;\n if (initialGroupOrderComparator) {\n return this.mergeGridCommonParams(initialGroupOrderComparator);\n }\n // this is the deprecated way, so provide a proxy to make it compatible\n if (defaultGroupOrderComparator) {\n return function (params) { return defaultGroupOrderComparator(params.nodeA, params.nodeB); };\n }\n };\n GridOptionsWrapper.prototype.getIsFullWidthCellFunc = function () {\n var _a = this.gridOptions, isFullWidthRow = _a.isFullWidthRow, isFullWidthCell = _a.isFullWidthCell;\n if (isFullWidthRow) {\n return this.mergeGridCommonParams(isFullWidthRow);\n }\n // this is the deprecated way, so provide a proxy to make it compatible\n if (isFullWidthCell) {\n return function (params) { return isFullWidthCell(params.rowNode); };\n }\n };\n GridOptionsWrapper.prototype.getFullWidthCellRendererParams = function () {\n return this.gridOptions.fullWidthCellRendererParams;\n };\n GridOptionsWrapper.prototype.isEmbedFullWidthRows = function () {\n return isTrue(this.gridOptions.embedFullWidthRows) || isTrue(this.gridOptions.deprecatedEmbedFullWidthRows);\n };\n GridOptionsWrapper.prototype.isDetailRowAutoHeight = function () {\n return isTrue(this.gridOptions.detailRowAutoHeight);\n };\n GridOptionsWrapper.prototype.getSuppressKeyboardEventFunc = function () {\n return this.gridOptions.suppressKeyboardEvent;\n };\n GridOptionsWrapper.prototype.getBusinessKeyForNodeFunc = function () {\n return this.gridOptions.getBusinessKeyForNode;\n };\n GridOptionsWrapper.prototype.getApi = function () {\n return this.gridOptions.api;\n };\n GridOptionsWrapper.prototype.getColumnApi = function () {\n return this.gridOptions.columnApi;\n };\n GridOptionsWrapper.prototype.isReadOnlyEdit = function () {\n return isTrue(this.gridOptions.readOnlyEdit);\n };\n GridOptionsWrapper.prototype.isImmutableData = function () {\n // we used to have a property immutableData for this. however this was deprecated\n // in favour of having Immutable Data on by default when getRowId is provided\n var getRowIdProvided = this.gridOptions.getRowId != null;\n var immutableData = isTrue(this.gridOptions.immutableData);\n // this property is a backwards compatibility property, for those who want\n // the old behaviour of Row ID's but NOT Immutable Data.\n var resetRowDataOnUpdate = isTrue(this.gridOptions.resetRowDataOnUpdate);\n if (resetRowDataOnUpdate) {\n return false;\n }\n return getRowIdProvided || immutableData;\n };\n GridOptionsWrapper.prototype.isEnsureDomOrder = function () {\n return isTrue(this.gridOptions.ensureDomOrder);\n };\n GridOptionsWrapper.prototype.isEnableCharts = function () {\n if (isTrue(this.gridOptions.enableCharts)) {\n return ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'enableCharts');\n }\n return false;\n };\n GridOptionsWrapper.prototype.isEnableChartToolPanelsButton = function () {\n return isTrue(this.gridOptions.enableChartToolPanelsButton);\n };\n GridOptionsWrapper.prototype.getColResizeDefault = function () {\n return this.gridOptions.colResizeDefault;\n };\n GridOptionsWrapper.prototype.isSingleClickEdit = function () {\n return isTrue(this.gridOptions.singleClickEdit);\n };\n GridOptionsWrapper.prototype.isSuppressClickEdit = function () {\n return isTrue(this.gridOptions.suppressClickEdit);\n };\n GridOptionsWrapper.prototype.isStopEditingWhenCellsLoseFocus = function () {\n return isTrue(this.gridOptions.stopEditingWhenCellsLoseFocus);\n };\n GridOptionsWrapper.prototype.getGroupDefaultExpanded = function () {\n return this.gridOptions.groupDefaultExpanded;\n };\n GridOptionsWrapper.prototype.getMaxConcurrentDatasourceRequests = function () {\n var res = toNumber(this.gridOptions.maxConcurrentDatasourceRequests);\n if (res == null) {\n return 2;\n } // 2 is the default\n if (res <= 0) {\n return;\n } // negative number, eg -1, means no max restriction\n return res;\n };\n GridOptionsWrapper.prototype.getMaxBlocksInCache = function () {\n return this.gridOptions.maxBlocksInCache;\n };\n GridOptionsWrapper.prototype.getCacheOverflowSize = function () {\n return this.gridOptions.cacheOverflowSize;\n };\n GridOptionsWrapper.prototype.getPaginationPageSize = function () {\n return toNumber(this.gridOptions.paginationPageSize);\n };\n GridOptionsWrapper.prototype.isPaginateChildRows = function () {\n var shouldPaginate = this.isGroupRemoveSingleChildren() || this.isGroupRemoveLowestSingleChildren();\n if (shouldPaginate) {\n return true;\n }\n return isTrue(this.gridOptions.paginateChildRows);\n };\n GridOptionsWrapper.prototype.getCacheBlockSize = function () {\n return oneOrGreater(this.gridOptions.cacheBlockSize);\n };\n GridOptionsWrapper.prototype.getInfiniteInitialRowCount = function () {\n return this.gridOptions.infiniteInitialRowCount;\n };\n GridOptionsWrapper.prototype.getServerSideInitialRowCount = function () {\n var rowCount = this.gridOptions.serverSideInitialRowCount;\n if (typeof rowCount === 'number' && rowCount > 0) {\n return rowCount;\n }\n return 1;\n };\n GridOptionsWrapper.prototype.isPurgeClosedRowNodes = function () {\n return isTrue(this.gridOptions.purgeClosedRowNodes);\n };\n GridOptionsWrapper.prototype.isSuppressPaginationPanel = function () {\n return isTrue(this.gridOptions.suppressPaginationPanel);\n };\n GridOptionsWrapper.prototype.getRowData = function () {\n return this.gridOptions.rowData;\n };\n GridOptionsWrapper.prototype.isEnableRtl = function () {\n return isTrue(this.gridOptions.enableRtl);\n };\n GridOptionsWrapper.prototype.getRowGroupPanelShow = function () {\n return this.gridOptions.rowGroupPanelShow;\n };\n GridOptionsWrapper.prototype.getPivotPanelShow = function () {\n return this.gridOptions.pivotPanelShow;\n };\n GridOptionsWrapper.prototype.isAngularCompileRows = function () {\n return isTrue(this.gridOptions.angularCompileRows);\n };\n GridOptionsWrapper.prototype.isAngularCompileFilters = function () {\n return isTrue(this.gridOptions.angularCompileFilters);\n };\n GridOptionsWrapper.prototype.isDebug = function () {\n return isTrue(this.gridOptions.debug);\n };\n GridOptionsWrapper.prototype.getColumnDefs = function () {\n return this.gridOptions.columnDefs;\n };\n GridOptionsWrapper.prototype.getColumnTypes = function () {\n return this.gridOptions.columnTypes;\n };\n GridOptionsWrapper.prototype.getDatasource = function () {\n return this.gridOptions.datasource;\n };\n GridOptionsWrapper.prototype.getViewportDatasource = function () {\n return this.gridOptions.viewportDatasource;\n };\n GridOptionsWrapper.prototype.getServerSideDatasource = function () {\n return this.gridOptions.serverSideDatasource;\n };\n GridOptionsWrapper.prototype.isAccentedSort = function () {\n return isTrue(this.gridOptions.accentedSort);\n };\n GridOptionsWrapper.prototype.isEnableBrowserTooltips = function () {\n return isTrue(this.gridOptions.enableBrowserTooltips);\n };\n GridOptionsWrapper.prototype.isEnableCellExpressions = function () {\n return isTrue(this.gridOptions.enableCellExpressions);\n };\n GridOptionsWrapper.prototype.isEnableGroupEdit = function () {\n return isTrue(this.gridOptions.enableGroupEdit);\n };\n GridOptionsWrapper.prototype.isSuppressMiddleClickScrolls = function () {\n return isTrue(this.gridOptions.suppressMiddleClickScrolls);\n };\n GridOptionsWrapper.prototype.isPreventDefaultOnContextMenu = function () {\n return isTrue(this.gridOptions.preventDefaultOnContextMenu);\n };\n GridOptionsWrapper.prototype.isSuppressPreventDefaultOnMouseWheel = function () {\n return isTrue(this.gridOptions.suppressPreventDefaultOnMouseWheel);\n };\n GridOptionsWrapper.prototype.isSuppressColumnVirtualisation = function () {\n return isTrue(this.gridOptions.suppressColumnVirtualisation);\n };\n GridOptionsWrapper.prototype.isSuppressRowVirtualisation = function () {\n return isTrue(this.gridOptions.suppressRowVirtualisation);\n };\n GridOptionsWrapper.prototype.isSuppressContextMenu = function () {\n return isTrue(this.gridOptions.suppressContextMenu);\n };\n GridOptionsWrapper.prototype.isAllowContextMenuWithControlKey = function () {\n return isTrue(this.gridOptions.allowContextMenuWithControlKey);\n };\n GridOptionsWrapper.prototype.isSuppressCopyRowsToClipboard = function () {\n return isTrue(this.gridOptions.suppressCopyRowsToClipboard);\n };\n GridOptionsWrapper.prototype.isSuppressCopySingleCellRanges = function () {\n return isTrue(this.gridOptions.suppressCopySingleCellRanges);\n };\n GridOptionsWrapper.prototype.isCopyHeadersToClipboard = function () {\n return isTrue(this.gridOptions.copyHeadersToClipboard);\n };\n GridOptionsWrapper.prototype.isCopyGroupHeadersToClipboard = function () {\n return isTrue(this.gridOptions.copyGroupHeadersToClipboard);\n };\n GridOptionsWrapper.prototype.isSuppressClipboardPaste = function () {\n return isTrue(this.gridOptions.suppressClipboardPaste);\n };\n GridOptionsWrapper.prototype.isSuppressLastEmptyLineOnPaste = function () {\n return isTrue(this.gridOptions.suppressLastEmptyLineOnPaste);\n };\n GridOptionsWrapper.prototype.isPagination = function () {\n return isTrue(this.gridOptions.pagination);\n };\n GridOptionsWrapper.prototype.isSuppressEnterpriseResetOnNewColumns = function () {\n return isTrue(this.gridOptions.suppressEnterpriseResetOnNewColumns);\n };\n GridOptionsWrapper.prototype.getProcessDataFromClipboardFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.processDataFromClipboard);\n };\n GridOptionsWrapper.prototype.getAsyncTransactionWaitMillis = function () {\n return exists(this.gridOptions.asyncTransactionWaitMillis) ? this.gridOptions.asyncTransactionWaitMillis : Constants.BATCH_WAIT_MILLIS;\n };\n GridOptionsWrapper.prototype.isSuppressMovableColumns = function () {\n return isTrue(this.gridOptions.suppressMovableColumns);\n };\n GridOptionsWrapper.prototype.isAnimateRows = function () {\n // never allow animating if enforcing the row order\n if (this.isEnsureDomOrder()) {\n return false;\n }\n return isTrue(this.gridOptions.animateRows);\n };\n GridOptionsWrapper.prototype.isSuppressColumnMoveAnimation = function () {\n return isTrue(this.gridOptions.suppressColumnMoveAnimation);\n };\n GridOptionsWrapper.prototype.isSuppressAggFuncInHeader = function () {\n return isTrue(this.gridOptions.suppressAggFuncInHeader);\n };\n GridOptionsWrapper.prototype.isSuppressAggAtRootLevel = function () {\n return isTrue(this.gridOptions.suppressAggAtRootLevel);\n };\n GridOptionsWrapper.prototype.isSuppressAggFilteredOnly = function () {\n var isGroupAggFiltering = this.getGroupAggFiltering() !== undefined;\n return isGroupAggFiltering || isTrue(this.gridOptions.suppressAggFilteredOnly);\n };\n GridOptionsWrapper.prototype.isRemovePivotHeaderRowWhenSingleValueColumn = function () {\n return isTrue(this.gridOptions.removePivotHeaderRowWhenSingleValueColumn);\n };\n GridOptionsWrapper.prototype.isShowOpenedGroup = function () {\n return isTrue(this.gridOptions.showOpenedGroup);\n };\n GridOptionsWrapper.prototype.isReactUi = function () {\n return isTrue(this.gridOptions.reactUi);\n };\n GridOptionsWrapper.prototype.isSuppressReactUi = function () {\n return isTrue(this.gridOptions.suppressReactUi);\n };\n GridOptionsWrapper.prototype.isEnableRangeSelection = function () {\n return ModuleRegistry.isRegistered(ModuleNames.RangeSelectionModule) && isTrue(this.gridOptions.enableRangeSelection);\n };\n GridOptionsWrapper.prototype.isEnableRangeHandle = function () {\n return isTrue(this.gridOptions.enableRangeHandle);\n };\n GridOptionsWrapper.prototype.isEnableFillHandle = function () {\n return isTrue(this.gridOptions.enableFillHandle);\n };\n GridOptionsWrapper.prototype.getFillHandleDirection = function () {\n var direction = this.gridOptions.fillHandleDirection;\n if (!direction) {\n return 'xy';\n }\n if (direction !== 'x' && direction !== 'y' && direction !== 'xy') {\n doOnce(function () { return console.warn(\"AG Grid: valid values for fillHandleDirection are 'x', 'y' and 'xy'. Default to 'xy'.\"); }, 'warn invalid fill direction');\n return 'xy';\n }\n return direction;\n };\n GridOptionsWrapper.prototype.getFillOperation = function () {\n return this.mergeGridCommonParams(this.gridOptions.fillOperation);\n };\n GridOptionsWrapper.prototype.isSuppressMultiRangeSelection = function () {\n return isTrue(this.gridOptions.suppressMultiRangeSelection);\n };\n GridOptionsWrapper.prototype.isPaginationAutoPageSize = function () {\n return isTrue(this.gridOptions.paginationAutoPageSize);\n };\n GridOptionsWrapper.prototype.isRememberGroupStateWhenNewData = function () {\n return isTrue(this.gridOptions.rememberGroupStateWhenNewData);\n };\n GridOptionsWrapper.prototype.getIcons = function () {\n return this.gridOptions.icons;\n };\n GridOptionsWrapper.prototype.getGroupAggFiltering = function () {\n var userValue = this.gridOptions.groupAggFiltering;\n if (typeof userValue === 'function') {\n return this.mergeGridCommonParams(userValue);\n }\n if (isTrue(userValue)) {\n return function () { return true; };\n }\n return undefined;\n };\n GridOptionsWrapper.prototype.getAggFuncs = function () {\n return this.gridOptions.aggFuncs;\n };\n GridOptionsWrapper.prototype.getSortingOrder = function () {\n return this.gridOptions.sortingOrder;\n };\n GridOptionsWrapper.prototype.getAlignedGrids = function () {\n return this.gridOptions.alignedGrids;\n };\n GridOptionsWrapper.prototype.isMasterDetail = function () {\n var masterDetail = isTrue(this.gridOptions.masterDetail);\n if (masterDetail) {\n return ModuleRegistry.assertRegistered(ModuleNames.MasterDetailModule, 'masterDetail');\n }\n else {\n return false;\n }\n };\n GridOptionsWrapper.prototype.isKeepDetailRows = function () {\n return isTrue(this.gridOptions.keepDetailRows);\n };\n GridOptionsWrapper.prototype.getKeepDetailRowsCount = function () {\n var keepDetailRowsCount = this.gridOptions.keepDetailRowsCount;\n if (exists(keepDetailRowsCount) && keepDetailRowsCount > 0) {\n return this.gridOptions.keepDetailRowsCount;\n }\n return DEFAULT_KEEP_DETAIL_ROW_COUNT;\n };\n GridOptionsWrapper.prototype.getIsRowMasterFunc = function () {\n return this.gridOptions.isRowMaster;\n };\n GridOptionsWrapper.prototype.getIsRowSelectableFunc = function () {\n return this.gridOptions.isRowSelectable;\n };\n GridOptionsWrapper.prototype.getGroupRowRendererParams = function () {\n return this.gridOptions.groupRowRendererParams;\n };\n GridOptionsWrapper.prototype.getOverlayLoadingTemplate = function () {\n return this.gridOptions.overlayLoadingTemplate;\n };\n GridOptionsWrapper.prototype.getOverlayNoRowsTemplate = function () {\n return this.gridOptions.overlayNoRowsTemplate;\n };\n GridOptionsWrapper.prototype.isSuppressAutoSize = function () {\n return isTrue(this.gridOptions.suppressAutoSize);\n };\n GridOptionsWrapper.prototype.isEnableCellTextSelection = function () {\n return isTrue(this.gridOptions.enableCellTextSelection);\n };\n GridOptionsWrapper.prototype.isSuppressParentsInRowNodes = function () {\n return isTrue(this.gridOptions.suppressParentsInRowNodes);\n };\n GridOptionsWrapper.prototype.isSuppressClipboardApi = function () {\n return isTrue(this.gridOptions.suppressClipboardApi);\n };\n GridOptionsWrapper.prototype.isFunctionsReadOnly = function () {\n return isTrue(this.gridOptions.functionsReadOnly);\n };\n GridOptionsWrapper.prototype.isEnableCellTextSelect = function () {\n return isTrue(this.gridOptions.enableCellTextSelection);\n };\n GridOptionsWrapper.prototype.getDefaultColDef = function () {\n return this.gridOptions.defaultColDef;\n };\n GridOptionsWrapper.prototype.getDefaultColGroupDef = function () {\n return this.gridOptions.defaultColGroupDef;\n };\n GridOptionsWrapper.prototype.getDefaultExportParams = function (type) {\n if (this.gridOptions.defaultExportParams) {\n console.warn(\"AG Grid: Since v25.2 `defaultExportParams` has been replaced by `default\" + capitalise(type) + \"ExportParams`'\");\n if (type === 'csv') {\n return this.gridOptions.defaultExportParams;\n }\n return this.gridOptions.defaultExportParams;\n }\n if (type === 'csv' && this.gridOptions.defaultCsvExportParams) {\n return this.gridOptions.defaultCsvExportParams;\n }\n if (type === 'excel' && this.gridOptions.defaultExcelExportParams) {\n return this.gridOptions.defaultExcelExportParams;\n }\n };\n GridOptionsWrapper.prototype.isSuppressCsvExport = function () {\n return isTrue(this.gridOptions.suppressCsvExport);\n };\n GridOptionsWrapper.prototype.isAllowShowChangeAfterFilter = function () {\n return isTrue(this.gridOptions.allowShowChangeAfterFilter);\n };\n GridOptionsWrapper.prototype.isSuppressExcelExport = function () {\n return isTrue(this.gridOptions.suppressExcelExport);\n };\n GridOptionsWrapper.prototype.isSuppressMakeColumnVisibleAfterUnGroup = function () {\n return isTrue(this.gridOptions.suppressMakeColumnVisibleAfterUnGroup);\n };\n GridOptionsWrapper.prototype.getDataPathFunc = function () {\n return this.gridOptions.getDataPath;\n };\n GridOptionsWrapper.prototype.getIsServerSideGroupFunc = function () {\n return this.gridOptions.isServerSideGroup;\n };\n GridOptionsWrapper.prototype.getIsServerSideGroupOpenByDefaultFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.isServerSideGroupOpenByDefault);\n };\n GridOptionsWrapper.prototype.getIsGroupOpenByDefaultFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.isGroupOpenByDefault);\n };\n GridOptionsWrapper.prototype.getServerSideGroupKeyFunc = function () {\n return this.gridOptions.getServerSideGroupKey;\n };\n GridOptionsWrapper.prototype.getGroupRowAggFunc = function () {\n var _a = this.gridOptions, getGroupRowAgg = _a.getGroupRowAgg, groupRowAggNodes = _a.groupRowAggNodes;\n if (getGroupRowAgg) {\n return this.mergeGridCommonParams(getGroupRowAgg);\n }\n // this is the deprecated way, so provide a proxy to make it compatible\n if (groupRowAggNodes) {\n return function (params) { return groupRowAggNodes(params.nodes); };\n }\n };\n GridOptionsWrapper.prototype.getContextMenuItemsFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.getContextMenuItems);\n };\n GridOptionsWrapper.prototype.getMainMenuItemsFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.getMainMenuItems);\n };\n GridOptionsWrapper.prototype.getRowIdFunc = function () {\n var _a = this.gridOptions, getRowId = _a.getRowId, getRowNodeId = _a.getRowNodeId;\n if (getRowId) {\n return this.mergeGridCommonParams(getRowId);\n }\n // this is the deprecated way, so provide a proxy to make it compatible\n if (getRowNodeId) {\n return function (params) { return getRowNodeId(params.data); };\n }\n };\n GridOptionsWrapper.prototype.getNavigateToNextHeaderFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.navigateToNextHeader);\n };\n GridOptionsWrapper.prototype.getTabToNextHeaderFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.tabToNextHeader);\n };\n GridOptionsWrapper.prototype.getNavigateToNextCellFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.navigateToNextCell);\n };\n GridOptionsWrapper.prototype.getTabToNextCellFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.tabToNextCell);\n };\n GridOptionsWrapper.prototype.getGridTabIndex = function () {\n return (this.gridOptions.tabIndex || 0).toString();\n };\n GridOptionsWrapper.prototype.isTreeData = function () {\n var usingTreeData = isTrue(this.gridOptions.treeData);\n if (usingTreeData) {\n return ModuleRegistry.assertRegistered(ModuleNames.RowGroupingModule, 'Tree Data');\n }\n return false;\n };\n GridOptionsWrapper.prototype.isValueCache = function () {\n return isTrue(this.gridOptions.valueCache);\n };\n GridOptionsWrapper.prototype.isValueCacheNeverExpires = function () {\n return isTrue(this.gridOptions.valueCacheNeverExpires);\n };\n GridOptionsWrapper.prototype.isDeltaSort = function () {\n return isTrue(this.gridOptions.deltaSort);\n };\n GridOptionsWrapper.prototype.isAggregateOnlyChangedColumns = function () {\n return isTrue(this.gridOptions.aggregateOnlyChangedColumns);\n };\n GridOptionsWrapper.prototype.getProcessPivotResultColDefFunc = function () {\n return this.gridOptions.processPivotResultColDef || this.gridOptions.processSecondaryColDef;\n };\n GridOptionsWrapper.prototype.getProcessPivotResultColGroupDefFunc = function () {\n return this.gridOptions.processPivotResultColGroupDef || this.gridOptions.processSecondaryColGroupDef;\n };\n GridOptionsWrapper.prototype.getSendToClipboardFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.sendToClipboard);\n };\n GridOptionsWrapper.prototype.getProcessRowPostCreateFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.processRowPostCreate);\n };\n GridOptionsWrapper.prototype.getProcessCellForClipboardFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.processCellForClipboard);\n };\n GridOptionsWrapper.prototype.getProcessHeaderForClipboardFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.processHeaderForClipboard);\n };\n GridOptionsWrapper.prototype.getProcessGroupHeaderForClipboardFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.processGroupHeaderForClipboard);\n };\n GridOptionsWrapper.prototype.getProcessCellFromClipboardFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.processCellFromClipboard);\n };\n GridOptionsWrapper.prototype.getViewportRowModelPageSize = function () {\n return oneOrGreater(this.gridOptions.viewportRowModelPageSize, DEFAULT_VIEWPORT_ROW_MODEL_PAGE_SIZE);\n };\n GridOptionsWrapper.prototype.getViewportRowModelBufferSize = function () {\n return zeroOrGreater(this.gridOptions.viewportRowModelBufferSize, DEFAULT_VIEWPORT_ROW_MODEL_BUFFER_SIZE);\n };\n GridOptionsWrapper.prototype.isServerSideSortAllLevels = function () {\n var isEnabled = isTrue(this.gridOptions.serverSideSortAllLevels);\n if (!this.isRowModelServerSide() && isEnabled) {\n doOnce(function () { return console.warn('AG Grid: The `serverSideSortAllLevels` property can only be used with the server side row model.'); }, 'serverSideSortAllLevels');\n return false;\n }\n return isEnabled;\n };\n GridOptionsWrapper.prototype.isServerSideFilterAllLevels = function () {\n var isEnabled = isTrue(this.gridOptions.serverSideFilterAllLevels);\n if (!this.isRowModelServerSide() && isEnabled) {\n doOnce(function () { return console.warn('AG Grid: The `serverSideFilterAllLevels` property can only be used with the server side row model.'); }, 'serverSideFilterAllLevels');\n return false;\n }\n return isEnabled;\n };\n GridOptionsWrapper.prototype.isServerSideSortOnServer = function () {\n var isEnabled = isTrue(this.gridOptions.serverSideSortOnServer);\n if (!this.isRowModelServerSide() && isEnabled) {\n doOnce(function () { return console.warn('AG Grid: The `serverSideSortOnServer` property can only be used with the server side row model.'); }, 'serverSideSortOnServerRowModel');\n return false;\n }\n if (this.isTreeData() && isEnabled) {\n doOnce(function () { return console.warn('AG Grid: The `serverSideSortOnServer` property cannot be used while using tree data.'); }, 'serverSideSortOnServerTreeData');\n return false;\n }\n return isEnabled;\n };\n GridOptionsWrapper.prototype.isServerSideFilterOnServer = function () {\n var isEnabled = isTrue(this.gridOptions.serverSideFilterOnServer);\n if (!this.isRowModelServerSide() && isEnabled) {\n doOnce(function () { return console.warn('AG Grid: The `serverSideFilterOnServer` property can only be used with the server side row model.'); }, 'serverSideFilterOnServerRowModel');\n return false;\n }\n if (this.isTreeData() && isEnabled) {\n doOnce(function () { return console.warn('AG Grid: The `serverSideFilterOnServer` property cannot be used while using tree data.'); }, 'serverSideFilterOnServerTreeData');\n return false;\n }\n return isEnabled;\n };\n GridOptionsWrapper.prototype.getPostSortFunc = function () {\n var _a = this.gridOptions, postSortRows = _a.postSortRows, postSort = _a.postSort;\n if (postSortRows) {\n return this.mergeGridCommonParams(postSortRows);\n }\n // this is the deprecated way, so provide a proxy to make it compatible\n if (postSort) {\n return function (params) { return postSort(params.nodes); };\n }\n };\n GridOptionsWrapper.prototype.getChartToolbarItemsFunc = function () {\n return this.mergeGridCommonParams(this.gridOptions.getChartToolbarItems);\n };\n GridOptionsWrapper.prototype.getChartThemeOverrides = function () {\n return this.gridOptions.chartThemeOverrides;\n };\n GridOptionsWrapper.prototype.getCustomChartThemes = function () {\n return this.gridOptions.customChartThemes;\n };\n GridOptionsWrapper.prototype.getChartThemes = function () {\n // return default themes if user hasn't supplied any\n return this.gridOptions.chartThemes || ['ag-default', 'ag-material', 'ag-pastel', 'ag-vivid', 'ag-solar'];\n };\n GridOptionsWrapper.prototype.getChartToolPanelsDef = function () {\n return this.gridOptions.chartToolPanelsDef;\n };\n GridOptionsWrapper.prototype.getClipboardDelimiter = function () {\n return exists(this.gridOptions.clipboardDelimiter) ? this.gridOptions.clipboardDelimiter : '\\t';\n };\n GridOptionsWrapper.prototype.setProperty = function (key, value, force) {\n if (force === void 0) { force = false; }\n var previousValue = this.gridOptions[key];\n if (force || previousValue !== value) {\n this.gridOptions[key] = value;\n var event_1 = {\n type: key,\n currentValue: value,\n previousValue: previousValue\n };\n this.propertyEventService.dispatchEvent(event_1);\n }\n };\n GridOptionsWrapper.prototype.addEventListener = function (key, listener) {\n this.propertyEventService.addEventListener(key, listener);\n };\n GridOptionsWrapper.prototype.removeEventListener = function (key, listener) {\n this.propertyEventService.removeEventListener(key, listener);\n };\n GridOptionsWrapper.prototype.isSkipHeaderOnAutoSize = function () {\n return !!this.gridOptions.skipHeaderOnAutoSize;\n };\n GridOptionsWrapper.prototype.getAutoSizePadding = function () {\n var value = this.gridOptions.autoSizePadding;\n return value != null && value >= 0 ? value : 20;\n };\n // properties\n GridOptionsWrapper.prototype.getHeaderHeight = function () {\n if (typeof this.gridOptions.headerHeight === 'number') {\n return this.gridOptions.headerHeight;\n }\n return this.getFromTheme(25, 'headerHeight');\n };\n GridOptionsWrapper.prototype.getFloatingFiltersHeight = function () {\n if (typeof this.gridOptions.floatingFiltersHeight === 'number') {\n return this.gridOptions.floatingFiltersHeight;\n }\n return this.getFromTheme(25, 'headerHeight');\n };\n GridOptionsWrapper.prototype.getGroupHeaderHeight = function () {\n if (typeof this.gridOptions.groupHeaderHeight === 'number') {\n return this.gridOptions.groupHeaderHeight;\n }\n return this.getHeaderHeight();\n };\n GridOptionsWrapper.prototype.getPivotHeaderHeight = function () {\n if (typeof this.gridOptions.pivotHeaderHeight === 'number') {\n return this.gridOptions.pivotHeaderHeight;\n }\n return this.getHeaderHeight();\n };\n GridOptionsWrapper.prototype.getPivotGroupHeaderHeight = function () {\n if (typeof this.gridOptions.pivotGroupHeaderHeight === 'number') {\n return this.gridOptions.pivotGroupHeaderHeight;\n }\n return this.getGroupHeaderHeight();\n };\n GridOptionsWrapper.prototype.isExternalFilterPresent = function () {\n if (typeof this.gridOptions.isExternalFilterPresent === 'function') {\n return this.gridOptions.isExternalFilterPresent({ api: this.getApi(), columnApi: this.getColumnApi(), context: this.getContext() });\n }\n return false;\n };\n GridOptionsWrapper.prototype.doesExternalFilterPass = function (node) {\n if (typeof this.gridOptions.doesExternalFilterPass === 'function') {\n return this.gridOptions.doesExternalFilterPass(node);\n }\n return false;\n };\n GridOptionsWrapper.prototype.getTooltipDelay = function (type) {\n var _a = this.gridOptions, tooltipShowDelay = _a.tooltipShowDelay, tooltipHideDelay = _a.tooltipHideDelay;\n var delay = type === 'show' ? tooltipShowDelay : tooltipHideDelay;\n var capitalisedType = capitalise(type);\n if (exists(delay)) {\n if (delay < 0) {\n doOnce(function () { return console.warn(\"ag-grid: tooltip\" + capitalisedType + \"Delay should not be lower than 0\"); }, \"tooltip\" + capitalisedType + \"DelayWarn\");\n }\n return Math.max(200, delay);\n }\n return null;\n };\n GridOptionsWrapper.prototype.isTooltipMouseTrack = function () {\n return isTrue(this.gridOptions.tooltipMouseTrack);\n };\n GridOptionsWrapper.prototype.isSuppressModelUpdateAfterUpdateTransaction = function () {\n return isTrue(this.gridOptions.suppressModelUpdateAfterUpdateTransaction);\n };\n GridOptionsWrapper.prototype.getDocument = function () {\n // if user is providing document, we use the users one,\n // otherwise we use the document on the global namespace.\n var result = null;\n if (this.gridOptions.getDocument && exists(this.gridOptions.getDocument)) {\n result = this.gridOptions.getDocument();\n }\n else if (this.eGridDiv) {\n result = this.eGridDiv.ownerDocument;\n }\n if (result && exists(result)) {\n return result;\n }\n return document;\n };\n GridOptionsWrapper.prototype.getMinColWidth = function () {\n var minColWidth = this.gridOptions.minColWidth;\n if (exists(minColWidth) && minColWidth > GridOptionsWrapper_1.MIN_COL_WIDTH) {\n return this.gridOptions.minColWidth;\n }\n var measuredMin = this.getFromTheme(null, 'headerCellMinWidth');\n return exists(measuredMin) ? Math.max(measuredMin, GridOptionsWrapper_1.MIN_COL_WIDTH) : GridOptionsWrapper_1.MIN_COL_WIDTH;\n };\n GridOptionsWrapper.prototype.getMaxColWidth = function () {\n if (this.gridOptions.maxColWidth && this.gridOptions.maxColWidth > GridOptionsWrapper_1.MIN_COL_WIDTH) {\n return this.gridOptions.maxColWidth;\n }\n return null;\n };\n GridOptionsWrapper.prototype.getColWidth = function () {\n if (typeof this.gridOptions.colWidth !== 'number' || this.gridOptions.colWidth < GridOptionsWrapper_1.MIN_COL_WIDTH) {\n return 200;\n }\n return this.gridOptions.colWidth;\n };\n GridOptionsWrapper.prototype.getRowBuffer = function () {\n var rowBuffer = this.gridOptions.rowBuffer;\n if (typeof rowBuffer === 'number') {\n if (rowBuffer < 0) {\n doOnce(function () { return console.warn(\"AG Grid: rowBuffer should not be negative\"); }, 'warn rowBuffer negative');\n this.gridOptions.rowBuffer = rowBuffer = 0;\n }\n }\n else {\n rowBuffer = Constants.ROW_BUFFER_SIZE;\n }\n return rowBuffer;\n };\n GridOptionsWrapper.prototype.getRowBufferInPixels = function () {\n var rowsToBuffer = this.getRowBuffer();\n var defaultRowHeight = this.getRowHeightAsNumber();\n return rowsToBuffer * defaultRowHeight;\n };\n // the user might be using some non-standard scrollbar, eg a scrollbar that has zero\n // width and overlays (like the Safari scrollbar, but presented in Chrome). so we\n // allow the user to provide the scroll width before we work it out.\n GridOptionsWrapper.prototype.getScrollbarWidth = function () {\n if (this.scrollbarWidth == null) {\n var useGridOptions = typeof this.gridOptions.scrollbarWidth === 'number' && this.gridOptions.scrollbarWidth >= 0;\n var scrollbarWidth = useGridOptions ? this.gridOptions.scrollbarWidth : getScrollbarWidth();\n if (scrollbarWidth != null) {\n this.scrollbarWidth = scrollbarWidth;\n this.eventService.dispatchEvent({\n type: Events.EVENT_SCROLLBAR_WIDTH_CHANGED\n });\n }\n }\n return this.scrollbarWidth;\n };\n GridOptionsWrapper.prototype.checkForDeprecated = function () {\n // casting to generic object, so typescript compiles even though\n // we are looking for attributes that don't exist\n var options = this.gridOptions;\n if (options.deprecatedEmbedFullWidthRows) {\n console.warn(\"AG Grid: since v21.2, deprecatedEmbedFullWidthRows has been replaced with embedFullWidthRows.\");\n }\n if (options.rowDeselection) {\n console.warn('AG Grid: since v24.x, rowDeselection is deprecated and the behaviour is true by default. Please use `suppressRowDeselection` to prevent rows from being deselected.');\n }\n if (options.enableMultiRowDragging) {\n options.rowDragMultiRow = true;\n delete options.enableMultiRowDragging;\n console.warn('AG Grid: since v26.1, `enableMultiRowDragging` is deprecated. Please use `rowDragMultiRow`.');\n }\n var checkRenamedProperty = function (oldProp, newProp, version) {\n if (options[oldProp] != null) {\n console.warn(\"AG Grid: since version \" + version + \", '\" + oldProp + \"' is deprecated / renamed, please use the new property name '\" + newProp + \"' instead.\");\n if (options[newProp] == null) {\n options[newProp] = options[oldProp];\n }\n }\n };\n checkRenamedProperty('batchUpdateWaitMillis', 'asyncTransactionWaitMillis', '23.1.x');\n checkRenamedProperty('deltaRowDataMode', 'immutableData', '23.1.x');\n checkRenamedProperty('serverSideFilteringAlwaysResets', 'serverSideFilterAllLevels', '28.0.0');\n checkRenamedProperty('serverSideSortingAlwaysResets', 'serverSideSortAllLevels', '28.0.0');\n if (options.immutableColumns || options.deltaColumnMode) {\n console.warn('AG Grid: since v24.0, immutableColumns and deltaColumnMode properties are gone. The grid now works like this as default. To keep column order maintained, set grid property applyColumnDefOrder=true');\n }\n checkRenamedProperty('suppressSetColumnStateEvents', 'suppressColumnStateEvents', '24.0.x');\n if (options.groupRowInnerRenderer || options.groupRowInnerRendererParams || options.groupRowInnerRendererFramework) {\n console.warn('AG Grid: since v24.0, grid properties groupRowInnerRenderer, groupRowInnerRendererFramework and groupRowInnerRendererParams are no longer used.');\n console.warn(' Instead use the grid properties groupRowRendererParams.innerRenderer, groupRowRendererParams.innerRendererFramework and groupRowRendererParams.innerRendererParams.');\n console.warn(' For example instead of this:');\n console.warn(' groupRowInnerRenderer: \"myRenderer\"');\n console.warn(' groupRowInnerRendererParams: {x: a}');\n console.warn(' Replace with this:');\n console.warn(' groupRowRendererParams: {');\n console.warn(' innerRenderer: \"myRenderer\",');\n console.warn(' innerRendererParams: {x: a}');\n console.warn(' }');\n console.warn(' We have copied the properties over for you. However to stop this error message, please change your application code.');\n if (!options.groupRowRendererParams) {\n options.groupRowRendererParams = {};\n }\n var params = options.groupRowRendererParams;\n if (options.groupRowInnerRenderer) {\n params.innerRenderer = options.groupRowInnerRenderer;\n }\n if (options.groupRowInnerRendererParams) {\n params.innerRendererParams = options.groupRowInnerRendererParams;\n }\n if (options.groupRowInnerRendererFramework) {\n params.innerRendererFramework = options.groupRowInnerRendererFramework;\n }\n }\n if (options.rememberGroupStateWhenNewData) {\n console.warn('AG Grid: since v24.0, grid property rememberGroupStateWhenNewData is deprecated. This feature was provided before Transaction Updates worked (which keep group state). Now that transaction updates are possible and they keep group state, this feature is no longer needed.');\n }\n if (options.detailCellRendererParams && options.detailCellRendererParams.autoHeight) {\n console.warn('AG Grid: since v24.1, grid property detailCellRendererParams.autoHeight is replaced with grid property detailRowAutoHeight. This allows this feature to work when you provide a custom DetailCellRenderer');\n options.detailRowAutoHeight = true;\n }\n if (options.suppressKeyboardEvent) {\n console.warn(\"AG Grid: since v24.1 suppressKeyboardEvent in the gridOptions has been deprecated and will be removed in\\n future versions of AG Grid. If you need this to be set for every column use the defaultColDef property.\");\n }\n if (options.suppressEnterpriseResetOnNewColumns) {\n console.warn('AG Grid: since v25, grid property suppressEnterpriseResetOnNewColumns is deprecated. This was a temporary property to allow changing columns in Server Side Row Model without triggering a reload. Now that it is possible to dynamically change columns in the grid, this is no longer needed.');\n }\n if (options.suppressColumnStateEvents) {\n console.warn('AG Grid: since v25, grid property suppressColumnStateEvents no longer works due to a refactor that we did. It should be possible to achieve similar using event.source, which would be \"api\" if the event was due to setting column state via the API');\n }\n if (options.defaultExportParams) {\n console.warn('AG Grid: since v25.2, the grid property `defaultExportParams` has been replaced by `defaultCsvExportParams` and `defaultExcelExportParams`.');\n }\n if (options.stopEditingWhenGridLosesFocus) {\n console.warn('AG Grid: since v25.2.2, the grid property `stopEditingWhenGridLosesFocus` has been replaced by `stopEditingWhenCellsLoseFocus`.');\n options.stopEditingWhenCellsLoseFocus = true;\n }\n if (options.applyColumnDefOrder) {\n console.warn('AG Grid: since v26.0, the grid property `applyColumnDefOrder` is no longer needed, as this is the default behaviour. To turn this behaviour off, set maintainColumnOrder=true');\n }\n if (options.groupMultiAutoColumn) {\n console.warn(\"AG Grid: since v26.0, the grid property `groupMultiAutoColumn` has been replaced by `groupDisplayType = 'multipleColumns'`\");\n options.groupDisplayType = 'multipleColumns';\n }\n if (options.groupUseEntireRow) {\n console.warn(\"AG Grid: since v26.0, the grid property `groupUseEntireRow` has been replaced by `groupDisplayType = 'groupRows'`\");\n options.groupDisplayType = 'groupRows';\n }\n if (options.groupSuppressAutoColumn) {\n var propName = options.treeData ? 'treeDataDisplayType' : 'groupDisplayType';\n console.warn(\"AG Grid: since v26.0, the grid property `groupSuppressAutoColumn` has been replaced by `\" + propName + \" = 'custom'`\");\n options.groupDisplayType = 'custom';\n }\n if (options.defaultGroupOrderComparator) {\n console.warn(\"AG Grid: since v27.2, the grid property `defaultGroupOrderComparator` is deprecated and has been replaced by `initialGroupOrderComparator` and now receives a single params object.\");\n }\n if (options.defaultGroupSortComparator) {\n console.warn(\"AG Grid: since v26.0, the grid property `defaultGroupSortComparator` has been replaced by `initialGroupOrderComparator`\");\n options.defaultGroupOrderComparator = options.defaultGroupSortComparator;\n }\n if (options.groupRowAggNodes) {\n console.warn(\"AG Grid: since v27.2, the grid property `groupRowAggNodes` is deprecated and has been replaced by `getGroupRowAgg` and now receives a single params object.\");\n }\n if (options.postSort) {\n console.warn(\"AG Grid: since v27.2, the grid property `postSort` is deprecated and has been replaced by `postSortRows` and now receives a single params object.\");\n }\n if (options.isFullWidthCell) {\n console.warn(\"AG Grid: since v27.2, the grid property `isFullWidthCell` is deprecated and has been replaced by `isFullWidthRow` and now receives a single params object.\");\n }\n if (options.localeTextFunc) {\n console.warn(\"AG Grid: since v27.2, the grid property `localeTextFunc` is deprecated and has been replaced by `getLocaleText` and now receives a single params object.\");\n }\n if (options.colWidth) {\n console.warn('AG Grid: since v26.1, the grid property `colWidth` is deprecated and should be set via `defaultColDef.width`.');\n }\n if (options.minColWidth) {\n console.warn('AG Grid: since v26.1, the grid property `minColWidth` is deprecated and should be set via `defaultColDef.minWidth`.');\n }\n if (options.maxColWidth) {\n console.warn('AG Grid: since v26.1, the grid property `maxColWidth` is deprecated and should be set via `defaultColDef.maxWidth`.');\n }\n if (options.reactUi) {\n console.warn('AG Grid: since v27.0, React UI is on by default, so no need for reactUi=true. To turn it off, set suppressReactUi=true.');\n }\n if (options.suppressReactUi) {\n console.warn('AG Grid: The legacy React rendering engine is deprecated and will be removed in the next major version of the grid.');\n }\n if (options.suppressCellSelection) {\n console.warn('AG Grid: since v27.0, `suppressCellSelection` has been replaced by `suppressCellFocus`.');\n options.suppressCellFocus = options.suppressCellSelection;\n }\n if (options.getRowNodeId) {\n console.warn('AG Grid: since v27.1, `getRowNodeId` is deprecated and has been replaced by `getRowId`. The difference: if getRowId() is implemented then immutable data is enabled by default.');\n }\n if (options.immutableData) {\n if (options.getRowId) {\n console.warn('AG Grid: since v27.1, `immutableData` is deprecated. With the `getRowId` callback implemented, immutable data is enabled by default so you can remove `immutableData=true`.');\n }\n else {\n console.warn('AG Grid: since v27.1, `immutableData` is deprecated. To enable immutable data you must implement the `getRowId()` callback.');\n }\n }\n if (options.clipboardDeliminator) {\n console.warn('AG Grid: since v27.1, `clipboardDeliminator` has been replaced by `clipboardDelimiter`.');\n options.clipboardDelimiter = options.clipboardDeliminator;\n }\n checkRenamedProperty('processSecondaryColDef', 'processPivotResultColDef', '28.0.x');\n checkRenamedProperty('processSecondaryColGroupDef', 'processPivotResultColGroupDef', '28.0.x');\n if (options.serverSideStoreType) {\n console.warn('AG Grid: since v28.0, `serverSideStoreType` has been replaced by `serverSideInfiniteScroll`. Set to true to use Partial Store, and false to use Full Store.');\n options.serverSideInfiniteScroll = options.serverSideStoreType === 'partial';\n }\n checkRenamedProperty('getServerSideStoreParams', 'getServerSideGroupLevelParams', '28.0.x');\n };\n GridOptionsWrapper.prototype.checkForViolations = function () {\n if (this.isTreeData()) {\n this.treeDataViolations();\n }\n };\n GridOptionsWrapper.prototype.treeDataViolations = function () {\n if (this.isRowModelDefault()) {\n if (missing(this.getDataPathFunc())) {\n console.warn('AG Grid: property usingTreeData=true with rowModel=clientSide, but you did not ' +\n 'provide getDataPath function, please provide getDataPath function if using tree data.');\n }\n }\n if (this.isRowModelServerSide()) {\n if (missing(this.getIsServerSideGroupFunc())) {\n console.warn('AG Grid: property usingTreeData=true with rowModel=serverSide, but you did not ' +\n 'provide isServerSideGroup function, please provide isServerSideGroup function if using tree data.');\n }\n if (missing(this.getServerSideGroupKeyFunc())) {\n console.warn('AG Grid: property usingTreeData=true with rowModel=serverSide, but you did not ' +\n 'provide getServerSideGroupKey function, please provide getServerSideGroupKey function if using tree data.');\n }\n }\n };\n GridOptionsWrapper.prototype.getLocaleTextFunc = function () {\n var _this = this;\n var _a = this.gridOptions, localeText = _a.localeText, getLocaleText = _a.getLocaleText, localeTextFunc = _a.localeTextFunc;\n if (getLocaleText) {\n //key: string, defaultValue: string, variableValues?: string[]\n return function (key, defaultValue, variableValues) {\n var params = {\n key: key,\n defaultValue: defaultValue,\n variableValues: variableValues,\n api: _this.getApi(),\n columnApi: _this.getColumnApi(),\n context: _this.getContext()\n };\n return getLocaleText(params);\n };\n }\n if (localeTextFunc) {\n return localeTextFunc;\n }\n return function (key, defaultValue, variableValues) {\n var localisedText = localeText && localeText[key];\n if (localisedText && variableValues && variableValues.length) {\n var found = 0;\n while (true) {\n if (found >= variableValues.length) {\n break;\n }\n var idx = localisedText.indexOf('${variable}');\n if (idx === -1) {\n break;\n }\n localisedText = localisedText.replace('${variable}', variableValues[found++]);\n }\n }\n return (localisedText !== null && localisedText !== void 0 ? localisedText : defaultValue);\n };\n };\n // responsible for calling the onXXX functions on gridOptions\n GridOptionsWrapper.prototype.globalEventHandler = function (eventName, event) {\n // prevent events from being fired _after_ the grid has been destroyed\n if (this.destroyed) {\n return;\n }\n var callbackMethodName = ComponentUtil.getCallbackForEvent(eventName);\n if (typeof this.gridOptions[callbackMethodName] === 'function') {\n this.gridOptions[callbackMethodName](event);\n }\n };\n GridOptionsWrapper.prototype.setRowHeightVariable = function (height) {\n var oldRowHeight = this.eGridDiv.style.getPropertyValue('--ag-line-height').trim();\n var newRowHeight = height + \"px\";\n if (oldRowHeight != newRowHeight) {\n this.eGridDiv.style.setProperty('--ag-line-height', newRowHeight);\n }\n };\n // we don't allow dynamic row height for virtual paging\n GridOptionsWrapper.prototype.getRowHeightAsNumber = function () {\n if (!this.gridOptions.rowHeight || missing(this.gridOptions.rowHeight)) {\n return this.getDefaultRowHeight();\n }\n var rowHeight = this.gridOptions.rowHeight;\n if (rowHeight && this.isNumeric(rowHeight)) {\n this.setRowHeightVariable(rowHeight);\n return rowHeight;\n }\n console.warn('AG Grid row height must be a number if not using standard row model');\n return this.getDefaultRowHeight();\n };\n GridOptionsWrapper.prototype.isGetRowHeightFunction = function () {\n return typeof this.gridOptions.getRowHeight === 'function';\n };\n GridOptionsWrapper.prototype.getRowHeightForNode = function (rowNode, allowEstimate, defaultRowHeight) {\n if (allowEstimate === void 0) { allowEstimate = false; }\n if (defaultRowHeight == null) {\n defaultRowHeight = this.getDefaultRowHeight();\n }\n // check the function first, in case use set both function and\n // number, when using virtual pagination then function can be\n // used for pinned rows and the number for the body rows.\n if (this.isGetRowHeightFunction()) {\n if (allowEstimate) {\n return { height: defaultRowHeight, estimated: true };\n }\n var params = {\n node: rowNode,\n data: rowNode.data\n };\n var height = this.mergeGridCommonParams(this.gridOptions.getRowHeight)(params);\n if (this.isNumeric(height)) {\n if (height === 0) {\n doOnce(function () { return console.warn('AG Grid: The return of `getRowHeight` cannot be zero. If the intention is to hide rows, use a filter instead.'); }, 'invalidRowHeight');\n }\n return { height: Math.max(1, height), estimated: false };\n }\n }\n if (rowNode.detail && this.isMasterDetail()) {\n // if autoHeight, we want the height to grow to the new height starting at 1, as otherwise a flicker would happen,\n // as the detail goes to the default (eg 200px) and then immediately shrink up/down to the new measured height\n // (due to auto height) which looks bad, especially if doing row animation.\n if (this.isDetailRowAutoHeight()) {\n return { height: 1, estimated: false };\n }\n if (this.isNumeric(this.gridOptions.detailRowHeight)) {\n return { height: this.gridOptions.detailRowHeight, estimated: false };\n }\n return { height: DEFAULT_DETAIL_ROW_HEIGHT, estimated: false };\n }\n var rowHeight = this.gridOptions.rowHeight && this.isNumeric(this.gridOptions.rowHeight) ? this.gridOptions.rowHeight : defaultRowHeight;\n return { height: rowHeight, estimated: false };\n };\n GridOptionsWrapper.prototype.isDynamicRowHeight = function () {\n return typeof this.gridOptions.getRowHeight === 'function';\n };\n GridOptionsWrapper.prototype.getListItemHeight = function () {\n return this.getFromTheme(20, 'listItemHeight');\n };\n GridOptionsWrapper.prototype.chartMenuPanelWidth = function () {\n return this.environment.chartMenuPanelWidth();\n };\n GridOptionsWrapper.prototype.isNumeric = function (value) {\n return !isNaN(value) && typeof value === 'number' && isFinite(value);\n };\n GridOptionsWrapper.prototype.getFromTheme = function (defaultValue, sassVariableName) {\n var theme = this.environment.getTheme().theme;\n if (theme && theme.indexOf('ag-theme') === 0) {\n return this.environment.getSassVariable(theme, sassVariableName);\n }\n return defaultValue;\n };\n GridOptionsWrapper.prototype.getDefaultRowHeight = function () {\n return this.getFromTheme(DEFAULT_ROW_HEIGHT, 'rowHeight');\n };\n GridOptionsWrapper.prototype.matchesGroupDisplayType = function (toMatch, supplied) {\n var groupDisplayTypeValues = ['groupRows', 'multipleColumns', 'custom', 'singleColumn'];\n if (groupDisplayTypeValues.indexOf(supplied) < 0) {\n console.warn(\"AG Grid: '\" + supplied + \"' is not a valid groupDisplayType value - possible values are: '\" + groupDisplayTypeValues.join(\"', '\") + \"'\");\n return false;\n }\n return supplied === toMatch;\n };\n GridOptionsWrapper.prototype.matchesTreeDataDisplayType = function (toMatch, supplied) {\n var treeDataDisplayTypeValues = ['auto', 'custom'];\n if (treeDataDisplayTypeValues.indexOf(supplied) < 0) {\n console.warn(\"AG Grid: '\" + supplied + \"' is not a valid treeDataDisplayType value - possible values are: '\" + treeDataDisplayTypeValues.join(\"', '\") + \"'\");\n return false;\n }\n return supplied === toMatch;\n };\n var GridOptionsWrapper_1;\n GridOptionsWrapper.MIN_COL_WIDTH = 10;\n GridOptionsWrapper.PROP_HEADER_HEIGHT = 'headerHeight';\n GridOptionsWrapper.PROP_GROUP_REMOVE_SINGLE_CHILDREN = 'groupRemoveSingleChildren';\n GridOptionsWrapper.PROP_GROUP_REMOVE_LOWEST_SINGLE_CHILDREN = 'groupRemoveLowestSingleChildren';\n GridOptionsWrapper.PROP_GROUP_DISPLAY_TYPE = 'groupDisplayType';\n GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT = 'pivotHeaderHeight';\n GridOptionsWrapper.PROP_SUPPRESS_CLIPBOARD_PASTE = 'suppressClipboardPaste';\n GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT = 'groupHeaderHeight';\n GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT = 'pivotGroupHeaderHeight';\n GridOptionsWrapper.PROP_NAVIGATE_TO_NEXT_CELL = 'navigateToNextCell';\n GridOptionsWrapper.PROP_TAB_TO_NEXT_CELL = 'tabToNextCell';\n GridOptionsWrapper.PROP_NAVIGATE_TO_NEXT_HEADER = 'navigateToNextHeader';\n GridOptionsWrapper.PROP_TAB_TO_NEXT_HEADER = 'tabToNextHeader';\n GridOptionsWrapper.PROP_IS_EXTERNAL_FILTER_PRESENT = 'isExternalFilterPresent';\n GridOptionsWrapper.PROP_DOES_EXTERNAL_FILTER_PASS = 'doesExternalFilterPass';\n GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT = 'floatingFiltersHeight';\n GridOptionsWrapper.PROP_SUPPRESS_ROW_CLICK_SELECTION = 'suppressRowClickSelection';\n GridOptionsWrapper.PROP_SUPPRESS_ROW_DRAG = 'suppressRowDrag';\n GridOptionsWrapper.PROP_SUPPRESS_MOVE_WHEN_ROW_DRAG = 'suppressMoveWhenRowDragging';\n GridOptionsWrapper.PROP_GET_ROW_CLASS = 'getRowClass';\n GridOptionsWrapper.PROP_GET_ROW_STYLE = 'getRowStyle';\n GridOptionsWrapper.PROP_GET_ROW_HEIGHT = 'getRowHeight';\n GridOptionsWrapper.PROP_POPUP_PARENT = 'popupParent';\n GridOptionsWrapper.PROP_DOM_LAYOUT = 'domLayout';\n GridOptionsWrapper.PROP_ROW_CLASS = 'rowClass';\n GridOptionsWrapper.PROP_FILL_HANDLE_DIRECTION = 'fillHandleDirection';\n GridOptionsWrapper.PROP_GROUP_ROW_AGG_NODES = 'groupRowAggNodes';\n GridOptionsWrapper.PROP_GET_GROUP_ROW_AGG = 'getGroupRowAgg';\n GridOptionsWrapper.PROP_GET_BUSINESS_KEY_FOR_NODE = 'getBusinessKeyForNode';\n GridOptionsWrapper.PROP_GET_CHILD_COUNT = 'getChildCount';\n GridOptionsWrapper.PROP_PROCESS_ROW_POST_CREATE = 'processRowPostCreate';\n GridOptionsWrapper.PROP_GET_ROW_NODE_ID = 'getRowNodeId';\n GridOptionsWrapper.PROP_GET_ROW_ID = 'getRowId';\n GridOptionsWrapper.PROP_IS_FULL_WIDTH_CELL = 'isFullWidthCell';\n GridOptionsWrapper.PROP_IS_FULL_WIDTH_ROW = 'isFullWidthRow';\n GridOptionsWrapper.PROP_IS_ROW_SELECTABLE = 'isRowSelectable';\n GridOptionsWrapper.PROP_IS_ROW_MASTER = 'isRowMaster';\n GridOptionsWrapper.PROP_POST_SORT = 'postSort';\n GridOptionsWrapper.PROP_POST_SORT_ROWS = 'postSortRows';\n GridOptionsWrapper.PROP_GET_DOCUMENT = 'getDocument';\n GridOptionsWrapper.PROP_POST_PROCESS_POPUP = 'postProcessPopup';\n GridOptionsWrapper.PROP_DEFAULT_GROUP_ORDER_COMPARATOR = 'defaultGroupOrderComparator';\n GridOptionsWrapper.PROP_INITIAL_GROUP_ORDER_COMPARATOR = 'initialGroupOrderComparator';\n GridOptionsWrapper.PROP_PAGINATION_NUMBER_FORMATTER = 'paginationNumberFormatter';\n GridOptionsWrapper.PROP_GET_CONTEXT_MENU_ITEMS = 'getContextMenuItems';\n GridOptionsWrapper.PROP_GET_MAIN_MENU_ITEMS = 'getMainMenuItems';\n GridOptionsWrapper.PROP_PROCESS_CELL_FOR_CLIPBOARD = 'processCellForClipboard';\n GridOptionsWrapper.PROP_PROCESS_CELL_FROM_CLIPBOARD = 'processCellFromClipboard';\n GridOptionsWrapper.PROP_SEND_TO_CLIPBOARD = 'sendToClipboard';\n GridOptionsWrapper.PROP_PROCESS_PIVOT_RESULT_COL_DEF = 'processPivotResultColDef';\n GridOptionsWrapper.PROP_PROCESS_PIVOT_RESULT_COL_GROUP_DEF = 'processPivotResultColGroupDef';\n GridOptionsWrapper.PROP_GET_CHART_TOOLBAR_ITEMS = 'getChartToolbarItems';\n GridOptionsWrapper.PROP_GET_SERVER_SIDE_GROUP_PARAMS = 'getServerSideGroupLevelParams';\n GridOptionsWrapper.PROP_IS_SERVER_SIDE_GROUPS_OPEN_BY_DEFAULT = 'isServerSideGroupOpenByDefault';\n GridOptionsWrapper.PROP_IS_APPLY_SERVER_SIDE_TRANSACTION = 'isApplyServerSideTransaction';\n GridOptionsWrapper.PROP_IS_SERVER_SIDE_GROUP = 'isServerSideGroup';\n GridOptionsWrapper.PROP_GET_SERVER_SIDE_GROUP_KEY = 'getServerSideGroupKey';\n GridOptionsWrapper.PROP_AUTO_GROUP_COLUMN_DEF = 'autoGroupColumnDef';\n GridOptionsWrapper.PROP_DEFAULT_COL_DEF = 'defaultColDef';\n __decorate$2v([\n Autowired('gridOptions')\n ], GridOptionsWrapper.prototype, \"gridOptions\", void 0);\n __decorate$2v([\n Autowired('eventService')\n ], GridOptionsWrapper.prototype, \"eventService\", void 0);\n __decorate$2v([\n Autowired('environment')\n ], GridOptionsWrapper.prototype, \"environment\", void 0);\n __decorate$2v([\n Autowired('eGridDiv')\n ], GridOptionsWrapper.prototype, \"eGridDiv\", void 0);\n __decorate$2v([\n __param$8(0, Qualifier('gridApi')), __param$8(1, Qualifier('columnApi'))\n ], GridOptionsWrapper.prototype, \"agWire\", null);\n __decorate$2v([\n PreDestroy\n ], GridOptionsWrapper.prototype, \"destroy\", null);\n __decorate$2v([\n PostConstruct\n ], GridOptionsWrapper.prototype, \"init\", null);\n GridOptionsWrapper = GridOptionsWrapper_1 = __decorate$2v([\n Bean('gridOptionsWrapper')\n ], GridOptionsWrapper);\n return GridOptionsWrapper;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2T = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2u = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$7 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar __rest = (undefined && undefined.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\n t[p[i]] = s[p[i]];\n }\n return t;\n};\nvar __values$4 = (undefined && undefined.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\nvar __read$l = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$f = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$l(arguments[i]));\n return ar;\n};\nvar ColumnModel = /** @class */ (function (_super) {\n __extends$2T(ColumnModel, _super);\n function ColumnModel() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n // header row count, based on user provided columns\n _this.primaryHeaderRowCount = 0;\n _this.secondaryHeaderRowCount = 0;\n // header row count, either above, or based on pivoting if we are pivoting\n _this.gridHeaderRowCount = 0;\n // leave level columns of the displayed trees\n _this.displayedColumnsLeft = [];\n _this.displayedColumnsRight = [];\n _this.displayedColumnsCenter = [];\n // all three lists above combined\n _this.displayedColumns = [];\n // for fast lookup, to see if a column or group is still displayed\n _this.displayedColumnsAndGroupsMap = {};\n // all columns to be rendered\n _this.viewportColumns = [];\n // A hash key to keep track of changes in viewport columns\n _this.viewportColumnsHash = '';\n // same as viewportColumns, except we always include columns with headerAutoHeight\n _this.headerViewportColumns = [];\n // all columns to be rendered in the centre\n _this.viewportColumnsCenter = [];\n // same as viewportColumnsCenter, except we always include columns with headerAutoHeight\n _this.headerViewportColumnsCenter = [];\n _this.autoHeightActiveAtLeastOnce = false;\n _this.rowGroupColumns = [];\n _this.valueColumns = [];\n _this.pivotColumns = [];\n _this.ready = false;\n _this.autoGroupsNeedBuilding = false;\n _this.forceRecreateAutoGroups = false;\n _this.pivotMode = false;\n _this.bodyWidth = 0;\n _this.leftWidth = 0;\n _this.rightWidth = 0;\n _this.bodyWidthDirty = true;\n _this.flexColsCalculatedAtLestOnce = false;\n return _this;\n }\n ColumnModel.prototype.init = function () {\n var _this = this;\n this.suppressColumnVirtualisation = this.gridOptionsWrapper.isSuppressColumnVirtualisation();\n var pivotMode = this.gridOptionsWrapper.isPivotMode();\n if (this.isPivotSettingAllowed(pivotMode)) {\n this.pivotMode = pivotMode;\n }\n this.usingTreeData = this.gridOptionsWrapper.isTreeData();\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_GROUP_DISPLAY_TYPE, function () { return _this.onAutoGroupColumnDefChanged(); });\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_AUTO_GROUP_COLUMN_DEF, function () { return _this.onAutoGroupColumnDefChanged(); });\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DEFAULT_COL_DEF, function () { return _this.onDefaultColDefChanged(); });\n };\n ColumnModel.prototype.onAutoGroupColumnDefChanged = function () {\n this.autoGroupsNeedBuilding = true;\n this.forceRecreateAutoGroups = true;\n this.updateGridColumns();\n this.updateDisplayedColumns('gridOptionsChanged');\n };\n ColumnModel.prototype.onDefaultColDefChanged = function () {\n // likewise for autoGroupCol, the default col def impacts this\n this.forceRecreateAutoGroups = true;\n this.createColumnsFromColumnDefs(true);\n };\n ColumnModel.prototype.setColumnDefs = function (columnDefs, source) {\n if (source === void 0) { source = 'api'; }\n var colsPreviouslyExisted = !!this.columnDefs;\n this.columnDefs = columnDefs;\n this.createColumnsFromColumnDefs(colsPreviouslyExisted, source);\n };\n ColumnModel.prototype.createColumnsFromColumnDefs = function (colsPreviouslyExisted, source) {\n var _this = this;\n if (source === void 0) { source = 'api'; }\n // only need to raise before/after events if updating columns, never if setting columns for first time\n var raiseEventsFunc = colsPreviouslyExisted ? this.compareColumnStatesAndRaiseEvents(source) : undefined;\n // always invalidate cache on changing columns, as the column id's for the new columns\n // could overlap with the old id's, so the cache would return old values for new columns.\n this.valueCache.expire();\n // NOTE ==================\n // we should be destroying the existing columns and groups if they exist, for example, the original column\n // group adds a listener to the columns, it should be also removing the listeners\n this.autoGroupsNeedBuilding = true;\n var oldPrimaryColumns = this.primaryColumns;\n var oldPrimaryTree = this.primaryColumnTree;\n var balancedTreeResult = this.columnFactory.createColumnTree(this.columnDefs, true, oldPrimaryTree);\n this.primaryColumnTree = balancedTreeResult.columnTree;\n this.primaryHeaderRowCount = balancedTreeResult.treeDept + 1;\n this.primaryColumns = this.getColumnsFromTree(this.primaryColumnTree);\n this.primaryColumnsMap = {};\n this.primaryColumns.forEach(function (col) { return _this.primaryColumnsMap[col.getId()] = col; });\n this.extractRowGroupColumns(source, oldPrimaryColumns);\n this.extractPivotColumns(source, oldPrimaryColumns);\n this.extractValueColumns(source, oldPrimaryColumns);\n this.ready = true;\n // if we are showing secondary columns, then no need to update grid columns\n // at this point, as it's the pivot service responsibility to change these\n // if we are no longer pivoting (ie and need to revert back to primary, otherwise\n // we shouldn't be touching the primary).\n var gridColsNotProcessed = this.gridColsArePrimary === undefined;\n var processGridCols = this.gridColsArePrimary || gridColsNotProcessed;\n if (processGridCols) {\n this.updateGridColumns();\n if (colsPreviouslyExisted && !this.gridOptionsWrapper.isMaintainColumnOrder()) {\n this.orderGridColumnsLikePrimary();\n }\n this.updateDisplayedColumns(source);\n this.checkViewportColumns();\n }\n // this event is not used by AG Grid, but left here for backwards compatibility,\n // in case applications use it\n this.dispatchEverythingChanged(source);\n if (raiseEventsFunc) {\n raiseEventsFunc();\n }\n this.dispatchNewColumnsLoaded();\n };\n ColumnModel.prototype.dispatchNewColumnsLoaded = function () {\n var newColumnsLoadedEvent = {\n type: Events.EVENT_NEW_COLUMNS_LOADED\n };\n this.eventService.dispatchEvent(newColumnsLoadedEvent);\n };\n // this event is legacy, no grid code listens to it. instead the grid listens to New Columns Loaded\n ColumnModel.prototype.dispatchEverythingChanged = function (source) {\n if (source === void 0) { source = 'api'; }\n var eventEverythingChanged = {\n type: Events.EVENT_COLUMN_EVERYTHING_CHANGED,\n source: source\n };\n this.eventService.dispatchEvent(eventEverythingChanged);\n };\n ColumnModel.prototype.orderGridColumnsLikePrimary = function () {\n var _this = this;\n var primaryColumns = this.primaryColumns;\n if (!primaryColumns) {\n return;\n }\n this.gridColumns.sort(function (colA, colB) {\n var primaryIndexA = primaryColumns.indexOf(colA);\n var primaryIndexB = primaryColumns.indexOf(colB);\n // if both cols are present in primary, then we just return the position,\n // so position is maintained.\n var indexAPresent = primaryIndexA >= 0;\n var indexBPresent = primaryIndexB >= 0;\n if (indexAPresent && indexBPresent) {\n return primaryIndexA - primaryIndexB;\n }\n if (indexAPresent) {\n // B is auto group column, so put B first\n return 1;\n }\n if (indexBPresent) {\n // A is auto group column, so put A first\n return -1;\n }\n // otherwise both A and B are auto-group columns. so we just keep the order\n // as they were already in.\n var gridIndexA = _this.gridColumns.indexOf(colA);\n var gridIndexB = _this.gridColumns.indexOf(colB);\n return gridIndexA - gridIndexB;\n });\n this.gridColumns = this.placeLockedColumns(this.gridColumns);\n };\n ColumnModel.prototype.getAllDisplayedAutoHeightCols = function () {\n return this.displayedAutoHeightCols;\n };\n ColumnModel.prototype.setViewport = function () {\n if (this.gridOptionsWrapper.isEnableRtl()) {\n this.viewportLeft = this.bodyWidth - this.scrollPosition - this.scrollWidth;\n this.viewportRight = this.bodyWidth - this.scrollPosition;\n }\n else {\n this.viewportLeft = this.scrollPosition;\n this.viewportRight = this.scrollWidth + this.scrollPosition;\n }\n };\n // used by clipboard service, to know what columns to paste into\n ColumnModel.prototype.getDisplayedColumnsStartingAt = function (column) {\n var currentColumn = column;\n var columns = [];\n while (currentColumn != null) {\n columns.push(currentColumn);\n currentColumn = this.getDisplayedColAfter(currentColumn);\n }\n return columns;\n };\n // checks what columns are currently displayed due to column virtualisation. fires an event\n // if the list of columns has changed.\n // + setColumnWidth(), setViewportPosition(), setColumnDefs(), sizeColumnsToFit()\n ColumnModel.prototype.checkViewportColumns = function () {\n // check displayCenterColumnTree exists first, as it won't exist when grid is initialising\n if (this.displayedColumnsCenter == null) {\n return;\n }\n var viewportColumnsChanged = this.extractViewport();\n if (!viewportColumnsChanged) {\n return;\n }\n var event = {\n type: Events.EVENT_VIRTUAL_COLUMNS_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.setViewportPosition = function (scrollWidth, scrollPosition) {\n if (scrollWidth !== this.scrollWidth || scrollPosition !== this.scrollPosition || this.bodyWidthDirty) {\n this.scrollWidth = scrollWidth;\n this.scrollPosition = scrollPosition;\n // we need to call setVirtualViewportLeftAndRight() at least once after the body width changes,\n // as the viewport can stay the same, but in RTL, if body width changes, we need to work out the\n // virtual columns again\n this.bodyWidthDirty = true;\n this.setViewport();\n if (this.ready) {\n this.checkViewportColumns();\n }\n }\n };\n ColumnModel.prototype.isPivotMode = function () {\n return this.pivotMode;\n };\n ColumnModel.prototype.isPivotSettingAllowed = function (pivot) {\n if (pivot && this.gridOptionsWrapper.isTreeData()) {\n console.warn(\"AG Grid: Pivot mode not available in conjunction Tree Data i.e. 'gridOptions.treeData: true'\");\n return false;\n }\n return true;\n };\n ColumnModel.prototype.setPivotMode = function (pivotMode, source) {\n if (source === void 0) { source = 'api'; }\n if (pivotMode === this.pivotMode || !this.isPivotSettingAllowed(this.pivotMode)) {\n return;\n }\n this.pivotMode = pivotMode;\n // we need to update grid columns to cover the scenario where user has groupSuppressAutoColumn=true, as\n // this means we don't use auto group column UNLESS we are in pivot mode (it's mandatory in pivot mode),\n // so need to updateGridColumn() to check it autoGroupCol needs to be added / removed\n this.autoGroupsNeedBuilding = true;\n this.updateGridColumns();\n this.updateDisplayedColumns(source);\n var event = {\n type: Events.EVENT_COLUMN_PIVOT_MODE_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.getSecondaryPivotColumn = function (pivotKeys, valueColKey) {\n if (missing(this.secondaryColumns)) {\n return null;\n }\n var valueColumnToFind = this.getPrimaryColumn(valueColKey);\n var foundColumn = null;\n this.secondaryColumns.forEach(function (column) {\n var thisPivotKeys = column.getColDef().pivotKeys;\n var pivotValueColumn = column.getColDef().pivotValueColumn;\n var pivotKeyMatches = areEqual(thisPivotKeys, pivotKeys);\n var pivotValueMatches = pivotValueColumn === valueColumnToFind;\n if (pivotKeyMatches && pivotValueMatches) {\n foundColumn = column;\n }\n });\n return foundColumn;\n };\n ColumnModel.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('columnModel');\n };\n ColumnModel.prototype.setFirstRightAndLastLeftPinned = function (source) {\n var lastLeft;\n var firstRight;\n if (this.gridOptionsWrapper.isEnableRtl()) {\n lastLeft = this.displayedColumnsLeft ? this.displayedColumnsLeft[0] : null;\n firstRight = this.displayedColumnsRight ? last(this.displayedColumnsRight) : null;\n }\n else {\n lastLeft = this.displayedColumnsLeft ? last(this.displayedColumnsLeft) : null;\n firstRight = this.displayedColumnsRight ? this.displayedColumnsRight[0] : null;\n }\n this.gridColumns.forEach(function (column) {\n column.setLastLeftPinned(column === lastLeft, source);\n column.setFirstRightPinned(column === firstRight, source);\n });\n };\n ColumnModel.prototype.autoSizeColumns = function (params) {\n var _this = this;\n var columns = params.columns, skipHeader = params.skipHeader, skipHeaderGroups = params.skipHeaderGroups, stopAtGroup = params.stopAtGroup, _a = params.source, source = _a === void 0 ? 'api' : _a;\n // because of column virtualisation, we can only do this function on columns that are\n // actually rendered, as non-rendered columns (outside the viewport and not rendered\n // due to column virtualisation) are not present. this can result in all rendered columns\n // getting narrowed, which in turn introduces more rendered columns on the RHS which\n // did not get autosized in the original run, leaving the visible grid with columns on\n // the LHS sized, but RHS no. so we keep looping through the visible columns until\n // no more cols are available (rendered) to be resized\n // we autosize after animation frames finish in case any cell renderers need to complete first. this can\n // happen eg if client code is calling api.autoSizeAllColumns() straight after grid is initialised, but grid\n // hasn't fully drawn out all the cells yet (due to cell renderers in animation frames).\n this.animationFrameService.flushAllFrames();\n // keep track of which cols we have resized in here\n var columnsAutosized = [];\n // initialise with anything except 0 so that while loop executes at least once\n var changesThisTimeAround = -1;\n var shouldSkipHeader = skipHeader != null ? skipHeader : this.gridOptionsWrapper.isSkipHeaderOnAutoSize();\n var shouldSkipHeaderGroups = skipHeaderGroups != null ? skipHeaderGroups : shouldSkipHeader;\n while (changesThisTimeAround !== 0) {\n changesThisTimeAround = 0;\n this.actionOnGridColumns(columns, function (column) {\n // if already autosized, skip it\n if (columnsAutosized.indexOf(column) >= 0) {\n return false;\n }\n // get how wide this col should be\n var preferredWidth = _this.autoWidthCalculator.getPreferredWidthForColumn(column, shouldSkipHeader);\n // preferredWidth = -1 if this col is not on the screen\n if (preferredWidth > 0) {\n var newWidth = _this.normaliseColumnWidth(column, preferredWidth);\n column.setActualWidth(newWidth, source);\n columnsAutosized.push(column);\n changesThisTimeAround++;\n }\n return true;\n }, source);\n }\n if (!shouldSkipHeaderGroups) {\n this.autoSizeColumnGroupsByColumns(columns, stopAtGroup);\n }\n this.fireColumnResizedEvent(columnsAutosized, true, 'autosizeColumns');\n };\n ColumnModel.prototype.fireColumnResizedEvent = function (columns, finished, source, flexColumns) {\n if (flexColumns === void 0) { flexColumns = null; }\n if (columns && columns.length) {\n var event_1 = {\n type: Events.EVENT_COLUMN_RESIZED,\n columns: columns,\n column: columns.length === 1 ? columns[0] : null,\n flexColumns: flexColumns,\n finished: finished,\n source: source\n };\n this.eventService.dispatchEvent(event_1);\n }\n };\n ColumnModel.prototype.autoSizeColumn = function (key, skipHeader, source) {\n if (source === void 0) { source = \"api\"; }\n if (key) {\n this.autoSizeColumns({ columns: [key], skipHeader: skipHeader, skipHeaderGroups: true, source: source });\n }\n };\n ColumnModel.prototype.autoSizeColumnGroupsByColumns = function (keys, stopAtGroup) {\n var e_1, _a, e_2, _b;\n var columnGroups = new Set();\n var columns = this.getGridColumns(keys);\n columns.forEach(function (col) {\n var parent = col.getParent();\n while (parent && parent != stopAtGroup) {\n if (!parent.isPadding()) {\n columnGroups.add(parent);\n }\n parent = parent.getParent();\n }\n });\n var headerGroupCtrl;\n var resizedColumns = [];\n try {\n for (var columnGroups_1 = __values$4(columnGroups), columnGroups_1_1 = columnGroups_1.next(); !columnGroups_1_1.done; columnGroups_1_1 = columnGroups_1.next()) {\n var columnGroup = columnGroups_1_1.value;\n try {\n for (var _c = (e_2 = void 0, __values$4(this.ctrlsService.getHeaderRowContainerCtrls())), _d = _c.next(); !_d.done; _d = _c.next()) {\n var headerContainerCtrl = _d.value;\n headerGroupCtrl = headerContainerCtrl.getHeaderCtrlForColumn(columnGroup);\n if (headerGroupCtrl) {\n break;\n }\n }\n }\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\n finally {\n try {\n if (_d && !_d.done && (_b = _c.return)) _b.call(_c);\n }\n finally { if (e_2) throw e_2.error; }\n }\n if (headerGroupCtrl) {\n headerGroupCtrl.resizeLeafColumnsToFit();\n }\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (columnGroups_1_1 && !columnGroups_1_1.done && (_a = columnGroups_1.return)) _a.call(columnGroups_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n return resizedColumns;\n };\n ColumnModel.prototype.autoSizeAllColumns = function (skipHeader, source) {\n if (source === void 0) { source = \"api\"; }\n var allDisplayedColumns = this.getAllDisplayedColumns();\n this.autoSizeColumns({ columns: allDisplayedColumns, skipHeader: skipHeader, source: source });\n };\n // Possible candidate for reuse (alot of recursive traversal duplication)\n ColumnModel.prototype.getColumnsFromTree = function (rootColumns) {\n var result = [];\n var recursiveFindColumns = function (childColumns) {\n for (var i = 0; i < childColumns.length; i++) {\n var child = childColumns[i];\n if (child instanceof Column) {\n result.push(child);\n }\n else if (child instanceof ProvidedColumnGroup) {\n recursiveFindColumns(child.getChildren());\n }\n }\n };\n recursiveFindColumns(rootColumns);\n return result;\n };\n ColumnModel.prototype.getAllDisplayedTrees = function () {\n if (this.displayedTreeLeft && this.displayedTreeRight && this.displayedTreeCentre) {\n return this.displayedTreeLeft\n .concat(this.displayedTreeCentre)\n .concat(this.displayedTreeRight);\n }\n return null;\n };\n // + columnSelectPanel\n ColumnModel.prototype.getPrimaryColumnTree = function () {\n return this.primaryColumnTree;\n };\n // + gridPanel -> for resizing the body and setting top margin\n ColumnModel.prototype.getHeaderRowCount = function () {\n return this.gridHeaderRowCount;\n };\n // + headerRenderer -> setting pinned body width\n ColumnModel.prototype.getDisplayedTreeLeft = function () {\n return this.displayedTreeLeft;\n };\n // + headerRenderer -> setting pinned body width\n ColumnModel.prototype.getDisplayedTreeRight = function () {\n return this.displayedTreeRight;\n };\n // + headerRenderer -> setting pinned body width\n ColumnModel.prototype.getDisplayedTreeCentre = function () {\n return this.displayedTreeCentre;\n };\n // gridPanel -> ensureColumnVisible\n ColumnModel.prototype.isColumnDisplayed = function (column) {\n return this.getAllDisplayedColumns().indexOf(column) >= 0;\n };\n // + csvCreator\n ColumnModel.prototype.getAllDisplayedColumns = function () {\n return this.displayedColumns;\n };\n ColumnModel.prototype.getViewportColumns = function () {\n return this.viewportColumns;\n };\n ColumnModel.prototype.getDisplayedLeftColumnsForRow = function (rowNode) {\n if (!this.colSpanActive) {\n return this.displayedColumnsLeft;\n }\n return this.getDisplayedColumnsForRow(rowNode, this.displayedColumnsLeft);\n };\n ColumnModel.prototype.getDisplayedRightColumnsForRow = function (rowNode) {\n if (!this.colSpanActive) {\n return this.displayedColumnsRight;\n }\n return this.getDisplayedColumnsForRow(rowNode, this.displayedColumnsRight);\n };\n ColumnModel.prototype.getDisplayedColumnsForRow = function (rowNode, displayedColumns, filterCallback, emptySpaceBeforeColumn) {\n var result = [];\n var lastConsideredCol = null;\n var _loop_1 = function (i) {\n var col = displayedColumns[i];\n var maxAllowedColSpan = displayedColumns.length - i;\n var colSpan = Math.min(col.getColSpan(rowNode), maxAllowedColSpan);\n var columnsToCheckFilter = [col];\n if (colSpan > 1) {\n var colsToRemove = colSpan - 1;\n for (var j = 1; j <= colsToRemove; j++) {\n columnsToCheckFilter.push(displayedColumns[i + j]);\n }\n i += colsToRemove;\n }\n // see which cols we should take out for column virtualisation\n var filterPasses;\n if (filterCallback) {\n // if user provided a callback, means some columns may not be in the viewport.\n // the user will NOT provide a callback if we are talking about pinned areas,\n // as pinned areas have no horizontal scroll and do not virtualise the columns.\n // if lots of columns, that means column spanning, and we set filterPasses = true\n // if one or more of the columns spanned pass the filter.\n filterPasses = false;\n columnsToCheckFilter.forEach(function (colForFilter) {\n if (filterCallback(colForFilter)) {\n filterPasses = true;\n }\n });\n }\n else {\n filterPasses = true;\n }\n if (filterPasses) {\n if (result.length === 0 && lastConsideredCol) {\n var gapBeforeColumn = emptySpaceBeforeColumn ? emptySpaceBeforeColumn(col) : false;\n if (gapBeforeColumn) {\n result.push(lastConsideredCol);\n }\n }\n result.push(col);\n }\n lastConsideredCol = col;\n out_i_1 = i;\n };\n var out_i_1;\n for (var i = 0; i < displayedColumns.length; i++) {\n _loop_1(i);\n i = out_i_1;\n }\n return result;\n };\n // + rowRenderer\n // if we are not column spanning, this just returns back the virtual centre columns,\n // however if we are column spanning, then different rows can have different virtual\n // columns, so we have to work out the list for each individual row.\n ColumnModel.prototype.getViewportCenterColumnsForRow = function (rowNode) {\n var _this = this;\n if (!this.colSpanActive) {\n return this.viewportColumnsCenter;\n }\n var emptySpaceBeforeColumn = function (col) {\n var left = col.getLeft();\n return exists(left) && left > _this.viewportLeft;\n };\n // if doing column virtualisation, then we filter based on the viewport.\n var filterCallback = this.suppressColumnVirtualisation ? null : this.isColumnInRowViewport.bind(this);\n return this.getDisplayedColumnsForRow(rowNode, this.displayedColumnsCenter, filterCallback, emptySpaceBeforeColumn);\n };\n ColumnModel.prototype.getAriaColumnIndex = function (col) {\n return this.getAllGridColumns().indexOf(col) + 1;\n };\n ColumnModel.prototype.isColumnInHeaderViewport = function (col) {\n // for headers, we never filter out autoHeaderHeight columns, if calculating\n if (col.isAutoHeaderHeight()) {\n return true;\n }\n return this.isColumnInRowViewport(col);\n };\n ColumnModel.prototype.isColumnInRowViewport = function (col) {\n // we never filter out autoHeight columns, as we need them in the DOM for calculating Auto Height\n if (col.isAutoHeight()) {\n return true;\n }\n var columnLeft = col.getLeft() || 0;\n var columnRight = columnLeft + col.getActualWidth();\n // adding 200 for buffer size, so some cols off viewport are rendered.\n // this helps horizontal scrolling so user rarely sees white space (unless\n // they scroll horizontally fast). however we are conservative, as the more\n // buffer the slower the vertical redraw speed\n var leftBounds = this.viewportLeft - 200;\n var rightBounds = this.viewportRight + 200;\n var columnToMuchLeft = columnLeft < leftBounds && columnRight < leftBounds;\n var columnToMuchRight = columnLeft > rightBounds && columnRight > rightBounds;\n return !columnToMuchLeft && !columnToMuchRight;\n };\n // used by:\n // + angularGrid -> setting pinned body width\n // note: this should be cached\n ColumnModel.prototype.getDisplayedColumnsLeftWidth = function () {\n return this.getWidthOfColsInList(this.displayedColumnsLeft);\n };\n // note: this should be cached\n ColumnModel.prototype.getDisplayedColumnsRightWidth = function () {\n return this.getWidthOfColsInList(this.displayedColumnsRight);\n };\n ColumnModel.prototype.updatePrimaryColumnList = function (keys, masterList, actionIsAdd, columnCallback, eventType, source) {\n var _this = this;\n if (source === void 0) { source = \"api\"; }\n if (!keys || missingOrEmpty(keys)) {\n return;\n }\n var atLeastOne = false;\n keys.forEach(function (key) {\n var columnToAdd = _this.getPrimaryColumn(key);\n if (!columnToAdd) {\n return;\n }\n if (actionIsAdd) {\n if (masterList.indexOf(columnToAdd) >= 0) {\n return;\n }\n masterList.push(columnToAdd);\n }\n else {\n if (masterList.indexOf(columnToAdd) < 0) {\n return;\n }\n removeFromArray(masterList, columnToAdd);\n }\n columnCallback(columnToAdd);\n atLeastOne = true;\n });\n if (!atLeastOne) {\n return;\n }\n if (this.autoGroupsNeedBuilding) {\n this.updateGridColumns();\n }\n this.updateDisplayedColumns(source);\n var event = {\n type: eventType,\n columns: masterList,\n column: masterList.length === 1 ? masterList[0] : null,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.setRowGroupColumns = function (colKeys, source) {\n if (source === void 0) { source = \"api\"; }\n this.autoGroupsNeedBuilding = true;\n this.setPrimaryColumnList(colKeys, this.rowGroupColumns, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.setRowGroupActive.bind(this), source);\n };\n ColumnModel.prototype.setRowGroupActive = function (active, column, source) {\n if (active === column.isRowGroupActive()) {\n return;\n }\n column.setRowGroupActive(active, source);\n if (active && !this.gridOptionsWrapper.isSuppressRowGroupHidesColumns()) {\n this.setColumnVisible(column, false, source);\n }\n if (!active && !this.gridOptionsWrapper.isSuppressMakeColumnVisibleAfterUnGroup()) {\n this.setColumnVisible(column, true, source);\n }\n };\n ColumnModel.prototype.addRowGroupColumn = function (key, source) {\n if (source === void 0) { source = \"api\"; }\n if (key) {\n this.addRowGroupColumns([key], source);\n }\n };\n ColumnModel.prototype.addRowGroupColumns = function (keys, source) {\n if (source === void 0) { source = \"api\"; }\n this.autoGroupsNeedBuilding = true;\n this.updatePrimaryColumnList(keys, this.rowGroupColumns, true, this.setRowGroupActive.bind(this, true), Events.EVENT_COLUMN_ROW_GROUP_CHANGED, source);\n };\n ColumnModel.prototype.removeRowGroupColumns = function (keys, source) {\n if (source === void 0) { source = \"api\"; }\n this.autoGroupsNeedBuilding = true;\n this.updatePrimaryColumnList(keys, this.rowGroupColumns, false, this.setRowGroupActive.bind(this, false), Events.EVENT_COLUMN_ROW_GROUP_CHANGED, source);\n };\n ColumnModel.prototype.removeRowGroupColumn = function (key, source) {\n if (source === void 0) { source = \"api\"; }\n if (key) {\n this.removeRowGroupColumns([key], source);\n }\n };\n ColumnModel.prototype.addPivotColumns = function (keys, source) {\n if (source === void 0) { source = \"api\"; }\n this.updatePrimaryColumnList(keys, this.pivotColumns, true, function (column) { return column.setPivotActive(true, source); }, Events.EVENT_COLUMN_PIVOT_CHANGED, source);\n };\n ColumnModel.prototype.setPivotColumns = function (colKeys, source) {\n if (source === void 0) { source = \"api\"; }\n this.setPrimaryColumnList(colKeys, this.pivotColumns, Events.EVENT_COLUMN_PIVOT_CHANGED, function (added, column) {\n column.setPivotActive(added, source);\n }, source);\n };\n ColumnModel.prototype.addPivotColumn = function (key, source) {\n if (source === void 0) { source = \"api\"; }\n this.addPivotColumns([key], source);\n };\n ColumnModel.prototype.removePivotColumns = function (keys, source) {\n if (source === void 0) { source = \"api\"; }\n this.updatePrimaryColumnList(keys, this.pivotColumns, false, function (column) { return column.setPivotActive(false, source); }, Events.EVENT_COLUMN_PIVOT_CHANGED, source);\n };\n ColumnModel.prototype.removePivotColumn = function (key, source) {\n if (source === void 0) { source = \"api\"; }\n this.removePivotColumns([key], source);\n };\n ColumnModel.prototype.setPrimaryColumnList = function (colKeys, masterList, eventName, columnCallback, source) {\n var _this = this;\n masterList.length = 0;\n if (exists(colKeys)) {\n colKeys.forEach(function (key) {\n var column = _this.getPrimaryColumn(key);\n if (column) {\n masterList.push(column);\n }\n });\n }\n (this.primaryColumns || []).forEach(function (column) {\n var added = masterList.indexOf(column) >= 0;\n columnCallback(added, column);\n });\n if (this.autoGroupsNeedBuilding) {\n this.updateGridColumns();\n }\n this.updateDisplayedColumns(source);\n this.fireColumnEvent(eventName, masterList, source);\n };\n ColumnModel.prototype.setValueColumns = function (colKeys, source) {\n if (source === void 0) { source = \"api\"; }\n this.setPrimaryColumnList(colKeys, this.valueColumns, Events.EVENT_COLUMN_VALUE_CHANGED, this.setValueActive.bind(this), source);\n };\n ColumnModel.prototype.setValueActive = function (active, column, source) {\n if (active === column.isValueActive()) {\n return;\n }\n column.setValueActive(active, source);\n if (active && !column.getAggFunc()) {\n var initialAggFunc = this.aggFuncService.getDefaultAggFunc(column);\n column.setAggFunc(initialAggFunc);\n }\n };\n ColumnModel.prototype.addValueColumns = function (keys, source) {\n if (source === void 0) { source = \"api\"; }\n this.updatePrimaryColumnList(keys, this.valueColumns, true, this.setValueActive.bind(this, true), Events.EVENT_COLUMN_VALUE_CHANGED, source);\n };\n ColumnModel.prototype.addValueColumn = function (colKey, source) {\n if (source === void 0) { source = \"api\"; }\n if (colKey) {\n this.addValueColumns([colKey], source);\n }\n };\n ColumnModel.prototype.removeValueColumn = function (colKey, source) {\n if (source === void 0) { source = \"api\"; }\n this.removeValueColumns([colKey], source);\n };\n ColumnModel.prototype.removeValueColumns = function (keys, source) {\n if (source === void 0) { source = \"api\"; }\n this.updatePrimaryColumnList(keys, this.valueColumns, false, this.setValueActive.bind(this, false), Events.EVENT_COLUMN_VALUE_CHANGED, source);\n };\n // returns the width we can set to this col, taking into consideration min and max widths\n ColumnModel.prototype.normaliseColumnWidth = function (column, newWidth) {\n var minWidth = column.getMinWidth();\n if (exists(minWidth) && newWidth < minWidth) {\n newWidth = minWidth;\n }\n var maxWidth = column.getMaxWidth();\n if (exists(maxWidth) && column.isGreaterThanMax(newWidth)) {\n newWidth = maxWidth;\n }\n return newWidth;\n };\n ColumnModel.prototype.getPrimaryOrGridColumn = function (key) {\n var column = this.getPrimaryColumn(key);\n return column || this.getGridColumn(key);\n };\n ColumnModel.prototype.setColumnWidths = function (columnWidths, shiftKey, // @takeFromAdjacent - if user has 'shift' pressed, then pixels are taken from adjacent column\n finished, // @finished - ends up in the event, tells the user if more events are to come\n source) {\n var _this = this;\n if (source === void 0) { source = \"api\"; }\n var sets = [];\n columnWidths.forEach(function (columnWidth) {\n var col = _this.getPrimaryOrGridColumn(columnWidth.key);\n if (!col) {\n return;\n }\n sets.push({\n width: columnWidth.newWidth,\n ratios: [1],\n columns: [col]\n });\n // if user wants to do shift resize by default, then we invert the shift operation\n var defaultIsShift = _this.gridOptionsWrapper.getColResizeDefault() === 'shift';\n if (defaultIsShift) {\n shiftKey = !shiftKey;\n }\n if (shiftKey) {\n var otherCol = _this.getDisplayedColAfter(col);\n if (!otherCol) {\n return;\n }\n var widthDiff = col.getActualWidth() - columnWidth.newWidth;\n var otherColWidth = otherCol.getActualWidth() + widthDiff;\n sets.push({\n width: otherColWidth,\n ratios: [1],\n columns: [otherCol]\n });\n }\n });\n if (sets.length === 0) {\n return;\n }\n this.resizeColumnSets({\n resizeSets: sets,\n finished: finished,\n source: source\n });\n };\n ColumnModel.prototype.checkMinAndMaxWidthsForSet = function (columnResizeSet) {\n var columns = columnResizeSet.columns, width = columnResizeSet.width;\n // every col has a min width, so sum them all up and see if we have enough room\n // for all the min widths\n var minWidthAccumulated = 0;\n var maxWidthAccumulated = 0;\n var maxWidthActive = true;\n columns.forEach(function (col) {\n var minWidth = col.getMinWidth();\n minWidthAccumulated += minWidth || 0;\n var maxWidth = col.getMaxWidth();\n if (exists(maxWidth) && maxWidth > 0) {\n maxWidthAccumulated += maxWidth;\n }\n else {\n // if at least one columns has no max width, it means the group of columns\n // then has no max width, as at least one column can take as much width as possible\n maxWidthActive = false;\n }\n });\n var minWidthPasses = width >= minWidthAccumulated;\n var maxWidthPasses = !maxWidthActive || (width <= maxWidthAccumulated);\n return minWidthPasses && maxWidthPasses;\n };\n // method takes sets of columns and resizes them. either all sets will be resized, or nothing\n // be resized. this is used for example when user tries to resize a group and holds shift key,\n // then both the current group (grows), and the adjacent group (shrinks), will get resized,\n // so that's two sets for this method.\n ColumnModel.prototype.resizeColumnSets = function (params) {\n var _this = this;\n var resizeSets = params.resizeSets, finished = params.finished, source = params.source;\n var passMinMaxCheck = !resizeSets || resizeSets.every(function (columnResizeSet) { return _this.checkMinAndMaxWidthsForSet(columnResizeSet); });\n if (!passMinMaxCheck) {\n // even though we are not going to resize beyond min/max size, we still need to raise event when finished\n if (finished) {\n var columns = resizeSets && resizeSets.length > 0 ? resizeSets[0].columns : null;\n this.fireColumnResizedEvent(columns, finished, source);\n }\n return; // don't resize!\n }\n var changedCols = [];\n var allResizedCols = [];\n resizeSets.forEach(function (set) {\n var width = set.width, columns = set.columns, ratios = set.ratios;\n // keep track of pixels used, and last column gets the remaining,\n // to cater for rounding errors, and min width adjustments\n var newWidths = {};\n var finishedCols = {};\n columns.forEach(function (col) { return allResizedCols.push(col); });\n // the loop below goes through each col. if a col exceeds it's min/max width,\n // it then gets set to its min/max width and the column is removed marked as 'finished'\n // and the calculation is done again leaving this column out. take for example columns\n // {A, width: 50, maxWidth: 100}\n // {B, width: 50}\n // {C, width: 50}\n // and then the set is set to width 600 - on the first pass the grid tries to set each column\n // to 200. it checks A and sees 200 > 100 and so sets the width to 100. col A is then marked\n // as 'finished' and the calculation is done again with the remaining cols B and C, which end up\n // splitting the remaining 500 pixels.\n var finishedColsGrew = true;\n var loopCount = 0;\n var _loop_2 = function () {\n loopCount++;\n if (loopCount > 1000) {\n // this should never happen, but in the future, someone might introduce a bug here,\n // so we stop the browser from hanging and report bug properly\n console.error('AG Grid: infinite loop in resizeColumnSets');\n return \"break\";\n }\n finishedColsGrew = false;\n var subsetCols = [];\n var subsetRatioTotal = 0;\n var pixelsToDistribute = width;\n columns.forEach(function (col, index) {\n var thisColFinished = finishedCols[col.getId()];\n if (thisColFinished) {\n pixelsToDistribute -= newWidths[col.getId()];\n }\n else {\n subsetCols.push(col);\n var ratioThisCol = ratios[index];\n subsetRatioTotal += ratioThisCol;\n }\n });\n // because we are not using all of the ratios (cols can be missing),\n // we scale the ratio. if all columns are included, then subsetRatioTotal=1,\n // and so the ratioScale will be 1.\n var ratioScale = 1 / subsetRatioTotal;\n subsetCols.forEach(function (col, index) {\n var lastCol = index === (subsetCols.length - 1);\n var colNewWidth;\n if (lastCol) {\n colNewWidth = pixelsToDistribute;\n }\n else {\n colNewWidth = Math.round(ratios[index] * width * ratioScale);\n pixelsToDistribute -= colNewWidth;\n }\n var minWidth = col.getMinWidth();\n var maxWidth = col.getMaxWidth();\n if (exists(minWidth) && colNewWidth < minWidth) {\n colNewWidth = minWidth;\n finishedCols[col.getId()] = true;\n finishedColsGrew = true;\n }\n else if (exists(maxWidth) && maxWidth > 0 && colNewWidth > maxWidth) {\n colNewWidth = maxWidth;\n finishedCols[col.getId()] = true;\n finishedColsGrew = true;\n }\n newWidths[col.getId()] = colNewWidth;\n });\n };\n while (finishedColsGrew) {\n var state_1 = _loop_2();\n if (state_1 === \"break\")\n break;\n }\n columns.forEach(function (col) {\n var newWidth = newWidths[col.getId()];\n var actualWidth = col.getActualWidth();\n if (actualWidth !== newWidth) {\n col.setActualWidth(newWidth, source);\n changedCols.push(col);\n }\n });\n });\n // if no cols changed, then no need to update more or send event.\n var atLeastOneColChanged = changedCols.length > 0;\n var flexedCols = [];\n if (atLeastOneColChanged) {\n flexedCols = this.refreshFlexedColumns({ resizingCols: allResizedCols, skipSetLeft: true });\n this.setLeftValues(source);\n this.updateBodyWidths();\n this.checkViewportColumns();\n }\n // check for change first, to avoid unnecessary firing of events\n // however we always fire 'finished' events. this is important\n // when groups are resized, as if the group is changing slowly,\n // eg 1 pixel at a time, then each change will fire change events\n // in all the columns in the group, but only one with get the pixel.\n var colsForEvent = allResizedCols.concat(flexedCols);\n if (atLeastOneColChanged || finished) {\n this.fireColumnResizedEvent(colsForEvent, finished, source, flexedCols);\n }\n };\n ColumnModel.prototype.setColumnAggFunc = function (key, aggFunc, source) {\n if (source === void 0) { source = \"api\"; }\n if (!key) {\n return;\n }\n var column = this.getPrimaryColumn(key);\n if (!column) {\n return;\n }\n column.setAggFunc(aggFunc);\n this.fireColumnEvent(Events.EVENT_COLUMN_VALUE_CHANGED, [column], source);\n };\n ColumnModel.prototype.fireColumnEvent = function (type, columns, source) {\n var event = {\n type: type,\n columns: columns,\n column: (columns && columns.length == 1) ? columns[0] : null,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.moveRowGroupColumn = function (fromIndex, toIndex, source) {\n if (source === void 0) { source = \"api\"; }\n var column = this.rowGroupColumns[fromIndex];\n this.rowGroupColumns.splice(fromIndex, 1);\n this.rowGroupColumns.splice(toIndex, 0, column);\n var event = {\n type: Events.EVENT_COLUMN_ROW_GROUP_CHANGED,\n columns: this.rowGroupColumns,\n column: this.rowGroupColumns.length === 1 ? this.rowGroupColumns[0] : null,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.moveColumns = function (columnsToMoveKeys, toIndex, source) {\n if (source === void 0) { source = \"api\"; }\n this.columnAnimationService.start();\n if (toIndex > this.gridColumns.length - columnsToMoveKeys.length) {\n console.warn('AG Grid: tried to insert columns in invalid location, toIndex = ' + toIndex);\n console.warn('AG Grid: remember that you should not count the moving columns when calculating the new index');\n return;\n }\n // we want to pull all the columns out first and put them into an ordered list\n var columnsToMove = this.getGridColumns(columnsToMoveKeys);\n var failedRules = !this.doesMovePassRules(columnsToMove, toIndex);\n if (failedRules) {\n return;\n }\n moveInArray(this.gridColumns, columnsToMove, toIndex);\n this.updateDisplayedColumns(source);\n var event = {\n type: Events.EVENT_COLUMN_MOVED,\n columns: columnsToMove,\n column: columnsToMove.length === 1 ? columnsToMove[0] : null,\n toIndex: toIndex,\n source: source\n };\n this.eventService.dispatchEvent(event);\n this.columnAnimationService.finish();\n };\n ColumnModel.prototype.doesMovePassRules = function (columnsToMove, toIndex) {\n // make a copy of what the grid columns would look like after the move\n var proposedColumnOrder = this.getProposedColumnOrder(columnsToMove, toIndex);\n return this.doesOrderPassRules(proposedColumnOrder);\n };\n ColumnModel.prototype.doesOrderPassRules = function (gridOrder) {\n if (!this.doesMovePassMarryChildren(gridOrder)) {\n return false;\n }\n if (!this.doesMovePassLockedPositions(gridOrder)) {\n return false;\n }\n return true;\n };\n ColumnModel.prototype.getProposedColumnOrder = function (columnsToMove, toIndex) {\n var proposedColumnOrder = this.gridColumns.slice();\n moveInArray(proposedColumnOrder, columnsToMove, toIndex);\n return proposedColumnOrder;\n };\n // returns the provided cols sorted in same order as they appear in grid columns. eg if grid columns\n // contains [a,b,c,d,e] and col passed is [e,a] then the passed cols are sorted into [a,e]\n ColumnModel.prototype.sortColumnsLikeGridColumns = function (cols) {\n var _this = this;\n if (!cols || cols.length <= 1) {\n return;\n }\n var notAllColsInGridColumns = cols.filter(function (c) { return _this.gridColumns.indexOf(c) < 0; }).length > 0;\n if (notAllColsInGridColumns) {\n return;\n }\n cols.sort(function (a, b) {\n var indexA = _this.gridColumns.indexOf(a);\n var indexB = _this.gridColumns.indexOf(b);\n return indexA - indexB;\n });\n };\n ColumnModel.prototype.doesMovePassLockedPositions = function (proposedColumnOrder) {\n // Placement is a number indicating 'left' 'center' or 'right' as 0 1 2\n var lastPlacement = 0;\n var rulePassed = true;\n var lockPositionToPlacement = function (position) {\n if (!position) { // false or undefined\n return 1;\n }\n if (position === true) {\n return 0;\n }\n return position === 'left' ? 0 : 2; // Otherwise 'right'\n };\n proposedColumnOrder.forEach(function (col) {\n var placement = lockPositionToPlacement(col.getColDef().lockPosition);\n if (placement < lastPlacement) { // If placement goes down, we're not in the correct order\n rulePassed = false;\n }\n lastPlacement = placement;\n });\n return rulePassed;\n };\n ColumnModel.prototype.doesMovePassMarryChildren = function (allColumnsCopy) {\n var rulePassed = true;\n this.columnUtils.depthFirstOriginalTreeSearch(null, this.gridBalancedTree, function (child) {\n if (!(child instanceof ProvidedColumnGroup)) {\n return;\n }\n var columnGroup = child;\n var colGroupDef = columnGroup.getColGroupDef();\n var marryChildren = colGroupDef && colGroupDef.marryChildren;\n if (!marryChildren) {\n return;\n }\n var newIndexes = [];\n columnGroup.getLeafColumns().forEach(function (col) {\n var newColIndex = allColumnsCopy.indexOf(col);\n newIndexes.push(newColIndex);\n });\n var maxIndex = Math.max.apply(Math, newIndexes);\n var minIndex = Math.min.apply(Math, newIndexes);\n // spread is how far the first column in this group is away from the last column\n var spread = maxIndex - minIndex;\n var maxSpread = columnGroup.getLeafColumns().length - 1;\n // if the columns\n if (spread > maxSpread) {\n rulePassed = false;\n }\n // console.log(`maxIndex = ${maxIndex}, minIndex = ${minIndex}, spread = ${spread}, maxSpread = ${maxSpread}, fail = ${spread > (count-1)}`)\n // console.log(allColumnsCopy.map( col => col.getColDef().field).join(','));\n });\n return rulePassed;\n };\n ColumnModel.prototype.moveColumn = function (key, toIndex, source) {\n if (source === void 0) { source = \"api\"; }\n this.moveColumns([key], toIndex, source);\n };\n ColumnModel.prototype.moveColumnByIndex = function (fromIndex, toIndex, source) {\n if (source === void 0) { source = \"api\"; }\n var column = this.gridColumns[fromIndex];\n this.moveColumn(column, toIndex, source);\n };\n ColumnModel.prototype.getColumnDefs = function () {\n var _this = this;\n if (!this.primaryColumns) {\n return;\n }\n var cols = this.primaryColumns.slice();\n if (this.gridColsArePrimary) {\n cols.sort(function (a, b) { return _this.gridColumns.indexOf(a) - _this.gridColumns.indexOf(b); });\n }\n else if (this.lastPrimaryOrder) {\n cols.sort(function (a, b) { return _this.lastPrimaryOrder.indexOf(a) - _this.lastPrimaryOrder.indexOf(b); });\n }\n return this.columnDefFactory.buildColumnDefs(cols, this.rowGroupColumns, this.pivotColumns);\n };\n // used by:\n // + angularGrid -> for setting body width\n // + rowController -> setting main row widths (when inserting and resizing)\n // need to cache this\n ColumnModel.prototype.getBodyContainerWidth = function () {\n return this.bodyWidth;\n };\n ColumnModel.prototype.getContainerWidth = function (pinned) {\n switch (pinned) {\n case Constants.PINNED_LEFT:\n return this.leftWidth;\n case Constants.PINNED_RIGHT:\n return this.rightWidth;\n default:\n return this.bodyWidth;\n }\n };\n // after setColumnWidth or updateGroupsAndDisplayedColumns\n ColumnModel.prototype.updateBodyWidths = function () {\n var newBodyWidth = this.getWidthOfColsInList(this.displayedColumnsCenter);\n var newLeftWidth = this.getWidthOfColsInList(this.displayedColumnsLeft);\n var newRightWidth = this.getWidthOfColsInList(this.displayedColumnsRight);\n // this is used by virtual col calculation, for RTL only, as a change to body width can impact displayed\n // columns, due to RTL inverting the y coordinates\n this.bodyWidthDirty = this.bodyWidth !== newBodyWidth;\n var atLeastOneChanged = this.bodyWidth !== newBodyWidth || this.leftWidth !== newLeftWidth || this.rightWidth !== newRightWidth;\n if (atLeastOneChanged) {\n this.bodyWidth = newBodyWidth;\n this.leftWidth = newLeftWidth;\n this.rightWidth = newRightWidth;\n // when this fires, it is picked up by the gridPanel, which ends up in\n // gridPanel calling setWidthAndScrollPosition(), which in turn calls setViewportPosition()\n var event_2 = {\n type: Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED,\n };\n this.eventService.dispatchEvent(event_2);\n }\n };\n // + rowController\n ColumnModel.prototype.getValueColumns = function () {\n return this.valueColumns ? this.valueColumns : [];\n };\n // + rowController\n ColumnModel.prototype.getPivotColumns = function () {\n return this.pivotColumns ? this.pivotColumns : [];\n };\n // + clientSideRowModel\n ColumnModel.prototype.isPivotActive = function () {\n return this.pivotColumns && this.pivotColumns.length > 0 && this.pivotMode;\n };\n // + toolPanel\n ColumnModel.prototype.getRowGroupColumns = function () {\n return this.rowGroupColumns ? this.rowGroupColumns : [];\n };\n // + rowController -> while inserting rows\n ColumnModel.prototype.getDisplayedCenterColumns = function () {\n return this.displayedColumnsCenter;\n };\n // + rowController -> while inserting rows\n ColumnModel.prototype.getDisplayedLeftColumns = function () {\n return this.displayedColumnsLeft;\n };\n ColumnModel.prototype.getDisplayedRightColumns = function () {\n return this.displayedColumnsRight;\n };\n ColumnModel.prototype.getDisplayedColumns = function (type) {\n switch (type) {\n case Constants.PINNED_LEFT:\n return this.getDisplayedLeftColumns();\n case Constants.PINNED_RIGHT:\n return this.getDisplayedRightColumns();\n default:\n return this.getDisplayedCenterColumns();\n }\n };\n // used by:\n // + clientSideRowController -> sorting, building quick filter text\n // + headerRenderer -> sorting (clearing icon)\n ColumnModel.prototype.getAllPrimaryColumns = function () {\n return this.primaryColumns ? this.primaryColumns.slice() : null;\n };\n ColumnModel.prototype.getSecondaryColumns = function () {\n return this.secondaryColumns ? this.secondaryColumns.slice() : null;\n };\n ColumnModel.prototype.getAllColumnsForQuickFilter = function () {\n return this.columnsForQuickFilter;\n };\n // + moveColumnController\n ColumnModel.prototype.getAllGridColumns = function () {\n return this.gridColumns;\n };\n ColumnModel.prototype.isEmpty = function () {\n return missingOrEmpty(this.gridColumns);\n };\n ColumnModel.prototype.isRowGroupEmpty = function () {\n return missingOrEmpty(this.rowGroupColumns);\n };\n ColumnModel.prototype.setColumnVisible = function (key, visible, source) {\n if (source === void 0) { source = \"api\"; }\n this.setColumnsVisible([key], visible, source);\n };\n ColumnModel.prototype.setColumnsVisible = function (keys, visible, source) {\n if (visible === void 0) { visible = false; }\n this.applyColumnState({\n state: keys.map(function (key) { return ({\n colId: typeof key === 'string' ? key : key.getColId(),\n hide: !visible,\n }); }),\n });\n };\n ColumnModel.prototype.setColumnPinned = function (key, pinned, source) {\n if (source === void 0) { source = \"api\"; }\n if (key) {\n this.setColumnsPinned([key], pinned, source);\n }\n };\n ColumnModel.prototype.setColumnsPinned = function (keys, pinned, source) {\n if (source === void 0) { source = \"api\"; }\n if (this.gridOptionsWrapper.getDomLayout() === 'print') {\n console.warn(\"Changing the column pinning status is not allowed with domLayout='print'\");\n return;\n }\n this.columnAnimationService.start();\n var actualPinned;\n if (pinned === true || pinned === Constants.PINNED_LEFT) {\n actualPinned = Constants.PINNED_LEFT;\n }\n else if (pinned === Constants.PINNED_RIGHT) {\n actualPinned = Constants.PINNED_RIGHT;\n }\n else {\n actualPinned = null;\n }\n this.actionOnGridColumns(keys, function (col) {\n if (col.getPinned() !== actualPinned) {\n col.setPinned(actualPinned);\n return true;\n }\n return false;\n }, source, function () {\n var event = {\n type: Events.EVENT_COLUMN_PINNED,\n pinned: actualPinned,\n column: null,\n columns: null,\n source: source\n };\n return event;\n });\n this.columnAnimationService.finish();\n };\n // does an action on a set of columns. provides common functionality for looking up the\n // columns based on key, getting a list of effected columns, and then updated the event\n // with either one column (if it was just one col) or a list of columns\n // used by: autoResize, setVisible, setPinned\n ColumnModel.prototype.actionOnGridColumns = function (// the column keys this action will be on\n keys, \n // the action to do - if this returns false, the column was skipped\n // and won't be included in the event\n action, \n // should return back a column event of the right type\n source, createEvent) {\n var _this = this;\n if (missingOrEmpty(keys)) {\n return;\n }\n var updatedColumns = [];\n keys.forEach(function (key) {\n var column = _this.getGridColumn(key);\n if (!column) {\n return;\n }\n // need to check for false with type (ie !== instead of !=)\n // as not returning anything (undefined) would also be false\n var resultOfAction = action(column);\n if (resultOfAction !== false) {\n updatedColumns.push(column);\n }\n });\n if (!updatedColumns.length) {\n return;\n }\n this.updateDisplayedColumns(source);\n if (exists(createEvent) && createEvent) {\n var event_3 = createEvent();\n event_3.columns = updatedColumns;\n event_3.column = updatedColumns.length === 1 ? updatedColumns[0] : null;\n this.eventService.dispatchEvent(event_3);\n }\n };\n ColumnModel.prototype.getDisplayedColBefore = function (col) {\n var allDisplayedColumns = this.getAllDisplayedColumns();\n var oldIndex = allDisplayedColumns.indexOf(col);\n if (oldIndex > 0) {\n return allDisplayedColumns[oldIndex - 1];\n }\n return null;\n };\n // used by:\n // + rowRenderer -> for navigation\n ColumnModel.prototype.getDisplayedColAfter = function (col) {\n var allDisplayedColumns = this.getAllDisplayedColumns();\n var oldIndex = allDisplayedColumns.indexOf(col);\n if (oldIndex < (allDisplayedColumns.length - 1)) {\n return allDisplayedColumns[oldIndex + 1];\n }\n return null;\n };\n ColumnModel.prototype.getDisplayedGroupAfter = function (columnGroup) {\n return this.getDisplayedGroupAtDirection(columnGroup, 'After');\n };\n ColumnModel.prototype.getDisplayedGroupBefore = function (columnGroup) {\n return this.getDisplayedGroupAtDirection(columnGroup, 'Before');\n };\n ColumnModel.prototype.getDisplayedGroupAtDirection = function (columnGroup, direction) {\n // pick the last displayed column in this group\n var requiredLevel = columnGroup.getProvidedColumnGroup().getLevel() + columnGroup.getPaddingLevel();\n var colGroupLeafColumns = columnGroup.getDisplayedLeafColumns();\n var col = direction === 'After' ? last(colGroupLeafColumns) : colGroupLeafColumns[0];\n var getDisplayColMethod = \"getDisplayedCol\" + direction;\n while (true) {\n // keep moving to the next col, until we get to another group\n var column = this[getDisplayColMethod](col);\n if (!column) {\n return null;\n }\n var groupPointer = this.getColumnGroupAtLevel(column, requiredLevel);\n if (groupPointer !== columnGroup) {\n return groupPointer;\n }\n }\n };\n ColumnModel.prototype.getColumnGroupAtLevel = function (column, level) {\n // get group at same level as the one we are looking for\n var groupPointer = column.getParent();\n var originalGroupLevel;\n var groupPointerLevel;\n while (true) {\n var groupPointerProvidedColumnGroup = groupPointer.getProvidedColumnGroup();\n originalGroupLevel = groupPointerProvidedColumnGroup.getLevel();\n groupPointerLevel = groupPointer.getPaddingLevel();\n if (originalGroupLevel + groupPointerLevel <= level) {\n break;\n }\n groupPointer = groupPointer.getParent();\n }\n return groupPointer;\n };\n ColumnModel.prototype.isPinningLeft = function () {\n return this.displayedColumnsLeft.length > 0;\n };\n ColumnModel.prototype.isPinningRight = function () {\n return this.displayedColumnsRight.length > 0;\n };\n ColumnModel.prototype.getPrimaryAndSecondaryAndAutoColumns = function () {\n var _a;\n return (_a = []).concat.apply(_a, __spread$f([\n this.primaryColumns || [],\n this.groupAutoColumns || [],\n this.secondaryColumns || [],\n ]));\n };\n ColumnModel.prototype.getPrimaryAndAutoGroupCols = function () {\n var _a;\n return (_a = []).concat.apply(_a, __spread$f([\n this.primaryColumns || [],\n this.groupAutoColumns || [],\n ]));\n };\n ColumnModel.prototype.getPrimaryAndSecondaryColumns = function () {\n var _a;\n return (_a = []).concat.apply(_a, __spread$f([\n this.primaryColumns || [],\n this.secondaryColumns || [],\n ]));\n };\n ColumnModel.prototype.createStateItemFromColumn = function (column) {\n var rowGroupIndex = column.isRowGroupActive() ? this.rowGroupColumns.indexOf(column) : null;\n var pivotIndex = column.isPivotActive() ? this.pivotColumns.indexOf(column) : null;\n var aggFunc = column.isValueActive() ? column.getAggFunc() : null;\n var sort = column.getSort() != null ? column.getSort() : null;\n var sortIndex = column.getSortIndex() != null ? column.getSortIndex() : null;\n var flex = column.getFlex() != null && column.getFlex() > 0 ? column.getFlex() : null;\n var res = {\n colId: column.getColId(),\n width: column.getActualWidth(),\n hide: !column.isVisible(),\n pinned: column.getPinned(),\n sort: sort,\n sortIndex: sortIndex,\n aggFunc: aggFunc,\n rowGroup: column.isRowGroupActive(),\n rowGroupIndex: rowGroupIndex,\n pivot: column.isPivotActive(),\n pivotIndex: pivotIndex,\n flex: flex\n };\n return res;\n };\n ColumnModel.prototype.getColumnState = function () {\n if (missing(this.primaryColumns) || !this.isAlive()) {\n return [];\n }\n var colsForState = this.getPrimaryAndSecondaryAndAutoColumns();\n var res = colsForState.map(this.createStateItemFromColumn.bind(this));\n this.orderColumnStateList(res);\n return res;\n };\n ColumnModel.prototype.orderColumnStateList = function (columnStateList) {\n // for fast looking, store the index of each column\n var colIdToGridIndexMap = convertToMap(this.gridColumns.map(function (col, index) { return [col.getColId(), index]; }));\n columnStateList.sort(function (itemA, itemB) {\n var posA = colIdToGridIndexMap.has(itemA.colId) ? colIdToGridIndexMap.get(itemA.colId) : -1;\n var posB = colIdToGridIndexMap.has(itemB.colId) ? colIdToGridIndexMap.get(itemB.colId) : -1;\n return posA - posB;\n });\n };\n ColumnModel.prototype.resetColumnState = function (source) {\n // NOTE = there is one bug here that no customer has noticed - if a column has colDef.lockPosition,\n // this is ignored below when ordering the cols. to work, we should always put lockPosition cols first.\n // As a work around, developers should just put lockPosition columns first in their colDef list.\n if (source === void 0) { source = \"api\"; }\n // we can't use 'allColumns' as the order might of messed up, so get the primary ordered list\n var primaryColumns = this.getColumnsFromTree(this.primaryColumnTree);\n var columnStates = [];\n // we start at 1000, so if user has mix of rowGroup and group specified, it will work with both.\n // eg IF user has ColA.rowGroupIndex=0, ColB.rowGroupIndex=1, ColC.rowGroup=true,\n // THEN result will be ColA.rowGroupIndex=0, ColB.rowGroupIndex=1, ColC.rowGroup=1000\n var letRowGroupIndex = 1000;\n var letPivotIndex = 1000;\n var colsToProcess = [];\n if (this.groupAutoColumns) {\n colsToProcess = colsToProcess.concat(this.groupAutoColumns);\n }\n if (primaryColumns) {\n colsToProcess = colsToProcess.concat(primaryColumns);\n }\n colsToProcess.forEach(function (column) {\n var getValueOrNull = function (a, b) { return a != null ? a : b != null ? b : null; };\n var colDef = column.getColDef();\n var sort = getValueOrNull(colDef.sort, colDef.initialSort);\n var sortIndex = getValueOrNull(colDef.sortIndex, colDef.initialSortIndex);\n var hide = getValueOrNull(colDef.hide, colDef.initialHide);\n var pinned = getValueOrNull(colDef.pinned, colDef.initialPinned);\n var width = getValueOrNull(colDef.width, colDef.initialWidth);\n var flex = getValueOrNull(colDef.flex, colDef.initialFlex);\n var rowGroupIndex = getValueOrNull(colDef.rowGroupIndex, colDef.initialRowGroupIndex);\n var rowGroup = getValueOrNull(colDef.rowGroup, colDef.initialRowGroup);\n if (rowGroupIndex == null && (rowGroup == null || rowGroup == false)) {\n rowGroupIndex = null;\n rowGroup = null;\n }\n var pivotIndex = getValueOrNull(colDef.pivotIndex, colDef.initialPivotIndex);\n var pivot = getValueOrNull(colDef.pivot, colDef.initialPivot);\n if (pivotIndex == null && (pivot == null || pivot == false)) {\n pivotIndex = null;\n pivot = null;\n }\n var aggFunc = getValueOrNull(colDef.aggFunc, colDef.initialAggFunc);\n var stateItem = {\n colId: column.getColId(),\n sort: sort,\n sortIndex: sortIndex,\n hide: hide,\n pinned: pinned,\n width: width,\n flex: flex,\n rowGroup: rowGroup,\n rowGroupIndex: rowGroupIndex,\n pivot: pivot,\n pivotIndex: pivotIndex,\n aggFunc: aggFunc,\n };\n if (missing(rowGroupIndex) && rowGroup) {\n stateItem.rowGroupIndex = letRowGroupIndex++;\n }\n if (missing(pivotIndex) && pivot) {\n stateItem.pivotIndex = letPivotIndex++;\n }\n columnStates.push(stateItem);\n });\n this.applyColumnState({ state: columnStates, applyOrder: true }, source);\n };\n ColumnModel.prototype.applyColumnState = function (params, source) {\n var _this = this;\n if (source === void 0) { source = \"api\"; }\n if (missingOrEmpty(this.primaryColumns)) {\n return false;\n }\n if (params && params.state && !params.state.forEach) {\n console.warn('AG Grid: applyColumnState() - the state attribute should be an array, however an array was not found. Please provide an array of items (one for each col you want to change) for state.');\n return false;\n }\n var applyStates = function (states, existingColumns, getById) {\n var raiseEventsFunc = _this.compareColumnStatesAndRaiseEvents(source);\n _this.autoGroupsNeedBuilding = true;\n // at the end below, this list will have all columns we got no state for\n var columnsWithNoState = existingColumns.slice();\n var rowGroupIndexes = {};\n var pivotIndexes = {};\n var autoGroupColumnStates = [];\n // If pivoting is modified, these are the states we try to reapply after\n // the secondary columns are re-generated\n var unmatchedAndAutoStates = [];\n var unmatchedCount = 0;\n var previousRowGroupCols = _this.rowGroupColumns.slice();\n var previousPivotCols = _this.pivotColumns.slice();\n states.forEach(function (state) {\n var colId = state.colId || '';\n // auto group columns are re-created so deferring syncing with ColumnState\n var isAutoGroupColumn = colId.startsWith(Constants.GROUP_AUTO_COLUMN_ID);\n if (isAutoGroupColumn) {\n autoGroupColumnStates.push(state);\n unmatchedAndAutoStates.push(state);\n return;\n }\n var column = getById(colId);\n if (!column) {\n unmatchedAndAutoStates.push(state);\n unmatchedCount += 1;\n }\n else {\n _this.syncColumnWithStateItem(column, state, params.defaultState, rowGroupIndexes, pivotIndexes, false, source);\n removeFromArray(columnsWithNoState, column);\n }\n });\n // anything left over, we got no data for, so add in the column as non-value, non-rowGroup and hidden\n var applyDefaultsFunc = function (col) {\n return _this.syncColumnWithStateItem(col, null, params.defaultState, rowGroupIndexes, pivotIndexes, false, source);\n };\n columnsWithNoState.forEach(applyDefaultsFunc);\n // sort the lists according to the indexes that were provided\n var comparator = function (indexes, oldList, colA, colB) {\n var indexA = indexes[colA.getId()];\n var indexB = indexes[colB.getId()];\n var aHasIndex = indexA != null;\n var bHasIndex = indexB != null;\n if (aHasIndex && bHasIndex) {\n // both a and b are new cols with index, so sort on index\n return indexA - indexB;\n }\n if (aHasIndex) {\n // a has an index, so it should be before a\n return -1;\n }\n if (bHasIndex) {\n // b has an index, so it should be before a\n return 1;\n }\n var oldIndexA = oldList.indexOf(colA);\n var oldIndexB = oldList.indexOf(colB);\n var aHasOldIndex = oldIndexA >= 0;\n var bHasOldIndex = oldIndexB >= 0;\n if (aHasOldIndex && bHasOldIndex) {\n // both a and b are old cols, so sort based on last order\n return oldIndexA - oldIndexB;\n }\n if (aHasOldIndex) {\n // a is old, b is new, so b is first\n return -1;\n }\n // this bit does matter, means both are new cols\n // but without index or that b is old and a is new\n return 1;\n };\n _this.rowGroupColumns.sort(comparator.bind(_this, rowGroupIndexes, previousRowGroupCols));\n _this.pivotColumns.sort(comparator.bind(_this, pivotIndexes, previousPivotCols));\n _this.updateGridColumns();\n // sync newly created auto group columns with ColumnState\n var autoGroupColsCopy = _this.groupAutoColumns ? _this.groupAutoColumns.slice() : [];\n autoGroupColumnStates.forEach(function (stateItem) {\n var autoCol = _this.getAutoColumn(stateItem.colId);\n removeFromArray(autoGroupColsCopy, autoCol);\n _this.syncColumnWithStateItem(autoCol, stateItem, params.defaultState, null, null, true, source);\n });\n // autogroup cols with nothing else, apply the default\n autoGroupColsCopy.forEach(applyDefaultsFunc);\n _this.applyOrderAfterApplyState(params);\n _this.updateDisplayedColumns(source);\n _this.dispatchEverythingChanged(source);\n raiseEventsFunc(); // Will trigger secondary column changes if pivoting modified\n return { unmatchedAndAutoStates: unmatchedAndAutoStates, unmatchedCount: unmatchedCount };\n };\n this.columnAnimationService.start();\n var _a = applyStates(params.state || [], this.primaryColumns || [], function (id) { return _this.getPrimaryColumn(id); }), unmatchedAndAutoStates = _a.unmatchedAndAutoStates, unmatchedCount = _a.unmatchedCount;\n // If there are still states left over, see if we can apply them to newly generated\n // secondary or auto columns. Also if defaults exist, ensure they are applied to secondary cols\n if (unmatchedAndAutoStates.length > 0 || exists(params.defaultState)) {\n unmatchedCount = applyStates(unmatchedAndAutoStates, this.secondaryColumns || [], function (id) { return _this.getSecondaryColumn(id); }).unmatchedCount;\n }\n this.columnAnimationService.finish();\n return unmatchedCount === 0; // Successful if no states unaccounted for\n };\n ColumnModel.prototype.applyOrderAfterApplyState = function (params) {\n var _this = this;\n if (!params.applyOrder || !params.state) {\n return;\n }\n var newOrder = [];\n var processedColIds = {};\n params.state.forEach(function (item) {\n if (!item.colId || processedColIds[item.colId]) {\n return;\n }\n var col = _this.gridColumnsMap[item.colId];\n if (col) {\n newOrder.push(col);\n processedColIds[item.colId] = true;\n }\n });\n // add in all other columns\n var autoGroupInsertIndex = 0;\n this.gridColumns.forEach(function (col) {\n var colId = col.getColId();\n var alreadyProcessed = processedColIds[colId] != null;\n if (alreadyProcessed) {\n return;\n }\n var isAutoGroupCol = colId.startsWith(Constants.GROUP_AUTO_COLUMN_ID);\n if (isAutoGroupCol) {\n // auto group columns, if missing from state list, are added to the start.\n // it's common to have autoGroup missing, as grouping could be on by default\n // on a column, but the user could of since removed the grouping via the UI.\n // if we don't inc the insert index, autoGroups will be inserted in reverse order\n insertIntoArray(newOrder, col, autoGroupInsertIndex++);\n }\n else {\n // normal columns, if missing from state list, are added at the end\n newOrder.push(col);\n }\n });\n // this is already done in updateGridColumns, however we changed the order above (to match the order of the state\n // columns) so we need to do it again. we could of put logic into the order above to take into account fixed\n // columns, however if we did then we would have logic for updating fixed columns twice. reusing the logic here\n // is less sexy for the code here, but it keeps consistency.\n newOrder = this.placeLockedColumns(newOrder);\n if (!this.doesMovePassMarryChildren(newOrder)) {\n console.warn('AG Grid: Applying column order broke a group where columns should be married together. Applying new order has been discarded.');\n return;\n }\n this.gridColumns = newOrder;\n };\n ColumnModel.prototype.compareColumnStatesAndRaiseEvents = function (source) {\n var _this = this;\n var startState = {\n rowGroupColumns: this.rowGroupColumns.slice(),\n pivotColumns: this.pivotColumns.slice(),\n valueColumns: this.valueColumns.slice()\n };\n var columnStateBefore = this.getColumnState();\n var columnStateBeforeMap = {};\n columnStateBefore.forEach(function (col) {\n columnStateBeforeMap[col.colId] = col;\n });\n return function () {\n if (_this.gridOptionsWrapper.isSuppressColumnStateEvents()) {\n return;\n }\n var colsForState = _this.getPrimaryAndSecondaryAndAutoColumns();\n // raises generic ColumnEvents where all columns are returned rather than what has changed\n var raiseWhenListsDifferent = function (eventType, colsBefore, colsAfter, idMapper) {\n var beforeList = colsBefore.map(idMapper);\n var afterList = colsAfter.map(idMapper);\n var unchanged = areEqual(beforeList, afterList);\n if (unchanged) {\n return;\n }\n // returning all columns rather than what has changed!\n var event = {\n type: eventType,\n columns: colsAfter,\n column: colsAfter.length === 1 ? colsAfter[0] : null,\n source: source\n };\n _this.eventService.dispatchEvent(event);\n };\n // determines which columns have changed according to supplied predicate\n var getChangedColumns = function (changedPredicate) {\n var changedColumns = [];\n colsForState.forEach(function (column) {\n var colStateBefore = columnStateBeforeMap[column.getColId()];\n if (colStateBefore && changedPredicate(colStateBefore, column)) {\n changedColumns.push(column);\n }\n });\n return changedColumns;\n };\n var columnIdMapper = function (c) { return c.getColId(); };\n raiseWhenListsDifferent(Events.EVENT_COLUMN_ROW_GROUP_CHANGED, startState.rowGroupColumns, _this.rowGroupColumns, columnIdMapper);\n raiseWhenListsDifferent(Events.EVENT_COLUMN_PIVOT_CHANGED, startState.pivotColumns, _this.pivotColumns, columnIdMapper);\n var valueChangePredicate = function (cs, c) {\n var oldActive = cs.aggFunc != null;\n var activeChanged = oldActive != c.isValueActive();\n // we only check aggFunc if the agg is active\n var aggFuncChanged = oldActive && cs.aggFunc != c.getAggFunc();\n return activeChanged || aggFuncChanged;\n };\n var changedValues = getChangedColumns(valueChangePredicate);\n if (changedValues.length > 0) {\n // we pass all value columns, now the ones that changed. this is the same\n // as pivot and rowGroup cols, but different to all other properties below.\n // this is more for backwards compatibility, as it's always been this way.\n // really it should be the other way, as the order of the cols makes no difference\n // for valueColumns (apart from displaying them in the tool panel).\n _this.fireColumnEvent(Events.EVENT_COLUMN_VALUE_CHANGED, _this.valueColumns, source);\n }\n var resizeChangePredicate = function (cs, c) { return cs.width != c.getActualWidth(); };\n _this.fireColumnResizedEvent(getChangedColumns(resizeChangePredicate), true, source);\n var pinnedChangePredicate = function (cs, c) { return cs.pinned != c.getPinned(); };\n _this.raiseColumnPinnedEvent(getChangedColumns(pinnedChangePredicate), source);\n var visibilityChangePredicate = function (cs, c) { return cs.hide == c.isVisible(); };\n _this.raiseColumnVisibleEvent(getChangedColumns(visibilityChangePredicate), source);\n var sortChangePredicate = function (cs, c) { return cs.sort != c.getSort() || cs.sortIndex != c.getSortIndex(); };\n if (getChangedColumns(sortChangePredicate).length > 0) {\n _this.sortController.dispatchSortChangedEvents(source);\n }\n // special handling for moved column events\n _this.raiseColumnMovedEvent(columnStateBefore, source);\n };\n };\n ColumnModel.prototype.raiseColumnPinnedEvent = function (changedColumns, source) {\n if (!changedColumns.length) {\n return;\n }\n // if just one column, we use this, otherwise we don't include the col\n var column = changedColumns.length === 1 ? changedColumns[0] : null;\n // only include visible if it's common in all columns\n var pinned = this.getCommonValue(changedColumns, function (col) { return col.getPinned(); });\n var event = {\n type: Events.EVENT_COLUMN_PINNED,\n // mistake in typing, 'undefined' should be allowed, as 'null' means 'not pinned'\n pinned: pinned != null ? pinned : null,\n columns: changedColumns,\n column: column,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.getCommonValue = function (cols, valueGetter) {\n if (!cols || cols.length == 0) {\n return undefined;\n }\n // compare each value to the first value. if nothing differs, then value is common so return it.\n var firstValue = valueGetter(cols[0]);\n for (var i = 1; i < cols.length; i++) {\n if (firstValue !== valueGetter(cols[i])) {\n // values differ, no common value\n return undefined;\n }\n }\n return firstValue;\n };\n ColumnModel.prototype.raiseColumnVisibleEvent = function (changedColumns, source) {\n if (!changedColumns.length) {\n return;\n }\n // if just one column, we use this, otherwise we don't include the col\n var column = changedColumns.length === 1 ? changedColumns[0] : null;\n // only include visible if it's common in all columns\n var visible = this.getCommonValue(changedColumns, function (col) { return col.isVisible(); });\n var event = {\n type: Events.EVENT_COLUMN_VISIBLE,\n visible: visible,\n columns: changedColumns,\n column: column,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.raiseColumnMovedEvent = function (colStateBefore, source) {\n // we are only interested in columns that were both present and visible before and after\n var _this = this;\n var colStateAfter = this.getColumnState();\n var colStateAfterMapped = {};\n colStateAfter.forEach(function (s) { return colStateAfterMapped[s.colId] = s; });\n // get id's of cols in both before and after lists\n var colsIntersectIds = {};\n colStateBefore.forEach(function (s) {\n if (colStateAfterMapped[s.colId]) {\n colsIntersectIds[s.colId] = true;\n }\n });\n // filter state lists, so we only have cols that were present before and after\n var beforeFiltered = colStateBefore.filter(function (c) { return colsIntersectIds[c.colId]; });\n var afterFiltered = colStateAfter.filter(function (c) { return colsIntersectIds[c.colId]; });\n // see if any cols are in a different location\n var movedColumns = [];\n afterFiltered.forEach(function (csAfter, index) {\n var csBefore = beforeFiltered && beforeFiltered[index];\n if (csBefore && csBefore.colId !== csAfter.colId) {\n var gridCol = _this.getGridColumn(csBefore.colId);\n if (gridCol) {\n movedColumns.push(gridCol);\n }\n }\n });\n if (!movedColumns.length) {\n return;\n }\n var event = {\n type: Events.EVENT_COLUMN_MOVED,\n columns: movedColumns,\n column: null,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.syncColumnWithStateItem = function (column, stateItem, defaultState, rowGroupIndexes, pivotIndexes, autoCol, source) {\n if (!column) {\n return;\n }\n var getValue = function (key1, key2) {\n var obj = { value1: undefined, value2: undefined };\n var calculated = false;\n if (stateItem) {\n if (stateItem[key1] !== undefined) {\n obj.value1 = stateItem[key1];\n calculated = true;\n }\n if (exists(key2) && stateItem[key2] !== undefined) {\n obj.value2 = stateItem[key2];\n calculated = true;\n }\n }\n if (!calculated && defaultState) {\n if (defaultState[key1] !== undefined) {\n obj.value1 = defaultState[key1];\n }\n if (exists(key2) && defaultState[key2] !== undefined) {\n obj.value2 = defaultState[key2];\n }\n }\n return obj;\n };\n // following ensures we are left with boolean true or false, eg converts (null, undefined, 0) all to true\n var hide = getValue('hide').value1;\n if (hide !== undefined) {\n column.setVisible(!hide, source);\n }\n // sets pinned to 'left' or 'right'\n var pinned = getValue('pinned').value1;\n if (pinned !== undefined) {\n column.setPinned(pinned);\n }\n // if width provided and valid, use it, otherwise stick with the old width\n var minColWidth = this.columnUtils.calculateColMinWidth(column.getColDef());\n // flex\n var flex = getValue('flex').value1;\n if (flex !== undefined) {\n column.setFlex(flex);\n }\n // width - we only set width if column is not flexing\n var noFlexThisCol = column.getFlex() <= 0;\n if (noFlexThisCol) {\n // both null and undefined means we skip, as it's not possible to 'clear' width (a column must have a width)\n var width = getValue('width').value1;\n if (width != null) {\n if (minColWidth != null && width >= minColWidth) {\n column.setActualWidth(width, source);\n }\n }\n }\n var sort = getValue('sort').value1;\n if (sort !== undefined) {\n if (sort === Constants.SORT_DESC || sort === Constants.SORT_ASC) {\n column.setSort(sort, source);\n }\n else {\n column.setSort(undefined, source);\n }\n }\n var sortIndex = getValue('sortIndex').value1;\n if (sortIndex !== undefined) {\n column.setSortIndex(sortIndex);\n }\n // we do not do aggFunc, rowGroup or pivot for auto cols or secondary cols\n if (autoCol || !column.isPrimary()) {\n return;\n }\n var aggFunc = getValue('aggFunc').value1;\n if (aggFunc !== undefined) {\n if (typeof aggFunc === 'string') {\n column.setAggFunc(aggFunc);\n if (!column.isValueActive()) {\n column.setValueActive(true, source);\n this.valueColumns.push(column);\n }\n }\n else {\n if (exists(aggFunc)) {\n console.warn('AG Grid: stateItem.aggFunc must be a string. if using your own aggregation ' +\n 'functions, register the functions first before using them in get/set state. This is because it is ' +\n 'intended for the column state to be stored and retrieved as simple JSON.');\n }\n // Note: we do not call column.setAggFunc(null), so that next time we aggregate\n // by this column (eg drag the column to the agg section int he toolpanel) it will\n // default to the last aggregation function.\n if (column.isValueActive()) {\n column.setValueActive(false, source);\n removeFromArray(this.valueColumns, column);\n }\n }\n }\n var _a = getValue('rowGroup', 'rowGroupIndex'), rowGroup = _a.value1, rowGroupIndex = _a.value2;\n if (rowGroup !== undefined || rowGroupIndex !== undefined) {\n if (typeof rowGroupIndex === 'number' || rowGroup) {\n if (!column.isRowGroupActive()) {\n column.setRowGroupActive(true, source);\n this.rowGroupColumns.push(column);\n }\n if (rowGroupIndexes && typeof rowGroupIndex === 'number') {\n rowGroupIndexes[column.getId()] = rowGroupIndex;\n }\n }\n else {\n if (column.isRowGroupActive()) {\n column.setRowGroupActive(false, source);\n removeFromArray(this.rowGroupColumns, column);\n }\n }\n }\n var _b = getValue('pivot', 'pivotIndex'), pivot = _b.value1, pivotIndex = _b.value2;\n if (pivot !== undefined || pivotIndex !== undefined) {\n if (typeof pivotIndex === 'number' || pivot) {\n if (!column.isPivotActive()) {\n column.setPivotActive(true, source);\n this.pivotColumns.push(column);\n }\n if (pivotIndexes && typeof pivotIndex === 'number') {\n pivotIndexes[column.getId()] = pivotIndex;\n }\n }\n else {\n if (column.isPivotActive()) {\n column.setPivotActive(false, source);\n removeFromArray(this.pivotColumns, column);\n }\n }\n }\n };\n ColumnModel.prototype.getGridColumns = function (keys) {\n return this.getColumns(keys, this.getGridColumn.bind(this));\n };\n ColumnModel.prototype.getColumns = function (keys, columnLookupCallback) {\n var foundColumns = [];\n if (keys) {\n keys.forEach(function (key) {\n var column = columnLookupCallback(key);\n if (column) {\n foundColumns.push(column);\n }\n });\n }\n return foundColumns;\n };\n // used by growGroupPanel\n ColumnModel.prototype.getColumnWithValidation = function (key) {\n if (key == null) {\n return null;\n }\n var column = this.getGridColumn(key);\n if (!column) {\n console.warn('AG Grid: could not find column ' + key);\n }\n return column;\n };\n ColumnModel.prototype.getPrimaryColumn = function (key) {\n if (!this.primaryColumns) {\n return null;\n }\n return this.getColumn(key, this.primaryColumns, this.primaryColumnsMap);\n };\n ColumnModel.prototype.getGridColumn = function (key) {\n return this.getColumn(key, this.gridColumns, this.gridColumnsMap);\n };\n ColumnModel.prototype.getSecondaryColumn = function (key) {\n if (!this.secondaryColumns) {\n return null;\n }\n return this.getColumn(key, this.secondaryColumns, this.secondaryColumnsMap);\n };\n ColumnModel.prototype.getColumn = function (key, columnList, columnMap) {\n if (!key) {\n return null;\n }\n // most of the time this method gets called the key is a string, so we put this shortcut in\n // for performance reasons, to see if we can match for ID (it doesn't do auto columns, that's done below)\n if (typeof key == 'string' && columnMap[key]) {\n return columnMap[key];\n }\n for (var i = 0; i < columnList.length; i++) {\n if (this.columnsMatch(columnList[i], key)) {\n return columnList[i];\n }\n }\n return this.getAutoColumn(key);\n };\n ColumnModel.prototype.getSourceColumnsForGroupColumn = function (groupCol) {\n var sourceColumnId = groupCol.getColDef().showRowGroup;\n if (!sourceColumnId) {\n return null;\n }\n if (sourceColumnId === true) {\n return this.rowGroupColumns.slice(0);\n }\n var column = this.getPrimaryColumn(sourceColumnId);\n return column ? [column] : null;\n };\n ColumnModel.prototype.getAutoColumn = function (key) {\n var _this = this;\n if (!this.groupAutoColumns ||\n !exists(this.groupAutoColumns) ||\n missing(this.groupAutoColumns)) {\n return null;\n }\n return this.groupAutoColumns.find(function (groupCol) { return _this.columnsMatch(groupCol, key); }) || null;\n };\n ColumnModel.prototype.columnsMatch = function (column, key) {\n var columnMatches = column === key;\n var colDefMatches = column.getColDef() === key;\n var idMatches = column.getColId() == key;\n return columnMatches || colDefMatches || idMatches;\n };\n ColumnModel.prototype.getDisplayNameForColumn = function (column, location, includeAggFunc) {\n if (includeAggFunc === void 0) { includeAggFunc = false; }\n if (!column) {\n return null;\n }\n var headerName = this.getHeaderName(column.getColDef(), column, null, null, location);\n if (includeAggFunc) {\n return this.wrapHeaderNameWithAggFunc(column, headerName);\n }\n return headerName;\n };\n ColumnModel.prototype.getDisplayNameForProvidedColumnGroup = function (columnGroup, providedColumnGroup, location) {\n var colGroupDef = providedColumnGroup ? providedColumnGroup.getColGroupDef() : null;\n if (colGroupDef) {\n return this.getHeaderName(colGroupDef, null, columnGroup, providedColumnGroup, location);\n }\n return null;\n };\n ColumnModel.prototype.getDisplayNameForColumnGroup = function (columnGroup, location) {\n return this.getDisplayNameForProvidedColumnGroup(columnGroup, columnGroup.getProvidedColumnGroup(), location);\n };\n // location is where the column is going to appear, ie who is calling us\n ColumnModel.prototype.getHeaderName = function (colDef, column, columnGroup, providedColumnGroup, location) {\n var headerValueGetter = colDef.headerValueGetter;\n if (headerValueGetter) {\n var params = {\n colDef: colDef,\n column: column,\n columnGroup: columnGroup,\n providedColumnGroup: providedColumnGroup,\n location: location,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n if (typeof headerValueGetter === 'function') {\n // valueGetter is a function, so just call it\n return headerValueGetter(params);\n }\n else if (typeof headerValueGetter === 'string') {\n // valueGetter is an expression, so execute the expression\n return this.expressionService.evaluate(headerValueGetter, params);\n }\n console.warn('ag-grid: headerValueGetter must be a function or a string');\n return '';\n }\n else if (colDef.headerName != null) {\n return colDef.headerName;\n }\n else if (colDef.field) {\n return camelCaseToHumanText(colDef.field);\n }\n return '';\n };\n ColumnModel.prototype.wrapHeaderNameWithAggFunc = function (column, headerName) {\n if (this.gridOptionsWrapper.isSuppressAggFuncInHeader()) {\n return headerName;\n }\n // only columns with aggregation active can have aggregations\n var pivotValueColumn = column.getColDef().pivotValueColumn;\n var pivotActiveOnThisColumn = exists(pivotValueColumn);\n var aggFunc = null;\n var aggFuncFound;\n // otherwise we have a measure that is active, and we are doing aggregation on it\n if (pivotActiveOnThisColumn) {\n var isCollapsedHeaderEnabled = this.gridOptionsWrapper.isRemovePivotHeaderRowWhenSingleValueColumn() && this.valueColumns.length === 1;\n var isTotalColumn = column.getColDef().pivotTotalColumnIds !== undefined;\n if (isCollapsedHeaderEnabled && !isTotalColumn) {\n return headerName; // Skip decorating the header - in this case the label is the pivot key, not the value col\n }\n aggFunc = pivotValueColumn ? pivotValueColumn.getAggFunc() : null;\n aggFuncFound = true;\n }\n else {\n var measureActive = column.isValueActive();\n var aggregationPresent = this.pivotMode || !this.isRowGroupEmpty();\n if (measureActive && aggregationPresent) {\n aggFunc = column.getAggFunc();\n aggFuncFound = true;\n }\n else {\n aggFuncFound = false;\n }\n }\n if (aggFuncFound) {\n var aggFuncString = (typeof aggFunc === 'string') ? aggFunc : 'func';\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n var aggFuncStringTranslated = localeTextFunc(aggFuncString, aggFuncString);\n return aggFuncStringTranslated + \"(\" + headerName + \")\";\n }\n return headerName;\n };\n // returns the group with matching colId and instanceId. If instanceId is missing,\n // matches only on the colId.\n ColumnModel.prototype.getColumnGroup = function (colId, instanceId) {\n if (!colId) {\n return null;\n }\n if (colId instanceof ColumnGroup) {\n return colId;\n }\n var allColumnGroups = this.getAllDisplayedTrees();\n var checkInstanceId = typeof instanceId === 'number';\n var result = null;\n this.columnUtils.depthFirstAllColumnTreeSearch(allColumnGroups, function (child) {\n if (child instanceof ColumnGroup) {\n var columnGroup = child;\n var matched = void 0;\n if (checkInstanceId) {\n matched = colId === columnGroup.getGroupId() && instanceId === columnGroup.getInstanceId();\n }\n else {\n matched = colId === columnGroup.getGroupId();\n }\n if (matched) {\n result = columnGroup;\n }\n }\n });\n return result;\n };\n ColumnModel.prototype.isReady = function () {\n return this.ready;\n };\n ColumnModel.prototype.extractValueColumns = function (source, oldPrimaryColumns) {\n this.valueColumns = this.extractColumns(oldPrimaryColumns, this.valueColumns, function (col, flag) { return col.setValueActive(flag, source); }, \n // aggFunc doesn't have index variant, cos order of value cols doesn't matter, so always return null\n function () { return undefined; }, function () { return undefined; }, \n // aggFunc is a string, so return it's existence\n function (colDef) {\n var aggFunc = colDef.aggFunc;\n // null or empty string means clear\n if (aggFunc === null || aggFunc === '') {\n return null;\n }\n if (aggFunc === undefined) {\n return;\n }\n return !!aggFunc;\n }, function (colDef) {\n // return false if any of the following: null, undefined, empty string\n return colDef.initialAggFunc != null && colDef.initialAggFunc != '';\n });\n // all new columns added will have aggFunc missing, so set it to what is in the colDef\n this.valueColumns.forEach(function (col) {\n var colDef = col.getColDef();\n // if aggFunc provided, we always override, as reactive property\n if (colDef.aggFunc != null && colDef.aggFunc != '') {\n col.setAggFunc(colDef.aggFunc);\n }\n else {\n // otherwise we use initialAggFunc only if no agg func set - which happens when new column only\n if (!col.getAggFunc()) {\n col.setAggFunc(colDef.initialAggFunc);\n }\n }\n });\n };\n ColumnModel.prototype.extractRowGroupColumns = function (source, oldPrimaryColumns) {\n this.rowGroupColumns = this.extractColumns(oldPrimaryColumns, this.rowGroupColumns, function (col, flag) { return col.setRowGroupActive(flag, source); }, function (colDef) { return colDef.rowGroupIndex; }, function (colDef) { return colDef.initialRowGroupIndex; }, function (colDef) { return colDef.rowGroup; }, function (colDef) { return colDef.initialRowGroup; });\n };\n ColumnModel.prototype.extractColumns = function (oldPrimaryColumns, previousCols, setFlagFunc, getIndexFunc, getInitialIndexFunc, getValueFunc, getInitialValueFunc) {\n if (oldPrimaryColumns === void 0) { oldPrimaryColumns = []; }\n if (previousCols === void 0) { previousCols = []; }\n var colsWithIndex = [];\n var colsWithValue = [];\n // go though all cols.\n // if value, change\n // if default only, change only if new\n (this.primaryColumns || []).forEach(function (col) {\n var colIsNew = oldPrimaryColumns.indexOf(col) < 0;\n var colDef = col.getColDef();\n var value = attrToBoolean(getValueFunc(colDef));\n var initialValue = attrToBoolean(getInitialValueFunc(colDef));\n var index = attrToNumber(getIndexFunc(colDef));\n var initialIndex = attrToNumber(getInitialIndexFunc(colDef));\n var include;\n var valuePresent = value !== undefined;\n var indexPresent = index !== undefined;\n var initialValuePresent = initialValue !== undefined;\n var initialIndexPresent = initialIndex !== undefined;\n if (valuePresent) {\n include = value; // boolean value is guaranteed as attrToBoolean() is used above\n }\n else if (indexPresent) {\n if (index === null) {\n // if col is new we don't want to use the default / initial if index is set to null. Similarly,\n // we don't want to include the property for existing columns, i.e. we want to 'clear' it.\n include = false;\n }\n else {\n // note that 'null >= 0' evaluates to true which means 'rowGroupIndex = null' would enable row\n // grouping if the null check didn't exist above.\n include = index >= 0;\n }\n }\n else {\n if (colIsNew) {\n // as no value or index is 'present' we use the default / initial when col is new\n if (initialValuePresent) {\n include = initialValue;\n }\n else if (initialIndexPresent) {\n include = initialIndex != null && initialIndex >= 0;\n }\n else {\n include = false;\n }\n }\n else {\n // otherwise include it if included last time, e.g. if we are extracting row group cols and this col\n // is an existing row group col (i.e. it exists in 'previousCols') then we should include it.\n include = previousCols.indexOf(col) >= 0;\n }\n }\n if (include) {\n var useIndex = colIsNew ? (index != null || initialIndex != null) : index != null;\n useIndex ? colsWithIndex.push(col) : colsWithValue.push(col);\n }\n });\n var getIndexForCol = function (col) {\n var index = getIndexFunc(col.getColDef());\n var defaultIndex = getInitialIndexFunc(col.getColDef());\n return index != null ? index : defaultIndex;\n };\n // sort cols with index, and add these first\n colsWithIndex.sort(function (colA, colB) {\n var indexA = getIndexForCol(colA);\n var indexB = getIndexForCol(colB);\n if (indexA === indexB) {\n return 0;\n }\n if (indexA < indexB) {\n return -1;\n }\n return 1;\n });\n var res = [].concat(colsWithIndex);\n // second add columns that were there before and in the same order as they were before,\n // so we are preserving order of current grouping of columns that simply have rowGroup=true\n previousCols.forEach(function (col) {\n if (colsWithValue.indexOf(col) >= 0) {\n res.push(col);\n }\n });\n // lastly put in all remaining cols\n colsWithValue.forEach(function (col) {\n if (res.indexOf(col) < 0) {\n res.push(col);\n }\n });\n // set flag=false for removed cols\n previousCols.forEach(function (col) {\n if (res.indexOf(col) < 0) {\n setFlagFunc(col, false);\n }\n });\n // set flag=true for newly added cols\n res.forEach(function (col) {\n if (previousCols.indexOf(col) < 0) {\n setFlagFunc(col, true);\n }\n });\n return res;\n };\n ColumnModel.prototype.extractPivotColumns = function (source, oldPrimaryColumns) {\n this.pivotColumns = this.extractColumns(oldPrimaryColumns, this.pivotColumns, function (col, flag) { return col.setPivotActive(flag, source); }, function (colDef) { return colDef.pivotIndex; }, function (colDef) { return colDef.initialPivotIndex; }, function (colDef) { return colDef.pivot; }, function (colDef) { return colDef.initialPivot; });\n };\n ColumnModel.prototype.resetColumnGroupState = function (source) {\n if (source === void 0) { source = \"api\"; }\n var stateItems = [];\n this.columnUtils.depthFirstOriginalTreeSearch(null, this.primaryColumnTree, function (child) {\n if (child instanceof ProvidedColumnGroup) {\n var colGroupDef = child.getColGroupDef();\n var groupState = {\n groupId: child.getGroupId(),\n open: !colGroupDef ? undefined : colGroupDef.openByDefault\n };\n stateItems.push(groupState);\n }\n });\n this.setColumnGroupState(stateItems, source);\n };\n ColumnModel.prototype.getColumnGroupState = function () {\n var columnGroupState = [];\n this.columnUtils.depthFirstOriginalTreeSearch(null, this.gridBalancedTree, function (node) {\n if (node instanceof ProvidedColumnGroup) {\n columnGroupState.push({\n groupId: node.getGroupId(),\n open: node.isExpanded()\n });\n }\n });\n return columnGroupState;\n };\n ColumnModel.prototype.setColumnGroupState = function (stateItems, source) {\n var _this = this;\n if (source === void 0) { source = \"api\"; }\n this.columnAnimationService.start();\n var impactedGroups = [];\n stateItems.forEach(function (stateItem) {\n var groupKey = stateItem.groupId;\n var newValue = stateItem.open;\n var providedColumnGroup = _this.getProvidedColumnGroup(groupKey);\n if (!providedColumnGroup) {\n return;\n }\n if (providedColumnGroup.isExpanded() === newValue) {\n return;\n }\n _this.logger.log('columnGroupOpened(' + providedColumnGroup.getGroupId() + ',' + newValue + ')');\n providedColumnGroup.setExpanded(newValue);\n impactedGroups.push(providedColumnGroup);\n });\n this.updateGroupsAndDisplayedColumns(source);\n this.setFirstRightAndLastLeftPinned(source);\n impactedGroups.forEach(function (providedColumnGroup) {\n var event = {\n type: Events.EVENT_COLUMN_GROUP_OPENED,\n columnGroup: providedColumnGroup\n };\n _this.eventService.dispatchEvent(event);\n });\n this.columnAnimationService.finish();\n };\n // called by headerRenderer - when a header is opened or closed\n ColumnModel.prototype.setColumnGroupOpened = function (key, newValue, source) {\n if (source === void 0) { source = \"api\"; }\n var keyAsString;\n if (key instanceof ProvidedColumnGroup) {\n keyAsString = key.getId();\n }\n else {\n keyAsString = key || '';\n }\n this.setColumnGroupState([{ groupId: keyAsString, open: newValue }], source);\n };\n ColumnModel.prototype.getProvidedColumnGroup = function (key) {\n // if (key instanceof ProvidedColumnGroup) { return key; }\n if (typeof key !== 'string') {\n console.error('AG Grid: group key must be a string');\n }\n // otherwise, search for the column group by id\n var res = null;\n this.columnUtils.depthFirstOriginalTreeSearch(null, this.gridBalancedTree, function (node) {\n if (node instanceof ProvidedColumnGroup) {\n if (node.getId() === key) {\n res = node;\n }\n }\n });\n return res;\n };\n ColumnModel.prototype.calculateColumnsForDisplay = function () {\n var _this = this;\n var columnsForDisplay;\n if (this.pivotMode && missing(this.secondaryColumns)) {\n // pivot mode is on, but we are not pivoting, so we only\n // show columns we are aggregating on\n columnsForDisplay = this.gridColumns.filter(function (column) {\n var isAutoGroupCol = _this.groupAutoColumns && includes(_this.groupAutoColumns, column);\n var isValueCol = _this.valueColumns && includes(_this.valueColumns, column);\n return isAutoGroupCol || isValueCol;\n });\n }\n else {\n // otherwise continue as normal. this can be working on the primary\n // or secondary columns, whatever the gridColumns are set to\n columnsForDisplay = this.gridColumns.filter(function (column) {\n // keep col if a) it's auto-group or b) it's visible\n var isAutoGroupCol = _this.groupAutoColumns && includes(_this.groupAutoColumns, column);\n return isAutoGroupCol || column.isVisible();\n });\n }\n return columnsForDisplay;\n };\n ColumnModel.prototype.checkColSpanActiveInCols = function (columns) {\n var result = false;\n columns.forEach(function (col) {\n if (exists(col.getColDef().colSpan)) {\n result = true;\n }\n });\n return result;\n };\n ColumnModel.prototype.calculateColumnsForGroupDisplay = function () {\n var _this = this;\n this.groupDisplayColumns = [];\n this.groupDisplayColumnsMap = {};\n var checkFunc = function (col) {\n var colDef = col.getColDef();\n var underlyingColumn = colDef.showRowGroup;\n if (colDef && exists(underlyingColumn)) {\n _this.groupDisplayColumns.push(col);\n if (typeof underlyingColumn === 'string') {\n _this.groupDisplayColumnsMap[underlyingColumn] = col;\n }\n else if (underlyingColumn === true) {\n _this.getRowGroupColumns().forEach(function (rowGroupCol) {\n _this.groupDisplayColumnsMap[rowGroupCol.getId()] = col;\n });\n }\n }\n };\n this.gridColumns.forEach(checkFunc);\n if (this.groupAutoColumns) {\n this.groupAutoColumns.forEach(checkFunc);\n }\n };\n ColumnModel.prototype.getGroupDisplayColumns = function () {\n return this.groupDisplayColumns;\n };\n ColumnModel.prototype.getGroupDisplayColumnForGroup = function (rowGroupColumnId) {\n return this.groupDisplayColumnsMap[rowGroupColumnId];\n };\n ColumnModel.prototype.updateDisplayedColumns = function (source) {\n var columnsForDisplay = this.calculateColumnsForDisplay();\n this.buildDisplayedTrees(columnsForDisplay);\n this.calculateColumnsForGroupDisplay();\n // also called when group opened/closed\n this.updateGroupsAndDisplayedColumns(source);\n // also called when group opened/closed\n this.setFirstRightAndLastLeftPinned(source);\n };\n ColumnModel.prototype.isSecondaryColumnsPresent = function () {\n return exists(this.secondaryColumns);\n };\n ColumnModel.prototype.setSecondaryColumns = function (colDefs, source) {\n var _this = this;\n if (source === void 0) { source = \"api\"; }\n var newColsPresent = colDefs && colDefs.length > 0;\n // if not cols passed, and we had no cols anyway, then do nothing\n if (!newColsPresent && missing(this.secondaryColumns)) {\n return;\n }\n if (newColsPresent) {\n this.processSecondaryColumnDefinitions(colDefs);\n var balancedTreeResult = this.columnFactory.createColumnTree(colDefs, false, this.secondaryBalancedTree || this.previousSecondaryColumns || undefined);\n this.secondaryBalancedTree = balancedTreeResult.columnTree;\n this.secondaryHeaderRowCount = balancedTreeResult.treeDept + 1;\n this.secondaryColumns = this.getColumnsFromTree(this.secondaryBalancedTree);\n this.secondaryColumnsMap = {};\n this.secondaryColumns.forEach(function (col) { return _this.secondaryColumnsMap[col.getId()] = col; });\n this.previousSecondaryColumns = null;\n }\n else {\n this.previousSecondaryColumns = this.secondaryBalancedTree;\n this.secondaryBalancedTree = null;\n this.secondaryHeaderRowCount = -1;\n this.secondaryColumns = null;\n this.secondaryColumnsMap = {};\n }\n this.updateGridColumns();\n this.updateDisplayedColumns(source);\n };\n ColumnModel.prototype.processSecondaryColumnDefinitions = function (colDefs) {\n var columnCallback = this.gridOptionsWrapper.getProcessPivotResultColDefFunc();\n var groupCallback = this.gridOptionsWrapper.getProcessPivotResultColGroupDefFunc();\n if (!columnCallback && !groupCallback) {\n return undefined;\n }\n var searchForColDefs = function (colDefs2) {\n colDefs2.forEach(function (abstractColDef) {\n var isGroup = exists(abstractColDef.children);\n if (isGroup) {\n var colGroupDef = abstractColDef;\n if (groupCallback) {\n groupCallback(colGroupDef);\n }\n searchForColDefs(colGroupDef.children);\n }\n else {\n var colDef = abstractColDef;\n if (columnCallback) {\n columnCallback(colDef);\n }\n }\n });\n };\n if (colDefs) {\n searchForColDefs(colDefs);\n }\n };\n // called from: setColumnState, setColumnDefs, setSecondaryColumns\n ColumnModel.prototype.updateGridColumns = function () {\n var _this = this;\n var prevGridCols = this.gridBalancedTree;\n if (this.gridColsArePrimary) {\n this.lastPrimaryOrder = this.gridColumns;\n }\n else {\n this.lastSecondaryOrder = this.gridColumns;\n }\n var sortOrderToRecover = undefined;\n if (this.secondaryColumns && this.secondaryBalancedTree) {\n var hasSameColumns = this.secondaryColumns.every(function (col) {\n return _this.gridColumnsMap[col.getColId()] !== undefined;\n });\n this.gridBalancedTree = this.secondaryBalancedTree.slice();\n this.gridHeaderRowCount = this.secondaryHeaderRowCount;\n this.gridColumns = this.secondaryColumns.slice();\n this.gridColsArePrimary = false;\n // If the current columns are the same or a subset of the previous\n // we keep the previous order, otherwise we go back to the order the pivot\n // cols are generated in\n if (hasSameColumns) {\n sortOrderToRecover = this.lastSecondaryOrder;\n }\n }\n else if (this.primaryColumns) {\n this.gridBalancedTree = this.primaryColumnTree.slice();\n this.gridHeaderRowCount = this.primaryHeaderRowCount;\n this.gridColumns = this.primaryColumns.slice();\n this.gridColsArePrimary = true;\n // updateGridColumns gets called after user adds a row group. we want to maintain the order of the columns\n // when this happens (eg if user moved a column) rather than revert back to the original column order.\n // likewise if changing in/out of pivot mode, we want to maintain the order of the cols\n sortOrderToRecover = this.lastPrimaryOrder;\n }\n // create the new auto columns\n var areAutoColsChanged = this.createGroupAutoColumnsIfNeeded();\n // if auto group cols have changed, and we have a sort order, we need to move auto cols to the start\n if (areAutoColsChanged && sortOrderToRecover) {\n var groupAutoColsMap_1 = convertToMap(this.groupAutoColumns.map(function (col) { return [col, true]; }));\n // if group columns has changed, we don't preserve the group column order, so remove them from the old order\n sortOrderToRecover = sortOrderToRecover.filter(function (col) { return groupAutoColsMap_1.has(col); });\n // and add them to the start of the order\n sortOrderToRecover = __spread$f(this.groupAutoColumns, sortOrderToRecover);\n }\n this.addAutoGroupToGridColumns();\n this.orderGridColsLike(sortOrderToRecover);\n this.gridColumns = this.placeLockedColumns(this.gridColumns);\n this.setupQuickFilterColumns();\n this.clearDisplayedAndViewportColumns();\n this.colSpanActive = this.checkColSpanActiveInCols(this.gridColumns);\n this.gridColumnsMap = {};\n this.gridColumns.forEach(function (col) { return _this.gridColumnsMap[col.getId()] = col; });\n this.setAutoHeightActive();\n if (!areEqual(prevGridCols, this.gridBalancedTree)) {\n var event_4 = {\n type: Events.EVENT_GRID_COLUMNS_CHANGED\n };\n this.eventService.dispatchEvent(event_4);\n }\n };\n ColumnModel.prototype.setAutoHeightActive = function () {\n this.autoHeightActive = this.gridColumns.filter(function (col) { return col.isAutoHeight(); }).length > 0;\n if (this.autoHeightActive) {\n this.autoHeightActiveAtLeastOnce = true;\n var rowModelType = this.rowModel.getType();\n var supportedRowModel = rowModelType === Constants.ROW_MODEL_TYPE_CLIENT_SIDE || rowModelType === Constants.ROW_MODEL_TYPE_SERVER_SIDE;\n if (!supportedRowModel) {\n var message_1 = 'AG Grid - autoHeight columns only work with Client Side Row Model and Server Side Row Model.';\n doOnce(function () { return console.warn(message_1); }, 'autoHeightActive.wrongRowModel');\n }\n }\n };\n ColumnModel.prototype.orderGridColsLike = function (colsOrder) {\n if (missing(colsOrder)) {\n return;\n }\n var lastOrderMapped = convertToMap(colsOrder.map(function (col, index) { return [col, index]; }));\n // only do the sort if at least one column is accounted for. columns will be not accounted for\n // if changing from secondary to primary columns\n var noColsFound = true;\n this.gridColumns.forEach(function (col) {\n if (lastOrderMapped.has(col)) {\n noColsFound = false;\n }\n });\n if (noColsFound) {\n return;\n }\n // order cols in the same order as before. we need to make sure that all\n // cols still exists, so filter out any that no longer exist.\n var gridColsMap = convertToMap(this.gridColumns.map(function (col) { return [col, true]; }));\n var oldColsOrdered = colsOrder.filter(function (col) { return gridColsMap.has(col); });\n var oldColsMap = convertToMap(oldColsOrdered.map(function (col) { return [col, true]; }));\n var newColsOrdered = this.gridColumns.filter(function (col) { return !oldColsMap.has(col); });\n // add in the new columns, at the end (if no group), or at the end of the group (if a group)\n var newGridColumns = oldColsOrdered.slice();\n newColsOrdered.forEach(function (newCol) {\n var parent = newCol.getOriginalParent();\n // if no parent, means we are not grouping, so just add the column to the end\n if (!parent) {\n newGridColumns.push(newCol);\n return;\n }\n // find the group the column belongs to. if no siblings at the current level (eg col in group on it's\n // own) then go up one level and look for siblings there.\n var siblings = [];\n while (!siblings.length && parent) {\n var leafCols = parent.getLeafColumns();\n leafCols.forEach(function (leafCol) {\n var presentInNewGriColumns = newGridColumns.indexOf(leafCol) >= 0;\n var noYetInSiblings = siblings.indexOf(leafCol) < 0;\n if (presentInNewGriColumns && noYetInSiblings) {\n siblings.push(leafCol);\n }\n });\n parent = parent.getOriginalParent();\n }\n // if no siblings exist at any level, this means the col is in a group (or parent groups) on it's own\n if (!siblings.length) {\n newGridColumns.push(newCol);\n return;\n }\n // find index of last column in the group\n var indexes = siblings.map(function (col) { return newGridColumns.indexOf(col); });\n var lastIndex = Math.max.apply(Math, __spread$f(indexes));\n insertIntoArray(newGridColumns, newCol, lastIndex + 1);\n });\n this.gridColumns = newGridColumns;\n };\n ColumnModel.prototype.isPrimaryColumnGroupsPresent = function () {\n return this.primaryHeaderRowCount > 1;\n };\n // if we are using autoGroupCols, then they should be included for quick filter. this covers the\n // following scenarios:\n // a) user provides 'field' into autoGroupCol of normal grid, so now because a valid col to filter leafs on\n // b) using tree data and user depends on autoGroupCol for first col, and we also want to filter on this\n // (tree data is a bit different, as parent rows can be filtered on, unlike row grouping)\n ColumnModel.prototype.setupQuickFilterColumns = function () {\n if (this.groupAutoColumns) {\n this.columnsForQuickFilter = (this.primaryColumns || []).concat(this.groupAutoColumns);\n }\n else if (this.primaryColumns) {\n this.columnsForQuickFilter = this.primaryColumns;\n }\n };\n ColumnModel.prototype.placeLockedColumns = function (cols) {\n var left = [];\n var normal = [];\n var right = [];\n cols.forEach(function (col) {\n var position = col.getColDef().lockPosition;\n if (position === 'right') {\n right.push(col);\n }\n else if (position === 'left' || position === true) {\n left.push(col);\n }\n else {\n normal.push(col);\n }\n });\n return __spread$f(left, normal, right);\n };\n ColumnModel.prototype.addAutoGroupToGridColumns = function () {\n if (missing(this.groupAutoColumns)) {\n return;\n }\n this.gridColumns = this.groupAutoColumns ? this.groupAutoColumns.concat(this.gridColumns) : this.gridColumns;\n var autoColBalancedTree = this.columnFactory.createForAutoGroups(this.groupAutoColumns, this.gridBalancedTree);\n this.gridBalancedTree = autoColBalancedTree.concat(this.gridBalancedTree);\n };\n // gets called after we copy down grid columns, to make sure any part of the gui\n // that tries to draw, eg the header, it will get empty lists of columns rather\n // than stale columns. for example, the header will received gridColumnsChanged\n // event, so will try and draw, but it will draw successfully when it acts on the\n // virtualColumnsChanged event\n ColumnModel.prototype.clearDisplayedAndViewportColumns = function () {\n this.displayedTreeLeft = [];\n this.displayedTreeRight = [];\n this.displayedTreeCentre = [];\n this.viewportRowLeft = {};\n this.viewportRowRight = {};\n this.viewportRowCenter = {};\n this.displayedColumnsLeft = [];\n this.displayedColumnsRight = [];\n this.displayedColumnsCenter = [];\n this.displayedColumns = [];\n this.viewportColumns = [];\n this.headerViewportColumns = [];\n this.viewportColumnsHash = '';\n };\n ColumnModel.prototype.updateGroupsAndDisplayedColumns = function (source) {\n this.updateOpenClosedVisibilityInColumnGroups();\n this.deriveDisplayedColumns(source);\n this.refreshFlexedColumns();\n this.extractViewport();\n this.updateBodyWidths();\n // this event is picked up by the gui, headerRenderer and rowRenderer, to recalculate what columns to display\n var event = {\n type: Events.EVENT_DISPLAYED_COLUMNS_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnModel.prototype.deriveDisplayedColumns = function (source) {\n this.derivedDisplayedColumnsFromDisplayedTree(this.displayedTreeLeft, this.displayedColumnsLeft);\n this.derivedDisplayedColumnsFromDisplayedTree(this.displayedTreeCentre, this.displayedColumnsCenter);\n this.derivedDisplayedColumnsFromDisplayedTree(this.displayedTreeRight, this.displayedColumnsRight);\n this.joinDisplayedColumns();\n this.setLeftValues(source);\n this.displayedAutoHeightCols = this.displayedColumns.filter(function (col) { return col.isAutoHeight(); });\n };\n ColumnModel.prototype.isAutoRowHeightActive = function () {\n return this.autoHeightActive;\n };\n ColumnModel.prototype.wasAutoRowHeightEverActive = function () {\n return this.autoHeightActiveAtLeastOnce;\n };\n ColumnModel.prototype.joinDisplayedColumns = function () {\n if (this.gridOptionsWrapper.isEnableRtl()) {\n this.displayedColumns = this.displayedColumnsRight\n .concat(this.displayedColumnsCenter)\n .concat(this.displayedColumnsLeft);\n }\n else {\n this.displayedColumns = this.displayedColumnsLeft\n .concat(this.displayedColumnsCenter)\n .concat(this.displayedColumnsRight);\n }\n };\n // sets the left pixel position of each column\n ColumnModel.prototype.setLeftValues = function (source) {\n this.setLeftValuesOfColumns(source);\n this.setLeftValuesOfGroups();\n };\n ColumnModel.prototype.setLeftValuesOfColumns = function (source) {\n var _this = this;\n if (!this.primaryColumns) {\n return;\n }\n // go through each list of displayed columns\n var allColumns = this.primaryColumns.slice(0);\n // let totalColumnWidth = this.getWidthOfColsInList()\n var doingRtl = this.gridOptionsWrapper.isEnableRtl();\n [\n this.displayedColumnsLeft,\n this.displayedColumnsRight,\n this.displayedColumnsCenter\n ].forEach(function (columns) {\n if (doingRtl) {\n // when doing RTL, we start at the top most pixel (ie RHS) and work backwards\n var left_1 = _this.getWidthOfColsInList(columns);\n columns.forEach(function (column) {\n left_1 -= column.getActualWidth();\n column.setLeft(left_1, source);\n });\n }\n else {\n // otherwise normal LTR, we start at zero\n var left_2 = 0;\n columns.forEach(function (column) {\n column.setLeft(left_2, source);\n left_2 += column.getActualWidth();\n });\n }\n removeAllFromArray(allColumns, columns);\n });\n // items left in allColumns are columns not displayed, so remove the left position. this is\n // important for the rows, as if a col is made visible, then taken out, then made visible again,\n // we don't want the animation of the cell floating in from the old position, whatever that was.\n allColumns.forEach(function (column) {\n column.setLeft(null, source);\n });\n };\n ColumnModel.prototype.setLeftValuesOfGroups = function () {\n // a groups left value is the lest left value of it's children\n [\n this.displayedTreeLeft,\n this.displayedTreeRight,\n this.displayedTreeCentre\n ].forEach(function (columns) {\n columns.forEach(function (column) {\n if (column instanceof ColumnGroup) {\n var columnGroup = column;\n columnGroup.checkLeft();\n }\n });\n });\n };\n ColumnModel.prototype.derivedDisplayedColumnsFromDisplayedTree = function (tree, columns) {\n columns.length = 0;\n this.columnUtils.depthFirstDisplayedColumnTreeSearch(tree, function (child) {\n if (child instanceof Column) {\n columns.push(child);\n }\n });\n };\n ColumnModel.prototype.extractViewportColumns = function () {\n if (this.suppressColumnVirtualisation) {\n // no virtualisation, so don't filter\n this.viewportColumnsCenter = this.displayedColumnsCenter;\n this.headerViewportColumnsCenter = this.displayedColumnsCenter;\n }\n else {\n // filter out what should be visible\n this.viewportColumnsCenter = this.displayedColumnsCenter.filter(this.isColumnInRowViewport.bind(this));\n this.headerViewportColumnsCenter = this.displayedColumnsCenter.filter(this.isColumnInHeaderViewport.bind(this));\n }\n this.viewportColumns = this.viewportColumnsCenter\n .concat(this.displayedColumnsLeft)\n .concat(this.displayedColumnsRight);\n this.headerViewportColumns = this.headerViewportColumnsCenter\n .concat(this.displayedColumnsLeft)\n .concat(this.displayedColumnsRight);\n };\n ColumnModel.prototype.getVirtualHeaderGroupRow = function (type, dept) {\n var result;\n switch (type) {\n case Constants.PINNED_LEFT:\n result = this.viewportRowLeft[dept];\n break;\n case Constants.PINNED_RIGHT:\n result = this.viewportRowRight[dept];\n break;\n default:\n result = this.viewportRowCenter[dept];\n break;\n }\n if (missing(result)) {\n result = [];\n }\n return result;\n };\n ColumnModel.prototype.calculateHeaderRows = function () {\n // go through each group, see if any of it's cols are displayed, and if yes,\n // then this group is included\n this.viewportRowLeft = {};\n this.viewportRowRight = {};\n this.viewportRowCenter = {};\n // for easy lookup when building the groups.\n var virtualColIds = {};\n this.headerViewportColumns.forEach(function (col) { return virtualColIds[col.getId()] = true; });\n var testGroup = function (children, result, dept) {\n var returnValue = false;\n for (var i = 0; i < children.length; i++) {\n // see if this item is within viewport\n var child = children[i];\n var addThisItem = false;\n if (child instanceof Column) {\n // for column, test if column is included\n addThisItem = virtualColIds[child.getId()] === true;\n }\n else {\n // if group, base decision on children\n var columnGroup = child;\n var displayedChildren = columnGroup.getDisplayedChildren();\n if (displayedChildren) {\n addThisItem = testGroup(displayedChildren, result, dept + 1);\n }\n }\n if (addThisItem) {\n returnValue = true;\n if (!result[dept]) {\n result[dept] = [];\n }\n result[dept].push(child);\n }\n }\n return returnValue;\n };\n testGroup(this.displayedTreeLeft, this.viewportRowLeft, 0);\n testGroup(this.displayedTreeRight, this.viewportRowRight, 0);\n testGroup(this.displayedTreeCentre, this.viewportRowCenter, 0);\n };\n ColumnModel.prototype.extractViewport = function () {\n var hashColumn = function (c) { return c.getId() + \"-\" + (c.getPinned() || 'normal'); };\n this.extractViewportColumns();\n var newHash = this.viewportColumns.map(hashColumn).join('#');\n var changed = this.viewportColumnsHash !== newHash;\n if (changed) {\n this.viewportColumnsHash = newHash;\n this.calculateHeaderRows();\n }\n return changed;\n };\n ColumnModel.prototype.refreshFlexedColumns = function (params) {\n var _this = this;\n if (params === void 0) { params = {}; }\n var source = params.source ? params.source : 'flex';\n if (params.viewportWidth != null) {\n this.flexViewportWidth = params.viewportWidth;\n }\n if (!this.flexViewportWidth) {\n return [];\n }\n // If the grid has left-over space, divide it between flexing columns in proportion to their flex value.\n // A \"flexing column\" is one that has a 'flex' value set and is not currently being constrained by its\n // minWidth or maxWidth rules.\n var flexAfterDisplayIndex = -1;\n if (params.resizingCols) {\n params.resizingCols.forEach(function (col) {\n var indexOfCol = _this.displayedColumnsCenter.indexOf(col);\n if (flexAfterDisplayIndex < indexOfCol) {\n flexAfterDisplayIndex = indexOfCol;\n }\n });\n }\n var isColFlex = function (col) {\n var afterResizingCols = _this.displayedColumnsCenter.indexOf(col) > flexAfterDisplayIndex;\n return col.getFlex() && afterResizingCols;\n };\n var knownWidthColumns = this.displayedColumnsCenter.filter(function (col) { return !isColFlex(col); });\n var flexingColumns = this.displayedColumnsCenter.filter(function (col) { return isColFlex(col); });\n var changedColumns = [];\n if (!flexingColumns.length) {\n return [];\n }\n var flexingColumnSizes = [];\n var spaceForFlexingColumns;\n outer: while (true) {\n var totalFlex = flexingColumns.reduce(function (count, col) { return count + col.getFlex(); }, 0);\n spaceForFlexingColumns = this.flexViewportWidth - this.getWidthOfColsInList(knownWidthColumns);\n for (var i = 0; i < flexingColumns.length; i++) {\n var col = flexingColumns[i];\n var widthByFlexRule = spaceForFlexingColumns * col.getFlex() / totalFlex;\n var constrainedWidth = 0;\n var minWidth = col.getMinWidth();\n var maxWidth = col.getMaxWidth();\n if (exists(minWidth) && widthByFlexRule < minWidth) {\n constrainedWidth = minWidth;\n }\n else if (exists(maxWidth) && widthByFlexRule > maxWidth) {\n constrainedWidth = maxWidth;\n }\n if (constrainedWidth) {\n // This column is not in fact flexing as it is being constrained to a specific size\n // so remove it from the list of flexing columns and start again\n col.setActualWidth(constrainedWidth, source);\n removeFromArray(flexingColumns, col);\n changedColumns.push(col);\n knownWidthColumns.push(col);\n continue outer;\n }\n flexingColumnSizes[i] = Math.round(widthByFlexRule);\n }\n break;\n }\n var remainingSpace = spaceForFlexingColumns;\n flexingColumns.forEach(function (col, i) {\n col.setActualWidth(Math.min(flexingColumnSizes[i], remainingSpace), source);\n changedColumns.push(col);\n remainingSpace -= flexingColumnSizes[i];\n });\n if (!params.skipSetLeft) {\n this.setLeftValues(source);\n }\n if (params.updateBodyWidths) {\n this.updateBodyWidths();\n }\n if (params.fireResizedEvent) {\n this.fireColumnResizedEvent(changedColumns, true, source, flexingColumns);\n }\n // if the user sets rowData directly into GridOptions, then the row data is set before\n // grid is attached to the DOM. this means the columns are not flexed, and then the rows\n // have the wrong height (as they depend on column widths). so once the columns have\n // been flexed for the first time (only happens once grid is attached to DOM, as dependency\n // on getting the grid width, which only happens after attached after ResizeObserver fires)\n // we get get rows to re-calc their heights.\n if (!this.flexColsCalculatedAtLestOnce) {\n if (this.gridOptionsWrapper.isRowModelDefault()) {\n this.rowModel.resetRowHeights();\n }\n this.flexColsCalculatedAtLestOnce = true;\n }\n return flexingColumns;\n };\n // called from api\n ColumnModel.prototype.sizeColumnsToFit = function (gridWidth, source, silent, params) {\n if (source === void 0) { source = \"sizeColumnsToFit\"; }\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;\n var limitsMap = {};\n if (params) {\n (_b = (_a = params) === null || _a === void 0 ? void 0 : _a.columnLimits) === null || _b === void 0 ? void 0 : _b.forEach(function (_a) {\n var key = _a.key, dimensions = __rest(_a, [\"key\"]);\n limitsMap[typeof key === 'string' ? key : key.getColId()] = dimensions;\n });\n }\n // avoid divide by zero\n var allDisplayedColumns = this.getAllDisplayedColumns();\n var doColumnsAlreadyFit = gridWidth === this.getWidthOfColsInList(allDisplayedColumns);\n if (gridWidth <= 0 || !allDisplayedColumns.length || doColumnsAlreadyFit) {\n return;\n }\n var colsToSpread = [];\n var colsToNotSpread = [];\n allDisplayedColumns.forEach(function (column) {\n if (column.getColDef().suppressSizeToFit === true) {\n colsToNotSpread.push(column);\n }\n else {\n colsToSpread.push(column);\n }\n });\n // make a copy of the cols that are going to be resized\n var colsToFireEventFor = colsToSpread.slice(0);\n var finishedResizing = false;\n var moveToNotSpread = function (column) {\n removeFromArray(colsToSpread, column);\n colsToNotSpread.push(column);\n };\n // resetting cols to their original width makes the sizeColumnsToFit more deterministic,\n // rather than depending on the current size of the columns. most users call sizeColumnsToFit\n // immediately after grid is created, so will make no difference. however if application is calling\n // sizeColumnsToFit repeatedly (eg after column group is opened / closed repeatedly) we don't want\n // the columns to start shrinking / growing over time.\n //\n // NOTE: the process below will assign values to `this.actualWidth` of each column without firing events\n // for this reason we need to manually fire resize events after the resize has been done for each column.\n colsToSpread.forEach(function (column) { return column.resetActualWidth(source); });\n while (!finishedResizing) {\n finishedResizing = true;\n var availablePixels = gridWidth - this.getWidthOfColsInList(colsToNotSpread);\n if (availablePixels <= 0) {\n // no width, set everything to minimum\n colsToSpread.forEach(function (column) {\n var _a, _b, _c, _d;\n var widthOverride = (_c = (_b = (_a = limitsMap) === null || _a === void 0 ? void 0 : _a[column.getId()]) === null || _b === void 0 ? void 0 : _b.minWidth, (_c !== null && _c !== void 0 ? _c : (_d = params) === null || _d === void 0 ? void 0 : _d.defaultMinWidth));\n if (typeof widthOverride === 'number') {\n column.setActualWidth(widthOverride);\n return;\n }\n column.setMinimum(source);\n });\n }\n else {\n var scale = availablePixels / this.getWidthOfColsInList(colsToSpread);\n // we set the pixels for the last col based on what's left, as otherwise\n // we could be a pixel or two short or extra because of rounding errors.\n var pixelsForLastCol = availablePixels;\n // backwards through loop, as we are removing items as we go\n for (var i = colsToSpread.length - 1; i >= 0; i--) {\n var column = colsToSpread[i];\n var widthOverride = (_c = limitsMap) === null || _c === void 0 ? void 0 : _c[column.getId()];\n var minOverride = (_e = (_d = widthOverride) === null || _d === void 0 ? void 0 : _d.minWidth, (_e !== null && _e !== void 0 ? _e : (_f = params) === null || _f === void 0 ? void 0 : _f.defaultMinWidth));\n var maxOverride = (_h = (_g = widthOverride) === null || _g === void 0 ? void 0 : _g.maxWidth, (_h !== null && _h !== void 0 ? _h : (_j = params) === null || _j === void 0 ? void 0 : _j.defaultMaxWidth));\n var colMinWidth = (_k = column.getMinWidth(), (_k !== null && _k !== void 0 ? _k : 0));\n var colMaxWidth = (_l = column.getMaxWidth(), (_l !== null && _l !== void 0 ? _l : Number.MAX_VALUE));\n var minWidth = typeof minOverride === 'number' && minOverride > colMinWidth ? minOverride : column.getMinWidth();\n var maxWidth = typeof maxOverride === 'number' && maxOverride < colMaxWidth ? maxOverride : column.getMaxWidth();\n var newWidth = Math.round(column.getActualWidth() * scale);\n if (exists(minWidth) && newWidth < minWidth) {\n newWidth = minWidth;\n moveToNotSpread(column);\n finishedResizing = false;\n }\n else if (exists(maxWidth) && newWidth > maxWidth) {\n newWidth = maxWidth;\n moveToNotSpread(column);\n finishedResizing = false;\n }\n else if (i === 0) { // if this is the last column\n newWidth = pixelsForLastCol;\n }\n column.setActualWidth(newWidth, source, true);\n pixelsForLastCol -= newWidth;\n }\n }\n }\n // see notes above\n colsToFireEventFor.forEach(function (col) {\n col.fireColumnWidthChangedEvent(source);\n });\n this.setLeftValues(source);\n this.updateBodyWidths();\n if (silent) {\n return;\n }\n this.fireColumnResizedEvent(colsToFireEventFor, true, source);\n };\n ColumnModel.prototype.buildDisplayedTrees = function (visibleColumns) {\n var leftVisibleColumns = [];\n var rightVisibleColumns = [];\n var centerVisibleColumns = [];\n visibleColumns.forEach(function (column) {\n switch (column.getPinned()) {\n case \"left\":\n leftVisibleColumns.push(column);\n break;\n case \"right\":\n rightVisibleColumns.push(column);\n break;\n default:\n centerVisibleColumns.push(column);\n break;\n }\n });\n var groupInstanceIdCreator = new GroupInstanceIdCreator();\n this.displayedTreeLeft = this.displayedGroupCreator.createDisplayedGroups(leftVisibleColumns, this.gridBalancedTree, groupInstanceIdCreator, Constants.PINNED_LEFT, this.displayedTreeLeft);\n this.displayedTreeRight = this.displayedGroupCreator.createDisplayedGroups(rightVisibleColumns, this.gridBalancedTree, groupInstanceIdCreator, Constants.PINNED_RIGHT, this.displayedTreeRight);\n this.displayedTreeCentre = this.displayedGroupCreator.createDisplayedGroups(centerVisibleColumns, this.gridBalancedTree, groupInstanceIdCreator, null, this.displayedTreeCentre);\n this.updateDisplayedMap();\n };\n ColumnModel.prototype.updateDisplayedMap = function () {\n var _this = this;\n this.displayedColumnsAndGroupsMap = {};\n var func = function (child) {\n _this.displayedColumnsAndGroupsMap[child.getUniqueId()] = child;\n };\n this.columnUtils.depthFirstAllColumnTreeSearch(this.displayedTreeCentre, func);\n this.columnUtils.depthFirstAllColumnTreeSearch(this.displayedTreeLeft, func);\n this.columnUtils.depthFirstAllColumnTreeSearch(this.displayedTreeRight, func);\n };\n ColumnModel.prototype.isDisplayed = function (item) {\n var fromMap = this.displayedColumnsAndGroupsMap[item.getUniqueId()];\n // check for reference, in case new column / group with same id is now present\n return fromMap === item;\n };\n ColumnModel.prototype.updateOpenClosedVisibilityInColumnGroups = function () {\n var allColumnGroups = this.getAllDisplayedTrees();\n this.columnUtils.depthFirstAllColumnTreeSearch(allColumnGroups, function (child) {\n if (child instanceof ColumnGroup) {\n var columnGroup = child;\n columnGroup.calculateDisplayedColumns();\n }\n });\n };\n ColumnModel.prototype.getGroupAutoColumns = function () {\n return this.groupAutoColumns;\n };\n /**\n * Creates new auto group columns if required\n * @returns whether auto cols have changed\n */\n ColumnModel.prototype.createGroupAutoColumnsIfNeeded = function () {\n if (!this.autoGroupsNeedBuilding) {\n return false;\n }\n this.autoGroupsNeedBuilding = false;\n var groupFullWidthRow = this.gridOptionsWrapper.isGroupUseEntireRow(this.pivotMode);\n // we need to allow suppressing auto-column separately for group and pivot as the normal situation\n // is CSRM and user provides group column themselves for normal view, but when they go into pivot the\n // columns are generated by the grid so no opportunity for user to provide group column. so need a way\n // to suppress auto-col for grouping only, and not pivot.\n // however if using Viewport RM or SSRM and user is providing the columns, the user may wish full control\n // of the group column in this instance.\n var suppressAutoColumn = this.pivotMode ?\n this.gridOptionsWrapper.isPivotSuppressAutoColumn() : this.gridOptionsWrapper.isGroupSuppressAutoColumn();\n var groupingActive = this.rowGroupColumns.length > 0 || this.usingTreeData;\n var needAutoColumns = groupingActive && !suppressAutoColumn && !groupFullWidthRow;\n if (needAutoColumns) {\n var existingCols = this.groupAutoColumns || [];\n var newAutoGroupCols = this.autoGroupColService.createAutoGroupColumns(existingCols, this.rowGroupColumns);\n var autoColsDifferent = !this.autoColsEqual(newAutoGroupCols, this.groupAutoColumns);\n // we force recreate when suppressColumnStateEvents changes, so new group cols pick up the new\n // definitions. otherwise we could ignore the new cols because they appear to be the same.\n if (autoColsDifferent || this.forceRecreateAutoGroups) {\n this.groupAutoColumns = newAutoGroupCols;\n return true;\n }\n }\n else {\n this.groupAutoColumns = null;\n }\n return false;\n };\n ColumnModel.prototype.autoColsEqual = function (colsA, colsB) {\n return areEqual(colsA, colsB, function (a, b) { return a.getColId() === b.getColId(); });\n };\n ColumnModel.prototype.getWidthOfColsInList = function (columnList) {\n return columnList.reduce(function (width, col) { return width + col.getActualWidth(); }, 0);\n };\n ColumnModel.prototype.getGridBalancedTree = function () {\n return this.gridBalancedTree;\n };\n ColumnModel.prototype.hasFloatingFilters = function () {\n if (!this.gridColumns) {\n return false;\n }\n var res = this.gridColumns.some(function (col) { return col.getColDef().floatingFilter; });\n return res;\n };\n ColumnModel.prototype.getFirstDisplayedColumn = function () {\n var isRtl = this.gridOptionsWrapper.isEnableRtl();\n var queryOrder = [\n 'getDisplayedLeftColumns',\n 'getDisplayedCenterColumns',\n 'getDisplayedRightColumns'\n ];\n if (isRtl) {\n queryOrder.reverse();\n }\n for (var i = 0; i < queryOrder.length; i++) {\n var container = this[queryOrder[i]]();\n if (container.length) {\n return isRtl ? last(container) : container[0];\n }\n }\n return null;\n };\n ColumnModel.prototype.setColumnHeaderHeight = function (col, height) {\n var changed = col.setAutoHeaderHeight(height);\n if (changed) {\n var event_5 = {\n type: Events.EVENT_COLUMN_HEADER_HEIGHT_CHANGED,\n column: col,\n columns: [col],\n source: 'autosizeColumnHeaderHeight',\n };\n this.eventService.dispatchEvent(event_5);\n }\n };\n ColumnModel.prototype.getColumnGroupHeaderRowHeight = function () {\n if (this.isPivotMode()) {\n return this.gridOptionsWrapper.getPivotGroupHeaderHeight();\n }\n else {\n return this.gridOptionsWrapper.getGroupHeaderHeight();\n }\n };\n ColumnModel.prototype.getColumnHeaderRowHeight = function () {\n var defaultHeight = (this.isPivotMode() ?\n this.gridOptionsWrapper.getPivotHeaderHeight() :\n this.gridOptionsWrapper.getHeaderHeight());\n var displayedHeights = this.getAllDisplayedColumns()\n .filter(function (col) { return col.isAutoHeaderHeight(); })\n .map(function (col) { return col.getAutoHeaderHeight() || 0; });\n return Math.max.apply(Math, __spread$f([defaultHeight], displayedHeights));\n };\n __decorate$2u([\n Autowired('expressionService')\n ], ColumnModel.prototype, \"expressionService\", void 0);\n __decorate$2u([\n Autowired('columnFactory')\n ], ColumnModel.prototype, \"columnFactory\", void 0);\n __decorate$2u([\n Autowired('displayedGroupCreator')\n ], ColumnModel.prototype, \"displayedGroupCreator\", void 0);\n __decorate$2u([\n Autowired('ctrlsService')\n ], ColumnModel.prototype, \"ctrlsService\", void 0);\n __decorate$2u([\n Autowired('autoWidthCalculator')\n ], ColumnModel.prototype, \"autoWidthCalculator\", void 0);\n __decorate$2u([\n Autowired('columnUtils')\n ], ColumnModel.prototype, \"columnUtils\", void 0);\n __decorate$2u([\n Autowired('columnAnimationService')\n ], ColumnModel.prototype, \"columnAnimationService\", void 0);\n __decorate$2u([\n Autowired('autoGroupColService')\n ], ColumnModel.prototype, \"autoGroupColService\", void 0);\n __decorate$2u([\n Optional('aggFuncService')\n ], ColumnModel.prototype, \"aggFuncService\", void 0);\n __decorate$2u([\n Optional('valueCache')\n ], ColumnModel.prototype, \"valueCache\", void 0);\n __decorate$2u([\n Optional('animationFrameService')\n ], ColumnModel.prototype, \"animationFrameService\", void 0);\n __decorate$2u([\n Autowired('rowModel')\n ], ColumnModel.prototype, \"rowModel\", void 0);\n __decorate$2u([\n Autowired('sortController')\n ], ColumnModel.prototype, \"sortController\", void 0);\n __decorate$2u([\n Autowired('columnDefFactory')\n ], ColumnModel.prototype, \"columnDefFactory\", void 0);\n __decorate$2u([\n PostConstruct\n ], ColumnModel.prototype, \"init\", null);\n __decorate$2u([\n __param$7(0, Qualifier('loggerFactory'))\n ], ColumnModel.prototype, \"setBeans\", null);\n ColumnModel = __decorate$2u([\n Bean('columnModel')\n ], ColumnModel);\n return ColumnModel;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2S = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2t = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n// takes in a list of columns, as specified by the column definitions, and returns column groups\nvar ColumnUtils = /** @class */ (function (_super) {\n __extends$2S(ColumnUtils, _super);\n function ColumnUtils() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ColumnUtils.prototype.calculateColMinWidth = function (colDef) {\n return colDef.minWidth != null ? colDef.minWidth : this.gridOptionsWrapper.getMinColWidth();\n };\n ColumnUtils.prototype.calculateColMaxWidth = function (colDef) {\n return colDef.maxWidth != null ? colDef.maxWidth : (this.gridOptionsWrapper.getMaxColWidth() || Number.MAX_SAFE_INTEGER);\n };\n ColumnUtils.prototype.calculateColInitialWidth = function (colDef) {\n var minColWidth = this.calculateColMinWidth(colDef);\n var maxColWidth = this.calculateColMaxWidth(colDef);\n var width;\n var colDefWidth = attrToNumber(colDef.width);\n var colDefInitialWidth = attrToNumber(colDef.initialWidth);\n if (colDefWidth != null) {\n width = colDefWidth;\n }\n else if (colDefInitialWidth != null) {\n width = colDefInitialWidth;\n }\n else {\n width = this.gridOptionsWrapper.getColWidth();\n }\n return Math.max(Math.min(width, maxColWidth), minColWidth);\n };\n ColumnUtils.prototype.getOriginalPathForColumn = function (column, originalBalancedTree) {\n var result = [];\n var found = false;\n var recursePath = function (balancedColumnTree, dept) {\n for (var i = 0; i < balancedColumnTree.length; i++) {\n if (found) {\n return;\n }\n // quit the search, so 'result' is kept with the found result\n var node = balancedColumnTree[i];\n if (node instanceof ProvidedColumnGroup) {\n var nextNode = node;\n recursePath(nextNode.getChildren(), dept + 1);\n result[dept] = node;\n }\n else if (node === column) {\n found = true;\n }\n }\n };\n recursePath(originalBalancedTree, 0);\n // we should always find the path, but in case there is a bug somewhere, returning null\n // will make it fail rather than provide a 'hard to track down' bug\n return found ? result : null;\n };\n ColumnUtils.prototype.depthFirstOriginalTreeSearch = function (parent, tree, callback) {\n var _this = this;\n if (!tree) {\n return;\n }\n tree.forEach(function (child) {\n if (child instanceof ProvidedColumnGroup) {\n _this.depthFirstOriginalTreeSearch(child, child.getChildren(), callback);\n }\n callback(child, parent);\n });\n };\n ColumnUtils.prototype.depthFirstAllColumnTreeSearch = function (tree, callback) {\n var _this = this;\n if (!tree) {\n return;\n }\n tree.forEach(function (child) {\n if (child instanceof ColumnGroup) {\n _this.depthFirstAllColumnTreeSearch(child.getChildren(), callback);\n }\n callback(child);\n });\n };\n ColumnUtils.prototype.depthFirstDisplayedColumnTreeSearch = function (tree, callback) {\n var _this = this;\n if (!tree) {\n return;\n }\n tree.forEach(function (child) {\n if (child instanceof ColumnGroup) {\n _this.depthFirstDisplayedColumnTreeSearch(child.getDisplayedChildren(), callback);\n }\n callback(child);\n });\n };\n ColumnUtils = __decorate$2t([\n Bean('columnUtils')\n ], ColumnUtils);\n return ColumnUtils;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2R = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2s = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n// takes in a list of columns, as specified by the column definitions, and returns column groups\nvar DisplayedGroupCreator = /** @class */ (function (_super) {\n __extends$2R(DisplayedGroupCreator, _super);\n function DisplayedGroupCreator() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n DisplayedGroupCreator.prototype.createDisplayedGroups = function (\n // all displayed columns sorted - this is the columns the grid should show\n sortedVisibleColumns, \n // the tree of columns, as provided by the users, used to know what groups columns roll up into\n balancedColumnTree, \n // creates unique id's for the group\n groupInstanceIdCreator, \n // whether it's left, right or center col\n pinned, \n // we try to reuse old groups if we can, to allow gui to do animation\n oldDisplayedGroups) {\n var _this = this;\n var result = [];\n var previousRealPath;\n var previousOriginalPath;\n var oldColumnsMapped = this.mapOldGroupsById(oldDisplayedGroups);\n // go through each column, then do a bottom up comparison to the previous column, and start\n // to share groups if they converge at any point.\n sortedVisibleColumns.forEach(function (currentColumn) {\n var currentOriginalPath = _this.getOriginalPathForColumn(balancedColumnTree, currentColumn);\n var currentRealPath = [];\n var firstColumn = !previousOriginalPath;\n for (var i = 0; i < currentOriginalPath.length; i++) {\n if (firstColumn || currentOriginalPath[i] !== previousOriginalPath[i]) {\n // new group needed\n var newGroup = _this.createColumnGroup(currentOriginalPath[i], groupInstanceIdCreator, oldColumnsMapped, pinned);\n currentRealPath[i] = newGroup;\n // if top level, add to result, otherwise add to parent\n if (i == 0) {\n result.push(newGroup);\n }\n else {\n currentRealPath[i - 1].addChild(newGroup);\n }\n }\n else {\n // reuse old group\n currentRealPath[i] = previousRealPath[i];\n }\n }\n var noColumnGroups = currentRealPath.length === 0;\n if (noColumnGroups) {\n // if we are not grouping, then the result of the above is an empty\n // path (no groups), and we just add the column to the root list.\n result.push(currentColumn);\n }\n else {\n var leafGroup = last(currentRealPath);\n leafGroup.addChild(currentColumn);\n }\n previousRealPath = currentRealPath;\n previousOriginalPath = currentOriginalPath;\n });\n this.setupParentsIntoColumns(result, null);\n return result;\n };\n DisplayedGroupCreator.prototype.createColumnGroup = function (providedGroup, groupInstanceIdCreator, oldColumnsMapped, pinned) {\n var groupId = providedGroup.getGroupId();\n var instanceId = groupInstanceIdCreator.getInstanceIdForKey(groupId);\n var uniqueId = ColumnGroup.createUniqueId(groupId, instanceId);\n var columnGroup = oldColumnsMapped[uniqueId];\n // if the user is setting new colDefs, it is possible that the id's overlap, and we\n // would have a false match from above. so we double check we are talking about the\n // same original column group.\n if (columnGroup && columnGroup.getProvidedColumnGroup() !== providedGroup) {\n columnGroup = null;\n }\n if (exists(columnGroup)) {\n // clean out the old column group here, as we will be adding children into it again\n columnGroup.reset();\n }\n else {\n columnGroup = new ColumnGroup(providedGroup, groupId, instanceId, pinned);\n this.context.createBean(columnGroup);\n }\n return columnGroup;\n };\n // returns back a 2d map of ColumnGroup as follows: groupId -> instanceId -> ColumnGroup\n DisplayedGroupCreator.prototype.mapOldGroupsById = function (displayedGroups) {\n var result = {};\n var recursive = function (columnsOrGroups) {\n columnsOrGroups.forEach(function (columnOrGroup) {\n if (columnOrGroup instanceof ColumnGroup) {\n var columnGroup = columnOrGroup;\n result[columnOrGroup.getUniqueId()] = columnGroup;\n recursive(columnGroup.getChildren());\n }\n });\n };\n if (displayedGroups) {\n recursive(displayedGroups);\n }\n return result;\n };\n DisplayedGroupCreator.prototype.setupParentsIntoColumns = function (columnsOrGroups, parent) {\n var _this = this;\n columnsOrGroups.forEach(function (columnsOrGroup) {\n columnsOrGroup.setParent(parent);\n if (columnsOrGroup instanceof ColumnGroup) {\n var columnGroup = columnsOrGroup;\n _this.setupParentsIntoColumns(columnGroup.getChildren(), columnGroup);\n }\n });\n };\n DisplayedGroupCreator.prototype.getOriginalPathForColumn = function (balancedColumnTree, column) {\n var result = [];\n var found = false;\n var recursePath = function (columnTree, dept) {\n for (var i = 0; i < columnTree.length; i++) {\n // quit the search, so 'result' is kept with the found result\n if (found) {\n return;\n }\n var node = columnTree[i];\n if (node instanceof ProvidedColumnGroup) {\n recursePath(node.getChildren(), dept + 1);\n result[dept] = node;\n }\n else if (node === column) {\n found = true;\n }\n }\n };\n recursePath(balancedColumnTree, 0);\n // it's possible we didn't find a path. this happens if the column is generated\n // by the grid (auto-group), in that the definition didn't come from the client. in this case,\n // we create a fake original path.\n if (found) {\n return result;\n }\n console.warn('AG Grid: could not get path');\n return null;\n };\n DisplayedGroupCreator = __decorate$2s([\n Bean('displayedGroupCreator')\n ], DisplayedGroupCreator);\n return DisplayedGroupCreator;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2Q = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2r = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgStackComponentsRegistry = /** @class */ (function (_super) {\n __extends$2Q(AgStackComponentsRegistry, _super);\n function AgStackComponentsRegistry() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.componentsMappedByName = {};\n return _this;\n }\n AgStackComponentsRegistry.prototype.setupComponents = function (components) {\n var _this = this;\n if (components) {\n components.forEach(function (componentMeta) { return _this.addComponent(componentMeta); });\n }\n };\n AgStackComponentsRegistry.prototype.addComponent = function (componentMeta) {\n // get name of the class as a string\n // let className = getNameOfClass(ComponentClass);\n // insert a dash after every capital letter\n // let classEscaped = className.replace(/([A-Z])/g, \"-$1\").toLowerCase();\n var classEscaped = componentMeta.componentName.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n // put all to upper case\n var classUpperCase = classEscaped.toUpperCase();\n // finally store\n this.componentsMappedByName[classUpperCase] = componentMeta.componentClass;\n };\n AgStackComponentsRegistry.prototype.getComponentClass = function (htmlTag) {\n return this.componentsMappedByName[htmlTag];\n };\n AgStackComponentsRegistry = __decorate$2r([\n Bean('agStackComponentsRegistry')\n ], AgStackComponentsRegistry);\n return AgStackComponentsRegistry;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __read$k = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar Color = /** @class */ (function () {\n /**\n * Every color component should be in the [0, 1] range.\n * Some easing functions (such as elastic easing) can overshoot the target value by some amount.\n * So, when animating colors, if the source or target color components are already near\n * or at the edge of the allowed [0, 1] range, it is possible for the intermediate color\n * component value to end up outside of that range mid-animation. For this reason the constructor\n * performs range checking/constraining.\n * @param r Red component.\n * @param g Green component.\n * @param b Blue component.\n * @param a Alpha (opacity) component.\n */\n function Color(r, g, b, a) {\n if (a === void 0) { a = 1; }\n // NaN is treated as 0.\n this.r = Math.min(1, Math.max(0, r || 0));\n this.g = Math.min(1, Math.max(0, g || 0));\n this.b = Math.min(1, Math.max(0, b || 0));\n this.a = Math.min(1, Math.max(0, a || 0));\n }\n /**\n * The given string can be in one of the following formats:\n * - #rgb\n * - #rrggbb\n * - rgb(r, g, b)\n * - rgba(r, g, b, a)\n * - CSS color name such as 'white', 'orange', 'cyan', etc.\n * @param str\n */\n Color.fromString = function (str) {\n // hexadecimal notation\n if (str.indexOf('#') >= 0) { // there can be some leading whitespace\n return Color.fromHexString(str);\n }\n // color name\n var hex = Color.nameToHex[str];\n if (hex) {\n return Color.fromHexString(hex);\n }\n // rgb(a) notation\n if (str.indexOf('rgb') >= 0) {\n return Color.fromRgbaString(str);\n }\n throw new Error(\"Invalid color string: '\" + str + \"'\");\n };\n // See https://drafts.csswg.org/css-color/#hex-notation\n Color.parseHex = function (input) {\n input = input.replace(/ /g, '').slice(1);\n var parts;\n switch (input.length) {\n case 6:\n case 8:\n parts = [];\n for (var i = 0; i < input.length; i += 2) {\n parts.push(parseInt(\"\" + input[i] + input[i + 1], 16));\n }\n break;\n case 3:\n case 4:\n parts = input.split('').map(function (p) { return parseInt(p, 16); }).map(function (p) { return p + p * 16; });\n break;\n }\n if (parts.length >= 3) {\n if (parts.every(function (p) { return p >= 0; })) {\n if (parts.length === 3) {\n parts.push(255);\n }\n return parts;\n }\n }\n };\n Color.fromHexString = function (str) {\n var values = Color.parseHex(str);\n if (values) {\n var _a = __read$k(values, 4), r = _a[0], g = _a[1], b = _a[2], a = _a[3];\n return new Color(r / 255, g / 255, b / 255, a / 255);\n }\n throw new Error(\"Malformed hexadecimal color string: '\" + str + \"'\");\n };\n Color.stringToRgba = function (str) {\n // Find positions of opening and closing parentheses.\n var _a = __read$k([NaN, NaN], 2), po = _a[0], pc = _a[1];\n for (var i = 0; i < str.length; i++) {\n var c = str[i];\n if (!po && c === '(') {\n po = i;\n }\n else if (c === ')') {\n pc = i;\n break;\n }\n }\n var contents = po && pc && str.substring(po + 1, pc);\n if (!contents) {\n return;\n }\n var parts = contents.split(',');\n var rgba = [];\n for (var i = 0; i < parts.length; i++) {\n var part = parts[i];\n var value = parseFloat(part);\n if (isNaN(value)) {\n return;\n }\n if (part.indexOf('%') >= 0) { // percentage r, g, or b value\n value = Math.max(0, Math.min(100, value));\n value /= 100;\n }\n else {\n if (i === 3) { // alpha component\n value = Math.max(0, Math.min(1, value));\n }\n else { // absolute r, g, or b value\n value = Math.max(0, Math.min(255, value));\n value /= 255;\n }\n }\n rgba.push(value);\n }\n return rgba;\n };\n Color.fromRgbaString = function (str) {\n var rgba = Color.stringToRgba(str);\n if (rgba) {\n if (rgba.length === 3) {\n return new Color(rgba[0], rgba[1], rgba[2]);\n }\n else if (rgba.length === 4) {\n return new Color(rgba[0], rgba[1], rgba[2], rgba[3]);\n }\n }\n throw new Error(\"Malformed rgb/rgba color string: '\" + str + \"'\");\n };\n Color.fromArray = function (arr) {\n if (arr.length === 4) {\n return new Color(arr[0], arr[1], arr[2], arr[3]);\n }\n if (arr.length === 3) {\n return new Color(arr[0], arr[1], arr[2]);\n }\n throw new Error('The given array should contain 3 or 4 color components (numbers).');\n };\n Color.fromHSB = function (h, s, b, alpha) {\n if (alpha === void 0) { alpha = 1; }\n var rgb = Color.HSBtoRGB(h, s, b);\n return new Color(rgb[0], rgb[1], rgb[2], alpha);\n };\n Color.padHex = function (str) {\n // Can't use `padStart(2, '0')` here because of IE.\n return str.length === 1 ? '0' + str : str;\n };\n Color.prototype.toHexString = function () {\n var hex = '#'\n + Color.padHex(Math.round(this.r * 255).toString(16))\n + Color.padHex(Math.round(this.g * 255).toString(16))\n + Color.padHex(Math.round(this.b * 255).toString(16));\n if (this.a < 1) {\n hex += Color.padHex(Math.round(this.a * 255).toString(16));\n }\n return hex;\n };\n Color.prototype.toRgbaString = function (fractionDigits) {\n if (fractionDigits === void 0) { fractionDigits = 3; }\n var components = [\n Math.round(this.r * 255),\n Math.round(this.g * 255),\n Math.round(this.b * 255)\n ];\n var k = Math.pow(10, fractionDigits);\n if (this.a !== 1) {\n components.push(Math.round(this.a * k) / k);\n return \"rgba(\" + components.join(', ') + \")\";\n }\n return \"rgb(\" + components.join(', ') + \")\";\n };\n Color.prototype.toString = function () {\n if (this.a === 1) {\n return this.toHexString();\n }\n return this.toRgbaString();\n };\n Color.prototype.toHSB = function () {\n return Color.RGBtoHSB(this.r, this.g, this.b);\n };\n /**\n * Converts the given RGB triple to an array of HSB (HSV) components.\n * The hue component will be `NaN` for achromatic colors.\n */\n Color.RGBtoHSB = function (r, g, b) {\n var min = Math.min(r, g, b);\n var max = Math.max(r, g, b);\n var S = max !== 0 ? (max - min) / max : 0;\n var H = NaN;\n // min == max, means all components are the same\n // and the color is a shade of gray with no hue (H is NaN)\n if (min !== max) {\n var delta = max - min;\n var rc = (max - r) / delta;\n var gc = (max - g) / delta;\n var bc = (max - b) / delta;\n if (r === max) {\n H = bc - gc;\n }\n else if (g === max) {\n H = 2.0 + rc - bc;\n }\n else {\n H = 4.0 + gc - rc;\n }\n H /= 6.0;\n if (H < 0) {\n H = H + 1.0;\n }\n }\n return [H * 360, S, max];\n };\n /**\n * Converts the given HSB (HSV) triple to an array of RGB components.\n */\n Color.HSBtoRGB = function (H, S, B) {\n if (isNaN(H)) {\n H = 0;\n }\n H = (((H % 360) + 360) % 360) / 360; // normalize hue to [0, 360] interval, then scale to [0, 1]\n var r = 0;\n var g = 0;\n var b = 0;\n if (S === 0) {\n r = g = b = B;\n }\n else {\n var h = (H - Math.floor(H)) * 6;\n var f = h - Math.floor(h);\n var p = B * (1 - S);\n var q = B * (1 - S * f);\n var t = B * (1 - (S * (1 - f)));\n switch (h >> 0) { // discard the floating point part of the number\n case 0:\n r = B;\n g = t;\n b = p;\n break;\n case 1:\n r = q;\n g = B;\n b = p;\n break;\n case 2:\n r = p;\n g = B;\n b = t;\n break;\n case 3:\n r = p;\n g = q;\n b = B;\n break;\n case 4:\n r = t;\n g = p;\n b = B;\n break;\n case 5:\n r = B;\n g = p;\n b = q;\n break;\n }\n }\n return [r, g, b];\n };\n Color.prototype.derive = function (hueShift, saturationFactor, brightnessFactor, opacityFactor) {\n var hsb = Color.RGBtoHSB(this.r, this.g, this.b);\n var b = hsb[2];\n if (b == 0 && brightnessFactor > 1.0) {\n b = 0.05;\n }\n var h = (((hsb[0] + hueShift) % 360) + 360) % 360;\n var s = Math.max(Math.min(hsb[1] * saturationFactor, 1.0), 0.0);\n b = Math.max(Math.min(b * brightnessFactor, 1.0), 0.0);\n var a = Math.max(Math.min(this.a * opacityFactor, 1.0), 0.0);\n var rgba = Color.HSBtoRGB(h, s, b);\n rgba.push(a);\n return Color.fromArray(rgba);\n };\n Color.prototype.brighter = function () {\n return this.derive(0, 1.0, 1.0 / 0.7, 1.0);\n };\n Color.prototype.darker = function () {\n return this.derive(0, 1.0, 0.7, 1.0);\n };\n /**\n * CSS Color Module Level 4:\n * https://drafts.csswg.org/css-color/#named-colors\n */\n Color.nameToHex = Object.freeze({\n aliceblue: '#F0F8FF',\n antiquewhite: '#FAEBD7',\n aqua: '#00FFFF',\n aquamarine: '#7FFFD4',\n azure: '#F0FFFF',\n beige: '#F5F5DC',\n bisque: '#FFE4C4',\n black: '#000000',\n blanchedalmond: '#FFEBCD',\n blue: '#0000FF',\n blueviolet: '#8A2BE2',\n brown: '#A52A2A',\n burlywood: '#DEB887',\n cadetblue: '#5F9EA0',\n chartreuse: '#7FFF00',\n chocolate: '#D2691E',\n coral: '#FF7F50',\n cornflowerblue: '#6495ED',\n cornsilk: '#FFF8DC',\n crimson: '#DC143C',\n cyan: '#00FFFF',\n darkblue: '#00008B',\n darkcyan: '#008B8B',\n darkgoldenrod: '#B8860B',\n darkgray: '#A9A9A9',\n darkgreen: '#006400',\n darkgrey: '#A9A9A9',\n darkkhaki: '#BDB76B',\n darkmagenta: '#8B008B',\n darkolivegreen: '#556B2F',\n darkorange: '#FF8C00',\n darkorchid: '#9932CC',\n darkred: '#8B0000',\n darksalmon: '#E9967A',\n darkseagreen: '#8FBC8F',\n darkslateblue: '#483D8B',\n darkslategray: '#2F4F4F',\n darkslategrey: '#2F4F4F',\n darkturquoise: '#00CED1',\n darkviolet: '#9400D3',\n deeppink: '#FF1493',\n deepskyblue: '#00BFFF',\n dimgray: '#696969',\n dimgrey: '#696969',\n dodgerblue: '#1E90FF',\n firebrick: '#B22222',\n floralwhite: '#FFFAF0',\n forestgreen: '#228B22',\n fuchsia: '#FF00FF',\n gainsboro: '#DCDCDC',\n ghostwhite: '#F8F8FF',\n gold: '#FFD700',\n goldenrod: '#DAA520',\n gray: '#808080',\n green: '#008000',\n greenyellow: '#ADFF2F',\n grey: '#808080',\n honeydew: '#F0FFF0',\n hotpink: '#FF69B4',\n indianred: '#CD5C5C',\n indigo: '#4B0082',\n ivory: '#FFFFF0',\n khaki: '#F0E68C',\n lavender: '#E6E6FA',\n lavenderblush: '#FFF0F5',\n lawngreen: '#7CFC00',\n lemonchiffon: '#FFFACD',\n lightblue: '#ADD8E6',\n lightcoral: '#F08080',\n lightcyan: '#E0FFFF',\n lightgoldenrodyellow: '#FAFAD2',\n lightgray: '#D3D3D3',\n lightgreen: '#90EE90',\n lightgrey: '#D3D3D3',\n lightpink: '#FFB6C1',\n lightsalmon: '#FFA07A',\n lightseagreen: '#20B2AA',\n lightskyblue: '#87CEFA',\n lightslategray: '#778899',\n lightslategrey: '#778899',\n lightsteelblue: '#B0C4DE',\n lightyellow: '#FFFFE0',\n lime: '#00FF00',\n limegreen: '#32CD32',\n linen: '#FAF0E6',\n magenta: '#FF00FF',\n maroon: '#800000',\n mediumaquamarine: '#66CDAA',\n mediumblue: '#0000CD',\n mediumorchid: '#BA55D3',\n mediumpurple: '#9370DB',\n mediumseagreen: '#3CB371',\n mediumslateblue: '#7B68EE',\n mediumspringgreen: '#00FA9A',\n mediumturquoise: '#48D1CC',\n mediumvioletred: '#C71585',\n midnightblue: '#191970',\n mintcream: '#F5FFFA',\n mistyrose: '#FFE4E1',\n moccasin: '#FFE4B5',\n navajowhite: '#FFDEAD',\n navy: '#000080',\n oldlace: '#FDF5E6',\n olive: '#808000',\n olivedrab: '#6B8E23',\n orange: '#FFA500',\n orangered: '#FF4500',\n orchid: '#DA70D6',\n palegoldenrod: '#EEE8AA',\n palegreen: '#98FB98',\n paleturquoise: '#AFEEEE',\n palevioletred: '#DB7093',\n papayawhip: '#FFEFD5',\n peachpuff: '#FFDAB9',\n peru: '#CD853F',\n pink: '#FFC0CB',\n plum: '#DDA0DD',\n powderblue: '#B0E0E6',\n purple: '#800080',\n rebeccapurple: '#663399',\n red: '#FF0000',\n rosybrown: '#BC8F8F',\n royalblue: '#4169E1',\n saddlebrown: '#8B4513',\n salmon: '#FA8072',\n sandybrown: '#F4A460',\n seagreen: '#2E8B57',\n seashell: '#FFF5EE',\n sienna: '#A0522D',\n silver: '#C0C0C0',\n skyblue: '#87CEEB',\n slateblue: '#6A5ACD',\n slategray: '#708090',\n slategrey: '#708090',\n snow: '#FFFAFA',\n springgreen: '#00FF7F',\n steelblue: '#4682B4',\n tan: '#D2B48C',\n teal: '#008080',\n thistle: '#D8BFD8',\n tomato: '#FF6347',\n turquoise: '#40E0D0',\n violet: '#EE82EE',\n wheat: '#F5DEB3',\n white: '#FFFFFF',\n whitesmoke: '#F5F5F5',\n yellow: '#FFFF00',\n yellowgreen: '#9ACD32'\n });\n return Color;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n// Based on https://stackoverflow.com/a/14991797\n// This will parse a delimited string into an array of arrays.\nfunction stringToArray(strData, delimiter) {\n if (delimiter === void 0) { delimiter = ','; }\n var data = [];\n var isNewline = function (char) { return char === '\\r' || char === '\\n'; };\n var insideQuotedField = false;\n if (strData === '') {\n return [['']];\n }\n var _loop_1 = function (row, column, position) {\n var previousChar = strData[position - 1];\n var currentChar = strData[position];\n var nextChar = strData[position + 1];\n var ensureDataExists = function () {\n if (!data[row]) {\n // create row if it doesn't exist\n data[row] = [];\n }\n if (!data[row][column]) {\n // create column if it doesn't exist\n data[row][column] = '';\n }\n };\n ensureDataExists();\n if (currentChar === '\"') {\n if (insideQuotedField) {\n if (nextChar === '\"') {\n // unescape double quote\n data[row][column] += '\"';\n position++;\n }\n else {\n // exit quoted field\n insideQuotedField = false;\n }\n return out_row_1 = row, out_column_1 = column, out_position_1 = position, \"continue\";\n }\n else if (previousChar === undefined || previousChar === delimiter || isNewline(previousChar)) {\n // enter quoted field\n insideQuotedField = true;\n return out_row_1 = row, out_column_1 = column, out_position_1 = position, \"continue\";\n }\n }\n if (!insideQuotedField) {\n if (currentChar === delimiter) {\n // move to next column\n column++;\n ensureDataExists();\n return out_row_1 = row, out_column_1 = column, out_position_1 = position, \"continue\";\n }\n else if (isNewline(currentChar)) {\n // move to next row\n column = 0;\n row++;\n ensureDataExists();\n if (currentChar === '\\r' && nextChar === '\\n') {\n // skip over second newline character if it exists\n position++;\n }\n return out_row_1 = row, out_column_1 = column, out_position_1 = position, \"continue\";\n }\n }\n // add current character to current column\n data[row][column] += currentChar;\n out_row_1 = row;\n out_column_1 = column;\n out_position_1 = position;\n };\n var out_row_1, out_column_1, out_position_1;\n // iterate over each character, keep track of current row and column (of the returned array)\n for (var row = 0, column = 0, position = 0; position < strData.length; position++) {\n _loop_1(row, column, position);\n row = out_row_1;\n column = out_column_1;\n position = out_position_1;\n }\n return data;\n}\n\nvar CsvUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n stringToArray: stringToArray\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar rtlNegativeScroll;\n/**\n * This method adds a class to an element and remove that class from all siblings.\n * Useful for toggling state.\n * @param {HTMLElement} element The element to receive the class\n * @param {string} elementClass The class to be assigned to the element\n * @param {boolean} otherElementClass The class to be assigned to siblings of the element, but not the element itself\n */\nfunction radioCssClass(element, elementClass, otherElementClass) {\n var parent = element.parentElement;\n var sibling = parent && parent.firstChild;\n while (sibling) {\n if (elementClass) {\n sibling.classList.toggle(elementClass, sibling === element);\n }\n if (otherElementClass) {\n sibling.classList.toggle(otherElementClass, sibling !== element);\n }\n sibling = sibling.nextSibling;\n }\n}\nfunction isFocusableFormField(element) {\n var matches = Element.prototype.matches || Element.prototype.msMatchesSelector;\n var isFocusable = matches.call(element, Constants.INPUT_SELECTOR);\n var isNotFocusable = matches.call(element, Constants.FOCUSABLE_EXCLUDE);\n var isElementVisible = isVisible(element);\n var focusable = isFocusable && !isNotFocusable && isElementVisible;\n return focusable;\n}\nfunction setDisplayed(element, displayed) {\n element.classList.toggle('ag-hidden', !displayed);\n}\nfunction setVisible(element, visible) {\n element.classList.toggle('ag-invisible', !visible);\n}\nfunction setDisabled(element, disabled) {\n var attributeName = 'disabled';\n var addOrRemoveDisabledAttribute = disabled ?\n function (e) { return e.setAttribute(attributeName, ''); } :\n function (e) { return e.removeAttribute(attributeName); };\n addOrRemoveDisabledAttribute(element);\n nodeListForEach(element.querySelectorAll('input'), function (input) { return addOrRemoveDisabledAttribute(input); });\n}\nfunction isElementChildOfClass(element, cls, maxNest) {\n var counter = 0;\n while (element) {\n if (element.classList.contains(cls)) {\n return true;\n }\n element = element.parentElement;\n if (typeof maxNest == 'number') {\n if (++counter > maxNest) {\n break;\n }\n }\n else if (element === maxNest) {\n break;\n }\n }\n return false;\n}\n// returns back sizes as doubles instead of strings. similar to\n// getBoundingClientRect, however getBoundingClientRect does not:\n// a) work with fractions (eg browser is zooming)\n// b) has CSS transitions applied (eg CSS scale, browser zoom), which we don't want, we want the un-transitioned values\nfunction getElementSize(el) {\n var _a = window.getComputedStyle(el), height = _a.height, width = _a.width, paddingTop = _a.paddingTop, paddingRight = _a.paddingRight, paddingBottom = _a.paddingBottom, paddingLeft = _a.paddingLeft, marginTop = _a.marginTop, marginRight = _a.marginRight, marginBottom = _a.marginBottom, marginLeft = _a.marginLeft, boxSizing = _a.boxSizing;\n return {\n height: parseFloat(height),\n width: parseFloat(width),\n paddingTop: parseFloat(paddingTop),\n paddingRight: parseFloat(paddingRight),\n paddingBottom: parseFloat(paddingBottom),\n paddingLeft: parseFloat(paddingLeft),\n marginTop: parseFloat(marginTop),\n marginRight: parseFloat(marginRight),\n marginBottom: parseFloat(marginBottom),\n marginLeft: parseFloat(marginLeft),\n boxSizing: boxSizing\n };\n}\nfunction getInnerHeight(el) {\n var size = getElementSize(el);\n if (size.boxSizing === 'border-box') {\n return size.height - size.paddingTop - size.paddingBottom;\n }\n return size.height;\n}\nfunction getInnerWidth(el) {\n var size = getElementSize(el);\n if (size.boxSizing === 'border-box') {\n return size.width - size.paddingLeft - size.paddingRight;\n }\n return size.width;\n}\nfunction getAbsoluteHeight(el) {\n var size = getElementSize(el);\n var marginRight = size.marginBottom + size.marginTop;\n return Math.ceil(el.offsetHeight + marginRight);\n}\nfunction getAbsoluteWidth(el) {\n var size = getElementSize(el);\n var marginWidth = size.marginLeft + size.marginRight;\n return Math.ceil(el.offsetWidth + marginWidth);\n}\nfunction isRtlNegativeScroll() {\n if (typeof rtlNegativeScroll === \"boolean\") {\n return rtlNegativeScroll;\n }\n var template = document.createElement('div');\n template.style.direction = 'rtl';\n template.style.width = '1px';\n template.style.height = '1px';\n template.style.position = 'fixed';\n template.style.top = '0px';\n template.style.overflow = 'hidden';\n template.dir = 'rtl';\n template.innerHTML = /* html */\n \"<div style=\\\"width: 2px\\\">\\n <span style=\\\"display: inline-block; width: 1px\\\"></span>\\n <span style=\\\"display: inline-block; width: 1px\\\"></span>\\n </div>\";\n document.body.appendChild(template);\n template.scrollLeft = 1;\n rtlNegativeScroll = Math.floor(template.scrollLeft) === 0;\n document.body.removeChild(template);\n return rtlNegativeScroll;\n}\nfunction getScrollLeft(element, rtl) {\n var scrollLeft = element.scrollLeft;\n if (rtl) {\n // Absolute value - for FF that reports RTL scrolls in negative numbers\n scrollLeft = Math.abs(scrollLeft);\n if (isBrowserChrome() && !isRtlNegativeScroll()) {\n scrollLeft = element.scrollWidth - element.clientWidth - scrollLeft;\n }\n }\n return scrollLeft;\n}\nfunction setScrollLeft(element, value, rtl) {\n if (rtl) {\n // Chrome and Safari when doing RTL have the END position of the scroll as zero, not the start\n if (isRtlNegativeScroll()) {\n value *= -1;\n }\n else if (isBrowserSafari() || isBrowserChrome()) {\n value = element.scrollWidth - element.clientWidth - value;\n }\n }\n element.scrollLeft = value;\n}\nfunction clearElement(el) {\n while (el && el.firstChild) {\n el.removeChild(el.firstChild);\n }\n}\n/** @deprecated */\nfunction removeElement(parent, cssSelector) {\n removeFromParent(parent.querySelector(cssSelector));\n}\nfunction removeFromParent(node) {\n if (node && node.parentNode) {\n node.parentNode.removeChild(node);\n }\n}\nfunction isVisible(element) {\n return element.offsetParent !== null;\n}\n/**\n * Loads the template and returns it as an element. makes up for no simple way in\n * the dom api to load html directly, eg we cannot do this: document.createElement(template)\n * @param {string} template\n * @returns {HTMLElement}\n */\nfunction loadTemplate(template) {\n var tempDiv = document.createElement('div');\n tempDiv.innerHTML = (template || '').trim();\n return tempDiv.firstChild;\n}\nfunction appendHtml(eContainer, htmlTemplate) {\n if (eContainer.lastChild) {\n // https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML\n // we put the items at the start, so new items appear underneath old items,\n // so when expanding/collapsing groups, the new rows don't go on top of the\n // rows below that are moving our of the way\n eContainer.insertAdjacentHTML('afterbegin', htmlTemplate);\n }\n else {\n eContainer.innerHTML = htmlTemplate;\n }\n}\n/** @deprecated */\nfunction getElementAttribute(element, attributeName) {\n if (element.attributes && element.attributes[attributeName]) {\n var attribute = element.attributes[attributeName];\n return attribute.value;\n }\n return null;\n}\nfunction offsetHeight(element) {\n return element && element.clientHeight ? element.clientHeight : 0;\n}\nfunction offsetWidth(element) {\n return element && element.clientWidth ? element.clientWidth : 0;\n}\nfunction ensureDomOrder(eContainer, eChild, eChildBefore) {\n // if already in right order, do nothing\n if (eChildBefore && eChildBefore.nextSibling === eChild) {\n return;\n }\n var focusedEl = document.activeElement;\n var eChildHasFocus = eChild.contains(focusedEl);\n if (eChildBefore) {\n if (eChildBefore.nextSibling) {\n // insert between the eRowBefore and the row after it\n eContainer.insertBefore(eChild, eChildBefore.nextSibling);\n }\n else {\n // if nextSibling is missing, means other row is at end, so just append new row at the end\n eContainer.appendChild(eChild);\n }\n }\n else {\n // otherwise put at start\n if (eContainer.firstChild && eContainer.firstChild !== eChild) {\n // insert it at the first location\n eContainer.insertAdjacentElement('afterbegin', eChild);\n }\n }\n if (eChildHasFocus && focusedEl && browserSupportsPreventScroll()) {\n focusedEl.focus({ preventScroll: true });\n }\n}\nfunction setDomChildOrder(eContainer, orderedChildren) {\n for (var i = 0; i < orderedChildren.length; i++) {\n var correctCellAtIndex = orderedChildren[i];\n var actualCellAtIndex = eContainer.children[i];\n if (actualCellAtIndex !== correctCellAtIndex) {\n eContainer.insertBefore(correctCellAtIndex, actualCellAtIndex);\n }\n }\n}\nfunction insertWithDomOrder(eContainer, eToInsert, eChildBefore) {\n if (eChildBefore) {\n // if previous element exists, just slot in after the previous element\n eChildBefore.insertAdjacentElement('afterend', eToInsert);\n }\n else {\n if (eContainer.firstChild) {\n // insert it at the first location\n eContainer.insertAdjacentElement('afterbegin', eToInsert);\n }\n else {\n // otherwise eContainer is empty, so just append it\n eContainer.appendChild(eToInsert);\n }\n }\n}\n/** @deprecated */\nfunction prependDC(parent, documentFragment) {\n if (exists(parent.firstChild)) {\n parent.insertBefore(documentFragment, parent.firstChild);\n }\n else {\n parent.appendChild(documentFragment);\n }\n}\nfunction addStylesToElement(eElement, styles) {\n if (!styles) {\n return;\n }\n Object.keys(styles).forEach(function (key) {\n var keyCamelCase = hyphenToCamelCase(key);\n if (keyCamelCase) {\n eElement.style[keyCamelCase] = styles[key];\n }\n });\n}\nfunction isHorizontalScrollShowing(element) {\n return element.clientWidth < element.scrollWidth;\n}\nfunction isVerticalScrollShowing(element) {\n return element.clientHeight < element.scrollHeight;\n}\nfunction setElementWidth(element, width) {\n if (width === 'flex') {\n element.style.removeProperty('width');\n element.style.removeProperty('minWidth');\n element.style.removeProperty('maxWidth');\n element.style.flex = '1 1 auto';\n }\n else {\n setFixedWidth(element, width);\n }\n}\nfunction setFixedWidth(element, width) {\n width = formatSize(width);\n element.style.width = width.toString();\n element.style.maxWidth = width.toString();\n element.style.minWidth = width.toString();\n}\nfunction setElementHeight(element, height) {\n if (height === 'flex') {\n element.style.removeProperty('height');\n element.style.removeProperty('minHeight');\n element.style.removeProperty('maxHeight');\n element.style.flex = '1 1 auto';\n }\n else {\n setFixedHeight(element, height);\n }\n}\nfunction setFixedHeight(element, height) {\n height = formatSize(height);\n element.style.height = height.toString();\n element.style.maxHeight = height.toString();\n element.style.minHeight = height.toString();\n}\nfunction formatSize(size) {\n if (typeof size === 'number') {\n return size + \"px\";\n }\n return size;\n}\n/**\n * Returns true if it is a DOM node\n * taken from: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object\n * @param {any} o\n * @return {boolean}\n */\nfunction isNode(o) {\n return (typeof Node === 'function'\n ? o instanceof Node\n : o && typeof o === 'object' && typeof o.nodeType === 'number' && typeof o.nodeName === 'string');\n}\n//\n/**\n * Returns true if it is a DOM element\n * taken from: http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object\n * @param {any} o\n * @returns {boolean}\n */\nfunction isElement(o) {\n return (typeof HTMLElement === 'function'\n ? o instanceof HTMLElement //DOM2\n : o && isNonNullObject(o) && o.nodeType === 1 && typeof o.nodeName === 'string');\n}\nfunction isNodeOrElement(o) {\n return isNode(o) || isElement(o);\n}\n/**\n * Makes a copy of a node list into a list\n * @param {NodeList} nodeList\n * @returns {Node[]}\n */\nfunction copyNodeList(nodeList) {\n if (nodeList == null) {\n return [];\n }\n var result = [];\n nodeListForEach(nodeList, function (node) { return result.push(node); });\n return result;\n}\nfunction iterateNamedNodeMap(map, callback) {\n if (!map) {\n return;\n }\n for (var i = 0; i < map.length; i++) {\n var attr = map[i];\n callback(attr.name, attr.value);\n }\n}\n/** @deprecated */\nfunction setCheckboxState(eCheckbox, state) {\n if (typeof state === 'boolean') {\n eCheckbox.checked = state;\n eCheckbox.indeterminate = false;\n }\n else {\n // isNodeSelected returns back undefined if it's a group and the children\n // are a mix of selected and unselected\n eCheckbox.indeterminate = true;\n }\n}\nfunction addOrRemoveAttribute(element, name, value) {\n if (value == null) {\n element.removeAttribute(name);\n }\n else {\n element.setAttribute(name, value.toString());\n }\n}\nfunction nodeListForEach(nodeList, action) {\n if (nodeList == null) {\n return;\n }\n for (var i = 0; i < nodeList.length; i++) {\n action(nodeList[i]);\n }\n}\n\nvar DomUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n radioCssClass: radioCssClass,\n isFocusableFormField: isFocusableFormField,\n setDisplayed: setDisplayed,\n setVisible: setVisible,\n setDisabled: setDisabled,\n isElementChildOfClass: isElementChildOfClass,\n getElementSize: getElementSize,\n getInnerHeight: getInnerHeight,\n getInnerWidth: getInnerWidth,\n getAbsoluteHeight: getAbsoluteHeight,\n getAbsoluteWidth: getAbsoluteWidth,\n isRtlNegativeScroll: isRtlNegativeScroll,\n getScrollLeft: getScrollLeft,\n setScrollLeft: setScrollLeft,\n clearElement: clearElement,\n removeElement: removeElement,\n removeFromParent: removeFromParent,\n isVisible: isVisible,\n loadTemplate: loadTemplate,\n appendHtml: appendHtml,\n getElementAttribute: getElementAttribute,\n offsetHeight: offsetHeight,\n offsetWidth: offsetWidth,\n ensureDomOrder: ensureDomOrder,\n setDomChildOrder: setDomChildOrder,\n insertWithDomOrder: insertWithDomOrder,\n prependDC: prependDC,\n addStylesToElement: addStylesToElement,\n isHorizontalScrollShowing: isHorizontalScrollShowing,\n isVerticalScrollShowing: isVerticalScrollShowing,\n setElementWidth: setElementWidth,\n setFixedWidth: setFixedWidth,\n setElementHeight: setElementHeight,\n setFixedHeight: setFixedHeight,\n formatSize: formatSize,\n isNode: isNode,\n isElement: isElement,\n isNodeOrElement: isNodeOrElement,\n copyNodeList: copyNodeList,\n iterateNamedNodeMap: iterateNamedNodeMap,\n setCheckboxState: setCheckboxState,\n addOrRemoveAttribute: addOrRemoveAttribute,\n nodeListForEach: nodeListForEach\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/** @deprecated */\nfunction getNameOfClass(theClass) {\n var funcNameRegex = /function (.{1,})\\(/;\n var funcAsString = theClass.toString();\n var results = funcNameRegex.exec(funcAsString);\n return results && results.length > 1 ? results[1] : \"\";\n}\nfunction findLineByLeastSquares(values) {\n var len = values.length;\n var maxDecimals = 0;\n if (len <= 1) {\n return values;\n }\n for (var i = 0; i < values.length; i++) {\n var value = values[i];\n var splitExponent = value.toString().split('e-');\n if (splitExponent.length > 1) {\n maxDecimals = Math.max(maxDecimals, parseInt(splitExponent[1], 10));\n continue;\n }\n if (Math.floor(value) === value) {\n continue;\n }\n maxDecimals = Math.max(maxDecimals, value.toString().split('.')[1].length);\n }\n var sum_x = 0;\n var sum_y = 0;\n var sum_xy = 0;\n var sum_xx = 0;\n var y = 0;\n for (var x = 0; x < len; x++) {\n y = values[x];\n sum_x += x;\n sum_y += y;\n sum_xx += x * x;\n sum_xy += x * y;\n }\n var m = (len * sum_xy - sum_x * sum_y) / (len * sum_xx - sum_x * sum_x);\n var b = (sum_y / len) - (m * sum_x) / len;\n var result = [];\n for (var x = 0; x <= len; x++) {\n result.push(parseFloat((x * m + b).toFixed(maxDecimals)));\n }\n return result;\n}\n/**\n * Converts a CSS object into string\n * @param {Object} stylesToUse an object eg: {color: 'black', top: '25px'}\n * @return {string} A string like \"color: black; top: 25px;\" for html\n */\nfunction cssStyleObjectToMarkup(stylesToUse) {\n if (!stylesToUse) {\n return '';\n }\n var resParts = [];\n iterateObject(stylesToUse, function (styleKey, styleValue) {\n var styleKeyDashed = camelCaseToHyphen(styleKey);\n resParts.push(styleKeyDashed + \": \" + styleValue + \";\");\n });\n return resParts.join(' ');\n}\n/**\n * Displays a message to the browser. this is useful in iPad, where you can't easily see the console.\n * so the javascript code can use this to give feedback. this is NOT intended to be called in production.\n * it is intended the AG Grid developer calls this to troubleshoot, but then takes out the calls before\n * checking in.\n * @param {string} msg\n */\nfunction message(msg) {\n var eMessage = document.createElement('div');\n var eBox = document.querySelector('#__ag__message');\n eMessage.innerHTML = msg;\n if (!eBox) {\n var template = \"<div id=\\\"__ag__message\\\" style=\\\"display: inline-block; position: absolute; top: 0px; left: 0px; color: white; background-color: black; z-index: 20; padding: 2px; border: 1px solid darkred; height: 200px; overflow-y: auto;\\\"></div>\";\n eBox = loadTemplate(template);\n if (document.body) {\n document.body.appendChild(eBox);\n }\n }\n eBox.insertBefore(eMessage, eBox.children[0]);\n}\n/**\n * cell renderers are used in a few places. they bind to dom slightly differently to other cell renderes as they\n * can return back strings (instead of html elemnt) in the getGui() method. common code placed here to handle that.\n * @param {AgPromise<ICellRendererComp>} cellRendererPromise\n * @param {HTMLElement} eTarget\n */\nfunction bindCellRendererToHtmlElement(cellRendererPromise, eTarget) {\n cellRendererPromise.then(function (cellRenderer) {\n var gui = cellRenderer.getGui();\n if (gui != null) {\n if (typeof gui === 'object') {\n eTarget.appendChild(gui);\n }\n else {\n eTarget.innerHTML = gui;\n }\n }\n });\n}\n\nvar GeneralUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n getNameOfClass: getNameOfClass,\n findLineByLeastSquares: findLineByLeastSquares,\n cssStyleObjectToMarkup: cssStyleObjectToMarkup,\n message: message,\n bindCellRendererToHtmlElement: bindCellRendererToHtmlElement\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n// ARIA HELPER FUNCTIONS\nfunction setAriaAttribute(element, attribute, value) {\n element.setAttribute(ariaAttributeName(attribute), value.toString());\n}\nfunction removeAriaAttribute(element, attribute) {\n element.removeAttribute(ariaAttributeName(attribute));\n}\nfunction ariaAttributeName(attribute) {\n return \"aria-\" + attribute;\n}\nfunction setAriaRole(element, role) {\n if (role) {\n element.setAttribute('role', role);\n }\n else {\n element.removeAttribute('role');\n }\n}\nfunction getAriaSortState(column) {\n var sort;\n if (column.isSortAscending()) {\n sort = 'ascending';\n }\n else if (column.isSortDescending()) {\n sort = 'descending';\n }\n else {\n sort = 'none';\n }\n return sort;\n}\n// ARIA ATTRIBUTE GETTERS\nfunction getAriaLevel(element) {\n return parseInt(element.getAttribute('aria-level'), 10);\n}\nfunction getAriaPosInSet(element) {\n return parseInt(element.getAttribute('aria-posinset'), 10);\n}\nfunction getAriaDescribedBy(element) {\n return element.getAttribute('aria-describedby') || '';\n}\n// ARIA ATTRIBUTE SETTERS\nfunction setAriaLabel(element, label) {\n var key = 'label';\n if (label) {\n setAriaAttribute(element, key, label);\n }\n else {\n removeAriaAttribute(element, key);\n }\n}\nfunction setAriaLabelledBy(element, labelledBy) {\n var key = 'labelledby';\n if (labelledBy) {\n setAriaAttribute(element, key, labelledBy);\n }\n else {\n removeAriaAttribute(element, key);\n }\n}\nfunction setAriaDescription(element, description) {\n var key = 'description';\n if (description) {\n setAriaAttribute(element, key, description);\n }\n else {\n removeAriaAttribute(element, key);\n }\n}\nfunction setAriaDescribedBy(element, describedby) {\n var key = 'describedby';\n if (describedby) {\n setAriaAttribute(element, key, describedby);\n }\n else {\n removeAriaAttribute(element, key);\n }\n}\nfunction setAriaLevel(element, level) {\n setAriaAttribute(element, 'level', level);\n}\nfunction setAriaDisabled(element, disabled) {\n setAriaAttribute(element, 'disabled', disabled);\n}\nfunction setAriaExpanded(element, expanded) {\n setAriaAttribute(element, 'expanded', expanded);\n}\nfunction removeAriaExpanded(element) {\n removeAriaAttribute(element, 'expanded');\n}\nfunction setAriaSetSize(element, setsize) {\n setAriaAttribute(element, 'setsize', setsize);\n}\nfunction setAriaPosInSet(element, position) {\n setAriaAttribute(element, 'posinset', position);\n}\nfunction setAriaMultiSelectable(element, multiSelectable) {\n setAriaAttribute(element, 'multiselectable', multiSelectable);\n}\nfunction setAriaRowCount(element, rowCount) {\n setAriaAttribute(element, 'rowcount', rowCount);\n}\nfunction setAriaRowIndex(element, rowIndex) {\n setAriaAttribute(element, 'rowindex', rowIndex);\n}\nfunction setAriaColCount(element, colCount) {\n setAriaAttribute(element, 'colcount', colCount);\n}\nfunction setAriaColIndex(element, colIndex) {\n setAriaAttribute(element, 'colindex', colIndex);\n}\nfunction setAriaColSpan(element, colSpan) {\n setAriaAttribute(element, 'colspan', colSpan);\n}\nfunction setAriaSort(element, sort) {\n setAriaAttribute(element, 'sort', sort);\n}\nfunction removeAriaSort(element) {\n removeAriaAttribute(element, 'sort');\n}\nfunction setAriaSelected(element, selected) {\n var attributeName = 'selected';\n if (selected) {\n setAriaAttribute(element, attributeName, selected);\n }\n else {\n removeAriaAttribute(element, attributeName);\n }\n}\nfunction setAriaChecked(element, checked) {\n setAriaAttribute(element, 'checked', checked === undefined ? 'mixed' : checked);\n}\n\nvar AriaUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n setAriaRole: setAriaRole,\n getAriaSortState: getAriaSortState,\n getAriaLevel: getAriaLevel,\n getAriaPosInSet: getAriaPosInSet,\n getAriaDescribedBy: getAriaDescribedBy,\n setAriaLabel: setAriaLabel,\n setAriaLabelledBy: setAriaLabelledBy,\n setAriaDescription: setAriaDescription,\n setAriaDescribedBy: setAriaDescribedBy,\n setAriaLevel: setAriaLevel,\n setAriaDisabled: setAriaDisabled,\n setAriaExpanded: setAriaExpanded,\n removeAriaExpanded: removeAriaExpanded,\n setAriaSetSize: setAriaSetSize,\n setAriaPosInSet: setAriaPosInSet,\n setAriaMultiSelectable: setAriaMultiSelectable,\n setAriaRowCount: setAriaRowCount,\n setAriaRowIndex: setAriaRowIndex,\n setAriaColCount: setAriaColCount,\n setAriaColIndex: setAriaColIndex,\n setAriaColSpan: setAriaColSpan,\n setAriaSort: setAriaSort,\n removeAriaSort: removeAriaSort,\n setAriaSelected: setAriaSelected,\n setAriaChecked: setAriaChecked\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __read$j = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\n/**\n * Serialises a Date to a string of format `yyyy-MM-dd HH:mm:ss`.\n * An alternative separator can be provided to be used instead of hyphens.\n * @param date The date to serialise\n * @param includeTime Whether to include the time in the serialised string\n * @param separator The separator to use between date parts\n */\nfunction serialiseDate(date, includeTime, separator) {\n if (includeTime === void 0) { includeTime = true; }\n if (separator === void 0) { separator = '-'; }\n if (!date) {\n return null;\n }\n var serialised = [date.getFullYear(), date.getMonth() + 1, date.getDate()].map(function (part) { return padStartWidthZeros(part, 2); }).join(separator);\n if (includeTime) {\n serialised += ' ' + [date.getHours(), date.getMinutes(), date.getSeconds()].map(function (part) { return padStartWidthZeros(part, 2); }).join(':');\n }\n return serialised;\n}\nvar calculateOrdinal = function (value) {\n if (value > 3 && value < 21) {\n return 'th';\n }\n var remainder = value % 10;\n switch (remainder) {\n case 1: return \"st\";\n case 2: return \"nd\";\n case 3: return \"rd\";\n }\n return 'th';\n};\n/**\n * Serialises a Date to a string of format the defined format, does not include time.\n * @param date The date to serialise\n * @param format The string to format the date to, defaults to YYYY-MM-DD\n */\nfunction dateToFormattedString(date, format) {\n if (format === void 0) { format = 'YYYY-MM-DD'; }\n var fullYear = padStartWidthZeros(date.getFullYear(), 4);\n var months = [\n 'January', 'February', 'March', 'April', 'May', 'June',\n 'July', 'August', 'September', 'October', 'November', 'December',\n ];\n var days = [\n 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',\n ];\n var replace = {\n YYYY: function () { return fullYear.slice(fullYear.length - 4, fullYear.length); },\n YY: function () { return fullYear.slice(fullYear.length - 2, fullYear.length); },\n Y: function () { return \"\" + date.getFullYear(); },\n MMMM: function () { return months[date.getMonth()]; },\n MMM: function () { return months[date.getMonth()].slice(0, 3); },\n MM: function () { return padStartWidthZeros(date.getMonth() + 1, 2); },\n Mo: function () { return \"\" + (date.getMonth() + 1) + calculateOrdinal(date.getMonth() + 1); },\n M: function () { return \"\" + (date.getMonth() + 1); },\n Do: function () { return \"\" + date.getDate() + calculateOrdinal(date.getDate()); },\n DD: function () { return padStartWidthZeros(date.getDate(), 2); },\n D: function () { return \"\" + date.getDate(); },\n dddd: function () { return days[date.getDay()]; },\n ddd: function () { return days[date.getDay()].slice(0, 3); },\n dd: function () { return days[date.getDay()].slice(0, 2); },\n do: function () { return \"\" + date.getDay() + calculateOrdinal(date.getDay()); },\n d: function () { return \"\" + date.getDay(); },\n };\n var regexp = new RegExp(Object.keys(replace).join('|'), 'g');\n return format.replace(regexp, function (match) {\n if (match in replace) {\n return replace[match]();\n }\n return match;\n });\n}\n/**\n * Parses a date and time from a string in the format `yyyy-MM-dd HH:mm:ss`\n */\nfunction parseDateTimeFromString(value) {\n if (!value) {\n return null;\n }\n var _a = __read$j(value.split(' '), 2), dateStr = _a[0], timeStr = _a[1];\n if (!dateStr) {\n return null;\n }\n var fields = dateStr.split('-').map(function (f) { return parseInt(f, 10); });\n if (fields.filter(function (f) { return !isNaN(f); }).length !== 3) {\n return null;\n }\n var _b = __read$j(fields, 3), year = _b[0], month = _b[1], day = _b[2];\n var date = new Date(year, month - 1, day);\n if (date.getFullYear() !== year ||\n date.getMonth() !== month - 1 ||\n date.getDate() !== day) {\n // date was not parsed as expected so must have been invalid\n return null;\n }\n if (!timeStr || timeStr === '00:00:00') {\n return date;\n }\n var _c = __read$j(timeStr.split(':').map(function (part) { return parseInt(part, 10); }), 3), hours = _c[0], minutes = _c[1], seconds = _c[2];\n if (hours >= 0 && hours < 24) {\n date.setHours(hours);\n }\n if (minutes >= 0 && minutes < 60) {\n date.setMinutes(minutes);\n }\n if (seconds >= 0 && seconds < 60) {\n date.setSeconds(seconds);\n }\n return date;\n}\n\nvar DateUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n serialiseDate: serialiseDate,\n dateToFormattedString: dateToFormattedString,\n parseDateTimeFromString: parseDateTimeFromString\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n//\n// IMPORTANT NOTE!\n//\n// If you change the list below, copy/paste the new content into the docs page javascript-grid-icons\n//\nvar iconNameClassMap = {\n // header column group shown when expanded (click to contract)\n columnGroupOpened: 'expanded',\n // header column group shown when contracted (click to expand)\n columnGroupClosed: 'contracted',\n // tool panel column group contracted (click to expand)\n columnSelectClosed: 'tree-closed',\n // tool panel column group expanded (click to contract)\n columnSelectOpen: 'tree-open',\n // column tool panel header expand/collapse all button, shown when some children are expanded and\n // others are collapsed\n columnSelectIndeterminate: 'tree-indeterminate',\n // shown on ghost icon while dragging column to the side of the grid to pin\n columnMovePin: 'pin',\n // shown on ghost icon while dragging over part of the page that is not a drop zone\n columnMoveHide: 'eye-slash',\n // shown on ghost icon while dragging columns to reorder\n columnMoveMove: 'arrows',\n // animating icon shown when dragging a column to the right of the grid causes horizontal scrolling\n columnMoveLeft: 'left',\n // animating icon shown when dragging a column to the left of the grid causes horizontal scrolling\n columnMoveRight: 'right',\n // shown on ghost icon while dragging over Row Groups drop zone\n columnMoveGroup: 'group',\n // shown on ghost icon while dragging over Values drop zone\n columnMoveValue: 'aggregation',\n // shown on ghost icon while dragging over pivot drop zone\n columnMovePivot: 'pivot',\n // shown on ghost icon while dragging over drop zone that doesn't support it, e.g.\n // string column over aggregation drop zone\n dropNotAllowed: 'not-allowed',\n // shown on row group when contracted (click to expand)\n groupContracted: 'tree-closed',\n // shown on row group when expanded (click to contract)\n groupExpanded: 'tree-open',\n // context menu chart item\n chart: 'chart',\n // chart window title bar\n close: 'cross',\n // X (remove) on column 'pill' after adding it to a drop zone list\n cancel: 'cancel',\n // indicates the currently active pin state in the \"Pin column\" sub-menu of the column menu\n check: 'tick',\n // \"go to first\" button in pagination controls\n first: 'first',\n // \"go to previous\" button in pagination controls\n previous: 'previous',\n // \"go to next\" button in pagination controls\n next: 'next',\n // \"go to last\" button in pagination controls\n last: 'last',\n // shown on top right of chart when chart is linked to range data (click to unlink)\n linked: 'linked',\n // shown on top right of chart when chart is not linked to range data (click to link)\n unlinked: 'unlinked',\n // \"Choose colour\" button on chart settings tab\n colorPicker: 'color-picker',\n // rotating spinner shown by the loading cell renderer\n groupLoading: 'loading',\n // button to launch enterprise column menu\n menu: 'menu',\n // filter tool panel tab\n filter: 'filter',\n // column tool panel tab\n columns: 'columns',\n // button in chart regular size window title bar (click to maximise)\n maximize: 'maximize',\n // button in chart maximised window title bar (click to make regular size)\n minimize: 'minimize',\n // \"Pin column\" item in column header menu\n menuPin: 'pin',\n // \"Value aggregation\" column menu item (shown on numeric columns when grouping is active)\"\n menuValue: 'aggregation',\n // \"Group by {column-name}\" item in column header menu\n menuAddRowGroup: 'group',\n // \"Un-Group by {column-name}\" item in column header menu\n menuRemoveRowGroup: 'group',\n // context menu copy item\n clipboardCopy: 'copy',\n // context menu paste item\n clipboardPaste: 'paste',\n // identifies the pivot drop zone\n pivotPanel: 'pivot',\n // \"Row groups\" drop zone in column tool panel\n rowGroupPanel: 'group',\n // columns tool panel Values drop zone\n valuePanel: 'aggregation',\n // drag handle used to pick up draggable columns\n columnDrag: 'grip',\n // drag handle used to pick up draggable rows\n rowDrag: 'grip',\n // context menu export item\n save: 'save',\n // csv export\n csvExport: 'csv',\n // excel export,\n excelExport: 'excel',\n // icon on dropdown editors\n smallDown: 'small-down',\n // version of small-right used in RTL mode\n smallLeft: 'small-left',\n // separater between column 'pills' when you add multiple columns to the header drop zone\n smallRight: 'small-right',\n smallUp: 'small-up',\n // show on column header when column is sorted ascending\n sortAscending: 'asc',\n // show on column header when column is sorted descending\n sortDescending: 'desc',\n // show on column header when column has no sort, only when enabled with gridOptions.unSortIcon=true\n sortUnSort: 'none'\n};\n/**\n * If icon provided, use this (either a string, or a function callback).\n * if not, then use the default icon from the theme\n * @param {string} iconName\n * @param {GridOptionsWrapper} gridOptionsWrapper\n * @param {Column | null} [column]\n * @returns {HTMLElement}\n */\nfunction createIcon(iconName, gridOptionsWrapper, column) {\n var iconContents = createIconNoSpan(iconName, gridOptionsWrapper, column);\n if (iconContents && iconContents.className.indexOf('ag-icon') > -1) {\n return iconContents;\n }\n var eResult = document.createElement('span');\n eResult.appendChild(iconContents);\n return eResult;\n}\nfunction createIconNoSpan(iconName, gridOptionsWrapper, column, forceCreate) {\n var userProvidedIcon = null;\n // check col for icon first\n var icons = column && column.getColDef().icons;\n if (icons) {\n userProvidedIcon = icons[iconName];\n }\n // if not in col, try grid options\n if (gridOptionsWrapper && !userProvidedIcon) {\n var optionsIcons = gridOptionsWrapper.getIcons();\n if (optionsIcons) {\n userProvidedIcon = optionsIcons[iconName];\n }\n }\n // now if user provided, use it\n if (userProvidedIcon) {\n var rendererResult = void 0;\n if (typeof userProvidedIcon === 'function') {\n rendererResult = userProvidedIcon();\n }\n else if (typeof userProvidedIcon === 'string') {\n rendererResult = userProvidedIcon;\n }\n else {\n throw new Error('icon from grid options needs to be a string or a function');\n }\n if (typeof rendererResult === 'string') {\n return loadTemplate(rendererResult);\n }\n if (isNodeOrElement(rendererResult)) {\n return rendererResult;\n }\n console.warn('AG Grid: iconRenderer should return back a string or a dom object');\n }\n else {\n var span = document.createElement('span');\n var cssClass = iconNameClassMap[iconName];\n if (!cssClass) {\n if (!forceCreate) {\n console.warn(\"AG Grid: Did not find icon \" + iconName);\n cssClass = '';\n }\n else {\n cssClass = iconName;\n }\n }\n span.setAttribute('class', \"ag-icon ag-icon-\" + cssClass);\n span.setAttribute('unselectable', 'on');\n setAriaRole(span, 'presentation');\n return span;\n }\n}\n\nvar IconUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n iconNameClassMap: iconNameClassMap,\n createIcon: createIcon,\n createIconNoSpan: createIconNoSpan\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar KeyCode = /** @class */ (function () {\n function KeyCode() {\n }\n KeyCode.BACKSPACE = 'Backspace';\n KeyCode.TAB = 'Tab';\n KeyCode.ENTER = 'Enter';\n KeyCode.ESCAPE = 'Escape';\n KeyCode.SPACE = ' ';\n KeyCode.LEFT = 'ArrowLeft';\n KeyCode.UP = 'ArrowUp';\n KeyCode.RIGHT = 'ArrowRight';\n KeyCode.DOWN = 'ArrowDown';\n KeyCode.DELETE = 'Delete';\n KeyCode.F2 = 'F2';\n KeyCode.PAGE_UP = 'PageUp';\n KeyCode.PAGE_DOWN = 'PageDown';\n KeyCode.PAGE_HOME = 'Home';\n KeyCode.PAGE_END = 'End';\n // these should be used with `event.code` instead of `event.key`\n // as `event.key` changes when non-latin keyboards are used\n KeyCode.A = 'KeyA';\n KeyCode.C = 'KeyC';\n KeyCode.V = 'KeyV';\n KeyCode.D = 'KeyD';\n KeyCode.Z = 'KeyZ';\n KeyCode.Y = 'KeyY';\n return KeyCode;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar NUMPAD_DEL_NUMLOCK_ON_KEY = 'Del';\n// Using legacy values to match AZERTY keyboards\nvar NUMPAD_DEL_NUMLOCK_ON_KEYCODE = 46;\nvar A_KEYCODE = 65;\nvar C_KEYCODE = 67;\nvar V_KEYCODE = 86;\nvar D_KEYCODE = 68;\nvar Z_KEYCODE = 90;\nvar Y_KEYCODE = 89;\nfunction isEventFromPrintableCharacter(event) {\n // no allowed printable chars have alt or ctrl key combinations\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return false;\n }\n // if key is length 1, eg if it is 'a' for the a key, or '2' for the '2' key.\n // non-printable characters have names, eg 'Enter' or 'Backspace'.\n var printableCharacter = event.key.length === 1;\n // IE11 & Edge treat the numpad del key differently - with numlock on we get \"Del\" for key,\n // so this addition checks if its IE11/Edge and handles that specific case the same was as all other browsers\n var numpadDelWithNumlockOnForEdgeOrIe = isNumpadDelWithNumLockOnForEdge(event);\n return printableCharacter || numpadDelWithNumlockOnForEdgeOrIe;\n}\n/**\n * Allows user to tell the grid to skip specific keyboard events\n * @param {GridOptionsWrapper} gridOptionsWrapper\n * @param {KeyboardEvent} keyboardEvent\n * @param {RowNode} rowNode\n * @param {Column} column\n * @param {boolean} editing\n * @returns {boolean}\n */\nfunction isUserSuppressingKeyboardEvent(gridOptionsWrapper, keyboardEvent, rowNode, column, editing) {\n var gridOptionsFunc = gridOptionsWrapper.getSuppressKeyboardEventFunc();\n var colDefFunc = column ? column.getColDef().suppressKeyboardEvent : undefined;\n // if no callbacks provided by user, then do nothing\n if (!gridOptionsFunc && !colDefFunc) {\n return false;\n }\n var params = {\n event: keyboardEvent,\n editing: editing,\n column: column,\n api: gridOptionsWrapper.getApi(),\n node: rowNode,\n data: rowNode.data,\n colDef: column.getColDef(),\n context: gridOptionsWrapper.getContext(),\n columnApi: gridOptionsWrapper.getColumnApi()\n };\n // colDef get first preference on suppressing events\n if (colDefFunc) {\n var colDefFuncResult = colDefFunc(params);\n // if colDef func suppressed, then return now, no need to call gridOption func\n if (colDefFuncResult) {\n return true;\n }\n }\n if (gridOptionsFunc) {\n // if gridOption func, return the result\n return gridOptionsFunc(params);\n }\n // otherwise return false, don't suppress, as colDef didn't suppress and no func on gridOptions\n return false;\n}\nfunction isUserSuppressingHeaderKeyboardEvent(gridOptionsWrapper, keyboardEvent, headerRowIndex, column) {\n var colDef = column.getDefinition();\n var colDefFunc = colDef && colDef.suppressHeaderKeyboardEvent;\n if (!exists(colDefFunc)) {\n return false;\n }\n var params = {\n api: gridOptionsWrapper.getApi(),\n columnApi: gridOptionsWrapper.getColumnApi(),\n context: gridOptionsWrapper.getContext(),\n colDef: colDef,\n column: column,\n headerRowIndex: headerRowIndex,\n event: keyboardEvent\n };\n return !!colDefFunc(params);\n}\nfunction isNumpadDelWithNumLockOnForEdge(event) {\n return (isBrowserEdge()) &&\n event.key === NUMPAD_DEL_NUMLOCK_ON_KEY &&\n event.charCode === NUMPAD_DEL_NUMLOCK_ON_KEYCODE;\n}\nfunction normaliseQwertyAzerty(keyboardEvent) {\n var keyCode = keyboardEvent.keyCode;\n var code;\n switch (keyCode) {\n case A_KEYCODE:\n code = KeyCode.A;\n break;\n case C_KEYCODE:\n code = KeyCode.C;\n break;\n case V_KEYCODE:\n code = KeyCode.V;\n break;\n case D_KEYCODE:\n code = KeyCode.D;\n break;\n case Z_KEYCODE:\n code = KeyCode.Z;\n break;\n case Y_KEYCODE:\n code = KeyCode.Y;\n break;\n default:\n code = keyboardEvent.code;\n }\n return code;\n}\nfunction isDeleteKey(key, alwaysReturnFalseOnBackspace) {\n if (alwaysReturnFalseOnBackspace === void 0) { alwaysReturnFalseOnBackspace = false; }\n if (key === KeyCode.DELETE) {\n return true;\n }\n if (!alwaysReturnFalseOnBackspace && key === KeyCode.BACKSPACE) {\n return isMacOsUserAgent();\n }\n return false;\n}\n\nvar KeyboardUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n isEventFromPrintableCharacter: isEventFromPrintableCharacter,\n isUserSuppressingKeyboardEvent: isUserSuppressingKeyboardEvent,\n isUserSuppressingHeaderKeyboardEvent: isUserSuppressingHeaderKeyboardEvent,\n normaliseQwertyAzerty: normaliseQwertyAzerty,\n isDeleteKey: isDeleteKey\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/**\n * `True` if the event is close to the original event by X pixels either vertically or horizontally.\n * we only start dragging after X pixels so this allows us to know if we should start dragging yet.\n * @param {MouseEvent | TouchEvent} e1\n * @param {MouseEvent | TouchEvent} e2\n * @param {number} pixelCount\n * @returns {boolean}\n */\nfunction areEventsNear(e1, e2, pixelCount) {\n // by default, we wait 4 pixels before starting the drag\n if (pixelCount === 0) {\n return false;\n }\n var diffX = Math.abs(e1.clientX - e2.clientX);\n var diffY = Math.abs(e1.clientY - e2.clientY);\n return Math.max(diffX, diffY) <= pixelCount;\n}\n\nvar MouseUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n areEventsNear: areEventsNear\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/**\n * Gets called by: a) ClientSideNodeManager and b) GroupStage to do sorting.\n * when in ClientSideNodeManager we always have indexes (as this sorts the items the\n * user provided) but when in GroupStage, the nodes can contain filler nodes that\n * don't have order id's\n * @param {RowNode[]} rowNodes\n * @param {Object} rowNodeOrder\n *\n * @returns a boolean representing whether nodes were reordered\n */\nfunction sortRowNodesByOrder(rowNodes, rowNodeOrder) {\n if (!rowNodes) {\n return false;\n }\n var comparator = function (nodeA, nodeB) {\n var positionA = rowNodeOrder[nodeA.id];\n var positionB = rowNodeOrder[nodeB.id];\n var aHasIndex = positionA !== undefined;\n var bHasIndex = positionB !== undefined;\n var bothNodesAreUserNodes = aHasIndex && bHasIndex;\n var bothNodesAreFillerNodes = !aHasIndex && !bHasIndex;\n if (bothNodesAreUserNodes) {\n // when comparing two nodes the user has provided, they always\n // have indexes\n return positionA - positionB;\n }\n if (bothNodesAreFillerNodes) {\n // when comparing two filler nodes, we have no index to compare them\n // against, however we want this sorting to be deterministic, so that\n // the rows don't jump around as the user does delta updates. so we\n // want the same sort result. so we use the __objectId - which doesn't make sense\n // from a sorting point of view, but does give consistent behaviour between\n // calls. otherwise groups jump around as delta updates are done.\n // note: previously here we used nodeId, however this gave a strange order\n // as string ordering of numbers is wrong, so using id based on creation order\n // as least gives better looking order.\n return nodeA.__objectId - nodeB.__objectId;\n }\n if (aHasIndex) {\n return 1;\n }\n return -1;\n };\n // check if the list first needs sorting\n var rowNodeA;\n var rowNodeB;\n var atLeastOneOutOfOrder = false;\n for (var i = 0; i < rowNodes.length - 1; i++) {\n rowNodeA = rowNodes[i];\n rowNodeB = rowNodes[i + 1];\n if (comparator(rowNodeA, rowNodeB) > 0) {\n atLeastOneOutOfOrder = true;\n break;\n }\n }\n if (atLeastOneOutOfOrder) {\n rowNodes.sort(comparator);\n return true;\n }\n return false;\n}\nfunction traverseNodesWithKey(nodes, callback) {\n var keyParts = [];\n recursiveSearchNodes(nodes);\n function recursiveSearchNodes(currentNodes) {\n if (!currentNodes) {\n return;\n }\n currentNodes.forEach(function (node) {\n // also checking for children for tree data\n if (node.group || node.hasChildren()) {\n keyParts.push(node.key);\n var key = keyParts.join('|');\n callback(node, key);\n recursiveSearchNodes(node.childrenAfterGroup);\n keyParts.pop();\n }\n });\n }\n}\n\nvar RowNodeUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n sortRowNodesByOrder: sortRowNodesByOrder,\n traverseNodesWithKey: traverseNodesWithKey\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction convertToSet(list) {\n var set = new Set();\n list.forEach(function (x) { return set.add(x); });\n return set;\n}\n\nvar SetUtils = /*#__PURE__*/Object.freeze({\n __proto__: null,\n convertToSet: convertToSet\n});\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __assign$f = (undefined && undefined.__assign) || function () {\n __assign$f = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$f.apply(this, arguments);\n};\nvar utils = __assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f(__assign$f({}, GeneralUtils), AriaUtils), ArrayUtils), BrowserUtils), CsvUtils), DateUtils), DomUtils), EventUtils), FunctionUtils), FuzzyMatchUtils), GenericUtils), IconUtils), KeyboardUtils), MapUtils), MouseUtils), NumberUtils), ObjectUtils), RowNodeUtils), SetUtils), StringUtils);\nvar _ = utils;\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar NumberSequence = /** @class */ (function () {\n function NumberSequence(initValue, step) {\n if (initValue === void 0) { initValue = 0; }\n if (step === void 0) { step = 1; }\n this.nextValue = initValue;\n this.step = step;\n }\n NumberSequence.prototype.next = function () {\n var valToReturn = this.nextValue;\n this.nextValue += this.step;\n return valToReturn;\n };\n NumberSequence.prototype.peek = function () {\n return this.nextValue;\n };\n NumberSequence.prototype.skip = function (count) {\n this.nextValue += count;\n };\n return NumberSequence;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar AgPromiseStatus;\n(function (AgPromiseStatus) {\n AgPromiseStatus[AgPromiseStatus[\"IN_PROGRESS\"] = 0] = \"IN_PROGRESS\";\n AgPromiseStatus[AgPromiseStatus[\"RESOLVED\"] = 1] = \"RESOLVED\";\n})(AgPromiseStatus || (AgPromiseStatus = {}));\nvar AgPromise = /** @class */ (function () {\n function AgPromise(callback) {\n var _this = this;\n this.status = AgPromiseStatus.IN_PROGRESS;\n this.resolution = null;\n this.waiters = [];\n callback(function (value) { return _this.onDone(value); }, function (params) { return _this.onReject(params); });\n }\n AgPromise.all = function (promises) {\n return new AgPromise(function (resolve) {\n var remainingToResolve = promises.length;\n var combinedValues = new Array(remainingToResolve);\n promises.forEach(function (promise, index) {\n promise.then(function (value) {\n combinedValues[index] = value;\n remainingToResolve--;\n if (remainingToResolve === 0) {\n resolve(combinedValues);\n }\n });\n });\n });\n };\n AgPromise.resolve = function (value) {\n if (value === void 0) { value = null; }\n return new AgPromise(function (resolve) { return resolve(value); });\n };\n AgPromise.prototype.then = function (func) {\n var _this = this;\n return new AgPromise(function (resolve) {\n if (_this.status === AgPromiseStatus.RESOLVED) {\n resolve(func(_this.resolution));\n }\n else {\n _this.waiters.push(function (value) { return resolve(func(value)); });\n }\n });\n };\n AgPromise.prototype.resolveNow = function (ifNotResolvedValue, ifResolved) {\n return this.status === AgPromiseStatus.RESOLVED ? ifResolved(this.resolution) : ifNotResolvedValue;\n };\n AgPromise.prototype.onDone = function (value) {\n this.status = AgPromiseStatus.RESOLVED;\n this.resolution = value;\n this.waiters.forEach(function (waiter) { return waiter(value); });\n };\n AgPromise.prototype.onReject = function (params) {\n console.warn('TBI');\n };\n return AgPromise;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/**\n * A Util Class only used when debugging for printing time to console\n */\nvar Timer = /** @class */ (function () {\n function Timer() {\n this.timestamp = new Date().getTime();\n }\n Timer.prototype.print = function (msg) {\n var duration = (new Date().getTime()) - this.timestamp;\n console.info(msg + \" = \" + duration);\n this.timestamp = new Date().getTime();\n };\n return Timer;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2P = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$e = (undefined && undefined.__assign) || function () {\n __assign$e = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$e.apply(this, arguments);\n};\nvar __decorate$2q = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TooltipStates;\n(function (TooltipStates) {\n TooltipStates[TooltipStates[\"NOTHING\"] = 0] = \"NOTHING\";\n TooltipStates[TooltipStates[\"WAITING_TO_SHOW\"] = 1] = \"WAITING_TO_SHOW\";\n TooltipStates[TooltipStates[\"SHOWING\"] = 2] = \"SHOWING\";\n})(TooltipStates || (TooltipStates = {}));\nvar CustomTooltipFeature = /** @class */ (function (_super) {\n __extends$2P(CustomTooltipFeature, _super);\n function CustomTooltipFeature(parentComp) {\n var _this = _super.call(this) || this;\n _this.DEFAULT_SHOW_TOOLTIP_DELAY = 2000;\n _this.DEFAULT_HIDE_TOOLTIP_DELAY = 10000;\n _this.SHOW_QUICK_TOOLTIP_DIFF = 1000;\n _this.FADE_OUT_TOOLTIP_TIMEOUT = 1000;\n _this.state = TooltipStates.NOTHING;\n // when showing the tooltip, we need to make sure it's the most recent instance we request, as due to\n // async we could request two tooltips before the first instance returns, in which case we should\n // disregard the second instance.\n _this.tooltipInstanceCount = 0;\n _this.tooltipMouseTrack = false;\n _this.parentComp = parentComp;\n return _this;\n }\n CustomTooltipFeature.prototype.postConstruct = function () {\n this.tooltipShowDelay = this.gridOptionsWrapper.getTooltipDelay('show') || this.DEFAULT_SHOW_TOOLTIP_DELAY;\n this.tooltipHideDelay = this.gridOptionsWrapper.getTooltipDelay('hide') || this.DEFAULT_HIDE_TOOLTIP_DELAY;\n this.tooltipMouseTrack = this.gridOptionsWrapper.isTooltipMouseTrack();\n var el = this.parentComp.getGui();\n this.addManagedListener(el, 'mouseenter', this.onMouseEnter.bind(this));\n this.addManagedListener(el, 'mouseleave', this.onMouseLeave.bind(this));\n this.addManagedListener(el, 'mousemove', this.onMouseMove.bind(this));\n this.addManagedListener(el, 'mousedown', this.onMouseDown.bind(this));\n this.addManagedListener(el, 'keydown', this.onKeyDown.bind(this));\n };\n CustomTooltipFeature.prototype.destroy = function () {\n // if this component gets destroyed while tooltip is showing, need to make sure\n // we don't end with no mouseLeave event resulting in zombie tooltip\n this.setToDoNothing();\n _super.prototype.destroy.call(this);\n };\n CustomTooltipFeature.prototype.onMouseEnter = function (e) {\n if (isIOSUserAgent()) {\n return;\n }\n // every mouseenter should be following by a mouseleave, however for some unkonwn, it's possible for\n // mouseenter to be called twice in a row, which can happen if editing the cell. this was reported\n // in https://ag-grid.atlassian.net/browse/AG-4422. to get around this, we check the state, and if\n // state is !=nothing, then we know mouseenter was already received.\n if (this.state != TooltipStates.NOTHING) {\n return;\n }\n // if another tooltip was hidden very recently, we only wait 200ms to show, not the normal waiting time\n var delay = this.isLastTooltipHiddenRecently() ? 200 : this.tooltipShowDelay;\n this.showTooltipTimeoutId = window.setTimeout(this.showTooltip.bind(this), delay);\n this.lastMouseEvent = e;\n this.state = TooltipStates.WAITING_TO_SHOW;\n };\n CustomTooltipFeature.prototype.onMouseLeave = function () {\n this.setToDoNothing();\n };\n CustomTooltipFeature.prototype.onKeyDown = function () {\n this.setToDoNothing();\n };\n CustomTooltipFeature.prototype.setToDoNothing = function () {\n if (this.state === TooltipStates.SHOWING) {\n this.hideTooltip();\n }\n this.clearTimeouts();\n this.state = TooltipStates.NOTHING;\n };\n CustomTooltipFeature.prototype.onMouseMove = function (e) {\n // there is a delay from the time we mouseOver a component and the time the\n // tooltip is displayed, so we need to track mousemove to be able to correctly\n // position the tooltip when showTooltip is called.\n this.lastMouseEvent = e;\n if (this.tooltipMouseTrack &&\n this.state === TooltipStates.SHOWING &&\n this.tooltipComp) {\n this.positionTooltipUnderLastMouseEvent();\n }\n };\n CustomTooltipFeature.prototype.onMouseDown = function () {\n this.setToDoNothing();\n };\n CustomTooltipFeature.prototype.hideTooltip = function () {\n // check if comp exists - due to async, although we asked for\n // one, the instance may not be back yet\n if (this.tooltipComp) {\n this.destroyTooltipComp();\n CustomTooltipFeature.lastTooltipHideTime = new Date().getTime();\n }\n this.state = TooltipStates.NOTHING;\n };\n CustomTooltipFeature.prototype.destroyTooltipComp = function () {\n var _this = this;\n // add class to fade out the tooltip\n this.tooltipComp.getGui().classList.add('ag-tooltip-hiding');\n // make local copies of these variables, as we use them in the async function below,\n // and we clear then to 'undefined' later, so need to take a copy before they are undefined.\n var tooltipPopupDestroyFunc = this.tooltipPopupDestroyFunc;\n var tooltipComp = this.tooltipComp;\n window.setTimeout(function () {\n tooltipPopupDestroyFunc();\n _this.getContext().destroyBean(tooltipComp);\n }, this.FADE_OUT_TOOLTIP_TIMEOUT);\n this.tooltipPopupDestroyFunc = undefined;\n this.tooltipComp = undefined;\n };\n CustomTooltipFeature.prototype.isLastTooltipHiddenRecently = function () {\n // return true if <1000ms since last time we hid a tooltip\n var now = new Date().getTime();\n var then = CustomTooltipFeature.lastTooltipHideTime;\n return (now - then) < this.SHOW_QUICK_TOOLTIP_DIFF;\n };\n CustomTooltipFeature.prototype.showTooltip = function () {\n var params = __assign$e({}, this.parentComp.getTooltipParams());\n if (!exists(params.value)) {\n this.setToDoNothing();\n return;\n }\n this.state = TooltipStates.SHOWING;\n this.tooltipInstanceCount++;\n // we pass in tooltipInstanceCount so the callback knows what the count was when\n // we requested the tooltip, so if another tooltip was requested in the mean time\n // we disregard it\n var callback = this.newTooltipComponentCallback.bind(this, this.tooltipInstanceCount);\n var userDetails = this.userComponentFactory.getTooltipCompDetails(params);\n userDetails.newAgStackInstance().then(callback);\n };\n CustomTooltipFeature.prototype.newTooltipComponentCallback = function (tooltipInstanceCopy, tooltipComp) {\n var compNoLongerNeeded = this.state !== TooltipStates.SHOWING || this.tooltipInstanceCount !== tooltipInstanceCopy;\n if (compNoLongerNeeded) {\n this.getContext().destroyBean(tooltipComp);\n return;\n }\n var eGui = tooltipComp.getGui();\n this.tooltipComp = tooltipComp;\n if (!eGui.classList.contains('ag-tooltip')) {\n eGui.classList.add('ag-tooltip-custom');\n }\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var addPopupRes = this.popupService.addPopup({\n eChild: eGui,\n ariaLabel: translate('ariaLabelTooltip', 'Tooltip')\n });\n if (addPopupRes) {\n this.tooltipPopupDestroyFunc = addPopupRes.hideFunc;\n }\n // this.tooltipPopupDestroyFunc = this.popupService.addPopup(false, eGui, false);\n this.positionTooltipUnderLastMouseEvent();\n this.hideTooltipTimeoutId = window.setTimeout(this.hideTooltip.bind(this), this.tooltipHideDelay);\n };\n CustomTooltipFeature.prototype.positionTooltipUnderLastMouseEvent = function () {\n this.popupService.positionPopupUnderMouseEvent({\n type: 'tooltip',\n mouseEvent: this.lastMouseEvent,\n ePopup: this.tooltipComp.getGui(),\n nudgeY: 18\n });\n };\n CustomTooltipFeature.prototype.clearTimeouts = function () {\n if (this.showTooltipTimeoutId) {\n window.clearTimeout(this.showTooltipTimeoutId);\n this.showTooltipTimeoutId = undefined;\n }\n if (this.hideTooltipTimeoutId) {\n window.clearTimeout(this.hideTooltipTimeoutId);\n this.hideTooltipTimeoutId = undefined;\n }\n };\n __decorate$2q([\n Autowired('popupService')\n ], CustomTooltipFeature.prototype, \"popupService\", void 0);\n __decorate$2q([\n Autowired('userComponentFactory')\n ], CustomTooltipFeature.prototype, \"userComponentFactory\", void 0);\n __decorate$2q([\n Autowired('columnApi')\n ], CustomTooltipFeature.prototype, \"columnApi\", void 0);\n __decorate$2q([\n Autowired('gridApi')\n ], CustomTooltipFeature.prototype, \"gridApi\", void 0);\n __decorate$2q([\n PostConstruct\n ], CustomTooltipFeature.prototype, \"postConstruct\", null);\n return CustomTooltipFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar CssClassManager = /** @class */ (function () {\n function CssClassManager(getGui) {\n // to minimise DOM hits, we only apply CSS classes if they have changed. as adding a CSS class that is already\n // there, or removing one that wasn't present, all takes CPU.\n this.cssClassStates = {};\n this.getGui = getGui;\n }\n CssClassManager.prototype.addCssClass = function (className) {\n var _this = this;\n var list = (className || '').split(' ');\n if (list.length > 1) {\n list.forEach(function (cls) { return _this.addCssClass(cls); });\n return;\n }\n var updateNeeded = this.cssClassStates[className] !== true;\n if (updateNeeded && className.length) {\n this.getGui().classList.add(className);\n this.cssClassStates[className] = true;\n }\n };\n CssClassManager.prototype.removeCssClass = function (className) {\n var _this = this;\n var list = (className || '').split(' ');\n if (list.length > 1) {\n list.forEach(function (cls) { return _this.removeCssClass(cls); });\n return;\n }\n var updateNeeded = this.cssClassStates[className] !== false;\n if (updateNeeded && className.length) {\n this.getGui().classList.remove(className);\n this.cssClassStates[className] = false;\n }\n };\n CssClassManager.prototype.containsCssClass = function (className) {\n return this.getGui().classList.contains(className);\n };\n CssClassManager.prototype.addOrRemoveCssClass = function (className, addOrRemove) {\n var _this = this;\n if (!className) {\n return;\n }\n // we check for spaces before doing the split, as doing the split\n // created a performance problem (on windows only, see AG-6765)\n if (className.indexOf(' ') >= 0) {\n var list = (className || '').split(' ');\n if (list.length > 1) {\n list.forEach(function (cls) { return _this.addOrRemoveCssClass(cls, addOrRemove); });\n return;\n }\n }\n var updateNeeded = this.cssClassStates[className] !== addOrRemove;\n if (updateNeeded && className.length) {\n this.getGui().classList.toggle(className, addOrRemove);\n this.cssClassStates[className] = addOrRemove;\n }\n };\n return CssClassManager;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2O = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2p = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar compIdSequence = new NumberSequence();\nvar Component = /** @class */ (function (_super) {\n __extends$2O(Component, _super);\n function Component(template) {\n var _this = _super.call(this) || this;\n // if false, then CSS class \"ag-hidden\" is applied, which sets \"display: none\"\n _this.displayed = true;\n // if false, then CSS class \"ag-invisible\" is applied, which sets \"visibility: hidden\"\n _this.visible = true;\n // unique id for this row component. this is used for getting a reference to the HTML dom.\n // we cannot use the RowNode id as this is not unique (due to animation, old rows can be lying\n // around as we create a new rowComp instance for the same row node).\n _this.compId = compIdSequence.next();\n _this.cssClassManager = new CssClassManager(function () { return _this.eGui; });\n if (template) {\n _this.setTemplate(template);\n }\n return _this;\n }\n Component.prototype.preConstructOnComponent = function () {\n this.usingBrowserTooltips = this.gridOptionsWrapper.isEnableBrowserTooltips();\n };\n Component.prototype.getCompId = function () {\n return this.compId;\n };\n Component.prototype.getTooltipParams = function () {\n return {\n value: this.tooltipText,\n location: 'UNKNOWN'\n };\n };\n Component.prototype.setTooltip = function (newTooltipText) {\n var _this = this;\n var removeTooltip = function () {\n if (_this.usingBrowserTooltips) {\n _this.getGui().removeAttribute('title');\n }\n else {\n _this.tooltipFeature = _this.destroyBean(_this.tooltipFeature);\n }\n };\n var addTooltip = function () {\n if (_this.usingBrowserTooltips) {\n _this.getGui().setAttribute('title', _this.tooltipText);\n }\n else {\n _this.tooltipFeature = _this.createBean(new CustomTooltipFeature(_this));\n }\n };\n if (this.tooltipText != newTooltipText) {\n if (this.tooltipText) {\n removeTooltip();\n }\n if (newTooltipText != null) {\n this.tooltipText = newTooltipText;\n if (this.tooltipText) {\n addTooltip();\n }\n }\n }\n };\n // for registered components only, eg creates AgCheckbox instance from ag-checkbox HTML tag\n Component.prototype.createChildComponentsFromTags = function (parentNode, paramsMap) {\n var _this = this;\n // we MUST take a copy of the list first, as the 'swapComponentForNode' adds comments into the DOM\n // which messes up the traversal order of the children.\n var childNodeList = copyNodeList(parentNode.childNodes);\n childNodeList.forEach(function (childNode) {\n if (!(childNode instanceof HTMLElement)) {\n return;\n }\n var childComp = _this.createComponentFromElement(childNode, function (childComp) {\n // copy over all attributes, including css classes, so any attributes user put on the tag\n // wll be carried across\n var childGui = childComp.getGui();\n if (childGui) {\n _this.copyAttributesFromNode(childNode, childComp.getGui());\n }\n }, paramsMap);\n if (childComp) {\n if (childComp.addItems && childNode.children.length) {\n _this.createChildComponentsFromTags(childNode, paramsMap);\n // converting from HTMLCollection to Array\n var items = Array.prototype.slice.call(childNode.children);\n childComp.addItems(items);\n }\n // replace the tag (eg ag-checkbox) with the proper HTMLElement (eg 'div') in the dom\n _this.swapComponentForNode(childComp, parentNode, childNode);\n }\n else if (childNode.childNodes) {\n _this.createChildComponentsFromTags(childNode, paramsMap);\n }\n });\n };\n Component.prototype.createComponentFromElement = function (element, afterPreCreateCallback, paramsMap) {\n var key = element.nodeName;\n var componentParams = paramsMap ? paramsMap[element.getAttribute('ref')] : undefined;\n var ComponentClass = this.agStackComponentsRegistry.getComponentClass(key);\n if (ComponentClass) {\n Component.elementGettingCreated = element;\n var newComponent = new ComponentClass(componentParams);\n newComponent.setParentComponent(this);\n this.createBean(newComponent, null, afterPreCreateCallback);\n return newComponent;\n }\n return null;\n };\n Component.prototype.copyAttributesFromNode = function (source, dest) {\n iterateNamedNodeMap(source.attributes, function (name, value) { return dest.setAttribute(name, value); });\n };\n Component.prototype.swapComponentForNode = function (newComponent, parentNode, childNode) {\n var eComponent = newComponent.getGui();\n parentNode.replaceChild(eComponent, childNode);\n parentNode.insertBefore(document.createComment(childNode.nodeName), eComponent);\n this.addDestroyFunc(this.destroyBean.bind(this, newComponent));\n this.swapInComponentForQuerySelectors(newComponent, childNode);\n };\n Component.prototype.swapInComponentForQuerySelectors = function (newComponent, childNode) {\n var thisNoType = this;\n this.iterateOverQuerySelectors(function (querySelector) {\n if (thisNoType[querySelector.attributeName] === childNode) {\n thisNoType[querySelector.attributeName] = newComponent;\n }\n });\n };\n Component.prototype.iterateOverQuerySelectors = function (action) {\n var thisPrototype = Object.getPrototypeOf(this);\n while (thisPrototype != null) {\n var metaData = thisPrototype.__agComponentMetaData;\n var currentProtoName = getFunctionName(thisPrototype.constructor);\n if (metaData && metaData[currentProtoName] && metaData[currentProtoName].querySelectors) {\n metaData[currentProtoName].querySelectors.forEach(function (querySelector) { return action(querySelector); });\n }\n thisPrototype = Object.getPrototypeOf(thisPrototype);\n }\n };\n Component.prototype.setTemplate = function (template, paramsMap) {\n var eGui = loadTemplate(template);\n this.setTemplateFromElement(eGui, paramsMap);\n };\n Component.prototype.setTemplateFromElement = function (element, paramsMap) {\n this.eGui = element;\n this.eGui.__agComponent = this;\n this.wireQuerySelectors();\n // context will not be available when user sets template in constructor\n if (!!this.getContext()) {\n this.createChildComponentsFromTags(this.getGui(), paramsMap);\n }\n };\n Component.prototype.createChildComponentsPreConstruct = function () {\n // ui exists if user sets template in constructor. when this happens, we have to wait for the context\n // to be autoWired first before we can create child components.\n if (!!this.getGui()) {\n this.createChildComponentsFromTags(this.getGui());\n }\n };\n Component.prototype.wireQuerySelectors = function () {\n var _this = this;\n if (!this.eGui) {\n return;\n }\n var thisNoType = this;\n this.iterateOverQuerySelectors(function (querySelector) {\n var setResult = function (result) { return thisNoType[querySelector.attributeName] = result; };\n // if it's a ref selector, and match is on top level component, we return\n // the element. otherwise no way of components putting ref=xxx on the top\n // level element as querySelector only looks at children.\n var topLevelRefMatch = querySelector.refSelector\n && _this.eGui.getAttribute('ref') === querySelector.refSelector;\n if (topLevelRefMatch) {\n setResult(_this.eGui);\n }\n else {\n // otherwise use querySelector, which looks at children\n var resultOfQuery = _this.eGui.querySelector(querySelector.querySelector);\n if (resultOfQuery) {\n setResult(resultOfQuery.__agComponent || resultOfQuery);\n }\n }\n });\n };\n Component.prototype.getGui = function () {\n return this.eGui;\n };\n Component.prototype.getFocusableElement = function () {\n return this.eGui;\n };\n Component.prototype.setParentComponent = function (component) {\n this.parentComponent = component;\n };\n Component.prototype.getParentComponent = function () {\n return this.parentComponent;\n };\n // this method is for older code, that wants to provide the gui element,\n // it is not intended for this to be in ag-Stack\n Component.prototype.setGui = function (eGui) {\n this.eGui = eGui;\n };\n Component.prototype.queryForHtmlElement = function (cssSelector) {\n return this.eGui.querySelector(cssSelector);\n };\n Component.prototype.queryForHtmlInputElement = function (cssSelector) {\n return this.eGui.querySelector(cssSelector);\n };\n Component.prototype.appendChild = function (newChild, container) {\n if (newChild == null) {\n return;\n }\n if (!container) {\n container = this.eGui;\n }\n if (isNodeOrElement(newChild)) {\n container.appendChild(newChild);\n }\n else {\n var childComponent = newChild;\n container.appendChild(childComponent.getGui());\n }\n };\n Component.prototype.isDisplayed = function () {\n return this.displayed;\n };\n Component.prototype.setVisible = function (visible) {\n if (visible !== this.visible) {\n this.visible = visible;\n setVisible(this.eGui, visible);\n }\n };\n Component.prototype.setDisplayed = function (displayed) {\n if (displayed !== this.displayed) {\n this.displayed = displayed;\n setDisplayed(this.eGui, displayed);\n var event_1 = {\n type: Component.EVENT_DISPLAYED_CHANGED,\n visible: this.displayed\n };\n this.dispatchEvent(event_1);\n }\n };\n Component.prototype.destroy = function () {\n if (this.tooltipFeature) {\n this.tooltipFeature = this.destroyBean(this.tooltipFeature);\n }\n _super.prototype.destroy.call(this);\n };\n Component.prototype.addGuiEventListener = function (event, listener) {\n var _this = this;\n this.eGui.addEventListener(event, listener);\n this.addDestroyFunc(function () { return _this.eGui.removeEventListener(event, listener); });\n };\n Component.prototype.addCssClass = function (className) {\n this.cssClassManager.addCssClass(className);\n };\n Component.prototype.removeCssClass = function (className) {\n this.cssClassManager.removeCssClass(className);\n };\n Component.prototype.containsCssClass = function (className) {\n return this.cssClassManager.containsCssClass(className);\n };\n Component.prototype.addOrRemoveCssClass = function (className, addOrRemove) {\n this.cssClassManager.addOrRemoveCssClass(className, addOrRemove);\n };\n Component.prototype.getAttribute = function (key) {\n var eGui = this.eGui;\n return eGui ? eGui.getAttribute(key) : null;\n };\n Component.prototype.getRefElement = function (refName) {\n return this.queryForHtmlElement(\"[ref=\\\"\" + refName + \"\\\"]\");\n };\n Component.EVENT_DISPLAYED_CHANGED = 'displayedChanged';\n __decorate$2p([\n Autowired('agStackComponentsRegistry')\n ], Component.prototype, \"agStackComponentsRegistry\", void 0);\n __decorate$2p([\n PreConstruct\n ], Component.prototype, \"preConstructOnComponent\", null);\n __decorate$2p([\n PreConstruct\n ], Component.prototype, \"createChildComponentsPreConstruct\", null);\n return Component;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction QuerySelector(selector) {\n return querySelectorFunc.bind(this, selector, undefined);\n}\nfunction RefSelector(ref) {\n return querySelectorFunc.bind(this, \"[ref=\" + ref + \"]\", ref);\n}\nfunction querySelectorFunc(selector, refSelector, classPrototype, methodOrAttributeName, index) {\n if (selector === null) {\n console.error('AG Grid: QuerySelector selector should not be null');\n return;\n }\n if (typeof index === 'number') {\n console.error('AG Grid: QuerySelector should be on an attribute');\n return;\n }\n addToObjectProps(classPrototype, 'querySelectors', {\n attributeName: methodOrAttributeName,\n querySelector: selector,\n refSelector: refSelector\n });\n}\n// // think we should take this out, put property bindings on the\n// export function Method(eventName?: string): Function {\n// return methodFunc.bind(this, eventName);\n// }\n//\n// function methodFunc(alias: string, target: Object, methodName: string) {\n// if (alias === null) {\n// console.error(\"AG Grid: EventListener eventName should not be null\");\n// return;\n// }\n//\n// addToObjectProps(target, 'methods', {\n// methodName: methodName,\n// alias: alias\n// });\n// }\nfunction addToObjectProps(target, key, value) {\n // it's an attribute on the class\n var props = getOrCreateProps(target, getFunctionName(target.constructor));\n if (!props[key]) {\n props[key] = [];\n }\n props[key].push(value);\n}\nfunction getOrCreateProps(target, instanceName) {\n if (!target.__agComponentMetaData) {\n target.__agComponentMetaData = {};\n }\n if (!target.__agComponentMetaData[instanceName]) {\n target.__agComponentMetaData[instanceName] = {};\n }\n return target.__agComponentMetaData[instanceName];\n}\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2N = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2o = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n// optional floating filter for user provided filters - instead of providing a floating filter,\n// they can provide a getModelAsString() method on the filter instead. this class just displays\n// the string returned from getModelAsString()\nvar ReadOnlyFloatingFilter = /** @class */ (function (_super) {\n __extends$2N(ReadOnlyFloatingFilter, _super);\n function ReadOnlyFloatingFilter() {\n return _super.call(this, /* html */ \"\\n <div class=\\\"ag-floating-filter-input\\\" role=\\\"presentation\\\">\\n <ag-input-text-field ref=\\\"eFloatingFilterText\\\"></ag-input-text-field>\\n </div>\") || this;\n }\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n ReadOnlyFloatingFilter.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n ReadOnlyFloatingFilter.prototype.init = function (params) {\n this.params = params;\n var displayName = this.columnModel.getDisplayNameForColumn(params.column, 'header', true);\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.eFloatingFilterText\n .setDisabled(true)\n .setInputAriaLabel(displayName + \" \" + translate('ariaFilterInput', 'Filter Input'));\n };\n ReadOnlyFloatingFilter.prototype.onParentModelChanged = function (parentModel) {\n var _this = this;\n if (!parentModel) {\n this.eFloatingFilterText.setValue('');\n return;\n }\n this.params.parentFilterInstance(function (filterInstance) {\n // it would be nice to check if getModelAsString was present before creating this component,\n // however that is not possible, as React Hooks and VueJS don't attached the methods to the Filter until\n // AFTER the filter is created, not allowing inspection before this (we create floating filters as columns\n // are drawn, but the parent filters are only created when needed).\n if (filterInstance.getModelAsString) {\n var modelAsString = filterInstance.getModelAsString(parentModel);\n _this.eFloatingFilterText.setValue(modelAsString);\n }\n });\n };\n __decorate$2o([\n RefSelector('eFloatingFilterText')\n ], ReadOnlyFloatingFilter.prototype, \"eFloatingFilterText\", void 0);\n __decorate$2o([\n Autowired('columnModel')\n ], ReadOnlyFloatingFilter.prototype, \"columnModel\", void 0);\n return ReadOnlyFloatingFilter;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/** Provides sync access to async component. Date component can be lazy created - this class encapsulates\n * this by keeping value locally until DateComp has loaded, then passing DateComp the value. */\nvar DateCompWrapper = /** @class */ (function () {\n function DateCompWrapper(context, userComponentFactory, dateComponentParams, eParent) {\n var _this = this;\n this.alive = true;\n this.context = context;\n this.eParent = eParent;\n var compDetails = userComponentFactory.getDateCompDetails(dateComponentParams);\n var promise = compDetails.newAgStackInstance();\n promise.then(function (dateComp) {\n // because async, check the filter still exists after component comes back\n if (!_this.alive) {\n context.destroyBean(dateComp);\n return;\n }\n _this.dateComp = dateComp;\n if (!dateComp) {\n return;\n }\n eParent.appendChild(dateComp.getGui());\n if (dateComp.afterGuiAttached) {\n dateComp.afterGuiAttached();\n }\n if (_this.tempValue) {\n dateComp.setDate(_this.tempValue);\n }\n if (_this.disabled != null) {\n _this.setDateCompDisabled(_this.disabled);\n }\n });\n }\n DateCompWrapper.prototype.destroy = function () {\n this.alive = false;\n this.dateComp = this.context.destroyBean(this.dateComp);\n };\n DateCompWrapper.prototype.getDate = function () {\n return this.dateComp ? this.dateComp.getDate() : this.tempValue;\n };\n DateCompWrapper.prototype.setDate = function (value) {\n if (this.dateComp) {\n this.dateComp.setDate(value);\n }\n else {\n this.tempValue = value;\n }\n };\n DateCompWrapper.prototype.setDisabled = function (disabled) {\n if (this.dateComp) {\n this.setDateCompDisabled(disabled);\n }\n else {\n this.disabled = disabled;\n }\n };\n DateCompWrapper.prototype.setDisplayed = function (displayed) {\n setDisplayed(this.eParent, displayed);\n };\n DateCompWrapper.prototype.setInputPlaceholder = function (placeholder) {\n if (this.dateComp && this.dateComp.setInputPlaceholder) {\n this.dateComp.setInputPlaceholder(placeholder);\n }\n };\n DateCompWrapper.prototype.setInputAriaLabel = function (label) {\n if (this.dateComp && this.dateComp.setInputAriaLabel) {\n this.dateComp.setInputAriaLabel(label);\n }\n };\n DateCompWrapper.prototype.afterGuiAttached = function (params) {\n if (this.dateComp && typeof this.dateComp.afterGuiAttached === 'function') {\n this.dateComp.afterGuiAttached(params);\n }\n };\n DateCompWrapper.prototype.setDateCompDisabled = function (disabled) {\n if (this.dateComp == null) {\n return;\n }\n if (this.dateComp.setDisabled == null) {\n return;\n }\n this.dateComp.setDisabled(disabled);\n };\n return DateCompWrapper;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __assign$d = (undefined && undefined.__assign) || function () {\n __assign$d = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$d.apply(this, arguments);\n};\n/* Common logic for options, used by both filters and floating filters. */\nvar OptionsFactory = /** @class */ (function () {\n function OptionsFactory() {\n this.customFilterOptions = {};\n }\n OptionsFactory.prototype.init = function (params, defaultOptions) {\n this.filterOptions = params.filterOptions || defaultOptions;\n this.mapCustomOptions();\n this.selectDefaultItem(params);\n this.checkForDeprecatedParams();\n };\n OptionsFactory.prototype.checkForDeprecatedParams = function () {\n if (this.filterOptions.some(function (opt) { return typeof opt != 'string' && opt.test != null; })) {\n console.warn(\"AG Grid: [IFilterOptionDef] since v26.2.0, test() has been replaced with predicate().\");\n }\n if (this.filterOptions.some(function (opt) { return typeof opt != 'string' && opt.hideFilterInput != null; })) {\n console.warn(\"AG Grid: [IFilterOptionDef] since v26.2.0, useOfHideFilterInput has been replaced with numberOfInputs.\");\n }\n };\n OptionsFactory.prototype.getFilterOptions = function () {\n return this.filterOptions;\n };\n OptionsFactory.prototype.mapCustomOptions = function () {\n var _this = this;\n if (!this.filterOptions) {\n return;\n }\n this.filterOptions.forEach(function (filterOption) {\n if (typeof filterOption === 'string') {\n return;\n }\n var requiredProperties = [['displayKey'], ['displayName'], ['predicate', 'test']];\n var propertyCheck = function (keys) {\n if (!keys.some(function (key) { return filterOption[key] != null; })) {\n console.warn(\"AG Grid: ignoring FilterOptionDef as it doesn't contain one of '\" + keys + \"'\");\n return false;\n }\n return true;\n };\n if (!requiredProperties.every(propertyCheck)) {\n _this.filterOptions = _this.filterOptions.filter(function (v) { return v === filterOption; }) || [];\n return;\n }\n var test = filterOption.test;\n var mutatedFilterOptions = __assign$d({}, filterOption);\n if (test != null && filterOption.predicate == null) {\n mutatedFilterOptions.predicate = function (v, cv) { return test(v[0], cv); };\n delete mutatedFilterOptions.test;\n }\n if (mutatedFilterOptions.hideFilterInput && mutatedFilterOptions.numberOfInputs == null) {\n mutatedFilterOptions.numberOfInputs = 0;\n delete mutatedFilterOptions.hideFilterInput;\n }\n _this.customFilterOptions[filterOption.displayKey] = mutatedFilterOptions;\n });\n };\n OptionsFactory.prototype.selectDefaultItem = function (params) {\n if (params.defaultOption) {\n this.defaultOption = params.defaultOption;\n }\n else if (this.filterOptions.length >= 1) {\n var firstFilterOption = this.filterOptions[0];\n if (typeof firstFilterOption === 'string') {\n this.defaultOption = firstFilterOption;\n }\n else if (firstFilterOption.displayKey) {\n this.defaultOption = firstFilterOption.displayKey;\n }\n else {\n console.warn(\"AG Grid: invalid FilterOptionDef supplied as it doesn't contain a 'displayKey'\");\n }\n }\n else {\n console.warn('AG Grid: no filter options for filter');\n }\n };\n OptionsFactory.prototype.getDefaultOption = function () {\n return this.defaultOption;\n };\n OptionsFactory.prototype.getCustomOption = function (name) {\n return this.customFilterOptions[name];\n };\n return OptionsFactory;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar DEFAULT_FILTER_LOCALE_TEXT = {\n applyFilter: 'Apply',\n clearFilter: 'Clear',\n resetFilter: 'Reset',\n cancelFilter: 'Cancel',\n textFilter: 'Text Filter',\n numberFilter: 'Number Filter',\n dateFilter: 'Date Filter',\n setFilter: 'Set Filter',\n filterOoo: 'Filter...',\n empty: 'Choose One',\n equals: 'Equals',\n notEqual: 'Not equal',\n lessThan: 'Less than',\n greaterThan: 'Greater than',\n inRange: 'In range',\n inRangeStart: 'From',\n inRangeEnd: 'To',\n lessThanOrEqual: 'Less than or equals',\n greaterThanOrEqual: 'Greater than or equals',\n contains: 'Contains',\n notContains: 'Not contains',\n startsWith: 'Starts with',\n endsWith: 'Ends with',\n blank: 'Blank',\n notBlank: 'Not blank',\n andCondition: 'AND',\n orCondition: 'OR',\n dateFormatOoo: 'yyyy-mm-dd',\n};\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2M = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$c = (undefined && undefined.__assign) || function () {\n __assign$c = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$c.apply(this, arguments);\n};\nvar __decorate$2n = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ManagedFocusFeature = /** @class */ (function (_super) {\n __extends$2M(ManagedFocusFeature, _super);\n function ManagedFocusFeature(eFocusableElement, callbacks) {\n if (callbacks === void 0) { callbacks = {}; }\n var _this = _super.call(this) || this;\n _this.eFocusableElement = eFocusableElement;\n _this.callbacks = callbacks;\n _this.callbacks = __assign$c({ shouldStopEventPropagation: function () { return false; }, onTabKeyDown: function (e) {\n if (e.defaultPrevented) {\n return;\n }\n var nextRoot = _this.focusService.findNextFocusableElement(_this.eFocusableElement, false, e.shiftKey);\n if (!nextRoot) {\n return;\n }\n nextRoot.focus();\n e.preventDefault();\n } }, callbacks);\n return _this;\n }\n ManagedFocusFeature.prototype.postConstruct = function () {\n this.eFocusableElement.classList.add(ManagedFocusFeature.FOCUS_MANAGED_CLASS);\n this.addKeyDownListeners(this.eFocusableElement);\n if (this.callbacks.onFocusIn) {\n this.addManagedListener(this.eFocusableElement, 'focusin', this.callbacks.onFocusIn);\n }\n if (this.callbacks.onFocusOut) {\n this.addManagedListener(this.eFocusableElement, 'focusout', this.callbacks.onFocusOut);\n }\n };\n ManagedFocusFeature.prototype.addKeyDownListeners = function (eGui) {\n var _this = this;\n this.addManagedListener(eGui, 'keydown', function (e) {\n if (e.defaultPrevented || isStopPropagationForAgGrid(e)) {\n return;\n }\n if (_this.callbacks.shouldStopEventPropagation(e)) {\n stopPropagationForAgGrid(e);\n return;\n }\n if (e.key === KeyCode.TAB) {\n _this.callbacks.onTabKeyDown(e);\n }\n else if (_this.callbacks.handleKeyDown) {\n _this.callbacks.handleKeyDown(e);\n }\n });\n };\n ManagedFocusFeature.FOCUS_MANAGED_CLASS = 'ag-focus-managed';\n __decorate$2n([\n Autowired('focusService')\n ], ManagedFocusFeature.prototype, \"focusService\", void 0);\n __decorate$2n([\n PostConstruct\n ], ManagedFocusFeature.prototype, \"postConstruct\", null);\n return ManagedFocusFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2L = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2m = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n/**\n * Contains common logic to all provided filters (apply button, clear button, etc).\n * All the filters that come with AG Grid extend this class. User filters do not\n * extend this class.\n *\n * @param M type of filter-model managed by the concrete sub-class that extends this type\n * @param V type of value managed by the concrete sub-class that extends this type\n */\nvar ProvidedFilter = /** @class */ (function (_super) {\n __extends$2L(ProvidedFilter, _super);\n function ProvidedFilter(filterNameKey) {\n var _this = _super.call(this) || this;\n _this.filterNameKey = filterNameKey;\n _this.applyActive = false;\n _this.hidePopup = null;\n // after the user hits 'apply' the model gets copied to here. this is then the model that we use for\n // all filtering. so if user changes UI but doesn't hit apply, then the UI will be out of sync with this model.\n // this is what we want, as the UI should only become the 'active' filter once it's applied. when apply is\n // inactive, this model will be in sync (following the debounce ms). if the UI is not a valid filter\n // (eg the value is missing so nothing to filter on, or for set filter all checkboxes are checked so filter\n // not active) then this appliedModel will be null/undefined.\n _this.appliedModel = null;\n return _this;\n }\n ProvidedFilter.prototype.postConstruct = function () {\n this.resetTemplate(); // do this first to create the DOM\n this.createManagedBean(new ManagedFocusFeature(this.getFocusableElement(), {\n handleKeyDown: this.handleKeyDown.bind(this)\n }));\n };\n // override\n ProvidedFilter.prototype.handleKeyDown = function (e) { };\n ProvidedFilter.prototype.getFilterTitle = function () {\n return this.translate(this.filterNameKey);\n };\n ProvidedFilter.prototype.isFilterActive = function () {\n // filter is active if we have a valid applied model\n return !!this.appliedModel;\n };\n ProvidedFilter.prototype.resetTemplate = function (paramsMap) {\n var templateString = /* html */ \"\\n <div class=\\\"ag-filter-wrapper\\\">\\n <div class=\\\"ag-filter-body-wrapper ag-\" + this.getCssIdentifier() + \"-body-wrapper\\\">\\n \" + this.createBodyTemplate() + \"\\n </div>\\n </div>\";\n this.setTemplate(templateString, paramsMap);\n };\n ProvidedFilter.prototype.isReadOnly = function () {\n return !!this.providedFilterParams.readOnly;\n };\n ProvidedFilter.prototype.init = function (params) {\n var _this = this;\n this.setParams(params);\n this.resetUiToDefaults(true).then(function () {\n _this.updateUiVisibility();\n _this.setupOnBtApplyDebounce();\n });\n };\n ProvidedFilter.prototype.setParams = function (params) {\n this.providedFilterParams = params;\n this.applyActive = ProvidedFilter.isUseApplyButton(params);\n this.createButtonPanel();\n };\n ProvidedFilter.prototype.createButtonPanel = function () {\n var _this = this;\n var buttons = this.providedFilterParams.buttons;\n if (!buttons || buttons.length < 1 || this.isReadOnly()) {\n return;\n }\n var eButtonsPanel = document.createElement('div');\n eButtonsPanel.classList.add('ag-filter-apply-panel');\n var addButton = function (type) {\n var text;\n var clickListener;\n switch (type) {\n case 'apply':\n text = _this.translate('applyFilter');\n clickListener = function (e) { return _this.onBtApply(false, false, e); };\n break;\n case 'clear':\n text = _this.translate('clearFilter');\n clickListener = function () { return _this.onBtClear(); };\n break;\n case 'reset':\n text = _this.translate('resetFilter');\n clickListener = function () { return _this.onBtReset(); };\n break;\n case 'cancel':\n text = _this.translate('cancelFilter');\n clickListener = function (e) { _this.onBtCancel(e); };\n break;\n default:\n console.warn('AG Grid: Unknown button type specified');\n return;\n }\n var button = loadTemplate(\n /* html */\n \"<button\\n type=\\\"button\\\"\\n ref=\\\"\" + type + \"FilterButton\\\"\\n class=\\\"ag-standard-button ag-filter-apply-panel-button\\\"\\n >\" + text + \"\\n </button>\");\n eButtonsPanel.appendChild(button);\n _this.addManagedListener(button, 'click', clickListener);\n };\n convertToSet(buttons).forEach(function (type) { return addButton(type); });\n this.getGui().appendChild(eButtonsPanel);\n };\n // subclasses can override this to provide alternative debounce defaults\n ProvidedFilter.prototype.getDefaultDebounceMs = function () {\n return 0;\n };\n ProvidedFilter.prototype.setupOnBtApplyDebounce = function () {\n var debounceMs = ProvidedFilter.getDebounceMs(this.providedFilterParams, this.getDefaultDebounceMs());\n this.onBtApplyDebounce = debounce(this.onBtApply.bind(this), debounceMs);\n };\n ProvidedFilter.prototype.getModel = function () {\n return this.appliedModel ? this.appliedModel : null;\n };\n ProvidedFilter.prototype.setModel = function (model) {\n var _this = this;\n var promise = model != null ? this.setModelIntoUi(model) : this.resetUiToDefaults();\n return promise.then(function () {\n _this.updateUiVisibility();\n // we set the model from the GUI, rather than the provided model,\n // so the model is consistent, e.g. handling of null/undefined will be the same,\n // or if model is case insensitive, then casing is removed.\n _this.applyModel();\n });\n };\n ProvidedFilter.prototype.onBtCancel = function (e) {\n var _this = this;\n var currentModel = this.getModel();\n var afterAppliedFunc = function () {\n _this.onUiChanged(false, 'prevent');\n if (_this.providedFilterParams.closeOnApply) {\n _this.close(e);\n }\n };\n if (currentModel != null) {\n this.setModelIntoUi(currentModel).then(afterAppliedFunc);\n }\n else {\n this.resetUiToDefaults().then(afterAppliedFunc);\n }\n };\n ProvidedFilter.prototype.onBtClear = function () {\n var _this = this;\n this.resetUiToDefaults().then(function () { return _this.onUiChanged(); });\n };\n ProvidedFilter.prototype.onBtReset = function () {\n this.onBtClear();\n this.onBtApply();\n };\n /**\n * Applies changes made in the UI to the filter, and returns true if the model has changed.\n */\n ProvidedFilter.prototype.applyModel = function () {\n var newModel = this.getModelFromUi();\n if (!this.isModelValid(newModel)) {\n return false;\n }\n var previousModel = this.appliedModel;\n this.appliedModel = newModel;\n // models can be same if user pasted same content into text field, or maybe just changed the case\n // and it's a case insensitive filter\n return !this.areModelsEqual(previousModel, newModel);\n };\n ProvidedFilter.prototype.isModelValid = function (model) {\n return true;\n };\n ProvidedFilter.prototype.onBtApply = function (afterFloatingFilter, afterDataChange, e) {\n if (afterFloatingFilter === void 0) { afterFloatingFilter = false; }\n if (afterDataChange === void 0) { afterDataChange = false; }\n if (this.applyModel()) {\n // the floating filter uses 'afterFloatingFilter' info, so it doesn't refresh after filter changed if change\n // came from floating filter\n this.providedFilterParams.filterChangedCallback({ afterFloatingFilter: afterFloatingFilter, afterDataChange: afterDataChange });\n }\n var closeOnApply = this.providedFilterParams.closeOnApply;\n // only close if an apply button is visible, otherwise we'd be closing every time a change was made!\n if (closeOnApply && this.applyActive && !afterFloatingFilter && !afterDataChange) {\n this.close(e);\n }\n };\n ProvidedFilter.prototype.onNewRowsLoaded = function () {\n };\n ProvidedFilter.prototype.close = function (e) {\n if (!this.hidePopup) {\n return;\n }\n var keyboardEvent = e;\n var key = keyboardEvent && keyboardEvent.key;\n var params;\n if (key === 'Enter' || key === 'Space') {\n params = { keyboardEvent: keyboardEvent };\n }\n this.hidePopup(params);\n this.hidePopup = null;\n };\n /**\n * By default, if the change came from a floating filter it will be applied immediately, otherwise if there is no\n * apply button it will be applied after a debounce, otherwise it will not be applied at all. This behaviour can\n * be adjusted by using the apply parameter.\n */\n ProvidedFilter.prototype.onUiChanged = function (fromFloatingFilter, apply) {\n if (fromFloatingFilter === void 0) { fromFloatingFilter = false; }\n this.updateUiVisibility();\n this.providedFilterParams.filterModifiedCallback();\n if (this.applyActive && !this.isReadOnly) {\n var isValid = this.isModelValid(this.getModelFromUi());\n setDisabled(this.getRefElement('applyFilterButton'), !isValid);\n }\n if ((fromFloatingFilter && !apply) || apply === 'immediately') {\n this.onBtApply(fromFloatingFilter);\n }\n else if ((!this.applyActive && !apply) || apply === 'debounce') {\n this.onBtApplyDebounce();\n }\n };\n ProvidedFilter.prototype.afterGuiAttached = function (params) {\n if (params == null) {\n return;\n }\n this.hidePopup = params.hidePopup;\n };\n // static, as used by floating filter also\n ProvidedFilter.getDebounceMs = function (params, debounceDefault) {\n if (ProvidedFilter.isUseApplyButton(params)) {\n if (params.debounceMs != null) {\n console.warn('AG Grid: debounceMs is ignored when apply button is present');\n }\n return 0;\n }\n return params.debounceMs != null ? params.debounceMs : debounceDefault;\n };\n // static, as used by floating filter also\n ProvidedFilter.isUseApplyButton = function (params) {\n return !!params.buttons && params.buttons.indexOf('apply') >= 0;\n };\n ProvidedFilter.prototype.destroy = function () {\n this.hidePopup = null;\n _super.prototype.destroy.call(this);\n };\n ProvidedFilter.prototype.translate = function (key) {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n return translate(key, DEFAULT_FILTER_LOCALE_TEXT[key]);\n };\n ProvidedFilter.prototype.getCellValue = function (rowNode) {\n var _a = this.providedFilterParams, api = _a.api, colDef = _a.colDef, column = _a.column, columnApi = _a.columnApi, context = _a.context;\n return this.providedFilterParams.valueGetter({\n api: api,\n colDef: colDef,\n column: column,\n columnApi: columnApi,\n context: context,\n data: rowNode.data,\n getValue: function (field) { return rowNode.data[field]; },\n node: rowNode,\n });\n };\n __decorate$2m([\n Autowired('rowModel')\n ], ProvidedFilter.prototype, \"rowModel\", void 0);\n __decorate$2m([\n Autowired('valueService')\n ], ProvidedFilter.prototype, \"valueService\", void 0);\n __decorate$2m([\n PostConstruct\n ], ProvidedFilter.prototype, \"postConstruct\", null);\n return ProvidedFilter;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2K = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2l = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgAbstractLabel = /** @class */ (function (_super) {\n __extends$2K(AgAbstractLabel, _super);\n function AgAbstractLabel(config, template) {\n var _this = _super.call(this, template) || this;\n _this.labelSeparator = '';\n _this.labelAlignment = 'left';\n _this.disabled = false;\n _this.label = '';\n _this.config = config || {};\n return _this;\n }\n AgAbstractLabel.prototype.postConstruct = function () {\n this.addCssClass('ag-labeled');\n this.eLabel.classList.add('ag-label');\n var _a = this.config, labelSeparator = _a.labelSeparator, label = _a.label, labelWidth = _a.labelWidth, labelAlignment = _a.labelAlignment;\n if (labelSeparator != null) {\n this.setLabelSeparator(labelSeparator);\n }\n if (label != null) {\n this.setLabel(label);\n }\n if (labelWidth != null) {\n this.setLabelWidth(labelWidth);\n }\n this.setLabelAlignment(labelAlignment || this.labelAlignment);\n this.refreshLabel();\n };\n AgAbstractLabel.prototype.refreshLabel = function () {\n clearElement(this.eLabel);\n if (typeof this.label === 'string') {\n this.eLabel.innerText = this.label + this.labelSeparator;\n }\n else if (this.label) {\n this.eLabel.appendChild(this.label);\n }\n if (this.label === '') {\n this.eLabel.classList.add('ag-hidden');\n setAriaRole(this.eLabel, 'presentation');\n }\n else {\n this.eLabel.classList.remove('ag-hidden');\n setAriaRole(this.eLabel, null);\n }\n };\n AgAbstractLabel.prototype.setLabelSeparator = function (labelSeparator) {\n if (this.labelSeparator === labelSeparator) {\n return this;\n }\n this.labelSeparator = labelSeparator;\n if (this.label != null) {\n this.refreshLabel();\n }\n return this;\n };\n AgAbstractLabel.prototype.getLabelId = function () {\n this.eLabel.id = this.eLabel.id || \"ag-\" + this.getCompId() + \"-label\";\n return this.eLabel.id;\n };\n AgAbstractLabel.prototype.getLabel = function () {\n return this.label;\n };\n AgAbstractLabel.prototype.setLabel = function (label) {\n if (this.label === label) {\n return this;\n }\n this.label = label;\n this.refreshLabel();\n return this;\n };\n AgAbstractLabel.prototype.setLabelAlignment = function (alignment) {\n var eGui = this.getGui();\n var eGuiClassList = eGui.classList;\n eGuiClassList.toggle('ag-label-align-left', alignment === 'left');\n eGuiClassList.toggle('ag-label-align-right', alignment === 'right');\n eGuiClassList.toggle('ag-label-align-top', alignment === 'top');\n return this;\n };\n AgAbstractLabel.prototype.setLabelWidth = function (width) {\n if (this.label == null) {\n return this;\n }\n setElementWidth(this.eLabel, width);\n return this;\n };\n AgAbstractLabel.prototype.setDisabled = function (disabled) {\n disabled = !!disabled;\n var element = this.getGui();\n setDisabled(element, disabled);\n element.classList.toggle('ag-disabled', disabled);\n this.disabled = disabled;\n return this;\n };\n AgAbstractLabel.prototype.isDisabled = function () {\n return !!this.disabled;\n };\n __decorate$2l([\n PostConstruct\n ], AgAbstractLabel.prototype, \"postConstruct\", null);\n return AgAbstractLabel;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2J = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgAbstractField = /** @class */ (function (_super) {\n __extends$2J(AgAbstractField, _super);\n function AgAbstractField(config, template, className) {\n var _this = _super.call(this, config, template) || this;\n _this.className = className;\n return _this;\n }\n AgAbstractField.prototype.postConstruct = function () {\n _super.prototype.postConstruct.call(this);\n if (this.className) {\n this.addCssClass(this.className);\n }\n };\n AgAbstractField.prototype.onValueChange = function (callbackFn) {\n var _this = this;\n this.addManagedListener(this, AgAbstractField.EVENT_CHANGED, function () { return callbackFn(_this.getValue()); });\n return this;\n };\n AgAbstractField.prototype.getWidth = function () {\n return this.getGui().clientWidth;\n };\n AgAbstractField.prototype.setWidth = function (width) {\n setFixedWidth(this.getGui(), width);\n return this;\n };\n AgAbstractField.prototype.getPreviousValue = function () {\n return this.previousValue;\n };\n AgAbstractField.prototype.getValue = function () {\n return this.value;\n };\n AgAbstractField.prototype.setValue = function (value, silent) {\n if (this.value === value) {\n return this;\n }\n this.previousValue = this.value;\n this.value = value;\n if (!silent) {\n this.dispatchEvent({ type: AgAbstractField.EVENT_CHANGED });\n }\n return this;\n };\n AgAbstractField.EVENT_CHANGED = 'valueChange';\n return AgAbstractField;\n}(AgAbstractLabel));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2I = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2k = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgPickerField = /** @class */ (function (_super) {\n __extends$2I(AgPickerField, _super);\n function AgPickerField(config, className, pickerIcon, ariaRole) {\n var _this = _super.call(this, config, \n /* html */ \"<div class=\\\"ag-picker-field\\\" role=\\\"presentation\\\">\\n <div ref=\\\"eLabel\\\"></div>\\n <div ref=\\\"eWrapper\\\"\\n class=\\\"ag-wrapper ag-picker-field-wrapper\\\"\\n tabIndex=\\\"-1\\\"\\n aria-expanded=\\\"false\\\"\\n \" + (ariaRole ? \"role=\\\"\" + ariaRole + \"\\\"\" : '') + \"\\n >\\n <div ref=\\\"eDisplayField\\\" class=\\\"ag-picker-field-display\\\"></div>\\n <div ref=\\\"eIcon\\\" class=\\\"ag-picker-field-icon\\\" aria-hidden=\\\"true\\\"></div>\\n </div>\\n </div>\", className) || this;\n _this.pickerIcon = pickerIcon;\n _this.isPickerDisplayed = false;\n _this.isDestroyingPicker = false;\n _this.skipClick = false;\n return _this;\n }\n AgPickerField.prototype.postConstruct = function () {\n var _this = this;\n _super.prototype.postConstruct.call(this);\n var displayId = this.getCompId() + \"-display\";\n this.eDisplayField.setAttribute('id', displayId);\n setAriaDescribedBy(this.eWrapper, displayId);\n var clickHandler = function () {\n if (_this.skipClick) {\n _this.skipClick = false;\n return;\n }\n if (_this.isDisabled()) {\n return;\n }\n _this.pickerComponent = _this.showPicker();\n };\n var eGui = this.getGui();\n this.addManagedListener(eGui, 'mousedown', function (e) {\n if (!_this.skipClick &&\n _this.pickerComponent &&\n _this.pickerComponent.isAlive() &&\n isVisible(_this.pickerComponent.getGui()) &&\n eGui.contains(e.target)) {\n _this.skipClick = true;\n }\n });\n this.addManagedListener(eGui, 'keydown', function (e) {\n switch (e.key) {\n case KeyCode.UP:\n case KeyCode.DOWN:\n case KeyCode.ENTER:\n case KeyCode.SPACE:\n clickHandler();\n case KeyCode.ESCAPE:\n if (_this.isPickerDisplayed) {\n e.preventDefault();\n }\n break;\n }\n });\n this.addManagedListener(this.eWrapper, 'click', clickHandler);\n this.addManagedListener(this.eLabel, 'click', clickHandler);\n if (this.pickerIcon) {\n var icon = createIconNoSpan(this.pickerIcon, this.gridOptionsWrapper);\n if (icon) {\n this.eIcon.appendChild(icon);\n }\n }\n };\n AgPickerField.prototype.refreshLabel = function () {\n if (exists(this.getLabel())) {\n setAriaLabelledBy(this.eWrapper, this.getLabelId());\n }\n else {\n this.eWrapper.removeAttribute('aria-labelledby');\n }\n _super.prototype.refreshLabel.call(this);\n };\n AgPickerField.prototype.setAriaLabel = function (label) {\n setAriaLabel(this.eWrapper, label);\n return this;\n };\n AgPickerField.prototype.setInputWidth = function (width) {\n setElementWidth(this.eWrapper, width);\n return this;\n };\n AgPickerField.prototype.getFocusableElement = function () {\n return this.eWrapper;\n };\n __decorate$2k([\n RefSelector('eLabel')\n ], AgPickerField.prototype, \"eLabel\", void 0);\n __decorate$2k([\n RefSelector('eWrapper')\n ], AgPickerField.prototype, \"eWrapper\", void 0);\n __decorate$2k([\n RefSelector('eDisplayField')\n ], AgPickerField.prototype, \"eDisplayField\", void 0);\n __decorate$2k([\n RefSelector('eIcon')\n ], AgPickerField.prototype, \"eIcon\", void 0);\n return AgPickerField;\n}(AgAbstractField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2H = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2j = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgList = /** @class */ (function (_super) {\n __extends$2H(AgList, _super);\n function AgList(cssIdentifier) {\n if (cssIdentifier === void 0) { cssIdentifier = 'default'; }\n var _this = _super.call(this, /* html */ \"<div class=\\\"ag-list ag-\" + cssIdentifier + \"-list\\\" role=\\\"listbox\\\"></div>\") || this;\n _this.cssIdentifier = cssIdentifier;\n _this.options = [];\n _this.itemEls = [];\n return _this;\n }\n AgList.prototype.init = function () {\n this.addManagedListener(this.getGui(), 'keydown', this.handleKeyDown.bind(this));\n };\n AgList.prototype.handleKeyDown = function (e) {\n var key = e.key;\n switch (key) {\n case KeyCode.ENTER:\n if (!this.highlightedEl) {\n this.setValue(this.getValue());\n }\n else {\n var pos = this.itemEls.indexOf(this.highlightedEl);\n this.setValueByIndex(pos);\n }\n break;\n case KeyCode.DOWN:\n case KeyCode.UP:\n var isDown = key === KeyCode.DOWN;\n var itemToHighlight = void 0;\n e.preventDefault();\n if (!this.highlightedEl) {\n itemToHighlight = this.itemEls[isDown ? 0 : this.itemEls.length - 1];\n }\n else {\n var currentIdx = this.itemEls.indexOf(this.highlightedEl);\n var nextPos = currentIdx + (isDown ? 1 : -1);\n nextPos = Math.min(Math.max(nextPos, 0), this.itemEls.length - 1);\n itemToHighlight = this.itemEls[nextPos];\n }\n this.highlightItem(itemToHighlight);\n break;\n }\n };\n AgList.prototype.addOptions = function (listOptions) {\n var _this = this;\n listOptions.forEach(function (listOption) { return _this.addOption(listOption); });\n return this;\n };\n AgList.prototype.addOption = function (listOption) {\n var value = listOption.value, text = listOption.text;\n var sanitisedText = escapeString(text || value);\n this.options.push({ value: value, text: sanitisedText });\n this.renderOption(value, sanitisedText);\n this.updateIndices();\n return this;\n };\n AgList.prototype.updateIndices = function () {\n var options = this.getGui().querySelectorAll('.ag-list-item');\n options.forEach(function (option, idx) {\n setAriaPosInSet(option, idx + 1);\n setAriaSetSize(option, options.length);\n });\n };\n AgList.prototype.renderOption = function (value, text) {\n var _this = this;\n var itemEl = document.createElement('div');\n setAriaRole(itemEl, 'option');\n itemEl.classList.add('ag-list-item', \"ag-\" + this.cssIdentifier + \"-list-item\");\n itemEl.innerHTML = \"<span>\" + text + \"</span>\";\n itemEl.tabIndex = -1;\n this.itemEls.push(itemEl);\n this.addManagedListener(itemEl, 'mouseover', function () { return _this.highlightItem(itemEl); });\n this.addManagedListener(itemEl, 'mouseleave', function () { return _this.clearHighlighted(); });\n this.addManagedListener(itemEl, 'click', function () { return _this.setValue(value); });\n this.getGui().appendChild(itemEl);\n };\n AgList.prototype.setValue = function (value, silent) {\n if (this.value === value) {\n this.fireItemSelected();\n return this;\n }\n if (value == null) {\n this.reset();\n return this;\n }\n var idx = this.options.findIndex(function (option) { return option.value === value; });\n if (idx !== -1) {\n var option = this.options[idx];\n this.value = option.value;\n this.displayValue = option.text != null ? option.text : option.value;\n this.highlightItem(this.itemEls[idx]);\n if (!silent) {\n this.fireChangeEvent();\n }\n }\n return this;\n };\n AgList.prototype.setValueByIndex = function (idx) {\n return this.setValue(this.options[idx].value);\n };\n AgList.prototype.getValue = function () {\n return this.value;\n };\n AgList.prototype.getDisplayValue = function () {\n return this.displayValue;\n };\n AgList.prototype.refreshHighlighted = function () {\n var _this = this;\n this.clearHighlighted();\n var idx = this.options.findIndex(function (option) { return option.value === _this.value; });\n if (idx !== -1) {\n this.highlightItem(this.itemEls[idx]);\n }\n };\n AgList.prototype.reset = function () {\n this.value = null;\n this.displayValue = null;\n this.clearHighlighted();\n this.fireChangeEvent();\n };\n AgList.prototype.highlightItem = function (el) {\n if (!el.offsetParent) {\n return;\n }\n this.clearHighlighted();\n this.highlightedEl = el;\n this.highlightedEl.classList.add(AgList.ACTIVE_CLASS);\n setAriaSelected(this.highlightedEl, true);\n this.highlightedEl.focus();\n };\n AgList.prototype.clearHighlighted = function () {\n if (!this.highlightedEl || !this.highlightedEl.offsetParent) {\n return;\n }\n this.highlightedEl.classList.remove(AgList.ACTIVE_CLASS);\n setAriaSelected(this.highlightedEl, false);\n this.highlightedEl = null;\n };\n AgList.prototype.fireChangeEvent = function () {\n this.dispatchEvent({ type: AgAbstractField.EVENT_CHANGED });\n this.fireItemSelected();\n };\n AgList.prototype.fireItemSelected = function () {\n this.dispatchEvent({ type: AgList.EVENT_ITEM_SELECTED });\n };\n AgList.EVENT_ITEM_SELECTED = 'selectedItem';\n AgList.ACTIVE_CLASS = 'ag-active-item';\n __decorate$2j([\n PostConstruct\n ], AgList.prototype, \"init\", null);\n return AgList;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2G = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2i = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgSelect = /** @class */ (function (_super) {\n __extends$2G(AgSelect, _super);\n function AgSelect(config) {\n return _super.call(this, config, 'ag-select', 'smallDown', 'listbox') || this;\n }\n AgSelect.prototype.init = function () {\n var _this = this;\n this.listComponent = this.createBean(new AgList('select'));\n this.listComponent.setParentComponent(this);\n this.eWrapper.tabIndex = 0;\n this.listComponent.addManagedListener(this.listComponent, AgList.EVENT_ITEM_SELECTED, function () { if (_this.hideList) {\n _this.hideList();\n } });\n this.listComponent.addManagedListener(this.listComponent, AgAbstractField.EVENT_CHANGED, function () {\n _this.setValue(_this.listComponent.getValue(), false, true);\n if (_this.hideList) {\n _this.hideList();\n }\n });\n };\n AgSelect.prototype.showPicker = function () {\n var _this = this;\n var listGui = this.listComponent.getGui();\n var eDocument = this.gridOptionsWrapper.getDocument();\n var destroyMouseWheelFunc = this.addManagedListener(eDocument.body, 'wheel', function (e) {\n if (!listGui.contains(e.target) && _this.hideList) {\n _this.hideList();\n }\n });\n var destroyFocusOutFunc = this.addManagedListener(listGui, 'focusout', function (e) {\n if (!listGui.contains(e.relatedTarget) && _this.hideList) {\n _this.hideList();\n }\n });\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var addPopupRes = this.popupService.addPopup({\n modal: true,\n eChild: listGui,\n closeOnEsc: true,\n closedCallback: function () {\n _this.hideList = null;\n _this.isPickerDisplayed = false;\n destroyFocusOutFunc();\n destroyMouseWheelFunc();\n if (_this.isAlive()) {\n setAriaExpanded(_this.eWrapper, false);\n _this.getFocusableElement().focus();\n }\n },\n ariaLabel: translate('ariaLabelSelectField', 'Select Field')\n });\n if (addPopupRes) {\n this.hideList = addPopupRes.hideFunc;\n }\n this.isPickerDisplayed = true;\n setElementWidth(listGui, getAbsoluteWidth(this.eWrapper));\n setAriaExpanded(this.eWrapper, true);\n listGui.style.maxHeight = getInnerHeight(this.popupService.getPopupParent()) + 'px';\n listGui.style.position = 'absolute';\n this.popupService.positionPopupUnderComponent({\n type: 'ag-list',\n eventSource: this.eWrapper,\n ePopup: listGui,\n keepWithinBounds: true\n });\n this.listComponent.refreshHighlighted();\n return this.listComponent;\n };\n AgSelect.prototype.addOptions = function (options) {\n var _this = this;\n options.forEach(function (option) { return _this.addOption(option); });\n return this;\n };\n AgSelect.prototype.addOption = function (option) {\n this.listComponent.addOption(option);\n return this;\n };\n AgSelect.prototype.setValue = function (value, silent, fromPicker) {\n if (this.value === value) {\n return this;\n }\n if (!fromPicker) {\n this.listComponent.setValue(value, true);\n }\n var newValue = this.listComponent.getValue();\n if (newValue === this.getValue()) {\n return this;\n }\n this.eDisplayField.innerHTML = this.listComponent.getDisplayValue();\n return _super.prototype.setValue.call(this, value, silent);\n };\n AgSelect.prototype.destroy = function () {\n if (this.hideList) {\n this.hideList();\n }\n this.destroyBean(this.listComponent);\n _super.prototype.destroy.call(this);\n };\n __decorate$2i([\n Autowired('popupService')\n ], AgSelect.prototype, \"popupService\", void 0);\n __decorate$2i([\n PostConstruct\n ], AgSelect.prototype, \"init\", null);\n return AgSelect;\n}(AgPickerField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2F = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2h = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgAbstractInputField = /** @class */ (function (_super) {\n __extends$2F(AgAbstractInputField, _super);\n function AgAbstractInputField(config, className, inputType, displayFieldTag) {\n if (inputType === void 0) { inputType = 'text'; }\n if (displayFieldTag === void 0) { displayFieldTag = 'input'; }\n var _this = _super.call(this, config, /* html */ \"\\n <div role=\\\"presentation\\\">\\n <div ref=\\\"eLabel\\\" class=\\\"ag-input-field-label\\\"></div>\\n <div ref=\\\"eWrapper\\\" class=\\\"ag-wrapper ag-input-wrapper\\\" role=\\\"presentation\\\">\\n <\" + displayFieldTag + \" ref=\\\"eInput\\\" class=\\\"ag-input-field-input\\\"></\" + displayFieldTag + \">\\n </div>\\n </div>\", className) || this;\n _this.inputType = inputType;\n _this.displayFieldTag = displayFieldTag;\n return _this;\n }\n AgAbstractInputField.prototype.postConstruct = function () {\n _super.prototype.postConstruct.call(this);\n this.setInputType();\n this.eLabel.classList.add(this.className + \"-label\");\n this.eWrapper.classList.add(this.className + \"-input-wrapper\");\n this.eInput.classList.add(this.className + \"-input\");\n this.addCssClass('ag-input-field');\n this.eInput.id = this.eInput.id || \"ag-\" + this.getCompId() + \"-input\";\n var _a = this.config, width = _a.width, value = _a.value;\n if (width != null) {\n this.setWidth(width);\n }\n if (value != null) {\n this.setValue(value);\n }\n this.addInputListeners();\n };\n AgAbstractInputField.prototype.refreshLabel = function () {\n if (exists(this.getLabel())) {\n setAriaLabelledBy(this.eInput, this.getLabelId());\n }\n else {\n this.eInput.removeAttribute('aria-labelledby');\n }\n _super.prototype.refreshLabel.call(this);\n };\n AgAbstractInputField.prototype.addInputListeners = function () {\n var _this = this;\n this.addManagedListener(this.eInput, 'input', function (e) { return _this.setValue(e.target.value); });\n };\n AgAbstractInputField.prototype.setInputType = function () {\n if (this.displayFieldTag === 'input') {\n this.eInput.setAttribute('type', this.inputType);\n }\n };\n AgAbstractInputField.prototype.getInputElement = function () {\n return this.eInput;\n };\n AgAbstractInputField.prototype.setInputWidth = function (width) {\n setElementWidth(this.eWrapper, width);\n return this;\n };\n AgAbstractInputField.prototype.setInputName = function (name) {\n this.getInputElement().setAttribute('name', name);\n return this;\n };\n AgAbstractInputField.prototype.getFocusableElement = function () {\n return this.eInput;\n };\n AgAbstractInputField.prototype.setMaxLength = function (length) {\n var eInput = this.eInput;\n eInput.maxLength = length;\n return this;\n };\n AgAbstractInputField.prototype.setInputPlaceholder = function (placeholder) {\n addOrRemoveAttribute(this.eInput, 'placeholder', placeholder);\n return this;\n };\n AgAbstractInputField.prototype.setInputAriaLabel = function (label) {\n setAriaLabel(this.eInput, label);\n return this;\n };\n AgAbstractInputField.prototype.setDisabled = function (disabled) {\n setDisabled(this.eInput, disabled);\n return _super.prototype.setDisabled.call(this, disabled);\n };\n __decorate$2h([\n RefSelector('eLabel')\n ], AgAbstractInputField.prototype, \"eLabel\", void 0);\n __decorate$2h([\n RefSelector('eWrapper')\n ], AgAbstractInputField.prototype, \"eWrapper\", void 0);\n __decorate$2h([\n RefSelector('eInput')\n ], AgAbstractInputField.prototype, \"eInput\", void 0);\n return AgAbstractInputField;\n}(AgAbstractField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2E = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2g = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ConditionPosition;\n(function (ConditionPosition) {\n ConditionPosition[ConditionPosition[\"One\"] = 0] = \"One\";\n ConditionPosition[ConditionPosition[\"Two\"] = 1] = \"Two\";\n})(ConditionPosition || (ConditionPosition = {}));\n/**\n * Every filter with a dropdown where the user can specify a comparing type against the filter values.\n *\n * @param M type of filter-model managed by the concrete sub-class that extends this type\n * @param V type of value managed by the concrete sub-class that extends this type\n * @param E type of UI element used for collecting user-input\n */\nvar SimpleFilter = /** @class */ (function (_super) {\n __extends$2E(SimpleFilter, _super);\n function SimpleFilter() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SimpleFilter.prototype.getNumberOfInputs = function (type) {\n var customOpts = this.optionsFactory.getCustomOption(type);\n if (customOpts) {\n var numberOfInputs = customOpts.numberOfInputs;\n return numberOfInputs != null ? numberOfInputs : 1;\n }\n var zeroInputTypes = [\n SimpleFilter.EMPTY, SimpleFilter.NOT_BLANK, SimpleFilter.BLANK,\n ];\n if (type && zeroInputTypes.indexOf(type) >= 0) {\n return 0;\n }\n else if (type === SimpleFilter.IN_RANGE) {\n return 2;\n }\n return 1;\n };\n // floating filter calls this when user applies filter from floating filter\n SimpleFilter.prototype.onFloatingFilterChanged = function (type, value) {\n this.setTypeFromFloatingFilter(type);\n this.setValueFromFloatingFilter(value);\n this.onUiChanged(true);\n };\n SimpleFilter.prototype.setTypeFromFloatingFilter = function (type) {\n this.eType1.setValue(type);\n this.eType2.setValue(this.optionsFactory.getDefaultOption());\n (this.isDefaultOperator('AND') ? this.eJoinOperatorAnd : this.eJoinOperatorOr).setValue(true);\n };\n SimpleFilter.prototype.getModelFromUi = function () {\n if (!this.isConditionUiComplete(ConditionPosition.One)) {\n return null;\n }\n if (this.isAllowTwoConditions() && this.isConditionUiComplete(ConditionPosition.Two)) {\n return {\n filterType: this.getFilterType(),\n operator: this.getJoinOperator(),\n condition1: this.createCondition(ConditionPosition.One),\n condition2: this.createCondition(ConditionPosition.Two)\n };\n }\n return this.createCondition(ConditionPosition.One);\n };\n SimpleFilter.prototype.getConditionTypes = function () {\n return [\n this.eType1.getValue(),\n this.eType2.getValue(),\n ];\n };\n SimpleFilter.prototype.getJoinOperator = function () {\n return this.eJoinOperatorOr.getValue() === true ? 'OR' : 'AND';\n };\n SimpleFilter.prototype.areModelsEqual = function (a, b) {\n // both are missing\n if (!a && !b) {\n return true;\n }\n // one is missing, other present\n if ((!a && b) || (a && !b)) {\n return false;\n }\n // one is combined, the other is not\n var aIsSimple = !a.operator;\n var bIsSimple = !b.operator;\n var oneSimpleOneCombined = (!aIsSimple && bIsSimple) || (aIsSimple && !bIsSimple);\n if (oneSimpleOneCombined) {\n return false;\n }\n var res;\n // otherwise both present, so compare\n if (aIsSimple) {\n var aSimple = a;\n var bSimple = b;\n res = this.areSimpleModelsEqual(aSimple, bSimple);\n }\n else {\n var aCombined = a;\n var bCombined = b;\n res = aCombined.operator === bCombined.operator\n && this.areSimpleModelsEqual(aCombined.condition1, bCombined.condition1)\n && this.areSimpleModelsEqual(aCombined.condition2, bCombined.condition2);\n }\n return res;\n };\n SimpleFilter.prototype.setModelIntoUi = function (model) {\n var isCombined = model.operator;\n if (isCombined) {\n var combinedModel = model;\n var orChecked = combinedModel.operator === 'OR';\n this.eJoinOperatorAnd.setValue(!orChecked);\n this.eJoinOperatorOr.setValue(orChecked);\n this.eType1.setValue(combinedModel.condition1.type);\n this.eType2.setValue(combinedModel.condition2.type);\n this.setConditionIntoUi(combinedModel.condition1, ConditionPosition.One);\n this.setConditionIntoUi(combinedModel.condition2, ConditionPosition.Two);\n }\n else {\n var simpleModel = model;\n this.eJoinOperatorAnd.setValue(this.isDefaultOperator('AND'));\n this.eJoinOperatorOr.setValue(this.isDefaultOperator('OR'));\n this.eType1.setValue(simpleModel.type);\n this.eType2.setValue(this.optionsFactory.getDefaultOption());\n this.setConditionIntoUi(simpleModel, ConditionPosition.One);\n this.setConditionIntoUi(null, ConditionPosition.Two);\n }\n return AgPromise.resolve();\n };\n SimpleFilter.prototype.doesFilterPass = function (params) {\n var _this = this;\n var model = this.getModel();\n if (model == null) {\n return true;\n }\n var operator = model.operator;\n var models = [];\n if (operator) {\n var combinedModel = model;\n models.push(combinedModel.condition1, combinedModel.condition2);\n }\n else {\n models.push(model);\n }\n var combineFunction = operator && operator === 'OR' ? 'some' : 'every';\n return models[combineFunction](function (m) { return _this.individualConditionPasses(params, m); });\n };\n SimpleFilter.prototype.setParams = function (params) {\n _super.prototype.setParams.call(this, params);\n this.optionsFactory = new OptionsFactory();\n this.optionsFactory.init(params, this.getDefaultFilterOptions());\n this.allowTwoConditions = !params.suppressAndOrCondition;\n this.alwaysShowBothConditions = !!params.alwaysShowBothConditions;\n this.defaultJoinOperator = this.getDefaultJoinOperator(params.defaultJoinOperator);\n this.putOptionsIntoDropdown();\n this.addChangedListeners();\n };\n SimpleFilter.prototype.getDefaultJoinOperator = function (defaultJoinOperator) {\n return includes(['AND', 'OR'], defaultJoinOperator) ? defaultJoinOperator : 'AND';\n };\n SimpleFilter.prototype.putOptionsIntoDropdown = function () {\n var _this = this;\n var filterOptions = this.optionsFactory.getFilterOptions();\n var eTypes = [this.eType1, this.eType2];\n // Add specified options to all condition drop-downs.\n filterOptions.forEach(function (option) {\n var listOption = typeof option === 'string' ?\n _this.createBoilerplateListOption(option) :\n _this.createCustomListOption(option);\n eTypes.forEach(function (eType) { return eType.addOption(listOption); });\n });\n // Make drop-downs read-only if there is only one option.\n eTypes.forEach(function (eType) { return eType.setDisabled(filterOptions.length <= 1); });\n };\n SimpleFilter.prototype.createBoilerplateListOption = function (option) {\n return { value: option, text: this.translate(option) };\n };\n SimpleFilter.prototype.createCustomListOption = function (option) {\n var displayKey = option.displayKey;\n var customOption = this.optionsFactory.getCustomOption(option.displayKey);\n return {\n value: displayKey,\n text: customOption ?\n this.gridOptionsWrapper.getLocaleTextFunc()(customOption.displayKey, customOption.displayName) :\n this.translate(displayKey),\n };\n };\n SimpleFilter.prototype.isAllowTwoConditions = function () {\n return this.allowTwoConditions;\n };\n SimpleFilter.prototype.createBodyTemplate = function () {\n return /* html */ \"\\n <ag-select class=\\\"ag-filter-select\\\" ref=\\\"eOptions1\\\"></ag-select>\\n \" + this.createValueTemplate(ConditionPosition.One) + \"\\n <div class=\\\"ag-filter-condition\\\" ref=\\\"eJoinOperatorPanel\\\">\\n <ag-radio-button ref=\\\"eJoinOperatorAnd\\\" class=\\\"ag-filter-condition-operator ag-filter-condition-operator-and\\\"></ag-radio-button>\\n <ag-radio-button ref=\\\"eJoinOperatorOr\\\" class=\\\"ag-filter-condition-operator ag-filter-condition-operator-or\\\"></ag-radio-button>\\n </div>\\n <ag-select class=\\\"ag-filter-select\\\" ref=\\\"eOptions2\\\"></ag-select>\\n \" + this.createValueTemplate(ConditionPosition.Two);\n };\n SimpleFilter.prototype.getCssIdentifier = function () {\n return 'simple-filter';\n };\n SimpleFilter.prototype.updateUiVisibility = function () {\n var _this = this;\n var elementConditionGroups = [\n [this.eType1],\n [this.eType2, this.eJoinOperatorPanel, this.eJoinOperatorAnd, this.eJoinOperatorOr],\n ];\n var elementBodies = [this.eCondition1Body, this.eCondition2Body];\n elementConditionGroups.forEach(function (group, position) {\n var visible = _this.isConditionVisible(position);\n var disabled = _this.isConditionDisabled(position);\n group.forEach(function (element) {\n if (element instanceof AgAbstractInputField || element instanceof AgSelect) {\n element.setDisabled(disabled);\n element.setDisplayed(visible);\n }\n else {\n setDisabled(element, disabled);\n setDisplayed(element, visible);\n }\n });\n });\n elementBodies.forEach(function (element, index) {\n setDisplayed(element, _this.isConditionBodyVisible(index));\n });\n this.forEachInput(function (element, index, position, numberOfInputs) {\n _this.setElementDisplayed(element, index < numberOfInputs);\n _this.setElementDisabled(element, _this.isConditionDisabled(position));\n });\n this.resetPlaceholder();\n };\n SimpleFilter.prototype.afterGuiAttached = function (params) {\n _super.prototype.afterGuiAttached.call(this, params);\n this.resetPlaceholder();\n if (!params || (!params.suppressFocus && !this.isReadOnly())) {\n var firstInput = this.getInputs()[0][0];\n if (!firstInput) {\n return;\n }\n if (firstInput instanceof AgAbstractInputField) {\n firstInput.getInputElement().focus();\n }\n }\n };\n // allow sub-classes to reset HTML placeholders after UI update.\n SimpleFilter.prototype.resetPlaceholder = function () {\n var _this = this;\n var globalTranslate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.forEachInput(function (element, index, _, numberOfInputs) {\n if (!(element instanceof AgAbstractInputField)) {\n return;\n }\n var placeholder = index === 0 && numberOfInputs > 1 ? 'inRangeStart' :\n index === 0 ? 'filterOoo' :\n 'inRangeEnd';\n var ariaLabel = index === 0 && numberOfInputs > 1 ? globalTranslate('ariaFilterFromValue', 'Filter from value') :\n index === 0 ? globalTranslate('ariaFilterValue', 'Filter Value') :\n globalTranslate('ariaFilterToValue', 'Filter to Value');\n element.setInputPlaceholder(_this.translate(placeholder));\n element.setInputAriaLabel(ariaLabel);\n });\n };\n SimpleFilter.prototype.setElementValue = function (element, value, silent) {\n if (element instanceof AgAbstractInputField) {\n element.setValue(value != null ? String(value) : null, silent);\n }\n };\n SimpleFilter.prototype.setElementDisplayed = function (element, displayed) {\n if (element instanceof Component) {\n setDisplayed(element.getGui(), displayed);\n }\n };\n SimpleFilter.prototype.setElementDisabled = function (element, disabled) {\n if (element instanceof Component) {\n setDisabled(element.getGui(), disabled);\n }\n };\n SimpleFilter.prototype.attachElementOnChange = function (element, listener) {\n if (element instanceof AgAbstractInputField) {\n element.onValueChange(listener);\n }\n };\n SimpleFilter.prototype.forEachInput = function (cb) {\n var _this = this;\n var inputs = this.getInputs();\n this.getConditionTypes().forEach(function (type, position) {\n var numberOfInputs = _this.getNumberOfInputs(type);\n for (var index = 0; index < inputs[position].length; index++) {\n var input = inputs[position][index];\n if (input != null) {\n cb(input, index, position, numberOfInputs);\n }\n }\n });\n };\n SimpleFilter.prototype.isConditionVisible = function (position) {\n if (position === 0) {\n return true;\n } // Position 0 should always be visible.\n if (!this.allowTwoConditions) {\n return false;\n } // Short-circuit if no tail conditions.\n if (this.isReadOnly()) {\n // Only display a condition when read-only if the condition is complete.\n return this.isConditionUiComplete(position);\n }\n if (this.alwaysShowBothConditions) {\n return true;\n }\n // Only display a 2nd or later condition when the previous condition is complete.\n return this.isConditionUiComplete(position - 1);\n };\n SimpleFilter.prototype.isConditionDisabled = function (position) {\n if (this.isReadOnly()) {\n return true;\n } // Read-only mode trumps everything.\n if (!this.isConditionVisible(position)) {\n return true;\n } // Invisible implies disabled.\n if (position === 0) {\n return false;\n } // Position 0 should typically be editable.\n // Only allow editing of a 2nd or later condition if the previous condition is complete.\n return !this.isConditionUiComplete(position - 1);\n };\n SimpleFilter.prototype.isConditionBodyVisible = function (position) {\n if (!this.isConditionVisible(position)) {\n return false;\n }\n // Check that the condition needs inputs.\n var type = this.getConditionTypes()[position];\n var numberOfInputs = this.getNumberOfInputs(type);\n return numberOfInputs > 0;\n };\n // returns true if the UI represents a working filter, eg all parts are filled out.\n // eg if text filter and textfield blank then returns false.\n SimpleFilter.prototype.isConditionUiComplete = function (position) {\n var type = this.getConditionTypes()[position];\n if (type === SimpleFilter.EMPTY) {\n return false;\n }\n if (this.getValues(position).some(function (v) { return v == null; })) {\n return false;\n }\n return true;\n };\n SimpleFilter.prototype.resetUiToDefaults = function (silent) {\n var _this = this;\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var filteringLabel = translate('ariaFilteringOperator', 'Filtering operator');\n var uniqueGroupId = 'ag-simple-filter-and-or-' + this.getCompId();\n var defaultOption = this.optionsFactory.getDefaultOption();\n this.eType1\n .setValue(defaultOption, silent)\n .setAriaLabel(filteringLabel)\n .setDisabled(this.isReadOnly());\n this.eType2\n .setValue(this.optionsFactory.getDefaultOption(), silent)\n .setAriaLabel(filteringLabel)\n .setDisabled(this.isReadOnly());\n this.eJoinOperatorAnd\n .setValue(this.isDefaultOperator('AND'), silent)\n .setName(uniqueGroupId)\n .setLabel(this.translate('andCondition'))\n .setDisabled(this.isReadOnly());\n this.eJoinOperatorOr\n .setValue(this.isDefaultOperator('OR'), silent)\n .setName(uniqueGroupId)\n .setLabel(this.translate('orCondition'))\n .setDisabled(this.isReadOnly());\n this.forEachInput(function (element) {\n _this.setElementValue(element, null, silent);\n _this.setElementDisabled(element, _this.isReadOnly());\n });\n this.resetPlaceholder();\n return AgPromise.resolve();\n };\n // puts model values into the UI\n SimpleFilter.prototype.setConditionIntoUi = function (model, position) {\n var _this = this;\n var values = this.mapValuesFromModel(model);\n this.forEachInput(function (element, index, elPosition, _) {\n if (elPosition !== position) {\n return;\n }\n _this.setElementValue(element, values[index] != null ? values[index] : null);\n });\n };\n // after floating filter changes, this sets the 'value' section. this is implemented by the base class\n // (as that's where value is controlled), the 'type' part from the floating filter is dealt with in this class.\n SimpleFilter.prototype.setValueFromFloatingFilter = function (value) {\n var _this = this;\n this.forEachInput(function (element, index, position, _) {\n _this.setElementValue(element, index === 0 && position === 0 ? value : null);\n });\n };\n SimpleFilter.prototype.isDefaultOperator = function (operator) {\n return operator === this.defaultJoinOperator;\n };\n SimpleFilter.prototype.addChangedListeners = function () {\n var _this = this;\n if (this.isReadOnly()) {\n return;\n }\n var listener = function () { return _this.onUiChanged(); };\n this.eType1.onValueChange(listener);\n this.eType2.onValueChange(listener);\n this.eJoinOperatorOr.onValueChange(listener);\n this.eJoinOperatorAnd.onValueChange(listener);\n this.forEachInput(function (element) {\n _this.attachElementOnChange(element, listener);\n });\n };\n /** returns true if the row passes the said condition */\n SimpleFilter.prototype.individualConditionPasses = function (params, filterModel) {\n var cellValue = this.getCellValue(params.node);\n var values = this.mapValuesFromModel(filterModel);\n var customFilterOption = this.optionsFactory.getCustomOption(filterModel.type);\n var customFilterResult = this.evaluateCustomFilter(customFilterOption, values, cellValue);\n if (customFilterResult != null) {\n return customFilterResult;\n }\n if (cellValue == null) {\n return this.evaluateNullValue(filterModel.type);\n }\n return this.evaluateNonNullValue(values, cellValue, filterModel, params);\n };\n SimpleFilter.prototype.evaluateCustomFilter = function (customFilterOption, values, cellValue) {\n if (customFilterOption == null) {\n return;\n }\n var predicate = customFilterOption.predicate;\n // only execute the custom filter if a value exists or a value isn't required, i.e. input is hidden\n if (predicate != null && !values.some(function (v) { return v == null; })) {\n return predicate(values, cellValue);\n }\n // No custom filter invocation, indicate that to the caller.\n return;\n };\n SimpleFilter.prototype.isBlank = function (cellValue) {\n return cellValue == null ||\n (typeof cellValue === 'string' && cellValue.trim().length === 0);\n };\n SimpleFilter.EMPTY = 'empty';\n SimpleFilter.BLANK = 'blank';\n SimpleFilter.NOT_BLANK = 'notBlank';\n SimpleFilter.EQUALS = 'equals';\n SimpleFilter.NOT_EQUAL = 'notEqual';\n SimpleFilter.LESS_THAN = 'lessThan';\n SimpleFilter.LESS_THAN_OR_EQUAL = 'lessThanOrEqual';\n SimpleFilter.GREATER_THAN = 'greaterThan';\n SimpleFilter.GREATER_THAN_OR_EQUAL = 'greaterThanOrEqual';\n SimpleFilter.IN_RANGE = 'inRange';\n SimpleFilter.CONTAINS = 'contains';\n SimpleFilter.NOT_CONTAINS = 'notContains';\n SimpleFilter.STARTS_WITH = 'startsWith';\n SimpleFilter.ENDS_WITH = 'endsWith';\n __decorate$2g([\n RefSelector('eOptions1')\n ], SimpleFilter.prototype, \"eType1\", void 0);\n __decorate$2g([\n RefSelector('eOptions2')\n ], SimpleFilter.prototype, \"eType2\", void 0);\n __decorate$2g([\n RefSelector('eJoinOperatorPanel')\n ], SimpleFilter.prototype, \"eJoinOperatorPanel\", void 0);\n __decorate$2g([\n RefSelector('eJoinOperatorAnd')\n ], SimpleFilter.prototype, \"eJoinOperatorAnd\", void 0);\n __decorate$2g([\n RefSelector('eJoinOperatorOr')\n ], SimpleFilter.prototype, \"eJoinOperatorOr\", void 0);\n __decorate$2g([\n RefSelector('eCondition1Body')\n ], SimpleFilter.prototype, \"eCondition1Body\", void 0);\n __decorate$2g([\n RefSelector('eCondition2Body')\n ], SimpleFilter.prototype, \"eCondition2Body\", void 0);\n return SimpleFilter;\n}(ProvidedFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2D = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar ScalarFilter = /** @class */ (function (_super) {\n __extends$2D(ScalarFilter, _super);\n function ScalarFilter() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ScalarFilter.prototype.setParams = function (params) {\n _super.prototype.setParams.call(this, params);\n this.scalarFilterParams = params;\n };\n ScalarFilter.prototype.evaluateNullValue = function (filterType) {\n switch (filterType) {\n case ScalarFilter.EQUALS:\n case ScalarFilter.NOT_EQUAL:\n if (this.scalarFilterParams.includeBlanksInEquals) {\n return true;\n }\n break;\n case ScalarFilter.GREATER_THAN:\n case ScalarFilter.GREATER_THAN_OR_EQUAL:\n if (this.scalarFilterParams.includeBlanksInGreaterThan) {\n return true;\n }\n break;\n case ScalarFilter.LESS_THAN:\n case ScalarFilter.LESS_THAN_OR_EQUAL:\n if (this.scalarFilterParams.includeBlanksInLessThan) {\n return true;\n }\n break;\n case ScalarFilter.IN_RANGE:\n if (this.scalarFilterParams.includeBlanksInRange) {\n return true;\n }\n break;\n case ScalarFilter.BLANK:\n return true;\n case ScalarFilter.NOT_BLANK:\n return false;\n }\n return false;\n };\n ScalarFilter.prototype.evaluateNonNullValue = function (values, cellValue, filterModel) {\n var comparator = this.comparator();\n var compareResult = values[0] != null ? comparator(values[0], cellValue) : 0;\n switch (filterModel.type) {\n case ScalarFilter.EQUALS:\n return compareResult === 0;\n case ScalarFilter.NOT_EQUAL:\n return compareResult !== 0;\n case ScalarFilter.GREATER_THAN:\n return compareResult > 0;\n case ScalarFilter.GREATER_THAN_OR_EQUAL:\n return compareResult >= 0;\n case ScalarFilter.LESS_THAN:\n return compareResult < 0;\n case ScalarFilter.LESS_THAN_OR_EQUAL:\n return compareResult <= 0;\n case ScalarFilter.IN_RANGE: {\n var compareToResult = comparator(values[1], cellValue);\n return this.scalarFilterParams.inRangeInclusive ?\n compareResult >= 0 && compareToResult <= 0 :\n compareResult > 0 && compareToResult < 0;\n }\n case ScalarFilter.BLANK:\n return this.isBlank(cellValue);\n case ScalarFilter.NOT_BLANK:\n return !this.isBlank(cellValue);\n default:\n console.warn('AG Grid: Unexpected type of filter \"' + filterModel.type + '\", it looks like the filter was configured with incorrect Filter Options');\n return true;\n }\n };\n return ScalarFilter;\n}(SimpleFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2C = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$b = (undefined && undefined.__assign) || function () {\n __assign$b = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$b.apply(this, arguments);\n};\nvar __decorate$2f = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar DEFAULT_MIN_YEAR = 1000;\nvar DEFAULT_MAX_YEAR = Infinity;\nvar DateFilter = /** @class */ (function (_super) {\n __extends$2C(DateFilter, _super);\n function DateFilter() {\n var _this = _super.call(this, 'dateFilter') || this;\n _this.minValidYear = DEFAULT_MIN_YEAR;\n _this.maxValidYear = DEFAULT_MAX_YEAR;\n return _this;\n }\n DateFilter.prototype.afterGuiAttached = function (params) {\n _super.prototype.afterGuiAttached.call(this, params);\n this.dateCondition1FromComp.afterGuiAttached(params);\n };\n DateFilter.prototype.mapValuesFromModel = function (filterModel) {\n // unlike the other filters, we do two things here:\n // 1) allow for different attribute names (same as done for other filters) (eg the 'from' and 'to'\n // are in different locations in Date and Number filter models)\n // 2) convert the type (because Date filter uses Dates, however model is 'string')\n //\n // NOTE: The conversion of string to date also removes the timezone - i.e. when user picks\n // a date from the UI, it will have timezone info in it. This is lost when creating\n // the model. When we recreate the date again here, it's without a timezone.\n var _a = filterModel || {}, dateFrom = _a.dateFrom, dateTo = _a.dateTo, type = _a.type;\n return [\n dateFrom && parseDateTimeFromString(dateFrom) || null,\n dateTo && parseDateTimeFromString(dateTo) || null,\n ].slice(0, this.getNumberOfInputs(type));\n };\n DateFilter.prototype.comparator = function () {\n return this.dateFilterParams.comparator ? this.dateFilterParams.comparator : this.defaultComparator.bind(this);\n };\n DateFilter.prototype.defaultComparator = function (filterDate, cellValue) {\n // The default comparator assumes that the cellValue is a date\n var cellAsDate = cellValue;\n if (cellValue == null || cellAsDate < filterDate) {\n return -1;\n }\n if (cellAsDate > filterDate) {\n return 1;\n }\n return 0;\n };\n DateFilter.prototype.setParams = function (params) {\n _super.prototype.setParams.call(this, params);\n this.dateFilterParams = params;\n var yearParser = function (param, fallback) {\n if (params[param] != null) {\n if (!isNaN(params[param])) {\n return params[param] == null ? fallback : Number(params[param]);\n }\n else {\n console.warn(\"AG Grid: DateFilter \" + param + \" is not a number\");\n }\n }\n return fallback;\n };\n this.minValidYear = yearParser('minValidYear', DEFAULT_MIN_YEAR);\n this.maxValidYear = yearParser('maxValidYear', DEFAULT_MAX_YEAR);\n if (this.minValidYear > this.maxValidYear) {\n console.warn(\"AG Grid: DateFilter minValidYear should be <= maxValidYear\");\n }\n this.createDateComponents();\n };\n DateFilter.prototype.createDateComponents = function () {\n var _this = this;\n var createDateCompWrapper = function (element) {\n return new DateCompWrapper(_this.getContext(), _this.userComponentFactory, {\n onDateChanged: function () { return _this.onUiChanged(); },\n filterParams: _this.dateFilterParams\n }, element);\n };\n this.dateCondition1FromComp = createDateCompWrapper(this.eCondition1PanelFrom);\n this.dateCondition1ToComp = createDateCompWrapper(this.eCondition1PanelTo);\n this.dateCondition2FromComp = createDateCompWrapper(this.eCondition2PanelFrom);\n this.dateCondition2ToComp = createDateCompWrapper(this.eCondition2PanelTo);\n this.addDestroyFunc(function () {\n _this.forEachInput(function (element) { return element.destroy(); });\n });\n };\n DateFilter.prototype.setElementValue = function (element, value, silent) {\n element.setDate(value);\n };\n DateFilter.prototype.setElementDisplayed = function (element, displayed) {\n element.setDisplayed(displayed);\n };\n DateFilter.prototype.setElementDisabled = function (element, disabled) {\n element.setDisabled(disabled);\n };\n DateFilter.prototype.getDefaultFilterOptions = function () {\n return DateFilter.DEFAULT_FILTER_OPTIONS;\n };\n DateFilter.prototype.createValueTemplate = function (position) {\n var pos = position === ConditionPosition.One ? '1' : '2';\n return /* html */ \"\\n <div class=\\\"ag-filter-body\\\" ref=\\\"eCondition\" + pos + \"Body\\\">\\n <div class=\\\"ag-filter-from ag-filter-date-from\\\" ref=\\\"eCondition\" + pos + \"PanelFrom\\\"></div>\\n <div class=\\\"ag-filter-to ag-filter-date-to\\\" ref=\\\"eCondition\" + pos + \"PanelTo\\\"></div>\\n </div>\";\n };\n DateFilter.prototype.isConditionUiComplete = function (position) {\n var _this = this;\n if (!_super.prototype.isConditionUiComplete.call(this, position)) {\n return false;\n }\n var isValidDate = function (value) { return value != null\n && value.getUTCFullYear() >= _this.minValidYear\n && value.getUTCFullYear() <= _this.maxValidYear; };\n var valid = true;\n this.forEachInput(function (element, index, elPosition, numberOfInputs) {\n if (elPosition !== position || !valid || index >= numberOfInputs) {\n return;\n }\n valid = valid && isValidDate(element.getDate());\n });\n return valid;\n };\n DateFilter.prototype.areSimpleModelsEqual = function (aSimple, bSimple) {\n return aSimple.dateFrom === bSimple.dateFrom\n && aSimple.dateTo === bSimple.dateTo\n && aSimple.type === bSimple.type;\n };\n DateFilter.prototype.getFilterType = function () {\n return 'date';\n };\n DateFilter.prototype.createCondition = function (position) {\n var type = this.getConditionTypes()[position];\n var model = {};\n var values = this.getValues(position);\n if (values.length > 0) {\n model.dateFrom = serialiseDate(values[0]);\n }\n if (values.length > 1) {\n model.dateTo = serialiseDate(values[1]);\n }\n return __assign$b({ dateFrom: null, dateTo: null, filterType: this.getFilterType(), type: type }, model);\n };\n DateFilter.prototype.resetPlaceholder = function () {\n var globalTranslate = this.gridOptionsWrapper.getLocaleTextFunc();\n var placeholder = this.translate('dateFormatOoo');\n var ariaLabel = globalTranslate('ariaFilterValue', 'Filter Value');\n this.forEachInput(function (element) {\n element.setInputPlaceholder(placeholder);\n element.setInputAriaLabel(ariaLabel);\n });\n };\n DateFilter.prototype.getInputs = function () {\n return [\n [this.dateCondition1FromComp, this.dateCondition1ToComp],\n [this.dateCondition2FromComp, this.dateCondition2ToComp],\n ];\n };\n DateFilter.prototype.getValues = function (position) {\n var result = [];\n this.forEachInput(function (element, index, elPosition, numberOfInputs) {\n if (position === elPosition && index < numberOfInputs) {\n result.push(element.getDate());\n }\n });\n return result;\n };\n DateFilter.DEFAULT_FILTER_OPTIONS = [\n ScalarFilter.EQUALS,\n ScalarFilter.GREATER_THAN,\n ScalarFilter.LESS_THAN,\n ScalarFilter.NOT_EQUAL,\n ScalarFilter.IN_RANGE,\n ScalarFilter.BLANK,\n ScalarFilter.NOT_BLANK,\n ];\n __decorate$2f([\n RefSelector('eCondition1PanelFrom')\n ], DateFilter.prototype, \"eCondition1PanelFrom\", void 0);\n __decorate$2f([\n RefSelector('eCondition1PanelTo')\n ], DateFilter.prototype, \"eCondition1PanelTo\", void 0);\n __decorate$2f([\n RefSelector('eCondition2PanelFrom')\n ], DateFilter.prototype, \"eCondition2PanelFrom\", void 0);\n __decorate$2f([\n RefSelector('eCondition2PanelTo')\n ], DateFilter.prototype, \"eCondition2PanelTo\", void 0);\n __decorate$2f([\n Autowired('userComponentFactory')\n ], DateFilter.prototype, \"userComponentFactory\", void 0);\n return DateFilter;\n}(ScalarFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2B = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar SimpleFloatingFilter = /** @class */ (function (_super) {\n __extends$2B(SimpleFloatingFilter, _super);\n function SimpleFloatingFilter() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SimpleFloatingFilter.prototype.getDefaultDebounceMs = function () {\n return 0;\n };\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n SimpleFloatingFilter.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n // used by:\n // 1) NumberFloatingFilter & TextFloatingFilter: Always, for both when editable and read only.\n // 2) DateFloatingFilter: Only when read only (as we show text rather than a date picker when read only)\n SimpleFloatingFilter.prototype.getTextFromModel = function (model) {\n if (!model) {\n return null;\n }\n var isCombined = model.operator != null;\n if (isCombined) {\n var combinedModel = model;\n var _a = combinedModel || {}, condition1 = _a.condition1, condition2 = _a.condition2;\n var customOption1 = this.getTextFromModel(condition1);\n var customOption2 = this.getTextFromModel(condition2);\n return [\n customOption1,\n combinedModel.operator,\n customOption2,\n ].join(' ');\n }\n else {\n var condition = model;\n var customOption = this.optionsFactory.getCustomOption(condition.type);\n // For custom filter options we display the Name of the filter instead\n // of displaying the `from` value, as it wouldn't be relevant\n var _b = customOption || {}, displayKey = _b.displayKey, displayName = _b.displayName, numberOfInputs = _b.numberOfInputs;\n if (displayKey && displayName && numberOfInputs === 0) {\n this.gridOptionsWrapper.getLocaleTextFunc()(displayKey, displayName);\n return displayName;\n }\n return this.conditionToString(condition, customOption);\n }\n };\n SimpleFloatingFilter.prototype.isEventFromFloatingFilter = function (event) {\n return event && event.afterFloatingFilter;\n };\n SimpleFloatingFilter.prototype.getLastType = function () {\n return this.lastType;\n };\n SimpleFloatingFilter.prototype.isReadOnly = function () {\n return this.readOnly;\n };\n SimpleFloatingFilter.prototype.setLastTypeFromModel = function (model) {\n // if no model provided by the parent filter use default\n if (!model) {\n this.lastType = this.optionsFactory.getDefaultOption();\n return;\n }\n var isCombined = model.operator;\n var condition;\n if (isCombined) {\n var combinedModel = model;\n condition = combinedModel.condition1;\n }\n else {\n condition = model;\n }\n this.lastType = condition.type;\n };\n SimpleFloatingFilter.prototype.canWeEditAfterModelFromParentFilter = function (model) {\n if (!model) {\n // if no model, then we can edit as long as the lastType is something we can edit, as this\n // is the type we will provide to the parent filter if the user decides to use the floating filter.\n return this.isTypeEditable(this.lastType);\n }\n // never allow editing if the filter is combined (ie has two parts)\n var isCombined = model.operator;\n if (isCombined) {\n return false;\n }\n var simpleModel = model;\n return this.isTypeEditable(simpleModel.type);\n };\n SimpleFloatingFilter.prototype.init = function (params) {\n this.optionsFactory = new OptionsFactory();\n this.optionsFactory.init(params.filterParams, this.getDefaultFilterOptions());\n this.lastType = this.optionsFactory.getDefaultOption();\n // readOnly is a property of IProvidedFilterParams - we need to find a better (type-safe)\n // way to support reading this in the future.\n this.readOnly = !!params.filterParams.readOnly;\n // we are editable if:\n // 1) there is a type (user has configured filter wrong if not type)\n // AND\n // 2) the default type is not 'in range'\n var editable = this.isTypeEditable(this.lastType);\n this.setEditable(editable);\n };\n SimpleFloatingFilter.prototype.doesFilterHaveSingleInput = function (filterType) {\n var customFilterOption = this.optionsFactory.getCustomOption(filterType);\n var numberOfInputs = (customFilterOption || {}).numberOfInputs;\n return numberOfInputs == null || numberOfInputs == 1;\n };\n SimpleFloatingFilter.prototype.isTypeEditable = function (type) {\n var uneditableTypes = [\n SimpleFilter.IN_RANGE, SimpleFilter.EMPTY, SimpleFilter.BLANK, SimpleFilter.NOT_BLANK,\n ];\n return !!type &&\n !this.isReadOnly() &&\n this.doesFilterHaveSingleInput(type) &&\n uneditableTypes.indexOf(type) < 0;\n };\n return SimpleFloatingFilter;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2A = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2e = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar DateFloatingFilter = /** @class */ (function (_super) {\n __extends$2A(DateFloatingFilter, _super);\n function DateFloatingFilter() {\n return _super.call(this, /* html */ \"\\n <div class=\\\"ag-floating-filter-input\\\" role=\\\"presentation\\\">\\n <ag-input-text-field ref=\\\"eReadOnlyText\\\"></ag-input-text-field>\\n <div ref=\\\"eDateWrapper\\\" style=\\\"display: flex;\\\"></div>\\n </div>\") || this;\n }\n DateFloatingFilter.prototype.getDefaultFilterOptions = function () {\n return DateFilter.DEFAULT_FILTER_OPTIONS;\n };\n DateFloatingFilter.prototype.conditionToString = function (condition, options) {\n var type = condition.type;\n var numberOfInputs = (options || {}).numberOfInputs;\n var isRange = type == SimpleFilter.IN_RANGE || numberOfInputs === 2;\n var dateFrom = parseDateTimeFromString(condition.dateFrom);\n var dateTo = parseDateTimeFromString(condition.dateTo);\n var format = this.filterParams.inRangeFloatingFilterDateFormat;\n if (isRange) {\n var formattedFrom = dateFrom !== null ? dateToFormattedString(dateFrom, format) : 'null';\n var formattedTo = dateTo !== null ? dateToFormattedString(dateTo, format) : 'null';\n return formattedFrom + \"-\" + formattedTo;\n }\n if (dateFrom != null) {\n return dateToFormattedString(dateFrom, format);\n }\n // cater for when the type doesn't need a value\n return \"\" + type;\n };\n DateFloatingFilter.prototype.init = function (params) {\n _super.prototype.init.call(this, params);\n this.params = params;\n this.filterParams = params.filterParams;\n this.createDateComponent();\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.eReadOnlyText\n .setDisabled(true)\n .setInputAriaLabel(translate('ariaDateFilterInput', 'Date Filter Input'));\n };\n DateFloatingFilter.prototype.setEditable = function (editable) {\n setDisplayed(this.eDateWrapper, editable);\n setDisplayed(this.eReadOnlyText.getGui(), !editable);\n };\n DateFloatingFilter.prototype.onParentModelChanged = function (model, event) {\n // We don't want to update the floating filter if the floating filter caused the change,\n // because the UI is already in sync. if we didn't do this, the UI would behave strangely\n // as it would be updating as the user is typing\n if (this.isEventFromFloatingFilter(event)) {\n return;\n }\n _super.prototype.setLastTypeFromModel.call(this, model);\n var allowEditing = !this.isReadOnly() &&\n this.canWeEditAfterModelFromParentFilter(model);\n this.setEditable(allowEditing);\n if (allowEditing) {\n if (model) {\n var dateModel = model;\n this.dateComp.setDate(parseDateTimeFromString(dateModel.dateFrom));\n }\n else {\n this.dateComp.setDate(null);\n }\n this.eReadOnlyText.setValue('');\n }\n else {\n this.eReadOnlyText.setValue(this.getTextFromModel(model));\n this.dateComp.setDate(null);\n }\n };\n DateFloatingFilter.prototype.onDateChanged = function () {\n var _this = this;\n var filterValueDate = this.dateComp.getDate();\n var filterValueText = serialiseDate(filterValueDate);\n this.params.parentFilterInstance(function (filterInstance) {\n if (filterInstance) {\n var date = parseDateTimeFromString(filterValueText);\n filterInstance.onFloatingFilterChanged(_this.getLastType() || null, date);\n }\n });\n };\n DateFloatingFilter.prototype.createDateComponent = function () {\n var _this = this;\n var debounceMs = ProvidedFilter.getDebounceMs(this.params.filterParams, this.getDefaultDebounceMs());\n var dateComponentParams = {\n onDateChanged: debounce(this.onDateChanged.bind(this), debounceMs),\n filterParams: this.params.column.getColDef().filterParams\n };\n this.dateComp = new DateCompWrapper(this.getContext(), this.userComponentFactory, dateComponentParams, this.eDateWrapper);\n this.addDestroyFunc(function () { return _this.dateComp.destroy(); });\n };\n __decorate$2e([\n Autowired('userComponentFactory')\n ], DateFloatingFilter.prototype, \"userComponentFactory\", void 0);\n __decorate$2e([\n RefSelector('eReadOnlyText')\n ], DateFloatingFilter.prototype, \"eReadOnlyText\", void 0);\n __decorate$2e([\n RefSelector('eDateWrapper')\n ], DateFloatingFilter.prototype, \"eDateWrapper\", void 0);\n return DateFloatingFilter;\n}(SimpleFloatingFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2z = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2d = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar DefaultDateComponent = /** @class */ (function (_super) {\n __extends$2z(DefaultDateComponent, _super);\n function DefaultDateComponent() {\n return _super.call(this, /* html */ \"\\n <div class=\\\"ag-filter-filter\\\">\\n <ag-input-text-field class=\\\"ag-date-filter\\\" ref=\\\"eDateInput\\\"></ag-input-text-field>\\n </div>\") || this;\n }\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n DefaultDateComponent.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n DefaultDateComponent.prototype.init = function (params) {\n var _this = this;\n var eDocument = this.gridOptionsWrapper.getDocument();\n var inputElement = this.eDateInput.getInputElement();\n if (this.shouldUseBrowserDatePicker(params)) {\n inputElement.type = 'date';\n }\n // ensures that the input element is focussed when a clear button is clicked\n this.addManagedListener(inputElement, 'mousedown', function () {\n if (_this.eDateInput.isDisabled()) {\n return;\n }\n inputElement.focus();\n });\n this.addManagedListener(inputElement, 'input', function (e) {\n if (e.target !== eDocument.activeElement) {\n return;\n }\n if (_this.eDateInput.isDisabled()) {\n return;\n }\n params.onDateChanged();\n });\n var _a = params.filterParams || {}, minValidYear = _a.minValidYear, maxValidYear = _a.maxValidYear;\n if (minValidYear) {\n inputElement.min = minValidYear + \"-01-01\";\n }\n if (maxValidYear) {\n inputElement.max = maxValidYear + \"-12-31\";\n }\n };\n DefaultDateComponent.prototype.getDate = function () {\n return parseDateTimeFromString(this.eDateInput.getValue());\n };\n DefaultDateComponent.prototype.setDate = function (date) {\n this.eDateInput.setValue(serialiseDate(date, false));\n };\n DefaultDateComponent.prototype.setInputPlaceholder = function (placeholder) {\n this.eDateInput.setInputPlaceholder(placeholder);\n };\n DefaultDateComponent.prototype.setDisabled = function (disabled) {\n this.eDateInput.setDisabled(disabled);\n };\n DefaultDateComponent.prototype.afterGuiAttached = function (params) {\n if (!params || !params.suppressFocus) {\n this.eDateInput.getInputElement().focus();\n }\n };\n DefaultDateComponent.prototype.shouldUseBrowserDatePicker = function (params) {\n if (params.filterParams && params.filterParams.browserDatePicker != null) {\n return params.filterParams.browserDatePicker;\n }\n return isBrowserChrome() || isBrowserFirefox();\n };\n __decorate$2d([\n RefSelector('eDateInput')\n ], DefaultDateComponent.prototype, \"eDateInput\", void 0);\n return DefaultDateComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2y = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2c = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar NumberFilter = /** @class */ (function (_super) {\n __extends$2y(NumberFilter, _super);\n function NumberFilter() {\n return _super.call(this, 'numberFilter') || this;\n }\n NumberFilter.prototype.mapValuesFromModel = function (filterModel) {\n var _a = filterModel || {}, filter = _a.filter, filterTo = _a.filterTo, type = _a.type;\n return [\n filter == null ? null : filter,\n filterTo == null ? null : filterTo,\n ].slice(0, this.getNumberOfInputs(type));\n };\n NumberFilter.prototype.getDefaultDebounceMs = function () {\n return 500;\n };\n NumberFilter.prototype.comparator = function () {\n return function (left, right) {\n if (left === right) {\n return 0;\n }\n return left < right ? 1 : -1;\n };\n };\n NumberFilter.prototype.setParams = function (params) {\n this.numberFilterParams = params;\n var allowedCharPattern = this.getAllowedCharPattern();\n if (allowedCharPattern) {\n var config = { allowedCharPattern: allowedCharPattern };\n this.resetTemplate({\n 'eValue-index0-1': config,\n 'eValue-index1-1': config,\n 'eValue-index0-2': config,\n 'eValue-index1-2': config,\n });\n }\n _super.prototype.setParams.call(this, params);\n };\n NumberFilter.prototype.getDefaultFilterOptions = function () {\n return NumberFilter.DEFAULT_FILTER_OPTIONS;\n };\n NumberFilter.prototype.createValueTemplate = function (position) {\n var pos = position === ConditionPosition.One ? '1' : '2';\n var allowedCharPattern = this.getAllowedCharPattern();\n var agElementTag = allowedCharPattern ? 'ag-input-text-field' : 'ag-input-number-field';\n return /* html */ \"\\n <div class=\\\"ag-filter-body\\\" ref=\\\"eCondition\" + pos + \"Body\\\" role=\\\"presentation\\\">\\n <\" + agElementTag + \" class=\\\"ag-filter-from ag-filter-filter\\\" ref=\\\"eValue-index0-\" + pos + \"\\\"></\" + agElementTag + \">\\n <\" + agElementTag + \" class=\\\"ag-filter-to ag-filter-filter\\\" ref=\\\"eValue-index1-\" + pos + \"\\\"></\" + agElementTag + \">\\n </div>\";\n };\n NumberFilter.prototype.getValues = function (position) {\n var _this = this;\n var result = [];\n this.forEachInput(function (element, index, elPosition, numberOfInputs) {\n if (position === elPosition && index < numberOfInputs) {\n result.push(_this.stringToFloat(element.getValue()));\n }\n });\n return result;\n };\n NumberFilter.prototype.areSimpleModelsEqual = function (aSimple, bSimple) {\n return aSimple.filter === bSimple.filter\n && aSimple.filterTo === bSimple.filterTo\n && aSimple.type === bSimple.type;\n };\n NumberFilter.prototype.getFilterType = function () {\n return 'number';\n };\n NumberFilter.prototype.stringToFloat = function (value) {\n if (typeof value === 'number') {\n return value;\n }\n var filterText = makeNull(value);\n if (filterText != null && filterText.trim() === '') {\n filterText = null;\n }\n if (this.numberFilterParams.numberParser) {\n return this.numberFilterParams.numberParser(filterText);\n }\n return filterText == null || filterText.trim() === '-' ? null : parseFloat(filterText);\n };\n NumberFilter.prototype.createCondition = function (position) {\n var type = this.getConditionTypes()[position];\n var model = {\n filterType: this.getFilterType(),\n type: type\n };\n var values = this.getValues(position);\n if (values.length > 0) {\n model.filter = values[0];\n }\n if (values.length > 1) {\n model.filterTo = values[1];\n }\n return model;\n };\n NumberFilter.prototype.getInputs = function () {\n return [\n [this.eValueFrom1, this.eValueTo1],\n [this.eValueFrom2, this.eValueTo2],\n ];\n };\n NumberFilter.prototype.getAllowedCharPattern = function () {\n var allowedCharPattern = (this.numberFilterParams || {}).allowedCharPattern;\n if (allowedCharPattern) {\n return allowedCharPattern;\n }\n if (!isBrowserChrome() && !isBrowserEdge()) {\n // only Chrome and Edge support the HTML5 number field, so for other browsers we provide an equivalent\n // constraint instead\n return '\\\\d\\\\-\\\\.';\n }\n return null;\n };\n NumberFilter.DEFAULT_FILTER_OPTIONS = [\n ScalarFilter.EQUALS,\n ScalarFilter.NOT_EQUAL,\n ScalarFilter.LESS_THAN,\n ScalarFilter.LESS_THAN_OR_EQUAL,\n ScalarFilter.GREATER_THAN,\n ScalarFilter.GREATER_THAN_OR_EQUAL,\n ScalarFilter.IN_RANGE,\n ScalarFilter.BLANK,\n ScalarFilter.NOT_BLANK,\n ];\n __decorate$2c([\n RefSelector('eValue-index0-1')\n ], NumberFilter.prototype, \"eValueFrom1\", void 0);\n __decorate$2c([\n RefSelector('eValue-index1-1')\n ], NumberFilter.prototype, \"eValueTo1\", void 0);\n __decorate$2c([\n RefSelector('eValue-index0-2')\n ], NumberFilter.prototype, \"eValueFrom2\", void 0);\n __decorate$2c([\n RefSelector('eValue-index1-2')\n ], NumberFilter.prototype, \"eValueTo2\", void 0);\n return NumberFilter;\n}(ScalarFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2x = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$a = (undefined && undefined.__assign) || function () {\n __assign$a = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$a.apply(this, arguments);\n};\nvar __decorate$2b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TextFilter = /** @class */ (function (_super) {\n __extends$2x(TextFilter, _super);\n function TextFilter() {\n return _super.call(this, 'textFilter') || this;\n }\n TextFilter.trimInput = function (value) {\n var trimmedInput = value && value.trim();\n // trim the input, unless it is all whitespace (this is consistent with Excel behaviour)\n return trimmedInput === '' ? value : trimmedInput;\n };\n TextFilter.prototype.getDefaultDebounceMs = function () {\n return 500;\n };\n TextFilter.prototype.setParams = function (params) {\n _super.prototype.setParams.call(this, params);\n this.textFilterParams = params;\n this.matcher = this.getTextMatcher();\n this.formatter = this.textFilterParams.textFormatter ||\n (this.textFilterParams.caseSensitive ? TextFilter.DEFAULT_FORMATTER : TextFilter.DEFAULT_LOWERCASE_FORMATTER);\n };\n TextFilter.prototype.getTextMatcher = function () {\n var legacyComparator = this.textFilterParams.textCustomComparator;\n if (legacyComparator) {\n _.doOnce(function () { return console.warn('AG Grid - textCustomComparator is deprecated, use textMatcher instead.'); }, 'textCustomComparator.deprecated');\n return function (_a) {\n var filterOption = _a.filterOption, value = _a.value, filterText = _a.filterText;\n return legacyComparator(filterOption, value, filterText);\n };\n }\n return this.textFilterParams.textMatcher || TextFilter.DEFAULT_MATCHER;\n };\n TextFilter.prototype.createCondition = function (position) {\n var type = this.getConditionTypes()[position];\n var model = {\n filterType: this.getFilterType(),\n type: type,\n };\n var values = this.getValues(position);\n if (values.length > 0) {\n model.filter = values[0];\n }\n if (values.length > 1) {\n model.filterTo = values[1];\n }\n return model;\n };\n TextFilter.prototype.getFilterType = function () {\n return 'text';\n };\n TextFilter.prototype.areSimpleModelsEqual = function (aSimple, bSimple) {\n return aSimple.filter === bSimple.filter &&\n aSimple.filterTo === bSimple.filterTo &&\n aSimple.type === bSimple.type;\n };\n TextFilter.prototype.getInputs = function () {\n return [\n [this.eValueFrom1, this.eValueTo1],\n [this.eValueFrom2, this.eValueTo2],\n ];\n };\n TextFilter.prototype.getValues = function (position) {\n var _this = this;\n var result = [];\n this.forEachInput(function (element, index, elPosition, numberOfInputs) {\n if (position === elPosition && index < numberOfInputs) {\n var value = makeNull(element.getValue());\n var cleanValue = (_this.textFilterParams.trimInput ? TextFilter.trimInput(value) : value) || null;\n result.push(cleanValue);\n element.setValue(cleanValue, true); // ensure clean value is visible\n }\n });\n return result;\n };\n TextFilter.prototype.getDefaultFilterOptions = function () {\n return TextFilter.DEFAULT_FILTER_OPTIONS;\n };\n TextFilter.prototype.createValueTemplate = function (position) {\n var pos = position === ConditionPosition.One ? '1' : '2';\n return /* html */ \"\\n <div class=\\\"ag-filter-body\\\" ref=\\\"eCondition\" + pos + \"Body\\\" role=\\\"presentation\\\">\\n <ag-input-text-field class=\\\".ag-filter-from ag-filter-filter\\\" ref=\\\"eValue-index0-\" + pos + \"\\\"></ag-input-text-field>\\n <ag-input-text-field class=\\\"ag-filter-to ag-filter-filter\\\" ref=\\\"eValue-index1-\" + pos + \"\\\"></ag-input-text-field>\\n </div>\";\n };\n TextFilter.prototype.mapValuesFromModel = function (filterModel) {\n var _a = filterModel || {}, filter = _a.filter, filterTo = _a.filterTo, type = _a.type;\n return [\n filter || null,\n filterTo || null,\n ].slice(0, this.getNumberOfInputs(type));\n };\n TextFilter.prototype.evaluateNullValue = function (filterType) {\n var filterTypesAllowNulls = [\n SimpleFilter.NOT_EQUAL, SimpleFilter.NOT_CONTAINS, SimpleFilter.BLANK,\n ];\n return filterType ? filterTypesAllowNulls.indexOf(filterType) >= 0 : false;\n };\n TextFilter.prototype.evaluateNonNullValue = function (values, cellValue, filterModel, params) {\n var _this = this;\n var formattedValues = values.map(function (v) { return _this.formatter(v); }) || [];\n var cellValueFormatted = this.formatter(cellValue);\n var _a = this.textFilterParams, api = _a.api, colDef = _a.colDef, column = _a.column, columnApi = _a.columnApi, context = _a.context, textFormatter = _a.textFormatter;\n if (filterModel.type === SimpleFilter.BLANK) {\n return this.isBlank(cellValue);\n }\n else if (filterModel.type === SimpleFilter.NOT_BLANK) {\n return !this.isBlank(cellValue);\n }\n var matcherParams = {\n api: api,\n colDef: colDef,\n column: column,\n columnApi: columnApi,\n context: context,\n node: params.node,\n data: params.data,\n filterOption: filterModel.type,\n value: cellValueFormatted,\n textFormatter: textFormatter,\n };\n return formattedValues.some(function (v) { return _this.matcher(__assign$a(__assign$a({}, matcherParams), { filterText: v })); });\n };\n TextFilter.DEFAULT_FILTER_OPTIONS = [\n SimpleFilter.CONTAINS,\n SimpleFilter.NOT_CONTAINS,\n SimpleFilter.EQUALS,\n SimpleFilter.NOT_EQUAL,\n SimpleFilter.STARTS_WITH,\n SimpleFilter.ENDS_WITH,\n SimpleFilter.BLANK,\n SimpleFilter.NOT_BLANK,\n ];\n TextFilter.DEFAULT_FORMATTER = function (from) { return from; };\n TextFilter.DEFAULT_LOWERCASE_FORMATTER = function (from) { return from == null ? null : from.toString().toLowerCase(); };\n TextFilter.DEFAULT_MATCHER = function (_a) {\n var filterOption = _a.filterOption, value = _a.value, filterText = _a.filterText;\n if (filterText == null) {\n return false;\n }\n switch (filterOption) {\n case TextFilter.CONTAINS:\n return value.indexOf(filterText) >= 0;\n case TextFilter.NOT_CONTAINS:\n return value.indexOf(filterText) < 0;\n case TextFilter.EQUALS:\n return value === filterText;\n case TextFilter.NOT_EQUAL:\n return value != filterText;\n case TextFilter.STARTS_WITH:\n return value.indexOf(filterText) === 0;\n case TextFilter.ENDS_WITH:\n var index = value.lastIndexOf(filterText);\n return index >= 0 && index === (value.length - filterText.length);\n default:\n return false;\n }\n };\n __decorate$2b([\n RefSelector('eValue-index0-1')\n ], TextFilter.prototype, \"eValueFrom1\", void 0);\n __decorate$2b([\n RefSelector('eValue-index1-1')\n ], TextFilter.prototype, \"eValueTo1\", void 0);\n __decorate$2b([\n RefSelector('eValue-index0-2')\n ], TextFilter.prototype, \"eValueFrom2\", void 0);\n __decorate$2b([\n RefSelector('eValue-index1-2')\n ], TextFilter.prototype, \"eValueTo2\", void 0);\n return TextFilter;\n}(SimpleFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2w = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2a = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TextInputFloatingFilter = /** @class */ (function (_super) {\n __extends$2w(TextInputFloatingFilter, _super);\n function TextInputFloatingFilter() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n TextInputFloatingFilter.prototype.postConstruct = function () {\n this.resetTemplate();\n };\n TextInputFloatingFilter.prototype.resetTemplate = function (paramsMap) {\n this.setTemplate(/* html */ \"\\n <div class=\\\"ag-floating-filter-input\\\" role=\\\"presentation\\\">\\n <ag-input-text-field ref=\\\"eFloatingFilterInput\\\"></ag-input-text-field>\\n </div>\\n \", paramsMap);\n };\n TextInputFloatingFilter.prototype.getDefaultDebounceMs = function () {\n return 500;\n };\n TextInputFloatingFilter.prototype.onParentModelChanged = function (model, event) {\n if (this.isEventFromFloatingFilter(event)) {\n // if the floating filter triggered the change, it is already in sync\n return;\n }\n this.setLastTypeFromModel(model);\n this.eFloatingFilterInput.setValue(this.getTextFromModel(model));\n this.setEditable(this.canWeEditAfterModelFromParentFilter(model));\n };\n TextInputFloatingFilter.prototype.init = function (params) {\n _super.prototype.init.call(this, params);\n this.params = params;\n this.applyActive = ProvidedFilter.isUseApplyButton(this.params.filterParams);\n var allowedCharPattern = this.params.filterParams.allowedCharPattern;\n if (allowedCharPattern != null) {\n this.resetTemplate({ eFloatingFilterInput: { allowedCharPattern: allowedCharPattern } });\n }\n if (!this.isReadOnly()) {\n var debounceMs = ProvidedFilter.getDebounceMs(this.params.filterParams, this.getDefaultDebounceMs());\n var toDebounce = debounce(this.syncUpWithParentFilter.bind(this), debounceMs);\n var filterGui = this.eFloatingFilterInput.getGui();\n this.addManagedListener(filterGui, 'input', toDebounce);\n this.addManagedListener(filterGui, 'keypress', toDebounce);\n this.addManagedListener(filterGui, 'keydown', toDebounce);\n }\n var columnDef = params.column.getDefinition();\n if (this.isReadOnly() || (columnDef.filterParams &&\n columnDef.filterParams.filterOptions &&\n columnDef.filterParams.filterOptions.length === 1 &&\n columnDef.filterParams.filterOptions[0] === 'inRange')) {\n this.eFloatingFilterInput.setDisabled(true);\n }\n var displayName = this.columnModel.getDisplayNameForColumn(params.column, 'header', true);\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.eFloatingFilterInput.setInputAriaLabel(displayName + \" \" + translate('ariaFilterInput', 'Filter Input'));\n };\n TextInputFloatingFilter.prototype.syncUpWithParentFilter = function (e) {\n var _this = this;\n var enterKeyPressed = e.key === KeyCode.ENTER;\n if (this.applyActive && !enterKeyPressed) {\n return;\n }\n var value = this.eFloatingFilterInput.getValue();\n if (this.params.filterParams.trimInput) {\n value = TextFilter.trimInput(value);\n this.eFloatingFilterInput.setValue(value, true); // ensure visible value is trimmed\n }\n this.params.parentFilterInstance(function (filterInstance) {\n if (filterInstance) {\n filterInstance.onFloatingFilterChanged(_this.getLastType() || null, value || null);\n }\n });\n };\n TextInputFloatingFilter.prototype.conditionToString = function (condition, options) {\n var numberOfInputs = (options || {}).numberOfInputs;\n var isRange = condition.type == SimpleFilter.IN_RANGE || numberOfInputs === 2;\n if (isRange) {\n return condition.filter + \"-\" + condition.filterTo;\n }\n // cater for when the type doesn't need a value\n if (condition.filter != null) {\n return \"\" + condition.filter;\n }\n return \"\" + condition.type;\n };\n TextInputFloatingFilter.prototype.setEditable = function (editable) {\n this.eFloatingFilterInput.setDisabled(!editable);\n };\n __decorate$2a([\n Autowired('columnModel')\n ], TextInputFloatingFilter.prototype, \"columnModel\", void 0);\n __decorate$2a([\n RefSelector('eFloatingFilterInput')\n ], TextInputFloatingFilter.prototype, \"eFloatingFilterInput\", void 0);\n __decorate$2a([\n PostConstruct\n ], TextInputFloatingFilter.prototype, \"postConstruct\", null);\n return TextInputFloatingFilter;\n}(SimpleFloatingFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2v = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar NumberFloatingFilter = /** @class */ (function (_super) {\n __extends$2v(NumberFloatingFilter, _super);\n function NumberFloatingFilter() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n NumberFloatingFilter.prototype.getDefaultFilterOptions = function () {\n return NumberFilter.DEFAULT_FILTER_OPTIONS;\n };\n return NumberFloatingFilter;\n}(TextInputFloatingFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2u = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar TextFloatingFilter = /** @class */ (function (_super) {\n __extends$2u(TextFloatingFilter, _super);\n function TextFloatingFilter() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n TextFloatingFilter.prototype.getDefaultFilterOptions = function () {\n return TextFilter.DEFAULT_FILTER_OPTIONS;\n };\n return TextFloatingFilter;\n}(TextInputFloatingFilter));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar TouchListener = /** @class */ (function () {\n function TouchListener(eElement, preventMouseClick) {\n var _this = this;\n if (preventMouseClick === void 0) { preventMouseClick = false; }\n this.destroyFuncs = [];\n this.touching = false;\n this.eventService = new EventService();\n this.eElement = eElement;\n this.preventMouseClick = preventMouseClick;\n var startListener = this.onTouchStart.bind(this);\n var moveListener = this.onTouchMove.bind(this);\n var endListener = this.onTouchEnd.bind(this);\n this.eElement.addEventListener(\"touchstart\", startListener, { passive: true });\n this.eElement.addEventListener(\"touchmove\", moveListener, { passive: true });\n // we set passive=false, as we want to prevent default on this event\n this.eElement.addEventListener(\"touchend\", endListener, { passive: false });\n this.destroyFuncs.push(function () {\n _this.eElement.removeEventListener(\"touchstart\", startListener, { passive: true });\n _this.eElement.removeEventListener(\"touchmove\", moveListener, { passive: true });\n _this.eElement.removeEventListener(\"touchend\", endListener, { passive: false });\n });\n }\n TouchListener.prototype.getActiveTouch = function (touchList) {\n for (var i = 0; i < touchList.length; i++) {\n var matches = touchList[i].identifier === this.touchStart.identifier;\n if (matches) {\n return touchList[i];\n }\n }\n return null;\n };\n TouchListener.prototype.addEventListener = function (eventType, listener) {\n this.eventService.addEventListener(eventType, listener);\n };\n TouchListener.prototype.removeEventListener = function (eventType, listener) {\n this.eventService.removeEventListener(eventType, listener);\n };\n TouchListener.prototype.onTouchStart = function (touchEvent) {\n var _this = this;\n // only looking at one touch point at any time\n if (this.touching) {\n return;\n }\n this.touchStart = touchEvent.touches[0];\n this.touching = true;\n this.moved = false;\n var touchStartCopy = this.touchStart;\n window.setTimeout(function () {\n var touchesMatch = _this.touchStart === touchStartCopy;\n if (_this.touching && touchesMatch && !_this.moved) {\n _this.moved = true;\n var event_1 = {\n type: TouchListener.EVENT_LONG_TAP,\n touchStart: _this.touchStart,\n touchEvent: touchEvent\n };\n _this.eventService.dispatchEvent(event_1);\n }\n }, 500);\n };\n TouchListener.prototype.onTouchMove = function (touchEvent) {\n if (!this.touching) {\n return;\n }\n var touch = this.getActiveTouch(touchEvent.touches);\n if (!touch) {\n return;\n }\n var eventIsFarAway = !areEventsNear(touch, this.touchStart, 4);\n if (eventIsFarAway) {\n this.moved = true;\n }\n };\n TouchListener.prototype.onTouchEnd = function (touchEvent) {\n if (!this.touching) {\n return;\n }\n if (!this.moved) {\n var event_2 = {\n type: TouchListener.EVENT_TAP,\n touchStart: this.touchStart\n };\n this.eventService.dispatchEvent(event_2);\n this.checkForDoubleTap();\n }\n // stops the tap from also been processed as a mouse click\n if (this.preventMouseClick && touchEvent.cancelable) {\n touchEvent.preventDefault();\n }\n this.touching = false;\n };\n TouchListener.prototype.checkForDoubleTap = function () {\n var now = new Date().getTime();\n if (this.lastTapTime && this.lastTapTime > 0) {\n // if previous tap, see if duration is short enough to be considered double tap\n var interval = now - this.lastTapTime;\n if (interval > TouchListener.DOUBLE_TAP_MILLIS) {\n // dispatch double tap event\n var event_3 = {\n type: TouchListener.EVENT_DOUBLE_TAP,\n touchStart: this.touchStart\n };\n this.eventService.dispatchEvent(event_3);\n // this stops a tripple tap ending up as two double taps\n this.lastTapTime = null;\n }\n else {\n this.lastTapTime = now;\n }\n }\n else {\n this.lastTapTime = now;\n }\n };\n TouchListener.prototype.destroy = function () {\n this.destroyFuncs.forEach(function (func) { return func(); });\n };\n TouchListener.EVENT_TAP = \"tap\";\n TouchListener.EVENT_DOUBLE_TAP = \"doubleTap\";\n TouchListener.EVENT_LONG_TAP = \"longTap\";\n TouchListener.DOUBLE_TAP_MILLIS = 500;\n return TouchListener;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2t = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$29 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SortIndicatorComp = /** @class */ (function (_super) {\n __extends$2t(SortIndicatorComp, _super);\n function SortIndicatorComp(skipTemplate) {\n var _this = _super.call(this) || this;\n if (!skipTemplate) {\n _this.setTemplate(SortIndicatorComp.TEMPLATE);\n }\n return _this;\n }\n SortIndicatorComp.prototype.attachCustomElements = function (eSortOrder, eSortAsc, eSortDesc, eSortMixed, eSortNone) {\n this.eSortOrder = eSortOrder;\n this.eSortAsc = eSortAsc;\n this.eSortDesc = eSortDesc;\n this.eSortMixed = eSortMixed;\n this.eSortNone = eSortNone;\n };\n SortIndicatorComp.prototype.setupSort = function (column, suppressOrder) {\n var _this = this;\n if (suppressOrder === void 0) { suppressOrder = false; }\n this.column = column;\n this.suppressOrder = suppressOrder;\n this.setupMultiSortIndicator();\n var canSort = !!this.column.getColDef().sortable;\n if (!canSort) {\n return;\n }\n this.addInIcon('sortAscending', this.eSortAsc, column);\n this.addInIcon('sortDescending', this.eSortDesc, column);\n this.addInIcon('sortUnSort', this.eSortNone, column);\n // Watch global events, as row group columns can effect their display column.\n this.addManagedListener(this.eventService, Events.EVENT_SORT_CHANGED, function () { return _this.onSortChanged(); });\n // when grouping changes so can sort indexes and icons\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, function () { return _this.onSortChanged(); });\n this.onSortChanged();\n };\n SortIndicatorComp.prototype.addInIcon = function (iconName, eParent, column) {\n if (eParent == null) {\n return;\n }\n var eIcon = createIconNoSpan(iconName, this.gridOptionsWrapper, column);\n if (eIcon) {\n eParent.appendChild(eIcon);\n }\n };\n SortIndicatorComp.prototype.onSortChanged = function () {\n this.updateIcons();\n if (!this.suppressOrder) {\n this.updateSortOrder();\n }\n };\n SortIndicatorComp.prototype.updateIcons = function () {\n var sortDirection = this.sortController.getDisplaySortForColumn(this.column);\n if (this.eSortAsc) {\n var isAscending = sortDirection === 'asc';\n this.eSortAsc.classList.toggle('ag-hidden', !isAscending);\n }\n if (this.eSortDesc) {\n var isDescending = sortDirection === 'desc';\n this.eSortDesc.classList.toggle('ag-hidden', !isDescending);\n }\n if (this.eSortNone) {\n var alwaysHideNoSort = !this.column.getColDef().unSortIcon && !this.gridOptionsWrapper.isUnSortIcon();\n var isNone = sortDirection === null || sortDirection === undefined;\n this.eSortNone.classList.toggle('ag-hidden', (alwaysHideNoSort || !isNone));\n }\n };\n SortIndicatorComp.prototype.setupMultiSortIndicator = function () {\n var _this = this;\n this.addInIcon('sortUnSort', this.eSortMixed, this.column);\n var isColumnShowingRowGroup = this.column.getColDef().showRowGroup;\n var areGroupsCoupled = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n if (areGroupsCoupled && isColumnShowingRowGroup) {\n // Watch global events, as row group columns can effect their display column.\n this.addManagedListener(this.eventService, Events.EVENT_SORT_CHANGED, function () { return _this.updateMultiSortIndicator(); });\n // when grouping changes so can sort indexes and icons\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, function () { return _this.updateMultiSortIndicator(); });\n this.updateMultiSortIndicator();\n }\n };\n SortIndicatorComp.prototype.updateMultiSortIndicator = function () {\n if (this.eSortMixed) {\n var isMixedSort = this.sortController.getDisplaySortForColumn(this.column) === 'mixed';\n this.eSortMixed.classList.toggle('ag-hidden', !isMixedSort);\n }\n };\n // we listen here for global sort events, NOT column sort events, as we want to do this\n // when sorting has been set on all column (if we listened just for our col (where we\n // set the asc / desc icons) then it's possible other cols are yet to get their sorting state.\n SortIndicatorComp.prototype.updateSortOrder = function () {\n var _this = this;\n var _a;\n if (!this.eSortOrder) {\n return;\n }\n var allColumnsWithSorting = this.sortController.getColumnsWithSortingOrdered();\n var indexThisCol = (_a = this.sortController.getDisplaySortIndexForColumn(this.column), (_a !== null && _a !== void 0 ? _a : -1));\n var moreThanOneColSorting = allColumnsWithSorting.some(function (col) { var _a; return _a = _this.sortController.getDisplaySortIndexForColumn(col), (_a !== null && _a !== void 0 ? _a : -1 >= 1); });\n var showIndex = indexThisCol >= 0 && moreThanOneColSorting;\n setDisplayed(this.eSortOrder, showIndex);\n if (indexThisCol >= 0) {\n this.eSortOrder.innerHTML = (indexThisCol + 1).toString();\n }\n else {\n clearElement(this.eSortOrder);\n }\n };\n SortIndicatorComp.TEMPLATE = \"<span class=\\\"ag-sort-indicator-container\\\">\\n <span ref=\\\"eSortOrder\\\" class=\\\"ag-sort-indicator-icon ag-sort-order ag-hidden\\\" aria-hidden=\\\"true\\\"></span>\\n <span ref=\\\"eSortAsc\\\" class=\\\"ag-sort-indicator-icon ag-sort-ascending-icon ag-hidden\\\" aria-hidden=\\\"true\\\"></span>\\n <span ref=\\\"eSortDesc\\\" class=\\\"ag-sort-indicator-icon ag-sort-descending-icon ag-hidden\\\" aria-hidden=\\\"true\\\"></span>\\n <span ref=\\\"eSortMixed\\\" class=\\\"ag-sort-indicator-icon ag-sort-mixed-icon ag-hidden\\\" aria-hidden=\\\"true\\\"></span>\\n <span ref=\\\"eSortNone\\\" class=\\\"ag-sort-indicator-icon ag-sort-none-icon ag-hidden\\\" aria-hidden=\\\"true\\\"></span>\\n </span>\";\n __decorate$29([\n RefSelector('eSortOrder')\n ], SortIndicatorComp.prototype, \"eSortOrder\", void 0);\n __decorate$29([\n RefSelector('eSortAsc')\n ], SortIndicatorComp.prototype, \"eSortAsc\", void 0);\n __decorate$29([\n RefSelector('eSortDesc')\n ], SortIndicatorComp.prototype, \"eSortDesc\", void 0);\n __decorate$29([\n RefSelector('eSortMixed')\n ], SortIndicatorComp.prototype, \"eSortMixed\", void 0);\n __decorate$29([\n RefSelector('eSortNone')\n ], SortIndicatorComp.prototype, \"eSortNone\", void 0);\n __decorate$29([\n Autowired('columnModel')\n ], SortIndicatorComp.prototype, \"columnModel\", void 0);\n __decorate$29([\n Autowired('sortController')\n ], SortIndicatorComp.prototype, \"sortController\", void 0);\n return SortIndicatorComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2s = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$28 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderComp = /** @class */ (function (_super) {\n __extends$2s(HeaderComp, _super);\n function HeaderComp() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.lastMovingChanged = 0;\n return _this;\n }\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n HeaderComp.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n HeaderComp.prototype.refresh = function (params) {\n this.params = params;\n // if template changed, then recreate the whole comp, the code required to manage\n // a changing template is to difficult for what it's worth.\n if (this.workOutTemplate() != this.currentTemplate) {\n return false;\n }\n if (this.workOutShowMenu() != this.currentShowMenu) {\n return false;\n }\n if (this.workOutSort() != this.currentSort) {\n return false;\n }\n this.setDisplayName(params);\n return true;\n };\n HeaderComp.prototype.workOutTemplate = function () {\n var template = firstExistingValue(this.params.template, HeaderComp.TEMPLATE);\n // take account of any newlines & whitespace before/after the actual template\n template = template && template.trim ? template.trim() : template;\n return template;\n };\n HeaderComp.prototype.init = function (params) {\n this.params = params;\n this.currentTemplate = this.workOutTemplate();\n this.setTemplate(this.currentTemplate);\n this.setupTap();\n this.setupIcons(params.column);\n this.setMenu();\n this.setupSort();\n this.setupFilterIcon();\n this.setDisplayName(params);\n };\n HeaderComp.prototype.setDisplayName = function (params) {\n if (this.currentDisplayName != params.displayName) {\n this.currentDisplayName = params.displayName;\n var displayNameSanitised = escapeString(this.currentDisplayName);\n if (this.eText) {\n this.eText.innerHTML = displayNameSanitised;\n }\n }\n };\n HeaderComp.prototype.setupIcons = function (column) {\n this.addInIcon('menu', this.eMenu, column);\n this.addInIcon('filter', this.eFilter, column);\n };\n HeaderComp.prototype.addInIcon = function (iconName, eParent, column) {\n if (eParent == null) {\n return;\n }\n var eIcon = createIconNoSpan(iconName, this.gridOptionsWrapper, column);\n if (eIcon) {\n eParent.appendChild(eIcon);\n }\n };\n HeaderComp.prototype.setupTap = function () {\n var _this = this;\n var options = this.gridOptionsWrapper;\n if (options.isSuppressTouch()) {\n return;\n }\n var touchListener = new TouchListener(this.getGui(), true);\n var suppressMenuHide = options.isSuppressMenuHide();\n var tapMenuButton = suppressMenuHide && exists(this.eMenu);\n var menuTouchListener = tapMenuButton ? new TouchListener(this.eMenu, true) : touchListener;\n if (this.params.enableMenu) {\n var eventType = tapMenuButton ? 'EVENT_TAP' : 'EVENT_LONG_TAP';\n var showMenuFn = function (event) {\n options.getApi().showColumnMenuAfterMouseClick(_this.params.column, event.touchStart);\n };\n this.addManagedListener(menuTouchListener, TouchListener[eventType], showMenuFn);\n }\n if (this.params.enableSorting) {\n var tapListener = function (event) {\n var target = event.touchStart.target;\n // When suppressMenuHide is true, a tap on the menu icon will bubble up\n // to the header container, in that case we should not sort\n if (suppressMenuHide && _this.eMenu.contains(target)) {\n return;\n }\n _this.sortController.progressSort(_this.params.column, false, \"uiColumnSorted\");\n };\n this.addManagedListener(touchListener, TouchListener.EVENT_TAP, tapListener);\n }\n // if tapMenuButton is true `touchListener` and `menuTouchListener` are different\n // so we need to make sure to destroy both listeners here\n this.addDestroyFunc(function () { return touchListener.destroy(); });\n if (tapMenuButton) {\n this.addDestroyFunc(function () { return menuTouchListener.destroy(); });\n }\n };\n HeaderComp.prototype.workOutShowMenu = function () {\n // we don't show the menu if on an iPad/iPhone, as the user cannot have a pointer device/\n // However if suppressMenuHide is set to true the menu will be displayed alwasys, so it's ok\n // to show it on iPad in this case (as hover isn't needed). If suppressMenuHide\n // is false (default) user will need to use longpress to display the menu.\n var menuHides = !this.gridOptionsWrapper.isSuppressMenuHide();\n var onIpadAndMenuHides = isIOSUserAgent() && menuHides;\n var showMenu = this.params.enableMenu && !onIpadAndMenuHides;\n return showMenu;\n };\n HeaderComp.prototype.setMenu = function () {\n var _this = this;\n // if no menu provided in template, do nothing\n if (!this.eMenu) {\n return;\n }\n this.currentShowMenu = this.workOutShowMenu();\n if (!this.currentShowMenu) {\n removeFromParent(this.eMenu);\n return;\n }\n var suppressMenuHide = this.gridOptionsWrapper.isSuppressMenuHide();\n this.addManagedListener(this.eMenu, 'click', function () { return _this.showMenu(_this.eMenu); });\n this.eMenu.classList.toggle('ag-header-menu-always-show', suppressMenuHide);\n };\n HeaderComp.prototype.showMenu = function (eventSource) {\n if (!eventSource) {\n eventSource = this.eMenu;\n }\n this.menuFactory.showMenuAfterButtonClick(this.params.column, eventSource, 'columnMenu');\n };\n HeaderComp.prototype.workOutSort = function () {\n return this.params.enableSorting;\n };\n HeaderComp.prototype.setupSort = function () {\n var _this = this;\n this.currentSort = this.params.enableSorting;\n // eSortIndicator will not be present when customers provided custom header\n // templates, in that case, we need to look for provided sort elements and\n // manually create eSortIndicator.\n if (!this.eSortIndicator) {\n this.eSortIndicator = this.context.createBean(new SortIndicatorComp(true));\n this.eSortIndicator.attachCustomElements(this.eSortOrder, this.eSortAsc, this.eSortDesc, this.eSortMixed, this.eSortNone);\n }\n this.eSortIndicator.setupSort(this.params.column);\n // we set up the indicator prior to the check for whether this column is sortable, as it allows the indicator to\n // set up the multi sort indicator which can appear irrelevant of whether this column can itself be sorted.\n // this can occur in the case of a non-sortable group display column.\n if (!this.currentSort) {\n return;\n }\n var sortUsingCtrl = this.gridOptionsWrapper.isMultiSortKeyCtrl();\n // keep track of last time the moving changed flag was set\n this.addManagedListener(this.params.column, Column.EVENT_MOVING_CHANGED, function () {\n _this.lastMovingChanged = new Date().getTime();\n });\n // add the event on the header, so when clicked, we do sorting\n if (this.eLabel) {\n this.addManagedListener(this.eLabel, 'click', function (event) {\n // sometimes when moving a column via dragging, this was also firing a clicked event.\n // here is issue raised by user: https://ag-grid.zendesk.com/agent/tickets/1076\n // this check stops sort if a) column is moving or b) column moved less than 200ms ago (so caters for race condition)\n var moving = _this.params.column.isMoving();\n var nowTime = new Date().getTime();\n // typically there is <2ms if moving flag was set recently, as it would be done in same VM turn\n var movedRecently = (nowTime - _this.lastMovingChanged) < 50;\n var columnMoving = moving || movedRecently;\n if (!columnMoving) {\n var multiSort = sortUsingCtrl ? (event.ctrlKey || event.metaKey) : event.shiftKey;\n _this.params.progressSort(multiSort);\n }\n });\n }\n var onSortingChanged = function () {\n var _a;\n _this.addOrRemoveCssClass('ag-header-cell-sorted-asc', _this.params.column.isSortAscending());\n _this.addOrRemoveCssClass('ag-header-cell-sorted-desc', _this.params.column.isSortDescending());\n _this.addOrRemoveCssClass('ag-header-cell-sorted-none', _this.params.column.isSortNone());\n if (_this.params.column.getColDef().showRowGroup) {\n var sourceColumns = _this.columnModel.getSourceColumnsForGroupColumn(_this.params.column);\n // this == is intentional, as it allows null and undefined to match, which are both unsorted states\n var sortDirectionsMatch = (_a = sourceColumns) === null || _a === void 0 ? void 0 : _a.every(function (sourceCol) { return _this.params.column.getSort() == sourceCol.getSort(); });\n var isMultiSorting = !sortDirectionsMatch;\n _this.addOrRemoveCssClass('ag-header-cell-sorted-mixed', isMultiSorting);\n }\n };\n this.addManagedListener(this.eventService, Events.EVENT_SORT_CHANGED, onSortingChanged);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, onSortingChanged);\n };\n HeaderComp.prototype.setupFilterIcon = function () {\n if (!this.eFilter) {\n return;\n }\n this.addManagedListener(this.params.column, Column.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));\n this.onFilterChanged();\n };\n HeaderComp.prototype.onFilterChanged = function () {\n var filterPresent = this.params.column.isFilterActive();\n this.eFilter.classList.toggle('ag-hidden', !filterPresent);\n };\n HeaderComp.TEMPLATE = \"<div class=\\\"ag-cell-label-container\\\" role=\\\"presentation\\\">\\n <span ref=\\\"eMenu\\\" class=\\\"ag-header-icon ag-header-cell-menu-button\\\" aria-hidden=\\\"true\\\"></span>\\n <div ref=\\\"eLabel\\\" class=\\\"ag-header-cell-label\\\" role=\\\"presentation\\\">\\n <span ref=\\\"eText\\\" class=\\\"ag-header-cell-text\\\"></span>\\n <span ref=\\\"eFilter\\\" class=\\\"ag-header-icon ag-header-label-icon ag-filter-icon\\\" aria-hidden=\\\"true\\\"></span>\\n <ag-sort-indicator ref=\\\"eSortIndicator\\\"></ag-sort-indicator>\\n </div>\\n </div>\";\n __decorate$28([\n Autowired('sortController')\n ], HeaderComp.prototype, \"sortController\", void 0);\n __decorate$28([\n Autowired('menuFactory')\n ], HeaderComp.prototype, \"menuFactory\", void 0);\n __decorate$28([\n Autowired('columnModel')\n ], HeaderComp.prototype, \"columnModel\", void 0);\n __decorate$28([\n RefSelector('eFilter')\n ], HeaderComp.prototype, \"eFilter\", void 0);\n __decorate$28([\n RefSelector('eSortIndicator')\n ], HeaderComp.prototype, \"eSortIndicator\", void 0);\n __decorate$28([\n RefSelector('eMenu')\n ], HeaderComp.prototype, \"eMenu\", void 0);\n __decorate$28([\n RefSelector('eLabel')\n ], HeaderComp.prototype, \"eLabel\", void 0);\n __decorate$28([\n RefSelector('eText')\n ], HeaderComp.prototype, \"eText\", void 0);\n __decorate$28([\n RefSelector('eSortOrder')\n ], HeaderComp.prototype, \"eSortOrder\", void 0);\n __decorate$28([\n RefSelector('eSortAsc')\n ], HeaderComp.prototype, \"eSortAsc\", void 0);\n __decorate$28([\n RefSelector('eSortDesc')\n ], HeaderComp.prototype, \"eSortDesc\", void 0);\n __decorate$28([\n RefSelector('eSortMixed')\n ], HeaderComp.prototype, \"eSortMixed\", void 0);\n __decorate$28([\n RefSelector('eSortNone')\n ], HeaderComp.prototype, \"eSortNone\", void 0);\n return HeaderComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2r = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$27 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderGroupComp = /** @class */ (function (_super) {\n __extends$2r(HeaderGroupComp, _super);\n function HeaderGroupComp() {\n return _super.call(this, HeaderGroupComp.TEMPLATE) || this;\n }\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n HeaderGroupComp.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n HeaderGroupComp.prototype.init = function (params) {\n this.params = params;\n this.checkWarnings();\n this.setupLabel();\n this.addGroupExpandIcon();\n this.setupExpandIcons();\n };\n HeaderGroupComp.prototype.checkWarnings = function () {\n var paramsAny = this.params;\n if (paramsAny.template) {\n var message_1 = \"AG Grid: A template was provided for Header Group Comp - templates are only supported for Header Comps (not groups)\";\n doOnce(function () { return console.warn(message_1); }, 'HeaderGroupComp.templateNotSupported');\n }\n };\n HeaderGroupComp.prototype.setupExpandIcons = function () {\n var _this = this;\n this.addInIcon(\"columnGroupOpened\", \"agOpened\");\n this.addInIcon(\"columnGroupClosed\", \"agClosed\");\n var expandAction = function (event) {\n if (isStopPropagationForAgGrid(event)) {\n return;\n }\n var newExpandedValue = !_this.params.columnGroup.isExpanded();\n _this.columnModel.setColumnGroupOpened(_this.params.columnGroup.getProvidedColumnGroup(), newExpandedValue, \"uiColumnExpanded\");\n };\n this.addTouchAndClickListeners(this.eCloseIcon, expandAction);\n this.addTouchAndClickListeners(this.eOpenIcon, expandAction);\n var stopPropagationAction = function (event) {\n stopPropagationForAgGrid(event);\n };\n // adding stopPropagation to the double click for the icons prevents double click action happening\n // when the icons are clicked. if the icons are double clicked, then the groups should open and\n // then close again straight away. if we also listened to double click, then the group would open,\n // close, then open, which is not what we want. double click should only action if the user double\n // clicks outside of the icons.\n this.addManagedListener(this.eCloseIcon, \"dblclick\", stopPropagationAction);\n this.addManagedListener(this.eOpenIcon, \"dblclick\", stopPropagationAction);\n this.addManagedListener(this.getGui(), \"dblclick\", expandAction);\n this.updateIconVisibility();\n var providedColumnGroup = this.params.columnGroup.getProvidedColumnGroup();\n this.addManagedListener(providedColumnGroup, ProvidedColumnGroup.EVENT_EXPANDED_CHANGED, this.updateIconVisibility.bind(this));\n this.addManagedListener(providedColumnGroup, ProvidedColumnGroup.EVENT_EXPANDABLE_CHANGED, this.updateIconVisibility.bind(this));\n };\n HeaderGroupComp.prototype.addTouchAndClickListeners = function (eElement, action) {\n var touchListener = new TouchListener(eElement, true);\n this.addManagedListener(touchListener, TouchListener.EVENT_TAP, action);\n this.addDestroyFunc(function () { return touchListener.destroy(); });\n this.addManagedListener(eElement, \"click\", action);\n };\n HeaderGroupComp.prototype.updateIconVisibility = function () {\n var columnGroup = this.params.columnGroup;\n if (columnGroup.isExpandable()) {\n var expanded = this.params.columnGroup.isExpanded();\n setDisplayed(this.eOpenIcon, expanded);\n setDisplayed(this.eCloseIcon, !expanded);\n }\n else {\n setDisplayed(this.eOpenIcon, false);\n setDisplayed(this.eCloseIcon, false);\n }\n };\n HeaderGroupComp.prototype.addInIcon = function (iconName, refName) {\n var eIcon = createIconNoSpan(iconName, this.gridOptionsWrapper, null);\n if (eIcon) {\n this.getRefElement(refName).appendChild(eIcon);\n }\n };\n HeaderGroupComp.prototype.addGroupExpandIcon = function () {\n if (!this.params.columnGroup.isExpandable()) {\n setDisplayed(this.eOpenIcon, false);\n setDisplayed(this.eCloseIcon, false);\n return;\n }\n };\n HeaderGroupComp.prototype.setupLabel = function () {\n // no renderer, default text render\n var displayName = this.params.displayName;\n if (exists(displayName)) {\n var displayNameSanitised = escapeString(displayName);\n this.getRefElement('agLabel').innerHTML = displayNameSanitised;\n }\n };\n HeaderGroupComp.TEMPLATE = \"<div class=\\\"ag-header-group-cell-label\\\" ref=\\\"agContainer\\\" role=\\\"presentation\\\">\\n <span ref=\\\"agLabel\\\" class=\\\"ag-header-group-text\\\" role=\\\"presentation\\\"></span>\\n <span ref=\\\"agOpened\\\" class=\\\"ag-header-icon ag-header-expand-icon ag-header-expand-icon-expanded\\\"></span>\\n <span ref=\\\"agClosed\\\" class=\\\"ag-header-icon ag-header-expand-icon ag-header-expand-icon-collapsed\\\"></span>\\n </div>\";\n __decorate$27([\n Autowired(\"columnModel\")\n ], HeaderGroupComp.prototype, \"columnModel\", void 0);\n __decorate$27([\n RefSelector(\"agOpened\")\n ], HeaderGroupComp.prototype, \"eOpenIcon\", void 0);\n __decorate$27([\n RefSelector(\"agClosed\")\n ], HeaderGroupComp.prototype, \"eCloseIcon\", void 0);\n return HeaderGroupComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2q = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar PopupComponent = /** @class */ (function (_super) {\n __extends$2q(PopupComponent, _super);\n function PopupComponent() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n PopupComponent.prototype.isPopup = function () {\n return true;\n };\n PopupComponent.prototype.setParentComponent = function (container) {\n container.addCssClass('ag-has-popup');\n _super.prototype.setParentComponent.call(this, container);\n };\n PopupComponent.prototype.destroy = function () {\n var parentComp = this.parentComponent;\n var hasParent = parentComp && parentComp.isAlive();\n if (hasParent) {\n parentComp.getGui().classList.remove('ag-has-popup');\n }\n _super.prototype.destroy.call(this);\n };\n return PopupComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2p = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$26 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar LargeTextCellEditor = /** @class */ (function (_super) {\n __extends$2p(LargeTextCellEditor, _super);\n function LargeTextCellEditor() {\n return _super.call(this, LargeTextCellEditor.TEMPLATE) || this;\n }\n LargeTextCellEditor.prototype.init = function (params) {\n this.params = params;\n this.focusAfterAttached = params.cellStartedEdit;\n this.eTextArea\n .setMaxLength(params.maxLength || 200)\n .setCols(params.cols || 60)\n .setRows(params.rows || 10);\n if (exists(params.value)) {\n this.eTextArea.setValue(params.value.toString(), true);\n }\n this.addGuiEventListener('keydown', this.onKeyDown.bind(this));\n };\n LargeTextCellEditor.prototype.onKeyDown = function (event) {\n var key = event.key;\n if (key === KeyCode.LEFT ||\n key === KeyCode.UP ||\n key === KeyCode.RIGHT ||\n key === KeyCode.DOWN ||\n (event.shiftKey && key === KeyCode.ENTER)) { // shift+enter allows for newlines\n event.stopPropagation();\n }\n };\n LargeTextCellEditor.prototype.afterGuiAttached = function () {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.eTextArea.setInputAriaLabel(translate('ariaInputEditor', 'Input Editor'));\n if (this.focusAfterAttached) {\n this.eTextArea.getFocusableElement().focus();\n }\n };\n LargeTextCellEditor.prototype.getValue = function () {\n return this.params.parseValue(this.eTextArea.getValue());\n };\n LargeTextCellEditor.TEMPLATE = \"<div class=\\\"ag-large-text\\\" tabindex=\\\"0\\\">\\n <ag-input-text-area ref=\\\"eTextArea\\\" class=\\\"ag-large-text-input\\\"></ag-input-text-area>\\n </div>\";\n __decorate$26([\n RefSelector(\"eTextArea\")\n ], LargeTextCellEditor.prototype, \"eTextArea\", void 0);\n return LargeTextCellEditor;\n}(PopupComponent));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2o = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$25 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SelectCellEditor = /** @class */ (function (_super) {\n __extends$2o(SelectCellEditor, _super);\n function SelectCellEditor() {\n var _this = _super.call(this, '<div class=\"ag-cell-edit-wrapper\"><ag-select class=\"ag-cell-editor\" ref=\"eSelect\"></ag-select></div>') || this;\n _this.startedByEnter = false;\n return _this;\n }\n SelectCellEditor.prototype.init = function (params) {\n var _this = this;\n this.focusAfterAttached = params.cellStartedEdit;\n if (missing(params.values)) {\n console.warn('AG Grid: no values found for select cellEditor');\n return;\n }\n this.startedByEnter = params.eventKey != null ? params.eventKey === KeyCode.ENTER : false;\n var hasValue = false;\n params.values.forEach(function (value) {\n var option = { value: value };\n var valueFormatted = _this.valueFormatterService.formatValue(params.column, null, value);\n var valueFormattedExits = valueFormatted !== null && valueFormatted !== undefined;\n option.text = valueFormattedExits ? valueFormatted : value;\n _this.eSelect.addOption(option);\n hasValue = hasValue || params.value === value;\n });\n if (hasValue) {\n this.eSelect.setValue(params.value, true);\n }\n else if (params.values.length) {\n this.eSelect.setValue(params.values[0], true);\n }\n // we don't want to add this if full row editing, otherwise selecting will stop the\n // full row editing.\n if (!this.gridOptionsWrapper.isFullRowEdit()) {\n this.eSelect.onValueChange(function () { return params.stopEditing(); });\n }\n };\n SelectCellEditor.prototype.afterGuiAttached = function () {\n if (this.focusAfterAttached) {\n this.eSelect.getFocusableElement().focus();\n }\n if (this.startedByEnter) {\n this.eSelect.showPicker();\n }\n };\n SelectCellEditor.prototype.focusIn = function () {\n this.eSelect.getFocusableElement().focus();\n };\n SelectCellEditor.prototype.getValue = function () {\n return this.eSelect.getValue();\n };\n SelectCellEditor.prototype.isPopup = function () {\n return false;\n };\n __decorate$25([\n Autowired('valueFormatterService')\n ], SelectCellEditor.prototype, \"valueFormatterService\", void 0);\n __decorate$25([\n RefSelector('eSelect')\n ], SelectCellEditor.prototype, \"eSelect\", void 0);\n return SelectCellEditor;\n}(PopupComponent));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2n = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar PopupSelectCellEditor = /** @class */ (function (_super) {\n __extends$2n(PopupSelectCellEditor, _super);\n function PopupSelectCellEditor() {\n var _this = _super.call(this) || this;\n doOnce(function () { return console.warn('AG Grid: The PopupSelectCellEditor (agPopupSelectCellEditor) is deprecated. Instead use {cellEditor: \"agSelectCellEditor\", cellEditorPopup: true} '); }, 'PopupSelectCellEditor.deprecated');\n return _this;\n }\n PopupSelectCellEditor.prototype.isPopup = function () {\n return true;\n };\n return PopupSelectCellEditor;\n}(SelectCellEditor));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2m = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$24 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TextCellEditor = /** @class */ (function (_super) {\n __extends$2m(TextCellEditor, _super);\n function TextCellEditor() {\n return _super.call(this, TextCellEditor.TEMPLATE) || this;\n }\n TextCellEditor.prototype.init = function (params) {\n this.params = params;\n var eInput = this.eInput;\n var startValue;\n // cellStartedEdit is only false if we are doing fullRow editing\n if (params.cellStartedEdit) {\n this.focusAfterAttached = true;\n if (params.eventKey === KeyCode.BACKSPACE || params.eventKey === KeyCode.DELETE) {\n startValue = '';\n }\n else if (params.charPress) {\n startValue = params.charPress;\n }\n else {\n startValue = this.getStartValue(params);\n if (params.eventKey !== KeyCode.F2) {\n this.highlightAllOnFocus = true;\n }\n }\n }\n else {\n this.focusAfterAttached = false;\n startValue = this.getStartValue(params);\n }\n if (startValue != null) {\n eInput.setValue(startValue, true);\n }\n this.addManagedListener(eInput.getGui(), 'keydown', function (event) {\n var key = event.key;\n if (key === KeyCode.PAGE_UP || key === KeyCode.PAGE_DOWN) {\n event.preventDefault();\n }\n });\n };\n TextCellEditor.prototype.afterGuiAttached = function () {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var eInput = this.eInput;\n eInput.setInputAriaLabel(translate('ariaInputEditor', 'Input Editor'));\n if (!this.focusAfterAttached) {\n return;\n }\n // Added for AG-3238. We can't remove this explicit focus() because Chrome requires an input\n // to be focused before setSelectionRange will work. But it triggers a bug in Safari where\n // explicitly focusing then blurring an empty field will cause the parent container to scroll.\n if (!isBrowserSafari()) {\n eInput.getFocusableElement().focus();\n }\n var inputEl = eInput.getInputElement();\n if (this.highlightAllOnFocus) {\n inputEl.select();\n }\n else {\n // when we started editing, we want the caret at the end, not the start.\n // this comes into play in two scenarios:\n // a) when user hits F2\n // b) when user hits a printable character\n var value = eInput.getValue();\n var len = (exists(value) && value.length) || 0;\n if (len) {\n inputEl.setSelectionRange(len, len);\n }\n }\n };\n // gets called when tabbing trough cells and in full row edit mode\n TextCellEditor.prototype.focusIn = function () {\n var eInput = this.eInput;\n var focusEl = eInput.getFocusableElement();\n var inputEl = eInput.getInputElement();\n focusEl.focus();\n inputEl.select();\n };\n TextCellEditor.prototype.getValue = function () {\n var eInput = this.eInput;\n return this.params.parseValue(eInput.getValue());\n };\n TextCellEditor.prototype.getStartValue = function (params) {\n var formatValue = params.useFormatter || params.column.getColDef().refData;\n return formatValue ? params.formatValue(params.value) : params.value;\n };\n TextCellEditor.prototype.isPopup = function () {\n return false;\n };\n TextCellEditor.TEMPLATE = '<div class=\"ag-cell-edit-wrapper\"><ag-input-text-field class=\"ag-cell-editor\" ref=\"eInput\"></ag-input-text-field></div>';\n __decorate$24([\n RefSelector('eInput')\n ], TextCellEditor.prototype, \"eInput\", void 0);\n return TextCellEditor;\n}(PopupComponent));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2l = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar PopupTextCellEditor = /** @class */ (function (_super) {\n __extends$2l(PopupTextCellEditor, _super);\n function PopupTextCellEditor() {\n var _this = _super.call(this) || this;\n doOnce(function () { return console.warn('AG Grid: The PopupTextCellEditor (agPopupTextCellEditor) is deprecated. Instead use {cellEditor: \"agTextCellEditor\", cellEditorPopup: true} '); }, 'PopupTextCellEditor.deprecated');\n return _this;\n }\n PopupTextCellEditor.prototype.isPopup = function () {\n return true;\n };\n return PopupTextCellEditor;\n}(TextCellEditor));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2k = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$23 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ARROW_UP = '\\u2191';\nvar ARROW_DOWN = '\\u2193';\nvar AnimateShowChangeCellRenderer = /** @class */ (function (_super) {\n __extends$2k(AnimateShowChangeCellRenderer, _super);\n function AnimateShowChangeCellRenderer() {\n var _this = _super.call(this, AnimateShowChangeCellRenderer.TEMPLATE) || this;\n _this.refreshCount = 0;\n return _this;\n }\n AnimateShowChangeCellRenderer.prototype.init = function (params) {\n // this.params = params;\n this.eValue = this.queryForHtmlElement('.ag-value-change-value');\n this.eDelta = this.queryForHtmlElement('.ag-value-change-delta');\n this.refresh(params);\n };\n AnimateShowChangeCellRenderer.prototype.showDelta = function (params, delta) {\n var absDelta = Math.abs(delta);\n var valueFormatted = params.formatValue(absDelta);\n var valueToUse = exists(valueFormatted) ? valueFormatted : absDelta;\n var deltaUp = (delta >= 0);\n if (deltaUp) {\n this.eDelta.innerHTML = ARROW_UP + valueToUse;\n }\n else {\n // because negative, use ABS to remove sign\n this.eDelta.innerHTML = ARROW_DOWN + valueToUse;\n }\n this.eDelta.classList.toggle('ag-value-change-delta-up', deltaUp);\n this.eDelta.classList.toggle('ag-value-change-delta-down', !deltaUp);\n };\n AnimateShowChangeCellRenderer.prototype.setTimerToRemoveDelta = function () {\n var _this = this;\n // the refreshCount makes sure that if the value updates again while\n // the below timer is waiting, then the below timer will realise it\n // is not the most recent and will not try to remove the delta value.\n this.refreshCount++;\n var refreshCountCopy = this.refreshCount;\n window.setTimeout(function () {\n if (refreshCountCopy === _this.refreshCount) {\n _this.hideDeltaValue();\n }\n }, 2000);\n };\n AnimateShowChangeCellRenderer.prototype.hideDeltaValue = function () {\n this.eValue.classList.remove('ag-value-change-value-highlight');\n clearElement(this.eDelta);\n };\n AnimateShowChangeCellRenderer.prototype.refresh = function (params) {\n var value = params.value;\n if (value === this.lastValue) {\n return false;\n }\n if (exists(params.valueFormatted)) {\n this.eValue.innerHTML = params.valueFormatted;\n }\n else if (exists(params.value)) {\n this.eValue.innerHTML = value;\n }\n else {\n clearElement(this.eValue);\n }\n // we don't show the delta if we are in the middle of a filter. see comment on FilterManager\n // with regards processingFilterChange\n if (this.filterManager.isSuppressFlashingCellsBecauseFiltering()) {\n return false;\n }\n if (typeof value === 'number' && typeof this.lastValue === 'number') {\n var delta = value - this.lastValue;\n this.showDelta(params, delta);\n }\n // highlight the current value, but only if it's not new, otherwise it\n // would get highlighted first time the value is shown\n if (this.lastValue) {\n this.eValue.classList.add('ag-value-change-value-highlight');\n }\n this.setTimerToRemoveDelta();\n this.lastValue = value;\n return true;\n };\n AnimateShowChangeCellRenderer.TEMPLATE = '<span>' +\n '<span class=\"ag-value-change-delta\"></span>' +\n '<span class=\"ag-value-change-value\"></span>' +\n '</span>';\n __decorate$23([\n Autowired('filterManager')\n ], AnimateShowChangeCellRenderer.prototype, \"filterManager\", void 0);\n return AnimateShowChangeCellRenderer;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2j = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$22 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AnimateSlideCellRenderer = /** @class */ (function (_super) {\n __extends$2j(AnimateSlideCellRenderer, _super);\n function AnimateSlideCellRenderer() {\n var _this = _super.call(this, AnimateSlideCellRenderer.TEMPLATE) || this;\n _this.refreshCount = 0;\n _this.eCurrent = _this.queryForHtmlElement('.ag-value-slide-current');\n return _this;\n }\n AnimateSlideCellRenderer.prototype.init = function (params) {\n this.refresh(params);\n };\n AnimateSlideCellRenderer.prototype.addSlideAnimation = function () {\n var _this = this;\n this.refreshCount++;\n // below we keep checking this, and stop working on the animation\n // if it no longer matches - this means another animation has started\n // and this one is stale.\n var refreshCountCopy = this.refreshCount;\n // if old animation, remove it\n if (this.ePrevious) {\n this.getGui().removeChild(this.ePrevious);\n }\n this.ePrevious = loadTemplate('<span class=\"ag-value-slide-previous ag-value-slide-out\"></span>');\n this.ePrevious.innerHTML = this.eCurrent.innerHTML;\n this.getGui().insertBefore(this.ePrevious, this.eCurrent);\n // having timeout of 0 allows use to skip to the next css turn,\n // so we know the previous css classes have been applied. so the\n // complex set of setTimeout below creates the animation\n window.setTimeout(function () {\n if (refreshCountCopy !== _this.refreshCount) {\n return;\n }\n _this.ePrevious.classList.add('ag-value-slide-out-end');\n }, 50);\n window.setTimeout(function () {\n if (refreshCountCopy !== _this.refreshCount) {\n return;\n }\n _this.getGui().removeChild(_this.ePrevious);\n _this.ePrevious = null;\n }, 3000);\n };\n AnimateSlideCellRenderer.prototype.refresh = function (params) {\n var value = params.value;\n if (missing(value)) {\n value = '';\n }\n if (value === this.lastValue) {\n return false;\n }\n // we don't show the delta if we are in the middle of a filter. see comment on FilterManager\n // with regards processingFilterChange\n if (this.filterManager.isSuppressFlashingCellsBecauseFiltering()) {\n return false;\n }\n this.addSlideAnimation();\n this.lastValue = value;\n if (exists(params.valueFormatted)) {\n this.eCurrent.innerHTML = params.valueFormatted;\n }\n else if (exists(params.value)) {\n this.eCurrent.innerHTML = value;\n }\n else {\n clearElement(this.eCurrent);\n }\n return true;\n };\n AnimateSlideCellRenderer.TEMPLATE = \"<span>\\n <span class=\\\"ag-value-slide-current\\\"></span>\\n </span>\";\n __decorate$22([\n Autowired('filterManager')\n ], AnimateSlideCellRenderer.prototype, \"filterManager\", void 0);\n return AnimateSlideCellRenderer;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar RowHighlightPosition;\n(function (RowHighlightPosition) {\n RowHighlightPosition[RowHighlightPosition[\"Above\"] = 0] = \"Above\";\n RowHighlightPosition[RowHighlightPosition[\"Below\"] = 1] = \"Below\";\n})(RowHighlightPosition || (RowHighlightPosition = {}));\nvar RowNode = /** @class */ (function () {\n function RowNode(beans) {\n /** The current row index. If the row is filtered out or in a collapsed group, this value will be `null`. */\n this.rowIndex = null;\n /** The key for the group eg Ireland, UK, USA */\n this.key = null;\n /** Children mapped by the pivot columns. */\n this.childrenMapped = {};\n /**\n * This will be `true` if it has a rowIndex assigned, otherwise `false`.\n */\n this.displayed = false;\n /** The row top position in pixels. */\n this.rowTop = null;\n /** The top pixel for this row last time, makes sense if data set was ordered or filtered,\n * it is used so new rows can animate in from their old position. */\n this.oldRowTop = null;\n /** `true` by default - can be overridden via gridOptions.isRowSelectable(rowNode) */\n this.selectable = true;\n /** Used by sorting service - to give deterministic sort to groups. Previously we\n * just id for this, however id is a string and had slower sorting compared to numbers. */\n this.__objectId = RowNode.OBJECT_ID_SEQUENCE++;\n /** When one or more Columns are using autoHeight, this keeps track of height of each autoHeight Cell,\n * indexed by the Column ID. */\n this.__autoHeights = {};\n /** `true` when nodes with the same id are being removed and added as part of the same batch transaction */\n this.alreadyRendered = false;\n this.highlighted = null;\n this.selected = false;\n this.beans = beans;\n }\n /** Replaces the data on the `rowNode`. When complete, the grid will refresh the the entire rendered row if it is showing. */\n RowNode.prototype.setData = function (data) {\n this.setDataCommon(data, false);\n };\n // similar to setRowData, however it is expected that the data is the same data item. this\n // is intended to be used with Redux type stores, where the whole data can be changed. we are\n // guaranteed that the data is the same entity (so grid doesn't need to worry about the id of the\n // underlying data changing, hence doesn't need to worry about selection). the grid, upon receiving\n // dataChanged event, will refresh the cells rather than rip them all out (so user can show transitions).\n RowNode.prototype.updateData = function (data) {\n this.setDataCommon(data, true);\n };\n RowNode.prototype.setDataCommon = function (data, update) {\n var oldData = this.data;\n this.data = data;\n this.beans.valueCache.onDataChanged();\n this.updateDataOnDetailNode();\n this.checkRowSelectable();\n var event = this.createDataChangedEvent(data, oldData, update);\n this.dispatchLocalEvent(event);\n };\n // when we are doing master / detail, the detail node is lazy created, but then kept around.\n // so if we show / hide the detail, the same detail rowNode is used. so we need to keep the data\n // in sync, otherwise expand/collapse of the detail would still show the old values.\n RowNode.prototype.updateDataOnDetailNode = function () {\n if (this.detailNode) {\n this.detailNode.data = this.data;\n }\n };\n RowNode.prototype.createDataChangedEvent = function (newData, oldData, update) {\n return {\n type: RowNode.EVENT_DATA_CHANGED,\n node: this,\n oldData: oldData,\n newData: newData,\n update: update\n };\n };\n RowNode.prototype.createLocalRowEvent = function (type) {\n return {\n type: type,\n node: this\n };\n };\n RowNode.prototype.getRowIndexString = function () {\n if (this.rowPinned === Constants.PINNED_TOP) {\n return 't-' + this.rowIndex;\n }\n if (this.rowPinned === Constants.PINNED_BOTTOM) {\n return 'b-' + this.rowIndex;\n }\n return this.rowIndex.toString();\n };\n RowNode.prototype.createDaemonNode = function () {\n var oldNode = new RowNode(this.beans);\n // just copy the id and data, this is enough for the node to be used\n // in the selection controller (the selection controller is the only\n // place where daemon nodes can live).\n oldNode.id = this.id;\n oldNode.data = this.data;\n oldNode.daemon = true;\n oldNode.selected = this.selected;\n oldNode.level = this.level;\n return oldNode;\n };\n RowNode.prototype.setDataAndId = function (data, id) {\n var oldNode = exists(this.id) ? this.createDaemonNode() : null;\n var oldData = this.data;\n this.data = data;\n this.updateDataOnDetailNode();\n this.setId(id);\n this.beans.selectionService.syncInRowNode(this, oldNode);\n this.checkRowSelectable();\n var event = this.createDataChangedEvent(data, oldData, false);\n this.dispatchLocalEvent(event);\n };\n RowNode.prototype.checkRowSelectable = function () {\n var isRowSelectableFunc = this.beans.gridOptionsWrapper.getIsRowSelectableFunc();\n this.setRowSelectable(isRowSelectableFunc ? isRowSelectableFunc(this) : true);\n };\n RowNode.prototype.setRowSelectable = function (newVal) {\n if (this.selectable !== newVal) {\n this.selectable = newVal;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_SELECTABLE_CHANGED));\n }\n var isGroupSelectsChildren = this.beans.gridOptionsWrapper.isGroupSelectsChildren();\n if (isGroupSelectsChildren) {\n var selected = this.calculateSelectedFromChildren();\n this.setSelected((selected !== null && selected !== void 0 ? selected : false));\n }\n }\n };\n RowNode.prototype.setId = function (id) {\n // see if user is providing the id's\n var getRowIdFunc = this.beans.gridOptionsWrapper.getRowIdFunc();\n if (getRowIdFunc) {\n // if user is providing the id's, then we set the id only after the data has been set.\n // this is important for virtual pagination and viewport, where empty rows exist.\n if (this.data) {\n // we pass 'true' as we skip this level when generating keys,\n // as we don't always have the key for this level (eg when updating\n // data via transaction on SSRM, we are getting key to look up the\n // RowNode, don't have the RowNode yet, thus no way to get the current key)\n var parentKeys = this.getGroupKeys(true);\n this.id = getRowIdFunc({\n data: this.data,\n parentKeys: parentKeys.length > 0 ? parentKeys : undefined,\n level: this.level\n });\n // make sure id provided doesn't start with 'row-group-' as this is reserved. also check that\n // it has 'startsWith' in case the user provided a number.\n if (this.id !== null && typeof this.id === 'string' && this.id.startsWith(RowNode.ID_PREFIX_ROW_GROUP)) {\n console.error(\"AG Grid: Row IDs cannot start with \" + RowNode.ID_PREFIX_ROW_GROUP + \", this is a reserved prefix for AG Grid's row grouping feature.\");\n }\n // force id to be a string\n if (this.id !== null && typeof this.id !== 'string') {\n this.id = '' + this.id;\n }\n }\n else {\n // this can happen if user has set blank into the rowNode after the row previously\n // having data. this happens in virtual page row model, when data is delete and\n // the page is refreshed.\n this.id = undefined;\n }\n }\n else {\n this.id = id;\n }\n };\n RowNode.prototype.getGroupKeys = function (excludeSelf) {\n if (excludeSelf === void 0) { excludeSelf = false; }\n var keys = [];\n var pointer = this;\n if (excludeSelf) {\n pointer = pointer.parent;\n }\n while (pointer && pointer.level >= 0) {\n keys.push(pointer.key);\n pointer = pointer.parent;\n }\n keys.reverse();\n return keys;\n };\n RowNode.prototype.isPixelInRange = function (pixel) {\n if (!exists(this.rowTop) || !exists(this.rowHeight)) {\n return false;\n }\n return pixel >= this.rowTop && pixel < (this.rowTop + this.rowHeight);\n };\n RowNode.prototype.setFirstChild = function (firstChild) {\n if (this.firstChild === firstChild) {\n return;\n }\n this.firstChild = firstChild;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_FIRST_CHILD_CHANGED));\n }\n };\n RowNode.prototype.setLastChild = function (lastChild) {\n if (this.lastChild === lastChild) {\n return;\n }\n this.lastChild = lastChild;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_LAST_CHILD_CHANGED));\n }\n };\n RowNode.prototype.setChildIndex = function (childIndex) {\n if (this.childIndex === childIndex) {\n return;\n }\n this.childIndex = childIndex;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_CHILD_INDEX_CHANGED));\n }\n };\n RowNode.prototype.setRowTop = function (rowTop) {\n this.oldRowTop = this.rowTop;\n if (this.rowTop === rowTop) {\n return;\n }\n this.rowTop = rowTop;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_TOP_CHANGED));\n }\n this.setDisplayed(rowTop !== null);\n };\n RowNode.prototype.clearRowTopAndRowIndex = function () {\n this.oldRowTop = null;\n this.setRowTop(null);\n this.setRowIndex(null);\n };\n RowNode.prototype.setDisplayed = function (displayed) {\n if (this.displayed === displayed) {\n return;\n }\n this.displayed = displayed;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_DISPLAYED_CHANGED));\n }\n };\n RowNode.prototype.setDragging = function (dragging) {\n if (this.dragging === dragging) {\n return;\n }\n this.dragging = dragging;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_DRAGGING_CHANGED));\n }\n };\n RowNode.prototype.setHighlighted = function (highlighted) {\n if (highlighted === this.highlighted) {\n return;\n }\n this.highlighted = highlighted;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_HIGHLIGHT_CHANGED));\n }\n };\n RowNode.prototype.setAllChildrenCount = function (allChildrenCount) {\n if (this.allChildrenCount === allChildrenCount) {\n return;\n }\n this.allChildrenCount = allChildrenCount;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED));\n }\n };\n RowNode.prototype.setMaster = function (master) {\n if (this.master === master) {\n return;\n }\n // if changing AWAY from master, then unexpand, otherwise\n // next time it's shown it is expanded again\n if (this.master && !master) {\n this.expanded = false;\n }\n this.master = master;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_MASTER_CHANGED));\n }\n };\n RowNode.prototype.setGroup = function (group) {\n if (this.group === group) {\n return;\n }\n // if we used to be a group, and no longer, then close the node\n if (this.group && !group) {\n this.expanded = false;\n }\n this.group = group;\n this.updateHasChildren();\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_GROUP_CHANGED));\n }\n };\n /**\n * Sets the row height.\n * Call if you want to change the height initially assigned to the row.\n * After calling, you must call `api.onRowHeightChanged()` so the grid knows it needs to work out the placement of the rows. */\n RowNode.prototype.setRowHeight = function (rowHeight, estimated) {\n if (estimated === void 0) { estimated = false; }\n this.rowHeight = rowHeight;\n this.rowHeightEstimated = estimated;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_HEIGHT_CHANGED));\n }\n };\n RowNode.prototype.setRowAutoHeight = function (cellHeight, column) {\n if (!this.__autoHeights) {\n this.__autoHeights = {};\n }\n var autoHeights = this.__autoHeights;\n autoHeights[column.getId()] = cellHeight;\n if (cellHeight != null) {\n if (this.checkAutoHeightsDebounced == null) {\n this.checkAutoHeightsDebounced = debounce(this.checkAutoHeights.bind(this), 1);\n }\n this.checkAutoHeightsDebounced();\n }\n };\n RowNode.prototype.checkAutoHeights = function () {\n var notAllPresent = false;\n var nonePresent = true;\n var newRowHeight = 0;\n var autoHeights = this.__autoHeights;\n if (autoHeights == null) {\n return;\n }\n var displayedAutoHeightCols = this.beans.columnModel.getAllDisplayedAutoHeightCols();\n displayedAutoHeightCols.forEach(function (col) {\n var cellHeight = autoHeights[col.getId()];\n if (cellHeight == null) {\n notAllPresent = true;\n return;\n }\n nonePresent = false;\n if (cellHeight > newRowHeight) {\n newRowHeight = cellHeight;\n }\n });\n if (notAllPresent) {\n return;\n }\n // we take min of 10, so we don't adjust for empty rows. if <10, we put to default.\n // this prevents the row starting very small when waiting for async components,\n // which would then mean the grid squashes in far to many rows (as small heights\n // means more rows fit in) which looks crap. so best ignore small values and assume\n // we are still waiting for values to render.\n if (nonePresent || newRowHeight < 10) {\n newRowHeight = this.beans.gridOptionsWrapper.getRowHeightForNode(this).height;\n }\n if (newRowHeight == this.rowHeight) {\n return;\n }\n this.setRowHeight(newRowHeight);\n var rowModel = this.beans.rowModel;\n if (rowModel.onRowHeightChangedDebounced) {\n rowModel.onRowHeightChangedDebounced();\n }\n };\n RowNode.prototype.setRowIndex = function (rowIndex) {\n if (this.rowIndex === rowIndex) {\n return;\n }\n this.rowIndex = rowIndex;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_ROW_INDEX_CHANGED));\n }\n };\n RowNode.prototype.setUiLevel = function (uiLevel) {\n if (this.uiLevel === uiLevel) {\n return;\n }\n this.uiLevel = uiLevel;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_UI_LEVEL_CHANGED));\n }\n };\n /**\n * Set the expanded state of this rowNode. Pass `true` to expand and `false` to collapse.\n */\n RowNode.prototype.setExpanded = function (expanded, e) {\n if (this.expanded === expanded) {\n return;\n }\n this.expanded = expanded;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_EXPANDED_CHANGED));\n }\n var event = Object.assign({}, this.createGlobalRowEvent(Events.EVENT_ROW_GROUP_OPENED), {\n expanded: expanded,\n event: e || null\n });\n this.beans.rowNodeEventThrottle.dispatchExpanded(event);\n // when using footers we need to refresh the group row, as the aggregation\n // values jump between group and footer\n if (this.beans.gridOptionsWrapper.isGroupIncludeFooter()) {\n this.beans.rowRenderer.refreshCells({ rowNodes: [this] });\n }\n };\n RowNode.prototype.createGlobalRowEvent = function (type) {\n return {\n type: type,\n node: this,\n data: this.data,\n rowIndex: this.rowIndex,\n rowPinned: this.rowPinned,\n context: this.beans.gridOptionsWrapper.getContext(),\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi()\n };\n };\n RowNode.prototype.dispatchLocalEvent = function (event) {\n if (this.eventService) {\n this.eventService.dispatchEvent(event);\n }\n };\n /**\n * Replaces the value on the `rowNode` for the specified column. When complete,\n * the grid will refresh the rendered cell on the required row only.\n *\n * @param colKey The column where the value should be updated\n * @param newValue The new value\n * @param eventSource The source of the event\n * @returns `True` if the value was changed, otherwise `False`.\n */\n RowNode.prototype.setDataValue = function (colKey, newValue, eventSource) {\n // When it is done via the editors, no 'cell changed' event gets fired, as it's assumed that\n // the cell knows about the change given it's in charge of the editing.\n // this method is for the client to call, so the cell listens for the change\n // event, and also flashes the cell when the change occurs.\n var column = this.beans.columnModel.getPrimaryColumn(colKey);\n var oldValue = this.beans.valueService.getValue(column, this);\n var valueChanged = this.beans.valueService.setValue(this, column, newValue, eventSource);\n this.dispatchCellChangedEvent(column, newValue, oldValue);\n this.checkRowSelectable();\n return valueChanged;\n };\n RowNode.prototype.setGroupValue = function (colKey, newValue) {\n var column = this.beans.columnModel.getGridColumn(colKey);\n if (missing(this.groupData)) {\n this.groupData = {};\n }\n var columnId = column.getColId();\n var oldValue = this.groupData[columnId];\n if (oldValue === newValue) {\n return;\n }\n this.groupData[columnId] = newValue;\n this.dispatchCellChangedEvent(column, newValue, oldValue);\n };\n // sets the data for an aggregation\n RowNode.prototype.setAggData = function (newAggData) {\n var _this = this;\n // find out all keys that could potentially change\n var colIds = getAllKeysInObjects([this.aggData, newAggData]);\n var oldAggData = this.aggData;\n this.aggData = newAggData;\n // if no event service, nobody has registered for events, so no need fire event\n if (this.eventService) {\n colIds.forEach(function (colId) {\n var column = _this.beans.columnModel.getGridColumn(colId);\n var value = _this.aggData ? _this.aggData[colId] : undefined;\n var oldValue = oldAggData ? oldAggData[colId] : undefined;\n _this.dispatchCellChangedEvent(column, value, oldValue);\n });\n }\n };\n RowNode.prototype.updateHasChildren = function () {\n // we need to return true when this.group=true, as this is used by server side row model\n // (as children are lazy loaded and stored in a cache anyway). otherwise we return true\n // if children exist.\n var newValue = (this.group && !this.footer) || (this.childrenAfterGroup && this.childrenAfterGroup.length > 0);\n if (newValue !== this.__hasChildren) {\n this.__hasChildren = !!newValue;\n if (this.eventService) {\n this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_HAS_CHILDREN_CHANGED));\n }\n }\n };\n RowNode.prototype.hasChildren = function () {\n if (this.__hasChildren == null) {\n this.updateHasChildren();\n }\n return this.__hasChildren;\n };\n RowNode.prototype.isEmptyRowGroupNode = function () {\n return this.group && missingOrEmpty(this.childrenAfterGroup);\n };\n RowNode.prototype.dispatchCellChangedEvent = function (column, newValue, oldValue) {\n var cellChangedEvent = {\n type: RowNode.EVENT_CELL_CHANGED,\n node: this,\n column: column,\n newValue: newValue,\n oldValue: oldValue\n };\n this.dispatchLocalEvent(cellChangedEvent);\n };\n /**\n * The first time `quickFilter` runs, the grid creates a one-off string representation of the row.\n * This string is then used for the quick filter instead of hitting each column separately.\n * When you edit, using grid editing, this string gets cleared down.\n * However if you edit without using grid editing, you will need to clear this string down for the row to be updated with the new values.\n * Otherwise new values will not work with the `quickFilter`. */\n RowNode.prototype.resetQuickFilterAggregateText = function () {\n this.quickFilterAggregateText = null;\n };\n RowNode.prototype.isExpandable = function () {\n return (this.hasChildren() && !this.footer) || this.master ? true : false;\n };\n /** Returns:\n * - `true` if node is selected,\n * - `false` if the node isn't selected\n * - `undefined` if it's partially selected (group where not all children are selected). */\n RowNode.prototype.isSelected = function () {\n // for footers, we just return what our sibling selected state is, as cannot select a footer\n if (this.footer) {\n return this.sibling.isSelected();\n }\n return this.selected;\n };\n /** Perform a depth-first search of this node and its children. */\n RowNode.prototype.depthFirstSearch = function (callback) {\n if (this.childrenAfterGroup) {\n this.childrenAfterGroup.forEach(function (child) { return child.depthFirstSearch(callback); });\n }\n callback(this);\n };\n // + selectionController.calculatedSelectedForAllGroupNodes()\n RowNode.prototype.calculateSelectedFromChildren = function () {\n var _a;\n var atLeastOneSelected = false;\n var atLeastOneDeSelected = false;\n var atLeastOneMixed = false;\n if (!((_a = this.childrenAfterGroup) === null || _a === void 0 ? void 0 : _a.length)) {\n return this.selectable ? this.selected : null;\n }\n for (var i = 0; i < this.childrenAfterGroup.length; i++) {\n var child = this.childrenAfterGroup[i];\n var childState = child.isSelected();\n // non-selectable nodes must be calculated from their children, or ignored if no value results.\n if (!child.selectable) {\n var selectable = child.calculateSelectedFromChildren();\n if (selectable === null) {\n continue;\n }\n childState = selectable;\n }\n switch (childState) {\n case true:\n atLeastOneSelected = true;\n break;\n case false:\n atLeastOneDeSelected = true;\n break;\n default:\n atLeastOneMixed = true;\n break;\n }\n }\n if (atLeastOneMixed || (atLeastOneSelected && atLeastOneDeSelected)) {\n return undefined;\n }\n else if (atLeastOneSelected) {\n return true;\n }\n else if (atLeastOneDeSelected) {\n return false;\n }\n else if (!this.selectable) {\n return null;\n }\n else {\n return this.selected;\n }\n };\n RowNode.prototype.setSelectedInitialValue = function (selected) {\n this.selected = selected;\n };\n /**\n * Select (or deselect) the node.\n * @param newValue -`true` for selection, `false` for deselection.\n * @param clearSelection - If selecting, then passing `true` will select the node exclusively (i.e. NOT do multi select). If doing deselection, `clearSelection` has no impact.\n * @param suppressFinishActions - Pass `true` to prevent the `selectionChanged` from being fired. Note that the `rowSelected` event will still be fired.\n */\n RowNode.prototype.setSelected = function (newValue, clearSelection, suppressFinishActions) {\n if (clearSelection === void 0) { clearSelection = false; }\n if (suppressFinishActions === void 0) { suppressFinishActions = false; }\n this.setSelectedParams({\n newValue: newValue,\n clearSelection: clearSelection,\n suppressFinishActions: suppressFinishActions,\n rangeSelect: false\n });\n };\n RowNode.prototype.isRowPinned = function () {\n return this.rowPinned === Constants.PINNED_TOP || this.rowPinned === Constants.PINNED_BOTTOM;\n };\n // to make calling code more readable, this is the same method as setSelected except it takes names parameters\n RowNode.prototype.setSelectedParams = function (params) {\n var _a;\n var groupSelectsChildren = this.beans.gridOptionsWrapper.isGroupSelectsChildren();\n var newValue = params.newValue === true;\n var clearSelection = params.clearSelection === true;\n var suppressFinishActions = params.suppressFinishActions === true;\n var rangeSelect = params.rangeSelect === true;\n // groupSelectsFiltered only makes sense when group selects children\n var groupSelectsFiltered = groupSelectsChildren && (params.groupSelectsFiltered === true);\n if (this.id === undefined) {\n console.warn('AG Grid: cannot select node until id for node is known');\n return 0;\n }\n if (this.rowPinned) {\n console.warn('AG Grid: cannot select pinned rows');\n return 0;\n }\n // if we are a footer, we don't do selection, just pass the info\n // to the sibling (the parent of the group)\n if (this.footer) {\n return this.sibling.setSelectedParams(params);\n }\n if (rangeSelect && this.beans.selectionService.getLastSelectedNode()) {\n var newRowClicked = this.beans.selectionService.getLastSelectedNode() !== this;\n var allowMultiSelect = this.beans.gridOptionsWrapper.isRowSelectionMulti();\n if (newRowClicked && allowMultiSelect) {\n var nodesChanged = this.doRowRangeSelection(params.newValue);\n this.beans.selectionService.setLastSelectedNode(this);\n return nodesChanged;\n }\n }\n var updatedCount = 0;\n // when groupSelectsFiltered, then this node may end up intermediate despite\n // trying to set it to true / false. this group will be calculated further on\n // down when we call calculatedSelectedForAllGroupNodes(). we need to skip it\n // here, otherwise the updatedCount would include it.\n var skipThisNode = groupSelectsFiltered && this.group;\n if (!skipThisNode) {\n var thisNodeWasSelected = this.selectThisNode(newValue, params.event);\n if (thisNodeWasSelected) {\n updatedCount++;\n }\n }\n if (groupSelectsChildren && ((_a = this.childrenAfterGroup) === null || _a === void 0 ? void 0 : _a.length)) {\n updatedCount += this.selectChildNodes(newValue, groupSelectsFiltered);\n }\n // clear other nodes if not doing multi select\n if (!suppressFinishActions) {\n var clearOtherNodes = newValue && (clearSelection || !this.beans.gridOptionsWrapper.isRowSelectionMulti());\n if (clearOtherNodes) {\n updatedCount += this.beans.selectionService.clearOtherNodes(this);\n }\n // only if we selected something, then update groups and fire events\n if (updatedCount > 0) {\n this.beans.selectionService.updateGroupsFromChildrenSelections();\n // this is the very end of the 'action node', so we are finished all the updates,\n // include any parent / child changes that this method caused\n var event_1 = {\n type: Events.EVENT_SELECTION_CHANGED\n };\n this.beans.eventService.dispatchEvent(event_1);\n }\n // so if user next does shift-select, we know where to start the selection from\n if (newValue) {\n this.beans.selectionService.setLastSelectedNode(this);\n }\n }\n return updatedCount;\n };\n // selects all rows between this node and the last selected node (or the top if this is the first selection).\n // not to be mixed up with 'cell range selection' where you drag the mouse, this is row range selection, by\n // holding down 'shift'.\n RowNode.prototype.doRowRangeSelection = function (value) {\n var _this = this;\n if (value === void 0) { value = true; }\n var groupsSelectChildren = this.beans.gridOptionsWrapper.isGroupSelectsChildren();\n var lastSelectedNode = this.beans.selectionService.getLastSelectedNode();\n var nodesToSelect = this.beans.rowModel.getNodesInRangeForSelection(this, lastSelectedNode);\n var updatedCount = 0;\n nodesToSelect.forEach(function (rowNode) {\n if (rowNode.group && groupsSelectChildren || (value === false && _this === rowNode)) {\n return;\n }\n var nodeWasSelected = rowNode.selectThisNode(value);\n if (nodeWasSelected) {\n updatedCount++;\n }\n });\n this.beans.selectionService.updateGroupsFromChildrenSelections();\n var event = {\n type: Events.EVENT_SELECTION_CHANGED\n };\n this.beans.eventService.dispatchEvent(event);\n return updatedCount;\n };\n RowNode.prototype.isParentOfNode = function (potentialParent) {\n var parentNode = this.parent;\n while (parentNode) {\n if (parentNode === potentialParent) {\n return true;\n }\n parentNode = parentNode.parent;\n }\n return false;\n };\n RowNode.prototype.selectThisNode = function (newValue, e) {\n // we only check selectable when newValue=true (ie selecting) to allow unselecting values,\n // as selectable is dynamic, need a way to unselect rows when selectable becomes false.\n var selectionNotAllowed = !this.selectable && newValue;\n var selectionNotChanged = this.selected === newValue;\n if (selectionNotAllowed || selectionNotChanged) {\n return false;\n }\n this.selected = newValue;\n if (this.eventService) {\n this.dispatchLocalEvent(this.createLocalRowEvent(RowNode.EVENT_ROW_SELECTED));\n }\n var event = Object.assign({}, this.createGlobalRowEvent(Events.EVENT_ROW_SELECTED), {\n event: e || null\n });\n this.beans.eventService.dispatchEvent(event);\n return true;\n };\n RowNode.prototype.selectChildNodes = function (newValue, groupSelectsFiltered) {\n var children = groupSelectsFiltered ? this.childrenAfterAggFilter : this.childrenAfterGroup;\n if (missing(children)) {\n return 0;\n }\n var updatedCount = 0;\n for (var i = 0; i < children.length; i++) {\n updatedCount += children[i].setSelectedParams({\n newValue: newValue,\n clearSelection: false,\n suppressFinishActions: true,\n groupSelectsFiltered: groupSelectsFiltered\n });\n }\n return updatedCount;\n };\n /** Add an event listener. */\n RowNode.prototype.addEventListener = function (eventType, listener) {\n if (!this.eventService) {\n this.eventService = new EventService();\n }\n this.eventService.addEventListener(eventType, listener);\n };\n /** Remove event listener. */\n RowNode.prototype.removeEventListener = function (eventType, listener) {\n if (!this.eventService) {\n return;\n }\n this.eventService.removeEventListener(eventType, listener);\n if (this.eventService.noRegisteredListenersExist()) {\n this.eventService = null;\n }\n };\n RowNode.prototype.onMouseEnter = function () {\n this.dispatchLocalEvent(this.createLocalRowEvent(RowNode.EVENT_MOUSE_ENTER));\n };\n RowNode.prototype.onMouseLeave = function () {\n this.dispatchLocalEvent(this.createLocalRowEvent(RowNode.EVENT_MOUSE_LEAVE));\n };\n RowNode.prototype.getFirstChildOfFirstChild = function (rowGroupColumn) {\n var currentRowNode = this;\n var isCandidate = true;\n var foundFirstChildPath = false;\n var nodeToSwapIn = null;\n // if we are hiding groups, then if we are the first child, of the first child,\n // all the way up to the column we are interested in, then we show the group cell.\n while (isCandidate && !foundFirstChildPath) {\n var parentRowNode = currentRowNode.parent;\n var firstChild = exists(parentRowNode) && currentRowNode.firstChild;\n if (firstChild) {\n if (parentRowNode.rowGroupColumn === rowGroupColumn) {\n foundFirstChildPath = true;\n nodeToSwapIn = parentRowNode;\n }\n }\n else {\n isCandidate = false;\n }\n currentRowNode = parentRowNode;\n }\n return foundFirstChildPath ? nodeToSwapIn : null;\n };\n RowNode.prototype.isFullWidthCell = function () {\n var isFullWidthCellFunc = this.beans.gridOptionsWrapper.getIsFullWidthCellFunc();\n return isFullWidthCellFunc ? isFullWidthCellFunc({ rowNode: this }) : false;\n };\n /**\n * Returns the route of the row node. If the Row Node is a group, it returns the route to that Row Node.\n * If the Row Node is not a group, it returns `undefined`.\n */\n RowNode.prototype.getRoute = function () {\n if (this.key == null) {\n return;\n }\n var res = [];\n var pointer = this;\n while (pointer.key != null) {\n res.push(pointer.key);\n pointer = pointer.parent;\n }\n return res.reverse();\n };\n RowNode.ID_PREFIX_ROW_GROUP = 'row-group-';\n RowNode.ID_PREFIX_TOP_PINNED = 't-';\n RowNode.ID_PREFIX_BOTTOM_PINNED = 'b-';\n RowNode.OBJECT_ID_SEQUENCE = 0;\n RowNode.EVENT_ROW_SELECTED = 'rowSelected';\n RowNode.EVENT_DATA_CHANGED = 'dataChanged';\n RowNode.EVENT_CELL_CHANGED = 'cellChanged';\n RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED = 'allChildrenCountChanged';\n RowNode.EVENT_MASTER_CHANGED = 'masterChanged';\n RowNode.EVENT_GROUP_CHANGED = 'groupChanged';\n RowNode.EVENT_MOUSE_ENTER = 'mouseEnter';\n RowNode.EVENT_MOUSE_LEAVE = 'mouseLeave';\n RowNode.EVENT_HEIGHT_CHANGED = 'heightChanged';\n RowNode.EVENT_TOP_CHANGED = 'topChanged';\n RowNode.EVENT_DISPLAYED_CHANGED = 'displayedChanged';\n RowNode.EVENT_FIRST_CHILD_CHANGED = 'firstChildChanged';\n RowNode.EVENT_LAST_CHILD_CHANGED = 'lastChildChanged';\n RowNode.EVENT_CHILD_INDEX_CHANGED = 'childIndexChanged';\n RowNode.EVENT_ROW_INDEX_CHANGED = 'rowIndexChanged';\n RowNode.EVENT_EXPANDED_CHANGED = 'expandedChanged';\n RowNode.EVENT_HAS_CHILDREN_CHANGED = 'hasChildrenChanged';\n RowNode.EVENT_SELECTABLE_CHANGED = 'selectableChanged';\n RowNode.EVENT_UI_LEVEL_CHANGED = 'uiLevelChanged';\n RowNode.EVENT_HIGHLIGHT_CHANGED = 'rowHighlightChanged';\n RowNode.EVENT_DRAGGING_CHANGED = 'draggingChanged';\n return RowNode;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2i = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$9 = (undefined && undefined.__assign) || function () {\n __assign$9 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$9.apply(this, arguments);\n};\nvar __decorate$21 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar CheckboxSelectionComponent = /** @class */ (function (_super) {\n __extends$2i(CheckboxSelectionComponent, _super);\n function CheckboxSelectionComponent() {\n return _super.call(this, /* html*/ \"\\n <div class=\\\"ag-selection-checkbox\\\" role=\\\"presentation\\\">\\n <ag-checkbox role=\\\"presentation\\\" ref=\\\"eCheckbox\\\"></ag-checkbox>\\n </div>\") || this;\n }\n CheckboxSelectionComponent.prototype.postConstruct = function () {\n this.eCheckbox.setPassive(true);\n };\n CheckboxSelectionComponent.prototype.getCheckboxId = function () {\n return this.eCheckbox.getInputElement().id;\n };\n CheckboxSelectionComponent.prototype.onDataChanged = function () {\n // when rows are loaded for the second time, this can impact the selection, as a row\n // could be loaded as already selected (if user scrolls down, and then up again).\n this.onSelectionChanged();\n };\n CheckboxSelectionComponent.prototype.onSelectableChanged = function () {\n this.showOrHideSelect();\n };\n CheckboxSelectionComponent.prototype.onSelectionChanged = function () {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var state = this.rowNode.isSelected();\n var stateName = state === undefined\n ? translate('ariaIndeterminate', 'indeterminate')\n : (state === true\n ? translate('ariaChecked', 'checked')\n : translate('ariaUnchecked', 'unchecked'));\n var ariaLabel = translate('ariaRowToggleSelection', 'Press Space to toggle row selection');\n this.eCheckbox.setValue(state, true);\n this.eCheckbox.setInputAriaLabel(ariaLabel + \" (\" + stateName + \")\");\n };\n CheckboxSelectionComponent.prototype.onCheckedClicked = function (event) {\n var groupSelectsFiltered = this.gridOptionsWrapper.isGroupSelectsFiltered();\n var updatedCount = this.rowNode.setSelectedParams({ newValue: false, rangeSelect: event.shiftKey, groupSelectsFiltered: groupSelectsFiltered });\n return updatedCount;\n };\n CheckboxSelectionComponent.prototype.onUncheckedClicked = function (event) {\n var groupSelectsFiltered = this.gridOptionsWrapper.isGroupSelectsFiltered();\n var updatedCount = this.rowNode.setSelectedParams({ newValue: true, rangeSelect: event.shiftKey, groupSelectsFiltered: groupSelectsFiltered });\n return updatedCount;\n };\n CheckboxSelectionComponent.prototype.init = function (params) {\n var _this = this;\n this.rowNode = params.rowNode;\n this.column = params.column;\n this.overrides = params.overrides;\n this.onSelectionChanged();\n // we don't want double click on this icon to open a group\n this.addManagedListener(this.eCheckbox.getInputElement(), 'dblclick', function (event) {\n stopPropagationForAgGrid(event);\n });\n this.addManagedListener(this.eCheckbox.getInputElement(), 'click', function (event) {\n // we don't want the row clicked event to fire when selecting the checkbox, otherwise the row\n // would possibly get selected twice\n stopPropagationForAgGrid(event);\n var isSelected = _this.eCheckbox.getValue();\n var previousValue = _this.eCheckbox.getPreviousValue();\n if (previousValue === undefined || isSelected === undefined) {\n // Indeterminate state - try toggling children to determine action.\n var result = _this.onUncheckedClicked(event || {});\n if (result === 0) {\n _this.onCheckedClicked(event);\n }\n }\n else if (isSelected) {\n _this.onCheckedClicked(event);\n }\n else {\n _this.onUncheckedClicked(event || {});\n }\n });\n this.addManagedListener(this.rowNode, RowNode.EVENT_ROW_SELECTED, this.onSelectionChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, this.onDataChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_SELECTABLE_CHANGED, this.onSelectableChanged.bind(this));\n var isRowSelectableFunc = this.gridOptionsWrapper.getIsRowSelectableFunc();\n var checkboxVisibleIsDynamic = isRowSelectableFunc || typeof this.getIsVisible() === 'function';\n if (checkboxVisibleIsDynamic) {\n var showOrHideSelectListener = this.showOrHideSelect.bind(this);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, showOrHideSelectListener);\n this.addManagedListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, showOrHideSelectListener);\n this.addManagedListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, showOrHideSelectListener);\n this.showOrHideSelect();\n }\n this.eCheckbox.getInputElement().setAttribute('tabindex', '-1');\n };\n CheckboxSelectionComponent.prototype.showOrHideSelect = function () {\n var _a, _b, _c, _d;\n // if the isRowSelectable() is not provided the row node is selectable by default\n var selectable = this.rowNode.selectable;\n // checkboxSelection callback is deemed a legacy solution however we will still consider it's result.\n // If selectable, then also check the colDef callback. if not selectable, this it short circuits - no need\n // to call the colDef callback.\n var isVisible = this.getIsVisible();\n if (selectable) {\n if (typeof isVisible === 'function') {\n var extraParams = (_a = this.overrides) === null || _a === void 0 ? void 0 : _a.callbackParams;\n var params = (_b = this.column) === null || _b === void 0 ? void 0 : _b.createColumnFunctionCallbackParams(this.rowNode);\n selectable = params ? isVisible(__assign$9(__assign$9({}, extraParams), params)) : false;\n }\n else {\n selectable = (isVisible !== null && isVisible !== void 0 ? isVisible : false);\n }\n }\n var disableInsteadOfHide = (_c = this.column) === null || _c === void 0 ? void 0 : _c.getColDef().showDisabledCheckboxes;\n if (disableInsteadOfHide) {\n this.eCheckbox.setDisabled(!selectable);\n this.setVisible(true);\n this.setDisplayed(true);\n return;\n }\n if ((_d = this.overrides) === null || _d === void 0 ? void 0 : _d.removeHidden) {\n this.setDisplayed(selectable);\n return;\n }\n this.setVisible(selectable);\n };\n CheckboxSelectionComponent.prototype.getIsVisible = function () {\n var _a, _b;\n if (this.overrides) {\n return this.overrides.isVisible;\n }\n // column will be missing if groupUseEntireRow=true\n return (_b = (_a = this.column) === null || _a === void 0 ? void 0 : _a.getColDef()) === null || _b === void 0 ? void 0 : _b.checkboxSelection;\n };\n __decorate$21([\n RefSelector('eCheckbox')\n ], CheckboxSelectionComponent.prototype, \"eCheckbox\", void 0);\n __decorate$21([\n PostConstruct\n ], CheckboxSelectionComponent.prototype, \"postConstruct\", null);\n return CheckboxSelectionComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2h = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$20 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __values$3 = (undefined && undefined.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\nvar DragSourceType;\n(function (DragSourceType) {\n DragSourceType[DragSourceType[\"ToolPanel\"] = 0] = \"ToolPanel\";\n DragSourceType[DragSourceType[\"HeaderCell\"] = 1] = \"HeaderCell\";\n DragSourceType[DragSourceType[\"RowDrag\"] = 2] = \"RowDrag\";\n DragSourceType[DragSourceType[\"ChartPanel\"] = 3] = \"ChartPanel\";\n})(DragSourceType || (DragSourceType = {}));\nvar VerticalDirection;\n(function (VerticalDirection) {\n VerticalDirection[VerticalDirection[\"Up\"] = 0] = \"Up\";\n VerticalDirection[VerticalDirection[\"Down\"] = 1] = \"Down\";\n})(VerticalDirection || (VerticalDirection = {}));\nvar HorizontalDirection;\n(function (HorizontalDirection) {\n HorizontalDirection[HorizontalDirection[\"Left\"] = 0] = \"Left\";\n HorizontalDirection[HorizontalDirection[\"Right\"] = 1] = \"Right\";\n})(HorizontalDirection || (HorizontalDirection = {}));\nvar DragAndDropService = /** @class */ (function (_super) {\n __extends$2h(DragAndDropService, _super);\n function DragAndDropService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.dragSourceAndParamsList = [];\n _this.dropTargets = [];\n return _this;\n }\n DragAndDropService_1 = DragAndDropService;\n DragAndDropService.prototype.init = function () {\n this.ePinnedIcon = createIcon('columnMovePin', this.gridOptionsWrapper, null);\n this.eHideIcon = createIcon('columnMoveHide', this.gridOptionsWrapper, null);\n this.eMoveIcon = createIcon('columnMoveMove', this.gridOptionsWrapper, null);\n this.eLeftIcon = createIcon('columnMoveLeft', this.gridOptionsWrapper, null);\n this.eRightIcon = createIcon('columnMoveRight', this.gridOptionsWrapper, null);\n this.eGroupIcon = createIcon('columnMoveGroup', this.gridOptionsWrapper, null);\n this.eAggregateIcon = createIcon('columnMoveValue', this.gridOptionsWrapper, null);\n this.ePivotIcon = createIcon('columnMovePivot', this.gridOptionsWrapper, null);\n this.eDropNotAllowedIcon = createIcon('dropNotAllowed', this.gridOptionsWrapper, null);\n };\n DragAndDropService.prototype.addDragSource = function (dragSource, allowTouch) {\n if (allowTouch === void 0) { allowTouch = false; }\n var params = {\n eElement: dragSource.eElement,\n dragStartPixels: dragSource.dragStartPixels,\n onDragStart: this.onDragStart.bind(this, dragSource),\n onDragStop: this.onDragStop.bind(this),\n onDragging: this.onDragging.bind(this)\n };\n this.dragSourceAndParamsList.push({ params: params, dragSource: dragSource });\n this.dragService.addDragSource(params, allowTouch);\n };\n DragAndDropService.prototype.removeDragSource = function (dragSource) {\n var sourceAndParams = this.dragSourceAndParamsList.find(function (item) { return item.dragSource === dragSource; });\n if (sourceAndParams) {\n this.dragService.removeDragSource(sourceAndParams.params);\n removeFromArray(this.dragSourceAndParamsList, sourceAndParams);\n }\n };\n DragAndDropService.prototype.clearDragSourceParamsList = function () {\n var _this = this;\n this.dragSourceAndParamsList.forEach(function (sourceAndParams) { return _this.dragService.removeDragSource(sourceAndParams.params); });\n this.dragSourceAndParamsList.length = 0;\n };\n DragAndDropService.prototype.nudge = function () {\n if (this.dragging) {\n this.onDragging(this.eventLastTime, true);\n }\n };\n DragAndDropService.prototype.onDragStart = function (dragSource, mouseEvent) {\n this.dragging = true;\n this.dragSource = dragSource;\n this.eventLastTime = mouseEvent;\n this.dragItem = this.dragSource.getDragItem();\n this.lastDropTarget = this.dragSource.dragSourceDropTarget;\n if (this.dragSource.onDragStarted) {\n this.dragSource.onDragStarted();\n }\n this.createGhost();\n };\n DragAndDropService.prototype.onDragStop = function (mouseEvent) {\n this.eventLastTime = null;\n this.dragging = false;\n if (this.dragSource.onDragStopped) {\n this.dragSource.onDragStopped();\n }\n if (this.lastDropTarget && this.lastDropTarget.onDragStop) {\n var draggingEvent = this.createDropTargetEvent(this.lastDropTarget, mouseEvent, null, null, false);\n this.lastDropTarget.onDragStop(draggingEvent);\n }\n this.lastDropTarget = null;\n this.dragItem = null;\n this.removeGhost();\n };\n DragAndDropService.prototype.onDragging = function (mouseEvent, fromNudge) {\n var _this = this;\n var _a, _b, _c, _d;\n var hDirection = this.getHorizontalDirection(mouseEvent);\n var vDirection = this.getVerticalDirection(mouseEvent);\n this.eventLastTime = mouseEvent;\n this.positionGhost(mouseEvent);\n // check if mouseEvent intersects with any of the drop targets\n var validDropTargets = this.dropTargets.filter(function (target) { return _this.isMouseOnDropTarget(mouseEvent, target); });\n var dropTarget = this.findCurrentDropTarget(mouseEvent, validDropTargets);\n if (dropTarget !== this.lastDropTarget) {\n this.leaveLastTargetIfExists(mouseEvent, hDirection, vDirection, fromNudge);\n if (this.lastDropTarget !== null && dropTarget === null) {\n (_b = (_a = this.dragSource).onGridExit) === null || _b === void 0 ? void 0 : _b.call(_a, this.dragItem);\n }\n if (this.lastDropTarget === null && dropTarget !== null) {\n (_d = (_c = this.dragSource).onGridEnter) === null || _d === void 0 ? void 0 : _d.call(_c, this.dragItem);\n }\n this.enterDragTargetIfExists(dropTarget, mouseEvent, hDirection, vDirection, fromNudge);\n this.lastDropTarget = dropTarget;\n }\n else if (dropTarget && dropTarget.onDragging) {\n var draggingEvent = this.createDropTargetEvent(dropTarget, mouseEvent, hDirection, vDirection, fromNudge);\n dropTarget.onDragging(draggingEvent);\n }\n };\n DragAndDropService.prototype.getAllContainersFromDropTarget = function (dropTarget) {\n var secondaryContainers = dropTarget.getSecondaryContainers ? dropTarget.getSecondaryContainers() : null;\n var containers = [[dropTarget.getContainer()]];\n return secondaryContainers ? containers.concat(secondaryContainers) : containers;\n };\n DragAndDropService.prototype.allContainersIntersect = function (mouseEvent, containers) {\n var e_1, _a;\n try {\n for (var containers_1 = __values$3(containers), containers_1_1 = containers_1.next(); !containers_1_1.done; containers_1_1 = containers_1.next()) {\n var container = containers_1_1.value;\n var rect = container.getBoundingClientRect();\n // if element is not visible, then width and height are zero\n if (rect.width === 0 || rect.height === 0) {\n return false;\n }\n var horizontalFit = mouseEvent.clientX >= rect.left && mouseEvent.clientX < rect.right;\n var verticalFit = mouseEvent.clientY >= rect.top && mouseEvent.clientY < rect.bottom;\n if (!horizontalFit || !verticalFit) {\n return false;\n }\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (containers_1_1 && !containers_1_1.done && (_a = containers_1.return)) _a.call(containers_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n return true;\n };\n // checks if the mouse is on the drop target. it checks eContainer and eSecondaryContainers\n DragAndDropService.prototype.isMouseOnDropTarget = function (mouseEvent, dropTarget) {\n var e_2, _a;\n var allContainersFromDropTarget = this.getAllContainersFromDropTarget(dropTarget);\n var mouseOverTarget = false;\n try {\n for (var allContainersFromDropTarget_1 = __values$3(allContainersFromDropTarget), allContainersFromDropTarget_1_1 = allContainersFromDropTarget_1.next(); !allContainersFromDropTarget_1_1.done; allContainersFromDropTarget_1_1 = allContainersFromDropTarget_1.next()) {\n var currentContainers = allContainersFromDropTarget_1_1.value;\n if (this.allContainersIntersect(mouseEvent, currentContainers)) {\n mouseOverTarget = true;\n break;\n }\n }\n }\n catch (e_2_1) { e_2 = { error: e_2_1 }; }\n finally {\n try {\n if (allContainersFromDropTarget_1_1 && !allContainersFromDropTarget_1_1.done && (_a = allContainersFromDropTarget_1.return)) _a.call(allContainersFromDropTarget_1);\n }\n finally { if (e_2) throw e_2.error; }\n }\n if (dropTarget.targetContainsSource && !dropTarget.getContainer().contains(this.dragSource.eElement)) {\n return false;\n }\n return mouseOverTarget && dropTarget.isInterestedIn(this.dragSource.type, this.dragSource.eElement);\n };\n DragAndDropService.prototype.findCurrentDropTarget = function (mouseEvent, validDropTargets) {\n var e_3, _a, e_4, _b;\n var len = validDropTargets.length;\n if (len === 0) {\n return null;\n }\n if (len === 1) {\n return validDropTargets[0];\n }\n var eDocument = this.gridOptionsWrapper.getDocument();\n // elementsFromPoint return a list of elements under\n // the mouseEvent sorted from topMost to bottomMost\n var elementStack = eDocument.elementsFromPoint(mouseEvent.clientX, mouseEvent.clientY);\n try {\n // loop over the sorted elementStack to find which dropTarget comes first\n for (var elementStack_1 = __values$3(elementStack), elementStack_1_1 = elementStack_1.next(); !elementStack_1_1.done; elementStack_1_1 = elementStack_1.next()) {\n var el = elementStack_1_1.value;\n try {\n for (var validDropTargets_1 = (e_4 = void 0, __values$3(validDropTargets)), validDropTargets_1_1 = validDropTargets_1.next(); !validDropTargets_1_1.done; validDropTargets_1_1 = validDropTargets_1.next()) {\n var dropTarget = validDropTargets_1_1.value;\n var containers = flatten(this.getAllContainersFromDropTarget(dropTarget));\n if (containers.indexOf(el) !== -1) {\n return dropTarget;\n }\n }\n }\n catch (e_4_1) { e_4 = { error: e_4_1 }; }\n finally {\n try {\n if (validDropTargets_1_1 && !validDropTargets_1_1.done && (_b = validDropTargets_1.return)) _b.call(validDropTargets_1);\n }\n finally { if (e_4) throw e_4.error; }\n }\n }\n }\n catch (e_3_1) { e_3 = { error: e_3_1 }; }\n finally {\n try {\n if (elementStack_1_1 && !elementStack_1_1.done && (_a = elementStack_1.return)) _a.call(elementStack_1);\n }\n finally { if (e_3) throw e_3.error; }\n }\n // we should never hit this point of the code because only\n // valid dropTargets should be provided to this method.\n return null;\n };\n DragAndDropService.prototype.enterDragTargetIfExists = function (dropTarget, mouseEvent, hDirection, vDirection, fromNudge) {\n if (!dropTarget) {\n return;\n }\n if (dropTarget.onDragEnter) {\n var dragEnterEvent = this.createDropTargetEvent(dropTarget, mouseEvent, hDirection, vDirection, fromNudge);\n dropTarget.onDragEnter(dragEnterEvent);\n }\n this.setGhostIcon(dropTarget.getIconName ? dropTarget.getIconName() : null);\n };\n DragAndDropService.prototype.leaveLastTargetIfExists = function (mouseEvent, hDirection, vDirection, fromNudge) {\n if (!this.lastDropTarget) {\n return;\n }\n if (this.lastDropTarget.onDragLeave) {\n var dragLeaveEvent = this.createDropTargetEvent(this.lastDropTarget, mouseEvent, hDirection, vDirection, fromNudge);\n this.lastDropTarget.onDragLeave(dragLeaveEvent);\n }\n this.setGhostIcon(null);\n };\n DragAndDropService.prototype.addDropTarget = function (dropTarget) {\n this.dropTargets.push(dropTarget);\n };\n DragAndDropService.prototype.removeDropTarget = function (dropTarget) {\n this.dropTargets = this.dropTargets.filter(function (target) { return target.getContainer() !== dropTarget.getContainer(); });\n };\n DragAndDropService.prototype.hasExternalDropZones = function () {\n return this.dropTargets.some(function (zones) { return zones.external; });\n };\n DragAndDropService.prototype.findExternalZone = function (params) {\n var externalTargets = this.dropTargets.filter(function (target) { return target.external; });\n return externalTargets.find(function (zone) { return zone.getContainer() === params.getContainer(); }) || null;\n };\n DragAndDropService.prototype.getHorizontalDirection = function (event) {\n var clientX = this.eventLastTime && this.eventLastTime.clientX;\n var eClientX = event.clientX;\n if (clientX === eClientX) {\n return null;\n }\n return clientX > eClientX ? HorizontalDirection.Left : HorizontalDirection.Right;\n };\n DragAndDropService.prototype.getVerticalDirection = function (event) {\n var clientY = this.eventLastTime && this.eventLastTime.clientY;\n var eClientY = event.clientY;\n if (clientY === eClientY) {\n return null;\n }\n return clientY > eClientY ? VerticalDirection.Up : VerticalDirection.Down;\n };\n DragAndDropService.prototype.createDropTargetEvent = function (dropTarget, event, hDirection, vDirection, fromNudge) {\n // localise x and y to the target\n var dropZoneTarget = dropTarget.getContainer();\n var rect = dropZoneTarget.getBoundingClientRect();\n var _a = this, api = _a.gridApi, columnApi = _a.columnApi, dragItem = _a.dragItem, dragSource = _a.dragSource;\n var x = event.clientX - rect.left;\n var y = event.clientY - rect.top;\n return { event: event, x: x, y: y, vDirection: vDirection, hDirection: hDirection, dragSource: dragSource, fromNudge: fromNudge, dragItem: dragItem, api: api, columnApi: columnApi, dropZoneTarget: dropZoneTarget };\n };\n DragAndDropService.prototype.positionGhost = function (event) {\n var ghost = this.eGhost;\n if (!ghost) {\n return;\n }\n var ghostRect = ghost.getBoundingClientRect();\n var ghostHeight = ghostRect.height;\n // for some reason, without the '-2', it still overlapped by 1 or 2 pixels, which\n // then brought in scrollbars to the browser. no idea why, but putting in -2 here\n // works around it which is good enough for me.\n var browserWidth = getBodyWidth() - 2;\n var browserHeight = getBodyHeight() - 2;\n var top = event.pageY - (ghostHeight / 2);\n var left = event.pageX - 10;\n var eDocument = this.gridOptionsWrapper.getDocument();\n var win = (eDocument.defaultView || window);\n var windowScrollY = win.pageYOffset || eDocument.documentElement.scrollTop;\n var windowScrollX = win.pageXOffset || eDocument.documentElement.scrollLeft;\n // check ghost is not positioned outside of the browser\n if (browserWidth > 0 && ((left + ghost.clientWidth) > (browserWidth + windowScrollX))) {\n left = browserWidth + windowScrollX - ghost.clientWidth;\n }\n if (left < 0) {\n left = 0;\n }\n if (browserHeight > 0 && ((top + ghost.clientHeight) > (browserHeight + windowScrollY))) {\n top = browserHeight + windowScrollY - ghost.clientHeight;\n }\n if (top < 0) {\n top = 0;\n }\n ghost.style.left = left + \"px\";\n ghost.style.top = top + \"px\";\n };\n DragAndDropService.prototype.removeGhost = function () {\n if (this.eGhost && this.eGhostParent) {\n this.eGhostParent.removeChild(this.eGhost);\n }\n this.eGhost = null;\n };\n DragAndDropService.prototype.createGhost = function () {\n this.eGhost = loadTemplate(DragAndDropService_1.GHOST_TEMPLATE);\n this.mouseEventService.stampTopLevelGridCompWithGridInstance(this.eGhost);\n var theme = this.environment.getTheme().theme;\n if (theme) {\n this.eGhost.classList.add(theme);\n }\n this.eGhostIcon = this.eGhost.querySelector('.ag-dnd-ghost-icon');\n this.setGhostIcon(null);\n var eText = this.eGhost.querySelector('.ag-dnd-ghost-label');\n var dragItemName = this.dragSource.dragItemName;\n if (isFunction(dragItemName)) {\n dragItemName = dragItemName();\n }\n eText.innerHTML = escapeString(dragItemName) || '';\n this.eGhost.style.height = '25px';\n this.eGhost.style.top = '20px';\n this.eGhost.style.left = '20px';\n var eDocument = this.gridOptionsWrapper.getDocument();\n var targetEl = null;\n try {\n targetEl = eDocument.fullscreenElement;\n }\n catch (e) {\n // some environments like SalesForce will throw errors\n // simply by trying to read the fullscreenElement property\n }\n finally {\n if (!targetEl) {\n targetEl = eDocument.querySelector('body');\n }\n }\n this.eGhostParent = targetEl;\n if (!this.eGhostParent) {\n console.warn('AG Grid: could not find document body, it is needed for dragging columns');\n }\n else {\n this.eGhostParent.appendChild(this.eGhost);\n }\n };\n DragAndDropService.prototype.setGhostIcon = function (iconName, shake) {\n if (shake === void 0) { shake = false; }\n clearElement(this.eGhostIcon);\n var eIcon = null;\n if (!iconName) {\n iconName = this.dragSource.defaultIconName || DragAndDropService_1.ICON_NOT_ALLOWED;\n }\n switch (iconName) {\n case DragAndDropService_1.ICON_PINNED:\n eIcon = this.ePinnedIcon;\n break;\n case DragAndDropService_1.ICON_MOVE:\n eIcon = this.eMoveIcon;\n break;\n case DragAndDropService_1.ICON_LEFT:\n eIcon = this.eLeftIcon;\n break;\n case DragAndDropService_1.ICON_RIGHT:\n eIcon = this.eRightIcon;\n break;\n case DragAndDropService_1.ICON_GROUP:\n eIcon = this.eGroupIcon;\n break;\n case DragAndDropService_1.ICON_AGGREGATE:\n eIcon = this.eAggregateIcon;\n break;\n case DragAndDropService_1.ICON_PIVOT:\n eIcon = this.ePivotIcon;\n break;\n case DragAndDropService_1.ICON_NOT_ALLOWED:\n eIcon = this.eDropNotAllowedIcon;\n break;\n case DragAndDropService_1.ICON_HIDE:\n eIcon = this.eHideIcon;\n break;\n }\n this.eGhostIcon.classList.toggle('ag-shake-left-to-right', shake);\n if (eIcon === this.eHideIcon && this.gridOptionsWrapper.isSuppressDragLeaveHidesColumns()) {\n return;\n }\n if (eIcon) {\n this.eGhostIcon.appendChild(eIcon);\n }\n };\n var DragAndDropService_1;\n DragAndDropService.ICON_PINNED = 'pinned';\n DragAndDropService.ICON_MOVE = 'move';\n DragAndDropService.ICON_LEFT = 'left';\n DragAndDropService.ICON_RIGHT = 'right';\n DragAndDropService.ICON_GROUP = 'group';\n DragAndDropService.ICON_AGGREGATE = 'aggregate';\n DragAndDropService.ICON_PIVOT = 'pivot';\n DragAndDropService.ICON_NOT_ALLOWED = 'notAllowed';\n DragAndDropService.ICON_HIDE = 'hide';\n DragAndDropService.GHOST_TEMPLATE = \"<div class=\\\"ag-dnd-ghost ag-unselectable\\\">\\n <span class=\\\"ag-dnd-ghost-icon ag-shake-left-to-right\\\"></span>\\n <div class=\\\"ag-dnd-ghost-label\\\"></div>\\n </div>\";\n __decorate$20([\n Autowired('dragService')\n ], DragAndDropService.prototype, \"dragService\", void 0);\n __decorate$20([\n Autowired('mouseEventService')\n ], DragAndDropService.prototype, \"mouseEventService\", void 0);\n __decorate$20([\n Autowired('environment')\n ], DragAndDropService.prototype, \"environment\", void 0);\n __decorate$20([\n Autowired('columnApi')\n ], DragAndDropService.prototype, \"columnApi\", void 0);\n __decorate$20([\n Autowired('gridApi')\n ], DragAndDropService.prototype, \"gridApi\", void 0);\n __decorate$20([\n PostConstruct\n ], DragAndDropService.prototype, \"init\", null);\n __decorate$20([\n PreDestroy\n ], DragAndDropService.prototype, \"clearDragSourceParamsList\", null);\n DragAndDropService = DragAndDropService_1 = __decorate$20([\n Bean('dragAndDropService')\n ], DragAndDropService);\n return DragAndDropService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2g = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1$ = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RowDragComp = /** @class */ (function (_super) {\n __extends$2g(RowDragComp, _super);\n function RowDragComp(cellValueFn, rowNode, column, customGui, dragStartPixels, suppressVisibilityChange) {\n var _this = _super.call(this) || this;\n _this.cellValueFn = cellValueFn;\n _this.rowNode = rowNode;\n _this.column = column;\n _this.customGui = customGui;\n _this.dragStartPixels = dragStartPixels;\n _this.suppressVisibilityChange = suppressVisibilityChange;\n _this.dragSource = null;\n return _this;\n }\n RowDragComp.prototype.isCustomGui = function () {\n return this.customGui != null;\n };\n RowDragComp.prototype.postConstruct = function () {\n if (!this.customGui) {\n this.setTemplate(/* html */ \"<div class=\\\"ag-drag-handle ag-row-drag\\\" aria-hidden=\\\"true\\\"></div>\");\n this.getGui().appendChild(createIconNoSpan('rowDrag', this.beans.gridOptionsWrapper, null));\n this.addDragSource();\n }\n else {\n this.setDragElement(this.customGui, this.dragStartPixels);\n }\n this.checkCompatibility();\n if (!this.suppressVisibilityChange) {\n var strategy = this.beans.gridOptionsWrapper.isRowDragManaged() ?\n new ManagedVisibilityStrategy(this, this.beans, this.rowNode, this.column) :\n new NonManagedVisibilityStrategy(this, this.beans, this.rowNode, this.column);\n this.createManagedBean(strategy, this.beans.context);\n }\n };\n RowDragComp.prototype.setDragElement = function (dragElement, dragStartPixels) {\n this.setTemplateFromElement(dragElement);\n this.addDragSource(dragStartPixels);\n };\n RowDragComp.prototype.getSelectedNodes = function () {\n var isRowDragMultiRow = this.beans.gridOptionsWrapper.isRowDragMultiRow();\n if (!isRowDragMultiRow) {\n return [this.rowNode];\n }\n var selection = this.beans.selectionService.getSelectedNodes();\n return selection.indexOf(this.rowNode) !== -1 ? selection : [this.rowNode];\n };\n // returns true if all compatibility items work out\n RowDragComp.prototype.checkCompatibility = function () {\n var managed = this.beans.gridOptionsWrapper.isRowDragManaged();\n var treeData = this.beans.gridOptionsWrapper.isTreeData();\n if (treeData && managed) {\n doOnce(function () {\n return console.warn('AG Grid: If using row drag with tree data, you cannot have rowDragManaged=true');\n }, 'RowDragComp.managedAndTreeData');\n }\n };\n RowDragComp.prototype.getDragItem = function () {\n return {\n rowNode: this.rowNode,\n rowNodes: this.getSelectedNodes(),\n columns: this.column ? [this.column] : undefined,\n defaultTextValue: this.cellValueFn(),\n };\n };\n RowDragComp.prototype.addDragSource = function (dragStartPixels) {\n var _this = this;\n if (dragStartPixels === void 0) { dragStartPixels = 4; }\n // if this is changing the drag element, delete the previous dragSource\n if (this.dragSource) {\n this.removeDragSource();\n }\n var rowDragText = this.gridOptionsWrapper.getRowDragText(this.column);\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.dragSource = {\n type: DragSourceType.RowDrag,\n eElement: this.getGui(),\n dragItemName: function () {\n var _a;\n var dragItem = _this.getDragItem();\n var dragItemCount = ((_a = dragItem.rowNodes) === null || _a === void 0 ? void 0 : _a.length) || 1;\n if (rowDragText) {\n return rowDragText(dragItem, dragItemCount);\n }\n return dragItemCount === 1 ? _this.cellValueFn() : dragItemCount + \" \" + translate('rowDragRows', 'rows');\n },\n getDragItem: function () { return _this.getDragItem(); },\n dragStartPixels: dragStartPixels,\n dragSourceDomDataKey: this.beans.gridOptionsWrapper.getDomDataKey()\n };\n this.beans.dragAndDropService.addDragSource(this.dragSource, true);\n };\n RowDragComp.prototype.removeDragSource = function () {\n if (this.dragSource) {\n this.beans.dragAndDropService.removeDragSource(this.dragSource);\n }\n this.dragSource = null;\n };\n __decorate$1$([\n Autowired('beans')\n ], RowDragComp.prototype, \"beans\", void 0);\n __decorate$1$([\n PostConstruct\n ], RowDragComp.prototype, \"postConstruct\", null);\n __decorate$1$([\n PreDestroy\n ], RowDragComp.prototype, \"removeDragSource\", null);\n return RowDragComp;\n}(Component));\nvar VisibilityStrategy = /** @class */ (function (_super) {\n __extends$2g(VisibilityStrategy, _super);\n function VisibilityStrategy(parent, rowNode, column) {\n var _this = _super.call(this) || this;\n _this.parent = parent;\n _this.rowNode = rowNode;\n _this.column = column;\n return _this;\n }\n VisibilityStrategy.prototype.setDisplayedOrVisible = function (neverDisplayed) {\n if (neverDisplayed) {\n this.parent.setDisplayed(false);\n }\n else {\n var shown = true;\n var isShownSometimes = false;\n if (this.column) {\n shown = this.column.isRowDrag(this.rowNode) || this.parent.isCustomGui();\n isShownSometimes = isFunction(this.column.getColDef().rowDrag);\n }\n // if shown sometimes, them some rows can have drag handle while other don't,\n // so we use setVisible to keep the handles horizontally aligned (as setVisible\n // keeps the empty space, whereas setDisplayed looses the space)\n if (isShownSometimes) {\n this.parent.setDisplayed(true);\n this.parent.setVisible(shown);\n }\n else {\n this.parent.setDisplayed(shown);\n this.parent.setVisible(true);\n }\n }\n };\n return VisibilityStrategy;\n}(BeanStub));\n// when non managed, the visibility depends on suppressRowDrag property only\nvar NonManagedVisibilityStrategy = /** @class */ (function (_super) {\n __extends$2g(NonManagedVisibilityStrategy, _super);\n function NonManagedVisibilityStrategy(parent, beans, rowNode, column) {\n var _this = _super.call(this, parent, rowNode, column) || this;\n _this.beans = beans;\n return _this;\n }\n NonManagedVisibilityStrategy.prototype.postConstruct = function () {\n this.addManagedListener(this.beans.gridOptionsWrapper, 'suppressRowDrag', this.onSuppressRowDrag.bind(this));\n // in case data changes, then we need to update visibility of drag item\n this.addManagedListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.beans.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.workOutVisibility.bind(this));\n this.workOutVisibility();\n };\n NonManagedVisibilityStrategy.prototype.onSuppressRowDrag = function () {\n this.workOutVisibility();\n };\n NonManagedVisibilityStrategy.prototype.workOutVisibility = function () {\n // only show the drag if both sort and filter are not present\n var neverDisplayed = this.beans.gridOptionsWrapper.isSuppressRowDrag();\n this.setDisplayedOrVisible(neverDisplayed);\n };\n __decorate$1$([\n PostConstruct\n ], NonManagedVisibilityStrategy.prototype, \"postConstruct\", null);\n return NonManagedVisibilityStrategy;\n}(VisibilityStrategy));\n// when managed, the visibility depends on sort, filter and row group, as well as suppressRowDrag property\nvar ManagedVisibilityStrategy = /** @class */ (function (_super) {\n __extends$2g(ManagedVisibilityStrategy, _super);\n function ManagedVisibilityStrategy(parent, beans, rowNode, column) {\n var _this = _super.call(this, parent, rowNode, column) || this;\n _this.beans = beans;\n return _this;\n }\n ManagedVisibilityStrategy.prototype.postConstruct = function () {\n // we do not show the component if sort, filter or grouping is active\n this.addManagedListener(this.beans.eventService, Events.EVENT_SORT_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.beans.eventService, Events.EVENT_FILTER_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.beans.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.beans.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.workOutVisibility.bind(this));\n // in case data changes, then we need to update visibility of drag item\n this.addManagedListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, this.workOutVisibility.bind(this));\n this.addManagedListener(this.beans.gridOptionsWrapper, 'suppressRowDrag', this.onSuppressRowDrag.bind(this));\n this.workOutVisibility();\n };\n ManagedVisibilityStrategy.prototype.onSuppressRowDrag = function () {\n this.workOutVisibility();\n };\n ManagedVisibilityStrategy.prototype.workOutVisibility = function () {\n // only show the drag if both sort and filter are not present\n var gridBodyCon = this.beans.ctrlsService.getGridBodyCtrl();\n var rowDragFeature = gridBodyCon.getRowDragFeature();\n var shouldPreventRowMove = rowDragFeature && rowDragFeature.shouldPreventRowMove();\n var suppressRowDrag = this.beans.gridOptionsWrapper.isSuppressRowDrag();\n var hasExternalDropZones = this.beans.dragAndDropService.hasExternalDropZones();\n var neverDisplayed = (shouldPreventRowMove && !hasExternalDropZones) || suppressRowDrag;\n this.setDisplayedOrVisible(neverDisplayed);\n };\n __decorate$1$([\n PostConstruct\n ], ManagedVisibilityStrategy.prototype, \"postConstruct\", null);\n return ManagedVisibilityStrategy;\n}(VisibilityStrategy));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2f = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$8 = (undefined && undefined.__assign) || function () {\n __assign$8 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$8.apply(this, arguments);\n};\nvar __decorate$1_ = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GroupCellRendererCtrl = /** @class */ (function (_super) {\n __extends$2f(GroupCellRendererCtrl, _super);\n function GroupCellRendererCtrl() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n GroupCellRendererCtrl.prototype.init = function (comp, eGui, eCheckbox, eExpanded, eContracted, compClass, params) {\n this.params = params;\n this.eGui = eGui;\n this.eCheckbox = eCheckbox;\n this.eExpanded = eExpanded;\n this.eContracted = eContracted;\n this.comp = comp;\n this.compClass = compClass;\n var topLevelFooter = this.isTopLevelFooter();\n var embeddedRowMismatch = this.isEmbeddedRowMismatch();\n // This allows for empty strings to appear as groups since\n // it will only return for null or undefined.\n var nullValue = params.value == null;\n var skipCell = false;\n // if the groupCellRenderer is inside of a footer and groupHideOpenParents is true\n // we should only display the groupCellRenderer if the current column is the rowGroupedColumn\n if (this.gridOptionsWrapper.isGroupIncludeFooter() && this.gridOptionsWrapper.isGroupHideOpenParents()) {\n var node = params.node;\n if (node.footer) {\n var showRowGroup = params.colDef && params.colDef.showRowGroup;\n var rowGroupColumnId = node.rowGroupColumn && node.rowGroupColumn.getColId();\n skipCell = showRowGroup !== rowGroupColumnId;\n }\n }\n this.cellIsBlank = topLevelFooter ? false : (embeddedRowMismatch || nullValue || skipCell);\n if (this.cellIsBlank) {\n return;\n }\n this.setupShowingValueForOpenedParent();\n this.findDisplayedGroupNode();\n this.addFullWidthRowDraggerIfNeeded();\n this.addExpandAndContract();\n this.addCheckboxIfNeeded();\n this.addValueElement();\n this.setupIndent();\n this.refreshAriaExpanded();\n };\n GroupCellRendererCtrl.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n // property cleanup to avoid memory leaks\n this.expandListener = null;\n };\n GroupCellRendererCtrl.prototype.refreshAriaExpanded = function () {\n var _a = this.params, node = _a.node, eParentOfValue = _a.eParentOfValue;\n if (this.expandListener) {\n this.expandListener = this.expandListener();\n }\n if (!this.isExpandable()) {\n removeAriaExpanded(eParentOfValue);\n return;\n }\n var listener = function () {\n // for react, we don't use JSX, as setting attributes via jsx is slower\n setAriaExpanded(eParentOfValue, !!node.expanded);\n };\n this.expandListener = this.addManagedListener(node, RowNode.EVENT_EXPANDED_CHANGED, listener) || null;\n listener();\n };\n GroupCellRendererCtrl.prototype.isTopLevelFooter = function () {\n if (!this.gridOptionsWrapper.isGroupIncludeTotalFooter()) {\n return false;\n }\n if (this.params.value != null || this.params.node.level != -1) {\n return false;\n }\n // at this point, we know it's the root node and there is no value present, so it's a footer cell.\n // the only thing to work out is if we are displaying groups across multiple\n // columns (groupMultiAutoColumn=true), we only want 'total' to appear in the first column.\n var colDef = this.params.colDef;\n var doingFullWidth = colDef == null;\n if (doingFullWidth) {\n return true;\n }\n if (colDef.showRowGroup === true) {\n return true;\n }\n var rowGroupCols = this.columnModel.getRowGroupColumns();\n // this is a sanity check, rowGroupCols should always be present\n if (!rowGroupCols || rowGroupCols.length === 0) {\n return true;\n }\n var firstRowGroupCol = rowGroupCols[0];\n return firstRowGroupCol.getId() === colDef.showRowGroup;\n };\n // if we are doing embedded full width rows, we only show the renderer when\n // in the body, or if pinning in the pinned section, or if pinning and RTL,\n // in the right section. otherwise we would have the cell repeated in each section.\n GroupCellRendererCtrl.prototype.isEmbeddedRowMismatch = function () {\n if (!this.params.fullWidth || !this.gridOptionsWrapper.isEmbedFullWidthRows()) {\n return false;\n }\n var pinnedLeftCell = this.params.pinned === Constants.PINNED_LEFT;\n var pinnedRightCell = this.params.pinned === Constants.PINNED_RIGHT;\n var bodyCell = !pinnedLeftCell && !pinnedRightCell;\n if (this.gridOptionsWrapper.isEnableRtl()) {\n if (this.columnModel.isPinningLeft()) {\n return !pinnedRightCell;\n }\n return !bodyCell;\n }\n if (this.columnModel.isPinningLeft()) {\n return !pinnedLeftCell;\n }\n return !bodyCell;\n };\n GroupCellRendererCtrl.prototype.findDisplayedGroupNode = function () {\n var column = this.params.column;\n var rowNode = this.params.node;\n if (this.showingValueForOpenedParent) {\n var pointer = rowNode.parent;\n while (pointer != null) {\n if (pointer.rowGroupColumn && column.isRowGroupDisplayed(pointer.rowGroupColumn.getId())) {\n this.displayedGroupNode = pointer;\n break;\n }\n pointer = pointer.parent;\n }\n }\n // if we didn't find a displayed group, set it to the row node\n if (missing(this.displayedGroupNode)) {\n this.displayedGroupNode = rowNode;\n }\n };\n GroupCellRendererCtrl.prototype.setupShowingValueForOpenedParent = function () {\n // note - this code depends on sortService.updateGroupDataForHiddenOpenParents, where group data\n // is updated to reflect the dragged down parents\n var rowNode = this.params.node;\n var column = this.params.column;\n if (!this.gridOptionsWrapper.isGroupHideOpenParents()) {\n this.showingValueForOpenedParent = false;\n return;\n }\n // hideOpenParents means rowNode.groupData can have data for the group this column is displaying, even though\n // this rowNode isn't grouping by the column we are displaying\n // if no groupData at all, we are not showing a parent value\n if (!rowNode.groupData) {\n this.showingValueForOpenedParent = false;\n return;\n }\n // this is the normal case, in that we are showing a group for which this column is configured. note that\n // this means the Row Group is closed (if it was open, we would not be displaying it)\n var showingGroupNode = rowNode.rowGroupColumn != null;\n if (showingGroupNode) {\n var keyOfGroupingColumn = rowNode.rowGroupColumn.getId();\n var configuredToShowThisGroupLevel = column.isRowGroupDisplayed(keyOfGroupingColumn);\n // if showing group as normal, we didn't take group info from parent\n if (configuredToShowThisGroupLevel) {\n this.showingValueForOpenedParent = false;\n return;\n }\n }\n // see if we are showing a Group Value for the Displayed Group. if we are showing a group value, and this Row Node\n // is not grouping by this Displayed Group, we must of gotten the value from a parent node\n var valPresent = rowNode.groupData[column.getId()] != null;\n this.showingValueForOpenedParent = valPresent;\n };\n GroupCellRendererCtrl.prototype.addValueElement = function () {\n if (this.displayedGroupNode.footer) {\n this.addFooterValue();\n }\n else {\n this.addGroupValue();\n this.addChildCount();\n }\n };\n GroupCellRendererCtrl.prototype.addGroupValue = function () {\n // we try and use the cellRenderer of the column used for the grouping if we can\n var paramsAdjusted = this.adjustParamsWithDetailsFromRelatedColumn();\n var innerCompDetails = this.getInnerCompDetails(paramsAdjusted);\n var valueFormatted = paramsAdjusted.valueFormatted, value = paramsAdjusted.value;\n var valueWhenNoRenderer = valueFormatted != null ? valueFormatted : value;\n this.comp.setInnerRenderer(innerCompDetails, valueWhenNoRenderer);\n };\n GroupCellRendererCtrl.prototype.adjustParamsWithDetailsFromRelatedColumn = function () {\n var relatedColumn = this.displayedGroupNode.rowGroupColumn;\n var column = this.params.column;\n if (!relatedColumn) {\n return this.params;\n }\n var notFullWidth = column != null;\n if (notFullWidth) {\n var showingThisRowGroup = column.isRowGroupDisplayed(relatedColumn.getId());\n if (!showingThisRowGroup) {\n return this.params;\n }\n }\n var params = this.params;\n var _a = this.params, value = _a.value, node = _a.node;\n var valueFormatted = this.valueFormatterService.formatValue(relatedColumn, node, value);\n // we don't update the original params, as they could of come through React,\n // as react has RowGroupCellRenderer, which means the params could be props which\n // would be read only\n var paramsAdjusted = __assign$8(__assign$8({}, params), { valueFormatted: valueFormatted });\n return paramsAdjusted;\n };\n GroupCellRendererCtrl.prototype.addFooterValue = function () {\n var footerValueGetter = this.params.footerValueGetter;\n var footerValue = '';\n if (footerValueGetter) {\n // params is same as we were given, except we set the value as the item to display\n var paramsClone = cloneObject(this.params);\n paramsClone.value = this.params.value;\n if (typeof footerValueGetter === 'function') {\n footerValue = footerValueGetter(paramsClone);\n }\n else if (typeof footerValueGetter === 'string') {\n footerValue = this.expressionService.evaluate(footerValueGetter, paramsClone);\n }\n else {\n console.warn('AG Grid: footerValueGetter should be either a function or a string (expression)');\n }\n }\n else {\n footerValue = 'Total ' + (this.params.value != null ? this.params.value : '');\n }\n var innerCompDetails = this.getInnerCompDetails(this.params);\n this.comp.setInnerRenderer(innerCompDetails, footerValue);\n };\n GroupCellRendererCtrl.prototype.getInnerCompDetails = function (params) {\n var _this = this;\n // for full width rows, we don't do any of the below\n if (params.fullWidth) {\n return this.userComponentFactory.getFullWidthGroupRowInnerCellRenderer(this.gridOptions.groupRowRendererParams, params);\n }\n // when grouping, the normal case is we use the cell renderer of the grouped column. eg if grouping by country\n // and then rating, we will use the country cell renderer for each country group row and likewise the rating\n // cell renderer for each rating group row.\n //\n // however if the user has innerCellRenderer defined, this gets preference and we don't use cell renderers\n // of the grouped columns.\n //\n // so we check and use in the following order:\n //\n // 1) thisColDef.cellRendererParams.innerRenderer of the column showing the groups (eg auto group column)\n // 2) groupedColDef.cellRenderer of the grouped column\n // 3) groupedColDef.cellRendererParams.innerRenderer\n // we check if cell renderer provided for the group cell renderer, eg colDef.cellRendererParams.innerRenderer\n var innerCompDetails = this.userComponentFactory\n .getInnerRendererDetails(params, params);\n // avoid using GroupCellRenderer again, otherwise stack overflow, as we insert same renderer again and again.\n // this covers off chance user is grouping by a column that is also configured with GroupCellRenderer\n var isGroupRowRenderer = function (details) { return details && details.componentClass == _this.compClass; };\n if (innerCompDetails && !isGroupRowRenderer(innerCompDetails)) {\n // use the renderer defined in cellRendererParams.innerRenderer\n return innerCompDetails;\n }\n var relatedColumn = this.displayedGroupNode.rowGroupColumn;\n var relatedColDef = relatedColumn ? relatedColumn.getColDef() : undefined;\n if (!relatedColDef) {\n return;\n }\n // otherwise see if we can use the cellRenderer of the column we are grouping by\n var relatedCompDetails = this.userComponentFactory\n .getCellRendererDetails(relatedColDef, params);\n if (relatedCompDetails && !isGroupRowRenderer(relatedCompDetails)) {\n // Only if the original column is using a specific renderer, it it is a using a DEFAULT one ignore it\n return relatedCompDetails;\n }\n if (isGroupRowRenderer(relatedCompDetails) &&\n relatedColDef.cellRendererParams &&\n relatedColDef.cellRendererParams.innerRenderer) {\n // edge case - this comes from a column which has been grouped dynamically, that has a renderer 'group'\n // and has an inner cell renderer\n var res = this.userComponentFactory.getInnerRendererDetails(relatedColDef.cellRendererParams, params);\n return res;\n }\n };\n GroupCellRendererCtrl.prototype.addChildCount = function () {\n // only include the child count if it's included, eg if user doing custom aggregation,\n // then this could be left out, or set to -1, ie no child count\n if (this.params.suppressCount) {\n return;\n }\n this.addManagedListener(this.displayedGroupNode, RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED, this.updateChildCount.bind(this));\n // filtering changes the child count, so need to cater for it\n this.updateChildCount();\n };\n GroupCellRendererCtrl.prototype.updateChildCount = function () {\n var allChildrenCount = this.displayedGroupNode.allChildrenCount;\n var showingGroupForThisNode = this.isShowRowGroupForThisRow();\n var showCount = showingGroupForThisNode && allChildrenCount != null && allChildrenCount >= 0;\n var countString = showCount ? \"(\" + allChildrenCount + \")\" : \"\";\n this.comp.setChildCount(countString);\n };\n GroupCellRendererCtrl.prototype.isShowRowGroupForThisRow = function () {\n if (this.gridOptionsWrapper.isTreeData()) {\n return true;\n }\n var rowGroupColumn = this.displayedGroupNode.rowGroupColumn;\n if (!rowGroupColumn) {\n return false;\n }\n // column is null for fullWidthRows\n var column = this.params.column;\n var thisColumnIsInterested = column == null || column.isRowGroupDisplayed(rowGroupColumn.getId());\n return thisColumnIsInterested;\n };\n GroupCellRendererCtrl.prototype.addExpandAndContract = function () {\n var params = this.params;\n var eExpandedIcon = createIconNoSpan('groupExpanded', this.gridOptionsWrapper, null);\n var eContractedIcon = createIconNoSpan('groupContracted', this.gridOptionsWrapper, null);\n if (eExpandedIcon) {\n this.eExpanded.appendChild(eExpandedIcon);\n }\n if (eContractedIcon) {\n this.eContracted.appendChild(eContractedIcon);\n }\n var eGroupCell = params.eGridCell;\n // if editing groups, then double click is to start editing\n if (!this.gridOptionsWrapper.isEnableGroupEdit() && this.isExpandable() && !params.suppressDoubleClickExpand) {\n this.addManagedListener(eGroupCell, 'dblclick', this.onCellDblClicked.bind(this));\n }\n this.addManagedListener(this.eExpanded, 'click', this.onExpandClicked.bind(this));\n this.addManagedListener(this.eContracted, 'click', this.onExpandClicked.bind(this));\n // expand / contract as the user hits enter\n this.addManagedListener(eGroupCell, 'keydown', this.onKeyDown.bind(this));\n this.addManagedListener(params.node, RowNode.EVENT_EXPANDED_CHANGED, this.showExpandAndContractIcons.bind(this));\n this.showExpandAndContractIcons();\n // because we don't show the expand / contract when there are no children, we need to check every time\n // the number of children change.\n var expandableChangedListener = this.onRowNodeIsExpandableChanged.bind(this);\n this.addManagedListener(this.displayedGroupNode, RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED, expandableChangedListener);\n this.addManagedListener(this.displayedGroupNode, RowNode.EVENT_MASTER_CHANGED, expandableChangedListener);\n this.addManagedListener(this.displayedGroupNode, RowNode.EVENT_GROUP_CHANGED, expandableChangedListener);\n this.addManagedListener(this.displayedGroupNode, RowNode.EVENT_HAS_CHILDREN_CHANGED, expandableChangedListener);\n };\n GroupCellRendererCtrl.prototype.onExpandClicked = function (mouseEvent) {\n if (isStopPropagationForAgGrid(mouseEvent)) {\n return;\n }\n // so if we expand a node, it does not also get selected.\n stopPropagationForAgGrid(mouseEvent);\n this.onExpandOrContract(mouseEvent);\n };\n GroupCellRendererCtrl.prototype.onExpandOrContract = function (e) {\n // must use the displayedGroup, so if data was dragged down, we expand the parent, not this row\n var rowNode = this.displayedGroupNode;\n var nextExpandState = !rowNode.expanded;\n if (!nextExpandState && rowNode.sticky) {\n this.scrollToStickyNode(rowNode);\n }\n rowNode.setExpanded(nextExpandState, e);\n };\n GroupCellRendererCtrl.prototype.scrollToStickyNode = function (rowNode) {\n var gridBodyCtrl = this.ctrlsService.getGridBodyCtrl();\n var scrollFeature = gridBodyCtrl.getScrollFeature();\n scrollFeature.setVerticalScrollPosition(rowNode.rowTop - rowNode.stickyRowTop);\n };\n GroupCellRendererCtrl.prototype.isExpandable = function () {\n if (this.showingValueForOpenedParent) {\n return true;\n }\n var rowNode = this.displayedGroupNode;\n var reducedLeafNode = this.columnModel.isPivotMode() && rowNode.leafGroup;\n var expandableGroup = rowNode.isExpandable() && !rowNode.footer && !reducedLeafNode;\n if (!expandableGroup) {\n return false;\n }\n // column is null for fullWidthRows\n var column = this.params.column;\n var displayingForOneColumnOnly = column != null && typeof column.getColDef().showRowGroup === 'string';\n if (displayingForOneColumnOnly) {\n var showing = this.isShowRowGroupForThisRow();\n return showing;\n }\n return true;\n };\n GroupCellRendererCtrl.prototype.showExpandAndContractIcons = function () {\n var _a = this, params = _a.params, displayedGroup = _a.displayedGroupNode, columnModel = _a.columnModel;\n var node = params.node;\n var isExpandable = this.isExpandable();\n if (isExpandable) {\n // if expandable, show one based on expand state.\n // if we were dragged down, means our parent is always expanded\n var expanded = this.showingValueForOpenedParent ? true : node.expanded;\n this.comp.setExpandedDisplayed(expanded);\n this.comp.setContractedDisplayed(!expanded);\n }\n else {\n // it not expandable, show neither\n this.comp.setExpandedDisplayed(false);\n this.comp.setContractedDisplayed(false);\n }\n // compensation padding for leaf nodes, so there is blank space instead of the expand icon\n var pivotMode = columnModel.isPivotMode();\n var pivotModeAndLeafGroup = pivotMode && displayedGroup.leafGroup;\n var addExpandableCss = isExpandable && !pivotModeAndLeafGroup;\n var isTotalFooterNode = node.footer && node.level === -1;\n this.comp.addOrRemoveCssClass('ag-cell-expandable', addExpandableCss);\n this.comp.addOrRemoveCssClass('ag-row-group', addExpandableCss);\n if (pivotMode) {\n this.comp.addOrRemoveCssClass('ag-pivot-leaf-group', pivotModeAndLeafGroup);\n }\n else if (!isTotalFooterNode) {\n this.comp.addOrRemoveCssClass('ag-row-group-leaf-indent', !addExpandableCss);\n }\n };\n GroupCellRendererCtrl.prototype.onRowNodeIsExpandableChanged = function () {\n // maybe if no children now, we should hide the expand / contract icons\n this.showExpandAndContractIcons();\n // if we have no children, this impacts the indent\n this.setIndent();\n this.refreshAriaExpanded();\n };\n GroupCellRendererCtrl.prototype.setupIndent = function () {\n // only do this if an indent - as this overwrites the padding that\n // the theme set, which will make things look 'not aligned' for the\n // first group level.\n var node = this.params.node;\n var suppressPadding = this.params.suppressPadding;\n if (!suppressPadding) {\n this.addManagedListener(node, RowNode.EVENT_UI_LEVEL_CHANGED, this.setIndent.bind(this));\n this.setIndent();\n }\n };\n GroupCellRendererCtrl.prototype.setIndent = function () {\n if (this.gridOptionsWrapper.isGroupHideOpenParents()) {\n return;\n }\n var params = this.params;\n var rowNode = params.node;\n // if we are only showing one group column, we don't want to be indenting based on level\n var fullWithRow = !!params.colDef;\n var treeData = this.gridOptionsWrapper.isTreeData();\n var manyDimensionThisColumn = !fullWithRow || treeData || params.colDef.showRowGroup === true;\n var paddingCount = manyDimensionThisColumn ? rowNode.uiLevel : 0;\n var userProvidedPaddingPixelsTheDeprecatedWay = params.padding >= 0;\n if (userProvidedPaddingPixelsTheDeprecatedWay) {\n doOnce(function () { return console.warn('AG Grid: cellRendererParams.padding no longer works, it was deprecated in since v14.2 and removed in v26, configuring padding for groupCellRenderer should be done with Sass variables and themes. Please see the AG Grid documentation page for Themes, in particular the property $row-group-indent-size.'); }, 'groupCellRenderer->doDeprecatedWay');\n }\n if (this.indentClass) {\n this.comp.addOrRemoveCssClass(this.indentClass, false);\n }\n this.indentClass = 'ag-row-group-indent-' + paddingCount;\n this.comp.addOrRemoveCssClass(this.indentClass, true);\n };\n GroupCellRendererCtrl.prototype.addFullWidthRowDraggerIfNeeded = function () {\n var _this = this;\n if (!this.params.fullWidth || !this.params.rowDrag) {\n return;\n }\n var rowDragComp = new RowDragComp(function () { return _this.params.value; }, this.params.node);\n this.createManagedBean(rowDragComp, this.context);\n this.eGui.insertAdjacentElement('afterbegin', rowDragComp.getGui());\n };\n GroupCellRendererCtrl.prototype.isUserWantsSelected = function () {\n var paramsCheckbox = this.params.checkbox;\n // if a function, we always return true as change detection can show or hide the checkbox.\n return typeof paramsCheckbox === 'function' || paramsCheckbox === true;\n };\n GroupCellRendererCtrl.prototype.addCheckboxIfNeeded = function () {\n var _this = this;\n var rowNode = this.displayedGroupNode;\n var checkboxNeeded = this.isUserWantsSelected() &&\n // footers cannot be selected\n !rowNode.footer &&\n // pinned rows cannot be selected\n !rowNode.rowPinned &&\n // details cannot be selected\n !rowNode.detail;\n if (checkboxNeeded) {\n var cbSelectionComponent_1 = new CheckboxSelectionComponent();\n this.getContext().createBean(cbSelectionComponent_1);\n cbSelectionComponent_1.init({\n rowNode: rowNode,\n column: this.params.column,\n overrides: {\n isVisible: this.params.checkbox,\n callbackParams: this.params,\n removeHidden: true,\n },\n });\n this.eCheckbox.appendChild(cbSelectionComponent_1.getGui());\n this.addDestroyFunc(function () { return _this.getContext().destroyBean(cbSelectionComponent_1); });\n }\n this.comp.setCheckboxVisible(checkboxNeeded);\n };\n GroupCellRendererCtrl.prototype.onKeyDown = function (event) {\n var enterKeyPressed = event.key === KeyCode.ENTER;\n if (!enterKeyPressed || this.params.suppressEnterExpand) {\n return;\n }\n var cellEditable = this.params.column && this.params.column.isCellEditable(this.params.node);\n if (cellEditable) {\n return;\n }\n this.onExpandOrContract(event);\n };\n GroupCellRendererCtrl.prototype.onCellDblClicked = function (mouseEvent) {\n if (isStopPropagationForAgGrid(mouseEvent)) {\n return;\n }\n // we want to avoid acting on double click events on the expand / contract icon,\n // as that icons already has expand / collapse functionality on it. otherwise if\n // the icon was double clicked, we would get 'click', 'click', 'dblclick' which\n // is open->close->open, however double click should be open->close only.\n var targetIsExpandIcon = isElementInEventPath(this.eExpanded, mouseEvent)\n || isElementInEventPath(this.eContracted, mouseEvent);\n if (!targetIsExpandIcon) {\n this.onExpandOrContract(mouseEvent);\n }\n };\n __decorate$1_([\n Autowired('expressionService')\n ], GroupCellRendererCtrl.prototype, \"expressionService\", void 0);\n __decorate$1_([\n Autowired('valueFormatterService')\n ], GroupCellRendererCtrl.prototype, \"valueFormatterService\", void 0);\n __decorate$1_([\n Autowired('columnModel')\n ], GroupCellRendererCtrl.prototype, \"columnModel\", void 0);\n __decorate$1_([\n Autowired('userComponentFactory')\n ], GroupCellRendererCtrl.prototype, \"userComponentFactory\", void 0);\n __decorate$1_([\n Autowired('gridOptions')\n ], GroupCellRendererCtrl.prototype, \"gridOptions\", void 0);\n __decorate$1_([\n Autowired(\"ctrlsService\")\n ], GroupCellRendererCtrl.prototype, \"ctrlsService\", void 0);\n return GroupCellRendererCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2e = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1Z = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GroupCellRenderer = /** @class */ (function (_super) {\n __extends$2e(GroupCellRenderer, _super);\n function GroupCellRenderer() {\n return _super.call(this, GroupCellRenderer.TEMPLATE) || this;\n }\n GroupCellRenderer.prototype.init = function (params) {\n var _this = this;\n var compProxy = {\n setInnerRenderer: function (compDetails, valueToDisplay) { return _this.setRenderDetails(compDetails, valueToDisplay); },\n setChildCount: function (count) { return _this.eChildCount.innerHTML = count; },\n addOrRemoveCssClass: function (cssClass, value) { return _this.addOrRemoveCssClass(cssClass, value); },\n setContractedDisplayed: function (expanded) { return setDisplayed(_this.eContracted, expanded); },\n setExpandedDisplayed: function (expanded) { return setDisplayed(_this.eExpanded, expanded); },\n setCheckboxVisible: function (visible) { return _this.eCheckbox.classList.toggle('ag-invisible', !visible); }\n };\n var ctrl = this.createManagedBean(new GroupCellRendererCtrl());\n var fullWidth = !params.colDef;\n var eGui = this.getGui();\n ctrl.init(compProxy, eGui, this.eCheckbox, this.eExpanded, this.eContracted, this.constructor, params);\n if (fullWidth) {\n setAriaRole(eGui, 'gridcell');\n }\n };\n GroupCellRenderer.prototype.setRenderDetails = function (compDetails, valueToDisplay) {\n var _this = this;\n if (compDetails) {\n var componentPromise = compDetails.newAgStackInstance();\n if (!componentPromise) {\n return;\n }\n componentPromise.then(function (comp) {\n if (!comp) {\n return;\n }\n var destroyComp = function () { return _this.context.destroyBean(comp); };\n if (_this.isAlive()) {\n _this.eValue.appendChild(comp.getGui());\n _this.addDestroyFunc(destroyComp);\n }\n else {\n destroyComp();\n }\n });\n }\n else {\n this.eValue.innerText = valueToDisplay;\n }\n };\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to have public here instead of private or protected\n GroupCellRenderer.prototype.destroy = function () {\n this.getContext().destroyBean(this.innerCellRenderer);\n _super.prototype.destroy.call(this);\n };\n GroupCellRenderer.prototype.refresh = function () {\n return false;\n };\n GroupCellRenderer.TEMPLATE = \"<span class=\\\"ag-cell-wrapper\\\">\\n <span class=\\\"ag-group-expanded\\\" ref=\\\"eExpanded\\\"></span>\\n <span class=\\\"ag-group-contracted\\\" ref=\\\"eContracted\\\"></span>\\n <span class=\\\"ag-group-checkbox ag-invisible\\\" ref=\\\"eCheckbox\\\"></span>\\n <span class=\\\"ag-group-value\\\" ref=\\\"eValue\\\"></span>\\n <span class=\\\"ag-group-child-count\\\" ref=\\\"eChildCount\\\"></span>\\n </span>\";\n __decorate$1Z([\n RefSelector('eExpanded')\n ], GroupCellRenderer.prototype, \"eExpanded\", void 0);\n __decorate$1Z([\n RefSelector('eContracted')\n ], GroupCellRenderer.prototype, \"eContracted\", void 0);\n __decorate$1Z([\n RefSelector('eCheckbox')\n ], GroupCellRenderer.prototype, \"eCheckbox\", void 0);\n __decorate$1Z([\n RefSelector('eValue')\n ], GroupCellRenderer.prototype, \"eValue\", void 0);\n __decorate$1Z([\n RefSelector('eChildCount')\n ], GroupCellRenderer.prototype, \"eChildCount\", void 0);\n return GroupCellRenderer;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2d = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1Y = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar LoadingCellRenderer = /** @class */ (function (_super) {\n __extends$2d(LoadingCellRenderer, _super);\n function LoadingCellRenderer() {\n return _super.call(this, LoadingCellRenderer.TEMPLATE) || this;\n }\n LoadingCellRenderer.prototype.init = function (params) {\n params.node.failedLoad ? this.setupFailed() : this.setupLoading();\n };\n LoadingCellRenderer.prototype.setupFailed = function () {\n this.eLoadingText.innerText = 'ERR';\n };\n LoadingCellRenderer.prototype.setupLoading = function () {\n var eLoadingIcon = createIconNoSpan('groupLoading', this.gridOptionsWrapper, null);\n if (eLoadingIcon) {\n this.eLoadingIcon.appendChild(eLoadingIcon);\n }\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n this.eLoadingText.innerText = localeTextFunc('loadingOoo', 'Loading');\n };\n LoadingCellRenderer.prototype.refresh = function (params) {\n return false;\n };\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n LoadingCellRenderer.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n LoadingCellRenderer.TEMPLATE = \"<div class=\\\"ag-loading\\\">\\n <span class=\\\"ag-loading-icon\\\" ref=\\\"eLoadingIcon\\\"></span>\\n <span class=\\\"ag-loading-text\\\" ref=\\\"eLoadingText\\\"></span>\\n </div>\";\n __decorate$1Y([\n RefSelector('eLoadingIcon')\n ], LoadingCellRenderer.prototype, \"eLoadingIcon\", void 0);\n __decorate$1Y([\n RefSelector('eLoadingText')\n ], LoadingCellRenderer.prototype, \"eLoadingText\", void 0);\n return LoadingCellRenderer;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2c = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar LoadingOverlayComponent$1 = /** @class */ (function (_super) {\n __extends$2c(LoadingOverlayComponent, _super);\n function LoadingOverlayComponent() {\n return _super.call(this) || this;\n }\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n LoadingOverlayComponent.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n LoadingOverlayComponent.prototype.init = function (params) {\n var template = this.gridOptionsWrapper.getOverlayLoadingTemplate() ?\n this.gridOptionsWrapper.getOverlayLoadingTemplate() : LoadingOverlayComponent.DEFAULT_LOADING_OVERLAY_TEMPLATE;\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n var localisedTemplate = template.replace('[LOADING...]', localeTextFunc('loadingOoo', 'Loading...'));\n this.setTemplate(localisedTemplate);\n };\n LoadingOverlayComponent.DEFAULT_LOADING_OVERLAY_TEMPLATE = '<span class=\"ag-overlay-loading-center\">[LOADING...]</span>';\n return LoadingOverlayComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2b = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar NoRowsOverlayComponent$1 = /** @class */ (function (_super) {\n __extends$2b(NoRowsOverlayComponent, _super);\n function NoRowsOverlayComponent() {\n return _super.call(this) || this;\n }\n // this is a user component, and IComponent has \"public destroy()\" as part of the interface.\n // so we need to override destroy() just to make the method public.\n NoRowsOverlayComponent.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n NoRowsOverlayComponent.prototype.init = function (params) {\n var template = this.gridOptionsWrapper.getOverlayNoRowsTemplate() ?\n this.gridOptionsWrapper.getOverlayNoRowsTemplate() : NoRowsOverlayComponent.DEFAULT_NO_ROWS_TEMPLATE;\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n var localisedTemplate = template.replace('[NO_ROWS_TO_SHOW]', localeTextFunc('noRowsToShow', 'No Rows To Show'));\n this.setTemplate(localisedTemplate);\n };\n NoRowsOverlayComponent.DEFAULT_NO_ROWS_TEMPLATE = '<span class=\"ag-overlay-no-rows-center\">[NO_ROWS_TO_SHOW]</span>';\n return NoRowsOverlayComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$2a = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar TooltipComponent$1 = /** @class */ (function (_super) {\n __extends$2a(TooltipComponent, _super);\n function TooltipComponent() {\n return _super.call(this, /* html */ \"<div class=\\\"ag-tooltip\\\"></div>\") || this;\n }\n // will need to type params\n TooltipComponent.prototype.init = function (params) {\n var value = params.value;\n this.getGui().innerHTML = escapeString(value);\n };\n return TooltipComponent;\n}(PopupComponent));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$29 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1X = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar UserComponentRegistry = /** @class */ (function (_super) {\n __extends$29(UserComponentRegistry, _super);\n function UserComponentRegistry() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.agGridDefaults = {\n //date\n agDateInput: DefaultDateComponent,\n //header\n agColumnHeader: HeaderComp,\n agColumnGroupHeader: HeaderGroupComp,\n agSortIndicator: SortIndicatorComp,\n //floating filters\n agTextColumnFloatingFilter: TextFloatingFilter,\n agNumberColumnFloatingFilter: NumberFloatingFilter,\n agDateColumnFloatingFilter: DateFloatingFilter,\n agReadOnlyFloatingFilter: ReadOnlyFloatingFilter,\n // renderers\n agAnimateShowChangeCellRenderer: AnimateShowChangeCellRenderer,\n agAnimateSlideCellRenderer: AnimateSlideCellRenderer,\n agGroupCellRenderer: GroupCellRenderer,\n agGroupRowRenderer: GroupCellRenderer,\n agLoadingCellRenderer: LoadingCellRenderer,\n //editors\n agCellEditor: TextCellEditor,\n agTextCellEditor: TextCellEditor,\n agSelectCellEditor: SelectCellEditor,\n agPopupTextCellEditor: PopupTextCellEditor,\n agPopupSelectCellEditor: PopupSelectCellEditor,\n agLargeTextCellEditor: LargeTextCellEditor,\n //filter\n agTextColumnFilter: TextFilter,\n agNumberColumnFilter: NumberFilter,\n agDateColumnFilter: DateFilter,\n //overlays\n agLoadingOverlay: LoadingOverlayComponent$1,\n agNoRowsOverlay: NoRowsOverlayComponent$1,\n // tooltips\n agTooltipComponent: TooltipComponent$1\n };\n _this.agDeprecatedNames = {\n set: {\n newComponentName: 'agSetColumnFilter',\n propertyHolder: 'filter'\n },\n text: {\n newComponentName: 'agTextColumnFilter',\n propertyHolder: 'filter'\n },\n number: {\n newComponentName: 'agNumberColumnFilter',\n propertyHolder: 'filter'\n },\n date: {\n newComponentName: 'agDateColumnFilter',\n propertyHolder: 'filter'\n },\n group: {\n newComponentName: 'agGroupCellRenderer',\n propertyHolder: 'cellRenderer'\n },\n animateShowChange: {\n newComponentName: 'agAnimateShowChangeCellRenderer',\n propertyHolder: 'cellRenderer'\n },\n animateSlide: {\n newComponentName: 'agAnimateSlideCellRenderer',\n propertyHolder: 'cellRenderer'\n },\n select: {\n newComponentName: 'agSelectCellEditor',\n propertyHolder: 'cellEditor'\n },\n largeText: {\n newComponentName: 'agLargeTextCellEditor',\n propertyHolder: 'cellEditor'\n },\n popupSelect: {\n newComponentName: 'agPopupSelectCellEditor',\n propertyHolder: 'cellEditor'\n },\n popupText: {\n newComponentName: 'agPopupTextCellEditor',\n propertyHolder: 'cellEditor'\n },\n richSelect: {\n newComponentName: 'agRichSelectCellEditor',\n propertyHolder: 'cellEditor'\n },\n headerComponent: {\n newComponentName: 'agColumnHeader',\n propertyHolder: 'headerComponent'\n }\n };\n _this.jsComps = {};\n _this.fwComps = {};\n return _this;\n }\n UserComponentRegistry.prototype.init = function () {\n var _this = this;\n if (this.gridOptions.components != null) {\n iterateObject(this.gridOptions.components, function (key, component) { return _this.registerJsComponent(key, component); });\n }\n if (this.gridOptions.frameworkComponents != null) {\n iterateObject(this.gridOptions.frameworkComponents, function (key, component) { return _this.registerFwComponent(key, component); });\n }\n };\n UserComponentRegistry.prototype.registerDefaultComponent = function (rawName, component) {\n var name = this.translateIfDeprecated(rawName);\n if (this.agGridDefaults[name]) {\n console.error(\"Trying to overwrite a default component. You should call registerComponent\");\n return;\n }\n this.agGridDefaults[name] = component;\n };\n UserComponentRegistry.prototype.registerJsComponent = function (rawName, component) {\n var name = this.translateIfDeprecated(rawName);\n if (this.fwComps[name]) {\n console.error(\"Trying to register a component that you have already registered for frameworks: \" + name);\n return;\n }\n this.jsComps[name] = component;\n };\n /**\n * B the business interface (ie IHeader)\n * A the agGridComponent interface (ie IHeaderComp). The final object acceptable by ag-grid\n */\n UserComponentRegistry.prototype.registerFwComponent = function (rawName, component) {\n var warningMessage = \"AG Grid: As of v27, registering components via grid property frameworkComponents is deprecated. Instead register both JavaScript AND Framework Components via the components property.\";\n doOnce(function () { return console.warn(warningMessage); }, \"UserComponentRegistry.frameworkComponentsDeprecated\");\n var name = this.translateIfDeprecated(rawName);\n this.fwComps[name] = component;\n };\n UserComponentRegistry.prototype.retrieve = function (rawName) {\n var name = this.translateIfDeprecated(rawName);\n var createResult = function (component, componentFromFramework) { return ({ componentFromFramework: componentFromFramework, component: component }); };\n // FrameworkOverrides.frameworkComponent() is used in two locations:\n // 1) for Vue, user provided components get registered via a framework specific way.\n // 2) for React, it's how the React UI provides alternative default components (eg GroupCellRenderer and DetailCellRenderer)\n var registeredViaFrameworkComp = this.getFrameworkOverrides().frameworkComponent(name, this.gridOptions.components);\n if (registeredViaFrameworkComp != null) {\n return createResult(registeredViaFrameworkComp, true);\n }\n var frameworkComponent = this.fwComps[name];\n if (frameworkComponent) {\n return createResult(frameworkComponent, true);\n }\n var jsComponent = this.jsComps[name];\n if (jsComponent) {\n var isFwkComp = this.getFrameworkOverrides().isFrameworkComponent(jsComponent);\n return createResult(jsComponent, isFwkComp);\n }\n var defaultComponent = this.agGridDefaults[name];\n if (defaultComponent) {\n return createResult(defaultComponent, false);\n }\n if (Object.keys(this.agGridDefaults).indexOf(name) < 0) {\n console.warn(\"AG Grid: Looking for component [\" + name + \"] but it wasn't found.\");\n }\n return null;\n };\n UserComponentRegistry.prototype.translateIfDeprecated = function (raw) {\n var deprecatedInfo = this.agDeprecatedNames[raw];\n if (deprecatedInfo != null) {\n doOnce(function () {\n console.warn(\"ag-grid. Since v15.0 component names have been renamed to be namespaced. You should rename \" + deprecatedInfo.propertyHolder + \":\" + raw + \" to \" + deprecatedInfo.propertyHolder + \":\" + deprecatedInfo.newComponentName);\n }, 'DEPRECATE_COMPONENT_' + raw);\n return deprecatedInfo.newComponentName;\n }\n return raw;\n };\n __decorate$1X([\n Autowired('gridOptions')\n ], UserComponentRegistry.prototype, \"gridOptions\", void 0);\n __decorate$1X([\n Autowired('agComponentUtils')\n ], UserComponentRegistry.prototype, \"agComponentUtils\", void 0);\n __decorate$1X([\n PostConstruct\n ], UserComponentRegistry.prototype, \"init\", null);\n UserComponentRegistry = __decorate$1X([\n Bean('userComponentRegistry')\n ], UserComponentRegistry);\n return UserComponentRegistry;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar DateComponent = {\n propertyName: 'dateComponent',\n cellRenderer: false\n};\nvar HeaderComponent = {\n propertyName: 'headerComponent',\n cellRenderer: false\n};\nvar HeaderGroupComponent = {\n propertyName: 'headerGroupComponent',\n cellRenderer: false\n};\nvar CellRendererComponent = {\n propertyName: 'cellRenderer',\n cellRenderer: true\n};\nvar CellEditorComponent = {\n propertyName: 'cellEditor',\n cellRenderer: false\n};\nvar InnerRendererComponent = {\n propertyName: 'innerRenderer',\n cellRenderer: true\n};\nvar LoadingOverlayComponent = {\n propertyName: 'loadingOverlayComponent',\n cellRenderer: false\n};\nvar NoRowsOverlayComponent = {\n propertyName: 'noRowsOverlayComponent',\n cellRenderer: false\n};\nvar TooltipComponent = {\n propertyName: 'tooltipComponent',\n cellRenderer: false\n};\nvar FilterComponent = {\n propertyName: 'filter',\n cellRenderer: false\n};\nvar FloatingFilterComponent = {\n propertyName: 'floatingFilterComponent',\n cellRenderer: false\n};\nvar ToolPanelComponent = {\n propertyName: 'toolPanel',\n cellRenderer: false\n};\nvar StatusPanelComponent = {\n propertyName: 'statusPanel',\n cellRenderer: false\n};\nvar FullWidth = {\n propertyName: 'fullWidthCellRenderer',\n cellRenderer: true\n};\nvar FullWidthLoading = {\n propertyName: 'loadingCellRenderer',\n cellRenderer: true\n};\nvar FullWidthGroup = {\n propertyName: 'groupRowRenderer',\n cellRenderer: true\n};\nvar FullWidthDetail = {\n propertyName: 'detailCellRenderer',\n cellRenderer: true\n};\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar FloatingFilterMapper = /** @class */ (function () {\n function FloatingFilterMapper() {\n }\n FloatingFilterMapper.getFloatingFilterType = function (filterType) {\n return this.filterToFloatingFilterMapping[filterType];\n };\n FloatingFilterMapper.filterToFloatingFilterMapping = {\n set: 'agSetColumnFloatingFilter',\n agSetColumnFilter: 'agSetColumnFloatingFilter',\n multi: 'agMultiColumnFloatingFilter',\n agMultiColumnFilter: 'agMultiColumnFloatingFilter',\n number: 'agNumberColumnFloatingFilter',\n agNumberColumnFilter: 'agNumberColumnFloatingFilter',\n date: 'agDateColumnFloatingFilter',\n agDateColumnFilter: 'agDateColumnFloatingFilter',\n text: 'agTextColumnFloatingFilter',\n agTextColumnFilter: 'agTextColumnFloatingFilter'\n };\n return FloatingFilterMapper;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$28 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1W = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar UserComponentFactory = /** @class */ (function (_super) {\n __extends$28(UserComponentFactory, _super);\n function UserComponentFactory() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n UserComponentFactory.prototype.getHeaderCompDetails = function (colDef, params) {\n return this.getCompDetails(colDef, HeaderComponent, 'agColumnHeader', params);\n };\n UserComponentFactory.prototype.getHeaderGroupCompDetails = function (params) {\n var colGroupDef = params.columnGroup.getColGroupDef();\n return this.getCompDetails(colGroupDef, HeaderGroupComponent, 'agColumnGroupHeader', params);\n };\n // this one is unusual, as it can be LoadingCellRenderer, DetailCellRenderer, FullWidthCellRenderer or GroupRowRenderer.\n // so we have to pass the type in.\n UserComponentFactory.prototype.getFullWidthCellRendererDetails = function (params) {\n return this.getCompDetails(this.gridOptions, FullWidth, null, params, true);\n };\n UserComponentFactory.prototype.getFullWidthLoadingCellRendererDetails = function (params) {\n return this.getCompDetails(this.gridOptions, FullWidthLoading, 'agLoadingCellRenderer', params, true);\n };\n UserComponentFactory.prototype.getFullWidthGroupCellRendererDetails = function (params) {\n return this.getCompDetails(this.gridOptions, FullWidthGroup, 'agGroupRowRenderer', params, true);\n };\n UserComponentFactory.prototype.getFullWidthDetailCellRendererDetails = function (params) {\n return this.getCompDetails(this.gridOptions, FullWidthDetail, 'agDetailCellRenderer', params, true);\n };\n // CELL RENDERER\n UserComponentFactory.prototype.getInnerRendererDetails = function (def, params) {\n return this.getCompDetails(def, InnerRendererComponent, null, params);\n };\n UserComponentFactory.prototype.getFullWidthGroupRowInnerCellRenderer = function (def, params) {\n return this.getCompDetails(def, InnerRendererComponent, null, params);\n };\n UserComponentFactory.prototype.getCellRendererDetails = function (def, params) {\n return this.getCompDetails(def, CellRendererComponent, null, params);\n };\n // CELL EDITOR\n UserComponentFactory.prototype.getCellEditorDetails = function (def, params) {\n return this.getCompDetails(def, CellEditorComponent, 'agCellEditor', params, true);\n };\n // FILTER\n UserComponentFactory.prototype.getFilterDetails = function (def, params, defaultFilter) {\n return this.getCompDetails(def, FilterComponent, defaultFilter, params, true);\n };\n UserComponentFactory.prototype.getDateCompDetails = function (params) {\n return this.getCompDetails(this.gridOptions, DateComponent, 'agDateInput', params, true);\n };\n UserComponentFactory.prototype.getLoadingOverlayCompDetails = function (params) {\n return this.getCompDetails(this.gridOptions, LoadingOverlayComponent, 'agLoadingOverlay', params, true);\n };\n UserComponentFactory.prototype.getNoRowsOverlayCompDetails = function (params) {\n return this.getCompDetails(this.gridOptions, NoRowsOverlayComponent, 'agNoRowsOverlay', params, true);\n };\n UserComponentFactory.prototype.getTooltipCompDetails = function (params) {\n return this.getCompDetails(params.colDef, TooltipComponent, 'agTooltipComponent', params, true);\n };\n UserComponentFactory.prototype.getSetFilterCellRendererDetails = function (def, params) {\n return this.getCompDetails(def, CellRendererComponent, null, params);\n };\n UserComponentFactory.prototype.getFloatingFilterCompDetails = function (def, params, defaultFloatingFilter) {\n return this.getCompDetails(def, FloatingFilterComponent, defaultFloatingFilter, params);\n };\n UserComponentFactory.prototype.getToolPanelCompDetails = function (toolPanelDef, params) {\n return this.getCompDetails(toolPanelDef, ToolPanelComponent, null, params, true);\n };\n UserComponentFactory.prototype.getStatusPanelCompDetails = function (def, params) {\n return this.getCompDetails(def, StatusPanelComponent, null, params, true);\n };\n UserComponentFactory.prototype.getCompDetails = function (defObject, type, defaultName, params, mandatory) {\n var _this = this;\n if (mandatory === void 0) { mandatory = false; }\n var propertyName = type.propertyName, cellRenderer = type.cellRenderer;\n var _a = this.getCompKeys(defObject, type, params), compName = _a.compName, jsComp = _a.jsComp, fwComp = _a.fwComp, paramsFromSelector = _a.paramsFromSelector, popupFromSelector = _a.popupFromSelector, popupPositionFromSelector = _a.popupPositionFromSelector;\n var lookupFromRegistry = function (key) {\n var item = _this.userComponentRegistry.retrieve(key);\n if (item) {\n jsComp = !item.componentFromFramework ? item.component : undefined;\n fwComp = item.componentFromFramework ? item.component : undefined;\n }\n };\n // if compOption is a string, means we need to look the item up\n if (compName != null) {\n lookupFromRegistry(compName);\n }\n // if lookup brought nothing back, and we have a default, lookup the default\n if (jsComp == null && fwComp == null && defaultName != null) {\n lookupFromRegistry(defaultName);\n }\n // if we have a comp option, and it's a function, replace it with an object equivalent adaptor\n if (jsComp && cellRenderer && !this.agComponentUtils.doesImplementIComponent(jsComp)) {\n jsComp = this.agComponentUtils.adaptFunction(propertyName, jsComp);\n }\n if (!jsComp && !fwComp) {\n if (mandatory) {\n console.error(\"Could not find component \" + compName + \", did you forget to configure this component?\");\n }\n return;\n }\n var paramsMerged = this.mergeParamsWithApplicationProvidedParams(defObject, type, params, paramsFromSelector);\n var componentFromFramework = jsComp == null;\n var componentClass = jsComp ? jsComp : fwComp;\n return {\n componentFromFramework: componentFromFramework,\n componentClass: componentClass,\n params: paramsMerged,\n type: type,\n popupFromSelector: popupFromSelector,\n popupPositionFromSelector: popupPositionFromSelector,\n newAgStackInstance: function () { return _this.newAgStackInstance(componentClass, componentFromFramework, paramsMerged, type); }\n };\n };\n UserComponentFactory.prototype.getCompKeys = function (defObject, type, params) {\n var _this = this;\n var propertyName = type.propertyName;\n var compName;\n var jsComp;\n var fwComp;\n var paramsFromSelector;\n var popupFromSelector;\n var popupPositionFromSelector;\n // there are two types of js comps, class based and func based. we can only check for\n // class based, by checking if getGui() exists. no way to differentiate js func based vs eg react func based\n // const isJsClassComp = (comp: any) => this.agComponentUtils.doesImplementIComponent(comp);\n // const fwActive = this.frameworkComponentWrapper != null;\n // pull from defObject if available\n if (defObject) {\n var defObjectAny = defObject;\n // if selector, use this\n var selectorFunc = defObjectAny[propertyName + 'Selector'];\n var selectorRes = selectorFunc ? selectorFunc(params) : null;\n var assignComp = function (providedJsComp, providedFwComp) {\n var xxxFrameworkDeprecatedWarn = function () {\n var warningMessage = \"AG Grid: As of v27, the property \" + propertyName + \"Framework is deprecated. The property \" + propertyName + \" can now be used for JavaScript AND Framework Components.\";\n doOnce(function () { return console.warn(warningMessage); }, \"UserComponentFactory.\" + propertyName + \"FrameworkDeprecated\");\n };\n if (typeof providedJsComp === 'string') {\n compName = providedJsComp;\n }\n else if (typeof providedFwComp === 'string') {\n xxxFrameworkDeprecatedWarn();\n compName = providedFwComp;\n // comp===true for filters, which means use the default comp\n }\n else if (providedJsComp != null && providedJsComp !== true) {\n var isFwkComp = _this.getFrameworkOverrides().isFrameworkComponent(providedJsComp);\n if (isFwkComp) {\n fwComp = providedJsComp;\n }\n else {\n jsComp = providedJsComp;\n }\n }\n else if (providedFwComp != null) {\n xxxFrameworkDeprecatedWarn();\n fwComp = providedFwComp;\n }\n };\n if (selectorRes) {\n if (selectorRes.frameworkComponent != null) {\n var warningMessage_1 = \"AG Grid: As of v27, the return for \" + propertyName + \"Selector has attributes [component, params] only. The attribute frameworkComponent is deprecated. You should now return back Framework Components using the 'component' attribute and the grid works out if it's a framework component or not.\";\n doOnce(function () { return console.warn(warningMessage_1); }, \"UserComponentFactory.\" + propertyName + \"FrameworkSelectorDeprecated\");\n assignComp(selectorRes.frameworkComponent, undefined);\n }\n else {\n assignComp(selectorRes.component, undefined);\n }\n paramsFromSelector = selectorRes.params;\n popupFromSelector = selectorRes.popup;\n popupPositionFromSelector = selectorRes.popupPosition;\n }\n else {\n // if no selector, or result of selector is empty, take from defObject\n assignComp(defObjectAny[propertyName], defObjectAny[propertyName + 'Framework']);\n }\n }\n return { compName: compName, jsComp: jsComp, fwComp: fwComp, paramsFromSelector: paramsFromSelector, popupFromSelector: popupFromSelector, popupPositionFromSelector: popupPositionFromSelector };\n };\n UserComponentFactory.prototype.newAgStackInstance = function (ComponentClass, componentFromFramework, params, type) {\n var propertyName = type.propertyName;\n var jsComponent = !componentFromFramework;\n // using javascript component\n var instance;\n if (jsComponent) {\n instance = new ComponentClass();\n }\n else {\n // Using framework component\n var thisComponentConfig = this.componentMetadataProvider.retrieve(propertyName);\n instance = this.frameworkComponentWrapper.wrap(ComponentClass, thisComponentConfig.mandatoryMethodList, thisComponentConfig.optionalMethodList, type);\n }\n var deferredInit = this.initComponent(instance, params);\n if (deferredInit == null) {\n return AgPromise.resolve(instance);\n }\n return deferredInit.then(function () { return instance; });\n };\n // used by Floating Filter\n UserComponentFactory.prototype.mergeParamsWithApplicationProvidedParams = function (defObject, type, paramsFromGrid, paramsFromSelector) {\n if (paramsFromSelector === void 0) { paramsFromSelector = null; }\n var params = {\n context: this.gridOptionsWrapper.getContext(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n api: this.gridOptionsWrapper.getApi()\n };\n mergeDeep(params, paramsFromGrid);\n // pull user params from either the old prop name and new prop name\n // eg either cellRendererParams and cellCompParams\n var defObjectAny = defObject;\n var userParams = defObjectAny && defObjectAny[type.propertyName + 'Params'];\n if (typeof userParams === 'function') {\n var userParamsFromFunc = userParams(paramsFromGrid);\n mergeDeep(params, userParamsFromFunc);\n }\n else if (typeof userParams === 'object') {\n mergeDeep(params, userParams);\n }\n mergeDeep(params, paramsFromSelector);\n return params;\n };\n UserComponentFactory.prototype.initComponent = function (component, params) {\n this.context.createBean(component);\n if (component.init == null) {\n return;\n }\n return component.init(params);\n };\n UserComponentFactory.prototype.getDefaultFloatingFilterType = function (def) {\n if (def == null) {\n return null;\n }\n var defaultFloatingFilterType = null;\n var _a = this.getCompKeys(def, FilterComponent), compName = _a.compName, jsComp = _a.jsComp, fwComp = _a.fwComp;\n if (compName) {\n // will be undefined if not in the map\n defaultFloatingFilterType = FloatingFilterMapper.getFloatingFilterType(compName);\n }\n else {\n var usingDefaultFilter = (jsComp == null && fwComp == null) && (def.filter === true);\n if (usingDefaultFilter) {\n var setFilterModuleLoaded = ModuleRegistry.isRegistered(ModuleNames.SetFilterModule);\n defaultFloatingFilterType = setFilterModuleLoaded ? 'agSetColumnFloatingFilter' : 'agTextColumnFloatingFilter';\n }\n }\n return defaultFloatingFilterType;\n };\n __decorate$1W([\n Autowired('gridOptions')\n ], UserComponentFactory.prototype, \"gridOptions\", void 0);\n __decorate$1W([\n Autowired('agComponentUtils')\n ], UserComponentFactory.prototype, \"agComponentUtils\", void 0);\n __decorate$1W([\n Autowired('componentMetadataProvider')\n ], UserComponentFactory.prototype, \"componentMetadataProvider\", void 0);\n __decorate$1W([\n Autowired('userComponentRegistry')\n ], UserComponentFactory.prototype, \"userComponentRegistry\", void 0);\n __decorate$1W([\n Optional('frameworkComponentWrapper')\n ], UserComponentFactory.prototype, \"frameworkComponentWrapper\", void 0);\n UserComponentFactory = __decorate$1W([\n Bean('userComponentFactory')\n ], UserComponentFactory);\n return UserComponentFactory;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n// Excel Export\nvar ExcelFactoryMode;\n(function (ExcelFactoryMode) {\n ExcelFactoryMode[ExcelFactoryMode[\"SINGLE_SHEET\"] = 0] = \"SINGLE_SHEET\";\n ExcelFactoryMode[ExcelFactoryMode[\"MULTI_SHEET\"] = 1] = \"MULTI_SHEET\";\n})(ExcelFactoryMode || (ExcelFactoryMode = {}));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$27 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1V = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n/** Adds drag listening onto an element. In AG Grid this is used twice, first is resizing columns,\n * second is moving the columns and column groups around (ie the 'drag' part of Drag and Drop. */\nvar DragService = /** @class */ (function (_super) {\n __extends$27(DragService, _super);\n function DragService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.dragEndFunctions = [];\n _this.dragSources = [];\n return _this;\n }\n DragService.prototype.init = function () {\n this.logger = this.loggerFactory.create('DragService');\n };\n DragService.prototype.removeAllListeners = function () {\n this.dragSources.forEach(this.removeListener.bind(this));\n this.dragSources.length = 0;\n };\n DragService.prototype.removeListener = function (dragSourceAndListener) {\n var element = dragSourceAndListener.dragSource.eElement;\n var mouseDownListener = dragSourceAndListener.mouseDownListener;\n element.removeEventListener('mousedown', mouseDownListener);\n // remove touch listener only if it exists\n if (dragSourceAndListener.touchEnabled) {\n var touchStartListener = dragSourceAndListener.touchStartListener;\n element.removeEventListener('touchstart', touchStartListener, { passive: true });\n }\n };\n DragService.prototype.removeDragSource = function (params) {\n var dragSourceAndListener = this.dragSources.find(function (item) { return item.dragSource === params; });\n if (!dragSourceAndListener) {\n return;\n }\n this.removeListener(dragSourceAndListener);\n removeFromArray(this.dragSources, dragSourceAndListener);\n };\n DragService.prototype.isDragging = function () {\n return this.dragging;\n };\n DragService.prototype.addDragSource = function (params, includeTouch) {\n var _this = this;\n if (includeTouch === void 0) { includeTouch = false; }\n var mouseListener = this.onMouseDown.bind(this, params);\n params.eElement.addEventListener('mousedown', mouseListener);\n var touchListener = null;\n var suppressTouch = this.gridOptionsWrapper.isSuppressTouch();\n if (includeTouch && !suppressTouch) {\n touchListener = function (touchEvent) {\n if (isFocusableFormField(touchEvent.target)) {\n return;\n }\n if (touchEvent.cancelable) {\n touchEvent.preventDefault();\n }\n _this.onTouchStart(params, touchEvent);\n };\n // we set passive=false, as we want to prevent default on this event\n params.eElement.addEventListener('touchstart', touchListener, { passive: false });\n }\n this.dragSources.push({\n dragSource: params,\n mouseDownListener: mouseListener,\n touchStartListener: touchListener,\n touchEnabled: includeTouch\n });\n };\n // gets called whenever mouse down on any drag source\n DragService.prototype.onTouchStart = function (params, touchEvent) {\n var _this = this;\n this.currentDragParams = params;\n this.dragging = false;\n var touch = touchEvent.touches[0];\n this.touchLastTime = touch;\n this.touchStart = touch;\n var touchMoveEvent = function (e) { return _this.onTouchMove(e, params.eElement); };\n var touchEndEvent = function (e) { return _this.onTouchUp(e, params.eElement); };\n var documentTouchMove = function (e) { if (e.cancelable) {\n e.preventDefault();\n } };\n var target = touchEvent.target;\n var events = [\n // Prevents the page document from moving while we are dragging items around.\n // preventDefault needs to be called in the touchmove listener and never inside the\n // touchstart, because using touchstart causes the click event to be cancelled on touch devices.\n { target: document, type: 'touchmove', listener: documentTouchMove, options: { passive: false } },\n { target: target, type: 'touchmove', listener: touchMoveEvent, options: { passive: true } },\n { target: target, type: 'touchend', listener: touchEndEvent, options: { passive: true } },\n { target: target, type: 'touchcancel', listener: touchEndEvent, options: { passive: true } }\n ];\n // temporally add these listeners, for the duration of the drag\n this.addTemporaryEvents(events);\n // see if we want to start dragging straight away\n if (params.dragStartPixels === 0) {\n this.onCommonMove(touch, this.touchStart, params.eElement);\n }\n };\n // gets called whenever mouse down on any drag source\n DragService.prototype.onMouseDown = function (params, mouseEvent) {\n var _this = this;\n var e = mouseEvent;\n if (params.skipMouseEvent && params.skipMouseEvent(mouseEvent)) {\n return;\n }\n // if there are two elements with parent / child relationship, and both are draggable,\n // when we drag the child, we should NOT drag the parent. an example of this is row moving\n // and range selection - row moving should get preference when use drags the rowDrag component.\n if (e._alreadyProcessedByDragService) {\n return;\n }\n e._alreadyProcessedByDragService = true;\n // only interested in left button clicks\n if (mouseEvent.button !== 0) {\n return;\n }\n this.currentDragParams = params;\n this.dragging = false;\n this.mouseStartEvent = mouseEvent;\n var eDocument = this.gridOptionsWrapper.getDocument();\n var mouseMoveEvent = function (event) { return _this.onMouseMove(event, params.eElement); };\n var mouseUpEvent = function (event) { return _this.onMouseUp(event, params.eElement); };\n var contextEvent = function (event) { return event.preventDefault(); };\n var target = eDocument;\n var events = [\n { target: target, type: 'mousemove', listener: mouseMoveEvent },\n { target: target, type: 'mouseup', listener: mouseUpEvent },\n { target: target, type: 'contextmenu', listener: contextEvent }\n ];\n // temporally add these listeners, for the duration of the drag\n this.addTemporaryEvents(events);\n //see if we want to start dragging straight away\n if (params.dragStartPixels === 0) {\n this.onMouseMove(mouseEvent, params.eElement);\n }\n };\n DragService.prototype.addTemporaryEvents = function (events) {\n events.forEach(function (currentEvent) {\n var target = currentEvent.target, type = currentEvent.type, listener = currentEvent.listener, options = currentEvent.options;\n target.addEventListener(type, listener, options);\n });\n this.dragEndFunctions.push(function () {\n events.forEach(function (currentEvent) {\n var target = currentEvent.target, type = currentEvent.type, listener = currentEvent.listener, options = currentEvent.options;\n target.removeEventListener(type, listener, options);\n });\n });\n };\n // returns true if the event is close to the original event by X pixels either vertically or horizontally.\n // we only start dragging after X pixels so this allows us to know if we should start dragging yet.\n DragService.prototype.isEventNearStartEvent = function (currentEvent, startEvent) {\n // by default, we wait 4 pixels before starting the drag\n var dragStartPixels = this.currentDragParams.dragStartPixels;\n var requiredPixelDiff = exists(dragStartPixels) ? dragStartPixels : 4;\n return areEventsNear(currentEvent, startEvent, requiredPixelDiff);\n };\n DragService.prototype.getFirstActiveTouch = function (touchList) {\n for (var i = 0; i < touchList.length; i++) {\n if (touchList[i].identifier === this.touchStart.identifier) {\n return touchList[i];\n }\n }\n return null;\n };\n DragService.prototype.onCommonMove = function (currentEvent, startEvent, el) {\n if (!this.dragging) {\n // if mouse hasn't travelled from the start position enough, do nothing\n if (!this.dragging && this.isEventNearStartEvent(currentEvent, startEvent)) {\n return;\n }\n this.dragging = true;\n var event_1 = {\n type: Events.EVENT_DRAG_STARTED,\n target: el\n };\n this.eventService.dispatchEvent(event_1);\n this.currentDragParams.onDragStart(startEvent);\n // we need ONE drag action at the startEvent, so that we are guaranteed the drop target\n // at the start gets notified. this is because the drag can start outside of the element\n // that started it, as the mouse is allowed drag away from the mouse down before it's\n // considered a drag (the isEventNearStartEvent() above). if we didn't do this, then\n // it would be possible to click a column by the edge, then drag outside of the drop zone\n // in less than 4 pixels and the drag officially starts outside of the header but the header\n // wouldn't be notified of the dragging.\n this.currentDragParams.onDragging(startEvent);\n }\n this.currentDragParams.onDragging(currentEvent);\n };\n DragService.prototype.onTouchMove = function (touchEvent, el) {\n var touch = this.getFirstActiveTouch(touchEvent.touches);\n if (!touch) {\n return;\n }\n // this.___statusPanel.setInfoText(Math.random() + ' onTouchMove preventDefault stopPropagation');\n this.onCommonMove(touch, this.touchStart, el);\n };\n // only gets called after a mouse down - as this is only added after mouseDown\n // and is removed when mouseUp happens\n DragService.prototype.onMouseMove = function (mouseEvent, el) {\n // when `isEnableCellTextSelect` is `true`, we need to preventDefault on mouseMove\n // to avoid the grid text being selected while dragging components.\n // Note: Safari also has an issue, where `user-select: none` is not being respected.\n if ((this.gridOptionsWrapper.isEnableCellTextSelect() || isBrowserSafari()) &&\n // The event type can be `mousedown` when `dragStartPixels=0`\n // we should only preventDefault on `mousemove`.\n mouseEvent.type === 'mousemove' &&\n mouseEvent.cancelable &&\n this.mouseEventService.isEventFromThisGrid(mouseEvent) &&\n // we should not prevent mouseMove when above a form field\n // as that would prevent the text in the field from being selected\n !this.isOverFormFieldElement(mouseEvent)) {\n mouseEvent.preventDefault();\n }\n this.onCommonMove(mouseEvent, this.mouseStartEvent, el);\n };\n DragService.prototype.isOverFormFieldElement = function (mouseEvent) {\n var _a, _b;\n var el = mouseEvent.target;\n var tagName = (_a = el) === null || _a === void 0 ? void 0 : _a.tagName.toLocaleLowerCase();\n return !!((_b = tagName) === null || _b === void 0 ? void 0 : _b.match('^a$|textarea|input|select|button'));\n };\n DragService.prototype.onTouchUp = function (touchEvent, el) {\n var touch = this.getFirstActiveTouch(touchEvent.changedTouches);\n // i haven't worked this out yet, but there is no matching touch\n // when we get the touch up event. to get around this, we swap in\n // the last touch. this is a hack to 'get it working' while we\n // figure out what's going on, why we are not getting a touch in\n // current event.\n if (!touch) {\n touch = this.touchLastTime;\n }\n // if mouse was left up before we started to move, then this is a tap.\n // we check this before onUpCommon as onUpCommon resets the dragging\n // let tap = !this.dragging;\n // let tapTarget = this.currentDragParams.eElement;\n this.onUpCommon(touch, el);\n // if tap, tell user\n // console.log(`${Math.random()} tap = ${tap}`);\n // if (tap) {\n // tapTarget.click();\n // }\n };\n DragService.prototype.onMouseUp = function (mouseEvent, el) {\n this.onUpCommon(mouseEvent, el);\n };\n DragService.prototype.onUpCommon = function (eventOrTouch, el) {\n if (this.dragging) {\n this.dragging = false;\n this.currentDragParams.onDragStop(eventOrTouch);\n var event_2 = {\n type: Events.EVENT_DRAG_STOPPED,\n target: el\n };\n this.eventService.dispatchEvent(event_2);\n }\n this.mouseStartEvent = null;\n this.touchStart = null;\n this.touchLastTime = null;\n this.currentDragParams = null;\n this.dragEndFunctions.forEach(function (func) { return func(); });\n this.dragEndFunctions.length = 0;\n };\n __decorate$1V([\n Autowired('loggerFactory')\n ], DragService.prototype, \"loggerFactory\", void 0);\n __decorate$1V([\n Autowired('mouseEventService')\n ], DragService.prototype, \"mouseEventService\", void 0);\n __decorate$1V([\n PostConstruct\n ], DragService.prototype, \"init\", null);\n __decorate$1V([\n PreDestroy\n ], DragService.prototype, \"removeAllListeners\", null);\n DragService = __decorate$1V([\n Bean('dragService')\n ], DragService);\n return DragService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$26 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$7 = (undefined && undefined.__assign) || function () {\n __assign$7 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$7.apply(this, arguments);\n};\nvar __decorate$1U = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar FilterManager = /** @class */ (function (_super) {\n __extends$26(FilterManager, _super);\n function FilterManager() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.allColumnFilters = new Map();\n _this.activeAggregateFilters = [];\n _this.activeColumnFilters = [];\n _this.quickFilter = null;\n _this.quickFilterParts = null;\n // this is true when the grid is processing the filter change. this is used by the cell comps, so that they\n // don't flash when data changes due to filter changes. there is no need to flash when filter changes as the\n // user is in control, so doesn't make sense to show flashing changes. for example, go to main demo where\n // this feature is turned off (hack code to always return false for isSuppressFlashingCellsBecauseFiltering(), put in)\n // 100,000 rows and group by country. then do some filtering. all the cells flash, which is silly.\n _this.processingFilterChange = false;\n return _this;\n }\n FilterManager_1 = FilterManager;\n FilterManager.prototype.init = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_GRID_COLUMNS_CHANGED, function () { return _this.onColumnsChanged(); });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_VALUE_CHANGED, function () { return _this.refreshFiltersForAggregations(); });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_CHANGED, function () { return _this.refreshFiltersForAggregations(); });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, function () { return _this.refreshFiltersForAggregations(); });\n this.quickFilter = this.parseQuickFilter(this.gridOptionsWrapper.getQuickFilterText());\n this.setQuickFilterParts();\n this.allowShowChangeAfterFilter = this.gridOptionsWrapper.isAllowShowChangeAfterFilter();\n this.externalFilterPresent = this.gridOptionsWrapper.isExternalFilterPresent();\n };\n FilterManager.prototype.setQuickFilterParts = function () {\n this.quickFilterParts = this.quickFilter ? this.quickFilter.split(' ') : null;\n };\n FilterManager.prototype.setFilterModel = function (model) {\n var _this = this;\n var allPromises = [];\n var previousModel = this.getFilterModel();\n if (model) {\n // mark the filters as we set them, so any active filters left over we stop\n var modelKeys_1 = convertToSet(Object.keys(model));\n this.allColumnFilters.forEach(function (filterWrapper, colId) {\n var newModel = model[colId];\n allPromises.push(_this.setModelOnFilterWrapper(filterWrapper.filterPromise, newModel));\n modelKeys_1.delete(colId);\n });\n // at this point, processedFields contains data for which we don't have a filter working yet\n modelKeys_1.forEach(function (colId) {\n var column = _this.columnModel.getPrimaryColumn(colId) || _this.columnModel.getGridColumn(colId);\n if (!column) {\n console.warn('AG Grid: setFilterModel() - no column found for colId: ' + colId);\n return;\n }\n if (!column.isFilterAllowed()) {\n console.warn('AG Grid: setFilterModel() - unable to fully apply model, filtering disabled for colId: ' + colId);\n return;\n }\n var filterWrapper = _this.getOrCreateFilterWrapper(column, 'NO_UI');\n if (!filterWrapper) {\n console.warn('AG-Grid: setFilterModel() - unable to fully apply model, unable to create filter for colId: ' + colId);\n return;\n }\n allPromises.push(_this.setModelOnFilterWrapper(filterWrapper.filterPromise, model[colId]));\n });\n }\n else {\n this.allColumnFilters.forEach(function (filterWrapper) {\n allPromises.push(_this.setModelOnFilterWrapper(filterWrapper.filterPromise, null));\n });\n }\n AgPromise.all(allPromises).then(function () {\n var currentModel = _this.getFilterModel();\n var columns = [];\n _this.allColumnFilters.forEach(function (filterWrapper, colId) {\n var before = previousModel ? previousModel[colId] : null;\n var after = currentModel ? currentModel[colId] : null;\n if (!_.jsonEquals(before, after)) {\n columns.push(filterWrapper.column);\n }\n });\n if (columns.length > 0) {\n _this.onFilterChanged({ columns: columns });\n }\n });\n };\n FilterManager.prototype.setModelOnFilterWrapper = function (filterPromise, newModel) {\n return new AgPromise(function (resolve) {\n filterPromise.then(function (filter) {\n if (typeof filter.setModel !== 'function') {\n console.warn('AG Grid: filter missing setModel method, which is needed for setFilterModel');\n resolve();\n }\n (filter.setModel(newModel) || AgPromise.resolve()).then(function () { return resolve(); });\n });\n });\n };\n FilterManager.prototype.getFilterModel = function () {\n var result = {};\n this.allColumnFilters.forEach(function (filterWrapper, key) {\n // because user can provide filters, we provide useful error checking and messages\n var filterPromise = filterWrapper.filterPromise;\n var filter = filterPromise.resolveNow(null, function (promiseFilter) { return promiseFilter; });\n if (filter == null) {\n return null;\n }\n if (typeof filter.getModel !== 'function') {\n console.warn('AG Grid: filter API missing getModel method, which is needed for getFilterModel');\n return;\n }\n var model = filter.getModel();\n if (exists(model)) {\n result[key] = model;\n }\n });\n return result;\n };\n FilterManager.prototype.isColumnFilterPresent = function () {\n return this.activeColumnFilters.length > 0;\n };\n FilterManager.prototype.isAggregateFilterPresent = function () {\n return !!this.activeAggregateFilters.length;\n };\n FilterManager.prototype.isExternalFilterPresent = function () {\n return this.externalFilterPresent;\n };\n FilterManager.prototype.doAggregateFiltersPass = function (node, filterToSkip) {\n return this.doColumnFiltersPass(node, filterToSkip, true);\n };\n // called by:\n // 1) onFilterChanged()\n // 2) onNewRowsLoaded()\n FilterManager.prototype.updateActiveFilters = function () {\n var _this = this;\n this.activeColumnFilters.length = 0;\n this.activeAggregateFilters.length = 0;\n var isFilterActive = function (filter) {\n if (!filter) {\n return false;\n } // this never happens, including to avoid compile error\n if (!filter.isFilterActive) {\n console.warn('AG Grid: Filter is missing isFilterActive() method');\n return false;\n }\n return filter.isFilterActive();\n };\n var groupFilterEnabled = !!this.gridOptionsWrapper.getGroupAggFiltering();\n var isAggFilter = function (column) {\n var isSecondary = !column.isPrimary();\n // the only filters that can appear on secondary columns are groupAgg filters\n if (isSecondary) {\n return true;\n }\n var isShowingPrimaryColumns = !_this.columnModel.isPivotActive();\n var isValueActive = column.isValueActive();\n // primary columns are only ever groupAgg filters if a) value is active and b) showing primary columns\n if (!isValueActive || !isShowingPrimaryColumns) {\n return false;\n }\n // from here on we know: isPrimary=true, isValueActive=true, isShowingPrimaryColumns=true\n if (_this.columnModel.isPivotMode()) {\n // primary column is pretending to be a pivot column, ie pivotMode=true, but we are\n // still showing primary columns\n return true;\n }\n else {\n // we are not pivoting, so we groupFilter when it's an agg column\n return groupFilterEnabled;\n }\n };\n this.allColumnFilters.forEach(function (filterWrapper) {\n if (filterWrapper.filterPromise.resolveNow(false, isFilterActive)) {\n var filterComp = filterWrapper.filterPromise.resolveNow(null, function (filter) { return filter; });\n if (isAggFilter(filterWrapper.column)) {\n _this.activeAggregateFilters.push(filterComp);\n }\n else {\n _this.activeColumnFilters.push(filterComp);\n }\n }\n });\n };\n FilterManager.prototype.updateFilterFlagInColumns = function (source, additionalEventAttributes) {\n this.allColumnFilters.forEach(function (filterWrapper) {\n var isFilterActive = filterWrapper.filterPromise.resolveNow(false, function (filter) { return filter.isFilterActive(); });\n filterWrapper.column.setFilterActive(isFilterActive, source, additionalEventAttributes);\n });\n };\n FilterManager.prototype.isAnyFilterPresent = function () {\n return this.isQuickFilterPresent() || this.isColumnFilterPresent() || this.isAggregateFilterPresent() || this.isExternalFilterPresent();\n };\n FilterManager.prototype.doColumnFiltersPass = function (node, filterToSkip, targetAggregates) {\n var data = node.data, aggData = node.aggData;\n var targetedFilters = targetAggregates ? this.activeAggregateFilters : this.activeColumnFilters;\n var targetedData = targetAggregates ? aggData : data;\n for (var i = 0; i < targetedFilters.length; i++) {\n var filter = targetedFilters[i];\n if (filter == null || filter === filterToSkip) {\n continue;\n }\n if (typeof filter.doesFilterPass !== 'function') {\n // because users can do custom filters, give nice error message\n throw new Error('Filter is missing method doesFilterPass');\n }\n if (!filter.doesFilterPass({ node: node, data: targetedData })) {\n return false;\n }\n }\n return true;\n };\n FilterManager.prototype.parseQuickFilter = function (newFilter) {\n if (!exists(newFilter)) {\n return null;\n }\n if (!this.gridOptionsWrapper.isRowModelDefault()) {\n console.warn('AG Grid - Quick filtering only works with the Client-Side Row Model');\n return null;\n }\n return newFilter.toUpperCase();\n };\n FilterManager.prototype.setQuickFilter = function (newFilter) {\n if (newFilter != null && typeof newFilter !== 'string') {\n console.warn(\"AG Grid - setQuickFilter() only supports string inputs, received: \" + typeof newFilter);\n return;\n }\n var parsedFilter = this.parseQuickFilter(newFilter);\n if (this.quickFilter !== parsedFilter) {\n this.quickFilter = parsedFilter;\n this.setQuickFilterParts();\n this.onFilterChanged();\n }\n };\n FilterManager.prototype.refreshFiltersForAggregations = function () {\n var isAggFiltering = this.gridOptionsWrapper.getGroupAggFiltering();\n if (isAggFiltering) {\n this.onFilterChanged();\n }\n };\n // sometimes (especially in React) the filter can call onFilterChanged when we are in the middle\n // of a render cycle. this would be bad, so we wait for render cycle to complete when this happens.\n // this happens in react when we change React State in the grid (eg setting RowCtrl's in RowContainer)\n // which results in React State getting applied in the main application, triggering a useEffect() to\n // be kicked off adn then the application calling the grid's API. in AG-6554, the custom filter was\n // getting it's useEffect() triggered in this way.\n FilterManager.prototype.callOnFilterChangedOutsideRenderCycle = function (params) {\n var _this = this;\n if (params === void 0) { params = {}; }\n var action = function () { return _this.onFilterChanged(params); };\n if (this.rowRenderer.isRefreshInProgress()) {\n setTimeout(action, 0);\n }\n else {\n action();\n }\n };\n FilterManager.prototype.onFilterChanged = function (params) {\n if (params === void 0) { params = {}; }\n var filterInstance = params.filterInstance, additionalEventAttributes = params.additionalEventAttributes, columns = params.columns;\n this.updateActiveFilters();\n this.updateFilterFlagInColumns('filterChanged', additionalEventAttributes);\n this.externalFilterPresent = this.gridOptionsWrapper.isExternalFilterPresent();\n this.allColumnFilters.forEach(function (filterWrapper) {\n if (!filterWrapper.filterPromise) {\n return;\n }\n filterWrapper.filterPromise.then(function (filter) {\n if (filter && filter !== filterInstance && filter.onAnyFilterChanged) {\n filter.onAnyFilterChanged();\n }\n });\n });\n var filterChangedEvent = {\n type: Events.EVENT_FILTER_CHANGED,\n columns: columns || [],\n };\n if (additionalEventAttributes) {\n mergeDeep(filterChangedEvent, additionalEventAttributes);\n }\n // because internal events are not async in ag-grid, when the dispatchEvent\n // method comes back, we know all listeners have finished executing.\n this.processingFilterChange = true;\n this.eventService.dispatchEvent(filterChangedEvent);\n this.processingFilterChange = false;\n };\n FilterManager.prototype.isSuppressFlashingCellsBecauseFiltering = function () {\n // if user has elected to always flash cell changes, then always return false, otherwise we suppress flashing\n // changes when filtering\n return !this.allowShowChangeAfterFilter && this.processingFilterChange;\n };\n FilterManager.prototype.isQuickFilterPresent = function () {\n return this.quickFilter !== null;\n };\n FilterManager.prototype.doesRowPassOtherFilters = function (filterToSkip, node) {\n return this.doesRowPassFilter({ rowNode: node, filterInstanceToSkip: filterToSkip });\n };\n FilterManager.prototype.doesRowPassQuickFilterNoCache = function (node, filterPart) {\n var _this = this;\n var columns = this.columnModel.getAllColumnsForQuickFilter();\n return columns.some(function (column) {\n var part = _this.getQuickFilterTextForColumn(column, node);\n return exists(part) && part.indexOf(filterPart) >= 0;\n });\n };\n FilterManager.prototype.doesRowPassQuickFilterCache = function (node, filterPart) {\n if (!node.quickFilterAggregateText) {\n this.aggregateRowForQuickFilter(node);\n }\n return node.quickFilterAggregateText.indexOf(filterPart) >= 0;\n };\n FilterManager.prototype.doesRowPassQuickFilter = function (node) {\n var _this = this;\n var usingCache = this.gridOptionsWrapper.isCacheQuickFilter();\n // each part must pass, if any fails, then the whole filter fails\n return this.quickFilterParts.every(function (part) {\n return usingCache ? _this.doesRowPassQuickFilterCache(node, part) : _this.doesRowPassQuickFilterNoCache(node, part);\n });\n };\n FilterManager.prototype.doesRowPassAggregateFilters = function (params) {\n if (this.isAggregateFilterPresent() && !this.doAggregateFiltersPass(params.rowNode, params.filterInstanceToSkip)) {\n return false;\n }\n // got this far, all filters pass\n return true;\n };\n FilterManager.prototype.doesRowPassFilter = function (params) {\n // the row must pass ALL of the filters, so if any of them fail,\n // we return true. that means if a row passes the quick filter,\n // but fails the column filter, it fails overall\n // first up, check quick filter\n if (this.isQuickFilterPresent() && !this.doesRowPassQuickFilter(params.rowNode)) {\n return false;\n }\n // secondly, give the client a chance to reject this row\n if (this.isExternalFilterPresent() && !this.gridOptionsWrapper.doesExternalFilterPass(params.rowNode)) {\n return false;\n }\n // lastly, check column filter\n if (this.isColumnFilterPresent() && !this.doColumnFiltersPass(params.rowNode, params.filterInstanceToSkip)) {\n return false;\n }\n // got this far, all filters pass\n return true;\n };\n FilterManager.prototype.getQuickFilterTextForColumn = function (column, node) {\n var value = this.valueService.getValue(column, node, true);\n var colDef = column.getColDef();\n if (colDef.getQuickFilterText) {\n var params = {\n value: value,\n node: node,\n data: node.data,\n column: column,\n colDef: colDef,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n value = colDef.getQuickFilterText(params);\n }\n return exists(value) ? value.toString().toUpperCase() : null;\n };\n FilterManager.prototype.aggregateRowForQuickFilter = function (node) {\n var _this = this;\n var stringParts = [];\n var columns = this.columnModel.getAllColumnsForQuickFilter();\n columns.forEach(function (column) {\n var part = _this.getQuickFilterTextForColumn(column, node);\n if (exists(part)) {\n stringParts.push(part);\n }\n });\n node.quickFilterAggregateText = stringParts.join(FilterManager_1.QUICK_FILTER_SEPARATOR);\n };\n FilterManager.prototype.onNewRowsLoaded = function (source) {\n this.allColumnFilters.forEach(function (filterWrapper) {\n filterWrapper.filterPromise.then(function (filter) {\n if (filter.onNewRowsLoaded) {\n filter.onNewRowsLoaded();\n }\n });\n });\n this.updateFilterFlagInColumns(source);\n this.updateActiveFilters();\n };\n FilterManager.prototype.createValueGetter = function (column) {\n var _this = this;\n return function (_a) {\n var node = _a.node;\n return _this.valueService.getValue(column, node, true);\n };\n };\n FilterManager.prototype.getFilterComponent = function (column, source, createIfDoesNotExist) {\n if (createIfDoesNotExist === void 0) { createIfDoesNotExist = true; }\n var _a;\n if (createIfDoesNotExist) {\n return ((_a = this.getOrCreateFilterWrapper(column, source)) === null || _a === void 0 ? void 0 : _a.filterPromise) || null;\n }\n var filterWrapper = this.cachedFilter(column);\n return filterWrapper ? filterWrapper.filterPromise : null;\n };\n FilterManager.prototype.isFilterActive = function (column) {\n var filterWrapper = this.cachedFilter(column);\n return !!filterWrapper && filterWrapper.filterPromise.resolveNow(false, function (filter) { return filter.isFilterActive(); });\n };\n FilterManager.prototype.getOrCreateFilterWrapper = function (column, source) {\n if (!column.isFilterAllowed()) {\n return null;\n }\n var filterWrapper = this.cachedFilter(column);\n if (!filterWrapper) {\n filterWrapper = this.createFilterWrapper(column, source);\n this.allColumnFilters.set(column.getColId(), filterWrapper);\n }\n else if (source !== 'NO_UI') {\n this.putIntoGui(filterWrapper, source);\n }\n return filterWrapper;\n };\n FilterManager.prototype.cachedFilter = function (column) {\n return this.allColumnFilters.get(column.getColId());\n };\n FilterManager.prototype.createFilterInstance = function (column) {\n var _this = this;\n var defaultFilter = ModuleRegistry.isRegistered(ModuleNames.SetFilterModule) ? 'agSetColumnFilter' : 'agTextColumnFilter';\n var colDef = column.getColDef();\n var filterInstance;\n var params = __assign$7(__assign$7({}, this.createFilterParams(column, colDef)), { filterModifiedCallback: function () {\n var event = {\n type: Events.EVENT_FILTER_MODIFIED,\n column: column,\n filterInstance: filterInstance\n };\n _this.eventService.dispatchEvent(event);\n }, filterChangedCallback: function (additionalEventAttributes) {\n var params = { filterInstance: filterInstance, additionalEventAttributes: additionalEventAttributes, columns: [column] };\n _this.callOnFilterChangedOutsideRenderCycle(params);\n }, doesRowPassOtherFilter: function (node) { return _this.doesRowPassOtherFilters(filterInstance, node); } });\n var compDetails = this.userComponentFactory.getFilterDetails(colDef, params, defaultFilter);\n if (!compDetails) {\n return null;\n }\n var componentPromise = compDetails.newAgStackInstance();\n if (componentPromise) {\n componentPromise.then(function (r) { return filterInstance = r; });\n }\n return componentPromise;\n };\n FilterManager.prototype.createFilterParams = function (column, colDef) {\n var params = {\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n column: column,\n colDef: cloneObject(colDef),\n rowModel: this.rowModel,\n filterChangedCallback: function () { },\n filterModifiedCallback: function () { },\n valueGetter: this.createValueGetter(column),\n context: this.gridOptionsWrapper.getContext(),\n doesRowPassOtherFilter: function () { return true; },\n };\n return params;\n };\n FilterManager.prototype.createFilterWrapper = function (column, source) {\n var filterWrapper = {\n column: column,\n filterPromise: null,\n compiledElement: null,\n guiPromise: AgPromise.resolve(null)\n };\n filterWrapper.filterPromise = this.createFilterInstance(column);\n if (filterWrapper.filterPromise) {\n this.putIntoGui(filterWrapper, source);\n }\n return filterWrapper;\n };\n FilterManager.prototype.putIntoGui = function (filterWrapper, source) {\n var _this = this;\n var eFilterGui = document.createElement('div');\n eFilterGui.className = 'ag-filter';\n filterWrapper.guiPromise = new AgPromise(function (resolve) {\n filterWrapper.filterPromise.then(function (filter) {\n var guiFromFilter = filter.getGui();\n if (!exists(guiFromFilter)) {\n console.warn(\"AG Grid: getGui method from filter returned \" + guiFromFilter + \", it should be a DOM element or an HTML template string.\");\n }\n // for backwards compatibility with Angular 1 - we\n // used to allow providing back HTML from getGui().\n // once we move away from supporting Angular 1\n // directly, we can change this.\n if (typeof guiFromFilter === 'string') {\n guiFromFilter = loadTemplate(guiFromFilter);\n }\n eFilterGui.appendChild(guiFromFilter);\n resolve(eFilterGui);\n var event = {\n type: Events.EVENT_FILTER_OPENED,\n column: filterWrapper.column,\n source: source,\n eGui: eFilterGui\n };\n _this.eventService.dispatchEvent(event);\n });\n });\n };\n FilterManager.prototype.onColumnsChanged = function () {\n var _this = this;\n var columns = [];\n this.allColumnFilters.forEach(function (wrapper, colId) {\n var currentColumn;\n if (wrapper.column.isPrimary()) {\n currentColumn = _this.columnModel.getPrimaryColumn(colId);\n }\n else {\n currentColumn = _this.columnModel.getGridColumn(colId);\n }\n if (currentColumn) {\n return;\n }\n columns.push(wrapper.column);\n _this.disposeFilterWrapper(wrapper, 'filterDestroyed');\n });\n if (columns.length > 0) {\n this.onFilterChanged({ columns: columns });\n }\n };\n // destroys the filter, so it not longer takes part\n FilterManager.prototype.destroyFilter = function (column, source) {\n if (source === void 0) { source = 'api'; }\n var filterWrapper = this.allColumnFilters.get(column.getColId());\n if (filterWrapper) {\n this.disposeFilterWrapper(filterWrapper, source);\n this.onFilterChanged({ columns: [column] });\n }\n };\n FilterManager.prototype.disposeFilterWrapper = function (filterWrapper, source) {\n var _this = this;\n filterWrapper.filterPromise.then(function (filter) {\n (filter.setModel(null) || AgPromise.resolve()).then(function () {\n _this.getContext().destroyBean(filter);\n filterWrapper.column.setFilterActive(false, source);\n _this.allColumnFilters.delete(filterWrapper.column.getColId());\n });\n });\n };\n FilterManager.prototype.destroy = function () {\n var _this = this;\n _super.prototype.destroy.call(this);\n this.allColumnFilters.forEach(function (filterWrapper) { return _this.disposeFilterWrapper(filterWrapper, 'filterDestroyed'); });\n };\n var FilterManager_1;\n FilterManager.QUICK_FILTER_SEPARATOR = '\\n';\n __decorate$1U([\n Autowired('valueService')\n ], FilterManager.prototype, \"valueService\", void 0);\n __decorate$1U([\n Autowired('columnModel')\n ], FilterManager.prototype, \"columnModel\", void 0);\n __decorate$1U([\n Autowired('rowModel')\n ], FilterManager.prototype, \"rowModel\", void 0);\n __decorate$1U([\n Autowired('userComponentFactory')\n ], FilterManager.prototype, \"userComponentFactory\", void 0);\n __decorate$1U([\n Autowired('rowRenderer')\n ], FilterManager.prototype, \"rowRenderer\", void 0);\n __decorate$1U([\n PostConstruct\n ], FilterManager.prototype, \"init\", null);\n __decorate$1U([\n PreDestroy\n ], FilterManager.prototype, \"destroy\", null);\n FilterManager = FilterManager_1 = __decorate$1U([\n Bean('filterManager')\n ], FilterManager);\n return FilterManager;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$25 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AbstractHeaderCellComp = /** @class */ (function (_super) {\n __extends$25(AbstractHeaderCellComp, _super);\n function AbstractHeaderCellComp(template, ctrl) {\n var _this = _super.call(this, template) || this;\n _this.ctrl = ctrl;\n return _this;\n }\n AbstractHeaderCellComp.prototype.getCtrl = function () {\n return this.ctrl;\n };\n return AbstractHeaderCellComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$24 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1T = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderFilterCellComp = /** @class */ (function (_super) {\n __extends$24(HeaderFilterCellComp, _super);\n function HeaderFilterCellComp(ctrl) {\n return _super.call(this, HeaderFilterCellComp.TEMPLATE, ctrl) || this;\n }\n HeaderFilterCellComp.prototype.postConstruct = function () {\n var _this = this;\n var eGui = this.getGui();\n var compProxy = {\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n addOrRemoveBodyCssClass: function (cssClassName, on) { return _this.eFloatingFilterBody.classList.toggle(cssClassName, on); },\n addOrRemoveButtonWrapperCssClass: function (cssClassName, on) { return _this.eButtonWrapper.classList.toggle(cssClassName, on); },\n setCompDetails: function (compDetails) { return _this.setCompDetails(compDetails); },\n getFloatingFilterComp: function () { return _this.compPromise; },\n setWidth: function (width) { return eGui.style.width = width; },\n setMenuIcon: function (eIcon) { return _this.eButtonShowMainFilter.appendChild(eIcon); }\n };\n this.ctrl.setComp(compProxy, eGui, this.eButtonShowMainFilter, this.eFloatingFilterBody);\n };\n HeaderFilterCellComp.prototype.setCompDetails = function (compDetails) {\n var _this = this;\n // because we are providing defaultFloatingFilterType, we know it will never be undefined;\n this.compPromise = compDetails.newAgStackInstance();\n this.compPromise.then(function (comp) { return _this.afterCompCreated(comp); });\n };\n HeaderFilterCellComp.prototype.afterCompCreated = function (comp) {\n var _this = this;\n if (!comp) {\n return;\n }\n this.addDestroyFunc(function () { return _this.context.destroyBean(comp); });\n if (!this.isAlive()) {\n return;\n }\n this.eFloatingFilterBody.appendChild(comp.getGui());\n if (comp.afterGuiAttached) {\n comp.afterGuiAttached();\n }\n };\n HeaderFilterCellComp.TEMPLATE = \"<div class=\\\"ag-header-cell ag-floating-filter\\\" role=\\\"gridcell\\\" tabindex=\\\"-1\\\">\\n <div ref=\\\"eFloatingFilterBody\\\" role=\\\"presentation\\\"></div>\\n <div class=\\\"ag-floating-filter-button ag-hidden\\\" ref=\\\"eButtonWrapper\\\" role=\\\"presentation\\\">\\n <button type=\\\"button\\\" aria-label=\\\"Open Filter Menu\\\" class=\\\"ag-floating-filter-button-button\\\" ref=\\\"eButtonShowMainFilter\\\" tabindex=\\\"-1\\\"></button>\\n </div>\\n </div>\";\n __decorate$1T([\n RefSelector('eFloatingFilterBody')\n ], HeaderFilterCellComp.prototype, \"eFloatingFilterBody\", void 0);\n __decorate$1T([\n RefSelector('eButtonWrapper')\n ], HeaderFilterCellComp.prototype, \"eButtonWrapper\", void 0);\n __decorate$1T([\n RefSelector('eButtonShowMainFilter')\n ], HeaderFilterCellComp.prototype, \"eButtonShowMainFilter\", void 0);\n __decorate$1T([\n PostConstruct\n ], HeaderFilterCellComp.prototype, \"postConstruct\", null);\n return HeaderFilterCellComp;\n}(AbstractHeaderCellComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$23 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1S = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar LayoutCssClasses;\n(function (LayoutCssClasses) {\n LayoutCssClasses[\"AUTO_HEIGHT\"] = \"ag-layout-auto-height\";\n LayoutCssClasses[\"NORMAL\"] = \"ag-layout-normal\";\n LayoutCssClasses[\"PRINT\"] = \"ag-layout-print\";\n})(LayoutCssClasses || (LayoutCssClasses = {}));\nvar LayoutFeature = /** @class */ (function (_super) {\n __extends$23(LayoutFeature, _super);\n function LayoutFeature(view) {\n var _this = _super.call(this) || this;\n _this.view = view;\n return _this;\n }\n LayoutFeature.prototype.postConstruct = function () {\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, this.updateLayoutClasses.bind(this));\n this.updateLayoutClasses();\n };\n LayoutFeature.prototype.updateLayoutClasses = function () {\n var domLayout = this.gridOptionsWrapper.getDomLayout();\n var params = {\n autoHeight: domLayout === Constants.DOM_LAYOUT_AUTO_HEIGHT,\n normal: domLayout === Constants.DOM_LAYOUT_NORMAL,\n print: domLayout === Constants.DOM_LAYOUT_PRINT\n };\n var cssClass = params.autoHeight ? LayoutCssClasses.AUTO_HEIGHT :\n params.print ? LayoutCssClasses.PRINT : LayoutCssClasses.NORMAL;\n this.view.updateLayoutClasses(cssClass, params);\n };\n __decorate$1S([\n Autowired('gridOptionsWrapper')\n ], LayoutFeature.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$1S([\n PostConstruct\n ], LayoutFeature.prototype, \"postConstruct\", null);\n return LayoutFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$22 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1R = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GridBodyScrollFeature = /** @class */ (function (_super) {\n __extends$22(GridBodyScrollFeature, _super);\n function GridBodyScrollFeature(eBodyViewport) {\n var _this = _super.call(this) || this;\n _this.scrollLeft = -1;\n _this.nextScrollTop = -1;\n _this.scrollTop = -1;\n _this.eBodyViewport = eBodyViewport;\n _this.resetLastHorizontalScrollElementDebounced = debounce(_this.resetLastHorizontalScrollElement.bind(_this), 500);\n return _this;\n }\n GridBodyScrollFeature.prototype.postConstruct = function () {\n var _this = this;\n this.enableRtl = this.gridOptionsWrapper.isEnableRtl();\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, this.onDisplayedColumnsWidthChanged.bind(this));\n this.ctrlsService.whenReady(function (p) {\n _this.centerRowContainerCtrl = p.centerRowContainerCtrl;\n _this.onDisplayedColumnsWidthChanged();\n _this.addScrollListener();\n });\n };\n GridBodyScrollFeature.prototype.addScrollListener = function () {\n var fakeHScroll = this.ctrlsService.getFakeHScrollCtrl();\n this.addManagedListener(this.centerRowContainerCtrl.getViewportElement(), 'scroll', this.onCenterViewportScroll.bind(this));\n this.addManagedListener(fakeHScroll.getViewport(), 'scroll', this.onFakeHorizontalScroll.bind(this));\n var onVerticalScroll = this.gridOptionsWrapper.isDebounceVerticalScrollbar() ?\n debounce(this.onVerticalScroll.bind(this), 100)\n : this.onVerticalScroll.bind(this);\n this.addManagedListener(this.eBodyViewport, 'scroll', onVerticalScroll);\n };\n GridBodyScrollFeature.prototype.onDisplayedColumnsWidthChanged = function () {\n if (this.enableRtl) {\n // because RTL is all backwards, a change in the width of the row\n // can cause a change in the scroll position, without a scroll event,\n // because the scroll position in RTL is a function that depends on\n // the width. to be convinced of this, take out this line, enable RTL,\n // scroll all the way to the left and then resize a column\n this.horizontallyScrollHeaderCenterAndFloatingCenter();\n }\n };\n GridBodyScrollFeature.prototype.horizontallyScrollHeaderCenterAndFloatingCenter = function (scrollLeft) {\n // when doing RTL, this method gets called once prematurely\n var notYetInitialised = this.centerRowContainerCtrl == null;\n if (notYetInitialised) {\n return;\n }\n if (scrollLeft === undefined) {\n scrollLeft = this.centerRowContainerCtrl.getCenterViewportScrollLeft();\n }\n var offset = this.enableRtl ? scrollLeft : -scrollLeft;\n var topCenterContainer = this.ctrlsService.getTopCenterRowContainerCtrl();\n var stickyTopCenterContainer = this.ctrlsService.getStickyTopCenterRowContainerCtrl();\n var bottomCenterContainer = this.ctrlsService.getBottomCenterRowContainerCtrl();\n var fakeHScroll = this.ctrlsService.getFakeHScrollCtrl();\n var centerHeaderContainer = this.ctrlsService.getHeaderRowContainerCtrl();\n centerHeaderContainer.setHorizontalScroll(offset);\n bottomCenterContainer.setContainerTranslateX(offset);\n topCenterContainer.setContainerTranslateX(offset);\n stickyTopCenterContainer.setContainerTranslateX(offset);\n var centerViewport = this.centerRowContainerCtrl.getViewportElement();\n var isCenterViewportLastHorizontal = this.lastHorizontalScrollElement === centerViewport;\n var partner = isCenterViewportLastHorizontal ?\n fakeHScroll.getViewport() :\n this.centerRowContainerCtrl.getViewportElement();\n setScrollLeft(partner, Math.abs(scrollLeft), this.enableRtl);\n };\n GridBodyScrollFeature.prototype.isControllingScroll = function (eDiv) {\n if (!this.lastHorizontalScrollElement) {\n this.lastHorizontalScrollElement = eDiv;\n return true;\n }\n return eDiv === this.lastHorizontalScrollElement;\n };\n GridBodyScrollFeature.prototype.onFakeHorizontalScroll = function () {\n var fakeHScrollViewport = this.ctrlsService.getFakeHScrollCtrl().getViewport();\n if (!this.isControllingScroll(fakeHScrollViewport)) {\n return;\n }\n this.onBodyHorizontalScroll(fakeHScrollViewport);\n };\n GridBodyScrollFeature.prototype.onCenterViewportScroll = function () {\n var centerContainerViewport = this.centerRowContainerCtrl.getViewportElement();\n if (!this.isControllingScroll(centerContainerViewport)) {\n return;\n }\n this.onBodyHorizontalScroll(centerContainerViewport);\n };\n GridBodyScrollFeature.prototype.onBodyHorizontalScroll = function (eSource) {\n var centerContainerViewport = this.centerRowContainerCtrl.getViewportElement();\n var scrollLeft = centerContainerViewport.scrollLeft;\n if (this.shouldBlockScrollUpdate('horizontal', scrollLeft, true)) {\n return;\n }\n // we do Math.round() rather than Math.floor(), to mirror how scroll values are applied.\n // eg if a scale is applied (ie user has zoomed the browser), then applying scroll=200\n // could result in 199.88, which then floor(199.88) = 199, however round(199.88) = 200.\n // initially Math.floor() was used, however this caused (almost) infinite loop with aligned grids,\n // as the scroll would move 1px at at time bouncing from one grid to the next (eg one grid would cause\n // scroll to 200px, the next to 199px, then the first back to 198px and so on).\n this.doHorizontalScroll(Math.round(getScrollLeft(eSource, this.enableRtl)));\n this.resetLastHorizontalScrollElementDebounced();\n };\n GridBodyScrollFeature.prototype.onVerticalScroll = function () {\n var scrollTop = this.eBodyViewport.scrollTop;\n if (this.shouldBlockScrollUpdate('vertical', scrollTop, true)) {\n return;\n }\n this.animationFrameService.setScrollTop(scrollTop);\n this.nextScrollTop = scrollTop;\n if (this.gridOptionsWrapper.isSuppressAnimationFrame()) {\n this.scrollTop = this.nextScrollTop;\n this.redrawRowsAfterScroll();\n }\n else {\n this.animationFrameService.schedule();\n }\n };\n GridBodyScrollFeature.prototype.resetLastHorizontalScrollElement = function () {\n this.lastHorizontalScrollElement = null;\n };\n GridBodyScrollFeature.prototype.doHorizontalScroll = function (scrollLeft) {\n var fakeHScrollViewport = this.ctrlsService.getFakeHScrollCtrl().getViewport();\n var fakeScrollLeft = getScrollLeft(fakeHScrollViewport, this.enableRtl);\n if (this.scrollLeft === scrollLeft && scrollLeft === fakeScrollLeft) {\n return;\n }\n this.scrollLeft = scrollLeft;\n this.fireScrollEvent('horizontal');\n this.horizontallyScrollHeaderCenterAndFloatingCenter(scrollLeft);\n this.onHorizontalViewportChanged();\n };\n GridBodyScrollFeature.prototype.fireScrollEvent = function (direction) {\n var _this = this;\n var bodyScrollEvent = {\n type: Events.EVENT_BODY_SCROLL,\n direction: direction,\n left: this.scrollLeft,\n top: this.scrollTop\n };\n this.eventService.dispatchEvent(bodyScrollEvent);\n window.clearTimeout(this.scrollTimer);\n this.scrollTimer = undefined;\n this.scrollTimer = window.setTimeout(function () {\n var bodyScrollEndEvent = Object.assign({}, bodyScrollEvent, {\n type: Events.EVENT_BODY_SCROLL_END\n });\n _this.eventService.dispatchEvent(bodyScrollEndEvent);\n }, 100);\n };\n GridBodyScrollFeature.prototype.shouldBlockScrollUpdate = function (direction, scrollTo, touchOnly) {\n // touch devices allow elastic scroll - which temporally scrolls the panel outside of the viewport\n // (eg user uses touch to go to the left of the grid, but drags past the left, the rows will actually\n // scroll past the left until the user releases the mouse). when this happens, we want ignore the scroll,\n // as otherwise it was causing the rows and header to flicker.\n if (touchOnly === void 0) { touchOnly = false; }\n // sometimes when scrolling, we got values that extended the maximum scroll allowed. we used to\n // ignore these scrolls. problem is the max scroll position could be skipped (eg the previous scroll event\n // could be 10px before the max position, and then current scroll event could be 20px after the max position).\n // if we just ignored the last event, we would be setting the scroll to 10px before the max position, when in\n // actual fact the user has exceeded the max scroll and thus scroll should be set to the max.\n if (touchOnly && !isIOSUserAgent()) {\n return false;\n }\n if (direction === 'vertical') {\n var clientHeight = getInnerHeight(this.eBodyViewport);\n var scrollHeight = this.eBodyViewport.scrollHeight;\n if (scrollTo < 0 || (scrollTo + clientHeight > scrollHeight)) {\n return true;\n }\n }\n if (direction === 'horizontal') {\n var clientWidth = this.centerRowContainerCtrl.getCenterWidth();\n var scrollWidth = this.centerRowContainerCtrl.getViewportElement().scrollWidth;\n if (this.enableRtl && isRtlNegativeScroll()) {\n if (scrollTo > 0) {\n return true;\n }\n }\n else if (scrollTo < 0) {\n return true;\n }\n if (Math.abs(scrollTo) + clientWidth > scrollWidth) {\n return true;\n }\n }\n return false;\n };\n GridBodyScrollFeature.prototype.redrawRowsAfterScroll = function () {\n this.fireScrollEvent('vertical');\n };\n GridBodyScrollFeature.prototype.onHorizontalViewportChanged = function () {\n this.centerRowContainerCtrl.onHorizontalViewportChanged();\n };\n // this is to cater for AG-3274, where grid is removed from the dom and then inserted back in again.\n // (which happens with some implementations of tabbing). this can result in horizontal scroll getting\n // reset back to the left, however no scroll event is fired. so we need to get header to also scroll\n // back to the left to be kept in sync.\n // adding and removing the grid from the DOM both resets the scroll position and\n // triggers a resize event, so notify listeners if the scroll position has changed\n GridBodyScrollFeature.prototype.checkScrollLeft = function () {\n if (this.scrollLeft !== this.centerRowContainerCtrl.getCenterViewportScrollLeft()) {\n this.onBodyHorizontalScroll(this.centerRowContainerCtrl.getViewportElement());\n }\n };\n GridBodyScrollFeature.prototype.executeAnimationFrameScroll = function () {\n var frameNeeded = this.scrollTop != this.nextScrollTop;\n if (frameNeeded) {\n this.scrollTop = this.nextScrollTop;\n this.redrawRowsAfterScroll();\n }\n return frameNeeded;\n };\n // called by scrollHorizontally method and alignedGridsService\n GridBodyScrollFeature.prototype.setHorizontalScrollPosition = function (hScrollPosition) {\n var minScrollLeft = 0;\n var maxScrollLeft = this.centerRowContainerCtrl.getViewportElement().scrollWidth - this.centerRowContainerCtrl.getCenterWidth();\n if (this.shouldBlockScrollUpdate('horizontal', hScrollPosition)) {\n if (this.enableRtl && isRtlNegativeScroll()) {\n hScrollPosition = hScrollPosition > 0 ? 0 : maxScrollLeft;\n }\n else {\n hScrollPosition = Math.min(Math.max(hScrollPosition, minScrollLeft), maxScrollLeft);\n }\n }\n setScrollLeft(this.centerRowContainerCtrl.getViewportElement(), Math.abs(hScrollPosition), this.enableRtl);\n // we need to manually do the event handling (rather than wait for the event)\n // for the alignedGridsService, as if we don't, the aligned grid service gets\n // notified async, and then it's 'consuming' flag doesn't get used right, and\n // we can end up with an infinite loop\n this.doHorizontalScroll(hScrollPosition);\n };\n GridBodyScrollFeature.prototype.setVerticalScrollPosition = function (vScrollPosition) {\n this.eBodyViewport.scrollTop = vScrollPosition;\n };\n GridBodyScrollFeature.prototype.getVScrollPosition = function () {\n var result = {\n top: this.eBodyViewport.scrollTop,\n bottom: this.eBodyViewport.scrollTop + this.eBodyViewport.offsetHeight\n };\n return result;\n };\n GridBodyScrollFeature.prototype.getHScrollPosition = function () {\n return this.centerRowContainerCtrl.getHScrollPosition();\n };\n GridBodyScrollFeature.prototype.isHorizontalScrollShowing = function () {\n return this.centerRowContainerCtrl.isHorizontalScrollShowing();\n };\n // called by the headerRootComp and moveColumnController\n GridBodyScrollFeature.prototype.scrollHorizontally = function (pixels) {\n var oldScrollPosition = this.centerRowContainerCtrl.getViewportElement().scrollLeft;\n this.setHorizontalScrollPosition(oldScrollPosition + pixels);\n return this.centerRowContainerCtrl.getViewportElement().scrollLeft - oldScrollPosition;\n };\n // gets called by rowRenderer when new data loaded, as it will want to scroll to the top\n GridBodyScrollFeature.prototype.scrollToTop = function () {\n this.eBodyViewport.scrollTop = 0;\n };\n // Valid values for position are bottom, middle and top\n GridBodyScrollFeature.prototype.ensureNodeVisible = function (comparator, position) {\n if (position === void 0) { position = null; }\n // look for the node index we want to display\n var rowCount = this.rowModel.getRowCount();\n var indexToSelect = -1;\n // go through all the nodes, find the one we want to show\n for (var i = 0; i < rowCount; i++) {\n var node = this.rowModel.getRow(i);\n if (typeof comparator === 'function') {\n // Have to assert type here, as type could be TData & Function\n var predicate = comparator;\n if (node && predicate(node)) {\n indexToSelect = i;\n break;\n }\n }\n else {\n // check object equality against node and data\n if (comparator === node || comparator === node.data) {\n indexToSelect = i;\n break;\n }\n }\n }\n if (indexToSelect >= 0) {\n this.ensureIndexVisible(indexToSelect, position);\n }\n };\n // Valid values for position are bottom, middle and top\n // position should be {'top','middle','bottom', or undefined/null}.\n // if undefined/null, then the grid will to the minimal amount of scrolling,\n // eg if grid needs to scroll up, it scrolls until row is on top,\n // if grid needs to scroll down, it scrolls until row is on bottom,\n // if row is already in view, grid does not scroll\n GridBodyScrollFeature.prototype.ensureIndexVisible = function (index, position) {\n // if for print or auto height, everything is always visible\n if (this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT) {\n return;\n }\n var rowCount = this.paginationProxy.getRowCount();\n if (typeof index !== 'number' || index < 0 || index >= rowCount) {\n console.warn('invalid row index for ensureIndexVisible: ' + index);\n return;\n }\n var isPaging = this.gridOptionsWrapper.isPagination();\n var paginationPanelEnabled = isPaging && !this.gridOptionsWrapper.isSuppressPaginationPanel();\n if (!paginationPanelEnabled) {\n this.paginationProxy.goToPageWithIndex(index);\n }\n var gridBodyCtrl = this.ctrlsService.getGridBodyCtrl();\n var stickyTopHeight = gridBodyCtrl.getStickyTopHeight();\n var rowNode = this.paginationProxy.getRow(index);\n var rowGotShiftedDuringOperation;\n do {\n var startingRowTop = rowNode.rowTop;\n var startingRowHeight = rowNode.rowHeight;\n var paginationOffset = this.paginationProxy.getPixelOffset();\n var rowTopPixel = rowNode.rowTop - paginationOffset;\n var rowBottomPixel = rowTopPixel + rowNode.rowHeight;\n var scrollPosition = this.getVScrollPosition();\n var heightOffset = this.heightScaler.getDivStretchOffset();\n var vScrollTop = scrollPosition.top + heightOffset;\n var vScrollBottom = scrollPosition.bottom + heightOffset;\n var viewportHeight = vScrollBottom - vScrollTop;\n // work out the pixels for top, middle and bottom up front,\n // make the if/else below easier to read\n var pxTop = this.heightScaler.getScrollPositionForPixel(rowTopPixel);\n var pxBottom = this.heightScaler.getScrollPositionForPixel(rowBottomPixel - viewportHeight);\n // make sure if middle, the row is not outside the top of the grid\n var pxMiddle = Math.min((pxTop + pxBottom) / 2, rowTopPixel);\n var rowAboveViewport = (vScrollTop + stickyTopHeight) > rowTopPixel;\n var rowBelowViewport = vScrollBottom < rowBottomPixel;\n var newScrollPosition = null;\n if (position === 'top') {\n newScrollPosition = pxTop;\n }\n else if (position === 'bottom') {\n newScrollPosition = pxBottom;\n }\n else if (position === 'middle') {\n newScrollPosition = pxMiddle;\n }\n else if (rowAboveViewport) {\n // if row is before, scroll up with row at top\n newScrollPosition = pxTop - stickyTopHeight;\n }\n else if (rowBelowViewport) {\n // if row is after, scroll down with row at bottom\n newScrollPosition = pxBottom;\n }\n if (newScrollPosition !== null) {\n this.eBodyViewport.scrollTop = newScrollPosition;\n this.rowRenderer.redrawAfterScroll();\n }\n // the row can get shifted if during the rendering (during rowRenderer.redrawAfterScroll()),\n // the height of a row changes due to lazy calculation of row heights when using\n // colDef.autoHeight or gridOptions.getRowHeight.\n // if row was shifted, then the position we scrolled to is incorrect.\n rowGotShiftedDuringOperation = (startingRowTop !== rowNode.rowTop)\n || (startingRowHeight !== rowNode.rowHeight);\n } while (rowGotShiftedDuringOperation);\n // so when we return back to user, the cells have rendered\n this.animationFrameService.flushAllFrames();\n };\n GridBodyScrollFeature.prototype.ensureColumnVisible = function (key, position) {\n if (position === void 0) { position = 'auto'; }\n var column = this.columnModel.getGridColumn(key);\n if (!column) {\n return;\n }\n // calling ensureColumnVisible on a pinned column doesn't make sense\n if (column.isPinned()) {\n return;\n }\n // defensive\n if (!this.columnModel.isColumnDisplayed(column)) {\n return;\n }\n var newHorizontalScroll = this.getPositionedHorizontalScroll(column, position);\n if (newHorizontalScroll !== null) {\n this.centerRowContainerCtrl.setCenterViewportScrollLeft(newHorizontalScroll);\n }\n // this will happen anyway, as the move will cause a 'scroll' event on the body, however\n // it is possible that the ensureColumnVisible method is called from within AG Grid and\n // the caller will need to have the columns rendered to continue, which will be before\n // the event has been worked on (which is the case for cell navigation).\n this.centerRowContainerCtrl.onHorizontalViewportChanged();\n // so when we return back to user, the cells have rendered\n this.animationFrameService.flushAllFrames();\n };\n GridBodyScrollFeature.prototype.getPositionedHorizontalScroll = function (column, position) {\n var _a = this.isColumnOutsideViewport(column), columnBeforeStart = _a.columnBeforeStart, columnAfterEnd = _a.columnAfterEnd;\n var viewportTooSmallForColumn = this.centerRowContainerCtrl.getCenterWidth() < column.getActualWidth();\n var viewportWidth = this.centerRowContainerCtrl.getCenterWidth();\n var isRtl = this.enableRtl;\n var alignColToStart = (isRtl ? columnBeforeStart : columnAfterEnd) || viewportTooSmallForColumn;\n var alignColToEnd = isRtl ? columnAfterEnd : columnBeforeStart;\n if (position !== 'auto') {\n alignColToStart = position === 'start';\n alignColToEnd = position === 'end';\n }\n var isMiddle = position === 'middle';\n if (alignColToStart || alignColToEnd || isMiddle) {\n var _b = this.getColumnBounds(column), colLeft = _b.colLeft, colMiddle = _b.colMiddle, colRight = _b.colRight;\n if (isMiddle) {\n return colMiddle - viewportWidth / 2;\n }\n if (alignColToStart) {\n return isRtl ? colRight : colLeft;\n }\n return isRtl ? (colLeft - viewportWidth) : (colRight - viewportWidth);\n }\n return null;\n };\n GridBodyScrollFeature.prototype.isColumnOutsideViewport = function (column) {\n var _a = this.getViewportBounds(), viewportStart = _a.start, viewportEnd = _a.end;\n var _b = this.getColumnBounds(column), colLeft = _b.colLeft, colRight = _b.colRight;\n var isRtl = this.enableRtl;\n var columnBeforeStart = isRtl ? (viewportStart > colRight) : (viewportEnd < colRight);\n var columnAfterEnd = isRtl ? (viewportEnd < colLeft) : (viewportStart > colLeft);\n return { columnBeforeStart: columnBeforeStart, columnAfterEnd: columnAfterEnd };\n };\n GridBodyScrollFeature.prototype.getColumnBounds = function (column) {\n var isRtl = this.enableRtl;\n var bodyWidth = this.columnModel.getBodyContainerWidth();\n var colWidth = column.getActualWidth();\n var colLeft = column.getLeft();\n var multiplier = isRtl ? -1 : 1;\n var colLeftPixel = isRtl ? (bodyWidth - colLeft) : colLeft;\n var colRightPixel = colLeftPixel + colWidth * multiplier;\n var colMidPixel = colLeftPixel + colWidth / 2 * multiplier;\n return { colLeft: colLeftPixel, colMiddle: colMidPixel, colRight: colRightPixel };\n };\n GridBodyScrollFeature.prototype.getViewportBounds = function () {\n var viewportWidth = this.centerRowContainerCtrl.getCenterWidth();\n var scrollPosition = this.centerRowContainerCtrl.getCenterViewportScrollLeft();\n var viewportStartPixel = scrollPosition;\n var viewportEndPixel = viewportWidth + scrollPosition;\n return { start: viewportStartPixel, end: viewportEndPixel, width: viewportWidth };\n };\n __decorate$1R([\n Autowired('ctrlsService')\n ], GridBodyScrollFeature.prototype, \"ctrlsService\", void 0);\n __decorate$1R([\n Autowired('animationFrameService')\n ], GridBodyScrollFeature.prototype, \"animationFrameService\", void 0);\n __decorate$1R([\n Autowired('paginationProxy')\n ], GridBodyScrollFeature.prototype, \"paginationProxy\", void 0);\n __decorate$1R([\n Autowired('rowModel')\n ], GridBodyScrollFeature.prototype, \"rowModel\", void 0);\n __decorate$1R([\n Autowired('rowContainerHeightService')\n ], GridBodyScrollFeature.prototype, \"heightScaler\", void 0);\n __decorate$1R([\n Autowired('rowRenderer')\n ], GridBodyScrollFeature.prototype, \"rowRenderer\", void 0);\n __decorate$1R([\n Autowired('columnModel')\n ], GridBodyScrollFeature.prototype, \"columnModel\", void 0);\n __decorate$1R([\n PostConstruct\n ], GridBodyScrollFeature.prototype, \"postConstruct\", null);\n return GridBodyScrollFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar AutoScrollService = /** @class */ (function () {\n function AutoScrollService(params) {\n this.tickingInterval = null;\n this.onScrollCallback = null;\n this.scrollContainer = params.scrollContainer;\n this.scrollHorizontally = params.scrollAxis.indexOf('x') !== -1;\n this.scrollVertically = params.scrollAxis.indexOf('y') !== -1;\n this.scrollByTick = params.scrollByTick != null ? params.scrollByTick : 20;\n if (params.onScrollCallback) {\n this.onScrollCallback = params.onScrollCallback;\n }\n if (this.scrollVertically) {\n this.getVerticalPosition = params.getVerticalPosition;\n this.setVerticalPosition = params.setVerticalPosition;\n }\n if (this.scrollHorizontally) {\n this.getHorizontalPosition = params.getHorizontalPosition;\n this.setHorizontalPosition = params.setHorizontalPosition;\n }\n this.shouldSkipVerticalScroll = params.shouldSkipVerticalScroll || (function () { return false; });\n this.shouldSkipHorizontalScroll = params.shouldSkipHorizontalScroll || (function () { return false; });\n }\n AutoScrollService.prototype.check = function (mouseEvent, forceSkipVerticalScroll) {\n if (forceSkipVerticalScroll === void 0) { forceSkipVerticalScroll = false; }\n var skipVerticalScroll = forceSkipVerticalScroll || this.shouldSkipVerticalScroll();\n if (skipVerticalScroll && this.shouldSkipHorizontalScroll()) {\n return;\n }\n var rect = this.scrollContainer.getBoundingClientRect();\n var scrollTick = this.scrollByTick;\n this.tickLeft = mouseEvent.clientX < (rect.left + scrollTick);\n this.tickRight = mouseEvent.clientX > (rect.right - scrollTick);\n this.tickUp = mouseEvent.clientY < (rect.top + scrollTick) && !skipVerticalScroll;\n this.tickDown = mouseEvent.clientY > (rect.bottom - scrollTick) && !skipVerticalScroll;\n if (this.tickLeft || this.tickRight || this.tickUp || this.tickDown) {\n this.ensureTickingStarted();\n }\n else {\n this.ensureCleared();\n }\n };\n AutoScrollService.prototype.ensureTickingStarted = function () {\n if (this.tickingInterval === null) {\n this.tickingInterval = window.setInterval(this.doTick.bind(this), 100);\n this.tickCount = 0;\n }\n };\n AutoScrollService.prototype.doTick = function () {\n this.tickCount++;\n var tickAmount;\n tickAmount = this.tickCount > 20 ? 200 : (this.tickCount > 10 ? 80 : 40);\n if (this.scrollVertically) {\n var vScrollPosition = this.getVerticalPosition();\n if (this.tickUp) {\n this.setVerticalPosition(vScrollPosition - tickAmount);\n }\n if (this.tickDown) {\n this.setVerticalPosition(vScrollPosition + tickAmount);\n }\n }\n if (this.scrollHorizontally) {\n var hScrollPosition = this.getHorizontalPosition();\n if (this.tickLeft) {\n this.setHorizontalPosition(hScrollPosition - tickAmount);\n }\n if (this.tickRight) {\n this.setHorizontalPosition(hScrollPosition + tickAmount);\n }\n }\n if (this.onScrollCallback) {\n this.onScrollCallback();\n }\n };\n AutoScrollService.prototype.ensureCleared = function () {\n if (this.tickingInterval) {\n window.clearInterval(this.tickingInterval);\n this.tickingInterval = null;\n }\n };\n return AutoScrollService;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$21 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$6 = (undefined && undefined.__assign) || function () {\n __assign$6 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$6.apply(this, arguments);\n};\nvar __decorate$1Q = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$i = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$e = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$i(arguments[i]));\n return ar;\n};\nvar RowDragFeature = /** @class */ (function (_super) {\n __extends$21(RowDragFeature, _super);\n function RowDragFeature(eContainer) {\n var _this = _super.call(this) || this;\n _this.isMultiRowDrag = false;\n _this.isGridSorted = false;\n _this.isGridFiltered = false;\n _this.isRowGroupActive = false;\n _this.eContainer = eContainer;\n return _this;\n }\n RowDragFeature.prototype.postConstruct = function () {\n var _this = this;\n if (this.gridOptionsWrapper.isRowModelDefault()) {\n this.clientSideRowModel = this.rowModel;\n }\n var refreshStatus = function () {\n _this.onSortChanged();\n _this.onFilterChanged();\n _this.onRowGroupChanged();\n };\n this.addManagedListener(this.eventService, Events.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.onRowGroupChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_MODEL_UPDATED, function () {\n refreshStatus();\n });\n refreshStatus();\n this.ctrlsService.whenReady(function () {\n var gridBodyCon = _this.ctrlsService.getGridBodyCtrl();\n _this.autoScrollService = new AutoScrollService({\n scrollContainer: gridBodyCon.getBodyViewportElement(),\n scrollAxis: 'y',\n getVerticalPosition: function () { return gridBodyCon.getScrollFeature().getVScrollPosition().top; },\n setVerticalPosition: function (position) { return gridBodyCon.getScrollFeature().setVerticalScrollPosition(position); },\n onScrollCallback: function () { _this.onDragging(_this.lastDraggingEvent); }\n });\n });\n };\n RowDragFeature.prototype.onSortChanged = function () {\n this.isGridSorted = this.sortController.isSortActive();\n };\n RowDragFeature.prototype.onFilterChanged = function () {\n this.isGridFiltered = this.filterManager.isAnyFilterPresent();\n };\n RowDragFeature.prototype.onRowGroupChanged = function () {\n var rowGroups = this.columnModel.getRowGroupColumns();\n this.isRowGroupActive = !missingOrEmpty(rowGroups);\n };\n RowDragFeature.prototype.getContainer = function () {\n return this.eContainer;\n };\n RowDragFeature.prototype.isInterestedIn = function (type) {\n return type === DragSourceType.RowDrag;\n };\n RowDragFeature.prototype.getIconName = function () {\n var managedDrag = this.gridOptionsWrapper.isRowDragManaged();\n if (managedDrag && this.shouldPreventRowMove()) {\n return DragAndDropService.ICON_NOT_ALLOWED;\n }\n return DragAndDropService.ICON_MOVE;\n };\n RowDragFeature.prototype.shouldPreventRowMove = function () {\n return this.isGridSorted || this.isGridFiltered || this.isRowGroupActive;\n };\n RowDragFeature.prototype.getRowNodes = function (draggingEvent) {\n var _this = this;\n if (!this.isFromThisGrid(draggingEvent)) {\n return draggingEvent.dragItem.rowNodes || [];\n }\n var isRowDragMultiRow = this.gridOptionsWrapper.isRowDragMultiRow();\n var selectedNodes = __spread$e(this.selectionService.getSelectedNodes()).sort(function (a, b) {\n if (a.rowIndex == null || b.rowIndex == null) {\n return 0;\n }\n return _this.getRowIndexNumber(a) - _this.getRowIndexNumber(b);\n });\n var currentNode = draggingEvent.dragItem.rowNode;\n if (isRowDragMultiRow && selectedNodes.indexOf(currentNode) !== -1) {\n this.isMultiRowDrag = true;\n return selectedNodes;\n }\n this.isMultiRowDrag = false;\n return [currentNode];\n };\n RowDragFeature.prototype.onDragEnter = function (draggingEvent) {\n // builds a lits of all rows being dragged before firing events\n draggingEvent.dragItem.rowNodes = this.getRowNodes(draggingEvent);\n // when entering, we fire the enter event, then in onEnterOrDragging,\n // we also fire the move event. so we get both events when entering.\n this.dispatchGridEvent(Events.EVENT_ROW_DRAG_ENTER, draggingEvent);\n this.getRowNodes(draggingEvent).forEach(function (rowNode) {\n rowNode.setDragging(true);\n });\n this.onEnterOrDragging(draggingEvent);\n };\n RowDragFeature.prototype.onDragging = function (draggingEvent) {\n this.onEnterOrDragging(draggingEvent);\n };\n RowDragFeature.prototype.isFromThisGrid = function (draggingEvent) {\n var dragSourceDomDataKey = draggingEvent.dragSource.dragSourceDomDataKey;\n return dragSourceDomDataKey === this.gridOptionsWrapper.getDomDataKey();\n };\n RowDragFeature.prototype.isDropZoneWithinThisGrid = function (draggingEvent) {\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var gridGui = gridBodyCon.getGui();\n var dropZoneTarget = draggingEvent.dropZoneTarget;\n return !gridGui.contains(dropZoneTarget);\n };\n RowDragFeature.prototype.onEnterOrDragging = function (draggingEvent) {\n // this event is fired for enter and move\n this.dispatchGridEvent(Events.EVENT_ROW_DRAG_MOVE, draggingEvent);\n this.lastDraggingEvent = draggingEvent;\n var pixel = this.mouseEventService.getNormalisedPosition(draggingEvent).y;\n var managedDrag = this.gridOptionsWrapper.isRowDragManaged();\n if (managedDrag) {\n this.doManagedDrag(draggingEvent, pixel);\n }\n this.autoScrollService.check(draggingEvent.event);\n };\n RowDragFeature.prototype.doManagedDrag = function (draggingEvent, pixel) {\n var isFromThisGrid = this.isFromThisGrid(draggingEvent);\n var managedDrag = this.gridOptionsWrapper.isRowDragManaged();\n var rowNodes = draggingEvent.dragItem.rowNodes;\n if (managedDrag && this.shouldPreventRowMove()) {\n return;\n }\n if (this.gridOptionsWrapper.isSuppressMoveWhenRowDragging() || !isFromThisGrid) {\n if (!this.isDropZoneWithinThisGrid(draggingEvent)) {\n this.clientSideRowModel.highlightRowAtPixel(rowNodes[0], pixel);\n }\n }\n else {\n this.moveRows(rowNodes, pixel);\n }\n };\n RowDragFeature.prototype.getRowIndexNumber = function (rowNode) {\n return parseInt(last(rowNode.getRowIndexString().split('-')), 10);\n };\n RowDragFeature.prototype.moveRowAndClearHighlight = function (draggingEvent) {\n var _this = this;\n var lastHighlightedRowNode = this.clientSideRowModel.getLastHighlightedRowNode();\n var isBelow = lastHighlightedRowNode && lastHighlightedRowNode.highlighted === RowHighlightPosition.Below;\n var pixel = this.mouseEventService.getNormalisedPosition(draggingEvent).y;\n var rowNodes = draggingEvent.dragItem.rowNodes;\n var increment = isBelow ? 1 : 0;\n if (this.isFromThisGrid(draggingEvent)) {\n rowNodes.forEach(function (rowNode) {\n if (rowNode.rowTop < pixel) {\n increment -= 1;\n }\n });\n this.moveRows(rowNodes, pixel, increment);\n }\n else {\n var getRowIdFunc_1 = this.gridOptionsWrapper.getRowIdFunc();\n var addIndex = this.clientSideRowModel.getRowIndexAtPixel(pixel) + 1;\n if (this.clientSideRowModel.getHighlightPosition(pixel) === RowHighlightPosition.Above) {\n addIndex--;\n }\n this.clientSideRowModel.updateRowData({\n add: rowNodes\n .map(function (node) { return node.data; })\n .filter(function (data) { return !_this.clientSideRowModel.getRowNode(getRowIdFunc_1 ? getRowIdFunc_1({ data: data, level: 0 }) : data.id); }),\n addIndex: addIndex\n });\n }\n this.clearRowHighlight();\n };\n RowDragFeature.prototype.clearRowHighlight = function () {\n this.clientSideRowModel.highlightRowAtPixel(null);\n };\n RowDragFeature.prototype.moveRows = function (rowNodes, pixel, increment) {\n if (increment === void 0) { increment = 0; }\n var rowWasMoved = this.clientSideRowModel.ensureRowsAtPixel(rowNodes, pixel, increment);\n if (rowWasMoved) {\n this.focusService.clearFocusedCell();\n if (this.rangeService) {\n this.rangeService.removeAllCellRanges();\n }\n }\n };\n RowDragFeature.prototype.addRowDropZone = function (params) {\n var _this = this;\n if (!params.getContainer()) {\n doOnce(function () { return console.warn('AG Grid: addRowDropZone - A container target needs to be provided'); }, 'add-drop-zone-empty-target');\n return;\n }\n if (this.dragAndDropService.findExternalZone(params)) {\n console.warn('AG Grid: addRowDropZone - target already exists in the list of DropZones. Use `removeRowDropZone` before adding it again.');\n return;\n }\n var processedParams = {\n getContainer: params.getContainer\n };\n if (params.fromGrid) {\n params.fromGrid = undefined;\n processedParams = params;\n }\n else {\n if (params.onDragEnter) {\n processedParams.onDragEnter = function (e) {\n params.onDragEnter(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_ENTER, e));\n };\n }\n if (params.onDragLeave) {\n processedParams.onDragLeave = function (e) {\n params.onDragLeave(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_LEAVE, e));\n };\n }\n if (params.onDragging) {\n processedParams.onDragging = function (e) {\n params.onDragging(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_MOVE, e));\n };\n }\n if (params.onDragStop) {\n processedParams.onDragStop = function (e) {\n params.onDragStop(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_END, e));\n };\n }\n }\n this.dragAndDropService.addDropTarget(__assign$6({ isInterestedIn: function (type) { return type === DragSourceType.RowDrag; }, getIconName: function () { return DragAndDropService.ICON_MOVE; }, external: true }, processedParams));\n };\n RowDragFeature.prototype.getRowDropZone = function (events) {\n var _this = this;\n var getContainer = this.getContainer.bind(this);\n var onDragEnter = this.onDragEnter.bind(this);\n var onDragLeave = this.onDragLeave.bind(this);\n var onDragging = this.onDragging.bind(this);\n var onDragStop = this.onDragStop.bind(this);\n if (!events) {\n return { getContainer: getContainer, onDragEnter: onDragEnter, onDragLeave: onDragLeave, onDragging: onDragging, onDragStop: onDragStop, /* @private */ fromGrid: true };\n }\n return {\n getContainer: getContainer,\n onDragEnter: events.onDragEnter\n ? (function (e) {\n onDragEnter(e);\n events.onDragEnter(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_ENTER, e));\n })\n : onDragEnter,\n onDragLeave: events.onDragLeave\n ? (function (e) {\n onDragLeave(e);\n events.onDragLeave(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_LEAVE, e));\n })\n : onDragLeave,\n onDragging: events.onDragging\n ? (function (e) {\n onDragging(e);\n events.onDragging(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_MOVE, e));\n })\n : onDragging,\n onDragStop: events.onDragStop\n ? (function (e) {\n onDragStop(e);\n events.onDragStop(_this.draggingToRowDragEvent(Events.EVENT_ROW_DRAG_END, e));\n })\n : onDragStop,\n fromGrid: true /* @private */\n };\n };\n RowDragFeature.prototype.draggingToRowDragEvent = function (type, draggingEvent) {\n var yNormalised = this.mouseEventService.getNormalisedPosition(draggingEvent).y;\n var mouseIsPastLastRow = yNormalised > this.paginationProxy.getCurrentPageHeight();\n var overIndex = -1;\n var overNode;\n if (!mouseIsPastLastRow) {\n overIndex = this.rowModel.getRowIndexAtPixel(yNormalised);\n overNode = this.rowModel.getRow(overIndex);\n }\n var vDirectionString;\n switch (draggingEvent.vDirection) {\n case VerticalDirection.Down:\n vDirectionString = 'down';\n break;\n case VerticalDirection.Up:\n vDirectionString = 'up';\n break;\n default:\n vDirectionString = null;\n break;\n }\n var event = {\n type: type,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext(),\n event: draggingEvent.event,\n node: draggingEvent.dragItem.rowNode,\n nodes: draggingEvent.dragItem.rowNodes,\n overIndex: overIndex,\n overNode: overNode,\n y: yNormalised,\n vDirection: vDirectionString\n };\n return event;\n };\n RowDragFeature.prototype.dispatchGridEvent = function (type, draggingEvent) {\n var event = this.draggingToRowDragEvent(type, draggingEvent);\n this.eventService.dispatchEvent(event);\n };\n RowDragFeature.prototype.onDragLeave = function (draggingEvent) {\n this.dispatchGridEvent(Events.EVENT_ROW_DRAG_LEAVE, draggingEvent);\n this.stopDragging(draggingEvent);\n if (this.gridOptionsWrapper.isRowDragManaged()) {\n this.clearRowHighlight();\n }\n if (this.isFromThisGrid(draggingEvent)) {\n this.isMultiRowDrag = false;\n }\n };\n RowDragFeature.prototype.onDragStop = function (draggingEvent) {\n this.dispatchGridEvent(Events.EVENT_ROW_DRAG_END, draggingEvent);\n this.stopDragging(draggingEvent);\n if (this.gridOptionsWrapper.isRowDragManaged() &&\n (this.gridOptionsWrapper.isSuppressMoveWhenRowDragging() || !this.isFromThisGrid(draggingEvent)) &&\n !this.isDropZoneWithinThisGrid(draggingEvent)) {\n this.moveRowAndClearHighlight(draggingEvent);\n }\n };\n RowDragFeature.prototype.stopDragging = function (draggingEvent) {\n this.autoScrollService.ensureCleared();\n this.getRowNodes(draggingEvent).forEach(function (rowNode) {\n rowNode.setDragging(false);\n });\n };\n __decorate$1Q([\n Autowired('dragAndDropService')\n ], RowDragFeature.prototype, \"dragAndDropService\", void 0);\n __decorate$1Q([\n Autowired('rowModel')\n ], RowDragFeature.prototype, \"rowModel\", void 0);\n __decorate$1Q([\n Autowired('paginationProxy')\n ], RowDragFeature.prototype, \"paginationProxy\", void 0);\n __decorate$1Q([\n Autowired('columnModel')\n ], RowDragFeature.prototype, \"columnModel\", void 0);\n __decorate$1Q([\n Autowired('focusService')\n ], RowDragFeature.prototype, \"focusService\", void 0);\n __decorate$1Q([\n Autowired('sortController')\n ], RowDragFeature.prototype, \"sortController\", void 0);\n __decorate$1Q([\n Autowired('filterManager')\n ], RowDragFeature.prototype, \"filterManager\", void 0);\n __decorate$1Q([\n Autowired('selectionService')\n ], RowDragFeature.prototype, \"selectionService\", void 0);\n __decorate$1Q([\n Autowired('mouseEventService')\n ], RowDragFeature.prototype, \"mouseEventService\", void 0);\n __decorate$1Q([\n Autowired('ctrlsService')\n ], RowDragFeature.prototype, \"ctrlsService\", void 0);\n __decorate$1Q([\n Optional('rangeService')\n ], RowDragFeature.prototype, \"rangeService\", void 0);\n __decorate$1Q([\n PostConstruct\n ], RowDragFeature.prototype, \"postConstruct\", null);\n return RowDragFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$20 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1P = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RowAnimationCssClasses;\n(function (RowAnimationCssClasses) {\n RowAnimationCssClasses[\"ANIMATION_ON\"] = \"ag-row-animation\";\n RowAnimationCssClasses[\"ANIMATION_OFF\"] = \"ag-row-no-animation\";\n})(RowAnimationCssClasses || (RowAnimationCssClasses = {}));\nvar CSS_CLASS_CELL_SELECTABLE = 'ag-selectable';\nvar CSS_CLASS_FORCE_VERTICAL_SCROLL = 'ag-force-vertical-scroll';\nvar CSS_CLASS_COLUMN_MOVING = 'ag-column-moving';\nvar GridBodyCtrl = /** @class */ (function (_super) {\n __extends$20(GridBodyCtrl, _super);\n function GridBodyCtrl() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.stickyTopHeight = 0;\n return _this;\n }\n GridBodyCtrl.prototype.getScrollFeature = function () {\n return this.bodyScrollFeature;\n };\n GridBodyCtrl.prototype.getBodyViewportElement = function () {\n return this.eBodyViewport;\n };\n GridBodyCtrl.prototype.setComp = function (comp, eGridBody, eBodyViewport, eTop, eBottom, eStickyTop) {\n this.comp = comp;\n this.eGridBody = eGridBody;\n this.eBodyViewport = eBodyViewport;\n this.eTop = eTop;\n this.eBottom = eBottom;\n this.eStickyTop = eStickyTop;\n this.setCellTextSelection(this.gridOptionsWrapper.isEnableCellTextSelect());\n this.createManagedBean(new LayoutFeature(this.comp));\n this.bodyScrollFeature = this.createManagedBean(new GridBodyScrollFeature(this.eBodyViewport));\n this.addRowDragListener();\n this.setupRowAnimationCssClass();\n this.addEventListeners();\n this.addFocusListeners([eTop, eBodyViewport, eBottom, eStickyTop]);\n this.onGridColumnsChanged();\n this.addBodyViewportListener();\n this.setFloatingHeights();\n this.disableBrowserDragging();\n this.addStopEditingWhenGridLosesFocus();\n this.ctrlsService.registerGridBodyCtrl(this);\n };\n GridBodyCtrl.prototype.getComp = function () {\n return this.comp;\n };\n GridBodyCtrl.prototype.addEventListeners = function () {\n this.addManagedListener(this.eventService, Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_SCROLL_VISIBILITY_CHANGED, this.onScrollVisibilityChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_PINNED_ROW_DATA_CHANGED, this.onPinnedRowDataChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_HEADER_HEIGHT_CHANGED, this.onHeaderHeightChanged.bind(this));\n };\n GridBodyCtrl.prototype.addFocusListeners = function (elements) {\n var _this = this;\n elements.forEach(function (element) {\n _this.addManagedListener(element, 'focusin', function (e) {\n var target = e.target;\n // element being focused is nested?\n var isFocusedElementNested = isElementChildOfClass(target, 'ag-root', element);\n element.classList.toggle('ag-has-focus', !isFocusedElementNested);\n });\n _this.addManagedListener(element, 'focusout', function (e) {\n var target = e.target, relatedTarget = e.relatedTarget;\n var gridContainRelatedTarget = element.contains(relatedTarget);\n var isNestedRelatedTarget = isElementChildOfClass(relatedTarget, 'ag-root', element);\n var isNestedTarget = isElementChildOfClass(target, 'ag-root', element);\n // element losing focus belongs to a nested grid,\n // it should not be handled here.\n if (isNestedTarget) {\n return;\n }\n // the grid does not contain, or the focus element is within\n // a nested grid\n if (!gridContainRelatedTarget || isNestedRelatedTarget) {\n element.classList.remove('ag-has-focus');\n }\n });\n });\n };\n // used by ColumnAnimationService\n GridBodyCtrl.prototype.setColumnMovingCss = function (moving) {\n this.comp.setColumnMovingCss(moving ? CSS_CLASS_COLUMN_MOVING : null, moving);\n };\n GridBodyCtrl.prototype.setCellTextSelection = function (selectable) {\n if (selectable === void 0) { selectable = false; }\n var cssClass = selectable ? CSS_CLASS_CELL_SELECTABLE : null;\n this.comp.setCellSelectableCss(cssClass, selectable);\n };\n GridBodyCtrl.prototype.onScrollVisibilityChanged = function () {\n var visible = this.scrollVisibleService.isVerticalScrollShowing();\n this.setVerticalScrollPaddingVisible(visible);\n this.setStickyTopWidth(visible);\n };\n GridBodyCtrl.prototype.onGridColumnsChanged = function () {\n var columns = this.columnModel.getAllGridColumns();\n this.comp.setColumnCount(columns ? columns.length : 0);\n };\n // if we do not do this, then the user can select a pic in the grid (eg an image in a custom cell renderer)\n // and then that will start the browser native drag n' drop, which messes up with our own drag and drop.\n GridBodyCtrl.prototype.disableBrowserDragging = function () {\n this.addManagedListener(this.eGridBody, 'dragstart', function (event) {\n if (event.target instanceof HTMLImageElement) {\n event.preventDefault();\n return false;\n }\n });\n };\n GridBodyCtrl.prototype.addStopEditingWhenGridLosesFocus = function () {\n var _this = this;\n if (!this.gridOptionsWrapper.isStopEditingWhenCellsLoseFocus()) {\n return;\n }\n var focusOutListener = function (event) {\n // this is the element the focus is moving to\n var elementWithFocus = event.relatedTarget;\n if (getTabIndex(elementWithFocus) === null) {\n _this.rowRenderer.stopEditing();\n return;\n }\n var clickInsideGrid = \n // see if click came from inside the viewports\n viewports.some(function (viewport) { return viewport.contains(elementWithFocus); })\n // and also that it's not from a detail grid\n && _this.mouseEventService.isElementInThisGrid(elementWithFocus);\n if (!clickInsideGrid) {\n var popupService = _this.popupService;\n clickInsideGrid =\n popupService.getActivePopups().some(function (popup) { return popup.contains(elementWithFocus); }) ||\n popupService.isElementWithinCustomPopup(elementWithFocus);\n }\n if (!clickInsideGrid) {\n _this.rowRenderer.stopEditing();\n }\n };\n var viewports = [this.eBodyViewport, this.eBottom, this.eTop, this.eStickyTop];\n viewports.forEach(function (viewport) { return _this.addManagedListener(viewport, 'focusout', focusOutListener); });\n };\n GridBodyCtrl.prototype.updateRowCount = function () {\n var headerCount = this.headerNavigationService.getHeaderRowCount();\n var rowCount = this.rowModel.isLastRowIndexKnown() ? this.rowModel.getRowCount() : -1;\n var total = rowCount === -1 ? -1 : (headerCount + rowCount);\n this.comp.setRowCount(total);\n };\n GridBodyCtrl.prototype.registerBodyViewportResizeListener = function (listener) {\n this.comp.registerBodyViewportResizeListener(listener);\n };\n GridBodyCtrl.prototype.setVerticalScrollPaddingVisible = function (visible) {\n var overflowY = visible ? 'scroll' : 'hidden';\n this.comp.setPinnedTopBottomOverflowY(overflowY);\n };\n GridBodyCtrl.prototype.isVerticalScrollShowing = function () {\n var show = this.gridOptionsWrapper.isAlwaysShowVerticalScroll();\n var cssClass = show ? CSS_CLASS_FORCE_VERTICAL_SCROLL : null;\n var allowVerticalScroll = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_NORMAL;\n this.comp.setAlwaysVerticalScrollClass(cssClass, show);\n return show || (allowVerticalScroll && isVerticalScrollShowing(this.eBodyViewport));\n };\n GridBodyCtrl.prototype.setupRowAnimationCssClass = function () {\n var _this = this;\n var listener = function () {\n // we don't want to use row animation if scaling, as rows jump strangely as you scroll,\n // when scaling and doing row animation.\n var animateRows = _this.gridOptionsWrapper.isAnimateRows() && !_this.rowContainerHeightService.isStretching();\n var animateRowsCssClass = animateRows ? RowAnimationCssClasses.ANIMATION_ON : RowAnimationCssClasses.ANIMATION_OFF;\n _this.comp.setRowAnimationCssOnBodyViewport(animateRowsCssClass, animateRows);\n };\n listener();\n this.addManagedListener(this.eventService, Events.EVENT_HEIGHT_SCALE_CHANGED, listener);\n };\n GridBodyCtrl.prototype.getGridBodyElement = function () {\n return this.eGridBody;\n };\n GridBodyCtrl.prototype.addBodyViewportListener = function () {\n var _this = this;\n // we want to listen for clicks directly on the eBodyViewport, so the user has a way of showing\n // the context menu if no rows or columns are displayed, or user simply clicks outside of a cell\n var listener = function (mouseEvent) {\n if (_this.gridOptionsWrapper.isPreventDefaultOnContextMenu()) {\n mouseEvent.preventDefault();\n }\n var target = mouseEvent.target;\n if (target === _this.eBodyViewport || target === _this.ctrlsService.getCenterRowContainerCtrl().getViewportElement()) {\n // show it\n if (_this.contextMenuFactory) {\n _this.contextMenuFactory.onContextMenu(mouseEvent, null, null, null, null, _this.eGridBody);\n }\n }\n };\n this.addManagedListener(this.eBodyViewport, 'contextmenu', listener);\n this.addManagedListener(this.eBodyViewport, 'wheel', this.onBodyViewportWheel.bind(this));\n this.addManagedListener(this.eStickyTop, 'wheel', this.onStickyTopWheel.bind(this));\n };\n GridBodyCtrl.prototype.onBodyViewportWheel = function (e) {\n if (!this.gridOptionsWrapper.isSuppressScrollWhenPopupsAreOpen()) {\n return;\n }\n if (this.popupService.hasAnchoredPopup()) {\n e.preventDefault();\n }\n };\n GridBodyCtrl.prototype.onStickyTopWheel = function (e) {\n e.preventDefault();\n if (e.offsetY) {\n this.scrollVertically(e.deltaY);\n }\n };\n GridBodyCtrl.prototype.getGui = function () {\n return this.eGridBody;\n };\n // called by rowDragFeature\n GridBodyCtrl.prototype.scrollVertically = function (pixels) {\n var oldScrollPosition = this.eBodyViewport.scrollTop;\n this.bodyScrollFeature.setVerticalScrollPosition(oldScrollPosition + pixels);\n return this.eBodyViewport.scrollTop - oldScrollPosition;\n };\n GridBodyCtrl.prototype.addRowDragListener = function () {\n this.rowDragFeature = this.createManagedBean(new RowDragFeature(this.eBodyViewport));\n this.dragAndDropService.addDropTarget(this.rowDragFeature);\n };\n GridBodyCtrl.prototype.getRowDragFeature = function () {\n return this.rowDragFeature;\n };\n GridBodyCtrl.prototype.onPinnedRowDataChanged = function () {\n this.setFloatingHeights();\n };\n GridBodyCtrl.prototype.setFloatingHeights = function () {\n var pinnedRowModel = this.pinnedRowModel;\n var floatingTopHeight = pinnedRowModel.getPinnedTopTotalHeight();\n if (floatingTopHeight) {\n // adding 1px for cell bottom border\n floatingTopHeight += 1;\n }\n var floatingBottomHeight = pinnedRowModel.getPinnedBottomTotalHeight();\n if (floatingBottomHeight) {\n // adding 1px for cell bottom border\n floatingBottomHeight += 1;\n }\n this.comp.setTopHeight(floatingTopHeight);\n this.comp.setBottomHeight(floatingBottomHeight);\n this.comp.setTopDisplay(floatingTopHeight ? 'inherit' : 'none');\n this.comp.setBottomDisplay(floatingBottomHeight ? 'inherit' : 'none');\n this.setStickyTopOffsetTop();\n };\n GridBodyCtrl.prototype.setStickyTopHeight = function (height) {\n if (height === void 0) { height = 0; }\n // console.log('setting sticky top height ' + height);\n this.comp.setStickyTopHeight(height + \"px\");\n this.stickyTopHeight = height;\n };\n GridBodyCtrl.prototype.getStickyTopHeight = function () {\n return this.stickyTopHeight;\n };\n GridBodyCtrl.prototype.setStickyTopWidth = function (vScrollVisible) {\n if (!vScrollVisible) {\n this.comp.setStickyTopWidth('100%');\n }\n else {\n var scrollbarWidth = this.gridOptionsWrapper.getScrollbarWidth();\n this.comp.setStickyTopWidth(\"calc(100% - \" + scrollbarWidth + \"px)\");\n }\n };\n GridBodyCtrl.prototype.onHeaderHeightChanged = function () {\n this.setStickyTopOffsetTop();\n };\n GridBodyCtrl.prototype.setStickyTopOffsetTop = function () {\n var headerCtrl = this.ctrlsService.getGridHeaderCtrl();\n var headerHeight = headerCtrl.getHeaderHeight();\n var pinnedTopHeight = this.pinnedRowModel.getPinnedTopTotalHeight();\n var height = 0;\n if (headerHeight > 0) {\n height += headerHeight + 1;\n }\n if (pinnedTopHeight > 0) {\n height += pinnedTopHeight + 1;\n }\n this.comp.setStickyTopTop(height + \"px\");\n };\n // method will call itself if no available width. this covers if the grid\n // isn't visible, but is just about to be visible.\n GridBodyCtrl.prototype.sizeColumnsToFit = function (params, nextTimeout) {\n var _this = this;\n var removeScrollWidth = this.isVerticalScrollShowing();\n var scrollWidthToRemove = removeScrollWidth ? this.gridOptionsWrapper.getScrollbarWidth() : 0;\n var bodyViewportWidth = getInnerWidth(this.eBodyViewport);\n var availableWidth = bodyViewportWidth - scrollWidthToRemove;\n if (availableWidth > 0) {\n this.columnModel.sizeColumnsToFit(availableWidth, \"sizeColumnsToFit\", false, params);\n return;\n }\n if (nextTimeout === undefined) {\n window.setTimeout(function () {\n _this.sizeColumnsToFit(params, 100);\n }, 0);\n }\n else if (nextTimeout === 100) {\n window.setTimeout(function () {\n _this.sizeColumnsToFit(params, 500);\n }, 100);\n }\n else if (nextTimeout === 500) {\n window.setTimeout(function () {\n _this.sizeColumnsToFit(params, -1);\n }, 500);\n }\n else {\n console.warn('AG Grid: tried to call sizeColumnsToFit() but the grid is coming back with ' +\n 'zero width, maybe the grid is not visible yet on the screen?');\n }\n };\n // + rangeService\n GridBodyCtrl.prototype.addScrollEventListener = function (listener) {\n this.eBodyViewport.addEventListener('scroll', listener);\n };\n // + focusService\n GridBodyCtrl.prototype.removeScrollEventListener = function (listener) {\n this.eBodyViewport.removeEventListener('scroll', listener);\n };\n __decorate$1P([\n Autowired('rowContainerHeightService')\n ], GridBodyCtrl.prototype, \"rowContainerHeightService\", void 0);\n __decorate$1P([\n Autowired('ctrlsService')\n ], GridBodyCtrl.prototype, \"ctrlsService\", void 0);\n __decorate$1P([\n Autowired('columnModel')\n ], GridBodyCtrl.prototype, \"columnModel\", void 0);\n __decorate$1P([\n Autowired('scrollVisibleService')\n ], GridBodyCtrl.prototype, \"scrollVisibleService\", void 0);\n __decorate$1P([\n Optional('contextMenuFactory')\n ], GridBodyCtrl.prototype, \"contextMenuFactory\", void 0);\n __decorate$1P([\n Autowired('headerNavigationService')\n ], GridBodyCtrl.prototype, \"headerNavigationService\", void 0);\n __decorate$1P([\n Autowired('dragAndDropService')\n ], GridBodyCtrl.prototype, \"dragAndDropService\", void 0);\n __decorate$1P([\n Autowired('pinnedRowModel')\n ], GridBodyCtrl.prototype, \"pinnedRowModel\", void 0);\n __decorate$1P([\n Autowired('rowRenderer')\n ], GridBodyCtrl.prototype, \"rowRenderer\", void 0);\n __decorate$1P([\n Autowired('popupService')\n ], GridBodyCtrl.prototype, \"popupService\", void 0);\n __decorate$1P([\n Autowired('mouseEventService')\n ], GridBodyCtrl.prototype, \"mouseEventService\", void 0);\n __decorate$1P([\n Autowired('rowModel')\n ], GridBodyCtrl.prototype, \"rowModel\", void 0);\n return GridBodyCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar SelectionHandleType;\n(function (SelectionHandleType) {\n SelectionHandleType[SelectionHandleType[\"FILL\"] = 0] = \"FILL\";\n SelectionHandleType[SelectionHandleType[\"RANGE\"] = 1] = \"RANGE\";\n})(SelectionHandleType || (SelectionHandleType = {}));\nvar CellRangeType;\n(function (CellRangeType) {\n CellRangeType[CellRangeType[\"VALUE\"] = 0] = \"VALUE\";\n CellRangeType[CellRangeType[\"DIMENSION\"] = 1] = \"DIMENSION\";\n})(CellRangeType || (CellRangeType = {}));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar CSS_CELL_RANGE_SELECTED = 'ag-cell-range-selected';\nvar CSS_CELL_RANGE_CHART = 'ag-cell-range-chart';\nvar CSS_CELL_RANGE_SINGLE_CELL = 'ag-cell-range-single-cell';\nvar CSS_CELL_RANGE_CHART_CATEGORY = 'ag-cell-range-chart-category';\nvar CSS_CELL_RANGE_HANDLE = 'ag-cell-range-handle';\nvar CSS_CELL_RANGE_TOP = 'ag-cell-range-top';\nvar CSS_CELL_RANGE_RIGHT = 'ag-cell-range-right';\nvar CSS_CELL_RANGE_BOTTOM = 'ag-cell-range-bottom';\nvar CSS_CELL_RANGE_LEFT = 'ag-cell-range-left';\nvar CellRangeFeature = /** @class */ (function () {\n function CellRangeFeature(beans, ctrl) {\n this.beans = beans;\n this.cellCtrl = ctrl;\n }\n CellRangeFeature.prototype.setComp = function (cellComp, eGui) {\n this.cellComp = cellComp;\n this.eGui = eGui;\n this.onRangeSelectionChanged();\n };\n CellRangeFeature.prototype.onRangeSelectionChanged = function () {\n // when using reactUi, given UI is async, it's possible this method is called before the comp is registered\n if (!this.cellComp) {\n return;\n }\n this.rangeCount = this.beans.rangeService.getCellRangeCount(this.cellCtrl.getCellPosition());\n this.hasChartRange = this.getHasChartRange();\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_SELECTED, this.rangeCount !== 0);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_SELECTED + \"-1\", this.rangeCount === 1);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_SELECTED + \"-2\", this.rangeCount === 2);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_SELECTED + \"-3\", this.rangeCount === 3);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_SELECTED + \"-4\", this.rangeCount >= 4);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_CHART, this.hasChartRange);\n setAriaSelected(this.eGui, this.rangeCount > 0 ? true : undefined);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_SINGLE_CELL, this.isSingleCell());\n this.updateRangeBorders();\n this.refreshHandle();\n };\n CellRangeFeature.prototype.updateRangeBorders = function () {\n var rangeBorders = this.getRangeBorders();\n var isSingleCell = this.isSingleCell();\n var isTop = !isSingleCell && rangeBorders.top;\n var isRight = !isSingleCell && rangeBorders.right;\n var isBottom = !isSingleCell && rangeBorders.bottom;\n var isLeft = !isSingleCell && rangeBorders.left;\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_TOP, isTop);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_RIGHT, isRight);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_BOTTOM, isBottom);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_LEFT, isLeft);\n };\n CellRangeFeature.prototype.isSingleCell = function () {\n var rangeService = this.beans.rangeService;\n return this.rangeCount === 1 && rangeService && !rangeService.isMoreThanOneCell();\n };\n CellRangeFeature.prototype.getHasChartRange = function () {\n var rangeService = this.beans.rangeService;\n if (!this.rangeCount || !rangeService) {\n return false;\n }\n var cellRanges = rangeService.getCellRanges();\n return cellRanges.length > 0 && cellRanges.every(function (range) { return includes([CellRangeType.DIMENSION, CellRangeType.VALUE], range.type); });\n };\n CellRangeFeature.prototype.updateRangeBordersIfRangeCount = function () {\n // we only need to update range borders if we are in a range\n if (this.rangeCount > 0) {\n this.updateRangeBorders();\n this.refreshHandle();\n }\n };\n CellRangeFeature.prototype.getRangeBorders = function () {\n var _this = this;\n var isRtl = this.beans.gridOptionsWrapper.isEnableRtl();\n var top = false;\n var right = false;\n var bottom = false;\n var left = false;\n var thisCol = this.cellCtrl.getCellPosition().column;\n var _a = this.beans, rangeService = _a.rangeService, columnModel = _a.columnModel;\n var leftCol;\n var rightCol;\n if (isRtl) {\n leftCol = columnModel.getDisplayedColAfter(thisCol);\n rightCol = columnModel.getDisplayedColBefore(thisCol);\n }\n else {\n leftCol = columnModel.getDisplayedColBefore(thisCol);\n rightCol = columnModel.getDisplayedColAfter(thisCol);\n }\n var ranges = rangeService.getCellRanges().filter(function (range) { return rangeService.isCellInSpecificRange(_this.cellCtrl.getCellPosition(), range); });\n // this means we are the first column in the grid\n if (!leftCol) {\n left = true;\n }\n // this means we are the last column in the grid\n if (!rightCol) {\n right = true;\n }\n for (var i = 0; i < ranges.length; i++) {\n if (top && right && bottom && left) {\n break;\n }\n var range = ranges[i];\n var startRow = rangeService.getRangeStartRow(range);\n var endRow = rangeService.getRangeEndRow(range);\n if (!top && this.beans.rowPositionUtils.sameRow(startRow, this.cellCtrl.getCellPosition())) {\n top = true;\n }\n if (!bottom && this.beans.rowPositionUtils.sameRow(endRow, this.cellCtrl.getCellPosition())) {\n bottom = true;\n }\n if (!left && leftCol && range.columns.indexOf(leftCol) < 0) {\n left = true;\n }\n if (!right && rightCol && range.columns.indexOf(rightCol) < 0) {\n right = true;\n }\n }\n return { top: top, right: right, bottom: bottom, left: left };\n };\n CellRangeFeature.prototype.refreshHandle = function () {\n if (!this.beans.rangeService) {\n return;\n }\n var shouldHaveSelectionHandle = this.shouldHaveSelectionHandle();\n if (this.selectionHandle && !shouldHaveSelectionHandle) {\n this.selectionHandle = this.beans.context.destroyBean(this.selectionHandle);\n }\n if (shouldHaveSelectionHandle) {\n this.addSelectionHandle();\n }\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_HANDLE, !!this.selectionHandle);\n };\n CellRangeFeature.prototype.shouldHaveSelectionHandle = function () {\n var _a = this.beans, gridOptionsWrapper = _a.gridOptionsWrapper, rangeService = _a.rangeService;\n var cellRanges = rangeService.getCellRanges();\n var rangesLen = cellRanges.length;\n if (this.rangeCount < 1 || rangesLen < 1) {\n return false;\n }\n var cellRange = last(cellRanges);\n var cellPosition = this.cellCtrl.getCellPosition();\n var isFillHandleAvailable = gridOptionsWrapper.isEnableFillHandle() && !this.cellCtrl.isSuppressFillHandle();\n var isRangeHandleAvailable = gridOptionsWrapper.isEnableRangeHandle();\n var handleIsAvailable = rangesLen === 1 && !this.cellCtrl.isEditing() && (isFillHandleAvailable || isRangeHandleAvailable);\n if (this.hasChartRange) {\n var hasCategoryRange = cellRanges[0].type === CellRangeType.DIMENSION;\n var isCategoryCell = hasCategoryRange && rangeService.isCellInSpecificRange(cellPosition, cellRanges[0]);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_RANGE_CHART_CATEGORY, isCategoryCell);\n handleIsAvailable = cellRange.type === CellRangeType.VALUE;\n }\n return handleIsAvailable &&\n cellRange.endRow != null &&\n rangeService.isContiguousRange(cellRange) &&\n rangeService.isBottomRightCell(cellRange, cellPosition);\n };\n CellRangeFeature.prototype.addSelectionHandle = function () {\n var _a = this.beans, gridOptionsWrapper = _a.gridOptionsWrapper, rangeService = _a.rangeService;\n var cellRangeType = last(rangeService.getCellRanges()).type;\n var selectionHandleFill = gridOptionsWrapper.isEnableFillHandle() && missing(cellRangeType);\n var type = selectionHandleFill ? SelectionHandleType.FILL : SelectionHandleType.RANGE;\n if (this.selectionHandle && this.selectionHandle.getType() !== type) {\n this.selectionHandle = this.beans.context.destroyBean(this.selectionHandle);\n }\n if (!this.selectionHandle) {\n this.selectionHandle = this.beans.selectionHandleFactory.createSelectionHandle(type);\n }\n this.selectionHandle.refresh(this.cellCtrl);\n };\n CellRangeFeature.prototype.destroy = function () {\n this.beans.context.destroyBean(this.selectionHandle);\n };\n return CellRangeFeature;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1$ = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n/**\n * Takes care of:\n * #) Cell Width (including when doing cell spanning, which makes width cover many columns)\n * #) Cell Height (when doing row span, otherwise we don't touch the height as it's just row height)\n * #) Cell Left (the horizontal positioning of the cell, the vertical positioning is on the row)\n */\nvar CellPositionFeature = /** @class */ (function (_super) {\n __extends$1$(CellPositionFeature, _super);\n function CellPositionFeature(ctrl, beans) {\n var _this = _super.call(this) || this;\n _this.cellCtrl = ctrl;\n _this.beans = beans;\n _this.column = ctrl.getColumn();\n _this.rowNode = ctrl.getRowNode();\n _this.setupColSpan();\n _this.setupRowSpan();\n return _this;\n }\n CellPositionFeature.prototype.setupRowSpan = function () {\n this.rowSpan = this.column.getRowSpan(this.rowNode);\n };\n CellPositionFeature.prototype.setComp = function (eGui) {\n this.eGui = eGui;\n this.onLeftChanged();\n this.onWidthChanged();\n this.applyRowSpan();\n };\n CellPositionFeature.prototype.onDisplayColumnsChanged = function () {\n var colsSpanning = this.getColSpanningList();\n if (!areEqual(this.colsSpanning, colsSpanning)) {\n this.colsSpanning = colsSpanning;\n this.onWidthChanged();\n this.onLeftChanged(); // left changes when doing RTL\n }\n };\n CellPositionFeature.prototype.setupColSpan = function () {\n // if no col span is active, then we don't set it up, as it would be wasteful of CPU\n if (this.column.getColDef().colSpan == null) {\n return;\n }\n this.colsSpanning = this.getColSpanningList();\n // because we are col spanning, a reorder of the cols can change what cols we are spanning over\n this.addManagedListener(this.beans.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayColumnsChanged.bind(this));\n // because we are spanning over multiple cols, we check for width any time any cols width changes.\n // this is expensive - really we should be explicitly checking only the cols we are spanning over\n // instead of every col, however it would be tricky code to track the cols we are spanning over, so\n // because hardly anyone will be using colSpan, am favouring this easier way for more maintainable code.\n this.addManagedListener(this.beans.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, this.onWidthChanged.bind(this));\n };\n CellPositionFeature.prototype.onWidthChanged = function () {\n if (!this.eGui) {\n return;\n }\n var width = this.getCellWidth();\n this.eGui.style.width = width + \"px\";\n };\n CellPositionFeature.prototype.getCellWidth = function () {\n if (!this.colsSpanning) {\n return this.column.getActualWidth();\n }\n return this.colsSpanning.reduce(function (width, col) { return width + col.getActualWidth(); }, 0);\n };\n CellPositionFeature.prototype.getColSpanningList = function () {\n var colSpan = this.column.getColSpan(this.rowNode);\n var colsSpanning = [];\n // if just one col, the col span is just the column we are in\n if (colSpan === 1) {\n colsSpanning.push(this.column);\n }\n else {\n var pointer = this.column;\n var pinned = this.column.getPinned();\n for (var i = 0; pointer && i < colSpan; i++) {\n colsSpanning.push(pointer);\n pointer = this.beans.columnModel.getDisplayedColAfter(pointer);\n if (!pointer || missing(pointer)) {\n break;\n }\n // we do not allow col spanning to span outside of pinned areas\n if (pinned !== pointer.getPinned()) {\n break;\n }\n }\n }\n return colsSpanning;\n };\n CellPositionFeature.prototype.onLeftChanged = function () {\n if (!this.eGui) {\n return;\n }\n var left = this.modifyLeftForPrintLayout(this.getCellLeft());\n this.eGui.style.left = left + 'px';\n };\n CellPositionFeature.prototype.getCellLeft = function () {\n var mostLeftCol;\n if (this.beans.gridOptionsWrapper.isEnableRtl() && this.colsSpanning) {\n mostLeftCol = last(this.colsSpanning);\n }\n else {\n mostLeftCol = this.column;\n }\n return mostLeftCol.getLeft();\n };\n CellPositionFeature.prototype.modifyLeftForPrintLayout = function (leftPosition) {\n if (!this.cellCtrl.isPrintLayout() || this.column.getPinned() === Constants.PINNED_LEFT) {\n return leftPosition;\n }\n var leftWidth = this.beans.columnModel.getDisplayedColumnsLeftWidth();\n if (this.column.getPinned() === Constants.PINNED_RIGHT) {\n var bodyWidth = this.beans.columnModel.getBodyContainerWidth();\n return leftWidth + bodyWidth + (leftPosition || 0);\n }\n // is in body\n return leftWidth + (leftPosition || 0);\n };\n CellPositionFeature.prototype.applyRowSpan = function () {\n if (this.rowSpan === 1) {\n return;\n }\n var singleRowHeight = this.beans.gridOptionsWrapper.getRowHeightAsNumber();\n var totalRowHeight = singleRowHeight * this.rowSpan;\n this.eGui.style.height = totalRowHeight + \"px\";\n this.eGui.style.zIndex = '1';\n };\n // overriding to make public, as we don't dispose this bean via context\n CellPositionFeature.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n return CellPositionFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1_ = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar CellCustomStyleFeature = /** @class */ (function (_super) {\n __extends$1_(CellCustomStyleFeature, _super);\n function CellCustomStyleFeature(ctrl, beans) {\n var _this = _super.call(this) || this;\n _this.staticClasses = [];\n _this.cellCtrl = ctrl;\n _this.beans = beans;\n _this.column = ctrl.getColumn();\n _this.rowNode = ctrl.getRowNode();\n return _this;\n }\n CellCustomStyleFeature.prototype.setComp = function (comp) {\n this.cellComp = comp;\n this.applyUserStyles();\n this.applyCellClassRules();\n this.applyClassesFromColDef();\n };\n CellCustomStyleFeature.prototype.applyCellClassRules = function () {\n var _this = this;\n var colDef = this.column.getColDef();\n var cellClassParams = {\n value: this.cellCtrl.getValue(),\n data: this.rowNode.data,\n node: this.rowNode,\n colDef: colDef,\n column: this.column,\n rowIndex: this.rowNode.rowIndex,\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext()\n };\n this.beans.stylingService.processClassRules(colDef.cellClassRules, cellClassParams, function (className) { return _this.cellComp.addOrRemoveCssClass(className, true); }, function (className) { return _this.cellComp.addOrRemoveCssClass(className, false); });\n };\n CellCustomStyleFeature.prototype.applyUserStyles = function () {\n var colDef = this.column.getColDef();\n if (!colDef.cellStyle) {\n return;\n }\n var styles;\n if (typeof colDef.cellStyle === 'function') {\n var cellStyleParams = {\n column: this.column,\n value: this.cellCtrl.getValue(),\n colDef: colDef,\n data: this.rowNode.data,\n node: this.rowNode,\n rowIndex: this.rowNode.rowIndex,\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext(),\n };\n var cellStyleFunc = colDef.cellStyle;\n styles = cellStyleFunc(cellStyleParams);\n }\n else {\n styles = colDef.cellStyle;\n }\n this.cellComp.setUserStyles(styles);\n };\n CellCustomStyleFeature.prototype.applyClassesFromColDef = function () {\n var _this = this;\n var colDef = this.column.getColDef();\n var cellClassParams = {\n value: this.cellCtrl.getValue(),\n data: this.rowNode.data,\n node: this.rowNode,\n column: this.column,\n colDef: colDef,\n rowIndex: this.rowNode.rowIndex,\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext()\n };\n if (this.staticClasses.length) {\n this.staticClasses.forEach(function (className) { return _this.cellComp.addOrRemoveCssClass(className, false); });\n }\n this.staticClasses = this.beans.stylingService.getStaticCellClasses(colDef, cellClassParams);\n if (this.staticClasses.length) {\n this.staticClasses.forEach(function (className) { return _this.cellComp.addOrRemoveCssClass(className, true); });\n }\n };\n // overriding to make public, as we don't dispose this bean via context\n CellCustomStyleFeature.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n return CellCustomStyleFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1Z = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar TooltipFeature = /** @class */ (function (_super) {\n __extends$1Z(TooltipFeature, _super);\n function TooltipFeature(ctrl, beans) {\n var _this = _super.call(this) || this;\n _this.ctrl = ctrl;\n _this.beans = beans;\n return _this;\n }\n TooltipFeature.prototype.setComp = function (comp) {\n this.comp = comp;\n this.setupTooltip();\n };\n TooltipFeature.prototype.setupTooltip = function () {\n this.browserTooltips = this.beans.gridOptionsWrapper.isEnableBrowserTooltips();\n this.updateTooltipText();\n if (this.browserTooltips) {\n this.comp.setTitle(this.tooltip != null ? this.tooltip : undefined);\n }\n else {\n this.createTooltipFeatureIfNeeded();\n }\n };\n TooltipFeature.prototype.updateTooltipText = function () {\n this.tooltip = this.ctrl.getTooltipValue();\n };\n TooltipFeature.prototype.createTooltipFeatureIfNeeded = function () {\n var _this = this;\n if (this.genericTooltipFeature != null) {\n return;\n }\n var parent = {\n getTooltipParams: function () { return _this.getTooltipParams(); },\n getGui: function () { return _this.ctrl.getGui(); }\n };\n this.genericTooltipFeature = this.createManagedBean(new CustomTooltipFeature(parent), this.beans.context);\n };\n TooltipFeature.prototype.refreshToolTip = function () {\n this.updateTooltipText();\n if (this.browserTooltips) {\n this.comp.setTitle(this.tooltip != null ? this.tooltip : undefined);\n }\n };\n TooltipFeature.prototype.getTooltipParams = function () {\n var ctrl = this.ctrl;\n var column = ctrl.getColumn ? ctrl.getColumn() : undefined;\n var colDef = ctrl.getColDef ? ctrl.getColDef() : undefined;\n var rowNode = ctrl.getRowNode ? ctrl.getRowNode() : undefined;\n return {\n location: ctrl.getLocation(),\n colDef: colDef,\n column: column,\n rowIndex: ctrl.getRowIndex ? ctrl.getRowIndex() : undefined,\n node: rowNode,\n data: rowNode ? rowNode.data : undefined,\n value: this.getTooltipText(),\n valueFormatted: ctrl.getValueFormatted ? ctrl.getValueFormatted() : undefined,\n };\n };\n TooltipFeature.prototype.getTooltipText = function () {\n return this.tooltip;\n };\n // overriding to make public, as we don't dispose this bean via context\n TooltipFeature.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n return TooltipFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$1O = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n/** Using the IoC has a slight performance consideration, which is no problem most of the\n * time, unless we are trashing objects - which is the case when scrolling and rowComp\n * and cellComp. So for performance reasons, RowComp and CellComp do not get autowired\n * with the IoC. Instead they get passed this object which is all the beans the RowComp\n * and CellComp need. Not autowiring all the cells gives performance improvement. */\nvar Beans = /** @class */ (function () {\n function Beans() {\n }\n Beans.prototype.postConstruct = function () {\n this.doingMasterDetail = this.gridOptionsWrapper.isMasterDetail();\n if (this.gridOptionsWrapper.isRowModelDefault()) {\n this.clientSideRowModel = this.rowModel;\n }\n if (this.gridOptionsWrapper.isRowModelServerSide()) {\n this.serverSideRowModel = this.rowModel;\n }\n };\n __decorate$1O([\n Autowired('resizeObserverService')\n ], Beans.prototype, \"resizeObserverService\", void 0);\n __decorate$1O([\n Autowired('paginationProxy')\n ], Beans.prototype, \"paginationProxy\", void 0);\n __decorate$1O([\n Autowired('context')\n ], Beans.prototype, \"context\", void 0);\n __decorate$1O([\n Autowired('columnApi')\n ], Beans.prototype, \"columnApi\", void 0);\n __decorate$1O([\n Autowired('gridApi')\n ], Beans.prototype, \"gridApi\", void 0);\n __decorate$1O([\n Autowired('gridOptionsWrapper')\n ], Beans.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$1O([\n Autowired('expressionService')\n ], Beans.prototype, \"expressionService\", void 0);\n __decorate$1O([\n Autowired('rowRenderer')\n ], Beans.prototype, \"rowRenderer\", void 0);\n __decorate$1O([\n Autowired('templateService')\n ], Beans.prototype, \"templateService\", void 0);\n __decorate$1O([\n Autowired('valueService')\n ], Beans.prototype, \"valueService\", void 0);\n __decorate$1O([\n Autowired('eventService')\n ], Beans.prototype, \"eventService\", void 0);\n __decorate$1O([\n Autowired('columnModel')\n ], Beans.prototype, \"columnModel\", void 0);\n __decorate$1O([\n Autowired('headerNavigationService')\n ], Beans.prototype, \"headerNavigationService\", void 0);\n __decorate$1O([\n Autowired('navigationService')\n ], Beans.prototype, \"navigationService\", void 0);\n __decorate$1O([\n Autowired('columnAnimationService')\n ], Beans.prototype, \"columnAnimationService\", void 0);\n __decorate$1O([\n Optional('rangeService')\n ], Beans.prototype, \"rangeService\", void 0);\n __decorate$1O([\n Autowired('focusService')\n ], Beans.prototype, \"focusService\", void 0);\n __decorate$1O([\n Optional('contextMenuFactory')\n ], Beans.prototype, \"contextMenuFactory\", void 0);\n __decorate$1O([\n Autowired('popupService')\n ], Beans.prototype, \"popupService\", void 0);\n __decorate$1O([\n Autowired('valueFormatterService')\n ], Beans.prototype, \"valueFormatterService\", void 0);\n __decorate$1O([\n Autowired('stylingService')\n ], Beans.prototype, \"stylingService\", void 0);\n __decorate$1O([\n Autowired('columnHoverService')\n ], Beans.prototype, \"columnHoverService\", void 0);\n __decorate$1O([\n Autowired('userComponentFactory')\n ], Beans.prototype, \"userComponentFactory\", void 0);\n __decorate$1O([\n Autowired('userComponentRegistry')\n ], Beans.prototype, \"userComponentRegistry\", void 0);\n __decorate$1O([\n Autowired('animationFrameService')\n ], Beans.prototype, \"animationFrameService\", void 0);\n __decorate$1O([\n Autowired('dragAndDropService')\n ], Beans.prototype, \"dragAndDropService\", void 0);\n __decorate$1O([\n Autowired('sortController')\n ], Beans.prototype, \"sortController\", void 0);\n __decorate$1O([\n Autowired('filterManager')\n ], Beans.prototype, \"filterManager\", void 0);\n __decorate$1O([\n Autowired('rowContainerHeightService')\n ], Beans.prototype, \"rowContainerHeightService\", void 0);\n __decorate$1O([\n Autowired('frameworkOverrides')\n ], Beans.prototype, \"frameworkOverrides\", void 0);\n __decorate$1O([\n Autowired('cellPositionUtils')\n ], Beans.prototype, \"cellPositionUtils\", void 0);\n __decorate$1O([\n Autowired('rowPositionUtils')\n ], Beans.prototype, \"rowPositionUtils\", void 0);\n __decorate$1O([\n Autowired('selectionService')\n ], Beans.prototype, \"selectionService\", void 0);\n __decorate$1O([\n Optional('selectionHandleFactory')\n ], Beans.prototype, \"selectionHandleFactory\", void 0);\n __decorate$1O([\n Autowired('rowCssClassCalculator')\n ], Beans.prototype, \"rowCssClassCalculator\", void 0);\n __decorate$1O([\n Autowired('rowModel')\n ], Beans.prototype, \"rowModel\", void 0);\n __decorate$1O([\n Autowired('ctrlsService')\n ], Beans.prototype, \"ctrlsService\", void 0);\n __decorate$1O([\n Autowired('ctrlsFactory')\n ], Beans.prototype, \"ctrlsFactory\", void 0);\n __decorate$1O([\n Autowired('agStackComponentsRegistry')\n ], Beans.prototype, \"agStackComponentsRegistry\", void 0);\n __decorate$1O([\n Autowired('valueCache')\n ], Beans.prototype, \"valueCache\", void 0);\n __decorate$1O([\n Autowired('rowNodeEventThrottle')\n ], Beans.prototype, \"rowNodeEventThrottle\", void 0);\n __decorate$1O([\n PostConstruct\n ], Beans.prototype, \"postConstruct\", null);\n Beans = __decorate$1O([\n Bean('beans')\n ], Beans);\n return Beans;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1Y = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar CellMouseListenerFeature = /** @class */ (function (_super) {\n __extends$1Y(CellMouseListenerFeature, _super);\n function CellMouseListenerFeature(ctrl, beans, column) {\n var _this = _super.call(this) || this;\n _this.cellCtrl = ctrl;\n _this.beans = beans;\n _this.column = column;\n return _this;\n }\n CellMouseListenerFeature.prototype.onMouseEvent = function (eventName, mouseEvent) {\n if (isStopPropagationForAgGrid(mouseEvent)) {\n return;\n }\n switch (eventName) {\n case 'click':\n this.onCellClicked(mouseEvent);\n break;\n case 'mousedown':\n case 'touchstart':\n this.onMouseDown(mouseEvent);\n break;\n case 'dblclick':\n this.onCellDoubleClicked(mouseEvent);\n break;\n case 'mouseout':\n this.onMouseOut(mouseEvent);\n break;\n case 'mouseover':\n this.onMouseOver(mouseEvent);\n break;\n }\n };\n CellMouseListenerFeature.prototype.onCellClicked = function (mouseEvent) {\n // iPad doesn't have double click - so we need to mimic it to enable editing for iPad.\n if (this.isDoubleClickOnIPad()) {\n this.onCellDoubleClicked(mouseEvent);\n mouseEvent.preventDefault(); // if we don't do this, then iPad zooms in\n return;\n }\n var _a = this.beans, eventService = _a.eventService, rangeService = _a.rangeService, gridOptionsWrapper = _a.gridOptionsWrapper;\n var multiKeyPressed = mouseEvent.ctrlKey || mouseEvent.metaKey;\n if (rangeService && multiKeyPressed) {\n // the mousedown event has created the range already, so we only intersect if there is more than one\n // range on this cell\n if (rangeService.getCellRangeCount(this.cellCtrl.getCellPosition()) > 1) {\n rangeService.intersectLastRange(true);\n }\n }\n var cellClickedEvent = this.cellCtrl.createEvent(mouseEvent, Events.EVENT_CELL_CLICKED);\n eventService.dispatchEvent(cellClickedEvent);\n var colDef = this.column.getColDef();\n if (colDef.onCellClicked) {\n // to make callback async, do in a timeout\n window.setTimeout(function () { return colDef.onCellClicked(cellClickedEvent); }, 0);\n }\n var editOnSingleClick = (gridOptionsWrapper.isSingleClickEdit() || colDef.singleClickEdit)\n && !gridOptionsWrapper.isSuppressClickEdit();\n if (editOnSingleClick) {\n this.cellCtrl.startRowOrCellEdit();\n }\n };\n // returns true if on iPad and this is second 'click' event in 200ms\n CellMouseListenerFeature.prototype.isDoubleClickOnIPad = function () {\n if (!isIOSUserAgent() || isEventSupported('dblclick')) {\n return false;\n }\n var nowMillis = new Date().getTime();\n var res = nowMillis - this.lastIPadMouseClickEvent < 200;\n this.lastIPadMouseClickEvent = nowMillis;\n return res;\n };\n CellMouseListenerFeature.prototype.onCellDoubleClicked = function (mouseEvent) {\n var colDef = this.column.getColDef();\n // always dispatch event to eventService\n var cellDoubleClickedEvent = this.cellCtrl.createEvent(mouseEvent, Events.EVENT_CELL_DOUBLE_CLICKED);\n this.beans.eventService.dispatchEvent(cellDoubleClickedEvent);\n // check if colDef also wants to handle event\n if (typeof colDef.onCellDoubleClicked === 'function') {\n // to make the callback async, do in a timeout\n window.setTimeout(function () { return colDef.onCellDoubleClicked(cellDoubleClickedEvent); }, 0);\n }\n var editOnDoubleClick = !this.beans.gridOptionsWrapper.isSingleClickEdit()\n && !this.beans.gridOptionsWrapper.isSuppressClickEdit();\n if (editOnDoubleClick) {\n this.cellCtrl.startRowOrCellEdit(null, null, mouseEvent);\n }\n };\n CellMouseListenerFeature.prototype.onMouseDown = function (mouseEvent) {\n var ctrlKey = mouseEvent.ctrlKey, metaKey = mouseEvent.metaKey, shiftKey = mouseEvent.shiftKey;\n var target = mouseEvent.target;\n var _a = this.beans, eventService = _a.eventService, rangeService = _a.rangeService;\n // do not change the range for right-clicks inside an existing range\n if (this.isRightClickInExistingRange(mouseEvent)) {\n return;\n }\n var ranges = rangeService && rangeService.getCellRanges().length != 0;\n if (!shiftKey || !ranges) {\n // We only need to pass true to focusCell when the browser is IE/Edge and we are trying\n // to focus the cell itself. This should never be true if the mousedown was triggered\n // due to a click on a cell editor for example.\n var forceBrowserFocus = (isBrowserEdge()) && !this.cellCtrl.isEditing() && !isFocusableFormField(target);\n this.cellCtrl.focusCell(forceBrowserFocus);\n }\n // if shift clicking, and a range exists, we keep the focus on the cell that started the\n // range as the user then changes the range selection.\n if (shiftKey && ranges) {\n // this stops the cell from getting focused\n mouseEvent.preventDefault();\n }\n // if we are clicking on a checkbox, we need to make sure the cell wrapping that checkbox\n // is focused but we don't want to change the range selection, so return here.\n if (this.containsWidget(target)) {\n return;\n }\n if (rangeService) {\n var thisCell = this.cellCtrl.getCellPosition();\n if (shiftKey) {\n rangeService.extendLatestRangeToCell(thisCell);\n }\n else {\n var ctrlKeyPressed = ctrlKey || metaKey;\n rangeService.setRangeToCell(thisCell, ctrlKeyPressed);\n }\n }\n eventService.dispatchEvent(this.cellCtrl.createEvent(mouseEvent, Events.EVENT_CELL_MOUSE_DOWN));\n };\n CellMouseListenerFeature.prototype.isRightClickInExistingRange = function (mouseEvent) {\n var rangeService = this.beans.rangeService;\n if (rangeService) {\n var cellInRange = rangeService.isCellInAnyRange(this.cellCtrl.getCellPosition());\n if (cellInRange && mouseEvent.button === 2) {\n return true;\n }\n }\n return false;\n };\n CellMouseListenerFeature.prototype.containsWidget = function (target) {\n return isElementChildOfClass(target, 'ag-selection-checkbox', 3);\n };\n CellMouseListenerFeature.prototype.onMouseOut = function (mouseEvent) {\n if (this.mouseStayingInsideCell(mouseEvent)) {\n return;\n }\n var cellMouseOutEvent = this.cellCtrl.createEvent(mouseEvent, Events.EVENT_CELL_MOUSE_OUT);\n this.beans.eventService.dispatchEvent(cellMouseOutEvent);\n this.beans.columnHoverService.clearMouseOver();\n };\n CellMouseListenerFeature.prototype.onMouseOver = function (mouseEvent) {\n if (this.mouseStayingInsideCell(mouseEvent)) {\n return;\n }\n var cellMouseOverEvent = this.cellCtrl.createEvent(mouseEvent, Events.EVENT_CELL_MOUSE_OVER);\n this.beans.eventService.dispatchEvent(cellMouseOverEvent);\n this.beans.columnHoverService.setMouseOver([this.column]);\n };\n CellMouseListenerFeature.prototype.mouseStayingInsideCell = function (e) {\n if (!e.target || !e.relatedTarget) {\n return false;\n }\n var eGui = this.cellCtrl.getGui();\n var cellContainsTarget = eGui.contains(e.target);\n var cellContainsRelatedTarget = eGui.contains(e.relatedTarget);\n return cellContainsTarget && cellContainsRelatedTarget;\n };\n CellMouseListenerFeature.prototype.destroy = function () {\n };\n return CellMouseListenerFeature;\n}(Beans));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1X = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar CellKeyboardListenerFeature = /** @class */ (function (_super) {\n __extends$1X(CellKeyboardListenerFeature, _super);\n function CellKeyboardListenerFeature(ctrl, beans, column, rowNode, rowCtrl) {\n var _this = _super.call(this) || this;\n _this.cellCtrl = ctrl;\n _this.beans = beans;\n _this.rowNode = rowNode;\n _this.rowCtrl = rowCtrl;\n return _this;\n }\n CellKeyboardListenerFeature.prototype.setComp = function (eGui) {\n this.eGui = eGui;\n };\n CellKeyboardListenerFeature.prototype.onKeyDown = function (event) {\n var key = event.key;\n switch (key) {\n case KeyCode.ENTER:\n this.onEnterKeyDown(event);\n break;\n case KeyCode.F2:\n this.onF2KeyDown(event);\n break;\n case KeyCode.ESCAPE:\n this.onEscapeKeyDown(event);\n break;\n case KeyCode.TAB:\n this.onTabKeyDown(event);\n break;\n case KeyCode.BACKSPACE:\n case KeyCode.DELETE:\n this.onBackspaceOrDeleteKeyPressed(key, event);\n break;\n case KeyCode.DOWN:\n case KeyCode.UP:\n case KeyCode.RIGHT:\n case KeyCode.LEFT:\n this.onNavigationKeyPressed(event, key);\n break;\n }\n };\n CellKeyboardListenerFeature.prototype.onNavigationKeyPressed = function (event, key) {\n if (this.cellCtrl.isEditing()) {\n return;\n }\n if (event.shiftKey && this.cellCtrl.isRangeSelectionEnabled()) {\n this.onShiftRangeSelect(event);\n }\n else {\n this.beans.navigationService.navigateToNextCell(event, key, this.cellCtrl.getCellPosition(), true);\n }\n // if we don't prevent default, the grid will scroll with the navigation keys\n event.preventDefault();\n };\n CellKeyboardListenerFeature.prototype.onShiftRangeSelect = function (event) {\n if (!this.beans.rangeService) {\n return;\n }\n var endCell = this.beans.rangeService.extendLatestRangeInDirection(event);\n if (endCell) {\n this.beans.navigationService.ensureCellVisible(endCell);\n }\n };\n CellKeyboardListenerFeature.prototype.onTabKeyDown = function (event) {\n this.beans.navigationService.onTabKeyDown(this.cellCtrl, event);\n };\n CellKeyboardListenerFeature.prototype.onBackspaceOrDeleteKeyPressed = function (key, event) {\n var _a = this, cellCtrl = _a.cellCtrl, beans = _a.beans, rowNode = _a.rowNode;\n var gridOptionsWrapper = beans.gridOptionsWrapper, rangeService = beans.rangeService, eventService = beans.eventService;\n if (cellCtrl.isEditing()) {\n return;\n }\n eventService.dispatchEvent({ type: Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_START });\n if (isDeleteKey(key, gridOptionsWrapper.isEnableCellEditingOnBackspace())) {\n if (rangeService && gridOptionsWrapper.isEnableRangeSelection()) {\n rangeService.clearCellRangeCellValues();\n }\n else if (cellCtrl.isCellEditable()) {\n rowNode.setDataValue(cellCtrl.getColumn(), null, 'cellKeyboardListenerFeature');\n }\n }\n else {\n cellCtrl.startRowOrCellEdit(key, undefined, event);\n }\n eventService.dispatchEvent({ type: Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_END });\n };\n CellKeyboardListenerFeature.prototype.onEnterKeyDown = function (e) {\n if (this.cellCtrl.isEditing() || this.rowCtrl.isEditing()) {\n this.cellCtrl.stopEditingAndFocus();\n }\n else {\n if (this.beans.gridOptionsWrapper.isEnterMovesDown()) {\n this.beans.navigationService.navigateToNextCell(null, KeyCode.DOWN, this.cellCtrl.getCellPosition(), false);\n }\n else {\n this.cellCtrl.startRowOrCellEdit(KeyCode.ENTER, undefined, e);\n if (this.cellCtrl.isEditing()) {\n // if we started editing, then we need to prevent default, otherwise the Enter action can get\n // applied to the cell editor. this happened, for example, with largeTextCellEditor where not\n // preventing default results in a 'new line' character getting inserted in the text area\n // when the editing was started\n e.preventDefault();\n }\n }\n }\n };\n CellKeyboardListenerFeature.prototype.onF2KeyDown = function (event) {\n if (!this.cellCtrl.isEditing()) {\n this.cellCtrl.startRowOrCellEdit(KeyCode.F2, undefined, event);\n }\n };\n CellKeyboardListenerFeature.prototype.onEscapeKeyDown = function (event) {\n if (this.cellCtrl.isEditing()) {\n this.cellCtrl.stopRowOrCellEdit(true);\n this.cellCtrl.focusCell(true);\n }\n };\n CellKeyboardListenerFeature.prototype.onKeyPress = function (event) {\n // check this, in case focus is on a (for example) a text field inside the cell,\n // in which cse we should not be listening for these key pressed\n var eventTarget = event.target;\n var eventOnChildComponent = eventTarget !== this.eGui;\n if (eventOnChildComponent || this.cellCtrl.isEditing()) {\n return;\n }\n var pressedChar = String.fromCharCode(event.charCode);\n if (pressedChar === ' ') {\n this.onSpaceKeyPressed(event);\n }\n else if (isEventFromPrintableCharacter(event)) {\n this.cellCtrl.startRowOrCellEdit(null, pressedChar, event);\n // if we don't prevent default, then the keypress also gets applied to the text field\n // (at least when doing the default editor), but we need to allow the editor to decide\n // what it wants to do. we only do this IF editing was started - otherwise it messes\n // up when the use is not doing editing, but using rendering with text fields in cellRenderer\n // (as it would block the the user from typing into text fields).\n event.preventDefault();\n }\n };\n CellKeyboardListenerFeature.prototype.onSpaceKeyPressed = function (event) {\n var gridOptionsWrapper = this.beans.gridOptionsWrapper;\n if (!this.cellCtrl.isEditing() && gridOptionsWrapper.isRowSelection()) {\n var currentSelection = this.rowNode.isSelected();\n var newSelection = !currentSelection;\n if (newSelection || !gridOptionsWrapper.isSuppressRowDeselection()) {\n var groupSelectsFiltered = this.beans.gridOptionsWrapper.isGroupSelectsFiltered();\n var updatedCount = this.rowNode.setSelectedParams({\n newValue: newSelection,\n rangeSelect: event.shiftKey,\n groupSelectsFiltered: groupSelectsFiltered\n });\n if (currentSelection === undefined && updatedCount === 0) {\n this.rowNode.setSelectedParams({\n newValue: false,\n rangeSelect: event.shiftKey,\n groupSelectsFiltered: groupSelectsFiltered\n });\n }\n }\n }\n // prevent default as space key, by default, moves browser scroll down\n event.preventDefault();\n };\n CellKeyboardListenerFeature.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n };\n return CellKeyboardListenerFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1W = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1N = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar DndSourceComp = /** @class */ (function (_super) {\n __extends$1W(DndSourceComp, _super);\n function DndSourceComp(rowNode, column, beans, eCell) {\n var _this = _super.call(this, \"<div class=\\\"ag-drag-handle ag-row-drag\\\" draggable=\\\"true\\\"></div>\") || this;\n _this.rowNode = rowNode;\n _this.column = column;\n _this.beans = beans;\n _this.eCell = eCell;\n return _this;\n }\n DndSourceComp.prototype.postConstruct = function () {\n var eGui = this.getGui();\n eGui.appendChild(createIconNoSpan('rowDrag', this.beans.gridOptionsWrapper, null));\n // we need to stop the event propagation here to avoid starting a range selection while dragging\n this.addGuiEventListener('mousedown', function (e) {\n e.stopPropagation();\n });\n this.addDragSource();\n this.checkVisibility();\n };\n DndSourceComp.prototype.addDragSource = function () {\n this.addGuiEventListener('dragstart', this.onDragStart.bind(this));\n };\n DndSourceComp.prototype.onDragStart = function (dragEvent) {\n var _this = this;\n var providedOnRowDrag = this.column.getColDef().dndSourceOnRowDrag;\n dragEvent.dataTransfer.setDragImage(this.eCell, 0, 0);\n // default behaviour is to convert data to json and set into drag component\n var defaultOnRowDrag = function () {\n try {\n var jsonData = JSON.stringify(_this.rowNode.data);\n dragEvent.dataTransfer.setData('application/json', jsonData);\n dragEvent.dataTransfer.setData('text/plain', jsonData);\n }\n catch (e) {\n // if we cannot convert the data to json, then we do not set the type\n }\n };\n if (providedOnRowDrag) {\n var params = {\n rowNode: this.rowNode, dragEvent: dragEvent,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n providedOnRowDrag(params);\n }\n else {\n defaultOnRowDrag();\n }\n };\n DndSourceComp.prototype.checkVisibility = function () {\n var visible = this.column.isDndSource(this.rowNode);\n this.setDisplayed(visible);\n };\n __decorate$1N([\n PostConstruct\n ], DndSourceComp.prototype, \"postConstruct\", null);\n return DndSourceComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1V = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$5 = (undefined && undefined.__assign) || function () {\n __assign$5 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$5.apply(this, arguments);\n};\nvar CSS_CELL = 'ag-cell';\nvar CSS_AUTO_HEIGHT = 'ag-cell-auto-height';\nvar CSS_NORMAL_HEIGHT = 'ag-cell-normal-height';\nvar CSS_CELL_FOCUS = 'ag-cell-focus';\nvar CSS_CELL_FIRST_RIGHT_PINNED = 'ag-cell-first-right-pinned';\nvar CSS_CELL_LAST_LEFT_PINNED = 'ag-cell-last-left-pinned';\nvar CSS_CELL_NOT_INLINE_EDITING = 'ag-cell-not-inline-editing';\nvar CSS_CELL_INLINE_EDITING = 'ag-cell-inline-editing';\nvar CSS_CELL_POPUP_EDITING = 'ag-cell-popup-editing';\nvar CSS_COLUMN_HOVER = 'ag-column-hover';\nvar CSS_CELL_WRAP_TEXT = 'ag-cell-wrap-text';\nvar instanceIdSequence$3 = 0;\nvar CellCtrl = /** @class */ (function (_super) {\n __extends$1V(CellCtrl, _super);\n function CellCtrl(column, rowNode, beans, rowCtrl) {\n var _this = _super.call(this) || this;\n _this.suppressRefreshCell = false;\n _this.onCellCompAttachedFuncs = [];\n _this.removeAutoHeightListeners = null;\n _this.column = column;\n _this.rowNode = rowNode;\n _this.beans = beans;\n _this.rowCtrl = rowCtrl;\n // unique id to this instance, including the column ID to help with debugging in React as it's used in 'key'\n _this.instanceId = column.getId() + '-' + instanceIdSequence$3++;\n _this.createCellPosition();\n _this.addFeatures();\n return _this;\n }\n CellCtrl.prototype.addFeatures = function () {\n var _this = this;\n this.cellPositionFeature = new CellPositionFeature(this, this.beans);\n this.addDestroyFunc(function () { return _this.cellPositionFeature.destroy(); });\n this.cellCustomStyleFeature = new CellCustomStyleFeature(this, this.beans);\n this.addDestroyFunc(function () { return _this.cellCustomStyleFeature.destroy(); });\n this.cellMouseListenerFeature = new CellMouseListenerFeature(this, this.beans, this.column);\n this.addDestroyFunc(function () { return _this.cellMouseListenerFeature.destroy(); });\n this.cellKeyboardListenerFeature = new CellKeyboardListenerFeature(this, this.beans, this.column, this.rowNode, this.rowCtrl);\n this.addDestroyFunc(function () { return _this.cellKeyboardListenerFeature.destroy(); });\n var rangeSelectionEnabled = this.beans.rangeService && this.beans.gridOptionsWrapper.isEnableRangeSelection();\n if (rangeSelectionEnabled) {\n this.cellRangeFeature = new CellRangeFeature(this.beans, this);\n this.addDestroyFunc(function () { return _this.cellRangeFeature.destroy(); });\n }\n this.addTooltipFeature();\n };\n CellCtrl.prototype.addTooltipFeature = function () {\n var _this = this;\n var getTooltipValue = function () {\n var colDef = _this.column.getColDef();\n var data = _this.rowNode.data;\n if (colDef.tooltipField && exists(data)) {\n return getValueUsingField(data, colDef.tooltipField, _this.column.isTooltipFieldContainsDots());\n }\n var valueGetter = colDef.tooltipValueGetter;\n if (valueGetter) {\n return valueGetter({\n location: 'cell',\n api: _this.beans.gridOptionsWrapper.getApi(),\n columnApi: _this.beans.gridOptionsWrapper.getColumnApi(),\n context: _this.beans.gridOptionsWrapper.getContext(),\n colDef: _this.column.getColDef(),\n column: _this.column,\n rowIndex: _this.cellPosition.rowIndex,\n node: _this.rowNode,\n data: _this.rowNode.data,\n value: _this.value,\n valueFormatted: _this.valueFormatted,\n });\n }\n return null;\n };\n var tooltipCtrl = {\n getColumn: function () { return _this.column; },\n getColDef: function () { return _this.column.getColDef(); },\n getRowIndex: function () { return _this.cellPosition.rowIndex; },\n getRowNode: function () { return _this.rowNode; },\n getGui: function () { return _this.getGui(); },\n getLocation: function () { return 'cell'; },\n getTooltipValue: getTooltipValue,\n // this makes no sense, why is the cell formatted value passed to the tooltip???\n getValueFormatted: function () { return _this.valueFormatted; }\n };\n this.tooltipFeature = new TooltipFeature(tooltipCtrl, this.beans);\n this.addDestroyFunc(function () { return _this.tooltipFeature.destroy(); });\n };\n CellCtrl.prototype.setComp = function (comp, eGui, eCellWrapper, printLayout, startEditing) {\n this.cellComp = comp;\n this.gow = this.beans.gridOptionsWrapper;\n this.eGui = eGui;\n this.printLayout = printLayout;\n // we force to make sure formatter gets called at least once,\n // even if value has not changed (is is undefined)\n this.updateAndFormatValue(true);\n this.addDomData();\n this.onCellFocused();\n this.applyStaticCssClasses();\n this.setWrapText();\n this.onFirstRightPinnedChanged();\n this.onLastLeftPinnedChanged();\n this.onColumnHover();\n this.setupControlComps();\n if (eCellWrapper) {\n this.refreshAutoHeight(eCellWrapper);\n }\n this.setAriaColIndex();\n if (!this.gow.isSuppressCellFocus()) {\n this.cellComp.setTabIndex(-1);\n }\n var colIdSanitised = escapeString(this.column.getId());\n this.cellComp.setColId(colIdSanitised);\n this.cellComp.setRole('gridcell');\n this.cellPositionFeature.setComp(eGui);\n this.cellCustomStyleFeature.setComp(comp);\n this.tooltipFeature.setComp(comp);\n this.cellKeyboardListenerFeature.setComp(this.eGui);\n if (this.cellRangeFeature) {\n this.cellRangeFeature.setComp(comp, eGui);\n }\n if (startEditing && this.isCellEditable()) {\n this.startEditing();\n }\n else {\n this.showValue();\n }\n if (this.onCellCompAttachedFuncs.length) {\n this.onCellCompAttachedFuncs.forEach(function (func) { return func(); });\n this.onCellCompAttachedFuncs = [];\n }\n };\n CellCtrl.prototype.refreshAutoHeight = function (eCellWrapper) {\n var _this = this;\n if (!this.column.isAutoHeight()) {\n return;\n }\n var eParentCell = eCellWrapper.parentElement;\n // taking minRowHeight from getRowHeightForNode means the getRowHeight() callback is used,\n // thus allowing different min heights for different rows.\n var minRowHeight = this.beans.gridOptionsWrapper.getRowHeightForNode(this.rowNode).height;\n var measureHeight = function (timesCalled) {\n if (_this.editing) {\n return;\n }\n // because of the retry's below, it's possible the retry's go beyond\n // the rows life.\n if (!_this.isAlive()) {\n return;\n }\n var _a = getElementSize(eParentCell), paddingTop = _a.paddingTop, paddingBottom = _a.paddingBottom;\n var wrapperHeight = eCellWrapper.offsetHeight;\n var autoHeight = wrapperHeight + paddingTop + paddingBottom;\n if (timesCalled < 5) {\n // if not in doc yet, means framework not yet inserted, so wait for next VM turn,\n // maybe it will be ready next VM turn\n var doc = _this.beans.gridOptionsWrapper.getDocument();\n var notYetInDom = !doc || !doc.contains(eCellWrapper);\n // this happens in React, where React hasn't put any content in. we say 'possibly'\n // as a) may not be React and b) the cell could be empty anyway\n var possiblyNoContentYet = autoHeight == 0;\n if (notYetInDom || possiblyNoContentYet) {\n _this.beans.frameworkOverrides.setTimeout(function () { return measureHeight(timesCalled + 1); }, 0);\n return;\n }\n }\n var newHeight = Math.max(autoHeight, minRowHeight);\n _this.rowNode.setRowAutoHeight(newHeight, _this.column);\n };\n var listener = function () { return measureHeight(0); };\n // do once to set size in case size doesn't change, common when cell is blank\n listener();\n var destroyResizeObserver = this.beans.resizeObserverService.observeResize(eCellWrapper, listener);\n if (this.removeAutoHeightListeners) {\n this.removeAutoHeightListeners();\n this.removeAutoHeightListeners = null;\n }\n this.removeAutoHeightListeners = function () {\n destroyResizeObserver();\n _this.rowNode.setRowAutoHeight(undefined, _this.column);\n };\n };\n CellCtrl.prototype.getInstanceId = function () {\n return this.instanceId;\n };\n CellCtrl.prototype.showValue = function (forceNewCellRendererInstance) {\n if (forceNewCellRendererInstance === void 0) { forceNewCellRendererInstance = false; }\n var valueToDisplay = this.valueFormatted != null ? this.valueFormatted : this.value;\n var params = this.createCellRendererParams();\n var compDetails = this.beans.userComponentFactory.getCellRendererDetails(this.column.getColDef(), params);\n this.cellComp.setRenderDetails(compDetails, valueToDisplay, forceNewCellRendererInstance);\n this.refreshHandle();\n };\n CellCtrl.prototype.setupControlComps = function () {\n var colDef = this.column.getColDef();\n this.includeSelection = this.isIncludeControl(colDef.checkboxSelection);\n this.includeRowDrag = this.isIncludeControl(colDef.rowDrag);\n this.includeDndSource = this.isIncludeControl(colDef.dndSource);\n this.cellComp.setIncludeSelection(this.includeSelection);\n this.cellComp.setIncludeDndSource(this.includeDndSource);\n this.cellComp.setIncludeRowDrag(this.includeRowDrag);\n };\n CellCtrl.prototype.isForceWrapper = function () {\n // text selection requires the value to be wrapped in another element\n var forceWrapper = this.beans.gridOptionsWrapper.isEnableCellTextSelection() || this.column.isAutoHeight();\n return forceWrapper;\n };\n CellCtrl.prototype.isIncludeControl = function (value) {\n var rowNodePinned = this.rowNode.rowPinned != null;\n var isFunc = typeof value === 'function';\n var res = rowNodePinned ? false : isFunc || value === true;\n return res;\n };\n CellCtrl.prototype.refreshShouldDestroy = function () {\n var colDef = this.column.getColDef();\n var selectionChanged = this.includeSelection != this.isIncludeControl(colDef.checkboxSelection);\n var rowDragChanged = this.includeRowDrag != this.isIncludeControl(colDef.rowDrag);\n var dndSourceChanged = this.includeDndSource != this.isIncludeControl(colDef.dndSource);\n return selectionChanged || rowDragChanged || dndSourceChanged;\n };\n // either called internally if single cell editing, or called by rowRenderer if row editing\n CellCtrl.prototype.startEditing = function (key, charPress, cellStartedEdit, event) {\n var _this = this;\n if (key === void 0) { key = null; }\n if (charPress === void 0) { charPress = null; }\n if (cellStartedEdit === void 0) { cellStartedEdit = false; }\n if (event === void 0) { event = null; }\n var _a, _b;\n if (!this.isCellEditable() || this.editing) {\n return;\n }\n // because of async in React, the cellComp may not be set yet, if no cellComp then we are\n // yet to initialise the cell, so we re-schedule this operation for when celLComp is attached\n if (!this.cellComp) {\n this.onCellCompAttachedFuncs.push(function () { _this.startEditing(key, charPress, cellStartedEdit, event); });\n return;\n }\n var editorParams = this.createCellEditorParams(key, charPress, cellStartedEdit);\n var colDef = this.column.getColDef();\n var compDetails = this.beans.userComponentFactory.getCellEditorDetails(colDef, editorParams);\n // if cellEditorSelector was used, we give preference to popup and popupPosition from the selector\n var popup = ((_a = compDetails) === null || _a === void 0 ? void 0 : _a.popupFromSelector) != null ? compDetails.popupFromSelector : !!colDef.cellEditorPopup;\n var position = ((_b = compDetails) === null || _b === void 0 ? void 0 : _b.popupPositionFromSelector) != null ? compDetails.popupPositionFromSelector : colDef.cellEditorPopupPosition;\n this.setEditing(true, popup);\n this.cellComp.setEditDetails(compDetails, popup, position);\n var e = this.createEvent(event, Events.EVENT_CELL_EDITING_STARTED);\n this.beans.eventService.dispatchEvent(e);\n };\n CellCtrl.prototype.setEditing = function (editing, inPopup) {\n if (inPopup === void 0) { inPopup = false; }\n if (this.editing === editing) {\n return;\n }\n this.editing = editing;\n this.editingInPopup = inPopup;\n this.setInlineEditingClass();\n this.refreshHandle();\n };\n // pass in 'true' to cancel the editing.\n CellCtrl.prototype.stopRowOrCellEdit = function (cancel) {\n if (cancel === void 0) { cancel = false; }\n if (this.beans.gridOptionsWrapper.isFullRowEdit()) {\n this.rowCtrl.stopRowEditing(cancel);\n }\n else {\n this.stopEditing(cancel);\n }\n };\n CellCtrl.prototype.onPopupEditorClosed = function () {\n if (!this.isEditing()) {\n return;\n }\n // note: this happens because of a click outside of the grid or if the popupEditor\n // is closed with `Escape` key. if another cell was clicked, then the editing will\n // have already stopped and returned on the conditional above.\n this.stopEditingAndFocus();\n };\n CellCtrl.prototype.takeValueFromCellEditor = function (cancel) {\n var noValueResult = { newValueExists: false };\n if (cancel) {\n return noValueResult;\n }\n var cellEditor = this.cellComp.getCellEditor();\n if (!cellEditor) {\n return noValueResult;\n }\n var userWantsToCancel = cellEditor.isCancelAfterEnd && cellEditor.isCancelAfterEnd();\n if (userWantsToCancel) {\n return noValueResult;\n }\n var newValue = cellEditor.getValue();\n return {\n newValue: newValue,\n newValueExists: true\n };\n };\n /**\n * @returns `True` if the value changes, otherwise `False`.\n */\n CellCtrl.prototype.saveNewValue = function (oldValue, newValue) {\n if (newValue === oldValue) {\n return false;\n }\n if (this.beans.gridOptionsWrapper.isReadOnlyEdit()) {\n this.dispatchEventForSaveValueReadOnly(oldValue, newValue);\n return false;\n }\n // we suppressRefreshCell because the call to rowNode.setDataValue() results in change detection\n // getting triggered, which results in all cells getting refreshed. we do not want this refresh\n // to happen on this call as we want to call it explicitly below. otherwise refresh gets called twice.\n // if we only did this refresh (and not the one below) then the cell would flash and not be forced.\n this.suppressRefreshCell = true;\n var valueChanged = this.rowNode.setDataValue(this.column, newValue);\n this.suppressRefreshCell = false;\n return valueChanged;\n };\n CellCtrl.prototype.dispatchEventForSaveValueReadOnly = function (oldValue, newValue) {\n var rowNode = this.rowNode;\n var event = {\n type: Events.EVENT_CELL_EDIT_REQUEST,\n event: null,\n rowIndex: rowNode.rowIndex,\n rowPinned: rowNode.rowPinned,\n column: this.column,\n api: this.beans.gridApi,\n columnApi: this.beans.columnApi,\n colDef: this.column.getColDef(),\n context: this.beans.gridOptionsWrapper.getContext(),\n data: rowNode.data,\n node: rowNode,\n oldValue: oldValue,\n newValue: newValue,\n value: newValue,\n source: undefined\n };\n this.beans.eventService.dispatchEvent(event);\n };\n /**\n * Ends the Cell Editing\n * @param cancel `True` if the edit process is being canceled.\n * @returns `True` if the value of the `GridCell` has been updated, otherwise `False`.\n */\n CellCtrl.prototype.stopEditing = function (cancel) {\n if (cancel === void 0) { cancel = false; }\n if (!this.editing) {\n return false;\n }\n var _a = this.takeValueFromCellEditor(cancel), newValue = _a.newValue, newValueExists = _a.newValueExists;\n var oldValue = this.getValueFromValueService();\n var valueChanged = false;\n if (newValueExists) {\n valueChanged = this.saveNewValue(oldValue, newValue);\n }\n this.setEditing(false);\n this.cellComp.setEditDetails(); // passing nothing stops editing\n this.updateAndFormatValue();\n this.refreshCell({ forceRefresh: true, suppressFlash: true });\n this.dispatchEditingStoppedEvent(oldValue, newValue, !cancel && !!valueChanged);\n return valueChanged;\n };\n CellCtrl.prototype.dispatchEditingStoppedEvent = function (oldValue, newValue, valueChanged) {\n var editingStoppedEvent = __assign$5(__assign$5({}, this.createEvent(null, Events.EVENT_CELL_EDITING_STOPPED)), { oldValue: oldValue,\n newValue: newValue,\n valueChanged: valueChanged });\n this.beans.eventService.dispatchEvent(editingStoppedEvent);\n };\n // if we are editing inline, then we don't have the padding in the cell (set in the themes)\n // to allow the text editor full access to the entire cell\n CellCtrl.prototype.setInlineEditingClass = function () {\n var _this = this;\n if (!this.isAlive()) {\n return;\n }\n // because of async in React, the cellComp may not be set yet, if no cellComp then we are\n // yet to initialise the cell, so we re-schedule this operation for when celLComp is attached\n if (!this.cellComp) {\n this.onCellCompAttachedFuncs.push(function () { _this.setInlineEditingClass(); });\n return;\n }\n // ag-cell-inline-editing - appears when user is inline editing\n // ag-cell-not-inline-editing - appears when user is no inline editing\n // ag-cell-popup-editing - appears when user is editing cell in popup (appears on the cell, not on the popup)\n // note: one of {ag-cell-inline-editing, ag-cell-not-inline-editing} is always present, they toggle.\n // however {ag-cell-popup-editing} shows when popup, so you have both {ag-cell-popup-editing}\n // and {ag-cell-not-inline-editing} showing at the same time.\n var editingInline = this.editing && !this.editingInPopup;\n var popupEditorShowing = this.editing && this.editingInPopup;\n this.cellComp.addOrRemoveCssClass(CSS_CELL_INLINE_EDITING, editingInline);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_NOT_INLINE_EDITING, !editingInline);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_POPUP_EDITING, popupEditorShowing);\n this.rowCtrl.setInlineEditingCss(this.editing);\n };\n // this is needed as the JS CellComp still allows isPopup() on the CellEditor class, so\n // it's possible the editor is in a popup even though it's not configured via the colDef as so\n CellCtrl.prototype.hackSayEditingInPopup = function () {\n if (this.editingInPopup) {\n return;\n }\n this.editingInPopup = true;\n this.setInlineEditingClass();\n };\n CellCtrl.prototype.createCellEditorParams = function (key, charPress, cellStartedEdit) {\n var res = {\n value: this.getValueFromValueService(),\n key: key,\n eventKey: key,\n charPress: charPress,\n column: this.column,\n colDef: this.column.getColDef(),\n rowIndex: this.getCellPosition().rowIndex,\n node: this.rowNode,\n data: this.rowNode.data,\n api: this.beans.gridOptionsWrapper.getApi(),\n cellStartedEdit: cellStartedEdit,\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext(),\n onKeyDown: this.onKeyDown.bind(this),\n stopEditing: this.stopEditingAndFocus.bind(this),\n eGridCell: this.getGui(),\n parseValue: this.parseValue.bind(this),\n formatValue: this.formatValue.bind(this)\n };\n return res;\n };\n CellCtrl.prototype.createCellRendererParams = function () {\n var _this = this;\n var addRowCompListener = function (eventType, listener) {\n console.warn('AG Grid: since AG Grid v26, params.addRowCompListener() is deprecated. If you need this functionality, please contact AG Grid support and advise why so that we can revert with an appropriate workaround, as we dont have any valid use cases for it. This method was originally provided as a work around to know when cells were destroyed in AG Grid before custom Cell Renderers could be provided.');\n _this.rowCtrl.addEventListener(eventType, listener);\n };\n var res = {\n value: this.value,\n valueFormatted: this.valueFormatted,\n getValue: this.getValueFromValueService.bind(this),\n setValue: function (value) { return _this.beans.valueService.setValue(_this.rowNode, _this.column, value); },\n formatValue: this.formatValue.bind(this),\n data: this.rowNode.data,\n node: this.rowNode,\n pinned: this.column.getPinned(),\n colDef: this.column.getColDef(),\n column: this.column,\n rowIndex: this.getCellPosition().rowIndex,\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext(),\n refreshCell: this.refreshCell.bind(this),\n eGridCell: this.getGui(),\n eParentOfValue: this.cellComp.getParentOfValue(),\n registerRowDragger: function (rowDraggerElement, dragStartPixels, value, suppressVisibilityChange) { return _this.registerRowDragger(rowDraggerElement, dragStartPixels, suppressVisibilityChange); },\n // this function is not documented anywhere, so we could drop it\n // it was in the olden days to allow user to register for when rendered\n // row was removed (the row comp was removed), however now that the user\n // can provide components for cells, the destroy method gets call when this\n // happens so no longer need to fire event.\n addRowCompListener: addRowCompListener\n };\n return res;\n };\n CellCtrl.prototype.parseValue = function (newValue) {\n var colDef = this.column.getColDef();\n var params = {\n node: this.rowNode,\n data: this.rowNode.data,\n oldValue: this.getValue(),\n newValue: newValue,\n colDef: colDef,\n column: this.column,\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext()\n };\n var valueParser = colDef.valueParser;\n return exists(valueParser) ? this.beans.expressionService.evaluate(valueParser, params) : newValue;\n };\n CellCtrl.prototype.setFocusOutOnEditor = function () {\n if (!this.editing) {\n return;\n }\n var cellEditor = this.cellComp.getCellEditor();\n if (cellEditor && cellEditor.focusOut) {\n cellEditor.focusOut();\n }\n };\n CellCtrl.prototype.setFocusInOnEditor = function () {\n if (!this.editing) {\n return;\n }\n var cellEditor = this.cellComp.getCellEditor();\n if (cellEditor && cellEditor.focusIn) {\n // if the editor is present, then we just focus it\n cellEditor.focusIn();\n }\n else {\n // if the editor is not present, it means async cell editor (eg React fibre)\n // and we are trying to set focus before the cell editor is present, so we\n // focus the cell instead\n this.focusCell(true);\n }\n };\n CellCtrl.prototype.onCellChanged = function (event) {\n // because of async in React, the cellComp may not be set yet, if no cellComp then we are\n // yet to initialise the cell, so no need to refresh.\n if (!this.cellComp) {\n return;\n }\n var eventImpactsThisCell = event.column === this.column;\n if (eventImpactsThisCell) {\n this.refreshCell({});\n }\n };\n // + stop editing {forceRefresh: true, suppressFlash: true}\n // + event cellChanged {}\n // + cellRenderer.params.refresh() {} -> method passes 'as is' to the cellRenderer, so params could be anything\n // + rowCtrl: event dataChanged {suppressFlash: !update, newData: !update}\n // + rowCtrl: api refreshCells() {animate: true/false}\n // + rowRenderer: api softRefreshView() {}\n CellCtrl.prototype.refreshCell = function (params) {\n // if we are in the middle of 'stopEditing', then we don't refresh here, as refresh gets called explicitly\n if (this.suppressRefreshCell || this.editing) {\n return;\n }\n // In React, due to async, it's possible a refresh was asked for before the CellComp\n // has been set. If this happens, we skip the refresh, as the cell is going to be\n // initialised anyway once the CellComp is set.\n if (!this.cellComp) {\n return;\n }\n var colDef = this.column.getColDef();\n var newData = params != null && !!params.newData;\n var suppressFlash = (params != null && !!params.suppressFlash) || !!colDef.suppressCellFlash;\n // we always refresh if cell has no value - this can happen when user provides Cell Renderer and the\n // cell renderer doesn't rely on a value, instead it could be looking directly at the data, or maybe\n // printing the current time (which would be silly)???. Generally speaking\n // non of {field, valueGetter, showRowGroup} is bad in the users application, however for this edge case, it's\n // best always refresh and take the performance hit rather than never refresh and users complaining in support\n // that cells are not updating.\n var noValueProvided = colDef.field == null && colDef.valueGetter == null && colDef.showRowGroup == null;\n var forceRefresh = (params && params.forceRefresh) || noValueProvided || newData;\n var valuesDifferent = this.updateAndFormatValue();\n var dataNeedsUpdating = forceRefresh || valuesDifferent;\n if (dataNeedsUpdating) {\n // if it's 'new data', then we don't refresh the cellRenderer, even if refresh method is available.\n // this is because if the whole data is new (ie we are showing stock price 'BBA' now and not 'SSD')\n // then we are not showing a movement in the stock price, rather we are showing different stock.\n this.showValue(newData);\n // we don't want to flash the cells when processing a filter change, as otherwise the UI would\n // be to busy. see comment in FilterManager with regards processingFilterChange\n var processingFilterChange = this.beans.filterManager.isSuppressFlashingCellsBecauseFiltering();\n var flashCell = !suppressFlash && !processingFilterChange &&\n (this.beans.gridOptionsWrapper.isEnableCellChangeFlash() || colDef.enableCellChangeFlash);\n if (flashCell) {\n this.flashCell();\n }\n this.cellCustomStyleFeature.applyUserStyles();\n this.cellCustomStyleFeature.applyClassesFromColDef();\n }\n this.refreshToolTip();\n // we do cellClassRules even if the value has not changed, so that users who have rules that\n // look at other parts of the row (where the other part of the row might of changed) will work.\n this.cellCustomStyleFeature.applyCellClassRules();\n };\n // cell editors call this, when they want to stop for reasons other\n // than what we pick up on. eg selecting from a dropdown ends editing.\n CellCtrl.prototype.stopEditingAndFocus = function (suppressNavigateAfterEdit) {\n if (suppressNavigateAfterEdit === void 0) { suppressNavigateAfterEdit = false; }\n this.stopRowOrCellEdit();\n this.focusCell(true);\n if (!suppressNavigateAfterEdit) {\n this.navigateAfterEdit();\n }\n };\n CellCtrl.prototype.navigateAfterEdit = function () {\n var fullRowEdit = this.beans.gridOptionsWrapper.isFullRowEdit();\n if (fullRowEdit) {\n return;\n }\n var enterMovesDownAfterEdit = this.beans.gridOptionsWrapper.isEnterMovesDownAfterEdit();\n if (enterMovesDownAfterEdit) {\n this.beans.navigationService.navigateToNextCell(null, KeyCode.DOWN, this.getCellPosition(), false);\n }\n };\n // user can also call this via API\n CellCtrl.prototype.flashCell = function (delays) {\n var flashDelay = delays && delays.flashDelay;\n var fadeDelay = delays && delays.fadeDelay;\n this.animateCell('data-changed', flashDelay, fadeDelay);\n };\n CellCtrl.prototype.animateCell = function (cssName, flashDelay, fadeDelay) {\n var _this = this;\n var fullName = \"ag-cell-\" + cssName;\n var animationFullName = \"ag-cell-\" + cssName + \"-animation\";\n var gridOptionsWrapper = this.beans.gridOptionsWrapper;\n if (!flashDelay) {\n flashDelay = gridOptionsWrapper.getCellFlashDelay();\n }\n if (!exists(fadeDelay)) {\n fadeDelay = gridOptionsWrapper.getCellFadeDelay();\n }\n // we want to highlight the cells, without any animation\n this.cellComp.addOrRemoveCssClass(fullName, true);\n this.cellComp.addOrRemoveCssClass(animationFullName, false);\n // then once that is applied, we remove the highlight with animation\n window.setTimeout(function () {\n if (!_this.isAlive()) {\n return;\n }\n _this.cellComp.addOrRemoveCssClass(fullName, false);\n _this.cellComp.addOrRemoveCssClass(animationFullName, true);\n _this.eGui.style.transition = \"background-color \" + fadeDelay + \"ms\";\n window.setTimeout(function () {\n if (!_this.isAlive()) {\n return;\n }\n // and then to leave things as we got them, we remove the animation\n _this.cellComp.addOrRemoveCssClass(animationFullName, false);\n _this.eGui.style.transition = '';\n }, fadeDelay);\n }, flashDelay);\n };\n CellCtrl.prototype.onFlashCells = function (event) {\n if (!this.cellComp) {\n return;\n }\n var cellId = this.beans.cellPositionUtils.createId(this.getCellPosition());\n var shouldFlash = event.cells[cellId];\n if (shouldFlash) {\n this.animateCell('highlight');\n }\n };\n CellCtrl.prototype.isCellEditable = function () {\n return this.column.isCellEditable(this.rowNode);\n };\n CellCtrl.prototype.isSuppressFillHandle = function () {\n return this.column.isSuppressFillHandle();\n };\n CellCtrl.prototype.formatValue = function (value) {\n var res = this.callValueFormatter(value);\n return res != null ? res : value;\n };\n CellCtrl.prototype.callValueFormatter = function (value) {\n return this.beans.valueFormatterService.formatValue(this.column, this.rowNode, value);\n };\n CellCtrl.prototype.updateAndFormatValue = function (force) {\n if (force === void 0) { force = false; }\n var oldValue = this.value;\n var oldValueFormatted = this.valueFormatted;\n this.value = this.getValueFromValueService();\n this.valueFormatted = this.callValueFormatter(this.value);\n var valuesDifferent = force ? true :\n !this.valuesAreEqual(oldValue, this.value) || this.valueFormatted != oldValueFormatted;\n return valuesDifferent;\n };\n CellCtrl.prototype.valuesAreEqual = function (val1, val2) {\n var _a, _b;\n // if the user provided an equals method, use that, otherwise do simple comparison\n var colDef = this.column.getColDef();\n return colDef.equals ? colDef.equals(val1, val2) : typeof val1 === typeof val2 && ((_a = val1) === null || _a === void 0 ? void 0 : _a.toString()) === ((_b = val2) === null || _b === void 0 ? void 0 : _b.toString());\n };\n CellCtrl.prototype.getComp = function () {\n return this.cellComp;\n };\n CellCtrl.prototype.getValueFromValueService = function () {\n // if we don't check this, then the grid will render leaf groups as open even if we are not\n // allowing the user to open leaf groups. confused? remember for pivot mode we don't allow\n // opening leaf groups, so we have to force leafGroups to be closed in case the user expanded\n // them via the API, or user user expanded them in the UI before turning on pivot mode\n var lockedClosedGroup = this.rowNode.leafGroup && this.beans.columnModel.isPivotMode();\n var isOpenGroup = this.rowNode.group && this.rowNode.expanded && !this.rowNode.footer && !lockedClosedGroup;\n // are we showing group footers\n var groupFootersEnabled = this.beans.gridOptionsWrapper.isGroupIncludeFooter();\n // if doing footers, we normally don't show agg data at group level when group is open\n var groupAlwaysShowAggData = this.beans.gridOptionsWrapper.isGroupSuppressBlankHeader();\n // if doing grouping and footers, we don't want to include the agg value\n // in the header when the group is open\n var ignoreAggData = (isOpenGroup && groupFootersEnabled) && !groupAlwaysShowAggData;\n var value = this.beans.valueService.getValue(this.column, this.rowNode, false, ignoreAggData);\n return value;\n };\n CellCtrl.prototype.getValue = function () {\n return this.value;\n };\n CellCtrl.prototype.getValueFormatted = function () {\n return this.valueFormatted;\n };\n CellCtrl.prototype.addDomData = function () {\n var _this = this;\n var element = this.getGui();\n this.beans.gridOptionsWrapper.setDomData(element, CellCtrl.DOM_DATA_KEY_CELL_CTRL, this);\n this.addDestroyFunc(function () { return _this.beans.gridOptionsWrapper.setDomData(element, CellCtrl.DOM_DATA_KEY_CELL_CTRL, null); });\n };\n CellCtrl.prototype.createEvent = function (domEvent, eventType) {\n var event = {\n type: eventType,\n node: this.rowNode,\n data: this.rowNode.data,\n value: this.value,\n column: this.column,\n colDef: this.column.getColDef(),\n context: this.beans.gridOptionsWrapper.getContext(),\n api: this.beans.gridApi,\n columnApi: this.beans.columnApi,\n rowPinned: this.rowNode.rowPinned,\n event: domEvent,\n rowIndex: this.rowNode.rowIndex\n };\n return event;\n };\n CellCtrl.prototype.onKeyPress = function (event) {\n this.cellKeyboardListenerFeature.onKeyPress(event);\n };\n CellCtrl.prototype.onKeyDown = function (event) {\n this.cellKeyboardListenerFeature.onKeyDown(event);\n };\n CellCtrl.prototype.onMouseEvent = function (eventName, mouseEvent) {\n this.cellMouseListenerFeature.onMouseEvent(eventName, mouseEvent);\n };\n CellCtrl.prototype.getGui = function () {\n return this.eGui;\n };\n CellCtrl.prototype.refreshToolTip = function () {\n this.tooltipFeature.refreshToolTip();\n };\n CellCtrl.prototype.getColSpanningList = function () {\n return this.cellPositionFeature.getColSpanningList();\n };\n CellCtrl.prototype.onLeftChanged = function () {\n if (!this.cellComp) {\n return;\n }\n this.cellPositionFeature.onLeftChanged();\n };\n CellCtrl.prototype.onDisplayedColumnsChanged = function () {\n if (!this.eGui) {\n return;\n }\n this.setAriaColIndex();\n };\n CellCtrl.prototype.setAriaColIndex = function () {\n var colIdx = this.beans.columnModel.getAriaColumnIndex(this.column);\n setAriaColIndex(this.getGui(), colIdx); // for react, we don't use JSX, as it slowed down column moving\n };\n CellCtrl.prototype.isSuppressNavigable = function () {\n return this.column.isSuppressNavigable(this.rowNode);\n };\n CellCtrl.prototype.onWidthChanged = function () {\n return this.cellPositionFeature.onWidthChanged();\n };\n CellCtrl.prototype.getColumn = function () {\n return this.column;\n };\n CellCtrl.prototype.getRowNode = function () {\n return this.rowNode;\n };\n CellCtrl.prototype.getBeans = function () {\n return this.beans;\n };\n CellCtrl.prototype.isPrintLayout = function () {\n return this.printLayout;\n };\n CellCtrl.prototype.appendChild = function (htmlElement) {\n this.eGui.appendChild(htmlElement);\n };\n CellCtrl.prototype.refreshHandle = function () {\n if (this.cellRangeFeature) {\n this.cellRangeFeature.refreshHandle();\n }\n };\n CellCtrl.prototype.getCellPosition = function () {\n return this.cellPosition;\n };\n CellCtrl.prototype.isEditing = function () {\n return this.editing;\n };\n // called by rowRenderer when user navigates via tab key\n CellCtrl.prototype.startRowOrCellEdit = function (key, charPress, event) {\n if (event === void 0) { event = null; }\n if (!this.cellComp) {\n return;\n }\n if (this.beans.gridOptionsWrapper.isFullRowEdit()) {\n this.rowCtrl.startRowEditing(key, charPress, this);\n }\n else {\n this.startEditing(key, charPress, true, event);\n }\n };\n CellCtrl.prototype.getRowCtrl = function () {\n return this.rowCtrl;\n };\n CellCtrl.prototype.getRowPosition = function () {\n return {\n rowIndex: this.cellPosition.rowIndex,\n rowPinned: this.cellPosition.rowPinned\n };\n };\n CellCtrl.prototype.updateRangeBordersIfRangeCount = function () {\n if (!this.cellComp) {\n return;\n }\n if (this.cellRangeFeature) {\n this.cellRangeFeature.updateRangeBordersIfRangeCount();\n }\n };\n CellCtrl.prototype.onRangeSelectionChanged = function () {\n if (!this.cellComp) {\n return;\n }\n if (this.cellRangeFeature) {\n this.cellRangeFeature.onRangeSelectionChanged();\n }\n };\n CellCtrl.prototype.isRangeSelectionEnabled = function () {\n return this.cellRangeFeature != null;\n };\n CellCtrl.prototype.focusCell = function (forceBrowserFocus) {\n if (forceBrowserFocus === void 0) { forceBrowserFocus = false; }\n this.beans.focusService.setFocusedCell({\n rowIndex: this.getCellPosition().rowIndex,\n column: this.column,\n rowPinned: this.rowNode.rowPinned,\n forceBrowserFocus: forceBrowserFocus\n });\n };\n CellCtrl.prototype.onRowIndexChanged = function () {\n // when index changes, this influences items that need the index, so we update the\n // grid cell so they are working off the new index.\n this.createCellPosition();\n // when the index of the row changes, ie means the cell may have lost or gained focus\n this.onCellFocused();\n // check range selection\n if (this.cellRangeFeature) {\n this.cellRangeFeature.onRangeSelectionChanged();\n }\n };\n CellCtrl.prototype.onFirstRightPinnedChanged = function () {\n if (!this.cellComp) {\n return;\n }\n var firstRightPinned = this.column.isFirstRightPinned();\n this.cellComp.addOrRemoveCssClass(CSS_CELL_FIRST_RIGHT_PINNED, firstRightPinned);\n };\n CellCtrl.prototype.onLastLeftPinnedChanged = function () {\n if (!this.cellComp) {\n return;\n }\n var lastLeftPinned = this.column.isLastLeftPinned();\n this.cellComp.addOrRemoveCssClass(CSS_CELL_LAST_LEFT_PINNED, lastLeftPinned);\n };\n CellCtrl.prototype.onCellFocused = function (event) {\n if (!this.cellComp || this.gow.isSuppressCellFocus()) {\n return;\n }\n var cellFocused = this.beans.focusService.isCellFocused(this.cellPosition);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_FOCUS, cellFocused);\n // see if we need to force browser focus - this can happen if focus is programmatically set\n if (cellFocused && event && event.forceBrowserFocus) {\n var focusEl = this.cellComp.getFocusableElement();\n focusEl.focus({ preventScroll: !!event.preventScrollOnBrowserFocus });\n }\n // if another cell was focused, and we are editing, then stop editing\n var fullRowEdit = this.beans.gridOptionsWrapper.isFullRowEdit();\n if (!cellFocused && !fullRowEdit && this.editing) {\n this.stopRowOrCellEdit();\n }\n };\n CellCtrl.prototype.createCellPosition = function () {\n this.cellPosition = {\n rowIndex: this.rowNode.rowIndex,\n rowPinned: makeNull(this.rowNode.rowPinned),\n column: this.column\n };\n };\n // CSS Classes that only get applied once, they never change\n CellCtrl.prototype.applyStaticCssClasses = function () {\n this.cellComp.addOrRemoveCssClass(CSS_CELL, true);\n this.cellComp.addOrRemoveCssClass(CSS_CELL_NOT_INLINE_EDITING, true);\n // normal cells fill the height of the row. autoHeight cells have no height to let them\n // fit the height of content.\n var autoHeight = this.column.isAutoHeight() == true;\n this.cellComp.addOrRemoveCssClass(CSS_AUTO_HEIGHT, autoHeight);\n this.cellComp.addOrRemoveCssClass(CSS_NORMAL_HEIGHT, !autoHeight);\n };\n CellCtrl.prototype.onColumnHover = function () {\n if (!this.cellComp) {\n return;\n }\n if (!this.beans.gridOptionsWrapper.isColumnHoverHighlight()) {\n return;\n }\n var isHovered = this.beans.columnHoverService.isHovered(this.column);\n this.cellComp.addOrRemoveCssClass(CSS_COLUMN_HOVER, isHovered);\n };\n CellCtrl.prototype.onColDefChanged = function () {\n if (!this.cellComp) {\n return;\n }\n this.setWrapText();\n if (!this.editing) {\n this.refreshCell({ forceRefresh: true, suppressFlash: true });\n }\n };\n CellCtrl.prototype.setWrapText = function () {\n var value = this.column.getColDef().wrapText == true;\n this.cellComp.addOrRemoveCssClass(CSS_CELL_WRAP_TEXT, value);\n };\n CellCtrl.prototype.dispatchCellContextMenuEvent = function (event) {\n var colDef = this.column.getColDef();\n var cellContextMenuEvent = this.createEvent(event, Events.EVENT_CELL_CONTEXT_MENU);\n this.beans.eventService.dispatchEvent(cellContextMenuEvent);\n if (colDef.onCellContextMenu) {\n // to make the callback async, do in a timeout\n window.setTimeout(function () { return colDef.onCellContextMenu(cellContextMenuEvent); }, 0);\n }\n };\n CellCtrl.prototype.getCellRenderer = function () {\n return this.cellComp ? this.cellComp.getCellRenderer() : null;\n };\n CellCtrl.prototype.getCellEditor = function () {\n return this.cellComp ? this.cellComp.getCellEditor() : null;\n };\n CellCtrl.prototype.destroy = function () {\n this.onCellCompAttachedFuncs = [];\n if (this.removeAutoHeightListeners) {\n this.removeAutoHeightListeners();\n this.removeAutoHeightListeners = null;\n }\n _super.prototype.destroy.call(this);\n };\n CellCtrl.prototype.createSelectionCheckbox = function () {\n var cbSelectionComponent = new CheckboxSelectionComponent();\n this.beans.context.createBean(cbSelectionComponent);\n cbSelectionComponent.init({ rowNode: this.rowNode, column: this.column });\n // put the checkbox in before the value\n return cbSelectionComponent;\n };\n CellCtrl.prototype.createDndSource = function () {\n var dndSourceComp = new DndSourceComp(this.rowNode, this.column, this.beans, this.eGui);\n this.beans.context.createBean(dndSourceComp);\n return dndSourceComp;\n };\n CellCtrl.prototype.registerRowDragger = function (customElement, dragStartPixels, suppressVisibilityChange) {\n var _this = this;\n // if previously existed, then we are only updating\n if (this.customRowDragComp) {\n this.customRowDragComp.setDragElement(customElement, dragStartPixels);\n return;\n }\n var newComp = this.createRowDragComp(customElement, dragStartPixels, suppressVisibilityChange);\n if (newComp) {\n this.customRowDragComp = newComp;\n this.addDestroyFunc(function () { return _this.beans.context.destroyBean(newComp); });\n }\n };\n CellCtrl.prototype.createRowDragComp = function (customElement, dragStartPixels, suppressVisibilityChange) {\n var _this = this;\n var pagination = this.beans.gridOptionsWrapper.isPagination();\n var rowDragManaged = this.beans.gridOptionsWrapper.isRowDragManaged();\n var clientSideRowModelActive = this.beans.gridOptionsWrapper.isRowModelDefault();\n if (rowDragManaged) {\n // row dragging only available in default row model\n if (!clientSideRowModelActive) {\n doOnce(function () { return console.warn('AG Grid: managed row dragging is only allowed in the Client Side Row Model'); }, 'CellComp.addRowDragging');\n return;\n }\n if (pagination) {\n doOnce(function () { return console.warn('AG Grid: managed row dragging is not possible when doing pagination'); }, 'CellComp.addRowDragging');\n return;\n }\n }\n // otherwise (normal case) we are creating a RowDraggingComp for the first time\n var rowDragComp = new RowDragComp(function () { return _this.value; }, this.rowNode, this.column, customElement, dragStartPixels, suppressVisibilityChange);\n this.beans.context.createBean(rowDragComp);\n return rowDragComp;\n };\n CellCtrl.DOM_DATA_KEY_CELL_CTRL = 'cellCtrl';\n return CellCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1U = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __values$2 = (undefined && undefined.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\nvar __read$h = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$d = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$h(arguments[i]));\n return ar;\n};\nvar RowType$1;\n(function (RowType) {\n RowType[\"Normal\"] = \"Normal\";\n RowType[\"FullWidth\"] = \"FullWidth\";\n RowType[\"FullWidthLoading\"] = \"FullWidthLoading\";\n RowType[\"FullWidthGroup\"] = \"FullWidthGroup\";\n RowType[\"FullWidthDetail\"] = \"FullWidthDetail\";\n})(RowType$1 || (RowType$1 = {}));\nvar instanceIdSequence$2 = 0;\nvar RowCtrl = /** @class */ (function (_super) {\n __extends$1U(RowCtrl, _super);\n function RowCtrl(rowNode, beans, animateIn, useAnimationFrameForCreate, printLayout) {\n var _this = _super.call(this) || this;\n _this.allRowGuis = [];\n _this.active = true;\n _this.centerCellCtrls = { list: [], map: {} };\n _this.leftCellCtrls = { list: [], map: {} };\n _this.rightCellCtrls = { list: [], map: {} };\n _this.lastMouseDownOnDragger = false;\n _this.updateColumnListsPending = false;\n _this.beans = beans;\n _this.rowNode = rowNode;\n _this.paginationPage = _this.beans.paginationProxy.getCurrentPage();\n _this.useAnimationFrameForCreate = useAnimationFrameForCreate;\n _this.printLayout = printLayout;\n _this.instanceId = rowNode.id + '-' + instanceIdSequence$2++;\n _this.setAnimateFlags(animateIn);\n _this.rowFocused = _this.beans.focusService.isRowFocused(_this.rowNode.rowIndex, _this.rowNode.rowPinned);\n _this.rowLevel = _this.beans.rowCssClassCalculator.calculateRowLevel(_this.rowNode);\n _this.setRowType();\n _this.addListeners();\n return _this;\n }\n RowCtrl.prototype.isSticky = function () {\n return this.rowNode.sticky;\n };\n RowCtrl.prototype.getBeans = function () {\n return this.beans;\n };\n RowCtrl.prototype.getInstanceId = function () {\n return this.instanceId;\n };\n RowCtrl.prototype.setComp = function (rowComp, element, containerType) {\n var gui = { rowComp: rowComp, element: element, containerType: containerType };\n this.allRowGuis.push(gui);\n if (containerType === RowContainerType.LEFT) {\n this.leftGui = gui;\n }\n else if (containerType === RowContainerType.RIGHT) {\n this.rightGui = gui;\n }\n else if (containerType === RowContainerType.FULL_WIDTH) {\n this.fullWidthGui = gui;\n }\n else {\n this.centerGui = gui;\n }\n var allNormalPresent = this.leftGui != null && this.rightGui != null && this.centerGui != null;\n var fullWidthPresent = this.fullWidthGui != null;\n if (allNormalPresent || fullWidthPresent) {\n this.initialiseRowComps();\n }\n if (this.rowType !== 'FullWidthLoading') {\n // this is fired within setComp as we know that the component renderer is now trying to render.\n // linked with the fact the function implementation queues behind requestAnimationFrame should allow\n // us to be certain that all rendering is done by the time the event fires.\n this.beans.rowRenderer.dispatchFirstDataRenderedEvent();\n }\n };\n RowCtrl.prototype.isCacheable = function () {\n return this.rowType === RowType$1.FullWidthDetail\n && this.beans.gridOptionsWrapper.isKeepDetailRows();\n };\n RowCtrl.prototype.setCached = function (cached) {\n var displayValue = cached ? 'none' : '';\n this.allRowGuis.forEach(function (rg) { return rg.element.style.display = displayValue; });\n };\n RowCtrl.prototype.initialiseRowComps = function () {\n var _this = this;\n var gow = this.beans.gridOptionsWrapper;\n this.onRowHeightChanged();\n this.updateRowIndexes();\n this.setFocusedClasses();\n this.setStylesFromGridOptions();\n if (gow.isRowSelection() && this.rowNode.selectable) {\n this.onRowSelected();\n }\n this.updateColumnLists(!this.useAnimationFrameForCreate);\n if (this.slideRowIn) {\n executeNextVMTurn(this.onTopChanged.bind(this));\n }\n if (this.fadeRowIn) {\n executeNextVMTurn(function () {\n _this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass('ag-opacity-zero', false); });\n });\n }\n var businessKey = this.getRowBusinessKey();\n var rowIdSanitised = escapeString(this.rowNode.id);\n var businessKeySanitised = escapeString(businessKey);\n this.allRowGuis.forEach(function (gui) {\n var comp = gui.rowComp;\n comp.setRole('row');\n var initialRowClasses = _this.getInitialRowClasses(gui.containerType);\n initialRowClasses.forEach(function (name) { return comp.addOrRemoveCssClass(name, true); });\n if (_this.rowNode.group) {\n setAriaExpanded(gui.element, _this.rowNode.expanded == true);\n }\n if (rowIdSanitised != null) {\n comp.setRowId(rowIdSanitised);\n }\n if (businessKeySanitised != null) {\n comp.setRowBusinessKey(businessKeySanitised);\n }\n if (_this.isFullWidth() && !_this.beans.gridOptionsWrapper.isSuppressCellFocus()) {\n comp.setTabIndex(-1);\n }\n // DOM DATA\n gow.setDomData(gui.element, RowCtrl.DOM_DATA_KEY_ROW_CTRL, _this);\n _this.addDestroyFunc(function () { return gow.setDomData(gui.element, RowCtrl.DOM_DATA_KEY_ROW_CTRL, null); });\n // adding hover functionality adds listener to this row, so we\n // do it lazily in an animation frame\n if (_this.useAnimationFrameForCreate) {\n _this.beans.animationFrameService.createTask(_this.addHoverFunctionality.bind(_this, gui.element), _this.rowNode.rowIndex, 'createTasksP2');\n }\n else {\n _this.addHoverFunctionality(gui.element);\n }\n if (_this.isFullWidth()) {\n _this.setupFullWidth(gui);\n }\n if (gow.isRowDragEntireRow()) {\n _this.addRowDraggerToRow(gui);\n }\n if (_this.useAnimationFrameForCreate) {\n // the height animation we only want active after the row is alive for 1 second.\n // this stops the row animation working when rows are initially crated. otherwise\n // auto-height rows get inserted into the dom and resized immediately, which gives\n // very bad UX (eg 10 rows get inserted, then all 10 expand, look particularly bad\n // when scrolling). so this makes sure when rows are shown for the first time, they\n // are resized immediately without animation.\n _this.beans.animationFrameService.addDestroyTask(function () {\n if (!_this.isAlive()) {\n return;\n }\n gui.rowComp.addOrRemoveCssClass('ag-after-created', true);\n });\n }\n });\n this.executeProcessRowPostCreateFunc();\n };\n RowCtrl.prototype.addRowDraggerToRow = function (gui) {\n var gow = this.beans.gridOptionsWrapper;\n if (gow.isEnableRangeSelection()) {\n doOnce(function () {\n console.warn('AG Grid: Setting `rowDragEntireRow: true` in the gridOptions doesn\\'t work with `enableRangeSelection: true`');\n }, 'rowDragAndRangeSelectionEnabled');\n return;\n }\n var translate = gow.getLocaleTextFunc();\n var rowDragComp = new RowDragComp(function () { return \"1 \" + translate('rowDragRow', 'row'); }, this.rowNode, undefined, gui.element, undefined, true);\n this.createManagedBean(rowDragComp, this.beans.context);\n };\n RowCtrl.prototype.setupFullWidth = function (gui) {\n var pinned = this.getPinnedForContainer(gui.containerType);\n var params = this.createFullWidthParams(gui.element, pinned);\n var masterDetailModuleLoaded = ModuleRegistry.isRegistered(ModuleNames.MasterDetailModule);\n if (this.rowType == RowType$1.FullWidthDetail && !masterDetailModuleLoaded) {\n if (ModuleRegistry.isPackageBased()) {\n console.warn(\"AG Grid: cell renderer 'agDetailCellRenderer' (for master detail) not found. Can only be used with ag-grid-enterprise package.\");\n }\n else {\n console.warn(\"AG Grid: cell renderer 'agDetailCellRenderer' (for master detail) not found. Can only be used with AG Grid Enterprise Module \" + ModuleNames.MasterDetailModule);\n }\n return;\n }\n var compDetails;\n switch (this.rowType) {\n case RowType$1.FullWidthDetail:\n compDetails = this.beans.userComponentFactory.getFullWidthDetailCellRendererDetails(params);\n break;\n case RowType$1.FullWidthGroup:\n compDetails = this.beans.userComponentFactory.getFullWidthGroupCellRendererDetails(params);\n break;\n case RowType$1.FullWidthLoading:\n compDetails = this.beans.userComponentFactory.getFullWidthLoadingCellRendererDetails(params);\n break;\n default:\n compDetails = this.beans.userComponentFactory.getFullWidthCellRendererDetails(params);\n break;\n }\n gui.rowComp.showFullWidth(compDetails);\n };\n RowCtrl.prototype.isPrintLayout = function () {\n return this.printLayout;\n };\n // use by autoWidthCalculator, as it clones the elements\n RowCtrl.prototype.getCellElement = function (column) {\n var cellCtrl = this.getCellCtrl(column);\n return cellCtrl ? cellCtrl.getGui() : null;\n };\n RowCtrl.prototype.executeProcessRowPostCreateFunc = function () {\n var func = this.beans.gridOptionsWrapper.getProcessRowPostCreateFunc();\n if (!func) {\n return;\n }\n var params = {\n eRow: this.centerGui ? this.centerGui.element : undefined,\n ePinnedLeftRow: this.leftGui ? this.leftGui.element : undefined,\n ePinnedRightRow: this.rightGui ? this.rightGui.element : undefined,\n node: this.rowNode,\n rowIndex: this.rowNode.rowIndex,\n addRenderedRowListener: this.addEventListener.bind(this),\n };\n func(params);\n };\n RowCtrl.prototype.setRowType = function () {\n var isStub = this.rowNode.stub;\n var isFullWidthCell = this.rowNode.isFullWidthCell();\n var isDetailCell = this.beans.doingMasterDetail && this.rowNode.detail;\n var pivotMode = this.beans.columnModel.isPivotMode();\n // we only use full width for groups, not footers. it wouldn't make sense to include footers if not looking\n // for totals. if users complain about this, then we should introduce a new property 'footerUseEntireRow'\n // so each can be set independently (as a customer complained about footers getting full width, hence\n // introducing this logic)\n var isGroupRow = !!this.rowNode.group && !this.rowNode.footer;\n var isFullWidthGroup = isGroupRow && this.beans.gridOptionsWrapper.isGroupUseEntireRow(pivotMode);\n if (isStub) {\n this.rowType = RowType$1.FullWidthLoading;\n }\n else if (isDetailCell) {\n this.rowType = RowType$1.FullWidthDetail;\n }\n else if (isFullWidthCell) {\n this.rowType = RowType$1.FullWidth;\n }\n else if (isFullWidthGroup) {\n this.rowType = RowType$1.FullWidthGroup;\n }\n else {\n this.rowType = RowType$1.Normal;\n }\n };\n RowCtrl.prototype.updateColumnLists = function (suppressAnimationFrame) {\n var _this = this;\n if (suppressAnimationFrame === void 0) { suppressAnimationFrame = false; }\n if (this.isFullWidth()) {\n return;\n }\n var noAnimation = suppressAnimationFrame\n || this.beans.gridOptionsWrapper.isSuppressAnimationFrame()\n || this.printLayout;\n if (noAnimation) {\n this.updateColumnListsImpl();\n return;\n }\n if (this.updateColumnListsPending) {\n return;\n }\n this.beans.animationFrameService.createTask(function () {\n if (!_this.active) {\n return;\n }\n _this.updateColumnListsImpl();\n }, this.rowNode.rowIndex, 'createTasksP1');\n this.updateColumnListsPending = true;\n };\n RowCtrl.prototype.createCellCtrls = function (prev, cols, pinned) {\n var _this = this;\n if (pinned === void 0) { pinned = null; }\n var res = {\n list: [],\n map: {}\n };\n var addCell = function (colInstanceId, cellCtrl) {\n res.list.push(cellCtrl);\n res.map[colInstanceId] = cellCtrl;\n };\n cols.forEach(function (col) {\n // we use instanceId's rather than colId as it's possible there is a Column with same Id,\n // but it's referring to a different column instance. Happens a lot with pivot, as pivot col id's are\n // reused eg pivot_0, pivot_1 etc\n var colInstanceId = col.getInstanceId();\n var cellCtrl = prev.map[colInstanceId];\n if (!cellCtrl) {\n cellCtrl = new CellCtrl(col, _this.rowNode, _this.beans, _this);\n }\n addCell(colInstanceId, cellCtrl);\n });\n prev.list.forEach(function (prevCellCtrl) {\n var cellInResult = res.map[prevCellCtrl.getColumn().getInstanceId()] != null;\n if (cellInResult) {\n return;\n }\n var keepCell = !_this.isCellEligibleToBeRemoved(prevCellCtrl, pinned);\n if (keepCell) {\n addCell(prevCellCtrl.getColumn().getInstanceId(), prevCellCtrl);\n return;\n }\n prevCellCtrl.destroy();\n });\n return res;\n };\n RowCtrl.prototype.updateColumnListsImpl = function () {\n var _this = this;\n this.updateColumnListsPending = false;\n var columnModel = this.beans.columnModel;\n if (this.printLayout) {\n this.centerCellCtrls = this.createCellCtrls(this.centerCellCtrls, columnModel.getAllDisplayedColumns());\n this.leftCellCtrls = { list: [], map: {} };\n this.rightCellCtrls = { list: [], map: {} };\n }\n else {\n var centerCols = columnModel.getViewportCenterColumnsForRow(this.rowNode);\n this.centerCellCtrls = this.createCellCtrls(this.centerCellCtrls, centerCols);\n var leftCols = columnModel.getDisplayedLeftColumnsForRow(this.rowNode);\n this.leftCellCtrls = this.createCellCtrls(this.leftCellCtrls, leftCols, Constants.PINNED_LEFT);\n var rightCols = columnModel.getDisplayedRightColumnsForRow(this.rowNode);\n this.rightCellCtrls = this.createCellCtrls(this.rightCellCtrls, rightCols, Constants.PINNED_RIGHT);\n }\n this.allRowGuis.forEach(function (item) {\n var cellControls = item.containerType === RowContainerType.LEFT ? _this.leftCellCtrls :\n item.containerType === RowContainerType.RIGHT ? _this.rightCellCtrls : _this.centerCellCtrls;\n item.rowComp.setCellCtrls(cellControls.list);\n });\n };\n RowCtrl.prototype.isCellEligibleToBeRemoved = function (cellCtrl, nextContainerPinned) {\n var REMOVE_CELL = true;\n var KEEP_CELL = false;\n // always remove the cell if it's not rendered or if it's in the wrong pinned location\n var column = cellCtrl.getColumn();\n if (column.getPinned() != nextContainerPinned) {\n return REMOVE_CELL;\n }\n // we want to try and keep editing and focused cells\n var editing = cellCtrl.isEditing();\n var focused = this.beans.focusService.isCellFocused(cellCtrl.getCellPosition());\n var mightWantToKeepCell = editing || focused;\n if (mightWantToKeepCell) {\n var column_1 = cellCtrl.getColumn();\n var displayedColumns = this.beans.columnModel.getAllDisplayedColumns();\n var cellStillDisplayed = displayedColumns.indexOf(column_1) >= 0;\n return cellStillDisplayed ? KEEP_CELL : REMOVE_CELL;\n }\n return REMOVE_CELL;\n };\n RowCtrl.prototype.setAnimateFlags = function (animateIn) {\n if (!this.isSticky() && animateIn) {\n var oldRowTopExists = exists(this.rowNode.oldRowTop);\n // if the row had a previous position, we slide it in (animate row top)\n this.slideRowIn = oldRowTopExists;\n // if the row had no previous position, we fade it in (animate\n this.fadeRowIn = !oldRowTopExists;\n }\n else {\n this.slideRowIn = false;\n this.fadeRowIn = false;\n }\n };\n RowCtrl.prototype.isEditing = function () {\n return this.editingRow;\n };\n RowCtrl.prototype.stopRowEditing = function (cancel) {\n this.stopEditing(cancel);\n };\n RowCtrl.prototype.isFullWidth = function () {\n return this.rowType !== RowType$1.Normal;\n };\n RowCtrl.prototype.getRowType = function () {\n return this.rowType;\n };\n RowCtrl.prototype.refreshFullWidth = function () {\n var _this = this;\n // returns 'true' if refresh succeeded\n var tryRefresh = function (gui, pinned) {\n if (!gui) {\n return true;\n } // no refresh needed\n var cellRenderer = gui.rowComp.getFullWidthCellRenderer();\n // no cell renderer, either means comp not yet ready, or comp ready but now reference\n // to it (happens in react when comp is stateless). if comp not ready, we don't need to\n // refresh, however we don't know which one, so we refresh to cover the case where it's\n // react comp without reference so need to force a refresh\n if (!cellRenderer) {\n return false;\n }\n // no refresh method present, so can't refresh, hard refresh needed\n if (!cellRenderer.refresh) {\n return false;\n }\n var params = _this.createFullWidthParams(gui.element, pinned);\n var refreshSucceeded = cellRenderer.refresh(params);\n return refreshSucceeded;\n };\n var fullWidthSuccess = tryRefresh(this.fullWidthGui, null);\n var centerSuccess = tryRefresh(this.centerGui, null);\n var leftSuccess = tryRefresh(this.leftGui, Constants.PINNED_LEFT);\n var rightSuccess = tryRefresh(this.rightGui, Constants.PINNED_RIGHT);\n var allFullWidthRowsRefreshed = fullWidthSuccess && centerSuccess && leftSuccess && rightSuccess;\n return allFullWidthRowsRefreshed;\n };\n RowCtrl.prototype.addListeners = function () {\n this.addManagedListener(this.rowNode, RowNode.EVENT_HEIGHT_CHANGED, this.onRowHeightChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_ROW_SELECTED, this.onRowSelected.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_ROW_INDEX_CHANGED, this.onRowIndexChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_TOP_CHANGED, this.onTopChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_EXPANDED_CHANGED, this.updateExpandedCss.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_HAS_CHILDREN_CHANGED, this.updateExpandedCss.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_DATA_CHANGED, this.onRowNodeDataChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, this.onRowNodeCellChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_HIGHLIGHT_CHANGED, this.onRowNodeHighlightChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_DRAGGING_CHANGED, this.onRowNodeDraggingChanged.bind(this));\n this.addManagedListener(this.rowNode, RowNode.EVENT_UI_LEVEL_CHANGED, this.onUiLevelChanged.bind(this));\n var eventService = this.beans.eventService;\n this.addManagedListener(eventService, Events.EVENT_PAGINATION_PIXEL_OFFSET_CHANGED, this.onPaginationPixelOffsetChanged.bind(this));\n this.addManagedListener(eventService, Events.EVENT_HEIGHT_SCALE_CHANGED, this.onTopChanged.bind(this));\n this.addManagedListener(eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));\n this.addManagedListener(eventService, Events.EVENT_VIRTUAL_COLUMNS_CHANGED, this.onVirtualColumnsChanged.bind(this));\n this.addManagedListener(eventService, Events.EVENT_CELL_FOCUSED, this.onCellFocusChanged.bind(this));\n this.addManagedListener(eventService, Events.EVENT_PAGINATION_CHANGED, this.onPaginationChanged.bind(this));\n this.addManagedListener(eventService, Events.EVENT_MODEL_UPDATED, this.onModelUpdated.bind(this));\n this.addManagedListener(eventService, Events.EVENT_COLUMN_MOVED, this.onColumnMoved.bind(this));\n this.addListenersForCellComps();\n };\n RowCtrl.prototype.onColumnMoved = function () {\n this.updateColumnLists();\n };\n RowCtrl.prototype.addListenersForCellComps = function () {\n var _this = this;\n this.addManagedListener(this.rowNode, RowNode.EVENT_ROW_INDEX_CHANGED, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onRowIndexChanged(); });\n });\n this.addManagedListener(this.rowNode, RowNode.EVENT_CELL_CHANGED, function (event) {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onCellChanged(event); });\n });\n };\n RowCtrl.prototype.onRowNodeDataChanged = function (event) {\n // if this is an update, we want to refresh, as this will allow the user to put in a transition\n // into the cellRenderer refresh method. otherwise this might be completely new data, in which case\n // we will want to completely replace the cells\n this.getAllCellCtrls().forEach(function (cellCtrl) {\n return cellCtrl.refreshCell({\n suppressFlash: !event.update,\n newData: !event.update\n });\n });\n // check for selected also, as this could be after lazy loading of the row data, in which case\n // the id might of just gotten set inside the row and the row selected state may of changed\n // as a result. this is what happens when selected rows are loaded in virtual pagination.\n // - niall note - since moving to the stub component, this may no longer be true, as replacing\n // the stub component now replaces the entire row\n this.onRowSelected();\n // as data has changed, then the style and class needs to be recomputed\n this.postProcessCss();\n };\n RowCtrl.prototype.onRowNodeCellChanged = function () {\n // as data has changed, then the style and class needs to be recomputed\n this.postProcessCss();\n };\n RowCtrl.prototype.postProcessCss = function () {\n this.setStylesFromGridOptions();\n this.postProcessClassesFromGridOptions();\n this.postProcessRowClassRules();\n this.postProcessRowDragging();\n };\n RowCtrl.prototype.onRowNodeHighlightChanged = function () {\n var highlighted = this.rowNode.highlighted;\n this.allRowGuis.forEach(function (gui) {\n var aboveOn = highlighted === RowHighlightPosition.Above;\n var belowOn = highlighted === RowHighlightPosition.Below;\n gui.rowComp.addOrRemoveCssClass('ag-row-highlight-above', aboveOn);\n gui.rowComp.addOrRemoveCssClass('ag-row-highlight-below', belowOn);\n });\n };\n RowCtrl.prototype.onRowNodeDraggingChanged = function () {\n this.postProcessRowDragging();\n };\n RowCtrl.prototype.postProcessRowDragging = function () {\n var dragging = this.rowNode.dragging;\n this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass('ag-row-dragging', dragging); });\n };\n RowCtrl.prototype.updateExpandedCss = function () {\n var expandable = this.rowNode.isExpandable();\n var expanded = this.rowNode.expanded == true;\n this.allRowGuis.forEach(function (gui) {\n gui.rowComp.addOrRemoveCssClass('ag-row-group', expandable);\n gui.rowComp.addOrRemoveCssClass('ag-row-group-expanded', expandable && expanded);\n gui.rowComp.addOrRemoveCssClass('ag-row-group-contracted', expandable && !expanded);\n setAriaExpanded(gui.element, expandable && expanded);\n });\n };\n RowCtrl.prototype.onDisplayedColumnsChanged = function () {\n // we skip animations for onDisplayedColumnChanged, as otherwise the client could remove columns and\n // then set data, and any old valueGetter's (ie from cols that were removed) would still get called.\n this.updateColumnLists(true);\n if (this.beans.columnModel.wasAutoRowHeightEverActive()) {\n this.rowNode.checkAutoHeights();\n }\n };\n RowCtrl.prototype.onVirtualColumnsChanged = function () {\n this.updateColumnLists();\n };\n RowCtrl.prototype.getRowPosition = function () {\n return {\n rowPinned: makeNull(this.rowNode.rowPinned),\n rowIndex: this.rowNode.rowIndex\n };\n };\n RowCtrl.prototype.onKeyboardNavigate = function (keyboardEvent) {\n var currentFullWidthComp = this.allRowGuis.find(function (c) { return c.element.contains(keyboardEvent.target); });\n var currentFullWidthContainer = currentFullWidthComp ? currentFullWidthComp.element : null;\n var isFullWidthContainerFocused = currentFullWidthContainer === keyboardEvent.target;\n if (!isFullWidthContainerFocused) {\n return;\n }\n var node = this.rowNode;\n var lastFocusedCell = this.beans.focusService.getFocusedCell();\n var cellPosition = {\n rowIndex: node.rowIndex,\n rowPinned: node.rowPinned,\n column: (lastFocusedCell && lastFocusedCell.column)\n };\n this.beans.navigationService.navigateToNextCell(keyboardEvent, keyboardEvent.key, cellPosition, true);\n keyboardEvent.preventDefault();\n };\n RowCtrl.prototype.onTabKeyDown = function (keyboardEvent) {\n if (keyboardEvent.defaultPrevented || isStopPropagationForAgGrid(keyboardEvent)) {\n return;\n }\n var currentFullWidthComp = this.allRowGuis.find(function (c) { return c.element.contains(keyboardEvent.target); });\n var currentFullWidthContainer = currentFullWidthComp ? currentFullWidthComp.element : null;\n var isFullWidthContainerFocused = currentFullWidthContainer === keyboardEvent.target;\n var nextEl = null;\n if (!isFullWidthContainerFocused) {\n nextEl = this.beans.focusService.findNextFocusableElement(currentFullWidthContainer, false, keyboardEvent.shiftKey);\n }\n if ((this.isFullWidth() && isFullWidthContainerFocused) || !nextEl) {\n this.beans.navigationService.onTabKeyDown(this, keyboardEvent);\n }\n };\n RowCtrl.prototype.onFullWidthRowFocused = function (event) {\n var _a;\n var node = this.rowNode;\n var isFocused = this.isFullWidth() && event.rowIndex === node.rowIndex && event.rowPinned == node.rowPinned;\n var element = this.fullWidthGui ? this.fullWidthGui.element : (_a = this.centerGui) === null || _a === void 0 ? void 0 : _a.element;\n if (!element) {\n return;\n } // can happen with react ui, comp not yet ready\n element.classList.toggle('ag-full-width-focus', isFocused);\n if (isFocused) {\n // we don't scroll normal rows into view when we focus them, so we don't want\n // to scroll Full Width rows either.\n element.focus({ preventScroll: true });\n }\n };\n RowCtrl.prototype.refreshCell = function (cellCtrl) {\n this.centerCellCtrls = this.removeCellCtrl(this.centerCellCtrls, cellCtrl);\n this.leftCellCtrls = this.removeCellCtrl(this.leftCellCtrls, cellCtrl);\n this.rightCellCtrls = this.removeCellCtrl(this.rightCellCtrls, cellCtrl);\n this.updateColumnLists();\n };\n RowCtrl.prototype.removeCellCtrl = function (prev, cellCtrlToRemove) {\n var res = {\n list: [],\n map: {}\n };\n prev.list.forEach(function (cellCtrl) {\n if (cellCtrl === cellCtrlToRemove) {\n return;\n }\n res.list.push(cellCtrl);\n res.map[cellCtrl.getInstanceId()] = cellCtrl;\n });\n return res;\n };\n RowCtrl.prototype.onMouseEvent = function (eventName, mouseEvent) {\n switch (eventName) {\n case 'dblclick':\n this.onRowDblClick(mouseEvent);\n break;\n case 'click':\n this.onRowClick(mouseEvent);\n break;\n case 'touchstart':\n case 'mousedown':\n this.onRowMouseDown(mouseEvent);\n break;\n }\n };\n RowCtrl.prototype.createRowEvent = function (type, domEvent) {\n return {\n type: type,\n node: this.rowNode,\n data: this.rowNode.data,\n rowIndex: this.rowNode.rowIndex,\n rowPinned: this.rowNode.rowPinned,\n context: this.beans.gridOptionsWrapper.getContext(),\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n event: domEvent\n };\n };\n RowCtrl.prototype.createRowEventWithSource = function (type, domEvent) {\n var event = this.createRowEvent(type, domEvent);\n // when first developing this, we included the rowComp in the event.\n // this seems very weird. so when introducing the event types, i left the 'source'\n // out of the type, and just include the source in the two places where this event\n // was fired (rowClicked and rowDoubleClicked). it doesn't make sense for any\n // users to be using this, as the rowComp isn't an object we expose, so would be\n // very surprising if a user was using it.\n event.source = this;\n return event;\n };\n RowCtrl.prototype.onRowDblClick = function (mouseEvent) {\n if (isStopPropagationForAgGrid(mouseEvent)) {\n return;\n }\n var agEvent = this.createRowEventWithSource(Events.EVENT_ROW_DOUBLE_CLICKED, mouseEvent);\n this.beans.eventService.dispatchEvent(agEvent);\n };\n RowCtrl.prototype.onRowMouseDown = function (mouseEvent) {\n this.lastMouseDownOnDragger = isElementChildOfClass(mouseEvent.target, 'ag-row-drag', 3);\n if (!this.isFullWidth()) {\n return;\n }\n var node = this.rowNode;\n var columnModel = this.beans.columnModel;\n if (this.beans.rangeService) {\n this.beans.rangeService.removeAllCellRanges();\n }\n this.beans.focusService.setFocusedCell({\n rowIndex: node.rowIndex,\n column: columnModel.getAllDisplayedColumns()[0],\n rowPinned: node.rowPinned,\n forceBrowserFocus: true\n });\n };\n RowCtrl.prototype.onRowClick = function (mouseEvent) {\n var stop = isStopPropagationForAgGrid(mouseEvent) || this.lastMouseDownOnDragger;\n if (stop) {\n return;\n }\n var agEvent = this.createRowEventWithSource(Events.EVENT_ROW_CLICKED, mouseEvent);\n this.beans.eventService.dispatchEvent(agEvent);\n // ctrlKey for windows, metaKey for Apple\n var multiSelectKeyPressed = mouseEvent.ctrlKey || mouseEvent.metaKey;\n var shiftKeyPressed = mouseEvent.shiftKey;\n // we do not allow selecting the group by clicking, when groupSelectChildren, as the logic to\n // handle this is broken. to observe, change the logic below and allow groups to be selected.\n // you will see the group gets selected, then all children get selected, then the grid unselects\n // the children (as the default behaviour when clicking is to unselect other rows) which results\n // in the group getting unselected (as all children are unselected). the correct thing would be\n // to change this, so that children of the selected group are not then subsequenly un-selected.\n var groupSelectsChildren = this.beans.gridOptionsWrapper.isGroupSelectsChildren();\n if (\n // we do not allow selecting groups by clicking (as the click here expands the group), or if it's a detail row,\n // so return if it's a group row\n (groupSelectsChildren && this.rowNode.group) ||\n // this is needed so we don't unselect other rows when we click this row, eg if this row is not selectable,\n // and we click it, the selection should not change (ie any currently selected row should stay selected)\n !this.rowNode.selectable ||\n // we also don't allow selection of pinned rows\n this.rowNode.rowPinned ||\n // if no selection method enabled, do nothing\n !this.beans.gridOptionsWrapper.isRowSelection() ||\n // if click selection suppressed, do nothing\n this.beans.gridOptionsWrapper.isSuppressRowClickSelection()) {\n return;\n }\n var multiSelectOnClick = this.beans.gridOptionsWrapper.isRowMultiSelectWithClick();\n var rowDeselectionWithCtrl = !this.beans.gridOptionsWrapper.isSuppressRowDeselection();\n if (this.rowNode.isSelected()) {\n if (multiSelectOnClick) {\n this.rowNode.setSelectedParams({ newValue: false, event: mouseEvent });\n }\n else if (multiSelectKeyPressed) {\n if (rowDeselectionWithCtrl) {\n this.rowNode.setSelectedParams({ newValue: false, event: mouseEvent });\n }\n }\n else {\n // selected with no multi key, must make sure anything else is unselected\n this.rowNode.setSelectedParams({ newValue: true, clearSelection: !shiftKeyPressed, rangeSelect: shiftKeyPressed, event: mouseEvent });\n }\n }\n else {\n var clearSelection = multiSelectOnClick ? false : !multiSelectKeyPressed;\n this.rowNode.setSelectedParams({ newValue: true, clearSelection: clearSelection, rangeSelect: shiftKeyPressed, event: mouseEvent });\n }\n };\n RowCtrl.prototype.setupDetailRowAutoHeight = function (eDetailGui) {\n var _this = this;\n if (this.rowType !== RowType$1.FullWidthDetail) {\n return;\n }\n if (!this.beans.gridOptionsWrapper.isDetailRowAutoHeight()) {\n return;\n }\n var checkRowSizeFunc = function () {\n var clientHeight = eDetailGui.clientHeight;\n // if the UI is not ready, the height can be 0, which we ignore, as otherwise a flicker will occur\n // as UI goes from the default height, to 0, then to the real height as UI becomes ready. this means\n // it's not possible for have 0 as auto-height, however this is an improbable use case, as even an\n // empty detail grid would still have some styling around it giving at least a few pixels.\n if (clientHeight != null && clientHeight > 0) {\n // we do the update in a timeout, to make sure we are not calling from inside the grid\n // doing another update\n var updateRowHeightFunc = function () {\n _this.rowNode.setRowHeight(clientHeight);\n if (_this.beans.clientSideRowModel) {\n _this.beans.clientSideRowModel.onRowHeightChanged();\n }\n else if (_this.beans.serverSideRowModel) {\n _this.beans.serverSideRowModel.onRowHeightChanged();\n }\n };\n _this.beans.frameworkOverrides.setTimeout(updateRowHeightFunc, 0);\n }\n };\n var resizeObserverDestroyFunc = this.beans.resizeObserverService.observeResize(eDetailGui, checkRowSizeFunc);\n this.addDestroyFunc(resizeObserverDestroyFunc);\n checkRowSizeFunc();\n };\n RowCtrl.prototype.createFullWidthParams = function (eRow, pinned) {\n var _this = this;\n var params = {\n fullWidth: true,\n data: this.rowNode.data,\n node: this.rowNode,\n value: this.rowNode.key,\n valueFormatted: this.rowNode.key,\n rowIndex: this.rowNode.rowIndex,\n api: this.beans.gridOptionsWrapper.getApi(),\n columnApi: this.beans.gridOptionsWrapper.getColumnApi(),\n context: this.beans.gridOptionsWrapper.getContext(),\n // these need to be taken out, as part of 'afterAttached' now\n eGridCell: eRow,\n eParentOfValue: eRow,\n pinned: pinned,\n addRenderedRowListener: this.addEventListener.bind(this),\n registerRowDragger: function (rowDraggerElement, dragStartPixels, value, suppressVisibilityChange) { return _this.addFullWidthRowDragging(rowDraggerElement, dragStartPixels, value, suppressVisibilityChange); }\n };\n return params;\n };\n RowCtrl.prototype.addFullWidthRowDragging = function (rowDraggerElement, dragStartPixels, value, suppressVisibilityChange) {\n if (value === void 0) { value = ''; }\n if (!this.isFullWidth()) {\n return;\n }\n var rowDragComp = new RowDragComp(function () { return value; }, this.rowNode, undefined, rowDraggerElement, dragStartPixels, suppressVisibilityChange);\n this.createManagedBean(rowDragComp, this.beans.context);\n };\n RowCtrl.prototype.onUiLevelChanged = function () {\n var newLevel = this.beans.rowCssClassCalculator.calculateRowLevel(this.rowNode);\n if (this.rowLevel != newLevel) {\n var classToAdd_1 = 'ag-row-level-' + newLevel;\n var classToRemove_1 = 'ag-row-level-' + this.rowLevel;\n this.allRowGuis.forEach(function (gui) {\n gui.rowComp.addOrRemoveCssClass(classToAdd_1, true);\n gui.rowComp.addOrRemoveCssClass(classToRemove_1, false);\n });\n }\n this.rowLevel = newLevel;\n };\n RowCtrl.prototype.isFirstRowOnPage = function () {\n return this.rowNode.rowIndex === this.beans.paginationProxy.getPageFirstRow();\n };\n RowCtrl.prototype.isLastRowOnPage = function () {\n return this.rowNode.rowIndex === this.beans.paginationProxy.getPageLastRow();\n };\n RowCtrl.prototype.onModelUpdated = function () {\n this.refreshFirstAndLastRowStyles();\n };\n RowCtrl.prototype.refreshFirstAndLastRowStyles = function () {\n var newFirst = this.isFirstRowOnPage();\n var newLast = this.isLastRowOnPage();\n if (this.firstRowOnPage !== newFirst) {\n this.firstRowOnPage = newFirst;\n this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass('ag-row-first', newFirst); });\n }\n if (this.lastRowOnPage !== newLast) {\n this.lastRowOnPage = newLast;\n this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass('ag-row-last', newLast); });\n }\n };\n RowCtrl.prototype.stopEditing = function (cancel) {\n var e_1, _a;\n if (cancel === void 0) { cancel = false; }\n // if we are already stopping row edit, there is\n // no need to start this process again.\n if (this.stoppingRowEdit) {\n return;\n }\n var cellControls = this.getAllCellCtrls();\n var isRowEdit = this.editingRow;\n this.stoppingRowEdit = true;\n var fireRowEditEvent = false;\n try {\n for (var cellControls_1 = __values$2(cellControls), cellControls_1_1 = cellControls_1.next(); !cellControls_1_1.done; cellControls_1_1 = cellControls_1.next()) {\n var ctrl = cellControls_1_1.value;\n var valueChanged = ctrl.stopEditing(cancel);\n if (isRowEdit && !cancel && !fireRowEditEvent && valueChanged) {\n fireRowEditEvent = true;\n }\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (cellControls_1_1 && !cellControls_1_1.done && (_a = cellControls_1.return)) _a.call(cellControls_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n if (fireRowEditEvent) {\n var event_1 = this.createRowEvent(Events.EVENT_ROW_VALUE_CHANGED);\n this.beans.eventService.dispatchEvent(event_1);\n }\n if (isRowEdit) {\n this.setEditingRow(false);\n }\n this.stoppingRowEdit = false;\n };\n RowCtrl.prototype.setInlineEditingCss = function (editing) {\n this.allRowGuis.forEach(function (gui) {\n gui.rowComp.addOrRemoveCssClass(\"ag-row-inline-editing\", editing);\n gui.rowComp.addOrRemoveCssClass(\"ag-row-not-inline-editing\", !editing);\n });\n };\n RowCtrl.prototype.setEditingRow = function (value) {\n this.editingRow = value;\n this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass('ag-row-editing', value); });\n var event = value ?\n this.createRowEvent(Events.EVENT_ROW_EDITING_STARTED)\n : this.createRowEvent(Events.EVENT_ROW_EDITING_STOPPED);\n this.beans.eventService.dispatchEvent(event);\n };\n RowCtrl.prototype.startRowEditing = function (key, charPress, sourceRenderedCell, event) {\n if (key === void 0) { key = null; }\n if (charPress === void 0) { charPress = null; }\n if (sourceRenderedCell === void 0) { sourceRenderedCell = null; }\n if (event === void 0) { event = null; }\n // don't do it if already editing\n if (this.editingRow) {\n return;\n }\n var atLeastOneEditing = this.getAllCellCtrls().reduce(function (prev, cellCtrl) {\n var cellStartedEdit = cellCtrl === sourceRenderedCell;\n if (cellStartedEdit) {\n cellCtrl.startEditing(key, charPress, cellStartedEdit, event);\n }\n else {\n cellCtrl.startEditing(null, null, cellStartedEdit, event);\n }\n if (prev) {\n return true;\n }\n return cellCtrl.isEditing();\n }, false);\n if (atLeastOneEditing) {\n this.setEditingRow(true);\n }\n };\n RowCtrl.prototype.getAllCellCtrls = function () {\n var res = __spread$d(this.centerCellCtrls.list, this.leftCellCtrls.list, this.rightCellCtrls.list);\n return res;\n };\n RowCtrl.prototype.postProcessClassesFromGridOptions = function () {\n var _this = this;\n var cssClasses = this.beans.rowCssClassCalculator.processClassesFromGridOptions(this.rowNode);\n if (!cssClasses || !cssClasses.length) {\n return;\n }\n cssClasses.forEach(function (classStr) {\n _this.allRowGuis.forEach(function (c) { return c.rowComp.addOrRemoveCssClass(classStr, true); });\n });\n };\n RowCtrl.prototype.postProcessRowClassRules = function () {\n var _this = this;\n this.beans.rowCssClassCalculator.processRowClassRules(this.rowNode, function (className) {\n _this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass(className, true); });\n }, function (className) {\n _this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass(className, false); });\n });\n };\n RowCtrl.prototype.setStylesFromGridOptions = function () {\n var rowStyles = this.processStylesFromGridOptions();\n this.allRowGuis.forEach(function (gui) { return gui.rowComp.setUserStyles(rowStyles); });\n };\n RowCtrl.prototype.getRowBusinessKey = function () {\n var businessKeyForNodeFunc = this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc();\n if (typeof businessKeyForNodeFunc !== 'function') {\n return;\n }\n return businessKeyForNodeFunc(this.rowNode);\n };\n RowCtrl.prototype.getPinnedForContainer = function (rowContainerType) {\n var pinned = rowContainerType === RowContainerType.LEFT\n ? Constants.PINNED_LEFT\n : rowContainerType === RowContainerType.RIGHT\n ? Constants.PINNED_RIGHT\n : null;\n return pinned;\n };\n RowCtrl.prototype.getInitialRowClasses = function (rowContainerType) {\n var pinned = this.getPinnedForContainer(rowContainerType);\n var params = {\n rowNode: this.rowNode,\n rowFocused: this.rowFocused,\n fadeRowIn: this.fadeRowIn,\n rowIsEven: this.rowNode.rowIndex % 2 === 0,\n rowLevel: this.rowLevel,\n fullWidthRow: this.isFullWidth(),\n firstRowOnPage: this.isFirstRowOnPage(),\n lastRowOnPage: this.isLastRowOnPage(),\n printLayout: this.printLayout,\n expandable: this.rowNode.isExpandable(),\n pinned: pinned\n };\n return this.beans.rowCssClassCalculator.getInitialRowClasses(params);\n };\n RowCtrl.prototype.processStylesFromGridOptions = function () {\n // part 1 - rowStyle\n var rowStyle = this.beans.gridOptionsWrapper.getRowStyle();\n if (rowStyle && typeof rowStyle === 'function') {\n console.warn('AG Grid: rowStyle should be an object of key/value styles, not be a function, use getRowStyle() instead');\n return;\n }\n // part 1 - rowStyleFunc\n var rowStyleFunc = this.beans.gridOptionsWrapper.getRowStyleFunc();\n var rowStyleFuncResult;\n if (rowStyleFunc) {\n var params = {\n data: this.rowNode.data,\n node: this.rowNode,\n rowIndex: this.rowNode.rowIndex\n };\n rowStyleFuncResult = rowStyleFunc(params);\n }\n return Object.assign({}, rowStyle, rowStyleFuncResult);\n };\n RowCtrl.prototype.onRowSelected = function () {\n var _this = this;\n // Treat undefined as false, if we pass undefined down it gets treated as toggle class, rather than explicitly\n // setting the required value\n var selected = !!this.rowNode.isSelected();\n this.allRowGuis.forEach(function (gui) {\n gui.rowComp.addOrRemoveCssClass('ag-row-selected', selected);\n setAriaSelected(gui.element, selected ? true : undefined);\n var ariaLabel = _this.createAriaLabel();\n setAriaLabel(gui.element, ariaLabel == null ? '' : ariaLabel);\n });\n };\n RowCtrl.prototype.createAriaLabel = function () {\n var selected = this.rowNode.isSelected();\n if (selected && this.beans.gridOptionsWrapper.isSuppressRowDeselection()) {\n return undefined;\n }\n var translate = this.beans.gridOptionsWrapper.getLocaleTextFunc();\n var label = translate(selected ? 'ariaRowDeselect' : 'ariaRowSelect', \"Press SPACE to \" + (selected ? 'deselect' : 'select') + \" this row.\");\n return label;\n };\n RowCtrl.prototype.isUseAnimationFrameForCreate = function () {\n return this.useAnimationFrameForCreate;\n };\n RowCtrl.prototype.addHoverFunctionality = function (eRow) {\n var _this = this;\n // because we use animation frames to do this, it's possible the row no longer exists\n // by the time we get to add it\n if (!this.active) {\n return;\n }\n // because mouseenter and mouseleave do not propagate, we cannot listen on the gridPanel\n // like we do for all the other mouse events.\n // because of the pinning, we cannot simply add / remove the class based on the eRow. we\n // have to check all eRow's (body & pinned). so the trick is if any of the rows gets a\n // mouse hover, it sets such in the rowNode, and then all three reflect the change as\n // all are listening for event on the row node.\n // step 1 - add listener, to set flag on row node\n this.addManagedListener(eRow, 'mouseenter', function () { return _this.rowNode.onMouseEnter(); });\n this.addManagedListener(eRow, 'mouseleave', function () { return _this.rowNode.onMouseLeave(); });\n // step 2 - listen for changes on row node (which any eRow can trigger)\n this.addManagedListener(this.rowNode, RowNode.EVENT_MOUSE_ENTER, function () {\n // if hover turned off, we don't add the class. we do this here so that if the application\n // toggles this property mid way, we remove the hover form the last row, but we stop\n // adding hovers from that point onwards.\n if (!_this.beans.gridOptionsWrapper.isSuppressRowHoverHighlight()) {\n eRow.classList.add('ag-row-hover');\n }\n });\n this.addManagedListener(this.rowNode, RowNode.EVENT_MOUSE_LEAVE, function () {\n eRow.classList.remove('ag-row-hover');\n });\n };\n // for animation, we don't want to animate entry or exit to a very far away pixel,\n // otherwise the row would move so fast, it would appear to disappear. so this method\n // moves the row closer to the viewport if it is far away, so the row slide in / out\n // at a speed the user can see.\n RowCtrl.prototype.roundRowTopToBounds = function (rowTop) {\n var gridBodyCon = this.beans.ctrlsService.getGridBodyCtrl();\n var range = gridBodyCon.getScrollFeature().getVScrollPosition();\n var minPixel = this.applyPaginationOffset(range.top, true) - 100;\n var maxPixel = this.applyPaginationOffset(range.bottom, true) + 100;\n return Math.min(Math.max(minPixel, rowTop), maxPixel);\n };\n RowCtrl.prototype.getFrameworkOverrides = function () {\n return this.beans.frameworkOverrides;\n };\n RowCtrl.prototype.onRowHeightChanged = function () {\n // check for exists first - if the user is resetting the row height, then\n // it will be null (or undefined) momentarily until the next time the flatten\n // stage is called where the row will then update again with a new height\n if (this.rowNode.rowHeight == null) {\n return;\n }\n var rowHeight = this.rowNode.rowHeight;\n var defaultRowHeight = this.beans.gridOptionsWrapper.getDefaultRowHeight();\n var isHeightFromFunc = this.beans.gridOptionsWrapper.isGetRowHeightFunction();\n var heightFromFunc = isHeightFromFunc ? this.beans.gridOptionsWrapper.getRowHeightForNode(this.rowNode).height : undefined;\n var lineHeight = heightFromFunc ? Math.min(defaultRowHeight, heightFromFunc) - 2 + \"px\" : undefined;\n this.allRowGuis.forEach(function (gui) {\n gui.element.style.height = rowHeight + \"px\";\n // If the row height is coming from a function, this means some rows can\n // be smaller than the theme had intended. so we set --ag-line-height on\n // the row, which is picked up by the theme CSS and is used in a calc\n // for the CSS line-height property, which makes sure the line-height is\n // not bigger than the row height, otherwise the row text would not fit.\n // We do not use rowNode.rowHeight here, as this could be the result of autoHeight,\n // and we found using the autoHeight result causes a loop, where changing the\n // line-height them impacts the cell height, resulting in a new autoHeight,\n // resulting in a new line-height and so on loop.\n // const heightFromFunc = this.beans.gridOptionsWrapper.getRowHeightForNode(this.rowNode).height;\n if (lineHeight) {\n gui.element.style.setProperty('--ag-line-height', lineHeight);\n }\n });\n };\n RowCtrl.prototype.addEventListener = function (eventType, listener) {\n if (eventType === 'renderedRowRemoved' || eventType === 'rowRemoved') {\n eventType = Events.EVENT_VIRTUAL_ROW_REMOVED;\n console.warn('AG Grid: Since version 11, event renderedRowRemoved is now called ' + Events.EVENT_VIRTUAL_ROW_REMOVED);\n }\n _super.prototype.addEventListener.call(this, eventType, listener);\n };\n RowCtrl.prototype.removeEventListener = function (eventType, listener) {\n if (eventType === 'renderedRowRemoved' || eventType === 'rowRemoved') {\n eventType = Events.EVENT_VIRTUAL_ROW_REMOVED;\n console.warn('AG Grid: Since version 11, event renderedRowRemoved and rowRemoved is now called ' + Events.EVENT_VIRTUAL_ROW_REMOVED);\n }\n _super.prototype.removeEventListener.call(this, eventType, listener);\n };\n // note - this is NOT called by context, as we don't wire / unwire the CellComp for performance reasons.\n RowCtrl.prototype.destroyFirstPass = function () {\n this.active = false;\n // why do we have this method? shouldn't everything below be added as a destroy func beside\n // the corresponding create logic?\n this.setupRemoveAnimation();\n var event = this.createRowEvent(Events.EVENT_VIRTUAL_ROW_REMOVED);\n this.dispatchEvent(event);\n this.beans.eventService.dispatchEvent(event);\n _super.prototype.destroy.call(this);\n };\n RowCtrl.prototype.setupRemoveAnimation = function () {\n // we don't animate sticky rows\n if (this.isSticky()) {\n return;\n }\n var rowStillVisibleJustNotInViewport = this.rowNode.rowTop != null;\n if (rowStillVisibleJustNotInViewport) {\n // if the row is not rendered, but in viewport, it means it has moved,\n // so we animate the row out. if the new location is very far away,\n // the animation will be so fast the row will look like it's just disappeared,\n // so instead we animate to a position just outside the viewport.\n var rowTop = this.roundRowTopToBounds(this.rowNode.rowTop);\n this.setRowTop(rowTop);\n }\n else {\n this.allRowGuis.forEach(function (gui) { return gui.rowComp.addOrRemoveCssClass('ag-opacity-zero', true); });\n }\n };\n RowCtrl.prototype.destroySecondPass = function () {\n this.allRowGuis.length = 0;\n var destroyCellCtrls = function (ctrls) {\n ctrls.list.forEach(function (c) { return c.destroy(); });\n return { list: [], map: {} };\n };\n this.centerCellCtrls = destroyCellCtrls(this.centerCellCtrls);\n this.leftCellCtrls = destroyCellCtrls(this.leftCellCtrls);\n this.rightCellCtrls = destroyCellCtrls(this.rightCellCtrls);\n };\n RowCtrl.prototype.setFocusedClasses = function () {\n var _this = this;\n this.allRowGuis.forEach(function (gui) {\n gui.rowComp.addOrRemoveCssClass('ag-row-focus', _this.rowFocused);\n gui.rowComp.addOrRemoveCssClass('ag-row-no-focus', !_this.rowFocused);\n });\n };\n RowCtrl.prototype.onCellFocusChanged = function () {\n var rowFocused = this.beans.focusService.isRowFocused(this.rowNode.rowIndex, this.rowNode.rowPinned);\n if (rowFocused !== this.rowFocused) {\n this.rowFocused = rowFocused;\n this.setFocusedClasses();\n }\n // if we are editing, then moving the focus out of a row will stop editing\n if (!rowFocused && this.editingRow) {\n this.stopEditing(false);\n }\n };\n RowCtrl.prototype.onPaginationChanged = function () {\n var currentPage = this.beans.paginationProxy.getCurrentPage();\n // it is possible this row is in the new page, but the page number has changed, which means\n // it needs to reposition itself relative to the new page\n if (this.paginationPage !== currentPage) {\n this.paginationPage = currentPage;\n this.onTopChanged();\n }\n this.refreshFirstAndLastRowStyles();\n };\n RowCtrl.prototype.onTopChanged = function () {\n this.setRowTop(this.rowNode.rowTop);\n };\n RowCtrl.prototype.onPaginationPixelOffsetChanged = function () {\n // the pixel offset is used when calculating rowTop to set on the row DIV\n this.onTopChanged();\n };\n // applies pagination offset, eg if on second page, and page height is 500px, then removes\n // 500px from the top position, so a row with rowTop 600px is displayed at location 100px.\n // reverse will take the offset away rather than add.\n RowCtrl.prototype.applyPaginationOffset = function (topPx, reverse) {\n if (reverse === void 0) { reverse = false; }\n if (this.rowNode.isRowPinned()) {\n return topPx;\n }\n var pixelOffset = this.beans.paginationProxy.getPixelOffset();\n var multiplier = reverse ? 1 : -1;\n return topPx + (pixelOffset * multiplier);\n };\n RowCtrl.prototype.setRowTop = function (pixels) {\n // print layout uses normal flow layout for row positioning\n if (this.printLayout) {\n return;\n }\n // need to make sure rowTop is not null, as this can happen if the node was once\n // visible (ie parent group was expanded) but is now not visible\n if (exists(pixels)) {\n var afterPaginationPixels = this.applyPaginationOffset(pixels);\n var afterScalingPixels = this.rowNode.isRowPinned() ? afterPaginationPixels : this.beans.rowContainerHeightService.getRealPixelPosition(afterPaginationPixels);\n var topPx = afterScalingPixels + \"px\";\n this.setRowTopStyle(topPx);\n }\n };\n // the top needs to be set into the DOM element when the element is created, not updated afterwards.\n // otherwise the transition would not work, as it would be transitioning from zero (the unset value).\n // for example, suppose a row that is outside the viewport, then user does a filter to remove other rows\n // and this row now appears in the viewport, and the row moves up (ie it was under the viewport and not rendered,\n // but now is in the viewport) then a new RowComp is created, however it should have it's position initialised\n // to below the viewport, so the row will appear to animate up. if we didn't set the initial position at creation\n // time, the row would animate down (ie from position zero).\n RowCtrl.prototype.getInitialRowTop = function () {\n var suppressRowTransform = this.beans.gridOptionsWrapper.isSuppressRowTransform();\n return suppressRowTransform ? this.getInitialRowTopShared() : undefined;\n };\n RowCtrl.prototype.getInitialTransform = function () {\n var suppressRowTransform = this.beans.gridOptionsWrapper.isSuppressRowTransform();\n return suppressRowTransform ? undefined : \"translateY(\" + this.getInitialRowTopShared() + \")\";\n };\n RowCtrl.prototype.getInitialRowTopShared = function () {\n // print layout uses normal flow layout for row positioning\n if (this.printLayout) {\n return '';\n }\n var rowTop;\n if (this.isSticky()) {\n rowTop = this.rowNode.stickyRowTop;\n }\n else {\n // if sliding in, we take the old row top. otherwise we just set the current row top.\n var pixels = this.slideRowIn ? this.roundRowTopToBounds(this.rowNode.oldRowTop) : this.rowNode.rowTop;\n var afterPaginationPixels = this.applyPaginationOffset(pixels);\n // we don't apply scaling if row is pinned\n rowTop = this.rowNode.isRowPinned() ? afterPaginationPixels : this.beans.rowContainerHeightService.getRealPixelPosition(afterPaginationPixels);\n }\n return rowTop + 'px';\n };\n RowCtrl.prototype.setRowTopStyle = function (topPx) {\n var suppressRowTransform = this.beans.gridOptionsWrapper.isSuppressRowTransform();\n this.allRowGuis.forEach(function (gui) { return suppressRowTransform ?\n gui.rowComp.setTop(topPx) :\n gui.rowComp.setTransform(\"translateY(\" + topPx + \")\"); });\n };\n RowCtrl.prototype.getRowNode = function () {\n return this.rowNode;\n };\n RowCtrl.prototype.getCellCtrl = function (column) {\n // first up, check for cell directly linked to this column\n var res = null;\n this.getAllCellCtrls().forEach(function (cellCtrl) {\n if (cellCtrl.getColumn() == column) {\n res = cellCtrl;\n }\n });\n if (res != null) {\n return res;\n }\n // second up, if not found, then check for spanned cols.\n // we do this second (and not at the same time) as this is\n // more expensive, as spanning cols is a\n // infrequently used feature so we don't need to do this most\n // of the time\n this.getAllCellCtrls().forEach(function (cellCtrl) {\n if (cellCtrl.getColSpanningList().indexOf(column) >= 0) {\n res = cellCtrl;\n }\n });\n return res;\n };\n RowCtrl.prototype.onRowIndexChanged = function () {\n // we only bother updating if the rowIndex is present. if it is not present, it means this row\n // is child of a group node, and the group node was closed, it's the only way to have no row index.\n // when this happens, row is about to be de-rendered, so we don't care, rowComp is about to die!\n if (this.rowNode.rowIndex != null) {\n this.onCellFocusChanged();\n this.updateRowIndexes();\n this.postProcessCss();\n }\n };\n RowCtrl.prototype.updateRowIndexes = function () {\n var rowIndexStr = this.rowNode.getRowIndexString();\n var headerRowCount = this.beans.headerNavigationService.getHeaderRowCount();\n var rowIsEven = this.rowNode.rowIndex % 2 === 0;\n var ariaRowIndex = headerRowCount + this.rowNode.rowIndex + 1;\n this.allRowGuis.forEach(function (c) {\n c.rowComp.setRowIndex(rowIndexStr);\n c.rowComp.addOrRemoveCssClass('ag-row-even', rowIsEven);\n c.rowComp.addOrRemoveCssClass('ag-row-odd', !rowIsEven);\n setAriaRowIndex(c.element, ariaRowIndex);\n });\n };\n // returns the pinned left container, either the normal one, or the embedded full with one if exists\n RowCtrl.prototype.getPinnedLeftRowElement = function () {\n return this.leftGui ? this.leftGui.element : undefined;\n };\n // returns the pinned right container, either the normal one, or the embedded full with one if exists\n RowCtrl.prototype.getPinnedRightRowElement = function () {\n return this.rightGui ? this.rightGui.element : undefined;\n };\n // returns the body container, either the normal one, or the embedded full with one if exists\n RowCtrl.prototype.getBodyRowElement = function () {\n return this.centerGui ? this.centerGui.element : undefined;\n };\n // returns the full width container\n RowCtrl.prototype.getFullWidthRowElement = function () {\n return this.fullWidthGui ? this.fullWidthGui.element : undefined;\n };\n RowCtrl.DOM_DATA_KEY_ROW_CTRL = 'renderedRow';\n return RowCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1T = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1M = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$g = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar RowContainerEventsFeature = /** @class */ (function (_super) {\n __extends$1T(RowContainerEventsFeature, _super);\n function RowContainerEventsFeature(element) {\n var _this = _super.call(this) || this;\n _this.element = element;\n return _this;\n }\n RowContainerEventsFeature.prototype.postConstruct = function () {\n this.addMouseListeners();\n this.mockContextMenuForIPad();\n this.addKeyboardEvents();\n };\n RowContainerEventsFeature.prototype.addKeyboardEvents = function () {\n var _this = this;\n var eventNames = ['keydown', 'keypress'];\n eventNames.forEach(function (eventName) {\n var listener = _this.processKeyboardEvent.bind(_this, eventName);\n _this.addManagedListener(_this.element, eventName, listener);\n });\n };\n RowContainerEventsFeature.prototype.addMouseListeners = function () {\n var _this = this;\n var mouseDownEvent = isEventSupported('touchstart') ? 'touchstart' : 'mousedown';\n var eventNames = ['dblclick', 'contextmenu', 'mouseover', 'mouseout', 'click', mouseDownEvent];\n eventNames.forEach(function (eventName) {\n var listener = _this.processMouseEvent.bind(_this, eventName);\n _this.addManagedListener(_this.element, eventName, listener);\n });\n };\n RowContainerEventsFeature.prototype.processMouseEvent = function (eventName, mouseEvent) {\n if (!this.mouseEventService.isEventFromThisGrid(mouseEvent) ||\n isStopPropagationForAgGrid(mouseEvent)) {\n return;\n }\n var rowComp = this.getRowForEvent(mouseEvent);\n var cellCtrl = this.mouseEventService.getRenderedCellForEvent(mouseEvent);\n if (eventName === \"contextmenu\") {\n this.handleContextMenuMouseEvent(mouseEvent, null, rowComp, cellCtrl);\n }\n else {\n if (cellCtrl) {\n cellCtrl.onMouseEvent(eventName, mouseEvent);\n }\n if (rowComp) {\n rowComp.onMouseEvent(eventName, mouseEvent);\n }\n }\n };\n RowContainerEventsFeature.prototype.mockContextMenuForIPad = function () {\n var _this = this;\n // we do NOT want this when not in iPad, otherwise we will be doing\n if (!isIOSUserAgent()) {\n return;\n }\n var touchListener = new TouchListener(this.element);\n var longTapListener = function (event) {\n var rowComp = _this.getRowForEvent(event.touchEvent);\n var cellComp = _this.mouseEventService.getRenderedCellForEvent(event.touchEvent);\n _this.handleContextMenuMouseEvent(null, event.touchEvent, rowComp, cellComp);\n };\n this.addManagedListener(touchListener, TouchListener.EVENT_LONG_TAP, longTapListener);\n this.addDestroyFunc(function () { return touchListener.destroy(); });\n };\n RowContainerEventsFeature.prototype.getRowForEvent = function (event) {\n var sourceElement = event.target;\n while (sourceElement) {\n var rowCon = this.gridOptionsWrapper.getDomData(sourceElement, RowCtrl.DOM_DATA_KEY_ROW_CTRL);\n if (rowCon) {\n return rowCon;\n }\n sourceElement = sourceElement.parentElement;\n }\n return null;\n };\n RowContainerEventsFeature.prototype.handleContextMenuMouseEvent = function (mouseEvent, touchEvent, rowComp, cellCtrl) {\n var rowNode = rowComp ? rowComp.getRowNode() : null;\n var column = cellCtrl ? cellCtrl.getColumn() : null;\n var value = null;\n if (column) {\n var event_1 = mouseEvent ? mouseEvent : touchEvent;\n cellCtrl.dispatchCellContextMenuEvent(event_1);\n value = this.valueService.getValue(column, rowNode);\n }\n // if user clicked on a cell, anchor to that cell, otherwise anchor to the grid panel\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var anchorToElement = cellCtrl ? cellCtrl.getGui() : gridBodyCon.getGridBodyElement();\n if (this.contextMenuFactory) {\n this.contextMenuFactory.onContextMenu(mouseEvent, touchEvent, rowNode, column, value, anchorToElement);\n }\n };\n RowContainerEventsFeature.prototype.processKeyboardEvent = function (eventName, keyboardEvent) {\n var cellComp = getCtrlForEvent(this.gridOptionsWrapper, keyboardEvent, CellCtrl.DOM_DATA_KEY_CELL_CTRL);\n var rowComp = getCtrlForEvent(this.gridOptionsWrapper, keyboardEvent, RowCtrl.DOM_DATA_KEY_ROW_CTRL);\n if (keyboardEvent.defaultPrevented) {\n return;\n }\n if (cellComp) {\n this.processCellKeyboardEvent(cellComp, eventName, keyboardEvent);\n }\n else if (rowComp && rowComp.isFullWidth()) {\n this.processFullWidthRowKeyboardEvent(rowComp, eventName, keyboardEvent);\n }\n };\n RowContainerEventsFeature.prototype.processCellKeyboardEvent = function (cellCtrl, eventName, keyboardEvent) {\n var rowNode = cellCtrl.getRowNode();\n var column = cellCtrl.getColumn();\n var editing = cellCtrl.isEditing();\n var gridProcessingAllowed = !isUserSuppressingKeyboardEvent(this.gridOptionsWrapper, keyboardEvent, rowNode, column, editing);\n if (gridProcessingAllowed) {\n switch (eventName) {\n case 'keydown':\n // first see if it's a scroll key, page up / down, home / end etc\n var wasScrollKey = !editing && this.navigationService.handlePageScrollingKey(keyboardEvent);\n // if not a scroll key, then we pass onto cell\n if (!wasScrollKey) {\n cellCtrl.onKeyDown(keyboardEvent);\n }\n // perform clipboard and undo / redo operations\n this.doGridOperations(keyboardEvent, cellCtrl.isEditing());\n break;\n case 'keypress':\n cellCtrl.onKeyPress(keyboardEvent);\n break;\n }\n }\n if (eventName === 'keydown') {\n var cellKeyDownEvent = cellCtrl.createEvent(keyboardEvent, Events.EVENT_CELL_KEY_DOWN);\n this.eventService.dispatchEvent(cellKeyDownEvent);\n }\n if (eventName === 'keypress') {\n var cellKeyPressEvent = cellCtrl.createEvent(keyboardEvent, Events.EVENT_CELL_KEY_PRESS);\n this.eventService.dispatchEvent(cellKeyPressEvent);\n }\n };\n RowContainerEventsFeature.prototype.processFullWidthRowKeyboardEvent = function (rowComp, eventName, keyboardEvent) {\n var rowNode = rowComp.getRowNode();\n var focusedCell = this.focusService.getFocusedCell();\n var column = (focusedCell && focusedCell.column);\n var gridProcessingAllowed = !isUserSuppressingKeyboardEvent(this.gridOptionsWrapper, keyboardEvent, rowNode, column, false);\n if (gridProcessingAllowed) {\n var key = keyboardEvent.key;\n if (eventName === 'keydown') {\n switch (key) {\n case KeyCode.UP:\n case KeyCode.DOWN:\n rowComp.onKeyboardNavigate(keyboardEvent);\n break;\n case KeyCode.TAB:\n rowComp.onTabKeyDown(keyboardEvent);\n }\n }\n }\n if (eventName === 'keydown') {\n var cellKeyDownEvent = rowComp.createRowEvent(Events.EVENT_CELL_KEY_DOWN, keyboardEvent);\n this.eventService.dispatchEvent(cellKeyDownEvent);\n }\n if (eventName === 'keypress') {\n var cellKeyPressEvent = rowComp.createRowEvent(Events.EVENT_CELL_KEY_PRESS, keyboardEvent);\n this.eventService.dispatchEvent(cellKeyPressEvent);\n }\n };\n RowContainerEventsFeature.prototype.doGridOperations = function (keyboardEvent, editing) {\n // check if ctrl or meta key pressed\n if (!keyboardEvent.ctrlKey && !keyboardEvent.metaKey) {\n return;\n }\n // if the cell the event came from is editing, then we do not\n // want to do the default shortcut keys, otherwise the editor\n // (eg a text field) would not be able to do the normal cut/copy/paste\n if (editing) {\n return;\n }\n // for copy / paste, we don't want to execute when the event\n // was from a child grid (happens in master detail)\n if (!this.mouseEventService.isEventFromThisGrid(keyboardEvent)) {\n return;\n }\n var keyCode = normaliseQwertyAzerty(keyboardEvent);\n if (keyCode === KeyCode.A) {\n return this.onCtrlAndA(keyboardEvent);\n }\n if (keyCode === KeyCode.C) {\n return this.onCtrlAndC(keyboardEvent);\n }\n if (keyCode === KeyCode.V) {\n return this.onCtrlAndV();\n }\n if (keyCode === KeyCode.D) {\n return this.onCtrlAndD(keyboardEvent);\n }\n if (keyCode === KeyCode.Z) {\n return this.onCtrlAndZ(keyboardEvent);\n }\n if (keyCode === KeyCode.Y) {\n return this.onCtrlAndY();\n }\n };\n RowContainerEventsFeature.prototype.onCtrlAndA = function (event) {\n var _a = this, pinnedRowModel = _a.pinnedRowModel, paginationProxy = _a.paginationProxy, rangeService = _a.rangeService;\n var PINNED_BOTTOM = Constants.PINNED_BOTTOM, PINNED_TOP = Constants.PINNED_TOP;\n if (rangeService && paginationProxy.isRowsToRender()) {\n var _b = __read$g([\n pinnedRowModel.isEmpty(PINNED_TOP),\n pinnedRowModel.isEmpty(PINNED_BOTTOM)\n ], 2), isEmptyPinnedTop = _b[0], isEmptyPinnedBottom = _b[1];\n var floatingStart = isEmptyPinnedTop ? null : PINNED_TOP;\n var floatingEnd = void 0;\n var rowEnd = void 0;\n if (isEmptyPinnedBottom) {\n floatingEnd = null;\n rowEnd = this.paginationProxy.getRowCount() - 1;\n }\n else {\n floatingEnd = PINNED_BOTTOM;\n rowEnd = pinnedRowModel.getPinnedBottomRowData().length - 1;\n }\n var allDisplayedColumns = this.columnModel.getAllDisplayedColumns();\n if (missingOrEmpty(allDisplayedColumns)) {\n return;\n }\n rangeService.setCellRange({\n rowStartIndex: 0,\n rowStartPinned: floatingStart,\n rowEndIndex: rowEnd,\n rowEndPinned: floatingEnd,\n columnStart: allDisplayedColumns[0],\n columnEnd: last(allDisplayedColumns)\n });\n }\n event.preventDefault();\n };\n RowContainerEventsFeature.prototype.onCtrlAndC = function (event) {\n if (!this.clipboardService || this.gridOptionsWrapper.isEnableCellTextSelection()) {\n return;\n }\n this.clipboardService.copyToClipboard();\n event.preventDefault();\n };\n RowContainerEventsFeature.prototype.onCtrlAndV = function () {\n if (ModuleRegistry.isRegistered(ModuleNames.ClipboardModule) && !this.gridOptionsWrapper.isSuppressClipboardPaste()) {\n this.clipboardService.pasteFromClipboard();\n }\n };\n RowContainerEventsFeature.prototype.onCtrlAndD = function (event) {\n if (ModuleRegistry.isRegistered(ModuleNames.ClipboardModule) && !this.gridOptionsWrapper.isSuppressClipboardPaste()) {\n this.clipboardService.copyRangeDown();\n }\n event.preventDefault();\n };\n RowContainerEventsFeature.prototype.onCtrlAndZ = function (event) {\n if (!this.gridOptionsWrapper.isUndoRedoCellEditing()) {\n return;\n }\n event.preventDefault();\n if (event.shiftKey) {\n this.undoRedoService.redo();\n }\n else {\n this.undoRedoService.undo();\n }\n };\n RowContainerEventsFeature.prototype.onCtrlAndY = function () {\n this.undoRedoService.redo();\n };\n __decorate$1M([\n Autowired('mouseEventService')\n ], RowContainerEventsFeature.prototype, \"mouseEventService\", void 0);\n __decorate$1M([\n Autowired('valueService')\n ], RowContainerEventsFeature.prototype, \"valueService\", void 0);\n __decorate$1M([\n Optional('contextMenuFactory')\n ], RowContainerEventsFeature.prototype, \"contextMenuFactory\", void 0);\n __decorate$1M([\n Autowired('ctrlsService')\n ], RowContainerEventsFeature.prototype, \"ctrlsService\", void 0);\n __decorate$1M([\n Autowired('navigationService')\n ], RowContainerEventsFeature.prototype, \"navigationService\", void 0);\n __decorate$1M([\n Autowired('focusService')\n ], RowContainerEventsFeature.prototype, \"focusService\", void 0);\n __decorate$1M([\n Autowired('undoRedoService')\n ], RowContainerEventsFeature.prototype, \"undoRedoService\", void 0);\n __decorate$1M([\n Autowired('columnModel')\n ], RowContainerEventsFeature.prototype, \"columnModel\", void 0);\n __decorate$1M([\n Autowired('paginationProxy')\n ], RowContainerEventsFeature.prototype, \"paginationProxy\", void 0);\n __decorate$1M([\n Autowired('pinnedRowModel')\n ], RowContainerEventsFeature.prototype, \"pinnedRowModel\", void 0);\n __decorate$1M([\n Optional('rangeService')\n ], RowContainerEventsFeature.prototype, \"rangeService\", void 0);\n __decorate$1M([\n Optional('clipboardService')\n ], RowContainerEventsFeature.prototype, \"clipboardService\", void 0);\n __decorate$1M([\n PostConstruct\n ], RowContainerEventsFeature.prototype, \"postConstruct\", null);\n return RowContainerEventsFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1S = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1L = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n// listens to changes in the center viewport size, for column and row virtualisation,\n// and adjusts grid as necessary. there are two viewports, one for horizontal and one for\n// vertical scrolling.\nvar ViewportSizeFeature = /** @class */ (function (_super) {\n __extends$1S(ViewportSizeFeature, _super);\n function ViewportSizeFeature(centerContainerCtrl) {\n var _this = _super.call(this) || this;\n _this.centerContainerCtrl = centerContainerCtrl;\n return _this;\n }\n ViewportSizeFeature.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function () {\n _this.gridBodyCtrl = _this.ctrlsService.getGridBodyCtrl();\n _this.listenForResize();\n });\n this.addManagedListener(this.eventService, Events.EVENT_SCROLLBAR_WIDTH_CHANGED, this.onScrollbarWidthChanged.bind(this));\n };\n ViewportSizeFeature.prototype.listenForResize = function () {\n var _this = this;\n var listener = function () { return _this.onCenterViewportResized(); };\n // centerContainer gets horizontal resizes\n this.centerContainerCtrl.registerViewportResizeListener(listener);\n // eBodyViewport gets vertical resizes\n this.gridBodyCtrl.registerBodyViewportResizeListener(listener);\n };\n ViewportSizeFeature.prototype.onScrollbarWidthChanged = function () {\n this.checkViewportAndScrolls();\n };\n ViewportSizeFeature.prototype.onCenterViewportResized = function () {\n if (this.centerContainerCtrl.isViewportVisible()) {\n this.checkViewportAndScrolls();\n var newWidth = this.centerContainerCtrl.getCenterWidth();\n if (newWidth !== this.centerWidth) {\n this.centerWidth = newWidth;\n this.columnModel.refreshFlexedColumns({ viewportWidth: this.centerWidth, updateBodyWidths: true, fireResizedEvent: true });\n }\n }\n else {\n this.bodyHeight = 0;\n }\n };\n // gets called every time the viewport size changes. we use this to check visibility of scrollbars\n // in the grid panel, and also to check size and position of viewport for row and column virtualisation.\n ViewportSizeFeature.prototype.checkViewportAndScrolls = function () {\n // results in updating anything that depends on scroll showing\n this.updateScrollVisibleService();\n // fires event if height changes, used by PaginationService, HeightScalerService, RowRenderer\n this.checkBodyHeight();\n // check for virtual columns for ColumnController\n this.onHorizontalViewportChanged();\n this.gridBodyCtrl.getScrollFeature().checkScrollLeft();\n };\n ViewportSizeFeature.prototype.getBodyHeight = function () {\n return this.bodyHeight;\n };\n ViewportSizeFeature.prototype.checkBodyHeight = function () {\n var eBodyViewport = this.gridBodyCtrl.getBodyViewportElement();\n var bodyHeight = getInnerHeight(eBodyViewport);\n if (this.bodyHeight !== bodyHeight) {\n this.bodyHeight = bodyHeight;\n var event_1 = {\n type: Events.EVENT_BODY_HEIGHT_CHANGED\n };\n this.eventService.dispatchEvent(event_1);\n }\n };\n ViewportSizeFeature.prototype.updateScrollVisibleService = function () {\n // because of column animation (which takes 200ms), we have to do this twice.\n // eg if user removes cols anywhere except at the RHS, then the cols on the RHS\n // will animate to the left to fill the gap. this animation means just after\n // the cols are removed, the remaining cols are still in the original location\n // at the start of the animation, so pre animation the H scrollbar is still needed,\n // but post animation it is not.\n this.updateScrollVisibleServiceImpl();\n setTimeout(this.updateScrollVisibleServiceImpl.bind(this), 500);\n };\n ViewportSizeFeature.prototype.updateScrollVisibleServiceImpl = function () {\n var params = {\n horizontalScrollShowing: this.isHorizontalScrollShowing(),\n verticalScrollShowing: this.gridBodyCtrl.isVerticalScrollShowing()\n };\n this.scrollVisibleService.setScrollsVisible(params);\n // fix - gridComp should just listen to event from above\n this.gridBodyCtrl.setVerticalScrollPaddingVisible(params.verticalScrollShowing);\n };\n ViewportSizeFeature.prototype.isHorizontalScrollShowing = function () {\n var isAlwaysShowHorizontalScroll = this.gridOptionsWrapper.isAlwaysShowHorizontalScroll();\n return isAlwaysShowHorizontalScroll || this.centerContainerCtrl.isViewportHScrollShowing();\n };\n // this gets called whenever a change in the viewport, so we can inform column controller it has to work\n // out the virtual columns again. gets called from following locations:\n // + ensureColVisible, scroll, init, layoutChanged, displayedColumnsChanged, API (doLayout)\n ViewportSizeFeature.prototype.onHorizontalViewportChanged = function () {\n var scrollWidth = this.centerContainerCtrl.getCenterWidth();\n var scrollPosition = this.centerContainerCtrl.getViewportScrollLeft();\n this.columnModel.setViewportPosition(scrollWidth, scrollPosition);\n };\n __decorate$1L([\n Autowired('ctrlsService')\n ], ViewportSizeFeature.prototype, \"ctrlsService\", void 0);\n __decorate$1L([\n Autowired('columnModel')\n ], ViewportSizeFeature.prototype, \"columnModel\", void 0);\n __decorate$1L([\n Autowired('scrollVisibleService')\n ], ViewportSizeFeature.prototype, \"scrollVisibleService\", void 0);\n __decorate$1L([\n PostConstruct\n ], ViewportSizeFeature.prototype, \"postConstruct\", null);\n return ViewportSizeFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1R = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1K = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SetPinnedLeftWidthFeature = /** @class */ (function (_super) {\n __extends$1R(SetPinnedLeftWidthFeature, _super);\n function SetPinnedLeftWidthFeature(element) {\n var _this = _super.call(this) || this;\n _this.element = element;\n return _this;\n }\n SetPinnedLeftWidthFeature.prototype.postConstruct = function () {\n this.addManagedListener(this.eventService, Events.EVENT_LEFT_PINNED_WIDTH_CHANGED, this.onPinnedLeftWidthChanged.bind(this));\n };\n SetPinnedLeftWidthFeature.prototype.onPinnedLeftWidthChanged = function () {\n var leftWidth = this.pinnedWidthService.getPinnedLeftWidth();\n var displayed = leftWidth > 0;\n setDisplayed(this.element, displayed);\n if (displayed) {\n setFixedWidth(this.element, leftWidth);\n }\n };\n __decorate$1K([\n Autowired('pinnedWidthService')\n ], SetPinnedLeftWidthFeature.prototype, \"pinnedWidthService\", void 0);\n __decorate$1K([\n PostConstruct\n ], SetPinnedLeftWidthFeature.prototype, \"postConstruct\", null);\n return SetPinnedLeftWidthFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1Q = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1J = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SetPinnedRightWidthFeature = /** @class */ (function (_super) {\n __extends$1Q(SetPinnedRightWidthFeature, _super);\n function SetPinnedRightWidthFeature(element) {\n var _this = _super.call(this) || this;\n _this.element = element;\n return _this;\n }\n SetPinnedRightWidthFeature.prototype.postConstruct = function () {\n this.addManagedListener(this.eventService, Events.EVENT_RIGHT_PINNED_WIDTH_CHANGED, this.onPinnedRightWidthChanged.bind(this));\n };\n SetPinnedRightWidthFeature.prototype.onPinnedRightWidthChanged = function () {\n var rightWidth = this.pinnedWidthService.getPinnedRightWidth();\n var displayed = rightWidth > 0;\n setDisplayed(this.element, displayed);\n if (displayed) {\n setFixedWidth(this.element, rightWidth);\n }\n };\n __decorate$1J([\n Autowired('pinnedWidthService')\n ], SetPinnedRightWidthFeature.prototype, \"pinnedWidthService\", void 0);\n __decorate$1J([\n PostConstruct\n ], SetPinnedRightWidthFeature.prototype, \"postConstruct\", null);\n return SetPinnedRightWidthFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1P = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1I = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SetHeightFeature = /** @class */ (function (_super) {\n __extends$1P(SetHeightFeature, _super);\n function SetHeightFeature(eContainer, eWrapper) {\n var _this = _super.call(this) || this;\n _this.eContainer = eContainer;\n _this.eWrapper = eWrapper;\n return _this;\n }\n SetHeightFeature.prototype.postConstruct = function () {\n this.addManagedListener(this.eventService, Events.EVENT_ROW_CONTAINER_HEIGHT_CHANGED, this.onHeightChanged.bind(this));\n };\n SetHeightFeature.prototype.onHeightChanged = function () {\n var height = this.maxDivHeightScaler.getUiContainerHeight();\n var heightString = height != null ? height + \"px\" : \"\";\n this.eContainer.style.height = heightString;\n if (this.eWrapper) {\n this.eWrapper.style.height = heightString;\n }\n };\n __decorate$1I([\n Autowired(\"rowContainerHeightService\")\n ], SetHeightFeature.prototype, \"maxDivHeightScaler\", void 0);\n __decorate$1I([\n PostConstruct\n ], SetHeightFeature.prototype, \"postConstruct\", null);\n return SetHeightFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1O = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1H = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar DragListenerFeature = /** @class */ (function (_super) {\n __extends$1O(DragListenerFeature, _super);\n function DragListenerFeature(eContainer) {\n var _this = _super.call(this) || this;\n _this.eContainer = eContainer;\n return _this;\n }\n DragListenerFeature.prototype.postConstruct = function () {\n var _this = this;\n if (!this.gridOptionsWrapper.isEnableRangeSelection() || // no range selection if no property\n missing(this.rangeService) // no range selection if not enterprise version\n ) {\n return;\n }\n var params = {\n eElement: this.eContainer,\n onDragStart: this.rangeService.onDragStart.bind(this.rangeService),\n onDragStop: this.rangeService.onDragStop.bind(this.rangeService),\n onDragging: this.rangeService.onDragging.bind(this.rangeService)\n };\n this.dragService.addDragSource(params);\n this.addDestroyFunc(function () { return _this.dragService.removeDragSource(params); });\n };\n __decorate$1H([\n Optional('rangeService')\n ], DragListenerFeature.prototype, \"rangeService\", void 0);\n __decorate$1H([\n Autowired('dragService')\n ], DragListenerFeature.prototype, \"dragService\", void 0);\n __decorate$1H([\n PostConstruct\n ], DragListenerFeature.prototype, \"postConstruct\", null);\n return DragListenerFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1N = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1G = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar CenterWidthFeature = /** @class */ (function (_super) {\n __extends$1N(CenterWidthFeature, _super);\n function CenterWidthFeature(callback) {\n var _this = _super.call(this) || this;\n _this.callback = callback;\n return _this;\n }\n CenterWidthFeature.prototype.postConstruct = function () {\n var listener = this.setWidth.bind(this);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, listener);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, listener);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, listener);\n this.setWidth();\n };\n CenterWidthFeature.prototype.setWidth = function () {\n var columnModel = this.columnModel;\n var printLayout = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n var centerWidth = columnModel.getBodyContainerWidth();\n var leftWidth = columnModel.getDisplayedColumnsLeftWidth();\n var rightWidth = columnModel.getDisplayedColumnsRightWidth();\n var totalWidth = printLayout ? centerWidth + leftWidth + rightWidth : centerWidth;\n this.callback(totalWidth);\n };\n __decorate$1G([\n Autowired('columnModel')\n ], CenterWidthFeature.prototype, \"columnModel\", void 0);\n __decorate$1G([\n PostConstruct\n ], CenterWidthFeature.prototype, \"postConstruct\", null);\n return CenterWidthFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1M = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1F = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$f = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$c = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$f(arguments[i]));\n return ar;\n};\nvar RowContainerName;\n(function (RowContainerName) {\n RowContainerName[\"LEFT\"] = \"left\";\n RowContainerName[\"RIGHT\"] = \"right\";\n RowContainerName[\"CENTER\"] = \"center\";\n RowContainerName[\"FULL_WIDTH\"] = \"fullWidth\";\n RowContainerName[\"TOP_LEFT\"] = \"topLeft\";\n RowContainerName[\"TOP_RIGHT\"] = \"topRight\";\n RowContainerName[\"TOP_CENTER\"] = \"topCenter\";\n RowContainerName[\"TOP_FULL_WIDTH\"] = \"topFullWidth\";\n RowContainerName[\"STICKY_TOP_LEFT\"] = \"stickyTopLeft\";\n RowContainerName[\"STICKY_TOP_RIGHT\"] = \"stickyTopRight\";\n RowContainerName[\"STICKY_TOP_CENTER\"] = \"stickyTopCenter\";\n RowContainerName[\"STICKY_TOP_FULL_WIDTH\"] = \"stickyTopFullWidth\";\n RowContainerName[\"BOTTOM_LEFT\"] = \"bottomLeft\";\n RowContainerName[\"BOTTOM_RIGHT\"] = \"bottomRight\";\n RowContainerName[\"BOTTOM_CENTER\"] = \"bottomCenter\";\n RowContainerName[\"BOTTOM_FULL_WIDTH\"] = \"bottomFullWidth\";\n})(RowContainerName || (RowContainerName = {}));\nvar RowContainerType;\n(function (RowContainerType) {\n RowContainerType[\"LEFT\"] = \"left\";\n RowContainerType[\"RIGHT\"] = \"right\";\n RowContainerType[\"CENTER\"] = \"center\";\n RowContainerType[\"FULL_WIDTH\"] = \"fullWidth\";\n})(RowContainerType || (RowContainerType = {}));\nfunction getRowContainerTypeForName(name) {\n switch (name) {\n case RowContainerName.CENTER:\n case RowContainerName.TOP_CENTER:\n case RowContainerName.STICKY_TOP_CENTER:\n case RowContainerName.BOTTOM_CENTER:\n return RowContainerType.CENTER;\n case RowContainerName.LEFT:\n case RowContainerName.TOP_LEFT:\n case RowContainerName.STICKY_TOP_LEFT:\n case RowContainerName.BOTTOM_LEFT:\n return RowContainerType.LEFT;\n case RowContainerName.RIGHT:\n case RowContainerName.TOP_RIGHT:\n case RowContainerName.STICKY_TOP_RIGHT:\n case RowContainerName.BOTTOM_RIGHT:\n return RowContainerType.RIGHT;\n case RowContainerName.FULL_WIDTH:\n case RowContainerName.TOP_FULL_WIDTH:\n case RowContainerName.STICKY_TOP_FULL_WIDTH:\n case RowContainerName.BOTTOM_FULL_WIDTH:\n return RowContainerType.FULL_WIDTH;\n default:\n throw Error('Invalid Row Container Type');\n }\n}\nvar ContainerCssClasses = convertToMap([\n [RowContainerName.CENTER, 'ag-center-cols-container'],\n [RowContainerName.LEFT, 'ag-pinned-left-cols-container'],\n [RowContainerName.RIGHT, 'ag-pinned-right-cols-container'],\n [RowContainerName.FULL_WIDTH, 'ag-full-width-container'],\n [RowContainerName.TOP_CENTER, 'ag-floating-top-container'],\n [RowContainerName.TOP_LEFT, 'ag-pinned-left-floating-top'],\n [RowContainerName.TOP_RIGHT, 'ag-pinned-right-floating-top'],\n [RowContainerName.TOP_FULL_WIDTH, 'ag-floating-top-full-width-container'],\n [RowContainerName.STICKY_TOP_CENTER, 'ag-sticky-top-container'],\n [RowContainerName.STICKY_TOP_LEFT, 'ag-pinned-left-sticky-top'],\n [RowContainerName.STICKY_TOP_RIGHT, 'ag-pinned-right-sticky-top'],\n [RowContainerName.STICKY_TOP_FULL_WIDTH, 'ag-sticky-top-full-width-container'],\n [RowContainerName.BOTTOM_CENTER, 'ag-floating-bottom-container'],\n [RowContainerName.BOTTOM_LEFT, 'ag-pinned-left-floating-bottom'],\n [RowContainerName.BOTTOM_RIGHT, 'ag-pinned-right-floating-bottom'],\n [RowContainerName.BOTTOM_FULL_WIDTH, 'ag-floating-bottom-full-width-container'],\n]);\nvar ViewportCssClasses = convertToMap([\n [RowContainerName.CENTER, 'ag-center-cols-viewport'],\n [RowContainerName.TOP_CENTER, 'ag-floating-top-viewport'],\n [RowContainerName.STICKY_TOP_CENTER, 'ag-sticky-top-viewport'],\n [RowContainerName.BOTTOM_CENTER, 'ag-floating-bottom-viewport'],\n]);\nvar WrapperCssClasses = convertToMap([\n [RowContainerName.CENTER, 'ag-center-cols-clipper'],\n]);\nvar RowContainerCtrl = /** @class */ (function (_super) {\n __extends$1M(RowContainerCtrl, _super);\n function RowContainerCtrl(name) {\n var _this = _super.call(this) || this;\n _this.name = name;\n return _this;\n }\n RowContainerCtrl.getRowContainerCssClasses = function (name) {\n var containerClass = ContainerCssClasses.get(name);\n var viewportClass = ViewportCssClasses.get(name);\n var wrapperClass = WrapperCssClasses.get(name);\n return { container: containerClass, viewport: viewportClass, wrapper: wrapperClass };\n };\n RowContainerCtrl.getPinned = function (name) {\n switch (name) {\n case RowContainerName.BOTTOM_LEFT:\n case RowContainerName.TOP_LEFT:\n case RowContainerName.STICKY_TOP_LEFT:\n case RowContainerName.LEFT:\n return Constants.PINNED_LEFT;\n case RowContainerName.BOTTOM_RIGHT:\n case RowContainerName.TOP_RIGHT:\n case RowContainerName.STICKY_TOP_RIGHT:\n case RowContainerName.RIGHT:\n return Constants.PINNED_RIGHT;\n default:\n return null;\n }\n };\n RowContainerCtrl.prototype.postConstruct = function () {\n var _this = this;\n this.enableRtl = this.gridOptionsWrapper.isEnableRtl();\n this.embedFullWidthRows = this.gridOptionsWrapper.isEmbedFullWidthRows();\n this.forContainers([RowContainerName.CENTER], function () { return _this.viewportSizeFeature = _this.createManagedBean(new ViewportSizeFeature(_this)); });\n };\n RowContainerCtrl.prototype.registerWithCtrlsService = function () {\n switch (this.name) {\n case RowContainerName.CENTER:\n this.ctrlsService.registerCenterRowContainerCtrl(this);\n break;\n case RowContainerName.LEFT:\n this.ctrlsService.registerLeftRowContainerCtrl(this);\n break;\n case RowContainerName.RIGHT:\n this.ctrlsService.registerRightRowContainerCtrl(this);\n break;\n case RowContainerName.TOP_CENTER:\n this.ctrlsService.registerTopCenterRowContainerCtrl(this);\n break;\n case RowContainerName.TOP_LEFT:\n this.ctrlsService.registerTopLeftRowContainerCon(this);\n break;\n case RowContainerName.TOP_RIGHT:\n this.ctrlsService.registerTopRightRowContainerCtrl(this);\n break;\n case RowContainerName.STICKY_TOP_CENTER:\n this.ctrlsService.registerStickyTopCenterRowContainerCtrl(this);\n break;\n case RowContainerName.STICKY_TOP_LEFT:\n this.ctrlsService.registerStickyTopLeftRowContainerCon(this);\n break;\n case RowContainerName.STICKY_TOP_RIGHT:\n this.ctrlsService.registerStickyTopRightRowContainerCtrl(this);\n break;\n case RowContainerName.BOTTOM_CENTER:\n this.ctrlsService.registerBottomCenterRowContainerCtrl(this);\n break;\n case RowContainerName.BOTTOM_LEFT:\n this.ctrlsService.registerBottomLeftRowContainerCtrl(this);\n break;\n case RowContainerName.BOTTOM_RIGHT:\n this.ctrlsService.registerBottomRightRowContainerCtrl(this);\n break;\n }\n };\n RowContainerCtrl.prototype.forContainers = function (names, callback) {\n if (names.indexOf(this.name) >= 0) {\n callback();\n }\n };\n RowContainerCtrl.prototype.getContainerElement = function () {\n return this.eContainer;\n };\n RowContainerCtrl.prototype.getViewportSizeFeature = function () {\n return this.viewportSizeFeature;\n };\n RowContainerCtrl.prototype.setComp = function (view, eContainer, eViewport, eWrapper) {\n var _this = this;\n this.comp = view;\n this.eContainer = eContainer;\n this.eViewport = eViewport;\n this.eWrapper = eWrapper;\n this.createManagedBean(new RowContainerEventsFeature(this.eContainer));\n this.addPreventScrollWhileDragging();\n this.listenOnDomOrder();\n this.stopHScrollOnPinnedRows();\n var allTopNoFW = [RowContainerName.TOP_CENTER, RowContainerName.TOP_LEFT, RowContainerName.TOP_RIGHT];\n var allStickyTopNoFW = [RowContainerName.STICKY_TOP_CENTER, RowContainerName.STICKY_TOP_LEFT, RowContainerName.STICKY_TOP_RIGHT];\n var allBottomNoFW = [RowContainerName.BOTTOM_CENTER, RowContainerName.BOTTOM_LEFT, RowContainerName.BOTTOM_RIGHT];\n var allMiddleNoFW = [RowContainerName.CENTER, RowContainerName.LEFT, RowContainerName.RIGHT];\n var allNoFW = __spread$c(allTopNoFW, allBottomNoFW, allMiddleNoFW, allStickyTopNoFW);\n var allMiddle = [RowContainerName.CENTER, RowContainerName.LEFT, RowContainerName.RIGHT, RowContainerName.FULL_WIDTH];\n var allCenter = [RowContainerName.CENTER, RowContainerName.TOP_CENTER, RowContainerName.STICKY_TOP_CENTER, RowContainerName.BOTTOM_CENTER];\n var allLeft = [RowContainerName.LEFT, RowContainerName.BOTTOM_LEFT, RowContainerName.TOP_LEFT, RowContainerName.STICKY_TOP_LEFT];\n var allRight = [RowContainerName.RIGHT, RowContainerName.BOTTOM_RIGHT, RowContainerName.TOP_RIGHT, RowContainerName.STICKY_TOP_RIGHT];\n this.forContainers(allLeft, function () { return _this.createManagedBean(new SetPinnedLeftWidthFeature(_this.eContainer)); });\n this.forContainers(allRight, function () { return _this.createManagedBean(new SetPinnedRightWidthFeature(_this.eContainer)); });\n this.forContainers(allMiddle, function () { return _this.createManagedBean(new SetHeightFeature(_this.eContainer, _this.eWrapper)); });\n this.forContainers(allNoFW, function () { return _this.createManagedBean(new DragListenerFeature(_this.eContainer)); });\n this.forContainers(allCenter, function () { return _this.createManagedBean(new CenterWidthFeature(function (width) { return _this.comp.setContainerWidth(width + \"px\"); })); });\n this.addListeners();\n this.registerWithCtrlsService();\n };\n RowContainerCtrl.prototype.addListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_SCROLL_VISIBILITY_CHANGED, function () { return _this.onScrollVisibilityChanged(); });\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, function () { return _this.onDisplayedColumnsChanged(); });\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, function () { return _this.onDisplayedColumnsWidthChanged(); });\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_ROWS_CHANGED, function () { return _this.onDisplayedRowsChanged(); });\n this.onScrollVisibilityChanged();\n this.onDisplayedColumnsChanged();\n this.onDisplayedColumnsWidthChanged();\n this.onDisplayedRowsChanged();\n };\n RowContainerCtrl.prototype.listenOnDomOrder = function () {\n var _this = this;\n // sticky section must show rows in set order\n var allStickyContainers = [RowContainerName.STICKY_TOP_CENTER, RowContainerName.STICKY_TOP_LEFT, RowContainerName.STICKY_TOP_RIGHT, RowContainerName.STICKY_TOP_FULL_WIDTH];\n var isStickContainer = allStickyContainers.indexOf(this.name) >= 0;\n if (isStickContainer) {\n this.comp.setDomOrder(true);\n return;\n }\n var listener = function () { return _this.comp.setDomOrder(_this.gridOptionsWrapper.isEnsureDomOrder()); };\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, listener);\n listener();\n };\n // when editing a pinned row, if the cell is half outside the scrollable area, the browser can\n // scroll the column into view. we do not want this, the pinned sections should never scroll.\n // so we listen to scrolls on these containers and reset the scroll if we find one.\n RowContainerCtrl.prototype.stopHScrollOnPinnedRows = function () {\n var _this = this;\n this.forContainers([RowContainerName.TOP_CENTER, RowContainerName.STICKY_TOP_CENTER, RowContainerName.BOTTOM_CENTER], function () {\n var resetScrollLeft = function () { return _this.eViewport.scrollLeft = 0; };\n _this.addManagedListener(_this.eViewport, 'scroll', resetScrollLeft);\n });\n };\n RowContainerCtrl.prototype.onDisplayedColumnsChanged = function () {\n var _this = this;\n this.forContainers([RowContainerName.CENTER], function () { return _this.onHorizontalViewportChanged(); });\n };\n RowContainerCtrl.prototype.onDisplayedColumnsWidthChanged = function () {\n var _this = this;\n this.forContainers([RowContainerName.CENTER], function () { return _this.onHorizontalViewportChanged(); });\n };\n RowContainerCtrl.prototype.onScrollVisibilityChanged = function () {\n if (this.name !== RowContainerName.CENTER) {\n return;\n }\n var visible = this.scrollVisibleService.isHorizontalScrollShowing();\n var scrollbarWidth = visible ? (this.gridOptionsWrapper.getScrollbarWidth() || 0) : 0;\n var height = scrollbarWidth == 0 ? '100%' : \"calc(100% + \" + scrollbarWidth + \"px)\";\n this.comp.setViewportHeight(height);\n };\n // this methods prevents the grid views from being scrolled while the dragService is being used\n // eg. the view should not scroll up and down while dragging rows using the rowDragComp.\n RowContainerCtrl.prototype.addPreventScrollWhileDragging = function () {\n var _this = this;\n var preventScroll = function (e) {\n if (_this.dragService.isDragging()) {\n if (e.cancelable) {\n e.preventDefault();\n }\n }\n };\n this.eContainer.addEventListener('touchmove', preventScroll, { passive: false });\n this.addDestroyFunc(function () { return _this.eContainer.removeEventListener('touchmove', preventScroll); });\n };\n // this gets called whenever a change in the viewport, so we can inform column controller it has to work\n // out the virtual columns again. gets called from following locations:\n // + ensureColVisible, scroll, init, layoutChanged, displayedColumnsChanged, API (doLayout)\n RowContainerCtrl.prototype.onHorizontalViewportChanged = function () {\n var scrollWidth = this.getCenterWidth();\n var scrollPosition = this.getCenterViewportScrollLeft();\n this.columnModel.setViewportPosition(scrollWidth, scrollPosition);\n };\n RowContainerCtrl.prototype.getCenterWidth = function () {\n return getInnerWidth(this.eViewport);\n };\n RowContainerCtrl.prototype.getCenterViewportScrollLeft = function () {\n // we defer to a util, as how you calculated scrollLeft when doing RTL depends on the browser\n return getScrollLeft(this.eViewport, this.enableRtl);\n };\n RowContainerCtrl.prototype.registerViewportResizeListener = function (listener) {\n var unsubscribeFromResize = this.resizeObserverService.observeResize(this.eViewport, listener);\n this.addDestroyFunc(function () { return unsubscribeFromResize(); });\n };\n RowContainerCtrl.prototype.isViewportVisible = function () {\n return isVisible(this.eViewport);\n };\n RowContainerCtrl.prototype.isViewportHScrollShowing = function () {\n return isHorizontalScrollShowing(this.eViewport);\n };\n RowContainerCtrl.prototype.getViewportScrollLeft = function () {\n return getScrollLeft(this.eViewport, this.enableRtl);\n };\n RowContainerCtrl.prototype.isHorizontalScrollShowing = function () {\n var isAlwaysShowHorizontalScroll = this.gridOptionsWrapper.isAlwaysShowHorizontalScroll();\n return isAlwaysShowHorizontalScroll || isHorizontalScrollShowing(this.eViewport);\n };\n RowContainerCtrl.prototype.getViewportElement = function () {\n return this.eViewport;\n };\n RowContainerCtrl.prototype.setContainerTranslateX = function (amount) {\n this.eContainer.style.transform = \"translateX(\" + amount + \"px)\";\n };\n RowContainerCtrl.prototype.getHScrollPosition = function () {\n var res = {\n left: this.eViewport.scrollLeft,\n right: this.eViewport.scrollLeft + this.eViewport.offsetWidth\n };\n return res;\n };\n RowContainerCtrl.prototype.setCenterViewportScrollLeft = function (value) {\n // we defer to a util, as how you calculated scrollLeft when doing RTL depends on the browser\n setScrollLeft(this.eViewport, value, this.enableRtl);\n };\n RowContainerCtrl.prototype.onDisplayedRowsChanged = function () {\n var _this = this;\n var fullWithContainer = this.name === RowContainerName.TOP_FULL_WIDTH\n || this.name === RowContainerName.STICKY_TOP_FULL_WIDTH\n || this.name === RowContainerName.BOTTOM_FULL_WIDTH\n || this.name === RowContainerName.FULL_WIDTH;\n var doesRowMatch = function (rowCtrl) {\n var fullWidthRow = rowCtrl.isFullWidth();\n var printLayout = _this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n var embedFW = _this.embedFullWidthRows || printLayout;\n var match = fullWithContainer ?\n !embedFW && fullWidthRow\n : embedFW || !fullWidthRow;\n return match;\n };\n // this list contains either all pinned top, center or pinned bottom rows\n var allRowsRegardlessOfFullWidth = this.getRowCtrls();\n // this filters out rows not for this container, eg if it's a full with row, but we are not full with container\n var rowsThisContainer = allRowsRegardlessOfFullWidth.filter(doesRowMatch);\n this.comp.setRowCtrls(rowsThisContainer);\n };\n RowContainerCtrl.prototype.getRowCtrls = function () {\n switch (this.name) {\n case RowContainerName.TOP_CENTER:\n case RowContainerName.TOP_LEFT:\n case RowContainerName.TOP_RIGHT:\n case RowContainerName.TOP_FULL_WIDTH:\n return this.rowRenderer.getTopRowCtrls();\n case RowContainerName.STICKY_TOP_CENTER:\n case RowContainerName.STICKY_TOP_LEFT:\n case RowContainerName.STICKY_TOP_RIGHT:\n case RowContainerName.STICKY_TOP_FULL_WIDTH:\n return this.rowRenderer.getStickyTopRowCtrls();\n case RowContainerName.BOTTOM_CENTER:\n case RowContainerName.BOTTOM_LEFT:\n case RowContainerName.BOTTOM_RIGHT:\n case RowContainerName.BOTTOM_FULL_WIDTH:\n return this.rowRenderer.getBottomRowCtrls();\n default:\n return this.rowRenderer.getRowCtrls();\n }\n };\n __decorate$1F([\n Autowired('scrollVisibleService')\n ], RowContainerCtrl.prototype, \"scrollVisibleService\", void 0);\n __decorate$1F([\n Autowired('dragService')\n ], RowContainerCtrl.prototype, \"dragService\", void 0);\n __decorate$1F([\n Autowired('ctrlsService')\n ], RowContainerCtrl.prototype, \"ctrlsService\", void 0);\n __decorate$1F([\n Autowired('columnModel')\n ], RowContainerCtrl.prototype, \"columnModel\", void 0);\n __decorate$1F([\n Autowired('resizeObserverService')\n ], RowContainerCtrl.prototype, \"resizeObserverService\", void 0);\n __decorate$1F([\n Autowired('rowRenderer')\n ], RowContainerCtrl.prototype, \"rowRenderer\", void 0);\n __decorate$1F([\n PostConstruct\n ], RowContainerCtrl.prototype, \"postConstruct\", null);\n return RowContainerCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1L = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1E = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GRID_BODY_TEMPLATE = /* html */ \"<div class=\\\"ag-root ag-unselectable\\\" role=\\\"grid\\\">\\n <ag-header-root ref=\\\"gridHeader\\\"></ag-header-root>\\n <div class=\\\"ag-floating-top\\\" ref=\\\"eTop\\\" role=\\\"presentation\\\">\\n <ag-row-container ref=\\\"topLeftContainer\\\" name=\\\"\" + RowContainerName.TOP_LEFT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"topCenterContainer\\\" name=\\\"\" + RowContainerName.TOP_CENTER + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"topRightContainer\\\" name=\\\"\" + RowContainerName.TOP_RIGHT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"topFullWidthContainer\\\" name=\\\"\" + RowContainerName.TOP_FULL_WIDTH + \"\\\"></ag-row-container>\\n </div>\\n <div class=\\\"ag-body-viewport\\\" ref=\\\"eBodyViewport\\\" role=\\\"presentation\\\">\\n <ag-row-container ref=\\\"leftContainer\\\" name=\\\"\" + RowContainerName.LEFT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"centerContainer\\\" name=\\\"\" + RowContainerName.CENTER + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"rightContainer\\\" name=\\\"\" + RowContainerName.RIGHT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"fullWidthContainer\\\" name=\\\"\" + RowContainerName.FULL_WIDTH + \"\\\"></ag-row-container>\\n </div>\\n <div class=\\\"ag-sticky-top\\\" ref=\\\"eStickyTop\\\" role=\\\"presentation\\\">\\n <ag-row-container ref=\\\"stickyTopLeftContainer\\\" name=\\\"\" + RowContainerName.STICKY_TOP_LEFT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"stickyTopCenterContainer\\\" name=\\\"\" + RowContainerName.STICKY_TOP_CENTER + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"stickyTopRightContainer\\\" name=\\\"\" + RowContainerName.STICKY_TOP_RIGHT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"stickyTopFullWidthContainer\\\" name=\\\"\" + RowContainerName.STICKY_TOP_FULL_WIDTH + \"\\\"></ag-row-container>\\n </div>\\n <div class=\\\"ag-floating-bottom\\\" ref=\\\"eBottom\\\" role=\\\"presentation\\\">\\n <ag-row-container ref=\\\"bottomLeftContainer\\\" name=\\\"\" + RowContainerName.BOTTOM_LEFT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"bottomCenterContainer\\\" name=\\\"\" + RowContainerName.BOTTOM_CENTER + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"bottomRightContainer\\\" name=\\\"\" + RowContainerName.BOTTOM_RIGHT + \"\\\"></ag-row-container>\\n <ag-row-container ref=\\\"bottomFullWidthContainer\\\" name=\\\"\" + RowContainerName.BOTTOM_FULL_WIDTH + \"\\\"></ag-row-container>\\n </div>\\n <ag-fake-horizontal-scroll></ag-fake-horizontal-scroll>\\n <ag-overlay-wrapper></ag-overlay-wrapper>\\n </div>\";\nvar GridBodyComp = /** @class */ (function (_super) {\n __extends$1L(GridBodyComp, _super);\n function GridBodyComp() {\n return _super.call(this, GRID_BODY_TEMPLATE) || this;\n }\n GridBodyComp.prototype.init = function () {\n var _this = this;\n var setHeight = function (height, element) {\n var heightString = height + \"px\";\n element.style.minHeight = heightString;\n element.style.height = heightString;\n };\n var compProxy = {\n setRowAnimationCssOnBodyViewport: function (cssClass, animate) { return _this.setRowAnimationCssOnBodyViewport(cssClass, animate); },\n setColumnCount: function (count) { return setAriaColCount(_this.getGui(), count); },\n setRowCount: function (count) { return setAriaRowCount(_this.getGui(), count); },\n setTopHeight: function (height) { return setHeight(height, _this.eTop); },\n setBottomHeight: function (height) { return setHeight(height, _this.eBottom); },\n setTopDisplay: function (display) { return _this.eTop.style.display = display; },\n setBottomDisplay: function (display) { return _this.eBottom.style.display = display; },\n setStickyTopHeight: function (height) { return _this.eStickyTop.style.height = height; },\n setStickyTopTop: function (top) { return _this.eStickyTop.style.top = top; },\n setStickyTopWidth: function (width) { return _this.eStickyTop.style.width = width; },\n setColumnMovingCss: function (cssClass, flag) { return _this.addOrRemoveCssClass(CSS_CLASS_COLUMN_MOVING, flag); },\n updateLayoutClasses: function (cssClass, params) {\n var bodyViewportClassList = _this.eBodyViewport.classList;\n bodyViewportClassList.toggle(LayoutCssClasses.AUTO_HEIGHT, params.autoHeight);\n bodyViewportClassList.toggle(LayoutCssClasses.NORMAL, params.normal);\n bodyViewportClassList.toggle(LayoutCssClasses.PRINT, params.print);\n _this.addOrRemoveCssClass(LayoutCssClasses.AUTO_HEIGHT, params.autoHeight);\n _this.addOrRemoveCssClass(LayoutCssClasses.NORMAL, params.normal);\n _this.addOrRemoveCssClass(LayoutCssClasses.PRINT, params.print);\n },\n setAlwaysVerticalScrollClass: function (cssClass, on) {\n return _this.eBodyViewport.classList.toggle(CSS_CLASS_FORCE_VERTICAL_SCROLL, on);\n },\n registerBodyViewportResizeListener: function (listener) {\n var unsubscribeFromResize = _this.resizeObserverService.observeResize(_this.eBodyViewport, listener);\n _this.addDestroyFunc(function () { return unsubscribeFromResize(); });\n },\n setPinnedTopBottomOverflowY: function (overflow) { return _this.eTop.style.overflowY = _this.eBottom.style.overflowY = overflow; },\n setCellSelectableCss: function (cssClass, selectable) {\n [_this.eTop, _this.eBodyViewport, _this.eBottom]\n .forEach(function (ct) { return ct.classList.toggle(CSS_CLASS_CELL_SELECTABLE, selectable); });\n },\n };\n this.ctrl = this.createManagedBean(new GridBodyCtrl());\n this.ctrl.setComp(compProxy, this.getGui(), this.eBodyViewport, this.eTop, this.eBottom, this.eStickyTop);\n if (this.rangeService || this.gridOptionsWrapper.isRowSelectionMulti()) {\n setAriaMultiSelectable(this.getGui(), true);\n }\n };\n GridBodyComp.prototype.setRowAnimationCssOnBodyViewport = function (cssClass, animateRows) {\n var bodyViewportClassList = this.eBodyViewport.classList;\n bodyViewportClassList.toggle(RowAnimationCssClasses.ANIMATION_ON, animateRows);\n bodyViewportClassList.toggle(RowAnimationCssClasses.ANIMATION_OFF, !animateRows);\n };\n GridBodyComp.prototype.getFloatingTopBottom = function () {\n return [this.eTop, this.eBottom];\n };\n __decorate$1E([\n Autowired('resizeObserverService')\n ], GridBodyComp.prototype, \"resizeObserverService\", void 0);\n __decorate$1E([\n Optional('rangeService')\n ], GridBodyComp.prototype, \"rangeService\", void 0);\n __decorate$1E([\n RefSelector('eBodyViewport')\n ], GridBodyComp.prototype, \"eBodyViewport\", void 0);\n __decorate$1E([\n RefSelector('eStickyTop')\n ], GridBodyComp.prototype, \"eStickyTop\", void 0);\n __decorate$1E([\n RefSelector('eTop')\n ], GridBodyComp.prototype, \"eTop\", void 0);\n __decorate$1E([\n RefSelector('eBottom')\n ], GridBodyComp.prototype, \"eBottom\", void 0);\n __decorate$1E([\n RefSelector('gridHeader')\n ], GridBodyComp.prototype, \"headerRootComp\", void 0);\n __decorate$1E([\n PostConstruct\n ], GridBodyComp.prototype, \"init\", null);\n return GridBodyComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1K = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1D = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ScrollVisibleService = /** @class */ (function (_super) {\n __extends$1K(ScrollVisibleService, _super);\n function ScrollVisibleService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ScrollVisibleService.prototype.postConstruct = function () {\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, this.onDisplayedColumnsWidthChanged.bind(this));\n };\n ScrollVisibleService.prototype.onDisplayedColumnsChanged = function () {\n this.update();\n };\n ScrollVisibleService.prototype.onDisplayedColumnsWidthChanged = function () {\n this.update();\n };\n ScrollVisibleService.prototype.update = function () {\n // because of column animation (which takes 200ms), we have to do this twice.\n // eg if user removes cols anywhere except at the RHS, then the cols on the RHS\n // will animate to the left to fill the gap. this animation means just after\n // the cols are removed, the remaining cols are still in the original location\n // at the start of the animation, so pre animation the H scrollbar is still needed,\n // but post animation it is not.\n this.updateImpl();\n setTimeout(this.updateImpl.bind(this), 500);\n };\n ScrollVisibleService.prototype.updateImpl = function () {\n var centerRowCtrl = this.ctrlsService.getCenterRowContainerCtrl();\n if (!centerRowCtrl) {\n return;\n }\n var params = {\n horizontalScrollShowing: centerRowCtrl.isHorizontalScrollShowing(),\n verticalScrollShowing: this.isVerticalScrollShowing()\n };\n this.setScrollsVisible(params);\n };\n ScrollVisibleService.prototype.setScrollsVisible = function (params) {\n var atLeastOneDifferent = this.horizontalScrollShowing !== params.horizontalScrollShowing ||\n this.verticalScrollShowing !== params.verticalScrollShowing;\n if (atLeastOneDifferent) {\n this.horizontalScrollShowing = params.horizontalScrollShowing;\n this.verticalScrollShowing = params.verticalScrollShowing;\n var event_1 = {\n type: Events.EVENT_SCROLL_VISIBILITY_CHANGED\n };\n this.eventService.dispatchEvent(event_1);\n }\n };\n // used by pagination service - to know page height\n ScrollVisibleService.prototype.isHorizontalScrollShowing = function () {\n return this.horizontalScrollShowing;\n };\n // used by header container\n ScrollVisibleService.prototype.isVerticalScrollShowing = function () {\n return this.verticalScrollShowing;\n };\n __decorate$1D([\n Autowired('ctrlsService')\n ], ScrollVisibleService.prototype, \"ctrlsService\", void 0);\n __decorate$1D([\n PostConstruct\n ], ScrollVisibleService.prototype, \"postConstruct\", null);\n ScrollVisibleService = __decorate$1D([\n Bean('scrollVisibleService')\n ], ScrollVisibleService);\n return ScrollVisibleService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1J = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1C = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar MouseEventService = /** @class */ (function (_super) {\n __extends$1J(MouseEventService, _super);\n function MouseEventService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.gridInstanceId = MouseEventService_1.gridInstanceSequence.next();\n return _this;\n }\n MouseEventService_1 = MouseEventService;\n // we put the instance id onto the main DOM element. this is used for events, when grids are inside grids,\n // so the grid can work out if the even came from this grid or a grid inside this one. see the ctrl+v logic\n // for where this is used.\n MouseEventService.prototype.stampTopLevelGridCompWithGridInstance = function (eGridDiv) {\n eGridDiv[MouseEventService_1.GRID_DOM_KEY] = this.gridInstanceId;\n };\n MouseEventService.prototype.getRenderedCellForEvent = function (event) {\n return getCtrlForEvent(this.gridOptionsWrapper, event, CellCtrl.DOM_DATA_KEY_CELL_CTRL);\n };\n // walks the path of the event, and returns true if this grid is the first one that it finds. if doing\n // master / detail grids, and a child grid is found, then it returns false. this stops things like copy/paste\n // getting executed on many grids at the same time.\n MouseEventService.prototype.isEventFromThisGrid = function (event) {\n var res = this.isElementInThisGrid(event.target);\n return res;\n };\n MouseEventService.prototype.isElementInThisGrid = function (element) {\n var pointer = element;\n while (pointer) {\n var instanceId = pointer[MouseEventService_1.GRID_DOM_KEY];\n if (exists(instanceId)) {\n var eventFromThisGrid = instanceId === this.gridInstanceId;\n return eventFromThisGrid;\n }\n pointer = pointer.parentElement;\n }\n return false;\n };\n MouseEventService.prototype.getCellPositionForEvent = function (event) {\n var cellComp = this.getRenderedCellForEvent(event);\n return cellComp ? cellComp.getCellPosition() : null;\n };\n MouseEventService.prototype.getNormalisedPosition = function (event) {\n var gridPanelHasScrolls = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_NORMAL;\n var e = event;\n var x;\n var y;\n if (e.clientX != null || e.clientY != null) {\n x = e.clientX;\n y = e.clientY;\n }\n else {\n x = e.x;\n y = e.y;\n }\n if (gridPanelHasScrolls) {\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var vRange = gridBodyCon.getScrollFeature().getVScrollPosition();\n var hRange = gridBodyCon.getScrollFeature().getHScrollPosition();\n x += hRange.left;\n y += vRange.top;\n }\n return { x: x, y: y };\n };\n var MouseEventService_1;\n MouseEventService.gridInstanceSequence = new NumberSequence();\n MouseEventService.GRID_DOM_KEY = '__ag_grid_instance';\n __decorate$1C([\n Autowired('ctrlsService')\n ], MouseEventService.prototype, \"ctrlsService\", void 0);\n MouseEventService = MouseEventService_1 = __decorate$1C([\n Bean('mouseEventService')\n ], MouseEventService);\n return MouseEventService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1I = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$4 = (undefined && undefined.__assign) || function () {\n __assign$4 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$4.apply(this, arguments);\n};\nvar __decorate$1B = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar NavigationService = /** @class */ (function (_super) {\n __extends$1I(NavigationService, _super);\n function NavigationService() {\n var _this = _super.call(this) || this;\n _this.onPageDown = throttle(_this.onPageDown, 100);\n _this.onPageUp = throttle(_this.onPageUp, 100);\n return _this;\n }\n NavigationService.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) {\n _this.gridBodyCon = p.gridBodyCtrl;\n });\n };\n NavigationService.prototype.handlePageScrollingKey = function (event) {\n var key = event.key;\n var alt = event.altKey;\n var ctrl = event.ctrlKey || event.metaKey;\n var rangeServiceShouldHandleShift = !!this.rangeService && event.shiftKey;\n var currentCell = this.mouseEventService.getCellPositionForEvent(event);\n if (!currentCell) {\n return false;\n }\n var processed = false;\n switch (key) {\n case KeyCode.PAGE_HOME:\n case KeyCode.PAGE_END:\n // handle home and end when ctrl & alt are NOT pressed\n if (!ctrl && !alt) {\n this.onHomeOrEndKey(key);\n processed = true;\n }\n break;\n case KeyCode.LEFT:\n case KeyCode.RIGHT:\n case KeyCode.UP:\n case KeyCode.DOWN:\n // handle when ctrl is pressed only, if shift is pressed\n // it will be handled by the rangeService\n if (ctrl && !alt && !rangeServiceShouldHandleShift) {\n this.onCtrlUpDownLeftRight(key, currentCell);\n processed = true;\n }\n break;\n case KeyCode.PAGE_DOWN:\n // handle page up and page down when ctrl & alt are NOT pressed\n if (!ctrl && !alt) {\n this.onPageDown(currentCell);\n processed = true;\n }\n break;\n case KeyCode.PAGE_UP:\n // handle page up and page down when ctrl & alt are NOT pressed\n if (!ctrl && !alt) {\n this.onPageUp(currentCell);\n processed = true;\n }\n break;\n }\n if (processed) {\n event.preventDefault();\n }\n return processed;\n };\n NavigationService.prototype.navigateTo = function (navigateParams) {\n var scrollIndex = navigateParams.scrollIndex, scrollType = navigateParams.scrollType, scrollColumn = navigateParams.scrollColumn, focusIndex = navigateParams.focusIndex, focusColumn = navigateParams.focusColumn;\n if (exists(scrollColumn) && !scrollColumn.isPinned()) {\n this.gridBodyCon.getScrollFeature().ensureColumnVisible(scrollColumn);\n }\n if (exists(scrollIndex)) {\n this.gridBodyCon.getScrollFeature().ensureIndexVisible(scrollIndex, scrollType);\n }\n // setFocusedCell relies on the browser default focus behavior to scroll the focused cell into view,\n // however, this behavior will cause the cell border to be cut off, or if we have sticky rows, the\n // cell will be completely hidden, so we call ensureIndexVisible without a position to guarantee\n // minimal scroll to get the row into view.\n if (!navigateParams.isAsync) {\n this.gridBodyCon.getScrollFeature().ensureIndexVisible(focusIndex);\n }\n // if we don't do this, the range will be left on the last cell, which will leave the last focused cell\n // highlighted.\n this.focusService.setFocusedCell({ rowIndex: focusIndex, column: focusColumn, rowPinned: null, forceBrowserFocus: true });\n if (this.rangeService) {\n var cellPosition = { rowIndex: focusIndex, rowPinned: null, column: focusColumn };\n this.rangeService.setRangeToCell(cellPosition);\n }\n };\n NavigationService.prototype.onPageDown = function (gridCell) {\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var scrollPosition = gridBodyCon.getScrollFeature().getVScrollPosition();\n var pixelsInOnePage = this.getViewportHeight();\n var pagingPixelOffset = this.paginationProxy.getPixelOffset();\n var currentPageBottomPixel = scrollPosition.top + pixelsInOnePage;\n var currentPageBottomRow = this.paginationProxy.getRowIndexAtPixel(currentPageBottomPixel + pagingPixelOffset);\n if (this.columnModel.isAutoRowHeightActive()) {\n this.navigateToNextPageWithAutoHeight(gridCell, currentPageBottomRow);\n }\n else {\n this.navigateToNextPage(gridCell, currentPageBottomRow);\n }\n };\n NavigationService.prototype.onPageUp = function (gridCell) {\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var scrollPosition = gridBodyCon.getScrollFeature().getVScrollPosition();\n var pagingPixelOffset = this.paginationProxy.getPixelOffset();\n var currentPageTopPixel = scrollPosition.top;\n var currentPageTopRow = this.paginationProxy.getRowIndexAtPixel(currentPageTopPixel + pagingPixelOffset);\n if (this.columnModel.isAutoRowHeightActive()) {\n this.navigateToNextPageWithAutoHeight(gridCell, currentPageTopRow, true);\n }\n else {\n this.navigateToNextPage(gridCell, currentPageTopRow, true);\n }\n };\n NavigationService.prototype.navigateToNextPage = function (gridCell, scrollIndex, up) {\n if (up === void 0) { up = false; }\n var _a, _b;\n var pixelsInOnePage = this.getViewportHeight();\n var firstRow = this.paginationProxy.getPageFirstRow();\n var lastRow = this.paginationProxy.getPageLastRow();\n var pagingPixelOffset = this.paginationProxy.getPixelOffset();\n var currentRowNode = this.paginationProxy.getRow(gridCell.rowIndex);\n var rowPixelDiff = up\n ? (((_a = currentRowNode) === null || _a === void 0 ? void 0 : _a.rowHeight) - pixelsInOnePage - pagingPixelOffset)\n : (pixelsInOnePage - pagingPixelOffset);\n var nextCellPixel = ((_b = currentRowNode) === null || _b === void 0 ? void 0 : _b.rowTop) + rowPixelDiff;\n var focusIndex = this.paginationProxy.getRowIndexAtPixel(nextCellPixel + pagingPixelOffset);\n if (focusIndex === gridCell.rowIndex) {\n var diff = up ? -1 : 1;\n scrollIndex = focusIndex = gridCell.rowIndex + diff;\n }\n var scrollType;\n if (up) {\n scrollType = 'bottom';\n if (focusIndex < firstRow) {\n focusIndex = firstRow;\n }\n if (scrollIndex < firstRow) {\n scrollIndex = firstRow;\n }\n }\n else {\n scrollType = 'top';\n if (focusIndex > lastRow) {\n focusIndex = lastRow;\n }\n if (scrollIndex > lastRow) {\n scrollIndex = lastRow;\n }\n }\n if (this.isRowTallerThanView(focusIndex)) {\n scrollIndex = focusIndex;\n scrollType = 'top';\n }\n this.navigateTo({\n scrollIndex: scrollIndex,\n scrollType: scrollType,\n scrollColumn: null,\n focusIndex: focusIndex,\n focusColumn: gridCell.column\n });\n };\n NavigationService.prototype.navigateToNextPageWithAutoHeight = function (gridCell, scrollIndex, up) {\n var _this = this;\n if (up === void 0) { up = false; }\n // because autoHeight will calculate the height of rows after scroll\n // first we scroll towards the required point, then we add a small\n // delay to allow the height to be recalculated, check which index\n // should be focused and then finally navigate to that index.\n // TODO: we should probably have an event fired once to scrollbar has\n // settled and all rowHeights have been calculated instead of relying\n // on a setTimeout of 50ms.\n this.navigateTo({\n scrollIndex: scrollIndex,\n scrollType: up ? 'bottom' : 'top',\n scrollColumn: null,\n focusIndex: scrollIndex,\n focusColumn: gridCell.column\n });\n setTimeout(function () {\n var focusIndex = _this.getNextFocusIndexForAutoHeight(gridCell, up);\n _this.navigateTo({\n scrollIndex: scrollIndex,\n scrollType: up ? 'bottom' : 'top',\n scrollColumn: null,\n focusIndex: focusIndex,\n focusColumn: gridCell.column,\n isAsync: true\n });\n }, 50);\n };\n NavigationService.prototype.getNextFocusIndexForAutoHeight = function (gridCell, up) {\n if (up === void 0) { up = false; }\n var _a;\n var step = up ? -1 : 1;\n var pixelsInOnePage = this.getViewportHeight();\n var lastRowIndex = this.paginationProxy.getPageLastRow();\n var pixelSum = 0;\n var currentIndex = gridCell.rowIndex;\n while (currentIndex >= 0 && currentIndex <= lastRowIndex) {\n var currentCell = this.paginationProxy.getRow(currentIndex);\n if (currentCell) {\n var currentCellHeight = (_a = currentCell.rowHeight, (_a !== null && _a !== void 0 ? _a : 0));\n if (pixelSum + currentCellHeight > pixelsInOnePage) {\n break;\n }\n pixelSum += currentCellHeight;\n }\n currentIndex += step;\n }\n return Math.max(0, Math.min(currentIndex, lastRowIndex));\n };\n NavigationService.prototype.getViewportHeight = function () {\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var scrollPosition = gridBodyCon.getScrollFeature().getVScrollPosition();\n var scrollbarWidth = this.gridOptionsWrapper.getScrollbarWidth();\n var pixelsInOnePage = scrollPosition.bottom - scrollPosition.top;\n if (this.ctrlsService.getCenterRowContainerCtrl().isHorizontalScrollShowing()) {\n pixelsInOnePage -= scrollbarWidth;\n }\n return pixelsInOnePage;\n };\n NavigationService.prototype.isRowTallerThanView = function (rowIndex) {\n var rowNode = this.paginationProxy.getRow(rowIndex);\n if (!rowNode) {\n return false;\n }\n var rowHeight = rowNode.rowHeight;\n if (typeof rowHeight !== 'number') {\n return false;\n }\n return rowHeight > this.getViewportHeight();\n };\n NavigationService.prototype.onCtrlUpDownLeftRight = function (key, gridCell) {\n var cellToFocus = this.cellNavigationService.getNextCellToFocus(key, gridCell, true);\n var rowIndex = cellToFocus.rowIndex, column = cellToFocus.column;\n this.navigateTo({\n scrollIndex: rowIndex,\n scrollType: null,\n scrollColumn: column,\n focusIndex: rowIndex,\n focusColumn: column\n });\n };\n // home brings focus to top left cell, end brings focus to bottom right, grid scrolled to bring\n // same cell into view (which means either scroll all the way up, or all the way down).\n NavigationService.prototype.onHomeOrEndKey = function (key) {\n var homeKey = key === KeyCode.PAGE_HOME;\n var allColumns = this.columnModel.getAllDisplayedColumns();\n var columnToSelect = homeKey ? allColumns[0] : last(allColumns);\n var scrollIndex = homeKey ? this.paginationProxy.getPageFirstRow() : this.paginationProxy.getPageLastRow();\n this.navigateTo({\n scrollIndex: scrollIndex,\n scrollType: null,\n scrollColumn: columnToSelect,\n focusIndex: scrollIndex,\n focusColumn: columnToSelect\n });\n };\n // result of keyboard event\n NavigationService.prototype.onTabKeyDown = function (previous, keyboardEvent) {\n var backwards = keyboardEvent.shiftKey;\n var movedToNextCell = this.tabToNextCellCommon(previous, backwards, keyboardEvent);\n if (movedToNextCell) {\n // only prevent default if we found a cell. so if user is on last cell and hits tab, then we default\n // to the normal tabbing so user can exit the grid.\n keyboardEvent.preventDefault();\n return;\n }\n // if we didn't move to next cell, then need to tab out of the cells, ie to the header (if going\n // backwards)\n if (backwards) {\n var _a = previous.getRowPosition(), rowIndex = _a.rowIndex, rowPinned = _a.rowPinned;\n var firstRow = rowPinned ? rowIndex === 0 : rowIndex === this.paginationProxy.getPageFirstRow();\n if (firstRow) {\n keyboardEvent.preventDefault();\n this.focusService.focusLastHeader(keyboardEvent);\n }\n }\n else {\n // if the case it's a popup editor, the focus is on the editor and not the previous cell.\n // in order for the tab navigation to work, we need to focus the browser back onto the\n // previous cell.\n if (previous instanceof CellCtrl) {\n previous.focusCell(true);\n }\n if (this.focusService.focusNextGridCoreContainer(backwards)) {\n keyboardEvent.preventDefault();\n }\n }\n };\n // comes from API\n NavigationService.prototype.tabToNextCell = function (backwards, event) {\n var focusedCell = this.focusService.getFocusedCell();\n // if no focus, then cannot navigate\n if (!focusedCell) {\n return false;\n }\n var cellOrRow = this.getCellByPosition(focusedCell);\n // if cell is not rendered, means user has scrolled away from the cell\n // or that the focusedCell is a Full Width Row\n if (!cellOrRow) {\n cellOrRow = this.rowRenderer.getRowByPosition(focusedCell);\n if (!cellOrRow || !cellOrRow.isFullWidth()) {\n return false;\n }\n }\n return this.tabToNextCellCommon(cellOrRow, backwards, event);\n };\n NavigationService.prototype.tabToNextCellCommon = function (previous, backwards, event) {\n var editing = previous.isEditing();\n // if cell is not editing, there is still chance row is editing if it's Full Row Editing\n if (!editing && previous instanceof CellCtrl) {\n var cell = previous;\n var row = cell.getRowCtrl();\n if (row) {\n editing = row.isEditing();\n }\n }\n var res;\n if (editing) {\n // if we are editing, we know it's not a Full Width Row (RowComp)\n if (this.gridOptionsWrapper.isFullRowEdit()) {\n res = this.moveToNextEditingRow(previous, backwards, event);\n }\n else {\n res = this.moveToNextEditingCell(previous, backwards, event);\n }\n }\n else {\n res = this.moveToNextCellNotEditing(previous, backwards);\n }\n // if a cell wasn't found, it's possible that focus was moved to the header\n return res || !!this.focusService.getFocusedHeader();\n };\n NavigationService.prototype.moveToNextEditingCell = function (previousCell, backwards, event) {\n if (event === void 0) { event = null; }\n var previousPos = previousCell.getCellPosition();\n // before we stop editing, we need to focus the cell element\n // so the grid doesn't detect that focus has left the grid\n previousCell.getGui().focus();\n // need to do this before getting next cell to edit, in case the next cell\n // has editable function (eg colDef.editable=func() ) and it depends on the\n // result of this cell, so need to save updates from the first edit, in case\n // the value is referenced in the function.\n previousCell.stopEditing();\n // find the next cell to start editing\n var nextCell = this.findNextCellToFocusOn(previousPos, backwards, true);\n if (nextCell == null) {\n return false;\n }\n // only prevent default if we found a cell. so if user is on last cell and hits tab, then we default\n // to the normal tabbing so user can exit the grid.\n nextCell.startEditing(null, null, true, event);\n nextCell.focusCell(false);\n return true;\n };\n NavigationService.prototype.moveToNextEditingRow = function (previousCell, backwards, event) {\n if (event === void 0) { event = null; }\n var previousPos = previousCell.getCellPosition();\n // find the next cell to start editing\n var nextCell = this.findNextCellToFocusOn(previousPos, backwards, true);\n if (nextCell == null) {\n return false;\n }\n var nextPos = nextCell.getCellPosition();\n var previousEditable = this.isCellEditable(previousPos);\n var nextEditable = this.isCellEditable(nextPos);\n var rowsMatch = nextPos && previousPos.rowIndex === nextPos.rowIndex && previousPos.rowPinned === nextPos.rowPinned;\n if (previousEditable) {\n previousCell.setFocusOutOnEditor();\n }\n if (!rowsMatch) {\n var pRow = previousCell.getRowCtrl();\n pRow.stopEditing();\n var nRow = nextCell.getRowCtrl();\n nRow.startRowEditing(undefined, undefined, undefined, event);\n }\n if (nextEditable) {\n nextCell.setFocusInOnEditor();\n nextCell.focusCell();\n }\n else {\n nextCell.focusCell(true);\n }\n return true;\n };\n NavigationService.prototype.moveToNextCellNotEditing = function (previousCell, backwards) {\n var displayedColumns = this.columnModel.getAllDisplayedColumns();\n var cellPos;\n if (previousCell instanceof RowCtrl) {\n cellPos = __assign$4(__assign$4({}, previousCell.getRowPosition()), { column: backwards ? displayedColumns[0] : last(displayedColumns) });\n }\n else {\n cellPos = previousCell.getCellPosition();\n }\n // find the next cell to start editing\n var nextCell = this.findNextCellToFocusOn(cellPos, backwards, false);\n // only prevent default if we found a cell. so if user is on last cell and hits tab, then we default\n // to the normal tabbing so user can exit the grid.\n if (nextCell instanceof CellCtrl) {\n nextCell.focusCell(true);\n }\n else if (nextCell) {\n return this.tryToFocusFullWidthRow(nextCell.getRowPosition(), backwards);\n }\n return exists(nextCell);\n };\n // called by the cell, when tab is pressed while editing.\n // @return: RenderedCell when navigation successful, otherwise null\n NavigationService.prototype.findNextCellToFocusOn = function (previousPosition, backwards, startEditing) {\n var nextPosition = previousPosition;\n while (true) {\n if (previousPosition !== nextPosition) {\n previousPosition = nextPosition;\n }\n if (!backwards) {\n nextPosition = this.getLastCellOfColSpan(nextPosition);\n }\n nextPosition = this.cellNavigationService.getNextTabbedCell(nextPosition, backwards);\n // allow user to override what cell to go to next\n var userFunc = this.gridOptionsWrapper.getTabToNextCellFunc();\n if (exists(userFunc)) {\n var params = {\n backwards: backwards,\n editing: startEditing,\n previousCellPosition: previousPosition,\n nextCellPosition: nextPosition ? nextPosition : null\n };\n var userCell = userFunc(params);\n if (exists(userCell)) {\n if (userCell.floating) {\n doOnce(function () { console.warn(\"AG Grid: tabToNextCellFunc return type should have attributes: rowIndex, rowPinned, column. However you had 'floating', maybe you meant 'rowPinned'?\"); }, 'no floating in userCell');\n userCell.rowPinned = userCell.floating;\n }\n nextPosition = {\n rowIndex: userCell.rowIndex,\n column: userCell.column,\n rowPinned: userCell.rowPinned\n };\n }\n else {\n nextPosition = null;\n }\n }\n // if no 'next cell', means we have got to last cell of grid, so nothing to move to,\n // so bottom right cell going forwards, or top left going backwards\n if (!nextPosition) {\n return null;\n }\n if (nextPosition.rowIndex < 0) {\n var headerLen = this.headerNavigationService.getHeaderRowCount();\n this.focusService.focusHeaderPosition({\n headerPosition: {\n headerRowIndex: headerLen + (nextPosition.rowIndex),\n column: nextPosition.column\n }\n });\n return null;\n }\n // if editing, but cell not editable, skip cell. we do this before we do all of\n // the 'ensure index visible' and 'flush all frames', otherwise if we are skipping\n // a bunch of cells (eg 10 rows) then all the work on ensuring cell visible is useless\n // (except for the last one) which causes grid to stall for a while.\n // note - for full row edit, we do focus non-editable cells, as the row stays in edit mode.\n var fullRowEdit = this.gridOptionsWrapper.isFullRowEdit();\n if (startEditing && !fullRowEdit) {\n var cellIsEditable = this.isCellEditable(nextPosition);\n if (!cellIsEditable) {\n continue;\n }\n }\n this.ensureCellVisible(nextPosition);\n // we have to call this after ensureColumnVisible - otherwise it could be a virtual column\n // or row that is not currently in view, hence the renderedCell would not exist\n var nextCell = this.getCellByPosition(nextPosition);\n // if next cell is fullWidth row, then no rendered cell,\n // as fullWidth rows have no cells, so we skip it\n if (!nextCell) {\n var row = this.rowRenderer.getRowByPosition(nextPosition);\n if (!row || !row.isFullWidth()) {\n continue;\n }\n else {\n return row;\n }\n }\n if (nextCell.isSuppressNavigable()) {\n continue;\n }\n // by default, when we click a cell, it gets selected into a range, so to keep keyboard navigation\n // consistent, we set into range here also.\n if (this.rangeService) {\n this.rangeService.setRangeToCell(nextPosition);\n }\n // we successfully tabbed onto a grid cell, so return true\n return nextCell;\n }\n };\n NavigationService.prototype.isCellEditable = function (cell) {\n var rowNode = this.lookupRowNodeForCell(cell);\n if (rowNode) {\n return cell.column.isCellEditable(rowNode);\n }\n return false;\n };\n NavigationService.prototype.getCellByPosition = function (cellPosition) {\n var rowCtrl = this.rowRenderer.getRowByPosition(cellPosition);\n if (!rowCtrl) {\n return null;\n }\n return rowCtrl.getCellCtrl(cellPosition.column);\n };\n NavigationService.prototype.lookupRowNodeForCell = function (cell) {\n if (cell.rowPinned === Constants.PINNED_TOP) {\n return this.pinnedRowModel.getPinnedTopRow(cell.rowIndex);\n }\n if (cell.rowPinned === Constants.PINNED_BOTTOM) {\n return this.pinnedRowModel.getPinnedBottomRow(cell.rowIndex);\n }\n return this.paginationProxy.getRow(cell.rowIndex);\n };\n // we use index for rows, but column object for columns, as the next column (by index) might not\n // be visible (header grouping) so it's not reliable, so using the column object instead.\n NavigationService.prototype.navigateToNextCell = function (event, key, currentCell, allowUserOverride) {\n // we keep searching for a next cell until we find one. this is how the group rows get skipped\n var nextCell = currentCell;\n var hitEdgeOfGrid = false;\n while (nextCell && (nextCell === currentCell || !this.isValidNavigateCell(nextCell))) {\n // if the current cell is spanning across multiple columns, we need to move\n // our current position to be the last cell on the right before finding the\n // the next target.\n if (this.gridOptionsWrapper.isEnableRtl()) {\n if (key === KeyCode.LEFT) {\n nextCell = this.getLastCellOfColSpan(nextCell);\n }\n }\n else if (key === KeyCode.RIGHT) {\n nextCell = this.getLastCellOfColSpan(nextCell);\n }\n nextCell = this.cellNavigationService.getNextCellToFocus(key, nextCell);\n // eg if going down, and nextCell=undefined, means we are gone past the last row\n hitEdgeOfGrid = missing(nextCell);\n }\n if (hitEdgeOfGrid && event && event.key === KeyCode.UP) {\n nextCell = {\n rowIndex: -1,\n rowPinned: null,\n column: currentCell.column\n };\n }\n // allow user to override what cell to go to next. when doing normal cell navigation (with keys)\n // we allow this, however if processing 'enter after edit' we don't allow override\n if (allowUserOverride) {\n var userFunc = this.gridOptionsWrapper.getNavigateToNextCellFunc();\n if (exists(userFunc)) {\n var params = {\n key: key,\n previousCellPosition: currentCell,\n nextCellPosition: nextCell ? nextCell : null,\n event: event\n };\n var userCell = userFunc(params);\n if (exists(userCell)) {\n if (userCell.floating) {\n doOnce(function () { console.warn(\"AG Grid: tabToNextCellFunc return type should have attributes: rowIndex, rowPinned, column. However you had 'floating', maybe you meant 'rowPinned'?\"); }, 'no floating in userCell');\n userCell.rowPinned = userCell.floating;\n }\n nextCell = {\n rowPinned: userCell.rowPinned,\n rowIndex: userCell.rowIndex,\n column: userCell.column\n };\n }\n else {\n nextCell = null;\n }\n }\n }\n // no next cell means we have reached a grid boundary, eg left, right, top or bottom of grid\n if (!nextCell) {\n return;\n }\n if (nextCell.rowIndex < 0) {\n var headerLen = this.headerNavigationService.getHeaderRowCount();\n this.focusService.focusHeaderPosition({\n headerPosition: { headerRowIndex: headerLen + (nextCell.rowIndex), column: currentCell.column },\n event: event || undefined\n });\n return;\n }\n // in case we have col spanning we get the cellComp and use it to get the\n // position. This was we always focus the first cell inside the spanning.\n var normalisedPosition = this.getNormalisedPosition(nextCell);\n if (normalisedPosition) {\n this.focusPosition(normalisedPosition);\n }\n else {\n this.tryToFocusFullWidthRow(nextCell);\n }\n };\n NavigationService.prototype.getNormalisedPosition = function (cellPosition) {\n // ensureCellVisible first, to make sure cell at position is rendered.\n this.ensureCellVisible(cellPosition);\n var cellCtrl = this.getCellByPosition(cellPosition);\n // not guaranteed to have a cellComp when using the SSRM as blocks are loading.\n if (!cellCtrl) {\n return null;\n }\n cellPosition = cellCtrl.getCellPosition();\n // we call this again, as nextCell can be different to it's previous value due to Column Spanning\n // (ie if cursor moving from right to left, and cell is spanning columns, then nextCell was the\n // last column in the group, however now it's the first column in the group). if we didn't do\n // ensureCellVisible again, then we could only be showing the last portion (last column) of the\n // merged cells.\n this.ensureCellVisible(cellPosition);\n return cellPosition;\n };\n NavigationService.prototype.tryToFocusFullWidthRow = function (position, backwards) {\n if (backwards === void 0) { backwards = false; }\n var displayedColumns = this.columnModel.getAllDisplayedColumns();\n var rowComp = this.rowRenderer.getRowByPosition(position);\n if (!rowComp || !rowComp.isFullWidth()) {\n return false;\n }\n var currentCellFocused = this.focusService.getFocusedCell();\n var cellPosition = {\n rowIndex: position.rowIndex,\n rowPinned: position.rowPinned,\n column: position.column || (backwards ? last(displayedColumns) : displayedColumns[0])\n };\n this.focusPosition(cellPosition);\n var fromBelow = currentCellFocused != null ? this.rowPositionUtils.before(cellPosition, currentCellFocused) : false;\n var focusEvent = {\n type: Events.EVENT_FULL_WIDTH_ROW_FOCUSED,\n rowIndex: cellPosition.rowIndex,\n rowPinned: cellPosition.rowPinned,\n column: cellPosition.column,\n isFullWidthCell: true,\n floating: cellPosition.rowPinned,\n fromBelow: fromBelow\n };\n this.eventService.dispatchEvent(focusEvent);\n return true;\n };\n NavigationService.prototype.focusPosition = function (cellPosition) {\n this.focusService.setFocusedCell({\n rowIndex: cellPosition.rowIndex,\n column: cellPosition.column,\n rowPinned: cellPosition.rowPinned,\n forceBrowserFocus: true\n });\n if (this.rangeService) {\n this.rangeService.setRangeToCell(cellPosition);\n }\n };\n NavigationService.prototype.isValidNavigateCell = function (cell) {\n var rowNode = this.rowPositionUtils.getRowNode(cell);\n // we do not allow focusing on detail rows and full width rows\n return !!rowNode;\n };\n NavigationService.prototype.getLastCellOfColSpan = function (cell) {\n var cellCtrl = this.getCellByPosition(cell);\n if (!cellCtrl) {\n return cell;\n }\n var colSpanningList = cellCtrl.getColSpanningList();\n if (colSpanningList.length === 1) {\n return cell;\n }\n return {\n rowIndex: cell.rowIndex,\n column: last(colSpanningList),\n rowPinned: cell.rowPinned\n };\n };\n NavigationService.prototype.ensureCellVisible = function (gridCell) {\n var _a;\n var isGroupStickyEnabled = this.gridOptionsWrapper.isGroupRowsSticky();\n var rowNode = this.rowModel.getRow(gridCell.rowIndex);\n // sticky rows are always visible, so the grid shouldn't scroll to focus them.\n var skipScrollToRow = isGroupStickyEnabled && ((_a = rowNode) === null || _a === void 0 ? void 0 : _a.sticky);\n // this scrolls the row into view\n if (!skipScrollToRow && missing(gridCell.rowPinned)) {\n this.gridBodyCon.getScrollFeature().ensureIndexVisible(gridCell.rowIndex);\n }\n if (!gridCell.column.isPinned()) {\n this.gridBodyCon.getScrollFeature().ensureColumnVisible(gridCell.column);\n }\n };\n __decorate$1B([\n Autowired('mouseEventService')\n ], NavigationService.prototype, \"mouseEventService\", void 0);\n __decorate$1B([\n Autowired('paginationProxy')\n ], NavigationService.prototype, \"paginationProxy\", void 0);\n __decorate$1B([\n Autowired('focusService')\n ], NavigationService.prototype, \"focusService\", void 0);\n __decorate$1B([\n Optional('rangeService')\n ], NavigationService.prototype, \"rangeService\", void 0);\n __decorate$1B([\n Autowired('columnModel')\n ], NavigationService.prototype, \"columnModel\", void 0);\n __decorate$1B([\n Autowired('rowModel')\n ], NavigationService.prototype, \"rowModel\", void 0);\n __decorate$1B([\n Autowired('ctrlsService')\n ], NavigationService.prototype, \"ctrlsService\", void 0);\n __decorate$1B([\n Autowired('rowRenderer')\n ], NavigationService.prototype, \"rowRenderer\", void 0);\n __decorate$1B([\n Autowired('headerNavigationService')\n ], NavigationService.prototype, \"headerNavigationService\", void 0);\n __decorate$1B([\n Autowired(\"rowPositionUtils\")\n ], NavigationService.prototype, \"rowPositionUtils\", void 0);\n __decorate$1B([\n Autowired(\"cellNavigationService\")\n ], NavigationService.prototype, \"cellNavigationService\", void 0);\n __decorate$1B([\n Autowired(\"pinnedRowModel\")\n ], NavigationService.prototype, \"pinnedRowModel\", void 0);\n __decorate$1B([\n PostConstruct\n ], NavigationService.prototype, \"postConstruct\", null);\n NavigationService = __decorate$1B([\n Bean('navigationService')\n ], NavigationService);\n return NavigationService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1H = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1A = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar PopupEditorWrapper = /** @class */ (function (_super) {\n __extends$1H(PopupEditorWrapper, _super);\n function PopupEditorWrapper(params) {\n var _this = _super.call(this, /* html */ \"<div class=\\\"ag-popup-editor\\\" tabindex=\\\"-1\\\"/>\") || this;\n _this.params = params;\n return _this;\n }\n PopupEditorWrapper.prototype.postConstruct = function () {\n this.gridOptionsWrapper.setDomData(this.getGui(), PopupEditorWrapper.DOM_KEY_POPUP_EDITOR_WRAPPER, true);\n this.addKeyDownListener();\n };\n PopupEditorWrapper.prototype.addKeyDownListener = function () {\n var _this = this;\n var eGui = this.getGui();\n var params = this.params;\n var listener = function (event) {\n if (!isUserSuppressingKeyboardEvent(_this.gridOptionsWrapper, event, params.node, params.column, true)) {\n params.onKeyDown(event);\n }\n };\n this.addManagedListener(eGui, 'keydown', listener);\n };\n PopupEditorWrapper.DOM_KEY_POPUP_EDITOR_WRAPPER = 'popupEditorWrapper';\n __decorate$1A([\n PostConstruct\n ], PopupEditorWrapper.prototype, \"postConstruct\", null);\n return PopupEditorWrapper;\n}(PopupComponent));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1G = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar CellComp = /** @class */ (function (_super) {\n __extends$1G(CellComp, _super);\n function CellComp(beans, cellCtrl, printLayout, eRow, editingRow) {\n var _this = _super.call(this) || this;\n // every time we go into edit mode, or back again, this gets incremented.\n // it's the components way of dealing with the async nature of framework components,\n // so if a framework component takes a while to be created, we know if the object\n // is still relevant when creating is finished. eg we could click edit / un-edit 20\n // times before the first React edit component comes back - we should discard\n // the first 19.\n _this.rendererVersion = 0;\n _this.editorVersion = 0;\n _this.beans = beans;\n _this.column = cellCtrl.getColumn();\n _this.rowNode = cellCtrl.getRowNode();\n _this.rowCtrl = cellCtrl.getRowCtrl();\n _this.eRow = eRow;\n _this.setTemplate(/* html */ \"<div comp-id=\\\"\" + _this.getCompId() + \"\\\"/>\");\n var eGui = _this.getGui();\n _this.forceWrapper = cellCtrl.isForceWrapper();\n _this.refreshWrapper(false);\n var setAttribute = function (name, value, element) {\n var actualElement = element ? element : eGui;\n if (value != null && value != '') {\n actualElement.setAttribute(name, value);\n }\n else {\n actualElement.removeAttribute(name);\n }\n };\n var compProxy = {\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n setUserStyles: function (styles) { return addStylesToElement(eGui, styles); },\n getFocusableElement: function () { return _this.getFocusableElement(); },\n setTabIndex: function (tabIndex) { return setAttribute('tabindex', tabIndex.toString()); },\n setRole: function (role) { return setAriaRole(eGui, role); },\n setColId: function (colId) { return setAttribute('col-id', colId); },\n setTitle: function (title) { return setAttribute('title', title); },\n setIncludeSelection: function (include) { return _this.includeSelection = include; },\n setIncludeRowDrag: function (include) { return _this.includeRowDrag = include; },\n setIncludeDndSource: function (include) { return _this.includeDndSource = include; },\n setRenderDetails: function (compDetails, valueToDisplay, force) {\n return _this.setRenderDetails(compDetails, valueToDisplay, force);\n },\n setEditDetails: function (compDetails, popup, position) {\n return _this.setEditDetails(compDetails, popup, position);\n },\n getCellEditor: function () { return _this.cellEditor || null; },\n getCellRenderer: function () { return _this.cellRenderer || null; },\n getParentOfValue: function () { return _this.getParentOfValue(); }\n };\n _this.cellCtrl = cellCtrl;\n cellCtrl.setComp(compProxy, _this.getGui(), _this.eCellWrapper, printLayout, editingRow);\n return _this;\n }\n CellComp.prototype.getParentOfValue = function () {\n if (this.eCellValue) {\n // if not editing, and using wrapper, then value goes in eCellValue\n return this.eCellValue;\n }\n if (this.eCellWrapper) {\n // if editing, and using wrapper, value (cell editor) goes in eCellWrapper\n return this.eCellWrapper;\n }\n // if editing or rendering, and not using wrapper, value (or comp) is directly inside cell\n return this.getGui();\n };\n CellComp.prototype.setRenderDetails = function (compDetails, valueToDisplay, forceNewCellRendererInstance) {\n // this can happen if the users asks for the cell to refresh, but we are not showing the vale as we are editing\n var isInlineEditing = this.cellEditor && !this.cellEditorPopupWrapper;\n if (isInlineEditing) {\n return;\n }\n // this means firstRender will be true for one pass only, as it's initialised to undefined\n this.firstRender = this.firstRender == null;\n // if display template has changed, means any previous Cell Renderer is in the wrong location\n var controlWrapperChanged = this.refreshWrapper(false);\n // all of these have dependencies on the eGui, so only do them after eGui is set\n if (compDetails) {\n var neverRefresh = forceNewCellRendererInstance || controlWrapperChanged;\n var cellRendererRefreshSuccessful = neverRefresh ? false : this.refreshCellRenderer(compDetails);\n if (!cellRendererRefreshSuccessful) {\n this.destroyRenderer();\n this.createCellRendererInstance(compDetails);\n }\n }\n else {\n this.destroyRenderer();\n this.insertValueWithoutCellRenderer(valueToDisplay);\n }\n };\n CellComp.prototype.setEditDetails = function (compDetails, popup, position) {\n if (compDetails) {\n this.createCellEditorInstance(compDetails, popup, position);\n }\n else {\n this.destroyEditor();\n }\n };\n CellComp.prototype.removeControls = function () {\n this.checkboxSelectionComp = this.beans.context.destroyBean(this.checkboxSelectionComp);\n this.dndSourceComp = this.beans.context.destroyBean(this.dndSourceComp);\n this.rowDraggingComp = this.beans.context.destroyBean(this.rowDraggingComp);\n };\n // returns true if wrapper was changed\n CellComp.prototype.refreshWrapper = function (editing) {\n var providingControls = this.includeRowDrag || this.includeDndSource || this.includeSelection;\n var usingWrapper = providingControls || this.forceWrapper;\n var putWrapperIn = usingWrapper && this.eCellWrapper == null;\n if (putWrapperIn) {\n this.eCellWrapper = loadTemplate(\"<div class=\\\"ag-cell-wrapper\\\" role=\\\"presentation\\\"></div>\");\n this.getGui().appendChild(this.eCellWrapper);\n }\n var takeWrapperOut = !usingWrapper && this.eCellWrapper != null;\n if (takeWrapperOut) {\n removeFromParent(this.eCellWrapper);\n this.eCellWrapper = undefined;\n }\n this.addOrRemoveCssClass('ag-cell-value', !usingWrapper);\n var usingCellValue = !editing && usingWrapper;\n var putCellValueIn = usingCellValue && this.eCellValue == null;\n if (putCellValueIn) {\n this.eCellValue = loadTemplate(\"<span class=\\\"ag-cell-value\\\" role=\\\"presentation\\\"></span>\");\n this.eCellWrapper.appendChild(this.eCellValue);\n }\n var takeCellValueOut = !usingCellValue && this.eCellValue != null;\n if (takeCellValueOut) {\n removeFromParent(this.eCellValue);\n this.eCellValue = undefined;\n }\n var templateChanged = putWrapperIn || takeWrapperOut || putCellValueIn || takeCellValueOut;\n if (templateChanged) {\n this.removeControls();\n }\n if (!editing && providingControls) {\n this.addControls();\n }\n return templateChanged;\n };\n CellComp.prototype.addControls = function () {\n var id = this.eCellValue.id = \"cell-\" + this.getCompId();\n var describedByIds = [];\n if (this.includeRowDrag) {\n if (this.rowDraggingComp == null) {\n this.rowDraggingComp = this.cellCtrl.createRowDragComp();\n if (this.rowDraggingComp) {\n // put the checkbox in before the value\n this.eCellWrapper.insertBefore(this.rowDraggingComp.getGui(), this.eCellValue);\n }\n }\n }\n if (this.includeDndSource) {\n if (this.dndSourceComp == null) {\n this.dndSourceComp = this.cellCtrl.createDndSource();\n // put the checkbox in before the value\n this.eCellWrapper.insertBefore(this.dndSourceComp.getGui(), this.eCellValue);\n }\n }\n if (this.includeSelection) {\n if (this.checkboxSelectionComp == null) {\n this.checkboxSelectionComp = this.cellCtrl.createSelectionCheckbox();\n this.eCellWrapper.insertBefore(this.checkboxSelectionComp.getGui(), this.eCellValue);\n }\n describedByIds.push(this.checkboxSelectionComp.getCheckboxId());\n }\n describedByIds.push(id);\n setAriaDescribedBy(this.getGui(), describedByIds.join(' '));\n };\n CellComp.prototype.createCellEditorInstance = function (compDetails, popup, position) {\n var _this = this;\n var versionCopy = this.editorVersion;\n var cellEditorPromise = compDetails.newAgStackInstance();\n if (!cellEditorPromise) {\n return;\n } // if empty, userComponentFactory already did a console message\n var params = compDetails.params;\n cellEditorPromise.then(function (c) { return _this.afterCellEditorCreated(versionCopy, c, params, popup, position); });\n // if we don't do this, and editor component is async, then there will be a period\n // when the component isn't present and keyboard navigation won't work - so example\n // of user hitting tab quickly (more quickly than renderers getting created) won't work\n var cellEditorAsync = missing(this.cellEditor);\n if (cellEditorAsync && params.cellStartedEdit) {\n this.cellCtrl.focusCell(true);\n }\n };\n CellComp.prototype.insertValueWithoutCellRenderer = function (valueToDisplay) {\n var eParent = this.getParentOfValue();\n clearElement(eParent);\n var escapedValue = valueToDisplay != null ? escapeString(valueToDisplay) : null;\n if (escapedValue != null) {\n eParent.innerHTML = escapedValue;\n }\n };\n CellComp.prototype.destroyEditorAndRenderer = function () {\n this.destroyRenderer();\n this.destroyEditor();\n };\n CellComp.prototype.destroyRenderer = function () {\n var context = this.beans.context;\n this.cellRenderer = context.destroyBean(this.cellRenderer);\n removeFromParent(this.cellRendererGui);\n this.cellRendererGui = null;\n this.rendererVersion++;\n };\n CellComp.prototype.destroyEditor = function () {\n var context = this.beans.context;\n if (this.hideEditorPopup) {\n this.hideEditorPopup();\n }\n this.hideEditorPopup = undefined;\n this.cellEditor = context.destroyBean(this.cellEditor);\n this.cellEditorPopupWrapper = context.destroyBean(this.cellEditorPopupWrapper);\n removeFromParent(this.cellEditorGui);\n this.cellEditorGui = null;\n this.editorVersion++;\n };\n CellComp.prototype.refreshCellRenderer = function (compClassAndParams) {\n if (this.cellRenderer == null || this.cellRenderer.refresh == null) {\n return false;\n }\n // if different Cell Renderer configured this time (eg user is using selector, and\n // returns different component) then don't refresh, force recreate of Cell Renderer\n if (this.cellRendererClass !== compClassAndParams.componentClass) {\n return false;\n }\n // take any custom params off of the user\n var result = this.cellRenderer.refresh(compClassAndParams.params);\n // NOTE on undefined: previous version of the cellRenderer.refresh() interface\n // returned nothing, if the method existed, we assumed it refreshed. so for\n // backwards compatibility, we assume if method exists and returns nothing,\n // that it was successful.\n return result === true || result === undefined;\n };\n CellComp.prototype.createCellRendererInstance = function (compDetails) {\n var _this = this;\n // never use task service if angularCompileRows=true, as that assume the cell renderers\n // are finished when the row is created. also we never use it if animation frame service\n // is turned off.\n // and lastly we never use it if doing auto-height, as the auto-height service checks the\n // row height directly after the cell is created, it doesn't wait around for the tasks to complete\n var angularCompileRows = this.beans.gridOptionsWrapper.isAngularCompileRows();\n var suppressAnimationFrame = this.beans.gridOptionsWrapper.isSuppressAnimationFrame();\n var useTaskService = !angularCompileRows && !suppressAnimationFrame;\n var displayComponentVersionCopy = this.rendererVersion;\n var componentClass = compDetails.componentClass;\n var createCellRendererFunc = function () {\n var staleTask = _this.rendererVersion !== displayComponentVersionCopy || !_this.isAlive();\n if (staleTask) {\n return;\n }\n // this can return null in the event that the user has switched from a renderer component to nothing, for example\n // when using a cellRendererSelect to return a component or null depending on row data etc\n var componentPromise = compDetails.newAgStackInstance();\n var callback = _this.afterCellRendererCreated.bind(_this, displayComponentVersionCopy, componentClass);\n if (componentPromise) {\n componentPromise.then(callback);\n }\n };\n // we only use task service when rendering for first time, which means it is not used when doing edits.\n // if we changed this (always use task service) would make sense, however it would break tests, possibly\n // test of users.\n if (useTaskService && this.firstRender) {\n this.beans.animationFrameService.createTask(createCellRendererFunc, this.rowNode.rowIndex, 'createTasksP2');\n }\n else {\n createCellRendererFunc();\n }\n };\n CellComp.prototype.getCtrl = function () {\n return this.cellCtrl;\n };\n CellComp.prototype.getRowCtrl = function () {\n return this.rowCtrl;\n };\n CellComp.prototype.getCellRenderer = function () {\n return this.cellRenderer;\n };\n CellComp.prototype.getCellEditor = function () {\n return this.cellEditor;\n };\n CellComp.prototype.afterCellRendererCreated = function (cellRendererVersion, cellRendererClass, cellRenderer) {\n var staleTask = !this.isAlive() || cellRendererVersion !== this.rendererVersion;\n if (staleTask) {\n this.beans.context.destroyBean(cellRenderer);\n return;\n }\n this.cellRenderer = cellRenderer;\n this.cellRendererClass = cellRendererClass;\n this.cellRendererGui = this.cellRenderer.getGui();\n if (this.cellRendererGui != null) {\n var eParent = this.getParentOfValue();\n clearElement(eParent);\n eParent.appendChild(this.cellRendererGui);\n }\n };\n CellComp.prototype.afterCellEditorCreated = function (requestVersion, cellEditor, params, popup, position) {\n // if editingCell=false, means user cancelled the editor before component was ready.\n // if versionMismatch, then user cancelled the edit, then started the edit again, and this\n // is the first editor which is now stale.\n var staleComp = requestVersion !== this.editorVersion;\n if (staleComp) {\n this.beans.context.destroyBean(cellEditor);\n return;\n }\n var editingCancelledByUserComp = cellEditor.isCancelBeforeStart && cellEditor.isCancelBeforeStart();\n if (editingCancelledByUserComp) {\n this.beans.context.destroyBean(cellEditor);\n this.cellCtrl.stopEditing();\n return;\n }\n if (!cellEditor.getGui) {\n console.warn(\"AG Grid: cellEditor for column \" + this.column.getId() + \" is missing getGui() method\");\n this.beans.context.destroyBean(cellEditor);\n return;\n }\n this.cellEditor = cellEditor;\n this.cellEditorGui = cellEditor.getGui();\n var cellEditorInPopup = popup || (cellEditor.isPopup !== undefined && cellEditor.isPopup());\n if (cellEditorInPopup) {\n if (!popup) {\n this.cellCtrl.hackSayEditingInPopup();\n }\n this.addPopupCellEditor(params, position);\n }\n else {\n this.addInCellEditor();\n }\n if (cellEditor.afterGuiAttached) {\n cellEditor.afterGuiAttached();\n }\n };\n CellComp.prototype.addInCellEditor = function () {\n var eGui = this.getGui();\n // if focus is inside the cell, we move focus to the cell itself\n // before removing it's contents, otherwise errors could be thrown.\n var eDocument = this.beans.gridOptionsWrapper.getDocument();\n if (eGui.contains(eDocument.activeElement)) {\n eGui.focus();\n }\n this.destroyRenderer();\n this.refreshWrapper(true);\n this.clearParentOfValue();\n if (this.cellEditorGui) {\n var eParent = this.getParentOfValue();\n eParent.appendChild(this.cellEditorGui);\n }\n };\n CellComp.prototype.addPopupCellEditor = function (params, position) {\n var _this = this;\n if (this.beans.gridOptionsWrapper.isFullRowEdit()) {\n console.warn('AG Grid: popup cellEditor does not work with fullRowEdit - you cannot use them both ' +\n '- either turn off fullRowEdit, or stop using popup editors.');\n }\n var cellEditor = this.cellEditor;\n // if a popup, then we wrap in a popup editor and return the popup\n this.cellEditorPopupWrapper = this.beans.context.createBean(new PopupEditorWrapper(params));\n var ePopupGui = this.cellEditorPopupWrapper.getGui();\n if (this.cellEditorGui) {\n ePopupGui.appendChild(this.cellEditorGui);\n }\n var popupService = this.beans.popupService;\n var useModelPopup = this.beans.gridOptionsWrapper.isStopEditingWhenCellsLoseFocus();\n // see if position provided by colDef, if not then check old way of method on cellComp\n var positionToUse = position != null ? position : cellEditor.getPopupPosition ? cellEditor.getPopupPosition() : 'over';\n var positionParams = {\n column: this.column,\n rowNode: this.rowNode,\n type: 'popupCellEditor',\n eventSource: this.getGui(),\n ePopup: ePopupGui,\n keepWithinBounds: true\n };\n var positionCallback = positionToUse === 'under' ?\n popupService.positionPopupUnderComponent.bind(popupService, positionParams)\n : popupService.positionPopupOverComponent.bind(popupService, positionParams);\n var translate = this.beans.gridOptionsWrapper.getLocaleTextFunc();\n var addPopupRes = popupService.addPopup({\n modal: useModelPopup,\n eChild: ePopupGui,\n closeOnEsc: true,\n closedCallback: function () { _this.cellCtrl.onPopupEditorClosed(); },\n anchorToElement: this.getGui(),\n positionCallback: positionCallback,\n ariaLabel: translate('ariaLabelCellEditor', 'Cell Editor')\n });\n if (addPopupRes) {\n this.hideEditorPopup = addPopupRes.hideFunc;\n }\n };\n CellComp.prototype.detach = function () {\n this.eRow.removeChild(this.getGui());\n };\n // if the row is also getting destroyed, then we don't need to remove from dom,\n // as the row will also get removed, so no need to take out the cells from the row\n // if the row is going (removing is an expensive operation, so only need to remove\n // the top part)\n //\n // note - this is NOT called by context, as we don't wire / unwire the CellComp for performance reasons.\n CellComp.prototype.destroy = function () {\n this.cellCtrl.stopEditing();\n this.destroyEditorAndRenderer();\n this.removeControls();\n _super.prototype.destroy.call(this);\n };\n CellComp.prototype.clearParentOfValue = function () {\n var eGui = this.getGui();\n // if focus is inside the cell, we move focus to the cell itself\n // before removing it's contents, otherwise errors could be thrown.\n var eDocument = this.beans.gridOptionsWrapper.getDocument();\n if (eGui.contains(eDocument.activeElement) && browserSupportsPreventScroll()) {\n eGui.focus({ preventScroll: true });\n }\n clearElement(this.getParentOfValue());\n };\n return CellComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1F = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar RowComp = /** @class */ (function (_super) {\n __extends$1F(RowComp, _super);\n function RowComp(ctrl, beans, containerType) {\n var _this = _super.call(this) || this;\n _this.cellComps = {};\n _this.beans = beans;\n _this.rowCtrl = ctrl;\n _this.setTemplate(/* html */ \"<div comp-id=\\\"\" + _this.getCompId() + \"\\\" style=\\\"\" + _this.getInitialStyle() + \"\\\"/>\");\n var eGui = _this.getGui();\n var style = eGui.style;\n var compProxy = {\n setDomOrder: function (domOrder) { return _this.domOrder = domOrder; },\n setCellCtrls: function (cellCtrls) { return _this.setCellCtrls(cellCtrls); },\n showFullWidth: function (compDetails) { return _this.showFullWidth(compDetails); },\n getFullWidthCellRenderer: function () { return _this.getFullWidthCellRenderer(); },\n addOrRemoveCssClass: function (name, on) { return _this.addOrRemoveCssClass(name, on); },\n setUserStyles: function (styles) { return addStylesToElement(eGui, styles); },\n setTop: function (top) { return style.top = top; },\n setTransform: function (transform) { return style.transform = transform; },\n setRowIndex: function (rowIndex) { return eGui.setAttribute('row-index', rowIndex); },\n setRole: function (role) { return setAriaRole(eGui, role); },\n setRowId: function (rowId) { return eGui.setAttribute('row-id', rowId); },\n setRowBusinessKey: function (businessKey) { return eGui.setAttribute('row-business-key', businessKey); },\n setTabIndex: function (tabIndex) { return eGui.setAttribute('tabindex', tabIndex.toString()); }\n };\n ctrl.setComp(compProxy, _this.getGui(), containerType);\n return _this;\n }\n RowComp.prototype.getInitialStyle = function () {\n var transform = this.rowCtrl.getInitialTransform();\n var top = this.rowCtrl.getInitialRowTop();\n return transform ? \"transform: \" + transform : \"top: \" + top;\n };\n RowComp.prototype.showFullWidth = function (compDetails) {\n var _this = this;\n var callback = function (cellRenderer) {\n if (_this.isAlive()) {\n var eGui = cellRenderer.getGui();\n _this.getGui().appendChild(eGui);\n _this.rowCtrl.setupDetailRowAutoHeight(eGui);\n _this.setFullWidthRowComp(cellRenderer);\n }\n else {\n _this.beans.context.destroyBean(cellRenderer);\n }\n };\n // if not in cache, create new one\n var res = compDetails.newAgStackInstance();\n if (!res) {\n return;\n }\n res.then(callback);\n };\n RowComp.prototype.setCellCtrls = function (cellCtrls) {\n var _this = this;\n var cellsToRemove = Object.assign({}, this.cellComps);\n cellCtrls.forEach(function (cellCtrl) {\n var key = cellCtrl.getInstanceId();\n var existingCellComp = _this.cellComps[key];\n if (existingCellComp == null) {\n _this.newCellComp(cellCtrl);\n }\n else {\n cellsToRemove[key] = null;\n }\n });\n var cellCompsToRemove = getAllValuesInObject(cellsToRemove)\n .filter(function (cellComp) { return cellComp != null; });\n this.destroyCells(cellCompsToRemove);\n this.ensureDomOrder(cellCtrls);\n };\n RowComp.prototype.ensureDomOrder = function (cellCtrls) {\n var _this = this;\n if (!this.domOrder) {\n return;\n }\n var elementsInOrder = [];\n cellCtrls.forEach(function (cellCtrl) {\n var cellComp = _this.cellComps[cellCtrl.getInstanceId()];\n if (cellComp) {\n elementsInOrder.push(cellComp.getGui());\n }\n });\n setDomChildOrder(this.getGui(), elementsInOrder);\n };\n RowComp.prototype.newCellComp = function (cellCtrl) {\n var cellComp = new CellComp(this.beans, cellCtrl, this.rowCtrl.isPrintLayout(), this.getGui(), this.rowCtrl.isEditing());\n this.cellComps[cellCtrl.getInstanceId()] = cellComp;\n this.getGui().appendChild(cellComp.getGui());\n };\n RowComp.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n this.destroyAllCells();\n };\n RowComp.prototype.destroyAllCells = function () {\n var cellsToDestroy = getAllValuesInObject(this.cellComps).filter(function (cp) { return cp != null; });\n this.destroyCells(cellsToDestroy);\n };\n RowComp.prototype.setFullWidthRowComp = function (fullWidthRowComponent) {\n var _this = this;\n if (this.fullWidthCellRenderer) {\n console.error('AG Grid - should not be setting fullWidthRowComponent twice');\n }\n this.fullWidthCellRenderer = fullWidthRowComponent;\n this.addDestroyFunc(function () {\n _this.fullWidthCellRenderer = _this.beans.context.destroyBean(_this.fullWidthCellRenderer);\n });\n };\n RowComp.prototype.getFullWidthCellRenderer = function () {\n return this.fullWidthCellRenderer;\n };\n RowComp.prototype.destroyCells = function (cellComps) {\n var _this = this;\n cellComps.forEach(function (cellComp) {\n // could be old reference, ie removed cell\n if (!cellComp) {\n return;\n }\n // check cellComp belongs in this container\n var instanceId = cellComp.getCtrl().getInstanceId();\n if (_this.cellComps[instanceId] !== cellComp) {\n return;\n }\n cellComp.detach();\n cellComp.destroy();\n _this.cellComps[instanceId] = null;\n });\n };\n return RowComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1E = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$3 = (undefined && undefined.__assign) || function () {\n __assign$3 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$3.apply(this, arguments);\n};\nvar __decorate$1z = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nfunction templateFactory() {\n var name = Component.elementGettingCreated.getAttribute('name');\n var cssClasses = RowContainerCtrl.getRowContainerCssClasses(name);\n var res;\n var template1 = name === RowContainerName.CENTER;\n var template2 = name === RowContainerName.TOP_CENTER\n || name === RowContainerName.STICKY_TOP_CENTER\n || name === RowContainerName.BOTTOM_CENTER;\n if (template1) {\n res = /* html */\n \"<div class=\\\"\" + cssClasses.wrapper + \"\\\" ref=\\\"eWrapper\\\" role=\\\"presentation\\\">\\n <div class=\\\"\" + cssClasses.viewport + \"\\\" ref=\\\"eViewport\\\" role=\\\"presentation\\\">\\n <div class=\\\"\" + cssClasses.container + \"\\\" ref=\\\"eContainer\\\"></div>\\n </div>\\n </div>\";\n }\n else if (template2) {\n res = /* html */\n \"<div class=\\\"\" + cssClasses.viewport + \"\\\" ref=\\\"eViewport\\\" role=\\\"presentation\\\">\\n <div class=\\\"\" + cssClasses.container + \"\\\" ref=\\\"eContainer\\\"></div>\\n </div>\";\n }\n else {\n res = /* html */\n \"<div class=\\\"\" + cssClasses.container + \"\\\" ref=\\\"eContainer\\\"></div>\";\n }\n return res;\n}\nvar RowContainerComp = /** @class */ (function (_super) {\n __extends$1E(RowContainerComp, _super);\n function RowContainerComp() {\n var _this = _super.call(this, templateFactory()) || this;\n _this.rowComps = {};\n _this.name = Component.elementGettingCreated.getAttribute('name');\n _this.type = getRowContainerTypeForName(_this.name);\n return _this;\n }\n RowContainerComp.prototype.postConstruct = function () {\n var _this = this;\n var compProxy = {\n setViewportHeight: function (height) { return _this.eViewport.style.height = height; },\n setRowCtrls: function (rowCtrls) { return _this.setRowCtrls(rowCtrls); },\n setDomOrder: function (domOrder) {\n _this.domOrder = domOrder;\n },\n setContainerWidth: function (width) { return _this.eContainer.style.width = width; }\n };\n var ctrl = this.createManagedBean(new RowContainerCtrl(this.name));\n ctrl.setComp(compProxy, this.eContainer, this.eViewport, this.eWrapper);\n };\n RowContainerComp.prototype.preDestroy = function () {\n // destroys all row comps\n this.setRowCtrls([]);\n };\n RowContainerComp.prototype.setRowCtrls = function (rowCtrls) {\n var _this = this;\n var oldRows = __assign$3({}, this.rowComps);\n this.rowComps = {};\n this.lastPlacedElement = null;\n var processRow = function (rowCon) {\n var instanceId = rowCon.getInstanceId();\n var existingRowComp = oldRows[instanceId];\n if (existingRowComp) {\n _this.rowComps[instanceId] = existingRowComp;\n delete oldRows[instanceId];\n _this.ensureDomOrder(existingRowComp.getGui());\n }\n else {\n var rowComp = _this.newRowComp(rowCon);\n _this.rowComps[instanceId] = rowComp;\n _this.appendRow(rowComp.getGui());\n }\n };\n rowCtrls.forEach(processRow);\n getAllValuesInObject(oldRows).forEach(function (oldRowComp) {\n _this.eContainer.removeChild(oldRowComp.getGui());\n oldRowComp.destroy();\n });\n setAriaRole(this.eContainer, rowCtrls.length ? \"rowgroup\" : \"presentation\");\n };\n RowContainerComp.prototype.appendRow = function (element) {\n if (this.domOrder) {\n insertWithDomOrder(this.eContainer, element, this.lastPlacedElement);\n }\n else {\n this.eContainer.appendChild(element);\n }\n this.lastPlacedElement = element;\n };\n RowContainerComp.prototype.ensureDomOrder = function (eRow) {\n if (this.domOrder) {\n ensureDomOrder(this.eContainer, eRow, this.lastPlacedElement);\n this.lastPlacedElement = eRow;\n }\n };\n RowContainerComp.prototype.newRowComp = function (rowCtrl) {\n RowContainerCtrl.getPinned(this.name);\n var res = new RowComp(rowCtrl, this.beans, this.type);\n return res;\n };\n __decorate$1z([\n Autowired('beans')\n ], RowContainerComp.prototype, \"beans\", void 0);\n __decorate$1z([\n RefSelector('eViewport')\n ], RowContainerComp.prototype, \"eViewport\", void 0);\n __decorate$1z([\n RefSelector('eContainer')\n ], RowContainerComp.prototype, \"eContainer\", void 0);\n __decorate$1z([\n RefSelector('eWrapper')\n ], RowContainerComp.prototype, \"eWrapper\", void 0);\n __decorate$1z([\n PostConstruct\n ], RowContainerComp.prototype, \"postConstruct\", null);\n __decorate$1z([\n PreDestroy\n ], RowContainerComp.prototype, \"preDestroy\", null);\n return RowContainerComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$1y = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar BodyDropPivotTarget = /** @class */ (function () {\n function BodyDropPivotTarget(pinned) {\n this.columnsToAggregate = [];\n this.columnsToGroup = [];\n this.columnsToPivot = [];\n this.pinned = pinned;\n }\n /** Callback for when drag enters */\n BodyDropPivotTarget.prototype.onDragEnter = function (draggingEvent) {\n var _this = this;\n this.clearColumnsList();\n // in pivot mode, we don't accept any drops if functions are read only\n if (this.gridOptionsWrapper.isFunctionsReadOnly()) {\n return;\n }\n var dragColumns = draggingEvent.dragItem.columns;\n if (!dragColumns) {\n return;\n }\n dragColumns.forEach(function (column) {\n // we don't allow adding secondary columns\n if (!column.isPrimary()) {\n return;\n }\n if (column.isAnyFunctionActive()) {\n return;\n }\n if (column.isAllowValue()) {\n _this.columnsToAggregate.push(column);\n }\n else if (column.isAllowRowGroup()) {\n _this.columnsToGroup.push(column);\n }\n else if (column.isAllowPivot()) {\n _this.columnsToPivot.push(column);\n }\n });\n };\n BodyDropPivotTarget.prototype.getIconName = function () {\n var totalColumns = this.columnsToAggregate.length + this.columnsToGroup.length + this.columnsToPivot.length;\n if (totalColumns > 0) {\n return this.pinned ? DragAndDropService.ICON_PINNED : DragAndDropService.ICON_MOVE;\n }\n return null;\n };\n /** Callback for when drag leaves */\n BodyDropPivotTarget.prototype.onDragLeave = function (draggingEvent) {\n // if we are taking columns out of the center, then we remove them from the report\n this.clearColumnsList();\n };\n BodyDropPivotTarget.prototype.clearColumnsList = function () {\n this.columnsToAggregate.length = 0;\n this.columnsToGroup.length = 0;\n this.columnsToPivot.length = 0;\n };\n /** Callback for when dragging */\n BodyDropPivotTarget.prototype.onDragging = function (draggingEvent) {\n };\n /** Callback for when drag stops */\n BodyDropPivotTarget.prototype.onDragStop = function (draggingEvent) {\n if (this.columnsToAggregate.length > 0) {\n this.columnModel.addValueColumns(this.columnsToAggregate, \"toolPanelDragAndDrop\");\n }\n if (this.columnsToGroup.length > 0) {\n this.columnModel.addRowGroupColumns(this.columnsToGroup, \"toolPanelDragAndDrop\");\n }\n if (this.columnsToPivot.length > 0) {\n this.columnModel.addPivotColumns(this.columnsToPivot, \"toolPanelDragAndDrop\");\n }\n };\n __decorate$1y([\n Autowired('columnModel')\n ], BodyDropPivotTarget.prototype, \"columnModel\", void 0);\n __decorate$1y([\n Autowired('gridOptionsWrapper')\n ], BodyDropPivotTarget.prototype, \"gridOptionsWrapper\", void 0);\n return BodyDropPivotTarget;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$1x = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$e = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar MoveColumnFeature = /** @class */ (function () {\n function MoveColumnFeature(pinned, eContainer) {\n this.needToMoveLeft = false;\n this.needToMoveRight = false;\n this.pinned = pinned;\n this.eContainer = eContainer;\n this.centerContainer = !exists(pinned);\n }\n MoveColumnFeature.prototype.init = function () {\n var _this = this;\n this.ctrlsService.whenReady(function () {\n _this.gridBodyCon = _this.ctrlsService.getGridBodyCtrl();\n });\n };\n MoveColumnFeature.prototype.getIconName = function () {\n return this.pinned ? DragAndDropService.ICON_PINNED : DragAndDropService.ICON_MOVE;\n };\n MoveColumnFeature.prototype.onDragEnter = function (draggingEvent) {\n // we do dummy drag, so make sure column appears in the right location when first placed\n var columns = draggingEvent.dragItem.columns;\n var dragCameFromToolPanel = draggingEvent.dragSource.type === DragSourceType.ToolPanel;\n if (dragCameFromToolPanel) {\n // the if statement doesn't work if drag leaves grid, then enters again\n this.setColumnsVisible(columns, true, \"uiColumnDragged\");\n }\n else {\n // restore previous state of visible columns upon re-entering. this means if the user drags\n // a group out, and then drags the group back in, only columns that were originally visible\n // will be visible again. otherwise a group with three columns (but only two visible) could\n // be dragged out, then when it's dragged in again, all three are visible. this stops that.\n var visibleState_1 = draggingEvent.dragItem.visibleState;\n var visibleColumns = (columns || []).filter(function (column) { return visibleState_1[column.getId()]; });\n this.setColumnsVisible(visibleColumns, true, \"uiColumnDragged\");\n }\n this.setColumnsPinned(columns, this.pinned, \"uiColumnDragged\");\n this.onDragging(draggingEvent, true, true);\n };\n MoveColumnFeature.prototype.onDragLeave = function (draggingEvent) {\n this.ensureIntervalCleared();\n };\n MoveColumnFeature.prototype.setColumnsVisible = function (columns, visible, source) {\n if (source === void 0) { source = \"api\"; }\n if (columns) {\n var allowedCols = columns.filter(function (c) { return !c.getColDef().lockVisible; });\n this.columnModel.setColumnsVisible(allowedCols, visible, source);\n }\n };\n MoveColumnFeature.prototype.setColumnsPinned = function (columns, pinned, source) {\n if (source === void 0) { source = \"api\"; }\n if (columns) {\n var allowedCols = columns.filter(function (c) { return !c.getColDef().lockPinned; });\n this.columnModel.setColumnsPinned(allowedCols, pinned, source);\n }\n };\n MoveColumnFeature.prototype.onDragStop = function () {\n this.ensureIntervalCleared();\n };\n MoveColumnFeature.prototype.normaliseX = function (x) {\n // flip the coordinate if doing RTL\n if (this.gridOptionsWrapper.isEnableRtl()) {\n var clientWidth = this.eContainer.clientWidth;\n x = clientWidth - x;\n }\n // adjust for scroll only if centre container (the pinned containers don't scroll)\n if (this.centerContainer) {\n x += this.ctrlsService.getCenterRowContainerCtrl().getCenterViewportScrollLeft();\n }\n return x;\n };\n MoveColumnFeature.prototype.checkCenterForScrolling = function (xAdjustedForScroll) {\n if (this.centerContainer) {\n // scroll if the mouse has gone outside the grid (or just outside the scrollable part if pinning)\n // putting in 50 buffer, so even if user gets to edge of grid, a scroll will happen\n var firstVisiblePixel = this.ctrlsService.getCenterRowContainerCtrl().getCenterViewportScrollLeft();\n var lastVisiblePixel = firstVisiblePixel + this.ctrlsService.getCenterRowContainerCtrl().getCenterWidth();\n if (this.gridOptionsWrapper.isEnableRtl()) {\n this.needToMoveRight = xAdjustedForScroll < (firstVisiblePixel + 50);\n this.needToMoveLeft = xAdjustedForScroll > (lastVisiblePixel - 50);\n }\n else {\n this.needToMoveLeft = xAdjustedForScroll < (firstVisiblePixel + 50);\n this.needToMoveRight = xAdjustedForScroll > (lastVisiblePixel - 50);\n }\n if (this.needToMoveLeft || this.needToMoveRight) {\n this.ensureIntervalStarted();\n }\n else {\n this.ensureIntervalCleared();\n }\n }\n };\n MoveColumnFeature.prototype.onDragging = function (draggingEvent, fromEnter, fakeEvent) {\n var _this = this;\n if (fromEnter === void 0) { fromEnter = false; }\n if (fakeEvent === void 0) { fakeEvent = false; }\n this.lastDraggingEvent = draggingEvent;\n // if moving up or down (ie not left or right) then do nothing\n if (missing(draggingEvent.hDirection)) {\n return;\n }\n var mouseXNormalised = this.normaliseX(draggingEvent.x);\n // if the user is dragging into the panel, ie coming from the side panel into the main grid,\n // we don't want to scroll the grid this time, it would appear like the table is jumping\n // each time a column is dragged in.\n if (!fromEnter) {\n this.checkCenterForScrolling(mouseXNormalised);\n }\n var hDirectionNormalised = this.normaliseDirection(draggingEvent.hDirection);\n var dragSourceType = draggingEvent.dragSource.type;\n var columnsToMove = draggingEvent.dragSource.getDragItem().columns;\n columnsToMove = columnsToMove.filter(function (col) {\n if (col.getColDef().lockPinned) {\n // if locked return true only if both col and container are same pin type.\n // double equals (==) here on purpose so that null==undefined is true (for not pinned options)\n return col.getPinned() == _this.pinned;\n }\n // if not pin locked, then always allowed to be in this container\n return true;\n });\n this.attemptMoveColumns(dragSourceType, columnsToMove, hDirectionNormalised, mouseXNormalised, fromEnter, fakeEvent);\n };\n MoveColumnFeature.prototype.normaliseDirection = function (hDirection) {\n if (this.gridOptionsWrapper.isEnableRtl()) {\n switch (hDirection) {\n case HorizontalDirection.Left: return HorizontalDirection.Right;\n case HorizontalDirection.Right: return HorizontalDirection.Left;\n default: console.error(\"AG Grid: Unknown direction \" + hDirection);\n }\n }\n else {\n return hDirection;\n }\n };\n // returns the index of the first column in the list ONLY if the cols are all beside\n // each other. if the cols are not beside each other, then returns null\n MoveColumnFeature.prototype.calculateOldIndex = function (movingCols) {\n var gridCols = this.columnModel.getAllGridColumns();\n var indexes = sortNumerically(movingCols.map(function (col) { return gridCols.indexOf(col); }));\n var firstIndex = indexes[0];\n var lastIndex = last(indexes);\n var spread = lastIndex - firstIndex;\n var gapsExist = spread !== indexes.length - 1;\n return gapsExist ? null : firstIndex;\n };\n MoveColumnFeature.prototype.attemptMoveColumns = function (dragSourceType, allMovingColumns, hDirection, mouseX, fromEnter, fakeEvent) {\n var draggingLeft = hDirection === HorizontalDirection.Left;\n var draggingRight = hDirection === HorizontalDirection.Right;\n if (dragSourceType === DragSourceType.HeaderCell) {\n // If the columns we're dragging are the only visible columns of their group, move the hidden ones too\n var newCols_1 = [];\n allMovingColumns.forEach(function (col) {\n var movingGroup = null;\n var parent = col.getParent();\n while (parent != null && parent.getDisplayedLeafColumns().length === 1) {\n movingGroup = parent;\n parent = parent.getParent();\n }\n if (movingGroup != null) {\n movingGroup.getLeafColumns().forEach(function (newCol) {\n if (!newCols_1.includes(newCol)) {\n newCols_1.push(newCol);\n }\n });\n }\n else if (!newCols_1.includes(col)) {\n newCols_1.push(col);\n }\n });\n allMovingColumns = newCols_1;\n }\n // it is important to sort the moving columns as they are in grid columns, as the list of moving columns\n // could themselves be part of 'married children' groups, which means we need to maintain the order within\n // the moving list.\n var allMovingColumnsOrdered = allMovingColumns.slice();\n this.columnModel.sortColumnsLikeGridColumns(allMovingColumnsOrdered);\n var validMoves = this.calculateValidMoves(allMovingColumnsOrdered, draggingRight, mouseX);\n // if cols are not adjacent, then this returns null. when moving, we constrain the direction of the move\n // (ie left or right) to the mouse direction. however\n var oldIndex = this.calculateOldIndex(allMovingColumnsOrdered);\n if (validMoves.length === 0) {\n return;\n }\n var firstValidMove = validMoves[0];\n // the two check below stop an error when the user grabs a group my a middle column, then\n // it is possible the mouse pointer is to the right of a column while been dragged left.\n // so we need to make sure that the mouse pointer is actually left of the left most column\n // if moving left, and right of the right most column if moving right\n // we check 'fromEnter' below so we move the column to the new spot if the mouse is coming from\n // outside the grid, eg if the column is moving from side panel, mouse is moving left, then we should\n // place the column to the RHS even if the mouse is moving left and the column is already on\n // the LHS. otherwise we stick to the rule described above.\n var constrainDirection = oldIndex !== null && !fromEnter;\n // don't consider 'fromEnter' when dragging header cells, otherwise group can jump to opposite direction of drag\n if (dragSourceType == DragSourceType.HeaderCell) {\n constrainDirection = oldIndex !== null;\n }\n // if the event was faked by a change in column pin state, then the original location of the column\n // is not reliable for dictating where the column may now be placed.\n if (constrainDirection && !fakeEvent) {\n // only allow left drag if this column is moving left\n if (draggingLeft && firstValidMove >= oldIndex) {\n return;\n }\n // only allow right drag if this column is moving right\n if (draggingRight && firstValidMove <= oldIndex) {\n return;\n }\n }\n // From when we find a move that passes all the rules\n // Remember what that move would look like in terms of displayed cols\n // keep going with further moves until we find a different result in displayed output\n // In this way potentialMoves contains all potential moves over 'hidden' columns\n var displayedCols = this.columnModel.getAllDisplayedColumns();\n var potentialMoves = [];\n var targetOrder = null;\n for (var i = 0; i < validMoves.length; i++) {\n var move = validMoves[i];\n var order = this.columnModel.getProposedColumnOrder(allMovingColumnsOrdered, move);\n if (!this.columnModel.doesOrderPassRules(order)) {\n continue;\n }\n var displayedOrder = order.filter(function (col) { return displayedCols.includes(col); });\n if (targetOrder === null) {\n targetOrder = displayedOrder;\n }\n else if (!_.areEqual(displayedOrder, targetOrder)) {\n break; // Stop looking for potential moves if the displayed result changes from the target\n }\n var fragCount = this.groupFragCount(order);\n potentialMoves.push({ move: move, fragCount: fragCount });\n }\n if (potentialMoves.length === 0) {\n return;\n }\n // The best move is the move with least group fragmentation\n potentialMoves.sort(function (a, b) { return a.fragCount - b.fragCount; });\n var bestMove = potentialMoves[0].move;\n this.columnModel.moveColumns(allMovingColumnsOrdered, bestMove, \"uiColumnDragged\");\n };\n // A measure of how fragmented in terms of groups an order of columns is\n MoveColumnFeature.prototype.groupFragCount = function (columns) {\n function parents(col) {\n var result = [];\n var parent = col.getOriginalParent();\n while (parent != null) {\n result.push(parent);\n parent = parent.getOriginalParent();\n }\n return result;\n }\n var count = 0;\n var _loop_1 = function (i) {\n var _a;\n var a = parents(columns[i]);\n var b = parents(columns[i + 1]);\n // iterate over the longest one\n _a = __read$e(a.length > b.length ? [a, b] : [b, a], 2), a = _a[0], b = _a[1];\n a.forEach(function (parent) {\n if (b.indexOf(parent) === -1) {\n count++; // More fragmented if other column doesn't share the parent\n }\n });\n };\n for (var i = 0; i < columns.length - 1; i++) {\n _loop_1(i);\n }\n return count;\n };\n MoveColumnFeature.prototype.calculateValidMoves = function (movingCols, draggingRight, mouseX) {\n var isMoveBlocked = this.gridOptionsWrapper.isSuppressMovableColumns() || movingCols.some(function (col) { return col.getColDef().suppressMovable; });\n if (isMoveBlocked) {\n return [];\n }\n // this is the list of cols on the screen, so it's these we use when comparing the x mouse position\n var allDisplayedCols = this.columnModel.getDisplayedColumns(this.pinned);\n // but this list is the list of all cols, when we move a col it's the index within this list that gets used,\n // so the result we return has to be and index location for this list\n var allGridCols = this.columnModel.getAllGridColumns();\n var movingDisplayedCols = allDisplayedCols.filter(function (col) { return includes(movingCols, col); });\n var otherDisplayedCols = allDisplayedCols.filter(function (col) { return !includes(movingCols, col); });\n var otherGridCols = allGridCols.filter(function (col) { return !includes(movingCols, col); });\n // work out how many DISPLAYED columns fit before the 'x' position. this gives us the displayIndex.\n // for example, if cols are a,b,c,d and we find a,b fit before 'x', then we want to place the moving\n // col between b and c (so that it is under the mouse position).\n var displayIndex = 0;\n var availableWidth = mouseX;\n // if we are dragging right, then the columns will be to the left of the mouse, so we also want to\n // include the width of the moving columns\n if (draggingRight) {\n var widthOfMovingDisplayedCols_1 = 0;\n movingDisplayedCols.forEach(function (col) { return widthOfMovingDisplayedCols_1 += col.getActualWidth(); });\n availableWidth -= widthOfMovingDisplayedCols_1;\n }\n if (availableWidth > 0) {\n // now count how many of the displayed columns will fit to the left\n for (var i = 0; i < otherDisplayedCols.length; i++) {\n var col = otherDisplayedCols[i];\n availableWidth -= col.getActualWidth();\n if (availableWidth < 0) {\n break;\n }\n displayIndex++;\n }\n // trial and error, if going right, we adjust by one, i didn't manage to quantify why, but it works\n if (draggingRight) {\n displayIndex++;\n }\n }\n // the display index is with respect to all the showing columns, however when we move, it's with\n // respect to all grid columns, so we need to translate from display index to grid index\n var firstValidMove;\n if (displayIndex > 0) {\n var leftColumn = otherDisplayedCols[displayIndex - 1];\n firstValidMove = otherGridCols.indexOf(leftColumn) + 1;\n }\n else {\n firstValidMove = otherGridCols.indexOf(otherDisplayedCols[0]);\n if (firstValidMove === -1) {\n firstValidMove = 0;\n }\n }\n var validMoves = [firstValidMove];\n var numberComparator = function (a, b) { return a - b; };\n // add in other valid moves due to hidden columns and married children. for example, a particular\n // move might break a group that has married children (so move isn't valid), however there could\n // be hidden columns (not displayed) that we could jump over to make the move valid. because\n // they are hidden, user doesn't see any different, however it allows moves that would otherwise\n // not work. for example imagine a group with 9 columns and all columns are hidden except the\n // middle one (so 4 hidden to left, 4 hidden to right), then when moving 'firstValidMove' will\n // be relative to the not-shown column, however we need to consider the move jumping over all the\n // hidden children. if we didn't do this, then if the group just described was at the end (RHS) of the\n // grid, there would be no way to put a column after it (as the grid would only consider beside the\n // visible column, which would fail valid move rules).\n if (draggingRight) {\n // if dragging right, then we add all the additional moves to the right. so in other words\n // if the next move is not valid, find the next move to the right that is valid.\n var pointer = firstValidMove + 1;\n var lastIndex = allGridCols.length - 1;\n while (pointer <= lastIndex) {\n validMoves.push(pointer);\n pointer++;\n }\n // adding columns here means the order is now messed up\n validMoves.sort(numberComparator);\n }\n else {\n // if dragging left we do the reverse of dragging right, we add in all the valid moves to the\n // left. however we also have to consider moves to the right for all hidden columns first.\n // (this logic is hard to reason with, it was worked out with trial and error,\n // more observation rather than science).\n // add moves to the right\n var pointer = firstValidMove;\n var lastIndex = allGridCols.length - 1;\n var displacedCol = allGridCols[pointer];\n while (pointer <= lastIndex && this.isColumnHidden(allDisplayedCols, displacedCol)) {\n pointer++;\n validMoves.push(pointer);\n displacedCol = allGridCols[pointer];\n }\n // add moves to the left\n pointer = firstValidMove - 1;\n var firstDisplayIndex = 0;\n while (pointer >= firstDisplayIndex) {\n validMoves.push(pointer);\n pointer--;\n }\n // adding columns here means the order is now messed up\n validMoves.sort(numberComparator).reverse();\n }\n return validMoves;\n };\n // isHidden takes into account visible=false and group=closed, ie it is not displayed\n MoveColumnFeature.prototype.isColumnHidden = function (displayedColumns, col) {\n return displayedColumns.indexOf(col) < 0;\n };\n MoveColumnFeature.prototype.ensureIntervalStarted = function () {\n if (!this.movingIntervalId) {\n this.intervalCount = 0;\n this.failedMoveAttempts = 0;\n this.movingIntervalId = window.setInterval(this.moveInterval.bind(this), 100);\n if (this.needToMoveLeft) {\n this.dragAndDropService.setGhostIcon(DragAndDropService.ICON_LEFT, true);\n }\n else {\n this.dragAndDropService.setGhostIcon(DragAndDropService.ICON_RIGHT, true);\n }\n }\n };\n MoveColumnFeature.prototype.ensureIntervalCleared = function () {\n if (this.movingIntervalId) {\n window.clearInterval(this.movingIntervalId);\n this.movingIntervalId = null;\n this.dragAndDropService.setGhostIcon(DragAndDropService.ICON_MOVE);\n }\n };\n MoveColumnFeature.prototype.moveInterval = function () {\n // the amounts we move get bigger at each interval, so the speed accelerates, starting a bit slow\n // and getting faster. this is to give smoother user experience. we max at 100px to limit the speed.\n var pixelsToMove;\n this.intervalCount++;\n pixelsToMove = 10 + (this.intervalCount * 5);\n if (pixelsToMove > 100) {\n pixelsToMove = 100;\n }\n var pixelsMoved = null;\n var scrollFeature = this.gridBodyCon.getScrollFeature();\n if (this.needToMoveLeft) {\n pixelsMoved = scrollFeature.scrollHorizontally(-pixelsToMove);\n }\n else if (this.needToMoveRight) {\n pixelsMoved = scrollFeature.scrollHorizontally(pixelsToMove);\n }\n if (pixelsMoved !== 0) {\n this.onDragging(this.lastDraggingEvent);\n this.failedMoveAttempts = 0;\n }\n else {\n // we count the failed move attempts. if we fail to move 7 times, then we pin the column.\n // this is how we achieve pining by dragging the column to the edge of the grid.\n this.failedMoveAttempts++;\n var columns = this.lastDraggingEvent.dragItem.columns;\n var columnsThatCanPin = columns.filter(function (c) { return !c.getColDef().lockPinned; });\n if (columnsThatCanPin.length > 0) {\n this.dragAndDropService.setGhostIcon(DragAndDropService.ICON_PINNED);\n if (this.failedMoveAttempts > 7) {\n var pinType = this.needToMoveLeft ? Constants.PINNED_LEFT : Constants.PINNED_RIGHT;\n this.setColumnsPinned(columnsThatCanPin, pinType, \"uiColumnDragged\");\n this.dragAndDropService.nudge();\n }\n }\n }\n };\n __decorate$1x([\n Autowired('columnModel')\n ], MoveColumnFeature.prototype, \"columnModel\", void 0);\n __decorate$1x([\n Autowired('dragAndDropService')\n ], MoveColumnFeature.prototype, \"dragAndDropService\", void 0);\n __decorate$1x([\n Autowired('gridOptionsWrapper')\n ], MoveColumnFeature.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$1x([\n Autowired('ctrlsService')\n ], MoveColumnFeature.prototype, \"ctrlsService\", void 0);\n __decorate$1x([\n PostConstruct\n ], MoveColumnFeature.prototype, \"init\", null);\n return MoveColumnFeature;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1D = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1w = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar BodyDropTarget = /** @class */ (function (_super) {\n __extends$1D(BodyDropTarget, _super);\n function BodyDropTarget(pinned, eContainer) {\n var _this = _super.call(this) || this;\n _this.pinned = pinned;\n _this.eContainer = eContainer;\n return _this;\n }\n BodyDropTarget.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) {\n switch (_this.pinned) {\n case Constants.PINNED_LEFT:\n _this.eSecondaryContainers = [\n [p.gridBodyCtrl.getBodyViewportElement(), p.leftRowContainerCtrl.getContainerElement()],\n [p.bottomLeftRowContainerCtrl.getContainerElement()],\n [p.topLeftRowContainerCtrl.getContainerElement()]\n ];\n break;\n case Constants.PINNED_RIGHT:\n _this.eSecondaryContainers = [\n [p.gridBodyCtrl.getBodyViewportElement(), p.rightRowContainerCtrl.getContainerElement()],\n [p.bottomRightRowContainerCtrl.getContainerElement()],\n [p.topRightRowContainerCtrl.getContainerElement()]\n ];\n break;\n default:\n _this.eSecondaryContainers = [\n [p.gridBodyCtrl.getBodyViewportElement(), p.centerRowContainerCtrl.getViewportElement()],\n [p.bottomCenterRowContainerCtrl.getViewportElement()],\n [p.topCenterRowContainerCtrl.getViewportElement()]\n ];\n break;\n }\n });\n };\n BodyDropTarget.prototype.isInterestedIn = function (type) {\n return type === DragSourceType.HeaderCell ||\n (type === DragSourceType.ToolPanel && this.gridOptionsWrapper.isAllowDragFromColumnsToolPanel());\n };\n BodyDropTarget.prototype.getSecondaryContainers = function () {\n return this.eSecondaryContainers;\n };\n BodyDropTarget.prototype.getContainer = function () {\n return this.eContainer;\n };\n BodyDropTarget.prototype.init = function () {\n this.moveColumnFeature = this.createManagedBean(new MoveColumnFeature(this.pinned, this.eContainer));\n this.bodyDropPivotTarget = this.createManagedBean(new BodyDropPivotTarget(this.pinned));\n this.dragAndDropService.addDropTarget(this);\n };\n BodyDropTarget.prototype.getIconName = function () {\n return this.currentDropListener.getIconName();\n };\n // we want to use the bodyPivotTarget if the user is dragging columns in from the toolPanel\n // and we are in pivot mode, as it has to logic to set pivot/value/group on the columns when\n // dropped into the grid's body.\n BodyDropTarget.prototype.isDropColumnInPivotMode = function (draggingEvent) {\n // in pivot mode, then if moving a column (ie didn't come from toolpanel) then it's\n // a standard column move, however if it came from the toolpanel, then we are introducing\n // dimensions or values to the grid\n return this.columnModel.isPivotMode() && draggingEvent.dragSource.type === DragSourceType.ToolPanel;\n };\n BodyDropTarget.prototype.onDragEnter = function (draggingEvent) {\n // we pick the drop listener depending on whether we are in pivot mode are not. if we are\n // in pivot mode, then dropping cols changes the row group, pivot, value stats. otherwise\n // we change visibility state and position.\n this.currentDropListener = this.isDropColumnInPivotMode(draggingEvent) ? this.bodyDropPivotTarget : this.moveColumnFeature;\n this.currentDropListener.onDragEnter(draggingEvent);\n };\n BodyDropTarget.prototype.onDragLeave = function (params) {\n this.currentDropListener.onDragLeave(params);\n };\n BodyDropTarget.prototype.onDragging = function (params) {\n this.currentDropListener.onDragging(params);\n };\n BodyDropTarget.prototype.onDragStop = function (params) {\n this.currentDropListener.onDragStop(params);\n };\n __decorate$1w([\n Autowired('dragAndDropService')\n ], BodyDropTarget.prototype, \"dragAndDropService\", void 0);\n __decorate$1w([\n Autowired('columnModel')\n ], BodyDropTarget.prototype, \"columnModel\", void 0);\n __decorate$1w([\n Autowired('ctrlsService')\n ], BodyDropTarget.prototype, \"ctrlsService\", void 0);\n __decorate$1w([\n PostConstruct\n ], BodyDropTarget.prototype, \"postConstruct\", null);\n __decorate$1w([\n PostConstruct\n ], BodyDropTarget.prototype, \"init\", null);\n return BodyDropTarget;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __read$d = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$b = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$d(arguments[i]));\n return ar;\n};\nvar CssClassApplier = /** @class */ (function () {\n function CssClassApplier() {\n }\n CssClassApplier.getHeaderClassesFromColDef = function (abstractColDef, gridOptionsWrapper, column, columnGroup) {\n if (missing(abstractColDef)) {\n return [];\n }\n return this.getColumnClassesFromCollDef(abstractColDef.headerClass, abstractColDef, gridOptionsWrapper, column, columnGroup);\n };\n CssClassApplier.getToolPanelClassesFromColDef = function (abstractColDef, gridOptionsWrapper, column, columnGroup) {\n if (missing(abstractColDef)) {\n return [];\n }\n return this.getColumnClassesFromCollDef(abstractColDef.toolPanelClass, abstractColDef, gridOptionsWrapper, column, columnGroup);\n };\n CssClassApplier.getClassParams = function (abstractColDef, gridOptionsWrapper, column, columnGroup) {\n return {\n // bad naming, as colDef here can be a group or a column,\n // however most people won't appreciate the difference,\n // so keeping it as colDef to avoid confusion.\n colDef: abstractColDef,\n column: column,\n columnGroup: columnGroup,\n api: gridOptionsWrapper.getApi(),\n columnApi: gridOptionsWrapper.getColumnApi(),\n context: gridOptionsWrapper.getContext()\n };\n };\n CssClassApplier.getColumnClassesFromCollDef = function (classesOrFunc, abstractColDef, gridOptionsWrapper, column, columnGroup) {\n if (missing(classesOrFunc)) {\n return [];\n }\n var classToUse;\n if (typeof classesOrFunc === 'function') {\n var params = this.getClassParams(abstractColDef, gridOptionsWrapper, column, columnGroup);\n classToUse = classesOrFunc(params);\n }\n else {\n classToUse = classesOrFunc;\n }\n if (typeof classToUse === 'string') {\n return [classToUse];\n }\n if (Array.isArray(classToUse)) {\n return __spread$b(classToUse);\n }\n return [];\n };\n return CssClassApplier;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1C = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1v = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderCellComp = /** @class */ (function (_super) {\n __extends$1C(HeaderCellComp, _super);\n function HeaderCellComp(ctrl) {\n var _this = _super.call(this, HeaderCellComp.TEMPLATE, ctrl) || this;\n _this.headerCompVersion = 0;\n _this.column = ctrl.getColumnGroupChild();\n _this.pinned = ctrl.getPinned();\n return _this;\n }\n HeaderCellComp.prototype.postConstruct = function () {\n var _this = this;\n var eGui = this.getGui();\n var setAttribute = function (name, value, element) {\n var actualElement = element ? element : eGui;\n if (value != null && value != '') {\n actualElement.setAttribute(name, value);\n }\n else {\n actualElement.removeAttribute(name);\n }\n };\n var compProxy = {\n setWidth: function (width) { return eGui.style.width = width; },\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n setColId: function (id) { return setAttribute('col-id', id); },\n setTitle: function (title) { return setAttribute('title', title); },\n setAriaDescription: function (label) { return setAriaDescription(eGui, label); },\n setAriaSort: function (sort) { return sort ? setAriaSort(eGui, sort) : removeAriaSort(eGui); },\n setUserCompDetails: function (compDetails) { return _this.setUserCompDetails(compDetails); },\n getUserCompInstance: function () { return _this.headerComp; }\n };\n this.ctrl.setComp(compProxy, this.getGui(), this.eResize, this.eHeaderCompWrapper);\n var selectAllGui = this.ctrl.getSelectAllGui();\n this.eResize.insertAdjacentElement('afterend', selectAllGui);\n };\n HeaderCellComp.prototype.destroyHeaderComp = function () {\n if (this.headerComp) {\n this.eHeaderCompWrapper.removeChild(this.headerCompGui);\n this.headerComp = this.destroyBean(this.headerComp);\n this.headerCompGui = undefined;\n }\n };\n HeaderCellComp.prototype.setUserCompDetails = function (compDetails) {\n var _this = this;\n this.headerCompVersion++;\n var versionCopy = this.headerCompVersion;\n compDetails.newAgStackInstance().then(function (comp) { return _this.afterCompCreated(versionCopy, comp); });\n };\n HeaderCellComp.prototype.afterCompCreated = function (version, headerComp) {\n if (version != this.headerCompVersion || !this.isAlive()) {\n this.destroyBean(headerComp);\n return;\n }\n this.destroyHeaderComp();\n this.headerComp = headerComp;\n this.headerCompGui = headerComp.getGui();\n this.eHeaderCompWrapper.appendChild(this.headerCompGui);\n this.ctrl.setDragSource(this.getGui());\n };\n HeaderCellComp.TEMPLATE = \"<div class=\\\"ag-header-cell\\\" role=\\\"columnheader\\\" tabindex=\\\"-1\\\">\\n <div ref=\\\"eResize\\\" class=\\\"ag-header-cell-resize\\\" role=\\\"presentation\\\"></div>\\n <div ref=\\\"eHeaderCompWrapper\\\" class=\\\"ag-header-cell-comp-wrapper\\\" role=\\\"presentation\\\"></div>\\n </div>\";\n __decorate$1v([\n RefSelector('eResize')\n ], HeaderCellComp.prototype, \"eResize\", void 0);\n __decorate$1v([\n RefSelector('eHeaderCompWrapper')\n ], HeaderCellComp.prototype, \"eHeaderCompWrapper\", void 0);\n __decorate$1v([\n PostConstruct\n ], HeaderCellComp.prototype, \"postConstruct\", null);\n __decorate$1v([\n PreDestroy\n ], HeaderCellComp.prototype, \"destroyHeaderComp\", null);\n return HeaderCellComp;\n}(AbstractHeaderCellComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1B = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1u = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderGroupCellComp = /** @class */ (function (_super) {\n __extends$1B(HeaderGroupCellComp, _super);\n function HeaderGroupCellComp(ctrl) {\n return _super.call(this, HeaderGroupCellComp.TEMPLATE, ctrl) || this;\n }\n HeaderGroupCellComp.prototype.postConstruct = function () {\n var _this = this;\n var eGui = this.getGui();\n var setAttribute = function (key, value) {\n return value != undefined ? eGui.setAttribute(key, value) : eGui.removeAttribute(key);\n };\n var compProxy = {\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n addOrRemoveResizableCssClass: function (cssClassName, on) { return _this.eResize.classList.toggle(cssClassName, on); },\n setWidth: function (width) { return eGui.style.width = width; },\n setColId: function (id) { return eGui.setAttribute(\"col-id\", id); },\n setAriaExpanded: function (expanded) { return setAttribute('aria-expanded', expanded); },\n setTitle: function (title) { return setAttribute(\"title\", title); },\n setUserCompDetails: function (details) { return _this.setUserCompDetails(details); }\n };\n this.ctrl.setComp(compProxy, eGui, this.eResize);\n };\n HeaderGroupCellComp.prototype.setUserCompDetails = function (details) {\n var _this = this;\n details.newAgStackInstance().then(function (comp) { return _this.afterHeaderCompCreated(comp); });\n };\n HeaderGroupCellComp.prototype.afterHeaderCompCreated = function (headerGroupComp) {\n var _this = this;\n var destroyFunc = function () { return _this.destroyBean(headerGroupComp); };\n if (!this.isAlive()) {\n destroyFunc();\n return;\n }\n this.getGui().appendChild(headerGroupComp.getGui());\n this.addDestroyFunc(destroyFunc);\n this.ctrl.setDragSource(headerGroupComp.getGui());\n };\n HeaderGroupCellComp.TEMPLATE = \"<div class=\\\"ag-header-group-cell\\\" role=\\\"columnheader\\\" tabindex=\\\"-1\\\">\\n <div ref=\\\"eResize\\\" class=\\\"ag-header-cell-resize\\\" role=\\\"presentation\\\"></div>\\n </div>\";\n __decorate$1u([\n Autowired('userComponentFactory')\n ], HeaderGroupCellComp.prototype, \"userComponentFactory\", void 0);\n __decorate$1u([\n RefSelector('eResize')\n ], HeaderGroupCellComp.prototype, \"eResize\", void 0);\n __decorate$1u([\n PostConstruct\n ], HeaderGroupCellComp.prototype, \"postConstruct\", null);\n return HeaderGroupCellComp;\n}(AbstractHeaderCellComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1A = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1t = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderRowType;\n(function (HeaderRowType) {\n HeaderRowType[\"COLUMN_GROUP\"] = \"group\";\n HeaderRowType[\"COLUMN\"] = \"column\";\n HeaderRowType[\"FLOATING_FILTER\"] = \"filter\";\n})(HeaderRowType || (HeaderRowType = {}));\nvar HeaderRowComp = /** @class */ (function (_super) {\n __extends$1A(HeaderRowComp, _super);\n function HeaderRowComp(ctrl) {\n var _this = _super.call(this) || this;\n _this.headerComps = {};\n var extraClass = ctrl.getType() == HeaderRowType.COLUMN_GROUP ? \"ag-header-row-column-group\" :\n ctrl.getType() == HeaderRowType.FLOATING_FILTER ? \"ag-header-row-column-filter\" : \"ag-header-row-column\";\n _this.setTemplate(/* html */ \"<div class=\\\"ag-header-row \" + extraClass + \"\\\" role=\\\"row\\\"></div>\");\n _this.ctrl = ctrl;\n return _this;\n }\n //noinspection JSUnusedLocalSymbols\n HeaderRowComp.prototype.init = function () {\n var _this = this;\n var compProxy = {\n setTransform: function (transform) { return _this.getGui().style.transform = transform; },\n setHeight: function (height) { return _this.getGui().style.height = height; },\n setTop: function (top) { return _this.getGui().style.top = top; },\n setHeaderCtrls: function (ctrls) { return _this.setHeaderCtrls(ctrls); },\n setWidth: function (width) { return _this.getGui().style.width = width; },\n setAriaRowIndex: function (rowIndex) { return setAriaRowIndex(_this.getGui(), rowIndex); }\n };\n this.ctrl.setComp(compProxy);\n };\n HeaderRowComp.prototype.destroyHeaderCtrls = function () {\n this.setHeaderCtrls([]);\n };\n HeaderRowComp.prototype.setHeaderCtrls = function (ctrls) {\n var _this = this;\n if (!this.isAlive()) {\n return;\n }\n var oldComps = this.headerComps;\n this.headerComps = {};\n ctrls.forEach(function (ctrl) {\n var id = ctrl.getInstanceId();\n var comp = oldComps[id];\n delete oldComps[id];\n if (comp == null) {\n comp = _this.createHeaderComp(ctrl);\n _this.getGui().appendChild(comp.getGui());\n }\n _this.headerComps[id] = comp;\n });\n iterateObject(oldComps, function (id, comp) {\n _this.getGui().removeChild(comp.getGui());\n _this.destroyBean(comp);\n });\n var ensureDomOrder = this.gridOptionsWrapper.isEnsureDomOrder();\n if (ensureDomOrder) {\n var comps = getAllValuesInObject(this.headerComps);\n // ordering the columns by left position orders them in the order they appear on the screen\n comps.sort(function (a, b) {\n var leftA = a.getCtrl().getColumnGroupChild().getLeft();\n var leftB = b.getCtrl().getColumnGroupChild().getLeft();\n return leftA - leftB;\n });\n var elementsInOrder = comps.map(function (c) { return c.getGui(); });\n setDomChildOrder(this.getGui(), elementsInOrder);\n }\n };\n HeaderRowComp.prototype.createHeaderComp = function (headerCtrl) {\n var result;\n switch (this.ctrl.getType()) {\n case HeaderRowType.COLUMN_GROUP:\n result = new HeaderGroupCellComp(headerCtrl);\n break;\n case HeaderRowType.FLOATING_FILTER:\n result = new HeaderFilterCellComp(headerCtrl);\n break;\n default:\n result = new HeaderCellComp(headerCtrl);\n break;\n }\n this.createBean(result);\n result.setParentComponent(this);\n return result;\n };\n __decorate$1t([\n PostConstruct\n ], HeaderRowComp.prototype, \"init\", null);\n __decorate$1t([\n PreDestroy\n ], HeaderRowComp.prototype, \"destroyHeaderCtrls\", null);\n return HeaderRowComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1z = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1s = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar instanceIdSequence$1 = 0;\nvar AbstractHeaderCellCtrl = /** @class */ (function (_super) {\n __extends$1z(AbstractHeaderCellCtrl, _super);\n function AbstractHeaderCellCtrl(columnGroupChild, parentRowCtrl) {\n var _this = _super.call(this) || this;\n _this.lastFocusEvent = null;\n _this.columnGroupChild = columnGroupChild;\n _this.parentRowCtrl = parentRowCtrl;\n // unique id to this instance, including the column ID to help with debugging in React as it's used in 'key'\n _this.instanceId = columnGroupChild.getUniqueId() + '-' + instanceIdSequence$1++;\n return _this;\n }\n AbstractHeaderCellCtrl.prototype.shouldStopEventPropagation = function (e) {\n var _a = this.focusService.getFocusedHeader(), headerRowIndex = _a.headerRowIndex, column = _a.column;\n return isUserSuppressingHeaderKeyboardEvent(this.gridOptionsWrapper, e, headerRowIndex, column);\n };\n AbstractHeaderCellCtrl.prototype.getWrapperHasFocus = function () {\n var eDocument = this.gridOptionsWrapper.getDocument();\n var activeEl = eDocument.activeElement;\n return activeEl === this.eGui;\n };\n AbstractHeaderCellCtrl.prototype.setGui = function (eGui) {\n this.eGui = eGui;\n this.addDomData();\n };\n AbstractHeaderCellCtrl.prototype.handleKeyDown = function (e) {\n var wrapperHasFocus = this.getWrapperHasFocus();\n switch (e.key) {\n case KeyCode.PAGE_DOWN:\n case KeyCode.PAGE_UP:\n case KeyCode.PAGE_HOME:\n case KeyCode.PAGE_END:\n if (wrapperHasFocus) {\n e.preventDefault();\n }\n }\n };\n AbstractHeaderCellCtrl.prototype.addDomData = function () {\n var _this = this;\n var key = AbstractHeaderCellCtrl.DOM_DATA_KEY_HEADER_CTRL;\n this.gridOptionsWrapper.setDomData(this.eGui, key, this);\n this.addDestroyFunc(function () { return _this.gridOptionsWrapper.setDomData(_this.eGui, key, null); });\n };\n AbstractHeaderCellCtrl.prototype.getGui = function () {\n return this.eGui;\n };\n AbstractHeaderCellCtrl.prototype.focus = function (event) {\n if (!this.eGui) {\n return false;\n }\n this.lastFocusEvent = event || null;\n this.eGui.focus();\n return true;\n };\n AbstractHeaderCellCtrl.prototype.getRowIndex = function () {\n return this.parentRowCtrl.getRowIndex();\n };\n AbstractHeaderCellCtrl.prototype.getParentRowCtrl = function () {\n return this.parentRowCtrl;\n };\n AbstractHeaderCellCtrl.prototype.getPinned = function () {\n return this.parentRowCtrl.getPinned();\n };\n AbstractHeaderCellCtrl.prototype.getInstanceId = function () {\n return this.instanceId;\n };\n AbstractHeaderCellCtrl.prototype.getColumnGroupChild = function () {\n return this.columnGroupChild;\n };\n AbstractHeaderCellCtrl.DOM_DATA_KEY_HEADER_CTRL = 'headerCtrl';\n __decorate$1s([\n Autowired('focusService')\n ], AbstractHeaderCellCtrl.prototype, \"focusService\", void 0);\n __decorate$1s([\n Autowired('beans')\n ], AbstractHeaderCellCtrl.prototype, \"beans\", void 0);\n __decorate$1s([\n Autowired('userComponentFactory')\n ], AbstractHeaderCellCtrl.prototype, \"userComponentFactory\", void 0);\n return AbstractHeaderCellCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar ClientSideRowModelSteps;\n(function (ClientSideRowModelSteps) {\n ClientSideRowModelSteps[\"EVERYTHING\"] = \"group\";\n ClientSideRowModelSteps[\"FILTER\"] = \"filter\";\n ClientSideRowModelSteps[\"SORT\"] = \"sort\";\n ClientSideRowModelSteps[\"MAP\"] = \"map\";\n ClientSideRowModelSteps[\"AGGREGATE\"] = \"aggregate\";\n ClientSideRowModelSteps[\"FILTER_AGGREGATES\"] = \"filter_aggregates\";\n ClientSideRowModelSteps[\"PIVOT\"] = \"pivot\";\n ClientSideRowModelSteps[\"NOTHING\"] = \"nothing\";\n})(ClientSideRowModelSteps || (ClientSideRowModelSteps = {}));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$1r = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nfunction unwrapUserComp(comp) {\n var compAsAny = comp;\n var isProxy = compAsAny != null && compAsAny.getFrameworkComponentInstance != null;\n return isProxy ? compAsAny.getFrameworkComponentInstance() : comp;\n}\nvar GridApi = /** @class */ (function () {\n function GridApi() {\n this.detailGridInfoMap = {};\n this.destroyCalled = false;\n }\n GridApi.prototype.registerOverlayWrapperComp = function (overlayWrapperComp) {\n this.overlayWrapperComp = overlayWrapperComp;\n };\n GridApi.prototype.registerSideBarComp = function (sideBarComp) {\n this.sideBarComp = sideBarComp;\n };\n GridApi.prototype.init = function () {\n var _this = this;\n switch (this.rowModel.getType()) {\n case Constants.ROW_MODEL_TYPE_CLIENT_SIDE:\n this.clientSideRowModel = this.rowModel;\n break;\n case Constants.ROW_MODEL_TYPE_INFINITE:\n this.infiniteRowModel = this.rowModel;\n break;\n case Constants.ROW_MODEL_TYPE_SERVER_SIDE:\n this.serverSideRowModel = this.rowModel;\n break;\n }\n this.ctrlsService.whenReady(function () {\n _this.gridBodyCtrl = _this.ctrlsService.getGridBodyCtrl();\n });\n };\n /** Used internally by grid. Not intended to be used by the client. Interface may change between releases. */\n GridApi.prototype.__getAlignedGridService = function () {\n return this.alignedGridsService;\n };\n /** Used internally by grid. Not intended to be used by the client. Interface may change between releases. */\n GridApi.prototype.__getContext = function () {\n return this.context;\n };\n /** Register a detail grid with the master grid when it is created. */\n GridApi.prototype.addDetailGridInfo = function (id, gridInfo) {\n this.detailGridInfoMap[id] = gridInfo;\n };\n /** Unregister a detail grid from the master grid when it is destroyed. */\n GridApi.prototype.removeDetailGridInfo = function (id) {\n this.detailGridInfoMap[id] = undefined;\n };\n /** Returns the `DetailGridInfo` corresponding to the supplied `detailGridId`. */\n GridApi.prototype.getDetailGridInfo = function (id) {\n return this.detailGridInfoMap[id];\n };\n /** Iterates through each `DetailGridInfo` in the grid and calls the supplied callback on each. */\n GridApi.prototype.forEachDetailGridInfo = function (callback) {\n var index = 0;\n iterateObject(this.detailGridInfoMap, function (id, gridInfo) {\n // check for undefined, as old references will still be lying around\n if (exists(gridInfo)) {\n callback(gridInfo, index);\n index++;\n }\n });\n };\n /** Similar to `exportDataAsCsv`, except returns the result as a string rather than download it. */\n GridApi.prototype.getDataAsCsv = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.CsvExportModule, 'api.getDataAsCsv')) {\n return this.csvCreator.getDataAsCsv(params);\n }\n };\n /** Downloads a CSV export of the grid's data. */\n GridApi.prototype.exportDataAsCsv = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.CsvExportModule, 'api.exportDataAsCSv')) {\n this.csvCreator.exportDataAsCsv(params);\n }\n };\n GridApi.prototype.getExcelExportMode = function (params) {\n var baseParams = this.gridOptionsWrapper.getDefaultExportParams('excel');\n var mergedParams = Object.assign({ exportMode: 'xlsx' }, baseParams, params);\n return mergedParams.exportMode;\n };\n /** Similar to `exportDataAsExcel`, except instead of downloading a file, it will return a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) to be processed by the user. */\n GridApi.prototype.getDataAsExcel = function (params) {\n if (!ModuleRegistry.assertRegistered(ModuleNames.ExcelExportModule, 'api.getDataAsExcel')) {\n return;\n }\n var exportMode = this.getExcelExportMode(params);\n if (this.excelCreator.getFactoryMode(exportMode) === ExcelFactoryMode.MULTI_SHEET) {\n console.warn('AG Grid: The Excel Exporter is currently on Multi Sheet mode. End that operation by calling `api.getMultipleSheetAsExcel()` or `api.exportMultipleSheetsAsExcel()`');\n return;\n }\n return this.excelCreator.getDataAsExcel(params);\n };\n /** Downloads an Excel export of the grid's data. */\n GridApi.prototype.exportDataAsExcel = function (params) {\n if (!ModuleRegistry.assertRegistered(ModuleNames.ExcelExportModule, 'api.exportDataAsExcel')) {\n return;\n }\n var exportMode = this.getExcelExportMode(params);\n if (this.excelCreator.getFactoryMode(exportMode) === ExcelFactoryMode.MULTI_SHEET) {\n console.warn('AG Grid: The Excel Exporter is currently on Multi Sheet mode. End that operation by calling `api.getMultipleSheetAsExcel()` or `api.exportMultipleSheetsAsExcel()`');\n return;\n }\n this.excelCreator.exportDataAsExcel(params);\n };\n /** This is method to be used to get the grid's data as a sheet, that will later be exported either by `getMultipleSheetsAsExcel()` or `exportMultipleSheetsAsExcel()`. */\n GridApi.prototype.getSheetDataForExcel = function (params) {\n if (!ModuleRegistry.assertRegistered(ModuleNames.ExcelExportModule, 'api.getSheetDataForExcel')) {\n return;\n }\n var exportMode = this.getExcelExportMode(params);\n this.excelCreator.setFactoryMode(ExcelFactoryMode.MULTI_SHEET, exportMode);\n return this.excelCreator.getSheetDataForExcel(params);\n };\n /** Similar to `exportMultipleSheetsAsExcel`, except instead of downloading a file, it will return a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) to be processed by the user. */\n GridApi.prototype.getMultipleSheetsAsExcel = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.ExcelExportModule, 'api.getMultipleSheetsAsExcel')) {\n return this.excelCreator.getMultipleSheetsAsExcel(params);\n }\n };\n /** Downloads an Excel export of multiple sheets in one file. */\n GridApi.prototype.exportMultipleSheetsAsExcel = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.ExcelExportModule, 'api.exportMultipleSheetsAsExcel')) {\n return this.excelCreator.exportMultipleSheetsAsExcel(params);\n }\n };\n /** @deprecated AG Grid: since version 18.x, api.setEnterpriseDatasource() should be replaced with api.setServerSideDatasource() */\n GridApi.prototype.setEnterpriseDatasource = function (datasource) {\n console.warn(\"AG Grid: since version 18.x, api.setEnterpriseDatasource() should be replaced with api.setServerSideDatasource()\");\n this.setServerSideDatasource(datasource);\n };\n /**\n * Sets an ARIA property in the grid panel (element with `role=\\\"grid\\\"`), and removes an ARIA property when the value is null.\n *\n * Example: `api.setGridAriaProperty('label', 'my grid')` will set `aria-label=\\\"my grid\\\"`.\n *\n * `api.setGridAriaProperty('label', null)` will remove the `aria-label` attribute from the grid element.\n */\n GridApi.prototype.setGridAriaProperty = function (property, value) {\n if (!property) {\n return;\n }\n var eGrid = this.ctrlsService.getGridBodyCtrl().getGui();\n var ariaProperty = \"aria-\" + property;\n if (value === null) {\n eGrid.removeAttribute(ariaProperty);\n }\n else {\n eGrid.setAttribute(ariaProperty, value);\n }\n };\n /** Set new datasource for Server-Side Row Model. */\n GridApi.prototype.setServerSideDatasource = function (datasource) {\n if (this.serverSideRowModel) {\n // should really have an IEnterpriseRowModel interface, so we are not casting to any\n this.serverSideRowModel.setDatasource(datasource);\n }\n else {\n console.warn(\"AG Grid: you can only use an enterprise datasource when gridOptions.rowModelType is '\" + Constants.ROW_MODEL_TYPE_SERVER_SIDE + \"'\");\n }\n };\n /**\n * Updates the `cacheBlockSize` used by `serverSideInfiniteScroll` when requesting data from the server.\n *\n * Note this purges all the cached data and reloads all the rows of the grid.\n * */\n GridApi.prototype.setCacheBlockSize = function (blockSize) {\n if (!this.serverSideRowModel) {\n console.warn(\"AG Grid: you can only set cacheBlockSize with gridOptions.rowModelType '\" + Constants.ROW_MODEL_TYPE_SERVER_SIDE + \"'\");\n return;\n }\n this.gridOptionsWrapper.setProperty('cacheBlockSize', blockSize);\n this.serverSideRowModel.resetRootStore();\n };\n /** Set new datasource for Infinite Row Model. */\n GridApi.prototype.setDatasource = function (datasource) {\n if (this.gridOptionsWrapper.isRowModelInfinite()) {\n this.rowModel.setDatasource(datasource);\n }\n else {\n console.warn(\"AG Grid: you can only use a datasource when gridOptions.rowModelType is '\" + Constants.ROW_MODEL_TYPE_INFINITE + \"'\");\n }\n };\n /** Set new datasource for Viewport Row Model. */\n GridApi.prototype.setViewportDatasource = function (viewportDatasource) {\n if (this.gridOptionsWrapper.isRowModelViewport()) {\n // this is bad coding, because it's using an interface that's exposed in the enterprise.\n // really we should create an interface in the core for viewportDatasource and let\n // the enterprise implement it, rather than casting to 'any' here\n this.rowModel.setViewportDatasource(viewportDatasource);\n }\n else {\n console.warn(\"AG Grid: you can only use a viewport datasource when gridOptions.rowModelType is '\" + Constants.ROW_MODEL_TYPE_VIEWPORT + \"'\");\n }\n };\n /** Set the row data. */\n GridApi.prototype.setRowData = function (rowData) {\n // immutable service is part of the CSRM module, if missing, no CSRM\n var missingImmutableService = this.immutableService == null;\n if (missingImmutableService) {\n console.warn('AG Grid: you can only set rowData when using the Client Side Row Model');\n return;\n }\n // if no keys provided provided for rows, then we can tread the operation as Immutable\n if (this.immutableService.isActive()) {\n this.immutableService.setRowData(rowData);\n }\n else {\n this.selectionService.reset();\n this.clientSideRowModel.setRowData(rowData);\n }\n };\n /** @deprecated AG Grid: since v12, api.setFloatingTopRowData() is now api.setPinnedTopRowData() */\n GridApi.prototype.setFloatingTopRowData = function (rows) {\n console.warn('AG Grid: since v12, api.setFloatingTopRowData() is now api.setPinnedTopRowData()');\n this.setPinnedTopRowData(rows);\n };\n /** @deprecated AG Grid: since v12, api.setFloatingBottomRowData() is now api.setPinnedBottomRowData() */\n GridApi.prototype.setFloatingBottomRowData = function (rows) {\n console.warn('AG Grid: since v12, api.setFloatingBottomRowData() is now api.setPinnedBottomRowData()');\n this.setPinnedBottomRowData(rows);\n };\n /** @deprecated AG Grid: since v12, api.getFloatingTopRowCount() is now api.getPinnedTopRowCount() */\n GridApi.prototype.getFloatingTopRowCount = function () {\n console.warn('AG Grid: since v12, api.getFloatingTopRowCount() is now api.getPinnedTopRowCount()');\n return this.getPinnedTopRowCount();\n };\n /** @deprecated AG Grid: since v12, api.getFloatingBottomRowCount() is now api.getPinnedBottomRowCount() */\n GridApi.prototype.getFloatingBottomRowCount = function () {\n console.warn('AG Grid: since v12, api.getFloatingBottomRowCount() is now api.getPinnedBottomRowCount()');\n return this.getPinnedBottomRowCount();\n };\n /** @deprecated AG Grid: since v12, api.getFloatingTopRow() is now api.getPinnedTopRow() */\n GridApi.prototype.getFloatingTopRow = function (index) {\n console.warn('AG Grid: since v12, api.getFloatingTopRow() is now api.getPinnedTopRow()');\n return this.getPinnedTopRow(index);\n };\n /** @deprecated AG Grid: since v12, api.getFloatingBottomRow() is now api.getPinnedBottomRow() */\n GridApi.prototype.getFloatingBottomRow = function (index) {\n console.warn('AG Grid: since v12, api.getFloatingBottomRow() is now api.getPinnedBottomRow()');\n return this.getPinnedBottomRow(index);\n };\n /** Set the top pinned rows. Call with no rows / undefined to clear top pinned rows. */\n GridApi.prototype.setPinnedTopRowData = function (rows) {\n this.pinnedRowModel.setPinnedTopRowData(rows);\n };\n /** Set the bottom pinned rows. Call with no rows / undefined to clear bottom pinned rows. */\n GridApi.prototype.setPinnedBottomRowData = function (rows) {\n this.pinnedRowModel.setPinnedBottomRowData(rows);\n };\n /** Gets the number of top pinned rows. */\n GridApi.prototype.getPinnedTopRowCount = function () {\n return this.pinnedRowModel.getPinnedTopRowCount();\n };\n /** Gets the number of bottom pinned rows. */\n GridApi.prototype.getPinnedBottomRowCount = function () {\n return this.pinnedRowModel.getPinnedBottomRowCount();\n };\n /** Gets the top pinned row with the specified index. */\n GridApi.prototype.getPinnedTopRow = function (index) {\n return this.pinnedRowModel.getPinnedTopRow(index);\n };\n /** Gets the top pinned row with the specified index. */\n GridApi.prototype.getPinnedBottomRow = function (index) {\n return this.pinnedRowModel.getPinnedBottomRow(index);\n };\n /**\n * Call to set new column definitions. The grid will redraw all the column headers, and then redraw all of the rows.\n */\n GridApi.prototype.setColumnDefs = function (colDefs, source) {\n if (source === void 0) { source = \"api\"; }\n this.columnModel.setColumnDefs(colDefs, source);\n };\n /** Call to set new auto group column definition. The grid will recreate any auto-group columns if present. */\n GridApi.prototype.setAutoGroupColumnDef = function (colDef, source) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_AUTO_GROUP_COLUMN_DEF, colDef, true);\n };\n /** Call to set new Default Column Definition. */\n GridApi.prototype.setDefaultColDef = function (colDef, source) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_DEFAULT_COL_DEF, colDef, true);\n };\n GridApi.prototype.expireValueCache = function () {\n this.valueCache.expire();\n };\n /**\n * Returns an object with two properties:\n * - `top`: The top pixel position of the current scroll in the grid\n * - `bottom`: The bottom pixel position of the current scroll in the grid\n */\n GridApi.prototype.getVerticalPixelRange = function () {\n return this.gridBodyCtrl.getScrollFeature().getVScrollPosition();\n };\n /**\n * Returns an object with two properties:\n * - `left`: The left pixel position of the current scroll in the grid\n * - `right`: The right pixel position of the current scroll in the grid\n */\n GridApi.prototype.getHorizontalPixelRange = function () {\n return this.gridBodyCtrl.getScrollFeature().getHScrollPosition();\n };\n /** If `true`, the horizontal scrollbar will always be present, even if not required. Otherwise, it will only be displayed when necessary. */\n GridApi.prototype.setAlwaysShowHorizontalScroll = function (show) {\n this.gridOptionsWrapper.setProperty('alwaysShowHorizontalScroll', show);\n };\n /** If `true`, the vertical scrollbar will always be present, even if not required. Otherwise it will only be displayed when necessary. */\n GridApi.prototype.setAlwaysShowVerticalScroll = function (show) {\n this.gridOptionsWrapper.setProperty('alwaysShowVerticalScroll', show);\n };\n /** Force refresh all tool panels by calling their `refresh` method. */\n GridApi.prototype.refreshToolPanel = function () {\n if (!this.sideBarComp) {\n return;\n }\n this.sideBarComp.refresh();\n };\n /** Performs change detection on all cells, refreshing cells where required. */\n GridApi.prototype.refreshCells = function (params) {\n if (params === void 0) { params = {}; }\n if (Array.isArray(params)) {\n // the old version of refreshCells() took an array of rowNodes for the first argument\n console.warn('since AG Grid v11.1, refreshCells() now takes parameters, please see the documentation.');\n return;\n }\n this.rowRenderer.refreshCells(params);\n };\n /** Flash rows, columns or individual cells. */\n GridApi.prototype.flashCells = function (params) {\n if (params === void 0) { params = {}; }\n this.rowRenderer.flashCells(params);\n };\n /** Remove row(s) from the DOM and recreate them again from scratch. */\n GridApi.prototype.redrawRows = function (params) {\n if (params === void 0) { params = {}; }\n var rowNodes = params ? params.rowNodes : undefined;\n this.rowRenderer.redrawRows(rowNodes);\n };\n GridApi.prototype.setFunctionsReadOnly = function (readOnly) {\n this.gridOptionsWrapper.setProperty('functionsReadOnly', readOnly);\n };\n /** Redraws the header. Useful if a column name changes, or something else that changes how the column header is displayed. */\n GridApi.prototype.refreshHeader = function () {\n this.ctrlsService.getHeaderRowContainerCtrls().forEach(function (c) { return c.refresh(); });\n };\n /** Returns `true` if any filter is set. This includes quick filter, advanced filter or external filter. */\n GridApi.prototype.isAnyFilterPresent = function () {\n return this.filterManager.isAnyFilterPresent();\n };\n /** Returns `true` if any column filter is set, otherwise `false`. */\n GridApi.prototype.isColumnFilterPresent = function () {\n return this.filterManager.isColumnFilterPresent() || this.filterManager.isAggregateFilterPresent();\n };\n /** Returns `true` if the quick filter is set, otherwise `false`. */\n GridApi.prototype.isQuickFilterPresent = function () {\n return this.filterManager.isQuickFilterPresent();\n };\n /**\n * Returns the row model inside the table.\n * From here you can see the original rows, rows after filter has been applied,\n * rows after aggregation has been applied, and the final set of 'to be displayed' rows.\n */\n GridApi.prototype.getModel = function () {\n return this.rowModel;\n };\n /** Expand or collapse a specific row node. */\n GridApi.prototype.setRowNodeExpanded = function (rowNode, expanded) {\n if (rowNode) {\n rowNode.setExpanded(expanded);\n }\n };\n /**\n * If after getting the model, you expand or collapse a group, call this method to inform the grid.\n * It will work out the final set of 'to be displayed' rows again (i.e. expand or collapse the group visually).\n */\n GridApi.prototype.onGroupExpandedOrCollapsed = function (deprecated_refreshFromIndex) {\n if (missing(this.clientSideRowModel)) {\n console.warn('AG Grid: cannot call onGroupExpandedOrCollapsed unless using normal row model');\n }\n if (exists(deprecated_refreshFromIndex)) {\n console.warn('AG Grid: api.onGroupExpandedOrCollapsed - refreshFromIndex parameter is no longer used, the grid will refresh all rows');\n }\n // we don't really want the user calling this if only one rowNode was expanded, instead they should be\n // calling rowNode.setExpanded(boolean) - this way we do a 'keepRenderedRows=false' so that the whole\n // grid gets refreshed again - otherwise the row with the rowNodes that were changed won't get updated,\n // and thus the expand icon in the group cell won't get 'opened' or 'closed'.\n this.clientSideRowModel.refreshModel({ step: ClientSideRowModelSteps.MAP });\n };\n /** @deprecated AG Grid: since version 18.x, api.refreshInMemoryRowModel() should be replaced with api.refreshClientSideRowModel() */\n GridApi.prototype.refreshInMemoryRowModel = function (step) {\n console.warn(\"AG Grid: since version 18.x, api.refreshInMemoryRowModel() should be replaced with api.refreshClientSideRowModel()\");\n this.refreshClientSideRowModel(step);\n };\n /** Gets the Client-Side Row Model to refresh, executing the grouping, filtering and sorting again. */\n GridApi.prototype.refreshClientSideRowModel = function (step) {\n if (missing(this.clientSideRowModel)) {\n console.warn('cannot call refreshClientSideRowModel unless using normal row model');\n }\n var paramsStep = ClientSideRowModelSteps.EVERYTHING;\n var stepsMapped = {\n group: ClientSideRowModelSteps.EVERYTHING,\n filter: ClientSideRowModelSteps.FILTER,\n map: ClientSideRowModelSteps.MAP,\n aggregate: ClientSideRowModelSteps.AGGREGATE,\n sort: ClientSideRowModelSteps.SORT,\n pivot: ClientSideRowModelSteps.PIVOT\n };\n if (exists(step)) {\n paramsStep = stepsMapped[step];\n }\n if (missing(paramsStep)) {\n console.error(\"AG Grid: invalid step \" + step + \", available steps are \" + Object.keys(stepsMapped).join(', '));\n return;\n }\n var animate = !this.gridOptionsWrapper.isSuppressAnimationFrame();\n var modelParams = {\n step: paramsStep,\n keepRenderedRows: true,\n keepEditingRows: true,\n animate: animate\n };\n this.clientSideRowModel.refreshModel(modelParams);\n };\n /** Returns `true` when there are no more animation frames left to process. */\n GridApi.prototype.isAnimationFrameQueueEmpty = function () {\n return this.animationFrameService.isQueueEmpty();\n };\n GridApi.prototype.flushAllAnimationFrames = function () {\n this.animationFrameService.flushAllFrames();\n };\n /**\n * Returns the row node with the given ID.\n * The row node ID is the one you provide from the callback `getRowId(params)`,\n * otherwise the ID is a number (cast as string) auto-generated by the grid when\n * the row data is set.\n */\n GridApi.prototype.getRowNode = function (id) {\n return this.rowModel.getRowNode(id);\n };\n /**\n * Gets the sizes that various UI elements will be rendered at with the current theme.\n * If you override the row or header height using `gridOptions`, the override value you provided will be returned.\n */\n GridApi.prototype.getSizesForCurrentTheme = function () {\n return {\n rowHeight: this.gridOptionsWrapper.getRowHeightAsNumber(),\n headerHeight: this.gridOptionsWrapper.getHeaderHeight()\n };\n };\n /** Expand all groups. */\n GridApi.prototype.expandAll = function () {\n if (this.clientSideRowModel) {\n this.clientSideRowModel.expandOrCollapseAll(true);\n }\n else if (this.serverSideRowModel) {\n this.serverSideRowModel.expandAll(true);\n }\n else {\n console.warn('AG Grid: expandAll only works with Client Side Row Model and Server Side Row Model');\n }\n };\n /** Collapse all groups. */\n GridApi.prototype.collapseAll = function () {\n if (this.clientSideRowModel) {\n this.clientSideRowModel.expandOrCollapseAll(false);\n }\n else if (this.serverSideRowModel) {\n this.serverSideRowModel.expandAll(false);\n }\n else {\n console.warn('AG Grid: collapseAll only works with Client Side Row Model and Server Side Row Model');\n }\n };\n /** Gets the tool panel instance corresponding to the supplied `id`. */\n GridApi.prototype.getToolPanelInstance = function (id) {\n if (!this.sideBarComp) {\n console.warn('AG Grid: toolPanel is only available in AG Grid Enterprise');\n return;\n }\n var comp = this.sideBarComp.getToolPanelInstance(id);\n return unwrapUserComp(comp);\n };\n GridApi.prototype.addVirtualRowListener = function (eventName, rowIndex, callback) {\n if (typeof eventName !== 'string') {\n console.warn('AG Grid: addVirtualRowListener is deprecated, please use addRenderedRowListener.');\n }\n this.addRenderedRowListener(eventName, rowIndex, callback);\n };\n /**\n * Registers a callback to a virtual row.\n * A virtual row is a row that is visually rendered on the screen (rows that are not visible because of the scroll position are not rendered).\n * Unlike normal events, you do not need to unregister rendered row listeners.\n * When the rendered row is removed from the grid, all associated rendered row listeners will also be removed.\n * listen for this event if your `cellRenderer` needs to do cleanup when the row no longer exists.\n */\n GridApi.prototype.addRenderedRowListener = function (eventName, rowIndex, callback) {\n if (eventName === 'virtualRowSelected') {\n console.warn(\"AG Grid: event virtualRowSelected is deprecated, to register for individual row\\n selection events, add a listener directly to the row node.\");\n }\n this.rowRenderer.addRenderedRowListener(eventName, rowIndex, callback);\n };\n /** Pass a quick filter text into the grid for filtering. */\n GridApi.prototype.setQuickFilter = function (newFilter) {\n this.filterManager.setQuickFilter(newFilter);\n };\n /** @deprecated AG Grid: do not use api for selection, call rowNode.setSelected(value) instead */\n GridApi.prototype.selectIndex = function (index, tryMulti, suppressEvents) {\n console.warn('AG Grid: do not use api for selection, call rowNode.setSelected(value) instead');\n if (suppressEvents) {\n console.warn('AG Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it');\n }\n this.selectionService.selectIndex(index, tryMulti);\n };\n /** @deprecated AG Grid: do not use api for selection, call rowNode.setSelected(value) instead. */\n GridApi.prototype.deselectIndex = function (index, suppressEvents) {\n if (suppressEvents === void 0) { suppressEvents = false; }\n console.warn('AG Grid: do not use api for selection, call rowNode.setSelected(value) instead');\n if (suppressEvents) {\n console.warn('AG Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it');\n }\n this.selectionService.deselectIndex(index);\n };\n /** @deprecated AG Grid: API for selection is deprecated, call rowNode.setSelected(value) instead. */\n GridApi.prototype.selectNode = function (node, tryMulti, suppressEvents) {\n if (tryMulti === void 0) { tryMulti = false; }\n if (suppressEvents === void 0) { suppressEvents = false; }\n console.warn('AG Grid: API for selection is deprecated, call rowNode.setSelected(value) instead');\n if (suppressEvents) {\n console.warn('AG Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it');\n }\n node.setSelectedParams({ newValue: true, clearSelection: !tryMulti });\n };\n /** @deprecated AG Grid: API for selection is deprecated, call rowNode.setSelected(value) instead. */\n GridApi.prototype.deselectNode = function (node, suppressEvents) {\n if (suppressEvents === void 0) { suppressEvents = false; }\n console.warn('AG Grid: API for selection is deprecated, call rowNode.setSelected(value) instead');\n if (suppressEvents) {\n console.warn('AG Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it');\n }\n node.setSelectedParams({ newValue: false });\n };\n /** Select all rows, regardless of filtering and rows that are not visible due to grouping being enabled and their groups not expanded. */\n GridApi.prototype.selectAll = function () {\n this.selectionService.selectAllRowNodes();\n };\n /** Clear all row selections, regardless of filtering. */\n GridApi.prototype.deselectAll = function () {\n this.selectionService.deselectAllRowNodes();\n };\n /** Select all filtered rows. */\n GridApi.prototype.selectAllFiltered = function () {\n this.selectionService.selectAllRowNodes(true);\n };\n /** Clear all filtered selections. */\n GridApi.prototype.deselectAllFiltered = function () {\n this.selectionService.deselectAllRowNodes(true);\n };\n /** @deprecated recomputeAggregates is deprecated, please call api.refreshClientSideRowModel('aggregate') instead */\n GridApi.prototype.recomputeAggregates = function () {\n if (missing(this.clientSideRowModel)) {\n console.warn('cannot call recomputeAggregates unless using normal row model');\n }\n console.warn(\"recomputeAggregates is deprecated, please call api.refreshClientSideRowModel('aggregate') instead\");\n this.clientSideRowModel.refreshModel({ step: ClientSideRowModelSteps.AGGREGATE });\n };\n /**\n * Sets columns to adjust in size to fit the grid horizontally.\n **/\n GridApi.prototype.sizeColumnsToFit = function (params) {\n this.gridBodyCtrl.sizeColumnsToFit(params);\n };\n /** Show the 'loading' overlay. */\n GridApi.prototype.showLoadingOverlay = function () {\n this.overlayWrapperComp.showLoadingOverlay();\n };\n /** Show the 'no rows' overlay. */\n GridApi.prototype.showNoRowsOverlay = function () {\n this.overlayWrapperComp.showNoRowsOverlay();\n };\n /** Hides the overlay if showing. */\n GridApi.prototype.hideOverlay = function () {\n this.overlayWrapperComp.hideOverlay();\n };\n GridApi.prototype.isNodeSelected = function (node) {\n console.warn('AG Grid: no need to call api.isNodeSelected(), just call node.isSelected() instead');\n return node.isSelected();\n };\n /** @deprecated Use getSelectedNodesById no longer exists, use getSelectedNodes(). */\n GridApi.prototype.getSelectedNodesById = function () {\n console.error('AG Grid: since version 3.4, getSelectedNodesById no longer exists, use getSelectedNodes() instead');\n return null;\n };\n /**\n * Returns an unsorted list of selected nodes.\n * Getting the underlying node (rather than the data) is useful when working with tree / aggregated data,\n * as the node can be traversed.\n */\n GridApi.prototype.getSelectedNodes = function () {\n return this.selectionService.getSelectedNodes();\n };\n /** Returns an unsorted list of selected rows (i.e. row data that you provided). */\n GridApi.prototype.getSelectedRows = function () {\n return this.selectionService.getSelectedRows();\n };\n /**\n * Returns a list of all selected nodes at 'best cost', a feature to be used with groups / trees.\n * If a group has all its children selected, then the group appears in the result, but not the children.\n * Designed for use with `'children'` as the group selection type, where groups don't actually appear in the selection normally.\n */\n GridApi.prototype.getBestCostNodeSelection = function () {\n return this.selectionService.getBestCostNodeSelection();\n };\n /** Retrieve rendered nodes. Due to virtualisation this will contain only the current visible rows and those in the buffer. */\n GridApi.prototype.getRenderedNodes = function () {\n return this.rowRenderer.getRenderedNodes();\n };\n /** @deprecated ensureColIndexVisible(index) no longer supported, use ensureColumnVisible(colKey) instead. */\n GridApi.prototype.ensureColIndexVisible = function (index) {\n console.warn('AG Grid: ensureColIndexVisible(index) no longer supported, use ensureColumnVisible(colKey) instead.');\n };\n /**\n * Ensures the column is visible by scrolling the table if needed.\n *\n * This will have no effect before the firstDataRendered event has fired.\n *\n * @param key - The column to ensure visible\n * @param position - Where the column will be positioned.\n * - `auto` - Scrolls the minimum amount to make sure the column is visible.\n * - `start` - Scrolls the column to the start of the viewport.\n * - `middle` - Scrolls the column to the middle of the viewport.\n * - `end` - Scrolls the column to the end of the viewport.\n */\n GridApi.prototype.ensureColumnVisible = function (key, position) {\n if (position === void 0) { position = 'auto'; }\n this.gridBodyCtrl.getScrollFeature().ensureColumnVisible(key, position);\n };\n /**\n * Vertically scrolls the grid until the provided row index is inside the visible viewport.\n * If a position is provided, the grid will attempt to scroll until the row is at the given position within the viewport.\n * This will have no effect before the firstDataRendered event has fired.\n */\n GridApi.prototype.ensureIndexVisible = function (index, position) {\n this.gridBodyCtrl.getScrollFeature().ensureIndexVisible(index, position);\n };\n /**\n * Vertically scrolls the grid until the provided row (or a row matching the provided comparator) is inside the visible viewport.\n * If a position is provided, the grid will attempt to scroll until the row is at the given position within the viewport.\n * This will have no effect before the firstDataRendered event has fired.\n */\n GridApi.prototype.ensureNodeVisible = function (nodeSelector, position) {\n if (position === void 0) { position = null; }\n this.gridBodyCtrl.getScrollFeature().ensureNodeVisible(nodeSelector, position);\n };\n /**\n * Similar to `forEachNode`, except lists all the leaf nodes.\n * This effectively goes through all the data that you provided to the grid before the grid performed any grouping.\n * If using tree data, goes through all the nodes for the data you provided, including nodes that have children,\n * but excluding groups the grid created where gaps were missing in the hierarchy.\n */\n GridApi.prototype.forEachLeafNode = function (callback) {\n if (missing(this.clientSideRowModel)) {\n console.warn('cannot call forEachNode unless using normal row model');\n }\n this.clientSideRowModel.forEachLeafNode(callback);\n };\n /**\n * Iterates through each node (row) in the grid and calls the callback for each node.\n * This works similar to the `forEach` method on a JavaScript array.\n * This is called for every node, ignoring any filtering or sorting applied within the grid.\n * If using the Infinite Row Model, then this gets called for each page loaded in the page cache.\n */\n GridApi.prototype.forEachNode = function (callback) {\n this.rowModel.forEachNode(callback);\n };\n /** Similar to `forEachNode`, except skips any filtered out data. */\n GridApi.prototype.forEachNodeAfterFilter = function (callback) {\n if (missing(this.clientSideRowModel)) {\n console.warn('cannot call forEachNodeAfterFilter unless using normal row model');\n }\n this.clientSideRowModel.forEachNodeAfterFilter(callback);\n };\n /** Similar to `forEachNodeAfterFilter`, except the callbacks are called in the order the rows are displayed in the grid. */\n GridApi.prototype.forEachNodeAfterFilterAndSort = function (callback) {\n if (missing(this.clientSideRowModel)) {\n console.warn('cannot call forEachNodeAfterFilterAndSort unless using normal row model');\n }\n this.clientSideRowModel.forEachNodeAfterFilterAndSort(callback);\n };\n /**\n * Returns the filter component instance for a column.\n * `key` can be a string field name or a ColDef object (matches on object reference, useful if field names are not unique).\n * If your filter is created asynchronously, `getFilterInstance` will return `null` so you will need to use the `callback` to access the filter instance instead.\n */\n GridApi.prototype.getFilterInstance = function (key, callback) {\n var res = this.getFilterInstanceImpl(key, function (instance) {\n if (!callback) {\n return;\n }\n var unwrapped = unwrapUserComp(instance);\n callback(unwrapped);\n });\n var unwrapped = unwrapUserComp(res);\n return unwrapped;\n };\n GridApi.prototype.getFilterInstanceImpl = function (key, callback) {\n var column = this.columnModel.getPrimaryColumn(key);\n if (!column) {\n return undefined;\n }\n var filterPromise = this.filterManager.getFilterComponent(column, 'NO_UI');\n var currentValue = filterPromise && filterPromise.resolveNow(null, function (filterComp) { return filterComp; });\n if (currentValue) {\n setTimeout(callback, 0, currentValue);\n }\n else if (filterPromise) {\n filterPromise.then(function (comp) {\n callback(comp);\n });\n }\n return currentValue;\n };\n /** Destroys a filter. Useful to force a particular filter to be created from scratch again. */\n GridApi.prototype.destroyFilter = function (key) {\n var column = this.columnModel.getPrimaryColumn(key);\n if (column) {\n return this.filterManager.destroyFilter(column, \"filterDestroyed\");\n }\n };\n /** Gets the status panel instance corresponding to the supplied `id`. */\n GridApi.prototype.getStatusPanel = function (key) {\n if (!this.statusBarService) {\n return;\n }\n var comp = this.statusBarService.getStatusPanel(key);\n return unwrapUserComp(comp);\n };\n GridApi.prototype.getColumnDef = function (key) {\n var column = this.columnModel.getPrimaryColumn(key);\n if (column) {\n return column.getColDef();\n }\n return null;\n };\n /**\n * Returns the current column definitions.\n */\n GridApi.prototype.getColumnDefs = function () { return this.columnModel.getColumnDefs(); };\n /** Informs the grid that a filter has changed. This is typically called after a filter change through one of the filter APIs. */\n GridApi.prototype.onFilterChanged = function () {\n this.filterManager.onFilterChanged();\n };\n /**\n * Gets the grid to act as if the sort was changed.\n * Useful if you update some values and want to get the grid to reorder them according to the new values.\n */\n GridApi.prototype.onSortChanged = function () {\n this.sortController.onSortChanged('api');\n };\n /** Sets the state of all the advanced filters. Provide it with what you get from `getFilterModel()` to restore filter state. */\n GridApi.prototype.setFilterModel = function (model) {\n this.filterManager.setFilterModel(model);\n };\n /** Gets the current state of all the advanced filters. Used for saving filter state. */\n GridApi.prototype.getFilterModel = function () {\n return this.filterManager.getFilterModel();\n };\n /** Returns the focused cell (or the last focused cell if the grid lost focus). */\n GridApi.prototype.getFocusedCell = function () {\n return this.focusService.getFocusedCell();\n };\n /** Clears the focused cell. */\n GridApi.prototype.clearFocusedCell = function () {\n return this.focusService.clearFocusedCell();\n };\n /** Sets the focus to the specified cell. `rowPinned` can be either 'top', 'bottom' or null (for not pinned). */\n GridApi.prototype.setFocusedCell = function (rowIndex, colKey, rowPinned) {\n this.focusService.setFocusedCell({ rowIndex: rowIndex, column: colKey, rowPinned: rowPinned, forceBrowserFocus: true });\n };\n /** Sets the `suppressRowDrag` property. */\n GridApi.prototype.setSuppressRowDrag = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_SUPPRESS_ROW_DRAG, value);\n };\n /** Sets the `suppressMoveWhenRowDragging` property. */\n GridApi.prototype.setSuppressMoveWhenRowDragging = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_SUPPRESS_MOVE_WHEN_ROW_DRAG, value);\n };\n /** Sets the `suppressRowClickSelection` property. */\n GridApi.prototype.setSuppressRowClickSelection = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_SUPPRESS_ROW_CLICK_SELECTION, value);\n };\n /** Adds a drop zone outside of the grid where rows can be dropped. */\n GridApi.prototype.addRowDropZone = function (params) {\n this.gridBodyCtrl.getRowDragFeature().addRowDropZone(params);\n };\n /** Removes an external drop zone added by `addRowDropZone`. */\n GridApi.prototype.removeRowDropZone = function (params) {\n var activeDropTarget = this.dragAndDropService.findExternalZone(params);\n if (activeDropTarget) {\n this.dragAndDropService.removeDropTarget(activeDropTarget);\n }\n };\n /** Returns the `RowDropZoneParams` to be used by another grid's `addRowDropZone` method. */\n GridApi.prototype.getRowDropZoneParams = function (events) {\n return this.gridBodyCtrl.getRowDragFeature().getRowDropZone(events);\n };\n /** Sets the height in pixels for the row containing the column label header. */\n GridApi.prototype.setHeaderHeight = function (headerHeight) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_HEADER_HEIGHT, headerHeight);\n };\n /**\n * Switch between layout options: `normal`, `autoHeight`, `print`.\n * Defaults to `normal` if no domLayout provided.\n */\n GridApi.prototype.setDomLayout = function (domLayout) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_DOM_LAYOUT, domLayout);\n };\n /** Sets the `enableCellTextSelection` property. */\n GridApi.prototype.setEnableCellTextSelection = function (selectable) {\n this.gridBodyCtrl.setCellTextSelection(selectable);\n };\n /** Sets the preferred direction for the selection fill handle. */\n GridApi.prototype.setFillHandleDirection = function (direction) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_FILL_HANDLE_DIRECTION, direction);\n };\n /** Sets the height in pixels for the rows containing header column groups. */\n GridApi.prototype.setGroupHeaderHeight = function (headerHeight) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT, headerHeight);\n };\n /** Sets the height in pixels for the row containing the floating filters. */\n GridApi.prototype.setFloatingFiltersHeight = function (headerHeight) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT, headerHeight);\n };\n /** Sets the height in pixels for the row containing the columns when in pivot mode. */\n GridApi.prototype.setPivotHeaderHeight = function (headerHeight) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT, headerHeight);\n };\n /** Sets the height in pixels for the row containing header column groups when in pivot mode. */\n GridApi.prototype.setPivotGroupHeaderHeight = function (headerHeight) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT, headerHeight);\n };\n GridApi.prototype.setIsExternalFilterPresent = function (isExternalFilterPresentFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_EXTERNAL_FILTER_PRESENT, isExternalFilterPresentFunc);\n };\n GridApi.prototype.setDoesExternalFilterPass = function (doesExternalFilterPassFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_DOES_EXTERNAL_FILTER_PASS, doesExternalFilterPassFunc);\n };\n GridApi.prototype.setNavigateToNextCell = function (navigateToNextCellFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_NAVIGATE_TO_NEXT_CELL, navigateToNextCellFunc);\n };\n GridApi.prototype.setTabToNextCell = function (tabToNextCellFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_TAB_TO_NEXT_CELL, tabToNextCellFunc);\n };\n GridApi.prototype.setTabToNextHeader = function (tabToNextHeaderFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_TAB_TO_NEXT_HEADER, tabToNextHeaderFunc);\n };\n GridApi.prototype.setNavigateToNextHeader = function (navigateToNextHeaderFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_NAVIGATE_TO_NEXT_HEADER, navigateToNextHeaderFunc);\n };\n GridApi.prototype.setGroupRowAggNodes = function (groupRowAggNodesFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GROUP_ROW_AGG_NODES, groupRowAggNodesFunc);\n };\n GridApi.prototype.setGetGroupRowAgg = function (getGroupRowAggFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_GROUP_ROW_AGG, getGroupRowAggFunc);\n };\n GridApi.prototype.setGetBusinessKeyForNode = function (getBusinessKeyForNodeFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_BUSINESS_KEY_FOR_NODE, getBusinessKeyForNodeFunc);\n };\n GridApi.prototype.setGetChildCount = function (getChildCountFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_CHILD_COUNT, getChildCountFunc);\n };\n GridApi.prototype.setProcessRowPostCreate = function (processRowPostCreateFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PROCESS_ROW_POST_CREATE, processRowPostCreateFunc);\n };\n GridApi.prototype.setGetRowNodeId = function (getRowNodeIdFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_ROW_NODE_ID, getRowNodeIdFunc);\n };\n GridApi.prototype.setGetRowId = function (getRowIdFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_ROW_ID, getRowIdFunc);\n };\n GridApi.prototype.setGetRowClass = function (rowClassFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_ROW_CLASS, rowClassFunc);\n };\n GridApi.prototype.setIsFullWidthCell = function (isFullWidthCellFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_FULL_WIDTH_CELL, isFullWidthCellFunc);\n };\n GridApi.prototype.setIsFullWidthRow = function (isFullWidthRowFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_FULL_WIDTH_ROW, isFullWidthRowFunc);\n };\n GridApi.prototype.setIsRowSelectable = function (isRowSelectableFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_ROW_SELECTABLE, isRowSelectableFunc);\n };\n GridApi.prototype.setIsRowMaster = function (isRowMasterFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_ROW_MASTER, isRowMasterFunc);\n };\n GridApi.prototype.setPostSort = function (postSortFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_POST_SORT, postSortFunc);\n };\n GridApi.prototype.setPostSortRows = function (postSortRowsFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_POST_SORT_ROWS, postSortRowsFunc);\n };\n GridApi.prototype.setGetDocument = function (getDocumentFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_DOCUMENT, getDocumentFunc);\n };\n GridApi.prototype.setGetContextMenuItems = function (getContextMenuItemsFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_CONTEXT_MENU_ITEMS, getContextMenuItemsFunc);\n };\n GridApi.prototype.setGetMainMenuItems = function (getMainMenuItemsFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_MAIN_MENU_ITEMS, getMainMenuItemsFunc);\n };\n GridApi.prototype.setProcessCellForClipboard = function (processCellForClipboardFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PROCESS_CELL_FOR_CLIPBOARD, processCellForClipboardFunc);\n };\n GridApi.prototype.setSendToClipboard = function (sendToClipboardFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_SEND_TO_CLIPBOARD, sendToClipboardFunc);\n };\n GridApi.prototype.setProcessCellFromClipboard = function (processCellFromClipboardFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PROCESS_CELL_FROM_CLIPBOARD, processCellFromClipboardFunc);\n };\n /** @deprecated use `setProcessPivotResultColDef` instead */\n GridApi.prototype.setProcessSecondaryColDef = function (processSecondaryColDefFunc) {\n console.warn('AG Grid: since version 28.0.x setProcessSecondaryColDef has been renamed, please use setProcessPivotResultColDef instead');\n this.setProcessPivotResultColDef(processSecondaryColDefFunc);\n };\n /** @deprecated use `setProcessPivotResultColGroupDef` instead */\n GridApi.prototype.setProcessSecondaryColGroupDef = function (processSecondaryColGroupDefFunc) {\n console.warn('AG Grid: since version 28.0.x setProcessSecondaryColGroupDef has been renamed, please use setProcessPivotResultColGroupDef instead');\n this.setProcessPivotResultColGroupDef(processSecondaryColGroupDefFunc);\n };\n GridApi.prototype.setProcessPivotResultColDef = function (processPivotResultColDefFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PROCESS_PIVOT_RESULT_COL_DEF, processPivotResultColDefFunc);\n };\n GridApi.prototype.setProcessPivotResultColGroupDef = function (processPivotResultColGroupDefFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PROCESS_PIVOT_RESULT_COL_GROUP_DEF, processPivotResultColGroupDefFunc);\n };\n GridApi.prototype.setPostProcessPopup = function (postProcessPopupFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_POST_PROCESS_POPUP, postProcessPopupFunc);\n };\n GridApi.prototype.setDefaultGroupOrderComparator = function (defaultGroupOrderComparatorFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_DEFAULT_GROUP_ORDER_COMPARATOR, defaultGroupOrderComparatorFunc);\n };\n GridApi.prototype.setInitialGroupOrderComparator = function (initialGroupOrderComparatorFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_INITIAL_GROUP_ORDER_COMPARATOR, initialGroupOrderComparatorFunc);\n };\n GridApi.prototype.setGetChartToolbarItems = function (getChartToolbarItemsFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_CHART_TOOLBAR_ITEMS, getChartToolbarItemsFunc);\n };\n GridApi.prototype.setPaginationNumberFormatter = function (paginationNumberFormatterFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_PAGINATION_NUMBER_FORMATTER, paginationNumberFormatterFunc);\n };\n /** @deprecated use setGetServerSideGroupLevelParams instead */\n GridApi.prototype.setGetServerSideStoreParams = function (getServerSideStoreParamsFunc) {\n this.setGetServerSideGroupLevelParams(getServerSideStoreParamsFunc);\n };\n GridApi.prototype.setGetServerSideGroupLevelParams = function (getServerSideGroupLevelParamsFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_SERVER_SIDE_GROUP_PARAMS, getServerSideGroupLevelParamsFunc);\n };\n GridApi.prototype.setIsServerSideGroupOpenByDefault = function (isServerSideGroupOpenByDefaultFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_SERVER_SIDE_GROUPS_OPEN_BY_DEFAULT, isServerSideGroupOpenByDefaultFunc);\n };\n GridApi.prototype.setIsApplyServerSideTransaction = function (isApplyServerSideTransactionFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_APPLY_SERVER_SIDE_TRANSACTION, isApplyServerSideTransactionFunc);\n };\n GridApi.prototype.setIsServerSideGroup = function (isServerSideGroupFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_IS_SERVER_SIDE_GROUP, isServerSideGroupFunc);\n };\n GridApi.prototype.setGetServerSideGroupKey = function (getServerSideGroupKeyFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_SERVER_SIDE_GROUP_KEY, getServerSideGroupKeyFunc);\n };\n GridApi.prototype.setGetRowStyle = function (rowStyleFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_ROW_STYLE, rowStyleFunc);\n };\n GridApi.prototype.setGetRowHeight = function (rowHeightFunc) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GET_ROW_HEIGHT, rowHeightFunc);\n };\n /** Returns `true` if the side bar is visible. */\n GridApi.prototype.isSideBarVisible = function () {\n return this.sideBarComp ? this.sideBarComp.isDisplayed() : false;\n };\n /** Show/hide the entire side bar, including any visible panel and the tab buttons. */\n GridApi.prototype.setSideBarVisible = function (show) {\n if (!this.sideBarComp) {\n if (show) {\n console.warn('AG Grid: sideBar is not loaded');\n }\n return;\n }\n this.sideBarComp.setDisplayed(show);\n };\n /** Sets the side bar position relative to the grid. Possible values are `'left'` or `'right'`. */\n GridApi.prototype.setSideBarPosition = function (position) {\n if (!this.sideBarComp) {\n console.warn('AG Grid: sideBar is not loaded');\n return;\n }\n this.sideBarComp.setSideBarPosition(position);\n };\n /** Opens a particular tool panel. Provide the ID of the tool panel to open. */\n GridApi.prototype.openToolPanel = function (key) {\n if (!this.sideBarComp) {\n console.warn('AG Grid: toolPanel is only available in AG Grid Enterprise');\n return;\n }\n this.sideBarComp.openToolPanel(key);\n };\n /** Closes the currently open tool panel (if any). */\n GridApi.prototype.closeToolPanel = function () {\n if (!this.sideBarComp) {\n console.warn('AG Grid: toolPanel is only available in AG Grid Enterprise');\n return;\n }\n this.sideBarComp.close();\n };\n /** Returns the ID of the currently shown tool panel if any, otherwise `null`. */\n GridApi.prototype.getOpenedToolPanel = function () {\n return this.sideBarComp ? this.sideBarComp.openedItem() : null;\n };\n /** Returns the current side bar configuration. If a shortcut was used, returns the detailed long form. */\n GridApi.prototype.getSideBar = function () {\n return this.gridOptionsWrapper.getSideBar();\n };\n /** Resets the side bar to the provided configuration. The parameter is the same as the sideBar grid property. The side bar is re-created from scratch with the new config. */\n GridApi.prototype.setSideBar = function (def) {\n this.gridOptionsWrapper.setProperty('sideBar', SideBarDefParser.parse(def));\n };\n GridApi.prototype.setSuppressClipboardPaste = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_SUPPRESS_CLIPBOARD_PASTE, value);\n };\n /** Returns `true` if the tool panel is showing, otherwise `false`. */\n GridApi.prototype.isToolPanelShowing = function () {\n return this.sideBarComp.isToolPanelShowing();\n };\n /** @deprecated AG Grid - since version 25.1, doLayout was taken out, as it's not needed. The grid responds to grid size changes automatically. */\n GridApi.prototype.doLayout = function () {\n var message = \"AG Grid - since version 25.1, doLayout was taken out, as it's not needed. The grid responds to grid size changes automatically\";\n doOnce(function () { return console.warn(message); }, 'doLayoutDeprecated');\n };\n /** Tells the grid to recalculate the row heights. */\n GridApi.prototype.resetRowHeights = function () {\n if (exists(this.clientSideRowModel)) {\n if (this.columnModel.isAutoRowHeightActive()) {\n console.warn('AG Grid: calling gridApi.resetRowHeights() makes no sense when using Auto Row Height.');\n return;\n }\n this.clientSideRowModel.resetRowHeights();\n }\n };\n GridApi.prototype.setGroupRemoveSingleChildren = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GROUP_REMOVE_SINGLE_CHILDREN, value);\n };\n GridApi.prototype.setGroupRemoveLowestSingleChildren = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GROUP_REMOVE_LOWEST_SINGLE_CHILDREN, value);\n };\n GridApi.prototype.setGroupDisplayType = function (value) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_GROUP_DISPLAY_TYPE, value);\n };\n /** Tells the grid a row height has changed. To be used after calling `rowNode.setRowHeight(newHeight)`. */\n GridApi.prototype.onRowHeightChanged = function () {\n if (this.clientSideRowModel) {\n this.clientSideRowModel.onRowHeightChanged();\n }\n else if (this.serverSideRowModel) {\n this.serverSideRowModel.onRowHeightChanged();\n }\n };\n /**\n * Gets the value for a column for a particular `rowNode` (row).\n * This is useful if you want the raw value of a cell e.g. if implementing your own CSV export.\n */\n GridApi.prototype.getValue = function (colKey, rowNode) {\n var column = this.columnModel.getPrimaryColumn(colKey);\n if (missing(column)) {\n column = this.columnModel.getGridColumn(colKey);\n }\n if (missing(column)) {\n return null;\n }\n return this.valueService.getValue(column, rowNode);\n };\n /** Add an event listener for the specified `eventType`. Works similar to `addEventListener` for a browser DOM element. */\n GridApi.prototype.addEventListener = function (eventType, listener) {\n var async = this.gridOptionsWrapper.useAsyncEvents();\n this.eventService.addEventListener(eventType, listener, async);\n };\n /** Add an event listener for all event types coming from the grid. */\n GridApi.prototype.addGlobalListener = function (listener) {\n var async = this.gridOptionsWrapper.useAsyncEvents();\n this.eventService.addGlobalListener(listener, async);\n };\n /** Remove an event listener. */\n GridApi.prototype.removeEventListener = function (eventType, listener) {\n var async = this.gridOptionsWrapper.useAsyncEvents();\n this.eventService.removeEventListener(eventType, listener, async);\n };\n /** Remove a global event listener. */\n GridApi.prototype.removeGlobalListener = function (listener) {\n var async = this.gridOptionsWrapper.useAsyncEvents();\n this.eventService.removeGlobalListener(listener, async);\n };\n GridApi.prototype.dispatchEvent = function (event) {\n this.eventService.dispatchEvent(event);\n };\n /** Will destroy the grid and release resources. If you are using a framework you do not need to call this, as the grid links in with the framework lifecycle. However if you are using Web Components or native JavaScript, you do need to call this, to avoid a memory leak in your application. */\n GridApi.prototype.destroy = function () {\n // this is needed as GridAPI is a bean, and GridAPI.destroy() is called as part\n // of context.destroy(). so we need to stop the infinite loop.\n if (this.destroyCalled) {\n return;\n }\n this.destroyCalled = true;\n // destroy the UI first (as they use the services)\n var gridCtrl = this.ctrlsService.getGridCtrl();\n if (gridCtrl) {\n gridCtrl.destroyGridUi();\n }\n // destroy the services\n this.context.destroy();\n };\n GridApi.prototype.cleanDownReferencesToAvoidMemoryLeakInCaseApplicationIsKeepingReferenceToDestroyedGrid = function () {\n // some users were raising support issues with regards memory leaks. the problem was the customers applications\n // were keeping references to the API. trying to educate them all would be difficult, easier to just remove\n // all references in the API so at least the core grid can be garbage collected.\n //\n // wait about 100ms before clearing down the references, in case user has some cleanup to do,\n // and needs to deference the API first\n setTimeout(removeAllReferences.bind(window, this, 'Grid API'), 100);\n };\n GridApi.prototype.warnIfDestroyed = function (methodName) {\n if (this.destroyCalled) {\n console.warn(\"AG Grid: Grid API method \" + methodName + \" was called on a grid that was destroyed.\");\n }\n return this.destroyCalled;\n };\n /** Reset the quick filter cache text on every rowNode. */\n GridApi.prototype.resetQuickFilter = function () {\n if (this.warnIfDestroyed('resetQuickFilter')) {\n return;\n }\n this.rowModel.forEachNode(function (node) { return node.quickFilterAggregateText = null; });\n };\n /** @deprecated AG Grid: in v20.1.x, api.getRangeSelections() is gone, please use getCellRanges() instead. */\n GridApi.prototype.getRangeSelections = function () {\n console.warn(\"AG Grid: in v20.1.x, api.getRangeSelections() is gone, please use getCellRanges() instead.\\n We had to change how cell selections works a small bit to allow charting to integrate. The return type of\\n getCellRanges() is a bit different, please check the AG Grid documentation.\");\n return null;\n };\n /** Returns the list of selected cell ranges. */\n GridApi.prototype.getCellRanges = function () {\n if (this.rangeService) {\n return this.rangeService.getCellRanges();\n }\n console.warn('AG Grid: cell range selection is only available in AG Grid Enterprise');\n return null;\n };\n GridApi.prototype.camelCaseToHumanReadable = function (camelCase) {\n return camelCaseToHumanText(camelCase);\n };\n /** @deprecated AG Grid: As of version 21.x, range selection changed slightly to allow charting integration. Please call api.addCellRange() instead of api.addRangeSelection() */\n GridApi.prototype.addRangeSelection = function (deprecatedNoLongerUsed) {\n console.warn('AG Grid: As of version 21.x, range selection changed slightly to allow charting integration. Please call api.addCellRange() instead of api.addRangeSelection()');\n };\n /** Adds the provided cell range to the selected ranges. */\n GridApi.prototype.addCellRange = function (params) {\n if (!this.rangeService) {\n console.warn('AG Grid: cell range selection is only available in AG Grid Enterprise');\n }\n this.rangeService.addCellRange(params);\n };\n /** Clears the selected ranges. */\n GridApi.prototype.clearRangeSelection = function () {\n if (!this.rangeService) {\n console.warn('AG Grid: cell range selection is only available in AG Grid Enterprise');\n }\n this.rangeService.removeAllCellRanges();\n };\n /** Reverts the last cell edit. */\n GridApi.prototype.undoCellEditing = function () {\n this.undoRedoService.undo();\n };\n /** Re-applies the most recently undone cell edit. */\n GridApi.prototype.redoCellEditing = function () {\n this.undoRedoService.redo();\n };\n /** Returns current number of available cell edit undo operations. */\n GridApi.prototype.getCurrentUndoSize = function () {\n return this.undoRedoService.getCurrentUndoStackSize();\n };\n /** Returns current number of available cell edit redo operations. */\n GridApi.prototype.getCurrentRedoSize = function () {\n return this.undoRedoService.getCurrentRedoStackSize();\n };\n /** Returns a list of models with information about the charts that are currently rendered from the grid. */\n GridApi.prototype.getChartModels = function () {\n if (ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'api.getChartModels') &&\n ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.getChartModels')) {\n return this.chartService.getChartModels();\n }\n };\n /** Returns the `ChartRef` using the supplied `chartId`. */\n GridApi.prototype.getChartRef = function (chartId) {\n if (ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'api.getChartRef') &&\n ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.getChartRef')) {\n return this.chartService.getChartRef(chartId);\n }\n };\n /** Returns a string containing the requested data URL which contains a representation of the chart image. */\n GridApi.prototype.getChartImageDataURL = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.getChartImageDataURL')) {\n return this.chartService.getChartImageDataURL(params);\n }\n };\n /** Downloads the chart image in the browser. */\n GridApi.prototype.downloadChart = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.downloadChart')) {\n return this.chartService.downloadChart(params);\n }\n };\n /** Open the Chart Tool Panel. */\n GridApi.prototype.openChartToolPanel = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.openChartToolPanel')) {\n return this.chartService.openChartToolPanel(params);\n }\n };\n /** Close the Chart Tool Panel. */\n GridApi.prototype.closeChartToolPanel = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.closeChartToolPanel')) {\n return this.chartService.closeChartToolPanel(params.chartId);\n }\n };\n /** Used to programmatically create charts from a range. */\n GridApi.prototype.createRangeChart = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'api.createRangeChart') &&\n ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.createRangeChart')) {\n return this.chartService.createRangeChart(params);\n }\n };\n /** Used to programmatically create cross filter charts from a range. */\n GridApi.prototype.createCrossFilterChart = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'api.createCrossFilterChart') &&\n ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.createCrossFilterChart')) {\n return this.chartService.createCrossFilterChart(params);\n }\n };\n /** Restores a chart using the `ChartModel` that was previously obtained from `getChartModels()`. */\n GridApi.prototype.restoreChart = function (chartModel, chartContainer) {\n if (ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'api.restoreChart') &&\n ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.restoreChart')) {\n return this.chartService.restoreChart(chartModel, chartContainer);\n }\n };\n /** Used to programmatically create pivot charts from a grid. */\n GridApi.prototype.createPivotChart = function (params) {\n if (ModuleRegistry.assertRegistered(ModuleNames.RangeSelectionModule, 'api.createPivotChart') &&\n ModuleRegistry.assertRegistered(ModuleNames.GridChartsModule, 'api.createPivotChart')) {\n return this.chartService.createPivotChart(params);\n }\n };\n /** Copies data to clipboard by following the same rules as pressing Ctrl+C. */\n GridApi.prototype.copyToClipboard = function (params) {\n if (!this.clipboardService) {\n console.warn('AG Grid: clipboard is only available in AG Grid Enterprise');\n }\n this.clipboardService.copyToClipboard(params);\n };\n /** Copies the selected rows to the clipboard. */\n GridApi.prototype.copySelectedRowsToClipboard = function (params) {\n if (!this.clipboardService) {\n console.warn('AG Grid: clipboard is only available in AG Grid Enterprise');\n }\n this.clipboardService.copySelectedRowsToClipboard(params);\n };\n /** Copies the selected ranges to the clipboard. */\n GridApi.prototype.copySelectedRangeToClipboard = function (params) {\n if (!this.clipboardService) {\n console.warn('AG Grid: clipboard is only available in AG Grid Enterprise');\n }\n this.clipboardService.copySelectedRangeToClipboard(params);\n };\n /** Copies the selected range down, similar to `Ctrl + D` in Excel. */\n GridApi.prototype.copySelectedRangeDown = function () {\n if (!this.clipboardService) {\n console.warn('AG Grid: clipboard is only available in AG Grid Enterprise');\n }\n this.clipboardService.copyRangeDown();\n };\n /** Shows the column menu after and positions it relative to the provided button element. Use in conjunction with your own header template. */\n GridApi.prototype.showColumnMenuAfterButtonClick = function (colKey, buttonElement) {\n // use grid column so works with pivot mode\n var column = this.columnModel.getGridColumn(colKey);\n this.menuFactory.showMenuAfterButtonClick(column, buttonElement, 'columnMenu');\n };\n /** Shows the column menu after and positions it relative to the mouse event. Use in conjunction with your own header template. */\n GridApi.prototype.showColumnMenuAfterMouseClick = function (colKey, mouseEvent) {\n // use grid column so works with pivot mode\n var column = this.columnModel.getGridColumn(colKey);\n if (!column) {\n column = this.columnModel.getPrimaryColumn(colKey);\n }\n if (!column) {\n console.error(\"AG Grid: column '\" + colKey + \"' not found\");\n return;\n }\n this.menuFactory.showMenuAfterMouseEvent(column, mouseEvent);\n };\n /** Hides any visible context menu or column menu. */\n GridApi.prototype.hidePopupMenu = function () {\n // hide the context menu if in enterprise\n if (this.contextMenuFactory) {\n this.contextMenuFactory.hideActiveMenu();\n }\n // and hide the column menu always\n this.menuFactory.hideActiveMenu();\n };\n /** DOM element to use as the popup parent for grid popups (context menu, column menu etc). */\n GridApi.prototype.setPopupParent = function (ePopupParent) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_POPUP_PARENT, ePopupParent);\n };\n /** Navigates the grid focus to the next cell, as if tabbing. */\n GridApi.prototype.tabToNextCell = function (event) {\n return this.navigationService.tabToNextCell(false, event);\n };\n /** Navigates the grid focus to the previous cell, as if shift-tabbing. */\n GridApi.prototype.tabToPreviousCell = function (event) {\n return this.navigationService.tabToNextCell(true, event);\n };\n /** Returns the list of active cell renderer instances. */\n GridApi.prototype.getCellRendererInstances = function (params) {\n if (params === void 0) { params = {}; }\n var res = this.rowRenderer.getCellRendererInstances(params);\n var unwrapped = res.map(unwrapUserComp);\n return unwrapped;\n };\n /** Returns the list of active cell editor instances. Optionally provide parameters to restrict to certain columns / row nodes. */\n GridApi.prototype.getCellEditorInstances = function (params) {\n if (params === void 0) { params = {}; }\n var res = this.rowRenderer.getCellEditorInstances(params);\n var unwrapped = res.map(unwrapUserComp);\n return unwrapped;\n };\n /** If the grid is editing, returns back details of the editing cell(s). */\n GridApi.prototype.getEditingCells = function () {\n return this.rowRenderer.getEditingCells();\n };\n /** If a cell is editing, it stops the editing. Pass `true` if you want to cancel the editing (i.e. don't accept changes). */\n GridApi.prototype.stopEditing = function (cancel) {\n if (cancel === void 0) { cancel = false; }\n this.rowRenderer.stopEditing(cancel);\n };\n /** Start editing the provided cell. If another cell is editing, the editing will be stopped in that other cell. */\n GridApi.prototype.startEditingCell = function (params) {\n var column = this.columnModel.getGridColumn(params.colKey);\n if (!column) {\n console.warn(\"AG Grid: no column found for \" + params.colKey);\n return;\n }\n var cellPosition = {\n rowIndex: params.rowIndex,\n rowPinned: params.rowPinned || null,\n column: column\n };\n var notPinned = params.rowPinned == null;\n if (notPinned) {\n this.gridBodyCtrl.getScrollFeature().ensureIndexVisible(params.rowIndex);\n }\n var cell = this.navigationService.getCellByPosition(cellPosition);\n if (!cell) {\n return;\n }\n cell.startRowOrCellEdit(params.key, params.charPress);\n };\n /** Add an aggregation function with the specified key. */\n GridApi.prototype.addAggFunc = function (key, aggFunc) {\n if (this.aggFuncService) {\n this.aggFuncService.addAggFunc(key, aggFunc);\n }\n };\n /** Add aggregations function with the specified keys. */\n GridApi.prototype.addAggFuncs = function (aggFuncs) {\n if (this.aggFuncService) {\n this.aggFuncService.addAggFuncs(aggFuncs);\n }\n };\n /** Clears all aggregation functions (including those provided by the grid). */\n GridApi.prototype.clearAggFuncs = function () {\n if (this.aggFuncService) {\n this.aggFuncService.clear();\n }\n };\n /** Apply transactions to the server side row model. */\n GridApi.prototype.applyServerSideTransaction = function (transaction) {\n if (!this.serverSideTransactionManager) {\n console.warn('AG Grid: Cannot apply Server Side Transaction if not using the Server Side Row Model.');\n return;\n }\n return this.serverSideTransactionManager.applyTransaction(transaction);\n };\n GridApi.prototype.applyServerSideTransactionAsync = function (transaction, callback) {\n if (!this.serverSideTransactionManager) {\n console.warn('AG Grid: Cannot apply Server Side Transaction if not using the Server Side Row Model.');\n return;\n }\n return this.serverSideTransactionManager.applyTransactionAsync(transaction, callback);\n };\n /** Gets all failed server side loads to retry. */\n GridApi.prototype.retryServerSideLoads = function () {\n if (!this.serverSideRowModel) {\n console.warn('AG Grid: API retryServerSideLoads() can only be used when using Server-Side Row Model.');\n return;\n }\n this.serverSideRowModel.retryLoads();\n };\n GridApi.prototype.flushServerSideAsyncTransactions = function () {\n if (!this.serverSideTransactionManager) {\n console.warn('AG Grid: Cannot flush Server Side Transaction if not using the Server Side Row Model.');\n return;\n }\n return this.serverSideTransactionManager.flushAsyncTransactions();\n };\n /** Update row data. Pass a transaction object with lists for `add`, `remove` and `update`. */\n GridApi.prototype.applyTransaction = function (rowDataTransaction) {\n if (!this.clientSideRowModel) {\n console.error('AG Grid: updateRowData() only works with ClientSideRowModel. Working with InfiniteRowModel was deprecated in v23.1 and removed in v24.1');\n return;\n }\n var res = this.clientSideRowModel.updateRowData(rowDataTransaction);\n // refresh all the full width rows\n this.rowRenderer.refreshFullWidthRows(res.update);\n // do change detection for all present cells\n if (!this.gridOptionsWrapper.isSuppressChangeDetection()) {\n this.rowRenderer.refreshCells();\n }\n return res;\n };\n /** Sets the `deltaSort` property */\n GridApi.prototype.setDeltaSort = function (enable) {\n this.gridOptionsWrapper.setProperty('deltaSort', enable);\n };\n /** @deprecated AG Grid: as of v23.1, grid API updateRowData(transaction) is now called applyTransaction(transaction). */\n GridApi.prototype.updateRowData = function (rowDataTransaction) {\n var message = 'AG Grid: as of v23.1, grid API updateRowData(transaction) is now called applyTransaction(transaction). updateRowData is deprecated and will be removed in a future major release.';\n doOnce(function () { return console.warn(message); }, 'updateRowData deprecated');\n return this.applyTransaction(rowDataTransaction);\n };\n /** Same as `applyTransaction` except executes asynchronously for efficiency. */\n GridApi.prototype.applyTransactionAsync = function (rowDataTransaction, callback) {\n if (!this.clientSideRowModel) {\n console.error('AG Grid: api.applyTransactionAsync() only works with ClientSideRowModel.');\n return;\n }\n this.clientSideRowModel.batchUpdateRowData(rowDataTransaction, callback);\n };\n /** Executes any remaining asynchronous grid transactions, if any are waiting to be executed. */\n GridApi.prototype.flushAsyncTransactions = function () {\n if (!this.clientSideRowModel) {\n console.error('AG Grid: api.applyTransactionAsync() only works with ClientSideRowModel.');\n return;\n }\n this.clientSideRowModel.flushAsyncTransactions();\n };\n /** @deprecated AG Grid: as of v23.1, grid API batchUpdateRowData(transaction, callback) is now called applyTransactionAsync(transaction, callback). */\n GridApi.prototype.batchUpdateRowData = function (rowDataTransaction, callback) {\n var message = 'AG Grid: as of v23.1, grid API batchUpdateRowData(transaction, callback) is now called applyTransactionAsync(transaction, callback). batchUpdateRowData is deprecated and will be removed in a future major release.';\n doOnce(function () { return console.warn(message); }, 'batchUpdateRowData deprecated');\n this.applyTransactionAsync(rowDataTransaction, callback);\n };\n /** @deprecated AG Grid: insertItemsAtIndex() is deprecated, use updateRowData(transaction) instead.*/\n GridApi.prototype.insertItemsAtIndex = function (index, items, skipRefresh) {\n console.warn('AG Grid: insertItemsAtIndex() is deprecated, use updateRowData(transaction) instead.');\n this.updateRowData({ add: items, addIndex: index, update: null, remove: null });\n };\n /** @deprecated AG Grid: removeItems() is deprecated, use updateRowData(transaction) instead. */\n GridApi.prototype.removeItems = function (rowNodes, skipRefresh) {\n console.warn('AG Grid: removeItems() is deprecated, use updateRowData(transaction) instead.');\n var dataToRemove = rowNodes.map(function (rowNode) { return rowNode.data; });\n this.updateRowData({ add: null, addIndex: null, update: null, remove: dataToRemove });\n };\n /** @deprecated AG Grid: addItems() is deprecated, use updateRowData(transaction) instead. */\n GridApi.prototype.addItems = function (items, skipRefresh) {\n console.warn('AG Grid: addItems() is deprecated, use updateRowData(transaction) instead.');\n this.updateRowData({ add: items, addIndex: null, update: null, remove: null });\n };\n /** @deprecated AG Grid: refreshVirtualPageCache() is now called refreshInfiniteCache(), please call refreshInfiniteCache() instead */\n GridApi.prototype.refreshVirtualPageCache = function () {\n console.warn('AG Grid: refreshVirtualPageCache() is now called refreshInfiniteCache(), please call refreshInfiniteCache() instead');\n this.refreshInfiniteCache();\n };\n /** @deprecated AG Grid: refreshInfinitePageCache() is now called refreshInfiniteCache(), please call refreshInfiniteCache() instead */\n GridApi.prototype.refreshInfinitePageCache = function () {\n console.warn('AG Grid: refreshInfinitePageCache() is now called refreshInfiniteCache(), please call refreshInfiniteCache() instead');\n this.refreshInfiniteCache();\n };\n /**\n * Marks all the currently loaded blocks in the cache for reload.\n * If you have 10 blocks in the cache, all 10 will be marked for reload.\n * The old data will continue to be displayed until the new data is loaded.\n */\n GridApi.prototype.refreshInfiniteCache = function () {\n if (this.infiniteRowModel) {\n this.infiniteRowModel.refreshCache();\n }\n else {\n console.warn(\"AG Grid: api.refreshInfiniteCache is only available when rowModelType='infinite'.\");\n }\n };\n /** @deprecated AG Grid: purgeVirtualPageCache() is now called purgeInfiniteCache(), please call purgeInfiniteCache() instead */\n GridApi.prototype.purgeVirtualPageCache = function () {\n console.warn('AG Grid: purgeVirtualPageCache() is now called purgeInfiniteCache(), please call purgeInfiniteCache() instead');\n this.purgeInfinitePageCache();\n };\n /** @deprecated AG Grid: purgeInfinitePageCache() is now called purgeInfiniteCache(), please call purgeInfiniteCache() instead */\n GridApi.prototype.purgeInfinitePageCache = function () {\n console.warn('AG Grid: purgeInfinitePageCache() is now called purgeInfiniteCache(), please call purgeInfiniteCache() instead');\n this.purgeInfiniteCache();\n };\n /**\n * Purges the cache.\n * The grid is then told to refresh. Only the blocks required to display the current data on screen are fetched (typically no more than 2).\n * The grid will display nothing while the new blocks are loaded.\n * Use this to immediately remove the old data from the user.\n */\n GridApi.prototype.purgeInfiniteCache = function () {\n if (this.infiniteRowModel) {\n this.infiniteRowModel.purgeCache();\n }\n else {\n console.warn(\"AG Grid: api.purgeInfiniteCache is only available when rowModelType='infinite'.\");\n }\n };\n /** @deprecated AG Grid: since version 18.x, api.purgeEnterpriseCache() should be replaced with api.refreshServerSide({purge: true}) */\n GridApi.prototype.purgeEnterpriseCache = function (route) {\n console.warn(\"AG Grid: since version 18.x, api.purgeEnterpriseCache() should be replaced with api.refreshServerSide({purge: true})\");\n this.purgeServerSideCache(route);\n };\n /** @deprecated AG Grid: since v25.0, api.purgeServerSideCache is deprecated. Please use api.refreshServerSide({purge: true}) instead. */\n GridApi.prototype.purgeServerSideCache = function (route) {\n if (route === void 0) { route = []; }\n if (this.serverSideRowModel) {\n console.warn(\"AG Grid: since v25.0, api.purgeServerSideCache is deprecated. Please use api.refreshServerSide({purge: true}) instead.\");\n this.refreshServerSide({\n route: route,\n purge: true\n });\n }\n else {\n console.warn(\"AG Grid: api.purgeServerSideCache is only available when rowModelType='serverSide'.\");\n }\n };\n /**\n * Refresh a server-side level.\n * If you pass no parameters, then the top level store is purged.\n * To purge a child level, pass in the string of keys to get to the desired level.\n */\n GridApi.prototype.refreshServerSide = function (params) {\n if (!this.serverSideRowModel) {\n console.warn(\"AG Grid: api.refreshServerSide is only available when rowModelType='serverSide'.\");\n return;\n }\n this.serverSideRowModel.refreshStore(params);\n };\n /** @deprecated use `refreshServerSide` instead */\n GridApi.prototype.refreshServerSideStore = function (params) {\n var message = \"AG Grid: Grid API refreshServerSideStore() was renamed to refreshServerSide() in v28.0\";\n doOnce(function () { return console.warn(message); }, 'refreshServerSideStore-renamed');\n return this.refreshServerSide(params);\n };\n /** @deprecated use `getServerSideGroupLevelState` instead */\n GridApi.prototype.getServerSideStoreState = function () {\n var message = \"AG Grid: Grid API getServerSideStoreState() was renamed to getServerSideGroupLevelState() in v28.0\";\n doOnce(function () { return console.warn(message); }, 'getServerSideStoreState-renamed');\n return this.getServerSideGroupLevelState();\n };\n /** Returns info on all server side group levels. */\n GridApi.prototype.getServerSideGroupLevelState = function () {\n if (!this.serverSideRowModel) {\n console.warn(\"AG Grid: api.getServerSideGroupLevelState is only available when rowModelType='serverSide'.\");\n return [];\n }\n return this.serverSideRowModel.getStoreState();\n };\n /** @deprecated AG Grid: getVirtualRowCount() is now called getInfiniteRowCount(), please call getInfiniteRowCount() instead */\n GridApi.prototype.getVirtualRowCount = function () {\n console.warn('AG Grid: getVirtualRowCount() is now called getInfiniteRowCount(), please call getInfiniteRowCount() instead');\n return this.getInfiniteRowCount();\n };\n /** The row count defines how many rows the grid allows scrolling to. */\n GridApi.prototype.getInfiniteRowCount = function () {\n if (this.infiniteRowModel) {\n return this.infiniteRowModel.getRowCount();\n }\n else {\n console.warn(\"AG Grid: api.getVirtualRowCount is only available when rowModelType='virtual'.\");\n }\n };\n /** @deprecated AG Grid: api.isMaxRowFound is deprecated, please use api.isLastRowIndexKnown() */\n GridApi.prototype.isMaxRowFound = function () {\n console.warn(\"AG Grid: api.isMaxRowFound is deprecated, please use api.isLastRowIndexKnown()\");\n return this.isLastRowIndexKnown();\n };\n /** Returns `true` if grid allows for scrolling past the last row to load more rows, thus providing infinite scroll. */\n GridApi.prototype.isLastRowIndexKnown = function () {\n if (this.infiniteRowModel) {\n return this.infiniteRowModel.isLastRowIndexKnown();\n }\n else {\n console.warn(\"AG Grid: api.isMaxRowFound is only available when rowModelType='virtual'.\");\n }\n };\n /** @deprecated AG Grid: setVirtualRowCount() is now called setInfiniteRowCount(), please call setInfiniteRowCount() instead */\n GridApi.prototype.setVirtualRowCount = function (rowCount, maxRowFound) {\n console.warn('AG Grid: setVirtualRowCount() is now called setInfiniteRowCount(), please call setInfiniteRowCount() instead');\n this.setRowCount(rowCount, maxRowFound);\n };\n /** @deprecated AG Grid: setInfiniteRowCount() is now called setRowCount(), please call setRowCount() instead */\n GridApi.prototype.setInfiniteRowCount = function (rowCount, maxRowFound) {\n console.warn('AG Grid: setInfiniteRowCount() is now called setRowCount(), please call setRowCount() instead');\n this.setRowCount(rowCount, maxRowFound);\n };\n /**\n * Sets the `rowCount` and `lastRowIndexKnown` properties.\n * The second parameter, `lastRowIndexKnown`, is optional and if left out, only `rowCount` is set.\n * Set `rowCount` to adjust the height of the vertical scroll.\n * Set `lastRowIndexKnown` to enable / disable searching for more rows.\n * Use this method if you add or remove rows into the dataset and need to reset the number of rows or put the data back into 'look for data' mode.\n */\n GridApi.prototype.setRowCount = function (rowCount, maxRowFound) {\n if (this.infiniteRowModel) {\n this.infiniteRowModel.setRowCount(rowCount, maxRowFound);\n }\n else {\n console.warn(\"AG Grid: api.setRowCount is only available for Infinite Row Model.\");\n }\n };\n /** @deprecated AG Grid: getVirtualPageState() is now called getCacheBlockState(), please call getCacheBlockState() instead */\n GridApi.prototype.getVirtualPageState = function () {\n console.warn('AG Grid: getVirtualPageState() is now called getCacheBlockState(), please call getCacheBlockState() instead');\n return this.getCacheBlockState();\n };\n /** @deprecated getInfinitePageState() is now called getCacheBlockState(), please call getCacheBlockState() instead */\n GridApi.prototype.getInfinitePageState = function () {\n console.warn('AG Grid: getInfinitePageState() is now called getCacheBlockState(), please call getCacheBlockState() instead');\n return this.getCacheBlockState();\n };\n /**\n * Returns an object representing the state of the cache. This is useful for debugging and understanding how the cache is working.\n */\n GridApi.prototype.getCacheBlockState = function () {\n return this.rowNodeBlockLoader.getBlockState();\n };\n /** @deprecated In AG Grid v25.2.0, checkGridSize() was removed, as it was legacy and didn't do anything useful. */\n GridApi.prototype.checkGridSize = function () {\n console.warn(\"In AG Grid v25.2.0, checkGridSize() was removed, as it was legacy and didn't do anything useful.\");\n };\n /** @deprecated In AG Grid v12, getFirstRenderedRow() was renamed to getFirstDisplayedRow() */\n GridApi.prototype.getFirstRenderedRow = function () {\n console.warn('In AG Grid v12, getFirstRenderedRow() was renamed to getFirstDisplayedRow()');\n return this.getFirstDisplayedRow();\n };\n /** Get the index of the first displayed row due to scrolling (includes invisible rendered rows in the buffer). */\n GridApi.prototype.getFirstDisplayedRow = function () {\n return this.rowRenderer.getFirstVirtualRenderedRow();\n };\n /** @deprecated In AG Grid v12, getLastRenderedRow() was renamed to getLastDisplayedRow() */\n GridApi.prototype.getLastRenderedRow = function () {\n console.warn('in AG Grid v12, getLastRenderedRow() was renamed to getLastDisplayedRow()');\n return this.getLastDisplayedRow();\n };\n /** Get the index of the last displayed row due to scrolling (includes invisible rendered rows in the buffer). */\n GridApi.prototype.getLastDisplayedRow = function () {\n return this.rowRenderer.getLastVirtualRenderedRow();\n };\n /** Returns the displayed `RowNode` at the given `index`. */\n GridApi.prototype.getDisplayedRowAtIndex = function (index) {\n return this.rowModel.getRow(index);\n };\n /** Returns the total number of displayed rows. */\n GridApi.prototype.getDisplayedRowCount = function () {\n return this.rowModel.getRowCount();\n };\n /**\n * Returns `true` when the last page is known.\n * This will always be `true` if you are using the Client-Side Row Model for pagination.\n * Returns `false` when the last page is not known; this only happens when using Infinite Row Model.\n */\n GridApi.prototype.paginationIsLastPageFound = function () {\n return this.paginationProxy.isLastPageFound();\n };\n /** Returns how many rows are being shown per page. */\n GridApi.prototype.paginationGetPageSize = function () {\n return this.paginationProxy.getPageSize();\n };\n /** Sets the `paginationPageSize`, then re-paginates the grid so the changes are applied immediately. */\n GridApi.prototype.paginationSetPageSize = function (size) {\n this.gridOptionsWrapper.setProperty('paginationPageSize', size);\n };\n /** Returns the 0-based index of the page which is showing. */\n GridApi.prototype.paginationGetCurrentPage = function () {\n return this.paginationProxy.getCurrentPage();\n };\n /** Returns the total number of pages. Returns `null` if `paginationIsLastPageFound() === false`. */\n GridApi.prototype.paginationGetTotalPages = function () {\n return this.paginationProxy.getTotalPages();\n };\n /** The total number of rows. Returns `null` if `paginationIsLastPageFound() === false`. */\n GridApi.prototype.paginationGetRowCount = function () {\n return this.paginationProxy.getMasterRowCount();\n };\n /** Navigates to the next page. */\n GridApi.prototype.paginationGoToNextPage = function () {\n this.paginationProxy.goToNextPage();\n };\n /** Navigates to the previous page. */\n GridApi.prototype.paginationGoToPreviousPage = function () {\n this.paginationProxy.goToPreviousPage();\n };\n /** Navigates to the first page. */\n GridApi.prototype.paginationGoToFirstPage = function () {\n this.paginationProxy.goToFirstPage();\n };\n /** Navigates to the last page. */\n GridApi.prototype.paginationGoToLastPage = function () {\n this.paginationProxy.goToLastPage();\n };\n /** Goes to the specified page. If the page requested doesn't exist, it will go to the last page. */\n GridApi.prototype.paginationGoToPage = function (page) {\n this.paginationProxy.goToPage(page);\n };\n GridApi.prototype.setRowClass = function (className) {\n this.gridOptionsWrapper.setProperty(GridOptionsWrapper.PROP_ROW_CLASS, className);\n };\n __decorate$1r([\n Optional('immutableService')\n ], GridApi.prototype, \"immutableService\", void 0);\n __decorate$1r([\n Optional('csvCreator')\n ], GridApi.prototype, \"csvCreator\", void 0);\n __decorate$1r([\n Optional('excelCreator')\n ], GridApi.prototype, \"excelCreator\", void 0);\n __decorate$1r([\n Autowired('rowRenderer')\n ], GridApi.prototype, \"rowRenderer\", void 0);\n __decorate$1r([\n Autowired('navigationService')\n ], GridApi.prototype, \"navigationService\", void 0);\n __decorate$1r([\n Autowired('filterManager')\n ], GridApi.prototype, \"filterManager\", void 0);\n __decorate$1r([\n Autowired('columnModel')\n ], GridApi.prototype, \"columnModel\", void 0);\n __decorate$1r([\n Autowired('selectionService')\n ], GridApi.prototype, \"selectionService\", void 0);\n __decorate$1r([\n Autowired('gridOptionsWrapper')\n ], GridApi.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$1r([\n Autowired('valueService')\n ], GridApi.prototype, \"valueService\", void 0);\n __decorate$1r([\n Autowired('alignedGridsService')\n ], GridApi.prototype, \"alignedGridsService\", void 0);\n __decorate$1r([\n Autowired('eventService')\n ], GridApi.prototype, \"eventService\", void 0);\n __decorate$1r([\n Autowired('pinnedRowModel')\n ], GridApi.prototype, \"pinnedRowModel\", void 0);\n __decorate$1r([\n Autowired('context')\n ], GridApi.prototype, \"context\", void 0);\n __decorate$1r([\n Autowired('rowModel')\n ], GridApi.prototype, \"rowModel\", void 0);\n __decorate$1r([\n Autowired('sortController')\n ], GridApi.prototype, \"sortController\", void 0);\n __decorate$1r([\n Autowired('paginationProxy')\n ], GridApi.prototype, \"paginationProxy\", void 0);\n __decorate$1r([\n Autowired('focusService')\n ], GridApi.prototype, \"focusService\", void 0);\n __decorate$1r([\n Autowired('dragAndDropService')\n ], GridApi.prototype, \"dragAndDropService\", void 0);\n __decorate$1r([\n Optional('rangeService')\n ], GridApi.prototype, \"rangeService\", void 0);\n __decorate$1r([\n Optional('clipboardService')\n ], GridApi.prototype, \"clipboardService\", void 0);\n __decorate$1r([\n Optional('aggFuncService')\n ], GridApi.prototype, \"aggFuncService\", void 0);\n __decorate$1r([\n Autowired('menuFactory')\n ], GridApi.prototype, \"menuFactory\", void 0);\n __decorate$1r([\n Optional('contextMenuFactory')\n ], GridApi.prototype, \"contextMenuFactory\", void 0);\n __decorate$1r([\n Autowired('valueCache')\n ], GridApi.prototype, \"valueCache\", void 0);\n __decorate$1r([\n Autowired('animationFrameService')\n ], GridApi.prototype, \"animationFrameService\", void 0);\n __decorate$1r([\n Optional('statusBarService')\n ], GridApi.prototype, \"statusBarService\", void 0);\n __decorate$1r([\n Optional('chartService')\n ], GridApi.prototype, \"chartService\", void 0);\n __decorate$1r([\n Optional('undoRedoService')\n ], GridApi.prototype, \"undoRedoService\", void 0);\n __decorate$1r([\n Optional('rowNodeBlockLoader')\n ], GridApi.prototype, \"rowNodeBlockLoader\", void 0);\n __decorate$1r([\n Optional('ssrmTransactionManager')\n ], GridApi.prototype, \"serverSideTransactionManager\", void 0);\n __decorate$1r([\n Autowired('ctrlsService')\n ], GridApi.prototype, \"ctrlsService\", void 0);\n __decorate$1r([\n Optional('frameworkComponentWrapper')\n ], GridApi.prototype, \"frameworkComponentWrapper\", void 0);\n __decorate$1r([\n PostConstruct\n ], GridApi.prototype, \"init\", null);\n __decorate$1r([\n PreDestroy\n ], GridApi.prototype, \"cleanDownReferencesToAvoidMemoryLeakInCaseApplicationIsKeepingReferenceToDestroyedGrid\", null);\n GridApi = __decorate$1r([\n Bean('gridApi')\n ], GridApi);\n return GridApi;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1y = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1q = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SetLeftFeature = /** @class */ (function (_super) {\n __extends$1y(SetLeftFeature, _super);\n function SetLeftFeature(columnOrGroup, eCell, beans, colsSpanning) {\n var _this = _super.call(this) || this;\n _this.columnOrGroup = columnOrGroup;\n _this.eCell = eCell;\n _this.ariaEl = _this.eCell.querySelector('[role=columnheader]') || _this.eCell;\n _this.colsSpanning = colsSpanning;\n _this.beans = beans;\n return _this;\n }\n SetLeftFeature.prototype.setColsSpanning = function (colsSpanning) {\n this.colsSpanning = colsSpanning;\n this.onLeftChanged();\n };\n SetLeftFeature.prototype.getColumnOrGroup = function () {\n if (this.beans.gridOptionsWrapper.isEnableRtl() && this.colsSpanning) {\n return last(this.colsSpanning);\n }\n return this.columnOrGroup;\n };\n SetLeftFeature.prototype.postConstruct = function () {\n this.addManagedListener(this.columnOrGroup, Column.EVENT_LEFT_CHANGED, this.onLeftChanged.bind(this));\n this.setLeftFirstTime();\n // when in print layout, the left position is also dependent on the width of the pinned sections.\n // so additionally update left if any column width changes.\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, this.onLeftChanged.bind(this));\n // setting left has a dependency on print layout\n this.addManagedListener(this.beans.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, this.onLeftChanged.bind(this));\n };\n SetLeftFeature.prototype.setLeftFirstTime = function () {\n var suppressMoveAnimation = this.beans.gridOptionsWrapper.isSuppressColumnMoveAnimation();\n var oldLeftExists = exists(this.columnOrGroup.getOldLeft());\n var animateColumnMove = this.beans.columnAnimationService.isActive() && oldLeftExists && !suppressMoveAnimation;\n if (animateColumnMove) {\n this.animateInLeft();\n }\n else {\n this.onLeftChanged();\n }\n };\n SetLeftFeature.prototype.animateInLeft = function () {\n var _this = this;\n var colOrGroup = this.getColumnOrGroup();\n var left = colOrGroup.getLeft();\n var oldLeft = colOrGroup.getOldLeft();\n var oldActualLeft = this.modifyLeftForPrintLayout(colOrGroup, oldLeft);\n var actualLeft = this.modifyLeftForPrintLayout(colOrGroup, left);\n this.setLeft(oldActualLeft);\n // we must keep track of the left we want to set to, as this would otherwise lead to a race\n // condition, if the user changed the left value many times in one VM turn, then we want to make\n // make sure the actualLeft we set in the timeout below (in the next VM turn) is the correct left\n // position. eg if user changes column position twice, then setLeft() below executes twice in next\n // VM turn, but only one (the correct one) should get applied.\n this.actualLeft = actualLeft;\n this.beans.columnAnimationService.executeNextVMTurn(function () {\n // test this left value is the latest one to be applied, and if not, do nothing\n if (_this.actualLeft === actualLeft) {\n _this.setLeft(actualLeft);\n }\n });\n };\n SetLeftFeature.prototype.onLeftChanged = function () {\n var colOrGroup = this.getColumnOrGroup();\n var left = colOrGroup.getLeft();\n this.actualLeft = this.modifyLeftForPrintLayout(colOrGroup, left);\n this.setLeft(this.actualLeft);\n };\n SetLeftFeature.prototype.modifyLeftForPrintLayout = function (colOrGroup, leftPosition) {\n var printLayout = this.beans.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n if (!printLayout) {\n return leftPosition;\n }\n if (colOrGroup.getPinned() === Constants.PINNED_LEFT) {\n return leftPosition;\n }\n var leftWidth = this.beans.columnModel.getDisplayedColumnsLeftWidth();\n if (colOrGroup.getPinned() === Constants.PINNED_RIGHT) {\n var bodyWidth = this.beans.columnModel.getBodyContainerWidth();\n return leftWidth + bodyWidth + leftPosition;\n }\n // is in body\n return leftWidth + leftPosition;\n };\n SetLeftFeature.prototype.setLeft = function (value) {\n // if the value is null, then that means the column is no longer\n // displayed. there is logic in the rendering to fade these columns\n // out, so we don't try and change their left positions.\n if (exists(value)) {\n this.eCell.style.left = value + \"px\";\n }\n var indexColumn;\n if (this.columnOrGroup instanceof Column) {\n indexColumn = this.columnOrGroup;\n }\n else {\n var columnGroup = this.columnOrGroup;\n var children = columnGroup.getLeafColumns();\n if (!children.length) {\n return;\n }\n if (children.length > 1) {\n setAriaColSpan(this.ariaEl, children.length);\n }\n indexColumn = children[0];\n }\n var index = this.beans.columnModel.getAriaColumnIndex(indexColumn);\n setAriaColIndex(this.ariaEl, index);\n };\n __decorate$1q([\n PostConstruct\n ], SetLeftFeature.prototype, \"postConstruct\", null);\n return SetLeftFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1x = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1p = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HoverFeature = /** @class */ (function (_super) {\n __extends$1x(HoverFeature, _super);\n function HoverFeature(columns, element) {\n var _this = _super.call(this) || this;\n _this.columns = columns;\n _this.element = element;\n return _this;\n }\n HoverFeature.prototype.postConstruct = function () {\n if (this.gridOptionsWrapper.isColumnHoverHighlight()) {\n this.addMouseHoverListeners();\n }\n };\n HoverFeature.prototype.addMouseHoverListeners = function () {\n this.addManagedListener(this.element, 'mouseout', this.onMouseOut.bind(this));\n this.addManagedListener(this.element, 'mouseover', this.onMouseOver.bind(this));\n };\n HoverFeature.prototype.onMouseOut = function () {\n this.columnHoverService.clearMouseOver();\n };\n HoverFeature.prototype.onMouseOver = function () {\n this.columnHoverService.setMouseOver(this.columns);\n };\n __decorate$1p([\n Autowired('columnHoverService')\n ], HoverFeature.prototype, \"columnHoverService\", void 0);\n __decorate$1p([\n PostConstruct\n ], HoverFeature.prototype, \"postConstruct\", null);\n return HoverFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1w = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1o = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderFilterCellCtrl = /** @class */ (function (_super) {\n __extends$1w(HeaderFilterCellCtrl, _super);\n function HeaderFilterCellCtrl(column, parentRowCtrl) {\n var _this = _super.call(this, column, parentRowCtrl) || this;\n _this.column = column;\n return _this;\n }\n HeaderFilterCellCtrl.prototype.setComp = function (comp, eGui, eButtonShowMainFilter, eFloatingFilterBody) {\n _super.prototype.setGui.call(this, eGui);\n this.comp = comp;\n this.eButtonShowMainFilter = eButtonShowMainFilter;\n this.eFloatingFilterBody = eFloatingFilterBody;\n var colDef = this.column.getColDef();\n var filterExists = !!colDef.filter || !!colDef.filterFramework;\n var floatingFilterExists = !!colDef.floatingFilter;\n this.active = filterExists && floatingFilterExists;\n this.setupWidth();\n this.setupLeft();\n this.setupHover();\n this.setupFocus();\n this.setupUserComp();\n this.setupSyncWithFilter();\n this.setupUi();\n this.addManagedListener(this.eButtonShowMainFilter, 'click', this.showParentFilter.bind(this));\n };\n HeaderFilterCellCtrl.prototype.setupUi = function () {\n this.comp.addOrRemoveButtonWrapperCssClass('ag-hidden', !this.active || this.suppressFilterButton);\n if (!this.active) {\n return;\n }\n this.comp.addOrRemoveBodyCssClass('ag-floating-filter-full-body', this.suppressFilterButton);\n this.comp.addOrRemoveBodyCssClass('ag-floating-filter-body', !this.suppressFilterButton);\n var eMenuIcon = createIconNoSpan('filter', this.gridOptionsWrapper, this.column);\n if (eMenuIcon) {\n this.eButtonShowMainFilter.appendChild(eMenuIcon);\n }\n };\n HeaderFilterCellCtrl.prototype.setupFocus = function () {\n this.createManagedBean(new ManagedFocusFeature(this.eGui, {\n shouldStopEventPropagation: this.shouldStopEventPropagation.bind(this),\n onTabKeyDown: this.onTabKeyDown.bind(this),\n handleKeyDown: this.handleKeyDown.bind(this),\n onFocusIn: this.onFocusIn.bind(this)\n }));\n };\n HeaderFilterCellCtrl.prototype.onTabKeyDown = function (e) {\n var eDocument = this.gridOptionsWrapper.getDocument();\n var activeEl = eDocument.activeElement;\n var wrapperHasFocus = activeEl === this.eGui;\n if (wrapperHasFocus) {\n return;\n }\n var nextFocusableEl = this.focusService.findNextFocusableElement(this.eGui, null, e.shiftKey);\n if (nextFocusableEl) {\n this.beans.headerNavigationService.scrollToColumn(this.column);\n e.preventDefault();\n nextFocusableEl.focus();\n return;\n }\n var nextFocusableColumn = this.findNextColumnWithFloatingFilter(e.shiftKey);\n if (!nextFocusableColumn) {\n return;\n }\n if (this.focusService.focusHeaderPosition({\n headerPosition: {\n headerRowIndex: this.getParentRowCtrl().getRowIndex(),\n column: nextFocusableColumn\n },\n event: e\n })) {\n e.preventDefault();\n }\n };\n HeaderFilterCellCtrl.prototype.findNextColumnWithFloatingFilter = function (backwards) {\n var columModel = this.beans.columnModel;\n var nextCol = this.column;\n do {\n nextCol = backwards\n ? columModel.getDisplayedColBefore(nextCol)\n : columModel.getDisplayedColAfter(nextCol);\n if (!nextCol) {\n break;\n }\n } while (!nextCol.getColDef().filter || !nextCol.getColDef().floatingFilter);\n return nextCol;\n };\n HeaderFilterCellCtrl.prototype.handleKeyDown = function (e) {\n _super.prototype.handleKeyDown.call(this, e);\n var wrapperHasFocus = this.getWrapperHasFocus();\n switch (e.key) {\n case KeyCode.UP:\n case KeyCode.DOWN:\n if (!wrapperHasFocus) {\n e.preventDefault();\n }\n case KeyCode.LEFT:\n case KeyCode.RIGHT:\n if (wrapperHasFocus) {\n return;\n }\n e.stopPropagation();\n case KeyCode.ENTER:\n if (wrapperHasFocus) {\n if (this.focusService.focusInto(this.eGui)) {\n e.preventDefault();\n }\n }\n break;\n case KeyCode.ESCAPE:\n if (!wrapperHasFocus) {\n this.eGui.focus();\n }\n }\n };\n HeaderFilterCellCtrl.prototype.onFocusIn = function (e) {\n var isRelatedWithin = this.eGui.contains(e.relatedTarget);\n // when the focus is already within the component,\n // we default to the browser's behavior\n if (isRelatedWithin) {\n return;\n }\n var notFromHeaderWrapper = !!e.relatedTarget && !e.relatedTarget.classList.contains('ag-floating-filter');\n var fromWithinHeader = !!e.relatedTarget && isElementChildOfClass(e.relatedTarget, 'ag-floating-filter');\n if (notFromHeaderWrapper && fromWithinHeader && e.target === this.eGui) {\n var lastFocusEvent = this.lastFocusEvent;\n var fromTab = !!(lastFocusEvent && lastFocusEvent.key === KeyCode.TAB);\n if (lastFocusEvent && fromTab) {\n var shouldFocusLast = lastFocusEvent.shiftKey;\n this.focusService.focusInto(this.eGui, shouldFocusLast);\n }\n }\n var rowIndex = this.getRowIndex();\n this.beans.focusService.setFocusedHeader(rowIndex, this.column);\n };\n HeaderFilterCellCtrl.prototype.setupHover = function () {\n var _this = this;\n this.createManagedBean(new HoverFeature([this.column], this.eGui));\n var listener = function () {\n if (!_this.gridOptionsWrapper.isColumnHoverHighlight()) {\n return;\n }\n var hovered = _this.columnHoverService.isHovered(_this.column);\n _this.comp.addOrRemoveCssClass('ag-column-hover', hovered);\n };\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_HOVER_CHANGED, listener);\n listener();\n };\n HeaderFilterCellCtrl.prototype.setupLeft = function () {\n var setLeftFeature = new SetLeftFeature(this.column, this.eGui, this.beans);\n this.createManagedBean(setLeftFeature);\n };\n HeaderFilterCellCtrl.prototype.setupUserComp = function () {\n var _this = this;\n if (!this.active) {\n return;\n }\n var colDef = this.column.getColDef();\n var filterParams = this.filterManager.createFilterParams(this.column, colDef);\n var finalFilterParams = this.userComponentFactory.mergeParamsWithApplicationProvidedParams(colDef, FilterComponent, filterParams);\n var defaultFloatingFilterType = this.userComponentFactory.getDefaultFloatingFilterType(colDef);\n if (defaultFloatingFilterType == null) {\n defaultFloatingFilterType = 'agReadOnlyFloatingFilter';\n }\n var params = {\n column: this.column,\n filterParams: finalFilterParams,\n currentParentModel: function () { return _this.currentParentModel(); },\n parentFilterInstance: function (cb) { return _this.parentFilterInstance(cb); },\n showParentFilter: function () { return _this.showParentFilter(); },\n suppressFilterButton: false // This one might be overridden from the colDef\n };\n // this is unusual - we need a params value OUTSIDE the component the params are for.\n // the params are for the floating filter component, but this property is actually for the wrapper.\n this.suppressFilterButton = colDef.floatingFilterComponentParams ? !!colDef.floatingFilterComponentParams.suppressFilterButton : false;\n var compDetails = this.userComponentFactory.getFloatingFilterCompDetails(colDef, params, defaultFloatingFilterType);\n if (compDetails) {\n this.comp.setCompDetails(compDetails);\n }\n };\n HeaderFilterCellCtrl.prototype.currentParentModel = function () {\n var filterComponent = this.getFilterComponent(false);\n return filterComponent ? filterComponent.resolveNow(null, function (filter) { return filter && filter.getModel(); }) : null;\n };\n HeaderFilterCellCtrl.prototype.getFilterComponent = function (createIfDoesNotExist) {\n if (createIfDoesNotExist === void 0) { createIfDoesNotExist = true; }\n return this.filterManager.getFilterComponent(this.column, 'NO_UI', createIfDoesNotExist);\n };\n HeaderFilterCellCtrl.prototype.parentFilterInstance = function (callback) {\n var filterComponent = this.getFilterComponent();\n if (filterComponent == null) {\n return;\n }\n filterComponent.then(function (instance) {\n callback(unwrapUserComp(instance));\n });\n };\n HeaderFilterCellCtrl.prototype.showParentFilter = function () {\n var eventSource = this.suppressFilterButton ? this.eFloatingFilterBody : this.eButtonShowMainFilter;\n this.menuFactory.showMenuAfterButtonClick(this.column, eventSource, 'floatingFilter', 'filterMenuTab', ['filterMenuTab']);\n };\n HeaderFilterCellCtrl.prototype.setupSyncWithFilter = function () {\n var _this = this;\n if (!this.active) {\n return;\n }\n var syncWithFilter = function (filterChangedEvent) {\n var compPromise = _this.comp.getFloatingFilterComp();\n if (!compPromise) {\n return;\n }\n var parentModel = _this.currentParentModel();\n compPromise.then(function (comp) {\n if (comp) {\n comp.onParentModelChanged(parentModel, filterChangedEvent);\n }\n });\n };\n this.addManagedListener(this.column, Column.EVENT_FILTER_CHANGED, syncWithFilter);\n if (this.filterManager.isFilterActive(this.column)) {\n syncWithFilter(null);\n }\n };\n HeaderFilterCellCtrl.prototype.setupWidth = function () {\n var _this = this;\n var listener = function () {\n var width = _this.column.getActualWidth() + \"px\";\n _this.comp.setWidth(width);\n };\n this.addManagedListener(this.column, Column.EVENT_WIDTH_CHANGED, listener);\n listener();\n };\n __decorate$1o([\n Autowired('filterManager')\n ], HeaderFilterCellCtrl.prototype, \"filterManager\", void 0);\n __decorate$1o([\n Autowired('columnHoverService')\n ], HeaderFilterCellCtrl.prototype, \"columnHoverService\", void 0);\n __decorate$1o([\n Autowired('menuFactory')\n ], HeaderFilterCellCtrl.prototype, \"menuFactory\", void 0);\n return HeaderFilterCellCtrl;\n}(AbstractHeaderCellCtrl));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1v = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1n = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ResizeFeature = /** @class */ (function (_super) {\n __extends$1v(ResizeFeature, _super);\n function ResizeFeature(pinned, column, eResize, comp, ctrl) {\n var _this = _super.call(this) || this;\n _this.pinned = pinned;\n _this.column = column;\n _this.eResize = eResize;\n _this.comp = comp;\n _this.ctrl = ctrl;\n return _this;\n }\n ResizeFeature.prototype.postConstruct = function () {\n var _this = this;\n var colDef = this.column.getColDef();\n var destroyResizeFuncs = [];\n var canResize;\n var canAutosize;\n var addResize = function () {\n setDisplayed(_this.eResize, canResize);\n if (!canResize) {\n return;\n }\n var finishedWithResizeFunc = _this.horizontalResizeService.addResizeBar({\n eResizeBar: _this.eResize,\n onResizeStart: _this.onResizeStart.bind(_this),\n onResizing: _this.onResizing.bind(_this, false),\n onResizeEnd: _this.onResizing.bind(_this, true)\n });\n destroyResizeFuncs.push(finishedWithResizeFunc);\n if (canAutosize) {\n var skipHeaderOnAutoSize_1 = _this.gridOptionsWrapper.isSkipHeaderOnAutoSize();\n var autoSizeColListener_1 = function () {\n _this.columnModel.autoSizeColumn(_this.column, skipHeaderOnAutoSize_1, \"uiColumnResized\");\n };\n _this.eResize.addEventListener('dblclick', autoSizeColListener_1);\n var touchListener_1 = new TouchListener(_this.eResize);\n touchListener_1.addEventListener(TouchListener.EVENT_DOUBLE_TAP, autoSizeColListener_1);\n _this.addDestroyFunc(function () {\n _this.eResize.removeEventListener('dblclick', autoSizeColListener_1);\n touchListener_1.removeEventListener(TouchListener.EVENT_DOUBLE_TAP, autoSizeColListener_1);\n touchListener_1.destroy();\n });\n }\n };\n var removeResize = function () {\n destroyResizeFuncs.forEach(function (f) { return f(); });\n destroyResizeFuncs.length = 0;\n };\n var refresh = function () {\n var resize = _this.column.isResizable();\n var autoSize = !_this.gridOptionsWrapper.isSuppressAutoSize() && !colDef.suppressAutoSize;\n var propertyChange = resize !== canResize || autoSize !== canAutosize;\n if (propertyChange) {\n canResize = resize;\n canAutosize = autoSize;\n removeResize();\n addResize();\n }\n };\n refresh();\n this.addDestroyFunc(removeResize);\n this.ctrl.addRefreshFunction(refresh);\n };\n ResizeFeature.prototype.onResizing = function (finished, resizeAmount) {\n var resizeAmountNormalised = this.normaliseResizeAmount(resizeAmount);\n var columnWidths = [{ key: this.column, newWidth: this.resizeStartWidth + resizeAmountNormalised }];\n this.columnModel.setColumnWidths(columnWidths, this.resizeWithShiftKey, finished, \"uiColumnDragged\");\n if (finished) {\n this.comp.addOrRemoveCssClass('ag-column-resizing', false);\n }\n };\n ResizeFeature.prototype.onResizeStart = function (shiftKey) {\n this.resizeStartWidth = this.column.getActualWidth();\n this.resizeWithShiftKey = shiftKey;\n this.comp.addOrRemoveCssClass('ag-column-resizing', true);\n };\n // optionally inverts the drag, depending on pinned and RTL\n // note - this method is duplicated in RenderedHeaderGroupCell - should refactor out?\n ResizeFeature.prototype.normaliseResizeAmount = function (dragChange) {\n var result = dragChange;\n var notPinningLeft = this.pinned !== Constants.PINNED_LEFT;\n var pinningRight = this.pinned === Constants.PINNED_RIGHT;\n if (this.gridOptionsWrapper.isEnableRtl()) {\n // for RTL, dragging left makes the col bigger, except when pinning left\n if (notPinningLeft) {\n result *= -1;\n }\n }\n else {\n // for LTR (ie normal), dragging left makes the col smaller, except when pinning right\n if (pinningRight) {\n result *= -1;\n }\n }\n return result;\n };\n __decorate$1n([\n Autowired('horizontalResizeService')\n ], ResizeFeature.prototype, \"horizontalResizeService\", void 0);\n __decorate$1n([\n Autowired('columnModel')\n ], ResizeFeature.prototype, \"columnModel\", void 0);\n __decorate$1n([\n PostConstruct\n ], ResizeFeature.prototype, \"postConstruct\", null);\n return ResizeFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1u = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgCheckbox = /** @class */ (function (_super) {\n __extends$1u(AgCheckbox, _super);\n function AgCheckbox(config, className, inputType) {\n if (className === void 0) { className = 'ag-checkbox'; }\n if (inputType === void 0) { inputType = 'checkbox'; }\n var _this = _super.call(this, config, className, inputType) || this;\n _this.labelAlignment = 'right';\n _this.selected = false;\n _this.readOnly = false;\n _this.passive = false;\n return _this;\n }\n AgCheckbox.prototype.addInputListeners = function () {\n this.addManagedListener(this.eInput, 'click', this.onCheckboxClick.bind(this));\n this.addManagedListener(this.eLabel, 'click', this.toggle.bind(this));\n };\n AgCheckbox.prototype.getNextValue = function () {\n return this.selected === undefined ? true : !this.selected;\n };\n AgCheckbox.prototype.setPassive = function (passive) {\n this.passive = passive;\n };\n AgCheckbox.prototype.isReadOnly = function () {\n return this.readOnly;\n };\n AgCheckbox.prototype.setReadOnly = function (readOnly) {\n this.eWrapper.classList.toggle('ag-disabled', readOnly);\n this.eInput.disabled = readOnly;\n this.readOnly = readOnly;\n };\n AgCheckbox.prototype.setDisabled = function (disabled) {\n this.eWrapper.classList.toggle('ag-disabled', disabled);\n return _super.prototype.setDisabled.call(this, disabled);\n };\n AgCheckbox.prototype.toggle = function () {\n if (this.eInput.disabled) {\n return;\n }\n var previousValue = this.isSelected();\n var nextValue = this.getNextValue();\n if (this.passive) {\n this.dispatchChange(nextValue, previousValue);\n }\n else {\n this.setValue(nextValue);\n }\n };\n AgCheckbox.prototype.getValue = function () {\n return this.isSelected();\n };\n AgCheckbox.prototype.setValue = function (value, silent) {\n this.refreshSelectedClass(value);\n this.setSelected(value, silent);\n return this;\n };\n AgCheckbox.prototype.setName = function (name) {\n var input = this.getInputElement();\n input.name = name;\n return this;\n };\n AgCheckbox.prototype.isSelected = function () {\n return this.selected;\n };\n AgCheckbox.prototype.setSelected = function (selected, silent) {\n if (this.isSelected() === selected) {\n return;\n }\n this.previousValue = this.isSelected();\n selected = this.selected = typeof selected === 'boolean' ? selected : undefined;\n this.eInput.checked = selected;\n this.eInput.indeterminate = selected === undefined;\n if (!silent) {\n this.dispatchChange(this.selected, this.previousValue);\n }\n };\n AgCheckbox.prototype.dispatchChange = function (selected, previousValue, event) {\n this.dispatchEvent({ type: AgCheckbox.EVENT_CHANGED, selected: selected, previousValue: previousValue, event: event });\n var input = this.getInputElement();\n var checkboxChangedEvent = {\n type: Events.EVENT_CHECKBOX_CHANGED,\n id: input.id,\n name: input.name,\n selected: selected,\n previousValue: previousValue\n };\n this.eventService.dispatchEvent(checkboxChangedEvent);\n };\n AgCheckbox.prototype.onCheckboxClick = function (e) {\n if (this.passive || this.eInput.disabled) {\n return;\n }\n var previousValue = this.isSelected();\n var selected = this.selected = e.target.checked;\n this.refreshSelectedClass(selected);\n this.dispatchChange(selected, previousValue, e);\n };\n AgCheckbox.prototype.refreshSelectedClass = function (value) {\n this.eWrapper.classList.toggle('ag-checked', value === true);\n this.eWrapper.classList.toggle('ag-indeterminate', value == null);\n };\n return AgCheckbox;\n}(AgAbstractInputField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1t = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1m = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SelectAllFeature = /** @class */ (function (_super) {\n __extends$1t(SelectAllFeature, _super);\n function SelectAllFeature(column) {\n var _this = _super.call(this) || this;\n _this.cbSelectAllVisible = false;\n _this.processingEventFromCheckbox = false;\n _this.column = column;\n var colDef = column.getColDef();\n _this.filteredOnly = colDef ? !!colDef.headerCheckboxSelectionFilteredOnly : false;\n return _this;\n }\n SelectAllFeature.prototype.onSpaceKeyPressed = function (e) {\n var checkbox = this.cbSelectAll;\n var eDocument = this.gridOptionsWrapper.getDocument();\n if (checkbox.isDisplayed() && !checkbox.getGui().contains(eDocument.activeElement)) {\n e.preventDefault();\n checkbox.setValue(!checkbox.getValue());\n }\n };\n SelectAllFeature.prototype.getCheckboxGui = function () {\n return this.cbSelectAll.getGui();\n };\n SelectAllFeature.prototype.setComp = function (ctrl) {\n this.headerCellCtrl = ctrl;\n this.cbSelectAll = this.createManagedBean(new AgCheckbox());\n this.cbSelectAll.addCssClass('ag-header-select-all');\n setAriaRole(this.cbSelectAll.getGui(), 'presentation');\n this.showOrHideSelectAll();\n this.addManagedListener(this.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.showOrHideSelectAll.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.showOrHideSelectAll.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_SELECTION_CHANGED, this.onSelectionChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_MODEL_UPDATED, this.onModelChanged.bind(this));\n this.addManagedListener(this.cbSelectAll, AgCheckbox.EVENT_CHANGED, this.onCbSelectAll.bind(this));\n this.cbSelectAll.getInputElement().setAttribute('tabindex', '-1');\n this.refreshSelectAllLabel();\n };\n SelectAllFeature.prototype.showOrHideSelectAll = function () {\n this.cbSelectAllVisible = this.isCheckboxSelection();\n this.cbSelectAll.setDisplayed(this.cbSelectAllVisible);\n if (this.cbSelectAllVisible) {\n // in case user is trying this feature with the wrong model type\n this.checkRightRowModelType();\n // make sure checkbox is showing the right state\n this.updateStateOfCheckbox();\n }\n this.refreshSelectAllLabel();\n };\n SelectAllFeature.prototype.onModelChanged = function () {\n if (!this.cbSelectAllVisible) {\n return;\n }\n this.updateStateOfCheckbox();\n };\n SelectAllFeature.prototype.onSelectionChanged = function () {\n if (!this.cbSelectAllVisible) {\n return;\n }\n this.updateStateOfCheckbox();\n };\n SelectAllFeature.prototype.getNextCheckboxState = function (selectionCount) {\n // if no rows, always have it unselected\n if (selectionCount.selected === 0 && selectionCount.notSelected === 0) {\n return false;\n }\n // if mix of selected and unselected, this is the tri-state\n if (selectionCount.selected > 0 && selectionCount.notSelected > 0) {\n return null;\n }\n // only selected\n if (selectionCount.selected > 0) {\n return true;\n }\n // nothing selected\n return false;\n };\n SelectAllFeature.prototype.updateStateOfCheckbox = function () {\n if (this.processingEventFromCheckbox) {\n return;\n }\n this.processingEventFromCheckbox = true;\n var selectionCount = this.getSelectionCount();\n var allSelected = this.getNextCheckboxState(selectionCount);\n this.cbSelectAll.setValue(allSelected);\n this.refreshSelectAllLabel();\n this.processingEventFromCheckbox = false;\n };\n SelectAllFeature.prototype.refreshSelectAllLabel = function () {\n if (!this.cbSelectAllVisible) {\n this.headerCellCtrl.setAriaDescriptionProperty('selectAll', null);\n }\n else {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var checked = this.cbSelectAll.getValue();\n var ariaStatus = checked ? translate('ariaChecked', 'checked') : translate('ariaUnchecked', 'unchecked');\n var ariaLabel = translate('ariaRowSelectAll', 'Press Space to toggle all rows selection');\n this.headerCellCtrl.setAriaDescriptionProperty('selectAll', ariaLabel + \" (\" + ariaStatus + \")\");\n }\n this.headerCellCtrl.refreshAriaDescription();\n };\n SelectAllFeature.prototype.getSelectionCount = function () {\n var _this = this;\n var selectedCount = 0;\n var notSelectedCount = 0;\n var callback = function (node) {\n if (_this.gridOptionsWrapper.isGroupSelectsChildren() && node.group) {\n return;\n }\n if (node.isSelected()) {\n selectedCount++;\n }\n else if (!node.selectable) ;\n else {\n notSelectedCount++;\n }\n };\n if (this.filteredOnly) {\n this.gridApi.forEachNodeAfterFilter(callback);\n }\n else {\n this.gridApi.forEachNode(callback);\n }\n return {\n notSelected: notSelectedCount,\n selected: selectedCount\n };\n };\n SelectAllFeature.prototype.checkRightRowModelType = function () {\n var rowModelType = this.rowModel.getType();\n var rowModelMatches = rowModelType === Constants.ROW_MODEL_TYPE_CLIENT_SIDE;\n if (!rowModelMatches) {\n console.warn(\"AG Grid: selectAllCheckbox is only available if using normal row model, you are using \" + rowModelType);\n }\n };\n SelectAllFeature.prototype.onCbSelectAll = function () {\n if (this.processingEventFromCheckbox) {\n return;\n }\n if (!this.cbSelectAllVisible) {\n return;\n }\n var value = this.cbSelectAll.getValue();\n if (value) {\n this.selectionService.selectAllRowNodes(this.filteredOnly);\n }\n else {\n this.selectionService.deselectAllRowNodes(this.filteredOnly);\n }\n };\n SelectAllFeature.prototype.isCheckboxSelection = function () {\n var result = this.column.getColDef().headerCheckboxSelection;\n if (typeof result === 'function') {\n var func = result;\n var params = {\n column: this.column,\n colDef: this.column.getColDef(),\n columnApi: this.columnApi,\n api: this.gridApi,\n context: this.gridOptionsWrapper.getContext()\n };\n result = func(params);\n }\n if (result) {\n if (this.gridOptionsWrapper.isRowModelServerSide()) {\n console.warn('AG Grid: headerCheckboxSelection is not supported for Server Side Row Model');\n return false;\n }\n if (this.gridOptionsWrapper.isRowModelInfinite()) {\n console.warn('AG Grid: headerCheckboxSelection is not supported for Infinite Row Model');\n return false;\n }\n if (this.gridOptionsWrapper.isRowModelViewport()) {\n console.warn('AG Grid: headerCheckboxSelection is not supported for Viewport Row Model');\n return false;\n }\n // otherwise the row model is compatible, so return true\n return true;\n }\n return false;\n };\n __decorate$1m([\n Autowired('gridApi')\n ], SelectAllFeature.prototype, \"gridApi\", void 0);\n __decorate$1m([\n Autowired('columnApi')\n ], SelectAllFeature.prototype, \"columnApi\", void 0);\n __decorate$1m([\n Autowired('rowModel')\n ], SelectAllFeature.prototype, \"rowModel\", void 0);\n __decorate$1m([\n Autowired('selectionService')\n ], SelectAllFeature.prototype, \"selectionService\", void 0);\n return SelectAllFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1s = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1l = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderCellCtrl = /** @class */ (function (_super) {\n __extends$1s(HeaderCellCtrl, _super);\n function HeaderCellCtrl(column, parentRowCtrl) {\n var _this = _super.call(this, column, parentRowCtrl) || this;\n _this.refreshFunctions = [];\n _this.userHeaderClasses = new Set();\n _this.ariaDescriptionProperties = new Map();\n _this.column = column;\n return _this;\n }\n HeaderCellCtrl.prototype.setComp = function (comp, eGui, eResize, eHeaderCompWrapper) {\n var _this = this;\n _super.prototype.setGui.call(this, eGui);\n this.comp = comp;\n this.updateState();\n this.setupWidth();\n this.setupMovingCss();\n this.setupMenuClass();\n this.setupSortableClass();\n this.setupWrapTextClass();\n this.setupAutoHeight(eHeaderCompWrapper);\n this.addColumnHoverListener();\n this.setupFilterCss();\n this.setupColId();\n this.setupClassesFromColDef();\n this.setupTooltip();\n this.addActiveHeaderMouseListeners();\n this.setupSelectAll();\n this.setupUserComp();\n this.refreshAria();\n this.createManagedBean(new ResizeFeature(this.getPinned(), this.column, eResize, comp, this));\n this.createManagedBean(new HoverFeature([this.column], eGui));\n this.createManagedBean(new SetLeftFeature(this.column, eGui, this.beans));\n this.createManagedBean(new ManagedFocusFeature(eGui, {\n shouldStopEventPropagation: function (e) { return _this.shouldStopEventPropagation(e); },\n onTabKeyDown: function () { return null; },\n handleKeyDown: this.handleKeyDown.bind(this),\n onFocusIn: this.onFocusIn.bind(this),\n onFocusOut: this.onFocusOut.bind(this)\n }));\n this.addManagedListener(this.column, Column.EVENT_COL_DEF_CHANGED, this.onColDefChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_VALUE_CHANGED, this.onColumnValueChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.onColumnRowGroupChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_CHANGED, this.onColumnPivotChanged.bind(this));\n };\n HeaderCellCtrl.prototype.setupUserComp = function () {\n var compDetails = this.lookupUserCompDetails();\n this.setCompDetails(compDetails);\n };\n HeaderCellCtrl.prototype.setCompDetails = function (compDetails) {\n this.userCompDetails = compDetails;\n this.comp.setUserCompDetails(compDetails);\n };\n HeaderCellCtrl.prototype.lookupUserCompDetails = function () {\n var params = this.createParams();\n var colDef = this.column.getColDef();\n return this.userComponentFactory.getHeaderCompDetails(colDef, params);\n };\n HeaderCellCtrl.prototype.createParams = function () {\n var _this = this;\n var colDef = this.column.getColDef();\n var params = {\n column: this.column,\n displayName: this.displayName,\n enableSorting: colDef.sortable,\n enableMenu: this.menuEnabled,\n showColumnMenu: function (source) {\n _this.gridApi.showColumnMenuAfterButtonClick(_this.column, source);\n },\n progressSort: function (multiSort) {\n _this.sortController.progressSort(_this.column, !!multiSort, \"uiColumnSorted\");\n },\n setSort: function (sort, multiSort) {\n _this.sortController.setSortForColumn(_this.column, sort, !!multiSort, \"uiColumnSorted\");\n },\n api: this.gridApi,\n columnApi: this.columnApi,\n context: this.gridOptionsWrapper.getContext(),\n eGridHeader: this.getGui()\n };\n return params;\n };\n HeaderCellCtrl.prototype.setupSelectAll = function () {\n this.selectAllFeature = this.createManagedBean(new SelectAllFeature(this.column));\n this.selectAllFeature.setComp(this);\n };\n HeaderCellCtrl.prototype.getSelectAllGui = function () {\n return this.selectAllFeature.getCheckboxGui();\n };\n HeaderCellCtrl.prototype.handleKeyDown = function (e) {\n _super.prototype.handleKeyDown.call(this, e);\n if (e.key === KeyCode.SPACE) {\n this.selectAllFeature.onSpaceKeyPressed(e);\n }\n if (e.key === KeyCode.ENTER) {\n this.onEnterKeyPressed(e);\n }\n };\n HeaderCellCtrl.prototype.onEnterKeyPressed = function (e) {\n /// THIS IS BAD - we are assuming the header is not a user provided comp\n var headerComp = this.comp.getUserCompInstance();\n if (!headerComp) {\n return;\n }\n if (e.ctrlKey || e.metaKey) {\n if (this.menuEnabled && headerComp.showMenu) {\n e.preventDefault();\n headerComp.showMenu();\n }\n }\n else if (this.sortable) {\n var multiSort = e.shiftKey;\n this.sortController.progressSort(this.column, multiSort, \"uiColumnSorted\");\n }\n };\n HeaderCellCtrl.prototype.isMenuEnabled = function () {\n return this.menuEnabled;\n };\n HeaderCellCtrl.prototype.onFocusIn = function (e) {\n if (!this.getGui().contains(e.relatedTarget)) {\n var rowIndex = this.getRowIndex();\n this.focusService.setFocusedHeader(rowIndex, this.column);\n }\n this.setActiveHeader(true);\n };\n HeaderCellCtrl.prototype.onFocusOut = function (e) {\n if (this.getGui().contains(e.relatedTarget)) {\n return;\n }\n this.setActiveHeader(false);\n };\n HeaderCellCtrl.prototype.setupTooltip = function () {\n var _this = this;\n var tooltipCtrl = {\n getColumn: function () { return _this.column; },\n getColDef: function () { return _this.column.getColDef(); },\n getGui: function () { return _this.eGui; },\n getLocation: function () { return 'header'; },\n getTooltipValue: function () {\n var res = _this.column.getColDef().headerTooltip;\n return res;\n },\n };\n var tooltipFeature = this.createManagedBean(new TooltipFeature(tooltipCtrl, this.beans));\n tooltipFeature.setComp(this.comp);\n this.refreshFunctions.push(function () { return tooltipFeature.refreshToolTip(); });\n };\n HeaderCellCtrl.prototype.setupClassesFromColDef = function () {\n var _this = this;\n var refreshHeaderClasses = function () {\n var colDef = _this.column.getColDef();\n var goa = _this.gridOptionsWrapper;\n var classes = CssClassApplier.getHeaderClassesFromColDef(colDef, goa, _this.column, null);\n var oldClasses = _this.userHeaderClasses;\n _this.userHeaderClasses = new Set(classes);\n classes.forEach(function (c) {\n if (oldClasses.has(c)) {\n // class already added, no need to apply it, but remove from old set\n oldClasses.delete(c);\n }\n else {\n // class new since last time, so apply it\n _this.comp.addOrRemoveCssClass(c, true);\n }\n });\n // now old set only has classes that were applied last time, but not this time, so remove them\n oldClasses.forEach(function (c) { return _this.comp.addOrRemoveCssClass(c, false); });\n };\n this.refreshFunctions.push(refreshHeaderClasses);\n refreshHeaderClasses();\n };\n HeaderCellCtrl.prototype.setDragSource = function (eSource) {\n var _this = this;\n this.dragSourceElement = eSource;\n this.removeDragSource();\n if (!eSource) {\n return;\n }\n if (!this.draggable) {\n return;\n }\n var hideColumnOnExit = !this.gridOptionsWrapper.isSuppressDragLeaveHidesColumns();\n this.moveDragSource = {\n type: DragSourceType.HeaderCell,\n eElement: eSource,\n defaultIconName: hideColumnOnExit ? DragAndDropService.ICON_HIDE : DragAndDropService.ICON_NOT_ALLOWED,\n getDragItem: function () { return _this.createDragItem(); },\n dragItemName: this.displayName,\n onDragStarted: function () { return _this.column.setMoving(true, \"uiColumnMoved\"); },\n onDragStopped: function () { return _this.column.setMoving(false, \"uiColumnMoved\"); },\n onGridEnter: function (dragItem) {\n var _a, _b;\n if (hideColumnOnExit) {\n var unlockedColumns = ((_b = (_a = dragItem) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.filter(function (col) { return !col.getColDef().lockVisible; })) || [];\n _this.columnModel.setColumnsVisible(unlockedColumns, true, \"uiColumnMoved\");\n }\n },\n onGridExit: function (dragItem) {\n var _a, _b;\n if (hideColumnOnExit) {\n var unlockedColumns = ((_b = (_a = dragItem) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.filter(function (col) { return !col.getColDef().lockVisible; })) || [];\n _this.columnModel.setColumnsVisible(unlockedColumns, false, \"uiColumnMoved\");\n }\n },\n };\n this.dragAndDropService.addDragSource(this.moveDragSource, true);\n };\n HeaderCellCtrl.prototype.createDragItem = function () {\n var visibleState = {};\n visibleState[this.column.getId()] = this.column.isVisible();\n return {\n columns: [this.column],\n visibleState: visibleState\n };\n };\n HeaderCellCtrl.prototype.removeDragSource = function () {\n if (this.moveDragSource) {\n this.dragAndDropService.removeDragSource(this.moveDragSource);\n this.moveDragSource = undefined;\n }\n };\n HeaderCellCtrl.prototype.onColDefChanged = function () {\n this.refresh();\n };\n HeaderCellCtrl.prototype.updateState = function () {\n var colDef = this.column.getColDef();\n this.menuEnabled = this.menuFactory.isMenuEnabled(this.column) && !colDef.suppressMenu;\n this.sortable = colDef.sortable;\n this.displayName = this.calculateDisplayName();\n this.draggable = this.workOutDraggable();\n };\n HeaderCellCtrl.prototype.addRefreshFunction = function (func) {\n this.refreshFunctions.push(func);\n };\n HeaderCellCtrl.prototype.refresh = function () {\n this.updateState();\n this.refreshHeaderComp();\n this.refreshAria();\n this.refreshFunctions.forEach(function (f) { return f(); });\n };\n HeaderCellCtrl.prototype.refreshHeaderComp = function () {\n var newCompDetails = this.lookupUserCompDetails();\n var compInstance = this.comp.getUserCompInstance();\n // only try refresh if old comp exists adn it is the correct type\n var attemptRefresh = compInstance != null && this.userCompDetails.componentClass == newCompDetails.componentClass;\n var headerCompRefreshed = attemptRefresh ? this.attemptHeaderCompRefresh(newCompDetails.params) : false;\n if (headerCompRefreshed) {\n // we do this as a refresh happens after colDefs change, and it's possible the column has had it's\n // draggable property toggled. no need to call this if not refreshing, as setDragSource is done\n // as part of appendHeaderComp\n this.setDragSource(this.dragSourceElement);\n }\n else {\n this.setCompDetails(newCompDetails);\n }\n };\n HeaderCellCtrl.prototype.attemptHeaderCompRefresh = function (params) {\n var headerComp = this.comp.getUserCompInstance();\n if (!headerComp) {\n return false;\n }\n // if no refresh method, then we want to replace the headerComp\n if (!headerComp.refresh) {\n return false;\n }\n var res = headerComp.refresh(params);\n return res;\n };\n HeaderCellCtrl.prototype.calculateDisplayName = function () {\n return this.columnModel.getDisplayNameForColumn(this.column, 'header', true);\n };\n HeaderCellCtrl.prototype.checkDisplayName = function () {\n // display name can change if aggFunc different, eg sum(Gold) is now max(Gold)\n if (this.displayName !== this.calculateDisplayName()) {\n this.refresh();\n }\n };\n HeaderCellCtrl.prototype.workOutDraggable = function () {\n var colDef = this.column.getColDef();\n var isSuppressMovableColumns = this.gridOptionsWrapper.isSuppressMovableColumns();\n var colCanMove = !isSuppressMovableColumns && !colDef.suppressMovable && !colDef.lockPosition;\n // we should still be allowed drag the column, even if it can't be moved, if the column\n // can be dragged to a rowGroup or pivot drop zone\n return !!colCanMove || !!colDef.enableRowGroup || !!colDef.enablePivot;\n };\n HeaderCellCtrl.prototype.onColumnRowGroupChanged = function () {\n this.checkDisplayName();\n };\n HeaderCellCtrl.prototype.onColumnPivotChanged = function () {\n this.checkDisplayName();\n };\n HeaderCellCtrl.prototype.onColumnValueChanged = function () {\n this.checkDisplayName();\n };\n HeaderCellCtrl.prototype.setupWidth = function () {\n var _this = this;\n var listener = function () {\n _this.comp.setWidth(_this.column.getActualWidth() + 'px');\n };\n this.addManagedListener(this.column, Column.EVENT_WIDTH_CHANGED, listener);\n listener();\n };\n HeaderCellCtrl.prototype.setupMovingCss = function () {\n var _this = this;\n var listener = function () {\n // this is what makes the header go dark when it is been moved (gives impression to\n // user that the column was picked up).\n _this.comp.addOrRemoveCssClass('ag-header-cell-moving', _this.column.isMoving());\n };\n this.addManagedListener(this.column, Column.EVENT_MOVING_CHANGED, listener);\n listener();\n };\n HeaderCellCtrl.prototype.setupMenuClass = function () {\n var _this = this;\n var listener = function () {\n _this.comp.addOrRemoveCssClass('ag-column-menu-visible', _this.column.isMenuVisible());\n };\n this.addManagedListener(this.column, Column.EVENT_MENU_VISIBLE_CHANGED, listener);\n listener();\n };\n HeaderCellCtrl.prototype.setupSortableClass = function () {\n var _this = this;\n var updateSortableCssClass = function () {\n _this.comp.addOrRemoveCssClass('ag-header-cell-sortable', !!_this.sortable);\n };\n updateSortableCssClass();\n this.addRefreshFunction(updateSortableCssClass);\n this.addManagedListener(this.column, Column.EVENT_SORT_CHANGED, this.refreshAriaSort.bind(this));\n };\n HeaderCellCtrl.prototype.setupWrapTextClass = function () {\n var _this = this;\n var listener = function () {\n var wrapText = !!_this.column.getColDef().wrapHeaderText;\n _this.comp.addOrRemoveCssClass('ag-header-cell-wrap-text', wrapText);\n };\n listener();\n this.addRefreshFunction(listener);\n };\n HeaderCellCtrl.prototype.setupAutoHeight = function (wrapperElement) {\n var _this = this;\n var measureHeight = function (timesCalled) {\n if (!_this.isAlive()) {\n return;\n }\n var _a = getElementSize(_this.getGui()), paddingTop = _a.paddingTop, paddingBottom = _a.paddingBottom;\n var wrapperHeight = wrapperElement.offsetHeight;\n var autoHeight = wrapperHeight + paddingTop + paddingBottom;\n if (timesCalled < 5) {\n // if not in doc yet, means framework not yet inserted, so wait for next VM turn,\n // maybe it will be ready next VM turn\n var doc = _this.beans.gridOptionsWrapper.getDocument();\n var notYetInDom = !doc || !doc.contains(wrapperElement);\n // this happens in React, where React hasn't put any content in. we say 'possibly'\n // as a) may not be React and b) the cell could be empty anyway\n var possiblyNoContentYet = autoHeight == 0;\n if (notYetInDom || possiblyNoContentYet) {\n _this.beans.frameworkOverrides.setTimeout(function () { return measureHeight(timesCalled + 1); }, 0);\n return;\n }\n }\n _this.columnModel.setColumnHeaderHeight(_this.column, autoHeight);\n };\n var isMeasuring = false;\n var stopResizeObserver;\n var checkMeasuring = function () {\n var newValue = _this.column.isAutoHeaderHeight();\n if (newValue && !isMeasuring) {\n startMeasuring();\n }\n if (!newValue && isMeasuring) {\n stopMeasuring();\n }\n };\n var startMeasuring = function () {\n isMeasuring = true;\n measureHeight(0);\n stopResizeObserver = _this.resizeObserverService.observeResize(wrapperElement, function () { return measureHeight(0); });\n };\n var stopMeasuring = function () {\n isMeasuring = false;\n if (stopResizeObserver) {\n stopResizeObserver();\n }\n stopResizeObserver = undefined;\n };\n checkMeasuring();\n this.addDestroyFunc(function () { return stopMeasuring(); });\n // In theory we could rely on the resize observer for everything - but since it's debounced\n // it can be a little janky for smooth movement. in this case its better to react to our own events\n // And unfortunately we cant _just_ rely on our own events, since custom components can change whenever\n this.addManagedListener(this.column, Column.EVENT_WIDTH_CHANGED, function () { return isMeasuring && measureHeight(0); });\n // Displaying the sort icon changes the available area for text, so sort changes can affect height\n this.addManagedListener(this.column, Column.EVENT_SORT_CHANGED, function () {\n // Rendering changes for sort, happen after the event... not ideal\n if (isMeasuring) {\n _this.beans.frameworkOverrides.setTimeout(function () { return measureHeight(0); });\n }\n });\n this.addRefreshFunction(checkMeasuring);\n };\n HeaderCellCtrl.prototype.refreshAriaSort = function () {\n if (this.sortable) {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.comp.setAriaSort(getAriaSortState(this.column));\n this.setAriaDescriptionProperty('sort', translate('ariaSortableColumn', 'Press ENTER to sort.'));\n }\n else {\n this.comp.setAriaSort();\n this.setAriaDescriptionProperty('sort', null);\n }\n };\n HeaderCellCtrl.prototype.refreshAriaMenu = function () {\n if (this.menuEnabled) {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n this.setAriaDescriptionProperty('menu', translate('ariaMenuColumn', 'Press CTRL ENTER to open column menu.'));\n }\n else {\n this.setAriaDescriptionProperty('menu', null);\n }\n };\n HeaderCellCtrl.prototype.setAriaDescriptionProperty = function (property, value) {\n if (value != null) {\n this.ariaDescriptionProperties.set(property, value);\n }\n else {\n this.ariaDescriptionProperties.delete(property);\n }\n };\n HeaderCellCtrl.prototype.refreshAriaDescription = function () {\n var descriptionArray = Array.from(this.ariaDescriptionProperties.values());\n this.comp.setAriaDescription(descriptionArray.length ? descriptionArray.join(' ') : undefined);\n };\n HeaderCellCtrl.prototype.refreshAria = function () {\n this.refreshAriaSort();\n this.refreshAriaMenu();\n this.refreshAriaDescription();\n };\n HeaderCellCtrl.prototype.addColumnHoverListener = function () {\n var _this = this;\n var listener = function () {\n if (!_this.gridOptionsWrapper.isColumnHoverHighlight()) {\n return;\n }\n var isHovered = _this.columnHoverService.isHovered(_this.column);\n _this.comp.addOrRemoveCssClass('ag-column-hover', isHovered);\n };\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_HOVER_CHANGED, listener);\n listener();\n };\n HeaderCellCtrl.prototype.setupFilterCss = function () {\n var _this = this;\n var listener = function () {\n _this.comp.addOrRemoveCssClass('ag-header-cell-filtered', _this.column.isFilterActive());\n };\n this.addManagedListener(this.column, Column.EVENT_FILTER_ACTIVE_CHANGED, listener);\n listener();\n };\n HeaderCellCtrl.prototype.setupColId = function () {\n this.comp.setColId(this.column.getColId());\n };\n HeaderCellCtrl.prototype.addActiveHeaderMouseListeners = function () {\n var _this = this;\n var listener = function (e) { return _this.setActiveHeader(e.type === 'mouseenter'); };\n this.addManagedListener(this.getGui(), 'mouseenter', listener);\n this.addManagedListener(this.getGui(), 'mouseleave', listener);\n };\n HeaderCellCtrl.prototype.setActiveHeader = function (active) {\n this.comp.addOrRemoveCssClass('ag-header-active', active);\n };\n __decorate$1l([\n Autowired('columnModel')\n ], HeaderCellCtrl.prototype, \"columnModel\", void 0);\n __decorate$1l([\n Autowired('columnHoverService')\n ], HeaderCellCtrl.prototype, \"columnHoverService\", void 0);\n __decorate$1l([\n Autowired('sortController')\n ], HeaderCellCtrl.prototype, \"sortController\", void 0);\n __decorate$1l([\n Autowired('menuFactory')\n ], HeaderCellCtrl.prototype, \"menuFactory\", void 0);\n __decorate$1l([\n Autowired('dragAndDropService')\n ], HeaderCellCtrl.prototype, \"dragAndDropService\", void 0);\n __decorate$1l([\n Autowired('resizeObserverService')\n ], HeaderCellCtrl.prototype, \"resizeObserverService\", void 0);\n __decorate$1l([\n Autowired('gridApi')\n ], HeaderCellCtrl.prototype, \"gridApi\", void 0);\n __decorate$1l([\n Autowired('columnApi')\n ], HeaderCellCtrl.prototype, \"columnApi\", void 0);\n __decorate$1l([\n PreDestroy\n ], HeaderCellCtrl.prototype, \"removeDragSource\", null);\n return HeaderCellCtrl;\n}(AbstractHeaderCellCtrl));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1r = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1k = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GroupResizeFeature = /** @class */ (function (_super) {\n __extends$1r(GroupResizeFeature, _super);\n function GroupResizeFeature(comp, eResize, pinned, columnGroup) {\n var _this = _super.call(this) || this;\n _this.eResize = eResize;\n _this.comp = comp;\n _this.pinned = pinned;\n _this.columnGroup = columnGroup;\n return _this;\n }\n GroupResizeFeature.prototype.postConstruct = function () {\n var _this = this;\n if (!this.columnGroup.isResizable()) {\n this.comp.addOrRemoveResizableCssClass('ag-hidden', true);\n return;\n }\n var finishedWithResizeFunc = this.horizontalResizeService.addResizeBar({\n eResizeBar: this.eResize,\n onResizeStart: this.onResizeStart.bind(this),\n onResizing: this.onResizing.bind(this, false),\n onResizeEnd: this.onResizing.bind(this, true)\n });\n this.addDestroyFunc(finishedWithResizeFunc);\n if (!this.gridOptionsWrapper.isSuppressAutoSize()) {\n var skipHeaderOnAutoSize_1 = this.gridOptionsWrapper.isSkipHeaderOnAutoSize();\n this.eResize.addEventListener('dblclick', function () {\n // get list of all the column keys we are responsible for\n var keys = [];\n var leafCols = _this.columnGroup.getDisplayedLeafColumns();\n leafCols.forEach(function (column) {\n // not all cols in the group may be participating with auto-resize\n if (!column.getColDef().suppressAutoSize) {\n keys.push(column.getColId());\n }\n });\n if (keys.length > 0) {\n _this.columnModel.autoSizeColumns({\n columns: keys,\n skipHeader: skipHeaderOnAutoSize_1,\n stopAtGroup: _this.columnGroup,\n source: 'uiColumnResized'\n });\n }\n _this.resizeLeafColumnsToFit();\n });\n }\n };\n GroupResizeFeature.prototype.onResizeStart = function (shiftKey) {\n var _this = this;\n this.calculateInitialValues();\n var takeFromGroup = null;\n if (shiftKey) {\n takeFromGroup = this.columnModel.getDisplayedGroupAfter(this.columnGroup);\n }\n if (takeFromGroup) {\n var takeFromLeafCols = takeFromGroup.getDisplayedLeafColumns();\n this.resizeTakeFromCols = takeFromLeafCols.filter(function (col) { return col.isResizable(); });\n this.resizeTakeFromStartWidth = 0;\n this.resizeTakeFromCols.forEach(function (col) { return _this.resizeTakeFromStartWidth += col.getActualWidth(); });\n this.resizeTakeFromRatios = [];\n this.resizeTakeFromCols.forEach(function (col) { return _this.resizeTakeFromRatios.push(col.getActualWidth() / _this.resizeTakeFromStartWidth); });\n }\n else {\n this.resizeTakeFromCols = null;\n this.resizeTakeFromStartWidth = null;\n this.resizeTakeFromRatios = null;\n }\n this.comp.addOrRemoveCssClass('ag-column-resizing', true);\n };\n GroupResizeFeature.prototype.onResizing = function (finished, resizeAmount) {\n var resizeAmountNormalised = this.normaliseDragChange(resizeAmount);\n var width = this.resizeStartWidth + resizeAmountNormalised;\n this.resizeColumns(width, finished);\n };\n GroupResizeFeature.prototype.resizeLeafColumnsToFit = function () {\n var preferredSize = this.autoWidthCalculator.getPreferredWidthForColumnGroup(this.columnGroup);\n this.calculateInitialValues();\n if (preferredSize > this.resizeStartWidth) {\n this.resizeColumns(preferredSize, true);\n }\n };\n GroupResizeFeature.prototype.resizeColumns = function (totalWidth, finished) {\n if (finished === void 0) { finished = true; }\n var resizeSets = [];\n resizeSets.push({\n columns: this.resizeCols,\n ratios: this.resizeRatios,\n width: totalWidth\n });\n if (this.resizeTakeFromCols) {\n var diff = totalWidth - this.resizeStartWidth;\n resizeSets.push({\n columns: this.resizeTakeFromCols,\n ratios: this.resizeTakeFromRatios,\n width: this.resizeTakeFromStartWidth - diff\n });\n }\n this.columnModel.resizeColumnSets({\n resizeSets: resizeSets,\n finished: finished,\n source: 'uiColumnDragged'\n });\n if (finished) {\n this.comp.addOrRemoveCssClass('ag-column-resizing', false);\n }\n };\n GroupResizeFeature.prototype.calculateInitialValues = function () {\n var _this = this;\n var leafCols = this.columnGroup.getDisplayedLeafColumns();\n this.resizeCols = leafCols.filter(function (col) { return col.isResizable(); });\n this.resizeStartWidth = 0;\n this.resizeCols.forEach(function (col) { return _this.resizeStartWidth += col.getActualWidth(); });\n this.resizeRatios = [];\n this.resizeCols.forEach(function (col) { return _this.resizeRatios.push(col.getActualWidth() / _this.resizeStartWidth); });\n };\n // optionally inverts the drag, depending on pinned and RTL\n // note - this method is duplicated in RenderedHeaderCell - should refactor out?\n GroupResizeFeature.prototype.normaliseDragChange = function (dragChange) {\n var result = dragChange;\n if (this.gridOptionsWrapper.isEnableRtl()) {\n // for RTL, dragging left makes the col bigger, except when pinning left\n if (this.pinned !== Constants.PINNED_LEFT) {\n result *= -1;\n }\n }\n else if (this.pinned === Constants.PINNED_RIGHT) {\n // for LTR (ie normal), dragging left makes the col smaller, except when pinning right\n result *= -1;\n }\n return result;\n };\n __decorate$1k([\n Autowired('horizontalResizeService')\n ], GroupResizeFeature.prototype, \"horizontalResizeService\", void 0);\n __decorate$1k([\n Autowired('autoWidthCalculator')\n ], GroupResizeFeature.prototype, \"autoWidthCalculator\", void 0);\n __decorate$1k([\n Autowired('columnModel')\n ], GroupResizeFeature.prototype, \"columnModel\", void 0);\n __decorate$1k([\n PostConstruct\n ], GroupResizeFeature.prototype, \"postConstruct\", null);\n return GroupResizeFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1q = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1j = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GroupWidthFeature = /** @class */ (function (_super) {\n __extends$1q(GroupWidthFeature, _super);\n function GroupWidthFeature(comp, columnGroup) {\n var _this = _super.call(this) || this;\n // the children can change, we keep destroy functions related to listening to the children here\n _this.removeChildListenersFuncs = [];\n _this.columnGroup = columnGroup;\n _this.comp = comp;\n return _this;\n }\n GroupWidthFeature.prototype.postConstruct = function () {\n // we need to listen to changes in child columns, as they impact our width\n this.addListenersToChildrenColumns();\n // the children belonging to this group can change, so we need to add and remove listeners as they change\n this.addManagedListener(this.columnGroup, ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED, this.onDisplayedChildrenChanged.bind(this));\n this.onWidthChanged();\n // the child listeners are not tied to this components life-cycle, as children can get added and removed\n // to the group - hence they are on a different life-cycle. so we must make sure the existing children\n // listeners are removed when we finally get destroyed\n this.addDestroyFunc(this.removeListenersOnChildrenColumns.bind(this));\n };\n GroupWidthFeature.prototype.addListenersToChildrenColumns = function () {\n var _this = this;\n // first destroy any old listeners\n this.removeListenersOnChildrenColumns();\n // now add new listeners to the new set of children\n var widthChangedListener = this.onWidthChanged.bind(this);\n this.columnGroup.getLeafColumns().forEach(function (column) {\n column.addEventListener(Column.EVENT_WIDTH_CHANGED, widthChangedListener);\n column.addEventListener(Column.EVENT_VISIBLE_CHANGED, widthChangedListener);\n _this.removeChildListenersFuncs.push(function () {\n column.removeEventListener(Column.EVENT_WIDTH_CHANGED, widthChangedListener);\n column.removeEventListener(Column.EVENT_VISIBLE_CHANGED, widthChangedListener);\n });\n });\n };\n GroupWidthFeature.prototype.removeListenersOnChildrenColumns = function () {\n this.removeChildListenersFuncs.forEach(function (func) { return func(); });\n this.removeChildListenersFuncs = [];\n };\n GroupWidthFeature.prototype.onDisplayedChildrenChanged = function () {\n this.addListenersToChildrenColumns();\n this.onWidthChanged();\n };\n GroupWidthFeature.prototype.onWidthChanged = function () {\n this.comp.setWidth(this.columnGroup.getActualWidth() + 'px');\n };\n __decorate$1j([\n PostConstruct\n ], GroupWidthFeature.prototype, \"postConstruct\", null);\n return GroupWidthFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1p = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1i = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderGroupCellCtrl = /** @class */ (function (_super) {\n __extends$1p(HeaderGroupCellCtrl, _super);\n function HeaderGroupCellCtrl(columnGroup, parentRowCtrl) {\n var _this = _super.call(this, columnGroup, parentRowCtrl) || this;\n _this.columnGroup = columnGroup;\n return _this;\n }\n HeaderGroupCellCtrl.prototype.setComp = function (comp, eGui, eResize) {\n _super.prototype.setGui.call(this, eGui);\n this.comp = comp;\n this.displayName = this.columnModel.getDisplayNameForColumnGroup(this.columnGroup, 'header');\n this.addClasses();\n this.addAttributes();\n this.setupMovingCss();\n this.setupExpandable();\n this.setupTooltip();\n this.setupUserComp();\n var pinned = this.getParentRowCtrl().getPinned();\n var leafCols = this.columnGroup.getProvidedColumnGroup().getLeafColumns();\n this.createManagedBean(new HoverFeature(leafCols, eGui));\n this.createManagedBean(new SetLeftFeature(this.columnGroup, eGui, this.beans));\n this.createManagedBean(new GroupWidthFeature(comp, this.columnGroup));\n this.groupResizeFeature = this.createManagedBean(new GroupResizeFeature(comp, eResize, pinned, this.columnGroup));\n this.createManagedBean(new ManagedFocusFeature(eGui, {\n shouldStopEventPropagation: this.shouldStopEventPropagation.bind(this),\n onTabKeyDown: function () { return undefined; },\n handleKeyDown: this.handleKeyDown.bind(this),\n onFocusIn: this.onFocusIn.bind(this)\n }));\n };\n HeaderGroupCellCtrl.prototype.resizeLeafColumnsToFit = function () {\n this.groupResizeFeature.onResizeStart(false);\n this.groupResizeFeature.resizeLeafColumnsToFit();\n };\n HeaderGroupCellCtrl.prototype.setupUserComp = function () {\n var _this = this;\n var displayName = this.displayName;\n var params = {\n displayName: this.displayName,\n columnGroup: this.columnGroup,\n setExpanded: function (expanded) {\n _this.columnModel.setColumnGroupOpened(_this.columnGroup.getProvidedColumnGroup(), expanded, \"gridInitializing\");\n },\n api: this.gridApi,\n columnApi: this.columnApi,\n context: this.gridOptionsWrapper.getContext()\n };\n if (!displayName) {\n var columnGroup = this.columnGroup;\n var leafCols = columnGroup.getLeafColumns();\n // find the top most column group that represents the same columns. so if we are dragging a group, we also\n // want to visually show the parent groups dragging for the same column set. for example imaging 5 levels\n // of grouping, with each group only containing the next group, and the last group containing three columns,\n // then when you move any group (even the lowest level group) you are in-fact moving all the groups, as all\n // the groups represent the same column set.\n while (columnGroup.getParent() && columnGroup.getParent().getLeafColumns().length === leafCols.length) {\n columnGroup = columnGroup.getParent();\n }\n var colGroupDef = columnGroup.getColGroupDef();\n if (colGroupDef) {\n displayName = colGroupDef.headerName;\n }\n if (!displayName) {\n displayName = leafCols ? this.columnModel.getDisplayNameForColumn(leafCols[0], 'header', true) : '';\n }\n }\n var compDetails = this.userComponentFactory.getHeaderGroupCompDetails(params);\n this.comp.setUserCompDetails(compDetails);\n };\n HeaderGroupCellCtrl.prototype.setupTooltip = function () {\n var _this = this;\n var colGroupDef = this.columnGroup.getColGroupDef();\n var tooltipCtrl = {\n getColumn: function () { return _this.columnGroup; },\n getGui: function () { return _this.eGui; },\n getLocation: function () { return 'headerGroup'; },\n getTooltipValue: function () { return colGroupDef && colGroupDef.headerTooltip; }\n };\n if (colGroupDef) {\n tooltipCtrl.getColDef = function () { return colGroupDef; };\n }\n var tooltipFeature = this.createManagedBean(new TooltipFeature(tooltipCtrl, this.beans));\n tooltipFeature.setComp(this.comp);\n };\n HeaderGroupCellCtrl.prototype.setupExpandable = function () {\n var providedColGroup = this.columnGroup.getProvidedColumnGroup();\n this.refreshExpanded();\n this.addManagedListener(providedColGroup, ProvidedColumnGroup.EVENT_EXPANDABLE_CHANGED, this.refreshExpanded.bind(this));\n this.addManagedListener(providedColGroup, ProvidedColumnGroup.EVENT_EXPANDED_CHANGED, this.refreshExpanded.bind(this));\n };\n HeaderGroupCellCtrl.prototype.refreshExpanded = function () {\n var column = this.columnGroup;\n this.expandable = column.isExpandable();\n var expanded = column.isExpanded();\n if (this.expandable) {\n this.comp.setAriaExpanded(expanded ? 'true' : 'false');\n }\n else {\n this.comp.setAriaExpanded(undefined);\n }\n };\n HeaderGroupCellCtrl.prototype.addAttributes = function () {\n this.comp.setColId(this.columnGroup.getUniqueId());\n };\n HeaderGroupCellCtrl.prototype.addClasses = function () {\n var _this = this;\n var colGroupDef = this.columnGroup.getColGroupDef();\n var classes = CssClassApplier.getHeaderClassesFromColDef(colGroupDef, this.gridOptionsWrapper, null, this.columnGroup);\n // having different classes below allows the style to not have a bottom border\n // on the group header, if no group is specified\n classes.push(this.columnGroup.isPadding() ? \"ag-header-group-cell-no-group\" : \"ag-header-group-cell-with-group\");\n classes.forEach(function (c) { return _this.comp.addOrRemoveCssClass(c, true); });\n };\n HeaderGroupCellCtrl.prototype.setupMovingCss = function () {\n var _this = this;\n var providedColumnGroup = this.columnGroup.getProvidedColumnGroup();\n var leafColumns = providedColumnGroup.getLeafColumns();\n // this function adds or removes the moving css, based on if the col is moving.\n // this is what makes the header go dark when it is been moved (gives impression to\n // user that the column was picked up).\n var listener = function () { return _this.comp.addOrRemoveCssClass('ag-header-cell-moving', _this.columnGroup.isMoving()); };\n leafColumns.forEach(function (col) {\n _this.addManagedListener(col, Column.EVENT_MOVING_CHANGED, listener);\n });\n listener();\n };\n HeaderGroupCellCtrl.prototype.onFocusIn = function (e) {\n if (!this.eGui.contains(e.relatedTarget)) {\n var rowIndex = this.getRowIndex();\n this.beans.focusService.setFocusedHeader(rowIndex, this.columnGroup);\n }\n };\n HeaderGroupCellCtrl.prototype.handleKeyDown = function (e) {\n _super.prototype.handleKeyDown.call(this, e);\n var wrapperHasFocus = this.getWrapperHasFocus();\n if (!this.expandable || !wrapperHasFocus) {\n return;\n }\n if (e.key === KeyCode.ENTER) {\n var column = this.columnGroup;\n var newExpandedValue = !column.isExpanded();\n this.columnModel.setColumnGroupOpened(column.getProvidedColumnGroup(), newExpandedValue, \"uiColumnExpanded\");\n }\n };\n // unlike columns, this will only get called once, as we don't react on props on column groups\n // (we will always destroy and recreate this comp if something changes)\n HeaderGroupCellCtrl.prototype.setDragSource = function (eHeaderGroup) {\n var _this = this;\n if (this.isSuppressMoving()) {\n return;\n }\n var allLeafColumns = this.columnGroup.getProvidedColumnGroup().getLeafColumns();\n var hideColumnOnExit = !this.gridOptionsWrapper.isSuppressDragLeaveHidesColumns();\n var dragSource = {\n type: DragSourceType.HeaderCell,\n eElement: eHeaderGroup,\n defaultIconName: hideColumnOnExit ? DragAndDropService.ICON_HIDE : DragAndDropService.ICON_NOT_ALLOWED,\n dragItemName: this.displayName,\n // we add in the original group leaf columns, so we move both visible and non-visible items\n getDragItem: this.getDragItemForGroup.bind(this),\n onDragStarted: function () { return allLeafColumns.forEach(function (col) { return col.setMoving(true, \"uiColumnDragged\"); }); },\n onDragStopped: function () { return allLeafColumns.forEach(function (col) { return col.setMoving(false, \"uiColumnDragged\"); }); },\n onGridEnter: function (dragItem) {\n var _a, _b;\n if (hideColumnOnExit) {\n var unlockedColumns = ((_b = (_a = dragItem) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.filter(function (col) { return !col.getColDef().lockVisible; })) || [];\n _this.columnModel.setColumnsVisible(unlockedColumns, true, \"uiColumnMoved\");\n }\n },\n onGridExit: function (dragItem) {\n var _a, _b;\n if (hideColumnOnExit) {\n var unlockedColumns = ((_b = (_a = dragItem) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.filter(function (col) { return !col.getColDef().lockVisible; })) || [];\n _this.columnModel.setColumnsVisible(unlockedColumns, false, \"uiColumnMoved\");\n }\n },\n };\n this.dragAndDropService.addDragSource(dragSource, true);\n this.addDestroyFunc(function () { return _this.dragAndDropService.removeDragSource(dragSource); });\n };\n // when moving the columns, we want to move all the columns (contained within the DragItem) in this group in one go,\n // and in the order they are currently in the screen.\n HeaderGroupCellCtrl.prototype.getDragItemForGroup = function () {\n var allColumnsOriginalOrder = this.columnGroup.getProvidedColumnGroup().getLeafColumns();\n // capture visible state, used when re-entering grid to dictate which columns should be visible\n var visibleState = {};\n allColumnsOriginalOrder.forEach(function (column) { return visibleState[column.getId()] = column.isVisible(); });\n var allColumnsCurrentOrder = [];\n this.columnModel.getAllDisplayedColumns().forEach(function (column) {\n if (allColumnsOriginalOrder.indexOf(column) >= 0) {\n allColumnsCurrentOrder.push(column);\n removeFromArray(allColumnsOriginalOrder, column);\n }\n });\n // we are left with non-visible columns, stick these in at the end\n allColumnsOriginalOrder.forEach(function (column) { return allColumnsCurrentOrder.push(column); });\n // create and return dragItem\n return {\n columns: allColumnsCurrentOrder,\n visibleState: visibleState\n };\n };\n HeaderGroupCellCtrl.prototype.isSuppressMoving = function () {\n // if any child is fixed, then don't allow moving\n var childSuppressesMoving = false;\n this.columnGroup.getLeafColumns().forEach(function (column) {\n if (column.getColDef().suppressMovable || column.getColDef().lockPosition) {\n childSuppressesMoving = true;\n }\n });\n var result = childSuppressesMoving || this.gridOptionsWrapper.isSuppressMovableColumns();\n return result;\n };\n __decorate$1i([\n Autowired('columnModel')\n ], HeaderGroupCellCtrl.prototype, \"columnModel\", void 0);\n __decorate$1i([\n Autowired('dragAndDropService')\n ], HeaderGroupCellCtrl.prototype, \"dragAndDropService\", void 0);\n __decorate$1i([\n Autowired('gridApi')\n ], HeaderGroupCellCtrl.prototype, \"gridApi\", void 0);\n __decorate$1i([\n Autowired('columnApi')\n ], HeaderGroupCellCtrl.prototype, \"columnApi\", void 0);\n return HeaderGroupCellCtrl;\n}(AbstractHeaderCellCtrl));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1o = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1h = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar instanceIdSequence = 0;\nvar HeaderRowCtrl = /** @class */ (function (_super) {\n __extends$1o(HeaderRowCtrl, _super);\n function HeaderRowCtrl(rowIndex, pinned, type) {\n var _this = _super.call(this) || this;\n _this.instanceId = instanceIdSequence++;\n _this.headerCellCtrls = {};\n _this.rowIndex = rowIndex;\n _this.pinned = pinned;\n _this.type = type;\n return _this;\n }\n HeaderRowCtrl.prototype.getInstanceId = function () {\n return this.instanceId;\n };\n HeaderRowCtrl.prototype.setComp = function (comp) {\n this.comp = comp;\n this.onRowHeightChanged();\n this.onVirtualColumnsChanged();\n this.setWidth();\n this.addEventListeners();\n if (isBrowserSafari()) {\n // fix for a Safari rendering bug that caused the header to flicker above chart panels\n // as you move the mouse over the header\n this.comp.setTransform('translateZ(0)');\n }\n comp.setAriaRowIndex(this.rowIndex + 1);\n };\n HeaderRowCtrl.prototype.addEventListeners = function () {\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_RESIZED, this.onColumnResized.bind(this));\n // when print layout changes, it changes what columns are in what section\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, this.onDisplayedColumnsChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_VIRTUAL_COLUMNS_CHANGED, this.onVirtualColumnsChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_HEADER_HEIGHT_CHANGED, this.onRowHeightChanged.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT, this.onRowHeightChanged.bind(this));\n };\n HeaderRowCtrl.prototype.getHeaderCellCtrl = function (column) {\n return values(this.headerCellCtrls).find(function (cellCtrl) { return cellCtrl.getColumnGroupChild() === column; });\n };\n HeaderRowCtrl.prototype.onDisplayedColumnsChanged = function () {\n this.onVirtualColumnsChanged();\n this.setWidth();\n this.onRowHeightChanged();\n };\n HeaderRowCtrl.prototype.getType = function () {\n return this.type;\n };\n HeaderRowCtrl.prototype.onColumnResized = function () {\n this.setWidth();\n };\n HeaderRowCtrl.prototype.setWidth = function () {\n var width = this.getWidthForRow();\n this.comp.setWidth(width + \"px\");\n };\n HeaderRowCtrl.prototype.getWidthForRow = function () {\n var printLayout = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n if (printLayout) {\n var pinned = this.pinned != null;\n if (pinned) {\n return 0;\n }\n return this.columnModel.getContainerWidth(Constants.PINNED_RIGHT)\n + this.columnModel.getContainerWidth(Constants.PINNED_LEFT)\n + this.columnModel.getContainerWidth(null);\n }\n // if not printing, just return the width as normal\n return this.columnModel.getContainerWidth(this.pinned);\n };\n HeaderRowCtrl.prototype.onRowHeightChanged = function () {\n var headerRowCount = this.columnModel.getHeaderRowCount();\n var sizes = [];\n var numberOfFloating = 0;\n if (this.columnModel.hasFloatingFilters()) {\n headerRowCount++;\n numberOfFloating = 1;\n }\n var groupHeight = this.columnModel.getColumnGroupHeaderRowHeight();\n var headerHeight = this.columnModel.getColumnHeaderRowHeight();\n var numberOfNonGroups = 1 + numberOfFloating;\n var numberOfGroups = headerRowCount - numberOfNonGroups;\n for (var i = 0; i < numberOfGroups; i++) {\n sizes.push(groupHeight);\n }\n sizes.push(headerHeight);\n for (var i = 0; i < numberOfFloating; i++) {\n sizes.push(this.gridOptionsWrapper.getFloatingFiltersHeight());\n }\n var topOffset = 0;\n for (var i = 0; i < this.rowIndex; i++) {\n topOffset += sizes[i];\n }\n var thisRowHeight = sizes[this.rowIndex] + 'px';\n this.comp.setTop(topOffset + 'px');\n this.comp.setHeight(thisRowHeight);\n };\n HeaderRowCtrl.prototype.getPinned = function () {\n return this.pinned;\n };\n HeaderRowCtrl.prototype.getRowIndex = function () {\n return this.rowIndex;\n };\n HeaderRowCtrl.prototype.onVirtualColumnsChanged = function () {\n var _this = this;\n var oldCtrls = this.headerCellCtrls;\n this.headerCellCtrls = {};\n var columns = this.getColumnsInViewport();\n columns.forEach(function (child) {\n // skip groups that have no displayed children. this can happen when the group is broken,\n // and this section happens to have nothing to display for the open / closed state.\n // (a broken group is one that is split, ie columns in the group have a non-group column\n // in between them)\n if (child.isEmptyGroup()) {\n return;\n }\n var idOfChild = child.getUniqueId();\n // if we already have this cell rendered, do nothing\n var headerCtrl = oldCtrls[idOfChild];\n delete oldCtrls[idOfChild];\n // it's possible there is a new Column with the same ID, but it's for a different Column.\n // this is common with pivoting, where the pivot cols change, but the id's are still pivot_0,\n // pivot_1 etc. so if new col but same ID, need to remove the old col here first as we are\n // about to replace it in the this.headerComps map.\n var forOldColumn = headerCtrl && headerCtrl.getColumnGroupChild() != child;\n if (forOldColumn) {\n _this.destroyBean(headerCtrl);\n headerCtrl = undefined;\n }\n if (headerCtrl == null) {\n switch (_this.type) {\n case HeaderRowType.FLOATING_FILTER:\n headerCtrl = _this.createBean(new HeaderFilterCellCtrl(child, _this));\n break;\n case HeaderRowType.COLUMN_GROUP:\n headerCtrl = _this.createBean(new HeaderGroupCellCtrl(child, _this));\n break;\n default:\n headerCtrl = _this.createBean(new HeaderCellCtrl(child, _this));\n break;\n }\n }\n _this.headerCellCtrls[idOfChild] = headerCtrl;\n });\n // we want to keep columns that are focused, otherwise keyboard navigation breaks\n var isFocusedAndDisplayed = function (ctrl) {\n var isFocused = _this.focusService.isHeaderWrapperFocused(ctrl);\n if (!isFocused) {\n return false;\n }\n var isDisplayed = _this.columnModel.isDisplayed(ctrl.getColumnGroupChild());\n return isDisplayed;\n };\n iterateObject(oldCtrls, function (id, oldCtrl) {\n var keepCtrl = isFocusedAndDisplayed(oldCtrl);\n if (keepCtrl) {\n _this.headerCellCtrls[id] = oldCtrl;\n }\n else {\n _this.destroyBean(oldCtrl);\n }\n });\n var ctrlsToDisplay = getAllValuesInObject(this.headerCellCtrls);\n this.comp.setHeaderCtrls(ctrlsToDisplay);\n };\n HeaderRowCtrl.prototype.destroyCtrls = function () {\n var _this = this;\n iterateObject(this.headerCellCtrls, function (key, ctrl) {\n _this.destroyBean(ctrl);\n });\n this.headerCellCtrls = {};\n };\n HeaderRowCtrl.prototype.getColumnsInViewport = function () {\n var printLayout = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n return printLayout ? this.getColumnsInViewportPrintLayout() : this.getColumnsInViewportNormalLayout();\n };\n HeaderRowCtrl.prototype.getColumnsInViewportPrintLayout = function () {\n var _this = this;\n // for print layout, we add all columns into the center\n if (this.pinned != null) {\n return [];\n }\n var viewportColumns = [];\n var actualDepth = this.getActualDepth();\n [Constants.PINNED_LEFT, null, Constants.PINNED_RIGHT].forEach(function (pinned) {\n var items = _this.columnModel.getVirtualHeaderGroupRow(pinned, actualDepth);\n viewportColumns = viewportColumns.concat(items);\n });\n return viewportColumns;\n };\n HeaderRowCtrl.prototype.getActualDepth = function () {\n return this.type == HeaderRowType.FLOATING_FILTER ? this.rowIndex - 1 : this.rowIndex;\n };\n HeaderRowCtrl.prototype.getColumnsInViewportNormalLayout = function () {\n // when in normal layout, we add the columns for that container only\n return this.columnModel.getVirtualHeaderGroupRow(this.pinned, this.getActualDepth());\n };\n HeaderRowCtrl.prototype.focusHeader = function (column, event) {\n var allCtrls = getAllValuesInObject(this.headerCellCtrls);\n var ctrl = allCtrls.find(function (ctrl) { return ctrl.getColumnGroupChild() == column; });\n if (!ctrl) {\n return false;\n }\n ctrl.focus(event);\n return true;\n };\n __decorate$1h([\n Autowired('columnModel')\n ], HeaderRowCtrl.prototype, \"columnModel\", void 0);\n __decorate$1h([\n Autowired('focusService')\n ], HeaderRowCtrl.prototype, \"focusService\", void 0);\n __decorate$1h([\n PreDestroy\n ], HeaderRowCtrl.prototype, \"destroyCtrls\", null);\n return HeaderRowCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1n = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1g = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$c = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$a = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$c(arguments[i]));\n return ar;\n};\nvar HeaderRowContainerCtrl = /** @class */ (function (_super) {\n __extends$1n(HeaderRowContainerCtrl, _super);\n function HeaderRowContainerCtrl(pinned) {\n var _this = _super.call(this) || this;\n _this.groupsRowCtrls = [];\n _this.pinned = pinned;\n return _this;\n }\n HeaderRowContainerCtrl.prototype.setComp = function (comp, eGui) {\n this.comp = comp;\n this.eViewport = eGui;\n this.setupCenterWidth();\n this.setupPinnedWidth();\n this.setupDragAndDrop(this.eViewport);\n this.addManagedListener(this.eventService, Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this));\n this.addManagedListener(this.eViewport, 'scroll', this.resetScrollLeft.bind(this));\n this.ctrlsService.registerHeaderContainer(this, this.pinned);\n if (this.columnModel.isReady()) {\n this.refresh();\n }\n };\n HeaderRowContainerCtrl.prototype.setupDragAndDrop = function (dropContainer) {\n var bodyDropTarget = new BodyDropTarget(this.pinned, dropContainer);\n this.createManagedBean(bodyDropTarget);\n };\n HeaderRowContainerCtrl.prototype.refresh = function (keepColumns) {\n var _this = this;\n if (keepColumns === void 0) { keepColumns = false; }\n var sequence = new NumberSequence();\n var focusedHeaderPosition = this.focusService.getFocusHeaderToUseAfterRefresh();\n var refreshColumnGroups = function () {\n var groupRowCount = _this.columnModel.getHeaderRowCount() - 1;\n _this.groupsRowCtrls = _this.destroyBeans(_this.groupsRowCtrls);\n for (var i = 0; i < groupRowCount; i++) {\n var ctrl = _this.createBean(new HeaderRowCtrl(sequence.next(), _this.pinned, HeaderRowType.COLUMN_GROUP));\n _this.groupsRowCtrls.push(ctrl);\n }\n };\n var refreshColumns = function () {\n var rowIndex = sequence.next();\n var needNewInstance = _this.columnsRowCtrl == null || !keepColumns || _this.columnsRowCtrl.getRowIndex() !== rowIndex;\n if (needNewInstance) {\n _this.destroyBean(_this.columnsRowCtrl);\n _this.columnsRowCtrl = _this.createBean(new HeaderRowCtrl(rowIndex, _this.pinned, HeaderRowType.COLUMN));\n }\n };\n var refreshFilters = function () {\n var includeFloatingFilter = _this.columnModel.hasFloatingFilters();\n var destroyPreviousComp = function () {\n _this.filtersRowCtrl = _this.destroyBean(_this.filtersRowCtrl);\n };\n if (!includeFloatingFilter) {\n destroyPreviousComp();\n return;\n }\n var rowIndex = sequence.next();\n if (_this.filtersRowCtrl) {\n var rowIndexMismatch = _this.filtersRowCtrl.getRowIndex() !== rowIndex;\n if (!keepColumns || rowIndexMismatch) {\n destroyPreviousComp();\n }\n }\n if (!_this.filtersRowCtrl) {\n _this.filtersRowCtrl = _this.createBean(new HeaderRowCtrl(rowIndex, _this.pinned, HeaderRowType.FLOATING_FILTER));\n }\n };\n refreshColumnGroups();\n refreshColumns();\n refreshFilters();\n var allCtrls = this.getAllCtrls();\n this.comp.setCtrls(allCtrls);\n this.restoreFocusOnHeader(focusedHeaderPosition);\n };\n HeaderRowContainerCtrl.prototype.restoreFocusOnHeader = function (position) {\n if (position == null || position.column.getPinned() != this.pinned) {\n return;\n }\n this.focusService.focusHeaderPosition({ headerPosition: position });\n };\n HeaderRowContainerCtrl.prototype.getAllCtrls = function () {\n var res = __spread$a(this.groupsRowCtrls, [this.columnsRowCtrl]);\n if (this.filtersRowCtrl) {\n res.push(this.filtersRowCtrl);\n }\n return res;\n };\n // grid cols have changed - this also means the number of rows in the header can have\n // changed. so we remove all the old rows and insert new ones for a complete refresh\n HeaderRowContainerCtrl.prototype.onGridColumnsChanged = function () {\n this.refresh(true);\n };\n HeaderRowContainerCtrl.prototype.setupCenterWidth = function () {\n var _this = this;\n if (this.pinned != null) {\n return;\n }\n this.createManagedBean(new CenterWidthFeature(function (width) { return _this.comp.setCenterWidth(width + \"px\"); }));\n };\n HeaderRowContainerCtrl.prototype.setHorizontalScroll = function (offset) {\n this.comp.setContainerTransform(\"translateX(\" + offset + \"px)\");\n };\n HeaderRowContainerCtrl.prototype.resetScrollLeft = function () {\n this.eViewport.scrollLeft = 0;\n };\n HeaderRowContainerCtrl.prototype.setupPinnedWidth = function () {\n var _this = this;\n if (this.pinned == null) {\n return;\n }\n var pinningLeft = this.pinned === Constants.PINNED_LEFT;\n var pinningRight = this.pinned === Constants.PINNED_RIGHT;\n var listener = function () {\n var width = pinningLeft ? _this.pinnedWidthService.getPinnedLeftWidth() : _this.pinnedWidthService.getPinnedRightWidth();\n if (width == null) {\n return;\n } // can happen at initialisation, width not yet set\n var hidden = width == 0;\n var isRtl = _this.gridOptionsWrapper.isEnableRtl();\n var scrollbarWidth = _this.gridOptionsWrapper.getScrollbarWidth();\n // if there is a scroll showing (and taking up space, so Windows, and not iOS)\n // in the body, then we add extra space to keep header aligned with the body,\n // as body width fits the cols and the scrollbar\n var addPaddingForScrollbar = _this.scrollVisibleService.isVerticalScrollShowing() && ((isRtl && pinningLeft) || (!isRtl && pinningRight));\n var widthWithPadding = addPaddingForScrollbar ? width + scrollbarWidth : width;\n _this.comp.setPinnedContainerWidth(widthWithPadding + 'px');\n _this.comp.addOrRemoveCssClass('ag-hidden', hidden);\n };\n this.addManagedListener(this.eventService, Events.EVENT_LEFT_PINNED_WIDTH_CHANGED, listener);\n this.addManagedListener(this.eventService, Events.EVENT_RIGHT_PINNED_WIDTH_CHANGED, listener);\n this.addManagedListener(this.eventService, Events.EVENT_SCROLL_VISIBILITY_CHANGED, listener);\n this.addManagedListener(this.eventService, Events.EVENT_SCROLLBAR_WIDTH_CHANGED, listener);\n };\n HeaderRowContainerCtrl.prototype.getHeaderCtrlForColumn = function (column) {\n if (column instanceof Column) {\n if (!this.columnsRowCtrl) {\n return;\n }\n return this.columnsRowCtrl.getHeaderCellCtrl(column);\n }\n if (this.groupsRowCtrls.length === 0) {\n return;\n }\n for (var i = 0; i < this.groupsRowCtrls.length; i++) {\n var ctrl = this.groupsRowCtrls[i].getHeaderCellCtrl(column);\n if (ctrl) {\n return ctrl;\n }\n }\n };\n HeaderRowContainerCtrl.prototype.getHtmlElementForColumnHeader = function (column) {\n /* tslint:enable */\n var cellCtrl = this.getHeaderCtrlForColumn(column);\n if (!cellCtrl) {\n return null;\n }\n return cellCtrl.getGui();\n };\n HeaderRowContainerCtrl.prototype.getRowType = function (rowIndex) {\n var allCtrls = this.getAllCtrls();\n var ctrl = allCtrls[rowIndex];\n return ctrl ? ctrl.getType() : undefined;\n };\n HeaderRowContainerCtrl.prototype.focusHeader = function (rowIndex, column, event) {\n var allCtrls = this.getAllCtrls();\n var ctrl = allCtrls[rowIndex];\n if (!ctrl) {\n return false;\n }\n return ctrl.focusHeader(column, event);\n };\n HeaderRowContainerCtrl.prototype.getRowCount = function () {\n return this.getAllCtrls().length;\n };\n __decorate$1g([\n Autowired('ctrlsService')\n ], HeaderRowContainerCtrl.prototype, \"ctrlsService\", void 0);\n __decorate$1g([\n Autowired('scrollVisibleService')\n ], HeaderRowContainerCtrl.prototype, \"scrollVisibleService\", void 0);\n __decorate$1g([\n Autowired('pinnedWidthService')\n ], HeaderRowContainerCtrl.prototype, \"pinnedWidthService\", void 0);\n __decorate$1g([\n Autowired('columnModel')\n ], HeaderRowContainerCtrl.prototype, \"columnModel\", void 0);\n __decorate$1g([\n Autowired('focusService')\n ], HeaderRowContainerCtrl.prototype, \"focusService\", void 0);\n return HeaderRowContainerCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1m = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1f = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderRowContainerComp = /** @class */ (function (_super) {\n __extends$1m(HeaderRowContainerComp, _super);\n function HeaderRowContainerComp(pinned) {\n var _this = _super.call(this) || this;\n _this.headerRowComps = {};\n _this.rowCompsList = [];\n _this.pinned = pinned;\n return _this;\n }\n HeaderRowContainerComp.prototype.init = function () {\n var _this = this;\n this.selectAndSetTemplate();\n var compProxy = {\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n setCtrls: function (ctrls) { return _this.setCtrls(ctrls); },\n // only gets called for center section\n setCenterWidth: function (width) { return _this.eCenterContainer.style.width = width; },\n setContainerTransform: function (transform) { return _this.eCenterContainer.style.transform = transform; },\n // only gets called for pinned sections\n setPinnedContainerWidth: function (width) {\n var eGui = _this.getGui();\n eGui.style.width = width;\n eGui.style.maxWidth = width;\n eGui.style.minWidth = width;\n }\n };\n var ctrl = this.createManagedBean(new HeaderRowContainerCtrl(this.pinned));\n ctrl.setComp(compProxy, this.getGui());\n };\n HeaderRowContainerComp.prototype.selectAndSetTemplate = function () {\n var pinnedLeft = this.pinned == Constants.PINNED_LEFT;\n var pinnedRight = this.pinned == Constants.PINNED_RIGHT;\n var template = pinnedLeft ? HeaderRowContainerComp.PINNED_LEFT_TEMPLATE :\n pinnedRight ? HeaderRowContainerComp.PINNED_RIGHT_TEMPLATE : HeaderRowContainerComp.CENTER_TEMPLATE;\n this.setTemplate(template);\n // for left and right, we add rows directly to the root element,\n // but for center container we add elements to the child container.\n this.eRowContainer = this.eCenterContainer ? this.eCenterContainer : this.getGui();\n };\n HeaderRowContainerComp.prototype.destroyRowComps = function () {\n this.setCtrls([]);\n };\n HeaderRowContainerComp.prototype.destroyRowComp = function (rowComp) {\n this.destroyBean(rowComp);\n this.eRowContainer.removeChild(rowComp.getGui());\n };\n HeaderRowContainerComp.prototype.setCtrls = function (ctrls) {\n var _this = this;\n var oldRowComps = this.headerRowComps;\n this.headerRowComps = {};\n this.rowCompsList = [];\n var prevGui;\n var appendEnsuringDomOrder = function (rowComp) {\n var eGui = rowComp.getGui();\n var notAlreadyIn = eGui.parentElement != _this.eRowContainer;\n if (notAlreadyIn) {\n _this.eRowContainer.appendChild(eGui);\n }\n if (prevGui) {\n ensureDomOrder(_this.eRowContainer, eGui, prevGui);\n }\n prevGui = eGui;\n };\n ctrls.forEach(function (ctrl) {\n var ctrlId = ctrl.getInstanceId();\n var existingComp = oldRowComps[ctrlId];\n delete oldRowComps[ctrlId];\n var rowComp = existingComp ? existingComp : _this.createBean(new HeaderRowComp(ctrl));\n _this.headerRowComps[ctrlId] = rowComp;\n _this.rowCompsList.push(rowComp);\n appendEnsuringDomOrder(rowComp);\n });\n getAllValuesInObject(oldRowComps).forEach(function (c) { return _this.destroyRowComp(c); });\n };\n HeaderRowContainerComp.PINNED_LEFT_TEMPLATE = \"<div class=\\\"ag-pinned-left-header\\\" role=\\\"presentation\\\"/>\";\n HeaderRowContainerComp.PINNED_RIGHT_TEMPLATE = \"<div class=\\\"ag-pinned-right-header\\\" role=\\\"presentation\\\"/>\";\n HeaderRowContainerComp.CENTER_TEMPLATE = \"<div class=\\\"ag-header-viewport\\\" role=\\\"presentation\\\">\\n <div class=\\\"ag-header-container\\\" ref=\\\"eCenterContainer\\\" role=\\\"rowgroup\\\"></div>\\n </div>\";\n __decorate$1f([\n RefSelector('eCenterContainer')\n ], HeaderRowContainerComp.prototype, \"eCenterContainer\", void 0);\n __decorate$1f([\n PostConstruct\n ], HeaderRowContainerComp.prototype, \"init\", null);\n __decorate$1f([\n PreDestroy\n ], HeaderRowContainerComp.prototype, \"destroyRowComps\", null);\n return HeaderRowContainerComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1l = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1e = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderNavigationDirection;\n(function (HeaderNavigationDirection) {\n HeaderNavigationDirection[HeaderNavigationDirection[\"UP\"] = 0] = \"UP\";\n HeaderNavigationDirection[HeaderNavigationDirection[\"DOWN\"] = 1] = \"DOWN\";\n HeaderNavigationDirection[HeaderNavigationDirection[\"LEFT\"] = 2] = \"LEFT\";\n HeaderNavigationDirection[HeaderNavigationDirection[\"RIGHT\"] = 3] = \"RIGHT\";\n})(HeaderNavigationDirection || (HeaderNavigationDirection = {}));\nvar HeaderNavigationService = /** @class */ (function (_super) {\n __extends$1l(HeaderNavigationService, _super);\n function HeaderNavigationService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n HeaderNavigationService.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) {\n _this.gridBodyCon = p.gridBodyCtrl;\n });\n };\n HeaderNavigationService.prototype.getHeaderRowCount = function () {\n var centerHeaderContainer = this.ctrlsService.getHeaderRowContainerCtrl();\n return centerHeaderContainer ? centerHeaderContainer.getRowCount() : 0;\n };\n HeaderNavigationService.prototype.getHeaderRowType = function (rowIndex) {\n var centerHeaderContainer = this.ctrlsService.getHeaderRowContainerCtrl();\n if (centerHeaderContainer) {\n return centerHeaderContainer.getRowType(rowIndex);\n }\n };\n /*\n * This method navigates grid header vertically\n * @return {boolean} true to preventDefault on the event that caused this navigation.\n */\n HeaderNavigationService.prototype.navigateVertically = function (direction, fromHeader, event) {\n if (!fromHeader) {\n fromHeader = this.focusService.getFocusedHeader();\n }\n if (!fromHeader) {\n return false;\n }\n var headerRowIndex = fromHeader.headerRowIndex, column = fromHeader.column;\n var rowLen = this.getHeaderRowCount();\n var isUp = direction === HeaderNavigationDirection.UP;\n var nextRow = isUp ? headerRowIndex - 1 : headerRowIndex + 1;\n var nextFocusColumn = null;\n var skipColumn = false;\n if (nextRow < 0) {\n nextRow = 0;\n nextFocusColumn = column;\n skipColumn = true;\n }\n if (nextRow >= rowLen) {\n nextRow = -1; // -1 indicates the focus should move to grid rows.\n }\n var currentRowType = this.getHeaderRowType(headerRowIndex);\n if (!skipColumn) {\n if (currentRowType === HeaderRowType.COLUMN_GROUP) {\n var currentColumn = column;\n nextFocusColumn = isUp ? column.getParent() : currentColumn.getDisplayedChildren()[0];\n }\n else if (currentRowType === HeaderRowType.FLOATING_FILTER) {\n nextFocusColumn = column;\n }\n else {\n var currentColumn = column;\n nextFocusColumn = isUp ? currentColumn.getParent() : currentColumn;\n }\n if (!nextFocusColumn) {\n return false;\n }\n }\n return this.focusService.focusHeaderPosition({\n headerPosition: { headerRowIndex: nextRow, column: nextFocusColumn },\n allowUserOverride: true,\n event: event\n });\n };\n /*\n * This method navigates grid header horizontally\n * @return {boolean} true to preventDefault on the event that caused this navigation.\n */\n HeaderNavigationService.prototype.navigateHorizontally = function (direction, fromTab, event) {\n if (fromTab === void 0) { fromTab = false; }\n var focusedHeader = this.focusService.getFocusedHeader();\n var isLeft = direction === HeaderNavigationDirection.LEFT;\n var isRtl = this.gridOptionsWrapper.isEnableRtl();\n var nextHeader;\n var normalisedDirection;\n // either navigating to the left or isRtl (cannot be both)\n if (isLeft !== isRtl) {\n normalisedDirection = 'Before';\n nextHeader = this.headerPositionUtils.findHeader(focusedHeader, normalisedDirection);\n }\n else {\n normalisedDirection = 'After';\n nextHeader = this.headerPositionUtils.findHeader(focusedHeader, normalisedDirection);\n }\n if (nextHeader || !fromTab) {\n return this.focusService.focusHeaderPosition({\n headerPosition: nextHeader,\n direction: normalisedDirection,\n fromTab: fromTab,\n allowUserOverride: true,\n event: event\n });\n }\n return this.focusNextHeaderRow(focusedHeader, normalisedDirection, event);\n };\n HeaderNavigationService.prototype.focusNextHeaderRow = function (focusedHeader, direction, event) {\n var currentIndex = focusedHeader.headerRowIndex;\n var nextPosition = null;\n var nextRowIndex;\n if (direction === 'Before') {\n if (currentIndex > 0) {\n nextRowIndex = currentIndex - 1;\n nextPosition = this.headerPositionUtils.findColAtEdgeForHeaderRow(nextRowIndex, 'end');\n }\n }\n else {\n nextRowIndex = currentIndex + 1;\n nextPosition = this.headerPositionUtils.findColAtEdgeForHeaderRow(nextRowIndex, 'start');\n }\n return this.focusService.focusHeaderPosition({\n headerPosition: nextPosition,\n direction: direction,\n fromTab: true,\n allowUserOverride: true,\n event: event\n });\n };\n HeaderNavigationService.prototype.scrollToColumn = function (column, direction) {\n if (direction === void 0) { direction = 'After'; }\n if (column.getPinned()) {\n return;\n }\n var columnToScrollTo;\n if (column instanceof ColumnGroup) {\n var columns = column.getDisplayedLeafColumns();\n columnToScrollTo = direction === 'Before' ? last(columns) : columns[0];\n }\n else {\n columnToScrollTo = column;\n }\n this.gridBodyCon.getScrollFeature().ensureColumnVisible(columnToScrollTo);\n };\n __decorate$1e([\n Autowired('focusService')\n ], HeaderNavigationService.prototype, \"focusService\", void 0);\n __decorate$1e([\n Autowired('headerPositionUtils')\n ], HeaderNavigationService.prototype, \"headerPositionUtils\", void 0);\n __decorate$1e([\n Autowired('animationFrameService')\n ], HeaderNavigationService.prototype, \"animationFrameService\", void 0);\n __decorate$1e([\n Autowired('ctrlsService')\n ], HeaderNavigationService.prototype, \"ctrlsService\", void 0);\n __decorate$1e([\n PostConstruct\n ], HeaderNavigationService.prototype, \"postConstruct\", null);\n HeaderNavigationService = __decorate$1e([\n Bean('headerNavigationService')\n ], HeaderNavigationService);\n return HeaderNavigationService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1k = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1d = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GridHeaderCtrl = /** @class */ (function (_super) {\n __extends$1k(GridHeaderCtrl, _super);\n function GridHeaderCtrl() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n GridHeaderCtrl.prototype.setComp = function (comp, eGui, eFocusableElement) {\n this.comp = comp;\n this.eGui = eGui;\n this.createManagedBean(new ManagedFocusFeature(eFocusableElement, {\n onTabKeyDown: this.onTabKeyDown.bind(this),\n handleKeyDown: this.handleKeyDown.bind(this),\n onFocusOut: this.onFocusOut.bind(this)\n }));\n // for setting ag-pivot-on / ag-pivot-off CSS classes\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, this.onPivotModeChanged.bind(this));\n this.onPivotModeChanged();\n this.setupHeaderHeight();\n this.ctrlsService.registerGridHeaderCtrl(this);\n };\n GridHeaderCtrl.prototype.setupHeaderHeight = function () {\n var listener = this.setHeaderHeight.bind(this);\n listener();\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_HEADER_HEIGHT, listener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT, listener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT, listener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT, listener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT, listener);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, listener);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_HEADER_HEIGHT_CHANGED, listener);\n };\n GridHeaderCtrl.prototype.getHeaderHeight = function () {\n return this.headerHeight;\n };\n GridHeaderCtrl.prototype.setHeaderHeight = function () {\n var _a = this, columnModel = _a.columnModel, gridOptionsWrapper = _a.gridOptionsWrapper;\n var numberOfFloating = 0;\n var headerRowCount = columnModel.getHeaderRowCount();\n var totalHeaderHeight;\n var hasFloatingFilters = columnModel.hasFloatingFilters();\n if (hasFloatingFilters) {\n headerRowCount++;\n numberOfFloating = 1;\n }\n var groupHeight = this.columnModel.getColumnGroupHeaderRowHeight();\n var headerHeight = this.columnModel.getColumnHeaderRowHeight();\n var numberOfNonGroups = 1 + numberOfFloating;\n var numberOfGroups = headerRowCount - numberOfNonGroups;\n totalHeaderHeight = numberOfFloating * gridOptionsWrapper.getFloatingFiltersHeight();\n totalHeaderHeight += numberOfGroups * groupHeight;\n totalHeaderHeight += headerHeight;\n if (this.headerHeight === totalHeaderHeight) {\n return;\n }\n this.headerHeight = totalHeaderHeight;\n // one extra pixel is needed here to account for the\n // height of the border\n var px = totalHeaderHeight + 1 + \"px\";\n this.comp.setHeightAndMinHeight(px);\n this.eventService.dispatchEvent({\n type: Events.EVENT_HEADER_HEIGHT_CHANGED\n });\n };\n GridHeaderCtrl.prototype.onPivotModeChanged = function () {\n var pivotMode = this.columnModel.isPivotMode();\n this.comp.addOrRemoveCssClass('ag-pivot-on', pivotMode);\n this.comp.addOrRemoveCssClass('ag-pivot-off', !pivotMode);\n };\n GridHeaderCtrl.prototype.onTabKeyDown = function (e) {\n var isRtl = this.gridOptionsWrapper.isEnableRtl();\n var direction = e.shiftKey !== isRtl\n ? HeaderNavigationDirection.LEFT\n : HeaderNavigationDirection.RIGHT;\n if (this.headerNavigationService.navigateHorizontally(direction, true, e) ||\n this.focusService.focusNextGridCoreContainer(e.shiftKey)) {\n e.preventDefault();\n }\n };\n GridHeaderCtrl.prototype.handleKeyDown = function (e) {\n var direction = null;\n switch (e.key) {\n case KeyCode.LEFT:\n direction = HeaderNavigationDirection.LEFT;\n case KeyCode.RIGHT:\n if (!exists(direction)) {\n direction = HeaderNavigationDirection.RIGHT;\n }\n this.headerNavigationService.navigateHorizontally(direction, false, e);\n break;\n case KeyCode.UP:\n direction = HeaderNavigationDirection.UP;\n case KeyCode.DOWN:\n if (!exists(direction)) {\n direction = HeaderNavigationDirection.DOWN;\n }\n if (this.headerNavigationService.navigateVertically(direction, null, e)) {\n e.preventDefault();\n }\n break;\n default:\n return;\n }\n };\n GridHeaderCtrl.prototype.onFocusOut = function (e) {\n var eDocument = this.gridOptionsWrapper.getDocument();\n var relatedTarget = e.relatedTarget;\n if (!relatedTarget && this.eGui.contains(eDocument.activeElement)) {\n return;\n }\n if (!this.eGui.contains(relatedTarget)) {\n this.focusService.clearFocusedHeader();\n }\n };\n __decorate$1d([\n Autowired('headerNavigationService')\n ], GridHeaderCtrl.prototype, \"headerNavigationService\", void 0);\n __decorate$1d([\n Autowired('focusService')\n ], GridHeaderCtrl.prototype, \"focusService\", void 0);\n __decorate$1d([\n Autowired('columnModel')\n ], GridHeaderCtrl.prototype, \"columnModel\", void 0);\n __decorate$1d([\n Autowired('ctrlsService')\n ], GridHeaderCtrl.prototype, \"ctrlsService\", void 0);\n return GridHeaderCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1j = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1c = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GridHeaderComp = /** @class */ (function (_super) {\n __extends$1j(GridHeaderComp, _super);\n function GridHeaderComp() {\n return _super.call(this, GridHeaderComp.TEMPLATE) || this;\n }\n GridHeaderComp.prototype.postConstruct = function () {\n var _this = this;\n var compProxy = {\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n setHeightAndMinHeight: function (height) {\n _this.getGui().style.height = height;\n _this.getGui().style.minHeight = height;\n }\n };\n var ctrl = this.createManagedBean(new GridHeaderCtrl());\n ctrl.setComp(compProxy, this.getGui(), this.getFocusableElement());\n var addContainer = function (container) {\n _this.createManagedBean(container);\n _this.appendChild(container);\n };\n addContainer(new HeaderRowContainerComp(Constants.PINNED_LEFT));\n addContainer(new HeaderRowContainerComp(null));\n addContainer(new HeaderRowContainerComp(Constants.PINNED_RIGHT));\n };\n GridHeaderComp.TEMPLATE = \"<div class=\\\"ag-header\\\" role=\\\"presentation\\\"/>\";\n __decorate$1c([\n PostConstruct\n ], GridHeaderComp.prototype, \"postConstruct\", null);\n return GridHeaderComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1i = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HorizontalResizeService = /** @class */ (function (_super) {\n __extends$1i(HorizontalResizeService, _super);\n function HorizontalResizeService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n HorizontalResizeService.prototype.addResizeBar = function (params) {\n var _this = this;\n var dragSource = {\n dragStartPixels: params.dragStartPixels || 0,\n eElement: params.eResizeBar,\n onDragStart: this.onDragStart.bind(this, params),\n onDragStop: this.onDragStop.bind(this, params),\n onDragging: this.onDragging.bind(this, params)\n };\n this.dragService.addDragSource(dragSource, true);\n // we pass remove func back to the caller, so call can tell us when they\n // are finished, and then we remove the listener from the drag source\n var finishedWithResizeFunc = function () { return _this.dragService.removeDragSource(dragSource); };\n return finishedWithResizeFunc;\n };\n HorizontalResizeService.prototype.onDragStart = function (params, mouseEvent) {\n this.dragStartX = mouseEvent.clientX;\n this.setResizeIcons();\n var shiftKey = mouseEvent instanceof MouseEvent && mouseEvent.shiftKey === true;\n params.onResizeStart(shiftKey);\n };\n HorizontalResizeService.prototype.setResizeIcons = function () {\n var ctrl = this.ctrlsService.getGridCtrl();\n // change the body cursor, so when drag moves out of the drag bar, the cursor is still 'resize' (or 'move'\n ctrl.setResizeCursor(true);\n // we don't want text selection outside the grid (otherwise it looks weird as text highlights when we move)\n ctrl.disableUserSelect(true);\n };\n HorizontalResizeService.prototype.onDragStop = function (params, mouseEvent) {\n params.onResizeEnd(this.resizeAmount);\n this.resetIcons();\n };\n HorizontalResizeService.prototype.resetIcons = function () {\n var ctrl = this.ctrlsService.getGridCtrl();\n ctrl.setResizeCursor(false);\n ctrl.disableUserSelect(false);\n };\n HorizontalResizeService.prototype.onDragging = function (params, mouseEvent) {\n this.resizeAmount = mouseEvent.clientX - this.dragStartX;\n params.onResizing(this.resizeAmount);\n };\n __decorate$1b([\n Autowired('dragService')\n ], HorizontalResizeService.prototype, \"dragService\", void 0);\n __decorate$1b([\n Autowired('ctrlsService')\n ], HorizontalResizeService.prototype, \"ctrlsService\", void 0);\n HorizontalResizeService = __decorate$1b([\n Bean('horizontalResizeService')\n ], HorizontalResizeService);\n return HorizontalResizeService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1h = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1a = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar StandardMenuFactory = /** @class */ (function (_super) {\n __extends$1h(StandardMenuFactory, _super);\n function StandardMenuFactory() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n StandardMenuFactory.prototype.hideActiveMenu = function () {\n if (this.hidePopup) {\n this.hidePopup();\n }\n };\n StandardMenuFactory.prototype.showMenuAfterMouseEvent = function (column, mouseEvent) {\n var _this = this;\n this.showPopup(column, function (eMenu) {\n _this.popupService.positionPopupUnderMouseEvent({\n column: column,\n type: 'columnMenu',\n mouseEvent: mouseEvent,\n ePopup: eMenu\n });\n }, mouseEvent.target);\n };\n StandardMenuFactory.prototype.showMenuAfterButtonClick = function (column, eventSource, containerType) {\n var _this = this;\n this.showPopup(column, function (eMenu) {\n _this.popupService.positionPopupUnderComponent({\n type: containerType,\n eventSource: eventSource,\n ePopup: eMenu,\n keepWithinBounds: true,\n column: column\n });\n }, eventSource);\n };\n StandardMenuFactory.prototype.showPopup = function (column, positionCallback, eventSource) {\n var _this = this;\n var filterWrapper = this.filterManager.getOrCreateFilterWrapper(column, 'COLUMN_MENU');\n if (!filterWrapper) {\n throw new Error('AG Grid - unable to show popup filter, filter instantiation failed');\n }\n var eMenu = document.createElement('div');\n setAriaRole(eMenu, 'presentation');\n eMenu.classList.add('ag-menu');\n this.tabListener = this.addManagedListener(eMenu, 'keydown', function (e) { return _this.trapFocusWithin(e, eMenu); });\n filterWrapper.guiPromise.then(function (gui) { return eMenu.appendChild(gui); });\n var hidePopup;\n var anchorToElement = eventSource || this.ctrlsService.getGridBodyCtrl().getGui();\n var closedCallback = function (e) {\n column.setMenuVisible(false, 'contextMenu');\n var isKeyboardEvent = e instanceof KeyboardEvent;\n if (_this.tabListener) {\n _this.tabListener = _this.tabListener();\n }\n if (isKeyboardEvent && eventSource && isVisible(eventSource)) {\n var focusableEl = _this.focusService.findTabbableParent(eventSource);\n if (focusableEl) {\n focusableEl.focus();\n }\n }\n };\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var addPopupRes = this.popupService.addPopup({\n modal: true,\n eChild: eMenu,\n closeOnEsc: true,\n closedCallback: closedCallback,\n positionCallback: function () { return positionCallback(eMenu); },\n anchorToElement: anchorToElement,\n ariaLabel: translate('ariaLabelColumnMenu', 'Column Menu')\n });\n if (addPopupRes) {\n this.hidePopup = hidePopup = addPopupRes.hideFunc;\n }\n filterWrapper.filterPromise.then(function (filter) {\n // need to make sure the filter is present before positioning, as only\n // after filter it is visible can we find out what the width of it is\n positionCallback(eMenu);\n if (filter.afterGuiAttached) {\n filter.afterGuiAttached({ container: 'columnMenu', hidePopup: hidePopup });\n }\n });\n column.setMenuVisible(true, 'contextMenu');\n };\n StandardMenuFactory.prototype.trapFocusWithin = function (e, menu) {\n if (e.key !== KeyCode.TAB ||\n e.defaultPrevented ||\n this.focusService.findNextFocusableElement(menu, false, e.shiftKey)) {\n return;\n }\n e.preventDefault();\n this.focusService.focusInto(menu, e.shiftKey);\n };\n StandardMenuFactory.prototype.isMenuEnabled = function (column) {\n // for standard, we show menu if filter is enabled, and the menu is not suppressed\n return column.isFilterAllowed();\n };\n __decorate$1a([\n Autowired('filterManager')\n ], StandardMenuFactory.prototype, \"filterManager\", void 0);\n __decorate$1a([\n Autowired('popupService')\n ], StandardMenuFactory.prototype, \"popupService\", void 0);\n __decorate$1a([\n Autowired('focusService')\n ], StandardMenuFactory.prototype, \"focusService\", void 0);\n __decorate$1a([\n Autowired('ctrlsService')\n ], StandardMenuFactory.prototype, \"ctrlsService\", void 0);\n StandardMenuFactory = __decorate$1a([\n Bean('menuFactory')\n ], StandardMenuFactory);\n return StandardMenuFactory;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1g = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$19 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TabbedLayout = /** @class */ (function (_super) {\n __extends$1g(TabbedLayout, _super);\n function TabbedLayout(params) {\n var _this = _super.call(this, TabbedLayout.getTemplate(params.cssClass)) || this;\n _this.items = [];\n _this.tabbedItemScrollMap = new Map();\n _this.params = params;\n if (params.items) {\n params.items.forEach(function (item) { return _this.addItem(item); });\n }\n return _this;\n }\n TabbedLayout.prototype.postConstruct = function () {\n this.createManagedBean(new ManagedFocusFeature(this.getFocusableElement(), {\n onTabKeyDown: this.onTabKeyDown.bind(this),\n handleKeyDown: this.handleKeyDown.bind(this)\n }));\n };\n TabbedLayout.getTemplate = function (cssClass) {\n return /* html */ \"<div class=\\\"ag-tabs \" + cssClass + \"\\\">\\n <div ref=\\\"eHeader\\\" role=\\\"tablist\\\" class=\\\"ag-tabs-header \" + (cssClass ? cssClass + \"-header\" : '') + \"\\\"></div>\\n <div ref=\\\"eBody\\\" role=\\\"presentation\\\" class=\\\"ag-tabs-body \" + (cssClass ? cssClass + \"-body\" : '') + \"\\\"></div>\\n </div>\";\n };\n TabbedLayout.prototype.handleKeyDown = function (e) {\n var eDocument = this.gridOptionsWrapper.getDocument();\n switch (e.key) {\n case KeyCode.RIGHT:\n case KeyCode.LEFT:\n if (!this.eHeader.contains(eDocument.activeElement)) {\n return;\n }\n var isRightKey = e.key === KeyCode.RIGHT;\n var isRtl = this.gridOptionsWrapper.isEnableRtl();\n var currentPosition = this.items.indexOf(this.activeItem);\n var nextPosition = isRightKey !== isRtl ? Math.min(currentPosition + 1, this.items.length - 1) : Math.max(currentPosition - 1, 0);\n if (currentPosition === nextPosition) {\n return;\n }\n e.preventDefault();\n var nextItem = this.items[nextPosition];\n this.showItemWrapper(nextItem);\n nextItem.eHeaderButton.focus();\n break;\n case KeyCode.UP:\n case KeyCode.DOWN:\n e.stopPropagation();\n break;\n }\n };\n TabbedLayout.prototype.onTabKeyDown = function (e) {\n if (e.defaultPrevented) {\n return;\n }\n var _a = this, focusService = _a.focusService, eHeader = _a.eHeader, eBody = _a.eBody, activeItem = _a.activeItem;\n var eDocument = this.gridOptionsWrapper.getDocument();\n var activeElement = eDocument.activeElement;\n e.preventDefault();\n if (eHeader.contains(activeElement)) {\n // focus is in header, move into body of popup\n focusService.focusInto(eBody, e.shiftKey);\n }\n else {\n // focus is in body, establish if it should return to header\n if (focusService.isFocusUnderManagedComponent(eBody)) {\n // focus was in a managed focus component and has now left, so we can return to the header\n activeItem.eHeaderButton.focus();\n }\n else {\n var nextEl = focusService.findNextFocusableElement(eBody, false, e.shiftKey);\n if (nextEl) {\n // if another element exists in the body that can be focussed, go to that\n nextEl.focus();\n }\n else {\n // otherwise return to the header\n activeItem.eHeaderButton.focus();\n }\n }\n }\n };\n TabbedLayout.prototype.setAfterAttachedParams = function (params) {\n this.afterAttachedParams = params;\n };\n TabbedLayout.prototype.showFirstItem = function () {\n if (this.items.length > 0) {\n this.showItemWrapper(this.items[0]);\n }\n };\n TabbedLayout.prototype.addItem = function (item) {\n var eHeaderButton = document.createElement('span');\n setAriaRole(eHeaderButton, 'tab');\n eHeaderButton.setAttribute('tabIndex', '-1');\n eHeaderButton.appendChild(item.title);\n eHeaderButton.classList.add('ag-tab');\n this.eHeader.appendChild(eHeaderButton);\n setAriaLabel(eHeaderButton, item.titleLabel);\n var wrapper = {\n tabbedItem: item,\n eHeaderButton: eHeaderButton\n };\n this.items.push(wrapper);\n eHeaderButton.addEventListener('click', this.showItemWrapper.bind(this, wrapper));\n };\n TabbedLayout.prototype.showItem = function (tabbedItem) {\n var itemWrapper = this.items.find(function (wrapper) { return wrapper.tabbedItem === tabbedItem; });\n if (itemWrapper) {\n this.showItemWrapper(itemWrapper);\n }\n };\n TabbedLayout.prototype.showItemWrapper = function (wrapper) {\n var _this = this;\n var tabbedItem = wrapper.tabbedItem, eHeaderButton = wrapper.eHeaderButton;\n if (this.params.onItemClicked) {\n this.params.onItemClicked({ item: tabbedItem });\n }\n if (this.activeItem === wrapper) {\n callIfPresent(this.params.onActiveItemClicked);\n return;\n }\n if (this.lastScrollListener) {\n this.lastScrollListener = this.lastScrollListener();\n }\n clearElement(this.eBody);\n tabbedItem.bodyPromise.then(function (body) {\n _this.eBody.appendChild(body);\n var onlyUnmanaged = !_this.focusService.isKeyboardMode();\n _this.focusService.focusInto(_this.eBody, false, onlyUnmanaged);\n if (tabbedItem.afterAttachedCallback) {\n tabbedItem.afterAttachedCallback(_this.afterAttachedParams);\n }\n if (_this.params.keepScrollPosition) {\n var scrollableContainer_1 = (tabbedItem.getScrollableContainer && tabbedItem.getScrollableContainer()) || body;\n _this.lastScrollListener = _this.addManagedListener(scrollableContainer_1, 'scroll', function () {\n _this.tabbedItemScrollMap.set(tabbedItem.name, scrollableContainer_1.scrollTop);\n });\n var scrollPosition_1 = _this.tabbedItemScrollMap.get(tabbedItem.name);\n if (scrollPosition_1 !== undefined) {\n // Safari needs a small timeout or it will fire a scroll event to position 0\n setTimeout(function () {\n scrollableContainer_1.scrollTop = scrollPosition_1;\n }, 0);\n }\n }\n });\n if (this.activeItem) {\n this.activeItem.eHeaderButton.classList.remove('ag-tab-selected');\n }\n eHeaderButton.classList.add('ag-tab-selected');\n this.activeItem = wrapper;\n };\n __decorate$19([\n Autowired('focusService')\n ], TabbedLayout.prototype, \"focusService\", void 0);\n __decorate$19([\n RefSelector('eHeader')\n ], TabbedLayout.prototype, \"eHeader\", void 0);\n __decorate$19([\n RefSelector('eBody')\n ], TabbedLayout.prototype, \"eBody\", void 0);\n __decorate$19([\n PostConstruct\n ], TabbedLayout.prototype, \"postConstruct\", null);\n return TabbedLayout;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/**\n * @deprecated\n */\nfunction simpleHttpRequest(params) {\n return new AgPromise(function (resolve) {\n var httpRequest = new XMLHttpRequest();\n httpRequest.open('GET', params.url);\n httpRequest.send();\n httpRequest.onreadystatechange = function () {\n if (httpRequest.readyState === 4 && httpRequest.status === 200) {\n resolve(JSON.parse(httpRequest.responseText));\n }\n };\n });\n}\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1f = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$18 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar DEBOUNCE_DELAY = 50;\nvar ResizeObserverService = /** @class */ (function (_super) {\n __extends$1f(ResizeObserverService, _super);\n function ResizeObserverService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.polyfillFunctions = [];\n return _this;\n }\n ResizeObserverService.prototype.observeResize = function (element, callback) {\n var _this = this;\n var eDocument = this.gridOptionsWrapper.getDocument();\n var win = (eDocument.defaultView || window);\n // this gets fired too often and might cause some relayout issues\n // so we add a debounce to the callback here to avoid the flashing effect.\n var debouncedCallback = debounce(callback, DEBOUNCE_DELAY);\n var useBrowserResizeObserver = function () {\n var resizeObserver = new win.ResizeObserver(debouncedCallback);\n resizeObserver.observe(element);\n return function () { return resizeObserver.disconnect(); };\n };\n var usePolyfill = function () {\n // initialise to the current width and height, so first call will have no changes\n var widthLastTime = offsetWidth(element);\n var heightLastTime = offsetHeight(element);\n // when finished, this gets turned to false.\n var running = true;\n var periodicallyCheckWidthAndHeight = function () {\n if (running) {\n var newWidth = offsetWidth(element);\n var newHeight = offsetHeight(element);\n var changed = newWidth !== widthLastTime || newHeight !== heightLastTime;\n if (changed) {\n widthLastTime = newWidth;\n heightLastTime = newHeight;\n callback();\n }\n _this.doNextPolyfillTurn(periodicallyCheckWidthAndHeight);\n }\n };\n periodicallyCheckWidthAndHeight();\n // the callback function we return sets running to false\n return function () { return running = false; };\n };\n var suppressResize = this.gridOptionsWrapper.isSuppressBrowserResizeObserver();\n var resizeObserverExists = !!win.ResizeObserver;\n if (resizeObserverExists && !suppressResize) {\n return useBrowserResizeObserver();\n }\n return usePolyfill();\n };\n ResizeObserverService.prototype.doNextPolyfillTurn = function (func) {\n this.polyfillFunctions.push(func);\n this.schedulePolyfill();\n };\n ResizeObserverService.prototype.schedulePolyfill = function () {\n var _this = this;\n if (this.polyfillScheduled) {\n return;\n }\n var executeAllFuncs = function () {\n var funcs = _this.polyfillFunctions;\n // make sure set scheduled to false and clear clear array\n // before executing the funcs, as the funcs could add more funcs\n _this.polyfillScheduled = false;\n _this.polyfillFunctions = [];\n funcs.forEach(function (f) { return f(); });\n };\n this.polyfillScheduled = true;\n this.getFrameworkOverrides().setTimeout(executeAllFuncs, DEBOUNCE_DELAY);\n };\n ResizeObserverService = __decorate$18([\n Bean('resizeObserverService')\n ], ResizeObserverService);\n return ResizeObserverService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1e = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$17 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AnimationFrameService = /** @class */ (function (_super) {\n __extends$1e(AnimationFrameService, _super);\n function AnimationFrameService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n // p1 and p2 are create tasks are to do with row and cell creation.\n // for them we want to execute according to row order, so we use\n // TaskItem so we know what index the item is for.\n _this.createTasksP1 = { list: [], sorted: false }; // eg drawing back-ground of rows\n _this.createTasksP2 = { list: [], sorted: false }; // eg cell renderers, adding hover functionality\n // destroy tasks are to do with row removal. they are done after row creation as the user will need to see new\n // rows first (as blank is scrolled into view), when we remove the old rows (no longer in view) is not as\n // important.\n _this.destroyTasks = [];\n _this.ticking = false;\n // we need to know direction of scroll, to build up rows in the direction of\n // the scroll. eg if user scrolls down, we extend the rows by building down.\n _this.scrollGoingDown = true;\n _this.lastScrollTop = 0;\n _this.taskCount = 0;\n _this.cancelledTasks = new Set();\n return _this;\n }\n AnimationFrameService.prototype.setScrollTop = function (scrollTop) {\n this.scrollGoingDown = scrollTop > this.lastScrollTop;\n this.lastScrollTop = scrollTop;\n };\n AnimationFrameService.prototype.init = function () {\n this.useAnimationFrame = !this.gridOptionsWrapper.isSuppressAnimationFrame();\n };\n AnimationFrameService.prototype.isOn = function () {\n return this.useAnimationFrame;\n };\n // this method is for our AG Grid sanity only - if animation frames are turned off,\n // then no place in the code should be looking to add any work to be done in animation\n // frames. this stops bugs - where some code is asking for a frame to be executed\n // when it should not.\n AnimationFrameService.prototype.verifyAnimationFrameOn = function (methodName) {\n if (this.useAnimationFrame === false) {\n console.warn(\"AG Grid: AnimationFrameService.\" + methodName + \" called but animation frames are off\");\n }\n };\n AnimationFrameService.prototype.createTask = function (task, index, list) {\n this.verifyAnimationFrameOn(list);\n var taskItem = { task: task, index: index, createOrder: ++this.taskCount };\n this.addTaskToList(this[list], taskItem);\n this.schedule();\n };\n AnimationFrameService.prototype.cancelTask = function (task) {\n this.cancelledTasks.add(task);\n };\n AnimationFrameService.prototype.addTaskToList = function (taskList, task) {\n taskList.list.push(task);\n taskList.sorted = false;\n };\n AnimationFrameService.prototype.sortTaskList = function (taskList) {\n if (taskList.sorted) {\n return;\n }\n var sortDirection = this.scrollGoingDown ? 1 : -1;\n // sort first by row index (taking into account scroll direction), then by\n // order of task creation (always ascending, so cells will render left-to-right)\n taskList.list.sort(function (a, b) { return a.index !== b.index ? sortDirection * (b.index - a.index) : b.createOrder - a.createOrder; });\n taskList.sorted = true;\n };\n AnimationFrameService.prototype.addDestroyTask = function (task) {\n this.verifyAnimationFrameOn('createTasksP3');\n this.destroyTasks.push(task);\n this.schedule();\n };\n AnimationFrameService.prototype.executeFrame = function (millis) {\n this.verifyAnimationFrameOn('executeFrame');\n var p1TaskList = this.createTasksP1;\n var p1Tasks = p1TaskList.list;\n var p2TaskList = this.createTasksP2;\n var p2Tasks = p2TaskList.list;\n var destroyTasks = this.destroyTasks;\n var frameStart = new Date().getTime();\n var duration = (new Date().getTime()) - frameStart;\n // 16ms is 60 fps\n var noMaxMillis = millis <= 0;\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n while (noMaxMillis || duration < millis) {\n var gridBodyDidSomething = gridBodyCon.getScrollFeature().executeAnimationFrameScroll();\n if (!gridBodyDidSomething) {\n var task = void 0;\n if (p1Tasks.length) {\n this.sortTaskList(p1TaskList);\n task = p1Tasks.pop().task;\n }\n else if (p2Tasks.length) {\n this.sortTaskList(p2TaskList);\n task = p2Tasks.pop().task;\n }\n else if (destroyTasks.length) {\n task = destroyTasks.pop();\n }\n else {\n this.cancelledTasks.clear();\n break;\n }\n if (!this.cancelledTasks.has(task)) {\n task();\n }\n }\n duration = (new Date().getTime()) - frameStart;\n }\n if (p1Tasks.length || p2Tasks.length || destroyTasks.length) {\n this.requestFrame();\n }\n else {\n this.stopTicking();\n }\n };\n AnimationFrameService.prototype.stopTicking = function () {\n this.ticking = false;\n };\n AnimationFrameService.prototype.flushAllFrames = function () {\n if (!this.useAnimationFrame) {\n return;\n }\n this.executeFrame(-1);\n };\n AnimationFrameService.prototype.schedule = function () {\n if (!this.useAnimationFrame) {\n return;\n }\n if (!this.ticking) {\n this.ticking = true;\n this.requestFrame();\n }\n };\n AnimationFrameService.prototype.requestFrame = function () {\n // check for the existence of requestAnimationFrame, and if\n // it's missing, then we polyfill it with setTimeout()\n var callback = this.executeFrame.bind(this, 60);\n var eDocument = this.gridOptionsWrapper.getDocument();\n var win = (eDocument.defaultView || window);\n if (win.requestAnimationFrame) {\n win.requestAnimationFrame(callback);\n }\n else if (win.webkitRequestAnimationFrame) {\n win.webkitRequestAnimationFrame(callback);\n }\n else {\n win.setTimeout(callback, 0);\n }\n };\n AnimationFrameService.prototype.isQueueEmpty = function () {\n return !this.ticking;\n };\n // a debounce utility used for parts of the app involved with rendering.\n // the advantage over normal debounce is the client can call flushAllFrames()\n // to make sure all rendering is complete. we don't wait any milliseconds,\n // as this is intended to batch calls in one VM turn.\n AnimationFrameService.prototype.debounce = function (func) {\n var _this = this;\n var pending = false;\n return function () {\n if (!_this.isOn()) {\n _this.getFrameworkOverrides().setTimeout(func, 0);\n return;\n }\n if (pending) {\n return;\n }\n pending = true;\n _this.addDestroyTask(function () {\n pending = false;\n func();\n });\n };\n };\n __decorate$17([\n Autowired('ctrlsService')\n ], AnimationFrameService.prototype, \"ctrlsService\", void 0);\n __decorate$17([\n PostConstruct\n ], AnimationFrameService.prototype, \"init\", null);\n AnimationFrameService = __decorate$17([\n Bean('animationFrameService')\n ], AnimationFrameService);\n return AnimationFrameService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1d = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$16 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RESIZE_CONTAINER_STYLE = 'ag-resizer-wrapper';\nvar RESIZE_TEMPLATE = /* html */ \"<div class=\\\"\" + RESIZE_CONTAINER_STYLE + \"\\\">\\n <div ref=\\\"eTopLeftResizer\\\" class=\\\"ag-resizer ag-resizer-topLeft\\\"></div>\\n <div ref=\\\"eTopResizer\\\" class=\\\"ag-resizer ag-resizer-top\\\"></div>\\n <div ref=\\\"eTopRightResizer\\\" class=\\\"ag-resizer ag-resizer-topRight\\\"></div>\\n <div ref=\\\"eRightResizer\\\" class=\\\"ag-resizer ag-resizer-right\\\"></div>\\n <div ref=\\\"eBottomRightResizer\\\" class=\\\"ag-resizer ag-resizer-bottomRight\\\"></div>\\n <div ref=\\\"eBottomResizer\\\" class=\\\"ag-resizer ag-resizer-bottom\\\"></div>\\n <div ref=\\\"eBottomLeftResizer\\\" class=\\\"ag-resizer ag-resizer-bottomLeft\\\"></div>\\n <div ref=\\\"eLeftResizer\\\" class=\\\"ag-resizer ag-resizer-left\\\"></div>\\n </div>\";\nvar PositionableFeature = /** @class */ (function (_super) {\n __extends$1d(PositionableFeature, _super);\n function PositionableFeature(element, config) {\n var _this = _super.call(this) || this;\n _this.element = element;\n _this.dragStartPosition = {\n x: 0,\n y: 0\n };\n _this.position = {\n x: 0,\n y: 0\n };\n _this.lastSize = {\n width: -1,\n height: -1\n };\n _this.positioned = false;\n _this.resizersAdded = false;\n _this.resizeListeners = [];\n _this.boundaryEl = null;\n _this.isResizing = false;\n _this.isMoving = false;\n _this.resizable = {};\n _this.movable = false;\n _this.currentResizer = null;\n _this.config = Object.assign({}, { popup: false }, config);\n return _this;\n }\n PositionableFeature.prototype.center = function () {\n var _a = this.offsetParent, clientHeight = _a.clientHeight, clientWidth = _a.clientWidth;\n var x = (clientWidth / 2) - (this.getWidth() / 2);\n var y = (clientHeight / 2) - (this.getHeight() / 2);\n this.offsetElement(x, y);\n };\n PositionableFeature.prototype.initialisePosition = function () {\n var _a = this.config, centered = _a.centered, forcePopupParentAsOffsetParent = _a.forcePopupParentAsOffsetParent, minWidth = _a.minWidth, width = _a.width, minHeight = _a.minHeight, height = _a.height, x = _a.x, y = _a.y;\n if (!this.offsetParent) {\n this.setOffsetParent();\n }\n var computedMinHeight = 0;\n var computedMinWidth = 0;\n // here we don't use the main offset parent but the element's offsetParent\n // in order to calculated the minWidth and minHeight correctly\n var isVisible = !!this.element.offsetParent;\n if (isVisible) {\n var boundaryEl = this.findBoundaryElement();\n var offsetParentComputedStyles = window.getComputedStyle(boundaryEl);\n if (offsetParentComputedStyles.minWidth != null) {\n var paddingWidth = boundaryEl.offsetWidth - this.element.offsetWidth;\n computedMinWidth = parseInt(offsetParentComputedStyles.minWidth, 10) - paddingWidth;\n }\n if (offsetParentComputedStyles.minHeight != null) {\n var paddingHeight = boundaryEl.offsetHeight - this.element.offsetHeight;\n computedMinHeight = parseInt(offsetParentComputedStyles.minHeight, 10) - paddingHeight;\n }\n }\n this.minHeight = minHeight || computedMinHeight;\n this.minWidth = minWidth || computedMinWidth;\n if (width) {\n this.setWidth(width);\n }\n if (height) {\n this.setHeight(height);\n }\n if (!width || !height) {\n this.refreshSize();\n }\n if (centered) {\n this.center();\n }\n else if (x || y) {\n this.offsetElement(x, y);\n }\n else if (isVisible && forcePopupParentAsOffsetParent && this.boundaryEl) {\n var top_1 = parseFloat(this.boundaryEl.style.top);\n var left = parseFloat(this.boundaryEl.style.left);\n this.offsetElement(isNaN(left) ? 0 : left, isNaN(top_1) ? 0 : top_1);\n }\n this.positioned = !!this.offsetParent;\n };\n PositionableFeature.prototype.isPositioned = function () {\n return this.positioned;\n };\n PositionableFeature.prototype.getPosition = function () {\n return this.position;\n };\n PositionableFeature.prototype.setMovable = function (movable, moveElement) {\n if (!this.config.popup || movable === this.movable) {\n return;\n }\n this.movable = movable;\n var params = this.moveElementDragListener || {\n eElement: moveElement,\n onDragStart: this.onMoveStart.bind(this),\n onDragging: this.onMove.bind(this),\n onDragStop: this.onMoveEnd.bind(this)\n };\n if (movable) {\n this.dragService.addDragSource(params);\n this.moveElementDragListener = params;\n }\n else {\n this.dragService.removeDragSource(params);\n this.moveElementDragListener = undefined;\n }\n };\n PositionableFeature.prototype.setResizable = function (resizable) {\n var _this = this;\n this.clearResizeListeners();\n if (resizable) {\n this.addResizers();\n }\n else {\n this.removeResizers();\n }\n if (typeof resizable === 'boolean') {\n if (resizable === false) {\n return;\n }\n resizable = {\n topLeft: resizable,\n top: resizable,\n topRight: resizable,\n right: resizable,\n bottomRight: resizable,\n bottom: resizable,\n bottomLeft: resizable,\n left: resizable\n };\n }\n Object.keys(resizable).forEach(function (side) {\n var resizableStructure = resizable;\n var val = !!resizableStructure[side];\n var resizerEl = _this.getResizerElement(side);\n var params = {\n dragStartPixels: 0,\n eElement: resizerEl,\n onDragStart: function (e) { return _this.onResizeStart(e, side); },\n onDragging: _this.onResize.bind(_this),\n onDragStop: function (e) { return _this.onResizeEnd(e, side); },\n };\n if (!!_this.resizable[side] !== val || (!_this.isAlive() && !val)) {\n if (val) {\n _this.dragService.addDragSource(params);\n _this.resizeListeners.push(params);\n resizerEl.style.pointerEvents = 'all';\n }\n else {\n resizerEl.style.pointerEvents = 'none';\n }\n }\n });\n };\n PositionableFeature.prototype.removeSizeFromEl = function () {\n this.element.style.removeProperty('height');\n this.element.style.removeProperty('width');\n this.element.style.removeProperty('flex');\n };\n PositionableFeature.prototype.restoreLastSize = function () {\n this.element.style.flex = '0 0 auto';\n var _a = this.lastSize, height = _a.height, width = _a.width;\n if (width !== -1) {\n this.element.style.width = width + \"px\";\n }\n if (height !== -1) {\n this.element.style.height = height + \"px\";\n }\n };\n PositionableFeature.prototype.getHeight = function () {\n return this.element.offsetHeight;\n };\n PositionableFeature.prototype.setHeight = function (height) {\n var popup = this.config.popup;\n var eGui = this.element;\n var isPercent = false;\n if (typeof height === 'string' && height.indexOf('%') !== -1) {\n setFixedHeight(eGui, height);\n height = getAbsoluteHeight(eGui);\n isPercent = true;\n }\n else if (this.positioned) {\n var elRect = this.element.getBoundingClientRect();\n var parentRect = this.offsetParent.getBoundingClientRect();\n height = Math.max(this.minHeight, height);\n var clientHeight = this.offsetParent.clientHeight;\n var yPosition = popup ? this.position.y : elRect.top;\n var parentTop = popup ? 0 : parentRect.top;\n if (clientHeight && (height + yPosition > clientHeight + parentTop)) {\n height = clientHeight - yPosition;\n }\n }\n if (this.getHeight() === height) {\n return;\n }\n if (!isPercent) {\n if (popup) {\n setFixedHeight(eGui, height);\n }\n else {\n eGui.style.height = height + \"px\";\n eGui.style.flex = '0 0 auto';\n this.lastSize.height = typeof height === 'number' ? height : parseFloat(height);\n }\n }\n else {\n eGui.style.maxHeight = 'unset';\n eGui.style.minHeight = 'unset';\n }\n };\n PositionableFeature.prototype.getWidth = function () {\n return this.element.offsetWidth;\n };\n PositionableFeature.prototype.setWidth = function (width) {\n var eGui = this.element;\n var popup = this.config.popup;\n var isPercent = false;\n if (typeof width === 'string' && width.indexOf('%') !== -1) {\n setFixedWidth(eGui, width);\n width = getAbsoluteWidth(eGui);\n isPercent = true;\n }\n else if (this.positioned) {\n width = Math.max(this.minWidth, width);\n var clientWidth = this.offsetParent.clientWidth;\n var xPosition = popup ? this.position.x : this.element.getBoundingClientRect().left;\n if (clientWidth && (width + xPosition > clientWidth)) {\n width = clientWidth - xPosition;\n }\n }\n if (this.getWidth() === width) {\n return;\n }\n if (!isPercent) {\n if (this.config.popup) {\n setFixedWidth(eGui, width);\n }\n else {\n eGui.style.width = width + \"px\";\n eGui.style.flex = ' unset';\n this.lastSize.width = typeof width === 'number' ? width : parseFloat(width);\n }\n }\n else {\n eGui.style.maxWidth = 'unset';\n eGui.style.minWidth = 'unset';\n }\n };\n PositionableFeature.prototype.offsetElement = function (x, y) {\n if (x === void 0) { x = 0; }\n if (y === void 0) { y = 0; }\n var ePopup = this.config.forcePopupParentAsOffsetParent ? this.boundaryEl : this.element;\n this.popupService.positionPopup({\n ePopup: ePopup,\n x: x,\n y: y,\n keepWithinBounds: true\n });\n this.setPosition(parseFloat(ePopup.style.left), parseFloat(ePopup.style.top));\n };\n PositionableFeature.prototype.setPosition = function (x, y) {\n this.position.x = x;\n this.position.y = y;\n };\n PositionableFeature.prototype.updateDragStartPosition = function (x, y) {\n this.dragStartPosition = { x: x, y: y };\n };\n PositionableFeature.prototype.calculateMouseMovement = function (params) {\n var e = params.e, isLeft = params.isLeft, isTop = params.isTop, anywhereWithin = params.anywhereWithin, topBuffer = params.topBuffer;\n var xDiff = e.clientX - this.dragStartPosition.x;\n var yDiff = e.clientY - this.dragStartPosition.y;\n var movementX = this.shouldSkipX(e, !!isLeft, !!anywhereWithin, xDiff) ? 0 : xDiff;\n var movementY = this.shouldSkipY(e, !!isTop, topBuffer, yDiff) ? 0 : yDiff;\n return { movementX: movementX, movementY: movementY };\n };\n PositionableFeature.prototype.shouldSkipX = function (e, isLeft, anywhereWithin, diff) {\n var elRect = this.element.getBoundingClientRect();\n var parentRect = this.offsetParent.getBoundingClientRect();\n var boundaryElRect = this.boundaryEl.getBoundingClientRect();\n var xPosition = this.config.popup ? this.position.x : elRect.left;\n // skip if cursor is outside of popupParent horizontally\n var skipX = ((xPosition <= 0 && parentRect.left >= e.clientX) ||\n (parentRect.right <= e.clientX && parentRect.right <= boundaryElRect.right));\n if (skipX) {\n return true;\n }\n if (isLeft) {\n skipX = (\n // skip if we are moving to the left and the cursor\n // is positioned to the right of the left side anchor\n (diff < 0 && e.clientX > xPosition + parentRect.left) ||\n // skip if we are moving to the right and the cursor\n // is positioned to the left of the dialog\n (diff > 0 && e.clientX < xPosition + parentRect.left));\n }\n else {\n if (anywhereWithin) {\n // if anywhereWithin is true, we allow to move\n // as long as the cursor is within the dialog\n skipX = ((diff < 0 && e.clientX > boundaryElRect.right) ||\n (diff > 0 && e.clientX < xPosition + parentRect.left));\n }\n else {\n skipX = (\n // if the movement is bound to the right side of the dialog\n // we skip if we are moving to the left and the cursor\n // is to the right of the dialog\n (diff < 0 && e.clientX > boundaryElRect.right) ||\n // or skip if we are moving to the right and the cursor\n // is to the left of the right side anchor\n (diff > 0 && e.clientX < boundaryElRect.right));\n }\n }\n return skipX;\n };\n PositionableFeature.prototype.shouldSkipY = function (e, isTop, topBuffer, diff) {\n if (topBuffer === void 0) { topBuffer = 0; }\n var elRect = this.element.getBoundingClientRect();\n var parentRect = this.offsetParent.getBoundingClientRect();\n var boundaryElRect = this.boundaryEl.getBoundingClientRect();\n var yPosition = this.config.popup ? this.position.y : elRect.top;\n // skip if cursor is outside of popupParent vertically\n var skipY = ((yPosition <= 0 && parentRect.top >= e.clientY) ||\n (parentRect.bottom <= e.clientY && parentRect.bottom <= boundaryElRect.bottom));\n if (skipY) {\n return true;\n }\n if (isTop) {\n skipY = (\n // skip if we are moving to towards top and the cursor is\n // below the top anchor + topBuffer\n // note: topBuffer is used when moving the dialog using the title bar\n (diff < 0 && e.clientY > yPosition + parentRect.top + topBuffer) ||\n // skip if we are moving to the bottom and the cursor is\n // above the top anchor\n (diff > 0 && e.clientY < yPosition + parentRect.top));\n }\n else {\n skipY = (\n // skip if we are moving towards the top and the cursor\n // is below the bottom anchor\n (diff < 0 && e.clientY > boundaryElRect.bottom) ||\n // skip if we are moving towards the bottom and the cursor\n // is above the bottom anchor\n (diff > 0 && e.clientY < boundaryElRect.bottom));\n }\n return skipY;\n };\n PositionableFeature.prototype.createResizeMap = function () {\n var eGui = this.element;\n this.resizerMap = {\n topLeft: { element: eGui.querySelector('[ref=eTopLeftResizer]') },\n top: { element: eGui.querySelector('[ref=eTopResizer]') },\n topRight: { element: eGui.querySelector('[ref=eTopRightResizer]') },\n right: { element: eGui.querySelector('[ref=eRightResizer]') },\n bottomRight: { element: eGui.querySelector('[ref=eBottomRightResizer]') },\n bottom: { element: eGui.querySelector('[ref=eBottomResizer]') },\n bottomLeft: { element: eGui.querySelector('[ref=eBottomLeftResizer]') },\n left: { element: eGui.querySelector('[ref=eLeftResizer]') }\n };\n };\n PositionableFeature.prototype.addResizers = function () {\n if (this.resizersAdded) {\n return;\n }\n var eGui = this.element;\n if (!eGui) {\n return;\n }\n var parser = new DOMParser();\n var resizers = parser.parseFromString(RESIZE_TEMPLATE, 'text/html').body;\n eGui.appendChild(resizers.firstChild);\n this.createResizeMap();\n this.resizersAdded = true;\n };\n PositionableFeature.prototype.removeResizers = function () {\n this.resizerMap = undefined;\n var resizerEl = this.element.querySelector(\".\" + RESIZE_CONTAINER_STYLE);\n if (resizerEl) {\n this.element.removeChild(resizerEl);\n }\n this.resizersAdded = false;\n };\n PositionableFeature.prototype.getResizerElement = function (side) {\n return this.resizerMap[side].element;\n };\n PositionableFeature.prototype.onResizeStart = function (e, side) {\n this.boundaryEl = this.findBoundaryElement();\n if (!this.positioned) {\n this.initialisePosition();\n }\n this.currentResizer = {\n isTop: !!side.match(/top/i),\n isRight: !!side.match(/right/i),\n isBottom: !!side.match(/bottom/i),\n isLeft: !!side.match(/left/i),\n };\n this.element.classList.add('ag-resizing');\n this.resizerMap[side].element.classList.add('ag-active');\n var _a = this.config, popup = _a.popup, forcePopupParentAsOffsetParent = _a.forcePopupParentAsOffsetParent;\n if (!popup && !forcePopupParentAsOffsetParent) {\n this.applySizeToSiblings(this.currentResizer.isBottom || this.currentResizer.isTop);\n }\n this.isResizing = true;\n this.updateDragStartPosition(e.clientX, e.clientY);\n };\n PositionableFeature.prototype.getSiblings = function () {\n var element = this.element;\n var parent = element.parentElement;\n if (!parent) {\n return null;\n }\n return Array.prototype.slice.call(parent.children).filter(function (el) { return !el.classList.contains('ag-hidden'); });\n };\n PositionableFeature.prototype.getMinSizeOfSiblings = function () {\n var siblings = this.getSiblings() || [];\n var height = 0;\n var width = 0;\n for (var i = 0; i < siblings.length; i++) {\n var currentEl = siblings[i];\n var isFlex = !!currentEl.style.flex && currentEl.style.flex !== '0 0 auto';\n if (currentEl === this.element) {\n continue;\n }\n var nextHeight = this.minHeight || 0;\n var nextWidth = this.minWidth || 0;\n if (isFlex) {\n var computedStyle = window.getComputedStyle(currentEl);\n if (computedStyle.minHeight) {\n nextHeight = parseInt(computedStyle.minHeight, 10);\n }\n if (computedStyle.minWidth) {\n nextWidth = parseInt(computedStyle.minWidth, 10);\n }\n }\n else {\n nextHeight = currentEl.offsetHeight;\n nextWidth = currentEl.offsetWidth;\n }\n height += nextHeight;\n width += nextWidth;\n }\n return { height: height, width: width };\n };\n PositionableFeature.prototype.applySizeToSiblings = function (vertical) {\n var containerToFlex = null;\n var siblings = this.getSiblings();\n if (!siblings) {\n return;\n }\n for (var i = 0; i < siblings.length; i++) {\n var el = siblings[i];\n if (el === containerToFlex) {\n continue;\n }\n if (vertical) {\n el.style.height = el.offsetHeight + \"px\";\n }\n else {\n el.style.width = el.offsetWidth + \"px\";\n }\n el.style.flex = '0 0 auto';\n if (el === this.element) {\n containerToFlex = siblings[i + 1];\n }\n }\n if (containerToFlex) {\n containerToFlex.style.removeProperty('height');\n containerToFlex.style.removeProperty('min-height');\n containerToFlex.style.removeProperty('max-height');\n containerToFlex.style.flex = '1 1 auto';\n }\n };\n PositionableFeature.prototype.onResize = function (e) {\n if (!this.isResizing || !this.currentResizer) {\n return;\n }\n var _a = this.config, popup = _a.popup, forcePopupParentAsOffsetParent = _a.forcePopupParentAsOffsetParent;\n var _b = this.currentResizer, isTop = _b.isTop, isRight = _b.isRight, isBottom = _b.isBottom, isLeft = _b.isLeft;\n var isHorizontal = isRight || isLeft;\n var isVertical = isBottom || isTop;\n var _c = this.calculateMouseMovement({ e: e, isLeft: isLeft, isTop: isTop }), movementX = _c.movementX, movementY = _c.movementY;\n var xPosition = this.position.x;\n var yPosition = this.position.y;\n var offsetLeft = 0;\n var offsetTop = 0;\n if (isHorizontal && movementX) {\n var direction = isLeft ? -1 : 1;\n var oldWidth = this.getWidth();\n var newWidth = oldWidth + (movementX * direction);\n var skipWidth = false;\n if (isLeft) {\n offsetLeft = oldWidth - newWidth;\n if (xPosition + offsetLeft <= 0 || newWidth <= this.minWidth) {\n skipWidth = true;\n offsetLeft = 0;\n }\n }\n if (!skipWidth) {\n this.setWidth(newWidth);\n }\n }\n if (isVertical && movementY) {\n var direction = isTop ? -1 : 1;\n var oldHeight = this.getHeight();\n var newHeight = oldHeight + (movementY * direction);\n var skipHeight = false;\n if (isTop) {\n offsetTop = oldHeight - newHeight;\n if (yPosition + offsetTop <= 0 || newHeight <= this.minHeight) {\n skipHeight = true;\n offsetTop = 0;\n }\n }\n else {\n // do not let the size of all siblings be higher than the parent container\n if (!this.config.popup &&\n !this.config.forcePopupParentAsOffsetParent &&\n oldHeight < newHeight &&\n (this.getMinSizeOfSiblings().height + newHeight) > this.element.parentElement.offsetHeight) {\n skipHeight = true;\n }\n }\n if (!skipHeight) {\n this.setHeight(newHeight);\n }\n }\n this.updateDragStartPosition(e.clientX, e.clientY);\n if ((popup || forcePopupParentAsOffsetParent) && offsetLeft || offsetTop) {\n this.offsetElement(xPosition + offsetLeft, yPosition + offsetTop);\n }\n };\n PositionableFeature.prototype.onResizeEnd = function (e, side) {\n this.isResizing = false;\n this.currentResizer = null;\n this.boundaryEl = null;\n var params = {\n type: 'resize',\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi()\n };\n this.element.classList.remove('ag-resizing');\n this.resizerMap[side].element.classList.remove('ag-active');\n this.dispatchEvent(params);\n };\n PositionableFeature.prototype.refreshSize = function () {\n var eGui = this.element;\n if (this.config.popup) {\n if (!this.config.width) {\n this.setWidth(eGui.offsetWidth);\n }\n if (!this.config.height) {\n this.setHeight(eGui.offsetHeight);\n }\n }\n };\n PositionableFeature.prototype.onMoveStart = function (e) {\n this.boundaryEl = this.findBoundaryElement();\n if (!this.positioned) {\n this.initialisePosition();\n }\n this.isMoving = true;\n this.element.classList.add('ag-moving');\n this.updateDragStartPosition(e.clientX, e.clientY);\n };\n PositionableFeature.prototype.onMove = function (e) {\n if (!this.isMoving) {\n return;\n }\n var _a = this.position, x = _a.x, y = _a.y;\n var topBuffer;\n if (this.config.calculateTopBuffer) {\n topBuffer = this.config.calculateTopBuffer();\n }\n var _b = this.calculateMouseMovement({\n e: e,\n isTop: true,\n anywhereWithin: true,\n topBuffer: topBuffer\n }), movementX = _b.movementX, movementY = _b.movementY;\n this.offsetElement(x + movementX, y + movementY);\n this.updateDragStartPosition(e.clientX, e.clientY);\n };\n PositionableFeature.prototype.onMoveEnd = function () {\n this.isMoving = false;\n this.boundaryEl = null;\n this.element.classList.remove('ag-moving');\n };\n PositionableFeature.prototype.setOffsetParent = function () {\n if (this.config.forcePopupParentAsOffsetParent) {\n this.offsetParent = this.popupService.getPopupParent();\n }\n else {\n this.offsetParent = this.element.offsetParent;\n }\n };\n PositionableFeature.prototype.findBoundaryElement = function () {\n var el = this.element;\n while (el) {\n if (window.getComputedStyle(el).position !== 'static') {\n return el;\n }\n el = el.parentElement;\n }\n return this.element;\n };\n PositionableFeature.prototype.clearResizeListeners = function () {\n while (this.resizeListeners.length) {\n var params = this.resizeListeners.pop();\n this.dragService.removeDragSource(params);\n }\n };\n PositionableFeature.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n if (this.moveElementDragListener) {\n this.dragService.removeDragSource(this.moveElementDragListener);\n }\n this.clearResizeListeners();\n this.removeResizers();\n };\n __decorate$16([\n Autowired('popupService')\n ], PositionableFeature.prototype, \"popupService\", void 0);\n __decorate$16([\n Autowired('dragService')\n ], PositionableFeature.prototype, \"dragService\", void 0);\n return PositionableFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1c = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$15 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AutoWidthCalculator = /** @class */ (function (_super) {\n __extends$1c(AutoWidthCalculator, _super);\n function AutoWidthCalculator() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n AutoWidthCalculator.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) {\n _this.centerRowContainerCtrl = p.centerRowContainerCtrl;\n });\n };\n // this is the trick: we create a dummy container and clone all the cells\n // into the dummy, then check the dummy's width. then destroy the dummy\n // as we don't need it any more.\n // drawback: only the cells visible on the screen are considered\n AutoWidthCalculator.prototype.getPreferredWidthForColumn = function (column, skipHeader) {\n var eHeaderCell = this.getHeaderCellForColumn(column);\n // cell isn't visible\n if (!eHeaderCell) {\n return -1;\n }\n var elements = this.rowRenderer.getAllCellsForColumn(column);\n if (!skipHeader) {\n // we only consider the lowest level cell, not the group cell. in 99% of the time, this\n // will be enough. if we consider groups, then it gets too complicated for what it's worth,\n // as the groups can span columns and this class only considers one column at a time.\n elements.push(eHeaderCell);\n }\n return this.addElementsToContainerAndGetWidth(elements);\n };\n AutoWidthCalculator.prototype.getPreferredWidthForColumnGroup = function (columnGroup) {\n var eHeaderCell = this.getHeaderCellForColumn(columnGroup);\n if (!eHeaderCell) {\n return -1;\n }\n return this.addElementsToContainerAndGetWidth([eHeaderCell]);\n };\n AutoWidthCalculator.prototype.addElementsToContainerAndGetWidth = function (elements) {\n var _this = this;\n var eDummyContainer = document.createElement('span');\n // position fixed, so it isn't restricted to the boundaries of the parent\n eDummyContainer.style.position = 'fixed';\n // we put the dummy into the body container, so it will inherit all the\n // css styles that the real cells are inheriting\n var eBodyContainer = this.centerRowContainerCtrl.getContainerElement();\n eBodyContainer.appendChild(eDummyContainer);\n elements.forEach(function (el) { return _this.cloneItemIntoDummy(el, eDummyContainer); });\n // at this point, all the clones are lined up vertically with natural widths. the dummy\n // container will have a width wide enough just to fit the largest.\n var dummyContainerWidth = eDummyContainer.offsetWidth;\n // we are finished with the dummy container, so get rid of it\n eBodyContainer.removeChild(eDummyContainer);\n // we add padding as I found sometimes the gui still put '...' after some of the texts. so the\n // user can configure the grid to add a few more pixels after the calculated width\n var autoSizePadding = this.gridOptionsWrapper.getAutoSizePadding();\n return dummyContainerWidth + autoSizePadding;\n };\n AutoWidthCalculator.prototype.getHeaderCellForColumn = function (column) {\n /* tslint:enable */\n var element = null;\n this.ctrlsService.getHeaderRowContainerCtrls().forEach(function (container) {\n var res = container.getHtmlElementForColumnHeader(column);\n if (res != null) {\n element = res;\n }\n });\n return element;\n };\n AutoWidthCalculator.prototype.cloneItemIntoDummy = function (eCell, eDummyContainer) {\n // make a deep clone of the cell\n var eCellClone = eCell.cloneNode(true);\n // the original has a fixed width, we remove this to allow the natural width based on content\n eCellClone.style.width = '';\n // the original has position = absolute, we need to remove this so it's positioned normally\n eCellClone.style.position = 'static';\n eCellClone.style.left = '';\n // we put the cell into a containing div, as otherwise the cells would just line up\n // on the same line, standard flow layout, by putting them into divs, they are laid\n // out one per line\n var eCloneParent = document.createElement('div');\n var eCloneParentClassList = eCloneParent.classList;\n var isHeader = ['ag-header-cell', 'ag-header-group-cell'].some(function (cls) { return eCellClone.classList.contains(cls); });\n if (isHeader) {\n eCloneParentClassList.add('ag-header', 'ag-header-row');\n eCloneParent.style.position = 'static';\n }\n else {\n eCloneParentClassList.add('ag-row');\n }\n // find parent using classes (headers have ag-header-cell, rows have ag-row), and copy classes from it.\n // if we didn't do this, things like ag-row-level-2 would be missing if present, which sets indents\n // onto group items.\n var pointer = eCell.parentElement;\n while (pointer) {\n var isRow = ['ag-header-row', 'ag-row'].some(function (cls) { return pointer.classList.contains(cls); });\n if (isRow) {\n for (var i = 0; i < pointer.classList.length; i++) {\n var item = pointer.classList[i];\n // we skip ag-row-position-absolute, as this has structural CSS applied that stops the\n // element from fitting into it's parent, and we need the element to stretch the parent\n // as we are measuring the parents width\n if (item != 'ag-row-position-absolute') {\n eCloneParentClassList.add(item);\n }\n }\n break;\n }\n pointer = pointer.parentElement;\n }\n // the twig on the branch, the branch on the tree, the tree in the hole,\n // the hole in the bog, the bog in the clone, the clone in the parent,\n // the parent in the dummy, and the dummy down in the vall-e-ooo, OOOOOOOOO! Oh row the rattling bog....\n eCloneParent.appendChild(eCellClone);\n eDummyContainer.appendChild(eCloneParent);\n };\n __decorate$15([\n Autowired('rowRenderer')\n ], AutoWidthCalculator.prototype, \"rowRenderer\", void 0);\n __decorate$15([\n Autowired('ctrlsService')\n ], AutoWidthCalculator.prototype, \"ctrlsService\", void 0);\n __decorate$15([\n Autowired('rowCssClassCalculator')\n ], AutoWidthCalculator.prototype, \"rowCssClassCalculator\", void 0);\n __decorate$15([\n PostConstruct\n ], AutoWidthCalculator.prototype, \"postConstruct\", null);\n AutoWidthCalculator = __decorate$15([\n Bean('autoWidthCalculator')\n ], AutoWidthCalculator);\n return AutoWidthCalculator;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1b = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$14 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __values$1 = (undefined && undefined.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\nvar __read$b = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$9 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$b(arguments[i]));\n return ar;\n};\nvar StickyRowFeature = /** @class */ (function (_super) {\n __extends$1b(StickyRowFeature, _super);\n function StickyRowFeature(createRowCon, destroyRowCtrls) {\n var _this = _super.call(this) || this;\n _this.createRowCon = createRowCon;\n _this.destroyRowCtrls = destroyRowCtrls;\n _this.stickyRowCtrls = [];\n _this.containerHeight = 0;\n return _this;\n }\n StickyRowFeature.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (params) {\n _this.gridBodyCtrl = params.gridBodyCtrl;\n });\n };\n StickyRowFeature.prototype.getStickyRowCtrls = function () {\n return this.stickyRowCtrls;\n };\n StickyRowFeature.prototype.checkStickyRows = function () {\n var height = 0;\n if (!this.gridOptionsWrapper.isGroupRowsSticky()) {\n this.refreshNodesAndContainerHeight([], height);\n return;\n }\n var stickyRows = [];\n var firstPixel = this.rowRenderer.getFirstVisibleVerticalPixel();\n var addStickyRow = function (stickyRow) {\n stickyRows.push(stickyRow);\n var lastAncester = stickyRow;\n while (lastAncester.expanded) {\n lastAncester = last(lastAncester.childrenAfterSort);\n }\n var lastChildBottom = lastAncester.rowTop + lastAncester.rowHeight;\n var stickRowBottom = firstPixel + height + stickyRow.rowHeight;\n if (lastChildBottom < stickRowBottom) {\n stickyRow.stickyRowTop = height + (lastChildBottom - stickRowBottom);\n }\n else {\n stickyRow.stickyRowTop = height;\n }\n height = 0;\n stickyRows.forEach(function (rowNode) {\n var thisRowLastPx = rowNode.stickyRowTop + rowNode.rowHeight;\n if (height < thisRowLastPx) {\n height = thisRowLastPx;\n }\n });\n };\n while (true) {\n var firstPixelAfterStickyRows = firstPixel + height;\n var firstIndex = this.rowModel.getRowIndexAtPixel(firstPixelAfterStickyRows);\n var firstRow = this.rowModel.getRow(firstIndex);\n if (firstRow == null) {\n break;\n }\n // only happens when pivoting, and we are showing root node\n if (firstRow.level < 0) {\n break;\n }\n var parents = [];\n var p = firstRow.parent;\n while (p.level >= 0) {\n parents.push(p);\n p = p.parent;\n }\n var firstMissingParent = parents.reverse().find(function (parent) { return stickyRows.indexOf(parent) < 0 && parent.displayed; });\n if (firstMissingParent) {\n addStickyRow(firstMissingParent);\n continue;\n }\n // if first row is an open group, and practically shown, it needs\n // to be stuck\n if (firstRow.group && firstRow.expanded && !firstRow.footer && firstRow.rowTop < firstPixelAfterStickyRows) {\n addStickyRow(firstRow);\n continue;\n }\n break;\n }\n this.refreshNodesAndContainerHeight(stickyRows, height);\n };\n StickyRowFeature.prototype.refreshNodesAndContainerHeight = function (allStickyNodes, height) {\n var e_1, _a, _b;\n var _this = this;\n var removedCtrls = this.stickyRowCtrls.filter(function (ctrl) { return allStickyNodes.indexOf(ctrl.getRowNode()) === -1; });\n var addedNodes = allStickyNodes.filter(function (rowNode) { return _this.stickyRowCtrls.findIndex(function (ctrl) { return ctrl.getRowNode() === rowNode; }) === -1; });\n var ctrlsToDestroy = {};\n removedCtrls.forEach(function (removedCtrl) {\n ctrlsToDestroy[removedCtrl.getRowNode().id] = removedCtrl;\n _this.stickyRowCtrls = _this.stickyRowCtrls.filter(function (ctrl) { return ctrl !== removedCtrl; });\n });\n try {\n for (var _c = __values$1(Object.values(ctrlsToDestroy)), _d = _c.next(); !_d.done; _d = _c.next()) {\n var ctrl = _d.value;\n ctrl.getRowNode().sticky = false;\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (_d && !_d.done && (_a = _c.return)) _a.call(_c);\n }\n finally { if (e_1) throw e_1.error; }\n }\n this.destroyRowCtrls(ctrlsToDestroy, false);\n var newCtrls = addedNodes.map(function (rowNode) {\n rowNode.sticky = true;\n return _this.createRowCon(rowNode, false, false);\n });\n (_b = this.stickyRowCtrls).push.apply(_b, __spread$9(newCtrls));\n this.stickyRowCtrls.forEach(function (ctrl) { return ctrl.setRowTop(ctrl.getRowNode().stickyRowTop); });\n this.stickyRowCtrls.sort(function (a, b) { return b.getRowNode().rowIndex - a.getRowNode().rowIndex; });\n if (this.containerHeight !== height) {\n this.containerHeight = height;\n this.gridBodyCtrl.setStickyTopHeight(height);\n }\n };\n __decorate$14([\n Autowired(\"rowModel\")\n ], StickyRowFeature.prototype, \"rowModel\", void 0);\n __decorate$14([\n Autowired(\"rowRenderer\")\n ], StickyRowFeature.prototype, \"rowRenderer\", void 0);\n __decorate$14([\n Autowired(\"ctrlsService\")\n ], StickyRowFeature.prototype, \"ctrlsService\", void 0);\n __decorate$14([\n PostConstruct\n ], StickyRowFeature.prototype, \"postConstruct\", null);\n return StickyRowFeature;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$1a = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$13 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$a = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$8 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$a(arguments[i]));\n return ar;\n};\nvar RowRenderer = /** @class */ (function (_super) {\n __extends$1a(RowRenderer, _super);\n function RowRenderer() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.destroyFuncsForColumnListeners = [];\n // map of row ids to row objects. keeps track of which elements\n // are rendered for which rows in the dom.\n _this.rowCtrlsByRowIndex = {};\n _this.zombieRowCtrls = {};\n _this.allRowCtrls = [];\n _this.topRowCtrls = [];\n _this.bottomRowCtrls = [];\n // we only allow one refresh at a time, otherwise the internal memory structure here\n // will get messed up. this can happen if the user has a cellRenderer, and inside the\n // renderer they call an API method that results in another pass of the refresh,\n // then it will be trying to draw rows in the middle of a refresh.\n _this.refreshInProgress = false;\n _this.dataFirstRenderedFired = false;\n return _this;\n }\n RowRenderer.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function () {\n _this.gridBodyCtrl = _this.ctrlsService.getGridBodyCtrl();\n _this.initialise();\n });\n };\n RowRenderer.prototype.initialise = function () {\n this.addManagedListener(this.eventService, Events.EVENT_PAGINATION_CHANGED, this.onPageLoaded.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_PINNED_ROW_DATA_CHANGED, this.onPinnedRowDataChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_BODY_SCROLL, this.redrawAfterScroll.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_BODY_HEIGHT_CHANGED, this.redrawAfterScroll.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, this.onDomLayoutChanged.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_ROW_CLASS, this.redrawRows.bind(this));\n if (this.gridOptionsWrapper.isGroupRowsSticky()) {\n if (this.rowModel.getType() != Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n doOnce(function () { return console.warn('AG Grid: The feature Sticky Row Groups only works with the Client Side Row Model'); }, 'rowRenderer.stickyWorksWithCsrmOnly');\n }\n else if (this.gridOptionsWrapper.isTreeData()) {\n doOnce(function () { return console.warn('AG Grid: The feature Sticky Row Groups does not work with Tree Data.'); }, 'rowRenderer.stickyDoesNotWorkWithTreeData');\n }\n else {\n this.stickyRowFeature = this.createManagedBean(new StickyRowFeature(this.createRowCon.bind(this), this.destroyRowCtrls.bind(this)));\n }\n }\n this.registerCellEventListeners();\n this.initialiseCache();\n this.printLayout = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n this.embedFullWidthRows = this.printLayout || this.gridOptionsWrapper.isEmbedFullWidthRows();\n this.redrawAfterModelUpdate();\n };\n RowRenderer.prototype.initialiseCache = function () {\n if (this.gridOptionsWrapper.isKeepDetailRows()) {\n var countProp = this.gridOptionsWrapper.getKeepDetailRowsCount();\n var count = countProp != null ? countProp : 3;\n this.cachedRowCtrls = new RowCtrlCache(count);\n }\n };\n RowRenderer.prototype.getRowCtrls = function () {\n return this.allRowCtrls;\n };\n RowRenderer.prototype.getStickyTopRowCtrls = function () {\n if (!this.stickyRowFeature) {\n return [];\n }\n return this.stickyRowFeature.getStickyRowCtrls();\n };\n RowRenderer.prototype.updateAllRowCtrls = function () {\n var liveList = getAllValuesInObject(this.rowCtrlsByRowIndex);\n if (this.gridOptionsWrapper.isEnsureDomOrder()) {\n liveList.sort(function (a, b) { return a.getRowNode().rowIndex - b.getRowNode.rowIndex; });\n }\n var zombieList = getAllValuesInObject(this.zombieRowCtrls);\n var cachedList = this.cachedRowCtrls ? this.cachedRowCtrls.getEntries() : [];\n this.allRowCtrls = __spread$8(liveList, zombieList, cachedList);\n };\n // in a clean design, each cell would register for each of these events. however when scrolling, all the cells\n // registering and de-registering for events is a performance bottleneck. so we register here once and inform\n // all active cells.\n RowRenderer.prototype.registerCellEventListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_CELL_FOCUSED, function (event) {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onCellFocused(event); });\n _this.getFullWidthRowCtrls().forEach(function (rowCtrl) {\n rowCtrl.onFullWidthRowFocused(event);\n });\n });\n this.addManagedListener(this.eventService, Events.EVENT_FLASH_CELLS, function (event) {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onFlashCells(event); });\n });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_HOVER_CHANGED, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onColumnHover(); });\n });\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onDisplayedColumnsChanged(); });\n });\n // only for printLayout - because we are rendering all the cells in the same row, regardless of pinned state,\n // then changing the width of the containers will impact left position. eg the center cols all have their\n // left position adjusted by the width of the left pinned column, so if the pinned left column width changes,\n // all the center cols need to be shifted to accommodate this. when in normal layout, the pinned cols are\n // in different containers so doesn't impact.\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, function () {\n if (_this.printLayout) {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onLeftChanged(); });\n }\n });\n var rangeSelectionEnabled = this.gridOptionsWrapper.isEnableRangeSelection();\n if (rangeSelectionEnabled) {\n this.addManagedListener(this.eventService, Events.EVENT_RANGE_SELECTION_CHANGED, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.onRangeSelectionChanged(); });\n });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_MOVED, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.updateRangeBordersIfRangeCount(); });\n });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PINNED, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.updateRangeBordersIfRangeCount(); });\n });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_VISIBLE, function () {\n _this.getAllCellCtrls().forEach(function (cellCtrl) { return cellCtrl.updateRangeBordersIfRangeCount(); });\n });\n }\n // add listeners to the grid columns\n this.refreshListenersToColumnsForCellComps();\n // if the grid columns change, then refresh the listeners again\n this.addManagedListener(this.eventService, Events.EVENT_GRID_COLUMNS_CHANGED, this.refreshListenersToColumnsForCellComps.bind(this));\n this.addDestroyFunc(this.removeGridColumnListeners.bind(this));\n };\n // executes all functions in destroyFuncsForColumnListeners and then clears the list\n RowRenderer.prototype.removeGridColumnListeners = function () {\n this.destroyFuncsForColumnListeners.forEach(function (func) { return func(); });\n this.destroyFuncsForColumnListeners.length = 0;\n };\n // this function adds listeners onto all the grid columns, which are the column that we could have cellComps for.\n // when the grid columns change, we add listeners again. in an ideal design, each CellComp would just register to\n // the column it belongs to on creation, however this was a bottleneck with the number of cells, so do it here\n // once instead.\n RowRenderer.prototype.refreshListenersToColumnsForCellComps = function () {\n var _this = this;\n this.removeGridColumnListeners();\n var cols = this.columnModel.getAllGridColumns();\n if (!cols) {\n return;\n }\n cols.forEach(function (col) {\n var forEachCellWithThisCol = function (callback) {\n _this.getAllCellCtrls().forEach(function (cellCtrl) {\n if (cellCtrl.getColumn() === col) {\n callback(cellCtrl);\n }\n });\n };\n var leftChangedListener = function () {\n forEachCellWithThisCol(function (cellCtrl) { return cellCtrl.onLeftChanged(); });\n };\n var widthChangedListener = function () {\n forEachCellWithThisCol(function (cellCtrl) { return cellCtrl.onWidthChanged(); });\n };\n var firstRightPinnedChangedListener = function () {\n forEachCellWithThisCol(function (cellCtrl) { return cellCtrl.onFirstRightPinnedChanged(); });\n };\n var lastLeftPinnedChangedListener = function () {\n forEachCellWithThisCol(function (cellCtrl) { return cellCtrl.onLastLeftPinnedChanged(); });\n };\n var colDefChangedListener = function () {\n forEachCellWithThisCol(function (cellCtrl) { return cellCtrl.onColDefChanged(); });\n };\n col.addEventListener(Column.EVENT_LEFT_CHANGED, leftChangedListener);\n col.addEventListener(Column.EVENT_WIDTH_CHANGED, widthChangedListener);\n col.addEventListener(Column.EVENT_FIRST_RIGHT_PINNED_CHANGED, firstRightPinnedChangedListener);\n col.addEventListener(Column.EVENT_LAST_LEFT_PINNED_CHANGED, lastLeftPinnedChangedListener);\n col.addEventListener(Column.EVENT_COL_DEF_CHANGED, colDefChangedListener);\n _this.destroyFuncsForColumnListeners.push(function () {\n col.removeEventListener(Column.EVENT_LEFT_CHANGED, leftChangedListener);\n col.removeEventListener(Column.EVENT_WIDTH_CHANGED, widthChangedListener);\n col.removeEventListener(Column.EVENT_FIRST_RIGHT_PINNED_CHANGED, firstRightPinnedChangedListener);\n col.removeEventListener(Column.EVENT_LAST_LEFT_PINNED_CHANGED, lastLeftPinnedChangedListener);\n col.removeEventListener(Column.EVENT_COL_DEF_CHANGED, colDefChangedListener);\n });\n });\n };\n RowRenderer.prototype.onDomLayoutChanged = function () {\n var printLayout = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n var embedFullWidthRows = printLayout || this.gridOptionsWrapper.isEmbedFullWidthRows();\n // if moving towards or away from print layout, means we need to destroy all rows, as rows are not laid\n // out using absolute positioning when doing print layout\n var destroyRows = embedFullWidthRows !== this.embedFullWidthRows || this.printLayout !== printLayout;\n this.printLayout = printLayout;\n this.embedFullWidthRows = embedFullWidthRows;\n if (destroyRows) {\n this.redrawAfterModelUpdate();\n }\n };\n // for row models that have datasources, when we update the datasource, we need to force the rowRenderer\n // to redraw all rows. otherwise the old rows from the old datasource will stay displayed.\n RowRenderer.prototype.datasourceChanged = function () {\n this.firstRenderedRow = 0;\n this.lastRenderedRow = -1;\n var rowIndexesToRemove = Object.keys(this.rowCtrlsByRowIndex);\n this.removeRowCtrls(rowIndexesToRemove);\n };\n RowRenderer.prototype.onPageLoaded = function (event) {\n var params = {\n recycleRows: event.keepRenderedRows,\n animate: event.animate,\n newData: event.newData,\n newPage: event.newPage,\n // because this is a model updated event (not pinned rows), we\n // can skip updating the pinned rows. this is needed so that if user\n // is doing transaction updates, the pinned rows are not getting constantly\n // trashed - or editing cells in pinned rows are not refreshed and put into read mode\n onlyBody: true\n };\n this.redrawAfterModelUpdate(params);\n };\n RowRenderer.prototype.getAllCellsForColumn = function (column) {\n var res = [];\n this.getAllRowCtrls().forEach(function (rowCtrl) {\n var eCell = rowCtrl.getCellElement(column);\n if (eCell) {\n res.push(eCell);\n }\n });\n return res;\n };\n RowRenderer.prototype.refreshFloatingRowComps = function () {\n this.refreshFloatingRows(this.topRowCtrls, this.pinnedRowModel.getPinnedTopRowData());\n this.refreshFloatingRows(this.bottomRowCtrls, this.pinnedRowModel.getPinnedBottomRowData());\n };\n RowRenderer.prototype.getTopRowCtrls = function () {\n return this.topRowCtrls;\n };\n RowRenderer.prototype.getBottomRowCtrls = function () {\n return this.bottomRowCtrls;\n };\n RowRenderer.prototype.refreshFloatingRows = function (rowComps, rowNodes) {\n var _this = this;\n rowComps.forEach(function (row) {\n row.destroyFirstPass();\n row.destroySecondPass();\n });\n rowComps.length = 0;\n if (!rowNodes) {\n return;\n }\n rowNodes.forEach(function (rowNode) {\n var rowCtrl = new RowCtrl(rowNode, _this.beans, false, false, _this.printLayout);\n rowComps.push(rowCtrl);\n });\n };\n RowRenderer.prototype.onPinnedRowDataChanged = function () {\n // recycling rows in order to ensure cell editing is not cancelled\n var params = {\n recycleRows: true\n };\n this.redrawAfterModelUpdate(params);\n };\n // if the row nodes are not rendered, no index is returned\n RowRenderer.prototype.getRenderedIndexesForRowNodes = function (rowNodes) {\n var result = [];\n if (missing(rowNodes)) {\n return result;\n }\n iterateObject(this.rowCtrlsByRowIndex, function (index, renderedRow) {\n var rowNode = renderedRow.getRowNode();\n if (rowNodes.indexOf(rowNode) >= 0) {\n result.push(index);\n }\n });\n return result;\n };\n RowRenderer.prototype.redrawRows = function (rowNodes) {\n // if no row nodes provided, then refresh everything\n var partialRefresh = rowNodes != null && rowNodes.length > 0;\n if (partialRefresh) {\n var indexesToRemove = this.getRenderedIndexesForRowNodes(rowNodes);\n // remove the rows\n this.removeRowCtrls(indexesToRemove);\n }\n // add draw them again\n this.redrawAfterModelUpdate({\n recycleRows: partialRefresh\n });\n };\n RowRenderer.prototype.getCellToRestoreFocusToAfterRefresh = function (params) {\n var _a;\n var focusedCell = ((_a = params) === null || _a === void 0 ? void 0 : _a.suppressKeepFocus) ? null : this.focusService.getFocusCellToUseAfterRefresh();\n if (focusedCell == null) {\n return null;\n }\n // if the dom is not actually focused on a cell, then we don't try to refocus. the problem this\n // solves is with editing - if the user is editing, eg focus is on a text field, and not on the\n // cell itself, then the cell can be registered as having focus, however it's the text field that\n // has the focus and not the cell div. therefore, when the refresh is finished, the grid will focus\n // the cell, and not the textfield. that means if the user is in a text field, and the grid refreshes,\n // the focus is lost from the text field. we do not want this.\n var eDocument = this.gridOptionsWrapper.getDocument();\n var activeElement = eDocument.activeElement;\n var cellDomData = this.gridOptionsWrapper.getDomData(activeElement, CellCtrl.DOM_DATA_KEY_CELL_CTRL);\n var rowDomData = this.gridOptionsWrapper.getDomData(activeElement, RowCtrl.DOM_DATA_KEY_ROW_CTRL);\n var gridElementFocused = cellDomData || rowDomData;\n return gridElementFocused ? focusedCell : null;\n };\n // gets called from:\n // +) initialisation (in registerGridComp) params = null\n // +) onDomLayoutChanged, params = null\n // +) onPageLoaded, recycleRows, animate, newData, newPage from event, onlyBody=true\n // +) onPinnedRowDataChanged, recycleRows = true\n // +) redrawRows (from Grid API), recycleRows = true/false\n RowRenderer.prototype.redrawAfterModelUpdate = function (params) {\n if (params === void 0) { params = {}; }\n this.getLockOnRefresh();\n var focusedCell = this.getCellToRestoreFocusToAfterRefresh(params);\n this.updateContainerHeights();\n this.scrollToTopIfNewData(params);\n // never recycle rows when print layout, we draw each row again from scratch. this is because print layout\n // uses normal dom layout to put cells into dom - it doesn't allow reordering rows.\n var recycleRows = !this.printLayout && !!params.recycleRows;\n var animate = params.animate && this.gridOptionsWrapper.isAnimateRows();\n // after modelUpdate, row indexes can change, so we clear out the rowsByIndex map,\n // however we can reuse the rows, so we keep them but index by rowNode.id\n var rowsToRecycle = recycleRows ? this.recycleRows() : null;\n if (!recycleRows) {\n this.removeAllRowComps();\n }\n var isFocusedCellGettingRecycled = function () {\n if (focusedCell == null || rowsToRecycle == null) {\n return false;\n }\n var res = false;\n iterateObject(rowsToRecycle, function (key, rowComp) {\n var rowNode = rowComp.getRowNode();\n var rowIndexEqual = rowNode.rowIndex == focusedCell.rowIndex;\n var pinnedEqual = rowNode.rowPinned == focusedCell.rowPinned;\n if (rowIndexEqual && pinnedEqual) {\n res = true;\n }\n });\n return res;\n };\n var focusedCellRecycled = isFocusedCellGettingRecycled();\n this.redraw(rowsToRecycle, animate);\n this.gridBodyCtrl.updateRowCount();\n if (!params.onlyBody) {\n this.refreshFloatingRowComps();\n }\n this.dispatchDisplayedRowsChanged();\n // if we focus a cell that's already focused, then we get an unnecessary 'cellFocused' event fired.\n // this was happening when user clicked 'expand' on a rowGroup, then cellFocused was getting fired twice.\n if (!focusedCellRecycled) {\n this.restoreFocusedCell(focusedCell);\n }\n this.releaseLockOnRefresh();\n };\n RowRenderer.prototype.scrollToTopIfNewData = function (params) {\n var scrollToTop = params.newData || params.newPage;\n var suppressScrollToTop = this.gridOptionsWrapper.isSuppressScrollOnNewData();\n if (scrollToTop && !suppressScrollToTop) {\n this.gridBodyCtrl.getScrollFeature().scrollToTop();\n }\n };\n RowRenderer.prototype.updateContainerHeights = function () {\n // when doing print layout, we don't explicitly set height on the containers\n if (this.printLayout) {\n this.rowContainerHeightService.setModelHeight(null);\n return;\n }\n var containerHeight = this.paginationProxy.getCurrentPageHeight();\n // we need at least 1 pixel for the horizontal scroll to work. so if there are now rows,\n // we still want the scroll to be present, otherwise there would be no way to scroll the header\n // which might be needed us user wants to access columns\n // on the RHS - and if that was where the filter was that cause no rows to be presented, there\n // is no way to remove the filter.\n if (containerHeight === 0) {\n containerHeight = 1;\n }\n this.rowContainerHeightService.setModelHeight(containerHeight);\n };\n RowRenderer.prototype.getLockOnRefresh = function () {\n if (this.refreshInProgress) {\n throw new Error(\"AG Grid: cannot get grid to draw rows when it is in the middle of drawing rows. \" +\n \"Your code probably called a grid API method while the grid was in the render stage. To overcome \" +\n \"this, put the API call into a timeout, e.g. instead of api.redrawRows(), \" +\n \"call setTimeout(function() { api.redrawRows(); }, 0). To see what part of your code \" +\n \"that caused the refresh check this stacktrace.\");\n }\n this.refreshInProgress = true;\n };\n RowRenderer.prototype.releaseLockOnRefresh = function () {\n this.refreshInProgress = false;\n };\n RowRenderer.prototype.isRefreshInProgress = function () {\n return this.refreshInProgress;\n };\n // sets the focus to the provided cell, if the cell is provided. this way, the user can call refresh without\n // worry about the focus been lost. this is important when the user is using keyboard navigation to do edits\n // and the cellEditor is calling 'refresh' to get other cells to update (as other cells might depend on the\n // edited cell).\n RowRenderer.prototype.restoreFocusedCell = function (cellPosition) {\n if (cellPosition) {\n this.focusService.setFocusedCell({\n rowIndex: cellPosition.rowIndex,\n column: cellPosition.column,\n rowPinned: cellPosition.rowPinned,\n forceBrowserFocus: true,\n preventScrollOnBrowserFocus: true\n });\n }\n };\n RowRenderer.prototype.stopEditing = function (cancel) {\n if (cancel === void 0) { cancel = false; }\n this.getAllRowCtrls().forEach(function (rowCtrl) {\n rowCtrl.stopEditing(cancel);\n });\n };\n RowRenderer.prototype.getAllCellCtrls = function () {\n var res = [];\n this.getAllRowCtrls().forEach(function (rowCtrl) { return res = res.concat(rowCtrl.getAllCellCtrls()); });\n return res;\n };\n RowRenderer.prototype.getAllRowCtrls = function () {\n var _this = this;\n var stickyRowCtrls = (this.stickyRowFeature && this.stickyRowFeature.getStickyRowCtrls()) || [];\n var res = __spread$8(this.topRowCtrls, this.bottomRowCtrls, stickyRowCtrls);\n Object.keys(this.rowCtrlsByRowIndex).forEach(function (key) { return res.push(_this.rowCtrlsByRowIndex[key]); });\n return res;\n };\n RowRenderer.prototype.addRenderedRowListener = function (eventName, rowIndex, callback) {\n var rowComp = this.rowCtrlsByRowIndex[rowIndex];\n if (rowComp) {\n rowComp.addEventListener(eventName, callback);\n }\n };\n RowRenderer.prototype.flashCells = function (params) {\n if (params === void 0) { params = {}; }\n var flashDelay = params.flashDelay, fadeDelay = params.fadeDelay;\n this.getCellCtrls(params.rowNodes, params.columns)\n .forEach(function (cellCtrl) { return cellCtrl.flashCell({ flashDelay: flashDelay, fadeDelay: fadeDelay }); });\n };\n RowRenderer.prototype.refreshCells = function (params) {\n if (params === void 0) { params = {}; }\n var refreshCellParams = {\n forceRefresh: params.force,\n newData: false,\n suppressFlash: params.suppressFlash\n };\n this.getCellCtrls(params.rowNodes, params.columns)\n .forEach(function (cellCtrl) {\n if (cellCtrl.refreshShouldDestroy()) {\n var rowCtrl = cellCtrl.getRowCtrl();\n if (rowCtrl) {\n rowCtrl.refreshCell(cellCtrl);\n }\n }\n else {\n cellCtrl.refreshCell(refreshCellParams);\n }\n });\n this.getFullWidthRowCtrls(params.rowNodes).forEach(function (fullWidthRowCtrl) {\n fullWidthRowCtrl.refreshFullWidth();\n });\n };\n RowRenderer.prototype.getCellRendererInstances = function (params) {\n var res = this.getCellCtrls(params.rowNodes, params.columns)\n .map(function (cellCtrl) { return cellCtrl.getCellRenderer(); })\n .filter(function (renderer) { return renderer != null; });\n return res;\n };\n RowRenderer.prototype.getCellEditorInstances = function (params) {\n var res = [];\n this.getCellCtrls(params.rowNodes, params.columns).forEach(function (cellCtrl) {\n var cellEditor = cellCtrl.getCellEditor();\n if (cellEditor) {\n res.push(cellEditor);\n }\n });\n return res;\n };\n RowRenderer.prototype.getEditingCells = function () {\n var res = [];\n this.getAllCellCtrls().forEach(function (cellCtrl) {\n if (cellCtrl.isEditing()) {\n var cellPosition = cellCtrl.getCellPosition();\n res.push(cellPosition);\n }\n });\n return res;\n };\n RowRenderer.prototype.mapRowNodes = function (rowNodes) {\n if (!rowNodes) {\n return;\n }\n var res = {\n top: {},\n bottom: {},\n normal: {}\n };\n rowNodes.forEach(function (rowNode) {\n var id = rowNode.id;\n if (rowNode.rowPinned === Constants.PINNED_TOP) {\n res.top[id] = rowNode;\n }\n else if (rowNode.rowPinned === Constants.PINNED_BOTTOM) {\n res.bottom[id] = rowNode;\n }\n else {\n res.normal[id] = rowNode;\n }\n });\n return res;\n };\n RowRenderer.prototype.isRowInMap = function (rowNode, rowIdsMap) {\n // skip this row if it is missing from the provided list\n var id = rowNode.id;\n var floating = rowNode.rowPinned;\n if (floating === Constants.PINNED_BOTTOM) {\n return rowIdsMap.bottom[id] != null;\n }\n if (floating === Constants.PINNED_TOP) {\n return rowIdsMap.top[id] != null;\n }\n return rowIdsMap.normal[id] != null;\n };\n // returns CellCtrl's that match the provided rowNodes and columns. eg if one row node\n // and two columns provided, that identifies 4 cells, so 4 CellCtrl's returned.\n RowRenderer.prototype.getCellCtrls = function (rowNodes, columns) {\n var _this = this;\n var rowIdsMap = this.mapRowNodes(rowNodes);\n var res = [];\n var colIdsMap;\n if (exists(columns)) {\n colIdsMap = {};\n columns.forEach(function (colKey) {\n var column = _this.columnModel.getGridColumn(colKey);\n if (exists(column)) {\n colIdsMap[column.getId()] = true;\n }\n });\n }\n var processRow = function (rowComp) {\n var rowNode = rowComp.getRowNode();\n // skip this row if it is missing from the provided list\n if (rowIdsMap != null && !_this.isRowInMap(rowNode, rowIdsMap)) {\n return;\n }\n rowComp.getAllCellCtrls().forEach(function (cellCtrl) {\n var colId = cellCtrl.getColumn().getId();\n var excludeColFromRefresh = colIdsMap && !colIdsMap[colId];\n if (excludeColFromRefresh) {\n return;\n }\n res.push(cellCtrl);\n });\n };\n iterateObject(this.rowCtrlsByRowIndex, function (index, rowComp) {\n processRow(rowComp);\n });\n if (this.topRowCtrls) {\n this.topRowCtrls.forEach(processRow);\n }\n if (this.bottomRowCtrls) {\n this.bottomRowCtrls.forEach(processRow);\n }\n return res;\n };\n RowRenderer.prototype.destroy = function () {\n this.removeAllRowComps();\n _super.prototype.destroy.call(this);\n };\n RowRenderer.prototype.removeAllRowComps = function () {\n var rowIndexesToRemove = Object.keys(this.rowCtrlsByRowIndex);\n this.removeRowCtrls(rowIndexesToRemove);\n };\n RowRenderer.prototype.recycleRows = function () {\n // remove all stub nodes, they can't be reused, as no rowNode id\n var stubNodeIndexes = [];\n iterateObject(this.rowCtrlsByRowIndex, function (index, rowComp) {\n var stubNode = rowComp.getRowNode().id == null;\n if (stubNode) {\n stubNodeIndexes.push(index);\n }\n });\n this.removeRowCtrls(stubNodeIndexes);\n // then clear out rowCompsByIndex, but before that take a copy, but index by id, not rowIndex\n var ctrlsByIdMap = {};\n iterateObject(this.rowCtrlsByRowIndex, function (index, rowComp) {\n var rowNode = rowComp.getRowNode();\n ctrlsByIdMap[rowNode.id] = rowComp;\n });\n this.rowCtrlsByRowIndex = {};\n return ctrlsByIdMap;\n };\n // takes array of row indexes\n RowRenderer.prototype.removeRowCtrls = function (rowsToRemove) {\n var _this = this;\n // if no fromIndex then set to -1, which will refresh everything\n // let realFromIndex = -1;\n rowsToRemove.forEach(function (indexToRemove) {\n var rowCtrl = _this.rowCtrlsByRowIndex[indexToRemove];\n if (rowCtrl) {\n rowCtrl.destroyFirstPass();\n rowCtrl.destroySecondPass();\n }\n delete _this.rowCtrlsByRowIndex[indexToRemove];\n });\n };\n // gets called when rows don't change, but viewport does, so after:\n // 1) height of grid body changes, ie number of displayed rows has changed\n // 2) grid scrolled to new position\n // 3) ensure index visible (which is a scroll)\n RowRenderer.prototype.redrawAfterScroll = function () {\n var cellFocused;\n // only try to refocus cells shifting in and out of sticky container\n // if the browser supports focus ({ preventScroll })\n if (this.stickyRowFeature && browserSupportsPreventScroll()) {\n cellFocused = this.getCellToRestoreFocusToAfterRefresh() || undefined;\n }\n this.getLockOnRefresh();\n this.redraw(null, false, true);\n this.releaseLockOnRefresh();\n this.dispatchDisplayedRowsChanged();\n if (cellFocused != null) {\n var newFocusedCell = this.getCellToRestoreFocusToAfterRefresh();\n if (cellFocused != null && newFocusedCell == null) {\n this.animationFrameService.flushAllFrames();\n this.restoreFocusedCell(cellFocused);\n }\n }\n };\n RowRenderer.prototype.removeRowCompsNotToDraw = function (indexesToDraw) {\n // for speedy lookup, dump into map\n var indexesToDrawMap = {};\n indexesToDraw.forEach(function (index) { return (indexesToDrawMap[index] = true); });\n var existingIndexes = Object.keys(this.rowCtrlsByRowIndex);\n var indexesNotToDraw = existingIndexes.filter(function (index) { return !indexesToDrawMap[index]; });\n this.removeRowCtrls(indexesNotToDraw);\n };\n RowRenderer.prototype.calculateIndexesToDraw = function (rowsToRecycle) {\n var _this = this;\n // all in all indexes in the viewport\n var indexesToDraw = createArrayOfNumbers(this.firstRenderedRow, this.lastRenderedRow);\n var checkRowToDraw = function (indexStr, rowComp) {\n var index = rowComp.getRowNode().rowIndex;\n if (index == null) {\n return;\n }\n if (index < _this.firstRenderedRow || index > _this.lastRenderedRow) {\n if (_this.doNotUnVirtualiseRow(rowComp)) {\n indexesToDraw.push(index);\n }\n }\n };\n // if we are redrawing due to scrolling change, then old rows are in this.rowCompsByIndex\n iterateObject(this.rowCtrlsByRowIndex, checkRowToDraw);\n // if we are redrawing due to model update, then old rows are in rowsToRecycle\n iterateObject(rowsToRecycle, checkRowToDraw);\n indexesToDraw.sort(function (a, b) { return a - b; });\n indexesToDraw = indexesToDraw.filter(function (index) {\n var rowNode = _this.paginationProxy.getRow(index);\n return rowNode && !rowNode.sticky;\n });\n return indexesToDraw;\n };\n RowRenderer.prototype.redraw = function (rowsToRecycle, animate, afterScroll) {\n var _this = this;\n if (animate === void 0) { animate = false; }\n if (afterScroll === void 0) { afterScroll = false; }\n this.rowContainerHeightService.updateOffset();\n this.workOutFirstAndLastRowsToRender();\n if (this.stickyRowFeature) {\n this.stickyRowFeature.checkStickyRows();\n }\n // the row can already exist and be in the following:\n // rowsToRecycle -> if model change, then the index may be different, however row may\n // exist here from previous time (mapped by id).\n // this.rowCompsByIndex -> if just a scroll, then this will contain what is currently in the viewport\n // this is all the indexes we want, including those that already exist, so this method\n // will end up going through each index and drawing only if the row doesn't already exist\n var indexesToDraw = this.calculateIndexesToDraw(rowsToRecycle);\n this.removeRowCompsNotToDraw(indexesToDraw);\n // never animate when doing print layout - as we want to get things ready to print as quickly as possible,\n // otherwise we risk the printer printing a row that's half faded (half way through fading in)\n if (this.printLayout) {\n animate = false;\n }\n indexesToDraw.forEach(function (rowIndex) {\n var rowCtrl = _this.createOrUpdateRowCtrl(rowIndex, rowsToRecycle, animate, afterScroll);\n if (exists(rowCtrl)) ;\n });\n if (rowsToRecycle) {\n var useAnimationFrame = afterScroll && !this.gridOptionsWrapper.isSuppressAnimationFrame() && !this.printLayout;\n if (useAnimationFrame) {\n this.beans.animationFrameService.addDestroyTask(function () {\n _this.destroyRowCtrls(rowsToRecycle, animate);\n _this.updateAllRowCtrls();\n _this.dispatchDisplayedRowsChanged();\n });\n }\n else {\n this.destroyRowCtrls(rowsToRecycle, animate);\n }\n }\n this.updateAllRowCtrls();\n };\n RowRenderer.prototype.dispatchDisplayedRowsChanged = function () {\n var event = { type: Events.EVENT_DISPLAYED_ROWS_CHANGED };\n this.eventService.dispatchEvent(event);\n };\n RowRenderer.prototype.onDisplayedColumnsChanged = function () {\n var pinningLeft = this.columnModel.isPinningLeft();\n var pinningRight = this.columnModel.isPinningRight();\n var atLeastOneChanged = this.pinningLeft !== pinningLeft || pinningRight !== this.pinningRight;\n if (atLeastOneChanged) {\n this.pinningLeft = pinningLeft;\n this.pinningRight = pinningRight;\n if (this.embedFullWidthRows) {\n this.redrawFullWidthEmbeddedRows();\n }\n }\n };\n // when embedding, what gets showed in each section depends on what is pinned. eg if embedding group expand / collapse,\n // then it should go into the pinned left area if pinning left, or the center area if not pinning.\n RowRenderer.prototype.redrawFullWidthEmbeddedRows = function () {\n // if either of the pinned panels has shown / hidden, then need to redraw the fullWidth bits when\n // embedded, as what appears in each section depends on whether we are pinned or not\n var rowsToRemove = [];\n this.getFullWidthRowCtrls().forEach(function (fullWidthCtrl) {\n var rowIndex = fullWidthCtrl.getRowNode().rowIndex;\n rowsToRemove.push(rowIndex.toString());\n });\n this.refreshFloatingRowComps();\n this.removeRowCtrls(rowsToRemove);\n this.redrawAfterScroll();\n };\n RowRenderer.prototype.getFullWidthRowCtrls = function (rowNodes) {\n var _this = this;\n var rowNodesMap = this.mapRowNodes(rowNodes);\n return getAllValuesInObject(this.rowCtrlsByRowIndex).filter(function (rowCtrl) {\n // include just full width\n if (!rowCtrl.isFullWidth()) {\n return false;\n }\n // if Row Nodes provided, we exclude where Row Node is missing\n var rowNode = rowCtrl.getRowNode();\n if (rowNodesMap != null && !_this.isRowInMap(rowNode, rowNodesMap)) {\n return false;\n }\n return true;\n });\n };\n RowRenderer.prototype.refreshFullWidthRows = function (rowNodesToRefresh) {\n var rowsToRemove = [];\n var selectivelyRefreshing = !!rowNodesToRefresh;\n var idsToRefresh = selectivelyRefreshing ? {} : undefined;\n if (selectivelyRefreshing && idsToRefresh) {\n rowNodesToRefresh.forEach(function (r) { return idsToRefresh[r.id] = true; });\n }\n this.getFullWidthRowCtrls().forEach(function (fullWidthRowCtrl) {\n var rowNode = fullWidthRowCtrl.getRowNode();\n if (selectivelyRefreshing && idsToRefresh) {\n // we refresh if a) this node is present or b) this parents nodes is present. checking parent\n // node is important for master/detail, as we want detail to refresh on changes to parent node.\n // it's also possible, if user is provider their own fullWidth, that details panels contain\n // some info on the parent, eg if in tree data and child row shows some data from parent row also.\n var parentId = (rowNode.level > 0 && rowNode.parent) ? rowNode.parent.id : undefined;\n var skipThisNode = !idsToRefresh[rowNode.id] && !idsToRefresh[parentId];\n if (skipThisNode) {\n return;\n }\n }\n var fullWidthRowsRefreshed = fullWidthRowCtrl.refreshFullWidth();\n if (!fullWidthRowsRefreshed) {\n var rowIndex = fullWidthRowCtrl.getRowNode().rowIndex;\n rowsToRemove.push(rowIndex.toString());\n }\n });\n this.removeRowCtrls(rowsToRemove);\n this.redrawAfterScroll();\n };\n RowRenderer.prototype.createOrUpdateRowCtrl = function (rowIndex, rowsToRecycle, animate, afterScroll) {\n var rowNode;\n var rowCtrl = this.rowCtrlsByRowIndex[rowIndex];\n // if no row comp, see if we can get it from the previous rowComps\n if (!rowCtrl) {\n rowNode = this.paginationProxy.getRow(rowIndex);\n if (exists(rowNode) && exists(rowsToRecycle) && rowsToRecycle[rowNode.id] && rowNode.alreadyRendered) {\n rowCtrl = rowsToRecycle[rowNode.id];\n rowsToRecycle[rowNode.id] = null;\n }\n }\n var creatingNewRowCtrl = !rowCtrl;\n if (creatingNewRowCtrl) {\n // create a new one\n if (!rowNode) {\n rowNode = this.paginationProxy.getRow(rowIndex);\n }\n if (exists(rowNode)) {\n rowCtrl = this.createRowCon(rowNode, animate, afterScroll);\n }\n else {\n // this should never happen - if somehow we are trying to create\n // a row for a rowNode that does not exist.\n return;\n }\n }\n if (rowNode) {\n // set node as 'alreadyRendered' to ensure we only recycle rowComps that have been rendered, this ensures\n // we don't reuse rowComps that have been removed and then re-added in the same batch transaction.\n rowNode.alreadyRendered = true;\n }\n this.rowCtrlsByRowIndex[rowIndex] = rowCtrl;\n return rowCtrl;\n };\n RowRenderer.prototype.destroyRowCtrls = function (rowCtrlsMap, animate) {\n var _this = this;\n var executeInAWhileFuncs = [];\n iterateObject(rowCtrlsMap, function (nodeId, rowCtrl) {\n // if row was used, then it's null\n if (!rowCtrl) {\n return;\n }\n if (_this.cachedRowCtrls && rowCtrl.isCacheable()) {\n _this.cachedRowCtrls.addRow(rowCtrl);\n return;\n }\n rowCtrl.destroyFirstPass();\n if (animate) {\n _this.zombieRowCtrls[rowCtrl.getInstanceId()] = rowCtrl;\n executeInAWhileFuncs.push(function () {\n rowCtrl.destroySecondPass();\n delete _this.zombieRowCtrls[rowCtrl.getInstanceId()];\n });\n }\n else {\n rowCtrl.destroySecondPass();\n }\n });\n if (animate) {\n // this ensures we fire displayedRowsChanged AFTER all the 'executeInAWhileFuncs' get\n // executed, as we added it to the end of the list.\n executeInAWhileFuncs.push(function () {\n _this.updateAllRowCtrls();\n _this.dispatchDisplayedRowsChanged();\n });\n executeInAWhile(executeInAWhileFuncs);\n }\n };\n RowRenderer.prototype.workOutFirstAndLastRowsToRender = function () {\n var newFirst;\n var newLast;\n if (!this.paginationProxy.isRowsToRender()) {\n newFirst = 0;\n newLast = -1; // setting to -1 means nothing in range\n }\n else if (this.printLayout) {\n newFirst = this.paginationProxy.getPageFirstRow();\n newLast = this.paginationProxy.getPageLastRow();\n }\n else {\n var bufferPixels = this.gridOptionsWrapper.getRowBufferInPixels();\n var gridBodyCtrl = this.ctrlsService.getGridBodyCtrl();\n var suppressRowVirtualisation = this.gridOptionsWrapper.isSuppressRowVirtualisation();\n var rowHeightsChanged = false;\n var firstPixel = void 0;\n var lastPixel = void 0;\n do {\n var paginationOffset = this.paginationProxy.getPixelOffset();\n var _a = this.paginationProxy.getCurrentPagePixelRange(), pageFirstPixel = _a.pageFirstPixel, pageLastPixel = _a.pageLastPixel;\n var divStretchOffset = this.rowContainerHeightService.getDivStretchOffset();\n var bodyVRange = gridBodyCtrl.getScrollFeature().getVScrollPosition();\n var bodyTopPixel = bodyVRange.top;\n var bodyBottomPixel = bodyVRange.bottom;\n if (suppressRowVirtualisation) {\n firstPixel = pageFirstPixel + divStretchOffset;\n lastPixel = pageLastPixel + divStretchOffset;\n }\n else {\n firstPixel = Math.max(bodyTopPixel + paginationOffset - bufferPixels, pageFirstPixel) + divStretchOffset;\n lastPixel = Math.min(bodyBottomPixel + paginationOffset + bufferPixels, pageLastPixel) + divStretchOffset;\n }\n this.firstVisibleVPixel = Math.max(bodyTopPixel + paginationOffset, pageFirstPixel) + divStretchOffset;\n // if the rows we are about to display get their heights changed, then that upsets the calcs from above.\n rowHeightsChanged = this.ensureAllRowsInRangeHaveHeightsCalculated(firstPixel, lastPixel);\n } while (rowHeightsChanged);\n var firstRowIndex = this.paginationProxy.getRowIndexAtPixel(firstPixel);\n var lastRowIndex = this.paginationProxy.getRowIndexAtPixel(lastPixel);\n var pageFirstRow = this.paginationProxy.getPageFirstRow();\n var pageLastRow = this.paginationProxy.getPageLastRow();\n // adjust, in case buffer extended actual size\n if (firstRowIndex < pageFirstRow) {\n firstRowIndex = pageFirstRow;\n }\n if (lastRowIndex > pageLastRow) {\n lastRowIndex = pageLastRow;\n }\n newFirst = firstRowIndex;\n newLast = lastRowIndex;\n }\n // sometimes user doesn't set CSS right and ends up with grid with no height and grid ends up\n // trying to render all the rows, eg 10,000+ rows. this will kill the browser. so instead of\n // killing the browser, we limit the number of rows. just in case some use case we didn't think\n // of, we also have a property to not do this operation.\n var rowLayoutNormal = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_NORMAL;\n var suppressRowCountRestriction = this.gridOptionsWrapper.isSuppressMaxRenderedRowRestriction();\n var rowBufferMaxSize = Math.max(this.gridOptionsWrapper.getRowBuffer(), 500);\n if (rowLayoutNormal && !suppressRowCountRestriction) {\n if (newLast - newFirst > rowBufferMaxSize) {\n newLast = newFirst + rowBufferMaxSize;\n }\n }\n var firstDiffers = newFirst !== this.firstRenderedRow;\n var lastDiffers = newLast !== this.lastRenderedRow;\n if (firstDiffers || lastDiffers) {\n this.firstRenderedRow = newFirst;\n this.lastRenderedRow = newLast;\n var event_1 = {\n type: Events.EVENT_VIEWPORT_CHANGED,\n firstRow: newFirst,\n lastRow: newLast\n };\n this.eventService.dispatchEvent(event_1);\n }\n };\n /**\n * This event will only be fired once, and is queued until after the browser next renders.\n * This allows us to fire an event during the start of the render cycle, when we first see data being rendered\n * but not execute the event until all of the data has finished being rendered to the dom.\n */\n RowRenderer.prototype.dispatchFirstDataRenderedEvent = function () {\n var _this = this;\n if (this.dataFirstRenderedFired) {\n return;\n }\n this.dataFirstRenderedFired = true;\n var event = {\n type: Events.EVENT_FIRST_DATA_RENDERED,\n firstRow: this.firstRenderedRow,\n lastRow: this.lastRenderedRow,\n };\n // See AG-7018\n window.requestAnimationFrame(function () {\n _this.beans.eventService.dispatchEvent(event);\n });\n };\n RowRenderer.prototype.ensureAllRowsInRangeHaveHeightsCalculated = function (topPixel, bottomPixel) {\n // ensureRowHeightsVisible only works with CSRM, as it's the only row model that allows lazy row height calcs.\n // all the other row models just hard code so the method just returns back false\n var res = this.paginationProxy.ensureRowHeightsValid(topPixel, bottomPixel, -1, -1);\n if (res) {\n this.updateContainerHeights();\n }\n return res;\n };\n RowRenderer.prototype.getFirstVisibleVerticalPixel = function () {\n return this.firstVisibleVPixel;\n };\n RowRenderer.prototype.getFirstVirtualRenderedRow = function () {\n return this.firstRenderedRow;\n };\n RowRenderer.prototype.getLastVirtualRenderedRow = function () {\n return this.lastRenderedRow;\n };\n // check that none of the rows to remove are editing or focused as:\n // a) if editing, we want to keep them, otherwise the user will loose the context of the edit,\n // eg user starts editing, enters some text, then scrolls down and then up, next time row rendered\n // the edit is reset - so we want to keep it rendered.\n // b) if focused, we want ot keep keyboard focus, so if user ctrl+c, it goes to clipboard,\n // otherwise the user can range select and drag (with focus cell going out of the viewport)\n // and then ctrl+c, nothing will happen if cell is removed from dom.\n // c) if detail record of master detail, as users complained that the context of detail rows\n // was getting lost when detail row out of view. eg user expands to show detail row,\n // then manipulates the detail panel (eg sorts the detail grid), then context is lost\n // after detail panel is scrolled out of / into view.\n RowRenderer.prototype.doNotUnVirtualiseRow = function (rowComp) {\n var REMOVE_ROW = false;\n var KEEP_ROW = true;\n var rowNode = rowComp.getRowNode();\n var rowHasFocus = this.focusService.isRowNodeFocused(rowNode);\n var rowIsEditing = rowComp.isEditing();\n var rowIsDetail = rowNode.detail;\n var mightWantToKeepRow = rowHasFocus || rowIsEditing || rowIsDetail;\n // if we deffo don't want to keep it,\n if (!mightWantToKeepRow) {\n return REMOVE_ROW;\n }\n // editing row, only remove if it is no longer rendered, eg filtered out or new data set.\n // the reason we want to keep is if user is scrolling up and down, we don't want to loose\n // the context of the editing in process.\n var rowNodePresent = this.paginationProxy.isRowPresent(rowNode);\n return rowNodePresent ? KEEP_ROW : REMOVE_ROW;\n };\n RowRenderer.prototype.createRowCon = function (rowNode, animate, afterScroll) {\n var rowCtrlFromCache = this.cachedRowCtrls ? this.cachedRowCtrls.getRow(rowNode) : null;\n if (rowCtrlFromCache) {\n return rowCtrlFromCache;\n }\n // we don't use animations frames for printing, so the user can put the grid into print mode\n // and immediately print - otherwise the user would have to wait for the rows to draw in the background\n // (via the animation frames) which is awkward to do from code.\n // we only do the animation frames after scrolling, as this is where we want the smooth user experience.\n // having animation frames for other times makes the grid look 'jumpy'.\n var suppressAnimationFrame = this.gridOptionsWrapper.isSuppressAnimationFrame();\n var useAnimationFrameForCreate = afterScroll && !suppressAnimationFrame && !this.printLayout;\n var res = new RowCtrl(rowNode, this.beans, animate, useAnimationFrameForCreate, this.printLayout);\n return res;\n };\n RowRenderer.prototype.getRenderedNodes = function () {\n var renderedRows = this.rowCtrlsByRowIndex;\n return Object.keys(renderedRows).map(function (key) { return renderedRows[key].getRowNode(); });\n };\n RowRenderer.prototype.getRowByPosition = function (rowPosition) {\n var rowCtrl;\n var rowIndex = rowPosition.rowIndex;\n switch (rowPosition.rowPinned) {\n case Constants.PINNED_TOP:\n rowCtrl = this.topRowCtrls[rowIndex];\n break;\n case Constants.PINNED_BOTTOM:\n rowCtrl = this.bottomRowCtrls[rowIndex];\n break;\n default:\n rowCtrl = this.rowCtrlsByRowIndex[rowIndex];\n if (!rowCtrl) {\n rowCtrl = this.getStickyTopRowCtrls().find(function (ctrl) { return ctrl.getRowNode().rowIndex === rowIndex; }) || null;\n }\n break;\n }\n return rowCtrl;\n };\n RowRenderer.prototype.getRowNode = function (gridRow) {\n switch (gridRow.rowPinned) {\n case Constants.PINNED_TOP:\n return this.pinnedRowModel.getPinnedTopRowData()[gridRow.rowIndex];\n case Constants.PINNED_BOTTOM:\n return this.pinnedRowModel.getPinnedBottomRowData()[gridRow.rowIndex];\n default:\n return this.rowModel.getRow(gridRow.rowIndex);\n }\n };\n // returns true if any row between startIndex and endIndex is rendered. used by\n // SSRM or IRM, as they don't want to purge visible blocks from cache.\n RowRenderer.prototype.isRangeInRenderedViewport = function (startIndex, endIndex) {\n // parent closed means the parent node is not expanded, thus these blocks are not visible\n var parentClosed = startIndex == null || endIndex == null;\n if (parentClosed) {\n return false;\n }\n var blockAfterViewport = startIndex > this.lastRenderedRow;\n var blockBeforeViewport = endIndex < this.firstRenderedRow;\n var blockInsideViewport = !blockBeforeViewport && !blockAfterViewport;\n return blockInsideViewport;\n };\n __decorate$13([\n Autowired(\"animationFrameService\")\n ], RowRenderer.prototype, \"animationFrameService\", void 0);\n __decorate$13([\n Autowired(\"paginationProxy\")\n ], RowRenderer.prototype, \"paginationProxy\", void 0);\n __decorate$13([\n Autowired(\"columnModel\")\n ], RowRenderer.prototype, \"columnModel\", void 0);\n __decorate$13([\n Autowired(\"pinnedRowModel\")\n ], RowRenderer.prototype, \"pinnedRowModel\", void 0);\n __decorate$13([\n Autowired(\"rowModel\")\n ], RowRenderer.prototype, \"rowModel\", void 0);\n __decorate$13([\n Autowired(\"focusService\")\n ], RowRenderer.prototype, \"focusService\", void 0);\n __decorate$13([\n Autowired(\"beans\")\n ], RowRenderer.prototype, \"beans\", void 0);\n __decorate$13([\n Autowired(\"rowContainerHeightService\")\n ], RowRenderer.prototype, \"rowContainerHeightService\", void 0);\n __decorate$13([\n Autowired(\"ctrlsService\")\n ], RowRenderer.prototype, \"ctrlsService\", void 0);\n __decorate$13([\n PostConstruct\n ], RowRenderer.prototype, \"postConstruct\", null);\n RowRenderer = __decorate$13([\n Bean(\"rowRenderer\")\n ], RowRenderer);\n return RowRenderer;\n}(BeanStub));\nvar RowCtrlCache = /** @class */ (function () {\n function RowCtrlCache(maxCount) {\n // map for fast access\n this.entriesMap = {};\n // list for keeping order\n this.entriesList = [];\n this.maxCount = maxCount;\n }\n RowCtrlCache.prototype.addRow = function (rowCtrl) {\n this.entriesMap[rowCtrl.getRowNode().id] = rowCtrl;\n this.entriesList.push(rowCtrl);\n rowCtrl.setCached(true);\n if (this.entriesList.length > this.maxCount) {\n var rowCtrlToDestroy = this.entriesList[0];\n rowCtrlToDestroy.destroyFirstPass();\n rowCtrlToDestroy.destroySecondPass();\n this.removeFromCache(rowCtrlToDestroy);\n }\n };\n RowCtrlCache.prototype.getRow = function (rowNode) {\n if (rowNode == null || rowNode.id == null) {\n return null;\n }\n var res = this.entriesMap[rowNode.id];\n if (!res) {\n return null;\n }\n this.removeFromCache(res);\n res.setCached(false);\n // this can happen if user reloads data, and a new RowNode is reusing\n // the same ID as the old one\n var rowNodeMismatch = res.getRowNode() != rowNode;\n return rowNodeMismatch ? null : res;\n };\n RowCtrlCache.prototype.removeFromCache = function (rowCtrl) {\n var rowNodeId = rowCtrl.getRowNode().id;\n delete this.entriesMap[rowNodeId];\n removeFromArray(this.entriesList, rowCtrl);\n };\n RowCtrlCache.prototype.getEntries = function () {\n return this.entriesList;\n };\n return RowCtrlCache;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$19 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$12 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ValueFormatterService = /** @class */ (function (_super) {\n __extends$19(ValueFormatterService, _super);\n function ValueFormatterService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ValueFormatterService.prototype.formatValue = function (column, node, value, suppliedFormatter, useFormatterFromColumn) {\n if (useFormatterFromColumn === void 0) { useFormatterFromColumn = true; }\n var result = null;\n var formatter;\n var colDef = column.getColDef();\n if (suppliedFormatter) {\n // use supplied formatter if provided, e.g. set filter items can have their own value formatters\n formatter = suppliedFormatter;\n }\n else if (useFormatterFromColumn) {\n // if row is pinned, give preference to the pinned formatter\n formatter = node && node.rowPinned && colDef.pinnedRowValueFormatter ?\n colDef.pinnedRowValueFormatter : colDef.valueFormatter;\n }\n if (formatter) {\n var params = {\n value: value,\n node: node,\n data: node ? node.data : null,\n colDef: colDef,\n column: column,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n result = this.expressionService.evaluate(formatter, params);\n }\n else if (colDef.refData) {\n return colDef.refData[value] || '';\n }\n // if we don't do this, then arrays get displayed as 1,2,3, but we want 1, 2, 3 (i.e. with spaces)\n if (result == null && Array.isArray(value)) {\n result = value.join(', ');\n }\n return result;\n };\n __decorate$12([\n Autowired('expressionService')\n ], ValueFormatterService.prototype, \"expressionService\", void 0);\n ValueFormatterService = __decorate$12([\n Bean('valueFormatterService')\n ], ValueFormatterService);\n return ValueFormatterService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$18 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$11 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar PinnedRowModel = /** @class */ (function (_super) {\n __extends$18(PinnedRowModel, _super);\n function PinnedRowModel() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n PinnedRowModel.prototype.init = function () {\n this.setPinnedTopRowData(this.gridOptionsWrapper.getPinnedTopRowData());\n this.setPinnedBottomRowData(this.gridOptionsWrapper.getPinnedBottomRowData());\n };\n PinnedRowModel.prototype.isEmpty = function (floating) {\n var rows = floating === Constants.PINNED_TOP ? this.pinnedTopRows : this.pinnedBottomRows;\n return missingOrEmpty(rows);\n };\n PinnedRowModel.prototype.isRowsToRender = function (floating) {\n return !this.isEmpty(floating);\n };\n PinnedRowModel.prototype.getRowAtPixel = function (pixel, floating) {\n var rows = floating === Constants.PINNED_TOP ? this.pinnedTopRows : this.pinnedBottomRows;\n if (missingOrEmpty(rows)) {\n return 0; // this should never happen, just in case, 0 is graceful failure\n }\n for (var i = 0; i < rows.length; i++) {\n var rowNode = rows[i];\n var rowTopPixel = rowNode.rowTop + rowNode.rowHeight - 1;\n // only need to range check against the top pixel, as we are going through the list\n // in order, first row to hit the pixel wins\n if (rowTopPixel >= pixel) {\n return i;\n }\n }\n return rows.length - 1;\n };\n PinnedRowModel.prototype.setPinnedTopRowData = function (rowData) {\n this.pinnedTopRows = this.createNodesFromData(rowData, true);\n var event = {\n type: Events.EVENT_PINNED_ROW_DATA_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n PinnedRowModel.prototype.setPinnedBottomRowData = function (rowData) {\n this.pinnedBottomRows = this.createNodesFromData(rowData, false);\n var event = {\n type: Events.EVENT_PINNED_ROW_DATA_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n PinnedRowModel.prototype.createNodesFromData = function (allData, isTop) {\n var _this = this;\n var rowNodes = [];\n if (allData) {\n var nextRowTop_1 = 0;\n allData.forEach(function (dataItem, index) {\n var rowNode = new RowNode(_this.beans);\n rowNode.data = dataItem;\n var idPrefix = isTop ? RowNode.ID_PREFIX_TOP_PINNED : RowNode.ID_PREFIX_BOTTOM_PINNED;\n rowNode.id = idPrefix + index;\n rowNode.rowPinned = isTop ? Constants.PINNED_TOP : Constants.PINNED_BOTTOM;\n rowNode.setRowTop(nextRowTop_1);\n rowNode.setRowHeight(_this.gridOptionsWrapper.getRowHeightForNode(rowNode).height);\n rowNode.setRowIndex(index);\n nextRowTop_1 += rowNode.rowHeight;\n rowNodes.push(rowNode);\n });\n }\n return rowNodes;\n };\n PinnedRowModel.prototype.getPinnedTopRowData = function () {\n return this.pinnedTopRows;\n };\n PinnedRowModel.prototype.getPinnedBottomRowData = function () {\n return this.pinnedBottomRows;\n };\n PinnedRowModel.prototype.getPinnedTopTotalHeight = function () {\n return this.getTotalHeight(this.pinnedTopRows);\n };\n PinnedRowModel.prototype.getPinnedTopRowCount = function () {\n return this.pinnedTopRows ? this.pinnedTopRows.length : 0;\n };\n PinnedRowModel.prototype.getPinnedBottomRowCount = function () {\n return this.pinnedBottomRows ? this.pinnedBottomRows.length : 0;\n };\n PinnedRowModel.prototype.getPinnedTopRow = function (index) {\n return this.pinnedTopRows[index];\n };\n PinnedRowModel.prototype.getPinnedBottomRow = function (index) {\n return this.pinnedBottomRows[index];\n };\n PinnedRowModel.prototype.forEachPinnedTopRow = function (callback) {\n if (missingOrEmpty(this.pinnedTopRows)) {\n return;\n }\n this.pinnedTopRows.forEach(callback);\n };\n PinnedRowModel.prototype.forEachPinnedBottomRow = function (callback) {\n if (missingOrEmpty(this.pinnedBottomRows)) {\n return;\n }\n this.pinnedBottomRows.forEach(callback);\n };\n PinnedRowModel.prototype.getPinnedBottomTotalHeight = function () {\n return this.getTotalHeight(this.pinnedBottomRows);\n };\n PinnedRowModel.prototype.getTotalHeight = function (rowNodes) {\n if (!rowNodes || rowNodes.length === 0) {\n return 0;\n }\n var lastNode = last(rowNodes);\n return lastNode.rowTop + lastNode.rowHeight;\n };\n __decorate$11([\n Autowired('beans')\n ], PinnedRowModel.prototype, \"beans\", void 0);\n __decorate$11([\n PostConstruct\n ], PinnedRowModel.prototype, \"init\", null);\n PinnedRowModel = __decorate$11([\n Bean('pinnedRowModel')\n ], PinnedRowModel);\n return PinnedRowModel;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar ServerSideTransactionResultStatus;\n(function (ServerSideTransactionResultStatus) {\n /** Transaction was successfully applied */\n ServerSideTransactionResultStatus[\"Applied\"] = \"Applied\";\n /**\n * Store was not found, transaction not applied.\n * Either invalid route, or the parent row has not yet been expanded.\n */\n ServerSideTransactionResultStatus[\"StoreNotFound\"] = \"StoreNotFound\";\n /**\n * Store is loading, transaction not applied.\n */\n ServerSideTransactionResultStatus[\"StoreLoading\"] = \"StoreLoading\";\n /**\n * Store is loading (as max loads exceeded), transaction not applied.\n */\n ServerSideTransactionResultStatus[\"StoreWaitingToLoad\"] = \"StoreWaitingToLoad\";\n /**\n * Store load attempt failed, transaction not applied.\n */\n ServerSideTransactionResultStatus[\"StoreLoadingFailed\"] = \"StoreLoadingFailed\";\n /**\n * Store is type Partial, which doesn't accept transactions\n */\n ServerSideTransactionResultStatus[\"StoreWrongType\"] = \"StoreWrongType\";\n /**\n * Transaction was cancelled, due to grid.\n * Callback isApplyServerSideTransaction() returning false\n */\n ServerSideTransactionResultStatus[\"Cancelled\"] = \"Cancelled\";\n})(ServerSideTransactionResultStatus || (ServerSideTransactionResultStatus = {}));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n// when doing transactions, or change detection, and grouping is present\n// in the data, there is no need for the ClientSideRowModel to update each\n// group after an update, ony parts that were impacted by the change.\n// this class keeps track of all groups that were impacted by a transaction.\n// the the different CSRM operations (filter, sort etc) use the forEach method\n// to visit each group that was changed.\nvar ChangedPath = /** @class */ (function () {\n function ChangedPath(keepingColumns, rootNode) {\n // whether changed path is active of not. it is active when a) doing\n // a transaction update or b) doing change detection. if we are doing\n // a CSRM refresh for other reasons (after sort or filter, or user calling\n // setRowData() without delta mode) then we are not active. we are also\n // marked as not active if secondary columns change in pivot (as this impacts\n // aggregations)\n this.active = true;\n // for each node in the change path, we also store which columns need\n // to be re-aggregated.\n this.nodeIdsToColumns = {};\n // for quick lookup, all items in the change path are mapped by nodeId\n this.mapToItems = {};\n this.keepingColumns = keepingColumns;\n this.pathRoot = {\n rowNode: rootNode,\n children: null\n };\n this.mapToItems[rootNode.id] = this.pathRoot;\n }\n // can be set inactive by:\n // a) ClientSideRowModel, if no transactions or\n // b) PivotService, if secondary columns changed\n ChangedPath.prototype.setInactive = function () {\n this.active = false;\n };\n ChangedPath.prototype.isActive = function () {\n return this.active;\n };\n ChangedPath.prototype.depthFirstSearchChangedPath = function (pathItem, callback) {\n if (pathItem.children) {\n for (var i = 0; i < pathItem.children.length; i++) {\n this.depthFirstSearchChangedPath(pathItem.children[i], callback);\n }\n }\n callback(pathItem.rowNode);\n };\n ChangedPath.prototype.depthFirstSearchEverything = function (rowNode, callback, traverseEverything) {\n if (rowNode.childrenAfterGroup) {\n for (var i = 0; i < rowNode.childrenAfterGroup.length; i++) {\n var childNode = rowNode.childrenAfterGroup[i];\n if (childNode.childrenAfterGroup) {\n this.depthFirstSearchEverything(rowNode.childrenAfterGroup[i], callback, traverseEverything);\n }\n else if (traverseEverything) {\n callback(childNode);\n }\n }\n }\n callback(rowNode);\n };\n // traverseLeafNodes -> used when NOT doing changed path, ie traversing everything. the callback\n // will be called for child nodes in addition to parent nodes.\n ChangedPath.prototype.forEachChangedNodeDepthFirst = function (callback, traverseLeafNodes, includeUnchangedNodes) {\n if (traverseLeafNodes === void 0) { traverseLeafNodes = false; }\n if (includeUnchangedNodes === void 0) { includeUnchangedNodes = false; }\n if (this.active && !includeUnchangedNodes) {\n // if we are active, then use the change path to callback\n // only for updated groups\n this.depthFirstSearchChangedPath(this.pathRoot, callback);\n }\n else {\n // we are not active, so callback for everything, walk the entire path\n this.depthFirstSearchEverything(this.pathRoot.rowNode, callback, traverseLeafNodes);\n }\n };\n ChangedPath.prototype.executeFromRootNode = function (callback) {\n callback(this.pathRoot.rowNode);\n };\n ChangedPath.prototype.createPathItems = function (rowNode) {\n var pointer = rowNode;\n var newEntryCount = 0;\n while (!this.mapToItems[pointer.id]) {\n var newEntry = {\n rowNode: pointer,\n children: null\n };\n this.mapToItems[pointer.id] = newEntry;\n newEntryCount++;\n pointer = pointer.parent;\n }\n return newEntryCount;\n };\n ChangedPath.prototype.populateColumnsMap = function (rowNode, columns) {\n var _this = this;\n if (!this.keepingColumns || !columns) {\n return;\n }\n var pointer = rowNode;\n while (pointer) {\n // if columns, add the columns in all the way to parent, merging\n // in any other columns that might be there already\n if (!this.nodeIdsToColumns[pointer.id]) {\n this.nodeIdsToColumns[pointer.id] = {};\n }\n columns.forEach(function (col) { return _this.nodeIdsToColumns[pointer.id][col.getId()] = true; });\n pointer = pointer.parent;\n }\n };\n ChangedPath.prototype.linkPathItems = function (rowNode, newEntryCount) {\n var pointer = rowNode;\n for (var i = 0; i < newEntryCount; i++) {\n var thisItem = this.mapToItems[pointer.id];\n var parentItem = this.mapToItems[pointer.parent.id];\n if (!parentItem.children) {\n parentItem.children = [];\n }\n parentItem.children.push(thisItem);\n pointer = pointer.parent;\n }\n };\n // called by\n // 1) change detection (provides cols) and\n // 2) groupStage if doing transaction update (doesn't provide cols)\n ChangedPath.prototype.addParentNode = function (rowNode, columns) {\n if (!rowNode || rowNode.isRowPinned()) {\n return;\n }\n // we cannot do both steps below in the same loop as\n // the second loop has a dependency on the first loop.\n // ie the hierarchy cannot be stitched up yet because\n // we don't have it built yet\n // create the new PathItem objects.\n var newEntryCount = this.createPathItems(rowNode);\n // link in the node items\n this.linkPathItems(rowNode, newEntryCount);\n // update columns\n this.populateColumnsMap(rowNode, columns);\n };\n ChangedPath.prototype.canSkip = function (rowNode) {\n return this.active && !this.mapToItems[rowNode.id];\n };\n ChangedPath.prototype.getValueColumnsForNode = function (rowNode, valueColumns) {\n if (!this.keepingColumns) {\n return valueColumns;\n }\n var colsForThisNode = this.nodeIdsToColumns[rowNode.id];\n var result = valueColumns.filter(function (col) { return colsForThisNode[col.getId()]; });\n return result;\n };\n ChangedPath.prototype.getNotValueColumnsForNode = function (rowNode, valueColumns) {\n if (!this.keepingColumns) {\n return null;\n }\n var colsForThisNode = this.nodeIdsToColumns[rowNode.id];\n var result = valueColumns.filter(function (col) { return !colsForThisNode[col.getId()]; });\n return result;\n };\n return ChangedPath;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$17 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar RowNodeBlock = /** @class */ (function (_super) {\n __extends$17(RowNodeBlock, _super);\n function RowNodeBlock(id) {\n var _this = _super.call(this) || this;\n _this.state = RowNodeBlock.STATE_WAITING_TO_LOAD;\n _this.version = 0;\n _this.id = id;\n return _this;\n }\n RowNodeBlock.prototype.getId = function () {\n return this.id;\n };\n RowNodeBlock.prototype.load = function () {\n this.state = RowNodeBlock.STATE_LOADING;\n this.loadFromDatasource();\n };\n RowNodeBlock.prototype.getVersion = function () {\n return this.version;\n };\n RowNodeBlock.prototype.setStateWaitingToLoad = function () {\n // in case any current loads in progress, this will have their results ignored\n this.version++;\n this.state = RowNodeBlock.STATE_WAITING_TO_LOAD;\n };\n RowNodeBlock.prototype.getState = function () {\n return this.state;\n };\n RowNodeBlock.prototype.pageLoadFailed = function (version) {\n var requestMostRecentAndLive = this.isRequestMostRecentAndLive(version);\n if (requestMostRecentAndLive) {\n this.state = RowNodeBlock.STATE_FAILED;\n this.processServerFail();\n }\n this.dispatchLoadCompleted(false);\n };\n RowNodeBlock.prototype.success = function (version, params) {\n this.successCommon(version, params);\n };\n RowNodeBlock.prototype.pageLoaded = function (version, rows, lastRow) {\n this.successCommon(version, { rowData: rows, rowCount: lastRow });\n };\n RowNodeBlock.prototype.isRequestMostRecentAndLive = function (version) {\n // thisIsMostRecentRequest - if block was refreshed, then another request\n // could of been sent after this one.\n var thisIsMostRecentRequest = version === this.version;\n // weAreNotDestroyed - if InfiniteStore is purged, then blocks are destroyed\n // and new blocks created. so data loads of old blocks are discarded.\n var weAreNotDestroyed = this.isAlive();\n return thisIsMostRecentRequest && weAreNotDestroyed;\n };\n RowNodeBlock.prototype.successCommon = function (version, params) {\n // need to dispatch load complete before processing the data, as PaginationComp checks\n // RowNodeBlockLoader to see if it is still loading, so the RowNodeBlockLoader needs to\n // be updated first (via LoadComplete event) before PaginationComp updates (via processServerResult method)\n this.dispatchLoadCompleted();\n var requestMostRecentAndLive = this.isRequestMostRecentAndLive(version);\n if (requestMostRecentAndLive) {\n this.state = RowNodeBlock.STATE_LOADED;\n this.processServerResult(params);\n }\n };\n RowNodeBlock.prototype.dispatchLoadCompleted = function (success) {\n if (success === void 0) { success = true; }\n // we fire event regardless of processing data or now, as we want\n // the concurrentLoadRequests count to be reduced in BlockLoader\n var event = {\n type: RowNodeBlock.EVENT_LOAD_COMPLETE,\n success: success,\n block: this\n };\n this.dispatchEvent(event);\n };\n RowNodeBlock.EVENT_LOAD_COMPLETE = 'loadComplete';\n RowNodeBlock.STATE_WAITING_TO_LOAD = 'needsLoading';\n RowNodeBlock.STATE_LOADING = 'loading';\n RowNodeBlock.STATE_LOADED = 'loaded';\n RowNodeBlock.STATE_FAILED = 'failed';\n return RowNodeBlock;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$16 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$10 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$6 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar RowNodeBlockLoader = /** @class */ (function (_super) {\n __extends$16(RowNodeBlockLoader, _super);\n function RowNodeBlockLoader() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.activeBlockLoadsCount = 0;\n _this.blocks = [];\n _this.active = true;\n return _this;\n }\n RowNodeBlockLoader_1 = RowNodeBlockLoader;\n RowNodeBlockLoader.prototype.postConstruct = function () {\n this.maxConcurrentRequests = this.gridOptionsWrapper.getMaxConcurrentDatasourceRequests();\n var blockLoadDebounceMillis = this.gridOptionsWrapper.getBlockLoadDebounceMillis();\n if (blockLoadDebounceMillis && blockLoadDebounceMillis > 0) {\n this.checkBlockToLoadDebounce = _.debounce(this.performCheckBlocksToLoad.bind(this), blockLoadDebounceMillis);\n }\n };\n RowNodeBlockLoader.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('RowNodeBlockLoader');\n };\n RowNodeBlockLoader.prototype.addBlock = function (block) {\n this.blocks.push(block);\n // note that we do not remove this listener when removing the block. this is because the\n // cache can get destroyed (and containing blocks) when a block is loading. however the loading block\n // is still counted as an active loading block and we must decrement activeBlockLoadsCount when it finishes.\n block.addEventListener(RowNodeBlock.EVENT_LOAD_COMPLETE, this.loadComplete.bind(this));\n this.checkBlockToLoad();\n };\n RowNodeBlockLoader.prototype.removeBlock = function (block) {\n _.removeFromArray(this.blocks, block);\n };\n RowNodeBlockLoader.prototype.destroy = function () {\n _super.prototype.destroy.call(this);\n this.active = false;\n };\n RowNodeBlockLoader.prototype.loadComplete = function () {\n this.activeBlockLoadsCount--;\n this.checkBlockToLoad();\n if (this.activeBlockLoadsCount == 0) {\n this.dispatchEvent({ type: RowNodeBlockLoader_1.BLOCK_LOADER_FINISHED_EVENT });\n }\n };\n RowNodeBlockLoader.prototype.checkBlockToLoad = function () {\n if (this.checkBlockToLoadDebounce) {\n this.checkBlockToLoadDebounce();\n }\n else {\n this.performCheckBlocksToLoad();\n }\n };\n RowNodeBlockLoader.prototype.performCheckBlocksToLoad = function () {\n if (!this.active) {\n return;\n }\n this.printCacheStatus();\n if (this.maxConcurrentRequests != null && this.activeBlockLoadsCount >= this.maxConcurrentRequests) {\n this.logger.log(\"checkBlockToLoad: max loads exceeded\");\n return;\n }\n var loadAvailability = this.maxConcurrentRequests !== undefined ? this.maxConcurrentRequests - this.activeBlockLoadsCount : undefined;\n var blocksToLoad = this.blocks.filter(function (block) { return (block.getState() === RowNodeBlock.STATE_WAITING_TO_LOAD); }).slice(0, loadAvailability);\n this.activeBlockLoadsCount += blocksToLoad.length;\n blocksToLoad.forEach(function (block) { return block.load(); });\n this.printCacheStatus();\n };\n RowNodeBlockLoader.prototype.getBlockState = function () {\n var result = {};\n this.blocks.forEach(function (block) {\n var _a = block.getBlockStateJson(), id = _a.id, state = _a.state;\n result[id] = state;\n });\n return result;\n };\n RowNodeBlockLoader.prototype.printCacheStatus = function () {\n if (this.logger.isLogging()) {\n this.logger.log(\"printCacheStatus: activePageLoadsCount = \" + this.activeBlockLoadsCount + \",\"\n + (\" blocks = \" + JSON.stringify(this.getBlockState())));\n }\n };\n RowNodeBlockLoader.prototype.isLoading = function () {\n return this.activeBlockLoadsCount > 0;\n };\n var RowNodeBlockLoader_1;\n RowNodeBlockLoader.BLOCK_LOADER_FINISHED_EVENT = 'blockLoaderFinished';\n __decorate$10([\n PostConstruct\n ], RowNodeBlockLoader.prototype, \"postConstruct\", null);\n __decorate$10([\n __param$6(0, Qualifier('loggerFactory'))\n ], RowNodeBlockLoader.prototype, \"setBeans\", null);\n RowNodeBlockLoader = RowNodeBlockLoader_1 = __decorate$10([\n Bean('rowNodeBlockLoader')\n ], RowNodeBlockLoader);\n return RowNodeBlockLoader;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$15 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$$ = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar PaginationProxy = /** @class */ (function (_super) {\n __extends$15(PaginationProxy, _super);\n function PaginationProxy() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.currentPage = 0;\n _this.topDisplayedRowIndex = 0;\n _this.bottomDisplayedRowIndex = 0;\n _this.pixelOffset = 0;\n _this.masterRowCount = 0;\n return _this;\n }\n PaginationProxy.prototype.postConstruct = function () {\n this.active = this.gridOptionsWrapper.isPagination();\n this.paginateChildRows = this.gridOptionsWrapper.isPaginateChildRows();\n this.addManagedListener(this.eventService, Events.EVENT_MODEL_UPDATED, this.onModelUpdated.bind(this));\n this.addManagedListener(this.gridOptionsWrapper, 'paginationPageSize', this.onPaginationPageSizeChanged.bind(this));\n this.onModelUpdated();\n };\n PaginationProxy.prototype.ensureRowHeightsValid = function (startPixel, endPixel, startLimitIndex, endLimitIndex) {\n var res = this.rowModel.ensureRowHeightsValid(startPixel, endPixel, this.getPageFirstRow(), this.getPageLastRow());\n if (res) {\n this.calculatePages();\n }\n return res;\n };\n PaginationProxy.prototype.onModelUpdated = function (modelUpdatedEvent) {\n this.calculatePages();\n var paginationChangedEvent = {\n type: Events.EVENT_PAGINATION_CHANGED,\n animate: modelUpdatedEvent ? modelUpdatedEvent.animate : false,\n newData: modelUpdatedEvent ? modelUpdatedEvent.newData : false,\n newPage: modelUpdatedEvent ? modelUpdatedEvent.newPage : false,\n keepRenderedRows: modelUpdatedEvent ? modelUpdatedEvent.keepRenderedRows : false\n };\n this.eventService.dispatchEvent(paginationChangedEvent);\n };\n PaginationProxy.prototype.onPaginationPageSizeChanged = function () {\n this.calculatePages();\n var paginationChangedEvent = {\n type: Events.EVENT_PAGINATION_CHANGED,\n animate: false,\n newData: false,\n newPage: false,\n // important to keep rendered rows, otherwise every time grid is resized,\n // we would destroy all the rows.\n keepRenderedRows: true\n };\n this.eventService.dispatchEvent(paginationChangedEvent);\n };\n PaginationProxy.prototype.goToPage = function (page) {\n if (!this.active || this.currentPage === page) {\n return;\n }\n this.currentPage = page;\n var event = {\n type: Events.EVENT_MODEL_UPDATED,\n animate: false,\n keepRenderedRows: false,\n newData: false,\n newPage: true\n };\n this.onModelUpdated(event);\n };\n PaginationProxy.prototype.getPixelOffset = function () {\n return this.pixelOffset;\n };\n PaginationProxy.prototype.getRow = function (index) {\n return this.rowModel.getRow(index);\n };\n PaginationProxy.prototype.getRowNode = function (id) {\n return this.rowModel.getRowNode(id);\n };\n PaginationProxy.prototype.getRowIndexAtPixel = function (pixel) {\n return this.rowModel.getRowIndexAtPixel(pixel);\n };\n PaginationProxy.prototype.getCurrentPageHeight = function () {\n if (missing(this.topRowBounds) || missing(this.bottomRowBounds)) {\n return 0;\n }\n return Math.max(this.bottomRowBounds.rowTop + this.bottomRowBounds.rowHeight - this.topRowBounds.rowTop, 0);\n };\n PaginationProxy.prototype.getCurrentPagePixelRange = function () {\n var pageFirstPixel = this.topRowBounds ? this.topRowBounds.rowTop : 0;\n var pageLastPixel = this.bottomRowBounds ? this.bottomRowBounds.rowTop + this.bottomRowBounds.rowHeight : 0;\n return { pageFirstPixel: pageFirstPixel, pageLastPixel: pageLastPixel };\n };\n PaginationProxy.prototype.isRowPresent = function (rowNode) {\n if (!this.rowModel.isRowPresent(rowNode)) {\n return false;\n }\n var nodeIsInPage = rowNode.rowIndex >= this.topDisplayedRowIndex && rowNode.rowIndex <= this.bottomDisplayedRowIndex;\n return nodeIsInPage;\n };\n PaginationProxy.prototype.isEmpty = function () {\n return this.rowModel.isEmpty();\n };\n PaginationProxy.prototype.isRowsToRender = function () {\n return this.rowModel.isRowsToRender();\n };\n PaginationProxy.prototype.getNodesInRangeForSelection = function (firstInRange, lastInRange) {\n return this.rowModel.getNodesInRangeForSelection(firstInRange, lastInRange);\n };\n PaginationProxy.prototype.forEachNode = function (callback) {\n return this.rowModel.forEachNode(callback);\n };\n PaginationProxy.prototype.getType = function () {\n return this.rowModel.getType();\n };\n PaginationProxy.prototype.getRowBounds = function (index) {\n var res = this.rowModel.getRowBounds(index);\n res.rowIndex = index;\n return res;\n };\n PaginationProxy.prototype.getPageFirstRow = function () {\n return this.topRowBounds ? this.topRowBounds.rowIndex : -1;\n };\n PaginationProxy.prototype.getPageLastRow = function () {\n return this.bottomRowBounds ? this.bottomRowBounds.rowIndex : -1;\n };\n PaginationProxy.prototype.getRowCount = function () {\n return this.rowModel.getRowCount();\n };\n PaginationProxy.prototype.getPageForIndex = function (index) {\n return Math.floor(index / this.pageSize);\n };\n PaginationProxy.prototype.goToPageWithIndex = function (index) {\n if (!this.active) {\n return;\n }\n var pageNumber = this.getPageForIndex(index);\n this.goToPage(pageNumber);\n };\n PaginationProxy.prototype.isRowInPage = function (row) {\n if (!this.active) {\n return true;\n }\n var rowPage = this.getPageForIndex(row.rowIndex);\n return rowPage === this.currentPage;\n };\n PaginationProxy.prototype.isLastPageFound = function () {\n return this.rowModel.isLastRowIndexKnown();\n };\n PaginationProxy.prototype.getCurrentPage = function () {\n return this.currentPage;\n };\n PaginationProxy.prototype.goToNextPage = function () {\n this.goToPage(this.currentPage + 1);\n };\n PaginationProxy.prototype.goToPreviousPage = function () {\n this.goToPage(this.currentPage - 1);\n };\n PaginationProxy.prototype.goToFirstPage = function () {\n this.goToPage(0);\n };\n PaginationProxy.prototype.goToLastPage = function () {\n var rowCount = this.rowModel.getRowCount();\n var lastPage = Math.floor(rowCount / this.pageSize);\n this.goToPage(lastPage);\n };\n PaginationProxy.prototype.getPageSize = function () {\n return this.pageSize;\n };\n PaginationProxy.prototype.getTotalPages = function () {\n return this.totalPages;\n };\n PaginationProxy.prototype.setPageSize = function () {\n // show put this into super class\n this.pageSize = this.gridOptionsWrapper.getPaginationPageSize();\n if (this.pageSize == null || this.pageSize < 1) {\n this.pageSize = 100;\n }\n };\n PaginationProxy.prototype.calculatePages = function () {\n if (this.active) {\n this.setPageSize();\n if (this.paginateChildRows) {\n this.calculatePagesAllRows();\n }\n else {\n this.calculatePagesMasterRowsOnly();\n }\n }\n else {\n this.calculatedPagesNotActive();\n }\n this.topRowBounds = this.rowModel.getRowBounds(this.topDisplayedRowIndex);\n if (this.topRowBounds) {\n this.topRowBounds.rowIndex = this.topDisplayedRowIndex;\n }\n this.bottomRowBounds = this.rowModel.getRowBounds(this.bottomDisplayedRowIndex);\n if (this.bottomRowBounds) {\n this.bottomRowBounds.rowIndex = this.bottomDisplayedRowIndex;\n }\n this.setPixelOffset(exists(this.topRowBounds) ? this.topRowBounds.rowTop : 0);\n };\n PaginationProxy.prototype.setPixelOffset = function (value) {\n if (this.pixelOffset === value) {\n return;\n }\n this.pixelOffset = value;\n this.eventService.dispatchEvent({ type: Events.EVENT_PAGINATION_PIXEL_OFFSET_CHANGED });\n };\n PaginationProxy.prototype.setZeroRows = function () {\n this.masterRowCount = 0;\n this.topDisplayedRowIndex = 0;\n this.bottomDisplayedRowIndex = -1;\n this.currentPage = 0;\n this.totalPages = 0;\n };\n PaginationProxy.prototype.calculatePagesMasterRowsOnly = function () {\n // const csrm = <ClientSideRowModel> this.rowModel;\n // const rootNode = csrm.getRootNode();\n // const masterRows = rootNode.childrenAfterSort;\n this.masterRowCount = this.rowModel.getTopLevelRowCount();\n // we say <=0 (rather than =0) as viewport returns -1 when no rows\n if (this.masterRowCount <= 0) {\n this.setZeroRows();\n return;\n }\n var masterLastRowIndex = this.masterRowCount - 1;\n this.totalPages = Math.floor((masterLastRowIndex) / this.pageSize) + 1;\n if (this.currentPage >= this.totalPages) {\n this.currentPage = this.totalPages - 1;\n }\n if (!isNumeric(this.currentPage) || this.currentPage < 0) {\n this.currentPage = 0;\n }\n var masterPageStartIndex = this.pageSize * this.currentPage;\n var masterPageEndIndex = (this.pageSize * (this.currentPage + 1)) - 1;\n if (masterPageEndIndex > masterLastRowIndex) {\n masterPageEndIndex = masterLastRowIndex;\n }\n this.topDisplayedRowIndex = this.rowModel.getTopLevelRowDisplayedIndex(masterPageStartIndex);\n // masterRows[masterPageStartIndex].rowIndex;\n if (masterPageEndIndex === masterLastRowIndex) {\n // if showing the last master row, then we want to show the very last row of the model\n this.bottomDisplayedRowIndex = this.rowModel.getRowCount() - 1;\n }\n else {\n var firstIndexNotToShow = this.rowModel.getTopLevelRowDisplayedIndex(masterPageEndIndex + 1);\n //masterRows[masterPageEndIndex + 1].rowIndex;\n // this gets the index of the last child - eg current row is open, we want to display all children,\n // the index of the last child is one less than the index of the next parent row.\n this.bottomDisplayedRowIndex = firstIndexNotToShow - 1;\n }\n };\n PaginationProxy.prototype.getMasterRowCount = function () {\n return this.masterRowCount;\n };\n PaginationProxy.prototype.calculatePagesAllRows = function () {\n this.masterRowCount = this.rowModel.getRowCount();\n if (this.masterRowCount === 0) {\n this.setZeroRows();\n return;\n }\n var maxRowIndex = this.masterRowCount - 1;\n this.totalPages = Math.floor((maxRowIndex) / this.pageSize) + 1;\n if (this.currentPage >= this.totalPages) {\n this.currentPage = this.totalPages - 1;\n }\n if (!isNumeric(this.currentPage) || this.currentPage < 0) {\n this.currentPage = 0;\n }\n this.topDisplayedRowIndex = this.pageSize * this.currentPage;\n this.bottomDisplayedRowIndex = (this.pageSize * (this.currentPage + 1)) - 1;\n if (this.bottomDisplayedRowIndex > maxRowIndex) {\n this.bottomDisplayedRowIndex = maxRowIndex;\n }\n };\n PaginationProxy.prototype.calculatedPagesNotActive = function () {\n this.pageSize = this.rowModel.getRowCount();\n this.totalPages = 1;\n this.currentPage = 0;\n this.topDisplayedRowIndex = 0;\n this.bottomDisplayedRowIndex = this.rowModel.getRowCount() - 1;\n };\n __decorate$$([\n Autowired('rowModel')\n ], PaginationProxy.prototype, \"rowModel\", void 0);\n __decorate$$([\n PostConstruct\n ], PaginationProxy.prototype, \"postConstruct\", null);\n PaginationProxy = __decorate$$([\n Bean('paginationProxy')\n ], PaginationProxy);\n return PaginationProxy;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$14 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$_ = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar StylingService = /** @class */ (function (_super) {\n __extends$14(StylingService, _super);\n function StylingService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n StylingService.prototype.processAllCellClasses = function (colDef, params, onApplicableClass, onNotApplicableClass) {\n this.processClassRules(colDef.cellClassRules, params, onApplicableClass, onNotApplicableClass);\n this.processStaticCellClasses(colDef, params, onApplicableClass);\n };\n StylingService.prototype.processClassRules = function (classRules, params, onApplicableClass, onNotApplicableClass) {\n if (classRules == null) {\n return;\n }\n var classNames = Object.keys(classRules);\n var classesToApply = {};\n var classesToRemove = {};\n var _loop_1 = function (i) {\n var className = classNames[i];\n var rule = classRules[className];\n var resultOfRule;\n if (typeof rule === 'string') {\n resultOfRule = this_1.expressionService.evaluate(rule, params);\n }\n else if (typeof rule === 'function') {\n resultOfRule = rule(params);\n }\n // in case className = 'my-class1 my-class2', we need to split into individual class names\n className.split(' ').forEach(function (singleClass) {\n if (singleClass == null || singleClass.trim() == '') {\n return;\n }\n resultOfRule ? classesToApply[singleClass] = true : classesToRemove[singleClass] = true;\n });\n };\n var this_1 = this;\n for (var i = 0; i < classNames.length; i++) {\n _loop_1(i);\n }\n // we remove all classes first, then add all classes second,\n // in case a class appears in more than one rule, this means it will be added\n // if appears in at least one truthy rule\n if (onNotApplicableClass) {\n Object.keys(classesToRemove).forEach(onNotApplicableClass);\n }\n Object.keys(classesToApply).forEach(onApplicableClass);\n };\n StylingService.prototype.getStaticCellClasses = function (colDef, params) {\n var cellClass = colDef.cellClass;\n if (!cellClass) {\n return [];\n }\n var classOrClasses;\n if (typeof cellClass === 'function') {\n var cellClassFunc = cellClass;\n classOrClasses = cellClassFunc(params);\n }\n else {\n classOrClasses = cellClass;\n }\n if (typeof classOrClasses === 'string') {\n classOrClasses = [classOrClasses];\n }\n return classOrClasses || [];\n };\n StylingService.prototype.processStaticCellClasses = function (colDef, params, onApplicableClass) {\n var classOrClasses = this.getStaticCellClasses(colDef, params);\n classOrClasses.forEach(function (cssClassItem) {\n onApplicableClass(cssClassItem);\n });\n };\n __decorate$_([\n Autowired('expressionService')\n ], StylingService.prototype, \"expressionService\", void 0);\n StylingService = __decorate$_([\n Bean('stylingService')\n ], StylingService);\n return StylingService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$13 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgRadioButton = /** @class */ (function (_super) {\n __extends$13(AgRadioButton, _super);\n function AgRadioButton(config) {\n return _super.call(this, config, 'ag-radio-button', 'radio') || this;\n }\n AgRadioButton.prototype.isSelected = function () {\n return this.eInput.checked;\n };\n AgRadioButton.prototype.toggle = function () {\n if (this.eInput.disabled) {\n return;\n }\n // do not allow an active radio button to be deselected\n if (!this.isSelected()) {\n this.setValue(true);\n }\n };\n AgRadioButton.prototype.addInputListeners = function () {\n _super.prototype.addInputListeners.call(this);\n this.addManagedListener(this.eventService, Events.EVENT_CHECKBOX_CHANGED, this.onChange.bind(this));\n };\n /**\n * This ensures that if another radio button in the same named group is selected, we deselect this radio button.\n * By default the browser does this for you, but we are managing classes ourselves in order to ensure input\n * elements are styled correctly in IE11, and the DOM 'changed' event is only fired when a button is selected,\n * not deselected, so we need to use our own event.\n */\n AgRadioButton.prototype.onChange = function (event) {\n if (event.selected &&\n event.name &&\n this.eInput.name &&\n this.eInput.name === event.name &&\n event.id &&\n this.eInput.id !== event.id) {\n this.setValue(false, true);\n }\n };\n return AgRadioButton;\n}(AgCheckbox));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$12 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgToggleButton = /** @class */ (function (_super) {\n __extends$12(AgToggleButton, _super);\n function AgToggleButton(config) {\n return _super.call(this, config, 'ag-toggle-button') || this;\n }\n AgToggleButton.prototype.setValue = function (value, silent) {\n _super.prototype.setValue.call(this, value, silent);\n this.addOrRemoveCssClass('ag-selected', this.getValue());\n return this;\n };\n return AgToggleButton;\n}(AgCheckbox));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$11 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgInputTextField = /** @class */ (function (_super) {\n __extends$11(AgInputTextField, _super);\n function AgInputTextField(config, className, inputType) {\n if (className === void 0) { className = 'ag-text-field'; }\n if (inputType === void 0) { inputType = 'text'; }\n return _super.call(this, config, className, inputType) || this;\n }\n AgInputTextField.prototype.postConstruct = function () {\n _super.prototype.postConstruct.call(this);\n if (this.config.allowedCharPattern) {\n this.preventDisallowedCharacters();\n }\n };\n AgInputTextField.prototype.setValue = function (value, silent) {\n var ret = _super.prototype.setValue.call(this, value, silent);\n if (this.eInput.value !== value) {\n this.eInput.value = exists(value) ? value : '';\n }\n return ret;\n };\n AgInputTextField.prototype.preventDisallowedCharacters = function () {\n var pattern = new RegExp(\"[\" + this.config.allowedCharPattern + \"]\");\n var preventDisallowedCharacters = function (event) {\n if (event.key && !pattern.test(event.key)) {\n event.preventDefault();\n }\n };\n this.addManagedListener(this.eInput, 'keypress', preventDisallowedCharacters);\n this.addManagedListener(this.eInput, 'paste', function (e) {\n var _a;\n var text = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text');\n if (text && text.split('').some(function (c) { return !pattern.test(c); })) {\n e.preventDefault();\n }\n });\n };\n return AgInputTextField;\n}(AgAbstractInputField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$10 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgInputTextArea = /** @class */ (function (_super) {\n __extends$10(AgInputTextArea, _super);\n function AgInputTextArea(config) {\n return _super.call(this, config, 'ag-text-area', null, 'textarea') || this;\n }\n AgInputTextArea.prototype.setValue = function (value, silent) {\n var ret = _super.prototype.setValue.call(this, value, silent);\n this.eInput.value = value;\n return ret;\n };\n AgInputTextArea.prototype.setCols = function (cols) {\n this.eInput.cols = cols;\n return this;\n };\n AgInputTextArea.prototype.setRows = function (rows) {\n this.eInput.rows = rows;\n return this;\n };\n return AgInputTextArea;\n}(AgAbstractInputField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$$ = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgInputNumberField = /** @class */ (function (_super) {\n __extends$$(AgInputNumberField, _super);\n function AgInputNumberField(config) {\n return _super.call(this, config, 'ag-number-field', 'number') || this;\n }\n AgInputNumberField.prototype.postConstruct = function () {\n var _this = this;\n _super.prototype.postConstruct.call(this);\n this.addManagedListener(this.eInput, 'blur', function () {\n var floatedValue = parseFloat(_this.eInput.value);\n var value = isNaN(floatedValue) ? '' : _this.normalizeValue(floatedValue.toString());\n if (_this.value !== value) {\n _this.setValue(value);\n }\n });\n this.addManagedListener(this.eInput, 'wheel', this.onWheel.bind(this));\n this.eInput.step = 'any';\n };\n AgInputNumberField.prototype.onWheel = function (e) {\n // Prevent default scroll events from incrementing / decrementing the input, since its inconsistent between browsers\n if (document.activeElement === this.eInput) {\n e.preventDefault();\n }\n };\n AgInputNumberField.prototype.normalizeValue = function (value) {\n if (value === '') {\n return '';\n }\n if (this.precision) {\n value = this.adjustPrecision(value);\n }\n var val = parseFloat(value);\n if (this.min != null && val < this.min) {\n value = this.min.toString();\n }\n else if (this.max != null && val > this.max) {\n value = this.max.toString();\n }\n return value;\n };\n AgInputNumberField.prototype.adjustPrecision = function (value) {\n if (this.precision) {\n var floatString = parseFloat(value).toFixed(this.precision);\n value = parseFloat(floatString).toString();\n }\n return value;\n };\n AgInputNumberField.prototype.setMin = function (min) {\n if (this.min === min) {\n return this;\n }\n this.min = min;\n addOrRemoveAttribute(this.eInput, 'min', min);\n return this;\n };\n AgInputNumberField.prototype.setMax = function (max) {\n if (this.max === max) {\n return this;\n }\n this.max = max;\n addOrRemoveAttribute(this.eInput, 'max', max);\n return this;\n };\n AgInputNumberField.prototype.setPrecision = function (precision) {\n this.precision = precision;\n return this;\n };\n AgInputNumberField.prototype.setStep = function (step) {\n if (this.step === step) {\n return this;\n }\n this.step = step;\n addOrRemoveAttribute(this.eInput, 'step', step);\n return this;\n };\n AgInputNumberField.prototype.setValue = function (value, silent) {\n value = this.adjustPrecision(value);\n var normalizedValue = this.normalizeValue(value);\n if (value != normalizedValue) {\n return this;\n }\n return _super.prototype.setValue.call(this, value, silent);\n };\n return AgInputNumberField;\n}(AgInputTextField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$_ = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgInputRange = /** @class */ (function (_super) {\n __extends$_(AgInputRange, _super);\n function AgInputRange(config) {\n return _super.call(this, config, 'ag-range-field', 'range') || this;\n }\n AgInputRange.prototype.postConstruct = function () {\n _super.prototype.postConstruct.call(this);\n var _a = this.config, min = _a.min, max = _a.max, step = _a.step;\n if (min != null) {\n this.setMinValue(min);\n }\n if (max != null) {\n this.setMaxValue(max);\n }\n this.setStep(step || 1);\n };\n AgInputRange.prototype.addInputListeners = function () {\n var _this = this;\n this.addManagedListener(this.eInput, 'input', function (e) {\n var value = e.target.value;\n _this.setValue(value);\n });\n };\n AgInputRange.prototype.setMinValue = function (value) {\n this.min = value;\n this.eInput.setAttribute('min', value.toString());\n return this;\n };\n AgInputRange.prototype.setMaxValue = function (value) {\n this.max = value;\n this.eInput.setAttribute('max', value.toString());\n return this;\n };\n AgInputRange.prototype.setStep = function (value) {\n this.eInput.setAttribute('step', value.toString());\n return this;\n };\n AgInputRange.prototype.setValue = function (value, silent) {\n if (this.min != null) {\n value = Math.max(parseFloat(value), this.min).toString();\n }\n if (this.max != null) {\n value = Math.min(parseFloat(value), this.max).toString();\n }\n var ret = _super.prototype.setValue.call(this, value, silent);\n this.eInput.value = value;\n return ret;\n };\n return AgInputRange;\n}(AgAbstractInputField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$Z = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$Z = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgSlider = /** @class */ (function (_super) {\n __extends$Z(AgSlider, _super);\n function AgSlider(config) {\n var _this = _super.call(this, config, AgSlider.TEMPLATE) || this;\n _this.labelAlignment = 'top';\n return _this;\n }\n AgSlider.prototype.init = function () {\n this.eSlider.addCssClass('ag-slider-field');\n };\n AgSlider.prototype.onValueChange = function (callbackFn) {\n var _this = this;\n var eventChanged = AgAbstractField.EVENT_CHANGED;\n this.addManagedListener(this.eText, eventChanged, function () {\n var textValue = parseFloat(_this.eText.getValue());\n _this.eSlider.setValue(textValue.toString(), true);\n callbackFn(textValue || 0);\n });\n this.addManagedListener(this.eSlider, eventChanged, function () {\n var sliderValue = _this.eSlider.getValue();\n _this.eText.setValue(sliderValue, true);\n callbackFn(parseFloat(sliderValue));\n });\n return this;\n };\n AgSlider.prototype.setSliderWidth = function (width) {\n this.eSlider.setWidth(width);\n return this;\n };\n AgSlider.prototype.setTextFieldWidth = function (width) {\n this.eText.setWidth(width);\n return this;\n };\n AgSlider.prototype.setMinValue = function (minValue) {\n this.eSlider.setMinValue(minValue);\n this.eText.setMin(minValue);\n return this;\n };\n AgSlider.prototype.setMaxValue = function (maxValue) {\n this.eSlider.setMaxValue(maxValue);\n this.eText.setMax(maxValue);\n return this;\n };\n AgSlider.prototype.getValue = function () {\n return this.eText.getValue();\n };\n AgSlider.prototype.setValue = function (value) {\n if (this.getValue() === value) {\n return this;\n }\n this.eText.setValue(value, true);\n this.eSlider.setValue(value, true);\n this.dispatchEvent({ type: AgAbstractField.EVENT_CHANGED });\n return this;\n };\n AgSlider.prototype.setStep = function (step) {\n this.eSlider.setStep(step);\n this.eText.setStep(step);\n return this;\n };\n AgSlider.TEMPLATE = \"<div class=\\\"ag-slider\\\">\\n <label ref=\\\"eLabel\\\"></label>\\n <div class=\\\"ag-wrapper ag-slider-wrapper\\\">\\n <ag-input-range ref=\\\"eSlider\\\"></ag-input-range>\\n <ag-input-number-field ref=\\\"eText\\\"></ag-input-number-field>\\n </div>\\n </div>\";\n __decorate$Z([\n RefSelector('eLabel')\n ], AgSlider.prototype, \"eLabel\", void 0);\n __decorate$Z([\n RefSelector('eSlider')\n ], AgSlider.prototype, \"eSlider\", void 0);\n __decorate$Z([\n RefSelector('eText')\n ], AgSlider.prototype, \"eText\", void 0);\n __decorate$Z([\n PostConstruct\n ], AgSlider.prototype, \"init\", null);\n return AgSlider;\n}(AgAbstractLabel));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$Y = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$Y = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgAngleSelect = /** @class */ (function (_super) {\n __extends$Y(AgAngleSelect, _super);\n function AgAngleSelect(config) {\n var _this = _super.call(this, config, AgAngleSelect.TEMPLATE) || this;\n _this.radius = 0;\n _this.offsetX = 0;\n _this.offsetY = 0;\n return _this;\n }\n AgAngleSelect.prototype.postConstruct = function () {\n var _this = this;\n _super.prototype.postConstruct.call(this);\n this.dragListener = {\n eElement: this.eParentCircle,\n dragStartPixels: 0,\n onDragStart: function (e) {\n _this.parentCircleRect = _this.eParentCircle.getBoundingClientRect();\n },\n onDragging: function (e) { return _this.calculateAngleDrag(e); },\n onDragStop: function () { }\n };\n this.dragService.addDragSource(this.dragListener);\n this.eAngleValue\n .setLabel('')\n .setLabelWidth(5)\n .setInputWidth(45)\n .setMin(0)\n .setMax(360)\n .setValue(\"\" + this.degrees)\n .onValueChange(function (value) {\n if (value == null || value === '') {\n value = '0';\n }\n value = _this.eAngleValue.normalizeValue(value);\n var floatValue = parseFloat(value);\n if (floatValue > 180) {\n floatValue = floatValue - 360;\n }\n _this.setValue(floatValue);\n });\n this.updateNumberInput();\n if (exists(this.getValue())) {\n this.eAngleValue.setValue(this.normalizeNegativeValue(this.getValue()).toString());\n }\n this.addManagedListener(this, AgAbstractField.EVENT_CHANGED, function () {\n var eDocument = _this.gridOptionsWrapper.getDocument();\n if (_this.eAngleValue.getInputElement().contains(eDocument.activeElement)) {\n return;\n }\n _this.updateNumberInput();\n });\n };\n AgAngleSelect.prototype.updateNumberInput = function () {\n var normalizedValue = this.normalizeNegativeValue(this.getValue());\n this.eAngleValue.setValue(normalizedValue.toString());\n };\n AgAngleSelect.prototype.positionChildCircle = function (radians) {\n var rect = this.parentCircleRect || { width: 24, height: 24 };\n var eChildCircle = this.eChildCircle;\n var centerX = rect.width / 2;\n var centerY = rect.height / 2;\n eChildCircle.style.left = centerX + Math.cos(radians) * 8 + \"px\";\n eChildCircle.style.top = centerY + Math.sin(radians) * 8 + \"px\";\n };\n AgAngleSelect.prototype.calculatePolar = function () {\n var x = this.offsetX;\n var y = this.offsetY;\n var radians = Math.atan2(y, x);\n this.degrees = this.toDegrees(radians);\n this.radius = Math.sqrt((x * x) + (y * y));\n this.positionChildCircle(radians);\n };\n AgAngleSelect.prototype.calculateCartesian = function () {\n var radians = this.toRadians(this.getValue());\n var radius = this.getRadius();\n this\n .setOffsetX(Math.cos(radians) * radius)\n .setOffsetY(Math.sin(radians) * radius);\n };\n AgAngleSelect.prototype.setOffsetX = function (offset) {\n if (this.offsetX !== offset) {\n this.offsetX = offset;\n this.calculatePolar();\n }\n return this;\n };\n AgAngleSelect.prototype.setOffsetY = function (offset) {\n if (this.offsetY !== offset) {\n this.offsetY = offset;\n this.calculatePolar();\n }\n return this;\n };\n AgAngleSelect.prototype.calculateAngleDrag = function (e) {\n var rect = this.parentCircleRect;\n var centerX = rect.width / 2;\n var centerY = rect.height / 2;\n var x = e.clientX - rect.left;\n var y = e.clientY - rect.top;\n var dx = x - centerX;\n var dy = y - centerY;\n var radians = Math.atan2(dy, dx);\n this.setValue(radians, true);\n };\n AgAngleSelect.prototype.toDegrees = function (radians) {\n return radians / Math.PI * 180;\n };\n AgAngleSelect.prototype.toRadians = function (degrees) {\n return degrees / 180 * Math.PI;\n };\n AgAngleSelect.prototype.normalizeNegativeValue = function (degrees) {\n return degrees < 0 ? 360 + degrees : degrees;\n };\n AgAngleSelect.prototype.normalizeAngle180 = function (radians) {\n radians %= Math.PI * 2;\n if (radians < -Math.PI) {\n radians += Math.PI * 2;\n }\n else if (radians >= Math.PI) {\n radians -= Math.PI * 2;\n }\n return radians;\n };\n AgAngleSelect.prototype.getRadius = function () {\n return this.radius;\n };\n AgAngleSelect.prototype.setRadius = function (r) {\n if (this.radius === r) {\n return this;\n }\n this.radius = r;\n this.calculateCartesian();\n return this;\n };\n AgAngleSelect.prototype.onValueChange = function (callbackFn) {\n var _this = this;\n this.addManagedListener(this, AgAbstractField.EVENT_CHANGED, function () {\n callbackFn(_this.degrees);\n });\n return this;\n };\n AgAngleSelect.prototype.getValue = function (radians) {\n return radians ? this.toRadians(this.degrees) : this.degrees;\n };\n AgAngleSelect.prototype.setValue = function (degrees, radians) {\n var radiansValue;\n if (!radians) {\n radiansValue = this.normalizeAngle180(this.toRadians(degrees));\n }\n else {\n radiansValue = degrees;\n }\n degrees = this.toDegrees(radiansValue);\n if (this.degrees !== degrees) {\n this.degrees = Math.floor(degrees);\n this.calculateCartesian();\n this.positionChildCircle(radiansValue);\n this.dispatchEvent({ type: AgAbstractField.EVENT_CHANGED });\n }\n return this;\n };\n AgAngleSelect.prototype.setWidth = function (width) {\n setFixedWidth(this.getGui(), width);\n return this;\n };\n AgAngleSelect.prototype.setDisabled = function (disabled) {\n _super.prototype.setDisabled.call(this, disabled);\n this.eAngleValue.setDisabled(disabled);\n return this;\n };\n AgAngleSelect.prototype.destroy = function () {\n this.dragService.removeDragSource(this.dragListener);\n _super.prototype.destroy.call(this);\n };\n AgAngleSelect.TEMPLATE = \"<div class=\\\"ag-angle-select\\\">\\n <div ref=\\\"eLabel\\\"></div>\\n <div class=\\\"ag-wrapper ag-angle-select-wrapper\\\">\\n <div ref=\\\"eAngleSelectField\\\" class=\\\"ag-angle-select-field\\\">\\n <div ref=\\\"eParentCircle\\\" class=\\\"ag-angle-select-parent-circle\\\">\\n <div ref=\\\"eChildCircle\\\" class=\\\"ag-angle-select-child-circle\\\"></div>\\n </div>\\n </div>\\n <ag-input-number-field ref=\\\"eAngleValue\\\"></ag-input-number-field>\\n </div>\\n </div>\";\n __decorate$Y([\n RefSelector('eLabel')\n ], AgAngleSelect.prototype, \"eLabel\", void 0);\n __decorate$Y([\n RefSelector('eParentCircle')\n ], AgAngleSelect.prototype, \"eParentCircle\", void 0);\n __decorate$Y([\n RefSelector('eChildCircle')\n ], AgAngleSelect.prototype, \"eChildCircle\", void 0);\n __decorate$Y([\n RefSelector('eAngleValue')\n ], AgAngleSelect.prototype, \"eAngleValue\", void 0);\n __decorate$Y([\n Autowired('dragService')\n ], AgAngleSelect.prototype, \"dragService\", void 0);\n return AgAngleSelect;\n}(AgAbstractLabel));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$X = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$X = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$9 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar AgColorPanel = /** @class */ (function (_super) {\n __extends$X(AgColorPanel, _super);\n function AgColorPanel(config) {\n var _this = _super.call(this, AgColorPanel.TEMPLATE) || this;\n _this.H = 1; // in the [0, 1] range\n _this.S = 1; // in the [0, 1] range\n _this.B = 1; // in the [0, 1] range\n _this.A = 1; // in the [0, 1] range\n _this.isSpectrumDragging = false;\n _this.isSpectrumHueDragging = false;\n _this.isSpectrumAlphaDragging = false;\n _this.colorChanged = false;\n _this.picker = config.picker;\n return _this;\n }\n AgColorPanel.prototype.postConstruct = function () {\n var eGui = this.getGui();\n this.initRecentColors();\n this.addManagedListener(this.spectrumVal, 'mousedown', this.onSpectrumDraggerDown.bind(this));\n this.addManagedListener(eGui, 'mousemove', this.onSpectrumDraggerMove.bind(this));\n this.addManagedListener(this.spectrumHue, 'mousedown', this.onSpectrumHueDown.bind(this));\n this.addManagedListener(eGui, 'mousemove', this.onSpectrumHueMove.bind(this));\n this.addManagedListener(this.spectrumAlpha, 'mousedown', this.onSpectrumAlphaDown.bind(this));\n this.addManagedListener(eGui, 'mousemove', this.onSpectrumAlphaMove.bind(this));\n // Listening to `mouseup` on the document on purpose. The user might release the mouse button\n // outside the UI control. When the mouse returns back to the control's area, the dragging\n // of the thumb is not expected and seen as a bug.\n this.addManagedListener(document, 'mouseup', this.onMouseUp.bind(this));\n this.addManagedListener(this.recentColors, 'click', this.onRecentColorClick.bind(this));\n };\n AgColorPanel.prototype.refreshSpectrumRect = function () {\n return this.spectrumValRect = this.spectrumVal.getBoundingClientRect();\n };\n AgColorPanel.prototype.refreshHueRect = function () {\n return this.spectrumHueRect = this.spectrumHue.getBoundingClientRect();\n };\n AgColorPanel.prototype.refreshAlphaRect = function () {\n return this.spectrumAlphaRect = this.spectrumAlpha.getBoundingClientRect();\n };\n AgColorPanel.prototype.onSpectrumDraggerDown = function (e) {\n this.refreshSpectrumRect();\n this.isSpectrumDragging = true;\n this.moveDragger(e);\n };\n AgColorPanel.prototype.onSpectrumDraggerMove = function (e) {\n if (this.isSpectrumDragging) {\n this.moveDragger(e);\n }\n };\n AgColorPanel.prototype.onSpectrumHueDown = function (e) {\n this.refreshHueRect();\n this.isSpectrumHueDragging = true;\n this.moveHueSlider(e);\n };\n AgColorPanel.prototype.onSpectrumHueMove = function (e) {\n if (this.isSpectrumHueDragging) {\n this.moveHueSlider(e);\n }\n };\n AgColorPanel.prototype.onSpectrumAlphaDown = function (e) {\n this.refreshAlphaRect();\n this.isSpectrumAlphaDragging = true;\n this.moveAlphaSlider(e);\n };\n AgColorPanel.prototype.onSpectrumAlphaMove = function (e) {\n if (this.isSpectrumAlphaDragging) {\n this.moveAlphaSlider(e);\n }\n };\n AgColorPanel.prototype.onMouseUp = function () {\n this.isSpectrumDragging = false;\n this.isSpectrumHueDragging = false;\n this.isSpectrumAlphaDragging = false;\n };\n AgColorPanel.prototype.moveDragger = function (e) {\n var valRect = this.spectrumValRect;\n if (valRect) {\n var x = e.clientX - valRect.left;\n var y = e.clientY - valRect.top;\n x = Math.max(x, 0);\n x = Math.min(x, valRect.width);\n y = Math.max(y, 0);\n y = Math.min(y, valRect.height);\n this.setSpectrumValue(x / valRect.width, 1 - y / valRect.height);\n }\n };\n AgColorPanel.prototype.moveHueSlider = function (e) {\n var hueRect = this.spectrumHueRect;\n if (hueRect) {\n var slider = this.spectrumHueSlider;\n var sliderRect = slider.getBoundingClientRect();\n var x = e.clientX - hueRect.left;\n x = Math.max(x, 0);\n x = Math.min(x, hueRect.width);\n this.H = 1 - x / hueRect.width;\n slider.style.left = (x + sliderRect.width / 2) + 'px';\n this.update();\n }\n };\n AgColorPanel.prototype.moveAlphaSlider = function (e) {\n var alphaRect = this.spectrumAlphaRect;\n if (alphaRect) {\n var slider = this.spectrumAlphaSlider;\n var sliderRect = slider.getBoundingClientRect();\n var x = e.clientX - alphaRect.left;\n x = Math.max(x, 0);\n x = Math.min(x, alphaRect.width);\n this.A = x / alphaRect.width;\n slider.style.left = (x + sliderRect.width / 2) + 'px';\n this.update();\n }\n };\n AgColorPanel.prototype.update = function () {\n var color = Color.fromHSB(this.H * 360, this.S, this.B, this.A);\n var spectrumColor = Color.fromHSB(this.H * 360, 1, 1);\n var rgbaColor = color.toRgbaString();\n // the recent color list needs to know color has actually changed\n var colorPicker = this.picker;\n var existingColor = Color.fromString(colorPicker.getValue());\n if (existingColor.toRgbaString() !== rgbaColor) {\n this.colorChanged = true;\n }\n colorPicker.setValue(rgbaColor);\n this.spectrumColor.style.backgroundColor = spectrumColor.toRgbaString();\n this.spectrumDragger.style.backgroundColor = rgbaColor;\n };\n /**\n * @param saturation In the [0, 1] interval.\n * @param brightness In the [0, 1] interval.\n */\n AgColorPanel.prototype.setSpectrumValue = function (saturation, brightness) {\n var valRect = this.spectrumValRect || this.refreshSpectrumRect();\n if (valRect) {\n var dragger = this.spectrumDragger;\n var draggerRect = dragger.getBoundingClientRect();\n saturation = Math.max(0, saturation);\n saturation = Math.min(1, saturation);\n brightness = Math.max(0, brightness);\n brightness = Math.min(1, brightness);\n this.S = saturation;\n this.B = brightness;\n dragger.style.left = (saturation * valRect.width - draggerRect.width / 2) + 'px';\n dragger.style.top = ((1 - brightness) * valRect.height - draggerRect.height / 2) + 'px';\n this.update();\n }\n };\n AgColorPanel.prototype.initRecentColors = function () {\n var recentColors = AgColorPanel.recentColors;\n var innerHtml = recentColors.map(function (color, index) {\n return \"<div class=\\\"ag-recent-color\\\" id=\" + index + \" style=\\\"background-color: \" + color + \"; width: 15px; height: 15px;\\\" recent-color=\\\"\" + color + \"\\\"></div>\";\n });\n this.recentColors.innerHTML = innerHtml.join('');\n };\n AgColorPanel.prototype.setValue = function (val) {\n var color = Color.fromString(val);\n var _a = __read$9(color.toHSB(), 3), h = _a[0], s = _a[1], b = _a[2];\n this.H = (isNaN(h) ? 0 : h) / 360;\n this.A = color.a;\n var spectrumHueRect = this.spectrumHueRect || this.refreshHueRect();\n var spectrumAlphaRect = this.spectrumAlphaRect || this.refreshAlphaRect();\n this.spectrumHueSlider.style.left = ((this.H - 1) * -spectrumHueRect.width) + \"px\";\n this.spectrumAlphaSlider.style.left = (this.A * spectrumAlphaRect.width) + \"px\";\n this.setSpectrumValue(s, b);\n };\n AgColorPanel.prototype.onRecentColorClick = function (e) {\n var target = e.target;\n if (!exists(target.id)) {\n return;\n }\n var id = parseInt(target.id, 10);\n this.setValue(AgColorPanel.recentColors[id]);\n this.destroy();\n };\n AgColorPanel.prototype.addRecentColor = function () {\n var color = Color.fromHSB(this.H * 360, this.S, this.B, this.A);\n var rgbaColor = color.toRgbaString();\n var recentColors = AgColorPanel.recentColors;\n if (!this.colorChanged || recentColors[0] === rgbaColor) {\n return;\n }\n // remove duplicate color\n recentColors = recentColors.filter(function (currentColor) { return currentColor != rgbaColor; });\n // add color to head\n recentColors = [rgbaColor].concat(recentColors);\n // ensure we don't exceed max number of recent colors\n if (recentColors.length > AgColorPanel.maxRecentColors) {\n recentColors = recentColors.slice(0, AgColorPanel.maxRecentColors);\n }\n AgColorPanel.recentColors = recentColors;\n };\n AgColorPanel.prototype.destroy = function () {\n this.addRecentColor();\n _super.prototype.destroy.call(this);\n };\n AgColorPanel.maxRecentColors = 8;\n AgColorPanel.recentColors = [];\n AgColorPanel.TEMPLATE = \"<div class=\\\"ag-color-panel\\\">\\n <div ref=\\\"spectrumColor\\\" class=\\\"ag-spectrum-color\\\">\\n <div class=\\\"ag-spectrum-sat ag-spectrum-fill\\\">\\n <div ref=\\\"spectrumVal\\\" class=\\\"ag-spectrum-val ag-spectrum-fill\\\">\\n <div ref=\\\"spectrumDragger\\\" class=\\\"ag-spectrum-dragger\\\"></div>\\n </div>\\n </div>\\n </div>\\n <div class=\\\"ag-spectrum-tools\\\">\\n <div ref=\\\"spectrumHue\\\" class=\\\"ag-spectrum-hue ag-spectrum-tool\\\">\\n <div class=\\\"ag-spectrum-hue-background\\\"></div>\\n <div ref=\\\"spectrumHueSlider\\\" class=\\\"ag-spectrum-slider\\\"></div>\\n </div>\\n <div ref=\\\"spectrumAlpha\\\" class=\\\"ag-spectrum-alpha ag-spectrum-tool\\\">\\n <div class=\\\"ag-spectrum-alpha-background\\\"></div>\\n <div ref=\\\"spectrumAlphaSlider\\\" class=\\\"ag-spectrum-slider\\\"></div>\\n </div>\\n <div ref=\\\"recentColors\\\" class=\\\"ag-recent-colors\\\"></div>\\n </div>\\n </div>\";\n __decorate$X([\n RefSelector('spectrumColor')\n ], AgColorPanel.prototype, \"spectrumColor\", void 0);\n __decorate$X([\n RefSelector('spectrumVal')\n ], AgColorPanel.prototype, \"spectrumVal\", void 0);\n __decorate$X([\n RefSelector('spectrumDragger')\n ], AgColorPanel.prototype, \"spectrumDragger\", void 0);\n __decorate$X([\n RefSelector('spectrumHue')\n ], AgColorPanel.prototype, \"spectrumHue\", void 0);\n __decorate$X([\n RefSelector('spectrumHueSlider')\n ], AgColorPanel.prototype, \"spectrumHueSlider\", void 0);\n __decorate$X([\n RefSelector('spectrumAlpha')\n ], AgColorPanel.prototype, \"spectrumAlpha\", void 0);\n __decorate$X([\n RefSelector('spectrumAlphaSlider')\n ], AgColorPanel.prototype, \"spectrumAlphaSlider\", void 0);\n __decorate$X([\n RefSelector('recentColors')\n ], AgColorPanel.prototype, \"recentColors\", void 0);\n __decorate$X([\n PostConstruct\n ], AgColorPanel.prototype, \"postConstruct\", null);\n return AgColorPanel;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$W = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$W = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgPanel = /** @class */ (function (_super) {\n __extends$W(AgPanel, _super);\n function AgPanel(config) {\n var _this = _super.call(this, AgPanel.getTemplate(config)) || this;\n _this.closable = true;\n _this.config = config;\n return _this;\n }\n AgPanel.getTemplate = function (config) {\n var cssIdentifier = (config && config.cssIdentifier) || 'default';\n return /* html */ \"<div class=\\\"ag-panel ag-\" + cssIdentifier + \"-panel\\\" tabindex=\\\"-1\\\">\\n <div ref=\\\"eTitleBar\\\" class=\\\"ag-panel-title-bar ag-\" + cssIdentifier + \"-panel-title-bar ag-unselectable\\\">\\n <span ref=\\\"eTitle\\\" class=\\\"ag-panel-title-bar-title ag-\" + cssIdentifier + \"-panel-title-bar-title\\\"></span>\\n <div ref=\\\"eTitleBarButtons\\\" class=\\\"ag-panel-title-bar-buttons ag-\" + cssIdentifier + \"-panel-title-bar-buttons\\\"></div>\\n </div>\\n <div ref=\\\"eContentWrapper\\\" class=\\\"ag-panel-content-wrapper ag-\" + cssIdentifier + \"-panel-content-wrapper\\\"></div>\\n </div>\";\n };\n AgPanel.prototype.postConstruct = function () {\n var _this = this;\n var _a = this.config, component = _a.component, closable = _a.closable, hideTitleBar = _a.hideTitleBar, title = _a.title, _b = _a.minWidth, minWidth = _b === void 0 ? 250 : _b, width = _a.width, _c = _a.minHeight, minHeight = _c === void 0 ? 250 : _c, height = _a.height, centered = _a.centered, popup = _a.popup, x = _a.x, y = _a.y;\n this.positionableFeature = new PositionableFeature(this.getGui(), {\n minWidth: minWidth, width: width, minHeight: minHeight, height: height, centered: centered, x: x, y: y, popup: popup,\n calculateTopBuffer: function () { return _this.positionableFeature.getHeight() - _this.getBodyHeight(); }\n });\n this.createManagedBean(this.positionableFeature);\n var eGui = this.getGui();\n if (component) {\n this.setBodyComponent(component);\n }\n if (!hideTitleBar) {\n if (title) {\n this.setTitle(title);\n }\n this.setClosable(closable != null ? closable : this.closable);\n }\n else {\n this.eTitleBar.classList.add('ag-hidden');\n }\n this.addManagedListener(this.eTitleBar, 'mousedown', function (e) {\n var eDocument = _this.gridOptionsWrapper.getDocument();\n if (eGui.contains(e.relatedTarget) ||\n eGui.contains(eDocument.activeElement) ||\n _this.eTitleBarButtons.contains(e.target)) {\n e.preventDefault();\n return;\n }\n var focusEl = _this.eContentWrapper.querySelector('button, [href], input, select, textarea, [tabindex]');\n if (focusEl) {\n focusEl.focus();\n }\n });\n if (popup && this.positionableFeature.isPositioned()) {\n return;\n }\n if (this.renderComponent) {\n this.renderComponent();\n }\n this.positionableFeature.initialisePosition();\n this.eContentWrapper.style.height = '0';\n };\n AgPanel.prototype.renderComponent = function () {\n var _this = this;\n var eGui = this.getGui();\n eGui.focus();\n this.close = function () {\n eGui.parentElement.removeChild(eGui);\n _this.destroy();\n };\n };\n AgPanel.prototype.getHeight = function () {\n return this.positionableFeature.getHeight();\n };\n AgPanel.prototype.setHeight = function (height) {\n this.positionableFeature.setHeight(height);\n };\n AgPanel.prototype.getWidth = function () {\n return this.positionableFeature.getWidth();\n };\n AgPanel.prototype.setWidth = function (width) {\n this.positionableFeature.setWidth(width);\n };\n AgPanel.prototype.setClosable = function (closable) {\n if (closable !== this.closable) {\n this.closable = closable;\n }\n if (closable) {\n var closeButtonComp = this.closeButtonComp = new Component(AgPanel.CLOSE_BTN_TEMPLATE);\n this.getContext().createBean(closeButtonComp);\n var eGui = closeButtonComp.getGui();\n var child = createIconNoSpan('close', this.gridOptionsWrapper);\n child.classList.add('ag-panel-title-bar-button-icon');\n eGui.appendChild(child);\n this.addTitleBarButton(closeButtonComp);\n closeButtonComp.addManagedListener(eGui, 'click', this.onBtClose.bind(this));\n }\n else if (this.closeButtonComp) {\n var eGui = this.closeButtonComp.getGui();\n eGui.parentElement.removeChild(eGui);\n this.closeButtonComp = this.destroyBean(this.closeButtonComp);\n }\n };\n AgPanel.prototype.setBodyComponent = function (bodyComponent) {\n bodyComponent.setParentComponent(this);\n this.eContentWrapper.appendChild(bodyComponent.getGui());\n };\n AgPanel.prototype.addTitleBarButton = function (button, position) {\n var eTitleBarButtons = this.eTitleBarButtons;\n var buttons = eTitleBarButtons.children;\n var len = buttons.length;\n if (position == null) {\n position = len;\n }\n position = Math.max(0, Math.min(position, len));\n button.addCssClass('ag-panel-title-bar-button');\n var eGui = button.getGui();\n if (position === 0) {\n eTitleBarButtons.insertAdjacentElement('afterbegin', eGui);\n }\n else if (position === len) {\n eTitleBarButtons.insertAdjacentElement('beforeend', eGui);\n }\n else {\n buttons[position - 1].insertAdjacentElement('afterend', eGui);\n }\n button.setParentComponent(this);\n };\n AgPanel.prototype.getBodyHeight = function () {\n return getInnerHeight(this.eContentWrapper);\n };\n AgPanel.prototype.getBodyWidth = function () {\n return getInnerWidth(this.eContentWrapper);\n };\n AgPanel.prototype.setTitle = function (title) {\n this.eTitle.innerText = title;\n };\n // called when user hits the 'x' in the top right\n AgPanel.prototype.onBtClose = function () {\n this.close();\n };\n AgPanel.prototype.destroy = function () {\n if (this.closeButtonComp) {\n this.closeButtonComp = this.destroyBean(this.closeButtonComp);\n }\n var eGui = this.getGui();\n if (eGui && eGui.offsetParent) {\n this.close();\n }\n _super.prototype.destroy.call(this);\n };\n AgPanel.CLOSE_BTN_TEMPLATE = \"<div class=\\\"ag-button\\\"></div>\";\n __decorate$W([\n RefSelector('eContentWrapper')\n ], AgPanel.prototype, \"eContentWrapper\", void 0);\n __decorate$W([\n RefSelector('eTitleBar')\n ], AgPanel.prototype, \"eTitleBar\", void 0);\n __decorate$W([\n RefSelector('eTitleBarButtons')\n ], AgPanel.prototype, \"eTitleBarButtons\", void 0);\n __decorate$W([\n RefSelector('eTitle')\n ], AgPanel.prototype, \"eTitle\", void 0);\n __decorate$W([\n PostConstruct\n ], AgPanel.prototype, \"postConstruct\", null);\n return AgPanel;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$V = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$2 = (undefined && undefined.__assign) || function () {\n __assign$2 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$2.apply(this, arguments);\n};\nvar __decorate$V = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgDialog = /** @class */ (function (_super) {\n __extends$V(AgDialog, _super);\n function AgDialog(config) {\n var _this = _super.call(this, __assign$2(__assign$2({}, config), { popup: true })) || this;\n _this.isMaximizable = false;\n _this.isMaximized = false;\n _this.maximizeListeners = [];\n _this.resizeListenerDestroy = null;\n _this.lastPosition = {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n return _this;\n }\n AgDialog.prototype.postConstruct = function () {\n var _this = this;\n var eGui = this.getGui();\n var _a = this.config, movable = _a.movable, resizable = _a.resizable, maximizable = _a.maximizable;\n this.addCssClass('ag-dialog');\n _super.prototype.postConstruct.call(this);\n this.addManagedListener(eGui, 'focusin', function (e) {\n if (eGui.contains(e.relatedTarget)) {\n return;\n }\n _this.popupService.bringPopupToFront(eGui);\n });\n if (movable) {\n this.setMovable(movable);\n }\n if (maximizable) {\n this.setMaximizable(maximizable);\n }\n if (resizable) {\n this.setResizable(resizable);\n }\n };\n AgDialog.prototype.renderComponent = function () {\n var eGui = this.getGui();\n var _a = this.config, alwaysOnTop = _a.alwaysOnTop, modal = _a.modal, title = _a.title;\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var addPopupRes = this.popupService.addPopup({\n modal: modal,\n eChild: eGui,\n closeOnEsc: true,\n closedCallback: this.destroy.bind(this),\n alwaysOnTop: alwaysOnTop,\n ariaLabel: title || translate('ariaLabelDialog', 'Dialog')\n });\n if (addPopupRes) {\n this.close = addPopupRes.hideFunc;\n }\n };\n AgDialog.prototype.toggleMaximize = function () {\n var position = this.positionableFeature.getPosition();\n if (this.isMaximized) {\n var _a = this.lastPosition, x = _a.x, y = _a.y, width = _a.width, height = _a.height;\n this.setWidth(width);\n this.setHeight(height);\n this.positionableFeature.offsetElement(x, y);\n }\n else {\n this.lastPosition.width = this.getWidth();\n this.lastPosition.height = this.getHeight();\n this.lastPosition.x = position.x;\n this.lastPosition.y = position.y;\n this.positionableFeature.offsetElement(0, 0);\n this.setHeight('100%');\n this.setWidth('100%');\n }\n this.isMaximized = !this.isMaximized;\n this.refreshMaximizeIcon();\n };\n AgDialog.prototype.refreshMaximizeIcon = function () {\n setDisplayed(this.maximizeIcon, !this.isMaximized);\n setDisplayed(this.minimizeIcon, this.isMaximized);\n };\n AgDialog.prototype.clearMaximizebleListeners = function () {\n if (this.maximizeListeners.length) {\n this.maximizeListeners.forEach(function (destroyListener) { return destroyListener(); });\n this.maximizeListeners.length = 0;\n }\n if (this.resizeListenerDestroy) {\n this.resizeListenerDestroy();\n this.resizeListenerDestroy = null;\n }\n };\n AgDialog.prototype.destroy = function () {\n this.maximizeButtonComp = this.destroyBean(this.maximizeButtonComp);\n this.clearMaximizebleListeners();\n _super.prototype.destroy.call(this);\n };\n AgDialog.prototype.setResizable = function (resizable) {\n this.positionableFeature.setResizable(resizable);\n };\n AgDialog.prototype.setMovable = function (movable) {\n this.positionableFeature.setMovable(movable, this.eTitleBar);\n };\n AgDialog.prototype.setMaximizable = function (maximizable) {\n var _this = this;\n if (!maximizable) {\n this.clearMaximizebleListeners();\n if (this.maximizeButtonComp) {\n this.destroyBean(this.maximizeButtonComp);\n this.maximizeButtonComp = this.maximizeIcon = this.minimizeIcon = undefined;\n }\n return;\n }\n var eTitleBar = this.eTitleBar;\n if (!eTitleBar || maximizable === this.isMaximizable) {\n return;\n }\n var maximizeButtonComp = this.maximizeButtonComp =\n this.createBean(new Component(/* html */ \"<div class=\\\"ag-dialog-button\\\"></span>\"));\n var eGui = maximizeButtonComp.getGui();\n eGui.appendChild(this.maximizeIcon = createIconNoSpan('maximize', this.gridOptionsWrapper));\n this.maximizeIcon.classList.add('ag-panel-title-bar-button-icon');\n eGui.appendChild(this.minimizeIcon = createIconNoSpan('minimize', this.gridOptionsWrapper));\n this.minimizeIcon.classList.add('ag-panel-title-bar-button-icon', 'ag-hidden');\n maximizeButtonComp.addManagedListener(eGui, 'click', this.toggleMaximize.bind(this));\n this.addTitleBarButton(maximizeButtonComp, 0);\n this.maximizeListeners.push(this.addManagedListener(eTitleBar, 'dblclick', this.toggleMaximize.bind(this)));\n this.resizeListenerDestroy = this.addManagedListener(this, 'resize', function () {\n _this.isMaximized = false;\n _this.refreshMaximizeIcon();\n });\n };\n __decorate$V([\n Autowired('popupService')\n ], AgDialog.prototype, \"popupService\", void 0);\n return AgDialog;\n}(AgPanel));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$U = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar AgColorPicker = /** @class */ (function (_super) {\n __extends$U(AgColorPicker, _super);\n function AgColorPicker(config) {\n var _this = _super.call(this, config, 'ag-color-picker', 'colorPicker') || this;\n if (config && config.color) {\n _this.value = config.color;\n }\n return _this;\n }\n AgColorPicker.prototype.postConstruct = function () {\n _super.prototype.postConstruct.call(this);\n if (this.value) {\n this.setValue(this.value);\n }\n };\n AgColorPicker.prototype.showPicker = function () {\n var _this = this;\n var eGuiRect = this.getGui().getBoundingClientRect();\n var colorDialog = this.createBean(new AgDialog({\n closable: false,\n modal: true,\n hideTitleBar: true,\n minWidth: 190,\n width: 190,\n height: 250,\n x: eGuiRect.right - 190,\n y: eGuiRect.top - 250\n }));\n this.isPickerDisplayed = true;\n colorDialog.addCssClass('ag-color-dialog');\n setAriaExpanded(this.eWrapper, true);\n var colorPanel = this.createBean(new AgColorPanel({ picker: this }));\n colorPanel.addDestroyFunc(function () {\n if (colorDialog.isAlive()) {\n _this.destroyBean(colorDialog);\n }\n });\n colorDialog.setParentComponent(this);\n colorDialog.setBodyComponent(colorPanel);\n colorPanel.setValue(this.getValue());\n colorDialog.addDestroyFunc(function () {\n // here we check if the picker was already being\n // destroyed to avoid a stack overflow\n if (!_this.isDestroyingPicker) {\n _this.isDestroyingPicker = true;\n if (colorPanel.isAlive()) {\n _this.destroyBean(colorPanel);\n }\n }\n else {\n _this.isDestroyingPicker = false;\n }\n if (_this.isAlive()) {\n setAriaExpanded(_this.eWrapper, false);\n _this.getFocusableElement().focus();\n }\n _this.isPickerDisplayed = false;\n });\n return colorDialog;\n };\n AgColorPicker.prototype.setValue = function (color) {\n if (this.value === color) {\n return this;\n }\n this.eDisplayField.style.backgroundColor = color;\n return _super.prototype.setValue.call(this, color);\n };\n AgColorPicker.prototype.getValue = function () {\n return this.value;\n };\n return AgColorPicker;\n}(AgPickerField));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$T = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$U = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgGroupComponent = /** @class */ (function (_super) {\n __extends$T(AgGroupComponent, _super);\n function AgGroupComponent(params) {\n if (params === void 0) { params = {}; }\n var _this = _super.call(this, AgGroupComponent.getTemplate(params)) || this;\n _this.suppressEnabledCheckbox = true;\n _this.suppressOpenCloseIcons = false;\n var title = params.title, enabled = params.enabled, items = params.items, suppressEnabledCheckbox = params.suppressEnabledCheckbox, suppressOpenCloseIcons = params.suppressOpenCloseIcons;\n _this.title = title;\n _this.cssIdentifier = params.cssIdentifier || 'default';\n _this.enabled = enabled != null ? enabled : true;\n _this.items = items || [];\n _this.alignItems = params.alignItems || 'center';\n if (suppressEnabledCheckbox != null) {\n _this.suppressEnabledCheckbox = suppressEnabledCheckbox;\n }\n if (suppressOpenCloseIcons != null) {\n _this.suppressOpenCloseIcons = suppressOpenCloseIcons;\n }\n return _this;\n }\n AgGroupComponent.getTemplate = function (params) {\n var cssIdentifier = params.cssIdentifier || 'default';\n var direction = params.direction || 'vertical';\n return /* html */ \"<div class=\\\"ag-group ag-\" + cssIdentifier + \"-group\\\" role=\\\"presentation\\\">\\n <div class=\\\"ag-group-title-bar ag-\" + cssIdentifier + \"-group-title-bar ag-unselectable\\\" ref=\\\"eTitleBar\\\" role=\\\"button\\\">\\n <span class=\\\"ag-group-title-bar-icon ag-\" + cssIdentifier + \"-group-title-bar-icon\\\" ref=\\\"eGroupOpenedIcon\\\" role=\\\"presentation\\\"></span>\\n <span class=\\\"ag-group-title-bar-icon ag-\" + cssIdentifier + \"-group-title-bar-icon\\\" ref=\\\"eGroupClosedIcon\\\" role=\\\"presentation\\\"></span>\\n <span ref=\\\"eTitle\\\" class=\\\"ag-group-title ag-\" + cssIdentifier + \"-group-title\\\"></span>\\n </div>\\n <div ref=\\\"eToolbar\\\" class=\\\"ag-group-toolbar ag-\" + cssIdentifier + \"-group-toolbar\\\">\\n <ag-checkbox ref=\\\"cbGroupEnabled\\\"></ag-checkbox>\\n </div>\\n <div ref=\\\"eContainer\\\" class=\\\"ag-group-container ag-group-container-\" + direction + \" ag-\" + cssIdentifier + \"-group-container\\\"></div>\\n </div>\";\n };\n AgGroupComponent.prototype.postConstruct = function () {\n if (this.items.length) {\n var initialItems = this.items;\n this.items = [];\n this.addItems(initialItems);\n }\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n this.cbGroupEnabled.setLabel(localeTextFunc('enabled', 'Enabled'));\n if (this.title) {\n this.setTitle(this.title);\n }\n if (this.enabled) {\n this.setEnabled(this.enabled);\n }\n this.setAlignItems(this.alignItems);\n this.hideEnabledCheckbox(this.suppressEnabledCheckbox);\n this.hideOpenCloseIcons(this.suppressOpenCloseIcons);\n this.setupExpandContract();\n this.refreshAriaStatus();\n this.refreshChildDisplay();\n };\n AgGroupComponent.prototype.setupExpandContract = function () {\n var _this = this;\n this.eGroupClosedIcon.appendChild(createIcon('columnSelectClosed', this.gridOptionsWrapper, null));\n this.eGroupOpenedIcon.appendChild(createIcon('columnSelectOpen', this.gridOptionsWrapper, null));\n this.addManagedListener(this.eTitleBar, 'click', function () { return _this.toggleGroupExpand(); });\n this.addManagedListener(this.eTitleBar, 'keydown', function (e) {\n switch (e.key) {\n case KeyCode.ENTER:\n case KeyCode.SPACE:\n e.preventDefault();\n _this.toggleGroupExpand();\n break;\n case KeyCode.RIGHT:\n case KeyCode.LEFT:\n e.preventDefault();\n _this.toggleGroupExpand(e.key === KeyCode.RIGHT);\n break;\n }\n });\n };\n AgGroupComponent.prototype.refreshAriaStatus = function () {\n if (!this.suppressOpenCloseIcons) {\n setAriaExpanded(this.eTitleBar, this.expanded);\n }\n };\n AgGroupComponent.prototype.refreshChildDisplay = function () {\n var showIcon = !this.suppressOpenCloseIcons;\n setDisplayed(this.eToolbar, this.expanded && !this.suppressEnabledCheckbox);\n setDisplayed(this.eGroupOpenedIcon, showIcon && this.expanded);\n setDisplayed(this.eGroupClosedIcon, showIcon && !this.expanded);\n };\n AgGroupComponent.prototype.isExpanded = function () {\n return this.expanded;\n };\n AgGroupComponent.prototype.setAlignItems = function (alignment) {\n if (this.alignItems !== alignment) {\n this.removeCssClass(\"ag-group-item-alignment-\" + this.alignItems);\n }\n this.alignItems = alignment;\n var newCls = \"ag-group-item-alignment-\" + this.alignItems;\n this.addCssClass(newCls);\n return this;\n };\n AgGroupComponent.prototype.toggleGroupExpand = function (expanded) {\n if (this.suppressOpenCloseIcons) {\n this.expanded = true;\n this.refreshChildDisplay();\n setDisplayed(this.eContainer, true);\n return this;\n }\n expanded = expanded != null ? expanded : !this.expanded;\n if (this.expanded === expanded) {\n return this;\n }\n this.expanded = expanded;\n this.refreshAriaStatus();\n this.refreshChildDisplay();\n setDisplayed(this.eContainer, expanded);\n this.dispatchEvent({ type: this.expanded ? AgGroupComponent.EVENT_EXPANDED : AgGroupComponent.EVENT_COLLAPSED });\n return this;\n };\n AgGroupComponent.prototype.addItems = function (items) {\n var _this = this;\n items.forEach(function (item) { return _this.addItem(item); });\n };\n AgGroupComponent.prototype.addItem = function (item) {\n var container = this.eContainer;\n var el = item instanceof Component ? item.getGui() : item;\n el.classList.add('ag-group-item', \"ag-\" + this.cssIdentifier + \"-group-item\");\n container.appendChild(el);\n this.items.push(el);\n };\n AgGroupComponent.prototype.hideItem = function (hide, index) {\n var itemToHide = this.items[index];\n itemToHide.classList.toggle('ag-hidden', hide);\n };\n AgGroupComponent.prototype.setTitle = function (title) {\n this.eTitle.innerText = title;\n return this;\n };\n AgGroupComponent.prototype.addCssClassToTitleBar = function (cssClass) {\n this.eTitleBar.classList.add(cssClass);\n };\n AgGroupComponent.prototype.setEnabled = function (enabled, skipToggle) {\n this.enabled = enabled;\n this.refreshDisabledStyles();\n this.toggleGroupExpand(enabled);\n if (!skipToggle) {\n this.cbGroupEnabled.setValue(enabled);\n }\n return this;\n };\n AgGroupComponent.prototype.isEnabled = function () {\n return this.enabled;\n };\n AgGroupComponent.prototype.onEnableChange = function (callbackFn) {\n var _this = this;\n this.cbGroupEnabled.onValueChange(function (newSelection) {\n _this.setEnabled(newSelection, true);\n callbackFn(newSelection);\n });\n return this;\n };\n AgGroupComponent.prototype.hideEnabledCheckbox = function (hide) {\n this.suppressEnabledCheckbox = hide;\n this.refreshChildDisplay();\n this.refreshDisabledStyles();\n return this;\n };\n AgGroupComponent.prototype.hideOpenCloseIcons = function (hide) {\n this.suppressOpenCloseIcons = hide;\n if (hide) {\n this.toggleGroupExpand(true);\n }\n return this;\n };\n AgGroupComponent.prototype.refreshDisabledStyles = function () {\n this.addOrRemoveCssClass('ag-disabled', !this.enabled);\n if (this.suppressEnabledCheckbox && !this.enabled) {\n this.eTitleBar.classList.add('ag-disabled-group-title-bar');\n this.eTitleBar.removeAttribute('tabindex');\n }\n else {\n this.eTitleBar.classList.remove('ag-disabled-group-title-bar');\n this.eTitleBar.setAttribute('tabindex', '0');\n }\n this.eContainer.classList.toggle('ag-disabled-group-container', !this.enabled);\n };\n AgGroupComponent.EVENT_EXPANDED = 'expanded';\n AgGroupComponent.EVENT_COLLAPSED = 'collapsed';\n __decorate$U([\n RefSelector('eTitleBar')\n ], AgGroupComponent.prototype, \"eTitleBar\", void 0);\n __decorate$U([\n RefSelector('eGroupOpenedIcon')\n ], AgGroupComponent.prototype, \"eGroupOpenedIcon\", void 0);\n __decorate$U([\n RefSelector('eGroupClosedIcon')\n ], AgGroupComponent.prototype, \"eGroupClosedIcon\", void 0);\n __decorate$U([\n RefSelector('eToolbar')\n ], AgGroupComponent.prototype, \"eToolbar\", void 0);\n __decorate$U([\n RefSelector('cbGroupEnabled')\n ], AgGroupComponent.prototype, \"cbGroupEnabled\", void 0);\n __decorate$U([\n RefSelector('eTitle')\n ], AgGroupComponent.prototype, \"eTitle\", void 0);\n __decorate$U([\n RefSelector('eContainer')\n ], AgGroupComponent.prototype, \"eContainer\", void 0);\n __decorate$U([\n PostConstruct\n ], AgGroupComponent.prototype, \"postConstruct\", null);\n return AgGroupComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$S = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$T = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TabGuardCtrl = /** @class */ (function (_super) {\n __extends$S(TabGuardCtrl, _super);\n function TabGuardCtrl(params) {\n var _this = _super.call(this) || this;\n _this.skipTabGuardFocus = false;\n var comp = params.comp, eTopGuard = params.eTopGuard, eBottomGuard = params.eBottomGuard, focusInnerElement = params.focusInnerElement, onFocusIn = params.onFocusIn, onFocusOut = params.onFocusOut, shouldStopEventPropagation = params.shouldStopEventPropagation, onTabKeyDown = params.onTabKeyDown, handleKeyDown = params.handleKeyDown, eFocusableElement = params.eFocusableElement;\n _this.comp = comp;\n _this.eTopGuard = eTopGuard;\n _this.eBottomGuard = eBottomGuard;\n _this.providedFocusInnerElement = focusInnerElement;\n _this.eFocusableElement = eFocusableElement;\n _this.providedFocusIn = onFocusIn;\n _this.providedFocusOut = onFocusOut;\n _this.providedShouldStopEventPropagation = shouldStopEventPropagation;\n _this.providedOnTabKeyDown = onTabKeyDown;\n _this.providedHandleKeyDown = handleKeyDown;\n return _this;\n }\n TabGuardCtrl.prototype.postConstruct = function () {\n var _this = this;\n this.createManagedBean(new ManagedFocusFeature(this.eFocusableElement, {\n shouldStopEventPropagation: function () { return _this.shouldStopEventPropagation(); },\n onTabKeyDown: function (e) { return _this.onTabKeyDown(e); },\n handleKeyDown: function (e) { return _this.handleKeyDown(e); },\n onFocusIn: function (e) { return _this.onFocusIn(e); },\n onFocusOut: function (e) { return _this.onFocusOut(e); }\n }));\n this.activateTabGuards();\n [this.eTopGuard, this.eBottomGuard].forEach(function (guard) { return _this.addManagedListener(guard, 'focus', _this.onFocus.bind(_this)); });\n };\n TabGuardCtrl.prototype.handleKeyDown = function (e) {\n if (this.providedHandleKeyDown) {\n this.providedHandleKeyDown(e);\n }\n };\n TabGuardCtrl.prototype.tabGuardsAreActive = function () {\n return !!this.eTopGuard && this.eTopGuard.hasAttribute('tabIndex');\n };\n TabGuardCtrl.prototype.shouldStopEventPropagation = function () {\n if (this.providedShouldStopEventPropagation) {\n return this.providedShouldStopEventPropagation();\n }\n return false;\n };\n TabGuardCtrl.prototype.activateTabGuards = function () {\n this.comp.setTabIndex(this.getGridTabIndex());\n };\n TabGuardCtrl.prototype.deactivateTabGuards = function () {\n this.comp.setTabIndex();\n };\n TabGuardCtrl.prototype.onFocus = function (e) {\n if (this.skipTabGuardFocus) {\n this.skipTabGuardFocus = false;\n return;\n }\n var fromBottom = e.target === this.eBottomGuard;\n if (this.providedFocusInnerElement) {\n this.providedFocusInnerElement(fromBottom);\n }\n else {\n this.focusInnerElement(fromBottom);\n }\n };\n TabGuardCtrl.prototype.onFocusIn = function (e) {\n if (this.providedFocusIn && this.providedFocusIn(e)) {\n return;\n }\n this.deactivateTabGuards();\n };\n TabGuardCtrl.prototype.onFocusOut = function (e) {\n if (this.providedFocusOut && this.providedFocusOut(e)) {\n return;\n }\n if (!this.eFocusableElement.contains(e.relatedTarget)) {\n this.activateTabGuards();\n }\n };\n TabGuardCtrl.prototype.onTabKeyDown = function (e) {\n var _this = this;\n if (this.providedOnTabKeyDown) {\n this.providedOnTabKeyDown(e);\n return;\n }\n if (e.defaultPrevented) {\n return;\n }\n var tabGuardsAreActive = this.tabGuardsAreActive();\n if (tabGuardsAreActive) {\n this.deactivateTabGuards();\n }\n var nextRoot = this.getNextFocusableElement(e.shiftKey);\n if (tabGuardsAreActive) {\n // ensure the tab guards are only re-instated once the event has finished processing, to avoid the browser\n // tabbing to the tab guard from inside the component\n setTimeout(function () { return _this.activateTabGuards(); }, 0);\n }\n if (!nextRoot) {\n return;\n }\n nextRoot.focus();\n e.preventDefault();\n };\n TabGuardCtrl.prototype.getGridTabIndex = function () {\n return this.gridOptionsWrapper.getGridTabIndex();\n };\n TabGuardCtrl.prototype.focusInnerElement = function (fromBottom) {\n if (fromBottom === void 0) { fromBottom = false; }\n var focusable = this.focusService.findFocusableElements(this.eFocusableElement);\n if (this.tabGuardsAreActive()) {\n // remove tab guards from this component from list of focusable elements\n focusable.splice(0, 1);\n focusable.splice(focusable.length - 1, 1);\n }\n if (!focusable.length) {\n return;\n }\n focusable[fromBottom ? focusable.length - 1 : 0].focus();\n };\n TabGuardCtrl.prototype.getNextFocusableElement = function (backwards) {\n return this.focusService.findNextFocusableElement(this.eFocusableElement, false, backwards);\n };\n TabGuardCtrl.prototype.forceFocusOutOfContainer = function (up) {\n if (up === void 0) { up = false; }\n var tabGuardToFocus = up ? this.eTopGuard : this.eBottomGuard;\n this.activateTabGuards();\n this.skipTabGuardFocus = true;\n tabGuardToFocus.focus();\n };\n __decorate$T([\n Autowired('focusService')\n ], TabGuardCtrl.prototype, \"focusService\", void 0);\n __decorate$T([\n PostConstruct\n ], TabGuardCtrl.prototype, \"postConstruct\", null);\n return TabGuardCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$R = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __read$8 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$7 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$8(arguments[i]));\n return ar;\n};\nvar TabGuardComp = /** @class */ (function (_super) {\n __extends$R(TabGuardComp, _super);\n function TabGuardComp() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n TabGuardComp.prototype.initialiseTabGuard = function (params) {\n this.eTopGuard = this.createTabGuard('top');\n this.eBottomGuard = this.createTabGuard('bottom');\n this.eFocusableElement = this.getFocusableElement();\n var tabGuards = [this.eTopGuard, this.eBottomGuard];\n var compProxy = {\n setTabIndex: function (tabIndex) {\n tabGuards.forEach(function (tabGuard) { return tabIndex != null ? tabGuard.setAttribute('tabIndex', tabIndex) : tabGuard.removeAttribute('tabIndex'); });\n }\n };\n this.addTabGuards(this.eTopGuard, this.eBottomGuard);\n this.tabGuardCtrl = this.createManagedBean(new TabGuardCtrl({\n comp: compProxy,\n eTopGuard: this.eTopGuard,\n eBottomGuard: this.eBottomGuard,\n eFocusableElement: this.eFocusableElement,\n onFocusIn: params.onFocusIn,\n onFocusOut: params.onFocusOut,\n focusInnerElement: params.focusInnerElement,\n handleKeyDown: params.handleKeyDown,\n onTabKeyDown: params.onTabKeyDown,\n shouldStopEventPropagation: params.shouldStopEventPropagation\n }));\n };\n TabGuardComp.prototype.createTabGuard = function (side) {\n var tabGuard = document.createElement('div');\n tabGuard.classList.add('ag-tab-guard', \"ag-tab-guard-\" + side);\n setAriaRole(tabGuard, 'presentation');\n return tabGuard;\n };\n TabGuardComp.prototype.addTabGuards = function (topTabGuard, bottomTabGuard) {\n this.eFocusableElement.insertAdjacentElement('afterbegin', topTabGuard);\n this.eFocusableElement.insertAdjacentElement('beforeend', bottomTabGuard);\n };\n TabGuardComp.prototype.removeAllChildrenExceptTabGuards = function () {\n var tabGuards = [this.eTopGuard, this.eBottomGuard];\n clearElement(this.getFocusableElement());\n this.addTabGuards.apply(this, __spread$7(tabGuards));\n };\n TabGuardComp.prototype.forceFocusOutOfContainer = function (up) {\n if (up === void 0) { up = false; }\n this.tabGuardCtrl.forceFocusOutOfContainer(up);\n };\n TabGuardComp.prototype.appendChild = function (newChild, container) {\n if (!isNodeOrElement(newChild)) {\n newChild = newChild.getGui();\n }\n var bottomTabGuard = this.eBottomGuard;\n if (bottomTabGuard) {\n bottomTabGuard.insertAdjacentElement('beforebegin', newChild);\n }\n else {\n _super.prototype.appendChild.call(this, newChild, container);\n }\n };\n return TabGuardComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$Q = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign$1 = (undefined && undefined.__assign) || function () {\n __assign$1 = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign$1.apply(this, arguments);\n};\nvar __decorate$S = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgMenuList = /** @class */ (function (_super) {\n __extends$Q(AgMenuList, _super);\n function AgMenuList(level) {\n if (level === void 0) { level = 1; }\n var _this = _super.call(this, /* html */ \"<div class=\\\"ag-menu-list\\\" role=\\\"tree\\\"></div>\") || this;\n _this.level = level;\n _this.menuItems = [];\n return _this;\n }\n AgMenuList.prototype.postConstruct = function () {\n var _this = this;\n this.initialiseTabGuard({\n onTabKeyDown: function (e) { return _this.onTabKeyDown(e); },\n handleKeyDown: function (e) { return _this.handleKeyDown(e); }\n });\n };\n AgMenuList.prototype.onTabKeyDown = function (e) {\n var parent = this.getParentComponent();\n var parentGui = parent && parent.getGui();\n var isManaged = parentGui && parentGui.classList.contains('ag-focus-managed');\n if (!isManaged) {\n e.preventDefault();\n }\n if (e.shiftKey) {\n this.closeIfIsChild(e);\n }\n };\n AgMenuList.prototype.handleKeyDown = function (e) {\n switch (e.key) {\n case KeyCode.UP:\n case KeyCode.RIGHT:\n case KeyCode.DOWN:\n case KeyCode.LEFT:\n e.preventDefault();\n this.handleNavKey(e.key);\n break;\n case KeyCode.ESCAPE:\n var topMenu = this.findTopMenu();\n if (topMenu) {\n this.focusService.focusInto(topMenu.getGui());\n }\n break;\n }\n };\n AgMenuList.prototype.clearActiveItem = function () {\n if (this.activeMenuItem) {\n this.activeMenuItem.deactivate();\n this.activeMenuItem = null;\n }\n };\n AgMenuList.prototype.addMenuItems = function (menuItems) {\n var _this = this;\n if (menuItems == null) {\n return;\n }\n menuItems.forEach(function (menuItemOrString) {\n if (menuItemOrString === 'separator') {\n _this.addSeparator();\n }\n else if (typeof menuItemOrString === 'string') {\n console.warn(\"AG Grid: unrecognised menu item \" + menuItemOrString);\n }\n else {\n _this.addItem(menuItemOrString);\n }\n });\n };\n AgMenuList.prototype.addItem = function (menuItemDef) {\n var _this = this;\n var menuItem = this.createManagedBean(new AgMenuItemComponent(__assign$1(__assign$1({}, menuItemDef), { isAnotherSubMenuOpen: function () { return _this.menuItems.some(function (m) { return m.isSubMenuOpen(); }); } })));\n menuItem.setParentComponent(this);\n setAriaLevel(menuItem.getGui(), this.level);\n this.menuItems.push(menuItem);\n this.appendChild(menuItem.getGui());\n this.addManagedListener(menuItem, AgMenuItemComponent.EVENT_MENU_ITEM_SELECTED, function (event) {\n _this.dispatchEvent(event);\n });\n this.addManagedListener(menuItem, AgMenuItemComponent.EVENT_MENU_ITEM_ACTIVATED, function (event) {\n if (_this.activeMenuItem && _this.activeMenuItem !== event.menuItem) {\n _this.activeMenuItem.deactivate();\n }\n _this.activeMenuItem = event.menuItem;\n });\n };\n AgMenuList.prototype.activateFirstItem = function () {\n var item = this.menuItems.filter(function (currentItem) { return !currentItem.isDisabled(); })[0];\n if (!item) {\n return;\n }\n item.activate();\n };\n AgMenuList.prototype.addSeparator = function () {\n var separatorHtml = /* html */ \"\\n <div class=\\\"ag-menu-separator\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"ag-menu-separator-part\\\"></div>\\n <div class=\\\"ag-menu-separator-part\\\"></div>\\n <div class=\\\"ag-menu-separator-part\\\"></div>\\n <div class=\\\"ag-menu-separator-part\\\"></div>\\n </div>\";\n this.appendChild(loadTemplate(separatorHtml));\n };\n AgMenuList.prototype.findTopMenu = function () {\n var parent = this.getParentComponent();\n if (!parent && this instanceof AgMenuList) {\n return this;\n }\n while (true) {\n var nextParent = parent && parent.getParentComponent && parent.getParentComponent();\n if (!nextParent || (!(nextParent instanceof AgMenuList || nextParent instanceof AgMenuItemComponent))) {\n break;\n }\n parent = nextParent;\n }\n return parent instanceof AgMenuList ? parent : undefined;\n };\n AgMenuList.prototype.handleNavKey = function (key) {\n switch (key) {\n case KeyCode.UP:\n case KeyCode.DOWN:\n var nextItem = this.findNextItem(key === KeyCode.UP);\n if (nextItem && nextItem !== this.activeMenuItem) {\n nextItem.activate();\n }\n return;\n }\n var left = this.gridOptionsWrapper.isEnableRtl() ? KeyCode.RIGHT : KeyCode.LEFT;\n if (key === left) {\n this.closeIfIsChild();\n }\n else {\n this.openChild();\n }\n };\n AgMenuList.prototype.closeIfIsChild = function (e) {\n var parentItem = this.getParentComponent();\n if (parentItem && parentItem instanceof AgMenuItemComponent) {\n if (e) {\n e.preventDefault();\n }\n parentItem.closeSubMenu();\n parentItem.getGui().focus();\n }\n };\n AgMenuList.prototype.openChild = function () {\n if (this.activeMenuItem) {\n this.activeMenuItem.openSubMenu(true);\n }\n };\n AgMenuList.prototype.findNextItem = function (up) {\n var items = this.menuItems.filter(function (item) { return !item.isDisabled(); });\n if (!items.length) {\n return;\n }\n if (!this.activeMenuItem) {\n return up ? last(items) : items[0];\n }\n if (up) {\n items.reverse();\n }\n var nextItem;\n var foundCurrent = false;\n for (var i = 0; i < items.length; i++) {\n var item = items[i];\n if (!foundCurrent) {\n if (item === this.activeMenuItem) {\n foundCurrent = true;\n }\n continue;\n }\n nextItem = item;\n break;\n }\n return nextItem || this.activeMenuItem;\n };\n AgMenuList.prototype.destroy = function () {\n this.clearActiveItem();\n _super.prototype.destroy.call(this);\n };\n __decorate$S([\n Autowired('focusService')\n ], AgMenuList.prototype, \"focusService\", void 0);\n __decorate$S([\n PostConstruct\n ], AgMenuList.prototype, \"postConstruct\", null);\n return AgMenuList;\n}(TabGuardComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$P = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$R = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgMenuPanel = /** @class */ (function (_super) {\n __extends$P(AgMenuPanel, _super);\n function AgMenuPanel(wrappedComponent) {\n var _this = _super.call(this) || this;\n _this.wrappedComponent = wrappedComponent;\n _this.setTemplateFromElement(wrappedComponent.getGui());\n return _this;\n }\n AgMenuPanel.prototype.postConstruct = function () {\n var _this = this;\n this.initialiseTabGuard({\n onTabKeyDown: function (e) { return _this.onTabKeyDown(e); },\n handleKeyDown: function (e) { return _this.handleKeyDown(e); }\n });\n };\n AgMenuPanel.prototype.handleKeyDown = function (e) {\n if (e.key === KeyCode.ESCAPE) {\n this.closePanel();\n }\n };\n AgMenuPanel.prototype.onTabKeyDown = function (e) {\n if (e.defaultPrevented) {\n return;\n }\n this.closePanel();\n e.preventDefault();\n };\n AgMenuPanel.prototype.closePanel = function () {\n var menuItem = this.parentComponent;\n menuItem.closeSubMenu();\n setTimeout(function () { return menuItem.getGui().focus(); }, 0);\n };\n __decorate$R([\n PostConstruct\n ], AgMenuPanel.prototype, \"postConstruct\", null);\n return AgMenuPanel;\n}(TabGuardComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$O = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$Q = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgMenuItemComponent = /** @class */ (function (_super) {\n __extends$O(AgMenuItemComponent, _super);\n function AgMenuItemComponent(params) {\n var _this = _super.call(this) || this;\n _this.params = params;\n _this.isActive = false;\n _this.subMenuIsOpen = false;\n _this.setTemplate(/* html */ \"<div class=\\\"\" + _this.getClassName() + \"\\\" tabindex=\\\"-1\\\" role=\\\"treeitem\\\"></div>\");\n return _this;\n }\n AgMenuItemComponent.prototype.init = function () {\n var _this = this;\n this.addIcon();\n this.addName();\n this.addShortcut();\n this.addSubMenu();\n this.addTooltip();\n var eGui = this.getGui();\n if (this.params.disabled) {\n this.addCssClass(this.getClassName('disabled'));\n setAriaDisabled(eGui, true);\n }\n else {\n this.addGuiEventListener('click', function (e) { return _this.onItemSelected(e); });\n this.addGuiEventListener('keydown', function (e) {\n if (e.key === KeyCode.ENTER || e.key === KeyCode.SPACE) {\n e.preventDefault();\n _this.onItemSelected(e);\n }\n });\n this.addGuiEventListener('mousedown', function (e) {\n // Prevent event bubbling to other event handlers such as PopupService triggering\n // premature closing of any open sub-menu popup.\n e.stopPropagation();\n e.preventDefault();\n });\n this.addGuiEventListener('mouseenter', function () { return _this.onMouseEnter(); });\n this.addGuiEventListener('mouseleave', function () { return _this.onMouseLeave(); });\n }\n if (this.params.cssClasses) {\n this.params.cssClasses.forEach(function (it) { return _this.addCssClass(it); });\n }\n };\n AgMenuItemComponent.prototype.isDisabled = function () {\n return !!this.params.disabled;\n };\n AgMenuItemComponent.prototype.openSubMenu = function (activateFirstItem) {\n var _this = this;\n if (activateFirstItem === void 0) { activateFirstItem = false; }\n this.closeSubMenu();\n if (!this.params.subMenu) {\n return;\n }\n var ePopup = loadTemplate(/* html */ \"<div class=\\\"ag-menu\\\" role=\\\"presentation\\\"></div>\");\n var destroySubMenu;\n if (this.params.subMenu instanceof Array) {\n var currentLevel = getAriaLevel(this.getGui());\n var nextLevel = isNaN(currentLevel) ? 1 : (currentLevel + 1);\n var childMenu_1 = this.createBean(new AgMenuList(nextLevel));\n childMenu_1.setParentComponent(this);\n childMenu_1.addMenuItems(this.params.subMenu);\n ePopup.appendChild(childMenu_1.getGui());\n // bubble menu item selected events\n this.addManagedListener(childMenu_1, AgMenuItemComponent.EVENT_MENU_ITEM_SELECTED, function (e) { return _this.dispatchEvent(e); });\n childMenu_1.addGuiEventListener('mouseenter', function () { return _this.cancelDeactivate(); });\n destroySubMenu = function () { return _this.destroyBean(childMenu_1); };\n if (activateFirstItem) {\n setTimeout(function () { return childMenu_1.activateFirstItem(); }, 0);\n }\n }\n else {\n var subMenu_1 = this.params.subMenu;\n var menuPanel = this.createBean(new AgMenuPanel(subMenu_1));\n menuPanel.setParentComponent(this);\n var subMenuGui_1 = menuPanel.getGui();\n var mouseEvent_1 = 'mouseenter';\n var mouseEnterListener_1 = function () { return _this.cancelDeactivate(); };\n subMenuGui_1.addEventListener(mouseEvent_1, mouseEnterListener_1);\n destroySubMenu = function () { return subMenuGui_1.removeEventListener(mouseEvent_1, mouseEnterListener_1); };\n ePopup.appendChild(subMenuGui_1);\n if (subMenu_1.afterGuiAttached) {\n setTimeout(function () { return subMenu_1.afterGuiAttached(); }, 0);\n }\n }\n var eGui = this.getGui();\n var positionCallback = this.popupService.positionPopupForMenu.bind(this.popupService, { eventSource: eGui, ePopup: ePopup });\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var addPopupRes = this.popupService.addPopup({\n modal: true,\n eChild: ePopup,\n positionCallback: positionCallback,\n anchorToElement: eGui,\n ariaLabel: translate('ariaLabelSubMenu', 'SubMenu')\n });\n this.subMenuIsOpen = true;\n setAriaExpanded(eGui, true);\n this.hideSubMenu = function () {\n if (addPopupRes) {\n addPopupRes.hideFunc();\n }\n _this.subMenuIsOpen = false;\n setAriaExpanded(eGui, false);\n destroySubMenu();\n };\n };\n AgMenuItemComponent.prototype.closeSubMenu = function () {\n if (!this.hideSubMenu) {\n return;\n }\n this.hideSubMenu();\n this.hideSubMenu = null;\n setAriaExpanded(this.getGui(), false);\n };\n AgMenuItemComponent.prototype.isSubMenuOpen = function () {\n return this.subMenuIsOpen;\n };\n AgMenuItemComponent.prototype.activate = function (openSubMenu) {\n var _this = this;\n this.cancelActivate();\n if (this.params.disabled) {\n return;\n }\n this.isActive = true;\n this.addCssClass(this.getClassName('active'));\n this.getGui().focus();\n if (openSubMenu && this.params.subMenu) {\n window.setTimeout(function () {\n if (_this.isAlive() && _this.isActive) {\n _this.openSubMenu();\n }\n }, 300);\n }\n this.onItemActivated();\n };\n AgMenuItemComponent.prototype.deactivate = function () {\n this.cancelDeactivate();\n this.removeCssClass(this.getClassName('active'));\n this.isActive = false;\n if (this.subMenuIsOpen) {\n this.hideSubMenu();\n }\n };\n AgMenuItemComponent.prototype.addIcon = function () {\n if (!this.params.checked && !this.params.icon && this.params.isCompact) {\n return;\n }\n var icon = loadTemplate(/* html */ \"<span ref=\\\"eIcon\\\" class=\\\"\" + this.getClassName('part') + \" \" + this.getClassName('icon') + \"\\\" role=\\\"presentation\\\"></span>\");\n if (this.params.checked) {\n icon.appendChild(createIconNoSpan('check', this.gridOptionsWrapper));\n }\n else if (this.params.icon) {\n if (isNodeOrElement(this.params.icon)) {\n icon.appendChild(this.params.icon);\n }\n else if (typeof this.params.icon === 'string') {\n icon.innerHTML = this.params.icon;\n }\n else {\n console.warn('AG Grid: menu item icon must be DOM node or string');\n }\n }\n this.getGui().appendChild(icon);\n };\n AgMenuItemComponent.prototype.addName = function () {\n if (!this.params.name && this.params.isCompact) {\n return;\n }\n var name = loadTemplate(/* html */ \"<span ref=\\\"eName\\\" class=\\\"\" + this.getClassName('part') + \" \" + this.getClassName('text') + \"\\\">\" + (this.params.name || '') + \"</span>\");\n this.getGui().appendChild(name);\n };\n AgMenuItemComponent.prototype.addTooltip = function () {\n if (!this.params.tooltip) {\n return;\n }\n this.tooltip = this.params.tooltip;\n if (this.gridOptionsWrapper.isEnableBrowserTooltips()) {\n this.getGui().setAttribute('title', this.tooltip);\n }\n else {\n this.createManagedBean(new CustomTooltipFeature(this));\n }\n };\n AgMenuItemComponent.prototype.getTooltipParams = function () {\n return {\n location: 'menu',\n value: this.tooltip\n };\n };\n AgMenuItemComponent.prototype.addShortcut = function () {\n if (!this.params.shortcut && this.params.isCompact) {\n return;\n }\n var shortcut = loadTemplate(/* html */ \"<span ref=\\\"eShortcut\\\" class=\\\"\" + this.getClassName('part') + \" \" + this.getClassName('shortcut') + \"\\\">\" + (this.params.shortcut || '') + \"</span>\");\n this.getGui().appendChild(shortcut);\n };\n AgMenuItemComponent.prototype.addSubMenu = function () {\n if (!this.params.subMenu && this.params.isCompact) {\n return;\n }\n var pointer = loadTemplate(/* html */ \"<span ref=\\\"ePopupPointer\\\" class=\\\"\" + this.getClassName('part') + \" \" + this.getClassName('popup-pointer') + \"\\\"></span>\");\n var eGui = this.getGui();\n if (this.params.subMenu) {\n var iconName = this.gridOptionsWrapper.isEnableRtl() ? 'smallLeft' : 'smallRight';\n setAriaExpanded(eGui, false);\n pointer.appendChild(createIconNoSpan(iconName, this.gridOptionsWrapper));\n }\n eGui.appendChild(pointer);\n };\n AgMenuItemComponent.prototype.onItemSelected = function (event) {\n if (this.params.action) {\n this.params.action();\n }\n else {\n this.openSubMenu(event && event.type === 'keydown');\n }\n if (this.params.subMenu && !this.params.action) {\n return;\n }\n var e = {\n type: AgMenuItemComponent.EVENT_MENU_ITEM_SELECTED,\n action: this.params.action,\n checked: this.params.checked,\n cssClasses: this.params.cssClasses,\n disabled: this.params.disabled,\n icon: this.params.icon,\n name: this.params.name,\n shortcut: this.params.shortcut,\n subMenu: this.params.subMenu,\n tooltip: this.params.tooltip,\n event: event\n };\n this.dispatchEvent(e);\n };\n AgMenuItemComponent.prototype.onItemActivated = function () {\n var event = {\n type: AgMenuItemComponent.EVENT_MENU_ITEM_ACTIVATED,\n menuItem: this,\n };\n this.dispatchEvent(event);\n };\n AgMenuItemComponent.prototype.cancelActivate = function () {\n if (this.activateTimeoutId) {\n window.clearTimeout(this.activateTimeoutId);\n this.activateTimeoutId = 0;\n }\n };\n AgMenuItemComponent.prototype.cancelDeactivate = function () {\n if (this.deactivateTimeoutId) {\n window.clearTimeout(this.deactivateTimeoutId);\n this.deactivateTimeoutId = 0;\n }\n };\n AgMenuItemComponent.prototype.onMouseEnter = function () {\n var _this = this;\n this.cancelDeactivate();\n if (this.params.isAnotherSubMenuOpen()) {\n // wait to see if the user enters the open sub-menu\n this.activateTimeoutId = window.setTimeout(function () { return _this.activate(true); }, AgMenuItemComponent.ACTIVATION_DELAY);\n }\n else {\n // activate immediately\n this.activate(true);\n }\n };\n AgMenuItemComponent.prototype.onMouseLeave = function () {\n var _this = this;\n this.cancelActivate();\n if (this.isSubMenuOpen()) {\n // wait to see if the user enters the sub-menu\n this.deactivateTimeoutId = window.setTimeout(function () { return _this.deactivate(); }, AgMenuItemComponent.ACTIVATION_DELAY);\n }\n else {\n // de-activate immediately\n this.deactivate();\n }\n };\n AgMenuItemComponent.prototype.getClassName = function (suffix) {\n var prefix = this.params.isCompact ? 'ag-compact-menu-option' : 'ag-menu-option';\n return suffix ? prefix + \"-\" + suffix : prefix;\n };\n AgMenuItemComponent.EVENT_MENU_ITEM_SELECTED = 'menuItemSelected';\n AgMenuItemComponent.EVENT_MENU_ITEM_ACTIVATED = 'menuItemActivated';\n AgMenuItemComponent.ACTIVATION_DELAY = 80;\n __decorate$Q([\n Autowired('popupService')\n ], AgMenuItemComponent.prototype, \"popupService\", void 0);\n __decorate$Q([\n PostConstruct\n ], AgMenuItemComponent.prototype, \"init\", null);\n return AgMenuItemComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$N = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$P = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$7 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$6 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$7(arguments[i]));\n return ar;\n};\nvar FocusService = /** @class */ (function (_super) {\n __extends$N(FocusService, _super);\n function FocusService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n FocusService_1 = FocusService;\n /**\n * Adds a gridCore to the list of the gridCores monitoring Keyboard Mode\n * in a specific HTMLDocument.\n *\n * @param doc {Document} - The Document containing the gridCore.\n * @param gridCore {GridComp} - The GridCore to be monitored.\n */\n FocusService.addKeyboardModeEvents = function (doc, controller) {\n var docControllers = FocusService_1.instancesMonitored.get(doc);\n if (docControllers && docControllers.length > 0) {\n if (docControllers.indexOf(controller) === -1) {\n docControllers.push(controller);\n }\n }\n else {\n FocusService_1.instancesMonitored.set(doc, [controller]);\n doc.addEventListener('keydown', FocusService_1.toggleKeyboardMode);\n doc.addEventListener('mousedown', FocusService_1.toggleKeyboardMode);\n }\n };\n /**\n * Removes a gridCore from the list of the gridCores monitoring Keyboard Mode\n * in a specific HTMLDocument.\n *\n * @param doc {Document} - The Document containing the gridCore.\n * @param gridCore {GridComp} - The GridCore to be removed.\n */\n FocusService.removeKeyboardModeEvents = function (doc, controller) {\n var docControllers = FocusService_1.instancesMonitored.get(doc);\n var newControllers = [];\n if (docControllers && docControllers.length) {\n newControllers = __spread$6(docControllers).filter(function (currentGridCore) { return currentGridCore !== controller; });\n FocusService_1.instancesMonitored.set(doc, newControllers);\n }\n if (newControllers.length === 0) {\n doc.removeEventListener('keydown', FocusService_1.toggleKeyboardMode);\n doc.removeEventListener('mousedown', FocusService_1.toggleKeyboardMode);\n }\n };\n /**\n * This method will be called by `keydown` and `mousedown` events on all Documents monitoring\n * KeyboardMode. It will then fire a KEYBOARD_FOCUS, MOUSE_FOCUS on each gridCore present in\n * the Document allowing each gridCore to maintain a state for KeyboardMode.\n *\n * @param event {KeyboardEvent | MouseEvent | TouchEvent} - The event triggered.\n */\n FocusService.toggleKeyboardMode = function (event) {\n var isKeyboardActive = FocusService_1.keyboardModeActive;\n var isKeyboardEvent = event.type === 'keydown';\n if (isKeyboardEvent) {\n // the following keys should not toggle keyboard mode.\n if (event.ctrlKey || event.metaKey || event.altKey) {\n return;\n }\n }\n if (isKeyboardActive && isKeyboardEvent || !isKeyboardActive && !isKeyboardEvent) {\n return;\n }\n FocusService_1.keyboardModeActive = isKeyboardEvent;\n var doc = event.target.ownerDocument;\n if (!doc) {\n return;\n }\n var controllersForDoc = FocusService_1.instancesMonitored.get(doc);\n if (controllersForDoc) {\n controllersForDoc.forEach(function (controller) {\n controller.dispatchEvent({ type: isKeyboardEvent ? Events.EVENT_KEYBOARD_FOCUS : Events.EVENT_MOUSE_FOCUS });\n });\n }\n };\n FocusService.prototype.init = function () {\n var _this = this;\n var clearFocusedCellListener = this.clearFocusedCell.bind(this);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, clearFocusedCellListener);\n this.addManagedListener(this.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.onColumnEverythingChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_GROUP_OPENED, clearFocusedCellListener);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, clearFocusedCellListener);\n this.ctrlsService.whenReady(function (p) {\n _this.gridCtrl = p.gridCtrl;\n var doc = _this.gridOptionsWrapper.getDocument();\n FocusService_1.addKeyboardModeEvents(doc, _this.gridCtrl);\n _this.addDestroyFunc(function () { return _this.unregisterGridCompController(_this.gridCtrl); });\n });\n };\n FocusService.prototype.unregisterGridCompController = function (gridCompController) {\n var doc = this.gridOptionsWrapper.getDocument();\n FocusService_1.removeKeyboardModeEvents(doc, gridCompController);\n };\n FocusService.prototype.onColumnEverythingChanged = function () {\n // if the columns change, check and see if this column still exists. if it does, then\n // we can keep the focused cell. if it doesn't, then we need to drop the focused cell.\n if (!this.focusedCellPosition) {\n return;\n }\n var col = this.focusedCellPosition.column;\n var colFromColumnModel = this.columnModel.getGridColumn(col.getId());\n if (col !== colFromColumnModel) {\n this.clearFocusedCell();\n }\n };\n FocusService.prototype.isKeyboardMode = function () {\n return FocusService_1.keyboardModeActive;\n };\n // we check if the browser is focusing something, and if it is, and\n // it's the cell we think is focused, then return the cell. so this\n // methods returns the cell if a) we think it has focus and b) the\n // browser thinks it has focus. this then returns nothing if we\n // first focus a cell, then second click outside the grid, as then the\n // grid cell will still be focused as far as the grid is concerned,\n // however the browser focus will have moved somewhere else.\n FocusService.prototype.getFocusCellToUseAfterRefresh = function () {\n var eDocument = this.gridOptionsWrapper.getDocument();\n if (this.gridOptionsWrapper.isSuppressFocusAfterRefresh() || !this.focusedCellPosition) {\n return null;\n }\n // we check that the browser is actually focusing on the grid, if it is not, then\n // we have nothing to worry about. we check for ROW data, as this covers both focused Rows (for Full Width Rows)\n // and Cells (covers cells as cells live in rows)\n if (this.isDomDataMissingInHierarchy(eDocument.activeElement, RowCtrl.DOM_DATA_KEY_ROW_CTRL)) {\n return null;\n }\n return this.focusedCellPosition;\n };\n FocusService.prototype.getFocusHeaderToUseAfterRefresh = function () {\n var eDocument = this.gridOptionsWrapper.getDocument();\n if (this.gridOptionsWrapper.isSuppressFocusAfterRefresh() || !this.focusedHeaderPosition) {\n return null;\n }\n // we check that the browser is actually focusing on the grid, if it is not, then\n // we have nothing to worry about\n if (this.isDomDataMissingInHierarchy(eDocument.activeElement, AbstractHeaderCellCtrl.DOM_DATA_KEY_HEADER_CTRL)) {\n return null;\n }\n return this.focusedHeaderPosition;\n };\n FocusService.prototype.isDomDataMissingInHierarchy = function (eBrowserCell, key) {\n var ePointer = eBrowserCell;\n while (ePointer) {\n var data = this.gridOptionsWrapper.getDomData(ePointer, key);\n if (data) {\n return false;\n }\n ePointer = ePointer.parentNode;\n }\n return true;\n };\n FocusService.prototype.clearFocusedCell = function () {\n this.focusedCellPosition = null;\n this.onCellFocused(false, false);\n };\n FocusService.prototype.getFocusedCell = function () {\n return this.focusedCellPosition;\n };\n FocusService.prototype.setFocusedCell = function (params) {\n var column = params.column, rowIndex = params.rowIndex, rowPinned = params.rowPinned, _a = params.forceBrowserFocus, forceBrowserFocus = _a === void 0 ? false : _a, _b = params.preventScrollOnBrowserFocus, preventScrollOnBrowserFocus = _b === void 0 ? false : _b;\n var gridColumn = this.columnModel.getGridColumn(column);\n // if column doesn't exist, then blank the focused cell and return. this can happen when user sets new columns,\n // and the focused cell is in a column that no longer exists. after columns change, the grid refreshes and tries\n // to re-focus the focused cell.\n if (!gridColumn) {\n this.focusedCellPosition = null;\n return;\n }\n this.focusedCellPosition = gridColumn ? {\n rowIndex: rowIndex,\n rowPinned: makeNull(rowPinned),\n column: gridColumn\n } : null;\n this.onCellFocused(forceBrowserFocus, preventScrollOnBrowserFocus);\n };\n FocusService.prototype.isCellFocused = function (cellPosition) {\n if (this.focusedCellPosition == null) {\n return false;\n }\n return this.focusedCellPosition.column === cellPosition.column &&\n this.isRowFocused(cellPosition.rowIndex, cellPosition.rowPinned);\n };\n FocusService.prototype.isRowNodeFocused = function (rowNode) {\n return this.isRowFocused(rowNode.rowIndex, rowNode.rowPinned);\n };\n FocusService.prototype.isHeaderWrapperFocused = function (headerCtrl) {\n if (this.focusedHeaderPosition == null) {\n return false;\n }\n var column = headerCtrl.getColumnGroupChild();\n var headerRowIndex = headerCtrl.getRowIndex();\n var pinned = headerCtrl.getPinned();\n var _a = this.focusedHeaderPosition, focusedColumn = _a.column, focusedHeaderRowIndex = _a.headerRowIndex;\n return column === focusedColumn &&\n headerRowIndex === focusedHeaderRowIndex &&\n pinned == focusedColumn.getPinned();\n };\n FocusService.prototype.clearFocusedHeader = function () {\n this.focusedHeaderPosition = null;\n };\n FocusService.prototype.getFocusedHeader = function () {\n return this.focusedHeaderPosition;\n };\n FocusService.prototype.setFocusedHeader = function (headerRowIndex, column) {\n this.focusedHeaderPosition = { headerRowIndex: headerRowIndex, column: column };\n };\n FocusService.prototype.focusHeaderPosition = function (params) {\n var direction = params.direction, fromTab = params.fromTab, allowUserOverride = params.allowUserOverride, event = params.event;\n var headerPosition = params.headerPosition;\n if (allowUserOverride) {\n var gridOptionsWrapper = this.gridOptionsWrapper;\n var currentPosition = this.getFocusedHeader();\n var headerRowCount = this.headerNavigationService.getHeaderRowCount();\n if (fromTab) {\n var userFunc = gridOptionsWrapper.getTabToNextHeaderFunc();\n if (userFunc) {\n var params_1 = {\n backwards: direction === 'Before',\n previousHeaderPosition: currentPosition,\n nextHeaderPosition: headerPosition,\n headerRowCount: headerRowCount,\n };\n headerPosition = userFunc(params_1);\n }\n }\n else {\n var userFunc = gridOptionsWrapper.getNavigateToNextHeaderFunc();\n if (userFunc && event) {\n var params_2 = {\n key: event.key,\n previousHeaderPosition: currentPosition,\n nextHeaderPosition: headerPosition,\n headerRowCount: headerRowCount,\n event: event,\n };\n headerPosition = userFunc(params_2);\n }\n }\n }\n if (!headerPosition) {\n return false;\n }\n if (headerPosition.headerRowIndex === -1) {\n return this.focusGridView(headerPosition.column);\n }\n this.headerNavigationService.scrollToColumn(headerPosition.column, direction);\n var headerRowContainerCtrl = this.ctrlsService.getHeaderRowContainerCtrl(headerPosition.column.getPinned());\n // this will automatically call the setFocusedHeader method above\n var focusSuccess = headerRowContainerCtrl.focusHeader(headerPosition.headerRowIndex, headerPosition.column, event);\n return focusSuccess;\n };\n FocusService.prototype.focusFirstHeader = function () {\n var firstColumn = this.columnModel.getAllDisplayedColumns()[0];\n if (!firstColumn) {\n return false;\n }\n if (firstColumn.getParent()) {\n firstColumn = this.columnModel.getColumnGroupAtLevel(firstColumn, 0);\n }\n return this.focusHeaderPosition({\n headerPosition: { headerRowIndex: 0, column: firstColumn }\n });\n };\n FocusService.prototype.focusLastHeader = function (event) {\n var headerRowIndex = this.headerNavigationService.getHeaderRowCount() - 1;\n var column = last(this.columnModel.getAllDisplayedColumns());\n return this.focusHeaderPosition({\n headerPosition: { headerRowIndex: headerRowIndex, column: column },\n event: event\n });\n };\n FocusService.prototype.isAnyCellFocused = function () {\n return !!this.focusedCellPosition;\n };\n FocusService.prototype.isRowFocused = function (rowIndex, floating) {\n if (this.focusedCellPosition == null) {\n return false;\n }\n return this.focusedCellPosition.rowIndex === rowIndex && this.focusedCellPosition.rowPinned === makeNull(floating);\n };\n FocusService.prototype.findFocusableElements = function (rootNode, exclude, onlyUnmanaged) {\n if (onlyUnmanaged === void 0) { onlyUnmanaged = false; }\n var focusableString = Constants.FOCUSABLE_SELECTOR;\n var excludeString = Constants.FOCUSABLE_EXCLUDE;\n if (exclude) {\n excludeString += ', ' + exclude;\n }\n if (onlyUnmanaged) {\n excludeString += ', [tabindex=\"-1\"]';\n }\n var nodes = Array.prototype.slice.apply(rootNode.querySelectorAll(focusableString));\n var excludeNodes = Array.prototype.slice.apply(rootNode.querySelectorAll(excludeString));\n if (!excludeNodes.length) {\n return nodes;\n }\n var diff = function (a, b) { return a.filter(function (element) { return b.indexOf(element) === -1; }); };\n return diff(nodes, excludeNodes);\n };\n FocusService.prototype.focusInto = function (rootNode, up, onlyUnmanaged) {\n if (up === void 0) { up = false; }\n if (onlyUnmanaged === void 0) { onlyUnmanaged = false; }\n var focusableElements = this.findFocusableElements(rootNode, null, onlyUnmanaged);\n var toFocus = up ? last(focusableElements) : focusableElements[0];\n if (toFocus) {\n toFocus.focus();\n return true;\n }\n return false;\n };\n FocusService.prototype.findNextFocusableElement = function (rootNode, onlyManaged, backwards) {\n if (rootNode === void 0) { rootNode = this.eGridDiv; }\n var focusable = this.findFocusableElements(rootNode, onlyManaged ? ':not([tabindex=\"-1\"])' : null);\n var eDocument = this.gridOptionsWrapper.getDocument();\n var activeEl = eDocument.activeElement;\n var currentIndex;\n if (onlyManaged) {\n currentIndex = focusable.findIndex(function (el) { return el.contains(activeEl); });\n }\n else {\n currentIndex = focusable.indexOf(activeEl);\n }\n var nextIndex = currentIndex + (backwards ? -1 : 1);\n if (nextIndex < 0 || nextIndex >= focusable.length) {\n return null;\n }\n return focusable[nextIndex];\n };\n FocusService.prototype.isFocusUnderManagedComponent = function (rootNode) {\n var eDocument = this.gridOptionsWrapper.getDocument();\n var managedContainers = rootNode.querySelectorAll(\".\" + ManagedFocusFeature.FOCUS_MANAGED_CLASS);\n if (!managedContainers.length) {\n return false;\n }\n for (var i = 0; i < managedContainers.length; i++) {\n if (managedContainers[i].contains(eDocument.activeElement)) {\n return true;\n }\n }\n return false;\n };\n FocusService.prototype.findTabbableParent = function (node, limit) {\n if (limit === void 0) { limit = 5; }\n var counter = 0;\n while (node && getTabIndex(node) === null && ++counter <= limit) {\n node = node.parentElement;\n }\n if (getTabIndex(node) === null) {\n return null;\n }\n return node;\n };\n FocusService.prototype.onCellFocused = function (forceBrowserFocus, preventScrollOnBrowserFocus) {\n var event = {\n type: Events.EVENT_CELL_FOCUSED,\n forceBrowserFocus: forceBrowserFocus,\n preventScrollOnBrowserFocus: preventScrollOnBrowserFocus,\n rowIndex: null,\n column: null,\n floating: null,\n rowPinned: null,\n isFullWidthCell: false\n };\n if (this.focusedCellPosition) {\n var rowIndex = event.rowIndex = this.focusedCellPosition.rowIndex;\n var rowPinned = event.rowPinned = this.focusedCellPosition.rowPinned;\n event.column = this.focusedCellPosition.column;\n var rowCtrl = this.rowRenderer.getRowByPosition({ rowIndex: rowIndex, rowPinned: rowPinned });\n if (rowCtrl) {\n event.isFullWidthCell = rowCtrl.isFullWidth();\n }\n }\n this.eventService.dispatchEvent(event);\n };\n FocusService.prototype.focusGridView = function (column, backwards) {\n // if suppressCellFocus is `true`, it means the user does not want to\n // navigate between the cells using tab. Instead, we put focus on either\n // the header or after the grid, depending on whether tab or shift-tab was pressed.\n if (this.gridOptionsWrapper.isSuppressCellFocus()) {\n if (backwards) {\n return this.focusLastHeader();\n }\n return this.focusNextGridCoreContainer(false);\n }\n var nextRow = backwards\n ? this.rowPositionUtils.getLastRow()\n : this.rowPositionUtils.getFirstRow();\n if (!nextRow) {\n return false;\n }\n var rowIndex = nextRow.rowIndex, rowPinned = nextRow.rowPinned;\n var focusedHeader = this.getFocusedHeader();\n if (!column && focusedHeader) {\n column = focusedHeader.column;\n }\n if (rowIndex == null || !column) {\n return false;\n }\n this.navigationService.ensureCellVisible({ rowIndex: rowIndex, column: column, rowPinned: rowPinned });\n this.setFocusedCell({\n rowIndex: rowIndex,\n column: column,\n rowPinned: makeNull(rowPinned),\n forceBrowserFocus: true\n });\n if (this.rangeService) {\n var cellPosition = { rowIndex: rowIndex, rowPinned: rowPinned, column: column };\n this.rangeService.setRangeToCell(cellPosition);\n }\n return true;\n };\n FocusService.prototype.focusNextGridCoreContainer = function (backwards) {\n if (this.gridCtrl.focusNextInnerContainer(backwards)) {\n return true;\n }\n if (!backwards && !this.gridCtrl.isDetailGrid()) {\n this.gridCtrl.forceFocusOutOfContainer();\n }\n return false;\n };\n var FocusService_1;\n FocusService.AG_KEYBOARD_FOCUS = 'ag-keyboard-focus';\n FocusService.keyboardModeActive = false;\n FocusService.instancesMonitored = new Map();\n __decorate$P([\n Autowired('eGridDiv')\n ], FocusService.prototype, \"eGridDiv\", void 0);\n __decorate$P([\n Autowired('columnModel')\n ], FocusService.prototype, \"columnModel\", void 0);\n __decorate$P([\n Autowired('headerNavigationService')\n ], FocusService.prototype, \"headerNavigationService\", void 0);\n __decorate$P([\n Autowired('rowRenderer')\n ], FocusService.prototype, \"rowRenderer\", void 0);\n __decorate$P([\n Autowired('rowPositionUtils')\n ], FocusService.prototype, \"rowPositionUtils\", void 0);\n __decorate$P([\n Optional('rangeService')\n ], FocusService.prototype, \"rangeService\", void 0);\n __decorate$P([\n Autowired('navigationService')\n ], FocusService.prototype, \"navigationService\", void 0);\n __decorate$P([\n Autowired('ctrlsService')\n ], FocusService.prototype, \"ctrlsService\", void 0);\n __decorate$P([\n PostConstruct\n ], FocusService.prototype, \"init\", null);\n FocusService = FocusService_1 = __decorate$P([\n Bean('focusService')\n ], FocusService);\n return FocusService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$M = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$O = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$6 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$5 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$6(arguments[i]));\n return ar;\n};\nvar DIRECTION;\n(function (DIRECTION) {\n DIRECTION[DIRECTION[\"vertical\"] = 0] = \"vertical\";\n DIRECTION[DIRECTION[\"horizontal\"] = 1] = \"horizontal\";\n})(DIRECTION || (DIRECTION = {}));\nvar instanceIdSeq = 0;\nvar PopupService = /** @class */ (function (_super) {\n __extends$M(PopupService, _super);\n function PopupService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.popupList = [];\n return _this;\n }\n PopupService.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) {\n _this.gridCtrl = p.gridCtrl;\n _this.addManagedListener(_this.gridCtrl, Events.EVENT_KEYBOARD_FOCUS, function () {\n _this.popupList.forEach(function (popup) { return popup.element.classList.add(FocusService.AG_KEYBOARD_FOCUS); });\n });\n _this.addManagedListener(_this.gridCtrl, Events.EVENT_MOUSE_FOCUS, function () {\n _this.popupList.forEach(function (popup) { return popup.element.classList.remove(FocusService.AG_KEYBOARD_FOCUS); });\n });\n });\n };\n PopupService.prototype.getPopupParent = function () {\n var ePopupParent = this.gridOptionsWrapper.getPopupParent();\n if (ePopupParent) {\n return ePopupParent;\n }\n return this.gridCtrl.getGui();\n };\n PopupService.prototype.positionPopupForMenu = function (params) {\n var sourceRect = params.eventSource.getBoundingClientRect();\n var parentRect = this.getParentRect();\n var y = this.keepXYWithinBounds(params.ePopup, sourceRect.top - parentRect.top, DIRECTION.vertical);\n var minWidth = (params.ePopup.clientWidth > 0) ? params.ePopup.clientWidth : 200;\n params.ePopup.style.minWidth = minWidth + \"px\";\n var widthOfParent = parentRect.right - parentRect.left;\n var maxX = widthOfParent - minWidth;\n // the x position of the popup depends on RTL or LTR. for normal cases, LTR, we put the child popup\n // to the right, unless it doesn't fit and we then put it to the left. for RTL it's the other way around,\n // we try place it first to the left, and then if not to the right.\n var x;\n if (this.gridOptionsWrapper.isEnableRtl()) {\n // for RTL, try left first\n x = xLeftPosition();\n if (x < 0) {\n x = xRightPosition();\n }\n if (x > maxX) {\n x = 0;\n }\n }\n else {\n // for LTR, try right first\n x = xRightPosition();\n if (x > maxX) {\n x = xLeftPosition();\n }\n if (x < 0) {\n x = 0;\n }\n }\n params.ePopup.style.left = x + \"px\";\n params.ePopup.style.top = y + \"px\";\n function xRightPosition() {\n return sourceRect.right - parentRect.left - 2;\n }\n function xLeftPosition() {\n return sourceRect.left - parentRect.left - minWidth;\n }\n };\n PopupService.prototype.positionPopupUnderMouseEvent = function (params) {\n var ePopup = params.ePopup, nudgeX = params.nudgeX, nudgeY = params.nudgeY;\n var _a = this.calculatePointerAlign(params.mouseEvent), x = _a.x, y = _a.y;\n this.positionPopup({\n ePopup: ePopup,\n x: x,\n y: y,\n nudgeX: nudgeX,\n nudgeY: nudgeY,\n keepWithinBounds: true\n });\n this.callPostProcessPopup(params.type, params.ePopup, null, params.mouseEvent, params.column, params.rowNode);\n };\n PopupService.prototype.calculatePointerAlign = function (e) {\n var parentRect = this.getParentRect();\n return {\n x: e.clientX - parentRect.left,\n y: e.clientY - parentRect.top\n };\n };\n PopupService.prototype.positionPopupUnderComponent = function (params) {\n var sourceRect = params.eventSource.getBoundingClientRect();\n var alignSide = params.alignSide || 'left';\n var parentRect = this.getParentRect();\n var x = sourceRect.left - parentRect.left;\n if (alignSide === 'right') {\n x -= (params.ePopup.offsetWidth - sourceRect.width);\n }\n this.positionPopup({\n ePopup: params.ePopup,\n nudgeX: params.nudgeX,\n nudgeY: params.nudgeY,\n x: x,\n y: sourceRect.top - parentRect.top + sourceRect.height,\n keepWithinBounds: params.keepWithinBounds\n });\n this.callPostProcessPopup(params.type, params.ePopup, params.eventSource, null, params.column, params.rowNode);\n };\n PopupService.prototype.positionPopupOverComponent = function (params) {\n var sourceRect = params.eventSource.getBoundingClientRect();\n var parentRect = this.getParentRect();\n this.positionPopup({\n ePopup: params.ePopup,\n nudgeX: params.nudgeX,\n nudgeY: params.nudgeY,\n x: sourceRect.left - parentRect.left,\n y: sourceRect.top - parentRect.top,\n keepWithinBounds: params.keepWithinBounds\n });\n this.callPostProcessPopup(params.type, params.ePopup, params.eventSource, null, params.column, params.rowNode);\n };\n PopupService.prototype.callPostProcessPopup = function (type, ePopup, eventSource, mouseEvent, column, rowNode) {\n var callback = this.gridOptionsWrapper.getPostProcessPopupFunc();\n if (callback) {\n var params = {\n column: column,\n rowNode: rowNode,\n ePopup: ePopup,\n type: type,\n eventSource: eventSource,\n mouseEvent: mouseEvent\n };\n callback(params);\n }\n };\n PopupService.prototype.positionPopup = function (params) {\n var ePopup = params.ePopup, keepWithinBounds = params.keepWithinBounds, nudgeX = params.nudgeX, nudgeY = params.nudgeY;\n var x = params.x, y = params.y;\n if (nudgeX) {\n x += nudgeX;\n }\n if (nudgeY) {\n y += nudgeY;\n }\n // if popup is overflowing to the bottom, move it up\n if (keepWithinBounds) {\n x = this.keepXYWithinBounds(ePopup, x, DIRECTION.horizontal);\n y = this.keepXYWithinBounds(ePopup, y, DIRECTION.vertical);\n }\n ePopup.style.left = x + \"px\";\n ePopup.style.top = y + \"px\";\n };\n PopupService.prototype.getActivePopups = function () {\n return this.popupList.map(function (popup) { return popup.element; });\n };\n PopupService.prototype.getPopupList = function () {\n return this.popupList;\n };\n PopupService.prototype.getParentRect = function () {\n // subtract the popup parent borders, because popupParent.getBoundingClientRect\n // returns the rect outside the borders, but the 0,0 coordinate for absolute\n // positioning is inside the border, leading the popup to be off by the width\n // of the border\n var eDocument = this.gridOptionsWrapper.getDocument();\n var popupParent = this.getPopupParent();\n if (popupParent === eDocument.body) {\n popupParent = eDocument.documentElement;\n }\n else if (getComputedStyle(popupParent).position === 'static') {\n popupParent = popupParent.offsetParent;\n }\n var style = getComputedStyle(popupParent);\n var bounds = popupParent.getBoundingClientRect();\n return {\n top: bounds.top + parseFloat(style.borderTopWidth) || 0,\n left: bounds.left + parseFloat(style.borderLeftWidth) || 0,\n right: bounds.right + parseFloat(style.borderRightWidth) || 0,\n bottom: bounds.bottom + parseFloat(style.borderBottomWidth) || 0,\n };\n };\n PopupService.prototype.keepXYWithinBounds = function (ePopup, position, direction) {\n var isVertical = direction === DIRECTION.vertical;\n var sizeProperty = isVertical ? 'clientHeight' : 'clientWidth';\n var anchorProperty = isVertical ? 'top' : 'left';\n var offsetProperty = isVertical ? 'offsetHeight' : 'offsetWidth';\n var scrollPositionProperty = isVertical ? 'scrollTop' : 'scrollLeft';\n var eDocument = this.gridOptionsWrapper.getDocument();\n var docElement = eDocument.documentElement;\n var popupParent = this.getPopupParent();\n var parentRect = popupParent.getBoundingClientRect();\n var documentRect = eDocument.documentElement.getBoundingClientRect();\n var isBody = popupParent === eDocument.body;\n var offsetSize = ePopup[offsetProperty];\n var getSize = isVertical ? getAbsoluteHeight : getAbsoluteWidth;\n var sizeOfParent = isBody ? (getSize(docElement) + docElement[scrollPositionProperty]) : popupParent[sizeProperty];\n if (isBody) {\n sizeOfParent -= Math.abs(documentRect[anchorProperty] - parentRect[anchorProperty]);\n }\n var max = sizeOfParent - offsetSize;\n return Math.min(Math.max(position, 0), Math.abs(max));\n };\n PopupService.prototype.keepPopupPositionedRelativeTo = function (params) {\n var _this = this;\n var eParent = this.getPopupParent();\n var parentRect = eParent.getBoundingClientRect();\n var sourceRect = params.element.getBoundingClientRect();\n var initialDiffTop = parentRect.top - sourceRect.top;\n var initialDiffLeft = parentRect.left - sourceRect.left;\n var lastDiffTop = initialDiffTop;\n var lastDiffLeft = initialDiffLeft;\n var topPx = params.ePopup.style.top;\n var top = parseInt(topPx.substring(0, topPx.length - 1), 10);\n var leftPx = params.ePopup.style.left;\n var left = parseInt(leftPx.substring(0, leftPx.length - 1), 10);\n return new AgPromise(function (resolve) {\n _this.getFrameworkOverrides().setInterval(function () {\n var pRect = eParent.getBoundingClientRect();\n var sRect = params.element.getBoundingClientRect();\n var elementNotInDom = sRect.top == 0 && sRect.left == 0 && sRect.height == 0 && sRect.width == 0;\n if (elementNotInDom) {\n params.hidePopup();\n return;\n }\n var currentDiffTop = pRect.top - sRect.top;\n if (currentDiffTop != lastDiffTop) {\n var newTop = _this.keepXYWithinBounds(params.ePopup, top + initialDiffTop - currentDiffTop, DIRECTION.vertical);\n params.ePopup.style.top = newTop + \"px\";\n }\n lastDiffTop = currentDiffTop;\n var currentDiffLeft = pRect.left - sRect.left;\n if (currentDiffLeft != lastDiffLeft) {\n var newLeft = _this.keepXYWithinBounds(params.ePopup, left + initialDiffLeft - currentDiffLeft, DIRECTION.horizontal);\n params.ePopup.style.left = newLeft + \"px\";\n }\n lastDiffLeft = currentDiffLeft;\n }, 200).then(function (intervalId) {\n var result = function () {\n if (intervalId != null) {\n window.clearInterval(intervalId);\n }\n };\n resolve(result);\n });\n });\n };\n PopupService.prototype.addPopup = function (params) {\n var _a;\n var _this = this;\n var modal = params.modal, eChild = params.eChild, closeOnEsc = params.closeOnEsc, closedCallback = params.closedCallback, click = params.click, alwaysOnTop = params.alwaysOnTop, afterGuiAttached = params.afterGuiAttached, positionCallback = params.positionCallback, anchorToElement = params.anchorToElement, ariaLabel = params.ariaLabel;\n var eDocument = this.gridOptionsWrapper.getDocument();\n var destroyPositionTracker = new AgPromise(function (resolve) { return resolve(function () { }); });\n if (!eDocument) {\n console.warn('ag-grid: could not find the document, document is empty');\n return { hideFunc: function () { }, stopAnchoringPromise: destroyPositionTracker };\n }\n var pos = this.popupList.findIndex(function (popup) { return popup.element === eChild; });\n if (pos !== -1) {\n var popup = this.popupList[pos];\n return { hideFunc: popup.hideFunc, stopAnchoringPromise: popup.stopAnchoringPromise };\n }\n var ePopupParent = this.getPopupParent();\n if (eChild.style.top == null) {\n eChild.style.top = '0px';\n }\n if (eChild.style.left == null) {\n eChild.style.left = '0px';\n }\n // add env CSS class to child, in case user provided a popup parent, which means\n // theme class may be missing\n var eWrapper = document.createElement('div');\n var allThemes = this.environment.getTheme().allThemes;\n if (allThemes.length) {\n (_a = eWrapper.classList).add.apply(_a, __spread$5(allThemes));\n }\n eWrapper.classList.add('ag-popup');\n eChild.classList.add(this.gridOptionsWrapper.isEnableRtl() ? 'ag-rtl' : 'ag-ltr', 'ag-popup-child');\n if (!eChild.hasAttribute('role')) {\n setAriaRole(eChild, 'dialog');\n }\n setAriaLabel(eChild, ariaLabel);\n if (this.focusService.isKeyboardMode()) {\n eChild.classList.add(FocusService.AG_KEYBOARD_FOCUS);\n }\n eWrapper.appendChild(eChild);\n ePopupParent.appendChild(eWrapper);\n if (alwaysOnTop) {\n this.setAlwaysOnTop(eWrapper, true);\n }\n else {\n this.bringPopupToFront(eWrapper);\n }\n var popupHidden = false;\n var hidePopupOnKeyboardEvent = function (event) {\n if (!eWrapper.contains(eDocument.activeElement)) {\n return;\n }\n var key = event.key;\n if (key === KeyCode.ESCAPE) {\n hidePopup({ keyboardEvent: event });\n }\n };\n var hidePopupOnMouseEvent = function (event) { return hidePopup({ mouseEvent: event }); };\n var hidePopupOnTouchEvent = function (event) { return hidePopup({ touchEvent: event }); };\n var hidePopup = function (popupParams) {\n if (popupParams === void 0) { popupParams = {}; }\n var mouseEvent = popupParams.mouseEvent, touchEvent = popupParams.touchEvent, keyboardEvent = popupParams.keyboardEvent;\n if (\n // we don't hide popup if the event was on the child, or any\n // children of this child\n _this.isEventFromCurrentPopup({ mouseEvent: mouseEvent, touchEvent: touchEvent }, eChild) ||\n // if the event to close is actually the open event, then ignore it\n _this.isEventSameChainAsOriginalEvent({ originalMouseEvent: click, mouseEvent: mouseEvent, touchEvent: touchEvent }) ||\n // this method should only be called once. the client can have different\n // paths, each one wanting to close, so this method may be called multiple times.\n popupHidden) {\n return;\n }\n popupHidden = true;\n ePopupParent.removeChild(eWrapper);\n eDocument.removeEventListener('keydown', hidePopupOnKeyboardEvent);\n eDocument.removeEventListener('mousedown', hidePopupOnMouseEvent);\n eDocument.removeEventListener('touchstart', hidePopupOnTouchEvent);\n eDocument.removeEventListener('contextmenu', hidePopupOnMouseEvent);\n _this.eventService.removeEventListener(Events.EVENT_DRAG_STARTED, hidePopupOnMouseEvent);\n if (closedCallback) {\n closedCallback(mouseEvent || touchEvent || keyboardEvent);\n }\n _this.popupList = _this.popupList.filter(function (popup) { return popup.element !== eChild; });\n if (destroyPositionTracker) {\n destroyPositionTracker.then(function (destroyFunc) { return destroyFunc && destroyFunc(); });\n }\n };\n if (afterGuiAttached) {\n afterGuiAttached({ hidePopup: hidePopup });\n }\n // if we add these listeners now, then the current mouse\n // click will be included, which we don't want\n window.setTimeout(function () {\n if (closeOnEsc) {\n eDocument.addEventListener('keydown', hidePopupOnKeyboardEvent);\n }\n if (modal) {\n eDocument.addEventListener('mousedown', hidePopupOnMouseEvent);\n _this.eventService.addEventListener(Events.EVENT_DRAG_STARTED, hidePopupOnMouseEvent);\n eDocument.addEventListener('touchstart', hidePopupOnTouchEvent);\n eDocument.addEventListener('contextmenu', hidePopupOnMouseEvent);\n }\n }, 0);\n if (positionCallback) {\n positionCallback();\n }\n if (anchorToElement) {\n // keeps popup positioned under created, eg if context menu, if user scrolls\n // using touchpad and the cell moves, it moves the popup to keep it with the cell.\n destroyPositionTracker = this.keepPopupPositionedRelativeTo({\n element: anchorToElement,\n ePopup: eChild,\n hidePopup: hidePopup\n });\n }\n this.popupList.push({\n element: eChild,\n wrapper: eWrapper,\n hideFunc: hidePopup,\n stopAnchoringPromise: destroyPositionTracker,\n instanceId: instanceIdSeq++,\n isAnchored: !!anchorToElement\n });\n return {\n hideFunc: hidePopup,\n stopAnchoringPromise: destroyPositionTracker\n };\n };\n PopupService.prototype.hasAnchoredPopup = function () {\n return this.popupList.some(function (popup) { return popup.isAnchored; });\n };\n PopupService.prototype.isEventFromCurrentPopup = function (params, target) {\n var mouseEvent = params.mouseEvent, touchEvent = params.touchEvent;\n var event = mouseEvent ? mouseEvent : touchEvent;\n if (!event) {\n return false;\n }\n var indexOfThisChild = this.popupList.findIndex(function (popup) { return popup.element === target; });\n if (indexOfThisChild === -1) {\n return false;\n }\n for (var i = indexOfThisChild; i < this.popupList.length; i++) {\n var popup = this.popupList[i];\n if (isElementInEventPath(popup.element, event)) {\n return true;\n }\n }\n // if the user did not write their own Custom Element to be rendered as popup\n // and this component has an additional popup element, they should have the\n // `ag-custom-component-popup` class to be detected as part of the Custom Component\n return this.isElementWithinCustomPopup(event.target);\n };\n PopupService.prototype.isElementWithinCustomPopup = function (el) {\n var eDocument = this.gridOptionsWrapper.getDocument();\n while (el && el !== eDocument.body) {\n if (el.classList.contains('ag-custom-component-popup') || el.parentElement === null) {\n return true;\n }\n el = el.parentElement;\n }\n return false;\n };\n // in some browsers, the context menu event can be fired before the click event, which means\n // the context menu event could open the popup, but then the click event closes it straight away.\n PopupService.prototype.isEventSameChainAsOriginalEvent = function (params) {\n var originalMouseEvent = params.originalMouseEvent, mouseEvent = params.mouseEvent, touchEvent = params.touchEvent;\n // we check the coordinates of the event, to see if it's the same event. there is a 1 / 1000 chance that\n // the event is a different event, however that is an edge case that is not very relevant (the user clicking\n // twice on the same location isn't a normal path).\n // event could be mouse event or touch event.\n var mouseEventOrTouch = null;\n if (mouseEvent) {\n // mouse event can be used direction, it has coordinates\n mouseEventOrTouch = mouseEvent;\n }\n else if (touchEvent) {\n // touch event doesn't have coordinates, need it's touch object\n mouseEventOrTouch = touchEvent.touches[0];\n }\n if (mouseEventOrTouch && originalMouseEvent) {\n // for x, allow 4px margin, to cover iPads, where touch (which opens menu) is followed\n // by browser click (when you finger up, touch is interrupted as click in browser)\n var screenX_1 = mouseEvent ? mouseEvent.screenX : 0;\n var screenY_1 = mouseEvent ? mouseEvent.screenY : 0;\n var xMatch = Math.abs(originalMouseEvent.screenX - screenX_1) < 5;\n var yMatch = Math.abs(originalMouseEvent.screenY - screenY_1) < 5;\n if (xMatch && yMatch) {\n return true;\n }\n }\n return false;\n };\n PopupService.prototype.getWrapper = function (ePopup) {\n while (!ePopup.classList.contains('ag-popup') && ePopup.parentElement) {\n ePopup = ePopup.parentElement;\n }\n return ePopup.classList.contains('ag-popup') ? ePopup : null;\n };\n PopupService.prototype.setAlwaysOnTop = function (ePopup, alwaysOnTop) {\n var eWrapper = this.getWrapper(ePopup);\n if (!eWrapper) {\n return;\n }\n eWrapper.classList.toggle('ag-always-on-top', !!alwaysOnTop);\n if (alwaysOnTop) {\n this.bringPopupToFront(eWrapper);\n }\n };\n PopupService.prototype.bringPopupToFront = function (ePopup) {\n var parent = this.getPopupParent();\n var popupList = Array.prototype.slice.call(parent.querySelectorAll('.ag-popup'));\n var popupLen = popupList.length;\n var alwaysOnTopList = Array.prototype.slice.call(parent.querySelectorAll('.ag-popup.ag-always-on-top'));\n var onTopLength = alwaysOnTopList.length;\n var eWrapper = this.getWrapper(ePopup);\n if (!eWrapper || popupLen <= 1 || !parent.contains(ePopup)) {\n return;\n }\n var pos = popupList.indexOf(eWrapper);\n var innerEls = eWrapper.querySelectorAll('div');\n var innerElsScrollMap = [];\n innerEls.forEach(function (el) {\n if (el.scrollTop !== 0) {\n innerElsScrollMap.push([el, el.scrollTop]);\n }\n });\n if (onTopLength) {\n var isPopupAlwaysOnTop = eWrapper.classList.contains('ag-always-on-top');\n if (isPopupAlwaysOnTop) {\n if (pos !== popupLen - 1) {\n last(alwaysOnTopList).insertAdjacentElement('afterend', eWrapper);\n }\n }\n else if (pos !== popupLen - onTopLength - 1) {\n alwaysOnTopList[0].insertAdjacentElement('beforebegin', eWrapper);\n }\n }\n else if (pos !== popupLen - 1) {\n last(popupList).insertAdjacentElement('afterend', eWrapper);\n }\n while (innerElsScrollMap.length) {\n var currentEl = innerElsScrollMap.pop();\n currentEl[0].scrollTop = currentEl[1];\n }\n var params = {\n type: 'popupToFront',\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n eWrapper: eWrapper\n };\n this.eventService.dispatchEvent(params);\n };\n __decorate$O([\n Autowired('environment')\n ], PopupService.prototype, \"environment\", void 0);\n __decorate$O([\n Autowired('focusService')\n ], PopupService.prototype, \"focusService\", void 0);\n __decorate$O([\n Autowired('ctrlsService')\n ], PopupService.prototype, \"ctrlsService\", void 0);\n __decorate$O([\n PostConstruct\n ], PopupService.prototype, \"postConstruct\", null);\n PopupService = __decorate$O([\n Bean('popupService')\n ], PopupService);\n return PopupService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$L = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$N = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar VirtualList = /** @class */ (function (_super) {\n __extends$L(VirtualList, _super);\n function VirtualList(cssIdentifier, ariaRole, listName) {\n if (cssIdentifier === void 0) { cssIdentifier = 'default'; }\n if (ariaRole === void 0) { ariaRole = 'listbox'; }\n var _this = _super.call(this, VirtualList.getTemplate(cssIdentifier)) || this;\n _this.cssIdentifier = cssIdentifier;\n _this.ariaRole = ariaRole;\n _this.listName = listName;\n _this.renderedRows = new Map();\n _this.rowHeight = 20;\n _this.isDestroyed = false;\n return _this;\n }\n VirtualList.prototype.postConstruct = function () {\n var _this = this;\n this.addScrollListener();\n this.rowHeight = this.getItemHeight();\n this.addResizeObserver();\n this.initialiseTabGuard({\n onFocusIn: function (e) { return _this.onFocusIn(e); },\n onFocusOut: function (e) { return _this.onFocusOut(e); },\n focusInnerElement: function (fromBottom) { return _this.focusInnerElement(fromBottom); },\n onTabKeyDown: function (e) { return _this.onTabKeyDown(e); },\n handleKeyDown: function (e) { return _this.handleKeyDown(e); }\n });\n this.setAriaProperties();\n };\n VirtualList.prototype.setAriaProperties = function () {\n var translate = this.gridOptionsWrapper.getLocaleTextFunc();\n var listName = translate('ariaDefaultListName', this.listName || 'List');\n var ariaEl = this.eContainer;\n setAriaRole(ariaEl, this.ariaRole);\n setAriaLabel(ariaEl, listName);\n };\n VirtualList.prototype.addResizeObserver = function () {\n var listener = this.drawVirtualRows.bind(this);\n var destroyObserver = this.resizeObserverService.observeResize(this.getGui(), listener);\n this.addDestroyFunc(destroyObserver);\n };\n VirtualList.prototype.focusInnerElement = function (fromBottom) {\n this.focusRow(fromBottom ? this.model.getRowCount() - 1 : 0);\n };\n VirtualList.prototype.onFocusIn = function (e) {\n var target = e.target;\n if (target.classList.contains('ag-virtual-list-item')) {\n this.lastFocusedRowIndex = getAriaPosInSet(target) - 1;\n }\n return false;\n };\n VirtualList.prototype.onFocusOut = function (e) {\n if (!this.getFocusableElement().contains(e.relatedTarget)) {\n this.lastFocusedRowIndex = null;\n }\n return false;\n };\n VirtualList.prototype.handleKeyDown = function (e) {\n switch (e.key) {\n case KeyCode.UP:\n case KeyCode.DOWN:\n if (this.navigate(e.key === KeyCode.UP)) {\n e.preventDefault();\n }\n break;\n }\n };\n VirtualList.prototype.onTabKeyDown = function (e) {\n if (this.navigate(e.shiftKey)) {\n e.preventDefault();\n }\n else {\n // focus on the first or last focusable element to ensure that any other handlers start from there\n this.focusService.focusInto(this.getGui(), !e.shiftKey);\n }\n };\n VirtualList.prototype.navigate = function (up) {\n if (this.lastFocusedRowIndex == null) {\n return false;\n }\n var nextRow = this.lastFocusedRowIndex + (up ? -1 : 1);\n if (nextRow < 0 || nextRow >= this.model.getRowCount()) {\n return false;\n }\n this.focusRow(nextRow);\n return true;\n };\n VirtualList.prototype.getLastFocusedRow = function () {\n return this.lastFocusedRowIndex;\n };\n VirtualList.prototype.focusRow = function (rowNumber) {\n var _this = this;\n this.ensureIndexVisible(rowNumber);\n window.setTimeout(function () {\n var renderedRow = _this.renderedRows.get(rowNumber);\n if (renderedRow) {\n renderedRow.eDiv.focus();\n }\n }, 10);\n };\n VirtualList.prototype.getComponentAt = function (rowIndex) {\n var comp = this.renderedRows.get(rowIndex);\n return comp && comp.rowComponent;\n };\n VirtualList.prototype.forEachRenderedRow = function (func) {\n this.renderedRows.forEach(function (value, key) { return func(value.rowComponent, key); });\n };\n VirtualList.getTemplate = function (cssIdentifier) {\n return /* html */ \"\\n <div class=\\\"ag-virtual-list-viewport ag-\" + cssIdentifier + \"-virtual-list-viewport\\\" role=\\\"presentation\\\">\\n <div class=\\\"ag-virtual-list-container ag-\" + cssIdentifier + \"-virtual-list-container\\\" ref=\\\"eContainer\\\"></div>\\n </div>\";\n };\n VirtualList.prototype.getItemHeight = function () {\n return this.gridOptionsWrapper.getListItemHeight();\n };\n VirtualList.prototype.ensureIndexVisible = function (index) {\n var lastRow = this.model.getRowCount();\n if (typeof index !== 'number' || index < 0 || index >= lastRow) {\n console.warn('AG Grid: invalid row index for ensureIndexVisible: ' + index);\n return;\n }\n var rowTopPixel = index * this.rowHeight;\n var rowBottomPixel = rowTopPixel + this.rowHeight;\n var eGui = this.getGui();\n var viewportTopPixel = eGui.scrollTop;\n var viewportHeight = eGui.offsetHeight;\n var viewportBottomPixel = viewportTopPixel + viewportHeight;\n var viewportScrolledPastRow = viewportTopPixel > rowTopPixel;\n var viewportScrolledBeforeRow = viewportBottomPixel < rowBottomPixel;\n if (viewportScrolledPastRow) {\n // if row is before, scroll up with row at top\n eGui.scrollTop = rowTopPixel;\n }\n else if (viewportScrolledBeforeRow) {\n // if row is below, scroll down with row at bottom\n var newScrollPosition = rowBottomPixel - viewportHeight;\n eGui.scrollTop = newScrollPosition;\n }\n };\n VirtualList.prototype.setComponentCreator = function (componentCreator) {\n this.componentCreator = componentCreator;\n };\n VirtualList.prototype.getRowHeight = function () {\n return this.rowHeight;\n };\n VirtualList.prototype.getScrollTop = function () {\n return this.getGui().scrollTop;\n };\n VirtualList.prototype.setRowHeight = function (rowHeight) {\n this.rowHeight = rowHeight;\n this.refresh();\n };\n VirtualList.prototype.refresh = function () {\n var _this = this;\n if (this.model == null || this.isDestroyed) {\n return;\n }\n var rowCount = this.model.getRowCount();\n this.eContainer.style.height = rowCount * this.rowHeight + \"px\";\n // ensure height is applied before attempting to redraw rows\n waitUntil(function () { return _this.eContainer.clientHeight >= rowCount * _this.rowHeight; }, function () {\n if (_this.isDestroyed) {\n return;\n }\n _this.clearVirtualRows();\n _this.drawVirtualRows();\n });\n };\n VirtualList.prototype.clearVirtualRows = function () {\n var _this = this;\n this.renderedRows.forEach(function (_, rowIndex) { return _this.removeRow(rowIndex); });\n };\n VirtualList.prototype.drawVirtualRows = function () {\n if (!this.isAlive()) {\n return;\n }\n var gui = this.getGui();\n var topPixel = gui.scrollTop;\n var bottomPixel = topPixel + gui.offsetHeight;\n var firstRow = Math.floor(topPixel / this.rowHeight);\n var lastRow = Math.floor(bottomPixel / this.rowHeight);\n this.ensureRowsRendered(firstRow, lastRow);\n };\n VirtualList.prototype.ensureRowsRendered = function (start, finish) {\n var _this = this;\n // remove any rows that are no longer required\n this.renderedRows.forEach(function (_, rowIndex) {\n if ((rowIndex < start || rowIndex > finish) && rowIndex !== _this.lastFocusedRowIndex) {\n _this.removeRow(rowIndex);\n }\n });\n // insert any required new rows\n for (var rowIndex = start; rowIndex <= finish; rowIndex++) {\n if (this.renderedRows.has(rowIndex)) {\n continue;\n }\n // check this row actually exists (in case overflow buffer window exceeds real data)\n if (rowIndex < this.model.getRowCount()) {\n this.insertRow(rowIndex);\n }\n }\n };\n VirtualList.prototype.insertRow = function (rowIndex) {\n var _this = this;\n var value = this.model.getRow(rowIndex);\n var eDiv = document.createElement('div');\n eDiv.classList.add('ag-virtual-list-item', \"ag-\" + this.cssIdentifier + \"-virtual-list-item\");\n setAriaRole(eDiv, this.ariaRole === 'tree' ? 'treeitem' : 'option');\n setAriaSetSize(eDiv, this.model.getRowCount());\n setAriaPosInSet(eDiv, rowIndex + 1);\n eDiv.setAttribute('tabindex', '-1');\n if (typeof this.model.isRowSelected === 'function') {\n var isSelected = this.model.isRowSelected(rowIndex);\n setAriaSelected(eDiv, !!isSelected);\n setAriaChecked(eDiv, isSelected);\n }\n eDiv.style.height = this.rowHeight + \"px\";\n eDiv.style.top = this.rowHeight * rowIndex + \"px\";\n var rowComponent = this.componentCreator(value, eDiv);\n rowComponent.addGuiEventListener('focusin', function () { return _this.lastFocusedRowIndex = rowIndex; });\n eDiv.appendChild(rowComponent.getGui());\n // keep the DOM order consistent with the order of the rows\n if (this.renderedRows.has(rowIndex - 1)) {\n this.renderedRows.get(rowIndex - 1).eDiv.insertAdjacentElement('afterend', eDiv);\n }\n else if (this.renderedRows.has(rowIndex + 1)) {\n this.renderedRows.get(rowIndex + 1).eDiv.insertAdjacentElement('beforebegin', eDiv);\n }\n else {\n this.eContainer.appendChild(eDiv);\n }\n this.renderedRows.set(rowIndex, { rowComponent: rowComponent, eDiv: eDiv });\n };\n VirtualList.prototype.removeRow = function (rowIndex) {\n var component = this.renderedRows.get(rowIndex);\n this.eContainer.removeChild(component.eDiv);\n this.destroyBean(component.rowComponent);\n this.renderedRows.delete(rowIndex);\n };\n VirtualList.prototype.addScrollListener = function () {\n var _this = this;\n this.addGuiEventListener('scroll', function () { return _this.drawVirtualRows(); });\n };\n VirtualList.prototype.setModel = function (model) {\n this.model = model;\n };\n VirtualList.prototype.destroy = function () {\n if (this.isDestroyed) {\n return;\n }\n this.clearVirtualRows();\n this.isDestroyed = true;\n _super.prototype.destroy.call(this);\n };\n __decorate$N([\n Autowired('resizeObserverService')\n ], VirtualList.prototype, \"resizeObserverService\", void 0);\n __decorate$N([\n Autowired('focusService')\n ], VirtualList.prototype, \"focusService\", void 0);\n __decorate$N([\n RefSelector('eContainer')\n ], VirtualList.prototype, \"eContainer\", void 0);\n __decorate$N([\n PostConstruct\n ], VirtualList.prototype, \"postConstruct\", null);\n return VirtualList;\n}(TabGuardComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar OUTSIDE_ANGULAR_EVENTS = ['mouseover', 'mouseout', 'mouseenter', 'mouseleave'];\nvar PASSIVE_EVENTS = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];\n/** The base frameworks, eg React & Angular, override this bean with implementations specific to their requirement. */\nvar VanillaFrameworkOverrides = /** @class */ (function () {\n function VanillaFrameworkOverrides() {\n this.isOutsideAngular = function (eventType) { return includes(OUTSIDE_ANGULAR_EVENTS, eventType); };\n }\n // for Vanilla JS, we use simple timeout\n VanillaFrameworkOverrides.prototype.setTimeout = function (action, timeout) {\n window.setTimeout(action, timeout);\n };\n VanillaFrameworkOverrides.prototype.setInterval = function (action, timeout) {\n return new AgPromise(function (resolve) {\n resolve(window.setInterval(action, timeout));\n });\n };\n // for Vanilla JS, we just add the event to the element\n VanillaFrameworkOverrides.prototype.addEventListener = function (element, type, listener, useCapture) {\n var isPassive = includes(PASSIVE_EVENTS, type);\n element.addEventListener(type, listener, { capture: !!useCapture, passive: isPassive });\n };\n // for Vanilla JS, we just execute the listener\n VanillaFrameworkOverrides.prototype.dispatchEvent = function (eventType, listener, global) {\n listener();\n };\n VanillaFrameworkOverrides.prototype.frameworkComponent = function (name) {\n return null;\n };\n VanillaFrameworkOverrides.prototype.isFrameworkComponent = function (comp) {\n return false;\n };\n return VanillaFrameworkOverrides;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$K = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$M = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$5 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$4 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$5(arguments[i]));\n return ar;\n};\nvar CellNavigationService = /** @class */ (function (_super) {\n __extends$K(CellNavigationService, _super);\n function CellNavigationService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n // returns null if no cell to focus on, ie at the end of the grid\n CellNavigationService.prototype.getNextCellToFocus = function (key, focusedCell, ctrlPressed) {\n if (ctrlPressed === void 0) { ctrlPressed = false; }\n if (ctrlPressed) {\n return this.getNextCellToFocusWithCtrlPressed(key, focusedCell);\n }\n return this.getNextCellToFocusWithoutCtrlPressed(key, focusedCell);\n };\n CellNavigationService.prototype.getNextCellToFocusWithCtrlPressed = function (key, focusedCell) {\n var upKey = key === KeyCode.UP;\n var downKey = key === KeyCode.DOWN;\n var leftKey = key === KeyCode.LEFT;\n var column;\n var rowIndex;\n if (upKey || downKey) {\n rowIndex = upKey ? this.paginationProxy.getPageFirstRow() : this.paginationProxy.getPageLastRow();\n column = focusedCell.column;\n }\n else {\n var allColumns = this.columnModel.getAllDisplayedColumns();\n var isRtl = this.gridOptionsWrapper.isEnableRtl();\n rowIndex = focusedCell.rowIndex;\n column = leftKey !== isRtl ? allColumns[0] : last(allColumns);\n }\n return {\n rowIndex: rowIndex,\n rowPinned: null,\n column: column\n };\n };\n CellNavigationService.prototype.getNextCellToFocusWithoutCtrlPressed = function (key, focusedCell) {\n // starting with the provided cell, we keep moving until we find a cell we can\n // focus on.\n var pointer = focusedCell;\n var finished = false;\n // finished will be true when either:\n // a) cell found that we can focus on\n // b) run out of cells (ie the method returns null)\n while (!finished) {\n switch (key) {\n case KeyCode.UP:\n pointer = this.getCellAbove(pointer);\n break;\n case KeyCode.DOWN:\n pointer = this.getCellBelow(pointer);\n break;\n case KeyCode.RIGHT:\n if (this.gridOptionsWrapper.isEnableRtl()) {\n pointer = this.getCellToLeft(pointer);\n }\n else {\n pointer = this.getCellToRight(pointer);\n }\n break;\n case KeyCode.LEFT:\n if (this.gridOptionsWrapper.isEnableRtl()) {\n pointer = this.getCellToRight(pointer);\n }\n else {\n pointer = this.getCellToLeft(pointer);\n }\n break;\n default:\n pointer = null;\n console.warn('AG Grid: unknown key for navigation ' + key);\n break;\n }\n if (pointer) {\n finished = this.isCellGoodToFocusOn(pointer);\n }\n else {\n finished = true;\n }\n }\n return pointer;\n };\n CellNavigationService.prototype.isCellGoodToFocusOn = function (gridCell) {\n var column = gridCell.column;\n var rowNode;\n switch (gridCell.rowPinned) {\n case Constants.PINNED_TOP:\n rowNode = this.pinnedRowModel.getPinnedTopRow(gridCell.rowIndex);\n break;\n case Constants.PINNED_BOTTOM:\n rowNode = this.pinnedRowModel.getPinnedBottomRow(gridCell.rowIndex);\n break;\n default:\n rowNode = this.rowModel.getRow(gridCell.rowIndex);\n break;\n }\n if (!rowNode) {\n return false;\n }\n var suppressNavigable = column.isSuppressNavigable(rowNode);\n return !suppressNavigable;\n };\n CellNavigationService.prototype.getCellToLeft = function (lastCell) {\n if (!lastCell) {\n return null;\n }\n var colToLeft = this.columnModel.getDisplayedColBefore(lastCell.column);\n if (!colToLeft) {\n return null;\n }\n return {\n rowIndex: lastCell.rowIndex,\n column: colToLeft,\n rowPinned: lastCell.rowPinned\n };\n };\n CellNavigationService.prototype.getCellToRight = function (lastCell) {\n if (!lastCell) {\n return null;\n }\n var colToRight = this.columnModel.getDisplayedColAfter(lastCell.column);\n // if already on right, do nothing\n if (!colToRight) {\n return null;\n }\n return {\n rowIndex: lastCell.rowIndex,\n column: colToRight,\n rowPinned: lastCell.rowPinned\n };\n };\n CellNavigationService.prototype.getRowBelow = function (rowPosition) {\n // if already on top row, do nothing\n var index = rowPosition.rowIndex;\n var pinned = rowPosition.rowPinned;\n if (this.isLastRowInContainer(rowPosition)) {\n switch (pinned) {\n case Constants.PINNED_BOTTOM:\n // never any rows after pinned bottom\n return null;\n case Constants.PINNED_TOP:\n // if on last row of pinned top, then next row is main body (if rows exist),\n // otherwise it's the pinned bottom\n if (this.rowModel.isRowsToRender()) {\n return { rowIndex: this.paginationProxy.getPageFirstRow(), rowPinned: null };\n }\n if (this.pinnedRowModel.isRowsToRender(Constants.PINNED_BOTTOM)) {\n return { rowIndex: 0, rowPinned: Constants.PINNED_BOTTOM };\n }\n return null;\n default:\n // if in the main body, then try pinned bottom, otherwise return nothing\n if (this.pinnedRowModel.isRowsToRender(Constants.PINNED_BOTTOM)) {\n return { rowIndex: 0, rowPinned: Constants.PINNED_BOTTOM };\n }\n return null;\n }\n }\n var rowNode = this.rowModel.getRow(rowPosition.rowIndex);\n var nextStickyPosition = this.getNextStickyPosition(rowNode);\n if (nextStickyPosition) {\n return nextStickyPosition;\n }\n return { rowIndex: index + 1, rowPinned: pinned };\n };\n CellNavigationService.prototype.getNextStickyPosition = function (rowNode, up) {\n if (!this.gridOptionsWrapper.isGroupRowsSticky() || !rowNode || !rowNode.sticky) {\n return;\n }\n var stickyRowCtrls = __spread$4(this.rowRenderer.getStickyTopRowCtrls()).sort(function (a, b) { return a.getRowNode().rowIndex - b.getRowNode().rowIndex; });\n var diff = up ? -1 : 1;\n var idx = stickyRowCtrls.findIndex(function (ctrl) { return ctrl.getRowNode().rowIndex === rowNode.rowIndex; });\n var nextCtrl = stickyRowCtrls[idx + diff];\n if (nextCtrl) {\n return { rowIndex: nextCtrl.getRowNode().rowIndex, rowPinned: null };\n }\n };\n CellNavigationService.prototype.getCellBelow = function (lastCell) {\n if (!lastCell) {\n return null;\n }\n var rowBelow = this.getRowBelow(lastCell);\n if (rowBelow) {\n return {\n rowIndex: rowBelow.rowIndex,\n column: lastCell.column,\n rowPinned: rowBelow.rowPinned\n };\n }\n return null;\n };\n CellNavigationService.prototype.isLastRowInContainer = function (rowPosition) {\n var pinned = rowPosition.rowPinned;\n var index = rowPosition.rowIndex;\n if (pinned === Constants.PINNED_TOP) {\n var lastTopIndex = this.pinnedRowModel.getPinnedTopRowData().length - 1;\n return lastTopIndex <= index;\n }\n if (pinned === Constants.PINNED_BOTTOM) {\n var lastBottomIndex = this.pinnedRowModel.getPinnedBottomRowData().length - 1;\n return lastBottomIndex <= index;\n }\n var lastBodyIndex = this.paginationProxy.getPageLastRow();\n return lastBodyIndex <= index;\n };\n CellNavigationService.prototype.getRowAbove = function (rowPosition) {\n // if already on top row, do nothing\n var index = rowPosition.rowIndex;\n var pinned = rowPosition.rowPinned;\n var isFirstRow = pinned ? index === 0 : index === this.paginationProxy.getPageFirstRow();\n // if already on top row, do nothing\n if (isFirstRow) {\n if (pinned === Constants.PINNED_TOP) {\n return null;\n }\n if (!pinned) {\n if (this.pinnedRowModel.isRowsToRender(Constants.PINNED_TOP)) {\n return this.getLastFloatingTopRow();\n }\n return null;\n }\n // last floating bottom\n if (this.rowModel.isRowsToRender()) {\n return this.getLastBodyCell();\n }\n if (this.pinnedRowModel.isRowsToRender(Constants.PINNED_TOP)) {\n return this.getLastFloatingTopRow();\n }\n return null;\n }\n var rowNode = this.rowModel.getRow(rowPosition.rowIndex);\n var nextStickyPosition = this.getNextStickyPosition(rowNode, true);\n if (nextStickyPosition) {\n return nextStickyPosition;\n }\n return { rowIndex: index - 1, rowPinned: pinned };\n };\n CellNavigationService.prototype.getCellAbove = function (lastCell) {\n if (!lastCell) {\n return null;\n }\n var rowAbove = this.getRowAbove({ rowIndex: lastCell.rowIndex, rowPinned: lastCell.rowPinned });\n if (rowAbove) {\n return {\n rowIndex: rowAbove.rowIndex,\n column: lastCell.column,\n rowPinned: rowAbove.rowPinned\n };\n }\n return null;\n };\n CellNavigationService.prototype.getLastBodyCell = function () {\n var lastBodyRow = this.paginationProxy.getPageLastRow();\n return { rowIndex: lastBodyRow, rowPinned: null };\n };\n CellNavigationService.prototype.getLastFloatingTopRow = function () {\n var lastFloatingRow = this.pinnedRowModel.getPinnedTopRowData().length - 1;\n return { rowIndex: lastFloatingRow, rowPinned: Constants.PINNED_TOP };\n };\n CellNavigationService.prototype.getNextTabbedCell = function (gridCell, backwards) {\n if (backwards) {\n return this.getNextTabbedCellBackwards(gridCell);\n }\n return this.getNextTabbedCellForwards(gridCell);\n };\n CellNavigationService.prototype.getNextTabbedCellForwards = function (gridCell) {\n var displayedColumns = this.columnModel.getAllDisplayedColumns();\n var newRowIndex = gridCell.rowIndex;\n var newFloating = gridCell.rowPinned;\n // move along to the next cell\n var newColumn = this.columnModel.getDisplayedColAfter(gridCell.column);\n // check if end of the row, and if so, go forward a row\n if (!newColumn) {\n newColumn = displayedColumns[0];\n var rowBelow = this.getRowBelow(gridCell);\n if (missing(rowBelow)) {\n return null;\n }\n // If we are tabbing and there is a paging panel present, tabbing should go\n // to the paging panel instead of loading the next page.\n if (!rowBelow.rowPinned && !this.paginationProxy.isRowInPage(rowBelow)) {\n return null;\n }\n newRowIndex = rowBelow ? rowBelow.rowIndex : null;\n newFloating = rowBelow ? rowBelow.rowPinned : null;\n }\n return { rowIndex: newRowIndex, column: newColumn, rowPinned: newFloating };\n };\n CellNavigationService.prototype.getNextTabbedCellBackwards = function (gridCell) {\n var displayedColumns = this.columnModel.getAllDisplayedColumns();\n var newRowIndex = gridCell.rowIndex;\n var newFloating = gridCell.rowPinned;\n // move along to the next cell\n var newColumn = this.columnModel.getDisplayedColBefore(gridCell.column);\n // check if end of the row, and if so, go forward a row\n if (!newColumn) {\n newColumn = last(displayedColumns);\n var rowAbove = this.getRowAbove({ rowIndex: gridCell.rowIndex, rowPinned: gridCell.rowPinned });\n if (missing(rowAbove)) {\n return null;\n }\n // If we are tabbing and there is a paging panel present, tabbing should go\n // to the paging panel instead of loading the next page.\n if (!rowAbove.rowPinned && !this.paginationProxy.isRowInPage(rowAbove)) {\n return null;\n }\n newRowIndex = rowAbove ? rowAbove.rowIndex : null;\n newFloating = rowAbove ? rowAbove.rowPinned : null;\n }\n return { rowIndex: newRowIndex, column: newColumn, rowPinned: newFloating };\n };\n __decorate$M([\n Autowired('columnModel')\n ], CellNavigationService.prototype, \"columnModel\", void 0);\n __decorate$M([\n Autowired('rowModel')\n ], CellNavigationService.prototype, \"rowModel\", void 0);\n __decorate$M([\n Autowired('rowRenderer')\n ], CellNavigationService.prototype, \"rowRenderer\", void 0);\n __decorate$M([\n Autowired('pinnedRowModel')\n ], CellNavigationService.prototype, \"pinnedRowModel\", void 0);\n __decorate$M([\n Autowired('paginationProxy')\n ], CellNavigationService.prototype, \"paginationProxy\", void 0);\n CellNavigationService = __decorate$M([\n Bean('cellNavigationService')\n ], CellNavigationService);\n return CellNavigationService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$J = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$L = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$5 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar AlignedGridsService = /** @class */ (function (_super) {\n __extends$J(AlignedGridsService, _super);\n function AlignedGridsService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n // flag to mark if we are consuming. to avoid cyclic events (ie other grid firing back to master\n // while processing a master event) we mark this if consuming an event, and if we are, then\n // we don't fire back any events.\n _this.consuming = false;\n return _this;\n }\n AlignedGridsService.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('AlignedGridsService');\n };\n AlignedGridsService.prototype.init = function () {\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_MOVED, this.fireColumnEvent.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_VISIBLE, this.fireColumnEvent.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PINNED, this.fireColumnEvent.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_GROUP_OPENED, this.fireColumnEvent.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_RESIZED, this.fireColumnEvent.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_BODY_SCROLL, this.fireScrollEvent.bind(this));\n };\n // common logic across all the fire methods\n AlignedGridsService.prototype.fireEvent = function (callback) {\n // if we are already consuming, then we are acting on an event from a master,\n // so we don't cause a cyclic firing of events\n if (this.consuming) {\n return;\n }\n // iterate through the aligned grids, and pass each aligned grid service to the callback\n var otherGrids = this.gridOptionsWrapper.getAlignedGrids();\n if (otherGrids) {\n otherGrids.forEach(function (otherGridOptions) {\n if (otherGridOptions.api) {\n var alignedGridService = otherGridOptions.api.__getAlignedGridService();\n callback(alignedGridService);\n }\n });\n }\n };\n // common logic across all consume methods. very little common logic, however extracting\n // guarantees consistency across the methods.\n AlignedGridsService.prototype.onEvent = function (callback) {\n this.consuming = true;\n callback();\n this.consuming = false;\n };\n AlignedGridsService.prototype.fireColumnEvent = function (event) {\n this.fireEvent(function (alignedGridsService) {\n alignedGridsService.onColumnEvent(event);\n });\n };\n AlignedGridsService.prototype.fireScrollEvent = function (event) {\n if (event.direction !== 'horizontal') {\n return;\n }\n this.fireEvent(function (alignedGridsService) {\n alignedGridsService.onScrollEvent(event);\n });\n };\n AlignedGridsService.prototype.onScrollEvent = function (event) {\n var _this = this;\n this.onEvent(function () {\n var gridBodyCon = _this.ctrlsService.getGridBodyCtrl();\n gridBodyCon.getScrollFeature().setHorizontalScrollPosition(event.left);\n });\n };\n AlignedGridsService.prototype.getMasterColumns = function (event) {\n var result = [];\n if (event.columns) {\n event.columns.forEach(function (column) {\n result.push(column);\n });\n }\n else if (event.column) {\n result.push(event.column);\n }\n return result;\n };\n AlignedGridsService.prototype.getColumnIds = function (event) {\n var result = [];\n if (event.columns) {\n event.columns.forEach(function (column) {\n result.push(column.getColId());\n });\n }\n else if (event.column) {\n result.push(event.column.getColId());\n }\n return result;\n };\n AlignedGridsService.prototype.onColumnEvent = function (event) {\n var _this = this;\n this.onEvent(function () {\n switch (event.type) {\n case Events.EVENT_COLUMN_MOVED:\n case Events.EVENT_COLUMN_VISIBLE:\n case Events.EVENT_COLUMN_PINNED:\n case Events.EVENT_COLUMN_RESIZED:\n var colEvent = event;\n _this.processColumnEvent(colEvent);\n break;\n case Events.EVENT_COLUMN_GROUP_OPENED:\n var groupOpenedEvent = event;\n _this.processGroupOpenedEvent(groupOpenedEvent);\n break;\n case Events.EVENT_COLUMN_PIVOT_CHANGED:\n // we cannot support pivoting with aligned grids as the columns will be out of sync as the\n // grids will have columns created based on the row data of the grid.\n console.warn('AG Grid: pivoting is not supported with aligned grids. ' +\n 'You can only use one of these features at a time in a grid.');\n break;\n }\n });\n };\n AlignedGridsService.prototype.processGroupOpenedEvent = function (groupOpenedEvent) {\n // likewise for column group\n var masterColumnGroup = groupOpenedEvent.columnGroup;\n var otherColumnGroup = null;\n if (masterColumnGroup) {\n var groupId = masterColumnGroup.getGroupId();\n otherColumnGroup = this.columnModel.getProvidedColumnGroup(groupId);\n }\n if (masterColumnGroup && !otherColumnGroup) {\n return;\n }\n this.logger.log('onColumnEvent-> processing ' + groupOpenedEvent + ' expanded = ' + masterColumnGroup.isExpanded());\n this.columnModel.setColumnGroupOpened(otherColumnGroup, masterColumnGroup.isExpanded(), \"alignedGridChanged\");\n };\n AlignedGridsService.prototype.processColumnEvent = function (colEvent) {\n var _this = this;\n var _a;\n // the column in the event is from the master grid. need to\n // look up the equivalent from this (other) grid\n var masterColumn = colEvent.column;\n var otherColumn = null;\n if (masterColumn) {\n otherColumn = this.columnModel.getPrimaryColumn(masterColumn.getColId());\n }\n // if event was with respect to a master column, that is not present in this\n // grid, then we ignore the event\n if (masterColumn && !otherColumn) {\n return;\n }\n // in time, all the methods below should use the column ids, it's a more generic way\n // of handling columns, and also allows for single or multi column events\n var masterColumns = this.getMasterColumns(colEvent);\n switch (colEvent.type) {\n case Events.EVENT_COLUMN_MOVED:\n // when the user moves columns via setColumnState, we can't depend on moving specific columns\n // to an index, as there maybe be many indexes columns moved to (as wasn't result of a mouse drag).\n // so only way to be sure is match the order of all columns using Column State.\n {\n var movedEvent = colEvent;\n var srcColState = colEvent.columnApi.getColumnState();\n var destColState = srcColState.map(function (s) { return ({ colId: s.colId }); });\n this.columnModel.applyColumnState({ state: destColState, applyOrder: true }, \"alignedGridChanged\");\n this.logger.log(\"onColumnEvent-> processing \" + colEvent.type + \" toIndex = \" + movedEvent.toIndex);\n }\n break;\n case Events.EVENT_COLUMN_VISIBLE:\n // when the user changes visibility via setColumnState, we can't depend on visibility flag in event\n // as there maybe be mix of true/false (as wasn't result of a mouse click to set visiblity).\n // so only way to be sure is match the visibility of all columns using Column State.\n {\n var visibleEvent = colEvent;\n var srcColState = colEvent.columnApi.getColumnState();\n var destColState = srcColState.map(function (s) { return ({ colId: s.colId, hide: s.hide }); });\n this.columnModel.applyColumnState({ state: destColState }, \"alignedGridChanged\");\n this.logger.log(\"onColumnEvent-> processing \" + colEvent.type + \" visible = \" + visibleEvent.visible);\n }\n break;\n case Events.EVENT_COLUMN_PINNED:\n {\n var pinnedEvent = colEvent;\n var srcColState = colEvent.columnApi.getColumnState();\n var destColState = srcColState.map(function (s) { return ({ colId: s.colId, pinned: s.pinned }); });\n this.columnModel.applyColumnState({ state: destColState }, \"alignedGridChanged\");\n this.logger.log(\"onColumnEvent-> processing \" + colEvent.type + \" pinned = \" + pinnedEvent.pinned);\n }\n break;\n case Events.EVENT_COLUMN_RESIZED:\n var resizedEvent = colEvent;\n var columnWidths_1 = {};\n masterColumns.forEach(function (column) {\n _this.logger.log(\"onColumnEvent-> processing \" + colEvent.type + \" actualWidth = \" + column.getActualWidth());\n columnWidths_1[column.getId()] = { key: column.getColId(), newWidth: column.getActualWidth() };\n });\n // don't set flex columns width\n (_a = resizedEvent.flexColumns) === null || _a === void 0 ? void 0 : _a.forEach(function (col) {\n if (columnWidths_1[col.getId()]) {\n delete columnWidths_1[col.getId()];\n }\n });\n this.columnModel.setColumnWidths(Object.values(columnWidths_1), false, resizedEvent.finished, \"alignedGridChanged\");\n break;\n }\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var isVerticalScrollShowing = gridBodyCon.isVerticalScrollShowing();\n var alignedGrids = this.gridOptionsWrapper.getAlignedGrids();\n if (alignedGrids) {\n alignedGrids.forEach(function (grid) {\n if (grid.api) {\n grid.api.setAlwaysShowVerticalScroll(isVerticalScrollShowing);\n }\n });\n }\n };\n __decorate$L([\n Autowired('columnModel')\n ], AlignedGridsService.prototype, \"columnModel\", void 0);\n __decorate$L([\n Autowired('ctrlsService')\n ], AlignedGridsService.prototype, \"ctrlsService\", void 0);\n __decorate$L([\n __param$5(0, Qualifier('loggerFactory'))\n ], AlignedGridsService.prototype, \"setBeans\", null);\n __decorate$L([\n PostConstruct\n ], AlignedGridsService.prototype, \"init\", null);\n AlignedGridsService = __decorate$L([\n Bean('alignedGridsService')\n ], AlignedGridsService);\n return AlignedGridsService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$I = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$K = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$4 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar SelectionService = /** @class */ (function (_super) {\n __extends$I(SelectionService, _super);\n function SelectionService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SelectionService.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('selectionService');\n this.reset();\n };\n SelectionService.prototype.init = function () {\n this.groupSelectsChildren = this.gridOptionsWrapper.isGroupSelectsChildren();\n this.addManagedListener(this.eventService, Events.EVENT_ROW_SELECTED, this.onRowSelected.bind(this));\n };\n SelectionService.prototype.setLastSelectedNode = function (rowNode) {\n this.lastSelectedNode = rowNode;\n };\n SelectionService.prototype.getLastSelectedNode = function () {\n return this.lastSelectedNode;\n };\n SelectionService.prototype.getSelectedNodes = function () {\n var selectedNodes = [];\n iterateObject(this.selectedNodes, function (key, rowNode) {\n if (rowNode) {\n selectedNodes.push(rowNode);\n }\n });\n return selectedNodes;\n };\n SelectionService.prototype.getSelectedRows = function () {\n var selectedRows = [];\n iterateObject(this.selectedNodes, function (key, rowNode) {\n if (rowNode && rowNode.data) {\n selectedRows.push(rowNode.data);\n }\n });\n return selectedRows;\n };\n SelectionService.prototype.removeGroupsFromSelection = function () {\n var _this = this;\n iterateObject(this.selectedNodes, function (key, rowNode) {\n if (rowNode && rowNode.group) {\n _this.selectedNodes[rowNode.id] = undefined;\n }\n });\n };\n // should only be called if groupSelectsChildren=true\n SelectionService.prototype.updateGroupsFromChildrenSelections = function (changedPath) {\n // we only do this when group selection state depends on selected children\n if (!this.gridOptionsWrapper.isGroupSelectsChildren()) {\n return;\n }\n // also only do it if CSRM (code should never allow this anyway)\n if (this.rowModel.getType() !== Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n return;\n }\n var clientSideRowModel = this.rowModel;\n var rootNode = clientSideRowModel.getRootNode();\n if (!changedPath) {\n changedPath = new ChangedPath(true, rootNode);\n changedPath.setInactive();\n }\n changedPath.forEachChangedNodeDepthFirst(function (rowNode) {\n if (rowNode !== rootNode) {\n var selected = rowNode.calculateSelectedFromChildren();\n rowNode.selectThisNode(selected === null ? false : selected);\n }\n });\n // clientSideRowModel.getTopLevelNodes()!.forEach((rowNode: RowNode) => {\n // rowNode.depthFirstSearch((node) => {\n // if (node.group) {\n // }\n // });\n // });\n };\n SelectionService.prototype.getNodeForIdIfSelected = function (id) {\n return this.selectedNodes[id];\n };\n SelectionService.prototype.clearOtherNodes = function (rowNodeToKeepSelected) {\n var _this = this;\n var groupsToRefresh = {};\n var updatedCount = 0;\n iterateObject(this.selectedNodes, function (key, otherRowNode) {\n if (otherRowNode && otherRowNode.id !== rowNodeToKeepSelected.id) {\n var rowNode = _this.selectedNodes[otherRowNode.id];\n updatedCount += rowNode.setSelectedParams({\n newValue: false,\n clearSelection: false,\n suppressFinishActions: true\n });\n if (_this.groupSelectsChildren && otherRowNode.parent) {\n groupsToRefresh[otherRowNode.parent.id] = otherRowNode.parent;\n }\n }\n });\n iterateObject(groupsToRefresh, function (key, group) {\n var selected = group.calculateSelectedFromChildren();\n group.selectThisNode(selected === null ? false : selected);\n });\n return updatedCount;\n };\n SelectionService.prototype.onRowSelected = function (event) {\n var rowNode = event.node;\n // we do not store the group rows when the groups select children\n if (this.groupSelectsChildren && rowNode.group) {\n return;\n }\n if (rowNode.isSelected()) {\n this.selectedNodes[rowNode.id] = rowNode;\n }\n else {\n this.selectedNodes[rowNode.id] = undefined;\n }\n };\n SelectionService.prototype.syncInRowNode = function (rowNode, oldNode) {\n this.syncInOldRowNode(rowNode, oldNode);\n this.syncInNewRowNode(rowNode);\n };\n // if the id has changed for the node, then this means the rowNode\n // is getting used for a different data item, which breaks\n // our selectedNodes, as the node now is mapped by the old id\n // which is inconsistent. so to keep the old node as selected,\n // we swap in the clone (with the old id and old data). this means\n // the oldNode is effectively a daemon we keep a reference to,\n // so if client calls api.getSelectedNodes(), it gets the daemon\n // in the result. when the client un-selects, the reference to the\n // daemon is removed. the daemon, because it's an oldNode, is not\n // used by the grid for rendering, it's a copy of what the node used\n // to be like before the id was changed.\n SelectionService.prototype.syncInOldRowNode = function (rowNode, oldNode) {\n var oldNodeHasDifferentId = exists(oldNode) && (rowNode.id !== oldNode.id);\n if (oldNodeHasDifferentId && oldNode) {\n var id = oldNode.id;\n var oldNodeSelected = this.selectedNodes[id] == rowNode;\n if (oldNodeSelected) {\n this.selectedNodes[oldNode.id] = oldNode;\n }\n }\n };\n SelectionService.prototype.syncInNewRowNode = function (rowNode) {\n if (exists(this.selectedNodes[rowNode.id])) {\n rowNode.setSelectedInitialValue(true);\n this.selectedNodes[rowNode.id] = rowNode;\n }\n else {\n rowNode.setSelectedInitialValue(false);\n }\n };\n SelectionService.prototype.reset = function () {\n this.logger.log('reset');\n this.selectedNodes = {};\n this.lastSelectedNode = null;\n };\n // returns a list of all nodes at 'best cost' - a feature to be used\n // with groups / trees. if a group has all it's children selected,\n // then the group appears in the result, but not the children.\n // Designed for use with 'children' as the group selection type,\n // where groups don't actually appear in the selection normally.\n SelectionService.prototype.getBestCostNodeSelection = function () {\n if (this.rowModel.getType() !== Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n console.warn('AG Grid: `getBestCostNodeSelection` is only available when using normal row model');\n return;\n }\n var clientSideRowModel = this.rowModel;\n var topLevelNodes = clientSideRowModel.getTopLevelNodes();\n if (topLevelNodes === null) {\n console.warn('AG Grid: `selectAll` not available doing `rowModel=virtual`');\n return;\n }\n var result = [];\n // recursive function, to find the selected nodes\n function traverse(nodes) {\n for (var i = 0, l = nodes.length; i < l; i++) {\n var node = nodes[i];\n if (node.isSelected()) {\n result.push(node);\n }\n else {\n // if not selected, then if it's a group, and the group\n // has children, continue to search for selections\n var maybeGroup = node;\n if (maybeGroup.group && maybeGroup.children) {\n traverse(maybeGroup.children);\n }\n }\n }\n }\n traverse(topLevelNodes);\n return result;\n };\n SelectionService.prototype.setRowModel = function (rowModel) {\n this.rowModel = rowModel;\n };\n SelectionService.prototype.isEmpty = function () {\n var count = 0;\n iterateObject(this.selectedNodes, function (nodeId, rowNode) {\n if (rowNode) {\n count++;\n }\n });\n return count === 0;\n };\n SelectionService.prototype.deselectAllRowNodes = function (justFiltered) {\n if (justFiltered === void 0) { justFiltered = false; }\n var callback = function (rowNode) { return rowNode.selectThisNode(false); };\n var rowModelClientSide = this.rowModel.getType() === Constants.ROW_MODEL_TYPE_CLIENT_SIDE;\n if (justFiltered) {\n if (!rowModelClientSide) {\n console.error('AG Grid: selecting just filtered only works with In Memory Row Model');\n return;\n }\n var clientSideRowModel = this.rowModel;\n clientSideRowModel.forEachNodeAfterFilter(callback);\n }\n else {\n iterateObject(this.selectedNodes, function (id, rowNode) {\n // remember the reference can be to null, as we never 'delete' from the map\n if (rowNode) {\n callback(rowNode);\n }\n });\n // this clears down the map (whereas above only sets the items in map to 'undefined')\n this.reset();\n }\n // the above does not clean up the parent rows if they are selected\n if (rowModelClientSide && this.groupSelectsChildren) {\n this.updateGroupsFromChildrenSelections();\n }\n var event = {\n type: Events.EVENT_SELECTION_CHANGED,\n };\n this.eventService.dispatchEvent(event);\n };\n SelectionService.prototype.selectAllRowNodes = function (justFiltered) {\n if (justFiltered === void 0) { justFiltered = false; }\n if (this.rowModel.getType() !== Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n throw new Error(\"selectAll only available with normal row model, ie not \" + this.rowModel.getType());\n }\n var clientSideRowModel = this.rowModel;\n var callback = function (rowNode) { return rowNode.selectThisNode(true); };\n if (justFiltered) {\n clientSideRowModel.forEachNodeAfterFilter(callback);\n }\n else {\n clientSideRowModel.forEachNode(callback);\n }\n // the above does not clean up the parent rows if they are selected\n if (this.rowModel.getType() === Constants.ROW_MODEL_TYPE_CLIENT_SIDE && this.groupSelectsChildren) {\n this.updateGroupsFromChildrenSelections();\n }\n var event = {\n type: Events.EVENT_SELECTION_CHANGED,\n };\n this.eventService.dispatchEvent(event);\n };\n /**\n * @method\n * @deprecated\n */\n SelectionService.prototype.selectNode = function (rowNode, tryMulti) {\n if (rowNode) {\n rowNode.setSelectedParams({ newValue: true, clearSelection: !tryMulti });\n }\n };\n /**\n * @method\n * @deprecated\n */\n SelectionService.prototype.deselectIndex = function (rowIndex) {\n var node = this.rowModel.getRow(rowIndex);\n this.deselectNode(node);\n };\n /**\n * @method\n * @deprecated\n */\n SelectionService.prototype.deselectNode = function (rowNode) {\n if (rowNode) {\n rowNode.setSelectedParams({ newValue: false, clearSelection: false });\n }\n };\n /**\n * @method\n * @deprecated\n */\n SelectionService.prototype.selectIndex = function (index, tryMulti) {\n var node = this.rowModel.getRow(index);\n this.selectNode(node, tryMulti);\n };\n __decorate$K([\n Autowired('rowModel')\n ], SelectionService.prototype, \"rowModel\", void 0);\n __decorate$K([\n __param$4(0, Qualifier('loggerFactory'))\n ], SelectionService.prototype, \"setBeans\", null);\n __decorate$K([\n PostConstruct\n ], SelectionService.prototype, \"init\", null);\n SelectionService = __decorate$K([\n Bean('selectionService')\n ], SelectionService);\n return SelectionService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$J = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ColumnApi = /** @class */ (function () {\n function ColumnApi() {\n }\n /** Gets the grid to size the columns to the specified width in pixels, e.g. `sizeColumnsToFit(900)`. To have the grid fit the columns to the grid's width, use the Grid API `gridApi.sizeColumnsToFit()` instead. */\n ColumnApi.prototype.sizeColumnsToFit = function (gridWidth) {\n // AG-3403 validate that gridWidth is provided because this method has the same name as\n // a method on the grid API that takes no arguments, and it's easy to confuse the two\n if (typeof gridWidth === \"undefined\") {\n console.error('AG Grid: missing parameter to columnApi.sizeColumnsToFit(gridWidth)');\n }\n this.columnModel.sizeColumnsToFit(gridWidth, 'api');\n };\n /** Call this if you want to open or close a column group. */\n ColumnApi.prototype.setColumnGroupOpened = function (group, newValue) { this.columnModel.setColumnGroupOpened(group, newValue, 'api'); };\n /** Returns the column group with the given name. */\n ColumnApi.prototype.getColumnGroup = function (name, instanceId) { return this.columnModel.getColumnGroup(name, instanceId); };\n /** Returns the provided column group with the given name. */\n ColumnApi.prototype.getProvidedColumnGroup = function (name) { return this.columnModel.getProvidedColumnGroup(name); };\n /** Returns the display name for a column. Useful if you are doing your own header rendering and want the grid to work out if `headerValueGetter` is used, or if you are doing your own column management GUI, to know what to show as the column name. */\n ColumnApi.prototype.getDisplayNameForColumn = function (column, location) { return this.columnModel.getDisplayNameForColumn(column, location) || ''; };\n /** Returns the display name for a column group (when grouping columns). */\n ColumnApi.prototype.getDisplayNameForColumnGroup = function (columnGroup, location) { return this.columnModel.getDisplayNameForColumnGroup(columnGroup, location) || ''; };\n /** Returns the column with the given `colKey`, which can either be the `colId` (a string) or the `colDef` (an object). */\n ColumnApi.prototype.getColumn = function (key) { return this.columnModel.getPrimaryColumn(key); };\n /** Returns all the columns, regardless of visible or not. */\n ColumnApi.prototype.getColumns = function () { return this.columnModel.getAllPrimaryColumns(); };\n /** Applies the state of the columns from a previous state. Returns `false` if one or more columns could not be found. */\n ColumnApi.prototype.applyColumnState = function (params) { return this.columnModel.applyColumnState(params, 'api'); };\n /** Gets the state of the columns. Typically used when saving column state. */\n ColumnApi.prototype.getColumnState = function () { return this.columnModel.getColumnState(); };\n /** Sets the state back to match the originally provided column definitions. */\n ColumnApi.prototype.resetColumnState = function () { this.columnModel.resetColumnState('api'); };\n /** Gets the state of the column groups. Typically used when saving column group state. */\n ColumnApi.prototype.getColumnGroupState = function () { return this.columnModel.getColumnGroupState(); };\n /** Sets the state of the column group state from a previous state. */\n ColumnApi.prototype.setColumnGroupState = function (stateItems) { this.columnModel.setColumnGroupState(stateItems, 'api'); };\n /** Sets the state back to match the originally provided column definitions. */\n ColumnApi.prototype.resetColumnGroupState = function () { this.columnModel.resetColumnGroupState('api'); };\n /** Returns `true` if pinning left or right, otherwise `false`. */\n ColumnApi.prototype.isPinning = function () { return this.columnModel.isPinningLeft() || this.columnModel.isPinningRight(); };\n /** Returns `true` if pinning left, otherwise `false`. */\n ColumnApi.prototype.isPinningLeft = function () { return this.columnModel.isPinningLeft(); };\n /** Returns `true` if pinning right, otherwise `false`. */\n ColumnApi.prototype.isPinningRight = function () { return this.columnModel.isPinningRight(); };\n /** Returns the column to the right of the provided column, taking into consideration open / closed column groups and visible columns. This is useful if you need to know what column is beside yours e.g. if implementing your own cell navigation. */\n ColumnApi.prototype.getDisplayedColAfter = function (col) { return this.columnModel.getDisplayedColAfter(col); };\n /** Same as `getVisibleColAfter` except gives column to the left. */\n ColumnApi.prototype.getDisplayedColBefore = function (col) { return this.columnModel.getDisplayedColBefore(col); };\n /** Sets the visibility of a column. Key can be the column ID or `Column` object. */\n ColumnApi.prototype.setColumnVisible = function (key, visible) { this.columnModel.setColumnVisible(key, visible, 'api'); };\n /** Same as `setColumnVisible`, but provide a list of column keys. */\n ColumnApi.prototype.setColumnsVisible = function (keys, visible) { this.columnModel.setColumnsVisible(keys, visible, 'api'); };\n /** Sets the column pinned / unpinned. Key can be the column ID, field, `ColDef` object or `Column` object. */\n ColumnApi.prototype.setColumnPinned = function (key, pinned) { this.columnModel.setColumnPinned(key, pinned, 'api'); };\n /** Same as `setColumnPinned`, but provide a list of column keys. */\n ColumnApi.prototype.setColumnsPinned = function (keys, pinned) { this.columnModel.setColumnsPinned(keys, pinned, 'api'); };\n /**\n * Returns all the grid columns, same as `getColumns()`, except\n *\n * a) it has the order of the columns that are presented in the grid\n *\n * b) it's after the 'pivot' step, so if pivoting, has the value columns for the pivot.\n */\n ColumnApi.prototype.getAllGridColumns = function () { return this.columnModel.getAllGridColumns(); };\n /** Same as `getAllDisplayedColumns` but just for the pinned left portion of the grid. */\n ColumnApi.prototype.getDisplayedLeftColumns = function () { return this.columnModel.getDisplayedLeftColumns(); };\n /** Same as `getAllDisplayedColumns` but just for the center portion of the grid. */\n ColumnApi.prototype.getDisplayedCenterColumns = function () { return this.columnModel.getDisplayedCenterColumns(); };\n /** Same as `getAllDisplayedColumns` but just for the pinned right portion of the grid. */\n ColumnApi.prototype.getDisplayedRightColumns = function () { return this.columnModel.getDisplayedRightColumns(); };\n /** Returns all columns currently displayed (e.g. are visible and if in a group, the group is showing the columns) for the pinned left, centre and pinned right portions of the grid. */\n ColumnApi.prototype.getAllDisplayedColumns = function () { return this.columnModel.getAllDisplayedColumns(); };\n /** Same as `getAllGridColumns()`, except only returns rendered columns, i.e. columns that are not within the viewport and therefore not rendered, due to column virtualisation, are not displayed. */\n ColumnApi.prototype.getAllDisplayedVirtualColumns = function () { return this.columnModel.getViewportColumns(); };\n /** Moves a column to `toIndex`. The column is first removed, then added at the `toIndex` location, thus index locations will change to the right of the column after the removal. */\n ColumnApi.prototype.moveColumn = function (key, toIndex) {\n if (typeof key === 'number') {\n // moveColumn used to take indexes, so this is advising user who hasn't moved to new method name\n console.warn('AG Grid: you are using moveColumn(fromIndex, toIndex) - moveColumn takes a column key and a destination index, not two indexes, to move with indexes use moveColumnByIndex(from,to) instead');\n this.columnModel.moveColumnByIndex(key, toIndex, 'api');\n }\n else {\n this.columnModel.moveColumn(key, toIndex, 'api');\n }\n };\n /** Same as `moveColumn` but works on index locations. */\n ColumnApi.prototype.moveColumnByIndex = function (fromIndex, toIndex) { this.columnModel.moveColumnByIndex(fromIndex, toIndex, 'api'); };\n /** Same as `moveColumn` but works on list. */\n ColumnApi.prototype.moveColumns = function (columnsToMoveKeys, toIndex) { this.columnModel.moveColumns(columnsToMoveKeys, toIndex, 'api'); };\n /** Move the column to a new position in the row grouping order. */\n ColumnApi.prototype.moveRowGroupColumn = function (fromIndex, toIndex) { this.columnModel.moveRowGroupColumn(fromIndex, toIndex); };\n /** Sets the agg function for a column. `aggFunc` can be one of `'min' | 'max' | 'sum'`. */\n ColumnApi.prototype.setColumnAggFunc = function (key, aggFunc) { this.columnModel.setColumnAggFunc(key, aggFunc); };\n /** Sets the column width on a single column. The finished flag gets included in the resulting event and not used internally by the grid. The finished flag is intended for dragging, where a dragging action will produce many `columnWidth` events, so the consumer of events knows when it receives the last event in a stream. The finished parameter is optional, and defaults to `true`. */\n ColumnApi.prototype.setColumnWidth = function (key, newWidth, finished, source) {\n if (finished === void 0) { finished = true; }\n this.columnModel.setColumnWidths([{ key: key, newWidth: newWidth }], false, finished, source);\n };\n /** Sets the column widths on multiple columns. This method offers better performance than calling `setColumnWidth` multiple times. The finished flag gets included in the resulting event and not used internally by the grid. The finished flag is intended for dragging, where a dragging action will produce many `columnWidth` events, so the consumer of events knows when it receives the last event in a stream. The finished parameter is optional, and defaults to `true`. */\n ColumnApi.prototype.setColumnWidths = function (columnWidths, finished, source) {\n if (finished === void 0) { finished = true; }\n this.columnModel.setColumnWidths(columnWidths, false, finished, source);\n };\n /** Set the pivot mode. */\n ColumnApi.prototype.setPivotMode = function (pivotMode) { this.columnModel.setPivotMode(pivotMode); };\n /** Get the pivot mode. */\n ColumnApi.prototype.isPivotMode = function () { return this.columnModel.isPivotMode(); };\n /** @deprecated Use `getPivotResultColumn` instead */\n ColumnApi.prototype.getSecondaryPivotColumn = function (pivotKeys, valueColKey) {\n console.warn('AG Grid: since version 28.0.x getSecondaryPivotColumn has been renamed, please use getPivotResultColumn instead');\n return this.getPivotResultColumn(pivotKeys, valueColKey);\n };\n /** Returns the pivot result column for the given `pivotKeys` and `valueColId`. Useful to then call operations on the pivot column. */\n ColumnApi.prototype.getPivotResultColumn = function (pivotKeys, valueColKey) { return this.columnModel.getSecondaryPivotColumn(pivotKeys, valueColKey); };\n /** Set the value columns. */\n ColumnApi.prototype.setValueColumns = function (colKeys) { this.columnModel.setValueColumns(colKeys, 'api'); };\n /** Get value columns. */\n ColumnApi.prototype.getValueColumns = function () { return this.columnModel.getValueColumns(); };\n /** Remove a value column. */\n ColumnApi.prototype.removeValueColumn = function (colKey) { this.columnModel.removeValueColumn(colKey, 'api'); };\n /** Same as `removeValueColumns` but provide a list. */\n ColumnApi.prototype.removeValueColumns = function (colKeys) { this.columnModel.removeValueColumns(colKeys, 'api'); };\n /** Add a value column. */\n ColumnApi.prototype.addValueColumn = function (colKey) { this.columnModel.addValueColumn(colKey, 'api'); };\n /** Same as `addValueColumn` but provide a list. */\n ColumnApi.prototype.addValueColumns = function (colKeys) { this.columnModel.addValueColumns(colKeys, 'api'); };\n /** Set the row group columns. */\n ColumnApi.prototype.setRowGroupColumns = function (colKeys) { this.columnModel.setRowGroupColumns(colKeys, 'api'); };\n /** Remove a column from the row groups. */\n ColumnApi.prototype.removeRowGroupColumn = function (colKey) { this.columnModel.removeRowGroupColumn(colKey, 'api'); };\n /** Same as `removeRowGroupColumn` but provide a list of columns. */\n ColumnApi.prototype.removeRowGroupColumns = function (colKeys) { this.columnModel.removeRowGroupColumns(colKeys, 'api'); };\n /** Add a column to the row groups. */\n ColumnApi.prototype.addRowGroupColumn = function (colKey) { this.columnModel.addRowGroupColumn(colKey, 'api'); };\n /** Same as `addRowGroupColumn` but provide a list of columns. */\n ColumnApi.prototype.addRowGroupColumns = function (colKeys) { this.columnModel.addRowGroupColumns(colKeys, 'api'); };\n /** Get row group columns. */\n ColumnApi.prototype.getRowGroupColumns = function () { return this.columnModel.getRowGroupColumns(); };\n /** Set the pivot columns. */\n ColumnApi.prototype.setPivotColumns = function (colKeys) { this.columnModel.setPivotColumns(colKeys, 'api'); };\n /** Remove a pivot column. */\n ColumnApi.prototype.removePivotColumn = function (colKey) { this.columnModel.removePivotColumn(colKey, 'api'); };\n /** Same as `removePivotColumn` but provide a list of columns. */\n ColumnApi.prototype.removePivotColumns = function (colKeys) { this.columnModel.removePivotColumns(colKeys, 'api'); };\n /** Add a pivot column. */\n ColumnApi.prototype.addPivotColumn = function (colKey) { this.columnModel.addPivotColumn(colKey, 'api'); };\n /** Same as `addPivotColumn` but provide a list of columns. */\n ColumnApi.prototype.addPivotColumns = function (colKeys) { this.columnModel.addPivotColumns(colKeys, 'api'); };\n /** Get the pivot columns. */\n ColumnApi.prototype.getPivotColumns = function () { return this.columnModel.getPivotColumns(); };\n /** Same as `getAllDisplayedColumnGroups` but just for the pinned left portion of the grid. */\n ColumnApi.prototype.getLeftDisplayedColumnGroups = function () { return this.columnModel.getDisplayedTreeLeft(); };\n /** Same as `getAllDisplayedColumnGroups` but just for the center portion of the grid. */\n ColumnApi.prototype.getCenterDisplayedColumnGroups = function () { return this.columnModel.getDisplayedTreeCentre(); };\n /** Same as `getAllDisplayedColumnGroups` but just for the pinned right portion of the grid. */\n ColumnApi.prototype.getRightDisplayedColumnGroups = function () { return this.columnModel.getDisplayedTreeRight(); };\n /** Returns all 'root' column headers. If you are not grouping columns, these return the columns. If you are grouping, these return the top level groups - you can navigate down through each one to get the other lower level headers and finally the columns at the bottom. */\n ColumnApi.prototype.getAllDisplayedColumnGroups = function () { return this.columnModel.getAllDisplayedTrees(); };\n /** Auto-sizes a column based on its contents. */\n ColumnApi.prototype.autoSizeColumn = function (key, skipHeader) { return this.columnModel.autoSizeColumn(key, skipHeader, 'api'); };\n /** Same as `autoSizeColumn`, but provide a list of column keys. */\n ColumnApi.prototype.autoSizeColumns = function (keys, skipHeader) {\n this.columnModel.autoSizeColumns({ columns: keys, skipHeader: skipHeader });\n };\n /** Calls `autoSizeColumns` on all displayed columns. */\n ColumnApi.prototype.autoSizeAllColumns = function (skipHeader) { this.columnModel.autoSizeAllColumns(skipHeader, 'api'); };\n /** @deprecated Use `setPivotResultColumns` instead. */\n ColumnApi.prototype.setSecondaryColumns = function (colDefs) {\n console.warn('AG Grid: since version 28.0.x setSecondaryColumns has been renamed, please use setPivotResultColumns instead');\n this.setPivotResultColumns(colDefs);\n };\n /** Set the pivot result columns. */\n ColumnApi.prototype.setPivotResultColumns = function (colDefs) { this.columnModel.setSecondaryColumns(colDefs, 'api'); };\n /** @deprecated Use `getPivotResultColumns` instead. */\n ColumnApi.prototype.getSecondaryColumns = function () {\n console.warn('AG Grid: since version 28.0.x getSecondaryColumns has been renamed, please use getPivotResultColumns instead');\n return this.getPivotResultColumns();\n };\n /** Returns the grid's pivot result columns. */\n ColumnApi.prototype.getPivotResultColumns = function () { return this.columnModel.getSecondaryColumns(); };\n /** @deprecated Use `getColumns` instead. */\n ColumnApi.prototype.getPrimaryColumns = function () {\n console.warn('AG Grid: since version 28.0.x getPrimaryColumns has been renamed, please use getColumns instead');\n return this.getColumns();\n };\n ColumnApi.prototype.cleanDownReferencesToAvoidMemoryLeakInCaseApplicationIsKeepingReferenceToDestroyedGrid = function () {\n // some users were raising support issues with regards memory leaks. the problem was the customers applications\n // were keeping references to the API. trying to educate them all would be difficult, easier to just remove\n // all references in the API so at least the core grid can be garbage collected.\n //\n // wait about 100ms before clearing down the references, in case user has some cleanup to do,\n // and needs to deference the API first\n setTimeout(_.removeAllReferences.bind(window, this, 'Column API'), 100);\n };\n // below goes through deprecated items, prints message to user, then calls the new version of the same method\n // public getColumnDefs(): (ColDef | ColGroupDef)[] {\n // this.setColumnGroupOpened(group, newValue);\n // return null;\n // }\n /** @deprecated Use `getColumns` instead */\n ColumnApi.prototype.getAllColumns = function () {\n console.warn('AG Grid: since version 28.0.x getAllColumns has been renamed, please use getColumns instead');\n return this.getColumns();\n };\n /** @deprecated columnGroupOpened no longer exists, use setColumnGroupOpened */\n ColumnApi.prototype.columnGroupOpened = function (group, newValue) {\n console.error('AG Grid: columnGroupOpened no longer exists, use setColumnGroupOpened');\n this.setColumnGroupOpened(group, newValue);\n };\n /** @deprecated hideColumns is deprecated, use setColumnsVisible */\n ColumnApi.prototype.hideColumns = function (colIds, hide) {\n console.error('AG Grid: hideColumns is deprecated, use setColumnsVisible');\n this.columnModel.setColumnsVisible(colIds, !hide, 'api');\n };\n /** @deprecated hideColumn is deprecated, use setColumnVisible */\n ColumnApi.prototype.hideColumn = function (colId, hide) {\n console.error('AG Grid: hideColumn is deprecated, use setColumnVisible');\n this.columnModel.setColumnVisible(colId, !hide, 'api');\n };\n /** @deprecated setState is deprecated, use setColumnState */\n ColumnApi.prototype.setState = function (columnState) {\n console.error('AG Grid: setState is deprecated, use setColumnState');\n return this.setColumnState(columnState);\n };\n /** @deprecated getState is deprecated, use getColumnState */\n ColumnApi.prototype.getState = function () {\n console.error('AG Grid: getState is deprecated, use getColumnState');\n return this.getColumnState();\n };\n /** @deprecated resetState is deprecated, use resetColumnState */\n ColumnApi.prototype.resetState = function () {\n console.error('AG Grid: resetState is deprecated, use resetColumnState');\n this.resetColumnState();\n };\n /** @deprecated getAggregationColumns is deprecated, use getValueColumns */\n ColumnApi.prototype.getAggregationColumns = function () {\n console.error('AG Grid: getAggregationColumns is deprecated, use getValueColumns');\n return this.columnModel.getValueColumns();\n };\n /** @deprecated removeAggregationColumn is deprecated, use removeValueColumn */\n ColumnApi.prototype.removeAggregationColumn = function (colKey) {\n console.error('AG Grid: removeAggregationColumn is deprecated, use removeValueColumn');\n this.columnModel.removeValueColumn(colKey, 'api');\n };\n /** @deprecated removeAggregationColumns is deprecated, use removeValueColumns */\n ColumnApi.prototype.removeAggregationColumns = function (colKeys) {\n console.error('AG Grid: removeAggregationColumns is deprecated, use removeValueColumns');\n this.columnModel.removeValueColumns(colKeys, 'api');\n };\n /** @deprecated addAggregationColumn is deprecated, use addValueColumn */\n ColumnApi.prototype.addAggregationColumn = function (colKey) {\n console.error('AG Grid: addAggregationColumn is deprecated, use addValueColumn');\n this.columnModel.addValueColumn(colKey, 'api');\n };\n /** @deprecated addAggregationColumns is deprecated, use addValueColumns */\n ColumnApi.prototype.addAggregationColumns = function (colKeys) {\n console.error('AG Grid: addAggregationColumns is deprecated, use addValueColumns');\n this.columnModel.addValueColumns(colKeys, 'api');\n };\n /** @deprecated setColumnAggFunction is deprecated, use setColumnAggFunc */\n ColumnApi.prototype.setColumnAggFunction = function (column, aggFunc) {\n console.error('AG Grid: setColumnAggFunction is deprecated, use setColumnAggFunc');\n this.columnModel.setColumnAggFunc(column, aggFunc, 'api');\n };\n /** @deprecated getDisplayNameForCol is deprecated, use getDisplayNameForColumn */\n ColumnApi.prototype.getDisplayNameForCol = function (column) {\n console.error('AG Grid: getDisplayNameForCol is deprecated, use getDisplayNameForColumn');\n return this.getDisplayNameForColumn(column, null);\n };\n /** @deprecated setColumnState is deprecated, use applyColumnState. */\n ColumnApi.prototype.setColumnState = function (columnState) {\n console.error('AG Grid: setColumnState is deprecated, use applyColumnState');\n return this.columnModel.applyColumnState({ state: columnState, applyOrder: true }, 'api');\n };\n /** @deprecated getOriginalColumnGroup is deprecated, use getProvidedColumnGroup. */\n ColumnApi.prototype.getOriginalColumnGroup = function (name) {\n console.error('AG Grid: getOriginalColumnGroup is deprecated, use getProvidedColumnGroup');\n return this.columnModel.getProvidedColumnGroup(name);\n };\n __decorate$J([\n Autowired('columnModel')\n ], ColumnApi.prototype, \"columnModel\", void 0);\n __decorate$J([\n PreDestroy\n ], ColumnApi.prototype, \"cleanDownReferencesToAvoidMemoryLeakInCaseApplicationIsKeepingReferenceToDestroyedGrid\", null);\n ColumnApi = __decorate$J([\n Bean('columnApi')\n ], ColumnApi);\n return ColumnApi;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$H = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$I = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ValueService = /** @class */ (function (_super) {\n __extends$H(ValueService, _super);\n function ValueService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.initialised = false;\n return _this;\n }\n ValueService.prototype.init = function () {\n var _this = this;\n this.cellExpressions = this.gridOptionsWrapper.isEnableCellExpressions();\n this.initialised = true;\n // We listen to our own event and use it to call the columnSpecific callback,\n // this way the handler calls are correctly interleaved with other global events\n this.eventService.addEventListener(Events.EVENT_CELL_VALUE_CHANGED, function (event) { return _this.callColumnCellValueChangedHandler(event); }, this.gridOptionsWrapper.useAsyncEvents());\n };\n ValueService.prototype.getValue = function (column, rowNode, forFilter, ignoreAggData) {\n if (forFilter === void 0) { forFilter = false; }\n if (ignoreAggData === void 0) { ignoreAggData = false; }\n // hack - the grid is getting refreshed before this bean gets initialised, race condition.\n // really should have a way so they get initialised in the right order???\n if (!this.initialised) {\n this.init();\n }\n if (!rowNode) {\n return;\n }\n // pull these out to make code below easier to read\n var colDef = column.getColDef();\n var field = colDef.field;\n var colId = column.getId();\n var data = rowNode.data;\n var result;\n // if there is a value getter, this gets precedence over a field\n var groupDataExists = rowNode.groupData && rowNode.groupData[colId] !== undefined;\n var aggDataExists = !ignoreAggData && rowNode.aggData && rowNode.aggData[colId] !== undefined;\n if (forFilter && colDef.filterValueGetter) {\n result = this.executeFilterValueGetter(colDef.filterValueGetter, data, column, rowNode);\n }\n else if (this.gridOptionsWrapper.isTreeData() && aggDataExists) {\n result = rowNode.aggData[colId];\n }\n else if (this.gridOptionsWrapper.isTreeData() && colDef.valueGetter) {\n result = this.executeValueGetter(colDef.valueGetter, data, column, rowNode);\n }\n else if (this.gridOptionsWrapper.isTreeData() && (field && data)) {\n result = getValueUsingField(data, field, column.isFieldContainsDots());\n }\n else if (groupDataExists) {\n result = rowNode.groupData[colId];\n }\n else if (aggDataExists) {\n result = rowNode.aggData[colId];\n }\n else if (colDef.valueGetter) {\n result = this.executeValueGetter(colDef.valueGetter, data, column, rowNode);\n }\n else if (field && data) {\n result = getValueUsingField(data, field, column.isFieldContainsDots());\n }\n // the result could be an expression itself, if we are allowing cell values to be expressions\n if (this.cellExpressions && (typeof result === 'string') && result.indexOf('=') === 0) {\n var cellValueGetter = result.substring(1);\n result = this.executeValueGetter(cellValueGetter, data, column, rowNode);\n }\n if (result == null) {\n var openedGroup = this.getOpenedGroup(rowNode, column);\n if (openedGroup != null) {\n return openedGroup;\n }\n }\n return result;\n };\n ValueService.prototype.getOpenedGroup = function (rowNode, column) {\n if (!this.gridOptionsWrapper.isShowOpenedGroup()) {\n return;\n }\n var colDef = column.getColDef();\n if (!colDef.showRowGroup) {\n return;\n }\n var showRowGroup = column.getColDef().showRowGroup;\n var pointer = rowNode.parent;\n while (pointer != null) {\n if (pointer.rowGroupColumn && (showRowGroup === true || showRowGroup === pointer.rowGroupColumn.getId())) {\n return pointer.key;\n }\n pointer = pointer.parent;\n }\n return undefined;\n };\n /**\n * Sets the value of a GridCell\n * @param rowNode The `RowNode` to be updated\n * @param colKey The `Column` to be updated\n * @param newValue The new value to be set\n * @param eventSource The event source\n * @returns `True` if the value has been updated, otherwise`False`.\n */\n ValueService.prototype.setValue = function (rowNode, colKey, newValue, eventSource) {\n var column = this.columnModel.getPrimaryColumn(colKey);\n if (!rowNode || !column) {\n return false;\n }\n // this will only happen if user is trying to paste into a group row, which doesn't make sense\n // the user should not be trying to paste into group rows\n if (missing(rowNode.data)) {\n rowNode.data = {};\n }\n // for backwards compatibility we are also retrieving the newValueHandler as well as the valueSetter\n var _a = column.getColDef(), field = _a.field, newValueHandler = _a.newValueHandler, valueSetter = _a.valueSetter;\n // need either a field or a newValueHandler for this to work\n if (missing(field) && missing(newValueHandler) && missing(valueSetter)) {\n // we don't tell user about newValueHandler, as that is deprecated\n console.warn(\"AG Grid: you need either field or valueSetter set on colDef for editing to work\");\n return false;\n }\n var params = {\n node: rowNode,\n data: rowNode.data,\n oldValue: this.getValue(column, rowNode),\n newValue: newValue,\n colDef: column.getColDef(),\n column: column,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n params.newValue = newValue;\n var valueWasDifferent;\n if (newValueHandler && exists(newValueHandler)) {\n valueWasDifferent = newValueHandler(params);\n }\n else if (exists(valueSetter)) {\n valueWasDifferent = this.expressionService.evaluate(valueSetter, params);\n }\n else {\n valueWasDifferent = this.setValueUsingField(rowNode.data, field, newValue, column.isFieldContainsDots());\n }\n // in case user forgot to return something (possible if they are not using TypeScript\n // and just forgot, or using an old newValueHandler we didn't always expect a return\n // value here), we default the return value to true, so we always refresh.\n if (valueWasDifferent === undefined) {\n valueWasDifferent = true;\n }\n // if no change to the value, then no need to do the updating, or notifying via events.\n // otherwise the user could be tabbing around the grid, and cellValueChange would get called\n // all the time.\n if (!valueWasDifferent) {\n return false;\n }\n // reset quick filter on this row\n rowNode.resetQuickFilterAggregateText();\n this.valueCache.onDataChanged();\n params.newValue = this.getValue(column, rowNode);\n var event = {\n type: Events.EVENT_CELL_VALUE_CHANGED,\n event: null,\n rowIndex: rowNode.rowIndex,\n rowPinned: rowNode.rowPinned,\n column: params.column,\n api: params.api,\n columnApi: params.columnApi,\n colDef: params.colDef,\n context: params.context,\n data: rowNode.data,\n node: rowNode,\n oldValue: params.oldValue,\n newValue: params.newValue,\n value: params.newValue,\n source: eventSource\n };\n this.eventService.dispatchEvent(event);\n return true;\n };\n ValueService.prototype.callColumnCellValueChangedHandler = function (event) {\n var onCellValueChanged = event.colDef.onCellValueChanged;\n if (typeof onCellValueChanged === 'function') {\n onCellValueChanged({\n node: event.node,\n data: event.data,\n oldValue: event.oldValue,\n newValue: event.newValue,\n colDef: event.colDef,\n column: event.column,\n api: event.api,\n columnApi: event.columnApi,\n context: event.context\n });\n }\n };\n ValueService.prototype.setValueUsingField = function (data, field, newValue, isFieldContainsDots) {\n if (!field) {\n return false;\n }\n // if no '.', then it's not a deep value\n var valuesAreSame = false;\n if (!isFieldContainsDots) {\n // soft comparison to match strings and numbers\n valuesAreSame = data[field] == newValue;\n if (!valuesAreSame) {\n data[field] = newValue;\n }\n }\n else {\n // otherwise it is a deep value, so need to dig for it\n var fieldPieces = field.split('.');\n var currentObject = data;\n while (fieldPieces.length > 0 && currentObject) {\n var fieldPiece = fieldPieces.shift();\n if (fieldPieces.length === 0) {\n // soft comparison to match strings and numbers\n valuesAreSame = currentObject[fieldPiece] == newValue;\n if (!valuesAreSame) {\n currentObject[fieldPiece] = newValue;\n }\n }\n else {\n currentObject = currentObject[fieldPiece];\n }\n }\n }\n return !valuesAreSame;\n };\n ValueService.prototype.executeFilterValueGetter = function (valueGetter, data, column, rowNode) {\n var params = {\n data: data,\n node: rowNode,\n column: column,\n colDef: column.getColDef(),\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext(),\n getValue: this.getValueCallback.bind(this, rowNode)\n };\n return this.expressionService.evaluate(valueGetter, params);\n };\n ValueService.prototype.executeValueGetter = function (valueGetter, data, column, rowNode) {\n var colId = column.getId();\n // if inside the same turn, just return back the value we got last time\n var valueFromCache = this.valueCache.getValue(rowNode, colId);\n if (valueFromCache !== undefined) {\n return valueFromCache;\n }\n var params = {\n data: data,\n node: rowNode,\n column: column,\n colDef: column.getColDef(),\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext(),\n getValue: this.getValueCallback.bind(this, rowNode)\n };\n var result = this.expressionService.evaluate(valueGetter, params);\n // if a turn is active, store the value in case the grid asks for it again\n this.valueCache.setValue(rowNode, colId, result);\n return result;\n };\n ValueService.prototype.getValueCallback = function (node, field) {\n var otherColumn = this.columnModel.getPrimaryColumn(field);\n if (otherColumn) {\n return this.getValue(otherColumn, node);\n }\n return null;\n };\n // used by row grouping and pivot, to get key for a row. col can be a pivot col or a row grouping col\n ValueService.prototype.getKeyForNode = function (col, rowNode) {\n var value = this.getValue(col, rowNode);\n var keyCreator = col.getColDef().keyCreator;\n var result = value;\n if (keyCreator) {\n var keyParams = {\n value: value,\n colDef: col.getColDef(),\n column: col,\n node: rowNode,\n data: rowNode.data,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n result = keyCreator(keyParams);\n }\n // if already a string, or missing, just return it\n if (typeof result === 'string' || result == null) {\n return result;\n }\n result = String(result);\n if (result === '[object Object]') {\n doOnce(function () {\n console.warn('AG Grid: a column you are grouping or pivoting by has objects as values. If you want to group by complex objects then either a) use a colDef.keyCreator (se AG Grid docs) or b) to toString() on the object to return a key');\n }, 'getKeyForNode - warn about [object,object]');\n }\n return result;\n };\n __decorate$I([\n Autowired('expressionService')\n ], ValueService.prototype, \"expressionService\", void 0);\n __decorate$I([\n Autowired('columnModel')\n ], ValueService.prototype, \"columnModel\", void 0);\n __decorate$I([\n Autowired('valueCache')\n ], ValueService.prototype, \"valueCache\", void 0);\n __decorate$I([\n PostConstruct\n ], ValueService.prototype, \"init\", null);\n ValueService = __decorate$I([\n Bean('valueService')\n ], ValueService);\n return ValueService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$G = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$H = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$3 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar ExpressionService = /** @class */ (function (_super) {\n __extends$G(ExpressionService, _super);\n function ExpressionService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.expressionToFunctionCache = {};\n return _this;\n }\n ExpressionService.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('ExpressionService');\n };\n ExpressionService.prototype.evaluate = function (expressionOrFunc, params) {\n if (typeof expressionOrFunc === 'function') {\n // valueGetter is a function, so just call it\n var func = expressionOrFunc;\n return func(params);\n }\n else if (typeof expressionOrFunc === 'string') {\n // valueGetter is an expression, so execute the expression\n var expression = expressionOrFunc;\n return this.evaluateExpression(expression, params);\n }\n else {\n console.error('AG Grid: value should be either a string or a function', expressionOrFunc);\n }\n };\n ExpressionService.prototype.evaluateExpression = function (expression, params) {\n try {\n var javaScriptFunction = this.createExpressionFunction(expression);\n // the params don't have all these values, rather we add every possible\n // value a params can have, which makes whatever is in the params available.\n var result = javaScriptFunction(params.value, params.context, params.oldValue, params.newValue, params.value, params.node, params.data, params.colDef, params.rowIndex, params.api, params.columnApi, params.getValue, params.column, params.columnGroup);\n return result;\n }\n catch (e) {\n // the expression failed, which can happen, as it's the client that\n // provides the expression. so print a nice message\n // tslint:disable-next-line\n console.log('Processing of the expression failed');\n // tslint:disable-next-line\n console.log('Expression = ' + expression);\n // tslint:disable-next-line\n console.log('Params =', params);\n // tslint:disable-next-line\n console.log('Exception = ' + e);\n return null;\n }\n };\n ExpressionService.prototype.createExpressionFunction = function (expression) {\n // check cache first\n if (this.expressionToFunctionCache[expression]) {\n return this.expressionToFunctionCache[expression];\n }\n // if not found in cache, return the function\n var functionBody = this.createFunctionBody(expression);\n var theFunction = new Function('x, ctx, oldValue, newValue, value, node, data, colDef, rowIndex, api, columnApi, getValue, column, columnGroup', functionBody);\n // store in cache\n this.expressionToFunctionCache[expression] = theFunction;\n return theFunction;\n };\n ExpressionService.prototype.createFunctionBody = function (expression) {\n // if the expression has the 'return' word in it, then use as is,\n // if not, then wrap it with return and ';' to make a function\n if (expression.indexOf('return') >= 0) {\n return expression;\n }\n else {\n return 'return ' + expression + ';';\n }\n };\n __decorate$H([\n __param$3(0, Qualifier('loggerFactory'))\n ], ExpressionService.prototype, \"setBeans\", null);\n ExpressionService = __decorate$H([\n Bean('expressionService')\n ], ExpressionService);\n return ExpressionService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$F = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$G = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar TemplateService = /** @class */ (function (_super) {\n __extends$F(TemplateService, _super);\n function TemplateService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.templateCache = {};\n _this.waitingCallbacks = {};\n return _this;\n }\n // returns the template if it is loaded, or null if it is not loaded\n // but will call the callback when it is loaded\n TemplateService.prototype.getTemplate = function (url, callback) {\n var templateFromCache = this.templateCache[url];\n if (templateFromCache) {\n return templateFromCache;\n }\n var callbackList = this.waitingCallbacks[url];\n var that = this;\n if (!callbackList) {\n // first time this was called, so need a new list for callbacks\n callbackList = [];\n this.waitingCallbacks[url] = callbackList;\n // and also need to do the http request\n var client = new XMLHttpRequest();\n client.onload = function () {\n that.handleHttpResult(this, url);\n };\n client.open(\"GET\", url);\n client.send();\n }\n // add this callback\n if (callback) {\n callbackList.push(callback);\n }\n // caller needs to wait for template to load, so return null\n return null;\n };\n TemplateService.prototype.handleHttpResult = function (httpResult, url) {\n if (httpResult.status !== 200 || httpResult.response === null) {\n console.warn(\"AG Grid: Unable to get template error \" + httpResult.status + \" - \" + url);\n return;\n }\n // response success, so process it\n // in IE9 the response is in - responseText\n this.templateCache[url] = httpResult.response || httpResult.responseText;\n // inform all listeners that this is now in the cache\n var callbacks = this.waitingCallbacks[url];\n for (var i = 0; i < callbacks.length; i++) {\n var callback = callbacks[i];\n // we could pass the callback the response, however we know the client of this code\n // is the cell renderer, and it passes the 'cellRefresh' method in as the callback\n // which doesn't take any parameters.\n callback();\n }\n };\n TemplateService = __decorate$G([\n Bean('templateService')\n ], TemplateService);\n return TemplateService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$E = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$F = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$2 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar LoggerFactory = /** @class */ (function (_super) {\n __extends$E(LoggerFactory, _super);\n function LoggerFactory() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n LoggerFactory.prototype.setBeans = function (gridOptionsWrapper) {\n this.logging = gridOptionsWrapper.isDebug();\n };\n LoggerFactory.prototype.create = function (name) {\n return new Logger(name, this.isLogging.bind(this));\n };\n LoggerFactory.prototype.isLogging = function () {\n return this.logging;\n };\n __decorate$F([\n __param$2(0, Qualifier('gridOptionsWrapper'))\n ], LoggerFactory.prototype, \"setBeans\", null);\n LoggerFactory = __decorate$F([\n Bean('loggerFactory')\n ], LoggerFactory);\n return LoggerFactory;\n}(BeanStub));\nvar Logger = /** @class */ (function () {\n function Logger(name, isLoggingFunc) {\n this.name = name;\n this.isLoggingFunc = isLoggingFunc;\n }\n Logger.prototype.isLogging = function () {\n return this.isLoggingFunc();\n };\n Logger.prototype.log = function (message) {\n if (this.isLoggingFunc()) {\n // tslint:disable-next-line\n console.log('AG Grid.' + this.name + ': ' + message);\n }\n };\n return Logger;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$D = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$E = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GridCtrl = /** @class */ (function (_super) {\n __extends$D(GridCtrl, _super);\n function GridCtrl() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n GridCtrl.prototype.setComp = function (view, eGridDiv, eGui) {\n var _this = this;\n this.view = view;\n this.eGridHostDiv = eGridDiv;\n this.eGui = eGui;\n // this drop target is just used to see if the drop event is inside the grid\n this.dragAndDropService.addDropTarget({\n getContainer: function () { return _this.eGui; },\n isInterestedIn: function (type) { return type === DragSourceType.HeaderCell || type === DragSourceType.ToolPanel; },\n getIconName: function () { return DragAndDropService.ICON_NOT_ALLOWED; },\n });\n this.mouseEventService.stampTopLevelGridCompWithGridInstance(eGridDiv);\n this.createManagedBean(new LayoutFeature(this.view));\n // important to set rtl before doLayout, as setting the RTL class impacts the scroll position,\n // which doLayout indirectly depends on\n this.addRtlSupport();\n this.addManagedListener(this, Events.EVENT_KEYBOARD_FOCUS, function () {\n _this.view.addOrRemoveKeyboardFocusClass(true);\n });\n this.addManagedListener(this, Events.EVENT_MOUSE_FOCUS, function () {\n _this.view.addOrRemoveKeyboardFocusClass(false);\n });\n var unsubscribeFromResize = this.resizeObserverService.observeResize(this.eGridHostDiv, this.onGridSizeChanged.bind(this));\n this.addDestroyFunc(function () { return unsubscribeFromResize(); });\n this.ctrlsService.registerGridCtrl(this);\n };\n GridCtrl.prototype.isDetailGrid = function () {\n var _a, _b;\n var el = this.focusService.findTabbableParent(this.getGui());\n return ((_b = (_a = el) === null || _a === void 0 ? void 0 : _a.getAttribute('row-id')) === null || _b === void 0 ? void 0 : _b.startsWith('detail')) || false;\n };\n GridCtrl.prototype.showDropZones = function () {\n return ModuleRegistry.isRegistered(ModuleNames.RowGroupingModule);\n };\n GridCtrl.prototype.showSideBar = function () {\n return ModuleRegistry.isRegistered(ModuleNames.SideBarModule);\n };\n GridCtrl.prototype.showStatusBar = function () {\n return ModuleRegistry.isRegistered(ModuleNames.StatusBarModule);\n };\n GridCtrl.prototype.showWatermark = function () {\n return ModuleRegistry.isRegistered(ModuleNames.EnterpriseCoreModule);\n };\n GridCtrl.prototype.onGridSizeChanged = function () {\n var event = {\n type: Events.EVENT_GRID_SIZE_CHANGED,\n clientWidth: this.eGridHostDiv.clientWidth,\n clientHeight: this.eGridHostDiv.clientHeight\n };\n this.eventService.dispatchEvent(event);\n };\n GridCtrl.prototype.addRtlSupport = function () {\n var cssClass = this.gridOptionsWrapper.isEnableRtl() ? 'ag-rtl' : 'ag-ltr';\n this.view.setRtlClass(cssClass);\n };\n GridCtrl.prototype.destroyGridUi = function () {\n this.view.destroyGridUi();\n };\n GridCtrl.prototype.getGui = function () {\n return this.eGui;\n };\n GridCtrl.prototype.setResizeCursor = function (on) {\n this.view.setCursor(on ? 'ew-resize' : null);\n };\n GridCtrl.prototype.disableUserSelect = function (on) {\n this.view.setUserSelect(on ? 'none' : null);\n };\n GridCtrl.prototype.focusNextInnerContainer = function (backwards) {\n var eDocument = this.gridOptionsWrapper.getDocument();\n var focusableContainers = this.view.getFocusableContainers();\n var idxWithFocus = focusableContainers.findIndex(function (container) { return container.contains(eDocument.activeElement); });\n var nextIdx = idxWithFocus + (backwards ? -1 : 1);\n if (nextIdx <= 0 || nextIdx >= focusableContainers.length) {\n return false;\n }\n return this.focusService.focusInto(focusableContainers[nextIdx]);\n };\n GridCtrl.prototype.focusInnerElement = function (fromBottom) {\n var focusableContainers = this.view.getFocusableContainers();\n if (fromBottom) {\n if (focusableContainers.length > 1) {\n return this.focusService.focusInto(last(focusableContainers), true);\n }\n var lastColumn = last(this.columnModel.getAllDisplayedColumns());\n if (this.focusService.focusGridView(lastColumn, true)) {\n return true;\n }\n }\n return this.focusService.focusFirstHeader();\n };\n GridCtrl.prototype.forceFocusOutOfContainer = function (up) {\n if (up === void 0) { up = false; }\n this.view.forceFocusOutOfContainer(up);\n };\n __decorate$E([\n Autowired('focusService')\n ], GridCtrl.prototype, \"focusService\", void 0);\n __decorate$E([\n Autowired('resizeObserverService')\n ], GridCtrl.prototype, \"resizeObserverService\", void 0);\n __decorate$E([\n Autowired('columnModel')\n ], GridCtrl.prototype, \"columnModel\", void 0);\n __decorate$E([\n Autowired('ctrlsService')\n ], GridCtrl.prototype, \"ctrlsService\", void 0);\n __decorate$E([\n Autowired('mouseEventService')\n ], GridCtrl.prototype, \"mouseEventService\", void 0);\n __decorate$E([\n Autowired('dragAndDropService')\n ], GridCtrl.prototype, \"dragAndDropService\", void 0);\n return GridCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$C = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$D = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar GridComp = /** @class */ (function (_super) {\n __extends$C(GridComp, _super);\n function GridComp(eGridDiv) {\n var _this = _super.call(this, undefined) || this;\n _this.eGridDiv = eGridDiv;\n return _this;\n }\n GridComp.prototype.postConstruct = function () {\n var _this = this;\n this.logger = this.loggerFactory.create('GridComp');\n var compProxy = {\n destroyGridUi: function () { return _this.destroyBean(_this); },\n setRtlClass: function (cssClass) { return _this.addCssClass(cssClass); },\n addOrRemoveKeyboardFocusClass: function (addOrRemove) { return _this.addOrRemoveCssClass(FocusService.AG_KEYBOARD_FOCUS, addOrRemove); },\n forceFocusOutOfContainer: this.forceFocusOutOfContainer.bind(this),\n updateLayoutClasses: this.updateLayoutClasses.bind(this),\n getFocusableContainers: this.getFocusableContainers.bind(this),\n setUserSelect: function (value) {\n _this.getGui().style.userSelect = value != null ? value : '';\n _this.getGui().style.webkitUserSelect = value != null ? value : '';\n },\n setCursor: function (value) {\n _this.getGui().style.cursor = value != null ? value : '';\n }\n };\n this.ctrl = this.createManagedBean(new GridCtrl());\n var template = this.createTemplate();\n this.setTemplate(template);\n this.ctrl.setComp(compProxy, this.eGridDiv, this.getGui());\n this.insertGridIntoDom();\n this.initialiseTabGuard({\n // we want to override the default behaviour to do nothing for onTabKeyDown\n onTabKeyDown: function () { return undefined; },\n focusInnerElement: function (fromBottom) { return _this.ctrl.focusInnerElement(fromBottom); }\n });\n };\n GridComp.prototype.insertGridIntoDom = function () {\n var _this = this;\n var eGui = this.getGui();\n this.eGridDiv.appendChild(eGui);\n this.addDestroyFunc(function () {\n _this.eGridDiv.removeChild(eGui);\n _this.logger.log('Grid removed from DOM');\n });\n };\n GridComp.prototype.updateLayoutClasses = function (cssClass, params) {\n var eRootWrapperBodyClassList = this.eRootWrapperBody.classList;\n eRootWrapperBodyClassList.toggle(LayoutCssClasses.AUTO_HEIGHT, params.autoHeight);\n eRootWrapperBodyClassList.toggle(LayoutCssClasses.NORMAL, params.normal);\n eRootWrapperBodyClassList.toggle(LayoutCssClasses.PRINT, params.print);\n this.addOrRemoveCssClass(LayoutCssClasses.AUTO_HEIGHT, params.autoHeight);\n this.addOrRemoveCssClass(LayoutCssClasses.NORMAL, params.normal);\n this.addOrRemoveCssClass(LayoutCssClasses.PRINT, params.print);\n };\n GridComp.prototype.createTemplate = function () {\n var dropZones = this.ctrl.showDropZones() ? '<ag-grid-header-drop-zones></ag-grid-header-drop-zones>' : '';\n var sideBar = this.ctrl.showSideBar() ? '<ag-side-bar ref=\"sideBar\"></ag-side-bar>' : '';\n var statusBar = this.ctrl.showStatusBar() ? '<ag-status-bar ref=\"statusBar\"></ag-status-bar>' : '';\n var watermark = this.ctrl.showWatermark() ? '<ag-watermark></ag-watermark>' : '';\n var template = /* html */ \"<div class=\\\"ag-root-wrapper\\\" role=\\\"presentation\\\">\\n \" + dropZones + \"\\n <div class=\\\"ag-root-wrapper-body\\\" ref=\\\"rootWrapperBody\\\" role=\\\"presentation\\\">\\n <ag-grid-body ref=\\\"gridBody\\\"></ag-grid-body>\\n \" + sideBar + \"\\n </div>\\n \" + statusBar + \"\\n <ag-pagination></ag-pagination>\\n \" + watermark + \"\\n </div>\";\n return template;\n };\n GridComp.prototype.getFocusableElement = function () {\n return this.eRootWrapperBody;\n };\n GridComp.prototype.getFocusableContainers = function () {\n var focusableContainers = [\n this.gridBodyComp.getGui()\n ];\n if (this.sideBarComp) {\n focusableContainers.push(this.sideBarComp.getGui());\n }\n return focusableContainers.filter(function (el) { return isVisible(el); });\n };\n __decorate$D([\n Autowired('loggerFactory')\n ], GridComp.prototype, \"loggerFactory\", void 0);\n __decorate$D([\n RefSelector('gridBody')\n ], GridComp.prototype, \"gridBodyComp\", void 0);\n __decorate$D([\n RefSelector('sideBar')\n ], GridComp.prototype, \"sideBarComp\", void 0);\n __decorate$D([\n RefSelector('rootWrapperBody')\n ], GridComp.prototype, \"eRootWrapperBody\", void 0);\n __decorate$D([\n PostConstruct\n ], GridComp.prototype, \"postConstruct\", null);\n return GridComp;\n}(TabGuardComp));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$B = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$C = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$4 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$3 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$4(arguments[i]));\n return ar;\n};\nvar SortController = /** @class */ (function (_super) {\n __extends$B(SortController, _super);\n function SortController() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SortController_1 = SortController;\n SortController.prototype.progressSort = function (column, multiSort, source) {\n var nextDirection = this.getNextSortDirection(column);\n this.setSortForColumn(column, nextDirection, multiSort, source);\n };\n SortController.prototype.setSortForColumn = function (column, sort, multiSort, source) {\n var _a;\n // auto correct - if sort not legal value, then set it to 'no sort' (which is null)\n if (sort !== Constants.SORT_ASC && sort !== Constants.SORT_DESC) {\n sort = null;\n }\n var isColumnsSortingCoupledToGroup = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n var columnsToUpdate = [column];\n if (isColumnsSortingCoupledToGroup) {\n if (column.getColDef().showRowGroup) {\n var rowGroupColumns = this.columnModel.getSourceColumnsForGroupColumn(column);\n var sortableRowGroupColumns = (_a = rowGroupColumns) === null || _a === void 0 ? void 0 : _a.filter(function (col) { return col.getColDef().sortable; });\n if (sortableRowGroupColumns) {\n columnsToUpdate = __spread$3([column], sortableRowGroupColumns);\n }\n }\n }\n columnsToUpdate.forEach(function (col) { return col.setSort(sort, source); });\n var doingMultiSort = (multiSort || this.gridOptionsWrapper.isAlwaysMultiSort()) && !this.gridOptionsWrapper.isSuppressMultiSort();\n // clear sort on all columns except those changed, and update the icons\n if (!doingMultiSort) {\n this.clearSortBarTheseColumns(columnsToUpdate, source);\n }\n // sortIndex used for knowing order of cols when multi-col sort\n this.updateSortIndex(column);\n this.dispatchSortChangedEvents(source);\n };\n SortController.prototype.updateSortIndex = function (lastColToChange) {\n var isCoupled = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n var groupParent = this.columnModel.getGroupDisplayColumnForGroup(lastColToChange.getId());\n var lastSortIndexCol = isCoupled ? groupParent || lastColToChange : lastColToChange;\n var allSortedCols = this.getIndexableColumnsOrdered();\n // reset sort index on everything\n this.columnModel.getPrimaryAndSecondaryAndAutoColumns().forEach(function (col) { return col.setSortIndex(null); });\n var allSortedColsWithoutChanges = allSortedCols.filter(function (col) { return col !== lastSortIndexCol; });\n var sortedColsWithIndices = !!lastSortIndexCol.getSort() ? __spread$3(allSortedColsWithoutChanges, [lastSortIndexCol]) : allSortedColsWithoutChanges;\n sortedColsWithIndices.forEach(function (col, idx) { return (col.setSortIndex(idx)); });\n };\n // gets called by API, so if data changes, use can call this, which will end up\n // working out the sort order again of the rows.\n SortController.prototype.onSortChanged = function (source) {\n this.dispatchSortChangedEvents(source);\n };\n SortController.prototype.isSortActive = function () {\n // pull out all the columns that have sorting set\n var allCols = this.columnModel.getPrimaryAndSecondaryAndAutoColumns();\n var sortedCols = allCols.filter(function (column) { return !!column.getSort(); });\n return sortedCols && sortedCols.length > 0;\n };\n SortController.prototype.dispatchSortChangedEvents = function (source) {\n var event = {\n type: Events.EVENT_SORT_CHANGED,\n source: source\n };\n this.eventService.dispatchEvent(event);\n };\n SortController.prototype.clearSortBarTheseColumns = function (columnsToSkip, source) {\n this.columnModel.getPrimaryAndSecondaryAndAutoColumns().forEach(function (columnToClear) {\n // Do not clear if either holding shift, or if column in question was clicked\n if (!columnsToSkip.includes(columnToClear)) {\n // setting to 'undefined' as null means 'none' rather than cleared, otherwise issue will arise\n // if sort order is: ['desc', null , 'asc'], as it will start at null rather than 'desc'.\n columnToClear.setSort(undefined, source);\n }\n });\n };\n SortController.prototype.getNextSortDirection = function (column) {\n var sortingOrder;\n if (column.getColDef().sortingOrder) {\n sortingOrder = column.getColDef().sortingOrder;\n }\n else if (this.gridOptionsWrapper.getSortingOrder()) {\n sortingOrder = this.gridOptionsWrapper.getSortingOrder();\n }\n else {\n sortingOrder = SortController_1.DEFAULT_SORTING_ORDER;\n }\n if (!Array.isArray(sortingOrder) || sortingOrder.length <= 0) {\n console.warn(\"AG Grid: sortingOrder must be an array with at least one element, currently it's \" + sortingOrder);\n return null;\n }\n var currentIndex = sortingOrder.indexOf(column.getSort());\n var notInArray = currentIndex < 0;\n var lastItemInArray = currentIndex == sortingOrder.length - 1;\n var result;\n if (notInArray || lastItemInArray) {\n result = sortingOrder[0];\n }\n else {\n result = sortingOrder[currentIndex + 1];\n }\n // verify the sort type exists, as the user could provide the sortingOrder, need to make sure it's valid\n if (SortController_1.DEFAULT_SORTING_ORDER.indexOf(result) < 0) {\n console.warn('AG Grid: invalid sort type ' + result);\n return null;\n }\n return result;\n };\n SortController.prototype.getColumnsOrderedForSort = function () {\n // pull out all the columns that have sorting set\n var allColumnsIncludingAuto = this.columnModel.getPrimaryAndSecondaryAndAutoColumns();\n // when both cols are missing sortIndex, we use the position of the col in all cols list.\n // this means if colDefs only have sort, but no sortIndex, we deterministically pick which\n // cols is sorted by first.\n var allColsIndexes = {};\n allColumnsIncludingAuto.forEach(function (col, index) { return allColsIndexes[col.getId()] = index; });\n // put the columns in order of which one got sorted first\n allColumnsIncludingAuto.sort(function (a, b) {\n var iA = a.getSortIndex();\n var iB = b.getSortIndex();\n if (iA != null && iB != null) {\n return iA - iB; // both present, normal comparison\n }\n else if (iA == null && iB == null) {\n // both missing, compare using column positions\n var posA = allColsIndexes[a.getId()];\n var posB = allColsIndexes[b.getId()];\n return posA > posB ? 1 : -1;\n }\n else if (iB == null) {\n return -1; // iB missing\n }\n else {\n return 1; // iA missing\n }\n });\n return allColumnsIncludingAuto;\n };\n SortController.prototype.getIndexableColumnsOrdered = function () {\n var _this = this;\n if (!this.gridOptionsWrapper.isColumnsSortingCoupledToGroup()) {\n return this.getColumnsWithSortingOrdered();\n }\n return this.getColumnsOrderedForSort()\n .filter(function (col) {\n var _a;\n if (!!col.getColDef().showRowGroup) {\n if (col.getColDef().field && col.getSort()) {\n return true;\n }\n var sourceCols = _this.columnModel.getSourceColumnsForGroupColumn(col);\n return (_a = sourceCols) === null || _a === void 0 ? void 0 : _a.some(function (col) { return !!col.getSort(); });\n }\n return !!col.getSort();\n });\n };\n SortController.prototype.getColumnsWithSortingOrdered = function () {\n // pull out all the columns that have sorting set\n var orderedColumns = this.getColumnsOrderedForSort();\n return orderedColumns.filter(function (column) { return !!column.getSort(); });\n };\n // used by server side row models, to sent sort to server\n SortController.prototype.getSortModel = function () {\n return this.getColumnsWithSortingOrdered().map(function (column) { return ({\n sort: column.getSort(),\n colId: column.getId()\n }); });\n };\n SortController.prototype.getSortOptions = function () {\n return this.getColumnsWithSortingOrdered().map(function (column) { return ({\n sort: column.getSort(),\n column: column\n }); });\n };\n SortController.prototype.canColumnDisplayMixedSort = function (column) {\n var isColumnSortCouplingActive = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n var isGroupDisplayColumn = !!column.getColDef().showRowGroup;\n return isColumnSortCouplingActive && isGroupDisplayColumn;\n };\n SortController.prototype.getDisplaySortForColumn = function (column) {\n var _a;\n var linkedColumns = this.columnModel.getSourceColumnsForGroupColumn(column);\n if (!this.canColumnDisplayMixedSort(column) || !((_a = linkedColumns) === null || _a === void 0 ? void 0 : _a.length)) {\n return column.getSort();\n }\n // if column has unique data, its sorting is independent - but can still be mixed\n var columnHasUniqueData = !!column.getColDef().field;\n var sortableColumns = columnHasUniqueData ? __spread$3([column], linkedColumns) : linkedColumns;\n var firstSort = sortableColumns[0].getSort();\n // the == is intentional, as null and undefined both represent no sort, which means they are equivalent\n var allMatch = sortableColumns.every(function (col) { return col.getSort() == firstSort; });\n if (!allMatch) {\n return 'mixed';\n }\n return firstSort;\n };\n SortController.prototype.getDisplaySortIndexForColumn = function (column) {\n var _this = this;\n var isColumnSortCouplingActive = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n if (!isColumnSortCouplingActive) {\n return this.getColumnsWithSortingOrdered().indexOf(column);\n }\n var displayColumn = this.columnModel.getGroupDisplayColumnForGroup(column.getId());\n if (displayColumn) {\n if (!!column.getSort()) {\n return this.getDisplaySortIndexForColumn(displayColumn);\n }\n return null;\n }\n var allSortedCols = this.getIndexableColumnsOrdered()\n .filter(function (col) { return !_this.columnModel.getGroupDisplayColumnForGroup(col.getId()); });\n return allSortedCols.indexOf(column);\n };\n var SortController_1;\n SortController.DEFAULT_SORTING_ORDER = [Constants.SORT_ASC, Constants.SORT_DESC, null];\n __decorate$C([\n Autowired('columnModel')\n ], SortController.prototype, \"columnModel\", void 0);\n SortController = SortController_1 = __decorate$C([\n Bean('sortController')\n ], SortController);\n return SortController;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$A = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$B = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ColumnHoverService = /** @class */ (function (_super) {\n __extends$A(ColumnHoverService, _super);\n function ColumnHoverService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ColumnHoverService.prototype.setMouseOver = function (columns) {\n this.selectedColumns = columns;\n var event = {\n type: Events.EVENT_COLUMN_HOVER_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnHoverService.prototype.clearMouseOver = function () {\n this.selectedColumns = null;\n var event = {\n type: Events.EVENT_COLUMN_HOVER_CHANGED\n };\n this.eventService.dispatchEvent(event);\n };\n ColumnHoverService.prototype.isHovered = function (column) {\n return !!this.selectedColumns && this.selectedColumns.indexOf(column) >= 0;\n };\n ColumnHoverService = __decorate$B([\n Bean('columnHoverService')\n ], ColumnHoverService);\n return ColumnHoverService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$z = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$A = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ColumnAnimationService = /** @class */ (function (_super) {\n __extends$z(ColumnAnimationService, _super);\n function ColumnAnimationService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.executeNextFuncs = [];\n _this.executeLaterFuncs = [];\n _this.active = false;\n _this.animationThreadCount = 0;\n return _this;\n }\n ColumnAnimationService.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) { return _this.gridBodyCtrl = p.gridBodyCtrl; });\n };\n ColumnAnimationService.prototype.isActive = function () {\n return this.active;\n };\n ColumnAnimationService.prototype.start = function () {\n if (this.active) {\n return;\n }\n if (this.gridOptionsWrapper.isSuppressColumnMoveAnimation()) {\n return;\n }\n // if doing RTL, we don't animate open / close as due to how the pixels are inverted,\n // the animation moves all the row the the right rather than to the left (ie it's the static\n // columns that actually get their coordinates updated)\n if (this.gridOptionsWrapper.isEnableRtl()) {\n return;\n }\n this.ensureAnimationCssClassPresent();\n this.active = true;\n };\n ColumnAnimationService.prototype.finish = function () {\n if (!this.active) {\n return;\n }\n this.flush();\n this.active = false;\n };\n ColumnAnimationService.prototype.executeNextVMTurn = function (func) {\n if (this.active) {\n this.executeNextFuncs.push(func);\n }\n else {\n func();\n }\n };\n ColumnAnimationService.prototype.executeLaterVMTurn = function (func) {\n if (this.active) {\n this.executeLaterFuncs.push(func);\n }\n else {\n func();\n }\n };\n ColumnAnimationService.prototype.ensureAnimationCssClassPresent = function () {\n var _this = this;\n // up the count, so we can tell if someone else has updated the count\n // by the time the 'wait' func executes\n this.animationThreadCount++;\n var animationThreadCountCopy = this.animationThreadCount;\n this.gridBodyCtrl.setColumnMovingCss(true);\n this.executeLaterFuncs.push(function () {\n // only remove the class if this thread was the last one to update it\n if (_this.animationThreadCount === animationThreadCountCopy) {\n _this.gridBodyCtrl.setColumnMovingCss(false);\n }\n });\n };\n ColumnAnimationService.prototype.flush = function () {\n var nowFuncs = this.executeNextFuncs;\n this.executeNextFuncs = [];\n var waitFuncs = this.executeLaterFuncs;\n this.executeLaterFuncs = [];\n if (nowFuncs.length === 0 && waitFuncs.length === 0) {\n return;\n }\n window.setTimeout(function () { return nowFuncs.forEach(function (func) { return func(); }); }, 0);\n window.setTimeout(function () { return waitFuncs.forEach(function (func) { return func(); }); }, 300);\n };\n __decorate$A([\n Autowired('ctrlsService')\n ], ColumnAnimationService.prototype, \"ctrlsService\", void 0);\n __decorate$A([\n PostConstruct\n ], ColumnAnimationService.prototype, \"postConstruct\", null);\n ColumnAnimationService = __decorate$A([\n Bean('columnAnimationService')\n ], ColumnAnimationService);\n return ColumnAnimationService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$y = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$z = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AutoGroupColService = /** @class */ (function (_super) {\n __extends$y(AutoGroupColService, _super);\n function AutoGroupColService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n AutoGroupColService_1 = AutoGroupColService;\n AutoGroupColService.prototype.createAutoGroupColumns = function (existingCols, rowGroupColumns) {\n var _this = this;\n var groupAutoColumns = [];\n var doingTreeData = this.gridOptionsWrapper.isTreeData();\n var doingMultiAutoColumn = this.gridOptionsWrapper.isGroupMultiAutoColumn();\n if (doingTreeData && doingMultiAutoColumn) {\n console.warn('AG Grid: you cannot mix groupMultiAutoColumn with treeData, only one column can be used to display groups when doing tree data');\n doingMultiAutoColumn = false;\n }\n // if doing groupMultiAutoColumn, then we call the method multiple times, once\n // for each column we are grouping by\n if (doingMultiAutoColumn) {\n rowGroupColumns.forEach(function (rowGroupCol, index) {\n groupAutoColumns.push(_this.createOneAutoGroupColumn(existingCols, rowGroupCol, index));\n });\n }\n else {\n groupAutoColumns.push(this.createOneAutoGroupColumn(existingCols));\n }\n return groupAutoColumns;\n };\n // rowGroupCol and index are missing if groupMultiAutoColumn=false\n AutoGroupColService.prototype.createOneAutoGroupColumn = function (existingCols, rowGroupCol, index) {\n // if one provided by user, use it, otherwise create one\n var defaultAutoColDef = this.generateDefaultColDef(rowGroupCol);\n // if doing multi, set the field\n var colId;\n if (rowGroupCol) {\n colId = Constants.GROUP_AUTO_COLUMN_ID + \"-\" + rowGroupCol.getId();\n }\n else {\n colId = AutoGroupColService_1.GROUP_AUTO_COLUMN_BUNDLE_ID;\n }\n var userAutoColDef = this.gridOptionsWrapper.getAutoGroupColumnDef();\n mergeDeep(defaultAutoColDef, userAutoColDef);\n defaultAutoColDef = this.columnFactory.mergeColDefs(defaultAutoColDef);\n defaultAutoColDef.colId = colId;\n // For tree data the filter is always allowed\n if (!this.gridOptionsWrapper.isTreeData()) {\n // we would only allow filter if the user has provided field or value getter. otherwise the filter\n // would not be able to work.\n var noFieldOrValueGetter = missing(defaultAutoColDef.field) && missing(defaultAutoColDef.valueGetter) && missing(defaultAutoColDef.filterValueGetter);\n if (noFieldOrValueGetter) {\n defaultAutoColDef.filter = false;\n }\n }\n // if showing many cols, we don't want to show more than one with a checkbox for selection\n if (index && index > 0) {\n defaultAutoColDef.headerCheckboxSelection = false;\n }\n var existingCol = existingCols.find(function (col) { return col.getId() == colId; });\n if (existingCol) {\n existingCol.setColDef(defaultAutoColDef, null);\n this.columnFactory.applyColumnState(existingCol, defaultAutoColDef);\n return existingCol;\n }\n var newCol = new Column(defaultAutoColDef, null, colId, true);\n this.context.createBean(newCol);\n return newCol;\n };\n AutoGroupColService.prototype.generateDefaultColDef = function (rowGroupCol) {\n var userDef = this.gridOptionsWrapper.getAutoGroupColumnDef();\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n var res = {\n headerName: localeTextFunc('group', 'Group')\n };\n var userHasProvidedGroupCellRenderer = userDef &&\n (userDef.cellRenderer || userDef.cellRendererFramework || userDef.cellRendererSelector);\n // only add the default group cell renderer if user hasn't provided one\n if (!userHasProvidedGroupCellRenderer) {\n res.cellRenderer = 'agGroupCellRenderer';\n }\n // we never allow moving the group column\n // defaultAutoColDef.suppressMovable = true;\n if (rowGroupCol) {\n var colDef = rowGroupCol.getColDef();\n Object.assign(res, {\n // cellRendererParams.groupKey: colDefToCopy.field;\n headerName: this.columnModel.getDisplayNameForColumn(rowGroupCol, 'header'),\n headerValueGetter: colDef.headerValueGetter\n });\n if (colDef.cellRenderer || colDef.cellRendererFramework) {\n Object.assign(res, {\n cellRendererParams: {\n innerRenderer: colDef.cellRenderer,\n innerRendererFramework: colDef.cellRendererFramework,\n innerRendererParams: colDef.cellRendererParams\n }\n });\n }\n res.showRowGroup = rowGroupCol.getColId();\n }\n else {\n res.showRowGroup = true;\n }\n return res;\n };\n var AutoGroupColService_1;\n AutoGroupColService.GROUP_AUTO_COLUMN_BUNDLE_ID = Constants.GROUP_AUTO_COLUMN_ID;\n __decorate$z([\n Autowired('columnModel')\n ], AutoGroupColService.prototype, \"columnModel\", void 0);\n __decorate$z([\n Autowired('columnFactory')\n ], AutoGroupColService.prototype, \"columnFactory\", void 0);\n AutoGroupColService = AutoGroupColService_1 = __decorate$z([\n Bean('autoGroupColService')\n ], AutoGroupColService);\n return AutoGroupColService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$x = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$y = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar PaginationAutoPageSizeService = /** @class */ (function (_super) {\n __extends$x(PaginationAutoPageSizeService, _super);\n function PaginationAutoPageSizeService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n PaginationAutoPageSizeService.prototype.postConstruct = function () {\n var _this = this;\n this.ctrlsService.whenReady(function (p) {\n _this.centerRowContainerCon = p.centerRowContainerCtrl;\n _this.addManagedListener(_this.eventService, Events.EVENT_BODY_HEIGHT_CHANGED, _this.onBodyHeightChanged.bind(_this));\n _this.addManagedListener(_this.eventService, Events.EVENT_SCROLL_VISIBILITY_CHANGED, _this.onScrollVisibilityChanged.bind(_this));\n _this.checkPageSize();\n });\n };\n PaginationAutoPageSizeService.prototype.notActive = function () {\n return !this.gridOptionsWrapper.isPaginationAutoPageSize();\n };\n PaginationAutoPageSizeService.prototype.onScrollVisibilityChanged = function () {\n this.checkPageSize();\n };\n PaginationAutoPageSizeService.prototype.onBodyHeightChanged = function () {\n this.checkPageSize();\n };\n PaginationAutoPageSizeService.prototype.checkPageSize = function () {\n if (this.notActive()) {\n return;\n }\n var rowHeight = this.gridOptionsWrapper.getRowHeightAsNumber();\n var bodyHeight = this.centerRowContainerCon.getViewportSizeFeature().getBodyHeight();\n if (bodyHeight > 0) {\n var newPageSize = Math.floor(bodyHeight / rowHeight);\n this.gridOptionsWrapper.setProperty('paginationPageSize', newPageSize);\n }\n };\n __decorate$y([\n Autowired('ctrlsService')\n ], PaginationAutoPageSizeService.prototype, \"ctrlsService\", void 0);\n __decorate$y([\n PostConstruct\n ], PaginationAutoPageSizeService.prototype, \"postConstruct\", null);\n PaginationAutoPageSizeService = __decorate$y([\n Bean('paginationAutoPageSizeService')\n ], PaginationAutoPageSizeService);\n return PaginationAutoPageSizeService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$w = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$x = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ValueCache = /** @class */ (function (_super) {\n __extends$w(ValueCache, _super);\n function ValueCache() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.cacheVersion = 0;\n return _this;\n }\n ValueCache.prototype.init = function () {\n this.active = this.gridOptionsWrapper.isValueCache();\n this.neverExpires = this.gridOptionsWrapper.isValueCacheNeverExpires();\n };\n ValueCache.prototype.onDataChanged = function () {\n if (this.neverExpires) {\n return;\n }\n this.expire();\n };\n ValueCache.prototype.expire = function () {\n this.cacheVersion++;\n };\n ValueCache.prototype.setValue = function (rowNode, colId, value) {\n if (this.active) {\n if (rowNode.__cacheVersion !== this.cacheVersion) {\n rowNode.__cacheVersion = this.cacheVersion;\n rowNode.__cacheData = {};\n }\n rowNode.__cacheData[colId] = value;\n }\n };\n ValueCache.prototype.getValue = function (rowNode, colId) {\n if (!this.active || rowNode.__cacheVersion !== this.cacheVersion) {\n return undefined;\n }\n return rowNode.__cacheData[colId];\n };\n __decorate$x([\n PostConstruct\n ], ValueCache.prototype, \"init\", null);\n ValueCache = __decorate$x([\n Bean('valueCache')\n ], ValueCache);\n return ValueCache;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$v = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$w = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ChangeDetectionService = /** @class */ (function (_super) {\n __extends$v(ChangeDetectionService, _super);\n function ChangeDetectionService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ChangeDetectionService.prototype.init = function () {\n if (this.rowModel.getType() === Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n this.clientSideRowModel = this.rowModel;\n }\n this.addManagedListener(this.eventService, Events.EVENT_CELL_VALUE_CHANGED, this.onCellValueChanged.bind(this));\n };\n ChangeDetectionService.prototype.onCellValueChanged = function (event) {\n // Clipboard service manages its own change detection, so no need to do it here.\n // The clipboard manages its own as otherwise this would happen once for every cell\n // that got updated as part of a paste operation, so e.g. if 100 cells in a paste operation,\n // this doChangeDetection would get called 100 times (once for each cell), instead clipboard\n // service executes the logic we have here once (in essence batching up all cell changes\n // into one change detection).\n if (event.source === Constants.SOURCE_PASTE) {\n return;\n }\n this.doChangeDetection(event.node, event.column);\n };\n ChangeDetectionService.prototype.doChangeDetection = function (rowNode, column) {\n if (this.gridOptionsWrapper.isSuppressChangeDetection()) {\n return;\n }\n // step 1 of change detection is to update the aggregated values\n if (this.clientSideRowModel && !rowNode.isRowPinned()) {\n var onlyChangedColumns = this.gridOptionsWrapper.isAggregateOnlyChangedColumns();\n var changedPath = new ChangedPath(onlyChangedColumns, this.clientSideRowModel.getRootNode());\n changedPath.addParentNode(rowNode.parent, [column]);\n this.clientSideRowModel.doAggregate(changedPath);\n }\n // step 2 of change detection is to refresh the cells\n this.rowRenderer.refreshCells();\n };\n __decorate$w([\n Autowired('rowModel')\n ], ChangeDetectionService.prototype, \"rowModel\", void 0);\n __decorate$w([\n Autowired('rowRenderer')\n ], ChangeDetectionService.prototype, \"rowRenderer\", void 0);\n __decorate$w([\n PostConstruct\n ], ChangeDetectionService.prototype, \"init\", null);\n ChangeDetectionService = __decorate$w([\n Bean('changeDetectionService')\n ], ChangeDetectionService);\n return ChangeDetectionService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$u = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$v = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar AgComponentUtils = /** @class */ (function (_super) {\n __extends$u(AgComponentUtils, _super);\n function AgComponentUtils() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n AgComponentUtils.prototype.adaptFunction = function (propertyName, jsCompFunc) {\n var metadata = this.componentMetadataProvider.retrieve(propertyName);\n if (metadata && metadata.functionAdapter) {\n return metadata.functionAdapter(jsCompFunc);\n }\n return null;\n };\n AgComponentUtils.prototype.adaptCellRendererFunction = function (callback) {\n var Adapter = /** @class */ (function () {\n function Adapter() {\n }\n Adapter.prototype.refresh = function (params) {\n return false;\n };\n Adapter.prototype.getGui = function () {\n return this.eGui;\n };\n Adapter.prototype.init = function (params) {\n var callbackResult = callback(params);\n var type = typeof callbackResult;\n if (type === 'string' || type === 'number' || type === 'boolean') {\n this.eGui = loadTemplate('<span>' + callbackResult + '</span>');\n return;\n }\n if (callbackResult == null) {\n this.eGui = loadTemplate('<span></span>');\n return;\n }\n this.eGui = callbackResult;\n };\n return Adapter;\n }());\n return Adapter;\n };\n AgComponentUtils.prototype.doesImplementIComponent = function (candidate) {\n if (!candidate) {\n return false;\n }\n return candidate.prototype && 'getGui' in candidate.prototype;\n };\n __decorate$v([\n Autowired(\"componentMetadataProvider\")\n ], AgComponentUtils.prototype, \"componentMetadataProvider\", void 0);\n AgComponentUtils = __decorate$v([\n Bean(\"agComponentUtils\")\n ], AgComponentUtils);\n return AgComponentUtils;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$t = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$u = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ComponentMetadataProvider = /** @class */ (function (_super) {\n __extends$t(ComponentMetadataProvider, _super);\n function ComponentMetadataProvider() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ComponentMetadataProvider.prototype.postConstruct = function () {\n this.componentMetaData = {\n dateComponent: {\n mandatoryMethodList: ['getDate', 'setDate'],\n optionalMethodList: ['afterGuiAttached', 'setInputPlaceholder', 'setInputAriaLabel']\n },\n detailCellRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: ['refresh'],\n functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)\n },\n headerComponent: {\n mandatoryMethodList: [],\n optionalMethodList: ['refresh']\n },\n headerGroupComponent: {\n mandatoryMethodList: [],\n optionalMethodList: []\n },\n loadingCellRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: []\n },\n loadingOverlayComponent: {\n mandatoryMethodList: [],\n optionalMethodList: []\n },\n noRowsOverlayComponent: {\n mandatoryMethodList: [],\n optionalMethodList: []\n },\n floatingFilterComponent: {\n mandatoryMethodList: ['onParentModelChanged'],\n optionalMethodList: ['afterGuiAttached']\n },\n floatingFilterWrapperComponent: {\n mandatoryMethodList: [],\n optionalMethodList: []\n },\n cellRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: ['refresh', 'afterGuiAttached'],\n functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)\n },\n cellEditor: {\n mandatoryMethodList: ['getValue'],\n optionalMethodList: ['isPopup', 'isCancelBeforeStart', 'isCancelAfterEnd', 'getPopupPosition', 'focusIn', 'focusOut', 'afterGuiAttached']\n },\n innerRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: ['afterGuiAttached'],\n functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)\n },\n fullWidthCellRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: ['refresh', 'afterGuiAttached'],\n functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)\n },\n pinnedRowCellRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: ['refresh', 'afterGuiAttached'],\n functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)\n },\n groupRowRenderer: {\n mandatoryMethodList: [],\n optionalMethodList: ['afterGuiAttached'],\n functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)\n },\n filter: {\n mandatoryMethodList: ['isFilterActive', 'doesFilterPass', 'getModel', 'setModel'],\n optionalMethodList: ['afterGuiAttached', 'onNewRowsLoaded', 'getModelAsString', 'onFloatingFilterChanged', 'onAnyFilterChanged']\n },\n filterComponent: {\n mandatoryMethodList: ['isFilterActive', 'doesFilterPass', 'getModel', 'setModel'],\n optionalMethodList: ['afterGuiAttached', 'onNewRowsLoaded', 'getModelAsString', 'onFloatingFilterChanged', 'onAnyFilterChanged']\n },\n statusPanel: {\n mandatoryMethodList: [],\n optionalMethodList: ['afterGuiAttached'],\n },\n toolPanel: {\n mandatoryMethodList: [],\n optionalMethodList: ['refresh', 'afterGuiAttached']\n },\n tooltipComponent: {\n mandatoryMethodList: [],\n optionalMethodList: []\n }\n };\n };\n ComponentMetadataProvider.prototype.retrieve = function (name) {\n return this.componentMetaData[name];\n };\n __decorate$u([\n Autowired(\"agComponentUtils\")\n ], ComponentMetadataProvider.prototype, \"agComponentUtils\", void 0);\n __decorate$u([\n PostConstruct\n ], ComponentMetadataProvider.prototype, \"postConstruct\", null);\n ComponentMetadataProvider = __decorate$u([\n Bean(\"componentMetadataProvider\")\n ], ComponentMetadataProvider);\n return ComponentMetadataProvider;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$s = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$t = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar MAT_GRID_SIZE = 8;\nvar BASE_GRID_SIZE = 4;\nvar BALHAM_GRID_SIZE = 4;\nvar ALPINE_GRID_SIZE = 6;\nvar HARD_CODED_SIZES = {\n // this item is required for custom themes\n 'ag-theme-custom': {\n headerHeight: 25,\n headerCellMinWidth: 24,\n listItemHeight: BASE_GRID_SIZE * 5,\n rowHeight: 25,\n chartMenuPanelWidth: 220\n },\n 'ag-theme-material': {\n headerHeight: MAT_GRID_SIZE * 7,\n headerCellMinWidth: 48,\n listItemHeight: MAT_GRID_SIZE * 4,\n rowHeight: MAT_GRID_SIZE * 6,\n chartMenuPanelWidth: 240\n },\n 'ag-theme-balham': {\n headerHeight: BALHAM_GRID_SIZE * 8,\n headerCellMinWidth: 24,\n listItemHeight: BALHAM_GRID_SIZE * 6,\n rowHeight: BALHAM_GRID_SIZE * 7,\n chartMenuPanelWidth: 220\n },\n 'ag-theme-alpine': {\n headerHeight: ALPINE_GRID_SIZE * 8,\n headerCellMinWidth: 36,\n listItemHeight: ALPINE_GRID_SIZE * 4,\n rowHeight: ALPINE_GRID_SIZE * 7,\n chartMenuPanelWidth: 240\n }\n};\n/**\n * this object contains a list of Sass variables and an array\n * of CSS styles required to get the correct value.\n * eg. $virtual-item-height requires a structure, so we can get its height.\n * <div class=\"ag-theme-balham\">\n * <div class=\"ag-virtual-list-container\">\n * <div class=\"ag-virtual-list-item\"></div>\n * </div>\n * </div>\n */\nvar SASS_PROPERTY_BUILDER = {\n headerHeight: ['ag-header-row'],\n headerCellMinWidth: ['ag-header-cell'],\n listItemHeight: ['ag-virtual-list-item'],\n rowHeight: ['ag-row'],\n chartMenuPanelWidth: ['ag-chart-docked-container']\n};\nvar CALCULATED_SIZES = {};\nvar Environment = /** @class */ (function (_super) {\n __extends$s(Environment, _super);\n function Environment() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n Environment.prototype.getSassVariable = function (theme, key) {\n var useTheme = 'ag-theme-' + (theme.match('material') ? 'material' : theme.match('balham') ? 'balham' : theme.match('alpine') ? 'alpine' : 'custom');\n var defaultValue = HARD_CODED_SIZES[useTheme][key];\n var calculatedValue = 0;\n if (!CALCULATED_SIZES[theme]) {\n CALCULATED_SIZES[theme] = {};\n }\n var size = CALCULATED_SIZES[theme][key];\n if (size != null) {\n return size;\n }\n if (SASS_PROPERTY_BUILDER[key]) {\n var classList = SASS_PROPERTY_BUILDER[key];\n var div = document.createElement('div');\n div.classList.add(theme);\n div.style.position = 'absolute';\n var el = classList.reduce(function (prevEl, currentClass) {\n var currentDiv = document.createElement('div');\n currentDiv.style.position = 'static';\n currentDiv.classList.add(currentClass);\n prevEl.appendChild(currentDiv);\n return currentDiv;\n }, div);\n if (document.body) {\n document.body.appendChild(div);\n var sizeName = key.toLowerCase().indexOf('height') !== -1 ? 'height' : 'width';\n calculatedValue = parseInt(window.getComputedStyle(el)[sizeName], 10);\n document.body.removeChild(div);\n }\n }\n CALCULATED_SIZES[theme][key] = calculatedValue || defaultValue;\n return CALCULATED_SIZES[theme][key];\n };\n Environment.prototype.isThemeDark = function () {\n var theme = this.getTheme().theme;\n return !!theme && theme.indexOf('dark') >= 0;\n };\n Environment.prototype.chartMenuPanelWidth = function () {\n var theme = this.getTheme().themeFamily;\n return this.getSassVariable(theme, 'chartMenuPanelWidth');\n };\n Environment.prototype.getTheme = function () {\n var reg = /\\bag-(material|(?:theme-([\\w\\-]*)))\\b/g;\n var el = this.eGridDiv;\n var themeMatch = null;\n var allThemes = [];\n while (el) {\n themeMatch = reg.exec(el.className);\n if (!themeMatch) {\n el = el.parentElement || undefined;\n }\n else {\n var matched = el.className.match(reg);\n if (matched) {\n allThemes = matched;\n }\n break;\n }\n }\n if (!themeMatch) {\n return { allThemes: allThemes };\n }\n var theme = themeMatch[0];\n var usingOldTheme = themeMatch[2] === undefined;\n if (usingOldTheme) {\n var newTheme_1 = theme.replace('ag-', 'ag-theme-');\n doOnce(function () { return console.warn(\"AG Grid: As of v19 old theme are no longer provided. Please replace \" + theme + \" with \" + newTheme_1 + \".\"); }, 'using-old-theme');\n }\n return { theme: theme, el: el, themeFamily: theme.replace(/-dark$/, ''), allThemes: allThemes };\n };\n __decorate$t([\n Autowired('eGridDiv')\n ], Environment.prototype, \"eGridDiv\", void 0);\n Environment = __decorate$t([\n Bean('environment')\n ], Environment);\n return Environment;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$r = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$s = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param$1 = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\n/**\n * This class solves the 'max height' problem, where the user might want to show more data than\n * the max div height actually allows.\n */\nvar RowContainerHeightService = /** @class */ (function (_super) {\n __extends$r(RowContainerHeightService, _super);\n function RowContainerHeightService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n // the scrollY position\n _this.scrollY = 0;\n // how tall the body is\n _this.uiBodyHeight = 0;\n return _this;\n }\n RowContainerHeightService.prototype.agWire = function (loggerFactory) {\n this.logger = loggerFactory.create(\"RowContainerHeightService\");\n };\n RowContainerHeightService.prototype.postConstruct = function () {\n this.addManagedListener(this.eventService, Events.EVENT_BODY_HEIGHT_CHANGED, this.updateOffset.bind(this));\n this.maxDivHeight = getMaxDivHeight();\n this.logger.log('maxDivHeight = ' + this.maxDivHeight);\n };\n RowContainerHeightService.prototype.isStretching = function () {\n return this.stretching;\n };\n RowContainerHeightService.prototype.getDivStretchOffset = function () {\n return this.divStretchOffset;\n };\n RowContainerHeightService.prototype.updateOffset = function () {\n if (!this.stretching) {\n return;\n }\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var newScrollY = gridBodyCon.getScrollFeature().getVScrollPosition().top;\n var newBodyHeight = this.getUiBodyHeight();\n var atLeastOneChanged = newScrollY !== this.scrollY || newBodyHeight !== this.uiBodyHeight;\n if (atLeastOneChanged) {\n this.scrollY = newScrollY;\n this.uiBodyHeight = newBodyHeight;\n this.calculateOffset();\n }\n };\n RowContainerHeightService.prototype.calculateOffset = function () {\n this.setUiContainerHeight(this.maxDivHeight);\n this.pixelsToShave = this.modelHeight - this.uiContainerHeight;\n this.maxScrollY = this.uiContainerHeight - this.uiBodyHeight;\n var scrollPercent = this.scrollY / this.maxScrollY;\n var divStretchOffset = scrollPercent * this.pixelsToShave;\n this.logger.log(\"Div Stretch Offset = \" + divStretchOffset + \" (\" + this.pixelsToShave + \" * \" + scrollPercent + \")\");\n this.setDivStretchOffset(divStretchOffset);\n };\n RowContainerHeightService.prototype.setUiContainerHeight = function (height) {\n if (height !== this.uiContainerHeight) {\n this.uiContainerHeight = height;\n this.eventService.dispatchEvent({ type: Events.EVENT_ROW_CONTAINER_HEIGHT_CHANGED });\n }\n };\n RowContainerHeightService.prototype.clearOffset = function () {\n this.setUiContainerHeight(this.modelHeight);\n this.pixelsToShave = 0;\n this.setDivStretchOffset(0);\n };\n RowContainerHeightService.prototype.setDivStretchOffset = function (newOffset) {\n // because we are talking pixels, no point in confusing things with half numbers\n var newOffsetFloor = typeof newOffset === 'number' ? Math.floor(newOffset) : null;\n if (this.divStretchOffset === newOffsetFloor) {\n return;\n }\n this.divStretchOffset = newOffsetFloor;\n this.eventService.dispatchEvent({ type: Events.EVENT_HEIGHT_SCALE_CHANGED });\n };\n RowContainerHeightService.prototype.setModelHeight = function (modelHeight) {\n this.modelHeight = modelHeight;\n this.stretching = modelHeight != null // null happens when in print layout\n && this.maxDivHeight > 0\n && modelHeight > this.maxDivHeight;\n if (this.stretching) {\n this.calculateOffset();\n }\n else {\n this.clearOffset();\n }\n };\n RowContainerHeightService.prototype.getUiContainerHeight = function () {\n return this.uiContainerHeight;\n };\n RowContainerHeightService.prototype.getRealPixelPosition = function (modelPixel) {\n return modelPixel - this.divStretchOffset;\n };\n RowContainerHeightService.prototype.getUiBodyHeight = function () {\n var gridBodyCon = this.ctrlsService.getGridBodyCtrl();\n var pos = gridBodyCon.getScrollFeature().getVScrollPosition();\n return pos.bottom - pos.top;\n };\n RowContainerHeightService.prototype.getScrollPositionForPixel = function (rowTop) {\n if (this.pixelsToShave <= 0) {\n return rowTop;\n }\n var modelMaxScroll = this.modelHeight - this.getUiBodyHeight();\n var scrollPercent = rowTop / modelMaxScroll;\n var scrollPixel = this.maxScrollY * scrollPercent;\n return scrollPixel;\n };\n __decorate$s([\n Autowired('ctrlsService')\n ], RowContainerHeightService.prototype, \"ctrlsService\", void 0);\n __decorate$s([\n __param$1(0, Qualifier(\"loggerFactory\"))\n ], RowContainerHeightService.prototype, \"agWire\", null);\n __decorate$s([\n PostConstruct\n ], RowContainerHeightService.prototype, \"postConstruct\", null);\n RowContainerHeightService = __decorate$s([\n Bean('rowContainerHeightService')\n ], RowContainerHeightService);\n return RowContainerHeightService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$q = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$r = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SelectableService = /** @class */ (function (_super) {\n __extends$q(SelectableService, _super);\n function SelectableService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SelectableService.prototype.init = function () {\n this.groupSelectsChildren = this.gridOptionsWrapper.isGroupSelectsChildren();\n this.isRowSelectableFunc = this.gridOptionsWrapper.getIsRowSelectableFunc();\n };\n SelectableService.prototype.updateSelectableAfterGrouping = function (rowNode) {\n if (this.isRowSelectableFunc) {\n var nextChildrenFunc = function (node) { return node.childrenAfterGroup; };\n this.recurseDown(rowNode.childrenAfterGroup, nextChildrenFunc);\n }\n };\n SelectableService.prototype.recurseDown = function (children, nextChildrenFunc) {\n var _this = this;\n if (!children) {\n return;\n }\n children.forEach(function (child) {\n if (!child.group) {\n return;\n } // only interested in groups\n if (child.hasChildren()) {\n _this.recurseDown(nextChildrenFunc(child), nextChildrenFunc);\n }\n var rowSelectable;\n if (_this.groupSelectsChildren) {\n // have this group selectable if at least one direct child is selectable\n var firstSelectable = (nextChildrenFunc(child) || []).find(function (rowNode) { return rowNode.selectable === true; });\n rowSelectable = exists(firstSelectable);\n }\n else {\n // directly retrieve selectable value from user callback\n rowSelectable = _this.isRowSelectableFunc ? _this.isRowSelectableFunc(child) : false;\n }\n child.setRowSelectable(rowSelectable);\n });\n };\n __decorate$r([\n PostConstruct\n ], SelectableService.prototype, \"init\", null);\n SelectableService = __decorate$r([\n Bean('selectableService')\n ], SelectableService);\n return SelectableService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$p = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$q = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar PaginationComp = /** @class */ (function (_super) {\n __extends$p(PaginationComp, _super);\n function PaginationComp() {\n var _this = _super.call(this) || this;\n _this.previousAndFirstButtonsDisabled = false;\n _this.nextButtonDisabled = false;\n _this.lastButtonDisabled = false;\n return _this;\n }\n PaginationComp.prototype.postConstruct = function () {\n var _this = this;\n var isRtl = this.gridOptionsWrapper.isEnableRtl();\n this.setTemplate(this.getTemplate());\n this.btFirst.insertAdjacentElement('afterbegin', createIconNoSpan(isRtl ? 'last' : 'first', this.gridOptionsWrapper));\n this.btPrevious.insertAdjacentElement('afterbegin', createIconNoSpan(isRtl ? 'next' : 'previous', this.gridOptionsWrapper));\n this.btNext.insertAdjacentElement('afterbegin', createIconNoSpan(isRtl ? 'previous' : 'next', this.gridOptionsWrapper));\n this.btLast.insertAdjacentElement('afterbegin', createIconNoSpan(isRtl ? 'first' : 'last', this.gridOptionsWrapper));\n var isPaging = this.gridOptionsWrapper.isPagination();\n var paginationPanelEnabled = isPaging && !this.gridOptionsWrapper.isSuppressPaginationPanel();\n if (!paginationPanelEnabled) {\n this.setDisplayed(false);\n return;\n }\n this.addManagedListener(this.eventService, Events.EVENT_PAGINATION_CHANGED, this.onPaginationChanged.bind(this));\n [\n { el: this.btFirst, fn: this.onBtFirst.bind(this) },\n { el: this.btPrevious, fn: this.onBtPrevious.bind(this) },\n { el: this.btNext, fn: this.onBtNext.bind(this) },\n { el: this.btLast, fn: this.onBtLast.bind(this) }\n ].forEach(function (item) {\n var el = item.el, fn = item.fn;\n _this.addManagedListener(el, 'click', fn);\n _this.addManagedListener(el, 'keydown', function (e) {\n if (e.key === KeyCode.ENTER || e.key === KeyCode.SPACE) {\n e.preventDefault();\n fn();\n }\n });\n });\n this.onPaginationChanged();\n };\n PaginationComp.prototype.onPaginationChanged = function () {\n this.enableOrDisableButtons();\n this.updateRowLabels();\n this.setCurrentPageLabel();\n this.setTotalLabels();\n };\n PaginationComp.prototype.onBtFirst = function () {\n if (!this.previousAndFirstButtonsDisabled) {\n this.paginationProxy.goToFirstPage();\n }\n };\n PaginationComp.prototype.setCurrentPageLabel = function () {\n var pagesExist = this.paginationProxy.getTotalPages() > 0;\n var currentPage = this.paginationProxy.getCurrentPage();\n var toDisplay = pagesExist ? currentPage + 1 : 0;\n this.lbCurrent.innerHTML = this.formatNumber(toDisplay);\n };\n PaginationComp.prototype.formatNumber = function (value) {\n var userFunc = this.gridOptionsWrapper.getPaginationNumberFormatterFunc();\n if (userFunc) {\n var params = { value: value };\n return userFunc(params);\n }\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n var thousandSeparator = localeTextFunc('thousandSeparator', ',');\n var decimalSeparator = localeTextFunc('decimalSeparator', '.');\n return formatNumberCommas(value, thousandSeparator, decimalSeparator);\n };\n PaginationComp.prototype.getTemplate = function () {\n var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();\n var strPage = localeTextFunc('page', 'Page');\n var strTo = localeTextFunc('to', 'to');\n var strOf = localeTextFunc('of', 'of');\n var strFirst = localeTextFunc('firstPage', 'First Page');\n var strPrevious = localeTextFunc('previousPage', 'Previous Page');\n var strNext = localeTextFunc('nextPage', 'Next Page');\n var strLast = localeTextFunc('lastPage', 'Last Page');\n var compId = this.getCompId();\n return /* html */ \"<div class=\\\"ag-paging-panel ag-unselectable\\\" id=\\\"ag-\" + compId + \"\\\">\\n <span class=\\\"ag-paging-row-summary-panel\\\" role=\\\"status\\\">\\n <span id=\\\"ag-\" + compId + \"-first-row\\\" ref=\\\"lbFirstRowOnPage\\\" class=\\\"ag-paging-row-summary-panel-number\\\"></span>\\n <span id=\\\"ag-\" + compId + \"-to\\\">\" + strTo + \"</span>\\n <span id=\\\"ag-\" + compId + \"-last-row\\\" ref=\\\"lbLastRowOnPage\\\" class=\\\"ag-paging-row-summary-panel-number\\\"></span>\\n <span id=\\\"ag-\" + compId + \"-of\\\">\" + strOf + \"</span>\\n <span id=\\\"ag-\" + compId + \"-row-count\\\" ref=\\\"lbRecordCount\\\" class=\\\"ag-paging-row-summary-panel-number\\\"></span>\\n </span>\\n <span class=\\\"ag-paging-page-summary-panel\\\" role=\\\"presentation\\\">\\n <div ref=\\\"btFirst\\\" class=\\\"ag-paging-button\\\" role=\\\"button\\\" aria-label=\\\"\" + strFirst + \"\\\"></div>\\n <div ref=\\\"btPrevious\\\" class=\\\"ag-paging-button\\\" role=\\\"button\\\" aria-label=\\\"\" + strPrevious + \"\\\"></div>\\n <span class=\\\"ag-paging-description\\\" role=\\\"status\\\">\\n <span id=\\\"ag-\" + compId + \"-start-page\\\">\" + strPage + \"</span>\\n <span id=\\\"ag-\" + compId + \"-start-page-number\\\" ref=\\\"lbCurrent\\\" class=\\\"ag-paging-number\\\"></span>\\n <span id=\\\"ag-\" + compId + \"-of-page\\\">\" + strOf + \"</span>\\n <span id=\\\"ag-\" + compId + \"-of-page-number\\\" ref=\\\"lbTotal\\\" class=\\\"ag-paging-number\\\"></span>\\n </span>\\n <div ref=\\\"btNext\\\" class=\\\"ag-paging-button\\\" role=\\\"button\\\" aria-label=\\\"\" + strNext + \"\\\"></div>\\n <div ref=\\\"btLast\\\" class=\\\"ag-paging-button\\\" role=\\\"button\\\" aria-label=\\\"\" + strLast + \"\\\"></div>\\n </span>\\n </div>\";\n };\n PaginationComp.prototype.onBtNext = function () {\n if (!this.nextButtonDisabled) {\n this.paginationProxy.goToNextPage();\n }\n };\n PaginationComp.prototype.onBtPrevious = function () {\n if (!this.previousAndFirstButtonsDisabled) {\n this.paginationProxy.goToPreviousPage();\n }\n };\n PaginationComp.prototype.onBtLast = function () {\n if (!this.lastButtonDisabled) {\n this.paginationProxy.goToLastPage();\n }\n };\n PaginationComp.prototype.enableOrDisableButtons = function () {\n var currentPage = this.paginationProxy.getCurrentPage();\n var maxRowFound = this.paginationProxy.isLastPageFound();\n var totalPages = this.paginationProxy.getTotalPages();\n this.previousAndFirstButtonsDisabled = currentPage === 0;\n this.toggleButtonDisabled(this.btFirst, this.previousAndFirstButtonsDisabled);\n this.toggleButtonDisabled(this.btPrevious, this.previousAndFirstButtonsDisabled);\n var zeroPagesToDisplay = this.isZeroPagesToDisplay();\n var onLastPage = maxRowFound && currentPage === (totalPages - 1);\n this.nextButtonDisabled = onLastPage || zeroPagesToDisplay;\n this.lastButtonDisabled = !maxRowFound || zeroPagesToDisplay || currentPage === (totalPages - 1);\n this.toggleButtonDisabled(this.btNext, this.nextButtonDisabled);\n this.toggleButtonDisabled(this.btLast, this.lastButtonDisabled);\n };\n PaginationComp.prototype.toggleButtonDisabled = function (button, disabled) {\n setAriaDisabled(button, disabled);\n button.classList.toggle('ag-disabled', disabled);\n if (disabled) {\n button.removeAttribute('tabindex');\n }\n else {\n button.setAttribute('tabindex', '0');\n }\n };\n PaginationComp.prototype.updateRowLabels = function () {\n var currentPage = this.paginationProxy.getCurrentPage();\n var pageSize = this.paginationProxy.getPageSize();\n var maxRowFound = this.paginationProxy.isLastPageFound();\n var rowCount = this.paginationProxy.isLastPageFound() ?\n this.paginationProxy.getMasterRowCount() : null;\n var startRow;\n var endRow;\n if (this.isZeroPagesToDisplay()) {\n startRow = endRow = 0;\n }\n else {\n startRow = (pageSize * currentPage) + 1;\n endRow = startRow + pageSize - 1;\n if (maxRowFound && endRow > rowCount) {\n endRow = rowCount;\n }\n }\n this.lbFirstRowOnPage.innerHTML = this.formatNumber(startRow);\n if (this.rowNodeBlockLoader.isLoading()) {\n this.lbLastRowOnPage.innerHTML = '?';\n }\n else {\n this.lbLastRowOnPage.innerHTML = this.formatNumber(endRow);\n }\n };\n PaginationComp.prototype.isZeroPagesToDisplay = function () {\n var maxRowFound = this.paginationProxy.isLastPageFound();\n var totalPages = this.paginationProxy.getTotalPages();\n return maxRowFound && totalPages === 0;\n };\n PaginationComp.prototype.setTotalLabels = function () {\n var lastPageFound = this.paginationProxy.isLastPageFound();\n var totalPages = this.paginationProxy.getTotalPages();\n var rowCount = lastPageFound ? this.paginationProxy.getMasterRowCount() : null;\n // When `pivotMode=true` and no grouping or value columns exist, a single 'hidden' group row (root node) is in\n // the grid and the pagination totals will correctly display total = 1. However this is confusing to users as\n // they can't see it. To address this UX issue we simply set the totals to zero in the pagination panel.\n if (rowCount === 1) {\n var firstRow = this.paginationProxy.getRow(0);\n // a group node with no group or agg data will not be visible to users\n var hiddenGroupRow = firstRow && firstRow.group && !(firstRow.groupData || firstRow.aggData);\n if (hiddenGroupRow) {\n this.setTotalLabelsToZero();\n return;\n }\n }\n if (lastPageFound) {\n this.lbTotal.innerHTML = this.formatNumber(totalPages);\n this.lbRecordCount.innerHTML = this.formatNumber(rowCount);\n }\n else {\n var moreText = this.gridOptionsWrapper.getLocaleTextFunc()('more', 'more');\n this.lbTotal.innerHTML = moreText;\n this.lbRecordCount.innerHTML = moreText;\n }\n };\n PaginationComp.prototype.setTotalLabelsToZero = function () {\n this.lbFirstRowOnPage.innerHTML = this.formatNumber(0);\n this.lbCurrent.innerHTML = this.formatNumber(0);\n this.lbLastRowOnPage.innerHTML = this.formatNumber(0);\n this.lbTotal.innerHTML = this.formatNumber(0);\n this.lbRecordCount.innerHTML = this.formatNumber(0);\n };\n __decorate$q([\n Autowired('paginationProxy')\n ], PaginationComp.prototype, \"paginationProxy\", void 0);\n __decorate$q([\n Autowired('rowNodeBlockLoader')\n ], PaginationComp.prototype, \"rowNodeBlockLoader\", void 0);\n __decorate$q([\n RefSelector('btFirst')\n ], PaginationComp.prototype, \"btFirst\", void 0);\n __decorate$q([\n RefSelector('btPrevious')\n ], PaginationComp.prototype, \"btPrevious\", void 0);\n __decorate$q([\n RefSelector('btNext')\n ], PaginationComp.prototype, \"btNext\", void 0);\n __decorate$q([\n RefSelector('btLast')\n ], PaginationComp.prototype, \"btLast\", void 0);\n __decorate$q([\n RefSelector('lbRecordCount')\n ], PaginationComp.prototype, \"lbRecordCount\", void 0);\n __decorate$q([\n RefSelector('lbFirstRowOnPage')\n ], PaginationComp.prototype, \"lbFirstRowOnPage\", void 0);\n __decorate$q([\n RefSelector('lbLastRowOnPage')\n ], PaginationComp.prototype, \"lbLastRowOnPage\", void 0);\n __decorate$q([\n RefSelector('lbCurrent')\n ], PaginationComp.prototype, \"lbCurrent\", void 0);\n __decorate$q([\n RefSelector('lbTotal')\n ], PaginationComp.prototype, \"lbTotal\", void 0);\n __decorate$q([\n PostConstruct\n ], PaginationComp.prototype, \"postConstruct\", null);\n return PaginationComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$o = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$p = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar LoadingType;\n(function (LoadingType) {\n LoadingType[LoadingType[\"Loading\"] = 0] = \"Loading\";\n LoadingType[LoadingType[\"NoRows\"] = 1] = \"NoRows\";\n})(LoadingType || (LoadingType = {}));\nvar OverlayWrapperComponent = /** @class */ (function (_super) {\n __extends$o(OverlayWrapperComponent, _super);\n function OverlayWrapperComponent() {\n var _this = _super.call(this, OverlayWrapperComponent.TEMPLATE) || this;\n _this.inProgress = false;\n _this.destroyRequested = false;\n _this.manuallyDisplayed = false;\n return _this;\n }\n OverlayWrapperComponent.prototype.updateLayoutClasses = function (cssClass, params) {\n var overlayWrapperClassList = this.eOverlayWrapper.classList;\n overlayWrapperClassList.toggle(LayoutCssClasses.AUTO_HEIGHT, params.autoHeight);\n overlayWrapperClassList.toggle(LayoutCssClasses.NORMAL, params.normal);\n overlayWrapperClassList.toggle(LayoutCssClasses.PRINT, params.print);\n };\n OverlayWrapperComponent.prototype.postConstruct = function () {\n this.createManagedBean(new LayoutFeature(this));\n this.setDisplayed(false);\n this.addManagedListener(this.eventService, Events.EVENT_ROW_DATA_UPDATED, this.onRowDataUpdated.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.onNewColumnsLoaded.bind(this));\n if (this.gridOptionsWrapper.isRowModelDefault() && !this.gridOptionsWrapper.getRowData()) {\n this.showLoadingOverlay();\n }\n this.gridApi.registerOverlayWrapperComp(this);\n };\n OverlayWrapperComponent.prototype.setWrapperTypeClass = function (loadingType) {\n var overlayWrapperClassList = this.eOverlayWrapper.classList;\n overlayWrapperClassList.toggle('ag-overlay-loading-wrapper', loadingType === LoadingType.Loading);\n overlayWrapperClassList.toggle('ag-overlay-no-rows-wrapper', loadingType === LoadingType.NoRows);\n };\n OverlayWrapperComponent.prototype.showLoadingOverlay = function () {\n if (this.gridOptionsWrapper.isSuppressLoadingOverlay()) {\n return;\n }\n var params = {};\n var compDetails = this.userComponentFactory.getLoadingOverlayCompDetails(params);\n var promise = compDetails.newAgStackInstance();\n this.showOverlay(promise, LoadingType.Loading);\n };\n OverlayWrapperComponent.prototype.showNoRowsOverlay = function () {\n if (this.gridOptionsWrapper.isSuppressNoRowsOverlay()) {\n return;\n }\n var params = {};\n var compDetails = this.userComponentFactory.getNoRowsOverlayCompDetails(params);\n var promise = compDetails.newAgStackInstance();\n this.showOverlay(promise, LoadingType.NoRows);\n };\n OverlayWrapperComponent.prototype.showOverlay = function (workItem, type) {\n var _this = this;\n if (this.inProgress) {\n return;\n }\n this.setWrapperTypeClass(type);\n this.destroyActiveOverlay();\n this.inProgress = true;\n if (workItem) {\n workItem.then(function (comp) {\n _this.inProgress = false;\n _this.eOverlayWrapper.appendChild(comp.getGui());\n _this.activeOverlay = comp;\n if (_this.destroyRequested) {\n _this.destroyRequested = false;\n _this.destroyActiveOverlay();\n }\n });\n }\n this.manuallyDisplayed = this.columnModel.isReady() && !this.paginationProxy.isEmpty();\n this.setDisplayed(true);\n };\n OverlayWrapperComponent.prototype.destroyActiveOverlay = function () {\n if (this.inProgress) {\n this.destroyRequested = true;\n return;\n }\n if (!this.activeOverlay) {\n return;\n }\n this.activeOverlay = this.getContext().destroyBean(this.activeOverlay);\n clearElement(this.eOverlayWrapper);\n };\n OverlayWrapperComponent.prototype.hideOverlay = function () {\n this.manuallyDisplayed = false;\n this.destroyActiveOverlay();\n this.setDisplayed(false);\n };\n OverlayWrapperComponent.prototype.destroy = function () {\n this.destroyActiveOverlay();\n _super.prototype.destroy.call(this);\n };\n OverlayWrapperComponent.prototype.showOrHideOverlay = function () {\n var isEmpty = this.paginationProxy.isEmpty();\n var isSuppressNoRowsOverlay = this.gridOptionsWrapper.isSuppressNoRowsOverlay();\n if (isEmpty && !isSuppressNoRowsOverlay) {\n this.showNoRowsOverlay();\n }\n else {\n this.hideOverlay();\n }\n };\n OverlayWrapperComponent.prototype.onRowDataUpdated = function () {\n this.showOrHideOverlay();\n };\n OverlayWrapperComponent.prototype.onNewColumnsLoaded = function () {\n // hide overlay if columns and rows exist, this can happen if columns are loaded after data.\n // this problem exists before of the race condition between the services (column controller in this case)\n // and the view (grid panel). if the model beans were all initialised first, and then the view beans second,\n // this race condition would not happen.\n if (this.columnModel.isReady() && !this.paginationProxy.isEmpty() && !this.manuallyDisplayed) {\n this.hideOverlay();\n }\n };\n // wrapping in outer div, and wrapper, is needed to center the loading icon\n // The idea for centering came from here: http://www.vanseodesign.com/css/vertical-centering/\n OverlayWrapperComponent.TEMPLATE = \"\\n <div class=\\\"ag-overlay\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"ag-overlay-panel\\\">\\n <div class=\\\"ag-overlay-wrapper\\\" ref=\\\"eOverlayWrapper\\\"></div>\\n </div>\\n </div>\";\n __decorate$p([\n Autowired('userComponentFactory')\n ], OverlayWrapperComponent.prototype, \"userComponentFactory\", void 0);\n __decorate$p([\n Autowired('paginationProxy')\n ], OverlayWrapperComponent.prototype, \"paginationProxy\", void 0);\n __decorate$p([\n Autowired('gridApi')\n ], OverlayWrapperComponent.prototype, \"gridApi\", void 0);\n __decorate$p([\n Autowired('columnModel')\n ], OverlayWrapperComponent.prototype, \"columnModel\", void 0);\n __decorate$p([\n RefSelector('eOverlayWrapper')\n ], OverlayWrapperComponent.prototype, \"eOverlayWrapper\", void 0);\n __decorate$p([\n PostConstruct\n ], OverlayWrapperComponent.prototype, \"postConstruct\", null);\n return OverlayWrapperComponent;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$n = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$o = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RowPositionUtils = /** @class */ (function (_super) {\n __extends$n(RowPositionUtils, _super);\n function RowPositionUtils() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n RowPositionUtils.prototype.getFirstRow = function () {\n var rowIndex = 0;\n var rowPinned;\n if (this.pinnedRowModel.getPinnedTopRowCount()) {\n rowPinned = Constants.PINNED_TOP;\n }\n else if (this.rowModel.getRowCount()) {\n rowPinned = null;\n rowIndex = this.paginationProxy.getPageFirstRow();\n }\n else if (this.pinnedRowModel.getPinnedBottomRowCount()) {\n rowPinned = Constants.PINNED_BOTTOM;\n }\n return rowPinned === undefined ? null : { rowIndex: rowIndex, rowPinned: rowPinned };\n };\n RowPositionUtils.prototype.getLastRow = function () {\n var rowIndex;\n var rowPinned = null;\n var pinnedBottomCount = this.pinnedRowModel.getPinnedBottomRowCount();\n var pinnedTopCount = this.pinnedRowModel.getPinnedTopRowCount();\n if (pinnedBottomCount) {\n rowPinned = Constants.PINNED_BOTTOM;\n rowIndex = pinnedBottomCount - 1;\n }\n else if (this.rowModel.getRowCount()) {\n rowPinned = null;\n rowIndex = this.paginationProxy.getPageLastRow();\n }\n else if (pinnedTopCount) {\n rowPinned = Constants.PINNED_TOP;\n rowIndex = pinnedTopCount - 1;\n }\n return rowIndex === undefined ? null : { rowIndex: rowIndex, rowPinned: rowPinned };\n };\n RowPositionUtils.prototype.getRowNode = function (gridRow) {\n switch (gridRow.rowPinned) {\n case Constants.PINNED_TOP:\n return this.pinnedRowModel.getPinnedTopRowData()[gridRow.rowIndex];\n case Constants.PINNED_BOTTOM:\n return this.pinnedRowModel.getPinnedBottomRowData()[gridRow.rowIndex];\n default:\n return this.rowModel.getRow(gridRow.rowIndex);\n }\n };\n RowPositionUtils.prototype.sameRow = function (rowA, rowB) {\n // if both missing\n if (!rowA && !rowB) {\n return true;\n }\n // if only one missing\n if ((rowA && !rowB) || (!rowA && rowB)) {\n return false;\n }\n // otherwise compare (use == to compare rowPinned because it can be null or undefined)\n return rowA.rowIndex === rowB.rowIndex && rowA.rowPinned == rowB.rowPinned;\n };\n // tests if this row selection is before the other row selection\n RowPositionUtils.prototype.before = function (rowA, rowB) {\n switch (rowA.rowPinned) {\n case Constants.PINNED_TOP:\n // we we are floating top, and other isn't, then we are always before\n if (rowB.rowPinned !== Constants.PINNED_TOP) {\n return true;\n }\n break;\n case Constants.PINNED_BOTTOM:\n // if we are floating bottom, and the other isn't, then we are never before\n if (rowB.rowPinned !== Constants.PINNED_BOTTOM) {\n return false;\n }\n break;\n default:\n // if we are not floating, but the other one is floating...\n if (exists(rowB.rowPinned)) {\n return rowB.rowPinned !== Constants.PINNED_TOP;\n }\n break;\n }\n return rowA.rowIndex < rowB.rowIndex;\n };\n RowPositionUtils.prototype.rowMax = function (rows) {\n var _this = this;\n var max;\n rows.forEach(function (row) {\n if (max === undefined || _this.before(max, row)) {\n max = row;\n }\n });\n return max;\n };\n RowPositionUtils.prototype.rowMin = function (rows) {\n var _this = this;\n var min;\n rows.forEach(function (row) {\n if (min === undefined || _this.before(row, min)) {\n min = row;\n }\n });\n return min;\n };\n __decorate$o([\n Autowired('rowModel')\n ], RowPositionUtils.prototype, \"rowModel\", void 0);\n __decorate$o([\n Autowired('pinnedRowModel')\n ], RowPositionUtils.prototype, \"pinnedRowModel\", void 0);\n __decorate$o([\n Autowired('paginationProxy')\n ], RowPositionUtils.prototype, \"paginationProxy\", void 0);\n RowPositionUtils = __decorate$o([\n Bean('rowPositionUtils')\n ], RowPositionUtils);\n return RowPositionUtils;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$m = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$n = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar CellPositionUtils = /** @class */ (function (_super) {\n __extends$m(CellPositionUtils, _super);\n function CellPositionUtils() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n CellPositionUtils.prototype.createId = function (cellPosition) {\n var rowIndex = cellPosition.rowIndex, rowPinned = cellPosition.rowPinned, column = cellPosition.column;\n return this.createIdFromValues(rowIndex, column, rowPinned);\n };\n CellPositionUtils.prototype.createIdFromValues = function (rowIndex, column, rowPinned) {\n return rowIndex + \".\" + (rowPinned == null ? 'null' : rowPinned) + \".\" + column.getId();\n };\n CellPositionUtils.prototype.equals = function (cellA, cellB) {\n var colsMatch = cellA.column === cellB.column;\n var floatingMatch = cellA.rowPinned === cellB.rowPinned;\n var indexMatch = cellA.rowIndex === cellB.rowIndex;\n return colsMatch && floatingMatch && indexMatch;\n };\n CellPositionUtils = __decorate$n([\n Bean('cellPositionUtils')\n ], CellPositionUtils);\n return CellPositionUtils;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$l = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar UndoRedoAction = /** @class */ (function () {\n function UndoRedoAction(cellValueChanges) {\n this.cellValueChanges = cellValueChanges;\n }\n return UndoRedoAction;\n}());\nvar RangeUndoRedoAction = /** @class */ (function (_super) {\n __extends$l(RangeUndoRedoAction, _super);\n function RangeUndoRedoAction(cellValueChanges, initialRange, finalRange, ranges) {\n var _this = _super.call(this, cellValueChanges) || this;\n _this.initialRange = initialRange;\n _this.finalRange = finalRange;\n _this.ranges = ranges;\n return _this;\n }\n return RangeUndoRedoAction;\n}(UndoRedoAction));\nvar UndoRedoStack = /** @class */ (function () {\n function UndoRedoStack(maxStackSize) {\n this.actionStack = [];\n this.maxStackSize = maxStackSize ? maxStackSize : UndoRedoStack.DEFAULT_STACK_SIZE;\n this.actionStack = new Array(this.maxStackSize);\n }\n UndoRedoStack.prototype.pop = function () {\n return this.actionStack.pop();\n };\n UndoRedoStack.prototype.push = function (item) {\n var shouldAddActions = item.cellValueChanges && item.cellValueChanges.length > 0;\n if (!shouldAddActions) {\n return;\n }\n if (this.actionStack.length === this.maxStackSize) {\n this.actionStack.shift();\n }\n this.actionStack.push(item);\n };\n UndoRedoStack.prototype.clear = function () {\n this.actionStack = [];\n };\n UndoRedoStack.prototype.getCurrentStackSize = function () {\n return this.actionStack.length;\n };\n UndoRedoStack.DEFAULT_STACK_SIZE = 10;\n return UndoRedoStack;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$k = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign = (undefined && undefined.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __decorate$m = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read$3 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$2 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$3(arguments[i]));\n return ar;\n};\nvar UndoRedoService = /** @class */ (function (_super) {\n __extends$k(UndoRedoService, _super);\n function UndoRedoService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.cellValueChanges = [];\n _this.activeCellEdit = null;\n _this.activeRowEdit = null;\n _this.isPasting = false;\n _this.isRangeInAction = false;\n _this.onCellValueChanged = function (event) {\n var eventCell = { column: event.column, rowIndex: event.rowIndex, rowPinned: event.rowPinned };\n var isCellEditing = _this.activeCellEdit !== null && _this.cellPositionUtils.equals(_this.activeCellEdit, eventCell);\n var isRowEditing = _this.activeRowEdit !== null && _this.rowPositionUtils.sameRow(_this.activeRowEdit, eventCell);\n var shouldCaptureAction = isCellEditing || isRowEditing || _this.isPasting || _this.isRangeInAction;\n if (!shouldCaptureAction) {\n return;\n }\n var rowPinned = event.rowPinned, rowIndex = event.rowIndex, column = event.column, oldValue = event.oldValue, value = event.value;\n var cellValueChange = {\n rowPinned: rowPinned,\n rowIndex: rowIndex,\n columnId: column.getColId(),\n newValue: value,\n oldValue: oldValue\n };\n _this.cellValueChanges.push(cellValueChange);\n };\n _this.clearStacks = function () {\n _this.undoStack.clear();\n _this.redoStack.clear();\n };\n return _this;\n }\n UndoRedoService.prototype.init = function () {\n var _this = this;\n if (!this.gridOptionsWrapper.isUndoRedoCellEditing()) {\n return;\n }\n var undoRedoLimit = this.gridOptionsWrapper.getUndoRedoCellEditingLimit();\n if (undoRedoLimit <= 0) {\n return;\n }\n this.undoStack = new UndoRedoStack(undoRedoLimit);\n this.redoStack = new UndoRedoStack(undoRedoLimit);\n this.addRowEditingListeners();\n this.addCellEditingListeners();\n this.addPasteListeners();\n this.addFillListeners();\n this.addCellKeyListeners();\n this.addManagedListener(this.eventService, Events.EVENT_CELL_VALUE_CHANGED, this.onCellValueChanged);\n // undo / redo is restricted to actual editing so we clear the stacks when other operations are\n // performed that change the order of the row / cols.\n this.addManagedListener(this.eventService, Events.EVENT_MODEL_UPDATED, function (e) {\n if (!e.keepUndoRedoStack) {\n _this.clearStacks();\n }\n });\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_GROUP_OPENED, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_MOVED, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PINNED, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_VISIBLE, this.clearStacks);\n this.addManagedListener(this.eventService, Events.EVENT_ROW_DRAG_END, this.clearStacks);\n this.ctrlsService.whenReady(function () {\n _this.gridBodyCtrl = _this.ctrlsService.getGridBodyCtrl();\n });\n };\n UndoRedoService.prototype.getCurrentUndoStackSize = function () {\n return this.undoStack ? this.undoStack.getCurrentStackSize() : 0;\n };\n UndoRedoService.prototype.getCurrentRedoStackSize = function () {\n return this.redoStack ? this.redoStack.getCurrentStackSize() : 0;\n };\n UndoRedoService.prototype.undo = function () {\n if (!this.undoStack) {\n return;\n }\n var undoAction = this.undoStack.pop();\n if (!undoAction || !undoAction.cellValueChanges) {\n return;\n }\n this.processAction(undoAction, function (cellValueChange) { return cellValueChange.oldValue; });\n if (undoAction instanceof RangeUndoRedoAction) {\n this.processRange(undoAction.ranges || [undoAction.initialRange]);\n }\n else {\n this.processCell(undoAction.cellValueChanges);\n }\n this.redoStack.push(undoAction);\n };\n UndoRedoService.prototype.redo = function () {\n if (!this.redoStack) {\n return;\n }\n var redoAction = this.redoStack.pop();\n if (!redoAction || !redoAction.cellValueChanges) {\n return;\n }\n this.processAction(redoAction, function (cellValueChange) { return cellValueChange.newValue; });\n if (redoAction instanceof RangeUndoRedoAction) {\n this.processRange(redoAction.ranges || [redoAction.finalRange]);\n }\n else {\n this.processCell(redoAction.cellValueChanges);\n }\n this.undoStack.push(redoAction);\n };\n UndoRedoService.prototype.processAction = function (action, valueExtractor) {\n var _this = this;\n action.cellValueChanges.forEach(function (cellValueChange) {\n var rowIndex = cellValueChange.rowIndex, rowPinned = cellValueChange.rowPinned, columnId = cellValueChange.columnId;\n var rowPosition = { rowIndex: rowIndex, rowPinned: rowPinned };\n var currentRow = _this.getRowNode(rowPosition);\n // checks if the row has been filtered out\n if (!currentRow.displayed) {\n return;\n }\n var extractedValue = valueExtractor(cellValueChange);\n // when values are 'complex objects' we need to invoke their `toString()` to obtain value\n var value = (typeof extractedValue.toString === 'function') ? extractedValue.toString() : extractedValue;\n currentRow.setDataValue(columnId, value);\n });\n };\n UndoRedoService.prototype.processRange = function (ranges) {\n var _this = this;\n var lastFocusedCell;\n this.rangeService.removeAllCellRanges(true);\n ranges.forEach(function (range, idx) {\n if (!range) {\n return;\n }\n var startRow = range.startRow;\n var endRow = range.endRow;\n if (idx === ranges.length - 1) {\n lastFocusedCell = {\n rowPinned: startRow.rowPinned,\n rowIndex: startRow.rowIndex,\n columnId: range.startColumn.getColId()\n };\n _this.setLastFocusedCell(lastFocusedCell);\n }\n var cellRangeParams = {\n rowStartIndex: startRow.rowIndex,\n rowStartPinned: startRow.rowPinned,\n rowEndIndex: endRow.rowIndex,\n rowEndPinned: endRow.rowPinned,\n columnStart: range.startColumn,\n columns: range.columns\n };\n _this.rangeService.addCellRange(cellRangeParams);\n });\n };\n UndoRedoService.prototype.processCell = function (cellValueChanges) {\n var cellValueChange = cellValueChanges[0];\n var rowIndex = cellValueChange.rowIndex, rowPinned = cellValueChange.rowPinned;\n var rowPosition = { rowIndex: rowIndex, rowPinned: rowPinned };\n var row = this.getRowNode(rowPosition);\n var lastFocusedCell = {\n rowPinned: cellValueChange.rowPinned,\n rowIndex: row.rowIndex,\n columnId: cellValueChange.columnId\n };\n this.setLastFocusedCell(lastFocusedCell, true);\n };\n UndoRedoService.prototype.setLastFocusedCell = function (lastFocusedCell, setRangeToCell) {\n var rowIndex = lastFocusedCell.rowIndex, columnId = lastFocusedCell.columnId, rowPinned = lastFocusedCell.rowPinned;\n var scrollFeature = this.gridBodyCtrl.getScrollFeature();\n var column = this.columnModel.getGridColumn(columnId);\n if (!column) {\n return;\n }\n scrollFeature.ensureIndexVisible(rowIndex);\n scrollFeature.ensureColumnVisible(column);\n var cellPosition = { rowIndex: rowIndex, column: column, rowPinned: rowPinned };\n this.focusService.setFocusedCell(__assign(__assign({}, cellPosition), { forceBrowserFocus: true }));\n if (setRangeToCell) {\n this.rangeService.setRangeToCell(cellPosition);\n }\n };\n UndoRedoService.prototype.addRowEditingListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_ROW_EDITING_STARTED, function (e) {\n _this.activeRowEdit = { rowIndex: e.rowIndex, rowPinned: e.rowPinned };\n });\n this.addManagedListener(this.eventService, Events.EVENT_ROW_EDITING_STOPPED, function () {\n var action = new UndoRedoAction(_this.cellValueChanges);\n _this.pushActionsToUndoStack(action);\n _this.activeRowEdit = null;\n });\n };\n UndoRedoService.prototype.addCellEditingListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_CELL_EDITING_STARTED, function (e) {\n _this.activeCellEdit = { column: e.column, rowIndex: e.rowIndex, rowPinned: e.rowPinned };\n });\n this.addManagedListener(this.eventService, Events.EVENT_CELL_EDITING_STOPPED, function (e) {\n _this.activeCellEdit = null;\n var shouldPushAction = e.valueChanged && !_this.activeRowEdit && !_this.isPasting && !_this.isRangeInAction;\n if (shouldPushAction) {\n var action = new UndoRedoAction(_this.cellValueChanges);\n _this.pushActionsToUndoStack(action);\n }\n });\n };\n UndoRedoService.prototype.addPasteListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_PASTE_START, function () {\n _this.isPasting = true;\n });\n this.addManagedListener(this.eventService, Events.EVENT_PASTE_END, function () {\n var action = new UndoRedoAction(_this.cellValueChanges);\n _this.pushActionsToUndoStack(action);\n _this.isPasting = false;\n });\n };\n UndoRedoService.prototype.addFillListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_FILL_START, function () {\n _this.isRangeInAction = true;\n });\n this.addManagedListener(this.eventService, Events.EVENT_FILL_END, function (event) {\n var action = new RangeUndoRedoAction(_this.cellValueChanges, event.initialRange, event.finalRange);\n _this.pushActionsToUndoStack(action);\n _this.isRangeInAction = false;\n });\n };\n UndoRedoService.prototype.addCellKeyListeners = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_START, function () {\n _this.isRangeInAction = true;\n });\n this.addManagedListener(this.eventService, Events.EVENT_KEY_SHORTCUT_CHANGED_CELL_END, function () {\n var action;\n if (_this.rangeService && _this.gridOptionsWrapper.isEnableRangeSelection()) {\n action = new RangeUndoRedoAction(_this.cellValueChanges, undefined, undefined, __spread$2(_this.rangeService.getCellRanges()));\n }\n else {\n action = new UndoRedoAction(_this.cellValueChanges);\n }\n _this.pushActionsToUndoStack(action);\n _this.isRangeInAction = false;\n });\n };\n UndoRedoService.prototype.pushActionsToUndoStack = function (action) {\n this.undoStack.push(action);\n this.cellValueChanges = [];\n this.redoStack.clear();\n };\n UndoRedoService.prototype.getRowNode = function (gridRow) {\n switch (gridRow.rowPinned) {\n case Constants.PINNED_TOP:\n return this.pinnedRowModel.getPinnedTopRowData()[gridRow.rowIndex];\n case Constants.PINNED_BOTTOM:\n return this.pinnedRowModel.getPinnedBottomRowData()[gridRow.rowIndex];\n default:\n return this.rowModel.getRow(gridRow.rowIndex);\n }\n };\n __decorate$m([\n Autowired('focusService')\n ], UndoRedoService.prototype, \"focusService\", void 0);\n __decorate$m([\n Autowired('ctrlsService')\n ], UndoRedoService.prototype, \"ctrlsService\", void 0);\n __decorate$m([\n Autowired('rowModel')\n ], UndoRedoService.prototype, \"rowModel\", void 0);\n __decorate$m([\n Autowired('pinnedRowModel')\n ], UndoRedoService.prototype, \"pinnedRowModel\", void 0);\n __decorate$m([\n Autowired('cellPositionUtils')\n ], UndoRedoService.prototype, \"cellPositionUtils\", void 0);\n __decorate$m([\n Autowired('rowPositionUtils')\n ], UndoRedoService.prototype, \"rowPositionUtils\", void 0);\n __decorate$m([\n Autowired('columnModel')\n ], UndoRedoService.prototype, \"columnModel\", void 0);\n __decorate$m([\n Optional('rangeService')\n ], UndoRedoService.prototype, \"rangeService\", void 0);\n __decorate$m([\n PostConstruct\n ], UndoRedoService.prototype, \"init\", null);\n UndoRedoService = __decorate$m([\n Bean('undoRedoService')\n ], UndoRedoService);\n return UndoRedoService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$j = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$l = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar HeaderPositionUtils = /** @class */ (function (_super) {\n __extends$j(HeaderPositionUtils, _super);\n function HeaderPositionUtils() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n HeaderPositionUtils.prototype.findHeader = function (focusedHeader, direction) {\n var nextColumn;\n var getGroupMethod;\n var getColMethod;\n if (focusedHeader.column instanceof ColumnGroup) {\n getGroupMethod = \"getDisplayedGroup\" + direction;\n nextColumn = this.columnModel[getGroupMethod](focusedHeader.column);\n }\n else {\n getColMethod = \"getDisplayedCol\" + direction;\n nextColumn = this.columnModel[getColMethod](focusedHeader.column);\n }\n if (nextColumn) {\n return {\n column: nextColumn,\n headerRowIndex: focusedHeader.headerRowIndex\n };\n }\n };\n HeaderPositionUtils.prototype.findColAtEdgeForHeaderRow = function (level, position) {\n var displayedColumns = this.columnModel.getAllDisplayedColumns();\n var column = displayedColumns[position === 'start' ? 0 : displayedColumns.length - 1];\n if (!column) {\n return;\n }\n var childContainer = this.ctrlsService.getHeaderRowContainerCtrl(column.getPinned());\n var type = childContainer.getRowType(level);\n if (type == HeaderRowType.COLUMN_GROUP) {\n var columnGroup = this.columnModel.getColumnGroupAtLevel(column, level);\n return {\n headerRowIndex: level,\n column: columnGroup\n };\n }\n return {\n // if type==null, means the header level didn't exist\n headerRowIndex: type == null ? -1 : level,\n column: column\n };\n };\n __decorate$l([\n Autowired('columnModel')\n ], HeaderPositionUtils.prototype, \"columnModel\", void 0);\n __decorate$l([\n Autowired('ctrlsService')\n ], HeaderPositionUtils.prototype, \"ctrlsService\", void 0);\n HeaderPositionUtils = __decorate$l([\n Bean('headerPositionUtils')\n ], HeaderPositionUtils);\n return HeaderPositionUtils;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$k = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar ColumnDefFactory = /** @class */ (function () {\n function ColumnDefFactory() {\n }\n ColumnDefFactory.prototype.buildColumnDefs = function (cols, rowGroupColumns, pivotColumns) {\n var _this = this;\n var res = [];\n var colGroupDefs = {};\n cols.forEach(function (col) {\n var colDef = _this.createDefFromColumn(col, rowGroupColumns, pivotColumns);\n var addToResult = true;\n var childDef = colDef;\n var pointer = col.getOriginalParent();\n while (pointer) {\n var parentDef = null;\n // we don't include padding groups, as the column groups provided\n // by application didn't have these. the whole point of padding groups\n // is to balance the column tree that the user provided.\n if (pointer.isPadding()) {\n pointer = pointer.getOriginalParent();\n continue;\n }\n // if colDef for this group already exists, use it\n var existingParentDef = colGroupDefs[pointer.getGroupId()];\n if (existingParentDef) {\n existingParentDef.children.push(childDef);\n // if we added to result, it would be the second time we did it\n addToResult = false;\n // we don't want to continue up the tree, as it has already been\n // done for this group\n break;\n }\n parentDef = _this.createDefFromGroup(pointer);\n if (parentDef) {\n parentDef.children = [childDef];\n colGroupDefs[parentDef.groupId] = parentDef;\n childDef = parentDef;\n pointer = pointer.getOriginalParent();\n }\n }\n if (addToResult) {\n res.push(childDef);\n }\n });\n return res;\n };\n ColumnDefFactory.prototype.createDefFromGroup = function (group) {\n var defCloned = deepCloneDefinition(group.getColGroupDef(), ['children']);\n if (defCloned) {\n defCloned.groupId = group.getGroupId();\n }\n return defCloned;\n };\n ColumnDefFactory.prototype.createDefFromColumn = function (col, rowGroupColumns, pivotColumns) {\n var colDefCloned = deepCloneDefinition(col.getColDef());\n colDefCloned.colId = col.getColId();\n colDefCloned.width = col.getActualWidth();\n colDefCloned.rowGroup = col.isRowGroupActive();\n colDefCloned.rowGroupIndex = col.isRowGroupActive() ? rowGroupColumns.indexOf(col) : null;\n colDefCloned.pivot = col.isPivotActive();\n colDefCloned.pivotIndex = col.isPivotActive() ? pivotColumns.indexOf(col) : null;\n colDefCloned.aggFunc = col.isValueActive() ? col.getAggFunc() : null;\n colDefCloned.hide = col.isVisible() ? undefined : true;\n colDefCloned.pinned = col.isPinned() ? col.getPinned() : null;\n colDefCloned.sort = col.getSort() ? col.getSort() : null;\n colDefCloned.sortIndex = col.getSortIndex() != null ? col.getSortIndex() : null;\n return colDefCloned;\n };\n ColumnDefFactory = __decorate$k([\n Bean('columnDefFactory')\n ], ColumnDefFactory);\n return ColumnDefFactory;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$j = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RowCssClassCalculator = /** @class */ (function () {\n function RowCssClassCalculator() {\n }\n RowCssClassCalculator.prototype.getInitialRowClasses = function (params) {\n var classes = [];\n if (exists(params.extraCssClass)) {\n classes.push(params.extraCssClass);\n }\n classes.push('ag-row');\n classes.push(params.rowFocused ? 'ag-row-focus' : 'ag-row-no-focus');\n if (params.fadeRowIn) {\n classes.push('ag-opacity-zero');\n }\n classes.push(params.rowIsEven ? 'ag-row-even' : 'ag-row-odd');\n if (params.rowNode.isRowPinned()) {\n classes.push('ag-row-pinned');\n }\n if (params.rowNode.isSelected()) {\n classes.push('ag-row-selected');\n }\n if (params.rowNode.footer) {\n classes.push('ag-row-footer');\n }\n classes.push('ag-row-level-' + params.rowLevel);\n if (params.rowNode.stub) {\n classes.push('ag-row-loading');\n }\n if (params.fullWidthRow) {\n classes.push('ag-full-width-row');\n }\n if (params.expandable) {\n classes.push('ag-row-group');\n classes.push(params.rowNode.expanded ? 'ag-row-group-expanded' : 'ag-row-group-contracted');\n }\n if (params.rowNode.dragging) {\n classes.push('ag-row-dragging');\n }\n pushAll(classes, this.processClassesFromGridOptions(params.rowNode));\n pushAll(classes, this.preProcessRowClassRules(params.rowNode));\n // we use absolute position unless we are doing print layout\n classes.push(params.printLayout ? 'ag-row-position-relative' : 'ag-row-position-absolute');\n if (params.firstRowOnPage) {\n classes.push('ag-row-first');\n }\n if (params.lastRowOnPage) {\n classes.push('ag-row-last');\n }\n if (params.fullWidthRow) {\n if (params.pinned === Constants.PINNED_LEFT) {\n classes.push('ag-cell-last-left-pinned');\n }\n if (params.pinned === Constants.PINNED_RIGHT) {\n classes.push('ag-cell-first-right-pinned');\n }\n }\n return classes;\n };\n RowCssClassCalculator.prototype.processClassesFromGridOptions = function (rowNode) {\n var res = [];\n var process = function (rowCls) {\n if (typeof rowCls === 'string') {\n res.push(rowCls);\n }\n else if (Array.isArray(rowCls)) {\n rowCls.forEach(function (e) { return res.push(e); });\n }\n };\n // part 1 - rowClass\n var rowClass = this.gridOptionsWrapper.getRowClass();\n if (rowClass) {\n if (typeof rowClass === 'function') {\n console.warn('AG Grid: rowClass should not be a function, please use getRowClass instead');\n return [];\n }\n process(rowClass);\n }\n // part 2 - rowClassFunc\n var rowClassFunc = this.gridOptionsWrapper.getRowClassFunc();\n if (rowClassFunc) {\n var params = {\n data: rowNode.data,\n node: rowNode,\n rowIndex: rowNode.rowIndex\n };\n var rowClassFuncResult = rowClassFunc(params);\n process(rowClassFuncResult);\n }\n return res;\n };\n RowCssClassCalculator.prototype.preProcessRowClassRules = function (rowNode) {\n var res = [];\n this.processRowClassRules(rowNode, function (className) {\n res.push(className);\n }, function (className) {\n // not catered for, if creating, no need\n // to remove class as it was never there\n });\n return res;\n };\n RowCssClassCalculator.prototype.processRowClassRules = function (rowNode, onApplicableClass, onNotApplicableClass) {\n var rowClassParams = {\n data: rowNode.data,\n node: rowNode,\n rowIndex: rowNode.rowIndex,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n };\n this.stylingService.processClassRules(this.gridOptionsWrapper.rowClassRules(), rowClassParams, onApplicableClass, onNotApplicableClass);\n };\n RowCssClassCalculator.prototype.calculateRowLevel = function (rowNode) {\n if (rowNode.group) {\n return rowNode.level;\n }\n // if a leaf, and a parent exists, put a level of the parent, else put level of 0 for top level item\n return rowNode.parent ? (rowNode.parent.level + 1) : 0;\n };\n __decorate$j([\n Autowired('stylingService')\n ], RowCssClassCalculator.prototype, \"stylingService\", void 0);\n __decorate$j([\n Autowired('gridOptionsWrapper')\n ], RowCssClassCalculator.prototype, \"gridOptionsWrapper\", void 0);\n RowCssClassCalculator = __decorate$j([\n Bean('rowCssClassCalculator')\n ], RowCssClassCalculator);\n return RowCssClassCalculator;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __decorate$i = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n// this logic is used by both SSRM and CSRM\nvar RowNodeSorter = /** @class */ (function () {\n function RowNodeSorter() {\n }\n RowNodeSorter.prototype.doFullSort = function (rowNodes, sortOptions) {\n var mapper = function (rowNode, pos) { return ({ currentPos: pos, rowNode: rowNode }); };\n var sortedRowNodes = rowNodes.map(mapper);\n sortedRowNodes.sort(this.compareRowNodes.bind(this, sortOptions));\n return sortedRowNodes.map(function (item) { return item.rowNode; });\n };\n RowNodeSorter.prototype.compareRowNodes = function (sortOptions, sortedNodeA, sortedNodeB) {\n var nodeA = sortedNodeA.rowNode;\n var nodeB = sortedNodeB.rowNode;\n // Iterate columns, return the first that doesn't match\n for (var i = 0, len = sortOptions.length; i < len; i++) {\n var sortOption = sortOptions[i];\n var isDescending = sortOption.sort === Constants.SORT_DESC;\n var valueA = this.getValue(nodeA, sortOption.column);\n var valueB = this.getValue(nodeB, sortOption.column);\n var comparatorResult = void 0;\n var providedComparator = this.getComparator(sortOption, nodeA);\n if (providedComparator) {\n //if comparator provided, use it\n comparatorResult = providedComparator(valueA, valueB, nodeA, nodeB, isDescending);\n }\n else {\n //otherwise do our own comparison\n comparatorResult = _.defaultComparator(valueA, valueB, this.gridOptionsWrapper.isAccentedSort());\n }\n // user provided comparators can return 'NaN' if they don't correctly handle 'undefined' values, this\n // typically occurs when the comparator is used on a group row\n var validResult = !isNaN(comparatorResult);\n if (validResult && comparatorResult !== 0) {\n return sortOption.sort === Constants.SORT_ASC ? comparatorResult : comparatorResult * -1;\n }\n }\n // All matched, we make is so that the original sort order is kept:\n return sortedNodeA.currentPos - sortedNodeB.currentPos;\n };\n RowNodeSorter.prototype.getComparator = function (sortOption, rowNode) {\n var column = sortOption.column;\n // comparator on col get preference over everything else\n var comparatorOnCol = column.getColDef().comparator;\n if (comparatorOnCol != null) {\n return comparatorOnCol;\n }\n if (!column.getColDef().showRowGroup) {\n return;\n }\n // if a 'field' is supplied on the autoGroupColumnDef we need to use the associated column comparator\n var groupLeafField = !rowNode.group && column.getColDef().field;\n if (!groupLeafField) {\n return;\n }\n var primaryColumn = this.columnModel.getPrimaryColumn(groupLeafField);\n if (!primaryColumn) {\n return;\n }\n return primaryColumn.getColDef().comparator;\n };\n RowNodeSorter.prototype.getValue = function (node, column) {\n var _a, _b;\n var primaryColumnsSortGroups = this.gridOptionsWrapper.isColumnsSortingCoupledToGroup();\n if (!primaryColumnsSortGroups) {\n return this.valueService.getValue(column, node, false, false);\n }\n var isNodeGroupedAtLevel = node.rowGroupColumn === column;\n if (isNodeGroupedAtLevel) {\n var isGroupRows = this.gridOptionsWrapper.isGroupUseEntireRow(this.columnModel.isPivotActive());\n if (isGroupRows) {\n // if the column has a provided a keyCreator, we have to use the key, as the group could be\n // irrelevant to the column value\n var keyCreator = column.getColDef().keyCreator;\n if (keyCreator) {\n return node.key;\n }\n // if the group was generated from the column data, all the leaf children should return the same\n // value\n var leafChild = (_a = node.allLeafChildren) === null || _a === void 0 ? void 0 : _a[0];\n if (leafChild) {\n return this.valueService.getValue(column, leafChild, false, false);\n }\n return undefined;\n }\n var displayCol = this.columnModel.getGroupDisplayColumnForGroup(column.getId());\n if (!displayCol) {\n return undefined;\n }\n return (_b = node.groupData) === null || _b === void 0 ? void 0 : _b[displayCol.getId()];\n }\n if (node.group && column.getColDef().showRowGroup) {\n return undefined;\n }\n return this.valueService.getValue(column, node, false, false);\n };\n __decorate$i([\n Autowired('gridOptionsWrapper')\n ], RowNodeSorter.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$i([\n Autowired('valueService')\n ], RowNodeSorter.prototype, \"valueService\", void 0);\n __decorate$i([\n Autowired('columnModel')\n ], RowNodeSorter.prototype, \"columnModel\", void 0);\n RowNodeSorter = __decorate$i([\n Bean('rowNodeSorter')\n ], RowNodeSorter);\n return RowNodeSorter;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$i = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$h = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar CtrlsService = /** @class */ (function (_super) {\n __extends$i(CtrlsService, _super);\n function CtrlsService() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.ready = false;\n _this.readyCallbacks = [];\n return _this;\n }\n CtrlsService_1 = CtrlsService;\n CtrlsService.prototype.checkReady = function () {\n this.ready =\n this.gridCtrl != null\n && this.gridBodyCtrl != null\n && this.centerRowContainerCtrl != null\n && this.leftRowContainerCtrl != null\n && this.rightRowContainerCtrl != null\n && this.bottomCenterRowContainerCtrl != null\n && this.bottomLeftRowContainerCtrl != null\n && this.bottomRightRowContainerCtrl != null\n && this.topCenterRowContainerCtrl != null\n && this.topLeftRowContainerCtrl != null\n && this.topRightRowContainerCtrl != null\n && this.stickyTopCenterRowContainerCtrl != null\n && this.stickyTopLeftRowContainerCtrl != null\n && this.stickyTopRightRowContainerCtrl != null\n && this.centerHeaderRowContainerCtrl != null\n && this.leftHeaderRowContainerCtrl != null\n && this.rightHeaderRowContainerCtrl != null\n && this.fakeHScrollCtrl != null\n && this.gridHeaderCtrl != null;\n if (this.ready) {\n var p_1 = this.createReadyParams();\n this.readyCallbacks.forEach(function (c) { return c(p_1); });\n this.readyCallbacks.length = 0;\n }\n };\n CtrlsService.prototype.whenReady = function (callback) {\n if (this.ready) {\n callback(this.createReadyParams());\n }\n else {\n this.readyCallbacks.push(callback);\n }\n };\n CtrlsService.prototype.createReadyParams = function () {\n return {\n centerRowContainerCtrl: this.centerRowContainerCtrl,\n leftRowContainerCtrl: this.leftRowContainerCtrl,\n rightRowContainerCtrl: this.rightRowContainerCtrl,\n bottomCenterRowContainerCtrl: this.bottomCenterRowContainerCtrl,\n bottomLeftRowContainerCtrl: this.bottomLeftRowContainerCtrl,\n bottomRightRowContainerCtrl: this.bottomRightRowContainerCtrl,\n topCenterRowContainerCtrl: this.topCenterRowContainerCtrl,\n topLeftRowContainerCtrl: this.topLeftRowContainerCtrl,\n topRightRowContainerCtrl: this.topRightRowContainerCtrl,\n stickyTopCenterRowContainerCtrl: this.stickyTopCenterRowContainerCtrl,\n stickyTopLeftRowContainerCtrl: this.stickyTopLeftRowContainerCtrl,\n stickyTopRightRowContainerCtrl: this.stickyTopRightRowContainerCtrl,\n centerHeaderRowContainerCtrl: this.centerHeaderRowContainerCtrl,\n leftHeaderRowContainerCtrl: this.leftHeaderRowContainerCtrl,\n rightHeaderRowContainerCtrl: this.rightHeaderRowContainerCtrl,\n fakeHScrollCtrl: this.fakeHScrollCtrl,\n gridBodyCtrl: this.gridBodyCtrl,\n gridCtrl: this.gridCtrl,\n gridHeaderCtrl: this.gridHeaderCtrl,\n };\n };\n CtrlsService.prototype.registerFakeHScrollCtrl = function (ctrl) {\n this.fakeHScrollCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerGridHeaderCtrl = function (gridHeaderCtrl) {\n this.gridHeaderCtrl = gridHeaderCtrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerCenterRowContainerCtrl = function (ctrl) {\n this.centerRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerLeftRowContainerCtrl = function (ctrl) {\n this.leftRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerRightRowContainerCtrl = function (ctrl) {\n this.rightRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerTopCenterRowContainerCtrl = function (ctrl) {\n this.topCenterRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerTopLeftRowContainerCon = function (ctrl) {\n this.topLeftRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerTopRightRowContainerCtrl = function (ctrl) {\n this.topRightRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerStickyTopCenterRowContainerCtrl = function (ctrl) {\n this.stickyTopCenterRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerStickyTopLeftRowContainerCon = function (ctrl) {\n this.stickyTopLeftRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerStickyTopRightRowContainerCtrl = function (ctrl) {\n this.stickyTopRightRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerBottomCenterRowContainerCtrl = function (ctrl) {\n this.bottomCenterRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerBottomLeftRowContainerCtrl = function (ctrl) {\n this.bottomLeftRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerBottomRightRowContainerCtrl = function (ctrl) {\n this.bottomRightRowContainerCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerHeaderContainer = function (ctrl, pinned) {\n switch (pinned) {\n case Constants.PINNED_LEFT:\n this.leftHeaderRowContainerCtrl = ctrl;\n break;\n case Constants.PINNED_RIGHT:\n this.rightHeaderRowContainerCtrl = ctrl;\n break;\n default:\n this.centerHeaderRowContainerCtrl = ctrl;\n break;\n }\n this.checkReady();\n };\n CtrlsService.prototype.registerGridBodyCtrl = function (ctrl) {\n this.gridBodyCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.registerGridCtrl = function (ctrl) {\n this.gridCtrl = ctrl;\n this.checkReady();\n };\n CtrlsService.prototype.getFakeHScrollCtrl = function () {\n return this.fakeHScrollCtrl;\n };\n CtrlsService.prototype.getGridHeaderCtrl = function () {\n return this.gridHeaderCtrl;\n };\n CtrlsService.prototype.getGridCtrl = function () {\n return this.gridCtrl;\n };\n CtrlsService.prototype.getCenterRowContainerCtrl = function () {\n return this.centerRowContainerCtrl;\n };\n CtrlsService.prototype.getTopCenterRowContainerCtrl = function () {\n return this.topCenterRowContainerCtrl;\n };\n CtrlsService.prototype.getBottomCenterRowContainerCtrl = function () {\n return this.bottomCenterRowContainerCtrl;\n };\n CtrlsService.prototype.getStickyTopCenterRowContainerCtrl = function () {\n return this.stickyTopCenterRowContainerCtrl;\n };\n CtrlsService.prototype.getGridBodyCtrl = function () {\n return this.gridBodyCtrl;\n };\n CtrlsService.prototype.getHeaderRowContainerCtrls = function () {\n return [this.leftHeaderRowContainerCtrl, this.rightHeaderRowContainerCtrl, this.centerHeaderRowContainerCtrl];\n };\n CtrlsService.prototype.getHeaderRowContainerCtrl = function (pinned) {\n switch (pinned) {\n case Constants.PINNED_LEFT: return this.leftHeaderRowContainerCtrl;\n case Constants.PINNED_RIGHT: return this.rightHeaderRowContainerCtrl;\n default: return this.centerHeaderRowContainerCtrl;\n }\n };\n var CtrlsService_1;\n CtrlsService.NAME = 'ctrlsService';\n CtrlsService = CtrlsService_1 = __decorate$h([\n Bean(CtrlsService_1.NAME)\n ], CtrlsService);\n return CtrlsService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$h = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$g = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar CtrlsFactory = /** @class */ (function (_super) {\n __extends$h(CtrlsFactory, _super);\n function CtrlsFactory() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.registry = {};\n return _this;\n }\n CtrlsFactory.prototype.register = function (meta) {\n this.registry[meta.controllerName] = meta.controllerClass;\n };\n CtrlsFactory.prototype.getInstance = function (name) {\n var ControllerClass = this.registry[name];\n if (ControllerClass == null) {\n return undefined;\n }\n return new ControllerClass();\n };\n CtrlsFactory = __decorate$g([\n Bean('ctrlsFactory')\n ], CtrlsFactory);\n return CtrlsFactory;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$g = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$f = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar FakeHScrollCtrl = /** @class */ (function (_super) {\n __extends$g(FakeHScrollCtrl, _super);\n function FakeHScrollCtrl() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n FakeHScrollCtrl.prototype.setComp = function (view, eGui, eViewport, eContainer) {\n this.view = view;\n this.eViewport = eViewport;\n this.eContainer = eContainer;\n this.eGui = eGui;\n this.addManagedListener(this.eventService, Events.EVENT_SCROLL_VISIBILITY_CHANGED, this.onScrollVisibilityChanged.bind(this));\n // When doing printing, this changes whether cols are pinned or not\n var spacerWidthsListener = this.setFakeHScrollSpacerWidths.bind(this);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, spacerWidthsListener);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, spacerWidthsListener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, spacerWidthsListener);\n this.addManagedListener(this.eventService, Events.EVENT_PINNED_ROW_DATA_CHANGED, this.onPinnedRowDataChanged.bind(this));\n this.onScrollVisibilityChanged();\n this.ctrlsService.registerFakeHScrollCtrl(this);\n this.view.addOrRemoveCssClass('ag-apple-scrollbar', isMacOsUserAgent() || isIOSUserAgent());\n };\n FakeHScrollCtrl.prototype.addActiveListenerToggles = function () {\n var _this = this;\n var activateEvents = ['mouseenter', 'mousedown', 'touchstart'];\n var deactivateEvents = ['mouseleave', 'touchend'];\n activateEvents.forEach(function (eventName) { return _this.addManagedListener(_this.eGui, eventName, function () { return _this.view.addOrRemoveCssClass('ag-scrollbar-active', true); }); });\n deactivateEvents.forEach(function (eventName) { return _this.addManagedListener(_this.eGui, eventName, function () { return _this.view.addOrRemoveCssClass('ag-scrollbar-active', false); }); });\n };\n FakeHScrollCtrl.prototype.initialiseInvisibleScrollbar = function () {\n if (this.invisibleScrollbar !== undefined) {\n return;\n }\n this.enableRtl = this.gridOptionsWrapper.isEnableRtl();\n this.invisibleScrollbar = isInvisibleScrollbar();\n if (this.invisibleScrollbar) {\n this.hideAndShowInvisibleScrollAsNeeded();\n this.addActiveListenerToggles();\n this.refreshCompBottom();\n }\n };\n FakeHScrollCtrl.prototype.onPinnedRowDataChanged = function () {\n this.refreshCompBottom();\n };\n FakeHScrollCtrl.prototype.refreshCompBottom = function () {\n if (!this.invisibleScrollbar) {\n return;\n }\n var bottomPinnedHeight = this.pinnedRowModel.getPinnedBottomTotalHeight();\n this.view.setBottom(bottomPinnedHeight);\n };\n FakeHScrollCtrl.prototype.onScrollVisibilityChanged = function () {\n // initialiseInvisibleScrollbar should only be called once, but the reason\n // this can't be inside `setComp` or `PostConstruct` is the DOM might not\n // be ready, so we call it until eventually, it gets calculated.\n if (this.invisibleScrollbar === undefined) {\n this.initialiseInvisibleScrollbar();\n }\n this.setScrollVisible();\n this.setFakeHScrollSpacerWidths();\n };\n FakeHScrollCtrl.prototype.hideAndShowInvisibleScrollAsNeeded = function () {\n var _this = this;\n this.addManagedListener(this.eventService, Events.EVENT_BODY_SCROLL, function (params) {\n if (params.direction === 'horizontal') {\n _this.view.addOrRemoveCssClass('ag-scrollbar-scrolling', true);\n }\n });\n this.addManagedListener(this.eventService, Events.EVENT_BODY_SCROLL_END, function () { return _this.view.addOrRemoveCssClass('ag-scrollbar-scrolling', false); });\n };\n FakeHScrollCtrl.prototype.setFakeHScrollSpacerWidths = function () {\n var vScrollShowing = this.scrollVisibleService.isVerticalScrollShowing();\n // we pad the right based on a) if cols are pinned to the right and\n // b) if v scroll is showing on the right (normal position of scroll)\n var rightSpacing = this.columnModel.getDisplayedColumnsRightWidth();\n var scrollOnRight = !this.enableRtl && vScrollShowing;\n var scrollbarWidth = this.gridOptionsWrapper.getScrollbarWidth();\n if (scrollOnRight) {\n rightSpacing += scrollbarWidth;\n }\n this.view.setRightSpacerFixedWidth(rightSpacing);\n this.view.includeRightSpacerScrollerCss('ag-scroller-corner', rightSpacing <= scrollbarWidth);\n // we pad the left based on a) if cols are pinned to the left and\n // b) if v scroll is showing on the left (happens in LTR layout only)\n var leftSpacing = this.columnModel.getDisplayedColumnsLeftWidth();\n var scrollOnLeft = this.enableRtl && vScrollShowing;\n if (scrollOnLeft) {\n leftSpacing += scrollbarWidth;\n }\n this.view.setLeftSpacerFixedWidth(leftSpacing);\n this.view.includeLeftSpacerScrollerCss('ag-scroller-corner', leftSpacing <= scrollbarWidth);\n };\n FakeHScrollCtrl.prototype.setScrollVisible = function () {\n var hScrollShowing = this.scrollVisibleService.isHorizontalScrollShowing();\n var invisibleScrollbar = this.invisibleScrollbar;\n var isSuppressHorizontalScroll = this.gridOptionsWrapper.isSuppressHorizontalScroll();\n var scrollbarWidth = hScrollShowing ? (this.gridOptionsWrapper.getScrollbarWidth() || 0) : 0;\n var adjustedScrollbarWidth = (scrollbarWidth === 0 && invisibleScrollbar) ? 15 : scrollbarWidth;\n var scrollContainerSize = !isSuppressHorizontalScroll ? adjustedScrollbarWidth : 0;\n this.view.addOrRemoveCssClass('ag-scrollbar-invisible', invisibleScrollbar);\n this.view.setHeight(scrollContainerSize);\n this.view.setViewportHeight(scrollContainerSize);\n this.view.setContainerHeight(scrollContainerSize);\n this.view.addOrRemoveCssClass('ag-hidden', !hScrollShowing);\n };\n FakeHScrollCtrl.prototype.getViewport = function () {\n return this.eViewport;\n };\n FakeHScrollCtrl.prototype.getContainer = function () {\n return this.eContainer;\n };\n __decorate$f([\n Autowired('scrollVisibleService')\n ], FakeHScrollCtrl.prototype, \"scrollVisibleService\", void 0);\n __decorate$f([\n Autowired('columnModel')\n ], FakeHScrollCtrl.prototype, \"columnModel\", void 0);\n __decorate$f([\n Autowired('ctrlsService')\n ], FakeHScrollCtrl.prototype, \"ctrlsService\", void 0);\n __decorate$f([\n Autowired('pinnedRowModel')\n ], FakeHScrollCtrl.prototype, \"pinnedRowModel\", void 0);\n return FakeHScrollCtrl;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$f = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$e = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar FakeHScrollComp = /** @class */ (function (_super) {\n __extends$f(FakeHScrollComp, _super);\n function FakeHScrollComp() {\n return _super.call(this, FakeHScrollComp.TEMPLATE) || this;\n }\n FakeHScrollComp.prototype.postConstruct = function () {\n var _this = this;\n var compProxy = {\n addOrRemoveCssClass: function (cssClassName, on) { return _this.addOrRemoveCssClass(cssClassName, on); },\n setHeight: function (height) { return setFixedHeight(_this.getGui(), height); },\n setBottom: function (bottom) { return _this.getGui().style.bottom = bottom + \"px\"; },\n setContainerHeight: function (height) { return setFixedHeight(_this.eContainer, height); },\n setViewportHeight: function (height) { return setFixedHeight(_this.eViewport, height); },\n setRightSpacerFixedWidth: function (width) { return setFixedWidth(_this.eRightSpacer, width); },\n setLeftSpacerFixedWidth: function (width) { return setFixedWidth(_this.eLeftSpacer, width); },\n includeLeftSpacerScrollerCss: function (cssClass, include) {\n return _this.eLeftSpacer.classList.toggle(cssClass, include);\n },\n includeRightSpacerScrollerCss: function (cssClass, include) {\n return _this.eRightSpacer.classList.toggle(cssClass, include);\n },\n };\n var ctrl = this.createManagedBean(new FakeHScrollCtrl());\n ctrl.setComp(compProxy, this.getGui(), this.eViewport, this.eContainer);\n this.createManagedBean(new CenterWidthFeature(function (width) { return _this.eContainer.style.width = width + \"px\"; }));\n };\n FakeHScrollComp.TEMPLATE = \"<div class=\\\"ag-body-horizontal-scroll\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"ag-horizontal-left-spacer\\\" ref=\\\"eLeftSpacer\\\"></div>\\n <div class=\\\"ag-body-horizontal-scroll-viewport\\\" ref=\\\"eViewport\\\">\\n <div class=\\\"ag-body-horizontal-scroll-container\\\" ref=\\\"eContainer\\\"></div>\\n </div>\\n <div class=\\\"ag-horizontal-right-spacer\\\" ref=\\\"eRightSpacer\\\"></div>\\n </div>\";\n __decorate$e([\n RefSelector('eLeftSpacer')\n ], FakeHScrollComp.prototype, \"eLeftSpacer\", void 0);\n __decorate$e([\n RefSelector('eRightSpacer')\n ], FakeHScrollComp.prototype, \"eRightSpacer\", void 0);\n __decorate$e([\n RefSelector('eViewport')\n ], FakeHScrollComp.prototype, \"eViewport\", void 0);\n __decorate$e([\n RefSelector('eContainer')\n ], FakeHScrollComp.prototype, \"eContainer\", void 0);\n __decorate$e([\n PostConstruct\n ], FakeHScrollComp.prototype, \"postConstruct\", null);\n return FakeHScrollComp;\n}(Component));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$e = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$d = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar PinnedWidthService = /** @class */ (function (_super) {\n __extends$e(PinnedWidthService, _super);\n function PinnedWidthService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n PinnedWidthService.prototype.postConstruct = function () {\n var listener = this.checkContainerWidths.bind(this);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_CHANGED, listener);\n this.addManagedListener(this.eventService, Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, listener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_DOM_LAYOUT, listener);\n };\n PinnedWidthService.prototype.checkContainerWidths = function () {\n var printLayout = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_PRINT;\n var newLeftWidth = printLayout ? 0 : this.columnModel.getDisplayedColumnsLeftWidth();\n var newRightWidth = printLayout ? 0 : this.columnModel.getDisplayedColumnsRightWidth();\n if (newLeftWidth != this.leftWidth) {\n this.leftWidth = newLeftWidth;\n this.eventService.dispatchEvent({ type: Events.EVENT_LEFT_PINNED_WIDTH_CHANGED });\n }\n if (newRightWidth != this.rightWidth) {\n this.rightWidth = newRightWidth;\n this.eventService.dispatchEvent({ type: Events.EVENT_RIGHT_PINNED_WIDTH_CHANGED });\n }\n };\n PinnedWidthService.prototype.getPinnedRightWidth = function () {\n return this.rightWidth;\n };\n PinnedWidthService.prototype.getPinnedLeftWidth = function () {\n return this.leftWidth;\n };\n __decorate$d([\n Autowired('columnModel')\n ], PinnedWidthService.prototype, \"columnModel\", void 0);\n __decorate$d([\n PostConstruct\n ], PinnedWidthService.prototype, \"postConstruct\", null);\n PinnedWidthService = __decorate$d([\n Bean('pinnedWidthService')\n ], PinnedWidthService);\n return PinnedWidthService;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __extends$d = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$c = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RowNodeEventThrottle = /** @class */ (function (_super) {\n __extends$d(RowNodeEventThrottle, _super);\n function RowNodeEventThrottle() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.events = [];\n return _this;\n }\n RowNodeEventThrottle.prototype.postConstruct = function () {\n if (this.rowModel.getType() == Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n this.clientSideRowModel = this.rowModel;\n }\n };\n // because the user can call rowNode.setExpanded() many times in one VM turn,\n // we throttle the calls to ClientSideRowModel using animationFrameService. this means for 100\n // row nodes getting expanded, we only update the CSRM once, and then we fire all events after\n // CSRM has updated.\n //\n // if we did not do this, then the user could call setExpanded on 100+ rows, causing the grid\n // to re-render 100+ times, which would be a performance lag.\n //\n // we use animationFrameService\n // rather than _.debounce() so this will get done if anyone flushes the animationFrameService\n // (eg user calls api.ensureRowVisible(), which in turn flushes ).\n RowNodeEventThrottle.prototype.dispatchExpanded = function (event) {\n var _this = this;\n // if not using CSRM, we don't debounce. otherwise this breaks the SSRM.\n if (this.clientSideRowModel == null) {\n this.eventService.dispatchEvent(event);\n return;\n }\n this.events.push(event);\n var func = function () {\n if (_this.clientSideRowModel) {\n _this.clientSideRowModel.onRowGroupOpened();\n }\n _this.events.forEach(function (e) { return _this.eventService.dispatchEvent(e); });\n _this.events = [];\n };\n if (this.dispatchExpandedDebounced == null) {\n this.dispatchExpandedDebounced = this.animationFrameService.debounce(func);\n }\n this.dispatchExpandedDebounced();\n };\n __decorate$c([\n Autowired('animationFrameService')\n ], RowNodeEventThrottle.prototype, \"animationFrameService\", void 0);\n __decorate$c([\n Autowired('rowModel')\n ], RowNodeEventThrottle.prototype, \"rowModel\", void 0);\n __decorate$c([\n PostConstruct\n ], RowNodeEventThrottle.prototype, \"postConstruct\", null);\n RowNodeEventThrottle = __decorate$c([\n Bean('rowNodeEventThrottle')\n ], RowNodeEventThrottle);\n return RowNodeEventThrottle;\n}(BeanStub));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar __read$2 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread$1 = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$2(arguments[i]));\n return ar;\n};\n// creates JavaScript vanilla Grid, including JavaScript (ag-stack) components, which can\n// be wrapped by the framework wrappers\nvar Grid = /** @class */ (function () {\n function Grid(eGridDiv, gridOptions, params) {\n if (!gridOptions) {\n console.error('AG Grid: no gridOptions provided to the grid');\n return;\n }\n this.gridOptions = gridOptions;\n new GridCoreCreator().create(eGridDiv, gridOptions, function (context) {\n var gridComp = new GridComp(eGridDiv);\n context.createBean(gridComp);\n }, undefined, params);\n }\n Grid.prototype.destroy = function () {\n if (this.gridOptions && this.gridOptions.api) {\n this.gridOptions.api.destroy();\n }\n };\n return Grid;\n}());\n// created services of grid only, no UI, so frameworks can use this if providing\n// their own UI\nvar GridCoreCreator = /** @class */ (function () {\n function GridCoreCreator() {\n }\n GridCoreCreator.prototype.create = function (eGridDiv, gridOptions, createUi, acceptChanges, params) {\n var _this = this;\n var debug = !!gridOptions.debug;\n var registeredModules = this.getRegisteredModules(params);\n var beanClasses = this.createBeansList(gridOptions.rowModelType, registeredModules);\n var providedBeanInstances = this.createProvidedBeans(eGridDiv, gridOptions, params);\n if (!beanClasses) {\n return;\n } // happens when no row model found\n var contextParams = {\n providedBeanInstances: providedBeanInstances,\n beanClasses: beanClasses,\n debug: debug\n };\n var logger = new Logger('AG Grid', function () { return gridOptions.debug; });\n var contextLogger = new Logger('Context', function () { return contextParams.debug; });\n var context = new Context(contextParams, contextLogger);\n var beans = context.getBean('beans');\n this.registerModuleUserComponents(beans, registeredModules);\n this.registerStackComponents(beans, registeredModules);\n this.registerControllers(beans, registeredModules);\n createUi(context);\n // we wait until the UI has finished initialising before setting in columns and rows\n beans.ctrlsService.whenReady(function () {\n _this.setColumnsAndData(beans);\n _this.dispatchGridReadyEvent(beans);\n var isEnterprise = ModuleRegistry.isRegistered(ModuleNames.EnterpriseCoreModule);\n logger.log(\"initialised successfully, enterprise = \" + isEnterprise);\n });\n if (acceptChanges) {\n acceptChanges(context);\n }\n };\n GridCoreCreator.prototype.registerControllers = function (beans, registeredModules) {\n registeredModules.forEach(function (module) {\n if (module.controllers) {\n module.controllers.forEach(function (meta) { return beans.ctrlsFactory.register(meta); });\n }\n });\n };\n GridCoreCreator.prototype.registerStackComponents = function (beans, registeredModules) {\n var agStackComponents = this.createAgStackComponentsList(registeredModules);\n beans.agStackComponentsRegistry.setupComponents(agStackComponents);\n };\n GridCoreCreator.prototype.getRegisteredModules = function (params) {\n var passedViaConstructor = params ? params.modules : null;\n var registered = ModuleRegistry.getRegisteredModules();\n var allModules = [];\n var mapNames = {};\n // adds to list and removes duplicates\n function addModule(moduleBased, mod) {\n function addIndividualModule(currentModule) {\n if (!mapNames[currentModule.moduleName]) {\n mapNames[currentModule.moduleName] = true;\n allModules.push(currentModule);\n ModuleRegistry.register(currentModule, moduleBased);\n }\n }\n addIndividualModule(mod);\n if (mod.dependantModules) {\n mod.dependantModules.forEach(addModule.bind(null, moduleBased));\n }\n }\n if (passedViaConstructor) {\n passedViaConstructor.forEach(addModule.bind(null, true));\n }\n if (registered) {\n registered.forEach(addModule.bind(null, !ModuleRegistry.isPackageBased()));\n }\n return allModules;\n };\n GridCoreCreator.prototype.registerModuleUserComponents = function (beans, registeredModules) {\n var moduleUserComps = this.extractModuleEntity(registeredModules, function (module) { return module.userComponents ? module.userComponents : []; });\n moduleUserComps.forEach(function (compMeta) {\n beans.userComponentRegistry.registerDefaultComponent(compMeta.componentName, compMeta.componentClass);\n });\n };\n GridCoreCreator.prototype.createProvidedBeans = function (eGridDiv, gridOptions, params) {\n var frameworkOverrides = params ? params.frameworkOverrides : null;\n if (missing(frameworkOverrides)) {\n frameworkOverrides = new VanillaFrameworkOverrides();\n }\n var seed = {\n gridOptions: gridOptions,\n eGridDiv: eGridDiv,\n globalEventListener: params ? params.globalEventListener : null,\n frameworkOverrides: frameworkOverrides\n };\n if (params && params.providedBeanInstances) {\n Object.assign(seed, params.providedBeanInstances);\n }\n return seed;\n };\n GridCoreCreator.prototype.createAgStackComponentsList = function (registeredModules) {\n var components = [\n { componentName: 'AgCheckbox', componentClass: AgCheckbox },\n { componentName: 'AgRadioButton', componentClass: AgRadioButton },\n { componentName: 'AgToggleButton', componentClass: AgToggleButton },\n { componentName: 'AgInputTextField', componentClass: AgInputTextField },\n { componentName: 'AgInputTextArea', componentClass: AgInputTextArea },\n { componentName: 'AgInputNumberField', componentClass: AgInputNumberField },\n { componentName: 'AgInputRange', componentClass: AgInputRange },\n { componentName: 'AgSelect', componentClass: AgSelect },\n { componentName: 'AgSlider', componentClass: AgSlider },\n { componentName: 'AgAngleSelect', componentClass: AgAngleSelect },\n { componentName: 'AgColorPicker', componentClass: AgColorPicker },\n { componentName: 'AgGridBody', componentClass: GridBodyComp },\n { componentName: 'AgHeaderRoot', componentClass: GridHeaderComp },\n { componentName: 'AgSortIndicator', componentClass: SortIndicatorComp },\n { componentName: 'AgPagination', componentClass: PaginationComp },\n { componentName: 'AgOverlayWrapper', componentClass: OverlayWrapperComponent },\n { componentName: 'AgGroupComponent', componentClass: AgGroupComponent },\n { componentName: 'AgPanel', componentClass: AgPanel },\n { componentName: 'AgDialog', componentClass: AgDialog },\n { componentName: 'AgRowContainer', componentClass: RowContainerComp },\n { componentName: 'AgFakeHorizontalScroll', componentClass: FakeHScrollComp }\n ];\n var moduleAgStackComps = this.extractModuleEntity(registeredModules, function (module) { return module.agStackComponents ? module.agStackComponents : []; });\n components = components.concat(moduleAgStackComps);\n return components;\n };\n GridCoreCreator.prototype.createBeansList = function (rowModelType, registeredModules) {\n var rowModelClass = this.getRowModelClass(rowModelType, registeredModules);\n if (!rowModelClass) {\n return;\n }\n // beans should only contain SERVICES, it should NEVER contain COMPONENTS\n var beans = [\n rowModelClass, Beans, RowPositionUtils, CellPositionUtils, HeaderPositionUtils,\n PaginationAutoPageSizeService, GridApi, UserComponentRegistry, AgComponentUtils,\n ComponentMetadataProvider, ResizeObserverService, UserComponentFactory,\n RowContainerHeightService, HorizontalResizeService,\n PinnedRowModel, DragService, DisplayedGroupCreator, EventService, GridOptionsWrapper,\n PopupService, SelectionService, FilterManager, ColumnModel, HeaderNavigationService,\n PaginationProxy, RowRenderer, ExpressionService, ColumnFactory, TemplateService,\n AlignedGridsService, NavigationService, ValueCache, ValueService, LoggerFactory,\n ColumnUtils, AutoWidthCalculator, StandardMenuFactory, DragAndDropService, ColumnApi,\n FocusService, MouseEventService, Environment, CellNavigationService, ValueFormatterService,\n StylingService, ScrollVisibleService, SortController, ColumnHoverService, ColumnAnimationService,\n SelectableService, AutoGroupColService, ChangeDetectionService, AnimationFrameService,\n UndoRedoService, AgStackComponentsRegistry, ColumnDefFactory,\n RowCssClassCalculator, RowNodeBlockLoader, RowNodeSorter, CtrlsService,\n PinnedWidthService, RowNodeEventThrottle, CtrlsFactory\n ];\n var moduleBeans = this.extractModuleEntity(registeredModules, function (module) { return module.beans ? module.beans : []; });\n beans.push.apply(beans, __spread$1(moduleBeans));\n // check for duplicates, as different modules could include the same beans that\n // they depend on, eg ClientSideRowModel in enterprise, and ClientSideRowModel in community\n var beansNoDuplicates = [];\n beans.forEach(function (bean) {\n if (beansNoDuplicates.indexOf(bean) < 0) {\n beansNoDuplicates.push(bean);\n }\n });\n return beansNoDuplicates;\n };\n GridCoreCreator.prototype.extractModuleEntity = function (moduleEntities, extractor) {\n return [].concat.apply([], __spread$1(moduleEntities.map(extractor)));\n };\n GridCoreCreator.prototype.setColumnsAndData = function (beans) {\n var columnDefs = beans.gridOptionsWrapper.getColumnDefs();\n beans.columnModel.setColumnDefs(columnDefs || [], \"gridInitializing\");\n beans.rowModel.start();\n };\n GridCoreCreator.prototype.dispatchGridReadyEvent = function (beans) {\n var readyEvent = {\n type: Events.EVENT_GRID_READY,\n };\n beans.eventService.dispatchEvent(readyEvent);\n };\n GridCoreCreator.prototype.getRowModelClass = function (rowModelType, registeredModules) {\n // default to client side\n if (!rowModelType) {\n rowModelType = Constants.ROW_MODEL_TYPE_CLIENT_SIDE;\n }\n var rowModelClasses = {};\n registeredModules.forEach(function (module) {\n iterateObject(module.rowModels, function (key, value) {\n rowModelClasses[key] = value;\n });\n });\n var rowModelClass = rowModelClasses[rowModelType];\n if (exists(rowModelClass)) {\n return rowModelClass;\n }\n if (ModuleRegistry.isPackageBased()) {\n if ([Constants.ROW_MODEL_TYPE_VIEWPORT, Constants.ROW_MODEL_TYPE_SERVER_SIDE].includes(rowModelType)) {\n // If package based only the enterprise row models could be missing.\n console.error(\"AG Grid: Row Model \\\"\" + rowModelType + \"\\\" not found. Please ensure the package 'ag-grid-enterprise' is imported. Please see: https://www.ag-grid.com/javascript-grid/packages/\");\n }\n else {\n console.error('AG Grid: could not find row model for rowModelType ' + rowModelType);\n }\n }\n else {\n if (rowModelType === Constants.ROW_MODEL_TYPE_INFINITE) {\n console.error(\"AG Grid: Row Model \\\"Infinite\\\" not found. Please ensure the \" + ModuleNames.InfiniteRowModelModule + \" module is registered. Please see: https://www.ag-grid.com/javascript-grid/modules/\");\n }\n else if (rowModelType === Constants.ROW_MODEL_TYPE_VIEWPORT) {\n console.error(\"AG Grid: Row Model \\\"Viewport\\\" not found. Please ensure the AG Grid Enterprise Module \" + ModuleNames.ViewportRowModelModule + \" module is registered. Please see: https://www.ag-grid.com/javascript-grid/modules/\");\n }\n else if (rowModelType === Constants.ROW_MODEL_TYPE_SERVER_SIDE) {\n console.error(\"AG Grid: Row Model \\\"Server Side\\\" not found. Please ensure the AG Grid Enterprise Module \" + ModuleNames.ServerSideRowModelModule + \" module is registered. Please see: https://www.ag-grid.com/javascript-grid/modules/\");\n }\n else if (rowModelType === Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n console.error(\"AG Grid: Row Model \\\"Client Side\\\" not found. Please ensure the \" + ModuleNames.ClientSideRowModelModule + \" module is registered. Please see: https://www.ag-grid.com/javascript-grid/modules/\");\n }\n else {\n console.error('AG Grid: could not find row model for rowModelType ' + rowModelType);\n }\n }\n };\n return GridCoreCreator;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nfunction defaultGroupComparator(valueA, valueB, nodeA, nodeB, accentedCompare) {\n if (accentedCompare === void 0) { accentedCompare = false; }\n console.warn('AG Grid: Since ag-grid 11.0.0 defaultGroupComparator is not necessary. You can remove this from your colDef');\n var nodeAIsGroup = exists(nodeA) && nodeA.group;\n var nodeBIsGroup = exists(nodeB) && nodeB.group;\n var bothAreGroups = nodeAIsGroup && nodeBIsGroup;\n var bothAreNormal = !nodeAIsGroup && !nodeBIsGroup;\n if (bothAreGroups) {\n return defaultComparator(nodeA.key, nodeB.key, accentedCompare);\n }\n if (bothAreNormal) {\n return defaultComparator(valueA, valueB, accentedCompare);\n }\n if (nodeAIsGroup) {\n return 1;\n }\n return -1;\n}\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar BaseComponentWrapper = /** @class */ (function () {\n function BaseComponentWrapper() {\n }\n BaseComponentWrapper.prototype.wrap = function (OriginalConstructor, mandatoryMethodList, optionalMethodList, componentType) {\n var _this = this;\n if (optionalMethodList === void 0) { optionalMethodList = []; }\n var wrapper = this.createWrapper(OriginalConstructor, componentType);\n mandatoryMethodList.forEach((function (methodName) {\n _this.createMethod(wrapper, methodName, true);\n }));\n optionalMethodList.forEach((function (methodName) {\n _this.createMethod(wrapper, methodName, false);\n }));\n return wrapper;\n };\n BaseComponentWrapper.prototype.unwrap = function (comp) {\n return comp;\n };\n BaseComponentWrapper.prototype.createMethod = function (wrapper, methodName, mandatory) {\n wrapper.addMethod(methodName, this.createMethodProxy(wrapper, methodName, mandatory));\n };\n BaseComponentWrapper.prototype.createMethodProxy = function (wrapper, methodName, mandatory) {\n return function () {\n if (wrapper.hasMethod(methodName)) {\n return wrapper.callMethod(methodName, arguments);\n }\n if (mandatory) {\n console.warn('AG Grid: Framework component is missing the method ' + methodName + '()');\n }\n return null;\n };\n };\n return BaseComponentWrapper;\n}());\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\n/************************************************************************************************\n * If you update these, then also update the `integrated-charts-toolbar` docs. *\n ************************************************************************************************/\nvar DEFAULT_CHART_GROUPS = {\n columnGroup: [\n 'column',\n 'stackedColumn',\n 'normalizedColumn'\n ],\n barGroup: [\n 'bar',\n 'stackedBar',\n 'normalizedBar'\n ],\n pieGroup: [\n 'pie',\n 'doughnut'\n ],\n lineGroup: [\n 'line'\n ],\n scatterGroup: [\n 'scatter',\n 'bubble'\n ],\n areaGroup: [\n 'area',\n 'stackedArea',\n 'normalizedArea'\n ],\n histogramGroup: [\n 'histogram'\n ],\n combinationGroup: [\n 'columnLineCombo',\n 'areaColumnCombo',\n 'customCombo'\n ]\n};\nvar CHART_TOOL_PANEL_ALLOW_LIST = [\n 'chartSettings',\n 'chartData',\n 'chartFormat'\n];\nvar CHART_TOOLBAR_ALLOW_LIST = [\n 'chartUnlink',\n 'chartLink',\n 'chartDownload'\n];\nvar CHART_TOOL_PANEL_MENU_OPTIONS = {\n settings: \"chartSettings\",\n data: \"chartData\",\n format: \"chartFormat\"\n};\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar BarColumnLabelPlacement;\n(function (BarColumnLabelPlacement) {\n BarColumnLabelPlacement[\"InsideBase\"] = \"insideBase\";\n BarColumnLabelPlacement[\"InsideEnd\"] = \"insideEnd\";\n BarColumnLabelPlacement[\"Center\"] = \"center\";\n BarColumnLabelPlacement[\"OutsideEnd\"] = \"outsideEnd\";\n})(BarColumnLabelPlacement || (BarColumnLabelPlacement = {}));\n\n/**\n * @ag-grid-community/core - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue\n * @version v28.2.0\n * @link https://www.ag-grid.com/\n * @license MIT\n */\nvar globalObj = typeof global === 'undefined' ? {} : global;\nglobalObj.HTMLElement = typeof HTMLElement === 'undefined' ? {} : HTMLElement;\nglobalObj.HTMLButtonElement = typeof HTMLButtonElement === 'undefined' ? {} : HTMLButtonElement;\nglobalObj.HTMLSelectElement = typeof HTMLSelectElement === 'undefined' ? {} : HTMLSelectElement;\nglobalObj.HTMLInputElement = typeof HTMLInputElement === 'undefined' ? {} : HTMLInputElement;\nglobalObj.Node = typeof Node === 'undefined' ? {} : Node;\nglobalObj.MouseEvent = typeof MouseEvent === 'undefined' ? {} : MouseEvent;\n\nvar __read$1 = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar __spread = (undefined && undefined.__spread) || function () {\n for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read$1(arguments[i]));\n return ar;\n};\nvar ClientSideNodeManager = /** @class */ (function () {\n function ClientSideNodeManager(rootNode, gridOptionsWrapper, eventService, columnModel, selectionService, beans) {\n this.nextId = 0;\n // when user is provide the id's, we also keep a map of ids to row nodes for convenience\n this.allNodesMap = {};\n this.rootNode = rootNode;\n this.gridOptionsWrapper = gridOptionsWrapper;\n this.eventService = eventService;\n this.columnModel = columnModel;\n this.beans = beans;\n this.selectionService = selectionService;\n this.rootNode.group = true;\n this.rootNode.level = -1;\n this.rootNode.id = ClientSideNodeManager.ROOT_NODE_ID;\n this.rootNode.allLeafChildren = [];\n this.rootNode.childrenAfterGroup = [];\n this.rootNode.childrenAfterSort = [];\n this.rootNode.childrenAfterAggFilter = [];\n this.rootNode.childrenAfterFilter = [];\n // if we make this class a bean, then can annotate postConstruct\n this.postConstruct();\n }\n // @PostConstruct - this is not a bean, so postConstruct called by constructor\n ClientSideNodeManager.prototype.postConstruct = function () {\n // func below doesn't have 'this' pointer, so need to pull out these bits\n this.suppressParentsInRowNodes = this.gridOptionsWrapper.isSuppressParentsInRowNodes();\n this.isRowMasterFunc = this.gridOptionsWrapper.getIsRowMasterFunc();\n this.doingTreeData = this.gridOptionsWrapper.isTreeData();\n this.doingMasterDetail = this.gridOptionsWrapper.isMasterDetail();\n };\n ClientSideNodeManager.prototype.getCopyOfNodesMap = function () {\n return _.cloneObject(this.allNodesMap);\n };\n ClientSideNodeManager.prototype.getRowNode = function (id) {\n return this.allNodesMap[id];\n };\n ClientSideNodeManager.prototype.setRowData = function (rowData) {\n var _this = this;\n if (typeof rowData === 'string') {\n console.warn('AG Grid: rowData must be an array, however you passed in a string. If you are loading JSON, make sure you convert the JSON string to JavaScript objects first');\n return;\n }\n var rootNode = this.rootNode;\n var sibling = this.rootNode.sibling;\n rootNode.childrenAfterFilter = null;\n rootNode.childrenAfterGroup = null;\n rootNode.childrenAfterAggFilter = null;\n rootNode.childrenAfterSort = null;\n rootNode.childrenMapped = null;\n rootNode.updateHasChildren();\n this.nextId = 0;\n this.allNodesMap = {};\n if (rowData) {\n // we use rootNode as the parent, however if using ag-grid-enterprise, the grouping stage\n // sets the parent node on each row (even if we are not grouping). so setting parent node\n // here is for benefit of ag-grid-community users\n rootNode.allLeafChildren = rowData.map(function (dataItem) { return _this.createNode(dataItem, _this.rootNode, ClientSideNodeManager.TOP_LEVEL); });\n }\n else {\n rootNode.allLeafChildren = [];\n rootNode.childrenAfterGroup = [];\n }\n if (sibling) {\n sibling.childrenAfterFilter = rootNode.childrenAfterFilter;\n sibling.childrenAfterGroup = rootNode.childrenAfterGroup;\n sibling.childrenAfterAggFilter = rootNode.childrenAfterAggFilter;\n sibling.childrenAfterSort = rootNode.childrenAfterSort;\n sibling.childrenMapped = rootNode.childrenMapped;\n sibling.allLeafChildren = rootNode.allLeafChildren;\n }\n };\n ClientSideNodeManager.prototype.updateRowData = function (rowDataTran, rowNodeOrder) {\n var rowNodeTransaction = {\n remove: [],\n update: [],\n add: []\n };\n var nodesToUnselect = [];\n this.executeRemove(rowDataTran, rowNodeTransaction, nodesToUnselect);\n this.executeUpdate(rowDataTran, rowNodeTransaction, nodesToUnselect);\n this.executeAdd(rowDataTran, rowNodeTransaction);\n this.updateSelection(nodesToUnselect);\n if (rowNodeOrder) {\n _.sortRowNodesByOrder(this.rootNode.allLeafChildren, rowNodeOrder);\n }\n return rowNodeTransaction;\n };\n ClientSideNodeManager.prototype.updateSelection = function (nodesToUnselect) {\n var selectionChanged = nodesToUnselect.length > 0;\n if (selectionChanged) {\n nodesToUnselect.forEach(function (rowNode) {\n rowNode.setSelected(false, false, true);\n });\n }\n // we do this regardless of nodes to unselect or not, as it's possible\n // a new node was inserted, so a parent that was previously selected (as all\n // children were selected) should not be tri-state (as new one unselected against\n // all other selected children).\n this.selectionService.updateGroupsFromChildrenSelections();\n if (selectionChanged) {\n var event_1 = {\n type: Events.EVENT_SELECTION_CHANGED\n };\n this.eventService.dispatchEvent(event_1);\n }\n };\n ClientSideNodeManager.prototype.executeAdd = function (rowDataTran, rowNodeTransaction) {\n var _this = this;\n var add = rowDataTran.add, addIndex = rowDataTran.addIndex;\n if (_.missingOrEmpty(add)) {\n return;\n }\n // create new row nodes for each data item\n var newNodes = add.map(function (item) { return _this.createNode(item, _this.rootNode, ClientSideNodeManager.TOP_LEVEL); });\n // add new row nodes to the root nodes 'allLeafChildren'\n var useIndex = typeof addIndex === 'number' && addIndex >= 0;\n var nodesBeforeIndex;\n var nodesAfterIndex;\n if (useIndex) {\n // new rows are inserted in one go by concatenating them in between the existing rows at the desired index.\n // this is much faster than splicing them individually into 'allLeafChildren' when there are large inserts.\n // allLeafChildren can be out of order, so we loop over all the Nodes to find the correct index that\n // represents the position `addIndex` intended to be.\n var allLeafChildren_1 = this.rootNode.allLeafChildren;\n // if addIndex is 0, it should always be added at the start of the array\n // there is no need to verify the order of node by nodeIndex.\n var normalizedAddIndex = addIndex === 0 ? 0 : (allLeafChildren_1.reduce(function (prevIdx, currNode, currIdx) {\n var _a;\n var rowIndex = currNode.rowIndex;\n var prevValueAtIndex = (_a = allLeafChildren_1[prevIdx]) === null || _a === void 0 ? void 0 : _a.rowIndex;\n var shouldUpdateIndex = rowIndex != null && prevValueAtIndex != null && rowIndex < addIndex && rowIndex > prevValueAtIndex;\n return shouldUpdateIndex ? currIdx : prevIdx;\n }, 0) + 1);\n nodesBeforeIndex = allLeafChildren_1.slice(0, normalizedAddIndex);\n nodesAfterIndex = allLeafChildren_1.slice(normalizedAddIndex, allLeafChildren_1.length);\n }\n else {\n nodesBeforeIndex = this.rootNode.allLeafChildren;\n nodesAfterIndex = [];\n }\n this.rootNode.allLeafChildren = __spread(nodesBeforeIndex, newNodes, nodesAfterIndex);\n if (this.rootNode.sibling) {\n this.rootNode.sibling.allLeafChildren = this.rootNode.allLeafChildren;\n }\n // add new row nodes to the transaction add items\n rowNodeTransaction.add = newNodes;\n };\n ClientSideNodeManager.prototype.executeRemove = function (rowDataTran, rowNodeTransaction, nodesToUnselect) {\n var _this = this;\n var remove = rowDataTran.remove;\n if (_.missingOrEmpty(remove)) {\n return;\n }\n var rowIdsRemoved = {};\n remove.forEach(function (item) {\n var rowNode = _this.lookupRowNode(item);\n if (!rowNode) {\n return;\n }\n // do delete - setting 'suppressFinishActions = true' to ensure EVENT_SELECTION_CHANGED is not raised for\n // each row node updated, instead it is raised once by the calling code if any selected nodes exist.\n if (rowNode.isSelected()) {\n nodesToUnselect.push(rowNode);\n }\n // so row renderer knows to fade row out (and not reposition it)\n rowNode.clearRowTopAndRowIndex();\n // NOTE: were we could remove from allLeaveChildren, however _.removeFromArray() is expensive, especially\n // if called multiple times (eg deleting lots of rows) and if allLeafChildren is a large list\n rowIdsRemoved[rowNode.id] = true;\n // _.removeFromArray(this.rootNode.allLeafChildren, rowNode);\n delete _this.allNodesMap[rowNode.id];\n rowNodeTransaction.remove.push(rowNode);\n });\n this.rootNode.allLeafChildren = this.rootNode.allLeafChildren.filter(function (rowNode) { return !rowIdsRemoved[rowNode.id]; });\n if (this.rootNode.sibling) {\n this.rootNode.sibling.allLeafChildren = this.rootNode.allLeafChildren;\n }\n };\n ClientSideNodeManager.prototype.executeUpdate = function (rowDataTran, rowNodeTransaction, nodesToUnselect) {\n var _this = this;\n var update = rowDataTran.update;\n if (_.missingOrEmpty(update)) {\n return;\n }\n update.forEach(function (item) {\n var rowNode = _this.lookupRowNode(item);\n if (!rowNode) {\n return;\n }\n rowNode.updateData(item);\n if (!rowNode.selectable && rowNode.isSelected()) {\n nodesToUnselect.push(rowNode);\n }\n _this.setMasterForRow(rowNode, item, ClientSideNodeManager.TOP_LEVEL, false);\n rowNodeTransaction.update.push(rowNode);\n });\n };\n ClientSideNodeManager.prototype.lookupRowNode = function (data) {\n var getRowIdFunc = this.gridOptionsWrapper.getRowIdFunc();\n var rowNode;\n if (getRowIdFunc) {\n // find rowNode using id\n var id = getRowIdFunc({ data: data, level: 0 });\n rowNode = this.allNodesMap[id];\n if (!rowNode) {\n console.error(\"AG Grid: could not find row id=\" + id + \", data item was not found for this id\");\n return null;\n }\n }\n else {\n // find rowNode using object references\n rowNode = this.rootNode.allLeafChildren.find(function (node) { return node.data === data; });\n if (!rowNode) {\n console.error(\"AG Grid: could not find data item as object was not found\", data);\n console.error(\"Consider using getRowId to help the Grid find matching row data\");\n return null;\n }\n }\n return rowNode || null;\n };\n ClientSideNodeManager.prototype.createNode = function (dataItem, parent, level) {\n var node = new RowNode(this.beans);\n node.group = false;\n this.setMasterForRow(node, dataItem, level, true);\n if (parent && !this.suppressParentsInRowNodes) {\n node.parent = parent;\n }\n node.level = level;\n node.setDataAndId(dataItem, this.nextId.toString());\n if (this.allNodesMap[node.id]) {\n console.warn(\"AG Grid: duplicate node id '\" + node.id + \"' detected from getRowId callback, this could cause issues in your grid.\");\n }\n this.allNodesMap[node.id] = node;\n this.nextId++;\n return node;\n };\n ClientSideNodeManager.prototype.setMasterForRow = function (rowNode, data, level, setExpanded) {\n if (this.doingTreeData) {\n rowNode.setMaster(false);\n if (setExpanded) {\n rowNode.expanded = false;\n }\n }\n else {\n // this is the default, for when doing grid data\n if (this.doingMasterDetail) {\n // if we are doing master detail, then the\n // default is that everything can be a Master Row.\n if (this.isRowMasterFunc) {\n rowNode.setMaster(this.isRowMasterFunc(data));\n }\n else {\n rowNode.setMaster(true);\n }\n }\n else {\n rowNode.setMaster(false);\n }\n if (setExpanded) {\n var rowGroupColumns = this.columnModel.getRowGroupColumns();\n var numRowGroupColumns = rowGroupColumns ? rowGroupColumns.length : 0;\n // need to take row group into account when determining level\n var masterRowLevel = level + numRowGroupColumns;\n rowNode.expanded = rowNode.master ? this.isExpanded(masterRowLevel) : false;\n }\n }\n };\n ClientSideNodeManager.prototype.isExpanded = function (level) {\n var expandByDefault = this.gridOptionsWrapper.getGroupDefaultExpanded();\n if (expandByDefault === -1) {\n return true;\n }\n return level < expandByDefault;\n };\n ClientSideNodeManager.TOP_LEVEL = 0;\n ClientSideNodeManager.ROOT_NODE_ID = 'ROOT_NODE_ID';\n return ClientSideNodeManager;\n}());\n\nvar __extends$c = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RecursionType;\n(function (RecursionType) {\n RecursionType[RecursionType[\"Normal\"] = 0] = \"Normal\";\n RecursionType[RecursionType[\"AfterFilter\"] = 1] = \"AfterFilter\";\n RecursionType[RecursionType[\"AfterFilterAndSort\"] = 2] = \"AfterFilterAndSort\";\n RecursionType[RecursionType[\"PivotNodes\"] = 3] = \"PivotNodes\";\n})(RecursionType || (RecursionType = {}));\nvar ClientSideRowModel = /** @class */ (function (_super) {\n __extends$c(ClientSideRowModel, _super);\n function ClientSideRowModel() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.onRowHeightChanged_debounced = _.debounce(_this.onRowHeightChanged.bind(_this), 100);\n _this.rowsToDisplay = []; // the rows mapped to rows to display\n return _this;\n }\n ClientSideRowModel.prototype.init = function () {\n var refreshEverythingFunc = this.refreshModel.bind(this, { step: ClientSideRowModelSteps.EVERYTHING });\n var animate = !this.gridOptionsWrapper.isSuppressAnimationFrame();\n var refreshEverythingAfterColsChangedFunc = this.refreshModel.bind(this, {\n step: ClientSideRowModelSteps.EVERYTHING,\n afterColumnsChanged: true,\n keepRenderedRows: true,\n animate: animate\n });\n this.addManagedListener(this.eventService, Events.EVENT_NEW_COLUMNS_LOADED, refreshEverythingAfterColsChangedFunc);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_ROW_GROUP_CHANGED, refreshEverythingFunc);\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_VALUE_CHANGED, this.onValueChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_CHANGED, this.refreshModel.bind(this, { step: ClientSideRowModelSteps.PIVOT }));\n this.addManagedListener(this.eventService, Events.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, refreshEverythingFunc);\n var refreshMapListener = this.refreshModel.bind(this, {\n step: ClientSideRowModelSteps.MAP,\n keepRenderedRows: true,\n animate: animate\n });\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_GROUP_REMOVE_SINGLE_CHILDREN, refreshMapListener);\n this.addManagedListener(this.gridOptionsWrapper, GridOptionsWrapper.PROP_GROUP_REMOVE_LOWEST_SINGLE_CHILDREN, refreshMapListener);\n this.rootNode = new RowNode(this.beans);\n this.nodeManager = new ClientSideNodeManager(this.rootNode, this.gridOptionsWrapper, this.eventService, this.columnModel, this.selectionService, this.beans);\n };\n ClientSideRowModel.prototype.start = function () {\n var rowData = this.gridOptionsWrapper.getRowData();\n if (rowData) {\n this.setRowData(rowData);\n }\n };\n ClientSideRowModel.prototype.ensureRowHeightsValid = function (startPixel, endPixel, startLimitIndex, endLimitIndex) {\n var atLeastOneChange;\n var res = false;\n // we do this multiple times as changing the row heights can also change the first and last rows,\n // so the first pass can make lots of rows smaller, which means the second pass we end up changing\n // more rows.\n do {\n atLeastOneChange = false;\n var rowAtStartPixel = this.getRowIndexAtPixel(startPixel);\n var rowAtEndPixel = this.getRowIndexAtPixel(endPixel);\n // keep check to current page if doing pagination\n var firstRow = Math.max(rowAtStartPixel, startLimitIndex);\n var lastRow = Math.min(rowAtEndPixel, endLimitIndex);\n for (var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {\n var rowNode = this.getRow(rowIndex);\n if (rowNode.rowHeightEstimated) {\n var rowHeight = this.gridOptionsWrapper.getRowHeightForNode(rowNode);\n rowNode.setRowHeight(rowHeight.height);\n atLeastOneChange = true;\n res = true;\n }\n }\n if (atLeastOneChange) {\n this.setRowTopAndRowIndex();\n }\n } while (atLeastOneChange);\n return res;\n };\n ClientSideRowModel.prototype.setRowTopAndRowIndex = function () {\n var defaultRowHeight = this.gridOptionsWrapper.getDefaultRowHeight();\n var nextRowTop = 0;\n // mapping displayed rows is not needed for this method, however it's used in\n // clearRowTopAndRowIndex(), and given we are looping through this.rowsToDisplay here,\n // we create the map here for performance reasons, so we don't loop a second time\n // in clearRowTopAndRowIndex()\n var displayedRowsMapped = new Set();\n // we don't estimate if doing fullHeight or autoHeight, as all rows get rendered all the time\n // with these two layouts.\n var allowEstimate = this.gridOptionsWrapper.getDomLayout() === Constants.DOM_LAYOUT_NORMAL;\n for (var i = 0; i < this.rowsToDisplay.length; i++) {\n var rowNode = this.rowsToDisplay[i];\n if (rowNode.id != null) {\n displayedRowsMapped.add(rowNode.id);\n }\n if (rowNode.rowHeight == null) {\n var rowHeight = this.gridOptionsWrapper.getRowHeightForNode(rowNode, allowEstimate, defaultRowHeight);\n rowNode.setRowHeight(rowHeight.height, rowHeight.estimated);\n }\n rowNode.setRowTop(nextRowTop);\n rowNode.setRowIndex(i);\n nextRowTop += rowNode.rowHeight;\n }\n return displayedRowsMapped;\n };\n ClientSideRowModel.prototype.clearRowTopAndRowIndex = function (changedPath, displayedRowsMapped) {\n var changedPathActive = changedPath.isActive();\n var clearIfNotDisplayed = function (rowNode) {\n if (rowNode && rowNode.id != null && !displayedRowsMapped.has(rowNode.id)) {\n rowNode.clearRowTopAndRowIndex();\n }\n };\n var recurse = function (rowNode) {\n clearIfNotDisplayed(rowNode);\n clearIfNotDisplayed(rowNode.detailNode);\n clearIfNotDisplayed(rowNode.sibling);\n if (rowNode.hasChildren()) {\n if (rowNode.childrenAfterGroup) {\n // if a changedPath is active, it means we are here because of a transaction update or\n // a change detection. neither of these impacts the open/closed state of groups. so if\n // a group is not open this time, it was not open last time. so we know all closed groups\n // already have their top positions cleared. so there is no need to traverse all the way\n // when changedPath is active and the rowNode is not expanded.\n var isRootNode = rowNode.level == -1; // we need to give special consideration for root node,\n // as expanded=undefined for root node\n var skipChildren = changedPathActive && !isRootNode && !rowNode.expanded;\n if (!skipChildren) {\n rowNode.childrenAfterGroup.forEach(recurse);\n }\n }\n }\n };\n recurse(this.rootNode);\n };\n // returns false if row was moved, otherwise true\n ClientSideRowModel.prototype.ensureRowsAtPixel = function (rowNodes, pixel, increment) {\n var _this = this;\n if (increment === void 0) { increment = 0; }\n var indexAtPixelNow = this.getRowIndexAtPixel(pixel);\n var rowNodeAtPixelNow = this.getRow(indexAtPixelNow);\n var animate = !this.gridOptionsWrapper.isSuppressAnimationFrame();\n if (rowNodeAtPixelNow === rowNodes[0]) {\n return false;\n }\n rowNodes.forEach(function (rowNode) {\n _.removeFromArray(_this.rootNode.allLeafChildren, rowNode);\n });\n rowNodes.forEach(function (rowNode, idx) {\n _.insertIntoArray(_this.rootNode.allLeafChildren, rowNode, Math.max(indexAtPixelNow + increment, 0) + idx);\n });\n this.refreshModel({\n step: ClientSideRowModelSteps.EVERYTHING,\n keepRenderedRows: true,\n keepEditingRows: true,\n animate: animate\n });\n return true;\n };\n ClientSideRowModel.prototype.highlightRowAtPixel = function (rowNode, pixel) {\n var indexAtPixelNow = pixel != null ? this.getRowIndexAtPixel(pixel) : null;\n var rowNodeAtPixelNow = indexAtPixelNow != null ? this.getRow(indexAtPixelNow) : null;\n if (!rowNodeAtPixelNow || !rowNode || rowNodeAtPixelNow === rowNode || pixel == null) {\n if (this.lastHighlightedRow) {\n this.lastHighlightedRow.setHighlighted(null);\n this.lastHighlightedRow = null;\n }\n return;\n }\n var highlight = this.getHighlightPosition(pixel, rowNodeAtPixelNow);\n if (this.lastHighlightedRow && this.lastHighlightedRow !== rowNodeAtPixelNow) {\n this.lastHighlightedRow.setHighlighted(null);\n this.lastHighlightedRow = null;\n }\n rowNodeAtPixelNow.setHighlighted(highlight);\n this.lastHighlightedRow = rowNodeAtPixelNow;\n };\n ClientSideRowModel.prototype.getHighlightPosition = function (pixel, rowNode) {\n if (!rowNode) {\n var index = this.getRowIndexAtPixel(pixel);\n rowNode = this.getRow(index || 0);\n if (!rowNode) {\n return RowHighlightPosition.Below;\n }\n }\n var rowTop = rowNode.rowTop, rowHeight = rowNode.rowHeight;\n return pixel - rowTop < rowHeight / 2 ? RowHighlightPosition.Above : RowHighlightPosition.Below;\n };\n ClientSideRowModel.prototype.getLastHighlightedRowNode = function () {\n return this.lastHighlightedRow;\n };\n ClientSideRowModel.prototype.isLastRowIndexKnown = function () {\n return true;\n };\n ClientSideRowModel.prototype.getRowCount = function () {\n if (this.rowsToDisplay) {\n return this.rowsToDisplay.length;\n }\n return 0;\n };\n ClientSideRowModel.prototype.getTopLevelRowCount = function () {\n var showingRootNode = this.rowsToDisplay && this.rowsToDisplay[0] === this.rootNode;\n if (showingRootNode) {\n return 1;\n }\n var filteredChildren = this.rootNode.childrenAfterAggFilter;\n return filteredChildren ? filteredChildren.length : 0;\n };\n ClientSideRowModel.prototype.getTopLevelRowDisplayedIndex = function (topLevelIndex) {\n var showingRootNode = this.rowsToDisplay && this.rowsToDisplay[0] === this.rootNode;\n if (showingRootNode) {\n return topLevelIndex;\n }\n var rowNode = this.rootNode.childrenAfterSort[topLevelIndex];\n if (this.gridOptionsWrapper.isGroupHideOpenParents()) {\n // if hideOpenParents, and this row open, then this row is now displayed at this index, first child is\n while (rowNode.expanded && rowNode.childrenAfterSort && rowNode.childrenAfterSort.length > 0) {\n rowNode = rowNode.childrenAfterSort[0];\n }\n }\n return rowNode.rowIndex;\n };\n ClientSideRowModel.prototype.getRowBounds = function (index) {\n if (_.missing(this.rowsToDisplay)) {\n return null;\n }\n var rowNode = this.rowsToDisplay[index];\n if (rowNode) {\n return {\n rowTop: rowNode.rowTop,\n rowHeight: rowNode.rowHeight\n };\n }\n return null;\n };\n ClientSideRowModel.prototype.onRowGroupOpened = function () {\n var animate = this.gridOptionsWrapper.isAnimateRows();\n this.refreshModel({ step: ClientSideRowModelSteps.MAP, keepRenderedRows: true, animate: animate });\n };\n ClientSideRowModel.prototype.onFilterChanged = function (event) {\n if (event.afterDataChange) {\n return;\n }\n var animate = this.gridOptionsWrapper.isAnimateRows();\n var primaryOrQuickFilterChanged = event.columns.length === 0 || event.columns.some(function (col) { return col.isPrimary(); });\n var step = primaryOrQuickFilterChanged ? ClientSideRowModelSteps.FILTER : ClientSideRowModelSteps.FILTER_AGGREGATES;\n this.refreshModel({ step: step, keepRenderedRows: true, animate: animate });\n };\n ClientSideRowModel.prototype.onSortChanged = function () {\n var animate = this.gridOptionsWrapper.isAnimateRows();\n this.refreshModel({ step: ClientSideRowModelSteps.SORT, keepRenderedRows: true, animate: animate, keepEditingRows: true });\n };\n ClientSideRowModel.prototype.getType = function () {\n return Constants.ROW_MODEL_TYPE_CLIENT_SIDE;\n };\n ClientSideRowModel.prototype.onValueChanged = function () {\n if (this.columnModel.isPivotActive()) {\n this.refreshModel({ step: ClientSideRowModelSteps.PIVOT });\n }\n else {\n this.refreshModel({ step: ClientSideRowModelSteps.AGGREGATE });\n }\n };\n ClientSideRowModel.prototype.createChangePath = function (rowNodeTransactions) {\n // for updates, if the row is updated at all, then we re-calc all the values\n // in that row. we could compare each value to each old value, however if we\n // did this, we would be calling the valueService twice, once on the old value\n // and once on the new value. so it's less valueGetter calls if we just assume\n // each column is different. that way the changedPath is used so that only\n // the impacted parent rows are recalculated, parents who's children have\n // not changed are not impacted.\n var noTransactions = _.missingOrEmpty(rowNodeTransactions);\n var changedPath = new ChangedPath(false, this.rootNode);\n if (noTransactions || this.gridOptionsWrapper.isTreeData()) {\n changedPath.setInactive();\n }\n return changedPath;\n };\n ClientSideRowModel.prototype.isSuppressModelUpdateAfterUpdateTransaction = function (params) {\n if (!this.gridOptionsWrapper.isSuppressModelUpdateAfterUpdateTransaction()) {\n return false;\n }\n // return true if we are only doing update transactions\n if (params.rowNodeTransactions == null) {\n return false;\n }\n var transWithAddsOrDeletes = params.rowNodeTransactions.filter(function (tx) {\n return (tx.add != null && tx.add.length > 0) || (tx.remove != null && tx.remove.length > 0);\n });\n var transactionsContainUpdatesOnly = transWithAddsOrDeletes == null || transWithAddsOrDeletes.length == 0;\n return transactionsContainUpdatesOnly;\n };\n ClientSideRowModel.prototype.refreshModel = function (params) {\n if (this.isSuppressModelUpdateAfterUpdateTransaction(params)) {\n return;\n }\n // this goes through the pipeline of stages. what's in my head is similar\n // to the diagram on this page:\n // http://commons.apache.org/sandbox/commons-pipeline/pipeline_basics.html\n // however we want to keep the results of each stage, hence we manually call\n // each step rather than have them chain each other.\n // fallthrough in below switch is on purpose,\n // eg if STEP_FILTER, then all steps below this\n // step get done\n // let start: number;\n // console.log('======= start =======');\n var changedPath = this.createChangePath(params.rowNodeTransactions);\n switch (params.step) {\n case ClientSideRowModelSteps.EVERYTHING:\n this.doRowGrouping(params.groupState, params.rowNodeTransactions, params.rowNodeOrder, changedPath, !!params.afterColumnsChanged);\n case ClientSideRowModelSteps.FILTER:\n this.doFilter(changedPath);\n case ClientSideRowModelSteps.PIVOT:\n this.doPivot(changedPath);\n case ClientSideRowModelSteps.AGGREGATE: // depends on agg fields\n this.doAggregate(changedPath);\n case ClientSideRowModelSteps.FILTER_AGGREGATES:\n this.doFilterAggregates(changedPath);\n case ClientSideRowModelSteps.SORT:\n this.doSort(params.rowNodeTransactions, changedPath);\n case ClientSideRowModelSteps.MAP:\n this.doRowsToDisplay();\n }\n // set all row tops to null, then set row tops on all visible rows. if we don't\n // do this, then the algorithm below only sets row tops, old row tops from old rows\n // will still lie around\n var displayedNodesMapped = this.setRowTopAndRowIndex();\n this.clearRowTopAndRowIndex(changedPath, displayedNodesMapped);\n var event = {\n type: Events.EVENT_MODEL_UPDATED,\n animate: params.animate,\n keepRenderedRows: params.keepRenderedRows,\n newData: params.newData,\n newPage: false,\n keepUndoRedoStack: params.keepUndoRedoStack\n };\n this.eventService.dispatchEvent(event);\n };\n ClientSideRowModel.prototype.isEmpty = function () {\n var rowsMissing = _.missing(this.rootNode.allLeafChildren) || this.rootNode.allLeafChildren.length === 0;\n return _.missing(this.rootNode) || rowsMissing || !this.columnModel.isReady();\n };\n ClientSideRowModel.prototype.isRowsToRender = function () {\n return _.exists(this.rowsToDisplay) && this.rowsToDisplay.length > 0;\n };\n ClientSideRowModel.prototype.getNodesInRangeForSelection = function (firstInRange, lastInRange) {\n // if lastSelectedNode is missing, we start at the first row\n var firstRowHit = !lastInRange;\n var lastRowHit = false;\n var lastRow;\n var result = [];\n var groupsSelectChildren = this.gridOptionsWrapper.isGroupSelectsChildren();\n this.forEachNodeAfterFilterAndSort(function (rowNode) {\n var lookingForLastRow = firstRowHit && !lastRowHit;\n // check if we need to flip the select switch\n if (!firstRowHit) {\n if (rowNode === lastInRange || rowNode === firstInRange) {\n firstRowHit = true;\n }\n }\n var skipThisGroupNode = rowNode.group && groupsSelectChildren;\n if (!skipThisGroupNode) {\n var inRange = firstRowHit && !lastRowHit;\n var childOfLastRow = rowNode.isParentOfNode(lastRow);\n if (inRange || childOfLastRow) {\n result.push(rowNode);\n }\n }\n if (lookingForLastRow) {\n if (rowNode === lastInRange || rowNode === firstInRange) {\n lastRowHit = true;\n if (rowNode === lastInRange) {\n lastRow = lastInRange;\n }\n else {\n lastRow = firstInRange;\n }\n }\n }\n });\n return result;\n };\n ClientSideRowModel.prototype.setDatasource = function (datasource) {\n console.error('AG Grid: should never call setDatasource on clientSideRowController');\n };\n ClientSideRowModel.prototype.getTopLevelNodes = function () {\n return this.rootNode ? this.rootNode.childrenAfterGroup : null;\n };\n ClientSideRowModel.prototype.getRootNode = function () {\n return this.rootNode;\n };\n ClientSideRowModel.prototype.getRow = function (index) {\n return this.rowsToDisplay[index];\n };\n ClientSideRowModel.prototype.isRowPresent = function (rowNode) {\n return this.rowsToDisplay.indexOf(rowNode) >= 0;\n };\n ClientSideRowModel.prototype.getRowIndexAtPixel = function (pixelToMatch) {\n if (this.isEmpty() || this.rowsToDisplay.length === 0) {\n return -1;\n }\n // do binary search of tree\n // http://oli.me.uk/2013/06/08/searching-javascript-arrays-with-a-binary-search/\n var bottomPointer = 0;\n var topPointer = this.rowsToDisplay.length - 1;\n // quick check, if the pixel is out of bounds, then return last row\n if (pixelToMatch <= 0) {\n // if pixel is less than or equal zero, it's always the first row\n return 0;\n }\n var lastNode = _.last(this.rowsToDisplay);\n if (lastNode.rowTop <= pixelToMatch) {\n return this.rowsToDisplay.length - 1;\n }\n var oldBottomPointer = -1;\n var oldTopPointer = -1;\n while (true) {\n var midPointer = Math.floor((bottomPointer + topPointer) / 2);\n var currentRowNode = this.rowsToDisplay[midPointer];\n if (this.isRowInPixel(currentRowNode, pixelToMatch)) {\n return midPointer;\n }\n if (currentRowNode.rowTop < pixelToMatch) {\n bottomPointer = midPointer + 1;\n }\n else if (currentRowNode.rowTop > pixelToMatch) {\n topPointer = midPointer - 1;\n }\n // infinite loops happen when there is space between rows. this can happen\n // when Auto Height is active, cos we re-calculate row tops asyncronously\n // when row heights change, which can temporarly result in gaps between rows.\n var caughtInInfiniteLoop = oldBottomPointer === bottomPointer\n && oldTopPointer === topPointer;\n if (caughtInInfiniteLoop) {\n return midPointer;\n }\n oldBottomPointer = bottomPointer;\n oldTopPointer = topPointer;\n }\n };\n ClientSideRowModel.prototype.isRowInPixel = function (rowNode, pixelToMatch) {\n var topPixel = rowNode.rowTop;\n var bottomPixel = rowNode.rowTop + rowNode.rowHeight;\n var pixelInRow = topPixel <= pixelToMatch && bottomPixel > pixelToMatch;\n return pixelInRow;\n };\n ClientSideRowModel.prototype.forEachLeafNode = function (callback) {\n if (this.rootNode.allLeafChildren) {\n this.rootNode.allLeafChildren.forEach(function (rowNode, index) { return callback(rowNode, index); });\n }\n };\n ClientSideRowModel.prototype.forEachNode = function (callback) {\n this.recursivelyWalkNodesAndCallback(this.rootNode.childrenAfterGroup, callback, RecursionType.Normal, 0);\n };\n ClientSideRowModel.prototype.forEachNodeAfterFilter = function (callback) {\n this.recursivelyWalkNodesAndCallback(this.rootNode.childrenAfterAggFilter, callback, RecursionType.AfterFilter, 0);\n };\n ClientSideRowModel.prototype.forEachNodeAfterFilterAndSort = function (callback) {\n this.recursivelyWalkNodesAndCallback(this.rootNode.childrenAfterSort, callback, RecursionType.AfterFilterAndSort, 0);\n };\n ClientSideRowModel.prototype.forEachPivotNode = function (callback) {\n this.recursivelyWalkNodesAndCallback([this.rootNode], callback, RecursionType.PivotNodes, 0);\n };\n // iterates through each item in memory, and calls the callback function\n // nodes - the rowNodes to traverse\n // callback - the user provided callback\n // recursion type - need this to know what child nodes to recurse, eg if looking at all nodes, or filtered notes etc\n // index - works similar to the index in forEach in javascript's array function\n ClientSideRowModel.prototype.recursivelyWalkNodesAndCallback = function (nodes, callback, recursionType, index) {\n if (!nodes) {\n return index;\n }\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n callback(node, index++);\n // go to the next level if it is a group\n if (node.hasChildren()) {\n // depending on the recursion type, we pick a difference set of children\n var nodeChildren = null;\n switch (recursionType) {\n case RecursionType.Normal:\n nodeChildren = node.childrenAfterGroup;\n break;\n case RecursionType.AfterFilter:\n nodeChildren = node.childrenAfterAggFilter;\n break;\n case RecursionType.AfterFilterAndSort:\n nodeChildren = node.childrenAfterSort;\n break;\n case RecursionType.PivotNodes:\n // for pivot, we don't go below leafGroup levels\n nodeChildren = !node.leafGroup ? node.childrenAfterSort : null;\n break;\n }\n if (nodeChildren) {\n index = this.recursivelyWalkNodesAndCallback(nodeChildren, callback, recursionType, index);\n }\n }\n }\n return index;\n };\n // it's possible to recompute the aggregate without doing the other parts\n // + gridApi.recomputeAggregates()\n ClientSideRowModel.prototype.doAggregate = function (changedPath) {\n if (this.aggregationStage) {\n this.aggregationStage.execute({ rowNode: this.rootNode, changedPath: changedPath });\n }\n };\n ClientSideRowModel.prototype.doFilterAggregates = function (changedPath) {\n if (this.filterAggregatesStage) {\n this.filterAggregatesStage.execute({ rowNode: this.rootNode, changedPath: changedPath });\n }\n else {\n // If filterAggregatesStage is undefined, then so is the grouping stage, so all children should be on the rootNode.\n this.rootNode.childrenAfterAggFilter = this.rootNode.childrenAfterFilter;\n }\n };\n // + gridApi.expandAll()\n // + gridApi.collapseAll()\n ClientSideRowModel.prototype.expandOrCollapseAll = function (expand) {\n var usingTreeData = this.gridOptionsWrapper.isTreeData();\n var usingPivotMode = this.columnModel.isPivotActive();\n var recursiveExpandOrCollapse = function (rowNodes) {\n if (!rowNodes) {\n return;\n }\n rowNodes.forEach(function (rowNode) {\n var actionRow = function () {\n rowNode.expanded = expand;\n recursiveExpandOrCollapse(rowNode.childrenAfterGroup);\n };\n if (usingTreeData) {\n var hasChildren = _.exists(rowNode.childrenAfterGroup);\n if (hasChildren) {\n actionRow();\n }\n return;\n }\n if (usingPivotMode) {\n var notLeafGroup = !rowNode.leafGroup;\n if (notLeafGroup) {\n actionRow();\n }\n return;\n }\n var isRowGroup = rowNode.group;\n if (isRowGroup) {\n actionRow();\n }\n });\n };\n if (this.rootNode) {\n recursiveExpandOrCollapse(this.rootNode.childrenAfterGroup);\n }\n this.refreshModel({ step: ClientSideRowModelSteps.MAP });\n var eventSource = expand ? 'expandAll' : 'collapseAll';\n var event = {\n type: Events.EVENT_EXPAND_COLLAPSE_ALL,\n source: eventSource\n };\n this.eventService.dispatchEvent(event);\n };\n ClientSideRowModel.prototype.doSort = function (rowNodeTransactions, changedPath) {\n this.sortStage.execute({\n rowNode: this.rootNode,\n rowNodeTransactions: rowNodeTransactions,\n changedPath: changedPath\n });\n };\n ClientSideRowModel.prototype.doRowGrouping = function (groupState, rowNodeTransactions, rowNodeOrder, changedPath, afterColumnsChanged) {\n if (this.groupStage) {\n if (rowNodeTransactions) {\n this.groupStage.execute({\n rowNode: this.rootNode,\n rowNodeTransactions: rowNodeTransactions,\n rowNodeOrder: rowNodeOrder,\n changedPath: changedPath\n });\n }\n else {\n this.groupStage.execute({\n rowNode: this.rootNode,\n changedPath: changedPath,\n afterColumnsChanged: afterColumnsChanged\n });\n // set open/closed state on groups\n this.restoreGroupState(groupState);\n }\n if (this.gridOptionsWrapper.isGroupSelectsChildren()) {\n this.selectionService.updateGroupsFromChildrenSelections(changedPath);\n }\n }\n else {\n this.rootNode.childrenAfterGroup = this.rootNode.allLeafChildren;\n if (this.rootNode.sibling) {\n this.rootNode.sibling.childrenAfterGroup = this.rootNode.childrenAfterGroup;\n }\n this.rootNode.updateHasChildren();\n }\n };\n ClientSideRowModel.prototype.restoreGroupState = function (groupState) {\n if (!groupState) {\n return;\n }\n _.traverseNodesWithKey(this.rootNode.childrenAfterGroup, function (node, key) {\n // if the group was open last time, then open it this time. however\n // if was not open last time, then don't touch the group, so the 'groupDefaultExpanded'\n // setting will take effect.\n if (typeof groupState[key] === 'boolean') {\n node.expanded = groupState[key];\n }\n });\n };\n ClientSideRowModel.prototype.doFilter = function (changedPath) {\n this.filterStage.execute({ rowNode: this.rootNode, changedPath: changedPath });\n };\n ClientSideRowModel.prototype.doPivot = function (changedPath) {\n if (this.pivotStage) {\n this.pivotStage.execute({ rowNode: this.rootNode, changedPath: changedPath });\n }\n };\n ClientSideRowModel.prototype.getGroupState = function () {\n if (!this.rootNode.childrenAfterGroup || !this.gridOptionsWrapper.isRememberGroupStateWhenNewData()) {\n return null;\n }\n var result = {};\n _.traverseNodesWithKey(this.rootNode.childrenAfterGroup, function (node, key) { return result[key] = node.expanded; });\n return result;\n };\n ClientSideRowModel.prototype.getCopyOfNodesMap = function () {\n return this.nodeManager.getCopyOfNodesMap();\n };\n ClientSideRowModel.prototype.getRowNode = function (id) {\n // although id is typed a string, this could be called by the user, and they could have passed a number\n var idIsGroup = typeof id == 'string' && id.indexOf(RowNode.ID_PREFIX_ROW_GROUP) == 0;\n if (idIsGroup) {\n // only one users complained about getRowNode not working for groups, after years of\n // this working for normal rows. so have done quick implementation. if users complain\n // about performance, then GroupStage should store / manage created groups in a map,\n // which is a chunk of work.\n var res_1 = undefined;\n this.forEachNode(function (node) {\n if (node.id === id) {\n res_1 = node;\n }\n });\n return res_1;\n }\n return this.nodeManager.getRowNode(id);\n };\n // rows: the rows to put into the model\n ClientSideRowModel.prototype.setRowData = function (rowData) {\n // no need to invalidate cache, as the cache is stored on the rowNode,\n // so new rowNodes means the cache is wiped anyway.\n // remember group state, so we can expand groups that should be expanded\n var groupState = this.getGroupState();\n this.nodeManager.setRowData(rowData);\n // - clears selection\n this.selectionService.reset();\n // - updates filters\n this.filterManager.onNewRowsLoaded('rowDataUpdated');\n // this event kicks off:\n // - shows 'no rows' overlay if needed\n var rowDataUpdatedEvent = {\n type: Events.EVENT_ROW_DATA_UPDATED\n };\n this.eventService.dispatchEvent(rowDataUpdatedEvent);\n this.refreshModel({\n step: ClientSideRowModelSteps.EVERYTHING,\n groupState: groupState,\n newData: true\n });\n };\n ClientSideRowModel.prototype.batchUpdateRowData = function (rowDataTransaction, callback) {\n var _this = this;\n if (this.applyAsyncTransactionsTimeout == null) {\n this.rowDataTransactionBatch = [];\n var waitMillis = this.gridOptionsWrapper.getAsyncTransactionWaitMillis();\n this.applyAsyncTransactionsTimeout = window.setTimeout(function () {\n _this.executeBatchUpdateRowData();\n }, waitMillis);\n }\n this.rowDataTransactionBatch.push({ rowDataTransaction: rowDataTransaction, callback: callback });\n };\n ClientSideRowModel.prototype.flushAsyncTransactions = function () {\n if (this.applyAsyncTransactionsTimeout != null) {\n clearTimeout(this.applyAsyncTransactionsTimeout);\n this.executeBatchUpdateRowData();\n }\n };\n ClientSideRowModel.prototype.executeBatchUpdateRowData = function () {\n var _this = this;\n this.valueCache.onDataChanged();\n var callbackFuncsBound = [];\n var rowNodeTrans = [];\n // The rowGroup stage uses rowNodeOrder if order was provided. if we didn't pass 'true' to\n // commonUpdateRowData, using addIndex would have no effect when grouping.\n var forceRowNodeOrder = false;\n if (this.rowDataTransactionBatch) {\n this.rowDataTransactionBatch.forEach(function (tranItem) {\n var rowNodeTran = _this.nodeManager.updateRowData(tranItem.rowDataTransaction, undefined);\n rowNodeTrans.push(rowNodeTran);\n if (tranItem.callback) {\n callbackFuncsBound.push(tranItem.callback.bind(null, rowNodeTran));\n }\n if (typeof tranItem.rowDataTransaction.addIndex === 'number') {\n forceRowNodeOrder = true;\n }\n });\n }\n this.commonUpdateRowData(rowNodeTrans, undefined, forceRowNodeOrder);\n // do callbacks in next VM turn so it's async\n if (callbackFuncsBound.length > 0) {\n window.setTimeout(function () {\n callbackFuncsBound.forEach(function (func) { return func(); });\n }, 0);\n }\n if (rowNodeTrans.length > 0) {\n var event_1 = {\n type: Events.EVENT_ASYNC_TRANSACTIONS_FLUSHED,\n results: rowNodeTrans\n };\n this.eventService.dispatchEvent(event_1);\n }\n this.rowDataTransactionBatch = null;\n this.applyAsyncTransactionsTimeout = undefined;\n };\n ClientSideRowModel.prototype.updateRowData = function (rowDataTran, rowNodeOrder) {\n this.valueCache.onDataChanged();\n var rowNodeTran = this.nodeManager.updateRowData(rowDataTran, rowNodeOrder);\n // if doing immutableData, addIndex is never present. however if doing standard transaction, and user\n // provided addIndex, then this is used in updateRowData. However if doing Enterprise, then the rowGroup\n // stage also uses the\n var forceRowNodeOrder = typeof rowDataTran.addIndex === 'number';\n this.commonUpdateRowData([rowNodeTran], rowNodeOrder, forceRowNodeOrder);\n return rowNodeTran;\n };\n ClientSideRowModel.prototype.createRowNodeOrder = function () {\n var suppressSortOrder = this.gridOptionsWrapper.isSuppressMaintainUnsortedOrder();\n if (suppressSortOrder) {\n return;\n }\n var orderMap = {};\n if (this.rootNode && this.rootNode.allLeafChildren) {\n for (var index = 0; index < this.rootNode.allLeafChildren.length; index++) {\n var node = this.rootNode.allLeafChildren[index];\n orderMap[node.id] = index;\n }\n }\n return orderMap;\n };\n // common to updateRowData and batchUpdateRowData\n ClientSideRowModel.prototype.commonUpdateRowData = function (rowNodeTrans, rowNodeOrder, forceRowNodeOrder) {\n var animate = !this.gridOptionsWrapper.isSuppressAnimationFrame();\n if (forceRowNodeOrder) {\n rowNodeOrder = this.createRowNodeOrder();\n }\n this.refreshModel({\n step: ClientSideRowModelSteps.EVERYTHING,\n rowNodeTransactions: rowNodeTrans,\n rowNodeOrder: rowNodeOrder,\n keepRenderedRows: true,\n keepEditingRows: true,\n animate: animate\n });\n // - updates filters\n this.filterManager.onNewRowsLoaded('rowDataUpdated');\n var event = {\n type: Events.EVENT_ROW_DATA_UPDATED\n };\n this.eventService.dispatchEvent(event);\n };\n ClientSideRowModel.prototype.doRowsToDisplay = function () {\n this.rowsToDisplay = this.flattenStage.execute({ rowNode: this.rootNode });\n };\n ClientSideRowModel.prototype.onRowHeightChanged = function () {\n this.refreshModel({ step: ClientSideRowModelSteps.MAP, keepRenderedRows: true, keepEditingRows: true, keepUndoRedoStack: true });\n };\n /** This method is debounced. It is used for row auto-height. If we don't debounce,\n * then the Row Models will end up recalculating each row position\n * for each row height change and result in the Row Renderer laying out rows.\n * This is particularly bad if using print layout, and showing eg 1,000 rows,\n * each row will change it's height, causing Row Model to update 1,000 times.\n */\n ClientSideRowModel.prototype.onRowHeightChangedDebounced = function () {\n this.onRowHeightChanged_debounced();\n };\n ClientSideRowModel.prototype.resetRowHeights = function () {\n var atLeastOne = false;\n this.forEachNode(function (rowNode) {\n rowNode.setRowHeight(rowNode.rowHeight, true);\n // we keep the height each row is at, however we set estimated=true rather than clear the height.\n // this means the grid will not reset the row heights back to defaults, rather it will re-calc\n // the height for each row as the row is displayed. otherwise the scroll will jump when heights are reset.\n var detailNode = rowNode.detailNode;\n if (detailNode) {\n detailNode.setRowHeight(detailNode.rowHeight, true);\n }\n atLeastOne = true;\n });\n if (atLeastOne) {\n this.onRowHeightChanged();\n }\n };\n __decorate$b([\n Autowired('columnModel')\n ], ClientSideRowModel.prototype, \"columnModel\", void 0);\n __decorate$b([\n Autowired('selectionService')\n ], ClientSideRowModel.prototype, \"selectionService\", void 0);\n __decorate$b([\n Autowired('filterManager')\n ], ClientSideRowModel.prototype, \"filterManager\", void 0);\n __decorate$b([\n Autowired('valueCache')\n ], ClientSideRowModel.prototype, \"valueCache\", void 0);\n __decorate$b([\n Autowired('beans')\n ], ClientSideRowModel.prototype, \"beans\", void 0);\n __decorate$b([\n Autowired('filterStage')\n ], ClientSideRowModel.prototype, \"filterStage\", void 0);\n __decorate$b([\n Autowired('sortStage')\n ], ClientSideRowModel.prototype, \"sortStage\", void 0);\n __decorate$b([\n Autowired('flattenStage')\n ], ClientSideRowModel.prototype, \"flattenStage\", void 0);\n __decorate$b([\n Optional('groupStage')\n ], ClientSideRowModel.prototype, \"groupStage\", void 0);\n __decorate$b([\n Optional('aggregationStage')\n ], ClientSideRowModel.prototype, \"aggregationStage\", void 0);\n __decorate$b([\n Optional('pivotStage')\n ], ClientSideRowModel.prototype, \"pivotStage\", void 0);\n __decorate$b([\n Optional('filterAggregatesStage')\n ], ClientSideRowModel.prototype, \"filterAggregatesStage\", void 0);\n __decorate$b([\n PostConstruct\n ], ClientSideRowModel.prototype, \"init\", null);\n ClientSideRowModel = __decorate$b([\n Bean('rowModel')\n ], ClientSideRowModel);\n return ClientSideRowModel;\n}(BeanStub));\n\nvar __extends$b = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$a = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar FilterStage = /** @class */ (function (_super) {\n __extends$b(FilterStage, _super);\n function FilterStage() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n FilterStage.prototype.execute = function (params) {\n var changedPath = params.changedPath;\n this.filterService.filter(changedPath);\n };\n __decorate$a([\n Autowired('filterService')\n ], FilterStage.prototype, \"filterService\", void 0);\n FilterStage = __decorate$a([\n Bean('filterStage')\n ], FilterStage);\n return FilterStage;\n}(BeanStub));\n\nvar __extends$a = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$9 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SortStage = /** @class */ (function (_super) {\n __extends$a(SortStage, _super);\n function SortStage() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SortStage.prototype.execute = function (params) {\n var _this = this;\n var sortOptions = this.sortController.getSortOptions();\n var sortActive = _.exists(sortOptions) && sortOptions.length > 0;\n var deltaSort = sortActive\n && _.exists(params.rowNodeTransactions)\n // in time we can remove this check, so that delta sort is always\n // on if transactions are present. it's off for now so that we can\n // selectively turn it on and test it with some select users before\n // rolling out to everyone.\n && this.gridOptionsWrapper.isDeltaSort();\n var sortContainsGroupColumns = sortOptions.some(function (opt) { return !!_this.columnModel.getGroupDisplayColumnForGroup(opt.column.getId()); });\n this.sortService.sort(sortOptions, sortActive, deltaSort, params.rowNodeTransactions, params.changedPath, sortContainsGroupColumns);\n };\n __decorate$9([\n Autowired('sortService')\n ], SortStage.prototype, \"sortService\", void 0);\n __decorate$9([\n Autowired('sortController')\n ], SortStage.prototype, \"sortController\", void 0);\n __decorate$9([\n Autowired('columnModel')\n ], SortStage.prototype, \"columnModel\", void 0);\n SortStage = __decorate$9([\n Bean('sortStage')\n ], SortStage);\n return SortStage;\n}(BeanStub));\n\nvar __extends$9 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$8 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar FlattenStage = /** @class */ (function (_super) {\n __extends$9(FlattenStage, _super);\n function FlattenStage() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n FlattenStage.prototype.execute = function (params) {\n var rootNode = params.rowNode;\n // even if not doing grouping, we do the mapping, as the client might\n // of passed in data that already has a grouping in it somewhere\n var result = [];\n // putting value into a wrapper so it's passed by reference\n var nextRowTop = { value: 0 };\n var skipLeafNodes = this.columnModel.isPivotMode();\n // if we are reducing, and not grouping, then we want to show the root node, as that\n // is where the pivot values are\n var showRootNode = skipLeafNodes && rootNode.leafGroup;\n var topList = showRootNode ? [rootNode] : rootNode.childrenAfterSort;\n this.recursivelyAddToRowsToDisplay(topList, result, nextRowTop, skipLeafNodes, 0);\n // we do not want the footer total if the gris is empty\n var atLeastOneRowPresent = result.length > 0;\n var includeGroupTotalFooter = !showRootNode\n // don't show total footer when showRootNode is true (i.e. in pivot mode and no groups)\n && atLeastOneRowPresent\n && this.gridOptionsWrapper.isGroupIncludeTotalFooter();\n if (includeGroupTotalFooter) {\n this.ensureFooterNodeExists(rootNode);\n this.addRowNodeToRowsToDisplay(rootNode.sibling, result, nextRowTop, 0);\n }\n return result;\n };\n FlattenStage.prototype.recursivelyAddToRowsToDisplay = function (rowsToFlatten, result, nextRowTop, skipLeafNodes, uiLevel) {\n if (_.missingOrEmpty(rowsToFlatten)) {\n return;\n }\n var hideOpenParents = this.gridOptionsWrapper.isGroupHideOpenParents();\n // these two are mutually exclusive, so if first set, we don't set the second\n var groupRemoveSingleChildren = this.gridOptionsWrapper.isGroupRemoveSingleChildren();\n var groupRemoveLowestSingleChildren = !groupRemoveSingleChildren && this.gridOptionsWrapper.isGroupRemoveLowestSingleChildren();\n for (var i = 0; i < rowsToFlatten.length; i++) {\n var rowNode = rowsToFlatten[i];\n // check all these cases, for working out if this row should be included in the final mapped list\n var isParent = rowNode.hasChildren();\n var isSkippedLeafNode = skipLeafNodes && !isParent;\n var isRemovedSingleChildrenGroup = groupRemoveSingleChildren &&\n isParent &&\n rowNode.childrenAfterGroup.length === 1;\n var isRemovedLowestSingleChildrenGroup = groupRemoveLowestSingleChildren &&\n isParent &&\n rowNode.leafGroup &&\n rowNode.childrenAfterGroup.length === 1;\n // hide open parents means when group is open, we don't show it. we also need to make sure the\n // group is expandable in the first place (as leaf groups are not expandable if pivot mode is on).\n // the UI will never allow expanding leaf groups, however the user might via the API (or menu option 'expand all')\n var neverAllowToExpand = skipLeafNodes && rowNode.leafGroup;\n var isHiddenOpenParent = hideOpenParents && rowNode.expanded && !rowNode.master && (!neverAllowToExpand);\n var thisRowShouldBeRendered = !isSkippedLeafNode && !isHiddenOpenParent &&\n !isRemovedSingleChildrenGroup && !isRemovedLowestSingleChildrenGroup;\n if (thisRowShouldBeRendered) {\n this.addRowNodeToRowsToDisplay(rowNode, result, nextRowTop, uiLevel);\n }\n // if we are pivoting, we never map below the leaf group\n if (skipLeafNodes && rowNode.leafGroup) {\n continue;\n }\n if (isParent) {\n var excludedParent = isRemovedSingleChildrenGroup || isRemovedLowestSingleChildrenGroup;\n // we traverse the group if it is expended, however we always traverse if the parent node\n // was removed (as the group will never be opened if it is not displayed, we show the children instead)\n if (rowNode.expanded || excludedParent) {\n // if the parent was excluded, then ui level is that of the parent\n var uiLevelForChildren = excludedParent ? uiLevel : uiLevel + 1;\n this.recursivelyAddToRowsToDisplay(rowNode.childrenAfterSort, result, nextRowTop, skipLeafNodes, uiLevelForChildren);\n // put a footer in if user is looking for it\n if (this.gridOptionsWrapper.isGroupIncludeFooter()) {\n this.ensureFooterNodeExists(rowNode);\n this.addRowNodeToRowsToDisplay(rowNode.sibling, result, nextRowTop, uiLevel);\n }\n }\n }\n else if (rowNode.master && rowNode.expanded) {\n var detailNode = this.createDetailNode(rowNode);\n this.addRowNodeToRowsToDisplay(detailNode, result, nextRowTop, uiLevel);\n }\n }\n };\n // duplicated method, it's also in floatingRowModel\n FlattenStage.prototype.addRowNodeToRowsToDisplay = function (rowNode, result, nextRowTop, uiLevel) {\n var isGroupMultiAutoColumn = this.gridOptionsWrapper.isGroupMultiAutoColumn();\n result.push(rowNode);\n rowNode.setUiLevel(isGroupMultiAutoColumn ? 0 : uiLevel);\n };\n FlattenStage.prototype.ensureFooterNodeExists = function (groupNode) {\n // only create footer node once, otherwise we have daemons and\n // the animate screws up with the daemons hanging around\n if (_.exists(groupNode.sibling)) {\n return;\n }\n var footerNode = new RowNode(this.beans);\n Object.keys(groupNode).forEach(function (key) {\n footerNode[key] = groupNode[key];\n });\n footerNode.footer = true;\n footerNode.setRowTop(null);\n footerNode.setRowIndex(null);\n // manually set oldRowTop to null so we discard any\n // previous information about its position.\n footerNode.oldRowTop = null;\n if (_.exists(footerNode.id)) {\n footerNode.id = 'rowGroupFooter_' + footerNode.id;\n }\n // get both header and footer to reference each other as siblings. this is never undone,\n // only overwritten. so if a group is expanded, then contracted, it will have a ghost\n // sibling - but that's fine, as we can ignore this if the header is contracted.\n footerNode.sibling = groupNode;\n groupNode.sibling = footerNode;\n };\n FlattenStage.prototype.createDetailNode = function (masterNode) {\n if (_.exists(masterNode.detailNode)) {\n return masterNode.detailNode;\n }\n var detailNode = new RowNode(this.beans);\n detailNode.detail = true;\n detailNode.selectable = false;\n detailNode.parent = masterNode;\n if (_.exists(masterNode.id)) {\n detailNode.id = 'detail_' + masterNode.id;\n }\n detailNode.data = masterNode.data;\n detailNode.level = masterNode.level + 1;\n masterNode.detailNode = detailNode;\n return detailNode;\n };\n __decorate$8([\n Autowired('columnModel')\n ], FlattenStage.prototype, \"columnModel\", void 0);\n __decorate$8([\n Autowired('beans')\n ], FlattenStage.prototype, \"beans\", void 0);\n FlattenStage = __decorate$8([\n Bean('flattenStage')\n ], FlattenStage);\n return FlattenStage;\n}(BeanStub));\n\nvar __extends$8 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$7 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar SortService = /** @class */ (function (_super) {\n __extends$8(SortService, _super);\n function SortService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n SortService.prototype.init = function () {\n this.postSortFunc = this.gridOptionsWrapper.getPostSortFunc();\n };\n SortService.prototype.sort = function (sortOptions, sortActive, useDeltaSort, rowNodeTransactions, changedPath, sortContainsGroupColumns) {\n var _this = this;\n var groupMaintainOrder = this.gridOptionsWrapper.isGroupMaintainOrder();\n var groupColumnsPresent = this.columnModel.getAllGridColumns().some(function (c) { return c.isRowGroupActive(); });\n var allDirtyNodes = {};\n if (useDeltaSort && rowNodeTransactions) {\n allDirtyNodes = this.calculateDirtyNodes(rowNodeTransactions);\n }\n var isPivotMode = this.columnModel.isPivotMode();\n var callback = function (rowNode) {\n // we clear out the 'pull down open parents' first, as the values mix up the sorting\n _this.pullDownGroupDataForHideOpenParents(rowNode.childrenAfterAggFilter, true);\n // It's pointless to sort rows which aren't being displayed. in pivot mode we don't need to sort the leaf group children.\n var skipSortingPivotLeafs = isPivotMode && rowNode.leafGroup;\n // Javascript sort is non deterministic when all the array items are equals, ie Comparator always returns 0,\n // so to ensure the array keeps its order, add an additional sorting condition manually, in this case we\n // are going to inspect the original array position. This is what sortedRowNodes is for.\n var skipSortingGroups = groupMaintainOrder && groupColumnsPresent && !rowNode.leafGroup && !sortContainsGroupColumns;\n if (!sortActive || skipSortingGroups || skipSortingPivotLeafs) {\n // when 'groupMaintainOrder' is enabled we skip sorting groups unless we are sorting on group columns\n var childrenToBeSorted = rowNode.childrenAfterAggFilter.slice(0);\n if (groupMaintainOrder && rowNode.childrenAfterSort) {\n var indexedOrders_1 = rowNode.childrenAfterSort.reduce(function (acc, row, idx) {\n acc[row.id] = idx;\n return acc;\n }, {});\n childrenToBeSorted.sort(function (row1, row2) { return (indexedOrders_1[row1.id] || 0) - (indexedOrders_1[row2.id] || 0); });\n }\n rowNode.childrenAfterSort = childrenToBeSorted;\n }\n else if (useDeltaSort) {\n rowNode.childrenAfterSort = _this.doDeltaSort(rowNode, allDirtyNodes, changedPath, sortOptions);\n }\n else {\n rowNode.childrenAfterSort = _this.rowNodeSorter.doFullSort(rowNode.childrenAfterAggFilter, sortOptions);\n }\n if (rowNode.sibling) {\n rowNode.sibling.childrenAfterSort = rowNode.childrenAfterSort;\n }\n _this.updateChildIndexes(rowNode);\n if (_this.postSortFunc) {\n var params = { nodes: rowNode.childrenAfterSort };\n _this.postSortFunc(params);\n }\n };\n if (changedPath) {\n changedPath.forEachChangedNodeDepthFirst(callback);\n }\n this.updateGroupDataForHideOpenParents(changedPath);\n };\n SortService.prototype.calculateDirtyNodes = function (rowNodeTransactions) {\n var dirtyNodes = {};\n var addNodesFunc = function (rowNodes) {\n if (rowNodes) {\n rowNodes.forEach(function (rowNode) { return dirtyNodes[rowNode.id] = true; });\n }\n };\n // all leaf level nodes in the transaction were impacted\n if (rowNodeTransactions) {\n rowNodeTransactions.forEach(function (tran) {\n addNodesFunc(tran.add);\n addNodesFunc(tran.update);\n addNodesFunc(tran.remove);\n });\n }\n return dirtyNodes;\n };\n SortService.prototype.doDeltaSort = function (rowNode, allTouchedNodes, changedPath, sortOptions) {\n var _this = this;\n var unsortedRows = rowNode.childrenAfterAggFilter;\n var oldSortedRows = rowNode.childrenAfterSort;\n if (!oldSortedRows) {\n return this.rowNodeSorter.doFullSort(unsortedRows, sortOptions);\n }\n var untouchedRowsMap = {};\n var touchedRows = [];\n unsortedRows.forEach(function (row) {\n if (allTouchedNodes[row.id] || !changedPath.canSkip(row)) {\n touchedRows.push(row);\n }\n else {\n untouchedRowsMap[row.id] = true;\n }\n });\n var sortedUntouchedRows = oldSortedRows.filter(function (child) { return untouchedRowsMap[child.id]; });\n var mapNodeToSortedNode = function (rowNode, pos) { return ({ currentPos: pos, rowNode: rowNode }); };\n var sortedChangedRows = touchedRows\n .map(mapNodeToSortedNode)\n .sort(function (a, b) { return _this.rowNodeSorter.compareRowNodes(sortOptions, a, b); });\n return this.mergeSortedArrays(sortOptions, sortedChangedRows, sortedUntouchedRows.map(mapNodeToSortedNode)).map(function (_a) {\n var rowNode = _a.rowNode;\n return rowNode;\n });\n };\n // Merge two sorted arrays into each other\n SortService.prototype.mergeSortedArrays = function (sortOptions, arr1, arr2) {\n var res = [];\n var i = 0;\n var j = 0;\n // Traverse both array, adding them in order\n while (i < arr1.length && j < arr2.length) {\n // Check if current element of first\n // array is smaller than current element\n // of second array. If yes, store first\n // array element and increment first array\n // index. Otherwise do same with second array\n var compareResult = this.rowNodeSorter.compareRowNodes(sortOptions, arr1[i], arr2[j]);\n if (compareResult < 0) {\n res.push(arr1[i++]);\n }\n else {\n res.push(arr2[j++]);\n }\n }\n // add remaining from arr1\n while (i < arr1.length) {\n res.push(arr1[i++]);\n }\n // add remaining from arr2\n while (j < arr2.length) {\n res.push(arr2[j++]);\n }\n return res;\n };\n SortService.prototype.updateChildIndexes = function (rowNode) {\n if (_.missing(rowNode.childrenAfterSort)) {\n return;\n }\n var listToSort = rowNode.childrenAfterSort;\n for (var i = 0; i < listToSort.length; i++) {\n var child = listToSort[i];\n var firstChild = i === 0;\n var lastChild = i === rowNode.childrenAfterSort.length - 1;\n child.setFirstChild(firstChild);\n child.setLastChild(lastChild);\n child.setChildIndex(i);\n }\n };\n SortService.prototype.updateGroupDataForHideOpenParents = function (changedPath) {\n var _this = this;\n if (!this.gridOptionsWrapper.isGroupHideOpenParents()) {\n return;\n }\n if (this.gridOptionsWrapper.isTreeData()) {\n var msg_1 = \"AG Grid: The property hideOpenParents dose not work with Tree Data. This is because Tree Data has values at the group level, it doesn't make sense to hide them (as opposed to Row Grouping, which only has Aggregated Values at the group level).\";\n _.doOnce(function () { return console.warn(msg_1); }, 'sortService.hideOpenParentsWithTreeData');\n return false;\n }\n // recurse breadth first over group nodes after sort to 'pull down' group data to child groups\n var callback = function (rowNode) {\n _this.pullDownGroupDataForHideOpenParents(rowNode.childrenAfterSort, false);\n rowNode.childrenAfterSort.forEach(function (child) {\n if (child.hasChildren()) {\n callback(child);\n }\n });\n };\n if (changedPath) {\n changedPath.executeFromRootNode(function (rowNode) { return callback(rowNode); });\n }\n };\n SortService.prototype.pullDownGroupDataForHideOpenParents = function (rowNodes, clearOperation) {\n var _this = this;\n if (!this.gridOptionsWrapper.isGroupHideOpenParents() || _.missing(rowNodes)) {\n return;\n }\n rowNodes.forEach(function (childRowNode) {\n var groupDisplayCols = _this.columnModel.getGroupDisplayColumns();\n groupDisplayCols.forEach(function (groupDisplayCol) {\n var showRowGroup = groupDisplayCol.getColDef().showRowGroup;\n if (typeof showRowGroup !== 'string') {\n console.error('AG Grid: groupHideOpenParents only works when specifying specific columns for colDef.showRowGroup');\n return;\n }\n var displayingGroupKey = showRowGroup;\n var rowGroupColumn = _this.columnModel.getPrimaryColumn(displayingGroupKey);\n var thisRowNodeMatches = rowGroupColumn === childRowNode.rowGroupColumn;\n if (thisRowNodeMatches) {\n return;\n }\n if (clearOperation) {\n // if doing a clear operation, we clear down the value for every possible group column\n childRowNode.setGroupValue(groupDisplayCol.getId(), undefined);\n }\n else {\n // if doing a set operation, we set only where the pull down is to occur\n var parentToStealFrom = childRowNode.getFirstChildOfFirstChild(rowGroupColumn);\n if (parentToStealFrom) {\n childRowNode.setGroupValue(groupDisplayCol.getId(), parentToStealFrom.key);\n }\n }\n });\n });\n };\n __decorate$7([\n Autowired('columnModel')\n ], SortService.prototype, \"columnModel\", void 0);\n __decorate$7([\n Autowired('rowNodeSorter')\n ], SortService.prototype, \"rowNodeSorter\", void 0);\n __decorate$7([\n PostConstruct\n ], SortService.prototype, \"init\", null);\n SortService = __decorate$7([\n Bean('sortService')\n ], SortService);\n return SortService;\n}(BeanStub));\n\nvar __extends$7 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$6 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar FilterService = /** @class */ (function (_super) {\n __extends$7(FilterService, _super);\n function FilterService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n FilterService.prototype.filter = function (changedPath) {\n var filterActive = this.filterManager.isColumnFilterPresent()\n || this.filterManager.isQuickFilterPresent()\n || this.filterManager.isExternalFilterPresent();\n this.filterNodes(filterActive, changedPath);\n };\n FilterService.prototype.filterNodes = function (filterActive, changedPath) {\n var _this = this;\n var filterCallback = function (rowNode, includeChildNodes) {\n // recursively get all children that are groups to also filter\n if (rowNode.hasChildren()) {\n // result of filter for this node. when filtering tree data, includeChildNodes = true when parent passes\n if (filterActive && !includeChildNodes) {\n rowNode.childrenAfterFilter = rowNode.childrenAfterGroup.filter(function (childNode) {\n // a group is included in the result if it has any children of it's own.\n // by this stage, the child groups are already filtered\n var passBecauseChildren = childNode.childrenAfterFilter && childNode.childrenAfterFilter.length > 0;\n // both leaf level nodes and tree data nodes have data. these get added if\n // the data passes the filter\n var passBecauseDataPasses = childNode.data\n && _this.filterManager.doesRowPassFilter({ rowNode: childNode });\n // note - tree data nodes pass either if a) they pass themselves or b) any children of that node pass\n return passBecauseChildren || passBecauseDataPasses;\n });\n }\n else {\n // if not filtering, the result is the original list\n rowNode.childrenAfterFilter = rowNode.childrenAfterGroup;\n }\n }\n else {\n rowNode.childrenAfterFilter = rowNode.childrenAfterGroup;\n }\n if (rowNode.sibling) {\n rowNode.sibling.childrenAfterFilter = rowNode.childrenAfterFilter;\n }\n };\n if (this.doingTreeDataFiltering()) {\n var treeDataDepthFirstFilter_1 = function (rowNode, alreadyFoundInParent) {\n // tree data filter traverses the hierarchy depth first and includes child nodes if parent passes\n // filter, and parent nodes will be include if any children exist.\n if (rowNode.childrenAfterGroup) {\n for (var i = 0; i < rowNode.childrenAfterGroup.length; i++) {\n var childNode = rowNode.childrenAfterGroup[i];\n // first check if current node passes filter before invoking child nodes\n var foundInParent = alreadyFoundInParent\n || _this.filterManager.doesRowPassFilter({ rowNode: childNode });\n if (childNode.childrenAfterGroup) {\n treeDataDepthFirstFilter_1(rowNode.childrenAfterGroup[i], foundInParent);\n }\n else {\n filterCallback(childNode, foundInParent);\n }\n }\n }\n filterCallback(rowNode, alreadyFoundInParent);\n };\n var treeDataFilterCallback = function (rowNode) { return treeDataDepthFirstFilter_1(rowNode, false); };\n changedPath.executeFromRootNode(treeDataFilterCallback);\n }\n else {\n var defaultFilterCallback = function (rowNode) { return filterCallback(rowNode, false); };\n changedPath.forEachChangedNodeDepthFirst(defaultFilterCallback, true);\n }\n };\n FilterService.prototype.doingTreeDataFiltering = function () {\n return this.gridOptionsWrapper.isTreeData() && !this.gridOptionsWrapper.isExcludeChildrenWhenTreeDataFiltering();\n };\n __decorate$6([\n Autowired('filterManager')\n ], FilterService.prototype, \"filterManager\", void 0);\n FilterService = __decorate$6([\n Bean(\"filterService\")\n ], FilterService);\n return FilterService;\n}(BeanStub));\n\nvar __extends$6 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$5 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __read = (undefined && undefined.__read) || function (o, n) {\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\n if (!m) return o;\n var i = m.call(o), r, ar = [], e;\n try {\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\n }\n catch (error) { e = { error: error }; }\n finally {\n try {\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\n }\n finally { if (e) throw e.error; }\n }\n return ar;\n};\nvar ImmutableService = /** @class */ (function (_super) {\n __extends$6(ImmutableService, _super);\n function ImmutableService() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n ImmutableService.prototype.postConstruct = function () {\n if (this.rowModel.getType() === Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {\n this.clientSideRowModel = this.rowModel;\n }\n };\n ImmutableService.prototype.isActive = function () {\n return this.gridOptionsWrapper.isImmutableData();\n };\n ImmutableService.prototype.setRowData = function (rowData) {\n var transactionAndMap = this.createTransactionForRowData(rowData);\n if (!transactionAndMap) {\n return;\n }\n var _a = __read(transactionAndMap, 2), transaction = _a[0], orderIdMap = _a[1];\n var nodeTransaction = this.clientSideRowModel.updateRowData(transaction, orderIdMap);\n // need to force updating of full width rows - note this wouldn't be necessary the full width cell comp listened\n // to the data change event on the row node and refreshed itself.\n if (nodeTransaction) {\n this.rowRenderer.refreshFullWidthRows(nodeTransaction.update);\n }\n };\n // converts the setRowData() command to a transaction\n ImmutableService.prototype.createTransactionForRowData = function (rowData) {\n if (_.missing(this.clientSideRowModel)) {\n console.error('AG Grid: ImmutableService only works with ClientSideRowModel');\n return;\n }\n var getRowIdFunc = this.gridOptionsWrapper.getRowIdFunc();\n if (getRowIdFunc == null) {\n console.error('AG Grid: ImmutableService requires getRowId() callback to be implemented, your row data needs IDs!');\n return;\n }\n // convert the data into a transaction object by working out adds, removes and updates\n var transaction = {\n remove: [],\n update: [],\n add: []\n };\n var existingNodesMap = this.clientSideRowModel.getCopyOfNodesMap();\n var suppressSortOrder = this.gridOptionsWrapper.isSuppressMaintainUnsortedOrder();\n var orderMap = suppressSortOrder ? undefined : {};\n if (_.exists(rowData)) {\n // split all the new data in the following:\n // if new, push to 'add'\n // if update, push to 'update'\n // if not changed, do not include in the transaction\n rowData.forEach(function (data, index) {\n var id = getRowIdFunc({ data: data, level: 0 });\n var existingNode = existingNodesMap[id];\n if (orderMap) {\n orderMap[id] = index;\n }\n if (existingNode) {\n var dataHasChanged = existingNode.data !== data;\n if (dataHasChanged) {\n transaction.update.push(data);\n }\n // otherwise, if data not changed, we just don't include it anywhere, as it's not a delta\n // remove from list, so we know the item is not to be removed\n existingNodesMap[id] = undefined;\n }\n else {\n transaction.add.push(data);\n }\n });\n }\n // at this point, all rows that are left, should be removed\n _.iterateObject(existingNodesMap, function (id, rowNode) {\n if (rowNode) {\n transaction.remove.push(rowNode.data);\n }\n });\n return [transaction, orderMap];\n };\n __decorate$5([\n Autowired('rowModel')\n ], ImmutableService.prototype, \"rowModel\", void 0);\n __decorate$5([\n Autowired('rowRenderer')\n ], ImmutableService.prototype, \"rowRenderer\", void 0);\n __decorate$5([\n Autowired('columnApi')\n ], ImmutableService.prototype, \"columnApi\", void 0);\n __decorate$5([\n Autowired('gridApi')\n ], ImmutableService.prototype, \"gridApi\", void 0);\n __decorate$5([\n Autowired('filterManager')\n ], ImmutableService.prototype, \"filterManager\", void 0);\n __decorate$5([\n PostConstruct\n ], ImmutableService.prototype, \"postConstruct\", null);\n ImmutableService = __decorate$5([\n Bean('immutableService')\n ], ImmutableService);\n return ImmutableService;\n}(BeanStub));\n\nvar ClientSideRowModelModule = {\n moduleName: ModuleNames.ClientSideRowModelModule,\n beans: [FilterStage, SortStage, FlattenStage, SortService, FilterService, ImmutableService],\n rowModels: { clientSide: ClientSideRowModel }\n};\n\nvar __extends$5 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar InfiniteBlock = /** @class */ (function (_super) {\n __extends$5(InfiniteBlock, _super);\n function InfiniteBlock(id, parentCache, params) {\n var _this = _super.call(this, id) || this;\n _this.parentCache = parentCache;\n _this.params = params;\n // we don't need to calculate these now, as the inputs don't change,\n // however it makes the code easier to read if we work them out up front\n _this.startRow = id * params.blockSize;\n _this.endRow = _this.startRow + params.blockSize;\n return _this;\n }\n InfiniteBlock.prototype.postConstruct = function () {\n this.createRowNodes();\n };\n InfiniteBlock.prototype.getBlockStateJson = function () {\n return {\n id: '' + this.getId(),\n state: {\n blockNumber: this.getId(),\n startRow: this.getStartRow(),\n endRow: this.getEndRow(),\n pageStatus: this.getState()\n }\n };\n };\n InfiniteBlock.prototype.setDataAndId = function (rowNode, data, index) {\n // if there's no id and the rowNode was rendered before, it means this\n // was a placeholder rowNode and should not be recycled. Setting\n // `alreadyRendered` to `false` forces the rowRenderer to flush it.\n if (!rowNode.id && rowNode.alreadyRendered) {\n rowNode.alreadyRendered = false;\n }\n if (_.exists(data)) {\n // this means if the user is not providing id's we just use the\n // index for the row. this will allow selection to work (that is based\n // on index) as long user is not inserting or deleting rows,\n // or wanting to keep selection between server side sorting or filtering\n rowNode.setDataAndId(data, index.toString());\n }\n else {\n rowNode.setDataAndId(undefined, undefined);\n }\n };\n InfiniteBlock.prototype.loadFromDatasource = function () {\n var _this = this;\n var params = this.createLoadParams();\n if (_.missing(this.params.datasource.getRows)) {\n console.warn(\"AG Grid: datasource is missing getRows method\");\n return;\n }\n // put in timeout, to force result to be async\n window.setTimeout(function () {\n _this.params.datasource.getRows(params);\n }, 0);\n };\n InfiniteBlock.prototype.processServerFail = function () {\n // todo - this method has better handling in SSRM\n };\n InfiniteBlock.prototype.createLoadParams = function () {\n // PROBLEM . . . . when the user sets sort via colDef.sort, then this code\n // is executing before the sort is set up, so server is not getting the sort\n // model. need to change with regards order - so the server side request is\n // AFTER thus it gets the right sort model.\n var params = {\n startRow: this.getStartRow(),\n endRow: this.getEndRow(),\n successCallback: this.pageLoaded.bind(this, this.getVersion()),\n failCallback: this.pageLoadFailed.bind(this, this.getVersion()),\n sortModel: this.params.sortModel,\n filterModel: this.params.filterModel,\n context: this.gridOptionsWrapper.getContext()\n };\n return params;\n };\n InfiniteBlock.prototype.forEachNode = function (callback, sequence, rowCount) {\n var _this = this;\n this.rowNodes.forEach(function (rowNode, index) {\n var rowIndex = _this.startRow + index;\n if (rowIndex < rowCount) {\n callback(rowNode, sequence.next());\n }\n });\n };\n InfiniteBlock.prototype.getLastAccessed = function () {\n return this.lastAccessed;\n };\n InfiniteBlock.prototype.getRow = function (rowIndex, dontTouchLastAccessed) {\n if (dontTouchLastAccessed === void 0) { dontTouchLastAccessed = false; }\n if (!dontTouchLastAccessed) {\n this.lastAccessed = this.params.lastAccessedSequence.next();\n }\n var localIndex = rowIndex - this.startRow;\n return this.rowNodes[localIndex];\n };\n InfiniteBlock.prototype.getStartRow = function () {\n return this.startRow;\n };\n InfiniteBlock.prototype.getEndRow = function () {\n return this.endRow;\n };\n // creates empty row nodes, data is missing as not loaded yet\n InfiniteBlock.prototype.createRowNodes = function () {\n this.rowNodes = [];\n for (var i = 0; i < this.params.blockSize; i++) {\n var rowIndex = this.startRow + i;\n var rowNode = new RowNode(this.beans);\n rowNode.setRowHeight(this.params.rowHeight);\n rowNode.uiLevel = 0;\n rowNode.setRowIndex(rowIndex);\n rowNode.setRowTop(this.params.rowHeight * rowIndex);\n this.rowNodes.push(rowNode);\n }\n };\n InfiniteBlock.prototype.processServerResult = function (params) {\n var _this = this;\n this.rowNodes.forEach(function (rowNode, index) {\n var data = params.rowData ? params.rowData[index] : undefined;\n _this.setDataAndId(rowNode, data, _this.startRow + index);\n });\n var finalRowCount = params.rowCount != null && params.rowCount >= 0 ? params.rowCount : undefined;\n this.parentCache.pageLoaded(this, finalRowCount);\n };\n InfiniteBlock.prototype.destroyRowNodes = function () {\n this.rowNodes.forEach(function (rowNode) {\n // this is needed, so row render knows to fade out the row, otherwise it\n // sees row top is present, and thinks the row should be shown.\n rowNode.clearRowTopAndRowIndex();\n });\n };\n __decorate$4([\n Autowired('beans')\n ], InfiniteBlock.prototype, \"beans\", void 0);\n __decorate$4([\n PostConstruct\n ], InfiniteBlock.prototype, \"postConstruct\", null);\n __decorate$4([\n PreDestroy\n ], InfiniteBlock.prototype, \"destroyRowNodes\", null);\n return InfiniteBlock;\n}(RowNodeBlock));\n\nvar __extends$4 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __param = (undefined && undefined.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n};\nvar InfiniteCache = /** @class */ (function (_super) {\n __extends$4(InfiniteCache, _super);\n function InfiniteCache(params) {\n var _this = _super.call(this) || this;\n _this.lastRowIndexKnown = false;\n _this.blocks = {};\n _this.blockCount = 0;\n _this.rowCount = params.initialRowCount;\n _this.params = params;\n return _this;\n }\n InfiniteCache.prototype.setBeans = function (loggerFactory) {\n this.logger = loggerFactory.create('InfiniteCache');\n };\n // the rowRenderer will not pass dontCreatePage, meaning when rendering the grid,\n // it will want new pages in the cache as it asks for rows. only when we are inserting /\n // removing rows via the api is dontCreatePage set, where we move rows between the pages.\n InfiniteCache.prototype.getRow = function (rowIndex, dontCreatePage) {\n if (dontCreatePage === void 0) { dontCreatePage = false; }\n var blockId = Math.floor(rowIndex / this.params.blockSize);\n var block = this.blocks[blockId];\n if (!block) {\n if (dontCreatePage) {\n return undefined;\n }\n block = this.createBlock(blockId);\n }\n return block.getRow(rowIndex);\n };\n InfiniteCache.prototype.createBlock = function (blockNumber) {\n var newBlock = this.createBean(new InfiniteBlock(blockNumber, this, this.params));\n this.blocks[newBlock.getId()] = newBlock;\n this.blockCount++;\n this.purgeBlocksIfNeeded(newBlock);\n this.params.rowNodeBlockLoader.addBlock(newBlock);\n return newBlock;\n };\n // we have this on infinite row model only, not server side row model,\n // because for server side, it would leave the children in inconsistent\n // state - eg if a node had children, but after the refresh it had data\n // for a different row, then the children would be with the wrong row node.\n InfiniteCache.prototype.refreshCache = function () {\n var nothingToRefresh = this.blockCount == 0;\n if (nothingToRefresh) {\n this.purgeCache();\n return;\n }\n this.getBlocksInOrder().forEach(function (block) { return block.setStateWaitingToLoad(); });\n this.params.rowNodeBlockLoader.checkBlockToLoad();\n };\n InfiniteCache.prototype.destroyAllBlocks = function () {\n var _this = this;\n this.getBlocksInOrder().forEach(function (block) { return _this.destroyBlock(block); });\n };\n InfiniteCache.prototype.getRowCount = function () {\n return this.rowCount;\n };\n InfiniteCache.prototype.isLastRowIndexKnown = function () {\n return this.lastRowIndexKnown;\n };\n // block calls this, when page loaded\n InfiniteCache.prototype.pageLoaded = function (block, lastRow) {\n // if we are not active, then we ignore all events, otherwise we could end up getting the\n // grid to refresh even though we are no longer the active cache\n if (!this.isAlive()) {\n return;\n }\n this.logger.log(\"onPageLoaded: page = \" + block.getId() + \", lastRow = \" + lastRow);\n this.checkRowCount(block, lastRow);\n // we fire cacheUpdated even if the row count has not changed, as some items need updating even\n // if no new rows to render. for example the pagination panel has '?' as the total rows when loading\n // is underway, which would need to get updated when loading finishes.\n this.onCacheUpdated();\n };\n InfiniteCache.prototype.purgeBlocksIfNeeded = function (blockToExclude) {\n var _this = this;\n // we exclude checking for the page just created, as this has yet to be accessed and hence\n // the lastAccessed stamp will not be updated for the first time yet\n var blocksForPurging = this.getBlocksInOrder().filter(function (b) { return b != blockToExclude; });\n var lastAccessedComparator = function (a, b) { return b.getLastAccessed() - a.getLastAccessed(); };\n blocksForPurging.sort(lastAccessedComparator);\n // we remove (maxBlocksInCache - 1) as we already excluded the 'just created' page.\n // in other words, after the splice operation below, we have taken out the blocks\n // we want to keep, which means we are left with blocks that we can potentially purge\n var maxBlocksProvided = this.params.maxBlocksInCache > 0;\n var blocksToKeep = maxBlocksProvided ? this.params.maxBlocksInCache - 1 : null;\n var emptyBlocksToKeep = InfiniteCache.MAX_EMPTY_BLOCKS_TO_KEEP - 1;\n blocksForPurging.forEach(function (block, index) {\n var purgeBecauseBlockEmpty = block.getState() === InfiniteBlock.STATE_WAITING_TO_LOAD && index >= emptyBlocksToKeep;\n var purgeBecauseCacheFull = maxBlocksProvided ? index >= blocksToKeep : false;\n if (purgeBecauseBlockEmpty || purgeBecauseCacheFull) {\n // if the block currently has rows been displayed, then don't remove it either.\n // this can happen if user has maxBlocks=2, and blockSize=5 (thus 10 max rows in cache)\n // but the screen is showing 20 rows, so at least 4 blocks are needed.\n if (_this.isBlockCurrentlyDisplayed(block)) {\n return;\n }\n // don't want to loose keyboard focus, so keyboard navigation can continue. so keep focused blocks.\n if (_this.isBlockFocused(block)) {\n return;\n }\n // at this point, block is not needed, so burn baby burn\n _this.removeBlockFromCache(block);\n }\n });\n };\n InfiniteCache.prototype.isBlockFocused = function (block) {\n var focusedCell = this.focusService.getFocusCellToUseAfterRefresh();\n if (!focusedCell) {\n return false;\n }\n if (focusedCell.rowPinned != null) {\n return false;\n }\n var blockIndexStart = block.getStartRow();\n var blockIndexEnd = block.getEndRow();\n var hasFocus = focusedCell.rowIndex >= blockIndexStart && focusedCell.rowIndex < blockIndexEnd;\n return hasFocus;\n };\n InfiniteCache.prototype.isBlockCurrentlyDisplayed = function (block) {\n var startIndex = block.getStartRow();\n var endIndex = block.getEndRow() - 1;\n return this.rowRenderer.isRangeInRenderedViewport(startIndex, endIndex);\n };\n InfiniteCache.prototype.removeBlockFromCache = function (blockToRemove) {\n if (!blockToRemove) {\n return;\n }\n this.destroyBlock(blockToRemove);\n // we do not want to remove the 'loaded' event listener, as the\n // concurrent loads count needs to be updated when the load is complete\n // if the purged page is in loading state\n };\n InfiniteCache.prototype.checkRowCount = function (block, lastRow) {\n // if client provided a last row, we always use it, as it could change between server calls\n // if user deleted data and then called refresh on the grid.\n if (typeof lastRow === 'number' && lastRow >= 0) {\n this.rowCount = lastRow;\n this.lastRowIndexKnown = true;\n }\n else if (!this.lastRowIndexKnown) {\n // otherwise, see if we need to add some virtual rows\n var lastRowIndex = (block.getId() + 1) * this.params.blockSize;\n var lastRowIndexPlusOverflow = lastRowIndex + this.params.overflowSize;\n if (this.rowCount < lastRowIndexPlusOverflow) {\n this.rowCount = lastRowIndexPlusOverflow;\n }\n }\n };\n InfiniteCache.prototype.setRowCount = function (rowCount, lastRowIndexKnown) {\n this.rowCount = rowCount;\n // if undefined is passed, we do not set this value, if one of {true,false}\n // is passed, we do set the value.\n if (_.exists(lastRowIndexKnown)) {\n this.lastRowIndexKnown = lastRowIndexKnown;\n }\n // if we are still searching, then the row count must not end at the end\n // of a particular page, otherwise the searching will not pop into the\n // next page\n if (!this.lastRowIndexKnown) {\n if (this.rowCount % this.params.blockSize === 0) {\n this.rowCount++;\n }\n }\n this.onCacheUpdated();\n };\n InfiniteCache.prototype.forEachNodeDeep = function (callback) {\n var _this = this;\n var sequence = new NumberSequence();\n this.getBlocksInOrder().forEach(function (block) { return block.forEachNode(callback, sequence, _this.rowCount); });\n };\n InfiniteCache.prototype.getBlocksInOrder = function () {\n // get all page id's as NUMBERS (not strings, as we need to sort as numbers) and in descending order\n var blockComparator = function (a, b) { return a.getId() - b.getId(); };\n var blocks = _.getAllValuesInObject(this.blocks).sort(blockComparator);\n return blocks;\n };\n InfiniteCache.prototype.destroyBlock = function (block) {\n delete this.blocks[block.getId()];\n this.destroyBean(block);\n this.blockCount--;\n this.params.rowNodeBlockLoader.removeBlock(block);\n };\n // gets called 1) row count changed 2) cache purged 3) items inserted\n InfiniteCache.prototype.onCacheUpdated = function () {\n if (this.isAlive()) {\n // if the virtualRowCount is shortened, then it's possible blocks exist that are no longer\n // in the valid range. so we must remove these. this can happen if user explicitly sets\n // the virtual row count, or the datasource returns a result and sets lastRow to something\n // less than virtualRowCount (can happen if user scrolls down, server reduces dataset size).\n this.destroyAllBlocksPastVirtualRowCount();\n // this results in both row models (infinite and server side) firing ModelUpdated,\n // however server side row model also updates the row indexes first\n var event_1 = {\n type: Events.EVENT_STORE_UPDATED\n };\n this.eventService.dispatchEvent(event_1);\n }\n };\n InfiniteCache.prototype.destroyAllBlocksPastVirtualRowCount = function () {\n var _this = this;\n var blocksToDestroy = [];\n this.getBlocksInOrder().forEach(function (block) {\n var startRow = block.getId() * _this.params.blockSize;\n if (startRow >= _this.rowCount) {\n blocksToDestroy.push(block);\n }\n });\n if (blocksToDestroy.length > 0) {\n blocksToDestroy.forEach(function (block) { return _this.destroyBlock(block); });\n }\n };\n InfiniteCache.prototype.purgeCache = function () {\n var _this = this;\n this.getBlocksInOrder().forEach(function (block) { return _this.removeBlockFromCache(block); });\n this.lastRowIndexKnown = false;\n // if zero rows in the cache, we need to get the SSRM to start asking for rows again.\n // otherwise if set to zero rows last time, and we don't update the row count, then after\n // the purge there will still be zero rows, meaning the SSRM won't request any rows.\n // to kick things off, at least one row needs to be asked for.\n if (this.rowCount === 0) {\n this.rowCount = this.params.initialRowCount;\n }\n this.onCacheUpdated();\n };\n InfiniteCache.prototype.getRowNodesInRange = function (firstInRange, lastInRange) {\n var _this = this;\n var result = [];\n var lastBlockId = -1;\n var inActiveRange = false;\n var numberSequence = new NumberSequence();\n // if only one node passed, we start the selection at the top\n if (_.missing(firstInRange)) {\n inActiveRange = true;\n }\n var foundGapInSelection = false;\n this.getBlocksInOrder().forEach(function (block) {\n if (foundGapInSelection) {\n return;\n }\n if (inActiveRange && (lastBlockId + 1 !== block.getId())) {\n foundGapInSelection = true;\n return;\n }\n lastBlockId = block.getId();\n block.forEachNode(function (rowNode) {\n var hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;\n if (inActiveRange || hitFirstOrLast) {\n result.push(rowNode);\n }\n if (hitFirstOrLast) {\n inActiveRange = !inActiveRange;\n }\n }, numberSequence, _this.rowCount);\n });\n // inActiveRange will be still true if we never hit the second rowNode\n var invalidRange = foundGapInSelection || inActiveRange;\n return invalidRange ? [] : result;\n };\n // this property says how many empty blocks should be in a cache, eg if scrolls down fast and creates 10\n // blocks all for loading, the grid will only load the last 2 - it will assume the blocks the user quickly\n // scrolled over are not needed to be loaded.\n InfiniteCache.MAX_EMPTY_BLOCKS_TO_KEEP = 2;\n __decorate$3([\n Autowired('rowRenderer')\n ], InfiniteCache.prototype, \"rowRenderer\", void 0);\n __decorate$3([\n Autowired(\"focusService\")\n ], InfiniteCache.prototype, \"focusService\", void 0);\n __decorate$3([\n __param(0, Qualifier('loggerFactory'))\n ], InfiniteCache.prototype, \"setBeans\", null);\n __decorate$3([\n PreDestroy\n ], InfiniteCache.prototype, \"destroyAllBlocks\", null);\n return InfiniteCache;\n}(BeanStub));\n\nvar __extends$3 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar InfiniteRowModel = /** @class */ (function (_super) {\n __extends$3(InfiniteRowModel, _super);\n function InfiniteRowModel() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n InfiniteRowModel.prototype.getRowBounds = function (index) {\n return {\n rowHeight: this.rowHeight,\n rowTop: this.rowHeight * index\n };\n };\n // we don't implement as lazy row heights is not supported in this row model\n InfiniteRowModel.prototype.ensureRowHeightsValid = function (startPixel, endPixel, startLimitIndex, endLimitIndex) {\n return false;\n };\n InfiniteRowModel.prototype.init = function () {\n var _this = this;\n if (!this.gridOptionsWrapper.isRowModelInfinite()) {\n return;\n }\n this.rowHeight = this.gridOptionsWrapper.getRowHeightAsNumber();\n this.addEventListeners();\n this.addDestroyFunc(function () { return _this.destroyCache(); });\n this.verifyProps();\n };\n InfiniteRowModel.prototype.verifyProps = function () {\n if (this.gridOptionsWrapper.getInitialGroupOrderComparator() != null) {\n var message_1 = \"AG Grid: initialGroupOrderComparator cannot be used with Infinite Row Model. If using Infinite Row Model, then sorting is done on the server side, nothing to do with the client.\";\n _.doOnce(function () { return console.warn(message_1); }, 'IRM.InitialGroupOrderComparator');\n }\n };\n InfiniteRowModel.prototype.start = function () {\n this.setDatasource(this.gridOptionsWrapper.getDatasource());\n };\n InfiniteRowModel.prototype.destroyDatasource = function () {\n if (this.datasource) {\n this.getContext().destroyBean(this.datasource);\n this.rowRenderer.datasourceChanged();\n this.datasource = null;\n }\n };\n InfiniteRowModel.prototype.addEventListeners = function () {\n this.addManagedListener(this.eventService, Events.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_NEW_COLUMNS_LOADED, this.onColumnEverything.bind(this));\n this.addManagedListener(this.eventService, Events.EVENT_STORE_UPDATED, this.onCacheUpdated.bind(this));\n };\n InfiniteRowModel.prototype.onFilterChanged = function () {\n this.reset();\n };\n InfiniteRowModel.prototype.onSortChanged = function () {\n this.reset();\n };\n InfiniteRowModel.prototype.onColumnEverything = function () {\n var resetRequired;\n // if cache params, we require reset only if sort model has changed. we don't need to check\n // for filter model, as the filter manager will fire an event when columns change that result\n // in the filter changing.\n if (this.cacheParams) {\n resetRequired = this.isSortModelDifferent();\n }\n else {\n // if no cacheParams, means first time creating the cache, so always create one\n resetRequired = true;\n }\n if (resetRequired) {\n this.reset();\n }\n };\n InfiniteRowModel.prototype.isSortModelDifferent = function () {\n return !_.jsonEquals(this.cacheParams.sortModel, this.sortController.getSortModel());\n };\n InfiniteRowModel.prototype.getType = function () {\n return Constants.ROW_MODEL_TYPE_INFINITE;\n };\n InfiniteRowModel.prototype.setDatasource = function (datasource) {\n this.destroyDatasource();\n this.datasource = datasource;\n // only reset if we have a valid datasource to working with\n if (datasource) {\n this.reset();\n }\n };\n InfiniteRowModel.prototype.isEmpty = function () {\n return !this.infiniteCache;\n };\n InfiniteRowModel.prototype.isRowsToRender = function () {\n return !!this.infiniteCache;\n };\n InfiniteRowModel.prototype.getNodesInRangeForSelection = function (firstInRange, lastInRange) {\n return this.infiniteCache ? this.infiniteCache.getRowNodesInRange(firstInRange, lastInRange) : [];\n };\n InfiniteRowModel.prototype.reset = function () {\n // important to return here, as the user could be setting filter or sort before\n // data-source is set\n if (!this.datasource) {\n return;\n }\n // if user is providing id's, then this means we can keep the selection between datasource hits,\n // as the rows will keep their unique id's even if, for example, server side sorting or filtering\n // is done.\n var getRowIdFunc = this.gridOptionsWrapper.getRowIdFunc();\n var userGeneratingIds = getRowIdFunc != null;\n if (!userGeneratingIds) {\n this.selectionService.reset();\n }\n this.resetCache();\n var event = this.createModelUpdatedEvent();\n this.eventService.dispatchEvent(event);\n };\n InfiniteRowModel.prototype.createModelUpdatedEvent = function () {\n return {\n type: Events.EVENT_MODEL_UPDATED,\n // not sure if these should all be false - noticed if after implementing,\n // maybe they should be true?\n newPage: false,\n newData: false,\n keepRenderedRows: true,\n animate: false\n };\n };\n InfiniteRowModel.prototype.resetCache = function () {\n // if not first time creating a cache, need to destroy the old one\n this.destroyCache();\n this.cacheParams = {\n // the user provided datasource\n datasource: this.datasource,\n // sort and filter model\n filterModel: this.filterManager.getFilterModel(),\n sortModel: this.sortController.getSortModel(),\n rowNodeBlockLoader: this.rowNodeBlockLoader,\n // properties - this way we take a snapshot of them, so if user changes any, they will be\n // used next time we create a new cache, which is generally after a filter or sort change,\n // or a new datasource is set\n initialRowCount: this.defaultIfInvalid(this.gridOptionsWrapper.getInfiniteInitialRowCount(), 1),\n maxBlocksInCache: this.gridOptionsWrapper.getMaxBlocksInCache(),\n rowHeight: this.gridOptionsWrapper.getRowHeightAsNumber(),\n // if user doesn't provide overflow, we use default overflow of 1, so user can scroll past\n // the current page and request first row of next page\n overflowSize: this.defaultIfInvalid(this.gridOptionsWrapper.getCacheOverflowSize(), 1),\n // page size needs to be 1 or greater. having it at 1 would be silly, as you would be hitting the\n // server for one page at a time. so the default if not specified is 100.\n blockSize: this.defaultIfInvalid(this.gridOptionsWrapper.getCacheBlockSize(), 100),\n // the cache could create this, however it is also used by the pages, so handy to create it\n // here as the settings are also passed to the pages\n lastAccessedSequence: new NumberSequence()\n };\n this.infiniteCache = this.createBean(new InfiniteCache(this.cacheParams));\n };\n InfiniteRowModel.prototype.defaultIfInvalid = function (value, defaultValue) {\n return value > 0 ? value : defaultValue;\n };\n InfiniteRowModel.prototype.destroyCache = function () {\n if (this.infiniteCache) {\n this.infiniteCache = this.destroyBean(this.infiniteCache);\n }\n };\n InfiniteRowModel.prototype.onCacheUpdated = function () {\n var event = this.createModelUpdatedEvent();\n this.eventService.dispatchEvent(event);\n };\n InfiniteRowModel.prototype.getRow = function (rowIndex) {\n if (!this.infiniteCache) {\n return undefined;\n }\n if (rowIndex >= this.infiniteCache.getRowCount()) {\n return undefined;\n }\n return this.infiniteCache.getRow(rowIndex);\n };\n InfiniteRowModel.prototype.getRowNode = function (id) {\n var result;\n this.forEachNode(function (rowNode) {\n if (rowNode.id === id) {\n result = rowNode;\n }\n });\n return result;\n };\n InfiniteRowModel.prototype.forEachNode = function (callback) {\n if (this.infiniteCache) {\n this.infiniteCache.forEachNodeDeep(callback);\n }\n };\n InfiniteRowModel.prototype.getTopLevelRowCount = function () {\n return this.getRowCount();\n };\n InfiniteRowModel.prototype.getTopLevelRowDisplayedIndex = function (topLevelIndex) {\n return topLevelIndex;\n };\n InfiniteRowModel.prototype.getRowIndexAtPixel = function (pixel) {\n if (this.rowHeight !== 0) { // avoid divide by zero error\n var rowIndexForPixel = Math.floor(pixel / this.rowHeight);\n var lastRowIndex = this.getRowCount() - 1;\n if (rowIndexForPixel > lastRowIndex) {\n return lastRowIndex;\n }\n return rowIndexForPixel;\n }\n return 0;\n };\n InfiniteRowModel.prototype.getRowCount = function () {\n return this.infiniteCache ? this.infiniteCache.getRowCount() : 0;\n };\n InfiniteRowModel.prototype.isRowPresent = function (rowNode) {\n var foundRowNode = this.getRowNode(rowNode.id);\n return !!foundRowNode;\n };\n InfiniteRowModel.prototype.refreshCache = function () {\n if (this.infiniteCache) {\n this.infiniteCache.refreshCache();\n }\n };\n InfiniteRowModel.prototype.purgeCache = function () {\n if (this.infiniteCache) {\n this.infiniteCache.purgeCache();\n }\n };\n // for iRowModel\n InfiniteRowModel.prototype.isLastRowIndexKnown = function () {\n if (this.infiniteCache) {\n return this.infiniteCache.isLastRowIndexKnown();\n }\n return false;\n };\n InfiniteRowModel.prototype.setRowCount = function (rowCount, lastRowIndexKnown) {\n if (this.infiniteCache) {\n this.infiniteCache.setRowCount(rowCount, lastRowIndexKnown);\n }\n };\n __decorate$2([\n Autowired('filterManager')\n ], InfiniteRowModel.prototype, \"filterManager\", void 0);\n __decorate$2([\n Autowired('sortController')\n ], InfiniteRowModel.prototype, \"sortController\", void 0);\n __decorate$2([\n Autowired('selectionService')\n ], InfiniteRowModel.prototype, \"selectionService\", void 0);\n __decorate$2([\n Autowired('rowRenderer')\n ], InfiniteRowModel.prototype, \"rowRenderer\", void 0);\n __decorate$2([\n Autowired('rowNodeBlockLoader')\n ], InfiniteRowModel.prototype, \"rowNodeBlockLoader\", void 0);\n __decorate$2([\n PostConstruct\n ], InfiniteRowModel.prototype, \"init\", null);\n __decorate$2([\n PreDestroy\n ], InfiniteRowModel.prototype, \"destroyDatasource\", null);\n InfiniteRowModel = __decorate$2([\n Bean('rowModel')\n ], InfiniteRowModel);\n return InfiniteRowModel;\n}(BeanStub));\n\nvar InfiniteRowModelModule = {\n moduleName: ModuleNames.InfiniteRowModelModule,\n rowModels: { infinite: InfiniteRowModel }\n};\n\nvar BaseCreator = /** @class */ (function () {\n function BaseCreator() {\n }\n BaseCreator.prototype.setBeans = function (beans) {\n this.beans = beans;\n };\n BaseCreator.prototype.getFileName = function (fileName) {\n var extension = this.getDefaultFileExtension();\n if (fileName == null || !fileName.length) {\n fileName = this.getDefaultFileName();\n }\n return fileName.indexOf('.') === -1 ? fileName + \".\" + extension : fileName;\n };\n BaseCreator.prototype.getData = function (params) {\n var serializingSession = this.createSerializingSession(params);\n var data = this.beans.gridSerializer.serialize(serializingSession, params);\n return data;\n };\n return BaseCreator;\n}());\n\nvar BaseGridSerializingSession = /** @class */ (function () {\n function BaseGridSerializingSession(config) {\n this.groupColumns = [];\n var columnModel = config.columnModel, valueService = config.valueService, gridOptionsWrapper = config.gridOptionsWrapper, processCellCallback = config.processCellCallback, processHeaderCallback = config.processHeaderCallback, processGroupHeaderCallback = config.processGroupHeaderCallback, processRowGroupCallback = config.processRowGroupCallback;\n this.columnModel = columnModel;\n this.valueService = valueService;\n this.gridOptionsWrapper = gridOptionsWrapper;\n this.processCellCallback = processCellCallback;\n this.processHeaderCallback = processHeaderCallback;\n this.processGroupHeaderCallback = processGroupHeaderCallback;\n this.processRowGroupCallback = processRowGroupCallback;\n }\n BaseGridSerializingSession.prototype.prepare = function (columnsToExport) {\n this.groupColumns = columnsToExport.filter(function (col) { return !!col.getColDef().showRowGroup; });\n };\n BaseGridSerializingSession.prototype.extractHeaderValue = function (column) {\n var value = this.getHeaderName(this.processHeaderCallback, column);\n return value != null ? value : '';\n };\n BaseGridSerializingSession.prototype.extractRowCellValue = function (column, index, accumulatedRowIndex, type, node) {\n // we render the group summary text e.g. \"-> Parent -> Child\"...\n var hideOpenParents = this.gridOptionsWrapper.isGroupHideOpenParents();\n var value = (!hideOpenParents && this.shouldRenderGroupSummaryCell(node, column, index))\n ? this.createValueForGroupNode(node)\n : this.valueService.getValue(column, node);\n var processedValue = this.processCell({\n accumulatedRowIndex: accumulatedRowIndex,\n rowNode: node,\n column: column,\n value: value,\n processCellCallback: this.processCellCallback,\n type: type\n });\n return processedValue != null ? processedValue : '';\n };\n BaseGridSerializingSession.prototype.shouldRenderGroupSummaryCell = function (node, column, currentColumnIndex) {\n var _a;\n var isGroupNode = node && node.group;\n // only on group rows\n if (!isGroupNode) {\n return false;\n }\n var currentColumnGroupIndex = this.groupColumns.indexOf(column);\n if (currentColumnGroupIndex !== -1 && ((_a = node.groupData) === null || _a === void 0 ? void 0 : _a[column.getId()])) {\n return true;\n }\n var isGroupUseEntireRow = this.gridOptionsWrapper.isGroupUseEntireRow(this.columnModel.isPivotMode());\n return currentColumnIndex === 0 && isGroupUseEntireRow;\n };\n BaseGridSerializingSession.prototype.getHeaderName = function (callback, column) {\n if (callback) {\n return callback({\n column: column,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext()\n });\n }\n return this.columnModel.getDisplayNameForColumn(column, 'csv', true);\n };\n BaseGridSerializingSession.prototype.createValueForGroupNode = function (node) {\n if (this.processRowGroupCallback) {\n return this.processRowGroupCallback({\n node: node,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext(),\n });\n }\n var keys = [node.key];\n if (!this.gridOptionsWrapper.isGroupMultiAutoColumn()) {\n while (node.parent) {\n node = node.parent;\n keys.push(node.key);\n }\n }\n return keys.reverse().join(' -> ');\n };\n BaseGridSerializingSession.prototype.processCell = function (params) {\n var accumulatedRowIndex = params.accumulatedRowIndex, rowNode = params.rowNode, column = params.column, value = params.value, processCellCallback = params.processCellCallback, type = params.type;\n if (processCellCallback) {\n return processCellCallback({\n accumulatedRowIndex: accumulatedRowIndex,\n column: column,\n node: rowNode,\n value: value,\n api: this.gridOptionsWrapper.getApi(),\n columnApi: this.gridOptionsWrapper.getColumnApi(),\n context: this.gridOptionsWrapper.getContext(),\n type: type\n });\n }\n return value != null ? value : '';\n };\n return BaseGridSerializingSession;\n}());\n\nvar Downloader = /** @class */ (function () {\n function Downloader() {\n }\n Downloader.download = function (fileName, content) {\n var win = document.defaultView || window;\n if (!win) {\n console.warn('AG Grid: There is no `window` associated with the current `document`');\n return;\n }\n var element = document.createElement('a');\n // @ts-ignore\n var url = win.URL.createObjectURL(content);\n element.setAttribute('href', url);\n element.setAttribute('download', fileName);\n element.style.display = 'none';\n document.body.appendChild(element);\n element.dispatchEvent(new MouseEvent('click', {\n bubbles: false,\n cancelable: true,\n view: win\n }));\n document.body.removeChild(element);\n win.setTimeout(function () {\n // @ts-ignore\n win.URL.revokeObjectURL(url);\n }, 0);\n };\n return Downloader;\n}());\n\nvar __extends$2 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar LINE_SEPARATOR$1 = '\\r\\n';\nvar CsvSerializingSession = /** @class */ (function (_super) {\n __extends$2(CsvSerializingSession, _super);\n function CsvSerializingSession(config) {\n var _this = _super.call(this, config) || this;\n _this.isFirstLine = true;\n _this.result = '';\n var suppressQuotes = config.suppressQuotes, columnSeparator = config.columnSeparator;\n _this.suppressQuotes = suppressQuotes;\n _this.columnSeparator = columnSeparator;\n return _this;\n }\n CsvSerializingSession.prototype.addCustomContent = function (content) {\n var _this = this;\n if (!content) {\n return;\n }\n if (typeof content === 'string') {\n if (!/^\\s*\\n/.test(content)) {\n this.beginNewLine();\n }\n // replace whatever newlines are supplied with the style we're using\n content = content.replace(/\\r?\\n/g, LINE_SEPARATOR$1);\n this.result += content;\n }\n else {\n content.forEach(function (row) {\n _this.beginNewLine();\n row.forEach(function (cell, index) {\n if (index !== 0) {\n _this.result += _this.columnSeparator;\n }\n _this.result += _this.putInQuotes(cell.data.value || '');\n if (cell.mergeAcross) {\n _this.appendEmptyCells(cell.mergeAcross);\n }\n });\n });\n }\n };\n CsvSerializingSession.prototype.onNewHeaderGroupingRow = function () {\n this.beginNewLine();\n return {\n onColumn: this.onNewHeaderGroupingRowColumn.bind(this)\n };\n };\n CsvSerializingSession.prototype.onNewHeaderGroupingRowColumn = function (columnGroup, header, index, span) {\n if (index != 0) {\n this.result += this.columnSeparator;\n }\n this.result += this.putInQuotes(header);\n this.appendEmptyCells(span);\n };\n CsvSerializingSession.prototype.appendEmptyCells = function (count) {\n for (var i = 1; i <= count; i++) {\n this.result += this.columnSeparator + this.putInQuotes(\"\");\n }\n };\n CsvSerializingSession.prototype.onNewHeaderRow = function () {\n this.beginNewLine();\n return {\n onColumn: this.onNewHeaderRowColumn.bind(this)\n };\n };\n CsvSerializingSession.prototype.onNewHeaderRowColumn = function (column, index) {\n if (index != 0) {\n this.result += this.columnSeparator;\n }\n this.result += this.putInQuotes(this.extractHeaderValue(column));\n };\n CsvSerializingSession.prototype.onNewBodyRow = function () {\n this.beginNewLine();\n return {\n onColumn: this.onNewBodyRowColumn.bind(this)\n };\n };\n CsvSerializingSession.prototype.onNewBodyRowColumn = function (column, index, node) {\n if (index != 0) {\n this.result += this.columnSeparator;\n }\n this.result += this.putInQuotes(this.extractRowCellValue(column, index, index, Constants.EXPORT_TYPE_CSV, node));\n };\n CsvSerializingSession.prototype.putInQuotes = function (value) {\n if (this.suppressQuotes) {\n return value;\n }\n if (value === null || value === undefined) {\n return '\"\"';\n }\n var stringValue;\n if (typeof value === 'string') {\n stringValue = value;\n }\n else if (typeof value.toString === 'function') {\n stringValue = value.toString();\n }\n else {\n console.warn('AG Grid: unknown value type during csv conversion');\n stringValue = '';\n }\n // replace each \" with \"\" (ie two sets of double quotes is how to do double quotes in csv)\n var valueEscaped = stringValue.replace(/\"/g, \"\\\"\\\"\");\n return '\"' + valueEscaped + '\"';\n };\n CsvSerializingSession.prototype.parse = function () {\n return this.result;\n };\n CsvSerializingSession.prototype.beginNewLine = function () {\n if (!this.isFirstLine) {\n this.result += LINE_SEPARATOR$1;\n }\n this.isFirstLine = false;\n };\n return CsvSerializingSession;\n}(BaseGridSerializingSession));\n\nvar __extends$1 = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar CsvCreator = /** @class */ (function (_super) {\n __extends$1(CsvCreator, _super);\n function CsvCreator() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n CsvCreator.prototype.postConstruct = function () {\n this.setBeans({\n gridSerializer: this.gridSerializer,\n gridOptionsWrapper: this.gridOptionsWrapper\n });\n };\n CsvCreator.prototype.getMergedParams = function (params) {\n var baseParams = this.gridOptionsWrapper.getDefaultExportParams('csv');\n return Object.assign({}, baseParams, params);\n };\n CsvCreator.prototype.export = function (userParams) {\n if (this.isExportSuppressed()) {\n console.warn(\"AG Grid: Export cancelled. Export is not allowed as per your configuration.\");\n return '';\n }\n var mergedParams = this.getMergedParams(userParams);\n var data = this.getData(mergedParams);\n var packagedFile = new Blob([\"\\ufeff\", data], { type: 'text/plain' });\n Downloader.download(this.getFileName(mergedParams.fileName), packagedFile);\n return data;\n };\n CsvCreator.prototype.exportDataAsCsv = function (params) {\n return this.export(params);\n };\n CsvCreator.prototype.getDataAsCsv = function (params) {\n var mergedParams = this.getMergedParams(params);\n return this.getData(mergedParams);\n };\n CsvCreator.prototype.getDefaultFileName = function () {\n return 'export.csv';\n };\n CsvCreator.prototype.getDefaultFileExtension = function () {\n return 'csv';\n };\n CsvCreator.prototype.createSerializingSession = function (params) {\n var _a = this, columnModel = _a.columnModel, valueService = _a.valueService, gridOptionsWrapper = _a.gridOptionsWrapper;\n var _b = params, processCellCallback = _b.processCellCallback, processHeaderCallback = _b.processHeaderCallback, processGroupHeaderCallback = _b.processGroupHeaderCallback, processRowGroupCallback = _b.processRowGroupCallback, suppressQuotes = _b.suppressQuotes, columnSeparator = _b.columnSeparator;\n return new CsvSerializingSession({\n columnModel: columnModel,\n valueService: valueService,\n gridOptionsWrapper: gridOptionsWrapper,\n processCellCallback: processCellCallback || undefined,\n processHeaderCallback: processHeaderCallback || undefined,\n processGroupHeaderCallback: processGroupHeaderCallback || undefined,\n processRowGroupCallback: processRowGroupCallback || undefined,\n suppressQuotes: suppressQuotes || false,\n columnSeparator: columnSeparator || ','\n });\n };\n CsvCreator.prototype.isExportSuppressed = function () {\n return this.gridOptionsWrapper.isSuppressCsvExport();\n };\n __decorate$1([\n Autowired('columnModel')\n ], CsvCreator.prototype, \"columnModel\", void 0);\n __decorate$1([\n Autowired('valueService')\n ], CsvCreator.prototype, \"valueService\", void 0);\n __decorate$1([\n Autowired('gridSerializer')\n ], CsvCreator.prototype, \"gridSerializer\", void 0);\n __decorate$1([\n Autowired('gridOptionsWrapper')\n ], CsvCreator.prototype, \"gridOptionsWrapper\", void 0);\n __decorate$1([\n PostConstruct\n ], CsvCreator.prototype, \"postConstruct\", null);\n CsvCreator = __decorate$1([\n Bean('csvCreator')\n ], CsvCreator);\n return CsvCreator;\n}(BaseCreator));\n\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar RowType;\n(function (RowType) {\n RowType[RowType[\"HEADER_GROUPING\"] = 0] = \"HEADER_GROUPING\";\n RowType[RowType[\"HEADER\"] = 1] = \"HEADER\";\n RowType[RowType[\"BODY\"] = 2] = \"BODY\";\n})(RowType || (RowType = {}));\nvar GridSerializer = /** @class */ (function (_super) {\n __extends(GridSerializer, _super);\n function GridSerializer() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n GridSerializer.prototype.serialize = function (gridSerializingSession, params) {\n if (params === void 0) { params = {}; }\n var columnsToExport = this.getColumnsToExport(params.allColumns, params.columnKeys);\n var serializeChain = _.compose(\n // first pass, put in the header names of the cols\n this.prepareSession(columnsToExport), this.prependContent(params), this.exportColumnGroups(params, columnsToExport), this.exportHeaders(params, columnsToExport), this.processPinnedTopRows(params, columnsToExport), this.processRows(params, columnsToExport), this.processPinnedBottomRows(params, columnsToExport), this.appendContent(params));\n return serializeChain(gridSerializingSession).parse();\n };\n GridSerializer.prototype.processRow = function (gridSerializingSession, params, columnsToExport, node) {\n var rowSkipper = params.shouldRowBeSkipped || (function () { return false; });\n var gridOptionsWrapper = this.gridOptionsWrapper;\n var context = gridOptionsWrapper.getContext();\n var api = gridOptionsWrapper.getApi();\n var columnApi = gridOptionsWrapper.getColumnApi();\n var skipSingleChildrenGroup = gridOptionsWrapper.isGroupRemoveSingleChildren();\n var skipLowestSingleChildrenGroup = gridOptionsWrapper.isGroupRemoveLowestSingleChildren();\n // if onlySelected, we ignore groupHideOpenParents as the user has explicitly selected the rows they wish to export.\n // similarly, if specific rowNodes are provided we do the same. (the clipboard service uses rowNodes to define which rows to export)\n var isClipboardExport = params.rowPositions != null;\n var isExplicitExportSelection = isClipboardExport || !!params.onlySelected;\n var hideOpenParents = gridOptionsWrapper.isGroupHideOpenParents() && !isExplicitExportSelection;\n var isLeafNode = this.columnModel.isPivotMode() ? node.leafGroup : !node.group;\n var skipRowGroups = params.skipGroups || params.skipRowGroups;\n var shouldSkipLowestGroup = skipLowestSingleChildrenGroup && node.leafGroup;\n var shouldSkipCurrentGroup = node.allChildrenCount === 1 && (skipSingleChildrenGroup || shouldSkipLowestGroup);\n if (skipRowGroups && params.skipGroups) {\n _.doOnce(function () { return console.warn('AG Grid: Since v25.2 `skipGroups` has been renamed to `skipRowGroups`.'); }, 'gridSerializer-skipGroups');\n }\n if ((!isLeafNode && (params.skipRowGroups || shouldSkipCurrentGroup || hideOpenParents)) ||\n (params.onlySelected && !node.isSelected()) ||\n (params.skipPinnedTop && node.rowPinned === 'top') ||\n (params.skipPinnedBottom && node.rowPinned === 'bottom')) {\n return;\n }\n // if we are in pivotMode, then the grid will show the root node only\n // if it's not a leaf group\n var nodeIsRootNode = node.level === -1;\n if (nodeIsRootNode && !node.leafGroup && (!node.footer || !isClipboardExport)) {\n return;\n }\n var shouldRowBeSkipped = rowSkipper({ node: node, api: api, columnApi: columnApi, context: context });\n if (shouldRowBeSkipped) {\n return;\n }\n var rowAccumulator = gridSerializingSession.onNewBodyRow();\n columnsToExport.forEach(function (column, index) {\n rowAccumulator.onColumn(column, index, node);\n });\n if (params.getCustomContentBelowRow) {\n var content = params.getCustomContentBelowRow({ node: node, api: api, columnApi: columnApi, context: context });\n if (content) {\n gridSerializingSession.addCustomContent(content);\n }\n }\n };\n GridSerializer.prototype.appendContent = function (params) {\n return function (gridSerializingSession) {\n var appendContent = params.customFooter || params.appendContent;\n if (appendContent) {\n if (params.customFooter) {\n _.doOnce(function () { return console.warn('AG Grid: Since version 25.2.0 the `customFooter` param has been deprecated. Use `appendContent` instead.'); }, 'gridSerializer-customFooter');\n }\n gridSerializingSession.addCustomContent(appendContent);\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.prependContent = function (params) {\n return function (gridSerializingSession) {\n var prependContent = params.customHeader || params.prependContent;\n if (prependContent) {\n if (params.customHeader) {\n _.doOnce(function () { return console.warn('AG Grid: Since version 25.2.0 the `customHeader` param has been deprecated. Use `prependContent` instead.'); }, 'gridSerializer-customHeader');\n }\n gridSerializingSession.addCustomContent(prependContent);\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.prepareSession = function (columnsToExport) {\n return function (gridSerializingSession) {\n gridSerializingSession.prepare(columnsToExport);\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.exportColumnGroups = function (params, columnsToExport) {\n var _this = this;\n return function (gridSerializingSession) {\n if (!params.skipColumnGroupHeaders) {\n var groupInstanceIdCreator = new GroupInstanceIdCreator();\n var displayedGroups = _this.displayedGroupCreator.createDisplayedGroups(columnsToExport, _this.columnModel.getGridBalancedTree(), groupInstanceIdCreator, null);\n _this.recursivelyAddHeaderGroups(displayedGroups, gridSerializingSession, params.processGroupHeaderCallback);\n }\n else if (params.columnGroups) {\n _.doOnce(function () { return console.warn('AG Grid: Since v25.2 the `columnGroups` param has deprecated, and groups are exported by default.'); }, 'gridSerializer-columnGroups');\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.exportHeaders = function (params, columnsToExport) {\n return function (gridSerializingSession) {\n if (!params.skipHeader && !params.skipColumnHeaders) {\n var gridRowIterator_1 = gridSerializingSession.onNewHeaderRow();\n columnsToExport.forEach(function (column, index) {\n gridRowIterator_1.onColumn(column, index, undefined);\n });\n }\n else if (params.skipHeader) {\n _.doOnce(function () { return console.warn('AG Grid: Since v25.2 the `skipHeader` param has been renamed to `skipColumnHeaders`.'); }, 'gridSerializer-skipHeader');\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.processPinnedTopRows = function (params, columnsToExport) {\n var _this = this;\n return function (gridSerializingSession) {\n var processRow = _this.processRow.bind(_this, gridSerializingSession, params, columnsToExport);\n if (params.rowPositions) {\n params.rowPositions\n // only pinnedTop rows, other models are processed by `processRows` and `processPinnedBottomsRows`\n .filter(function (position) { return position.rowPinned === 'top'; })\n .sort(function (a, b) { return a.rowIndex - b.rowIndex; })\n .map(function (position) { return _this.pinnedRowModel.getPinnedTopRow(position.rowIndex); })\n .forEach(processRow);\n }\n else {\n _this.pinnedRowModel.forEachPinnedTopRow(processRow);\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.processRows = function (params, columnsToExport) {\n var _this = this;\n return function (gridSerializingSession) {\n // when in pivot mode, we always render cols on screen, never 'all columns'\n var rowModel = _this.rowModel;\n var rowModelType = rowModel.getType();\n var usingCsrm = rowModelType === Constants.ROW_MODEL_TYPE_CLIENT_SIDE;\n var usingSsrm = rowModelType === Constants.ROW_MODEL_TYPE_SERVER_SIDE;\n var onlySelectedNonStandardModel = !usingCsrm && params.onlySelected;\n var processRow = _this.processRow.bind(_this, gridSerializingSession, params, columnsToExport);\n var _a = params.exportedRows, exportedRows = _a === void 0 ? 'filteredAndSorted' : _a;\n if (params.rowPositions) {\n params.rowPositions\n // pinnedRows are processed by `processPinnedTopRows` and `processPinnedBottomsRows`\n .filter(function (position) { return position.rowPinned == null; })\n .sort(function (a, b) { return a.rowIndex - b.rowIndex; })\n .map(function (position) { return rowModel.getRow(position.rowIndex); })\n .forEach(processRow);\n }\n else if (_this.columnModel.isPivotMode()) {\n if (usingCsrm) {\n rowModel.forEachPivotNode(processRow);\n }\n else {\n // must be enterprise, so we can just loop through all the nodes\n rowModel.forEachNode(processRow);\n }\n }\n else {\n // onlySelectedAllPages: user doing pagination and wants selected items from\n // other pages, so cannot use the standard row model as it won't have rows from\n // other pages.\n // onlySelectedNonStandardModel: if user wants selected in non standard row model\n // (eg viewport) then again RowModel cannot be used, so need to use selected instead.\n if (params.onlySelectedAllPages || onlySelectedNonStandardModel) {\n var selectedNodes = _this.selectionService.getSelectedNodes();\n selectedNodes.forEach(processRow);\n }\n else {\n // here is everything else - including standard row model and selected. we don't use\n // the selection model even when just using selected, so that the result is the order\n // of the rows appearing on the screen.\n if (exportedRows === 'all') {\n rowModel.forEachNode(processRow);\n }\n else if (usingCsrm) {\n rowModel.forEachNodeAfterFilterAndSort(processRow);\n }\n else if (usingSsrm) {\n rowModel.forEachNodeAfterFilterAndSort(processRow);\n }\n else {\n rowModel.forEachNode(processRow);\n }\n }\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.processPinnedBottomRows = function (params, columnsToExport) {\n var _this = this;\n return function (gridSerializingSession) {\n var processRow = _this.processRow.bind(_this, gridSerializingSession, params, columnsToExport);\n if (params.rowPositions) {\n params.rowPositions\n // only pinnedBottom rows, other models are processed by `processRows` and `processPinnedTopRows`\n .filter(function (position) { return position.rowPinned === 'bottom'; })\n .sort(function (a, b) { return a.rowIndex - b.rowIndex; })\n .map(function (position) { return _this.pinnedRowModel.getPinnedBottomRow(position.rowIndex); })\n .forEach(processRow);\n }\n else {\n _this.pinnedRowModel.forEachPinnedBottomRow(processRow);\n }\n return gridSerializingSession;\n };\n };\n GridSerializer.prototype.getColumnsToExport = function (allColumns, columnKeys) {\n if (allColumns === void 0) { allColumns = false; }\n var isPivotMode = this.columnModel.isPivotMode();\n if (columnKeys && columnKeys.length) {\n return this.columnModel.getGridColumns(columnKeys);\n }\n if (allColumns && !isPivotMode) {\n // add auto group column for tree data\n var columns = this.gridOptionsWrapper.isTreeData()\n ? this.columnModel.getGridColumns([Constants.GROUP_AUTO_COLUMN_ID])\n : [];\n return columns.concat(this.columnModel.getAllPrimaryColumns() || []);\n }\n return this.columnModel.getAllDisplayedColumns();\n };\n GridSerializer.prototype.recursivelyAddHeaderGroups = function (displayedGroups, gridSerializingSession, processGroupHeaderCallback) {\n var directChildrenHeaderGroups = [];\n displayedGroups.forEach(function (columnGroupChild) {\n var columnGroup = columnGroupChild;\n if (!columnGroup.getChildren) {\n return;\n }\n columnGroup.getChildren().forEach(function (it) { return directChildrenHeaderGroups.push(it); });\n });\n if (displayedGroups.length > 0 && displayedGroups[0] instanceof ColumnGroup) {\n this.doAddHeaderHeader(gridSerializingSession, displayedGroups, processGroupHeaderCallback);\n }\n if (directChildrenHeaderGroups && directChildrenHeaderGroups.length > 0) {\n this.recursivelyAddHeaderGroups(directChildrenHeaderGroups, gridSerializingSession, processGroupHeaderCallback);\n }\n };\n GridSerializer.prototype.doAddHeaderHeader = function (gridSerializingSession, displayedGroups, processGroupHeaderCallback) {\n var _this = this;\n var gridRowIterator = gridSerializingSession.onNewHeaderGroupingRow();\n var columnIndex = 0;\n displayedGroups.forEach(function (columnGroupChild) {\n var columnGroup = columnGroupChild;\n var name;\n if (processGroupHeaderCallback) {\n name = processGroupHeaderCallback({\n columnGroup: columnGroup,\n api: _this.gridOptionsWrapper.getApi(),\n columnApi: _this.gridOptionsWrapper.getColumnApi(),\n context: _this.gridOptionsWrapper.getContext()\n });\n }\n else {\n name = _this.columnModel.getDisplayNameForColumnGroup(columnGroup, 'header');\n }\n var collapsibleGroupRanges = columnGroup.getLeafColumns().reduce(function (collapsibleGroups, currentColumn, currentIdx, arr) {\n var lastGroup = _.last(collapsibleGroups);\n var groupShow = currentColumn.getColumnGroupShow() === 'open';\n if (!groupShow) {\n if (lastGroup && lastGroup[1] == null) {\n lastGroup[1] = currentIdx - 1;\n }\n }\n else if (!lastGroup || lastGroup[1] != null) {\n lastGroup = [currentIdx];\n collapsibleGroups.push(lastGroup);\n }\n if (currentIdx === arr.length - 1 && lastGroup && lastGroup[1] == null) {\n lastGroup[1] = currentIdx;\n }\n return collapsibleGroups;\n }, []);\n gridRowIterator.onColumn(columnGroup, name || '', columnIndex++, columnGroup.getLeafColumns().length - 1, collapsibleGroupRanges);\n });\n };\n __decorate([\n Autowired('displayedGroupCreator')\n ], GridSerializer.prototype, \"displayedGroupCreator\", void 0);\n __decorate([\n Autowired('columnModel')\n ], GridSerializer.prototype, \"columnModel\", void 0);\n __decorate([\n Autowired('rowModel')\n ], GridSerializer.prototype, \"rowModel\", void 0);\n __decorate([\n Autowired('pinnedRowModel')\n ], GridSerializer.prototype, \"pinnedRowModel\", void 0);\n __decorate([\n Autowired('selectionService')\n ], GridSerializer.prototype, \"selectionService\", void 0);\n __decorate([\n Autowired('rowPositionUtils')\n ], GridSerializer.prototype, \"rowPositionUtils\", void 0);\n GridSerializer = __decorate([\n Bean(\"gridSerializer\")\n ], GridSerializer);\n return GridSerializer;\n}(BeanStub));\n\nvar CsvExportModule = {\n moduleName: ModuleNames.CsvExportModule,\n beans: [CsvCreator, GridSerializer]\n};\n\nvar LINE_SEPARATOR = '\\r\\n';\nvar XmlFactory = /** @class */ (function () {\n function XmlFactory() {\n }\n XmlFactory.createHeader = function (headerElement) {\n if (headerElement === void 0) { headerElement = {}; }\n var headerStart = '<?';\n var headerEnd = '?>';\n var keys = ['version'];\n if (!headerElement.version) {\n headerElement.version = \"1.0\";\n }\n if (headerElement.encoding) {\n keys.push('encoding');\n }\n if (headerElement.standalone) {\n keys.push('standalone');\n }\n var att = keys.map(function (key) { return key + \"=\\\"\" + headerElement[key] + \"\\\"\"; }).join(' ');\n return headerStart + \"xml \" + att + \" \" + headerEnd;\n };\n XmlFactory.createXml = function (xmlElement, booleanTransformer) {\n var _this = this;\n var props = '';\n if (xmlElement.properties) {\n if (xmlElement.properties.prefixedAttributes) {\n xmlElement.properties.prefixedAttributes.forEach(function (prefixedSet) {\n Object.keys(prefixedSet.map).forEach(function (key) {\n props += _this.returnAttributeIfPopulated(prefixedSet.prefix + key, prefixedSet.map[key], booleanTransformer);\n });\n });\n }\n if (xmlElement.properties.rawMap) {\n Object.keys(xmlElement.properties.rawMap).forEach(function (key) {\n props += _this.returnAttributeIfPopulated(key, xmlElement.properties.rawMap[key], booleanTransformer);\n });\n }\n }\n var result = '<' + xmlElement.name + props;\n if (!xmlElement.children && xmlElement.textNode == null) {\n return result + '/>' + LINE_SEPARATOR;\n }\n if (xmlElement.textNode != null) {\n return result + '>' + xmlElement.textNode + '</' + xmlElement.name + '>' + LINE_SEPARATOR;\n }\n result += '>' + LINE_SEPARATOR;\n if (xmlElement.children) {\n xmlElement.children.forEach(function (it) {\n result += _this.createXml(it, booleanTransformer);\n });\n }\n return result + '</' + xmlElement.name + '>' + LINE_SEPARATOR;\n };\n XmlFactory.returnAttributeIfPopulated = function (key, value, booleanTransformer) {\n if (!value && value !== '' && value !== 0) {\n return '';\n }\n var xmlValue = value;\n if ((typeof (value) === 'boolean')) {\n if (booleanTransformer) {\n xmlValue = booleanTransformer(value);\n }\n }\n return \" \" + key + \"=\\\"\" + xmlValue + \"\\\"\";\n };\n return XmlFactory;\n}());\n\nvar __values = (undefined && undefined.__values) || function(o) {\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\n if (m) return m.call(o);\n if (o && typeof o.length === \"number\") return {\n next: function () {\n if (o && i >= o.length) o = void 0;\n return { value: o && o[i++], done: !o };\n }\n };\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\n};\n// table for crc calculation\n// from: https://referencesource.microsoft.com/#System/sys/System/IO/compression/Crc32Helper.cs,3b31978c7d7f7246,references\nvar crcTable = new Uint32Array([\n 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,\n 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,\n 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,\n 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,\n 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,\n 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,\n 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,\n 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\n 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,\n 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\n 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,\n 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,\n 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,\n 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,\n 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\n 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,\n 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\n 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,\n 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,\n 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\n]);\nvar ZipContainer = /** @class */ (function () {\n function ZipContainer() {\n }\n ZipContainer.addFolders = function (paths) {\n paths.forEach(this.addFolder.bind(this));\n };\n ZipContainer.addFolder = function (path) {\n this.folders.push({\n path: path,\n created: new Date(),\n isBase64: false\n });\n };\n ZipContainer.addFile = function (path, content, isBase64) {\n if (isBase64 === void 0) { isBase64 = false; }\n this.files.push({\n path: path,\n created: new Date(),\n content: content,\n isBase64: isBase64\n });\n };\n ZipContainer.getContent = function (mimeType) {\n if (mimeType === void 0) { mimeType = 'application/zip'; }\n var textOutput = this.buildFileStream();\n var uInt8Output = this.buildUint8Array(textOutput);\n this.clearStream();\n return new Blob([uInt8Output], { type: mimeType });\n };\n ZipContainer.clearStream = function () {\n this.folders = [];\n this.files = [];\n };\n ZipContainer.buildFileStream = function (fData) {\n var e_1, _a;\n if (fData === void 0) { fData = ''; }\n var totalFiles = this.folders.concat(this.files);\n var len = totalFiles.length;\n var foData = '';\n var lL = 0;\n var cL = 0;\n try {\n for (var totalFiles_1 = __values(totalFiles), totalFiles_1_1 = totalFiles_1.next(); !totalFiles_1_1.done; totalFiles_1_1 = totalFiles_1.next()) {\n var currentFile = totalFiles_1_1.value;\n var _b = this.getHeader(currentFile, lL), fileHeader = _b.fileHeader, folderHeader = _b.folderHeader, content = _b.content;\n lL += fileHeader.length + content.length;\n cL += folderHeader.length;\n fData += fileHeader + content;\n foData += folderHeader;\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (totalFiles_1_1 && !totalFiles_1_1.done && (_a = totalFiles_1.return)) _a.call(totalFiles_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n var foEnd = this.buildFolderEnd(len, cL, lL);\n return fData + foData + foEnd;\n };\n ZipContainer.getHeader = function (currentFile, offset) {\n var content = currentFile.content, path = currentFile.path, created = currentFile.created, isBase64 = currentFile.isBase64;\n var utf8_encode = _.utf8_encode, decToHex = _.decToHex;\n var utfPath = utf8_encode(path);\n var isUTF8 = utfPath !== path;\n var time = this.convertTime(created);\n var dt = this.convertDate(created);\n var extraFields = '';\n if (isUTF8) {\n var uExtraFieldPath = decToHex(1, 1) + decToHex(this.getFromCrc32Table(utfPath), 4) + utfPath;\n extraFields = \"\\x75\\x70\" + decToHex(uExtraFieldPath.length, 2) + uExtraFieldPath;\n }\n var _a = !content ? { size: 0, content: '' } : this.getConvertedContent(content, isBase64), size = _a.size, convertedContent = _a.content;\n var header = '\\x0A\\x00' +\n (isUTF8 ? '\\x00\\x08' : '\\x00\\x00') +\n '\\x00\\x00' +\n decToHex(time, 2) + // last modified time\n decToHex(dt, 2) + // last modified date\n decToHex(size ? this.getFromCrc32Table(convertedContent) : 0, 4) +\n decToHex(size, 4) + // compressed size\n decToHex(size, 4) + // uncompressed size\n decToHex(utfPath.length, 2) + // file name length\n decToHex(extraFields.length, 2); // extra field length\n var fileHeader = 'PK\\x03\\x04' + header + utfPath + extraFields;\n var folderHeader = 'PK\\x01\\x02' + // central header\n '\\x14\\x00' +\n header + // file header\n '\\x00\\x00' +\n '\\x00\\x00' +\n '\\x00\\x00' +\n (content ? '\\x00\\x00\\x00\\x00' : '\\x10\\x00\\x00\\x00') + // external file attributes\n decToHex(offset, 4) + // relative offset of local header\n utfPath + // file name\n extraFields; // extra field\n return { fileHeader: fileHeader, folderHeader: folderHeader, content: convertedContent || '' };\n };\n ZipContainer.getConvertedContent = function (content, isBase64) {\n if (isBase64 === void 0) { isBase64 = false; }\n if (isBase64) {\n content = content.split(';base64,')[1];\n }\n content = isBase64 ? atob(content) : content;\n return {\n size: content.length,\n content: content\n };\n };\n ZipContainer.buildFolderEnd = function (tLen, cLen, lLen) {\n var decToHex = _.decToHex;\n return 'PK\\x05\\x06' + // central folder end\n '\\x00\\x00' +\n '\\x00\\x00' +\n decToHex(tLen, 2) + // total number of entries in the central folder\n decToHex(tLen, 2) + // total number of entries in the central folder\n decToHex(cLen, 4) + // size of the central folder\n decToHex(lLen, 4) + // central folder start offset\n '\\x00\\x00';\n };\n ZipContainer.buildUint8Array = function (content) {\n var uint8 = new Uint8Array(content.length);\n for (var i = 0; i < uint8.length; i++) {\n uint8[i] = content.charCodeAt(i);\n }\n return uint8;\n };\n ZipContainer.getFromCrc32Table = function (content) {\n if (!content.length) {\n return 0;\n }\n var size = content.length;\n var iterable = new Uint8Array(size);\n for (var i = 0; i < size; i++) {\n iterable[i] = content.charCodeAt(i);\n }\n var crc = 0 ^ (-1);\n var j = 0;\n var k = 0;\n var l = 0;\n for (var i = 0; i < size; i++) {\n j = iterable[i];\n k = (crc ^ j) & 0xFF;\n l = crcTable[k];\n crc = (crc >>> 8) ^ l;\n }\n return crc ^ (-1);\n };\n ZipContainer.convertTime = function (date) {\n var time = date.getHours();\n time <<= 6;\n time = time | date.getMinutes();\n time <<= 5;\n time = time | date.getSeconds() / 2;\n return time;\n };\n ZipContainer.convertDate = function (date) {\n var dt = date.getFullYear() - 1980;\n dt <<= 4;\n dt = dt | (date.getMonth() + 1);\n dt <<= 5;\n dt = dt | date.getDate();\n return dt;\n };\n ZipContainer.folders = [];\n ZipContainer.files = [];\n return ZipContainer;\n}());\n\nvar AllCommunityModules = [ClientSideRowModelModule, InfiniteRowModelModule, CsvExportModule];\n\nModuleRegistry.registerModules(AllCommunityModules);\n\n\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ \"./node_modules/webpack/buildin/global.js\")))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC1jb21tdW5pdHkvZGlzdC9hZy1ncmlkLWNvbW11bml0eS5hdXRvLmVzbS5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9hZy1ncmlkLWNvbW11bml0eS9kaXN0L2FnLWdyaWQtY29tbXVuaXR5LmF1dG8uZXNtLmpzPzJjNTMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gICAgICAgICAgKiBAYWctZ3JpZC1jb21tdW5pdHkvYWxsLW1vZHVsZXMgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWUgKiBAdmVyc2lvbiB2MjguMi4wXG4gICAgICAgICAgKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAgICAgICAgICAqIEBsaWNlbnNlIE1JVFxuICAgICAgICAgICovXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG4vKipcbiAqIElmIHZhbHVlIGlzIHVuZGVmaW5lZCwgbnVsbCBvciBibGFuaywgcmV0dXJucyBudWxsLCBvdGhlcndpc2UgcmV0dXJucyB0aGUgdmFsdWVcbiAqIEBwYXJhbSB7VH0gdmFsdWVcbiAqIEByZXR1cm5zIHtUIHwgbnVsbH1cbiAqL1xuZnVuY3Rpb24gbWFrZU51bGwodmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbn1cbmZ1bmN0aW9uIGV4aXN0cyh2YWx1ZSwgYWxsb3dFbXB0eVN0cmluZykge1xuICAgIGlmIChhbGxvd0VtcHR5U3RyaW5nID09PSB2b2lkIDApIHsgYWxsb3dFbXB0eVN0cmluZyA9IGZhbHNlOyB9XG4gICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgKHZhbHVlICE9PSAnJyB8fCBhbGxvd0VtcHR5U3RyaW5nKTtcbn1cbmZ1bmN0aW9uIG1pc3NpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gIWV4aXN0cyh2YWx1ZSk7XG59XG5mdW5jdGlvbiBtaXNzaW5nT3JFbXB0eSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsIHx8IHZhbHVlLmxlbmd0aCA9PT0gMDtcbn1cbmZ1bmN0aW9uIHRvU3RyaW5nT3JOdWxsKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgdHlwZW9mIHZhbHVlLnRvU3RyaW5nID09PSAnZnVuY3Rpb24nID8gdmFsdWUudG9TdHJpbmcoKSA6IG51bGw7XG59XG4vLyBmb3IgcGFyc2luZyBodG1sIGF0dHJpYnV0ZXMsIHdoZXJlIHdlIHdhbnQgZW1wdHkgc3RyaW5ncyBhbmQgbWlzc2luZyBhdHRyaWJ1dGVzIHRvIGJlIHVuZGVmaW5lZFxuZnVuY3Rpb24gYXR0clRvTnVtYmVyKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gdW5kZWZpbmVkIG9yIGVtcHR5IG1lYW5zIGlnbm9yZSB0aGUgdmFsdWVcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgIC8vIG51bGwgb3IgYmxhbmsgbWVhbnMgY2xlYXJcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiBpc05hTih2YWx1ZSkgPyB1bmRlZmluZWQgOiB2YWx1ZTtcbiAgICB9XG4gICAgdmFyIHZhbHVlUGFyc2VkID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICByZXR1cm4gaXNOYU4odmFsdWVQYXJzZWQpID8gdW5kZWZpbmVkIDogdmFsdWVQYXJzZWQ7XG59XG4vLyBmb3IgcGFyc2luZyBodG1sIGF0dHJpYnV0ZXMsIHdoZXJlIHdlIHdhbnQgZW1wdHkgc3RyaW5ncyBhbmQgbWlzc2luZyBhdHRyaWJ1dGVzIHRvIGJlIHVuZGVmaW5lZFxuZnVuY3Rpb24gYXR0clRvQm9vbGVhbih2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIHVuZGVmaW5lZCBvciBlbXB0eSBtZWFucyBpZ25vcmUgdGhlIHZhbHVlXG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnJykge1xuICAgICAgICAvLyBudWxsIG1lYW5zIGNsZWFyXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIC8vIGlmIHNpbXBsZSBib29sZWFuLCByZXR1cm4gdGhlIGJvb2xlYW5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICAvLyBpZiBlcXVhbCB0byB0aGUgc3RyaW5nICd0cnVlJyAoaWdub3JpbmcgY2FzZSkgdGhlbiByZXR1cm4gdHJ1ZVxuICAgIHJldHVybiAoL3RydWUvaSkudGVzdCh2YWx1ZSk7XG59XG4vLyBmb3IgcGFyc2luZyBodG1sIGF0dHJpYnV0ZXMsIHdoZXJlIHdlIHdhbnQgZW1wdHkgc3RyaW5ncyBhbmQgbWlzc2luZyBhdHRyaWJ1dGVzIHRvIGJlIHVuZGVmaW5lZFxuZnVuY3Rpb24gYXR0clRvU3RyaW5nKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IG51bGwgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuLyoqIEBkZXByZWNhdGVkICovXG5mdW5jdGlvbiByZWZlcmVuY2VDb21wYXJlKGxlZnQsIHJpZ2h0KSB7XG4gICAgaWYgKGxlZnQgPT0gbnVsbCAmJiByaWdodCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAobGVmdCA9PSBudWxsICYmIHJpZ2h0ICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAobGVmdCAhPSBudWxsICYmIHJpZ2h0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQ7XG59XG5mdW5jdGlvbiBqc29uRXF1YWxzKHZhbDEsIHZhbDIpIHtcbiAgICB2YXIgdmFsMUpzb24gPSB2YWwxID8gSlNPTi5zdHJpbmdpZnkodmFsMSkgOiBudWxsO1xuICAgIHZhciB2YWwySnNvbiA9IHZhbDIgPyBKU09OLnN0cmluZ2lmeSh2YWwyKSA6IG51bGw7XG4gICAgcmV0dXJuIHZhbDFKc29uID09PSB2YWwySnNvbjtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDb21wYXJhdG9yKHZhbHVlQSwgdmFsdWVCLCBhY2NlbnRlZENvbXBhcmUpIHtcbiAgICBpZiAoYWNjZW50ZWRDb21wYXJlID09PSB2b2lkIDApIHsgYWNjZW50ZWRDb21wYXJlID0gZmFsc2U7IH1cbiAgICB2YXIgdmFsdWVBTWlzc2luZyA9IHZhbHVlQSA9PSBudWxsO1xuICAgIHZhciB2YWx1ZUJNaXNzaW5nID0gdmFsdWVCID09IG51bGw7XG4gICAgLy8gdGhpcyBpcyBmb3IgYWdncmVnYXRpb25zIHN1bSBhbmQgYXZnLCB3aGVyZSB0aGUgcmVzdWx0IGNhbiBiZSBhIG51bWJlciB0aGF0IGlzIHdyYXBwZWQuXG4gICAgLy8gaWYgd2UgZGlkbid0IGRvIHRoaXMsIHRoZW4gdGhlIHRvU3RyaW5nKCkgdmFsdWUgd291bGQgYmUgdXNlZCwgd2hpY2ggd291bGQgcmVzdWx0IGluXG4gICAgLy8gdGhlIHN0cmluZ3MgZ2V0dGluZyB1c2VkIGluc3RlYWQgb2YgdGhlIG51bWJlcnMuXG4gICAgaWYgKHZhbHVlQSAmJiB2YWx1ZUEudG9OdW1iZXIpIHtcbiAgICAgICAgdmFsdWVBID0gdmFsdWVBLnRvTnVtYmVyKCk7XG4gICAgfVxuICAgIGlmICh2YWx1ZUIgJiYgdmFsdWVCLnRvTnVtYmVyKSB7XG4gICAgICAgIHZhbHVlQiA9IHZhbHVlQi50b051bWJlcigpO1xuICAgIH1cbiAgICBpZiAodmFsdWVBTWlzc2luZyAmJiB2YWx1ZUJNaXNzaW5nKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBpZiAodmFsdWVBTWlzc2luZykge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmICh2YWx1ZUJNaXNzaW5nKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkb1F1aWNrQ29tcGFyZShhLCBiKSB7XG4gICAgICAgIHJldHVybiAoYSA+IGIgPyAxIDogKGEgPCBiID8gLTEgOiAwKSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWVBICE9PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZG9RdWlja0NvbXBhcmUodmFsdWVBLCB2YWx1ZUIpO1xuICAgIH1cbiAgICBpZiAoIWFjY2VudGVkQ29tcGFyZSkge1xuICAgICAgICByZXR1cm4gZG9RdWlja0NvbXBhcmUodmFsdWVBLCB2YWx1ZUIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB1c2luZyBsb2NhbCBjb21wYXJlIGFsc28gYWxsb3dzIGNoaW5lc2UgY29tcGFyaXNvbnNcbiAgICAgICAgcmV0dXJuIHZhbHVlQS5sb2NhbGVDb21wYXJlKHZhbHVlQik7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIC8vIGlmIHNvbWV0aGluZyB3cm9uZyB3aXRoIGxvY2FsZUNvbXBhcmUsIGVnIG5vdCBzdXBwb3J0ZWRcbiAgICAgICAgLy8gYnkgYnJvd3NlciwgdGhlbiBqdXN0IGNvbnRpbnVlIHdpdGggdGhlIHF1aWNrIG9uZVxuICAgICAgICByZXR1cm4gZG9RdWlja0NvbXBhcmUodmFsdWVBLCB2YWx1ZUIpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgU2V0IHx8IG9iamVjdCBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICB2YXIgYXJyXzEgPSBbXTtcbiAgICAgICAgb2JqZWN0LmZvckVhY2goZnVuY3Rpb24gKHZhbHVlKSB7IHJldHVybiBhcnJfMS5wdXNoKHZhbHVlKTsgfSk7XG4gICAgICAgIHJldHVybiBhcnJfMTtcbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXMob2JqZWN0KTtcbn1cblxudmFyIEdlbmVyaWNVdGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgbWFrZU51bGw6IG1ha2VOdWxsLFxuICAgIGV4aXN0czogZXhpc3RzLFxuICAgIG1pc3Npbmc6IG1pc3NpbmcsXG4gICAgbWlzc2luZ09yRW1wdHk6IG1pc3NpbmdPckVtcHR5LFxuICAgIHRvU3RyaW5nT3JOdWxsOiB0b1N0cmluZ09yTnVsbCxcbiAgICBhdHRyVG9OdW1iZXI6IGF0dHJUb051bWJlcixcbiAgICBhdHRyVG9Cb29sZWFuOiBhdHRyVG9Cb29sZWFuLFxuICAgIGF0dHJUb1N0cmluZzogYXR0clRvU3RyaW5nLFxuICAgIHJlZmVyZW5jZUNvbXBhcmU6IHJlZmVyZW5jZUNvbXBhcmUsXG4gICAganNvbkVxdWFsczoganNvbkVxdWFscyxcbiAgICBkZWZhdWx0Q29tcGFyYXRvcjogZGVmYXVsdENvbXBhcmF0b3IsXG4gICAgdmFsdWVzOiB2YWx1ZXNcbn0pO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgQ29sdW1uS2V5Q3JlYXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb2x1bW5LZXlDcmVhdG9yKCkge1xuICAgICAgICB0aGlzLmV4aXN0aW5nS2V5cyA9IHt9O1xuICAgIH1cbiAgICBDb2x1bW5LZXlDcmVhdG9yLnByb3RvdHlwZS5hZGRFeGlzdGluZ0tleXMgPSBmdW5jdGlvbiAoa2V5cykge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMuZXhpc3RpbmdLZXlzW2tleXNbaV1dID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uS2V5Q3JlYXRvci5wcm90b3R5cGUuZ2V0VW5pcXVlS2V5ID0gZnVuY3Rpb24gKGNvbElkLCBjb2xGaWVsZCkge1xuICAgICAgICAvLyBpbiBjYXNlIHVzZXIgcGFzc2VkIGluIG51bWJlciBmb3IgY29sSWQsIGNvbnZlcnQgdG8gc3RyaW5nXG4gICAgICAgIGNvbElkID0gdG9TdHJpbmdPck51bGwoY29sSWQpO1xuICAgICAgICB2YXIgY291bnQgPSAwO1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgdmFyIGlkVG9UcnkgPSB2b2lkIDA7XG4gICAgICAgICAgICBpZiAoY29sSWQpIHtcbiAgICAgICAgICAgICAgICBpZFRvVHJ5ID0gY29sSWQ7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlkVG9UcnkgKz0gJ18nICsgY291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY29sRmllbGQpIHtcbiAgICAgICAgICAgICAgICBpZFRvVHJ5ID0gY29sRmllbGQ7XG4gICAgICAgICAgICAgICAgaWYgKGNvdW50ICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlkVG9UcnkgKz0gJ18nICsgY291bnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWRUb1RyeSA9ICcnICsgY291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuZXhpc3RpbmdLZXlzW2lkVG9UcnldKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5leGlzdGluZ0tleXNbaWRUb1RyeV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiBpZFRvVHJ5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIENvbHVtbktleUNyZWF0b3I7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG5mdW5jdGlvbiBpdGVyYXRlT2JqZWN0KG9iamVjdCwgY2FsbGJhY2spIHtcbiAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7XG4gICAgICAgIG9iamVjdC5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwgaW5kZXgpIHsgcmV0dXJuIGNhbGxiYWNrKFwiXCIgKyBpbmRleCwgdmFsdWUpOyB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIE9iamVjdC5rZXlzKG9iamVjdCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBjYWxsYmFjayhrZXksIG9iamVjdFtrZXldKTsgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gY2xvbmVPYmplY3Qob2JqZWN0KSB7XG4gICAgdmFyIGNvcHkgPSB7fTtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iamVjdCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuICAgICAgICB2YXIgdmFsdWUgPSBvYmplY3Rba2V5XTtcbiAgICAgICAgY29weVtrZXldID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xufVxuZnVuY3Rpb24gZGVlcENsb25lT2JqZWN0KG9iamVjdCkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG9iamVjdCkpO1xufVxuLy8gcmV0dXJucyBjb3B5IG9mIGFuIG9iamVjdCwgZG9pbmcgYSBkZWVwIGNsb25lIG9mIGFueSBvYmplY3RzIHdpdGggdGhhdCBvYmplY3QuXG4vLyB0aGlzIGlzIHVzZWQgZm9yIGVnIGNyZWF0aW5nIGNvcGllcyBvZiBDb2x1bW4gRGVmaW5pdGlvbnMsIHdoZXJlIHdlIHdhbnQgdG9cbi8vIGRlZXAgY29weSBhbGwgb2JqZWN0cywgYnV0IGRvIG5vdCB3YW50IHRvIGRlZXAgY29weSBmdW5jdGlvbnMgKGVnIHdoZW4gdXNlciBwcm92aWRlc1xuLy8gYSBmdW5jdGlvbiBvciBjbGFzcyBmb3IgY29sRGVmLmNlbGxSZW5kZXJlcilcbmZ1bmN0aW9uIGRlZXBDbG9uZURlZmluaXRpb24ob2JqZWN0LCBrZXlzVG9Ta2lwKSB7XG4gICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgb2JqID0gb2JqZWN0O1xuICAgIHZhciByZXMgPSB7fTtcbiAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoa2V5c1RvU2tpcCAmJiBrZXlzVG9Ta2lwLmluZGV4T2Yoa2V5KSA+PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHZhbHVlID0gb2JqW2tleV07XG4gICAgICAgIC8vICdzaW1wbGUgb2JqZWN0JyBtZWFucyBhIGJ1bmNoIG9mIGtleS92YWx1ZSBwYWlycywgZWcge2ZpbHRlcjogJ215RmlsdGVyJ30uIGl0IGRvZXNcbiAgICAgICAgLy8gTk9UIGluY2x1ZGUgdGhlIGZvbGxvd2luZzpcbiAgICAgICAgLy8gMSkgYXJyYXlzXG4gICAgICAgIC8vIDIpIGZ1bmN0aW9ucyBvciBjbGFzc2VzIChlZyBDb2x1bW5BUEkgaW5zdGFuY2UpXG4gICAgICAgIHZhciBzb3VyY2VJc1NpbXBsZU9iamVjdCA9IGlzTm9uTnVsbE9iamVjdCh2YWx1ZSkgJiYgdmFsdWUuY29uc3RydWN0b3IgPT09IE9iamVjdDtcbiAgICAgICAgaWYgKHNvdXJjZUlzU2ltcGxlT2JqZWN0KSB7XG4gICAgICAgICAgICByZXNba2V5XSA9IGRlZXBDbG9uZURlZmluaXRpb24odmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBnZXRQcm9wZXJ0eShvYmplY3QsIGtleSkge1xuICAgIHJldHVybiBvYmplY3Rba2V5XTtcbn1cbmZ1bmN0aW9uIHNldFByb3BlcnR5KG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG59XG4vKipcbiAqIFdpbGwgY29weSB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMgZnJvbSBgc291cmNlYCBpbnRvIHRoZSBlcXVpdmFsZW50IHByb3BlcnRpZXMgb24gYHRhcmdldGAsIGlnbm9yaW5nIHByb3BlcnRpZXMgd2l0aFxuICogYSB2YWx1ZSBvZiBgdW5kZWZpbmVkYC5cbiAqL1xuZnVuY3Rpb24gY29weVByb3BlcnRpZXNJZlByZXNlbnQoc291cmNlLCB0YXJnZXQpIHtcbiAgICB2YXIgcHJvcGVydGllcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMjsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHByb3BlcnRpZXNbX2kgLSAyXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIHByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAocCkgeyByZXR1cm4gY29weVByb3BlcnR5SWZQcmVzZW50KHNvdXJjZSwgdGFyZ2V0LCBwKTsgfSk7XG59XG4vKipcbiAqIFdpbGwgY29weSB0aGUgc3BlY2lmaWVkIHByb3BlcnR5IGZyb20gYHNvdXJjZWAgaW50byB0aGUgZXF1aXZhbGVudCBwcm9wZXJ0eSBvbiBgdGFyZ2V0YCwgdW5sZXNzIHRoZSBwcm9wZXJ0eSBoYXMgYVxuICogdmFsdWUgb2YgYHVuZGVmaW5lZGAuIElmIGEgdHJhbnNmb3JtYXRpb24gaXMgcHJvdmlkZWQsIGl0IHdpbGwgYmUgYXBwbGllZCB0byB0aGUgdmFsdWUgYmVmb3JlIGJlaW5nIHNldCBvbiBgdGFyZ2V0YC5cbiAqL1xuZnVuY3Rpb24gY29weVByb3BlcnR5SWZQcmVzZW50KHNvdXJjZSwgdGFyZ2V0LCBwcm9wZXJ0eSwgdHJhbnNmb3JtKSB7XG4gICAgdmFyIHZhbHVlID0gZ2V0UHJvcGVydHkoc291cmNlLCBwcm9wZXJ0eSk7XG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgc2V0UHJvcGVydHkodGFyZ2V0LCBwcm9wZXJ0eSwgdHJhbnNmb3JtID8gdHJhbnNmb3JtKHZhbHVlKSA6IHZhbHVlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBnZXRBbGxLZXlzSW5PYmplY3RzKG9iamVjdHMpIHtcbiAgICB2YXIgYWxsVmFsdWVzID0ge307XG4gICAgb2JqZWN0cy5maWx0ZXIoZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gb2JqICE9IG51bGw7IH0pLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gYWxsVmFsdWVzW2tleV0gPSBudWxsOyB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMoYWxsVmFsdWVzKTtcbn1cbmZ1bmN0aW9uIGdldEFsbFZhbHVlc0luT2JqZWN0KG9iaikge1xuICAgIGlmICghb2JqKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdmFyIGFueU9iamVjdCA9IE9iamVjdDtcbiAgICBpZiAodHlwZW9mIGFueU9iamVjdC52YWx1ZXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGFueU9iamVjdC52YWx1ZXMob2JqKTtcbiAgICB9XG4gICAgdmFyIHJldCA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIG9iai5wcm9wZXJ0eUlzRW51bWVyYWJsZShrZXkpKSB7XG4gICAgICAgICAgICByZXQucHVzaChvYmpba2V5XSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbn1cbmZ1bmN0aW9uIG1lcmdlRGVlcChkZXN0LCBzb3VyY2UsIGNvcHlVbmRlZmluZWQsIG1ha2VDb3B5T2ZTaW1wbGVPYmplY3RzKSB7XG4gICAgaWYgKGNvcHlVbmRlZmluZWQgPT09IHZvaWQgMCkgeyBjb3B5VW5kZWZpbmVkID0gdHJ1ZTsgfVxuICAgIGlmIChtYWtlQ29weU9mU2ltcGxlT2JqZWN0cyA9PT0gdm9pZCAwKSB7IG1ha2VDb3B5T2ZTaW1wbGVPYmplY3RzID0gZmFsc2U7IH1cbiAgICBpZiAoIWV4aXN0cyhzb3VyY2UpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaXRlcmF0ZU9iamVjdChzb3VyY2UsIGZ1bmN0aW9uIChrZXksIHNvdXJjZVZhbHVlKSB7XG4gICAgICAgIHZhciBkZXN0VmFsdWUgPSBkZXN0W2tleV07XG4gICAgICAgIGlmIChkZXN0VmFsdWUgPT09IHNvdXJjZVZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2hlbiBjcmVhdGluZyBwYXJhbXMsIHdlIGRvbid0IHdhbnQgdG8ganVzdCBjb3B5IG9iamVjdHMgb3Zlci4gb3RoZXJ3aXNlIG1lcmdpbmcgQ29sRGVmcyAoZWcgRGVmYXVsdENvbERlZlxuICAgICAgICAvLyBhbmQgQ29sdW1uIFR5cGVzKSB3b3VsZCByZXN1bHQgaW4gcGFyYW1zIGdldHRpbmcgc2hhcmVkIGJldHdlZW4gb2JqZWN0cy5cbiAgICAgICAgLy8gYnkgcHV0dGluZyBhbiBlbXB0eSB2YWx1ZSBpbnRvIGRlc3RWYWx1ZSBmaXJzdCwgaXQgbWVhbnMgd2UgZW5kIHVwIGNvcHlpbmcgb3ZlciB2YWx1ZXMgZnJvbVxuICAgICAgICAvLyB0aGUgc291cmNlIG9iamVjdCwgcmF0aGVyIHRoYW4ganVzdCBjb3B5aW5nIGluIHRoZSBzb3VyY2Ugb2JqZWN0IGluIGl0J3MgZW50aXJldHkuXG4gICAgICAgIGlmIChtYWtlQ29weU9mU2ltcGxlT2JqZWN0cykge1xuICAgICAgICAgICAgdmFyIG9iamVjdElzRHVlVG9CZUNvcGllZCA9IGRlc3RWYWx1ZSA9PSBudWxsICYmIHNvdXJjZVZhbHVlICE9IG51bGw7XG4gICAgICAgICAgICBpZiAob2JqZWN0SXNEdWVUb0JlQ29waWVkKSB7XG4gICAgICAgICAgICAgICAgLy8gJ3NpbXBsZSBvYmplY3QnIG1lYW5zIGEgYnVuY2ggb2Yga2V5L3ZhbHVlIHBhaXJzLCBlZyB7ZmlsdGVyOiAnbXlGaWx0ZXInfSwgYXMgb3Bwb3NlZFxuICAgICAgICAgICAgICAgIC8vIHRvIGEgQ2xhc3MgaW5zdGFuY2UgKHN1Y2ggYXMgQ29sdW1uQVBJIGluc3RhbmNlKS5cbiAgICAgICAgICAgICAgICB2YXIgc291cmNlSXNTaW1wbGVPYmplY3QgPSB0eXBlb2Ygc291cmNlVmFsdWUgPT09ICdvYmplY3QnICYmIHNvdXJjZVZhbHVlLmNvbnN0cnVjdG9yID09PSBPYmplY3Q7XG4gICAgICAgICAgICAgICAgdmFyIGRvbnRDb3B5ID0gc291cmNlSXNTaW1wbGVPYmplY3Q7XG4gICAgICAgICAgICAgICAgaWYgKGRvbnRDb3B5KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3RWYWx1ZSA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBkZXN0W2tleV0gPSBkZXN0VmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChpc05vbk51bGxPYmplY3Qoc291cmNlVmFsdWUpICYmIGlzTm9uTnVsbE9iamVjdChkZXN0VmFsdWUpICYmICFBcnJheS5pc0FycmF5KGRlc3RWYWx1ZSkpIHtcbiAgICAgICAgICAgIG1lcmdlRGVlcChkZXN0VmFsdWUsIHNvdXJjZVZhbHVlLCBjb3B5VW5kZWZpbmVkLCBtYWtlQ29weU9mU2ltcGxlT2JqZWN0cyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29weVVuZGVmaW5lZCB8fCBzb3VyY2VWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkZXN0W2tleV0gPSBzb3VyY2VWYWx1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuZnVuY3Rpb24gbWlzc2luZ09yRW1wdHlPYmplY3QodmFsdWUpIHtcbiAgICByZXR1cm4gbWlzc2luZyh2YWx1ZSkgfHwgT2JqZWN0LmtleXModmFsdWUpLmxlbmd0aCA9PT0gMDtcbn1cbmZ1bmN0aW9uIGdldChzb3VyY2UsIGV4cHJlc3Npb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgIGlmIChzb3VyY2UgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgIH1cbiAgICB2YXIga2V5cyA9IGV4cHJlc3Npb24uc3BsaXQoJy4nKTtcbiAgICB2YXIgb2JqZWN0VG9SZWFkID0gc291cmNlO1xuICAgIHdoaWxlIChrZXlzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgb2JqZWN0VG9SZWFkID0gb2JqZWN0VG9SZWFkW2tleXMuc2hpZnQoKV07XG4gICAgICAgIGlmIChvYmplY3RUb1JlYWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgdmFsdWUgPSBvYmplY3RUb1JlYWRba2V5c1swXV07XG4gICAgcmV0dXJuIHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6IGRlZmF1bHRWYWx1ZTtcbn1cbmZ1bmN0aW9uIHNldCh0YXJnZXQsIGV4cHJlc3Npb24sIHZhbHVlKSB7XG4gICAgaWYgKHRhcmdldCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGtleXMgPSBleHByZXNzaW9uLnNwbGl0KCcuJyk7XG4gICAgdmFyIG9iamVjdFRvVXBkYXRlID0gdGFyZ2V0O1xuICAgIHdoaWxlIChrZXlzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgb2JqZWN0VG9VcGRhdGUgPSBvYmplY3RUb1VwZGF0ZVtrZXlzLnNoaWZ0KCldO1xuICAgICAgICBpZiAob2JqZWN0VG9VcGRhdGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIG9iamVjdFRvVXBkYXRlW2tleXNbMF1dID0gdmFsdWU7XG59XG5mdW5jdGlvbiBkZWVwRnJlZXplKG9iamVjdCkge1xuICAgIE9iamVjdC5mcmVlemUob2JqZWN0KTtcbiAgICB2YWx1ZXMob2JqZWN0KS5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgIGlmIChpc05vbk51bGxPYmplY3QodikgfHwgdHlwZW9mIHYgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGRlZXBGcmVlemUodik7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gb2JqZWN0O1xufVxuZnVuY3Rpb24gZ2V0VmFsdWVVc2luZ0ZpZWxkKGRhdGEsIGZpZWxkLCBmaWVsZENvbnRhaW5zRG90cykge1xuICAgIGlmICghZmllbGQgfHwgIWRhdGEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBpZiBubyAnLicsIHRoZW4gaXQncyBub3QgYSBkZWVwIHZhbHVlXG4gICAgaWYgKCFmaWVsZENvbnRhaW5zRG90cykge1xuICAgICAgICByZXR1cm4gZGF0YVtmaWVsZF07XG4gICAgfVxuICAgIC8vIG90aGVyd2lzZSBpdCBpcyBhIGRlZXAgdmFsdWUsIHNvIG5lZWQgdG8gZGlnIGZvciBpdFxuICAgIHZhciBmaWVsZHMgPSBmaWVsZC5zcGxpdCgnLicpO1xuICAgIHZhciBjdXJyZW50T2JqZWN0ID0gZGF0YTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpZWxkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoY3VycmVudE9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnRPYmplY3QgPSBjdXJyZW50T2JqZWN0W2ZpZWxkc1tpXV07XG4gICAgfVxuICAgIHJldHVybiBjdXJyZW50T2JqZWN0O1xufVxuLy8gdXNlZCBieSBDb2x1bW5BUEkgYW5kIEdyaWRBUEkgdG8gcmVtb3ZlIGFsbCByZWZlcmVuY2VzLCBzbyBrZWVwaW5nIGdyaWQgaW4gbWVtb3J5IHJlc3VsdGluZyBpbiBhXG4vLyBtZW1vcnkgbGVhayBpZiB1c2VyIGlzIG5vdCBkaXNwb3Npbmcgb2YgdGhlIEdyaWRBUEkgb3IgQ29sdW1uQXBpIHJlZmVyZW5jZXNcbmZ1bmN0aW9uIHJlbW92ZUFsbFJlZmVyZW5jZXMob2JqLCBvYmplY3ROYW1lKSB7XG4gICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gb2JqW2tleV07XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gcmVwbGFjZSBhbGwgdGhlIEBhdXRvd2lyZWQgc2VydmljZXMsIHdoaWNoIGFyZSBvYmplY3RzLiBhbnkgc2ltcGxlIHR5cGVzIChib29sZWFuLCBzdHJpbmcgZXRjKVxuICAgICAgICAvLyB3ZSBkb24ndCBjYXJlIGFib3V0XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBvYmpba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHZhciBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmopO1xuICAgIHZhciBwcm9wZXJ0aWVzID0ge307XG4gICAgT2JqZWN0LmtleXMocHJvdG8pLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgdmFsdWUgPSBwcm90b1trZXldO1xuICAgICAgICAvLyBsZWF2ZSBhbGwgYmFzaWMgdHlwZXMgLSB0aGlzIGlzIG5lZWRlZCBmb3IgR3JpZEFQSSB0byBsZWF2ZSB0aGUgXCJkZXN0cm95ZWQ6IGJvb2xlYW5cIiBhdHRyaWJ1dGUgYWxvbmVcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdmFyIGZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogXCIgKyBvYmplY3ROYW1lICsgXCIgZnVuY3Rpb24gXCIgKyBrZXkgKyBcIigpIGNhbm5vdCBiZSBjYWxsZWQgYXMgdGhlIGdyaWQgaGFzIGJlZW4gZGVzdHJveWVkLlxcbiAgICAgICAgICAgICAgICAgICAgIFBsZWFzZSBkb24ndCBjYWxsIGdyaWQgQVBJIGZ1bmN0aW9ucyBvbiBkZXN0cm95ZWQgZ3JpZHMgLSBhcyBhIG1hdHRlciBvZiBmYWN0IHlvdSBzaG91bGRuJ3RcXG4gICAgICAgICAgICAgICAgICAgICBiZSBrZWVwaW5nIHRoZSBBUEkgcmVmZXJlbmNlLCB5b3VyIGFwcGxpY2F0aW9uIGhhcyBhIG1lbW9yeSBsZWFrISBSZW1vdmUgdGhlIEFQSSByZWZlcmVuY2VcXG4gICAgICAgICAgICAgICAgICAgICB3aGVuIHRoZSBncmlkIGlzIGRlc3Ryb3llZC5cIik7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcHJvcGVydGllc1trZXldID0geyB2YWx1ZTogZnVuYywgd3JpdGFibGU6IHRydWUgfTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKG9iaiwgcHJvcGVydGllcyk7XG59XG5mdW5jdGlvbiBpc05vbk51bGxPYmplY3QodmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbDtcbn1cblxudmFyIE9iamVjdFV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBpdGVyYXRlT2JqZWN0OiBpdGVyYXRlT2JqZWN0LFxuICAgIGNsb25lT2JqZWN0OiBjbG9uZU9iamVjdCxcbiAgICBkZWVwQ2xvbmVPYmplY3Q6IGRlZXBDbG9uZU9iamVjdCxcbiAgICBkZWVwQ2xvbmVEZWZpbml0aW9uOiBkZWVwQ2xvbmVEZWZpbml0aW9uLFxuICAgIGdldFByb3BlcnR5OiBnZXRQcm9wZXJ0eSxcbiAgICBzZXRQcm9wZXJ0eTogc2V0UHJvcGVydHksXG4gICAgY29weVByb3BlcnRpZXNJZlByZXNlbnQ6IGNvcHlQcm9wZXJ0aWVzSWZQcmVzZW50LFxuICAgIGNvcHlQcm9wZXJ0eUlmUHJlc2VudDogY29weVByb3BlcnR5SWZQcmVzZW50LFxuICAgIGdldEFsbEtleXNJbk9iamVjdHM6IGdldEFsbEtleXNJbk9iamVjdHMsXG4gICAgZ2V0QWxsVmFsdWVzSW5PYmplY3Q6IGdldEFsbFZhbHVlc0luT2JqZWN0LFxuICAgIG1lcmdlRGVlcDogbWVyZ2VEZWVwLFxuICAgIG1pc3NpbmdPckVtcHR5T2JqZWN0OiBtaXNzaW5nT3JFbXB0eU9iamVjdCxcbiAgICBnZXQ6IGdldCxcbiAgICBzZXQ6IHNldCxcbiAgICBkZWVwRnJlZXplOiBkZWVwRnJlZXplLFxuICAgIGdldFZhbHVlVXNpbmdGaWVsZDogZ2V0VmFsdWVVc2luZ0ZpZWxkLFxuICAgIHJlbW92ZUFsbFJlZmVyZW5jZXM6IHJlbW92ZUFsbFJlZmVyZW5jZXMsXG4gICAgaXNOb25OdWxsT2JqZWN0OiBpc05vbk51bGxPYmplY3Rcbn0pO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgZG9PbmNlRmxhZ3MgPSB7fTtcbi8qKlxuICogSWYgdGhlIGtleSB3YXMgcGFzc2VkIGJlZm9yZSwgdGhlbiBkb2Vzbid0IGV4ZWN1dGUgdGhlIGZ1bmNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmNcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAqL1xuZnVuY3Rpb24gZG9PbmNlKGZ1bmMsIGtleSkge1xuICAgIGlmIChkb09uY2VGbGFnc1trZXldKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZnVuYygpO1xuICAgIGRvT25jZUZsYWdzW2tleV0gPSB0cnVlO1xufVxuZnVuY3Rpb24gZ2V0RnVuY3Rpb25OYW1lKGZ1bmNDb25zdHJ1Y3Rvcikge1xuICAgIC8vIGZvciBldmVyeSBvdGhlciBicm93c2VyIGluIHRoZSB3b3JsZFxuICAgIGlmIChmdW5jQ29uc3RydWN0b3IubmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY0NvbnN0cnVjdG9yLm5hbWU7XG4gICAgfVxuICAgIC8vIGZvciB0aGUgcGVzdGlsZW5jZSB0aGF0IGlzIGllMTFcbiAgICB2YXIgbWF0Y2hlcyA9IC9mdW5jdGlvblxccysoW15cXChdKykvLmV4ZWMoZnVuY0NvbnN0cnVjdG9yLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiBtYXRjaGVzICYmIG1hdGNoZXMubGVuZ3RoID09PSAyID8gbWF0Y2hlc1sxXS50cmltKCkgOiBudWxsO1xufVxuZnVuY3Rpb24gaXNGdW5jdGlvbih2YWwpIHtcbiAgICByZXR1cm4gISEodmFsICYmIHZhbC5jb25zdHJ1Y3RvciAmJiB2YWwuY2FsbCAmJiB2YWwuYXBwbHkpO1xufVxuZnVuY3Rpb24gZXhlY3V0ZUluQVdoaWxlKGZ1bmNzKSB7XG4gICAgZXhlY3V0ZUFmdGVyKGZ1bmNzLCA0MDApO1xufVxudmFyIGV4ZWN1dGVOZXh0Vk1UdXJuRnVuY3MgPSBbXTtcbnZhciBleGVjdXRlTmV4dFZNVHVyblBlbmRpbmcgPSBmYWxzZTtcbmZ1bmN0aW9uIGV4ZWN1dGVOZXh0Vk1UdXJuKGZ1bmMpIHtcbiAgICBleGVjdXRlTmV4dFZNVHVybkZ1bmNzLnB1c2goZnVuYyk7XG4gICAgaWYgKGV4ZWN1dGVOZXh0Vk1UdXJuUGVuZGluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGV4ZWN1dGVOZXh0Vk1UdXJuUGVuZGluZyA9IHRydWU7XG4gICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZnVuY3NDb3B5ID0gZXhlY3V0ZU5leHRWTVR1cm5GdW5jcy5zbGljZSgpO1xuICAgICAgICBleGVjdXRlTmV4dFZNVHVybkZ1bmNzLmxlbmd0aCA9IDA7XG4gICAgICAgIGV4ZWN1dGVOZXh0Vk1UdXJuUGVuZGluZyA9IGZhbHNlO1xuICAgICAgICBmdW5jc0NvcHkuZm9yRWFjaChmdW5jdGlvbiAoZnVuYykgeyByZXR1cm4gZnVuYygpOyB9KTtcbiAgICB9LCAwKTtcbn1cbmZ1bmN0aW9uIGV4ZWN1dGVBZnRlcihmdW5jcywgbWlsbGlzZWNvbmRzKSB7XG4gICAgaWYgKG1pbGxpc2Vjb25kcyA9PT0gdm9pZCAwKSB7IG1pbGxpc2Vjb25kcyA9IDA7IH1cbiAgICBpZiAoZnVuY3MubGVuZ3RoID4gMCkge1xuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBmdW5jcy5mb3JFYWNoKGZ1bmN0aW9uIChmdW5jKSB7IHJldHVybiBmdW5jKCk7IH0pOyB9LCBtaWxsaXNlY29uZHMpO1xuICAgIH1cbn1cbi8qKlxuICogZnJvbSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yNDAwNDc5MS9jYW4tc29tZW9uZS1leHBsYWluLXRoZS1kZWJvdW5jZS1mdW5jdGlvbi1pbi1qYXZhc2NyaXB0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBiZSBkZWJvdW5jZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3YWl0IFRoZSB0aW1lIGluIG1zIHRvIGRlYm91bmNlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGltbWVkaWF0ZSBJZiBpdCBzaG91bGQgcnVuIGltbWVkaWF0ZWx5IG9yIHdhaXQgZm9yIHRoZSBpbml0aWFsIGRlYm91bmNlIGRlbGF5XG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gVGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICovXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICBpZiAoaW1tZWRpYXRlID09PSB2b2lkIDApIHsgaW1tZWRpYXRlID0gZmFsc2U7IH1cbiAgICAvLyAncHJpdmF0ZScgdmFyaWFibGUgZm9yIGluc3RhbmNlXG4gICAgLy8gVGhlIHJldHVybmVkIGZ1bmN0aW9uIHdpbGwgYmUgYWJsZSB0byByZWZlcmVuY2UgdGhpcyBkdWUgdG8gY2xvc3VyZS5cbiAgICAvLyBFYWNoIGNhbGwgdG8gdGhlIHJldHVybmVkIGZ1bmN0aW9uIHdpbGwgc2hhcmUgdGhpcyBjb21tb24gdGltZXIuXG4gICAgdmFyIHRpbWVvdXQ7XG4gICAgLy8gQ2FsbGluZyBkZWJvdW5jZSByZXR1cm5zIGEgbmV3IGFub255bW91cyBmdW5jdGlvblxuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBhcmdzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVmZXJlbmNlIHRoZSBjb250ZXh0IGFuZCBhcmdzIGZvciB0aGUgc2V0VGltZW91dCBmdW5jdGlvblxuICAgICAgICB2YXIgY29udGV4dCA9IHRoaXM7XG4gICAgICAgIC8vIFNob3VsZCB0aGUgZnVuY3Rpb24gYmUgY2FsbGVkIG5vdz8gSWYgaW1tZWRpYXRlIGlzIHRydWVcbiAgICAgICAgLy8gICBhbmQgbm90IGFscmVhZHkgaW4gYSB0aW1lb3V0IHRoZW4gdGhlIGFuc3dlciBpczogWWVzXG4gICAgICAgIHZhciBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgICAvLyBUaGlzIGlzIHRoZSBiYXNpYyBkZWJvdW5jZSBiZWhhdmlvdXIgd2hlcmUgeW91IGNhbiBjYWxsIHRoaXNcbiAgICAgICAgLy8gICBmdW5jdGlvbiBzZXZlcmFsIHRpbWVzLCBidXQgaXQgd2lsbCBvbmx5IGV4ZWN1dGUgb25jZVxuICAgICAgICAvLyAgIFtiZWZvcmUgb3IgYWZ0ZXIgaW1wb3NpbmcgYSBkZWxheV0uXG4gICAgICAgIC8vICAgRWFjaCB0aW1lIHRoZSByZXR1cm5lZCBmdW5jdGlvbiBpcyBjYWxsZWQsIHRoZSB0aW1lciBzdGFydHMgb3Zlci5cbiAgICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgLy8gU2V0IHRoZSBuZXcgdGltZW91dFxuICAgICAgICB0aW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gSW5zaWRlIHRoZSB0aW1lb3V0IGZ1bmN0aW9uLCBjbGVhciB0aGUgdGltZW91dCB2YXJpYWJsZVxuICAgICAgICAgICAgLy8gd2hpY2ggd2lsbCBsZXQgdGhlIG5leHQgZXhlY3V0aW9uIHJ1biB3aGVuIGluICdpbW1lZGlhdGUnIG1vZGVcbiAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGZ1bmN0aW9uIGFscmVhZHkgcmFuIHdpdGggdGhlIGltbWVkaWF0ZSBmbGFnXG4gICAgICAgICAgICBpZiAoIWltbWVkaWF0ZSkge1xuICAgICAgICAgICAgICAgIC8vIENhbGwgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uIHdpdGggYXBwbHlcbiAgICAgICAgICAgICAgICAvLyBhcHBseSBsZXRzIHlvdSBkZWZpbmUgdGhlICd0aGlzJyBvYmplY3QgYXMgd2VsbCBhcyB0aGUgYXJndW1lbnRzXG4gICAgICAgICAgICAgICAgLy8gICAgKGJvdGggY2FwdHVyZWQgYmVmb3JlIHNldFRpbWVvdXQpXG4gICAgICAgICAgICAgICAgZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgd2FpdCk7XG4gICAgICAgIC8vIEltbWVkaWF0ZSBtb2RlIGFuZCBubyB3YWl0IHRpbWVyPyBFeGVjdXRlIHRoZSBmdW5jdGlvbi4uXG4gICAgICAgIGlmIChjYWxsTm93KSB7XG4gICAgICAgICAgICBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfTtcbn1cbi8qKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYmUgdGhyb3R0bGVkXG4gKiBAcGFyYW0ge251bWJlcn0gd2FpdCBUaGUgdGltZSBpbiBtcyB0byB0aHJvdHRsZVxuICogQHJldHVybiB7RnVuY3Rpb259IFRoZSB0aHJvdHRsZWQgZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gdGhyb3R0bGUoZnVuYywgd2FpdCkge1xuICAgIHZhciBwcmV2aW91c0NhbGwgPSAwO1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBhcmdzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbnRleHQgPSB0aGlzO1xuICAgICAgICB2YXIgY3VycmVudENhbGwgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgaWYgKGN1cnJlbnRDYWxsIC0gcHJldmlvdXNDYWxsIDwgd2FpdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHByZXZpb3VzQ2FsbCA9IGN1cnJlbnRDYWxsO1xuICAgICAgICBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgIH07XG59XG5mdW5jdGlvbiB3YWl0VW50aWwoY29uZGl0aW9uLCBjYWxsYmFjaywgdGltZW91dCwgdGltZW91dE1lc3NhZ2UpIHtcbiAgICBpZiAodGltZW91dCA9PT0gdm9pZCAwKSB7IHRpbWVvdXQgPSAxMDA7IH1cbiAgICB2YXIgdGltZVN0YW1wID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgdmFyIGludGVydmFsID0gbnVsbDtcbiAgICB2YXIgZXhlY3V0ZWQgPSBmYWxzZTtcbiAgICB2YXIgaW50ZXJuYWxDYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlYWNoZWRUaW1lb3V0ID0gKChuZXcgRGF0ZSgpLmdldFRpbWUoKSkgLSB0aW1lU3RhbXApID4gdGltZW91dDtcbiAgICAgICAgaWYgKGNvbmRpdGlvbigpIHx8IHJlYWNoZWRUaW1lb3V0KSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgZXhlY3V0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKGludGVydmFsICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICAgICAgICAgICAgaW50ZXJ2YWwgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlYWNoZWRUaW1lb3V0ICYmIHRpbWVvdXRNZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKHRpbWVvdXRNZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgaW50ZXJuYWxDYWxsYmFjaygpO1xuICAgIGlmICghZXhlY3V0ZWQpIHtcbiAgICAgICAgaW50ZXJ2YWwgPSB3aW5kb3cuc2V0SW50ZXJ2YWwoaW50ZXJuYWxDYWxsYmFjaywgMTApO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGNvbXBvc2UoKSB7XG4gICAgdmFyIGZucyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIGZuc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24gKGFyZykgeyByZXR1cm4gZm5zLnJlZHVjZShmdW5jdGlvbiAoY29tcG9zZWQsIGYpIHsgcmV0dXJuIGYoY29tcG9zZWQpOyB9LCBhcmcpOyB9O1xufVxuZnVuY3Rpb24gY2FsbElmUHJlc2VudChmdW5jKSB7XG4gICAgaWYgKGZ1bmMpIHtcbiAgICAgICAgZnVuYygpO1xuICAgIH1cbn1cbnZhciBub29wID0gZnVuY3Rpb24gKCkgeyByZXR1cm47IH07XG5cbnZhciBGdW5jdGlvblV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBkb09uY2U6IGRvT25jZSxcbiAgICBnZXRGdW5jdGlvbk5hbWU6IGdldEZ1bmN0aW9uTmFtZSxcbiAgICBpc0Z1bmN0aW9uOiBpc0Z1bmN0aW9uLFxuICAgIGV4ZWN1dGVJbkFXaGlsZTogZXhlY3V0ZUluQVdoaWxlLFxuICAgIGV4ZWN1dGVOZXh0Vk1UdXJuOiBleGVjdXRlTmV4dFZNVHVybixcbiAgICBleGVjdXRlQWZ0ZXI6IGV4ZWN1dGVBZnRlcixcbiAgICBkZWJvdW5jZTogZGVib3VuY2UsXG4gICAgdGhyb3R0bGU6IHRocm90dGxlLFxuICAgIHdhaXRVbnRpbDogd2FpdFVudGlsLFxuICAgIGNvbXBvc2U6IGNvbXBvc2UsXG4gICAgY2FsbElmUHJlc2VudDogY2FsbElmUHJlc2VudCxcbiAgICBub29wOiBub29wXG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIENvbnRleHQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29udGV4dChwYXJhbXMsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmJlYW5XcmFwcGVycyA9IHt9O1xuICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlO1xuICAgICAgICBpZiAoIXBhcmFtcyB8fCAhcGFyYW1zLmJlYW5DbGFzc2VzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb250ZXh0UGFyYW1zID0gcGFyYW1zO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwiPj4gY3JlYXRpbmcgYWctQXBwbGljYXRpb24gQ29udGV4dFwiKTtcbiAgICAgICAgdGhpcy5jcmVhdGVCZWFucygpO1xuICAgICAgICB2YXIgYmVhbkluc3RhbmNlcyA9IHRoaXMuZ2V0QmVhbkluc3RhbmNlcygpO1xuICAgICAgICB0aGlzLndpcmVCZWFucyhiZWFuSW5zdGFuY2VzKTtcbiAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwiPj4gYWctQXBwbGljYXRpb24gQ29udGV4dCByZWFkeSAtIGNvbXBvbmVudCBpcyBhbGl2ZVwiKTtcbiAgICB9XG4gICAgQ29udGV4dC5wcm90b3R5cGUuZ2V0QmVhbkluc3RhbmNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlcyh0aGlzLmJlYW5XcmFwcGVycykubWFwKGZ1bmN0aW9uIChiZWFuRW50cnkpIHsgcmV0dXJuIGJlYW5FbnRyeS5iZWFuSW5zdGFuY2U7IH0pO1xuICAgIH07XG4gICAgQ29udGV4dC5wcm90b3R5cGUuY3JlYXRlQmVhbiA9IGZ1bmN0aW9uIChiZWFuLCBhZnRlclByZUNyZWF0ZUNhbGxiYWNrKSB7XG4gICAgICAgIGlmICghYmVhbikge1xuICAgICAgICAgICAgdGhyb3cgRXJyb3IoXCJDYW4ndCB3aXJlIHRvIGJlYW4gc2luY2UgaXQgaXMgbnVsbFwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLndpcmVCZWFucyhbYmVhbl0sIGFmdGVyUHJlQ3JlYXRlQ2FsbGJhY2spO1xuICAgICAgICByZXR1cm4gYmVhbjtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLndpcmVCZWFucyA9IGZ1bmN0aW9uIChiZWFuSW5zdGFuY2VzLCBhZnRlclByZUNyZWF0ZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuYXV0b1dpcmVCZWFucyhiZWFuSW5zdGFuY2VzKTtcbiAgICAgICAgdGhpcy5tZXRob2RXaXJlQmVhbnMoYmVhbkluc3RhbmNlcyk7XG4gICAgICAgIHRoaXMuY2FsbExpZmVDeWNsZU1ldGhvZHMoYmVhbkluc3RhbmNlcywgJ3ByZUNvbnN0cnVjdE1ldGhvZHMnKTtcbiAgICAgICAgLy8gdGhlIGNhbGxiYWNrIHNldHMgdGhlIGF0dHJpYnV0ZXMsIHNvIHRoZSBjb21wb25lbnQgaGFzIGFjY2VzcyB0byBhdHRyaWJ1dGVzXG4gICAgICAgIC8vIGJlZm9yZSBwb3N0Q29uc3RydWN0IG1ldGhvZHMgaW4gdGhlIGNvbXBvbmVudCBhcmUgZXhlY3V0ZWRcbiAgICAgICAgaWYgKGV4aXN0cyhhZnRlclByZUNyZWF0ZUNhbGxiYWNrKSkge1xuICAgICAgICAgICAgYmVhbkluc3RhbmNlcy5mb3JFYWNoKGFmdGVyUHJlQ3JlYXRlQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FsbExpZmVDeWNsZU1ldGhvZHMoYmVhbkluc3RhbmNlcywgJ3Bvc3RDb25zdHJ1Y3RNZXRob2RzJyk7XG4gICAgfTtcbiAgICBDb250ZXh0LnByb3RvdHlwZS5jcmVhdGVCZWFucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gcmVnaXN0ZXIgYWxsIG5vcm1hbCBiZWFuc1xuICAgICAgICB0aGlzLmNvbnRleHRQYXJhbXMuYmVhbkNsYXNzZXMuZm9yRWFjaCh0aGlzLmNyZWF0ZUJlYW5XcmFwcGVyLmJpbmQodGhpcykpO1xuICAgICAgICAvLyByZWdpc3RlciBvdmVycmlkZSBiZWFucywgdGhlc2Ugd2lsbCBvdmVyd3JpdGUgYmVhbnMgYWJvdmUgb2Ygc2FtZSBuYW1lXG4gICAgICAgIC8vIGluc3RhbnRpYXRlIGFsbCBiZWFucyAtIG92ZXJyaWRkZW4gYmVhbnMgd2lsbCBiZSBsZWZ0IG91dFxuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMuYmVhbldyYXBwZXJzLCBmdW5jdGlvbiAoa2V5LCBiZWFuRW50cnkpIHtcbiAgICAgICAgICAgIHZhciBjb25zdHJ1Y3RvclBhcmFtc01ldGE7XG4gICAgICAgICAgICBpZiAoYmVhbkVudHJ5LmJlYW4uX19hZ0JlYW5NZXRhRGF0YSAmJiBiZWFuRW50cnkuYmVhbi5fX2FnQmVhbk1ldGFEYXRhLmF1dG93aXJlTWV0aG9kcyAmJiBiZWFuRW50cnkuYmVhbi5fX2FnQmVhbk1ldGFEYXRhLmF1dG93aXJlTWV0aG9kcy5hZ0NvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgY29uc3RydWN0b3JQYXJhbXNNZXRhID0gYmVhbkVudHJ5LmJlYW4uX19hZ0JlYW5NZXRhRGF0YS5hdXRvd2lyZU1ldGhvZHMuYWdDb25zdHJ1Y3RvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjb25zdHJ1Y3RvclBhcmFtcyA9IF90aGlzLmdldEJlYW5zRm9yUGFyYW1ldGVycyhjb25zdHJ1Y3RvclBhcmFtc01ldGEsIGJlYW5FbnRyeS5iZWFuLm5hbWUpO1xuICAgICAgICAgICAgdmFyIG5ld0luc3RhbmNlID0gYXBwbHlUb0NvbnN0cnVjdG9yKGJlYW5FbnRyeS5iZWFuLCBjb25zdHJ1Y3RvclBhcmFtcyk7XG4gICAgICAgICAgICBiZWFuRW50cnkuYmVhbkluc3RhbmNlID0gbmV3SW5zdGFuY2U7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgY3JlYXRlZEJlYW5OYW1lcyA9IE9iamVjdC5rZXlzKHRoaXMuYmVhbldyYXBwZXJzKS5qb2luKCcsICcpO1xuICAgICAgICB0aGlzLmxvZ2dlci5sb2coXCJjcmVhdGVkIGJlYW5zOiBcIiArIGNyZWF0ZWRCZWFuTmFtZXMpO1xuICAgIH07XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXG4gICAgQ29udGV4dC5wcm90b3R5cGUuY3JlYXRlQmVhbldyYXBwZXIgPSBmdW5jdGlvbiAoQmVhbkNsYXNzKSB7XG4gICAgICAgIHZhciBtZXRhRGF0YSA9IEJlYW5DbGFzcy5fX2FnQmVhbk1ldGFEYXRhO1xuICAgICAgICBpZiAoIW1ldGFEYXRhKSB7XG4gICAgICAgICAgICB2YXIgYmVhbk5hbWUgPSB2b2lkIDA7XG4gICAgICAgICAgICBpZiAoQmVhbkNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgIGJlYW5OYW1lID0gZ2V0RnVuY3Rpb25OYW1lKEJlYW5DbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYmVhbk5hbWUgPSBcIlwiICsgQmVhbkNsYXNzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvbnRleHQgaXRlbSBcIiArIGJlYW5OYW1lICsgXCIgaXMgbm90IGEgYmVhblwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYmVhbkVudHJ5ID0ge1xuICAgICAgICAgICAgYmVhbjogQmVhbkNsYXNzLFxuICAgICAgICAgICAgYmVhbkluc3RhbmNlOiBudWxsLFxuICAgICAgICAgICAgYmVhbk5hbWU6IG1ldGFEYXRhLmJlYW5OYW1lXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYmVhbldyYXBwZXJzW21ldGFEYXRhLmJlYW5OYW1lXSA9IGJlYW5FbnRyeTtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmF1dG9XaXJlQmVhbnMgPSBmdW5jdGlvbiAoYmVhbkluc3RhbmNlcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBiZWFuSW5zdGFuY2VzLmZvckVhY2goZnVuY3Rpb24gKGJlYW5JbnN0YW5jZSkge1xuICAgICAgICAgICAgX3RoaXMuZm9yRWFjaE1ldGFEYXRhSW5IaWVyYXJjaHkoYmVhbkluc3RhbmNlLCBmdW5jdGlvbiAobWV0YURhdGEsIGJlYW5OYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGF0dHJpYnV0ZXMgPSBtZXRhRGF0YS5hZ0NsYXNzQXR0cmlidXRlcztcbiAgICAgICAgICAgICAgICBpZiAoIWF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgb3RoZXJCZWFuID0gX3RoaXMubG9va3VwQmVhbkluc3RhbmNlKGJlYW5OYW1lLCBhdHRyaWJ1dGUuYmVhbk5hbWUsIGF0dHJpYnV0ZS5vcHRpb25hbCk7XG4gICAgICAgICAgICAgICAgICAgIGJlYW5JbnN0YW5jZVthdHRyaWJ1dGUuYXR0cmlidXRlTmFtZV0gPSBvdGhlckJlYW47XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb250ZXh0LnByb3RvdHlwZS5tZXRob2RXaXJlQmVhbnMgPSBmdW5jdGlvbiAoYmVhbkluc3RhbmNlcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBiZWFuSW5zdGFuY2VzLmZvckVhY2goZnVuY3Rpb24gKGJlYW5JbnN0YW5jZSkge1xuICAgICAgICAgICAgX3RoaXMuZm9yRWFjaE1ldGFEYXRhSW5IaWVyYXJjaHkoYmVhbkluc3RhbmNlLCBmdW5jdGlvbiAobWV0YURhdGEsIGJlYW5OYW1lKSB7XG4gICAgICAgICAgICAgICAgaXRlcmF0ZU9iamVjdChtZXRhRGF0YS5hdXRvd2lyZU1ldGhvZHMsIGZ1bmN0aW9uIChtZXRob2ROYW1lLCB3aXJlUGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHNraXAgY29uc3RydWN0b3IsIGFzIHRoaXMgaXMgZGVhbHQgd2l0aCBlbHNld2hlcmVcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1ldGhvZE5hbWUgPT09IFwiYWdDb25zdHJ1Y3RvclwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGluaXRQYXJhbXMgPSBfdGhpcy5nZXRCZWFuc0ZvclBhcmFtZXRlcnMod2lyZVBhcmFtcywgYmVhbk5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBiZWFuSW5zdGFuY2VbbWV0aG9kTmFtZV0uYXBwbHkoYmVhbkluc3RhbmNlLCBpbml0UGFyYW1zKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmZvckVhY2hNZXRhRGF0YUluSGllcmFyY2h5ID0gZnVuY3Rpb24gKGJlYW5JbnN0YW5jZSwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihiZWFuSW5zdGFuY2UpO1xuICAgICAgICB3aGlsZSAocHJvdG90eXBlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBjb25zdHJ1Y3RvciA9IHByb3RvdHlwZS5jb25zdHJ1Y3RvcjtcbiAgICAgICAgICAgIGlmIChjb25zdHJ1Y3Rvci5oYXNPd25Qcm9wZXJ0eSgnX19hZ0JlYW5NZXRhRGF0YScpKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1ldGFEYXRhID0gY29uc3RydWN0b3IuX19hZ0JlYW5NZXRhRGF0YTtcbiAgICAgICAgICAgICAgICB2YXIgYmVhbk5hbWUgPSB0aGlzLmdldEJlYW5OYW1lKGNvbnN0cnVjdG9yKTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhtZXRhRGF0YSwgYmVhbk5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJvdG90eXBlID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvdHlwZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmdldEJlYW5OYW1lID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XG4gICAgICAgIGlmIChjb25zdHJ1Y3Rvci5fX2FnQmVhbk1ldGFEYXRhICYmIGNvbnN0cnVjdG9yLl9fYWdCZWFuTWV0YURhdGEuYmVhbk5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25zdHJ1Y3Rvci5fX2FnQmVhbk1ldGFEYXRhLmJlYW5OYW1lO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb25zdHJ1Y3RvclN0cmluZyA9IGNvbnN0cnVjdG9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHZhciBiZWFuTmFtZSA9IGNvbnN0cnVjdG9yU3RyaW5nLnN1YnN0cmluZyg5LCBjb25zdHJ1Y3RvclN0cmluZy5pbmRleE9mKFwiKFwiKSk7XG4gICAgICAgIHJldHVybiBiZWFuTmFtZTtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmdldEJlYW5zRm9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uIChwYXJhbWV0ZXJzLCBiZWFuTmFtZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgYmVhbnNMaXN0ID0gW107XG4gICAgICAgIGlmIChwYXJhbWV0ZXJzKSB7XG4gICAgICAgICAgICBpdGVyYXRlT2JqZWN0KHBhcmFtZXRlcnMsIGZ1bmN0aW9uIChwYXJhbUluZGV4LCBvdGhlckJlYW5OYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIG90aGVyQmVhbiA9IF90aGlzLmxvb2t1cEJlYW5JbnN0YW5jZShiZWFuTmFtZSwgb3RoZXJCZWFuTmFtZSk7XG4gICAgICAgICAgICAgICAgYmVhbnNMaXN0W051bWJlcihwYXJhbUluZGV4KV0gPSBvdGhlckJlYW47XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmVhbnNMaXN0O1xuICAgIH07XG4gICAgQ29udGV4dC5wcm90b3R5cGUubG9va3VwQmVhbkluc3RhbmNlID0gZnVuY3Rpb24gKHdpcmluZ0JlYW4sIGJlYW5OYW1lLCBvcHRpb25hbCkge1xuICAgICAgICBpZiAob3B0aW9uYWwgPT09IHZvaWQgMCkgeyBvcHRpb25hbCA9IGZhbHNlOyB9XG4gICAgICAgIGlmIChiZWFuTmFtZSA9PT0gXCJjb250ZXh0XCIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbnRleHRQYXJhbXMucHJvdmlkZWRCZWFuSW5zdGFuY2VzICYmIHRoaXMuY29udGV4dFBhcmFtcy5wcm92aWRlZEJlYW5JbnN0YW5jZXMuaGFzT3duUHJvcGVydHkoYmVhbk5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0UGFyYW1zLnByb3ZpZGVkQmVhbkluc3RhbmNlc1tiZWFuTmFtZV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJlYW5FbnRyeSA9IHRoaXMuYmVhbldyYXBwZXJzW2JlYW5OYW1lXTtcbiAgICAgICAgaWYgKGJlYW5FbnRyeSkge1xuICAgICAgICAgICAgcmV0dXJuIGJlYW5FbnRyeS5iZWFuSW5zdGFuY2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFvcHRpb25hbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkFHIEdyaWQ6IHVuYWJsZSB0byBmaW5kIGJlYW4gcmVmZXJlbmNlIFwiICsgYmVhbk5hbWUgKyBcIiB3aGlsZSBpbml0aWFsaXNpbmcgXCIgKyB3aXJpbmdCZWFuKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmNhbGxMaWZlQ3ljbGVNZXRob2RzID0gZnVuY3Rpb24gKGJlYW5JbnN0YW5jZXMsIGxpZmVDeWNsZU1ldGhvZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBiZWFuSW5zdGFuY2VzLmZvckVhY2goZnVuY3Rpb24gKGJlYW5JbnN0YW5jZSkgeyByZXR1cm4gX3RoaXMuY2FsbExpZmVDeWNsZU1ldGhvZHNPbkJlYW4oYmVhbkluc3RhbmNlLCBsaWZlQ3ljbGVNZXRob2QpOyB9KTtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmNhbGxMaWZlQ3ljbGVNZXRob2RzT25CZWFuID0gZnVuY3Rpb24gKGJlYW5JbnN0YW5jZSwgbGlmZUN5Y2xlTWV0aG9kLCBtZXRob2RUb0lnbm9yZSkge1xuICAgICAgICAvLyBwdXR0aW5nIGFsbCBtZXRob2RzIGludG8gYSBtYXAgcmVtb3ZlcyBkdXBsaWNhdGVzXG4gICAgICAgIHZhciBhbGxNZXRob2RzID0ge307XG4gICAgICAgIC8vIGR1bXAgbWV0aG9kcyBmcm9tIGVhY2ggbGV2ZWwgb2YgdGhlIG1ldGFkYXRhIGhpZXJhcmNoeVxuICAgICAgICB0aGlzLmZvckVhY2hNZXRhRGF0YUluSGllcmFyY2h5KGJlYW5JbnN0YW5jZSwgZnVuY3Rpb24gKG1ldGFEYXRhKSB7XG4gICAgICAgICAgICB2YXIgbWV0aG9kcyA9IG1ldGFEYXRhW2xpZmVDeWNsZU1ldGhvZF07XG4gICAgICAgICAgICBpZiAobWV0aG9kcykge1xuICAgICAgICAgICAgICAgIG1ldGhvZHMuZm9yRWFjaChmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobWV0aG9kTmFtZSAhPSBtZXRob2RUb0lnbm9yZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWxsTWV0aG9kc1ttZXRob2ROYW1lXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBhbGxNZXRob2RzTGlzdCA9IE9iamVjdC5rZXlzKGFsbE1ldGhvZHMpO1xuICAgICAgICBhbGxNZXRob2RzTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChtZXRob2ROYW1lKSB7IHJldHVybiBiZWFuSW5zdGFuY2VbbWV0aG9kTmFtZV0oKTsgfSk7XG4gICAgfTtcbiAgICBDb250ZXh0LnByb3RvdHlwZS5nZXRCZWFuID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9va3VwQmVhbkluc3RhbmNlKFwiZ2V0QmVhblwiLCBuYW1lLCB0cnVlKTtcbiAgICB9O1xuICAgIENvbnRleHQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubG9nZ2VyLmxvZyhcIj4+IFNodXR0aW5nIGRvd24gYWctQXBwbGljYXRpb24gQ29udGV4dFwiKTtcbiAgICAgICAgdmFyIGJlYW5JbnN0YW5jZXMgPSB0aGlzLmdldEJlYW5JbnN0YW5jZXMoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95QmVhbnMoYmVhbkluc3RhbmNlcyk7XG4gICAgICAgIHRoaXMuY29udGV4dFBhcmFtcy5wcm92aWRlZEJlYW5JbnN0YW5jZXMgPSBudWxsO1xuICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IHRydWU7XG4gICAgICAgIHRoaXMubG9nZ2VyLmxvZyhcIj4+IGFnLUFwcGxpY2F0aW9uIENvbnRleHQgc2h1dCBkb3duIC0gY29tcG9uZW50IGlzIGRlYWRcIik7XG4gICAgfTtcbiAgICBDb250ZXh0LnByb3RvdHlwZS5kZXN0cm95QmVhbiA9IGZ1bmN0aW9uIChiZWFuKSB7XG4gICAgICAgIGlmICghYmVhbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVzdHJveUJlYW5zKFtiZWFuXSk7XG4gICAgfTtcbiAgICBDb250ZXh0LnByb3RvdHlwZS5kZXN0cm95QmVhbnMgPSBmdW5jdGlvbiAoYmVhbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFiZWFucykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIGJlYW5zLmZvckVhY2goZnVuY3Rpb24gKGJlYW4pIHtcbiAgICAgICAgICAgIF90aGlzLmNhbGxMaWZlQ3ljbGVNZXRob2RzT25CZWFuKGJlYW4sICdwcmVEZXN0cm95TWV0aG9kcycsICdkZXN0cm95Jyk7XG4gICAgICAgICAgICAvLyBjYWxsIGRlc3Ryb3koKSBleHBsaWNpdGx5IGlmIGl0IGV4aXN0c1xuICAgICAgICAgICAgdmFyIGJlYW5BbnkgPSBiZWFuO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBiZWFuQW55LmRlc3Ryb3kgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBiZWFuQW55LmRlc3Ryb3koKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9O1xuICAgIHJldHVybiBDb250ZXh0O1xufSgpKTtcbi8vIHRha2VuIGZyb206IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzM2MjQ3MS9ob3ctY2FuLWktY2FsbC1hLWphdmFzY3JpcHQtY29uc3RydWN0b3ItdXNpbmctY2FsbC1vci1hcHBseVxuLy8gYWxsb3dzIGNhbGxpbmcgJ2FwcGx5JyBvbiBhIGNvbnN0cnVjdG9yXG5mdW5jdGlvbiBhcHBseVRvQ29uc3RydWN0b3IoY29uc3RydWN0b3IsIGFyZ0FycmF5KSB7XG4gICAgdmFyIGFyZ3MgPSBbbnVsbF0uY29uY2F0KGFyZ0FycmF5KTtcbiAgICB2YXIgZmFjdG9yeUZ1bmN0aW9uID0gY29uc3RydWN0b3IuYmluZC5hcHBseShjb25zdHJ1Y3RvciwgYXJncyk7XG4gICAgcmV0dXJuIG5ldyBmYWN0b3J5RnVuY3Rpb24oKTtcbn1cbmZ1bmN0aW9uIFByZUNvbnN0cnVjdCh0YXJnZXQsIG1ldGhvZE5hbWUsIGRlc2NyaXB0b3IpIHtcbiAgICB2YXIgcHJvcHMgPSBnZXRPckNyZWF0ZVByb3BzJDEodGFyZ2V0LmNvbnN0cnVjdG9yKTtcbiAgICBpZiAoIXByb3BzLnByZUNvbnN0cnVjdE1ldGhvZHMpIHtcbiAgICAgICAgcHJvcHMucHJlQ29uc3RydWN0TWV0aG9kcyA9IFtdO1xuICAgIH1cbiAgICBwcm9wcy5wcmVDb25zdHJ1Y3RNZXRob2RzLnB1c2gobWV0aG9kTmFtZSk7XG59XG5mdW5jdGlvbiBQb3N0Q29uc3RydWN0KHRhcmdldCwgbWV0aG9kTmFtZSwgZGVzY3JpcHRvcikge1xuICAgIHZhciBwcm9wcyA9IGdldE9yQ3JlYXRlUHJvcHMkMSh0YXJnZXQuY29uc3RydWN0b3IpO1xuICAgIGlmICghcHJvcHMucG9zdENvbnN0cnVjdE1ldGhvZHMpIHtcbiAgICAgICAgcHJvcHMucG9zdENvbnN0cnVjdE1ldGhvZHMgPSBbXTtcbiAgICB9XG4gICAgcHJvcHMucG9zdENvbnN0cnVjdE1ldGhvZHMucHVzaChtZXRob2ROYW1lKTtcbn1cbmZ1bmN0aW9uIFByZURlc3Ryb3kodGFyZ2V0LCBtZXRob2ROYW1lLCBkZXNjcmlwdG9yKSB7XG4gICAgdmFyIHByb3BzID0gZ2V0T3JDcmVhdGVQcm9wcyQxKHRhcmdldC5jb25zdHJ1Y3Rvcik7XG4gICAgaWYgKCFwcm9wcy5wcmVEZXN0cm95TWV0aG9kcykge1xuICAgICAgICBwcm9wcy5wcmVEZXN0cm95TWV0aG9kcyA9IFtdO1xuICAgIH1cbiAgICBwcm9wcy5wcmVEZXN0cm95TWV0aG9kcy5wdXNoKG1ldGhvZE5hbWUpO1xufVxuZnVuY3Rpb24gQmVhbihiZWFuTmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoY2xhc3NDb25zdHJ1Y3Rvcikge1xuICAgICAgICB2YXIgcHJvcHMgPSBnZXRPckNyZWF0ZVByb3BzJDEoY2xhc3NDb25zdHJ1Y3Rvcik7XG4gICAgICAgIHByb3BzLmJlYW5OYW1lID0gYmVhbk5hbWU7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIEF1dG93aXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIHByb3BlcnR5S2V5LCBkZXNjcmlwdG9yKSB7XG4gICAgICAgIGF1dG93aXJlZEZ1bmModGFyZ2V0LCBuYW1lLCBmYWxzZSwgdGFyZ2V0LCBwcm9wZXJ0eUtleSwgbnVsbCk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIE9wdGlvbmFsKG5hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpIHtcbiAgICAgICAgYXV0b3dpcmVkRnVuYyh0YXJnZXQsIG5hbWUsIHRydWUsIHRhcmdldCwgcHJvcGVydHlLZXksIG51bGwpO1xuICAgIH07XG59XG5mdW5jdGlvbiBhdXRvd2lyZWRGdW5jKHRhcmdldCwgbmFtZSwgb3B0aW9uYWwsIGNsYXNzUHJvdG90eXBlLCBtZXRob2RPckF0dHJpYnV0ZU5hbWUsIGluZGV4KSB7XG4gICAgaWYgKG5hbWUgPT09IG51bGwpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkFHIEdyaWQ6IEF1dG93aXJlZCBuYW1lIHNob3VsZCBub3QgYmUgbnVsbFwiKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGluZGV4ID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBBdXRvd2lyZWQgc2hvdWxkIGJlIG9uIGFuIGF0dHJpYnV0ZVwiKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBpdCdzIGFuIGF0dHJpYnV0ZSBvbiB0aGUgY2xhc3NcbiAgICB2YXIgcHJvcHMgPSBnZXRPckNyZWF0ZVByb3BzJDEodGFyZ2V0LmNvbnN0cnVjdG9yKTtcbiAgICBpZiAoIXByb3BzLmFnQ2xhc3NBdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb3BzLmFnQ2xhc3NBdHRyaWJ1dGVzID0gW107XG4gICAgfVxuICAgIHByb3BzLmFnQ2xhc3NBdHRyaWJ1dGVzLnB1c2goe1xuICAgICAgICBhdHRyaWJ1dGVOYW1lOiBtZXRob2RPckF0dHJpYnV0ZU5hbWUsXG4gICAgICAgIGJlYW5OYW1lOiBuYW1lLFxuICAgICAgICBvcHRpb25hbDogb3B0aW9uYWxcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIFF1YWxpZmllcihuYW1lKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChjbGFzc1Byb3RvdHlwZSwgbWV0aG9kT3JBdHRyaWJ1dGVOYW1lLCBpbmRleCkge1xuICAgICAgICB2YXIgY29uc3RydWN0b3IgPSB0eXBlb2YgY2xhc3NQcm90b3R5cGUgPT0gXCJmdW5jdGlvblwiID8gY2xhc3NQcm90b3R5cGUgOiBjbGFzc1Byb3RvdHlwZS5jb25zdHJ1Y3RvcjtcbiAgICAgICAgdmFyIHByb3BzO1xuICAgICAgICBpZiAodHlwZW9mIGluZGV4ID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAvLyBpdCdzIGEgcGFyYW1ldGVyIG9uIGEgbWV0aG9kXG4gICAgICAgICAgICB2YXIgbWV0aG9kTmFtZSA9IHZvaWQgMDtcbiAgICAgICAgICAgIGlmIChtZXRob2RPckF0dHJpYnV0ZU5hbWUpIHtcbiAgICAgICAgICAgICAgICBwcm9wcyA9IGdldE9yQ3JlYXRlUHJvcHMkMShjb25zdHJ1Y3Rvcik7XG4gICAgICAgICAgICAgICAgbWV0aG9kTmFtZSA9IG1ldGhvZE9yQXR0cmlidXRlTmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHByb3BzID0gZ2V0T3JDcmVhdGVQcm9wcyQxKGNvbnN0cnVjdG9yKTtcbiAgICAgICAgICAgICAgICBtZXRob2ROYW1lID0gXCJhZ0NvbnN0cnVjdG9yXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXByb3BzLmF1dG93aXJlTWV0aG9kcykge1xuICAgICAgICAgICAgICAgIHByb3BzLmF1dG93aXJlTWV0aG9kcyA9IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFwcm9wcy5hdXRvd2lyZU1ldGhvZHNbbWV0aG9kTmFtZV0pIHtcbiAgICAgICAgICAgICAgICBwcm9wcy5hdXRvd2lyZU1ldGhvZHNbbWV0aG9kTmFtZV0gPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb3BzLmF1dG93aXJlTWV0aG9kc1ttZXRob2ROYW1lXVtpbmRleF0gPSBuYW1lO1xuICAgICAgICB9XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdldE9yQ3JlYXRlUHJvcHMkMSh0YXJnZXQpIHtcbiAgICBpZiAoIXRhcmdldC5oYXNPd25Qcm9wZXJ0eShcIl9fYWdCZWFuTWV0YURhdGFcIikpIHtcbiAgICAgICAgdGFyZ2V0Ll9fYWdCZWFuTWV0YURhdGEgPSB7fTtcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldC5fX2FnQmVhbk1ldGFEYXRhO1xufVxuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19hc3NpZ24kaSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fYXNzaWduKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgX19hc3NpZ24kaSA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24kaS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufTtcbnZhciBfX2RlY29yYXRlJDJBID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX19wYXJhbSRhID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19wYXJhbSkgfHwgZnVuY3Rpb24gKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxufTtcbnZhciBFdmVudFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRXZlbnRTZXJ2aWNlKCkge1xuICAgICAgICB0aGlzLmFsbFN5bmNMaXN0ZW5lcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuYWxsQXN5bmNMaXN0ZW5lcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZ2xvYmFsU3luY0xpc3RlbmVycyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdGhpcy5nbG9iYWxBc3luY0xpc3RlbmVycyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdGhpcy5hc3luY0Z1bmN0aW9uc1F1ZXVlID0gW107XG4gICAgICAgIHRoaXMuc2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgIC8vIHVzaW5nIGFuIG9iamVjdCBwZXJmb3JtcyBiZXR0ZXIgdGhhbiBhIFNldCBmb3IgdGhlIG51bWJlciBvZiBkaWZmZXJlbnQgZXZlbnRzIHdlIGhhdmVcbiAgICAgICAgdGhpcy5maXJlZEV2ZW50cyA9IHt9O1xuICAgIH1cbiAgICAvLyBiZWNhdXNlIHRoaXMgY2xhc3MgaXMgdXNlZCBib3RoIGluc2lkZSB0aGUgY29udGV4dCBhbmQgb3V0c2lkZSB0aGUgY29udGV4dCwgd2UgZG8gbm90XG4gICAgLy8gdXNlIGF1dG93aXJlZCBhdHRyaWJ1dGVzLCBhcyB0aGF0IHdvdWxkIGJlIGNvbmZ1c2luZywgYXMgc29tZXRpbWVzIHRoZSBhdHRyaWJ1dGVzXG4gICAgLy8gd291bGQgYmUgd2lyZWQsIGFuZCBzb21ldGltZXMgbm90LlxuICAgIC8vXG4gICAgLy8gdGhlIGdsb2JhbCBldmVudCBzZXJ2ZXJzIHVzZWQgYnkgQUcgR3JpZCBpcyBhdXRvd2lyZWQgYnkgdGhlIGNvbnRleHQgb25jZSwgYW5kIHRoaXNcbiAgICAvLyBzZXRCZWFucyBtZXRob2QgZ2V0cyBjYWxsZWQgb25jZS5cbiAgICAvL1xuICAgIC8vIHRoZSB0aW1lcyB3aGVuIHRoaXMgY2xhc3MgaXMgdXNlZCBvdXRzaWRlIG9mIHRoZSBjb250ZXh0IChlZyBSb3dOb2RlIGhhcyBhbiBpbnN0YW5jZSBvZiB0aGlzXG4gICAgLy8gY2xhc3MpIHRoZW4gaXQgaXMgbm90IGEgYmVhbiwgYW5kIHRoaXMgc2V0QmVhbnMgbWV0aG9kIGlzIG5vdCBjYWxsZWQuXG4gICAgRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5zZXRCZWFucyA9IGZ1bmN0aW9uIChsb2dnZXJGYWN0b3J5LCBncmlkT3B0aW9uc1dyYXBwZXIsIGZyYW1ld29ya092ZXJyaWRlcywgZ2xvYmFsRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICBpZiAoZ2xvYmFsRXZlbnRMaXN0ZW5lciA9PT0gdm9pZCAwKSB7IGdsb2JhbEV2ZW50TGlzdGVuZXIgPSBudWxsOyB9XG4gICAgICAgIHRoaXMuZnJhbWV3b3JrT3ZlcnJpZGVzID0gZnJhbWV3b3JrT3ZlcnJpZGVzO1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciA9IGdyaWRPcHRpb25zV3JhcHBlcjtcbiAgICAgICAgaWYgKGdsb2JhbEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHZhciBhc3luYyA9IGdyaWRPcHRpb25zV3JhcHBlci51c2VBc3luY0V2ZW50cygpO1xuICAgICAgICAgICAgdGhpcy5hZGRHbG9iYWxMaXN0ZW5lcihnbG9iYWxFdmVudExpc3RlbmVyLCBhc3luYyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEV2ZW50U2VydmljZS5wcm90b3R5cGUuZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgYXN5bmMsIGF1dG9DcmVhdGVMaXN0ZW5lckNvbGxlY3Rpb24pIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyTWFwID0gYXN5bmMgPyB0aGlzLmFsbEFzeW5jTGlzdGVuZXJzIDogdGhpcy5hbGxTeW5jTGlzdGVuZXJzO1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gbGlzdGVuZXJNYXAuZ2V0KGV2ZW50VHlwZSk7XG4gICAgICAgIC8vIE5vdGU6ICdhdXRvQ3JlYXRlTGlzdGVuZXJDb2xsZWN0aW9uJyBzaG91bGQgb25seSBiZSAndHJ1ZScgaWYgYSBsaXN0ZW5lciBpcyBhYm91dCB0byBiZSBhZGRlZC4gRm9yIGluc3RhbmNlXG4gICAgICAgIC8vIGdldExpc3RlbmVycygpIGlzIGFsc28gY2FsbGVkIGR1cmluZyBldmVudCBkaXNwYXRjaCBldmVuIHRob3VnaCBubyBsaXN0ZW5lcnMgYXJlIGFkZGVkLiBUaGlzIG1lYXN1cmUgcHJvdGVjdHNcbiAgICAgICAgLy8gYWdhaW5zdCAnbWVtb3J5IGJsb2F0JyBhcyBlbXB0eSBjb2xsZWN0aW9ucyB3aWxsIHByZXZlbnQgdGhlIFJvd05vZGUncyBldmVudCBzZXJ2aWNlIGZyb20gYmVpbmcgcmVtb3ZlZCBhZnRlclxuICAgICAgICAvLyB0aGUgUm93Q29tcCBpcyBkZXN0cm95ZWQsIHNlZSBub1JlZ2lzdGVyZWRMaXN0ZW5lcnNFeGlzdCgpIGJlbG93LlxuICAgICAgICBpZiAoIWxpc3RlbmVycyAmJiBhdXRvQ3JlYXRlTGlzdGVuZXJDb2xsZWN0aW9uKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMgPSBuZXcgU2V0KCk7XG4gICAgICAgICAgICBsaXN0ZW5lck1hcC5zZXQoZXZlbnRUeXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsaXN0ZW5lcnM7XG4gICAgfTtcbiAgICBFdmVudFNlcnZpY2UucHJvdG90eXBlLm5vUmVnaXN0ZXJlZExpc3RlbmVyc0V4aXN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hbGxTeW5jTGlzdGVuZXJzLnNpemUgPT09IDAgJiYgdGhpcy5hbGxBc3luY0xpc3RlbmVycy5zaXplID09PSAwICYmXG4gICAgICAgICAgICB0aGlzLmdsb2JhbFN5bmNMaXN0ZW5lcnMuc2l6ZSA9PT0gMCAmJiB0aGlzLmdsb2JhbEFzeW5jTGlzdGVuZXJzLnNpemUgPT09IDA7XG4gICAgfTtcbiAgICBFdmVudFNlcnZpY2UucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lciwgYXN5bmMpIHtcbiAgICAgICAgaWYgKGFzeW5jID09PSB2b2lkIDApIHsgYXN5bmMgPSBmYWxzZTsgfVxuICAgICAgICB0aGlzLmdldExpc3RlbmVycyhldmVudFR5cGUsIGFzeW5jLCB0cnVlKS5hZGQobGlzdGVuZXIpO1xuICAgIH07XG4gICAgRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIsIGFzeW5jKSB7XG4gICAgICAgIGlmIChhc3luYyA9PT0gdm9pZCAwKSB7IGFzeW5jID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZ2V0TGlzdGVuZXJzKGV2ZW50VHlwZSwgYXN5bmMsIGZhbHNlKTtcbiAgICAgICAgaWYgKCFsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICAgICAgaWYgKGxpc3RlbmVycy5zaXplID09PSAwKSB7XG4gICAgICAgICAgICB2YXIgbGlzdGVuZXJNYXAgPSBhc3luYyA/IHRoaXMuYWxsQXN5bmNMaXN0ZW5lcnMgOiB0aGlzLmFsbFN5bmNMaXN0ZW5lcnM7XG4gICAgICAgICAgICBsaXN0ZW5lck1hcC5kZWxldGUoZXZlbnRUeXBlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5hZGRHbG9iYWxMaXN0ZW5lciA9IGZ1bmN0aW9uIChsaXN0ZW5lciwgYXN5bmMpIHtcbiAgICAgICAgaWYgKGFzeW5jID09PSB2b2lkIDApIHsgYXN5bmMgPSBmYWxzZTsgfVxuICAgICAgICAoYXN5bmMgPyB0aGlzLmdsb2JhbEFzeW5jTGlzdGVuZXJzIDogdGhpcy5nbG9iYWxTeW5jTGlzdGVuZXJzKS5hZGQobGlzdGVuZXIpO1xuICAgIH07XG4gICAgRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5yZW1vdmVHbG9iYWxMaXN0ZW5lciA9IGZ1bmN0aW9uIChsaXN0ZW5lciwgYXN5bmMpIHtcbiAgICAgICAgaWYgKGFzeW5jID09PSB2b2lkIDApIHsgYXN5bmMgPSBmYWxzZTsgfVxuICAgICAgICAoYXN5bmMgPyB0aGlzLmdsb2JhbEFzeW5jTGlzdGVuZXJzIDogdGhpcy5nbG9iYWxTeW5jTGlzdGVuZXJzKS5kZWxldGUobGlzdGVuZXIpO1xuICAgIH07XG4gICAgRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5kaXNwYXRjaEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBhZ0V2ZW50ID0gZXZlbnQ7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlcikge1xuICAgICAgICAgICAgLy8gQXBwbHkgY29tbW9uIHByb3BlcnRpZXMgdG8gYWxsIGRpc3BhdGNoZWQgZXZlbnRzIGlmIHRoaXMgZXZlbnQgc2VydmljZSBoYXMgaGFkIGl0cyBiZWFucyBzZXQgd2l0aCBncmlkT3B0aW9uc1dyYXBwZXIuXG4gICAgICAgICAgICAvLyBOb3RlIHRoZXJlIGFyZSBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgRXZlbnRTZXJ2aWNlIHRoYXQgYXJlIHVzZWQgbG9jYWwgdG8gY29tcG9uZW50cyB3aGljaCBkbyBub3Qgc2V0IGdyaWRPcHRpb25zV3JhcHBlci4gXG4gICAgICAgICAgICBhZ0V2ZW50ID0gX19hc3NpZ24kaShfX2Fzc2lnbiRpKHt9LCBldmVudCksIHsgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSwgY29sdW1uQXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSwgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hUb0xpc3RlbmVycyhhZ0V2ZW50LCB0cnVlKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaFRvTGlzdGVuZXJzKGFnRXZlbnQsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5maXJlZEV2ZW50c1thZ0V2ZW50LnR5cGVdID0gdHJ1ZTtcbiAgICB9O1xuICAgIEV2ZW50U2VydmljZS5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudE9uY2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmZpcmVkRXZlbnRzW2V2ZW50LnR5cGVdKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFdmVudFNlcnZpY2UucHJvdG90eXBlLmRpc3BhdGNoVG9MaXN0ZW5lcnMgPSBmdW5jdGlvbiAoZXZlbnQsIGFzeW5jKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBldmVudFR5cGUgPSBldmVudC50eXBlO1xuICAgICAgICB2YXIgcHJvY2Vzc0V2ZW50TGlzdGVuZXJzID0gZnVuY3Rpb24gKGxpc3RlbmVycykgeyByZXR1cm4gbGlzdGVuZXJzLmZvckVhY2goZnVuY3Rpb24gKGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBpZiAoYXN5bmMpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kaXNwYXRjaEFzeW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGxpc3RlbmVyKGV2ZW50KTsgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcihldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pOyB9O1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZlbnRUeXBlLCBhc3luYywgZmFsc2UpO1xuICAgICAgICBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgICAgICBwcm9jZXNzRXZlbnRMaXN0ZW5lcnMobGlzdGVuZXJzKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZ2xvYmFsTGlzdGVuZXJzID0gYXN5bmMgPyB0aGlzLmdsb2JhbEFzeW5jTGlzdGVuZXJzIDogdGhpcy5nbG9iYWxTeW5jTGlzdGVuZXJzO1xuICAgICAgICBnbG9iYWxMaXN0ZW5lcnMuZm9yRWFjaChmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgICAgICAgIGlmIChhc3luYykge1xuICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoQXN5bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZnJhbWV3b3JrT3ZlcnJpZGVzLmRpc3BhdGNoRXZlbnQoZXZlbnRUeXBlLCBmdW5jdGlvbiAoKSB7IHJldHVybiBsaXN0ZW5lcihldmVudFR5cGUsIGV2ZW50KTsgfSwgdHJ1ZSk7IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZnJhbWV3b3JrT3ZlcnJpZGVzLmRpc3BhdGNoRXZlbnQoZXZlbnRUeXBlLCBmdW5jdGlvbiAoKSB7IHJldHVybiBsaXN0ZW5lcihldmVudFR5cGUsIGV2ZW50KTsgfSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gdGhpcyBnZXRzIGNhbGxlZCBpbnNpZGUgdGhlIGdyaWQncyB0aHJlYWQsIGZvciBlYWNoIGV2ZW50IHRoYXQgaXRcbiAgICAvLyB3YW50cyB0byBzZXQgYXN5bmMuIHRoZSBncmlkIHRoZW4gYmF0Y2hlcyB0aGUgZXZlbnRzIGludG8gb25lIHNldFRpbWVvdXQoKVxuICAgIC8vIGJlY2F1c2Ugc2V0VGltZW91dCgpIGlzIGFuIGV4cGVuc2l2ZSBvcGVyYXRpb24uIGlkZWFsbHkgd2Ugd291bGQgaGF2ZVxuICAgIC8vIGVhY2ggZXZlbnQgaW4gaXQncyBvd24gc2V0VGltZW91dCgpLCBidXQgd2UgYmF0Y2ggZm9yIHBlcmZvcm1hbmNlLlxuICAgIEV2ZW50U2VydmljZS5wcm90b3R5cGUuZGlzcGF0Y2hBc3luYyA9IGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgIC8vIGFkZCB0byB0aGUgcXVldWUgZm9yIGV4ZWN1dGluZyBsYXRlciBpbiB0aGUgbmV4dCBWTSB0dXJuXG4gICAgICAgIHRoaXMuYXN5bmNGdW5jdGlvbnNRdWV1ZS5wdXNoKGZ1bmMpO1xuICAgICAgICAvLyBjaGVjayBpZiB0aW1lb3V0IGlzIGFscmVhZHkgc2NoZWR1bGVkLiB0aGUgZmlyc3QgdGltZSB0aGUgZ3JpZCBjYWxsc1xuICAgICAgICAvLyB0aGlzIHdpdGhpbiBpdCdzIHRocmVhZCB0dXJuLCB0aGlzIHNob3VsZCBiZSBmYWxzZSwgc28gaXQgd2lsbCBzY2hlZHVsZVxuICAgICAgICAvLyB0aGUgJ2ZsdXNoIHF1ZXVlJyBtZXRob2QgdGhlIGZpcnN0IHRpbWUgaXQgY29tZXMgaGVyZS4gdGhlbiB0aGUgZmxhZyBpc1xuICAgICAgICAvLyBzZXQgdG8gJ3RydWUnIHNvIGl0IHdpbGwga25vdyBpdCdzIGFscmVhZHkgc2NoZWR1bGVkIGZvciBzdWJzZXF1ZW50IGNhbGxzLlxuICAgICAgICBpZiAoIXRoaXMuc2NoZWR1bGVkKSB7XG4gICAgICAgICAgICAvLyBpZiBub3Qgc2NoZWR1bGVkLCBzY2hlZHVsZSBvbmVcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KHRoaXMuZmx1c2hBc3luY1F1ZXVlLmJpbmQodGhpcyksIDApO1xuICAgICAgICAgICAgLy8gbWFyayB0aGF0IGl0IGlzIHNjaGVkdWxlZFxuICAgICAgICAgICAgdGhpcy5zY2hlZHVsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyB0aGlzIGhhcHBlbnMgaW4gdGhlIG5leHQgVk0gdHVybiBvbmx5LCBhbmQgZW1wdGllcyB0aGUgcXVldWUgb2YgZXZlbnRzXG4gICAgRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5mbHVzaEFzeW5jUXVldWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgIC8vIHdlIHRha2UgYSBjb3B5LCBiZWNhdXNlIHRoZSBldmVudCBsaXN0ZW5lciBjb3VsZCBiZSB1c2luZ1xuICAgICAgICAvLyB0aGUgZ3JpZCwgd2hpY2ggd291bGQgY2F1c2UgbW9yZSBldmVudHMsIHdoaWNoIHdvdWxkIGJlIHBvdGVudGlhbGx5XG4gICAgICAgIC8vIGFkZGVkIHRvIHRoZSBxdWV1ZSwgc28gc2FmZSB0byB0YWtlIGEgY29weSwgdGhlIG5ldyBldmVudHMgd2lsbFxuICAgICAgICAvLyBnZXQgZXhlY3V0ZWQgaW4gYSBsYXRlciBWTSB0dXJuIHJhdGhlciB0aGFuIHJpc2sgdXBkYXRpbmcgdGhlXG4gICAgICAgIC8vIHF1ZXVlIGFzIHdlIGFyZSBmbHVzaGluZyBpdC5cbiAgICAgICAgdmFyIHF1ZXVlQ29weSA9IHRoaXMuYXN5bmNGdW5jdGlvbnNRdWV1ZS5zbGljZSgpO1xuICAgICAgICB0aGlzLmFzeW5jRnVuY3Rpb25zUXVldWUgPSBbXTtcbiAgICAgICAgLy8gZXhlY3V0ZSB0aGUgcXVldWVcbiAgICAgICAgcXVldWVDb3B5LmZvckVhY2goZnVuY3Rpb24gKGZ1bmMpIHsgcmV0dXJuIGZ1bmMoKTsgfSk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDJBKFtcbiAgICAgICAgX19wYXJhbSRhKDAsIFF1YWxpZmllcignbG9nZ2VyRmFjdG9yeScpKSxcbiAgICAgICAgX19wYXJhbSRhKDEsIFF1YWxpZmllcignZ3JpZE9wdGlvbnNXcmFwcGVyJykpLFxuICAgICAgICBfX3BhcmFtJGEoMiwgUXVhbGlmaWVyKCdmcmFtZXdvcmtPdmVycmlkZXMnKSksXG4gICAgICAgIF9fcGFyYW0kYSgzLCBRdWFsaWZpZXIoJ2dsb2JhbEV2ZW50TGlzdGVuZXInKSlcbiAgICBdLCBFdmVudFNlcnZpY2UucHJvdG90eXBlLCBcInNldEJlYW5zXCIsIG51bGwpO1xuICAgIEV2ZW50U2VydmljZSA9IF9fZGVjb3JhdGUkMkEoW1xuICAgICAgICBCZWFuKCdldmVudFNlcnZpY2UnKVxuICAgIF0sIEV2ZW50U2VydmljZSk7XG4gICAgcmV0dXJuIEV2ZW50U2VydmljZTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBDb25zdGFudHMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29uc3RhbnRzKCkge1xuICAgIH1cbiAgICBDb25zdGFudHMuUk9XX0JVRkZFUl9TSVpFID0gMTA7XG4gICAgQ29uc3RhbnRzLkxBWU9VVF9JTlRFUlZBTCA9IDUwMDtcbiAgICBDb25zdGFudHMuQkFUQ0hfV0FJVF9NSUxMSVMgPSA1MDtcbiAgICBDb25zdGFudHMuRVhQT1JUX1RZUEVfRFJBR19DT1BZID0gJ2RyYWdDb3B5JztcbiAgICBDb25zdGFudHMuRVhQT1JUX1RZUEVfQ0xJUEJPQVJEID0gJ2NsaXBib2FyZCc7XG4gICAgQ29uc3RhbnRzLkVYUE9SVF9UWVBFX0VYQ0VMID0gJ2V4Y2VsJztcbiAgICBDb25zdGFudHMuRVhQT1JUX1RZUEVfQ1NWID0gJ2Nzdic7XG4gICAgQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0lORklOSVRFID0gJ2luZmluaXRlJztcbiAgICBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfVklFV1BPUlQgPSAndmlld3BvcnQnO1xuICAgIENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERSA9ICdjbGllbnRTaWRlJztcbiAgICBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfU0VSVkVSX1NJREUgPSAnc2VydmVyU2lkZSc7XG4gICAgQ29uc3RhbnRzLkFMV0FZUyA9ICdhbHdheXMnO1xuICAgIENvbnN0YW50cy5PTkxZX1dIRU5fR1JPVVBJTkcgPSAnb25seVdoZW5Hcm91cGluZyc7XG4gICAgQ29uc3RhbnRzLlBJTk5FRF9UT1AgPSAndG9wJztcbiAgICBDb25zdGFudHMuUElOTkVEX0JPVFRPTSA9ICdib3R0b20nO1xuICAgIENvbnN0YW50cy5ET01fTEFZT1VUX05PUk1BTCA9ICdub3JtYWwnO1xuICAgIENvbnN0YW50cy5ET01fTEFZT1VUX1BSSU5UID0gJ3ByaW50JztcbiAgICBDb25zdGFudHMuRE9NX0xBWU9VVF9BVVRPX0hFSUdIVCA9ICdhdXRvSGVpZ2h0JztcbiAgICBDb25zdGFudHMuR1JPVVBfQVVUT19DT0xVTU5fSUQgPSAnYWctR3JpZC1BdXRvQ29sdW1uJztcbiAgICBDb25zdGFudHMuU09VUkNFX1BBU1RFID0gJ3Bhc3RlJztcbiAgICBDb25zdGFudHMuUElOTkVEX1JJR0hUID0gJ3JpZ2h0JztcbiAgICBDb25zdGFudHMuUElOTkVEX0xFRlQgPSAnbGVmdCc7XG4gICAgQ29uc3RhbnRzLlNPUlRfQVNDID0gJ2FzYyc7XG4gICAgQ29uc3RhbnRzLlNPUlRfREVTQyA9ICdkZXNjJztcbiAgICBDb25zdGFudHMuSU5QVVRfU0VMRUNUT1IgPSAnaW5wdXQsIHNlbGVjdCwgYnV0dG9uLCB0ZXh0YXJlYSc7XG4gICAgQ29uc3RhbnRzLkZPQ1VTQUJMRV9TRUxFQ1RPUiA9ICdbdGFiaW5kZXhdLCBpbnB1dCwgc2VsZWN0LCBidXR0b24sIHRleHRhcmVhJztcbiAgICBDb25zdGFudHMuRk9DVVNBQkxFX0VYQ0xVREUgPSAnLmFnLWhpZGRlbiwgLmFnLWhpZGRlbiAqLCBbZGlzYWJsZWRdLCAuYWctZGlzYWJsZWQsIC5hZy1kaXNhYmxlZCAqJztcbiAgICByZXR1cm4gQ29uc3RhbnRzO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIE1vZHVsZU5hbWVzO1xuKGZ1bmN0aW9uIChNb2R1bGVOYW1lcykge1xuICAgIC8vIHdoZW4gdXNpbmcgbW9kdWxlcywgdXNlciByZWZlcmVuY2VzIHRoaXNcbiAgICBNb2R1bGVOYW1lc1tcIkNvbW11bml0eUNvcmVNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWNvbW11bml0eS9jb3JlXCI7XG4gICAgLy8gd2hlbiBub3QgdXNpbmcgbW9kdWxlcywgdXNlciByZWZlcmVuY2VzIHRoaXNcbiAgICBNb2R1bGVOYW1lc1tcIkNvbW11bml0eUFsbE1vZHVsZXNcIl0gPSBcIkBhZy1ncmlkLWNvbW11bml0eS9hbGxcIjtcbiAgICAvLyBjb21tdW5pdHkgbW9kdWxlc1xuICAgIE1vZHVsZU5hbWVzW1wiSW5maW5pdGVSb3dNb2RlbE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtY29tbXVuaXR5L2luZmluaXRlLXJvdy1tb2RlbFwiO1xuICAgIE1vZHVsZU5hbWVzW1wiQ2xpZW50U2lkZVJvd01vZGVsTW9kdWxlXCJdID0gXCJAYWctZ3JpZC1jb21tdW5pdHkvY2xpZW50LXNpZGUtcm93LW1vZGVsXCI7XG4gICAgTW9kdWxlTmFtZXNbXCJDc3ZFeHBvcnRNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWNvbW11bml0eS9jc3YtZXhwb3J0XCI7XG4gICAgLy8gZW50ZXJwcmlzZSBjb3JlIC0gdXNlcnMgbmV2ZXIgaW1wb3J0IG9uIHRoaXMsIGJ1dCBvdGhlciBlbnRlcnByaXNlIG1vZHVsZXMgZG9cbiAgICBNb2R1bGVOYW1lc1tcIkVudGVycHJpc2VDb3JlTW9kdWxlXCJdID0gXCJAYWctZ3JpZC1lbnRlcnByaXNlL2NvcmVcIjtcbiAgICAvLyB3aGVuIG5vdCB1c2luZyBtb2R1bGVzLCB1c2VyIHJlZmVyZW5jZXMgdGhpc1xuICAgIE1vZHVsZU5hbWVzW1wiRW50ZXJwcmlzZUFsbE1vZHVsZXNcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2UvYWxsXCI7XG4gICAgLy8gZW50ZXJwcmlzZSBtb2R1bGVzXG4gICAgTW9kdWxlTmFtZXNbXCJSb3dHcm91cGluZ01vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9yb3ctZ3JvdXBpbmdcIjtcbiAgICBNb2R1bGVOYW1lc1tcIkNvbHVtblRvb2xQYW5lbE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9jb2x1bW4tdG9vbC1wYW5lbFwiO1xuICAgIE1vZHVsZU5hbWVzW1wiRmlsdGVyc1Rvb2xQYW5lbE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9maWx0ZXItdG9vbC1wYW5lbFwiO1xuICAgIE1vZHVsZU5hbWVzW1wiTWVudU1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9tZW51XCI7XG4gICAgTW9kdWxlTmFtZXNbXCJTZXRGaWx0ZXJNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2Uvc2V0LWZpbHRlclwiO1xuICAgIE1vZHVsZU5hbWVzW1wiTXVsdGlGaWx0ZXJNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2UvbXVsdGktZmlsdGVyXCI7XG4gICAgTW9kdWxlTmFtZXNbXCJTdGF0dXNCYXJNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2Uvc3RhdHVzLWJhclwiO1xuICAgIE1vZHVsZU5hbWVzW1wiU2lkZUJhck1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9zaWRlLWJhclwiO1xuICAgIE1vZHVsZU5hbWVzW1wiUmFuZ2VTZWxlY3Rpb25Nb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2UvcmFuZ2Utc2VsZWN0aW9uXCI7XG4gICAgTW9kdWxlTmFtZXNbXCJNYXN0ZXJEZXRhaWxNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2UvbWFzdGVyLWRldGFpbFwiO1xuICAgIE1vZHVsZU5hbWVzW1wiUmljaFNlbGVjdE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9yaWNoLXNlbGVjdFwiO1xuICAgIE1vZHVsZU5hbWVzW1wiR3JpZENoYXJ0c01vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9jaGFydHNcIjtcbiAgICBNb2R1bGVOYW1lc1tcIlZpZXdwb3J0Um93TW9kZWxNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2Uvdmlld3BvcnQtcm93LW1vZGVsXCI7XG4gICAgTW9kdWxlTmFtZXNbXCJTZXJ2ZXJTaWRlUm93TW9kZWxNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2Uvc2VydmVyLXNpZGUtcm93LW1vZGVsXCI7XG4gICAgTW9kdWxlTmFtZXNbXCJFeGNlbEV4cG9ydE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9leGNlbC1leHBvcnRcIjtcbiAgICBNb2R1bGVOYW1lc1tcIkNsaXBib2FyZE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtZW50ZXJwcmlzZS9jbGlwYm9hcmRcIjtcbiAgICBNb2R1bGVOYW1lc1tcIlNwYXJrbGluZXNNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWVudGVycHJpc2Uvc3BhcmtsaW5lc1wiO1xuICAgIC8vIGZyYW1ld29yayB3cmFwcGVycyBjdXJyZW50bHkgZG9uJ3QgcHJvdmlkZSBiZWFucywgY29tcHMgZXRjLCBzbyBubyBuZWVkIHRvIGJlIG1vZHVsZXMsXG4gICAgLy8gaG93ZXZlciBpIGFyZ3VlIHRoZXkgc2hvdWxkIGJlIGFzIGluIHRoZW9yeSB0aGV5ICdjb3VsZCcgcHJvdmlkZSBiZWFucyBldGNcbiAgICBNb2R1bGVOYW1lc1tcIkFuZ3VsYXJNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWNvbW11bml0eS9hbmd1bGFyXCI7XG4gICAgTW9kdWxlTmFtZXNbXCJSZWFjdE1vZHVsZVwiXSA9IFwiQGFnLWdyaWQtY29tbXVuaXR5L3JlYWN0XCI7XG4gICAgTW9kdWxlTmFtZXNbXCJWdWVNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWNvbW11bml0eS92dWVcIjtcbiAgICBNb2R1bGVOYW1lc1tcIlBvbHltZXJNb2R1bGVcIl0gPSBcIkBhZy1ncmlkLWNvbW11bml0eS9wb2x5bWVyXCI7XG4gICAgLy8gYW5kIHRoZW4gdGhpcywgd2hpY2ggaXMgZGVmaW5pdGVseSBub3QgYSBncmlkIG1vZHVsZSwgYXMgaXQgc2hvdWxkIG5vdCBoYXZlIGFueSBkZXBlbmRlbmN5XG4gICAgLy8gb24gdGhlIGdyaWQgKGllIHNob3VsZG4ndCBldmVuIHJlZmVyZW5jZSB0aGUgTW9kdWxlIGludGVyZmFjZSlcbiAgICAvLyBDaGFydHNNb2R1bGUgPSBcIkBhZy1ncmlkLWNvbW11bml0eS9jaGFydHMtY29yZVwiLFxufSkoTW9kdWxlTmFtZXMgfHwgKE1vZHVsZU5hbWVzID0ge30pKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIE1vZHVsZVJlZ2lzdHJ5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE1vZHVsZVJlZ2lzdHJ5KCkge1xuICAgIH1cbiAgICBNb2R1bGVSZWdpc3RyeS5yZWdpc3RlciA9IGZ1bmN0aW9uIChtb2R1bGUsIG1vZHVsZUJhc2VkKSB7XG4gICAgICAgIGlmIChtb2R1bGVCYXNlZCA9PT0gdm9pZCAwKSB7IG1vZHVsZUJhc2VkID0gdHJ1ZTsgfVxuICAgICAgICBNb2R1bGVSZWdpc3RyeS5tb2R1bGVzTWFwW21vZHVsZS5tb2R1bGVOYW1lXSA9IG1vZHVsZTtcbiAgICAgICAgaWYgKE1vZHVsZVJlZ2lzdHJ5Lm1vZHVsZUJhc2VkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIE1vZHVsZVJlZ2lzdHJ5Lm1vZHVsZUJhc2VkID0gbW9kdWxlQmFzZWQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkubW9kdWxlQmFzZWQgIT09IG1vZHVsZUJhc2VkKSB7XG4gICAgICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogWW91IGFyZSBtaXhpbmcgbW9kdWxlcyAoaS5lLiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSkgYW5kIHBhY2thZ2VzIChhZy1ncmlkLWNvbW11bml0eSkgLSB5b3UgY2FuIG9ubHkgdXNlIG9uZSBvciB0aGUgb3RoZXIgb2YgdGhlc2UgbWVjaGFuaXNtcy5cIik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUGxlYXNlIHNlZSBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9qYXZhc2NyaXB0LWdyaWQvcGFja2FnZXMtbW9kdWxlcy8gZm9yIG1vcmUgaW5mb3JtYXRpb24uJyk7XG4gICAgICAgICAgICAgICAgfSwgJ01vZHVsZVBhY2thZ2VDaGVjaycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBub2luc3BlY3Rpb24gSlNVbnVzZWRHbG9iYWxTeW1ib2xzXG4gICAgTW9kdWxlUmVnaXN0cnkucmVnaXN0ZXJNb2R1bGVzID0gZnVuY3Rpb24gKG1vZHVsZXMsIG1vZHVsZUJhc2VkKSB7XG4gICAgICAgIGlmIChtb2R1bGVCYXNlZCA9PT0gdm9pZCAwKSB7IG1vZHVsZUJhc2VkID0gdHJ1ZTsgfVxuICAgICAgICBpZiAoIW1vZHVsZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBtb2R1bGVzLmZvckVhY2goZnVuY3Rpb24gKG1vZHVsZSkgeyByZXR1cm4gTW9kdWxlUmVnaXN0cnkucmVnaXN0ZXIobW9kdWxlLCBtb2R1bGVCYXNlZCk7IH0pO1xuICAgIH07XG4gICAgTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZCA9IGZ1bmN0aW9uIChtb2R1bGVOYW1lLCByZWFzb24pIHtcbiAgICAgICAgaWYgKHRoaXMuaXNSZWdpc3RlcmVkKG1vZHVsZU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd2FybmluZ0tleSA9IHJlYXNvbiArIG1vZHVsZU5hbWU7XG4gICAgICAgIHZhciB3YXJuaW5nTWVzc2FnZTtcbiAgICAgICAgaWYgKE1vZHVsZVJlZ2lzdHJ5Lm1vZHVsZUJhc2VkKSB7XG4gICAgICAgICAgICB3YXJuaW5nTWVzc2FnZSA9IFwiQUcgR3JpZDogdW5hYmxlIHRvIHVzZSBcIiArIHJlYXNvbiArIFwiIGFzIG1vZHVsZSBcIiArIG1vZHVsZU5hbWUgKyBcIiBpcyBub3QgcHJlc2VudC4gUGxlYXNlIHNlZTogaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vamF2YXNjcmlwdC1ncmlkL21vZHVsZXMvXCI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB3YXJuaW5nTWVzc2FnZSA9IFwiQUcgR3JpZDogdW5hYmxlIHRvIHVzZSBcIiArIHJlYXNvbiArIFwiIGFzIHBhY2thZ2UgJ2FnLWdyaWQtZW50ZXJwcmlzZScgaXMgbm90IHByZXNlbnQuIFBsZWFzZSBzZWU6IGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL2phdmFzY3JpcHQtZ3JpZC9wYWNrYWdlcy9cIjtcbiAgICAgICAgfVxuICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKHdhcm5pbmdNZXNzYWdlKTtcbiAgICAgICAgfSwgd2FybmluZ0tleSk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZCA9IGZ1bmN0aW9uIChtb2R1bGVOYW1lKSB7XG4gICAgICAgIHJldHVybiAhIU1vZHVsZVJlZ2lzdHJ5Lm1vZHVsZXNNYXBbbW9kdWxlTmFtZV07XG4gICAgfTtcbiAgICBNb2R1bGVSZWdpc3RyeS5nZXRSZWdpc3RlcmVkTW9kdWxlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlcyhNb2R1bGVSZWdpc3RyeS5tb2R1bGVzTWFwKTtcbiAgICB9O1xuICAgIE1vZHVsZVJlZ2lzdHJ5LmlzUGFja2FnZUJhc2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gIU1vZHVsZVJlZ2lzdHJ5Lm1vZHVsZUJhc2VkO1xuICAgIH07XG4gICAgLy8gaGF2aW5nIGluIGEgbWFwIGEpIHJlbW92ZXMgZHVwbGljYXRlcyBhbmQgYikgYWxsb3dzIGZhc3QgbG9va3VwXG4gICAgTW9kdWxlUmVnaXN0cnkubW9kdWxlc01hcCA9IHt9O1xuICAgIHJldHVybiBNb2R1bGVSZWdpc3RyeTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2RlY29yYXRlJDJ6ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgaW5zdGFuY2VJZFNlcXVlbmNlJDQgPSAwO1xuLy8gV3JhcHBlciBhcm91bmQgYSB1c2VyIHByb3ZpZGUgY29sdW1uIGRlZmluaXRpb24uIFRoZSBncmlkIHRyZWF0cyB0aGUgY29sdW1uIGRlZmluaXRpb24gYXMgcmVhZHkgb25seS5cbi8vIFRoaXMgY2xhc3MgY29udGFpbnMgYWxsIHRoZSBydW50aW1lIGluZm9ybWF0aW9uIGFib3V0IGEgY29sdW1uLCBwbHVzIHNvbWUgbG9naWMgKHRoZSBkZWZpbml0aW9uIGhhcyBubyBsb2dpYykuXG4vLyBUaGlzIGNsYXNzIGltcGxlbWVudHMgYm90aCBpbnRlcmZhY2VzIENvbHVtbkdyb3VwQ2hpbGQgYW5kIFByb3ZpZGVkQ29sdW1uR3JvdXBDaGlsZCBhcyB0aGUgY2xhc3MgY2FuXG4vLyBhcHBlYXIgYXMgYSBjaGlsZCBvZiBlaXRoZXIgdGhlIG9yaWdpbmFsIHRyZWUgb3IgdGhlIGRpc3BsYXllZCB0cmVlLiBIb3dldmVyIHRoZSByZWxldmFudCBncm91cCBjbGFzc2VzXG4vLyBmb3IgZWFjaCB0eXBlIG9ubHkgaW1wbGVtZW50cyBvbmUsIGFzIGVhY2ggZ3JvdXAgY2FuIG9ubHkgYXBwZWFyIGluIGl0J3MgYXNzb2NpYXRlZCB0cmVlIChlZyBQcm92aWRlZENvbHVtbkdyb3VwXG4vLyBjYW4gb25seSBhcHBlYXIgaW4gT3JpZ2luYWxDb2x1bW4gdHJlZSkuXG52YXIgQ29sdW1uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbHVtbihjb2xEZWYsIHVzZXJQcm92aWRlZENvbERlZiwgY29sSWQsIHByaW1hcnkpIHtcbiAgICAgICAgLy8gdXNlZCBieSBSZWFjdCAoYW5kIHBvc3NpYmx5IG90aGVyIGZyYW1ld29ya3MpIGFzIGtleSBmb3IgcmVuZGVyaW5nXG4gICAgICAgIHRoaXMuaW5zdGFuY2VJZCA9IGluc3RhbmNlSWRTZXF1ZW5jZSQ0Kys7XG4gICAgICAgIC8vIFRoZSBtZWFzdXJlZCBoZWlnaHQgb2YgdGhpcyBjb2x1bW4ncyBoZWFkZXIgd2hlbiBhdXRvSGVhZGVySGVpZ2h0IGlzIGVuYWJsZWRcbiAgICAgICAgdGhpcy5hdXRvSGVhZGVySGVpZ2h0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5tb3ZpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5tZW51VmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmZpbHRlckFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZSA9IG5ldyBFdmVudFNlcnZpY2UoKTtcbiAgICAgICAgdGhpcy5yb3dHcm91cEFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBpdm90QWN0aXZlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYWdncmVnYXRpb25BY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jb2xEZWYgPSBjb2xEZWY7XG4gICAgICAgIHRoaXMudXNlclByb3ZpZGVkQ29sRGVmID0gdXNlclByb3ZpZGVkQ29sRGVmO1xuICAgICAgICB0aGlzLmNvbElkID0gY29sSWQ7XG4gICAgICAgIHRoaXMucHJpbWFyeSA9IHByaW1hcnk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoY29sRGVmKTtcbiAgICB9XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRJbnN0YW5jZUlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZUlkO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRTdGF0ZSA9IGZ1bmN0aW9uIChjb2xEZWYpIHtcbiAgICAgICAgLy8gc29ydFxuICAgICAgICBpZiAoY29sRGVmLnNvcnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGNvbERlZi5zb3J0ID09PSBDb25zdGFudHMuU09SVF9BU0MgfHwgY29sRGVmLnNvcnQgPT09IENvbnN0YW50cy5TT1JUX0RFU0MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNvcnQgPSBjb2xEZWYuc29ydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb2xEZWYuaW5pdGlhbFNvcnQgPT09IENvbnN0YW50cy5TT1JUX0FTQyB8fCBjb2xEZWYuaW5pdGlhbFNvcnQgPT09IENvbnN0YW50cy5TT1JUX0RFU0MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNvcnQgPSBjb2xEZWYuaW5pdGlhbFNvcnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gc29ydEluZGV4XG4gICAgICAgIHZhciBzb3J0SW5kZXggPSBhdHRyVG9OdW1iZXIoY29sRGVmLnNvcnRJbmRleCk7XG4gICAgICAgIHZhciBpbml0aWFsU29ydEluZGV4ID0gYXR0clRvTnVtYmVyKGNvbERlZi5pbml0aWFsU29ydEluZGV4KTtcbiAgICAgICAgaWYgKHNvcnRJbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAoc29ydEluZGV4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zb3J0SW5kZXggPSBzb3J0SW5kZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoaW5pdGlhbFNvcnRJbmRleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc29ydEluZGV4ID0gaW5pdGlhbFNvcnRJbmRleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBoaWRlXG4gICAgICAgIHZhciBoaWRlID0gYXR0clRvQm9vbGVhbihjb2xEZWYuaGlkZSk7XG4gICAgICAgIHZhciBpbml0aWFsSGlkZSA9IGF0dHJUb0Jvb2xlYW4oY29sRGVmLmluaXRpYWxIaWRlKTtcbiAgICAgICAgaWYgKGhpZGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy52aXNpYmxlID0gIWhpZGU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpc2libGUgPSAhaW5pdGlhbEhpZGU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcGlubmVkXG4gICAgICAgIGlmIChjb2xEZWYucGlubmVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0UGlubmVkKGNvbERlZi5waW5uZWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRQaW5uZWQoY29sRGVmLmluaXRpYWxQaW5uZWQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGZsZXhcbiAgICAgICAgdmFyIGZsZXggPSBhdHRyVG9OdW1iZXIoY29sRGVmLmZsZXgpO1xuICAgICAgICB2YXIgaW5pdGlhbEZsZXggPSBhdHRyVG9OdW1iZXIoY29sRGVmLmluaXRpYWxGbGV4KTtcbiAgICAgICAgaWYgKGZsZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5mbGV4ID0gZmxleDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpbml0aWFsRmxleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmZsZXggPSBpbml0aWFsRmxleDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZ2V0cyBjYWxsZWQgd2hlbiB1c2VyIHByb3ZpZGVzIGFuIGFsdGVybmF0aXZlIGNvbERlZiwgZWdcbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldENvbERlZiA9IGZ1bmN0aW9uIChjb2xEZWYsIHVzZXJQcm92aWRlZENvbERlZikge1xuICAgICAgICB0aGlzLmNvbERlZiA9IGNvbERlZjtcbiAgICAgICAgdGhpcy51c2VyUHJvdmlkZWRDb2xEZWYgPSB1c2VyUHJvdmlkZWRDb2xEZWY7XG4gICAgICAgIHRoaXMuaW5pdE1pbkFuZE1heFdpZHRocygpO1xuICAgICAgICB0aGlzLmluaXREb3ROb3RhdGlvbigpO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQ29sdW1uRXZlbnQoQ29sdW1uLkVWRU5UX0NPTF9ERUZfQ0hBTkdFRCwgXCJhcGlcIikpO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29sdW1uIGRlZmluaXRpb24gcHJvdmlkZWQgYnkgdGhlIGFwcGxpY2F0aW9uLlxuICAgICAqIFRoaXMgbWF5IG5vdCBiZSBjb3JyZWN0LCBhcyBpdGVtcyBjYW4gYmUgc3VwZXJzZWRlZCBieSBkZWZhdWx0IGNvbHVtbiBvcHRpb25zLlxuICAgICAqIEhvd2V2ZXIgaXQncyB1c2VmdWwgZm9yIGNvbXBhcmlzb24sIGVnIHRvIGtub3cgd2hpY2ggYXBwbGljYXRpb24gY29sdW1uIGRlZmluaXRpb24gbWF0Y2hlcyB0aGF0IGNvbHVtbi5cbiAgICAgKi9cbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldFVzZXJQcm92aWRlZENvbERlZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudXNlclByb3ZpZGVkQ29sRGVmO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRQYXJlbnQgPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIHBhcmVudCBjb2x1bW4gZ3JvdXAsIGlmIGNvbHVtbiBncm91cGluZyBpcyBhY3RpdmUuICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRQYXJlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudDtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0T3JpZ2luYWxQYXJlbnQgPSBmdW5jdGlvbiAob3JpZ2luYWxQYXJlbnQpIHtcbiAgICAgICAgdGhpcy5vcmlnaW5hbFBhcmVudCA9IG9yaWdpbmFsUGFyZW50O1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRPcmlnaW5hbFBhcmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3JpZ2luYWxQYXJlbnQ7XG4gICAgfTtcbiAgICAvLyB0aGlzIGlzIGRvbmUgYWZ0ZXIgY29uc3RydWN0b3IgYXMgaXQgdXNlcyBncmlkT3B0aW9uc1dyYXBwZXJcbiAgICBDb2x1bW4ucHJvdG90eXBlLmluaXRpYWxpc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuaW5pdE1pbkFuZE1heFdpZHRocygpO1xuICAgICAgICB0aGlzLnJlc2V0QWN0dWFsV2lkdGgoJ2dyaWRJbml0aWFsaXppbmcnKTtcbiAgICAgICAgdGhpcy5pbml0RG90Tm90YXRpb24oKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZSgpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pbml0RG90Tm90YXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzdXBwcmVzc0RvdE5vdGF0aW9uID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0ZpZWxkRG90Tm90YXRpb24oKTtcbiAgICAgICAgdGhpcy5maWVsZENvbnRhaW5zRG90cyA9IGV4aXN0cyh0aGlzLmNvbERlZi5maWVsZCkgJiYgdGhpcy5jb2xEZWYuZmllbGQuaW5kZXhPZignLicpID49IDAgJiYgIXN1cHByZXNzRG90Tm90YXRpb247XG4gICAgICAgIHRoaXMudG9vbHRpcEZpZWxkQ29udGFpbnNEb3RzID0gZXhpc3RzKHRoaXMuY29sRGVmLnRvb2x0aXBGaWVsZCkgJiYgdGhpcy5jb2xEZWYudG9vbHRpcEZpZWxkLmluZGV4T2YoJy4nKSA+PSAwICYmICFzdXBwcmVzc0RvdE5vdGF0aW9uO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pbml0TWluQW5kTWF4V2lkdGhzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2xEZWY7XG4gICAgICAgIHRoaXMubWluV2lkdGggPSB0aGlzLmNvbHVtblV0aWxzLmNhbGN1bGF0ZUNvbE1pbldpZHRoKGNvbERlZik7XG4gICAgICAgIHRoaXMubWF4V2lkdGggPSB0aGlzLmNvbHVtblV0aWxzLmNhbGN1bGF0ZUNvbE1heFdpZHRoKGNvbERlZik7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLnJlc2V0QWN0dWFsV2lkdGggPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSAnYXBpJzsgfVxuICAgICAgICB2YXIgaW5pdGlhbFdpZHRoID0gdGhpcy5jb2x1bW5VdGlscy5jYWxjdWxhdGVDb2xJbml0aWFsV2lkdGgodGhpcy5jb2xEZWYpO1xuICAgICAgICB0aGlzLnNldEFjdHVhbFdpZHRoKGluaXRpYWxXaWR0aCwgc291cmNlLCB0cnVlKTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNFbXB0eUdyb3VwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzUm93R3JvdXBEaXNwbGF5ZWQgPSBmdW5jdGlvbiAoY29sSWQpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy5jb2xEZWYpIHx8IG1pc3NpbmcodGhpcy5jb2xEZWYuc2hvd1Jvd0dyb3VwKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaG93aW5nQWxsR3JvdXBzID0gdGhpcy5jb2xEZWYuc2hvd1Jvd0dyb3VwID09PSB0cnVlO1xuICAgICAgICB2YXIgc2hvd2luZ1RoaXNHcm91cCA9IHRoaXMuY29sRGVmLnNob3dSb3dHcm91cCA9PT0gY29sSWQ7XG4gICAgICAgIHJldHVybiBzaG93aW5nQWxsR3JvdXBzIHx8IHNob3dpbmdUaGlzR3JvdXA7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBgdHJ1ZWAgaWYgY29sdW1uIGlzIGEgcHJpbWFyeSBjb2x1bW4sIGBmYWxzZWAgaWYgc2Vjb25kYXJ5LiBTZWNvbmRhcnkgY29sdW1ucyBhcmUgdXNlZCBmb3IgcGl2b3RpbmcuICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1ByaW1hcnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW1hcnk7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBgdHJ1ZWAgaWYgY29sdW1uIGZpbHRlcmluZyBpcyBhbGxvd2VkLiAqL1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNGaWx0ZXJBbGxvd2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBmaWx0ZXIgZGVmaW5lZCBtZWFucyBpdCdzIGEgc3RyaW5nLCBjbGFzcyBvciB0cnVlLlxuICAgICAgICAvLyBpZiBpdHMgZmFsc2UsIG51bGwgb3IgdW5kZWZpbmVkIHRoZW4gaXQncyBmYWxzZS5cbiAgICAgICAgdmFyIGZpbHRlckRlZmluZWQgPSAhIXRoaXMuY29sRGVmLmZpbHRlciB8fCAhIXRoaXMuY29sRGVmLmZpbHRlckZyYW1ld29yaztcbiAgICAgICAgcmV0dXJuIGZpbHRlckRlZmluZWQ7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzRmllbGRDb250YWluc0RvdHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpZWxkQ29udGFpbnNEb3RzO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1Rvb2x0aXBGaWVsZENvbnRhaW5zRG90cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9vbHRpcEZpZWxkQ29udGFpbnNEb3RzO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS52YWxpZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbERlZkFueSA9IHRoaXMuY29sRGVmO1xuICAgICAgICBmdW5jdGlvbiB3YXJuT25jZShtc2csIGtleSwgb2JqKSB7XG4gICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKG1zZywgb2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4obXNnKTsgfSwga2V5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1c2luZ0NTUk0gPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd01vZGVsRGVmYXVsdCgpO1xuICAgICAgICBpZiAodXNpbmdDU1JNICYmICFNb2R1bGVSZWdpc3RyeS5pc1JlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuUm93R3JvdXBpbmdNb2R1bGUpKSB7XG4gICAgICAgICAgICB2YXIgcm93R3JvdXBpbmdJdGVtcyA9IFsnZW5hYmxlUm93R3JvdXAnLCAncm93R3JvdXAnLCAncm93R3JvdXBJbmRleCcsICdlbmFibGVQaXZvdCcsICdlbmFibGVWYWx1ZScsICdwaXZvdCcsICdwaXZvdEluZGV4JywgJ2FnZ0Z1bmMnXTtcbiAgICAgICAgICAgIHJvd0dyb3VwaW5nSXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgICAgIGlmIChleGlzdHMoY29sRGVmQW55W2l0ZW1dKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuaXNQYWNrYWdlQmFzZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2Fybk9uY2UoXCJBRyBHcmlkOiBcIiArIGl0ZW0gKyBcIiBpcyBvbmx5IHZhbGlkIGluIGFnLWdyaWQtZW50ZXJwcmlzZSwgeW91ciBjb2x1bW4gZGVmaW5pdGlvbiBzaG91bGQgbm90IGhhdmUgXCIgKyBpdGVtLCAnQ29sdW1uUm93R3JvdXBpbmdNaXNzaW5nJyArIGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2Fybk9uY2UoXCJBRyBHcmlkOiBcIiArIGl0ZW0gKyBcIiBpcyBvbmx5IHZhbGlkIHdpdGggQUcgR3JpZCBFbnRlcnByaXNlIE1vZHVsZSBcIiArIE1vZHVsZU5hbWVzLlJvd0dyb3VwaW5nTW9kdWxlICsgXCIgLSB5b3VyIGNvbHVtbiBkZWZpbml0aW9uIHNob3VsZCBub3QgaGF2ZSBcIiArIGl0ZW0sICdDb2x1bW5Sb3dHcm91cGluZ01pc3NpbmcnICsgaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIU1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5SaWNoU2VsZWN0TW9kdWxlKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29sRGVmLmNlbGxFZGl0b3IgPT09ICdhZ1JpY2hTZWxlY3QnIHx8IHRoaXMuY29sRGVmLmNlbGxFZGl0b3IgPT09ICdhZ1JpY2hTZWxlY3RDZWxsRWRpdG9yJykge1xuICAgICAgICAgICAgICAgIGlmIChNb2R1bGVSZWdpc3RyeS5pc1BhY2thZ2VCYXNlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHdhcm5PbmNlKFwiQUcgR3JpZDogXCIgKyB0aGlzLmNvbERlZi5jZWxsRWRpdG9yICsgXCIgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIGFnLWdyaWQtZW50ZXJwcmlzZVwiLCAnQ29sdW1uUmljaFNlbGVjdE1pc3NpbmcnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHdhcm5PbmNlKFwiQUcgR3JpZDogXCIgKyB0aGlzLmNvbERlZi5jZWxsRWRpdG9yICsgXCIgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIEFHIEdyaWQgRW50ZXJwcmlzZSBNb2R1bGUgXCIgKyBNb2R1bGVOYW1lcy5SaWNoU2VsZWN0TW9kdWxlLCAnQ29sdW1uUmljaFNlbGVjdE1pc3NpbmcnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKSkge1xuICAgICAgICAgICAgdmFyIGl0ZW1zTm90QWxsb3dlZFdpdGhUcmVlRGF0YSA9IFsncm93R3JvdXAnLCAncm93R3JvdXBJbmRleCcsICdwaXZvdCcsICdwaXZvdEluZGV4J107XG4gICAgICAgICAgICBpdGVtc05vdEFsbG93ZWRXaXRoVHJlZURhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgICAgIGlmIChleGlzdHMoY29sRGVmQW55W2l0ZW1dKSkge1xuICAgICAgICAgICAgICAgICAgICB3YXJuT25jZShcIkFHIEdyaWQ6IFwiICsgaXRlbSArIFwiIGlzIG5vdCBwb3NzaWJsZSB3aGVuIGRvaW5nIHRyZWUgZGF0YSwgeW91ciBjb2x1bW4gZGVmaW5pdGlvbiBzaG91bGQgbm90IGhhdmUgXCIgKyBpdGVtLCAnVHJlZURhdGFDYW5ub3RSb3dHcm91cCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChleGlzdHModGhpcy5jb2xEZWYud2lkdGgpICYmIHR5cGVvZiB0aGlzLmNvbERlZi53aWR0aCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHdhcm5PbmNlKCdBRyBHcmlkOiBjb2xEZWYud2lkdGggc2hvdWxkIGJlIGEgbnVtYmVyLCBub3QgJyArIHR5cGVvZiB0aGlzLmNvbERlZi53aWR0aCwgJ0NvbHVtbkNoZWNrX2FzZGZhd2VmJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbERlZkFueS5waW5uZWRSb3dDZWxsUmVuZGVyZXIpIHtcbiAgICAgICAgICAgIHdhcm5PbmNlKCdBRyBHcmlkOiBwaW5uZWRSb3dDZWxsUmVuZGVyZXIgbm8gbG9uZ2VyIGV4aXN0cywgdXNlIGNlbGxSZW5kZXJlclNlbGVjdG9yIGlmIHlvdSB3YW50IGEgZGlmZmVyZW50IENlbGwgUmVuZGVyZXIgZm9yIHBpbm5lZCByb3dzLiBDaGVjayBwYXJhbXMubm9kZS5yb3dQaW5uZWQuIFRoaXMgd2FzIGFuIHVuZm9ydHVuYXRlIChidXQgbmVjZXNzYXJ5KSBjaGFuZ2Ugd2UgaGFkIHRvIGRvIHRvIGFsbG93IGZ1dHVyZSBwbGFucyB3ZSBoYXZlIG9mIHJlLXNraW5uZyB0aGUgZGF0YSBncmlkIGluIGZyYW1ld29ya3Mgc3VjaCBhcyBSZWFjdCwgQW5ndWxhciBhbmQgVnVlLiBTZWUgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vamF2YXNjcmlwdC1ncmlkL2NlbGwtcmVuZGVyaW5nLyNtYW55LXJlbmRlcmVycy1vbmUtY29sdW1uJywgJ2NvbERlZi5waW5uZWRSb3dDZWxsUmVuZGVyZXItZGVwcmVjYXRlZCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb2xEZWZBbnkucGlubmVkUm93Q2VsbFJlbmRlcmVyUGFyYW1zKSB7XG4gICAgICAgICAgICB3YXJuT25jZSgnQUcgR3JpZDogcGlubmVkUm93Q2VsbFJlbmRlcmVyIG5vIGxvbmdlciBleGlzdHMsIHVzZSBjZWxsUmVuZGVyZXJTZWxlY3RvciBpZiB5b3Ugd2FudCBhIGRpZmZlcmVudCBDZWxsIFJlbmRlcmVyIGZvciBwaW5uZWQgcm93cy4gQ2hlY2sgcGFyYW1zLm5vZGUucm93UGlubmVkLiBUaGlzIHdhcyBhbiB1bmZvcnR1bmF0ZSAoYnV0IG5lY2Vzc2FyeSkgY2hhbmdlIHdlIGhhZCB0byBkbyB0byBhbGxvdyBmdXR1cmUgcGxhbnMgd2UgaGF2ZSBvZiByZS1za2lubmcgdGhlIGRhdGEgZ3JpZCBpbiBmcmFtZXdvcmtzIHN1Y2ggYXMgUmVhY3QsIEFuZ3VsYXIgYW5kIFZ1ZS4gU2VlIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL2phdmFzY3JpcHQtZ3JpZC9jZWxsLXJlbmRlcmluZy8jbWFueS1yZW5kZXJlcnMtb25lLWNvbHVtbicsICdjb2xEZWYucGlubmVkUm93Q2VsbFJlbmRlcmVyLWRlcHJlY2F0ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29sRGVmQW55LnBpbm5lZFJvd0NlbGxSZW5kZXJlckZyYW1ld29yaykge1xuICAgICAgICAgICAgd2Fybk9uY2UoJ0FHIEdyaWQ6IHBpbm5lZFJvd0NlbGxSZW5kZXJlciBubyBsb25nZXIgZXhpc3RzLCB1c2UgY2VsbFJlbmRlcmVyU2VsZWN0b3IgaWYgeW91IHdhbnQgYSBkaWZmZXJlbnQgQ2VsbCBSZW5kZXJlciBmb3IgcGlubmVkIHJvd3MuIENoZWNrIHBhcmFtcy5ub2RlLnJvd1Bpbm5lZC4gVGhpcyB3YXMgYW4gdW5mb3J0dW5hdGUgKGJ1dCBuZWNlc3NhcnkpIGNoYW5nZSB3ZSBoYWQgdG8gZG8gdG8gYWxsb3cgZnV0dXJlIHBsYW5zIHdlIGhhdmUgb2YgcmUtc2tpbm5nIHRoZSBkYXRhIGdyaWQgaW4gZnJhbWV3b3JrcyBzdWNoIGFzIFJlYWN0LCBBbmd1bGFyIGFuZCBWdWUuIFNlZSBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9qYXZhc2NyaXB0LWdyaWQvY2VsbC1yZW5kZXJpbmcvI21hbnktcmVuZGVyZXJzLW9uZS1jb2x1bW4nLCAnY29sRGVmLnBpbm5lZFJvd0NlbGxSZW5kZXJlci1kZXByZWNhdGVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbERlZkFueS5waW5uZWRSb3dWYWx1ZUdldHRlcikge1xuICAgICAgICAgICAgd2Fybk9uY2UoJ0FHIEdyaWQ6IHBpbm5lZFJvd0NlbGxSZW5kZXJlciBpcyBkZXByZWNhdGVkLCB1c2UgY2VsbFJlbmRlcmVyU2VsZWN0b3IgaWYgeW91IHdhbnQgYSBkaWZmZXJlbnQgQ2VsbCBSZW5kZXJlciBmb3IgcGlubmVkIHJvd3MuIENoZWNrIHBhcmFtcy5ub2RlLnJvd1Bpbm5lZC4gVGhpcyB3YXMgYW4gdW5mb3J0dW5hdGUgKGJ1dCBuZWNlc3NhcnkpIGNoYW5nZSB3ZSBoYWQgdG8gZG8gdG8gYWxsb3cgZnV0dXJlIHBsYW5zIHdlIGhhdmUgb2YgcmUtc2tpbm5nIHRoZSBkYXRhIGdyaWQgaW4gZnJhbWV3b3JrcyBzdWNoIGFzIFJlYWN0LCBBbmd1bGFyIGFuZCBWdWUuJywgJ2NvbERlZi5waW5uZWRSb3dDZWxsUmVuZGVyZXItZGVwcmVjYXRlZCcpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQWRkIGFuIGV2ZW50IGxpc3RlbmVyIHRvIHRoZSBjb2x1bW4uICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuYWRkRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIC8qKiBSZW1vdmUgZXZlbnQgbGlzdGVuZXIgZnJvbSB0aGUgY29sdW1uLiAqL1xuICAgIENvbHVtbi5wcm90b3R5cGUucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmNyZWF0ZUNvbHVtbkZ1bmN0aW9uQ2FsbGJhY2tQYXJhbXMgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbm9kZTogcm93Tm9kZSxcbiAgICAgICAgICAgIGRhdGE6IHJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcyxcbiAgICAgICAgICAgIGNvbERlZjogdGhpcy5jb2xEZWYsXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKVxuICAgICAgICB9O1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1N1cHByZXNzTmF2aWdhYmxlID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgLy8gaWYgYm9vbGVhbiBzZXQsIHRoZW4ganVzdCB1c2UgaXRcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmNvbERlZi5zdXBwcmVzc05hdmlnYWJsZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2xEZWYuc3VwcHJlc3NOYXZpZ2FibGU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgZnVuY3Rpb24sIHRoZW4gY2FsbCB0aGUgZnVuY3Rpb24gdG8gZmluZCBvdXRcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmNvbERlZi5zdXBwcmVzc05hdmlnYWJsZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHRoaXMuY3JlYXRlQ29sdW1uRnVuY3Rpb25DYWxsYmFja1BhcmFtcyhyb3dOb2RlKTtcbiAgICAgICAgICAgIHZhciB1c2VyRnVuYyA9IHRoaXMuY29sRGVmLnN1cHByZXNzTmF2aWdhYmxlO1xuICAgICAgICAgICAgcmV0dXJuIHVzZXJGdW5jKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0NlbGxFZGl0YWJsZSA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIC8vIG9ubHkgYWxsb3cgZWRpdGluZyBvZiBncm91cHMgaWYgdGhlIHVzZXIgaGFzIHRoaXMgb3B0aW9uIGVuYWJsZWRcbiAgICAgICAgaWYgKHJvd05vZGUuZ3JvdXAgJiYgIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlR3JvdXBFZGl0KCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5pc0NvbHVtbkZ1bmMocm93Tm9kZSwgdGhpcy5jb2xEZWYuZWRpdGFibGUpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1N1cHByZXNzRmlsbEhhbmRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhYXR0clRvQm9vbGVhbih0aGlzLmNvbERlZi5zdXBwcmVzc0ZpbGxIYW5kbGUpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0F1dG9IZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhIWF0dHJUb0Jvb2xlYW4odGhpcy5jb2xEZWYuYXV0b0hlaWdodCk7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzQXV0b0hlYWRlckhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhYXR0clRvQm9vbGVhbih0aGlzLmNvbERlZi5hdXRvSGVhZGVySGVpZ2h0KTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNSb3dEcmFnID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNDb2x1bW5GdW5jKHJvd05vZGUsIHRoaXMuY29sRGVmLnJvd0RyYWcpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0RuZFNvdXJjZSA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzQ29sdW1uRnVuYyhyb3dOb2RlLCB0aGlzLmNvbERlZi5kbmRTb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0NlbGxDaGVja2JveFNlbGVjdGlvbiA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzQ29sdW1uRnVuYyhyb3dOb2RlLCB0aGlzLmNvbERlZi5jaGVja2JveFNlbGVjdGlvbik7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzU3VwcHJlc3NQYXN0ZSA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzQ29sdW1uRnVuYyhyb3dOb2RlLCB0aGlzLmNvbERlZiA/IHRoaXMuY29sRGVmLnN1cHByZXNzUGFzdGUgOiBudWxsKTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNSZXNpemFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhIWF0dHJUb0Jvb2xlYW4odGhpcy5jb2xEZWYucmVzaXphYmxlKTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNDb2x1bW5GdW5jID0gZnVuY3Rpb24gKHJvd05vZGUsIHZhbHVlKSB7XG4gICAgICAgIC8vIGlmIGJvb2xlYW4gc2V0LCB0aGVuIGp1c3QgdXNlIGl0XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGZ1bmN0aW9uLCB0aGVuIGNhbGwgdGhlIGZ1bmN0aW9uIHRvIGZpbmQgb3V0XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSB0aGlzLmNyZWF0ZUNvbHVtbkZ1bmN0aW9uQ2FsbGJhY2tQYXJhbXMocm93Tm9kZSk7XG4gICAgICAgICAgICB2YXIgZWRpdGFibGVGdW5jID0gdmFsdWU7XG4gICAgICAgICAgICByZXR1cm4gZWRpdGFibGVGdW5jKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRNb3ZpbmcgPSBmdW5jdGlvbiAobW92aW5nLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy5tb3ZpbmcgPSBtb3Zpbmc7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfTU9WSU5HX0NIQU5HRUQsIHNvdXJjZSkpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5jcmVhdGVDb2x1bW5FdmVudCA9IGZ1bmN0aW9uICh0eXBlLCBzb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICBjb2x1bW46IHRoaXMsXG4gICAgICAgICAgICBjb2x1bW5zOiBbdGhpc10sXG4gICAgICAgICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgICAgICAgIGFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzTW92aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tb3Zpbmc7XG4gICAgfTtcbiAgICAvKiogSWYgc29ydGluZyBpcyBhY3RpdmUsIHJldHVybnMgdGhlIHNvcnQgZGlyZWN0aW9uIGUuZy4gYCdhc2MnYCBvciBgJ2Rlc2MnYC4gKi9cbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldFNvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNvcnQ7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldFNvcnQgPSBmdW5jdGlvbiAoc29ydCwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmICh0aGlzLnNvcnQgIT09IHNvcnQpIHtcbiAgICAgICAgICAgIHRoaXMuc29ydCA9IHNvcnQ7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQ29sdW1uRXZlbnQoQ29sdW1uLkVWRU5UX1NPUlRfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0TWVudVZpc2libGUgPSBmdW5jdGlvbiAodmlzaWJsZSwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmICh0aGlzLm1lbnVWaXNpYmxlICE9PSB2aXNpYmxlKSB7XG4gICAgICAgICAgICB0aGlzLm1lbnVWaXNpYmxlID0gdmlzaWJsZTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfTUVOVV9WSVNJQkxFX0NIQU5HRUQsIHNvdXJjZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzTWVudVZpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lbnVWaXNpYmxlO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1NvcnRBc2NlbmRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNvcnQgPT09IENvbnN0YW50cy5TT1JUX0FTQztcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNTb3J0RGVzY2VuZGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc29ydCA9PT0gQ29uc3RhbnRzLlNPUlRfREVTQztcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNTb3J0Tm9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG1pc3NpbmcodGhpcy5zb3J0KTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNTb3J0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZXhpc3RzKHRoaXMuc29ydCk7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldFNvcnRJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc29ydEluZGV4O1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRTb3J0SW5kZXggPSBmdW5jdGlvbiAoc29ydE9yZGVyKSB7XG4gICAgICAgIHRoaXMuc29ydEluZGV4ID0gc29ydE9yZGVyO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRBZ2dGdW5jID0gZnVuY3Rpb24gKGFnZ0Z1bmMpIHtcbiAgICAgICAgdGhpcy5hZ2dGdW5jID0gYWdnRnVuYztcbiAgICB9O1xuICAgIC8qKiBJZiBhZ2dyZWdhdGlvbiBpcyBzZXQgZm9yIHRoZSBjb2x1bW4sIHJldHVybnMgdGhlIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uLiAqL1xuICAgIENvbHVtbi5wcm90b3R5cGUuZ2V0QWdnRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWdnRnVuYztcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuZ2V0TGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGVmdDtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuZ2V0T2xkTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub2xkTGVmdDtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuZ2V0UmlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxlZnQgKyB0aGlzLmFjdHVhbFdpZHRoO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRMZWZ0ID0gZnVuY3Rpb24gKGxlZnQsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB0aGlzLm9sZExlZnQgPSB0aGlzLmxlZnQ7XG4gICAgICAgIGlmICh0aGlzLmxlZnQgIT09IGxlZnQpIHtcbiAgICAgICAgICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQ29sdW1uRXZlbnQoQ29sdW1uLkVWRU5UX0xFRlRfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiBmaWx0ZXIgaXMgYWN0aXZlIG9uIHRoZSBjb2x1bW4uICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0ZpbHRlckFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyQWN0aXZlO1xuICAgIH07XG4gICAgLy8gYWRkaXRpb25hbEV2ZW50QXR0cmlidXRlcyBpcyB1c2VkIGJ5IHByb3ZpZGVkIHNpbXBsZSBmbG9hdGluZyBmaWx0ZXIsIHNvIGl0IGNhbiBhZGQgJ2Zsb2F0aW5nRmlsdGVyPXRydWUnIHRvIHRoZSBldmVudFxuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0RmlsdGVyQWN0aXZlID0gZnVuY3Rpb24gKGFjdGl2ZSwgc291cmNlLCBhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmICh0aGlzLmZpbHRlckFjdGl2ZSAhPT0gYWN0aXZlKSB7XG4gICAgICAgICAgICB0aGlzLmZpbHRlckFjdGl2ZSA9IGFjdGl2ZTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfRklMVEVSX0FDVElWRV9DSEFOR0VELCBzb3VyY2UpKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmlsdGVyQ2hhbmdlZEV2ZW50ID0gdGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfRklMVEVSX0NIQU5HRUQsIHNvdXJjZSk7XG4gICAgICAgIGlmIChhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICBtZXJnZURlZXAoZmlsdGVyQ2hhbmdlZEV2ZW50LCBhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGZpbHRlckNoYW5nZWRFdmVudCk7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldFBpbm5lZCA9IGZ1bmN0aW9uIChwaW5uZWQpIHtcbiAgICAgICAgaWYgKHBpbm5lZCA9PT0gdHJ1ZSB8fCBwaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfTEVGVCkge1xuICAgICAgICAgICAgdGhpcy5waW5uZWQgPSBDb25zdGFudHMuUElOTkVEX0xFRlQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX1JJR0hUKSB7XG4gICAgICAgICAgICB0aGlzLnBpbm5lZCA9IENvbnN0YW50cy5QSU5ORURfUklHSFQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBpbm5lZCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0Rmlyc3RSaWdodFBpbm5lZCA9IGZ1bmN0aW9uIChmaXJzdFJpZ2h0UGlubmVkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKHRoaXMuZmlyc3RSaWdodFBpbm5lZCAhPT0gZmlyc3RSaWdodFBpbm5lZCkge1xuICAgICAgICAgICAgdGhpcy5maXJzdFJpZ2h0UGlubmVkID0gZmlyc3RSaWdodFBpbm5lZDtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfRklSU1RfUklHSFRfUElOTkVEX0NIQU5HRUQsIHNvdXJjZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldExhc3RMZWZ0UGlubmVkID0gZnVuY3Rpb24gKGxhc3RMZWZ0UGlubmVkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKHRoaXMubGFzdExlZnRQaW5uZWQgIT09IGxhc3RMZWZ0UGlubmVkKSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RMZWZ0UGlubmVkID0gbGFzdExlZnRQaW5uZWQ7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQ29sdW1uRXZlbnQoQ29sdW1uLkVWRU5UX0xBU1RfTEVGVF9QSU5ORURfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNGaXJzdFJpZ2h0UGlubmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5maXJzdFJpZ2h0UGlubmVkO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0xhc3RMZWZ0UGlubmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0TGVmdFBpbm5lZDtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNQaW5uZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbm5lZCA9PT0gQ29uc3RhbnRzLlBJTk5FRF9MRUZUIHx8IHRoaXMucGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX1JJR0hUO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1Bpbm5lZExlZnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbm5lZCA9PT0gQ29uc3RhbnRzLlBJTk5FRF9MRUZUO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1Bpbm5lZFJpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfUklHSFQ7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldFBpbm5lZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRWaXNpYmxlID0gZnVuY3Rpb24gKHZpc2libGUsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIgbmV3VmFsdWUgPSB2aXNpYmxlID09PSB0cnVlO1xuICAgICAgICBpZiAodGhpcy52aXNpYmxlICE9PSBuZXdWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy52aXNpYmxlID0gbmV3VmFsdWU7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQ29sdW1uRXZlbnQoQ29sdW1uLkVWRU5UX1ZJU0lCTEVfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNWaXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52aXNpYmxlO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIGNvbHVtbiBkZWZpbml0aW9uIGZvciB0aGlzIGNvbHVtbi5cbiAgICAgKiBUaGUgY29sdW1uIGRlZmluaXRpb24gd2lsbCBiZSB0aGUgcmVzdWx0IG9mIG1lcmdpbmcgdGhlIGFwcGxpY2F0aW9uIHByb3ZpZGVkIGNvbHVtbiBkZWZpbml0aW9uIHdpdGggYW55IHByb3ZpZGVkIGRlZmF1bHRzXG4gICAgICogKGUuZy4gYGRlZmF1bHRDb2xEZWZgIGdyaWQgb3B0aW9uLCBvciBjb2x1bW4gdHlwZXMuXG4gICAgICpcbiAgICAgKiBFcXVpdmFsZW50OiBgZ2V0RGVmaW5pdGlvbmAgKi9cbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldENvbERlZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sRGVmO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRDb2x1bW5Hcm91cFNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbERlZi5jb2x1bW5Hcm91cFNob3c7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB1bmlxdWUgSUQgZm9yIHRoZSBjb2x1bW4uXG4gICAgICpcbiAgICAgKiBFcXVpdmFsZW50OiBgZ2V0SWRgLCBgZ2V0VW5pcXVlSWRgICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRDb2xJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sSWQ7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB1bmlxdWUgSUQgZm9yIHRoZSBjb2x1bW4uXG4gICAgICpcbiAgICAgKiBFcXVpdmFsZW50OiBgZ2V0Q29sSWRgLCBgZ2V0VW5pcXVlSWRgICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sSWQoKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHVuaXF1ZSBJRCBmb3IgdGhlIGNvbHVtbi5cbiAgICAgKlxuICAgICAqIEVxdWl2YWxlbnQ6IGBnZXRDb2xJZGAsIGBnZXRJZGAgKi9cbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldFVuaXF1ZUlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRJZCgpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXREZWZpbml0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xEZWY7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyB0aGUgY3VycmVudCB3aWR0aCBvZiB0aGUgY29sdW1uLiBJZiB0aGUgY29sdW1uIGlzIHJlc2l6ZWQsIHRoZSBhY3R1YWwgd2lkdGggaXMgdGhlIG5ldyBzaXplLiAqL1xuICAgIENvbHVtbi5wcm90b3R5cGUuZ2V0QWN0dWFsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFjdHVhbFdpZHRoO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRBdXRvSGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRvSGVhZGVySGVpZ2h0O1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdHJ1ZSBpZiB0aGUgaGVhZGVyIGhlaWdodCBoYXMgY2hhbmdlZCAqL1xuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0QXV0b0hlYWRlckhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgdmFyIGNoYW5nZWQgPSBoZWlnaHQgIT09IHRoaXMuYXV0b0hlYWRlckhlaWdodDtcbiAgICAgICAgdGhpcy5hdXRvSGVhZGVySGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICByZXR1cm4gY2hhbmdlZDtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuY3JlYXRlQmFzZUNvbERlZlBhcmFtcyA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBub2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgZGF0YTogcm93Tm9kZS5kYXRhLFxuICAgICAgICAgICAgY29sRGVmOiB0aGlzLmNvbERlZixcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcyxcbiAgICAgICAgICAgIGFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBwYXJhbXM7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldENvbFNwYW4gPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICBpZiAobWlzc2luZyh0aGlzLmNvbERlZi5jb2xTcGFuKSkge1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtcyA9IHRoaXMuY3JlYXRlQmFzZUNvbERlZlBhcmFtcyhyb3dOb2RlKTtcbiAgICAgICAgdmFyIGNvbFNwYW4gPSB0aGlzLmNvbERlZi5jb2xTcGFuKHBhcmFtcyk7XG4gICAgICAgIC8vIGNvbFNwYW4gbXVzdCBiZSBudW1iZXIgZXF1YWwgdG8gb3IgZ3JlYXRlciB0aGFuIDFcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KGNvbFNwYW4sIDEpO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRSb3dTcGFuID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy5jb2xEZWYucm93U3BhbikpIHtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJhbXMgPSB0aGlzLmNyZWF0ZUJhc2VDb2xEZWZQYXJhbXMocm93Tm9kZSk7XG4gICAgICAgIHZhciByb3dTcGFuID0gdGhpcy5jb2xEZWYucm93U3BhbihwYXJhbXMpO1xuICAgICAgICAvLyByb3dTcGFuIG11c3QgYmUgbnVtYmVyIGVxdWFsIHRvIG9yIGdyZWF0ZXIgdGhhbiAxXG4gICAgICAgIHJldHVybiBNYXRoLm1heChyb3dTcGFuLCAxKTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0QWN0dWFsV2lkdGggPSBmdW5jdGlvbiAoYWN0dWFsV2lkdGgsIHNvdXJjZSwgc2lsZW50KSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmIChzaWxlbnQgPT09IHZvaWQgMCkgeyBzaWxlbnQgPSBmYWxzZTsgfVxuICAgICAgICBpZiAodGhpcy5taW5XaWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICBhY3R1YWxXaWR0aCA9IE1hdGgubWF4KGFjdHVhbFdpZHRoLCB0aGlzLm1pbldpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5tYXhXaWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICBhY3R1YWxXaWR0aCA9IE1hdGgubWluKGFjdHVhbFdpZHRoLCB0aGlzLm1heFdpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5hY3R1YWxXaWR0aCAhPT0gYWN0dWFsV2lkdGgpIHtcbiAgICAgICAgICAgIC8vIGRpc2FibGUgZmxleCBmb3IgdGhpcyBjb2x1bW4gaWYgaXQgd2FzIG1hbnVhbGx5IHJlc2l6ZWQuXG4gICAgICAgICAgICB0aGlzLmFjdHVhbFdpZHRoID0gYWN0dWFsV2lkdGg7XG4gICAgICAgICAgICBpZiAodGhpcy5mbGV4ICYmIHNvdXJjZSAhPT0gJ2ZsZXgnICYmIHNvdXJjZSAhPT0gJ2dyaWRJbml0aWFsaXppbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5mbGV4ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghc2lsZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJlQ29sdW1uV2lkdGhDaGFuZ2VkRXZlbnQoc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5maXJlQ29sdW1uV2lkdGhDaGFuZ2VkRXZlbnQgPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfV0lEVEhfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzR3JlYXRlclRoYW5NYXggPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICAgICAgaWYgKHRoaXMubWF4V2lkdGggIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHdpZHRoID4gdGhpcy5tYXhXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmdldE1pbldpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5taW5XaWR0aDtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuZ2V0TWF4V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1heFdpZHRoO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRGbGV4ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mbGV4IHx8IDA7XG4gICAgfTtcbiAgICAvLyB0aGlzIG1ldGhvZCBzaG91bGQgb25seSBiZSB1c2VkIGJ5IHRoZSBjb2x1bW5Nb2RlbCB0b1xuICAgIC8vIGNoYW5nZSBmbGV4IHdoZW4gcmVxdWlyZWQgYnkgdGhlIHNldENvbHVtblN0YXRlIG1ldGhvZC5cbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldEZsZXggPSBmdW5jdGlvbiAoZmxleCkge1xuICAgICAgICBpZiAodGhpcy5mbGV4ICE9PSBmbGV4KSB7XG4gICAgICAgICAgICB0aGlzLmZsZXggPSBmbGV4O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldE1pbmltdW0gPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmIChleGlzdHModGhpcy5taW5XaWR0aCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0QWN0dWFsV2lkdGgodGhpcy5taW5XaWR0aCwgc291cmNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5zZXRSb3dHcm91cEFjdGl2ZSA9IGZ1bmN0aW9uIChyb3dHcm91cCwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmICh0aGlzLnJvd0dyb3VwQWN0aXZlICE9PSByb3dHcm91cCkge1xuICAgICAgICAgICAgdGhpcy5yb3dHcm91cEFjdGl2ZSA9IHJvd0dyb3VwO1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUNvbHVtbkV2ZW50KENvbHVtbi5FVkVOVF9ST1dfR1JPVVBfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiByb3cgZ3JvdXAgaXMgY3VycmVudGx5IGFjdGl2ZSBmb3IgdGhpcyBjb2x1bW4uICovXG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc1Jvd0dyb3VwQWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dHcm91cEFjdGl2ZTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuc2V0UGl2b3RBY3RpdmUgPSBmdW5jdGlvbiAocGl2b3QsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICBpZiAodGhpcy5waXZvdEFjdGl2ZSAhPT0gcGl2b3QpIHtcbiAgICAgICAgICAgIHRoaXMucGl2b3RBY3RpdmUgPSBwaXZvdDtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVDb2x1bW5FdmVudChDb2x1bW4uRVZFTlRfUElWT1RfQ0hBTkdFRCwgc291cmNlKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiBwaXZvdCBpcyBjdXJyZW50bHkgYWN0aXZlIGZvciB0aGlzIGNvbHVtbi4gKi9cbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzUGl2b3RBY3RpdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpdm90QWN0aXZlO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0FueUZ1bmN0aW9uQWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1Bpdm90QWN0aXZlKCkgfHwgdGhpcy5pc1Jvd0dyb3VwQWN0aXZlKCkgfHwgdGhpcy5pc1ZhbHVlQWN0aXZlKCk7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzQW55RnVuY3Rpb25BbGxvd2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc0FsbG93UGl2b3QoKSB8fCB0aGlzLmlzQWxsb3dSb3dHcm91cCgpIHx8IHRoaXMuaXNBbGxvd1ZhbHVlKCk7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLnNldFZhbHVlQWN0aXZlID0gZnVuY3Rpb24gKHZhbHVlLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKHRoaXMuYWdncmVnYXRpb25BY3RpdmUgIT09IHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmFnZ3JlZ2F0aW9uQWN0aXZlID0gdmFsdWU7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQ29sdW1uRXZlbnQoQ29sdW1uLkVWRU5UX1ZBTFVFX0NIQU5HRUQsIHNvdXJjZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBgdHJ1ZWAgaWYgdmFsdWUgKGFnZ3JlZ2F0aW9uKSBpcyBjdXJyZW50bHkgYWN0aXZlIGZvciB0aGlzIGNvbHVtbi4gKi9cbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzVmFsdWVBY3RpdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFnZ3JlZ2F0aW9uQWN0aXZlO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0FsbG93UGl2b3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbERlZi5lbmFibGVQaXZvdCA9PT0gdHJ1ZTtcbiAgICB9O1xuICAgIENvbHVtbi5wcm90b3R5cGUuaXNBbGxvd1ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xEZWYuZW5hYmxlVmFsdWUgPT09IHRydWU7XG4gICAgfTtcbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzQWxsb3dSb3dHcm91cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sRGVmLmVuYWJsZVJvd0dyb3VwID09PSB0cnVlO1xuICAgIH07XG4gICAgQ29sdW1uLnByb3RvdHlwZS5nZXRNZW51VGFicyA9IGZ1bmN0aW9uIChkZWZhdWx0VmFsdWVzKSB7XG4gICAgICAgIHZhciBtZW51VGFicyA9IHRoaXMuZ2V0Q29sRGVmKCkubWVudVRhYnM7XG4gICAgICAgIGlmIChtZW51VGFicyA9PSBudWxsKSB7XG4gICAgICAgICAgICBtZW51VGFicyA9IGRlZmF1bHRWYWx1ZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1lbnVUYWJzO1xuICAgIH07XG4gICAgLy8gdGhpcyB1c2VkIHRvIGJlIG5lZWRlZCwgYXMgcHJldmlvdXMgdmVyc2lvbiBvZiBhZy1ncmlkIGhhZCBsb2NrUG9zaXRpb24gYXMgY29sdW1uIHN0YXRlLFxuICAgIC8vIHNvIGNvdWxkbid0IGRlcGVuZCBvbiBjb2xEZWYgdmVyc2lvbi5cbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzTG9ja1Bvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyMSwgY29sLmlzTG9ja1Bvc2l0aW9uKCkgc2hvdWxkIG5vdCBiZSB1c2VkLCBwbGVhc2UgdXNlIGNvbC5nZXRDb2xEZWYoKS5sb2NrUG9zaXRpb24gaW5zdGVhZC4nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sRGVmID8gISF0aGlzLmNvbERlZi5sb2NrUG9zaXRpb24gOiBmYWxzZTtcbiAgICB9O1xuICAgIC8vIHRoaXMgdXNlZCB0byBiZSBuZWVkZWQsIGFzIHByZXZpb3VzIHZlcnNpb24gb2YgYWctZ3JpZCBoYWQgbG9ja1Zpc2libGUgYXMgY29sdW1uIHN0YXRlLFxuICAgIC8vIHNvIGNvdWxkbid0IGRlcGVuZCBvbiBjb2xEZWYgdmVyc2lvbi5cbiAgICBDb2x1bW4ucHJvdG90eXBlLmlzTG9ja1Zpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjIxLCBjb2wuaXNMb2NrVmlzaWJsZSgpIHNob3VsZCBub3QgYmUgdXNlZCwgcGxlYXNlIHVzZSBjb2wuZ2V0Q29sRGVmKCkubG9ja1Zpc2libGUgaW5zdGVhZC4nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sRGVmID8gISF0aGlzLmNvbERlZi5sb2NrVmlzaWJsZSA6IGZhbHNlO1xuICAgIH07XG4gICAgLy8gdGhpcyB1c2VkIHRvIGJlIG5lZWRlZCwgYXMgcHJldmlvdXMgdmVyc2lvbiBvZiBhZy1ncmlkIGhhZCBsb2NrUGlubmVkIGFzIGNvbHVtbiBzdGF0ZSxcbiAgICAvLyBzbyBjb3VsZG4ndCBkZXBlbmQgb24gY29sRGVmIHZlcnNpb24uXG4gICAgQ29sdW1uLnByb3RvdHlwZS5pc0xvY2tQaW5uZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjIxLCBjb2wuaXNMb2NrUGlubmVkKCkgc2hvdWxkIG5vdCBiZSB1c2VkLCBwbGVhc2UgdXNlIGNvbC5nZXRDb2xEZWYoKS5sb2NrUGlubmVkIGluc3RlYWQuJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbERlZiA/ICEhdGhpcy5jb2xEZWYubG9ja1Bpbm5lZCA6IGZhbHNlO1xuICAgIH07XG4gICAgLy8gKyByZW5kZXJlZEhlYWRlckNlbGwgLSBmb3IgbWFraW5nIGhlYWRlciBjZWxsIHRyYW5zcGFyZW50IHdoZW4gbW92aW5nXG4gICAgQ29sdW1uLkVWRU5UX01PVklOR19DSEFOR0VEID0gJ21vdmluZ0NoYW5nZWQnO1xuICAgIC8vICsgcmVuZGVyZWRDZWxsIC0gY2hhbmdpbmcgbGVmdCBwb3NpdGlvblxuICAgIENvbHVtbi5FVkVOVF9MRUZUX0NIQU5HRUQgPSAnbGVmdENoYW5nZWQnO1xuICAgIC8vICsgcmVuZGVyZWRDZWxsIC0gY2hhbmdpbmcgd2lkdGhcbiAgICBDb2x1bW4uRVZFTlRfV0lEVEhfQ0hBTkdFRCA9ICd3aWR0aENoYW5nZWQnO1xuICAgIC8vICsgcmVuZGVyZWRDZWxsIC0gZm9yIGNoYW5naW5nIHBpbm5lZCBjbGFzc2VzXG4gICAgQ29sdW1uLkVWRU5UX0xBU1RfTEVGVF9QSU5ORURfQ0hBTkdFRCA9ICdsYXN0TGVmdFBpbm5lZENoYW5nZWQnO1xuICAgIENvbHVtbi5FVkVOVF9GSVJTVF9SSUdIVF9QSU5ORURfQ0hBTkdFRCA9ICdmaXJzdFJpZ2h0UGlubmVkQ2hhbmdlZCc7XG4gICAgLy8gKyByZW5kZXJlZENvbHVtbiAtIGZvciBjaGFuZ2luZyB2aXNpYmlsaXR5IGljb25cbiAgICBDb2x1bW4uRVZFTlRfVklTSUJMRV9DSEFOR0VEID0gJ3Zpc2libGVDaGFuZ2VkJztcbiAgICAvLyArIGV2ZXJ5IHRpbWUgdGhlIGZpbHRlciBjaGFuZ2VzLCB1c2VkIGluIHRoZSBmbG9hdGluZyBmaWx0ZXJzXG4gICAgQ29sdW1uLkVWRU5UX0ZJTFRFUl9DSEFOR0VEID0gJ2ZpbHRlckNoYW5nZWQnO1xuICAgIC8vICsgcmVuZGVyZWRIZWFkZXJDZWxsIC0gbWFya3MgdGhlIGhlYWRlciB3aXRoIGZpbHRlciBpY29uXG4gICAgQ29sdW1uLkVWRU5UX0ZJTFRFUl9BQ1RJVkVfQ0hBTkdFRCA9ICdmaWx0ZXJBY3RpdmVDaGFuZ2VkJztcbiAgICAvLyArIHJlbmRlcmVkSGVhZGVyQ2VsbCAtIG1hcmtzIHRoZSBoZWFkZXIgd2l0aCBzb3J0IGljb25cbiAgICBDb2x1bW4uRVZFTlRfU09SVF9DSEFOR0VEID0gJ3NvcnRDaGFuZ2VkJztcbiAgICAvLyArIHJlbmRlcmVkSGVhZGVyQ2VsbCAtIG1hcmtzIHRoZSBoZWFkZXIgd2l0aCBzb3J0IGljb25cbiAgICBDb2x1bW4uRVZFTlRfQ09MX0RFRl9DSEFOR0VEID0gJ2NvbERlZkNoYW5nZWQnO1xuICAgIENvbHVtbi5FVkVOVF9NRU5VX1ZJU0lCTEVfQ0hBTkdFRCA9ICdtZW51VmlzaWJsZUNoYW5nZWQnO1xuICAgIC8vICsgdG9vbHBhbmVsLCBmb3IgZ3VpIHVwZGF0ZXNcbiAgICBDb2x1bW4uRVZFTlRfUk9XX0dST1VQX0NIQU5HRUQgPSAnY29sdW1uUm93R3JvdXBDaGFuZ2VkJztcbiAgICAvLyArIHRvb2xwYW5lbCwgZm9yIGd1aSB1cGRhdGVzXG4gICAgQ29sdW1uLkVWRU5UX1BJVk9UX0NIQU5HRUQgPSAnY29sdW1uUGl2b3RDaGFuZ2VkJztcbiAgICAvLyArIHRvb2xwYW5lbCwgZm9yIGd1aSB1cGRhdGVzXG4gICAgQ29sdW1uLkVWRU5UX1ZBTFVFX0NIQU5HRUQgPSAnY29sdW1uVmFsdWVDaGFuZ2VkJztcbiAgICBfX2RlY29yYXRlJDJ6KFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkT3B0aW9uc1dyYXBwZXInKVxuICAgIF0sIENvbHVtbi5wcm90b3R5cGUsIFwiZ3JpZE9wdGlvbnNXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyeihbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uVXRpbHMnKVxuICAgIF0sIENvbHVtbi5wcm90b3R5cGUsIFwiY29sdW1uVXRpbHNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ6KFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIENvbHVtbi5wcm90b3R5cGUsIFwiaW5pdGlhbGlzZVwiLCBudWxsKTtcbiAgICByZXR1cm4gQ29sdW1uO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuZnVuY3Rpb24gZmlyc3RFeGlzdGluZ1ZhbHVlKCkge1xuICAgIHZhciB2YWx1ZXMgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YWx1ZXNbX2ldID0gYXJndW1lbnRzW19pXTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgICBpZiAoZXhpc3RzKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gZXhpc3RzQW5kTm90RW1wdHkodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCAmJiB2YWx1ZS5sZW5ndGggPiAwO1xufVxuZnVuY3Rpb24gbGFzdChhcnIpIHtcbiAgICBpZiAoIWFyciB8fCAhYXJyLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHJldHVybiBhcnJbYXJyLmxlbmd0aCAtIDFdO1xufVxuZnVuY3Rpb24gYXJlRXF1YWwoYSwgYiwgY29tcGFyYXRvcikge1xuICAgIGlmIChhID09IG51bGwgJiYgYiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gYSAhPSBudWxsICYmXG4gICAgICAgIGIgIT0gbnVsbCAmJlxuICAgICAgICBhLmxlbmd0aCA9PT0gYi5sZW5ndGggJiZcbiAgICAgICAgYS5ldmVyeShmdW5jdGlvbiAodmFsdWUsIGluZGV4KSB7IHJldHVybiBjb21wYXJhdG9yID8gY29tcGFyYXRvcih2YWx1ZSwgYltpbmRleF0pIDogYltpbmRleF0gPT09IHZhbHVlOyB9KTtcbn1cbi8qKiBAZGVwcmVjYXRlZCAqL1xuZnVuY3Rpb24gY29tcGFyZUFycmF5cyhhcnJheTEsIGFycmF5Mikge1xuICAgIHJldHVybiBhcmVFcXVhbChhcnJheTEsIGFycmF5Mik7XG59XG4vKiogQGRlcHJlY2F0ZWQgKi9cbmZ1bmN0aW9uIHNoYWxsb3dDb21wYXJlKGFycjEsIGFycjIpIHtcbiAgICByZXR1cm4gYXJlRXF1YWwoYXJyMSwgYXJyMik7XG59XG5mdW5jdGlvbiBzb3J0TnVtZXJpY2FsbHkoYXJyYXkpIHtcbiAgICByZXR1cm4gYXJyYXkuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYSAtIGI7IH0pO1xufVxuZnVuY3Rpb24gcmVtb3ZlUmVwZWF0c0Zyb21BcnJheShhcnJheSwgb2JqZWN0KSB7XG4gICAgaWYgKCFhcnJheSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAodmFyIGluZGV4ID0gYXJyYXkubGVuZ3RoIC0gMjsgaW5kZXggPj0gMDsgaW5kZXgtLSkge1xuICAgICAgICB2YXIgdGhpc09uZU1hdGNoZXMgPSBhcnJheVtpbmRleF0gPT09IG9iamVjdDtcbiAgICAgICAgdmFyIG5leHRPbmVNYXRjaGVzID0gYXJyYXlbaW5kZXggKyAxXSA9PT0gb2JqZWN0O1xuICAgICAgICBpZiAodGhpc09uZU1hdGNoZXMgJiYgbmV4dE9uZU1hdGNoZXMpIHtcbiAgICAgICAgICAgIGFycmF5LnNwbGljZShpbmRleCArIDEsIDEpO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gcmVtb3ZlRnJvbUFycmF5KGFycmF5LCBvYmplY3QpIHtcbiAgICB2YXIgaW5kZXggPSBhcnJheS5pbmRleE9mKG9iamVjdCk7XG4gICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgYXJyYXkuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG59XG5mdW5jdGlvbiByZW1vdmVBbGxGcm9tQXJyYXkoYXJyYXksIHRvUmVtb3ZlKSB7XG4gICAgdG9SZW1vdmUuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gcmVtb3ZlRnJvbUFycmF5KGFycmF5LCBpdGVtKTsgfSk7XG59XG5mdW5jdGlvbiBpbnNlcnRJbnRvQXJyYXkoYXJyYXksIG9iamVjdCwgdG9JbmRleCkge1xuICAgIGFycmF5LnNwbGljZSh0b0luZGV4LCAwLCBvYmplY3QpO1xufVxuZnVuY3Rpb24gaW5zZXJ0QXJyYXlJbnRvQXJyYXkoZGVzdCwgc3JjLCB0b0luZGV4KSB7XG4gICAgaWYgKGRlc3QgPT0gbnVsbCB8fCBzcmMgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIHB1dCBpdGVtcyBpbiBiYWNrd2FyZHMsIG90aGVyd2lzZSBpbnNlcnRlZCBpdGVtcyBlbmQgdXAgaW4gcmV2ZXJzZSBvcmRlclxuICAgIGZvciAodmFyIGkgPSBzcmMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGl0ZW0gPSBzcmNbaV07XG4gICAgICAgIGluc2VydEludG9BcnJheShkZXN0LCBpdGVtLCB0b0luZGV4KTtcbiAgICB9XG59XG5mdW5jdGlvbiBtb3ZlSW5BcnJheShhcnJheSwgb2JqZWN0c1RvTW92ZSwgdG9JbmRleCkge1xuICAgIC8vIGZpcnN0IHRha2Ugb3V0IGl0ZW1zIGZyb20gdGhlIGFycmF5XG4gICAgcmVtb3ZlQWxsRnJvbUFycmF5KGFycmF5LCBvYmplY3RzVG9Nb3ZlKTtcbiAgICAvLyBub3cgYWRkIHRoZSBvYmplY3RzLCBpbiBzYW1lIG9yZGVyIGFzIHByb3ZpZGVkIHRvIHVzLCB0aGF0IG1lYW5zIHdlIHN0YXJ0IGF0IHRoZSBlbmRcbiAgICAvLyBhcyB0aGUgb2JqZWN0cyB3aWxsIGJlIHB1c2hlZCB0byB0aGUgcmlnaHQgYXMgdGhleSBhcmUgaW5zZXJ0ZWRcbiAgICBvYmplY3RzVG9Nb3ZlLnNsaWNlKCkucmV2ZXJzZSgpLmZvckVhY2goZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gaW5zZXJ0SW50b0FycmF5KGFycmF5LCBvYmosIHRvSW5kZXgpOyB9KTtcbn1cbmZ1bmN0aW9uIGluY2x1ZGVzKGFycmF5LCB2YWx1ZSkge1xuICAgIHJldHVybiBhcnJheS5pbmRleE9mKHZhbHVlKSA+IC0xO1xufVxuZnVuY3Rpb24gZmxhdHRlbihhcnJheU9mQXJyYXlzKSB7XG4gICAgcmV0dXJuIFtdLmNvbmNhdC5hcHBseShbXSwgYXJyYXlPZkFycmF5cyk7XG59XG5mdW5jdGlvbiBwdXNoQWxsKHRhcmdldCwgc291cmNlKSB7XG4gICAgaWYgKHNvdXJjZSA9PSBudWxsIHx8IHRhcmdldCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc291cmNlLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlKSB7IHJldHVybiB0YXJnZXQucHVzaCh2YWx1ZSk7IH0pO1xufVxuZnVuY3Rpb24gdG9TdHJpbmdzKGFycmF5KSB7XG4gICAgcmV0dXJuIGFycmF5Lm1hcCh0b1N0cmluZ09yTnVsbCk7XG59XG5mdW5jdGlvbiBmb3JFYWNoUmV2ZXJzZShsaXN0LCBhY3Rpb24pIHtcbiAgICBpZiAobGlzdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYWN0aW9uKGxpc3RbaV0sIGkpO1xuICAgIH1cbn1cblxudmFyIEFycmF5VXRpbHMgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIGZpcnN0RXhpc3RpbmdWYWx1ZTogZmlyc3RFeGlzdGluZ1ZhbHVlLFxuICAgIGV4aXN0c0FuZE5vdEVtcHR5OiBleGlzdHNBbmROb3RFbXB0eSxcbiAgICBsYXN0OiBsYXN0LFxuICAgIGFyZUVxdWFsOiBhcmVFcXVhbCxcbiAgICBjb21wYXJlQXJyYXlzOiBjb21wYXJlQXJyYXlzLFxuICAgIHNoYWxsb3dDb21wYXJlOiBzaGFsbG93Q29tcGFyZSxcbiAgICBzb3J0TnVtZXJpY2FsbHk6IHNvcnROdW1lcmljYWxseSxcbiAgICByZW1vdmVSZXBlYXRzRnJvbUFycmF5OiByZW1vdmVSZXBlYXRzRnJvbUFycmF5LFxuICAgIHJlbW92ZUZyb21BcnJheTogcmVtb3ZlRnJvbUFycmF5LFxuICAgIHJlbW92ZUFsbEZyb21BcnJheTogcmVtb3ZlQWxsRnJvbUFycmF5LFxuICAgIGluc2VydEludG9BcnJheTogaW5zZXJ0SW50b0FycmF5LFxuICAgIGluc2VydEFycmF5SW50b0FycmF5OiBpbnNlcnRBcnJheUludG9BcnJheSxcbiAgICBtb3ZlSW5BcnJheTogbW92ZUluQXJyYXksXG4gICAgaW5jbHVkZXM6IGluY2x1ZGVzLFxuICAgIGZsYXR0ZW46IGZsYXR0ZW4sXG4gICAgcHVzaEFsbDogcHVzaEFsbCxcbiAgICB0b1N0cmluZ3M6IHRvU3RyaW5ncyxcbiAgICBmb3JFYWNoUmV2ZXJzZTogZm9yRWFjaFJldmVyc2Vcbn0pO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19kZWNvcmF0ZSQyeSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIENvbHVtbkdyb3VwID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbHVtbkdyb3VwKHByb3ZpZGVkQ29sdW1uR3JvdXAsIGdyb3VwSWQsIGluc3RhbmNlSWQsIHBpbm5lZCkge1xuICAgICAgICAvLyBkZXBlbmRzIG9uIHRoZSBvcGVuL2Nsb3NlZCBzdGF0ZSBvZiB0aGUgZ3JvdXAsIG9ubHkgZGlzcGxheWluZyBjb2x1bW5zIGFyZSBzdG9yZWQgaGVyZVxuICAgICAgICB0aGlzLmRpc3BsYXllZENoaWxkcmVuID0gW107XG4gICAgICAgIHRoaXMubG9jYWxFdmVudFNlcnZpY2UgPSBuZXcgRXZlbnRTZXJ2aWNlKCk7XG4gICAgICAgIHRoaXMuZ3JvdXBJZCA9IGdyb3VwSWQ7XG4gICAgICAgIHRoaXMuaW5zdGFuY2VJZCA9IGluc3RhbmNlSWQ7XG4gICAgICAgIHRoaXMucHJvdmlkZWRDb2x1bW5Hcm91cCA9IHByb3ZpZGVkQ29sdW1uR3JvdXA7XG4gICAgICAgIHRoaXMucGlubmVkID0gcGlubmVkO1xuICAgIH1cbiAgICAvLyB0aGlzIGlzIHN0YXRpYywgYSBpdCBpcyB1c2VkIG91dHNpZGUgb2YgdGhpcyBjbGFzc1xuICAgIENvbHVtbkdyb3VwLmNyZWF0ZVVuaXF1ZUlkID0gZnVuY3Rpb24gKGdyb3VwSWQsIGluc3RhbmNlSWQpIHtcbiAgICAgICAgcmV0dXJuIGdyb3VwSWQgKyAnXycgKyBpbnN0YW5jZUlkO1xuICAgIH07XG4gICAgLy8gYXMgdGhlIHVzZXIgaXMgYWRkaW5nIGFuZCByZW1vdmluZyBjb2x1bW5zLCB0aGUgZ3JvdXBzIGFyZSByZWNhbGN1bGF0ZWQuXG4gICAgLy8gdGhpcyByZXNldCBjbGVhcnMgb3V0IGFsbCBjaGlsZHJlbiwgcmVhZHkgZm9yIGNoaWxkcmVuIHRvIGJlIGFkZGVkIGFnYWluXG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBhcmVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuY2hpbGRyZW4gPSBudWxsO1xuICAgICAgICB0aGlzLmRpc3BsYXllZENoaWxkcmVuID0gbnVsbDtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRQYXJlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudDtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5zZXRQYXJlbnQgPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldFVuaXF1ZUlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gQ29sdW1uR3JvdXAuY3JlYXRlVW5pcXVlSWQodGhpcy5ncm91cElkLCB0aGlzLmluc3RhbmNlSWQpO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzRW1wdHlHcm91cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheWVkQ2hpbGRyZW4ubGVuZ3RoID09PSAwO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzTW92aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYWxsTGVhZkNvbHVtbnMgPSB0aGlzLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoKS5nZXRMZWFmQ29sdW1ucygpO1xuICAgICAgICBpZiAoIWFsbExlYWZDb2x1bW5zIHx8IGFsbExlYWZDb2x1bW5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhbGxMZWFmQ29sdW1ucy5ldmVyeShmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuaXNNb3ZpbmcoKTsgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuY2hlY2tMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBmaXJzdCBnZXQgYWxsIGNoaWxkcmVuIHRvIHNldExlZnQsIGFzIGl0IGltcGFjdHMgb3VyIGRlY2lzaW9uIGJlbG93XG4gICAgICAgIHRoaXMuZGlzcGxheWVkQ2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgY2hpbGQuY2hlY2tMZWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBzZXQgb3VyIGxlZnQgYmFzZWQgb24gZmlyc3QgZGlzcGxheWVkIGNvbHVtblxuICAgICAgICBpZiAodGhpcy5kaXNwbGF5ZWRDaGlsZHJlbi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKSkge1xuICAgICAgICAgICAgICAgIHZhciBsYXN0Q2hpbGQgPSBsYXN0KHRoaXMuZGlzcGxheWVkQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBsYXN0Q2hpbGRMZWZ0ID0gbGFzdENoaWxkLmdldExlZnQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldExlZnQobGFzdENoaWxkTGVmdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgZmlyc3RDaGlsZExlZnQgPSB0aGlzLmRpc3BsYXllZENoaWxkcmVuWzBdLmdldExlZnQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldExlZnQoZmlyc3RDaGlsZExlZnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gdGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCBhcyBpZiB3ZSBoYXZlIG5vIGRpc3BsYXllZCBjb2x1bW5zLCB0aGVuXG4gICAgICAgICAgICAvLyB0aGlzIGdyb3VwcyBzaG91bGQgbm90IGV2ZW4gZXhpc3QuXG4gICAgICAgICAgICB0aGlzLnNldExlZnQobnVsbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sZWZ0O1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldE9sZExlZnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9sZExlZnQ7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuc2V0TGVmdCA9IGZ1bmN0aW9uIChsZWZ0KSB7XG4gICAgICAgIHRoaXMub2xkTGVmdCA9IGxlZnQ7XG4gICAgICAgIGlmICh0aGlzLmxlZnQgIT09IGxlZnQpIHtcbiAgICAgICAgICAgIHRoaXMubGVmdCA9IGxlZnQ7XG4gICAgICAgICAgICB0aGlzLmxvY2FsRXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVBZ0V2ZW50KENvbHVtbkdyb3VwLkVWRU5UX0xFRlRfQ0hBTkdFRCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0UGlubmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waW5uZWQ7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuY3JlYXRlQWdFdmVudCA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIHJldHVybiB7IHR5cGU6IHR5cGUgfTtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5sb2NhbEV2ZW50U2VydmljZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmxvY2FsRXZlbnRTZXJ2aWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0R3JvdXBJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JvdXBJZDtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRJbnN0YW5jZUlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZUlkO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzQ2hpbGRJblRoaXNHcm91cERlZXBTZWFyY2ggPSBmdW5jdGlvbiAod2FudGVkQ2hpbGQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGZvdW5kQ2hpbGQpIHtcbiAgICAgICAgICAgIGlmICh3YW50ZWRDaGlsZCA9PT0gZm91bmRDaGlsZCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZm91bmRDaGlsZCBpbnN0YW5jZW9mIENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZvdW5kQ2hpbGQuaXNDaGlsZEluVGhpc0dyb3VwRGVlcFNlYXJjaCh3YW50ZWRDaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldEFjdHVhbFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZ3JvdXBBY3R1YWxXaWR0aCA9IDA7XG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXllZENoaWxkcmVuKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBBY3R1YWxXaWR0aCArPSBjaGlsZC5nZXRBY3R1YWxXaWR0aCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdyb3VwQWN0dWFsV2lkdGg7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuaXNSZXNpemFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5kaXNwbGF5ZWRDaGlsZHJlbikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGF0IGxlYXN0IG9uZSBjaGlsZCBpcyByZXNpemFibGUsIHRoZW4gdGhlIGdyb3VwIGlzIHJlc2l6YWJsZVxuICAgICAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZGlzcGxheWVkQ2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZC5pc1Jlc2l6YWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0TWluV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSAwO1xuICAgICAgICB0aGlzLmRpc3BsYXllZENoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGdyb3VwQ2hpbGQpIHtcbiAgICAgICAgICAgIHJlc3VsdCArPSBncm91cENoaWxkLmdldE1pbldpZHRoKCkgfHwgMDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuYWRkQ2hpbGQgPSBmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRDaGlsZHJlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheWVkQ2hpbGRyZW47XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0TGVhZkNvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdGhpcy5hZGRMZWFmQ29sdW1ucyhyZXN1bHQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldERpc3BsYXllZExlYWZDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHRoaXMuYWRkRGlzcGxheWVkTGVhZkNvbHVtbnMocmVzdWx0KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIC8vIHdoeSB0d28gbWV0aG9kcyBoZXJlIGRvaW5nIHRoZSBzYW1lIHRoaW5nP1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXREZWZpbml0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wcm92aWRlZENvbHVtbkdyb3VwLmdldENvbEdyb3VwRGVmKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0Q29sR3JvdXBEZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVkQ29sdW1uR3JvdXAuZ2V0Q29sR3JvdXBEZWYoKTtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5pc1BhZGRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVkQ29sdW1uR3JvdXAuaXNQYWRkaW5nKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuaXNFeHBhbmRhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wcm92aWRlZENvbHVtbkdyb3VwLmlzRXhwYW5kYWJsZSgpO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzRXhwYW5kZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVkQ29sdW1uR3JvdXAuaXNFeHBhbmRlZCgpO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLnNldEV4cGFuZGVkID0gZnVuY3Rpb24gKGV4cGFuZGVkKSB7XG4gICAgICAgIHRoaXMucHJvdmlkZWRDb2x1bW5Hcm91cC5zZXRFeHBhbmRlZChleHBhbmRlZCk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuYWRkRGlzcGxheWVkTGVhZkNvbHVtbnMgPSBmdW5jdGlvbiAobGVhZkNvbHVtbnMpIHtcbiAgICAgICAgdGhpcy5kaXNwbGF5ZWRDaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgICAgICAgaWYgKGNoaWxkIGluc3RhbmNlb2YgQ29sdW1uKSB7XG4gICAgICAgICAgICAgICAgbGVhZkNvbHVtbnMucHVzaChjaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjaGlsZCBpbnN0YW5jZW9mIENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgY2hpbGQuYWRkRGlzcGxheWVkTGVhZkNvbHVtbnMobGVhZkNvbHVtbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5hZGRMZWFmQ29sdW1ucyA9IGZ1bmN0aW9uIChsZWFmQ29sdW1ucykge1xuICAgICAgICB0aGlzLmNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBsZWFmQ29sdW1ucy5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoaWxkIGluc3RhbmNlb2YgQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICBjaGlsZC5hZGRMZWFmQ29sdW1ucyhsZWFmQ29sdW1ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldENoaWxkcmVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jaGlsZHJlbjtcbiAgICB9O1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRDb2x1bW5Hcm91cFNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3ZpZGVkQ29sdW1uR3JvdXAuZ2V0Q29sdW1uR3JvdXBTaG93KCk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvdmlkZWRDb2x1bW5Hcm91cDtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBnZXRPcmlnaW5hbENvbHVtbkdyb3VwIGlzIGRlcHJlY2F0ZWQsIHVzZSBnZXRPcmlnaW5hbENvbHVtbkdyb3VwLiAqL1xuICAgIENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRPcmlnaW5hbENvbHVtbkdyb3VwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGNvbHVtbkdyb3VwLmdldE9yaWdpbmFsQ29sdW1uR3JvdXAoKSBpcyBkZXByZWNhdGVkIGR1ZSB0byBhIG1ldGhvZCByZW5hbWUsIHVzZSBjb2x1bW5Hcm91cC5nZXRQcm92aWRlZENvbHVtbkdyb3VwKCkgaW5zdGVhZCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQcm92aWRlZENvbHVtbkdyb3VwKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0UGFkZGluZ0xldmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyZW50ID0gdGhpcy5nZXRQYXJlbnQoKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzUGFkZGluZygpIHx8ICFwYXJlbnQgfHwgIXBhcmVudC5pc1BhZGRpbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDEgKyBwYXJlbnQuZ2V0UGFkZGluZ0xldmVsKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Hcm91cC5wcm90b3R5cGUuY2FsY3VsYXRlRGlzcGxheWVkQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gY2xlYXIgb3V0IGxhc3QgdGltZSB3ZSBjYWxjdWxhdGVkXG4gICAgICAgIHRoaXMuZGlzcGxheWVkQ2hpbGRyZW4gPSBbXTtcbiAgICAgICAgLy8gZmluZCB0aGUgY29sdW1uIGdyb3VwIHRoYXQgaXMgY29udHJvbGxpbmcgZXhwYW5kYWJsZS4gdGhpcyBpcyByZWxldmFudCB3aGVuIHdlIGhhdmUgcGFkZGluZyAoZW1wdHkpXG4gICAgICAgIC8vIGdyb3Vwcywgd2hlcmUgdGhlIGV4cGFuZGFibGUgaXMgYWN0dWFsbHkgdGhlIGZpcnN0IHBhcmVudCB0aGF0IGlzIG5vdCBhIHBhZGRpbmcgZ3JvdXAuXG4gICAgICAgIHZhciBwYXJlbnRXaXRoRXhwYW5zaW9uID0gdGhpcztcbiAgICAgICAgd2hpbGUgKHBhcmVudFdpdGhFeHBhbnNpb24gIT0gbnVsbCAmJiBwYXJlbnRXaXRoRXhwYW5zaW9uLmlzUGFkZGluZygpKSB7XG4gICAgICAgICAgICBwYXJlbnRXaXRoRXhwYW5zaW9uID0gcGFyZW50V2l0aEV4cGFuc2lvbi5nZXRQYXJlbnQoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNFeHBhbmRhYmxlID0gcGFyZW50V2l0aEV4cGFuc2lvbiA/IHBhcmVudFdpdGhFeHBhbnNpb24ucHJvdmlkZWRDb2x1bW5Hcm91cC5pc0V4cGFuZGFibGUoKSA6IGZhbHNlO1xuICAgICAgICAvLyBpdCBub3QgZXhwYW5kYWJsZSwgZXZlcnl0aGluZyBpcyB2aXNpYmxlXG4gICAgICAgIGlmICghaXNFeHBhbmRhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENoaWxkcmVuID0gdGhpcy5jaGlsZHJlbjtcbiAgICAgICAgICAgIHRoaXMubG9jYWxFdmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUFnRXZlbnQoQ29sdW1uR3JvdXAuRVZFTlRfRElTUExBWUVEX0NISUxEUkVOX0NIQU5HRUQpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBBZGQgY29scyBiYXNlZCBvbiBjb2x1bW5Hcm91cFNob3dcbiAgICAgICAgLy8gTm90ZSAtIHRoZSBiZWxvdyBhbHNvIGFkZHMgcGFkZGluZyBncm91cHMsIHRoZXNlIGFyZSBhbHdheXMgYWRkZWQgYmVjYXVzZSB0aGV5IG5ldmVyIGhhdmVcbiAgICAgICAgLy8gY29sRGVmLmNvbHVtbkdyb3VwU2hvdyBzZXQuXG4gICAgICAgIHRoaXMuY2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIC8vIG5ldmVyIGFkZCBlbXB0eSBncm91cHNcbiAgICAgICAgICAgIHZhciBlbXB0eUdyb3VwID0gY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCAmJiAoIWNoaWxkLmRpc3BsYXllZENoaWxkcmVuIHx8ICFjaGlsZC5kaXNwbGF5ZWRDaGlsZHJlbi5sZW5ndGgpO1xuICAgICAgICAgICAgaWYgKGVtcHR5R3JvdXApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaGVhZGVyR3JvdXBTaG93ID0gY2hpbGQuZ2V0Q29sdW1uR3JvdXBTaG93KCk7XG4gICAgICAgICAgICBzd2l0Y2ggKGhlYWRlckdyb3VwU2hvdykge1xuICAgICAgICAgICAgICAgIGNhc2UgQ29sdW1uR3JvdXAuSEVBREVSX0dST1VQX1NIT1dfT1BFTjpcbiAgICAgICAgICAgICAgICAgICAgLy8gd2hlbiBzZXQgdG8gb3Blbiwgb25seSBzaG93IGNvbCBpZiBncm91cCBpcyBvcGVuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnRXaXRoRXhwYW5zaW9uLnByb3ZpZGVkQ29sdW1uR3JvdXAuaXNFeHBhbmRlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5kaXNwbGF5ZWRDaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIENvbHVtbkdyb3VwLkhFQURFUl9HUk9VUF9TSE9XX0NMT1NFRDpcbiAgICAgICAgICAgICAgICAgICAgLy8gd2hlbiBzZXQgdG8gb3Blbiwgb25seSBzaG93IGNvbCBpZiBncm91cCBpcyBvcGVuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFyZW50V2l0aEV4cGFuc2lvbi5wcm92aWRlZENvbHVtbkdyb3VwLmlzRXhwYW5kZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuZGlzcGxheWVkQ2hpbGRyZW4ucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZGlzcGxheWVkQ2hpbGRyZW4ucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5sb2NhbEV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlQWdFdmVudChDb2x1bW5Hcm91cC5FVkVOVF9ESVNQTEFZRURfQ0hJTERSRU5fQ0hBTkdFRCkpO1xuICAgIH07XG4gICAgQ29sdW1uR3JvdXAuSEVBREVSX0dST1VQX1NIT1dfT1BFTiA9ICdvcGVuJztcbiAgICBDb2x1bW5Hcm91cC5IRUFERVJfR1JPVVBfU0hPV19DTE9TRUQgPSAnY2xvc2VkJztcbiAgICBDb2x1bW5Hcm91cC5FVkVOVF9MRUZUX0NIQU5HRUQgPSAnbGVmdENoYW5nZWQnO1xuICAgIENvbHVtbkdyb3VwLkVWRU5UX0RJU1BMQVlFRF9DSElMRFJFTl9DSEFOR0VEID0gJ2Rpc3BsYXllZENoaWxkcmVuQ2hhbmdlZCc7XG4gICAgX19kZWNvcmF0ZSQyeShbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZE9wdGlvbnNXcmFwcGVyJylcbiAgICBdLCBDb2x1bW5Hcm91cC5wcm90b3R5cGUsIFwiZ3JpZE9wdGlvbnNXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIENvbHVtbkdyb3VwO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIFByb3ZpZGVkQ29sdW1uR3JvdXAgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHJvdmlkZWRDb2x1bW5Hcm91cChjb2xHcm91cERlZiwgZ3JvdXBJZCwgcGFkZGluZywgbGV2ZWwpIHtcbiAgICAgICAgdGhpcy5sb2NhbEV2ZW50U2VydmljZSA9IG5ldyBFdmVudFNlcnZpY2UoKTtcbiAgICAgICAgdGhpcy5leHBhbmRhYmxlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY29sR3JvdXBEZWYgPSBjb2xHcm91cERlZjtcbiAgICAgICAgdGhpcy5ncm91cElkID0gZ3JvdXBJZDtcbiAgICAgICAgdGhpcy5leHBhbmRlZCA9ICEhY29sR3JvdXBEZWYgJiYgISFjb2xHcm91cERlZi5vcGVuQnlEZWZhdWx0O1xuICAgICAgICB0aGlzLnBhZGRpbmcgPSBwYWRkaW5nO1xuICAgICAgICB0aGlzLmxldmVsID0gbGV2ZWw7XG4gICAgfVxuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLnNldE9yaWdpbmFsUGFyZW50ID0gZnVuY3Rpb24gKG9yaWdpbmFsUGFyZW50KSB7XG4gICAgICAgIHRoaXMub3JpZ2luYWxQYXJlbnQgPSBvcmlnaW5hbFBhcmVudDtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldE9yaWdpbmFsUGFyZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcmlnaW5hbFBhcmVudDtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldExldmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sZXZlbDtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzVmlzaWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmV0dXJuIHRydWUgaWYgYXQgbGVhc3Qgb25lIGNoaWxkIGlzIHZpc2libGVcbiAgICAgICAgaWYgKHRoaXMuY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoaWxkcmVuLnNvbWUoZnVuY3Rpb24gKGNoaWxkKSB7IHJldHVybiBjaGlsZC5pc1Zpc2libGUoKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgUHJvdmlkZWRDb2x1bW5Hcm91cC5wcm90b3R5cGUuaXNQYWRkaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wYWRkaW5nO1xuICAgIH07XG4gICAgUHJvdmlkZWRDb2x1bW5Hcm91cC5wcm90b3R5cGUuc2V0RXhwYW5kZWQgPSBmdW5jdGlvbiAoZXhwYW5kZWQpIHtcbiAgICAgICAgdGhpcy5leHBhbmRlZCA9IGV4cGFuZGVkID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGV4cGFuZGVkO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBQcm92aWRlZENvbHVtbkdyb3VwLkVWRU5UX0VYUEFOREVEX0NIQU5HRURcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5sb2NhbEV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzRXhwYW5kYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwYW5kYWJsZTtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmlzRXhwYW5kZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmV4cGFuZGVkO1xuICAgIH07XG4gICAgUHJvdmlkZWRDb2x1bW5Hcm91cC5wcm90b3R5cGUuZ2V0R3JvdXBJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JvdXBJZDtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmdldElkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRHcm91cElkKCk7XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5zZXRDaGlsZHJlbiA9IGZ1bmN0aW9uIChjaGlsZHJlbikge1xuICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW47XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRDaGlsZHJlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2hpbGRyZW47XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRDb2xHcm91cERlZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sR3JvdXBEZWY7XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRMZWFmQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB0aGlzLmFkZExlYWZDb2x1bW5zKHJlc3VsdCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5hZGRMZWFmQ29sdW1ucyA9IGZ1bmN0aW9uIChsZWFmQ29sdW1ucykge1xuICAgICAgICBpZiAoIXRoaXMuY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBsZWFmQ29sdW1ucy5wdXNoKGNoaWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoaWxkIGluc3RhbmNlb2YgUHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIGNoaWxkLmFkZExlYWZDb2x1bW5zKGxlYWZDb2x1bW5zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5nZXRDb2x1bW5Hcm91cFNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb2xHcm91cERlZiA9IHRoaXMuY29sR3JvdXBEZWY7XG4gICAgICAgIGlmICghY29sR3JvdXBEZWYpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sR3JvdXBEZWYuY29sdW1uR3JvdXBTaG93O1xuICAgIH07XG4gICAgLy8gbmVlZCB0byBjaGVjayB0aGF0IHRoaXMgZ3JvdXAgaGFzIGF0IGxlYXN0IG9uZSBjb2wgc2hvd2luZyB3aGVuIGJvdGggZXhwYW5kZWQgYW5kIGNvbnRyYWN0ZWQuXG4gICAgLy8gaWYgbm90LCB0aGVuIHdlIGRvbid0IGFsbG93IGV4cGFuZGluZyBhbmQgY29udHJhY3Rpbmcgb24gdGhpcyBncm91cFxuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLnNldHVwRXhwYW5kYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5zZXRFeHBhbmRhYmxlKCk7XG4gICAgICAgIC8vIG5vdGUgLSB3ZSBzaG91bGQgYmUgcmVtb3ZpbmcgdGhpcyBldmVudCBsaXN0ZW5lclxuICAgICAgICB0aGlzLmdldExlYWZDb2x1bW5zKCkuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuYWRkRXZlbnRMaXN0ZW5lcihDb2x1bW4uRVZFTlRfVklTSUJMRV9DSEFOR0VELCBfdGhpcy5vbkNvbHVtblZpc2liaWxpdHlDaGFuZ2VkLmJpbmQoX3RoaXMpKTsgfSk7XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLnByb3RvdHlwZS5zZXRFeHBhbmRhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1BhZGRpbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdhbnQgdG8gbWFrZSBzdXJlIHRoZSBncm91cCBkb2Vzbid0IGRpc2FwcGVhciB3aGVuIGl0J3Mgb3BlblxuICAgICAgICB2YXIgYXRMZWFzdE9uZVNob3dpbmdXaGVuT3BlbiA9IGZhbHNlO1xuICAgICAgICAvLyB3YW50IHRvIG1ha2Ugc3VyZSB0aGUgZ3JvdXAgZG9lc24ndCBkaXNhcHBlYXIgd2hlbiBpdCdzIGNsb3NlZFxuICAgICAgICB2YXIgYXRMZWFzdE9uZVNob3dpbmdXaGVuQ2xvc2VkID0gZmFsc2U7XG4gICAgICAgIC8vIHdhbnQgdG8gbWFrZSBzdXJlIHRoZSBncm91cCBoYXMgc29tZXRoaW5nIHRvIHNob3cgLyBoaWRlXG4gICAgICAgIHZhciBhdExlYXN0T25lQ2hhbmdlYWJsZSA9IGZhbHNlO1xuICAgICAgICB2YXIgY2hpbGRyZW4gPSB0aGlzLmZpbmRDaGlsZHJlblJlbW92aW5nUGFkZGluZygpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IGNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xuICAgICAgICAgICAgdmFyIGFic3RyYWN0Q29sdW1uID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICBpZiAoIWFic3RyYWN0Q29sdW1uLmlzVmlzaWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiB0aGUgYWJzdHJhY3RDb2x1bW4gaXMgYSBncmlkIGdlbmVyYXRlZCBncm91cCwgdGhlcmUgd2lsbCBiZSBubyBjb2xEZWZcbiAgICAgICAgICAgIHZhciBoZWFkZXJHcm91cFNob3cgPSBhYnN0cmFjdENvbHVtbi5nZXRDb2x1bW5Hcm91cFNob3coKTtcbiAgICAgICAgICAgIGlmIChoZWFkZXJHcm91cFNob3cgPT09IENvbHVtbkdyb3VwLkhFQURFUl9HUk9VUF9TSE9XX09QRU4pIHtcbiAgICAgICAgICAgICAgICBhdExlYXN0T25lU2hvd2luZ1doZW5PcGVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBhdExlYXN0T25lQ2hhbmdlYWJsZSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChoZWFkZXJHcm91cFNob3cgPT09IENvbHVtbkdyb3VwLkhFQURFUl9HUk9VUF9TSE9XX0NMT1NFRCkge1xuICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVTaG93aW5nV2hlbkNsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYXRMZWFzdE9uZUNoYW5nZWFibGUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYXRMZWFzdE9uZVNob3dpbmdXaGVuT3BlbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgYXRMZWFzdE9uZVNob3dpbmdXaGVuQ2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwYW5kYWJsZSA9IGF0TGVhc3RPbmVTaG93aW5nV2hlbk9wZW4gJiYgYXRMZWFzdE9uZVNob3dpbmdXaGVuQ2xvc2VkICYmIGF0TGVhc3RPbmVDaGFuZ2VhYmxlO1xuICAgICAgICBpZiAodGhpcy5leHBhbmRhYmxlICE9PSBleHBhbmRhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLmV4cGFuZGFibGUgPSBleHBhbmRhYmxlO1xuICAgICAgICAgICAgdmFyIGV2ZW50XzEgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogUHJvdmlkZWRDb2x1bW5Hcm91cC5FVkVOVF9FWFBBTkRBQkxFX0NIQU5HRURcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmxvY2FsRXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnRfMSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLmZpbmRDaGlsZHJlblJlbW92aW5nUGFkZGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB2YXIgcHJvY2VzcyA9IGZ1bmN0aW9uIChpdGVtcykge1xuICAgICAgICAgICAgaXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHBhZGRpbmcsIHdlIGFkZCB0aGlzIGNoaWxkcmVuIGluc3RlYWQgb2YgdGhlIHBhZGRpbmdcbiAgICAgICAgICAgICAgICB2YXIgc2tpcEJlY2F1c2VQYWRkaW5nID0gaXRlbSBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXAgJiYgaXRlbS5pc1BhZGRpbmcoKTtcbiAgICAgICAgICAgICAgICBpZiAoc2tpcEJlY2F1c2VQYWRkaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3MoaXRlbS5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXMucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgcHJvY2Vzcyh0aGlzLmNoaWxkcmVuKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLm9uQ29sdW1uVmlzaWJpbGl0eUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0RXhwYW5kYWJsZSgpO1xuICAgIH07XG4gICAgUHJvdmlkZWRDb2x1bW5Hcm91cC5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMubG9jYWxFdmVudFNlcnZpY2UuYWRkRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIFByb3ZpZGVkQ29sdW1uR3JvdXAucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmxvY2FsRXZlbnRTZXJ2aWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLkVWRU5UX0VYUEFOREVEX0NIQU5HRUQgPSAnZXhwYW5kZWRDaGFuZ2VkJztcbiAgICBQcm92aWRlZENvbHVtbkdyb3VwLkVWRU5UX0VYUEFOREFCTEVfQ0hBTkdFRCA9ICdleHBhbmRhYmxlQ2hhbmdlZCc7XG4gICAgcmV0dXJuIFByb3ZpZGVkQ29sdW1uR3JvdXA7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgRGVmYXVsdENvbHVtblR5cGVzID0ge1xuICAgIG51bWVyaWNDb2x1bW46IHtcbiAgICAgICAgaGVhZGVyQ2xhc3M6ICdhZy1yaWdodC1hbGlnbmVkLWhlYWRlcicsXG4gICAgICAgIGNlbGxDbGFzczogJ2FnLXJpZ2h0LWFsaWduZWQtY2VsbCdcbiAgICB9LFxuICAgIHJpZ2h0QWxpZ25lZDoge1xuICAgICAgICBoZWFkZXJDbGFzczogJ2FnLXJpZ2h0LWFsaWduZWQtaGVhZGVyJyxcbiAgICAgICAgY2VsbENsYXNzOiAnYWctcmlnaHQtYWxpZ25lZC1jZWxsJ1xuICAgIH1cbn07XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBBR19HUklEX1NUT1BfUFJPUEFHQVRJT04gPSAnX19hZ19HcmlkX1N0b3BfUHJvcGFnYXRpb24nO1xudmFyIFBBU1NJVkVfRVZFTlRTJDEgPSBbJ3RvdWNoc3RhcnQnLCAndG91Y2hlbmQnLCAndG91Y2htb3ZlJywgJ3RvdWNoY2FuY2VsJ107XG52YXIgc3VwcG9ydHMgPSB7fTtcbi8qKlxuICogYSB1c2VyIG9uY2UgcmFpc2VkIGFuIGlzc3VlIC0gdGhleSBzYWlkIHRoYXQgd2hlbiB5b3Ugb3BlbmVkIGEgcG9wdXAgKGVnIGNvbnRleHQgbWVudSlcbiAqIGFuZCB0aGVuIGNsaWNrZWQgb24gYSBzZWxlY3Rpb24gY2hlY2tib3gsIHRoZSBwb3B1cCB3YXNuJ3QgY2xvc2VkLiB0aGlzIGlzIGJlY2F1c2UgdGhlXG4gKiBwb3B1cCBsaXN0ZW5zIGZvciBjbGlja3Mgb24gdGhlIGJvZHksIGhvd2V2ZXIgYWctZ3JpZCBXQVMgc3RvcHBpbmcgcHJvcGFnYXRpb24gb24gdGhlXG4gKiBjaGVja2JveCBjbGlja3MgKHNvIHRoZSByb3dzIGRpZG4ndCBwaWNrIHRoZW0gdXAgYXMgcm93IHNlbGVjdGlvbiBzZWxlY3Rpb24gY2xpY2tzKS5cbiAqIHRvIGdldCBhcm91bmQgdGhpcywgd2UgaGF2ZSBhIHBhdHRlcm4gdG8gc3RvcCBwcm9wYWdhdGlvbiBmb3IgdGhlIHB1cnBvc2VzIG9mIEFHIEdyaWQsXG4gKiBidXQgd2Ugc3RpbGwgbGV0IHRoZSBldmVudCBwYXNzIGJhY2sgdG8gdGhlIGJvZHkuXG4gKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICovXG5mdW5jdGlvbiBzdG9wUHJvcGFnYXRpb25Gb3JBZ0dyaWQoZXZlbnQpIHtcbiAgICBldmVudFtBR19HUklEX1NUT1BfUFJPUEFHQVRJT05dID0gdHJ1ZTtcbn1cbmZ1bmN0aW9uIGlzU3RvcFByb3BhZ2F0aW9uRm9yQWdHcmlkKGV2ZW50KSB7XG4gICAgcmV0dXJuIGV2ZW50W0FHX0dSSURfU1RPUF9QUk9QQUdBVElPTl0gPT09IHRydWU7XG59XG52YXIgaXNFdmVudFN1cHBvcnRlZCA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHRhZ3MgPSB7XG4gICAgICAgIHNlbGVjdDogJ2lucHV0JyxcbiAgICAgICAgY2hhbmdlOiAnaW5wdXQnLFxuICAgICAgICBzdWJtaXQ6ICdmb3JtJyxcbiAgICAgICAgcmVzZXQ6ICdmb3JtJyxcbiAgICAgICAgZXJyb3I6ICdpbWcnLFxuICAgICAgICBsb2FkOiAnaW1nJyxcbiAgICAgICAgYWJvcnQ6ICdpbWcnXG4gICAgfTtcbiAgICB2YXIgZXZlbnRDaGVja2VyID0gZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xuICAgICAgICBpZiAodHlwZW9mIHN1cHBvcnRzW2V2ZW50TmFtZV0gPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIHN1cHBvcnRzW2V2ZW50TmFtZV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdzW2V2ZW50TmFtZV0gfHwgJ2RpdicpO1xuICAgICAgICBldmVudE5hbWUgPSAnb24nICsgZXZlbnROYW1lO1xuICAgICAgICByZXR1cm4gc3VwcG9ydHNbZXZlbnROYW1lXSA9IChldmVudE5hbWUgaW4gZWwpO1xuICAgIH07XG4gICAgcmV0dXJuIGV2ZW50Q2hlY2tlcjtcbn0pKCk7XG5mdW5jdGlvbiBnZXRDdHJsRm9yRXZlbnQoZ3JpZE9wdGlvbnNXcmFwcGVyLCBldmVudCwgdHlwZSkge1xuICAgIHZhciBzb3VyY2VFbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIHdoaWxlIChzb3VyY2VFbGVtZW50KSB7XG4gICAgICAgIHZhciByZW5kZXJlZENvbXAgPSBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tRGF0YShzb3VyY2VFbGVtZW50LCB0eXBlKTtcbiAgICAgICAgaWYgKHJlbmRlcmVkQ29tcCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkQ29tcDtcbiAgICAgICAgfVxuICAgICAgICBzb3VyY2VFbGVtZW50ID0gc291cmNlRWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbi8qKlxuICogQGRlcHJlY2F0ZWRcbiAqIEFkZHMgYWxsIHR5cGUgb2YgY2hhbmdlIGxpc3RlbmVycyB0byBhbiBlbGVtZW50LCBpbnRlbmRlZCB0byBiZSBhIHRleHQgZmllbGRcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7RXZlbnRMaXN0ZW5lcn0gbGlzdGVuZXJcbiAqL1xuZnVuY3Rpb24gYWRkQ2hhbmdlTGlzdGVuZXIoZWxlbWVudCwgbGlzdGVuZXIpIHtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZWQnLCBsaXN0ZW5lcik7XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdwYXN0ZScsIGxpc3RlbmVyKTtcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JywgbGlzdGVuZXIpO1xufVxuZnVuY3Rpb24gaXNFbGVtZW50SW5FdmVudFBhdGgoZWxlbWVudCwgZXZlbnQpIHtcbiAgICBpZiAoIWV2ZW50IHx8ICFlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIGdldEV2ZW50UGF0aChldmVudCkuaW5kZXhPZihlbGVtZW50KSA+PSAwO1xufVxuZnVuY3Rpb24gY3JlYXRlRXZlbnRQYXRoKGV2ZW50KSB7XG4gICAgdmFyIHJlcyA9IFtdO1xuICAgIHZhciBwb2ludGVyID0gZXZlbnQudGFyZ2V0O1xuICAgIHdoaWxlIChwb2ludGVyKSB7XG4gICAgICAgIHJlcy5wdXNoKHBvaW50ZXIpO1xuICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnRFbGVtZW50O1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuLyoqXG4gKiBmaXJlZm94IGRvZXNuJ3QgaGF2ZSBldmVudC5wYXRoIHNldCwgb3IgYW55IGFsdGVybmF0aXZlIHRvIGl0LCBzbyB3ZSBoYWNrXG4gKiBpdCBpbi4gdGhpcyBpcyBuZWVkZWQgYXMgaXQncyB0byBsYXRlIHRvIHdvcmsgb3V0IHRoZSBwYXRoIHdoZW4gdGhlIGl0ZW0gaXNcbiAqIHJlbW92ZWQgZnJvbSB0aGUgZG9tLiB1c2VkIGJ5IE1vdXNlRXZlbnRTZXJ2aWNlLCB3aGVyZSBpdCB3b3JrcyBvdXQgaWYgYSBjbGlja1xuICogd2FzIGZyb20gdGhlIGN1cnJlbnQgZ3JpZCwgb3IgYSBkZXRhaWwgZ3JpZCAobWFzdGVyIC8gZGV0YWlsKS5cbiAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG4gKi9cbmZ1bmN0aW9uIGFkZEFnR3JpZEV2ZW50UGF0aChldmVudCkge1xuICAgIGV2ZW50Ll9fYWdHcmlkRXZlbnRQYXRoID0gZ2V0RXZlbnRQYXRoKGV2ZW50KTtcbn1cbi8qKlxuICogR2V0cyB0aGUgcGF0aCBmb3IgYW4gRXZlbnQuXG4gKiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zOTI0NTQ4OC9ldmVudC1wYXRoLXVuZGVmaW5lZC13aXRoLWZpcmVmb3gtYW5kLXZ1ZS1qc1xuICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50XG4gKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICogQHJldHVybnMge0V2ZW50VGFyZ2V0W119XG4gKi9cbmZ1bmN0aW9uIGdldEV2ZW50UGF0aChldmVudCkge1xuICAgIHZhciBldmVudE5vVHlwZSA9IGV2ZW50O1xuICAgIGlmIChldmVudE5vVHlwZS5wYXRoKSB7XG4gICAgICAgIC8vIENocm9tZSBzdXBwb3J0cyBwYXRoXG4gICAgICAgIHJldHVybiBldmVudE5vVHlwZS5wYXRoO1xuICAgIH1cbiAgICBpZiAoZXZlbnROb1R5cGUuY29tcG9zZWRQYXRoKSB7XG4gICAgICAgIC8vIEZpcmVmb3ggc3VwcG9ydHMgY29tcG9zZVBhdGhcbiAgICAgICAgcmV0dXJuIGV2ZW50Tm9UeXBlLmNvbXBvc2VkUGF0aCgpO1xuICAgIH1cbiAgICBpZiAoZXZlbnROb1R5cGUuX19hZ0dyaWRFdmVudFBhdGgpIHtcbiAgICAgICAgLy8gRmlyZWZveCBzdXBwb3J0cyBjb21wb3NlUGF0aFxuICAgICAgICByZXR1cm4gZXZlbnROb1R5cGUuX19hZ0dyaWRFdmVudFBhdGg7XG4gICAgfVxuICAgIC8vIGFuZCBmaW5hbGx5LCBpZiBub25lIG9mIHRoZSBhYm92ZSB3b3JrZWQsXG4gICAgLy8gd2UgY3JlYXRlIHRoZSBwYXRoIG91cnNlbHZlc1xuICAgIHJldHVybiBjcmVhdGVFdmVudFBhdGgoZXZlbnQpO1xufVxuZnVuY3Rpb24gYWRkU2FmZVBhc3NpdmVFdmVudExpc3RlbmVyKGZyYW1ld29ya092ZXJyaWRlcywgZUVsZW1lbnQsIGV2ZW50LCBsaXN0ZW5lcikge1xuICAgIHZhciBpc1Bhc3NpdmUgPSBpbmNsdWRlcyhQQVNTSVZFX0VWRU5UUyQxLCBldmVudCk7XG4gICAgdmFyIG9wdGlvbnMgPSBpc1Bhc3NpdmUgPyB7IHBhc3NpdmU6IHRydWUgfSA6IHVuZGVmaW5lZDtcbiAgICAvLyB0aGlzIGNoZWNrIGlzIGhlcmUgZm9yIGNlcnRhaW4gc2NlbmFyaW9zIHdoZXJlIEkgYmVsaWV2ZSB0aGUgdXNlciBtdXN0IGJlIGRlc3Ryb3lpbmdcbiAgICAvLyB0aGUgZ3JpZCBzb21laG93IGJ1dCBjb250aW51aW5nIGZvciBpdCB0byBiZSB1c2VkXG4gICAgaWYgKGZyYW1ld29ya092ZXJyaWRlcyAmJiBmcmFtZXdvcmtPdmVycmlkZXMuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICBmcmFtZXdvcmtPdmVycmlkZXMuYWRkRXZlbnRMaXN0ZW5lcihlRWxlbWVudCwgZXZlbnQsIGxpc3RlbmVyLCBvcHRpb25zKTtcbiAgICB9XG59XG5cbnZhciBFdmVudFV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBzdG9wUHJvcGFnYXRpb25Gb3JBZ0dyaWQ6IHN0b3BQcm9wYWdhdGlvbkZvckFnR3JpZCxcbiAgICBpc1N0b3BQcm9wYWdhdGlvbkZvckFnR3JpZDogaXNTdG9wUHJvcGFnYXRpb25Gb3JBZ0dyaWQsXG4gICAgaXNFdmVudFN1cHBvcnRlZDogaXNFdmVudFN1cHBvcnRlZCxcbiAgICBnZXRDdHJsRm9yRXZlbnQ6IGdldEN0cmxGb3JFdmVudCxcbiAgICBhZGRDaGFuZ2VMaXN0ZW5lcjogYWRkQ2hhbmdlTGlzdGVuZXIsXG4gICAgaXNFbGVtZW50SW5FdmVudFBhdGg6IGlzRWxlbWVudEluRXZlbnRQYXRoLFxuICAgIGNyZWF0ZUV2ZW50UGF0aDogY3JlYXRlRXZlbnRQYXRoLFxuICAgIGFkZEFnR3JpZEV2ZW50UGF0aDogYWRkQWdHcmlkRXZlbnRQYXRoLFxuICAgIGdldEV2ZW50UGF0aDogZ2V0RXZlbnRQYXRoLFxuICAgIGFkZFNhZmVQYXNzaXZlRXZlbnRMaXN0ZW5lcjogYWRkU2FmZVBhc3NpdmVFdmVudExpc3RlbmVyXG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZGVjb3JhdGUkMnggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBCZWFuU3R1YiA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCZWFuU3R1YigpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5kZXN0cm95RnVuY3Rpb25zID0gW107XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgICAgIC8vIGZvciB2dWUgMyAtIHByZXZlbnRzIFZ1ZSBmcm9tIHRyeWluZyB0byBtYWtlIHRoaXMgKGFuZCBvYnZpb3VzbHkgYW55IHN1YiBjbGFzc2VzKSBmcm9tIGJlaW5nIHJlYWN0aXZlXG4gICAgICAgIC8vIHByZXZlbnRzIHZ1ZSBmcm9tIGNyZWF0aW5nIHByb3hpZXMgZm9yIGNyZWF0ZWQgb2JqZWN0cyBhbmQgcHJldmVudHMgaWRlbnRpdHkgcmVsYXRlZCBpc3N1ZXNcbiAgICAgICAgdGhpcy5fX3Zfc2tpcCA9IHRydWU7XG4gICAgICAgIHRoaXMuaXNBbGl2ZSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuICFfdGhpcy5kZXN0cm95ZWQ7IH07XG4gICAgfVxuICAgIC8vIHRoaXMgd2FzIGEgdGVzdCBjb25zdHJ1Y3RvciBuaWFsbCBidWlsdCwgd2hlbiBhY3RpdmUsIGl0IHByaW50cyBhZnRlciA1IHNlY29uZHMgYWxsIGJlYW5zL2NvbXBvbmVudHMgdGhhdCBhcmVcbiAgICAvLyBub3QgZGVzdHJveWVkLiB0byB1c2UsIGNyZWF0ZSBhIG5ldyBncmlkLCB0aGVuIGFwaS5kZXN0cm95KCkgYmVmb3JlIDUgc2Vjb25kcy4gdGhlbiBhbnl0aGluZyB0aGF0IGdldHMgcHJpbnRlZFxuICAgIC8vIHBvaW50cyB0byBhIGJlYW4gb3IgY29tcG9uZW50IHRoYXQgd2FzIG5vdCBwcm9wZXJseSBkaXNwb3NlZCBvZi5cbiAgICAvLyBjb25zdHJ1Y3RvcigpIHtcbiAgICAvLyAgICAgc2V0VGltZW91dCgoKT0+IHtcbiAgICAvLyAgICAgICAgIGlmICh0aGlzLmlzQWxpdmUoKSkge1xuICAgIC8vICAgICAgICAgICAgIGxldCBwcm90b3R5cGU6IGFueSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKTtcbiAgICAvLyAgICAgICAgICAgICBjb25zdCBjb25zdHJ1Y3RvcjogYW55ID0gcHJvdG90eXBlLmNvbnN0cnVjdG9yO1xuICAgIC8vICAgICAgICAgICAgIGNvbnN0IGNvbnN0cnVjdG9yU3RyaW5nID0gY29uc3RydWN0b3IudG9TdHJpbmcoKTtcbiAgICAvLyAgICAgICAgICAgICBjb25zdCBiZWFuTmFtZSA9IGNvbnN0cnVjdG9yU3RyaW5nLnN1YnN0cmluZyg5LCBjb25zdHJ1Y3RvclN0cmluZy5pbmRleE9mKFwiKFwiKSk7XG4gICAgLy8gICAgICAgICAgICAgY29uc29sZS5sb2coJ2lzIGFsaXZlICcgKyBiZWFuTmFtZSk7XG4gICAgLy8gICAgICAgICB9XG4gICAgLy8gICAgIH0sIDUwMDApO1xuICAgIC8vIH1cbiAgICAvLyBDZWxsQ29tcCBhbmQgR3JpZENvbXAgYW5kIG92ZXJyaWRlIHRoaXMgYmVjYXVzZSB0aGV5IGdldCB0aGUgRnJhbWV3b3JrT3ZlcnJpZGVzIGZyb20gdGhlIEJlYW5zIGJlYW5cbiAgICBCZWFuU3R1Yi5wcm90b3R5cGUuZ2V0RnJhbWV3b3JrT3ZlcnJpZGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mcmFtZXdvcmtPdmVycmlkZXM7XG4gICAgfTtcbiAgICBCZWFuU3R1Yi5wcm90b3R5cGUuZ2V0Q29udGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dDtcbiAgICB9O1xuICAgIEJlYW5TdHViLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBsZXQgcHJvdG90eXBlOiBhbnkgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcyk7XG4gICAgICAgIC8vIGNvbnN0IGNvbnN0cnVjdG9yOiBhbnkgPSBwcm90b3R5cGUuY29uc3RydWN0b3I7XG4gICAgICAgIC8vIGNvbnN0IGNvbnN0cnVjdG9yU3RyaW5nID0gY29uc3RydWN0b3IudG9TdHJpbmcoKTtcbiAgICAgICAgLy8gY29uc3QgYmVhbk5hbWUgPSBjb25zdHJ1Y3RvclN0cmluZy5zdWJzdHJpbmcoOSwgY29uc3RydWN0b3JTdHJpbmcuaW5kZXhPZihcIihcIikpO1xuICAgICAgICB0aGlzLmRlc3Ryb3lGdW5jdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAoZnVuYykgeyByZXR1cm4gZnVuYygpOyB9KTtcbiAgICAgICAgdGhpcy5kZXN0cm95RnVuY3Rpb25zLmxlbmd0aCA9IDA7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHsgdHlwZTogQmVhblN0dWIuRVZFTlRfREVTVFJPWUVEIH0pO1xuICAgIH07XG4gICAgQmVhblN0dWIucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIXRoaXMubG9jYWxFdmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMubG9jYWxFdmVudFNlcnZpY2UgPSBuZXcgRXZlbnRTZXJ2aWNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2NhbEV2ZW50U2VydmljZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgQmVhblN0dWIucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAodGhpcy5sb2NhbEV2ZW50U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5sb2NhbEV2ZW50U2VydmljZS5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCZWFuU3R1Yi5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudEFzeW5jID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmRpc3BhdGNoRXZlbnQoZXZlbnQpOyB9LCAwKTtcbiAgICB9O1xuICAgIEJlYW5TdHViLnByb3RvdHlwZS5kaXNwYXRjaEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLmxvY2FsRXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmxvY2FsRXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCZWFuU3R1Yi5wcm90b3R5cGUuYWRkTWFuYWdlZExpc3RlbmVyID0gZnVuY3Rpb24gKG9iamVjdCwgZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgICAgYWRkU2FmZVBhc3NpdmVFdmVudExpc3RlbmVyKHRoaXMuZ2V0RnJhbWV3b3JrT3ZlcnJpZGVzKCksIG9iamVjdCwgZXZlbnQsIGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG9iamVjdC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRlc3Ryb3lGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb2JqZWN0LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIF90aGlzLmRlc3Ryb3lGdW5jdGlvbnMgPSBfdGhpcy5kZXN0cm95RnVuY3Rpb25zLmZpbHRlcihmdW5jdGlvbiAoZm4pIHsgcmV0dXJuIGZuICE9PSBkZXN0cm95RnVuYzsgfSk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kZXN0cm95RnVuY3Rpb25zLnB1c2goZGVzdHJveUZ1bmMpO1xuICAgICAgICByZXR1cm4gZGVzdHJveUZ1bmM7XG4gICAgfTtcbiAgICBCZWFuU3R1Yi5wcm90b3R5cGUuYWRkRGVzdHJveUZ1bmMgPSBmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICAvLyBpZiB3ZSBhcmUgYWxyZWFkeSBkZXN0cm95ZWQsIHdlIGV4ZWN1dGUgdGhlIGZ1bmMgbm93XG4gICAgICAgIGlmICh0aGlzLmlzQWxpdmUoKSkge1xuICAgICAgICAgICAgdGhpcy5kZXN0cm95RnVuY3Rpb25zLnB1c2goZnVuYyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmdW5jKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEJlYW5TdHViLnByb3RvdHlwZS5jcmVhdGVNYW5hZ2VkQmVhbiA9IGZ1bmN0aW9uIChiZWFuLCBjb250ZXh0KSB7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLmNyZWF0ZUJlYW4oYmVhbiwgY29udGV4dCk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmModGhpcy5kZXN0cm95QmVhbi5iaW5kKHRoaXMsIGJlYW4sIGNvbnRleHQpKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIEJlYW5TdHViLnByb3RvdHlwZS5jcmVhdGVCZWFuID0gZnVuY3Rpb24gKGJlYW4sIGNvbnRleHQsIGFmdGVyUHJlQ3JlYXRlQ2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIChjb250ZXh0IHx8IHRoaXMuZ2V0Q29udGV4dCgpKS5jcmVhdGVCZWFuKGJlYW4sIGFmdGVyUHJlQ3JlYXRlQ2FsbGJhY2spO1xuICAgIH07XG4gICAgQmVhblN0dWIucHJvdG90eXBlLmRlc3Ryb3lCZWFuID0gZnVuY3Rpb24gKGJlYW4sIGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIChjb250ZXh0IHx8IHRoaXMuZ2V0Q29udGV4dCgpKS5kZXN0cm95QmVhbihiZWFuKTtcbiAgICB9O1xuICAgIEJlYW5TdHViLnByb3RvdHlwZS5kZXN0cm95QmVhbnMgPSBmdW5jdGlvbiAoYmVhbnMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKGJlYW5zKSB7XG4gICAgICAgICAgICBiZWFucy5mb3JFYWNoKGZ1bmN0aW9uIChiZWFuKSB7IHJldHVybiBfdGhpcy5kZXN0cm95QmVhbihiZWFuLCBjb250ZXh0KTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH07XG4gICAgQmVhblN0dWIuRVZFTlRfREVTVFJPWUVEID0gJ2Rlc3Ryb3llZCc7XG4gICAgX19kZWNvcmF0ZSQyeChbXG4gICAgICAgIEF1dG93aXJlZCgnZnJhbWV3b3JrT3ZlcnJpZGVzJylcbiAgICBdLCBCZWFuU3R1Yi5wcm90b3R5cGUsIFwiZnJhbWV3b3JrT3ZlcnJpZGVzXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyeChbXG4gICAgICAgIEF1dG93aXJlZCgnY29udGV4dCcpXG4gICAgXSwgQmVhblN0dWIucHJvdG90eXBlLCBcImNvbnRleHRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ4KFtcbiAgICAgICAgQXV0b3dpcmVkKCdldmVudFNlcnZpY2UnKVxuICAgIF0sIEJlYW5TdHViLnByb3RvdHlwZSwgXCJldmVudFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ4KFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkT3B0aW9uc1dyYXBwZXInKVxuICAgIF0sIEJlYW5TdHViLnByb3RvdHlwZSwgXCJncmlkT3B0aW9uc1dyYXBwZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ4KFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIEJlYW5TdHViLnByb3RvdHlwZSwgXCJkZXN0cm95XCIsIG51bGwpO1xuICAgIHJldHVybiBCZWFuU3R1Yjtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMlUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJ3ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX19wYXJhbSQ5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19wYXJhbSkgfHwgZnVuY3Rpb24gKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxufTtcbi8vIHRha2VzIENvbERlZnMgYW5kIENvbEdyb3VwRGVmcyBhbmQgdHVybnMgdGhlbSBpbnRvIENvbHVtbnMgYW5kIE9yaWdpbmFsR3JvdXBzXG52YXIgQ29sdW1uRmFjdG9yeSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMlUoQ29sdW1uRmFjdG9yeSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDb2x1bW5GYWN0b3J5KCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIENvbHVtbkZhY3RvcnkucHJvdG90eXBlLnNldEJlYW5zID0gZnVuY3Rpb24gKGxvZ2dlckZhY3RvcnkpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXJGYWN0b3J5LmNyZWF0ZSgnQ29sdW1uRmFjdG9yeScpO1xuICAgIH07XG4gICAgQ29sdW1uRmFjdG9yeS5wcm90b3R5cGUuY3JlYXRlQ29sdW1uVHJlZSA9IGZ1bmN0aW9uIChkZWZzLCBwcmltYXJ5Q29sdW1ucywgZXhpc3RpbmdUcmVlKSB7XG4gICAgICAgIC8vIGNvbHVtbiBrZXkgY3JlYXRvciBkaXNoZXMgb3V0IHVuaXF1ZSBjb2x1bW4gaWQncyBpbiBhIGRldGVybWluaXN0aWMgd2F5LFxuICAgICAgICAvLyBzbyBpZiB3ZSBoYXZlIHR3byBncmlkcyAodGhhdCBjb3VsZCBiZSBtYXN0ZXIvc2xhdmUpIHdpdGggc2FtZSBjb2x1bW4gZGVmaW5pdGlvbnMsXG4gICAgICAgIC8vIHRoZW4gdGhpcyBlbnN1cmVzIHRoZSB0d28gZ3JpZHMgdXNlIGlkZW50aWNhbCBpZCdzLlxuICAgICAgICB2YXIgY29sdW1uS2V5Q3JlYXRvciA9IG5ldyBDb2x1bW5LZXlDcmVhdG9yKCk7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuZXh0cmFjdEV4aXN0aW5nVHJlZURhdGEoZXhpc3RpbmdUcmVlKSwgZXhpc3RpbmdDb2xzID0gX2EuZXhpc3RpbmdDb2xzLCBleGlzdGluZ0dyb3VwcyA9IF9hLmV4aXN0aW5nR3JvdXBzLCBleGlzdGluZ0NvbEtleXMgPSBfYS5leGlzdGluZ0NvbEtleXM7XG4gICAgICAgIGNvbHVtbktleUNyZWF0b3IuYWRkRXhpc3RpbmdLZXlzKGV4aXN0aW5nQ29sS2V5cyk7XG4gICAgICAgIC8vIGNyZWF0ZSBhbSB1bmJhbGFuY2VkIHRyZWUgdGhhdCBtYXBzIHRoZSBwcm92aWRlZCBkZWZpbml0aW9uc1xuICAgICAgICB2YXIgdW5iYWxhbmNlZFRyZWUgPSB0aGlzLnJlY3Vyc2l2ZWx5Q3JlYXRlQ29sdW1ucyhkZWZzLCAwLCBwcmltYXJ5Q29sdW1ucywgZXhpc3RpbmdDb2xzLCBjb2x1bW5LZXlDcmVhdG9yLCBleGlzdGluZ0dyb3Vwcyk7XG4gICAgICAgIHZhciB0cmVlRGVwdCA9IHRoaXMuZmluZE1heERlcHQodW5iYWxhbmNlZFRyZWUsIDApO1xuICAgICAgICB0aGlzLmxvZ2dlci5sb2coJ051bWJlciBvZiBsZXZlbHMgZm9yIGdyb3VwZWQgY29sdW1ucyBpcyAnICsgdHJlZURlcHQpO1xuICAgICAgICB2YXIgY29sdW1uVHJlZSA9IHRoaXMuYmFsYW5jZUNvbHVtblRyZWUodW5iYWxhbmNlZFRyZWUsIDAsIHRyZWVEZXB0LCBjb2x1bW5LZXlDcmVhdG9yKTtcbiAgICAgICAgdmFyIGRlcHRGaXJzdENhbGxiYWNrID0gZnVuY3Rpb24gKGNoaWxkLCBwYXJlbnQpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICBjaGlsZC5zZXR1cEV4cGFuZGFibGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHdlIHNldCB0aGUgb3JpZ2luYWwgcGFyZW50cyBhdCB0aGUgZW5kLCByYXRoZXIgdGhhbiB3aGVuIHdlIGdvIGFsb25nLCBhcyBiYWxhbmNpbmcgdGhlIHRyZWVcbiAgICAgICAgICAgIC8vIGFkZHMgZXh0cmEgbGV2ZWxzIGludG8gdGhlIHRyZWUuIHNvIHdlIGNhbiBvbmx5IHNldCBwYXJlbnRzIHdoZW4gYmFsYW5jaW5nIGlzIGRvbmUuXG4gICAgICAgICAgICBjaGlsZC5zZXRPcmlnaW5hbFBhcmVudChwYXJlbnQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RPcmlnaW5hbFRyZWVTZWFyY2gobnVsbCwgY29sdW1uVHJlZSwgZGVwdEZpcnN0Q2FsbGJhY2spO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29sdW1uVHJlZTogY29sdW1uVHJlZSxcbiAgICAgICAgICAgIHRyZWVEZXB0OiB0cmVlRGVwdFxuICAgICAgICB9O1xuICAgIH07XG4gICAgQ29sdW1uRmFjdG9yeS5wcm90b3R5cGUuZXh0cmFjdEV4aXN0aW5nVHJlZURhdGEgPSBmdW5jdGlvbiAoZXhpc3RpbmdUcmVlKSB7XG4gICAgICAgIHZhciBleGlzdGluZ0NvbHMgPSBbXTtcbiAgICAgICAgdmFyIGV4aXN0aW5nR3JvdXBzID0gW107XG4gICAgICAgIHZhciBleGlzdGluZ0NvbEtleXMgPSBbXTtcbiAgICAgICAgaWYgKGV4aXN0aW5nVHJlZSkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5VdGlscy5kZXB0aEZpcnN0T3JpZ2luYWxUcmVlU2VhcmNoKG51bGwsIGV4aXN0aW5nVHJlZSwgZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgICAgICBpZiAoaXRlbSBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGdyb3VwID0gaXRlbTtcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdHcm91cHMucHVzaChncm91cCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29sID0gaXRlbTtcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdDb2xLZXlzLnB1c2goY29sLmdldElkKCkpO1xuICAgICAgICAgICAgICAgICAgICBleGlzdGluZ0NvbHMucHVzaChjb2wpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IGV4aXN0aW5nQ29sczogZXhpc3RpbmdDb2xzLCBleGlzdGluZ0dyb3VwczogZXhpc3RpbmdHcm91cHMsIGV4aXN0aW5nQ29sS2V5czogZXhpc3RpbmdDb2xLZXlzIH07XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5jcmVhdGVGb3JBdXRvR3JvdXBzID0gZnVuY3Rpb24gKGF1dG9Hcm91cENvbHMsIGdyaWRCYWxhbmNlZFRyZWUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIGF1dG9Hcm91cENvbHMubWFwKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIF90aGlzLmNyZWF0ZUF1dG9Hcm91cFRyZWVJdGVtKGdyaWRCYWxhbmNlZFRyZWUsIGNvbCk7IH0pO1xuICAgIH07XG4gICAgQ29sdW1uRmFjdG9yeS5wcm90b3R5cGUuY3JlYXRlQXV0b0dyb3VwVHJlZUl0ZW0gPSBmdW5jdGlvbiAoYmFsYW5jZWRDb2x1bW5UcmVlLCBjb2x1bW4pIHtcbiAgICAgICAgdmFyIGRlcHQgPSB0aGlzLmZpbmREZXB0aChiYWxhbmNlZENvbHVtblRyZWUpO1xuICAgICAgICAvLyBhdCB0aGUgZW5kLCB0aGlzIHdpbGwgYmUgdGhlIHRvcCBvZiB0aGUgdHJlZSBpdGVtLlxuICAgICAgICB2YXIgbmV4dENoaWxkID0gY29sdW1uO1xuICAgICAgICBmb3IgKHZhciBpID0gZGVwdCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICB2YXIgYXV0b0dyb3VwID0gbmV3IFByb3ZpZGVkQ29sdW1uR3JvdXAobnVsbCwgXCJGQUtFX1BBVEhfXCIgKyBjb2x1bW4uZ2V0SWQoKSArIFwifV9cIiArIGksIHRydWUsIGkpO1xuICAgICAgICAgICAgdGhpcy5jb250ZXh0LmNyZWF0ZUJlYW4oYXV0b0dyb3VwKTtcbiAgICAgICAgICAgIGF1dG9Hcm91cC5zZXRDaGlsZHJlbihbbmV4dENoaWxkXSk7XG4gICAgICAgICAgICBuZXh0Q2hpbGQuc2V0T3JpZ2luYWxQYXJlbnQoYXV0b0dyb3VwKTtcbiAgICAgICAgICAgIG5leHRDaGlsZCA9IGF1dG9Hcm91cDtcbiAgICAgICAgfVxuICAgICAgICAvLyBhdCB0aGlzIHBvaW50LCB0aGUgbmV4dENoaWxkIGlzIHRoZSB0b3AgbW9zdCBpdGVtIGluIHRoZSB0cmVlXG4gICAgICAgIHJldHVybiBuZXh0Q2hpbGQ7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5maW5kRGVwdGggPSBmdW5jdGlvbiAoYmFsYW5jZWRDb2x1bW5UcmVlKSB7XG4gICAgICAgIHZhciBkZXB0ID0gMDtcbiAgICAgICAgdmFyIHBvaW50ZXIgPSBiYWxhbmNlZENvbHVtblRyZWU7XG4gICAgICAgIHdoaWxlIChwb2ludGVyICYmIHBvaW50ZXJbMF0gJiYgcG9pbnRlclswXSBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgIGRlcHQrKztcbiAgICAgICAgICAgIHBvaW50ZXIgPSBwb2ludGVyWzBdLmdldENoaWxkcmVuKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlcHQ7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5iYWxhbmNlQ29sdW1uVHJlZSA9IGZ1bmN0aW9uICh1bmJhbGFuY2VkVHJlZSwgY3VycmVudERlcHQsIGNvbHVtbkRlcHQsIGNvbHVtbktleUNyZWF0b3IpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAvLyBnbyB0aHJvdWdoIGVhY2ggY2hpbGQsIGZvciBncm91cHMsIHJlY3Vyc2UgYSBsZXZlbCBkZWVwZXIsXG4gICAgICAgIC8vIGZvciBjb2x1bW5zIHdlIG5lZWQgdG8gcGFkXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdW5iYWxhbmNlZFRyZWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBjaGlsZCA9IHVuYmFsYW5jZWRUcmVlW2ldO1xuICAgICAgICAgICAgaWYgKGNoaWxkIGluc3RhbmNlb2YgUHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIC8vIGNoaWxkIGlzIGEgZ3JvdXAsIGFsbCB3ZSBkbyBpcyBnbyB0byB0aGUgbmV4dCBsZXZlbCBvZiByZWN1cnNpb25cbiAgICAgICAgICAgICAgICB2YXIgb3JpZ2luYWxHcm91cCA9IGNoaWxkO1xuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IHRoaXMuYmFsYW5jZUNvbHVtblRyZWUob3JpZ2luYWxHcm91cC5nZXRDaGlsZHJlbigpLCBjdXJyZW50RGVwdCArIDEsIGNvbHVtbkRlcHQsIGNvbHVtbktleUNyZWF0b3IpO1xuICAgICAgICAgICAgICAgIG9yaWdpbmFsR3JvdXAuc2V0Q2hpbGRyZW4obmV3Q2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKG9yaWdpbmFsR3JvdXApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY2hpbGQgaXMgYSBjb2x1bW4gLSBzbyBoZXJlIHdlIGFkZCBpbiB0aGUgcGFkZGVkIGNvbHVtbiBncm91cHMgaWYgbmVlZGVkXG4gICAgICAgICAgICAgICAgdmFyIGZpcnN0UGFkZGVkR3JvdXAgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRQYWRkZWRHcm91cCA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGZvciBsb29wIHdpbGwgTk9UIHJ1biBhbnkgbG9vcHMgaWYgbm8gcGFkZGVkIGNvbHVtbiBncm91cHMgYXJlIG5lZWRlZFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSBjb2x1bW5EZXB0IC0gMTsgaiA+PSBjdXJyZW50RGVwdDsgai0tKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdDb2xJZCA9IGNvbHVtbktleUNyZWF0b3IuZ2V0VW5pcXVlS2V5KG51bGwsIG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29sR3JvdXBEZWZNZXJnZWQgPSB0aGlzLmNyZWF0ZU1lcmdlZENvbEdyb3VwRGVmKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFkZGVkR3JvdXAgPSBuZXcgUHJvdmlkZWRDb2x1bW5Hcm91cChjb2xHcm91cERlZk1lcmdlZCwgbmV3Q29sSWQsIHRydWUsIGN1cnJlbnREZXB0KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250ZXh0LmNyZWF0ZUJlYW4ocGFkZGVkR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudFBhZGRlZEdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50UGFkZGVkR3JvdXAuc2V0Q2hpbGRyZW4oW3BhZGRlZEdyb3VwXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFBhZGRlZEdyb3VwID0gcGFkZGVkR3JvdXA7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZmlyc3RQYWRkZWRHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RQYWRkZWRHcm91cCA9IGN1cnJlbnRQYWRkZWRHcm91cDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBsaWtld2lzZSB0aGlzIGlmIHN0YXRlbWVudCB3aWxsIG5vdCBydW4gaWYgbm8gcGFkZGVkIGdyb3Vwc1xuICAgICAgICAgICAgICAgIGlmIChmaXJzdFBhZGRlZEdyb3VwICYmIGN1cnJlbnRQYWRkZWRHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChmaXJzdFBhZGRlZEdyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhhc0dyb3VwcyA9IHVuYmFsYW5jZWRUcmVlLnNvbWUoZnVuY3Rpb24gKGxlYWYpIHsgcmV0dXJuIGxlYWYgaW5zdGFuY2VvZiBQcm92aWRlZENvbHVtbkdyb3VwOyB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGhhc0dyb3Vwcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudFBhZGRlZEdyb3VwLnNldENoaWxkcmVuKFtjaGlsZF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50UGFkZGVkR3JvdXAuc2V0Q2hpbGRyZW4odW5iYWxhbmNlZFRyZWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5maW5kTWF4RGVwdCA9IGZ1bmN0aW9uICh0cmVlQ2hpbGRyZW4sIGRlcHQpIHtcbiAgICAgICAgdmFyIG1heERlcHRUaGlzTGV2ZWwgPSBkZXB0O1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWVDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGFic3RyYWN0Q29sdW1uID0gdHJlZUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgaWYgKGFic3RyYWN0Q29sdW1uIGluc3RhbmNlb2YgUHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5hbEdyb3VwID0gYWJzdHJhY3RDb2x1bW47XG4gICAgICAgICAgICAgICAgdmFyIG5ld0RlcHQgPSB0aGlzLmZpbmRNYXhEZXB0KG9yaWdpbmFsR3JvdXAuZ2V0Q2hpbGRyZW4oKSwgZGVwdCArIDEpO1xuICAgICAgICAgICAgICAgIGlmIChtYXhEZXB0VGhpc0xldmVsIDwgbmV3RGVwdCkge1xuICAgICAgICAgICAgICAgICAgICBtYXhEZXB0VGhpc0xldmVsID0gbmV3RGVwdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1heERlcHRUaGlzTGV2ZWw7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5yZWN1cnNpdmVseUNyZWF0ZUNvbHVtbnMgPSBmdW5jdGlvbiAoZGVmcywgbGV2ZWwsIHByaW1hcnlDb2x1bW5zLCBleGlzdGluZ0NvbHNDb3B5LCBjb2x1bW5LZXlDcmVhdG9yLCBleGlzdGluZ0dyb3Vwcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gKGRlZnMgfHwgW10pLm1hcChmdW5jdGlvbiAoZGVmKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuaXNDb2x1bW5Hcm91cChkZWYpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmNyZWF0ZUNvbHVtbkdyb3VwKHByaW1hcnlDb2x1bW5zLCBkZWYsIGxldmVsLCBleGlzdGluZ0NvbHNDb3B5LCBjb2x1bW5LZXlDcmVhdG9yLCBleGlzdGluZ0dyb3Vwcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMuY3JlYXRlQ29sdW1uKHByaW1hcnlDb2x1bW5zLCBkZWYsIGV4aXN0aW5nQ29sc0NvcHksIGNvbHVtbktleUNyZWF0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbHVtbkZhY3RvcnkucHJvdG90eXBlLmNyZWF0ZUNvbHVtbkdyb3VwID0gZnVuY3Rpb24gKHByaW1hcnlDb2x1bW5zLCBjb2xHcm91cERlZiwgbGV2ZWwsIGV4aXN0aW5nQ29sdW1ucywgY29sdW1uS2V5Q3JlYXRvciwgZXhpc3RpbmdHcm91cHMpIHtcbiAgICAgICAgdmFyIGNvbEdyb3VwRGVmTWVyZ2VkID0gdGhpcy5jcmVhdGVNZXJnZWRDb2xHcm91cERlZihjb2xHcm91cERlZik7XG4gICAgICAgIHZhciBncm91cElkID0gY29sdW1uS2V5Q3JlYXRvci5nZXRVbmlxdWVLZXkoY29sR3JvdXBEZWZNZXJnZWQuZ3JvdXBJZCB8fCBudWxsLCBudWxsKTtcbiAgICAgICAgdmFyIHByb3ZpZGVkR3JvdXAgPSBuZXcgUHJvdmlkZWRDb2x1bW5Hcm91cChjb2xHcm91cERlZk1lcmdlZCwgZ3JvdXBJZCwgZmFsc2UsIGxldmVsKTtcbiAgICAgICAgdGhpcy5jb250ZXh0LmNyZWF0ZUJlYW4ocHJvdmlkZWRHcm91cCk7XG4gICAgICAgIHZhciBleGlzdGluZ0dyb3VwID0gdGhpcy5maW5kRXhpc3RpbmdHcm91cChjb2xHcm91cERlZiwgZXhpc3RpbmdHcm91cHMpO1xuICAgICAgICAvLyBtYWtlIHN1cmUgd2UgcmVtb3ZlLCBzbyBpZiB1c2VyIHByb3ZpZGVkIGR1cGxpY2F0ZSBpZCwgdGhlbiB3ZSBkb24ndCBoYXZlIG1vcmUgdGhhblxuICAgICAgICAvLyBvbmUgY29sdW1uIGluc3RhbmNlIGZvciBjb2xEZWYgd2l0aCBjb21tb24gaWRcbiAgICAgICAgaWYgKGV4aXN0aW5nR3JvdXApIHtcbiAgICAgICAgICAgIHJlbW92ZUZyb21BcnJheShleGlzdGluZ0dyb3VwcywgZXhpc3RpbmdHcm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4aXN0aW5nR3JvdXAgJiYgZXhpc3RpbmdHcm91cC5pc0V4cGFuZGVkKCkpIHtcbiAgICAgICAgICAgIHByb3ZpZGVkR3JvdXAuc2V0RXhwYW5kZWQodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNoaWxkcmVuID0gdGhpcy5yZWN1cnNpdmVseUNyZWF0ZUNvbHVtbnMoY29sR3JvdXBEZWZNZXJnZWQuY2hpbGRyZW4sIGxldmVsICsgMSwgcHJpbWFyeUNvbHVtbnMsIGV4aXN0aW5nQ29sdW1ucywgY29sdW1uS2V5Q3JlYXRvciwgZXhpc3RpbmdHcm91cHMpO1xuICAgICAgICBwcm92aWRlZEdyb3VwLnNldENoaWxkcmVuKGNoaWxkcmVuKTtcbiAgICAgICAgcmV0dXJuIHByb3ZpZGVkR3JvdXA7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5jcmVhdGVNZXJnZWRDb2xHcm91cERlZiA9IGZ1bmN0aW9uIChjb2xHcm91cERlZikge1xuICAgICAgICB2YXIgY29sR3JvdXBEZWZNZXJnZWQgPSB7fTtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihjb2xHcm91cERlZk1lcmdlZCwgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RGVmYXVsdENvbEdyb3VwRGVmKCkpO1xuICAgICAgICBPYmplY3QuYXNzaWduKGNvbEdyb3VwRGVmTWVyZ2VkLCBjb2xHcm91cERlZik7XG4gICAgICAgIHRoaXMuY2hlY2tGb3JEZXByZWNhdGVkSXRlbXMoY29sR3JvdXBEZWZNZXJnZWQpO1xuICAgICAgICByZXR1cm4gY29sR3JvdXBEZWZNZXJnZWQ7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5jcmVhdGVDb2x1bW4gPSBmdW5jdGlvbiAocHJpbWFyeUNvbHVtbnMsIGNvbERlZiwgZXhpc3RpbmdDb2xzQ29weSwgY29sdW1uS2V5Q3JlYXRvcikge1xuICAgICAgICB2YXIgY29sRGVmTWVyZ2VkID0gdGhpcy5tZXJnZUNvbERlZnMoY29sRGVmKTtcbiAgICAgICAgdGhpcy5jaGVja0ZvckRlcHJlY2F0ZWRJdGVtcyhjb2xEZWZNZXJnZWQpO1xuICAgICAgICAvLyBzZWUgaWYgY29sdW1uIGFscmVhZHkgZXhpc3RzXG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmZpbmRFeGlzdGluZ0NvbHVtbihjb2xEZWYsIGV4aXN0aW5nQ29sc0NvcHkpO1xuICAgICAgICAvLyBtYWtlIHN1cmUgd2UgcmVtb3ZlLCBzbyBpZiB1c2VyIHByb3ZpZGVkIGR1cGxpY2F0ZSBpZCwgdGhlbiB3ZSBkb24ndCBoYXZlIG1vcmUgdGhhblxuICAgICAgICAvLyBvbmUgY29sdW1uIGluc3RhbmNlIGZvciBjb2xEZWYgd2l0aCBjb21tb24gaWRcbiAgICAgICAgaWYgKGV4aXN0aW5nQ29sc0NvcHkgJiYgY29sdW1uKSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkoZXhpc3RpbmdDb2xzQ29weSwgY29sdW1uKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgLy8gbm8gZXhpc3RpbmcgY29sdW1uLCBuZWVkIHRvIGNyZWF0ZSBvbmVcbiAgICAgICAgICAgIHZhciBjb2xJZCA9IGNvbHVtbktleUNyZWF0b3IuZ2V0VW5pcXVlS2V5KGNvbERlZk1lcmdlZC5jb2xJZCwgY29sRGVmTWVyZ2VkLmZpZWxkKTtcbiAgICAgICAgICAgIGNvbHVtbiA9IG5ldyBDb2x1bW4oY29sRGVmTWVyZ2VkLCBjb2xEZWYsIGNvbElkLCBwcmltYXJ5Q29sdW1ucyk7XG4gICAgICAgICAgICB0aGlzLmNvbnRleHQuY3JlYXRlQmVhbihjb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29sdW1uLnNldENvbERlZihjb2xEZWZNZXJnZWQsIGNvbERlZik7XG4gICAgICAgICAgICB0aGlzLmFwcGx5Q29sdW1uU3RhdGUoY29sdW1uLCBjb2xEZWZNZXJnZWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2x1bW47XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5hcHBseUNvbHVtblN0YXRlID0gZnVuY3Rpb24gKGNvbHVtbiwgY29sRGVmKSB7XG4gICAgICAgIC8vIGZsZXhcbiAgICAgICAgdmFyIGZsZXggPSBhdHRyVG9OdW1iZXIoY29sRGVmLmZsZXgpO1xuICAgICAgICBpZiAoZmxleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb2x1bW4uc2V0RmxleChmbGV4KTtcbiAgICAgICAgfVxuICAgICAgICAvLyB3aWR0aCAtIHdlIG9ubHkgc2V0IHdpZHRoIGlmIGNvbHVtbiBpcyBub3QgZmxleGluZ1xuICAgICAgICB2YXIgbm9GbGV4VGhpc0NvbCA9IGNvbHVtbi5nZXRGbGV4KCkgPD0gMDtcbiAgICAgICAgaWYgKG5vRmxleFRoaXNDb2wpIHtcbiAgICAgICAgICAgIC8vIGJvdGggbnVsbCBhbmQgdW5kZWZpbmVkIG1lYW5zIHdlIHNraXAsIGFzIGl0J3Mgbm90IHBvc3NpYmxlIHRvICdjbGVhcicgd2lkdGggKGEgY29sdW1uIG11c3QgaGF2ZSBhIHdpZHRoKVxuICAgICAgICAgICAgdmFyIHdpZHRoID0gYXR0clRvTnVtYmVyKGNvbERlZi53aWR0aCk7XG4gICAgICAgICAgICBpZiAod2lkdGggIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbHVtbi5zZXRBY3R1YWxXaWR0aCh3aWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2Ugc2V0IHRoZSB3aWR0aCBhZ2FpbiwgaW4gY2FzZSBtaW4gb3IgbWF4IHdpZHRoIGhhcyBjaGFuZ2VkLFxuICAgICAgICAgICAgICAgIC8vIGFuZCB3aWR0aCBuZWVkcyB0byBiZSBhZGp1c3RlZC5cbiAgICAgICAgICAgICAgICB2YXIgd2lkdGhCZWZvcmVVcGRhdGUgPSBjb2x1bW4uZ2V0QWN0dWFsV2lkdGgoKTtcbiAgICAgICAgICAgICAgICBjb2x1bW4uc2V0QWN0dWFsV2lkdGgod2lkdGhCZWZvcmVVcGRhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHNvcnQgLSBhbnl0aGluZyBidXQgdW5kZWZpbmVkIHdpbGwgc2V0IHNvcnQsIHRodXMgbnVsbCBvciBlbXB0eSBzdHJpbmcgd2lsbCBjbGVhciB0aGUgc29ydFxuICAgICAgICBpZiAoY29sRGVmLnNvcnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGNvbERlZi5zb3J0ID09IENvbnN0YW50cy5TT1JUX0FTQyB8fCBjb2xEZWYuc29ydCA9PSBDb25zdGFudHMuU09SVF9ERVNDKSB7XG4gICAgICAgICAgICAgICAgY29sdW1uLnNldFNvcnQoY29sRGVmLnNvcnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29sdW1uLnNldFNvcnQodW5kZWZpbmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBzb3J0ZWQgYXQgLSBhbnl0aGluZyBidXQgdW5kZWZpbmVkLCB0aHVzIG51bGwgd2lsbCBjbGVhciB0aGUgc29ydEluZGV4XG4gICAgICAgIHZhciBzb3J0SW5kZXggPSBhdHRyVG9OdW1iZXIoY29sRGVmLnNvcnRJbmRleCk7XG4gICAgICAgIGlmIChzb3J0SW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29sdW1uLnNldFNvcnRJbmRleChzb3J0SW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGhpZGUgLSBhbnl0aGluZyBidXQgdW5kZWZpbmVkLCB0aHVzIG51bGwgd2lsbCBjbGVhciB0aGUgaGlkZVxuICAgICAgICB2YXIgaGlkZSA9IGF0dHJUb0Jvb2xlYW4oY29sRGVmLmhpZGUpO1xuICAgICAgICBpZiAoaGlkZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb2x1bW4uc2V0VmlzaWJsZSghaGlkZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcGlubmVkIC0gYW55dGhpbmcgYnV0IHVuZGVmaW5lZCwgdGh1cyBudWxsIG9yIGVtcHR5IHN0cmluZyB3aWxsIHJlbW92ZSBwaW5uZWRcbiAgICAgICAgaWYgKGNvbERlZi5waW5uZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29sdW1uLnNldFBpbm5lZChjb2xEZWYucGlubmVkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uRmFjdG9yeS5wcm90b3R5cGUuZmluZEV4aXN0aW5nQ29sdW1uID0gZnVuY3Rpb24gKG5ld0NvbERlZiwgZXhpc3RpbmdDb2xzQ29weSkge1xuICAgICAgICByZXR1cm4gKGV4aXN0aW5nQ29sc0NvcHkgfHwgW10pLmZpbmQoZnVuY3Rpb24gKGV4aXN0aW5nQ29sKSB7XG4gICAgICAgICAgICB2YXIgZXhpc3RpbmdDb2xEZWYgPSBleGlzdGluZ0NvbC5nZXRVc2VyUHJvdmlkZWRDb2xEZWYoKTtcbiAgICAgICAgICAgIGlmICghZXhpc3RpbmdDb2xEZWYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbmV3SGFzSWQgPSBuZXdDb2xEZWYuY29sSWQgIT0gbnVsbDtcbiAgICAgICAgICAgIHZhciBuZXdIYXNGaWVsZCA9IG5ld0NvbERlZi5maWVsZCAhPSBudWxsO1xuICAgICAgICAgICAgaWYgKG5ld0hhc0lkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4aXN0aW5nQ29sLmdldElkKCkgPT09IG5ld0NvbERlZi5jb2xJZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuZXdIYXNGaWVsZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBleGlzdGluZ0NvbERlZi5maWVsZCA9PT0gbmV3Q29sRGVmLmZpZWxkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgbm8gaWQgb3IgZmllbGQgcHJlc2VudCwgdGhlbiB0cnkgb2JqZWN0IGVxdWl2YWxlbmNlLlxuICAgICAgICAgICAgaWYgKGV4aXN0aW5nQ29sRGVmID09PSBuZXdDb2xEZWYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5maW5kRXhpc3RpbmdHcm91cCA9IGZ1bmN0aW9uIChuZXdHcm91cERlZiwgZXhpc3RpbmdHcm91cHMpIHtcbiAgICAgICAgcmV0dXJuIGV4aXN0aW5nR3JvdXBzLmZpbmQoZnVuY3Rpb24gKGV4aXN0aW5nR3JvdXApIHtcbiAgICAgICAgICAgIHZhciBleGlzdGluZ0RlZiA9IGV4aXN0aW5nR3JvdXAuZ2V0Q29sR3JvdXBEZWYoKTtcbiAgICAgICAgICAgIGlmICghZXhpc3RpbmdEZWYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbmV3SGFzSWQgPSBuZXdHcm91cERlZi5ncm91cElkICE9IG51bGw7XG4gICAgICAgICAgICBpZiAobmV3SGFzSWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXhpc3RpbmdHcm91cC5nZXRJZCgpID09PSBuZXdHcm91cERlZi5ncm91cElkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbHVtbkZhY3RvcnkucHJvdG90eXBlLm1lcmdlQ29sRGVmcyA9IGZ1bmN0aW9uIChjb2xEZWYpIHtcbiAgICAgICAgLy8gc3RhcnQgd2l0aCBlbXB0eSBtZXJnZWQgZGVmaW5pdGlvblxuICAgICAgICB2YXIgY29sRGVmTWVyZ2VkID0ge307XG4gICAgICAgIC8vIG1lcmdlIHByb3BlcnRpZXMgZnJvbSBkZWZhdWx0IGNvbHVtbiBkZWZpbml0aW9uc1xuICAgICAgICB2YXIgZGVmYXVsdENvbERlZiA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERlZmF1bHRDb2xEZWYoKTtcbiAgICAgICAgbWVyZ2VEZWVwKGNvbERlZk1lcmdlZCwgZGVmYXVsdENvbERlZiwgZmFsc2UsIHRydWUpO1xuICAgICAgICAvLyBtZXJnZSBwcm9wZXJ0aWVzIGZyb20gY29sdW1uIHR5cGUgcHJvcGVydGllc1xuICAgICAgICB2YXIgY29sdW1uVHlwZSA9IGNvbERlZi50eXBlO1xuICAgICAgICBpZiAoIWNvbHVtblR5cGUpIHtcbiAgICAgICAgICAgIGNvbHVtblR5cGUgPSBkZWZhdWx0Q29sRGVmICYmIGRlZmF1bHRDb2xEZWYudHlwZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0eXBlIG9mIGJvdGggY29sRGVmIGFuZCBkZWZhdWx0Q29sRGVmLCB0aGVuIGNvbERlZiBnZXRzIHByZWZlcmVuY2VcbiAgICAgICAgaWYgKGNvbHVtblR5cGUpIHtcbiAgICAgICAgICAgIHRoaXMuYXNzaWduQ29sdW1uVHlwZXMoY29sdW1uVHlwZSwgY29sRGVmTWVyZ2VkKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBtZXJnZSBwcm9wZXJ0aWVzIGZyb20gY29sdW1uIGRlZmluaXRpb25zXG4gICAgICAgIG1lcmdlRGVlcChjb2xEZWZNZXJnZWQsIGNvbERlZiwgZmFsc2UsIHRydWUpO1xuICAgICAgICB2YXIgYXV0b0dyb3VwQ29sRGVmID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXV0b0dyb3VwQ29sdW1uRGVmKCk7XG4gICAgICAgIHZhciBpc1NvcnRpbmdDb3VwbGVkID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNDb2x1bW5zU29ydGluZ0NvdXBsZWRUb0dyb3VwKCk7XG4gICAgICAgIGlmIChjb2xEZWYucm93R3JvdXAgJiYgYXV0b0dyb3VwQ29sRGVmICYmIGlzU29ydGluZ0NvdXBsZWQpIHtcbiAgICAgICAgICAgIC8vIG92ZXJyaWRlIHRoZSBzb3J0IGZvciByb3cgZ3JvdXAgY29sdW1ucyB3aGVyZSB0aGUgYXV0b0dyb3VwQ29sRGVmIGRlZmluZXMgdGhlc2UgdmFsdWVzLlxuICAgICAgICAgICAgbWVyZ2VEZWVwKGNvbERlZk1lcmdlZCwgeyBzb3J0OiBhdXRvR3JvdXBDb2xEZWYuc29ydCwgaW5pdGlhbFNvcnQ6IGF1dG9Hcm91cENvbERlZi5pbml0aWFsU29ydCB9LCBmYWxzZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbERlZk1lcmdlZDtcbiAgICB9O1xuICAgIENvbHVtbkZhY3RvcnkucHJvdG90eXBlLmFzc2lnbkNvbHVtblR5cGVzID0gZnVuY3Rpb24gKHR5cGUsIGNvbERlZk1lcmdlZCkge1xuICAgICAgICB2YXIgdHlwZUtleXMgPSBbXTtcbiAgICAgICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgdmFyIGludmFsaWRBcnJheSA9IHR5cGUuc29tZShmdW5jdGlvbiAoYSkgeyByZXR1cm4gdHlwZW9mIGEgIT09ICdzdHJpbmcnOyB9KTtcbiAgICAgICAgICAgIGlmIChpbnZhbGlkQXJyYXkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBpZiBjb2xEZWYudHlwZSBpcyBzdXBwbGllZCBhbiBhcnJheSBpdCBzaG91bGQgYmUgb2YgdHlwZSAnc3RyaW5nW10nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdHlwZUtleXMgPSB0eXBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdHlwZUtleXMgPSB0eXBlLnNwbGl0KCcsJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBjb2xEZWYudHlwZSBzaG91bGQgYmUgb2YgdHlwZSAnc3RyaW5nJyB8ICdzdHJpbmdbXSdcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gbWVyZ2UgdXNlciBkZWZpbmVkIHdpdGggZGVmYXVsdCBjb2x1bW4gdHlwZXNcbiAgICAgICAgdmFyIGFsbENvbHVtblR5cGVzID0gT2JqZWN0LmFzc2lnbih7fSwgRGVmYXVsdENvbHVtblR5cGVzKTtcbiAgICAgICAgdmFyIHVzZXJUeXBlcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtblR5cGVzKCkgfHwge307XG4gICAgICAgIGl0ZXJhdGVPYmplY3QodXNlclR5cGVzLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgaWYgKGtleSBpbiBhbGxDb2x1bW5UeXBlcykge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHRoZSBjb2x1bW4gdHlwZSAnXCIgKyBrZXkgKyBcIicgaXMgYSBkZWZhdWx0IGNvbHVtbiB0eXBlIGFuZCBjYW5ub3QgYmUgb3ZlcnJpZGRlbi5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbGxDb2x1bW5UeXBlc1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0eXBlS2V5cy5mb3JFYWNoKGZ1bmN0aW9uICh0KSB7XG4gICAgICAgICAgICB2YXIgdHlwZUNvbERlZiA9IGFsbENvbHVtblR5cGVzW3QudHJpbSgpXTtcbiAgICAgICAgICAgIGlmICh0eXBlQ29sRGVmKSB7XG4gICAgICAgICAgICAgICAgbWVyZ2VEZWVwKGNvbERlZk1lcmdlZCwgdHlwZUNvbERlZiwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogY29sRGVmLnR5cGUgJ1wiICsgdCArIFwiJyBkb2VzIG5vdCBjb3JyZXNwb25kIHRvIGRlZmluZWQgZ3JpZE9wdGlvbnMuY29sdW1uVHlwZXNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uRmFjdG9yeS5wcm90b3R5cGUuY2hlY2tGb3JEZXByZWNhdGVkSXRlbXMgPSBmdW5jdGlvbiAoY29sRGVmKSB7XG4gICAgICAgIGlmIChjb2xEZWYpIHtcbiAgICAgICAgICAgIHZhciBjb2xEZWZOb1R5cGUgPSBjb2xEZWY7IC8vIHRha2Ugb3V0IHRoZSB0eXBlLCBzbyB3ZSBjYW4gYWNjZXNzIGF0dHJpYnV0ZXMgbm90IGRlZmluZWQgaW4gdGhlIHR5cGVcbiAgICAgICAgICAgIGlmIChjb2xEZWZOb1R5cGUuZ3JvdXAgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY29sRGVmLmdyb3VwIGlzIGludmFsaWQsIHBsZWFzZSBjaGVjayBkb2N1bWVudGF0aW9uIG9uIGhvdyB0byBkbyBncm91cGluZyBhcyBpdCBjaGFuZ2VkIGluIHZlcnNpb24gMycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbERlZk5vVHlwZS5oZWFkZXJHcm91cCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjb2xEZWYuaGVhZGVyR3JvdXAgaXMgaW52YWxpZCwgcGxlYXNlIGNoZWNrIGRvY3VtZW50YXRpb24gb24gaG93IHRvIGRvIGdyb3VwaW5nIGFzIGl0IGNoYW5nZWQgaW4gdmVyc2lvbiAzJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29sRGVmTm9UeXBlLmhlYWRlckdyb3VwU2hvdyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjb2xEZWYuaGVhZGVyR3JvdXBTaG93IGlzIGludmFsaWQsIHNob3VsZCBiZSBjb2x1bW5Hcm91cFNob3csIHBsZWFzZSBjaGVjayBkb2N1bWVudGF0aW9uIG9uIGhvdyB0byBkbyBncm91cGluZyBhcyBpdCBjaGFuZ2VkIGluIHZlcnNpb24gMycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbERlZk5vVHlwZS5zdXBwcmVzc1Jvd0dyb3VwICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGNvbERlZi5zdXBwcmVzc1Jvd0dyb3VwIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgY29sRGVmLnR5cGUgaW5zdGVhZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbERlZk5vVHlwZS5zdXBwcmVzc0FnZ3JlZ2F0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGNvbERlZi5zdXBwcmVzc0FnZ3JlZ2F0aW9uIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgY29sRGVmLnR5cGUgaW5zdGVhZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbERlZk5vVHlwZS5zdXBwcmVzc1Jvd0dyb3VwIHx8IGNvbERlZk5vVHlwZS5zdXBwcmVzc0FnZ3JlZ2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjb2xEZWYuc3VwcHJlc3NBZ2dyZWdhdGlvbiBhbmQgY29sRGVmLnN1cHByZXNzUm93R3JvdXAgYXJlIGRlcHJlY2F0ZWQsIHVzZSBhbGxvd1Jvd0dyb3VwLCBhbGxvd1Bpdm90IGFuZCBhbGxvd1ZhbHVlIGluc3RlYWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2xEZWZOb1R5cGUuZGlzcGxheU5hbWUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBGb3VuZCBkaXNwbGF5TmFtZSBcIiArIGNvbERlZk5vVHlwZS5kaXNwbGF5TmFtZSArIFwiLCBwbGVhc2UgdXNlIGhlYWRlck5hbWUgaW5zdGVhZCwgZGlzcGxheU5hbWUgaXMgZGVwcmVjYXRlZC5cIik7XG4gICAgICAgICAgICAgICAgY29sRGVmTm9UeXBlLmhlYWRlck5hbWUgPSBjb2xEZWZOb1R5cGUuZGlzcGxheU5hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGlmIG9iamVjdCBoYXMgY2hpbGRyZW4sIHdlIGFzc3VtZSBpdCdzIGEgZ3JvdXBcbiAgICBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZS5pc0NvbHVtbkdyb3VwID0gZnVuY3Rpb24gKGFic3RyYWN0Q29sRGVmKSB7XG4gICAgICAgIHJldHVybiBhYnN0cmFjdENvbERlZi5jaGlsZHJlbiAhPT0gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQydyhbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uVXRpbHMnKVxuICAgIF0sIENvbHVtbkZhY3RvcnkucHJvdG90eXBlLCBcImNvbHVtblV0aWxzXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydyhbXG4gICAgICAgIF9fcGFyYW0kOSgwLCBRdWFsaWZpZXIoJ2xvZ2dlckZhY3RvcnknKSlcbiAgICBdLCBDb2x1bW5GYWN0b3J5LnByb3RvdHlwZSwgXCJzZXRCZWFuc1wiLCBudWxsKTtcbiAgICBDb2x1bW5GYWN0b3J5ID0gX19kZWNvcmF0ZSQydyhbXG4gICAgICAgIEJlYW4oJ2NvbHVtbkZhY3RvcnknKVxuICAgIF0sIENvbHVtbkZhY3RvcnkpO1xuICAgIHJldHVybiBDb2x1bW5GYWN0b3J5O1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgRXZlbnRzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEV2ZW50cygpIHtcbiAgICB9XG4gICAgLyoqIEV2ZXJ5dGhpbmcgaGFzIGNoYW5nZWQgd2l0aCB0aGUgY29sdW1ucy4gRWl0aGVyIGNvbXBsZXRlIG5ldyBzZXQgb2YgY29sdW1ucyBzZXQsIG9yIHVzZXIgY2FsbGVkIHNldFN0YXRlKCkgKi9cbiAgICAvKiogQGRlcHJlY2F0ZWQgLSBncmlkIG5vIGxvbmdlciB1c2VzIHRoaXMsIGFuZCBzZXRTYXRlKCkgYWxzbyBmaXJlcyBpbmRpdmlkdWFsIGV2ZW50cyAqL1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fRVZFUllUSElOR19DSEFOR0VEID0gJ2NvbHVtbkV2ZXJ5dGhpbmdDaGFuZ2VkJztcbiAgICAvKiogVXNlciBoYXMgc2V0IGluIG5ldyBjb2x1bW5zLiAqL1xuICAgIEV2ZW50cy5FVkVOVF9ORVdfQ09MVU1OU19MT0FERUQgPSAnbmV3Q29sdW1uc0xvYWRlZCc7XG4gICAgLyoqIFRoZSBwaXZvdCBtb2RlIGZsYWcgd2FzIGNoYW5nZWQgKi9cbiAgICBFdmVudHMuRVZFTlRfQ09MVU1OX1BJVk9UX01PREVfQ0hBTkdFRCA9ICdjb2x1bW5QaXZvdE1vZGVDaGFuZ2VkJztcbiAgICAvKiogQSByb3cgZ3JvdXAgY29sdW1uIHdhcyBhZGRlZCwgcmVtb3ZlZCBvciBvcmRlciBjaGFuZ2VkLiAqL1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQgPSAnY29sdW1uUm93R3JvdXBDaGFuZ2VkJztcbiAgICAvKiogZXhwYW5kQWxsIC8gY29sbGFwc2VBbGwgd2FzIGNhbGxlZCBmcm9tIHRoZSBhcGkuICovXG4gICAgRXZlbnRzLkVWRU5UX0VYUEFORF9DT0xMQVBTRV9BTEwgPSAnZXhwYW5kT3JDb2xsYXBzZUFsbCc7XG4gICAgLyoqIEEgcGl2b3QgY29sdW1uIHdhcyBhZGRlZCwgcmVtb3ZlZCBvciBvcmRlciBjaGFuZ2VkLiAqL1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUElWT1RfQ0hBTkdFRCA9ICdjb2x1bW5QaXZvdENoYW5nZWQnO1xuICAgIC8qKiBUaGUgbGlzdCBvZiBncmlkIGNvbHVtbnMgaGFzIGNoYW5nZWQuICovXG4gICAgRXZlbnRzLkVWRU5UX0dSSURfQ09MVU1OU19DSEFOR0VEID0gJ2dyaWRDb2x1bW5zQ2hhbmdlZCc7XG4gICAgLyoqIEEgdmFsdWUgY29sdW1uIHdhcyBhZGRlZCwgcmVtb3ZlZCBvciBhZ2cgZnVuY3Rpb24gd2FzIGNoYW5nZWQuICovXG4gICAgRXZlbnRzLkVWRU5UX0NPTFVNTl9WQUxVRV9DSEFOR0VEID0gJ2NvbHVtblZhbHVlQ2hhbmdlZCc7XG4gICAgLyoqIEEgY29sdW1uIHdhcyBtb3ZlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQgPSAnY29sdW1uTW92ZWQnO1xuICAgIC8qKiBPbmUgb3IgbW9yZSBjb2x1bW5zIHdhcyBzaG93biAvIGhpZGRlbiAqL1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fVklTSUJMRSA9ICdjb2x1bW5WaXNpYmxlJztcbiAgICAvKiogT25lIG9yIG1vcmUgY29sdW1ucyB3YXMgcGlubmVkIC8gdW5waW5uZWQqL1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUElOTkVEID0gJ2NvbHVtblBpbm5lZCc7XG4gICAgLyoqIEEgY29sdW1uIGdyb3VwIHdhcyBvcGVuZWQgLyBjbG9zZWQgKi9cbiAgICBFdmVudHMuRVZFTlRfQ09MVU1OX0dST1VQX09QRU5FRCA9ICdjb2x1bW5Hcm91cE9wZW5lZCc7XG4gICAgLyoqIE9uZSBvciBtb3JlIGNvbHVtbnMgd2FzIHJlc2l6ZWQuIElmIGp1c3Qgb25lLCB0aGUgY29sdW1uIGluIHRoZSBldmVudCBpcyBzZXQuICovXG4gICAgRXZlbnRzLkVWRU5UX0NPTFVNTl9SRVNJWkVEID0gJ2NvbHVtblJlc2l6ZWQnO1xuICAgIC8qKiBUaGUgbGlzdCBvZiBkaXNwbGF5ZWQgY29sdW1ucyBoYXMgY2hhbmdlZCwgY2FuIHJlc3VsdCBmcm9tIGNvbHVtbnMgb3BlbiAvIGNsb3NlLCBjb2x1bW4gbW92ZSwgcGl2b3QsIGdyb3VwLCBldGMgKi9cbiAgICBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfQ0hBTkdFRCA9ICdkaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCc7XG4gICAgLyoqIFRoZSBsaXN0IG9mIHZpcnR1YWwgY29sdW1ucyBoYXMgY2hhbmdlZCwgcmVzdWx0cyBmcm9tIHZpZXdwb3J0IGNoYW5naW5nICovXG4gICAgRXZlbnRzLkVWRU5UX1ZJUlRVQUxfQ09MVU1OU19DSEFOR0VEID0gJ3ZpcnR1YWxDb2x1bW5zQ2hhbmdlZCc7XG4gICAgLyoqIEFzeW5jIFRyYW5zYWN0aW9ucyBFeGVjdXRlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9BU1lOQ19UUkFOU0FDVElPTlNfRkxVU0hFRCA9ICdhc3luY1RyYW5zYWN0aW9uc0ZsdXNoZWQnO1xuICAgIC8qKiBBIHJvdyBncm91cCB3YXMgb3BlbmVkIC8gY2xvc2VkICovXG4gICAgRXZlbnRzLkVWRU5UX1JPV19HUk9VUF9PUEVORUQgPSAncm93R3JvdXBPcGVuZWQnO1xuICAgIC8qKiBAZGVwcmVjYXRlZCB1c2UgRVZFTlRfUk9XX0RBVEFfVVBEQVRFRCBpbnN0ZWFkICovXG4gICAgRXZlbnRzLkVWRU5UX1JPV19EQVRBX0NIQU5HRUQgPSAncm93RGF0YUNoYW5nZWQnO1xuICAgIC8qKiBUaGUgY2xpZW50IGhhcyB1cGRhdGVkIGRhdGEgZm9yIHRoZSBncmlkICovXG4gICAgRXZlbnRzLkVWRU5UX1JPV19EQVRBX1VQREFURUQgPSAncm93RGF0YVVwZGF0ZWQnO1xuICAgIC8qKiBUaGUgY2xpZW50IGhhcyBzZXQgbmV3IGZsb2F0aW5nIGRhdGEgaW50byB0aGUgZ3JpZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9QSU5ORURfUk9XX0RBVEFfQ0hBTkdFRCA9ICdwaW5uZWRSb3dEYXRhQ2hhbmdlZCc7XG4gICAgLyoqIFJhbmdlIHNlbGVjdGlvbiBoYXMgY2hhbmdlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9SQU5HRV9TRUxFQ1RJT05fQ0hBTkdFRCA9ICdyYW5nZVNlbGVjdGlvbkNoYW5nZWQnO1xuICAgIC8qKiBDaGFydCB3YXMgY3JlYXRlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9DSEFSVF9DUkVBVEVEID0gJ2NoYXJ0Q3JlYXRlZCc7XG4gICAgLyoqIENoYXJ0IFJhbmdlIHNlbGVjdGlvbiBoYXMgY2hhbmdlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9DSEFSVF9SQU5HRV9TRUxFQ1RJT05fQ0hBTkdFRCA9ICdjaGFydFJhbmdlU2VsZWN0aW9uQ2hhbmdlZCc7XG4gICAgLyoqIENoYXJ0IE9wdGlvbnMgaGF2ZSBjaGFuZ2VkICovXG4gICAgRXZlbnRzLkVWRU5UX0NIQVJUX09QVElPTlNfQ0hBTkdFRCA9ICdjaGFydE9wdGlvbnNDaGFuZ2VkJztcbiAgICAvKiogQ2hhcnQgd2FzIGRlc3Ryb3llZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9DSEFSVF9ERVNUUk9ZRUQgPSAnY2hhcnREZXN0cm95ZWQnO1xuICAgIC8qKiBGb3Igd2hlbiB0aGUgdG9vbCBwYW5lbCBpcyBzaG93biAvIGhpZGRlbiAqL1xuICAgIEV2ZW50cy5FVkVOVF9UT09MX1BBTkVMX1ZJU0lCTEVfQ0hBTkdFRCA9ICd0b29sUGFuZWxWaXNpYmxlQ2hhbmdlZCc7XG4gICAgRXZlbnRzLkVWRU5UX1RPT0xfUEFORUxfU0laRV9DSEFOR0VEID0gJ3Rvb2xQYW5lbFNpemVDaGFuZ2VkJztcbiAgICBFdmVudHMuRVZFTlRfQ09MVU1OX1BBTkVMX0lURU1fRFJBR19TVEFSVCA9ICdjb2x1bW5QYW5lbEl0ZW1EcmFnU3RhcnQnO1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUEFORUxfSVRFTV9EUkFHX0VORCA9ICdjb2x1bW5QYW5lbEl0ZW1EcmFnRW5kJztcbiAgICAvKiogTW9kZWwgd2FzIHVwZGF0ZWQgLSBncmlkIHVwZGF0ZXMgdGhlIGRyYXduIHJvd3Mgd2hlbiB0aGlzIGhhcHBlbnMgKi9cbiAgICBFdmVudHMuRVZFTlRfTU9ERUxfVVBEQVRFRCA9ICdtb2RlbFVwZGF0ZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9QQVNURV9TVEFSVCA9ICdwYXN0ZVN0YXJ0JztcbiAgICBFdmVudHMuRVZFTlRfUEFTVEVfRU5EID0gJ3Bhc3RlRW5kJztcbiAgICBFdmVudHMuRVZFTlRfRklMTF9TVEFSVCA9ICdmaWxsU3RhcnQnO1xuICAgIEV2ZW50cy5FVkVOVF9GSUxMX0VORCA9ICdmaWxsRW5kJztcbiAgICBFdmVudHMuRVZFTlRfS0VZX1NIT1JUQ1VUX0NIQU5HRURfQ0VMTF9TVEFSVCA9ICdrZXlTaG9ydGN1dENoYW5nZWRDZWxsU3RhcnQnO1xuICAgIEV2ZW50cy5FVkVOVF9LRVlfU0hPUlRDVVRfQ0hBTkdFRF9DRUxMX0VORCA9ICdrZXlTaG9ydGN1dENoYW5nZWRDZWxsRW5kJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9DTElDS0VEID0gJ2NlbGxDbGlja2VkJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9ET1VCTEVfQ0xJQ0tFRCA9ICdjZWxsRG91YmxlQ2xpY2tlZCc7XG4gICAgRXZlbnRzLkVWRU5UX0NFTExfTU9VU0VfRE9XTiA9ICdjZWxsTW91c2VEb3duJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9DT05URVhUX01FTlUgPSAnY2VsbENvbnRleHRNZW51JztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9WQUxVRV9DSEFOR0VEID0gJ2NlbGxWYWx1ZUNoYW5nZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9DRUxMX0VESVRfUkVRVUVTVCA9ICdjZWxsRWRpdFJlcXVlc3QnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfVkFMVUVfQ0hBTkdFRCA9ICdyb3dWYWx1ZUNoYW5nZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9DRUxMX0ZPQ1VTRUQgPSAnY2VsbEZvY3VzZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9GVUxMX1dJRFRIX1JPV19GT0NVU0VEID0gJ2Z1bGxXaWR0aFJvd0ZvY3VzZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfU0VMRUNURUQgPSAncm93U2VsZWN0ZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9TRUxFQ1RJT05fQ0hBTkdFRCA9ICdzZWxlY3Rpb25DaGFuZ2VkJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9LRVlfRE9XTiA9ICdjZWxsS2V5RG93bic7XG4gICAgRXZlbnRzLkVWRU5UX0NFTExfS0VZX1BSRVNTID0gJ2NlbGxLZXlQcmVzcyc7XG4gICAgRXZlbnRzLkVWRU5UX0NFTExfTU9VU0VfT1ZFUiA9ICdjZWxsTW91c2VPdmVyJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9NT1VTRV9PVVQgPSAnY2VsbE1vdXNlT3V0JztcbiAgICAvKiogMiBldmVudHMgZm9yIGZpbHRlcmluZy4gVGhlIGdyaWQgTElTVEVOUyBmb3IgZmlsdGVyQ2hhbmdlZCBhbmQgYWZ0ZXJGaWx0ZXJDaGFuZ2VkICovXG4gICAgRXZlbnRzLkVWRU5UX0ZJTFRFUl9DSEFOR0VEID0gJ2ZpbHRlckNoYW5nZWQnO1xuICAgIC8qKiBGaWx0ZXIgd2FzIGNoYW5nZSBidXQgbm90IGFwcGxpZWQuIE9ubHkgdXNlZnVsIGlmIGFwcGx5IGJ1dHRvbnMgYXJlIHVzZWQgaW4gZmlsdGVycy4gKi9cbiAgICBFdmVudHMuRVZFTlRfRklMVEVSX01PRElGSUVEID0gJ2ZpbHRlck1vZGlmaWVkJztcbiAgICBFdmVudHMuRVZFTlRfRklMVEVSX09QRU5FRCA9ICdmaWx0ZXJPcGVuZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9TT1JUX0NIQU5HRUQgPSAnc29ydENoYW5nZWQnO1xuICAgIC8qKiBBIHJvdyB3YXMgcmVtb3ZlZCBmcm9tIHRoZSBkb20sIGZvciBhbnkgcmVhc29uLiBVc2UgdG8gY2xlYW4gdXAgcmVzb3VyY2VzIChpZiBhbnkpIHVzZWQgYnkgdGhlIHJvdy4gKi9cbiAgICBFdmVudHMuRVZFTlRfVklSVFVBTF9ST1dfUkVNT1ZFRCA9ICd2aXJ0dWFsUm93UmVtb3ZlZCc7XG4gICAgRXZlbnRzLkVWRU5UX1JPV19DTElDS0VEID0gJ3Jvd0NsaWNrZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfRE9VQkxFX0NMSUNLRUQgPSAncm93RG91YmxlQ2xpY2tlZCc7XG4gICAgLyoqIEdldHMgY2FsbGVkIG9uY2UgYWZ0ZXIgdGhlIGdyaWQgaGFzIGZpbmlzaGVkIGluaXRpYWxpc2luZy4gKi9cbiAgICBFdmVudHMuRVZFTlRfR1JJRF9SRUFEWSA9ICdncmlkUmVhZHknO1xuICAgIC8qKiBXaWR0aCBvZiBoZWlnaHQgb2YgdGhlIG1haW4gZ3JpZCBkaXYgaGFzIGNoYW5nZWQuIEdyaWQgbGlzdGVucyBmb3IgdGhpcyBhbmQgZG9lcyBsYXlvdXQgb2YgZ3JpZCBpZiBpdCdzXG4gICAgICogY2hhbmdlZCwgc28gYWx3YXlzIGZpbGxpbmcgdGhlIHNwYWNlIGl0IHdhcyBnaXZlbi4gKi9cbiAgICBFdmVudHMuRVZFTlRfR1JJRF9TSVpFX0NIQU5HRUQgPSAnZ3JpZFNpemVDaGFuZ2VkJztcbiAgICAvKiogVGhlIGluZGV4ZXMgb2YgdGhlIHJvd3MgcmVuZGVyZWQgaGFzIGNoYW5nZWQsIGVnIHVzZXIgaGFzIHNjcm9sbGVkIHRvIGEgbmV3IHZlcnRpY2FsIHBvc2l0aW9uLiAqL1xuICAgIEV2ZW50cy5FVkVOVF9WSUVXUE9SVF9DSEFOR0VEID0gJ3ZpZXdwb3J0Q2hhbmdlZCc7XG4gICAgLyogVGhlIHdpZHRoIG9mIHRoZSBzY3JvbGxiYXIgaGFzIGJlZW4gY2FsY3VsYXRlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9TQ1JPTExCQVJfV0lEVEhfQ0hBTkdFRCA9ICdzY3JvbGxiYXJXaWR0aENoYW5nZWQnO1xuICAgIC8qKiBSb3dzIHdlcmUgcmVuZGVyZWQgZm9yIHRoZSBmaXJzdCB0aW1lIChpZSBvbiBhc3luYyBkYXRhIGxvYWQpLiAqL1xuICAgIEV2ZW50cy5FVkVOVF9GSVJTVF9EQVRBX1JFTkRFUkVEID0gJ2ZpcnN0RGF0YVJlbmRlcmVkJztcbiAgICAvKiogQSBjb2x1bW4gZHJhZyBoYXMgc3RhcnRlZCwgZWl0aGVyIHJlc2l6aW5nIGEgY29sdW1uIG9yIG1vdmluZyBhIGNvbHVtbi4gKi9cbiAgICBFdmVudHMuRVZFTlRfRFJBR19TVEFSVEVEID0gJ2RyYWdTdGFydGVkJztcbiAgICAvKiogQSBjb2x1bW4gZHJhZyBoYXMgc3RvcHBlZCAqL1xuICAgIEV2ZW50cy5FVkVOVF9EUkFHX1NUT1BQRUQgPSAnZHJhZ1N0b3BwZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9DSEVDS0JPWF9DSEFOR0VEID0gJ2NoZWNrYm94Q2hhbmdlZCc7XG4gICAgRXZlbnRzLkVWRU5UX1JPV19FRElUSU5HX1NUQVJURUQgPSAncm93RWRpdGluZ1N0YXJ0ZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfRURJVElOR19TVE9QUEVEID0gJ3Jvd0VkaXRpbmdTdG9wcGVkJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9FRElUSU5HX1NUQVJURUQgPSAnY2VsbEVkaXRpbmdTdGFydGVkJztcbiAgICBFdmVudHMuRVZFTlRfQ0VMTF9FRElUSU5HX1NUT1BQRUQgPSAnY2VsbEVkaXRpbmdTdG9wcGVkJztcbiAgICAvKiogTWFpbiBib2R5IG9mIGdyaWQgaGFzIHNjcm9sbGVkLCBlaXRoZXIgaG9yaXpvbnRhbGx5IG9yIHZlcnRpY2FsbHkgKi9cbiAgICBFdmVudHMuRVZFTlRfQk9EWV9TQ1JPTEwgPSAnYm9keVNjcm9sbCc7XG4gICAgLyoqIE1haW4gYm9keSBvZiB0aGUgZ3JpZCBoYXMgc3RvcHBlZCBzY3JvbGxpbmcsIGVpdGhlciBob3Jpem9udGFsbHkgb3IgdmVydGljYWxseSAqL1xuICAgIEV2ZW50cy5FVkVOVF9CT0RZX1NDUk9MTF9FTkQgPSAnYm9keVNjcm9sbEVuZCc7XG4gICAgRXZlbnRzLkVWRU5UX0hFSUdIVF9TQ0FMRV9DSEFOR0VEID0gJ2hlaWdodFNjYWxlQ2hhbmdlZCc7XG4gICAgLyoqIFRoZSBkaXNwbGF5ZWQgcGFnZSBmb3IgcGFnaW5hdGlvbiBoYXMgY2hhbmdlZC4gRm9yIGV4YW1wbGUgdGhlIGRhdGEgd2FzIGZpbHRlcmVkIG9yIHNvcnRlZCxcbiAgICAgKiBvciB0aGUgdXNlciBoYXMgbW92ZWQgdG8gYSBkaWZmZXJlbnQgcGFnZS4gKi9cbiAgICBFdmVudHMuRVZFTlRfUEFHSU5BVElPTl9DSEFOR0VEID0gJ3BhZ2luYXRpb25DaGFuZ2VkJztcbiAgICAvKiogT25seSB1c2VkIGJ5IFJlYWN0LCBBbmd1bGFyLCBXZWIgQ29tcG9uZW50cyBhbmQgVnVlSlMgQUcgR3JpZCBjb21wb25lbnRzXG4gICAgICogKG5vdCB1c2VkIGlmIGRvaW5nIHBsYWluIEphdmFTY3JpcHQpLiBJZiB0aGUgZ3JpZCByZWNlaXZlcyBjaGFuZ2VzIGR1ZVxuICAgICAqIHRvIGJvdW5kIHByb3BlcnRpZXMsIHRoaXMgZXZlbnQgZmlyZXMgYWZ0ZXIgdGhlIGdyaWQgaGFzIGZpbmlzaGVkIHByb2Nlc3NpbmcgdGhlIGNoYW5nZS4gKi9cbiAgICBFdmVudHMuRVZFTlRfQ09NUE9ORU5UX1NUQVRFX0NIQU5HRUQgPSAnY29tcG9uZW50U3RhdGVDaGFuZ2VkJztcbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogIElOVEVSTkFMIEVWRU5UUzogU1RBUlQgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xuICAgIC8qKiBQbGVhc2UgcmVtZW1iZXIgdG8gYWRkIHRvIENvbXBvbmVudFV0aWwuRVhDTFVERURfSU5URVJOQUxfRVZFTlRTIHRvIG5vdCBoYXZlIHRoZXNlIGV2ZW50cyBleHBvc2VkIHRvIGZyYW1ld29yayBjb21wb25lbnRzLiAqL1xuICAgIC8qKiBBbGwgaXRlbXMgZnJvbSBoZXJlIGRvd24gYXJlIHVzZWQgaW50ZXJuYWxseSBieSB0aGUgZ3JpZCwgbm90IGludGVuZGVkIGZvciBleHRlcm5hbCB1c2UuICovXG4gICAgLy8gbm90IGRvY3VtZW50ZWQsIGVpdGhlciBleHBlcmltZW50YWwsIG9yIHdlIGp1c3QgZG9uJ3Qgd2FudCB1c2VycyB1c2luZyBhbiBkZXBlbmRpbmcgb24gdGhlbVxuICAgIEV2ZW50cy5FVkVOVF9CT0RZX0hFSUdIVF9DSEFOR0VEID0gJ2JvZHlIZWlnaHRDaGFuZ2VkJztcbiAgICBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfV0lEVEhfQ0hBTkdFRCA9ICdkaXNwbGF5ZWRDb2x1bW5zV2lkdGhDaGFuZ2VkJztcbiAgICBFdmVudHMuRVZFTlRfU0NST0xMX1ZJU0lCSUxJVFlfQ0hBTkdFRCA9ICdzY3JvbGxWaXNpYmlsaXR5Q2hhbmdlZCc7XG4gICAgRXZlbnRzLkVWRU5UX0NPTFVNTl9IT1ZFUl9DSEFOR0VEID0gJ2NvbHVtbkhvdmVyQ2hhbmdlZCc7XG4gICAgRXZlbnRzLkVWRU5UX0ZMQVNIX0NFTExTID0gJ2ZsYXNoQ2VsbHMnO1xuICAgIEV2ZW50cy5FVkVOVF9QQUdJTkFUSU9OX1BJWEVMX09GRlNFVF9DSEFOR0VEID0gJ3BhZ2luYXRpb25QaXhlbE9mZnNldENoYW5nZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfUk9XU19DSEFOR0VEID0gJ2Rpc3BsYXllZFJvd3NDaGFuZ2VkJztcbiAgICBFdmVudHMuRVZFTlRfTEVGVF9QSU5ORURfV0lEVEhfQ0hBTkdFRCA9ICdsZWZ0UGlubmVkV2lkdGhDaGFuZ2VkJztcbiAgICBFdmVudHMuRVZFTlRfUklHSFRfUElOTkVEX1dJRFRIX0NIQU5HRUQgPSAncmlnaHRQaW5uZWRXaWR0aENoYW5nZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfQ09OVEFJTkVSX0hFSUdIVF9DSEFOR0VEID0gJ3Jvd0NvbnRhaW5lckhlaWdodENoYW5nZWQnO1xuICAgIEV2ZW50cy5FVkVOVF9IRUFERVJfSEVJR0hUX0NIQU5HRUQgPSAnaGVhZGVySGVpZ2h0Q2hhbmdlZCc7XG4gICAgRXZlbnRzLkVWRU5UX0NPTFVNTl9IRUFERVJfSEVJR0hUX0NIQU5HRUQgPSAnY29sdW1uSGVhZGVySGVpZ2h0Q2hhbmdlZCc7XG4gICAgRXZlbnRzLkVWRU5UX1JPV19EUkFHX0VOVEVSID0gJ3Jvd0RyYWdFbnRlcic7XG4gICAgRXZlbnRzLkVWRU5UX1JPV19EUkFHX01PVkUgPSAncm93RHJhZ01vdmUnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfRFJBR19MRUFWRSA9ICdyb3dEcmFnTGVhdmUnO1xuICAgIEV2ZW50cy5FVkVOVF9ST1dfRFJBR19FTkQgPSAncm93RHJhZ0VuZCc7XG4gICAgLy8gcHJpbWFyaWx5IGZvciBjaGFydHNcbiAgICBFdmVudHMuRVZFTlRfUE9QVVBfVE9fRlJPTlQgPSAncG9wdXBUb0Zyb250JztcbiAgICAvLyB0aGVzZSBhcmUgdXNlZCBmb3Igc2VydmVyIHNpZGUgZ3JvdXAgYW5kIGFnZyAtIG9ubHkgdXNlZCBieSBDUyB3aXRoIFZpZXdwb3J0IFJvdyBNb2RlbCAtIGludGVudGlvbiBpc1xuICAgIC8vIHRvIGRlc2lnbiB0aGVzZSBiZXR0ZXIgYXJvdW5kIHNlcnZlciBzaWRlIGZ1bmN0aW9ucyBhbmQgdGhlbiByZWxlYXNlIHRvIGdlbmVyYWwgcHVibGljIHdoZW4gZnVsbHkgd29ya2luZyB3aXRoXG4gICAgLy8gYWxsIHRoZSByb3cgbW9kZWxzLlxuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRV9SRVFVRVNUID0gJ2NvbHVtblJvd0dyb3VwQ2hhbmdlUmVxdWVzdCc7XG4gICAgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9DSEFOR0VfUkVRVUVTVCA9ICdjb2x1bW5QaXZvdENoYW5nZVJlcXVlc3QnO1xuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fVkFMVUVfQ0hBTkdFX1JFUVVFU1QgPSAnY29sdW1uVmFsdWVDaGFuZ2VSZXF1ZXN0JztcbiAgICBFdmVudHMuRVZFTlRfQ09MVU1OX0FHR19GVU5DX0NIQU5HRV9SRVFVRVNUID0gJ2NvbHVtbkFnZ0Z1bmNDaGFuZ2VSZXF1ZXN0JztcbiAgICBFdmVudHMuRVZFTlRfS0VZQk9BUkRfRk9DVVMgPSAna2V5Ym9hcmRGb2N1cyc7XG4gICAgRXZlbnRzLkVWRU5UX01PVVNFX0ZPQ1VTID0gJ21vdXNlRm9jdXMnO1xuICAgIEV2ZW50cy5FVkVOVF9TVE9SRV9VUERBVEVEID0gJ3N0b3JlVXBkYXRlZCc7XG4gICAgcmV0dXJuIEV2ZW50cztcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbi8vIGNsYXNzIHJldHVybnMgdW5pcXVlIGluc3RhbmNlIGlkJ3MgZm9yIGNvbHVtbnMuXG4vLyBlZywgdGhlIGZvbGxvd2luZyBjYWxscyAoaW4gdGhpcyBvcmRlcikgd2lsbCByZXN1bHQgaW46XG4vL1xuLy8gZ2V0SW5zdGFuY2VJZEZvcktleSgnY291bnRyeScpID0+IDBcbi8vIGdldEluc3RhbmNlSWRGb3JLZXkoJ2NvdW50cnknKSA9PiAxXG4vLyBnZXRJbnN0YW5jZUlkRm9yS2V5KCdjb3VudHJ5JykgPT4gMlxuLy8gZ2V0SW5zdGFuY2VJZEZvcktleSgnY291bnRyeScpID0+IDNcbi8vIGdldEluc3RhbmNlSWRGb3JLZXkoJ2FnZScpID0+IDBcbi8vIGdldEluc3RhbmNlSWRGb3JLZXkoJ2FnZScpID0+IDFcbi8vIGdldEluc3RhbmNlSWRGb3JLZXkoJ2NvdW50cnknKSA9PiA0XG52YXIgR3JvdXBJbnN0YW5jZUlkQ3JlYXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBHcm91cEluc3RhbmNlSWRDcmVhdG9yKCkge1xuICAgICAgICAvLyB0aGlzIG1hcCBjb250YWlucyBrZXlzIHRvIG51bWJlcnMsIHNvIHdlIHJlbWVtYmVyIHdoYXQgdGhlIGxhc3QgY2FsbCB3YXNcbiAgICAgICAgdGhpcy5leGlzdGluZ0lkcyA9IHt9O1xuICAgIH1cbiAgICBHcm91cEluc3RhbmNlSWRDcmVhdG9yLnByb3RvdHlwZS5nZXRJbnN0YW5jZUlkRm9yS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgbGFzdFJlc3VsdCA9IHRoaXMuZXhpc3RpbmdJZHNba2V5XTtcbiAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgaWYgKHR5cGVvZiBsYXN0UmVzdWx0ICE9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgLy8gZmlyc3QgdGltZSB0aGlzIGtleVxuICAgICAgICAgICAgcmVzdWx0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGxhc3RSZXN1bHQgKyAxO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXhpc3RpbmdJZHNba2V5XSA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIHJldHVybiBHcm91cEluc3RhbmNlSWRDcmVhdG9yO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIHJlVW5lc2NhcGVkSHRtbCA9IC9bJjw+XCInXS9nO1xuLyoqXG4gKiBIVE1MIEVzY2FwZXMuXG4gKi9cbnZhciBIVE1MX0VTQ0FQRVMgPSB7XG4gICAgJyYnOiAnJmFtcDsnLFxuICAgICc8JzogJyZsdDsnLFxuICAgICc+JzogJyZndDsnLFxuICAgICdcIic6ICcmcXVvdDsnLFxuICAgIFwiJ1wiOiAnJiMzOTsnXG59O1xuLyoqXG4gKiBJdCBlbmNvZGVzIGFueSBzdHJpbmcgaW4gVVRGLTggZm9ybWF0XG4gKiB0YWtlbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXRoaWFzYnluZW5zL3V0ZjguanNcbiAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiB1dGY4X2VuY29kZShzKSB7XG4gICAgdmFyIHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGU7XG4gICAgZnVuY3Rpb24gdWNzMmRlY29kZShzdHJpbmcpIHtcbiAgICAgICAgdmFyIG91dHB1dCA9IFtdO1xuICAgICAgICBpZiAoIXN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZW4gPSBzdHJpbmcubGVuZ3RoO1xuICAgICAgICB2YXIgY291bnRlciA9IDA7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIGV4dHJhO1xuICAgICAgICB3aGlsZSAoY291bnRlciA8IGxlbikge1xuICAgICAgICAgICAgdmFsdWUgPSBzdHJpbmcuY2hhckNvZGVBdChjb3VudGVyKyspO1xuICAgICAgICAgICAgaWYgKHZhbHVlID49IDB4RDgwMCAmJiB2YWx1ZSA8PSAweERCRkYgJiYgY291bnRlciA8IGxlbikge1xuICAgICAgICAgICAgICAgIC8vIGhpZ2ggc3Vycm9nYXRlLCBhbmQgdGhlcmUgaXMgYSBuZXh0IGNoYXJhY3RlclxuICAgICAgICAgICAgICAgIGV4dHJhID0gc3RyaW5nLmNoYXJDb2RlQXQoY291bnRlcisrKTtcbiAgICAgICAgICAgICAgICBpZiAoKGV4dHJhICYgMHhGQzAwKSA9PSAweERDMDApIHsgLy8gbG93IHN1cnJvZ2F0ZVxuICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaCgoKHZhbHVlICYgMHgzRkYpIDw8IDEwKSArIChleHRyYSAmIDB4M0ZGKSArIDB4MTAwMDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdW5tYXRjaGVkIHN1cnJvZ2F0ZTsgb25seSBhcHBlbmQgdGhpcyBjb2RlIHVuaXQsIGluIGNhc2UgdGhlIG5leHRcbiAgICAgICAgICAgICAgICAgICAgLy8gY29kZSB1bml0IGlzIHRoZSBoaWdoIHN1cnJvZ2F0ZSBvZiBhIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlci0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBjaGVja1NjYWxhclZhbHVlKHBvaW50KSB7XG4gICAgICAgIGlmIChwb2ludCA+PSAweEQ4MDAgJiYgcG9pbnQgPD0gMHhERkZGKSB7XG4gICAgICAgICAgICB0aHJvdyBFcnJvcignTG9uZSBzdXJyb2dhdGUgVSsnICsgcG9pbnQudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCkgK1xuICAgICAgICAgICAgICAgICcgaXMgbm90IGEgc2NhbGFyIHZhbHVlJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlQnl0ZShwb2ludCwgc2hpZnQpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZ0Zyb21DaGFyQ29kZSgoKHBvaW50ID4+IHNoaWZ0KSAmIDB4M0YpIHwgMHg4MCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVuY29kZUNvZGVQb2ludChwb2ludCkge1xuICAgICAgICBpZiAoKHBvaW50ID49IDAgJiYgcG9pbnQgPD0gMzEgJiYgcG9pbnQgIT09IDEwKSkge1xuICAgICAgICAgICAgdmFyIGNvbnZlcnRlZENvZGUgPSBwb2ludC50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIHZhciBwYWRkZWRDb2RlID0gY29udmVydGVkQ29kZS5wYWRTdGFydCg0LCAnMCcpO1xuICAgICAgICAgICAgcmV0dXJuIFwiX3hcIiArIHBhZGRlZENvZGUgKyBcIl9cIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKHBvaW50ICYgMHhGRkZGRkY4MCkgPT0gMCkgeyAvLyAxLWJ5dGUgc2VxdWVuY2VcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdGcm9tQ2hhckNvZGUocG9pbnQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzeW1ib2wgPSAnJztcbiAgICAgICAgaWYgKChwb2ludCAmIDB4RkZGRkY4MDApID09IDApIHsgLy8gMi1ieXRlIHNlcXVlbmNlXG4gICAgICAgICAgICBzeW1ib2wgPSBzdHJpbmdGcm9tQ2hhckNvZGUoKChwb2ludCA+PiA2KSAmIDB4MUYpIHwgMHhDMCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoKHBvaW50ICYgMHhGRkZGMDAwMCkgPT0gMCkgeyAvLyAzLWJ5dGUgc2VxdWVuY2VcbiAgICAgICAgICAgIGNoZWNrU2NhbGFyVmFsdWUocG9pbnQpO1xuICAgICAgICAgICAgc3ltYm9sID0gc3RyaW5nRnJvbUNoYXJDb2RlKCgocG9pbnQgPj4gMTIpICYgMHgwRikgfCAweEUwKTtcbiAgICAgICAgICAgIHN5bWJvbCArPSBjcmVhdGVCeXRlKHBvaW50LCA2KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgocG9pbnQgJiAweEZGRTAwMDAwKSA9PSAwKSB7IC8vIDQtYnl0ZSBzZXF1ZW5jZVxuICAgICAgICAgICAgc3ltYm9sID0gc3RyaW5nRnJvbUNoYXJDb2RlKCgocG9pbnQgPj4gMTgpICYgMHgwNykgfCAweEYwKTtcbiAgICAgICAgICAgIHN5bWJvbCArPSBjcmVhdGVCeXRlKHBvaW50LCAxMik7XG4gICAgICAgICAgICBzeW1ib2wgKz0gY3JlYXRlQnl0ZShwb2ludCwgNik7XG4gICAgICAgIH1cbiAgICAgICAgc3ltYm9sICs9IHN0cmluZ0Zyb21DaGFyQ29kZSgocG9pbnQgJiAweDNGKSB8IDB4ODApO1xuICAgICAgICByZXR1cm4gc3ltYm9sO1xuICAgIH1cbiAgICB2YXIgY29kZVBvaW50cyA9IHVjczJkZWNvZGUocyk7XG4gICAgdmFyIGxlbmd0aCA9IGNvZGVQb2ludHMubGVuZ3RoO1xuICAgIHZhciBpbmRleCA9IC0xO1xuICAgIHZhciBjb2RlUG9pbnQ7XG4gICAgdmFyIGJ5dGVTdHJpbmcgPSAnJztcbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBjb2RlUG9pbnQgPSBjb2RlUG9pbnRzW2luZGV4XTtcbiAgICAgICAgYnl0ZVN0cmluZyArPSBlbmNvZGVDb2RlUG9pbnQoY29kZVBvaW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGJ5dGVTdHJpbmc7XG59XG4vKipcbiAqIENvbnZlcnRzIGEgY2FtZWxDYXNlIHN0cmluZyBpbnRvIGh5cGhlbmF0ZWQgc3RyaW5nXG4gKiBmcm9tIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL3lvdXNzbWFuLzc0NTU3ODA2MjYwOWU4YWNhYzlmXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGNhbWVsQ2FzZVRvSHlwaGVuKHN0cikge1xuICAgIGlmIChzdHIgPT09IG51bGwgfHwgc3RyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBzdHIucmVwbGFjZSgvKFtBLVpdKS9nLCBmdW5jdGlvbiAoZykgeyByZXR1cm4gJy0nICsgZ1swXS50b0xvd2VyQ2FzZSgpOyB9KTtcbn1cbi8qKlxuICogQ29udmVydHMgYSBoeXBoZW5hdGVkIHN0cmluZyBpbnRvIGNhbWVsQ2FzZSBzdHJpbmdcbiAqIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjY2MDk3Ny9jb252ZXJ0LWh5cGhlbnMtdG8tY2FtZWwtY2FzZS1jYW1lbGNhc2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gaHlwaGVuVG9DYW1lbENhc2Uoc3RyKSB7XG4gICAgaWYgKHN0ciA9PT0gbnVsbCB8fCBzdHIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8tKFthLXpdKS9nLCBmdW5jdGlvbiAoZykgeyByZXR1cm4gZ1sxXS50b1VwcGVyQ2FzZSgpOyB9KTtcbn1cbmZ1bmN0aW9uIGNhcGl0YWxpc2Uoc3RyKSB7XG4gICAgcmV0dXJuIHN0clswXS50b1VwcGVyQ2FzZSgpICsgc3RyLnN1YnN0cigxKS50b0xvd2VyQ2FzZSgpO1xufVxuZnVuY3Rpb24gZXNjYXBlU3RyaW5nKHRvRXNjYXBlLCBza2lwRXNjYXBpbmdIdG1sQ2hhcnMpIHtcbiAgICBpZiAodG9Fc2NhcGUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgLy8gd2UgY2FsbCB0b1N0cmluZygpIHR3aWNlLCBpbiBjYXNlIHZhbHVlIGlzIGFuIG9iamVjdCwgd2hlcmUgdXNlciBwcm92aWRlc1xuICAgIC8vIGEgdG9TdHJpbmcoKSBtZXRob2QsIGFuZCBmaXJzdCBjYWxsIHRvIHRvU3RyaW5nKCkgcmV0dXJucyBiYWNrIHNvbWV0aGluZyBvdGhlclxuICAgIC8vIHRoYW4gYSBzdHJpbmcgKGVnIGEgbnVtYmVyIHRvIHJlbmRlcilcbiAgICB2YXIgc3RyaW5nUmVzdWx0ID0gdG9Fc2NhcGUudG9TdHJpbmcoKS50b1N0cmluZygpO1xuICAgIGlmIChza2lwRXNjYXBpbmdIdG1sQ2hhcnMpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZ1Jlc3VsdDtcbiAgICB9XG4gICAgLy8gaW4gcmVhY3Qgd2UgZG9uJ3QgbmVlZCB0byBlc2NhcGUgaHRtbCBjaGFyYWN0ZXJzLCBhcyBpdCdzIGRvbmUgYnkgdGhlIGZyYW1ld29ya1xuICAgIHJldHVybiBzdHJpbmdSZXN1bHQucmVwbGFjZShyZVVuZXNjYXBlZEh0bWwsIGZ1bmN0aW9uIChjaHIpIHsgcmV0dXJuIEhUTUxfRVNDQVBFU1tjaHJdOyB9KTtcbn1cbi8qKlxuICogQ29udmVydHMgYSBjYW1lbENhc2Ugc3RyaW5nIGludG8gcmVndWxhciB0ZXh0XG4gKiBmcm9tOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xNTM2OTU2Ni9wdXR0aW5nLXNwYWNlLWluLWNhbWVsLWNhc2Utc3RyaW5nLXVzaW5nLXJlZ3VsYXItZXhwcmVzc2lvblxuICogQHBhcmFtIHtzdHJpbmd9IGNhbWVsQ2FzZVxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBjYW1lbENhc2VUb0h1bWFuVGV4dChjYW1lbENhc2UpIHtcbiAgICBpZiAoIWNhbWVsQ2FzZSB8fCBjYW1lbENhc2UgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIHJleCA9IC8oW0EtWl0pKFtBLVpdKShbYS16XSl8KFthLXpdKShbQS1aXSkvZztcbiAgICB2YXIgd29yZHMgPSBjYW1lbENhc2UucmVwbGFjZShyZXgsICckMSQ0ICQyJDMkNScpLnJlcGxhY2UoJy4nLCAnICcpLnNwbGl0KCcgJyk7XG4gICAgcmV0dXJuIHdvcmRzLm1hcChmdW5jdGlvbiAod29yZCkgeyByZXR1cm4gd29yZC5zdWJzdHJpbmcoMCwgMSkudG9VcHBlckNhc2UoKSArICgod29yZC5sZW5ndGggPiAxKSA/IHdvcmQuc3Vic3RyaW5nKDEsIHdvcmQubGVuZ3RoKSA6ICcnKTsgfSkuam9pbignICcpO1xufVxuXG52YXIgU3RyaW5nVXRpbHMgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIHV0ZjhfZW5jb2RlOiB1dGY4X2VuY29kZSxcbiAgICBjYW1lbENhc2VUb0h5cGhlbjogY2FtZWxDYXNlVG9IeXBoZW4sXG4gICAgaHlwaGVuVG9DYW1lbENhc2U6IGh5cGhlblRvQ2FtZWxDYXNlLFxuICAgIGNhcGl0YWxpc2U6IGNhcGl0YWxpc2UsXG4gICAgZXNjYXBlU3RyaW5nOiBlc2NhcGVTdHJpbmcsXG4gICAgY2FtZWxDYXNlVG9IdW1hblRleHQ6IGNhbWVsQ2FzZVRvSHVtYW5UZXh0XG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuZnVuY3Rpb24gY29udmVydFRvTWFwKGFycikge1xuICAgIHZhciBtYXAgPSBuZXcgTWFwKCk7XG4gICAgYXJyLmZvckVhY2goZnVuY3Rpb24gKHBhaXIpIHsgcmV0dXJuIG1hcC5zZXQocGFpclswXSwgcGFpclsxXSk7IH0pO1xuICAgIHJldHVybiBtYXA7XG59XG4vLyBoYW5keSBmb3Igb3JnYW5pc2luZyBhIGxpc3QgaW50byBhIG1hcCwgd2hlcmUgZWFjaCBpdGVtIGlzIG1hcHBlZCBieSBhbiBhdHRyaWJ1dGUsIGVnIG1hcHBpbmcgQ29sdW1ucyBieSBJRFxuZnVuY3Rpb24gbWFwQnlJZChhcnIsIGNhbGxiYWNrKSB7XG4gICAgdmFyIG1hcCA9IG5ldyBNYXAoKTtcbiAgICBhcnIuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gbWFwLnNldChjYWxsYmFjayhpdGVtKSwgaXRlbSk7IH0pO1xuICAgIHJldHVybiBtYXA7XG59XG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICAgIHZhciBhcnIgPSBbXTtcbiAgICBtYXAuZm9yRWFjaChmdW5jdGlvbiAoXywga2V5KSB7IHJldHVybiBhcnIucHVzaChrZXkpOyB9KTtcbiAgICByZXR1cm4gYXJyO1xufVxuXG52YXIgTWFwVXRpbHMgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIGNvbnZlcnRUb01hcDogY29udmVydFRvTWFwLFxuICAgIG1hcEJ5SWQ6IG1hcEJ5SWQsXG4gICAga2V5czoga2V5c1xufSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX3JlYWQkcCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCRqID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJHAoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBDb2xEZWZVdGlsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbERlZlV0aWwoKSB7XG4gICAgfVxuICAgIENvbERlZlV0aWwuU1RSSU5HX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdoZWFkZXJOYW1lJyxcbiAgICAgICAgJ2NvbHVtbkdyb3VwU2hvdycsXG4gICAgICAgICdoZWFkZXJDbGFzcycsXG4gICAgICAgICd0b29sUGFuZWxDbGFzcycsXG4gICAgICAgICdoZWFkZXJWYWx1ZUdldHRlcicsXG4gICAgICAgICdwaXZvdEtleXMnLFxuICAgICAgICAnZ3JvdXBJZCcsXG4gICAgICAgICdjb2xJZCcsXG4gICAgICAgICdzb3J0JyxcbiAgICAgICAgJ2luaXRpYWxTb3J0JyxcbiAgICAgICAgJ2ZpZWxkJyxcbiAgICAgICAgJ3R5cGUnLFxuICAgICAgICAndG9vbHRpcENvbXBvbmVudCcsXG4gICAgICAgICd0b29sdGlwRmllbGQnLFxuICAgICAgICAnaGVhZGVyVG9vbHRpcCcsXG4gICAgICAgICdjZWxsQ2xhc3MnLFxuICAgICAgICAnc2hvd1Jvd0dyb3VwJyxcbiAgICAgICAgJ2ZpbHRlcicsXG4gICAgICAgICdpbml0aWFsQWdnRnVuYycsXG4gICAgICAgICdkZWZhdWx0QWdnRnVuYycsXG4gICAgICAgICdhZ2dGdW5jJyxcbiAgICAgICAgJ3Bpbm5lZCcsXG4gICAgICAgICdpbml0aWFsUGlubmVkJyxcbiAgICAgICAgJ2NoYXJ0RGF0YVR5cGUnLFxuICAgICAgICAnY2VsbEVkaXRvclBvcHVwUG9zaXRpb24nXG4gICAgXTtcbiAgICBDb2xEZWZVdGlsLk9CSkVDVF9QUk9QRVJUSUVTID0gW1xuICAgICAgICAnaGVhZGVyR3JvdXBDb21wb25lbnQnLFxuICAgICAgICAnaGVhZGVyR3JvdXBDb21wb25lbnRGcmFtZXdvcmsnLFxuICAgICAgICAnaGVhZGVyR3JvdXBDb21wb25lbnRQYXJhbXMnLFxuICAgICAgICAnY2VsbFN0eWxlJyxcbiAgICAgICAgJ2NlbGxSZW5kZXJlcicsXG4gICAgICAgICdjZWxsUmVuZGVyZXJQYXJhbXMnLFxuICAgICAgICAnY2VsbFJlbmRlcmVyRnJhbWV3b3JrJyxcbiAgICAgICAgJ2NlbGxFZGl0b3InLFxuICAgICAgICAnY2VsbEVkaXRvckZyYW1ld29yaycsXG4gICAgICAgICdjZWxsRWRpdG9yUGFyYW1zJyxcbiAgICAgICAgJ3Bpbm5lZFJvd0NlbGxSZW5kZXJlckZyYW1ld29yaycsXG4gICAgICAgICdwaW5uZWRSb3dDZWxsUmVuZGVyZXJQYXJhbXMnLFxuICAgICAgICAnZmlsdGVyRnJhbWV3b3JrJyxcbiAgICAgICAgJ2ZpbHRlclBhcmFtcycsXG4gICAgICAgICdwaXZvdFZhbHVlQ29sdW1uJyxcbiAgICAgICAgJ2hlYWRlckNvbXBvbmVudCcsXG4gICAgICAgICdoZWFkZXJDb21wb25lbnRGcmFtZXdvcmsnLFxuICAgICAgICAnaGVhZGVyQ29tcG9uZW50UGFyYW1zJyxcbiAgICAgICAgJ2Zsb2F0aW5nRmlsdGVyQ29tcG9uZW50JyxcbiAgICAgICAgJ2Zsb2F0aW5nRmlsdGVyQ29tcG9uZW50UGFyYW1zJyxcbiAgICAgICAgJ2Zsb2F0aW5nRmlsdGVyQ29tcG9uZW50RnJhbWV3b3JrJyxcbiAgICAgICAgJ2Zsb2F0aW5nRmlsdGVyRnJhbWV3b3JrJyxcbiAgICAgICAgJ3Rvb2x0aXBDb21wb25lbnQnLFxuICAgICAgICAndG9vbHRpcENvbXBvbmVudFBhcmFtcycsXG4gICAgICAgICd0b29sdGlwQ29tcG9uZW50RnJhbWV3b3JrJyxcbiAgICAgICAgJ3JlZkRhdGEnLFxuICAgICAgICAnY29sdW1uc01lbnVQYXJhbXMnXG4gICAgXTtcbiAgICBDb2xEZWZVdGlsLkFSUkFZX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdjaGlsZHJlbicsXG4gICAgICAgICdzb3J0aW5nT3JkZXInLFxuICAgICAgICAnYWxsb3dlZEFnZ0Z1bmNzJyxcbiAgICAgICAgJ21lbnVUYWJzJyxcbiAgICAgICAgJ3Bpdm90VG90YWxDb2x1bW5JZHMnLFxuICAgICAgICAnY2VsbENsYXNzUnVsZXMnLFxuICAgICAgICAnaWNvbnMnXG4gICAgXTtcbiAgICBDb2xEZWZVdGlsLk5VTUJFUl9QUk9QRVJUSUVTID0gW1xuICAgICAgICAnc29ydGVkQXQnLFxuICAgICAgICAnc29ydEluZGV4JyxcbiAgICAgICAgJ2luaXRpYWxTb3J0SW5kZXgnLFxuICAgICAgICAnZmxleCcsXG4gICAgICAgICdpbml0aWFsRmxleCcsXG4gICAgICAgICd3aWR0aCcsXG4gICAgICAgICdpbml0aWFsV2lkdGgnLFxuICAgICAgICAnbWluV2lkdGgnLFxuICAgICAgICAnbWF4V2lkdGgnLFxuICAgICAgICAncm93R3JvdXBJbmRleCcsXG4gICAgICAgICdpbml0aWFsUm93R3JvdXBJbmRleCcsXG4gICAgICAgICdwaXZvdEluZGV4JyxcbiAgICAgICAgJ2luaXRpYWxQaXZvdEluZGV4J1xuICAgIF07XG4gICAgQ29sRGVmVXRpbC5CT09MRUFOX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdzdXBwcmVzc0NlbGxGbGFzaCcsXG4gICAgICAgICdzdXBwcmVzc0NvbHVtbnNUb29sUGFuZWwnLFxuICAgICAgICAnc3VwcHJlc3NGaWx0ZXJzVG9vbFBhbmVsJyxcbiAgICAgICAgJ29wZW5CeURlZmF1bHQnLFxuICAgICAgICAnbWFycnlDaGlsZHJlbicsXG4gICAgICAgICdoaWRlJyxcbiAgICAgICAgJ2luaXRpYWxIaWRlJyxcbiAgICAgICAgJ3Jvd0dyb3VwJyxcbiAgICAgICAgJ2luaXRpYWxSb3dHcm91cCcsXG4gICAgICAgICdwaXZvdCcsXG4gICAgICAgICdpbml0aWFsUGl2b3QnLFxuICAgICAgICAnY2hlY2tib3hTZWxlY3Rpb24nLFxuICAgICAgICAnc2hvd0Rpc2FibGVkQ2hlY2tib3hlcycsXG4gICAgICAgICdoZWFkZXJDaGVja2JveFNlbGVjdGlvbicsXG4gICAgICAgICdoZWFkZXJDaGVja2JveFNlbGVjdGlvbkZpbHRlcmVkT25seScsXG4gICAgICAgICdzdXBwcmVzc01lbnUnLFxuICAgICAgICAnc3VwcHJlc3NNb3ZhYmxlJyxcbiAgICAgICAgJ2xvY2tQb3NpdGlvbicsXG4gICAgICAgICdsb2NrVmlzaWJsZScsXG4gICAgICAgICdsb2NrUGlubmVkJyxcbiAgICAgICAgJ3VuU29ydEljb24nLFxuICAgICAgICAnc3VwcHJlc3NTaXplVG9GaXQnLFxuICAgICAgICAnc3VwcHJlc3NBdXRvU2l6ZScsXG4gICAgICAgICdlbmFibGVSb3dHcm91cCcsXG4gICAgICAgICdlbmFibGVQaXZvdCcsXG4gICAgICAgICdlbmFibGVWYWx1ZScsXG4gICAgICAgICdlZGl0YWJsZScsXG4gICAgICAgICdzdXBwcmVzc1Bhc3RlJyxcbiAgICAgICAgJ3N1cHByZXNzTmF2aWdhYmxlJyxcbiAgICAgICAgJ2VuYWJsZUNlbGxDaGFuZ2VGbGFzaCcsXG4gICAgICAgICdyb3dEcmFnJyxcbiAgICAgICAgJ2RuZFNvdXJjZScsXG4gICAgICAgICdhdXRvSGVpZ2h0JyxcbiAgICAgICAgJ3dyYXBUZXh0JyxcbiAgICAgICAgJ3NvcnRhYmxlJyxcbiAgICAgICAgJ3Jlc2l6YWJsZScsXG4gICAgICAgICdzaW5nbGVDbGlja0VkaXQnLFxuICAgICAgICAnZmxvYXRpbmdGaWx0ZXInLFxuICAgICAgICAnY2VsbEVkaXRvclBvcHVwJyxcbiAgICAgICAgJ3N1cHByZXNzRmlsbEhhbmRsZScsXG4gICAgICAgICd3cmFwSGVhZGVyVGV4dCcsXG4gICAgICAgICdhdXRvSGVhZGVySGVpZ2h0J1xuICAgIF07XG4gICAgQ29sRGVmVXRpbC5GVU5DVElPTl9QUk9QRVJUSUVTID0gW1xuICAgICAgICAnZG5kU291cmNlT25Sb3dEcmFnJyxcbiAgICAgICAgJ3ZhbHVlR2V0dGVyJyxcbiAgICAgICAgJ3ZhbHVlU2V0dGVyJyxcbiAgICAgICAgJ2ZpbHRlclZhbHVlR2V0dGVyJyxcbiAgICAgICAgJ2tleUNyZWF0b3InLFxuICAgICAgICAncGlubmVkUm93Q2VsbFJlbmRlcmVyJyxcbiAgICAgICAgJ3ZhbHVlRm9ybWF0dGVyJyxcbiAgICAgICAgJ3Bpbm5lZFJvd1ZhbHVlRm9ybWF0dGVyJyxcbiAgICAgICAgJ3ZhbHVlUGFyc2VyJyxcbiAgICAgICAgJ2NvbXBhcmF0b3InLFxuICAgICAgICAnZXF1YWxzJyxcbiAgICAgICAgJ3Bpdm90Q29tcGFyYXRvcicsXG4gICAgICAgICdzdXBwcmVzc0tleWJvYXJkRXZlbnQnLFxuICAgICAgICAnc3VwcHJlc3NIZWFkZXJLZXlib2FyZEV2ZW50JyxcbiAgICAgICAgJ2NvbFNwYW4nLFxuICAgICAgICAncm93U3BhbicsXG4gICAgICAgICdnZXRRdWlja0ZpbHRlclRleHQnLFxuICAgICAgICAnbmV3VmFsdWVIYW5kbGVyJyxcbiAgICAgICAgJ29uQ2VsbFZhbHVlQ2hhbmdlZCcsXG4gICAgICAgICdvbkNlbGxDbGlja2VkJyxcbiAgICAgICAgJ29uQ2VsbERvdWJsZUNsaWNrZWQnLFxuICAgICAgICAnb25DZWxsQ29udGV4dE1lbnUnLFxuICAgICAgICAncm93RHJhZ1RleHQnLFxuICAgICAgICAndG9vbHRpcFZhbHVlR2V0dGVyJyxcbiAgICAgICAgJ3Rvb2x0aXBDb21wb25lbnQnLFxuICAgICAgICAndG9vbHRpcENvbXBvbmVudEZyYW1ld29yaycsXG4gICAgICAgICdjZWxsUmVuZGVyZXJTZWxlY3RvcicsXG4gICAgICAgICdjZWxsRWRpdG9yU2VsZWN0b3InXG4gICAgXTtcbiAgICBDb2xEZWZVdGlsLkFMTF9QUk9QRVJUSUVTID0gX19zcHJlYWQkaihDb2xEZWZVdGlsLkFSUkFZX1BST1BFUlRJRVMsIENvbERlZlV0aWwuT0JKRUNUX1BST1BFUlRJRVMsIENvbERlZlV0aWwuU1RSSU5HX1BST1BFUlRJRVMsIENvbERlZlV0aWwuTlVNQkVSX1BST1BFUlRJRVMsIENvbERlZlV0aWwuRlVOQ1RJT05fUFJPUEVSVElFUywgQ29sRGVmVXRpbC5CT09MRUFOX1BST1BFUlRJRVMpO1xuICAgIC8vIHVzZWQgd2hlbiBkb2luZyBwcm9wZXJ0eSBjaGVja3MgLSB0aGlzIGNhdXNlcyBub2lzZSB3aGVuIHVzaW5nIGZyYW1ld29ya3Mgd2hpY2ggY2FuIGFkZCB0aGVpciBvd24gZncgc3BlY2lmaWNcbiAgICAvLyBwcm9wZXJ0aWVzIHRvIGNvbERlZnMsIGdyaWRPcHRpb25zIGV0Y1xuICAgIENvbERlZlV0aWwuRlJBTUVXT1JLX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdfX29iX18nLFxuICAgICAgICAnX192X3NraXAnLFxuICAgICAgICAnX19tZXRhZGF0YV9fJyxcbiAgICAgICAgJ21hcHBlZENvbHVtblByb3BlcnRpZXMnLFxuICAgICAgICAnaGFzQ2hpbGRDb2x1bW5zJyxcbiAgICAgICAgJ3RvQ29sRGVmJyxcbiAgICAgICAgJ2NyZWF0ZUNvbERlZkZyb21HcmlkQ29sdW1uJ1xuICAgIF07XG4gICAgcmV0dXJuIENvbERlZlV0aWw7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19yZWFkJG8gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgX19zcHJlYWQkaSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCRvKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG4vKipcbiAqIFRoZXNlIGtleXMgYXJlIHVzZWQgZm9yIHZhbGlkYXRpbmcgcHJvcGVydGllcyBzdXBwbGllZCBvbiBhIGdyaWRPcHRpb25zIG9iamVjdCwgYW5kIGZvciBjb2RlIGdlbmVyYXRpb24uXG4gKiBJZiB5b3UgY2hhbmdlIHRoZSBwcm9wZXJ0aWVzIG9uIHRoZSBncmlkT3B0aW9ucyBpbnRlcmZhY2UsIHlvdSAqbXVzdCogdXBkYXRlIHRoaXMgZmlsZSBhcyB3ZWxsIHRvIGJlIGNvbnNpc3RlbnQuXG4gKi9cbnZhciBQcm9wZXJ0eUtleXMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHJvcGVydHlLZXlzKCkge1xuICAgIH1cbiAgICBQcm9wZXJ0eUtleXMuU1RSSU5HX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdzb3J0aW5nT3JkZXInLCAncm93Q2xhc3MnLCAncm93U2VsZWN0aW9uJywgJ292ZXJsYXlMb2FkaW5nVGVtcGxhdGUnLCAnb3ZlcmxheU5vUm93c1RlbXBsYXRlJyxcbiAgICAgICAgJ3F1aWNrRmlsdGVyVGV4dCcsICdyb3dNb2RlbFR5cGUnLCAnZWRpdFR5cGUnLCAnZG9tTGF5b3V0JywgJ2NsaXBib2FyZERlbGltaXRlcicsICdyb3dHcm91cFBhbmVsU2hvdycsXG4gICAgICAgICdtdWx0aVNvcnRLZXknLCAncGl2b3RDb2x1bW5Hcm91cFRvdGFscycsICdwaXZvdFJvd1RvdGFscycsICdwaXZvdFBhbmVsU2hvdycsICdmaWxsSGFuZGxlRGlyZWN0aW9uJyxcbiAgICAgICAgJ3NlcnZlclNpZGVTdG9yZVR5cGUnLCAnZ3JvdXBEaXNwbGF5VHlwZScsICd0cmVlRGF0YURpc3BsYXlUeXBlJ1xuICAgIF07XG4gICAgUHJvcGVydHlLZXlzLk9CSkVDVF9QUk9QRVJUSUVTID0gW1xuICAgICAgICAnY29tcG9uZW50cycsICdmcmFtZXdvcmtDb21wb25lbnRzJywgJ3Jvd1N0eWxlJywgJ2NvbnRleHQnLCAnYXV0b0dyb3VwQ29sdW1uRGVmJywgJ2xvY2FsZVRleHQnLCAnaWNvbnMnLFxuICAgICAgICAnZGF0YXNvdXJjZScsICdzZXJ2ZXJTaWRlRGF0YXNvdXJjZScsICd2aWV3cG9ydERhdGFzb3VyY2UnLCAnZ3JvdXBSb3dSZW5kZXJlclBhcmFtcycsICdhZ2dGdW5jcycsICdmdWxsV2lkdGhDZWxsUmVuZGVyZXJQYXJhbXMnLFxuICAgICAgICAnZGVmYXVsdENvbEdyb3VwRGVmJywgJ2RlZmF1bHRDb2xEZWYnLCAnZGVmYXVsdEV4cG9ydFBhcmFtcycsICdkZWZhdWx0Q3N2RXhwb3J0UGFyYW1zJywgJ2RlZmF1bHRFeGNlbEV4cG9ydFBhcmFtcycsICdjb2x1bW5UeXBlcycsXG4gICAgICAgICdyb3dDbGFzc1J1bGVzJywgJ2RldGFpbENlbGxSZW5kZXJlclBhcmFtcycsICdsb2FkaW5nQ2VsbFJlbmRlcmVyUGFyYW1zJywgJ2xvYWRpbmdPdmVybGF5Q29tcG9uZW50UGFyYW1zJyxcbiAgICAgICAgJ25vUm93c092ZXJsYXlDb21wb25lbnRQYXJhbXMnLCAncG9wdXBQYXJlbnQnLCAnY29sUmVzaXplRGVmYXVsdCcsICdzdGF0dXNCYXInLCAnc2lkZUJhcicsICdjaGFydFRoZW1lT3ZlcnJpZGVzJyxcbiAgICAgICAgJ2N1c3RvbUNoYXJ0VGhlbWVzJywgJ2NoYXJ0VG9vbFBhbmVsc0RlZidcbiAgICBdO1xuICAgIFByb3BlcnR5S2V5cy5BUlJBWV9QUk9QRVJUSUVTID0gW1xuICAgICAgICAnYWxpZ25lZEdyaWRzJywgJ3Jvd0RhdGEnLCAnY29sdW1uRGVmcycsICdleGNlbFN0eWxlcycsICdwaW5uZWRUb3BSb3dEYXRhJywgJ3Bpbm5lZEJvdHRvbVJvd0RhdGEnLCAnY2hhcnRUaGVtZXMnXG4gICAgXTtcbiAgICBQcm9wZXJ0eUtleXMuTlVNQkVSX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdyb3dIZWlnaHQnLCAnZGV0YWlsUm93SGVpZ2h0JywgJ3Jvd0J1ZmZlcicsICdjb2xXaWR0aCcsICdoZWFkZXJIZWlnaHQnLCAnZ3JvdXBIZWFkZXJIZWlnaHQnLCAnZmxvYXRpbmdGaWx0ZXJzSGVpZ2h0JyxcbiAgICAgICAgJ3Bpdm90SGVhZGVySGVpZ2h0JywgJ3Bpdm90R3JvdXBIZWFkZXJIZWlnaHQnLCAnZ3JvdXBEZWZhdWx0RXhwYW5kZWQnLCAnbWluQ29sV2lkdGgnLCAnbWF4Q29sV2lkdGgnLCAndmlld3BvcnRSb3dNb2RlbFBhZ2VTaXplJyxcbiAgICAgICAgJ3ZpZXdwb3J0Um93TW9kZWxCdWZmZXJTaXplJywgJ2F1dG9TaXplUGFkZGluZycsICdtYXhCbG9ja3NJbkNhY2hlJywgJ21heENvbmN1cnJlbnREYXRhc291cmNlUmVxdWVzdHMnLCAndG9vbHRpcFNob3dEZWxheScsXG4gICAgICAgICd0b29sdGlwSGlkZURlbGF5JywgJ2NhY2hlT3ZlcmZsb3dTaXplJywgJ3BhZ2luYXRpb25QYWdlU2l6ZScsICdjYWNoZUJsb2NrU2l6ZScsICdpbmZpbml0ZUluaXRpYWxSb3dDb3VudCcsICdzZXJ2ZXJTaWRlSW5pdGlhbFJvd0NvdW50JywgJ3Njcm9sbGJhcldpZHRoJyxcbiAgICAgICAgJ2JhdGNoVXBkYXRlV2FpdE1pbGxpcycsICdhc3luY1RyYW5zYWN0aW9uV2FpdE1pbGxpcycsICdibG9ja0xvYWREZWJvdW5jZU1pbGxpcycsICdrZWVwRGV0YWlsUm93c0NvdW50JyxcbiAgICAgICAgJ3VuZG9SZWRvQ2VsbEVkaXRpbmdMaW1pdCcsICdjZWxsRmxhc2hEZWxheScsICdjZWxsRmFkZURlbGF5JywgJ3RhYkluZGV4J1xuICAgIF07XG4gICAgUHJvcGVydHlLZXlzLkJPT0xFQU5fUFJPUEVSVElFUyA9IFtcbiAgICAgICAgJ3N1cHByZXNzTWFrZUNvbHVtblZpc2libGVBZnRlclVuR3JvdXAnLCAnc3VwcHJlc3NSb3dDbGlja1NlbGVjdGlvbicsICdzdXBwcmVzc0NlbGxTZWxlY3Rpb24nLCAnc3VwcHJlc3NDZWxsRm9jdXMnLCAnc3VwcHJlc3NIb3Jpem9udGFsU2Nyb2xsJyxcbiAgICAgICAgJ2Fsd2F5c1Nob3dIb3Jpem9udGFsU2Nyb2xsJywgJ2Fsd2F5c1Nob3dWZXJ0aWNhbFNjcm9sbCcsICdkZWJ1ZycsICdlbmFibGVCcm93c2VyVG9vbHRpcHMnLCAnZW5hYmxlQ2VsbEV4cHJlc3Npb25zJyxcbiAgICAgICAgJ2FuZ3VsYXJDb21waWxlUm93cycsICdhbmd1bGFyQ29tcGlsZUZpbHRlcnMnLCAnZ3JvdXBTdXBwcmVzc0F1dG9Db2x1bW4nLCAnZ3JvdXBTZWxlY3RzQ2hpbGRyZW4nLCAnZ3JvdXBJbmNsdWRlRm9vdGVyJyxcbiAgICAgICAgJ2dyb3VwSW5jbHVkZVRvdGFsRm9vdGVyJywgJ2dyb3VwVXNlRW50aXJlUm93JywgJ2dyb3VwU3VwcHJlc3NCbGFua0hlYWRlcicsICdzdXBwcmVzc01lbnVIaWRlJywgJ3N1cHByZXNzUm93RGVzZWxlY3Rpb24nLFxuICAgICAgICAndW5Tb3J0SWNvbicsICdzdXBwcmVzc011bHRpU29ydCcsICdhbHdheXNNdWx0aVNvcnQnLCAnc2luZ2xlQ2xpY2tFZGl0JywgJ3N1cHByZXNzTG9hZGluZ092ZXJsYXknLCAnc3VwcHJlc3NOb1Jvd3NPdmVybGF5JywgJ3N1cHByZXNzQXV0b1NpemUnLFxuICAgICAgICAnc2tpcEhlYWRlck9uQXV0b1NpemUnLCAnc3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2RlcycsICdzdXBwcmVzc0NvbHVtbk1vdmVBbmltYXRpb24nLCAnc3VwcHJlc3NNb3ZhYmxlQ29sdW1ucycsXG4gICAgICAgICdzdXBwcmVzc0ZpZWxkRG90Tm90YXRpb24nLCAnZW5hYmxlUmFuZ2VTZWxlY3Rpb24nLCAnZW5hYmxlUmFuZ2VIYW5kbGUnLCAnZW5hYmxlRmlsbEhhbmRsZScsICdzdXBwcmVzc0NsZWFyT25GaWxsUmVkdWN0aW9uJyxcbiAgICAgICAgJ2RlbHRhU29ydCcsICdzdXBwcmVzc1RvdWNoJywgJ3N1cHByZXNzQXN5bmNFdmVudHMnLCAnYWxsb3dDb250ZXh0TWVudVdpdGhDb250cm9sS2V5JywgJ3N1cHByZXNzQ29udGV4dE1lbnUnLFxuICAgICAgICAncmVtZW1iZXJHcm91cFN0YXRlV2hlbk5ld0RhdGEnLCAnZW5hYmxlQ2VsbENoYW5nZUZsYXNoJywgJ3N1cHByZXNzRHJhZ0xlYXZlSGlkZXNDb2x1bW5zJywgJ3N1cHByZXNzUm93R3JvdXBIaWRlc0NvbHVtbnMnLCAnc3VwcHJlc3NNaWRkbGVDbGlja1Njcm9sbHMnLFxuICAgICAgICAnc3VwcHJlc3NQcmV2ZW50RGVmYXVsdE9uTW91c2VXaGVlbCcsICdzdXBwcmVzc0NvcHlSb3dzVG9DbGlwYm9hcmQnLCAnY29weUhlYWRlcnNUb0NsaXBib2FyZCcsICdjb3B5R3JvdXBIZWFkZXJzVG9DbGlwYm9hcmQnLFxuICAgICAgICAncGl2b3RNb2RlJywgJ3N1cHByZXNzQWdnRnVuY0luSGVhZGVyJywgJ3N1cHByZXNzQ29sdW1uVmlydHVhbGlzYXRpb24nLCAnc3VwcHJlc3NBZ2dBdFJvb3RMZXZlbCcsICdzdXBwcmVzc0ZvY3VzQWZ0ZXJSZWZyZXNoJyxcbiAgICAgICAgJ2Z1bmN0aW9uc1Bhc3NpdmUnLCAnZnVuY3Rpb25zUmVhZE9ubHknLCAnYW5pbWF0ZVJvd3MnLCAnZ3JvdXBTZWxlY3RzRmlsdGVyZWQnLCAnZ3JvdXBSZW1vdmVTaW5nbGVDaGlsZHJlbicsXG4gICAgICAgICdncm91cFJlbW92ZUxvd2VzdFNpbmdsZUNoaWxkcmVuJywgJ2VuYWJsZVJ0bCcsICdzdXBwcmVzc0NsaWNrRWRpdCcsICdyb3dEcmFnRW50aXJlUm93JywgJ3Jvd0RyYWdNYW5hZ2VkJywgJ3N1cHByZXNzUm93RHJhZycsXG4gICAgICAgICdzdXBwcmVzc01vdmVXaGVuUm93RHJhZ2dpbmcnLCAncm93RHJhZ011bHRpUm93JywgJ2VuYWJsZUdyb3VwRWRpdCcsICdlbWJlZEZ1bGxXaWR0aFJvd3MnLCAnZGVwcmVjYXRlZEVtYmVkRnVsbFdpZHRoUm93cycsXG4gICAgICAgICdzdXBwcmVzc1BhZ2luYXRpb25QYW5lbCcsICdncm91cEhpZGVPcGVuUGFyZW50cycsICdncm91cE11bHRpQXV0b0NvbHVtbicsICdwYWdpbmF0aW9uJyxcbiAgICAgICAgJ3N0b3BFZGl0aW5nV2hlbkdyaWRMb3Nlc0ZvY3VzJywgJ3BhZ2luYXRpb25BdXRvUGFnZVNpemUnLCAnc3VwcHJlc3NTY3JvbGxPbk5ld0RhdGEnLCAnc3VwcHJlc3NTY3JvbGxXaGVuUG9wdXBzQXJlT3BlbicsXG4gICAgICAgICdwdXJnZUNsb3NlZFJvd05vZGVzJywgJ2NhY2hlUXVpY2tGaWx0ZXInLCAnZGVsdGFSb3dEYXRhTW9kZScsICdlbnN1cmVEb21PcmRlcicsICdhY2NlbnRlZFNvcnQnLCAnc3VwcHJlc3NDaGFuZ2VEZXRlY3Rpb24nLFxuICAgICAgICAndmFsdWVDYWNoZScsICd2YWx1ZUNhY2hlTmV2ZXJFeHBpcmVzJywgJ2FnZ3JlZ2F0ZU9ubHlDaGFuZ2VkQ29sdW1ucycsICdzdXBwcmVzc0FuaW1hdGlvbkZyYW1lJywgJ3N1cHByZXNzRXhjZWxFeHBvcnQnLFxuICAgICAgICAnc3VwcHJlc3NDc3ZFeHBvcnQnLCAndHJlZURhdGEnLCAnbWFzdGVyRGV0YWlsJywgJ3N1cHByZXNzTXVsdGlSYW5nZVNlbGVjdGlvbicsICdlbnRlck1vdmVzRG93bkFmdGVyRWRpdCcsICdlbnRlck1vdmVzRG93bicsXG4gICAgICAgICdzdXBwcmVzc1Byb3BlcnR5TmFtZXNDaGVjaycsICdyb3dNdWx0aVNlbGVjdFdpdGhDbGljaycsICdzdXBwcmVzc0VudGVycHJpc2VSZXNldE9uTmV3Q29sdW1ucycsXG4gICAgICAgICdzdXBwcmVzc1Jvd0hvdmVySGlnaGxpZ2h0JywgJ3N1cHByZXNzUm93VHJhbnNmb3JtJywgJ3N1cHByZXNzQ2xpcGJvYXJkUGFzdGUnLCAnc3VwcHJlc3NMYXN0RW1wdHlMaW5lT25QYXN0ZScsXG4gICAgICAgICdzdXBwcmVzc1NldENvbHVtblN0YXRlRXZlbnRzJywgJ3N1cHByZXNzQ29sdW1uU3RhdGVFdmVudHMnLCAnZW5hYmxlQ2hhcnRzJywgJ2VuYWJsZUNoYXJ0VG9vbFBhbmVsc0J1dHRvbicsICdkZWx0YUNvbHVtbk1vZGUnLFxuICAgICAgICAnc3VwcHJlc3NNYWludGFpblVuc29ydGVkT3JkZXInLCAnZW5hYmxlQ2VsbFRleHRTZWxlY3Rpb24nLCAnc3VwcHJlc3NCcm93c2VyUmVzaXplT2JzZXJ2ZXInLCAnc3VwcHJlc3NNYXhSZW5kZXJlZFJvd1Jlc3RyaWN0aW9uJyxcbiAgICAgICAgJ2V4Y2x1ZGVDaGlsZHJlbldoZW5UcmVlRGF0YUZpbHRlcmluZycsICd0b29sdGlwTW91c2VUcmFjaycsICdrZWVwRGV0YWlsUm93cycsICdwYWdpbmF0ZUNoaWxkUm93cycsICdwcmV2ZW50RGVmYXVsdE9uQ29udGV4dE1lbnUnLFxuICAgICAgICAndW5kb1JlZG9DZWxsRWRpdGluZycsICdhbGxvd0RyYWdGcm9tQ29sdW1uc1Rvb2xQYW5lbCcsICdpbW11dGFibGVEYXRhJywgJ2ltbXV0YWJsZUNvbHVtbnMnLCAncGl2b3RTdXBwcmVzc0F1dG9Db2x1bW4nLFxuICAgICAgICAnc3VwcHJlc3NFeHBhbmRhYmxlUGl2b3RHcm91cHMnLCAnYXBwbHlDb2x1bW5EZWZPcmRlcicsICdkZWJvdW5jZVZlcnRpY2FsU2Nyb2xsYmFyJywgJ2RldGFpbFJvd0F1dG9IZWlnaHQnLFxuICAgICAgICAnc2VydmVyU2lkZUZpbHRlcmluZ0Fsd2F5c1Jlc2V0cycsICdzZXJ2ZXJTaWRlU29ydGluZ0Fsd2F5c1Jlc2V0cycsICdzZXJ2ZXJTaWRlU29ydEFsbExldmVscycsICdzZXJ2ZXJTaWRlRmlsdGVyQWxsTGV2ZWxzJyxcbiAgICAgICAgJ3NlcnZlclNpZGVTb3J0T25TZXJ2ZXInLCAnc2VydmVyU2lkZUZpbHRlck9uU2VydmVyJywgJ3N1cHByZXNzQWdnRmlsdGVyZWRPbmx5JywgJ3Nob3dPcGVuZWRHcm91cCcsICdzdXBwcmVzc0NsaXBib2FyZEFwaScsXG4gICAgICAgICdzdXBwcmVzc01vZGVsVXBkYXRlQWZ0ZXJVcGRhdGVUcmFuc2FjdGlvbicsICdzdG9wRWRpdGluZ1doZW5DZWxsc0xvc2VGb2N1cycsICdtYWludGFpbkNvbHVtbk9yZGVyJywgJ2dyb3VwTWFpbnRhaW5PcmRlcicsXG4gICAgICAgICdjb2x1bW5Ib3ZlckhpZ2hsaWdodCcsICdyZWFjdFVpJywgJ3N1cHByZXNzUmVhY3RVaScsICdyZWFkT25seUVkaXQnLCAnc3VwcHJlc3NSb3dWaXJ0dWFsaXNhdGlvbicsICdlbmFibGVDZWxsRWRpdGluZ09uQmFja3NwYWNlJyxcbiAgICAgICAgJ3Jlc2V0Um93RGF0YU9uVXBkYXRlJywgJ3JlbW92ZVBpdm90SGVhZGVyUm93V2hlblNpbmdsZVZhbHVlQ29sdW1uJywgJ3N1cHByZXNzQ29weVNpbmdsZUNlbGxSYW5nZXMnLFxuICAgICAgICAnZ3JvdXBSb3dzU3RpY2t5JywgJ3NlcnZlclNpZGVJbmZpbml0ZVNjcm9sbCcsICdyb3dHcm91cFBhbmVsU3VwcHJlc3NTb3J0JyxcbiAgICBdO1xuICAgIC8qKiBZb3UgZG8gbm90IG5lZWQgdG8gaW5jbHVkZSBldmVudCBjYWxsYmFja3MgaW4gdGhpcyBsaXN0LCBhcyB0aGV5IGFyZSBnZW5lcmF0ZWQgYXV0b21hdGljYWxseS4gKi9cbiAgICBQcm9wZXJ0eUtleXMuRlVOQ1RJT05fUFJPUEVSVElFUyA9IFtcbiAgICAgICAgJ2xvY2FsZVRleHRGdW5jJywgJ2dldExvY2FsZVRleHQnLCAnZ3JvdXBSb3dJbm5lclJlbmRlcmVyJywgJ2dyb3VwUm93SW5uZXJSZW5kZXJlckZyYW1ld29yaycsICdncm91cFJvd1JlbmRlcmVyJywgJ2dyb3VwUm93UmVuZGVyZXJGcmFtZXdvcmsnLFxuICAgICAgICAnaXNFeHRlcm5hbEZpbHRlclByZXNlbnQnLCAnZ2V0Um93SGVpZ2h0JywgJ2RvZXNFeHRlcm5hbEZpbHRlclBhc3MnLCAnZ2V0Um93Q2xhc3MnLCAnZ2V0Um93U3R5bGUnLCAnZ2V0Q29udGV4dE1lbnVJdGVtcycsICdnZXRNYWluTWVudUl0ZW1zJyxcbiAgICAgICAgJ3Byb2Nlc3NSb3dQb3N0Q3JlYXRlJywgJ3Byb2Nlc3NDZWxsRm9yQ2xpcGJvYXJkJywgJ2dyb3VwUm93QWdnTm9kZXMnLCAnZ2V0R3JvdXBSb3dBZ2cnLCAnZ2V0Um93Tm9kZUlkJywgJ2lzRnVsbFdpZHRoQ2VsbCcsICdpc0Z1bGxXaWR0aFJvdycsXG4gICAgICAgICdmdWxsV2lkdGhDZWxsUmVuZGVyZXInLCAnZnVsbFdpZHRoQ2VsbFJlbmRlcmVyRnJhbWV3b3JrJywgJ3Byb2Nlc3NTZWNvbmRhcnlDb2xEZWYnLCAncHJvY2Vzc1NlY29uZGFyeUNvbEdyb3VwRGVmJywgJ3Byb2Nlc3NQaXZvdFJlc3VsdENvbERlZicsXG4gICAgICAgICdwcm9jZXNzUGl2b3RSZXN1bHRDb2xHcm91cERlZicsICdnZXRCdXNpbmVzc0tleUZvck5vZGUnLCAnc2VuZFRvQ2xpcGJvYXJkJywgJ25hdmlnYXRlVG9OZXh0SGVhZGVyJywgJ3RhYlRvTmV4dEhlYWRlcicsICduYXZpZ2F0ZVRvTmV4dENlbGwnLFxuICAgICAgICAndGFiVG9OZXh0Q2VsbCcsICdwcm9jZXNzQ2VsbEZyb21DbGlwYm9hcmQnLCAnZ2V0RG9jdW1lbnQnLCAncG9zdFByb2Nlc3NQb3B1cCcsICdnZXRDaGlsZENvdW50JywgJ2dldERhdGFQYXRoJywgJ2xvYWRpbmdDZWxsUmVuZGVyZXInLFxuICAgICAgICAnbG9hZGluZ0NlbGxSZW5kZXJlckZyYW1ld29yaycsICdsb2FkaW5nT3ZlcmxheUNvbXBvbmVudCcsICdsb2FkaW5nT3ZlcmxheUNvbXBvbmVudEZyYW1ld29yaycsICdub1Jvd3NPdmVybGF5Q29tcG9uZW50JywgJ25vUm93c092ZXJsYXlDb21wb25lbnRGcmFtZXdvcmsnLFxuICAgICAgICAnZGV0YWlsQ2VsbFJlbmRlcmVyJywgJ2RldGFpbENlbGxSZW5kZXJlckZyYW1ld29yaycsICdpc1Jvd01hc3RlcicsICdpc1Jvd1NlbGVjdGFibGUnLCAncG9zdFNvcnQnLCAncG9zdFNvcnRSb3dzJywgJ3Byb2Nlc3NIZWFkZXJGb3JDbGlwYm9hcmQnLFxuICAgICAgICAncHJvY2Vzc0dyb3VwSGVhZGVyRm9yQ2xpcGJvYXJkJywgJ3BhZ2luYXRpb25OdW1iZXJGb3JtYXR0ZXInLCAncHJvY2Vzc0RhdGFGcm9tQ2xpcGJvYXJkJywgJ2dldFNlcnZlclNpZGVHcm91cEtleScsICdpc1NlcnZlclNpZGVHcm91cCcsICdzdXBwcmVzc0tleWJvYXJkRXZlbnQnLFxuICAgICAgICAnY3JlYXRlQ2hhcnRDb250YWluZXInLCAnZ2V0Q2hhcnRUb29sYmFySXRlbXMnLCAnZmlsbE9wZXJhdGlvbicsICdpc0FwcGx5U2VydmVyU2lkZVRyYW5zYWN0aW9uJywgJ2dldFNlcnZlclNpZGVTdG9yZVBhcmFtcycsICdnZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFBhcmFtcycsXG4gICAgICAgICdpc1NlcnZlclNpZGVHcm91cE9wZW5CeURlZmF1bHQnLCAnaXNHcm91cE9wZW5CeURlZmF1bHQnLCAnZGVmYXVsdEdyb3VwU29ydENvbXBhcmF0b3InLCAnZGVmYXVsdEdyb3VwT3JkZXJDb21wYXJhdG9yJywgJ2luaXRpYWxHcm91cE9yZGVyQ29tcGFyYXRvcicsXG4gICAgICAgICdsb2FkaW5nQ2VsbFJlbmRlcmVyU2VsZWN0b3InLCAnZ2V0Um93SWQnLCAnZ3JvdXBBZ2dGaWx0ZXJpbmcnLCAncm93RHJhZ1RleHQnXG4gICAgXTtcbiAgICBQcm9wZXJ0eUtleXMuQUxMX1BST1BFUlRJRVMgPSBfX3NwcmVhZCRpKFByb3BlcnR5S2V5cy5BUlJBWV9QUk9QRVJUSUVTLCBQcm9wZXJ0eUtleXMuT0JKRUNUX1BST1BFUlRJRVMsIFByb3BlcnR5S2V5cy5TVFJJTkdfUFJPUEVSVElFUywgUHJvcGVydHlLZXlzLk5VTUJFUl9QUk9QRVJUSUVTLCBQcm9wZXJ0eUtleXMuRlVOQ1RJT05fUFJPUEVSVElFUywgUHJvcGVydHlLZXlzLkJPT0xFQU5fUFJPUEVSVElFUyk7XG4gICAgLyoqXG4gICAgICogVXNlZCB3aGVuIHBlcmZvcm1pbmcgcHJvcGVydHkgY2hlY2tzLiBUaGlzIGF2b2lkcyBub2lzZSBjYXVzZWQgd2hlbiB1c2luZyBmcmFtZXdvcmtzLCB3aGljaCBjYW4gYWRkIHRoZWlyIG93blxuICAgICAqIGZyYW1ld29yay1zcGVjaWZpYyBwcm9wZXJ0aWVzIHRvIGNvbERlZnMsIGdyaWRPcHRpb25zIGV0Yy5cbiAgICAgKi9cbiAgICBQcm9wZXJ0eUtleXMuRlJBTUVXT1JLX1BST1BFUlRJRVMgPSBbXG4gICAgICAgICdfX29iX18nLCAnX192X3NraXAnLCAnX19tZXRhZGF0YV9fJywgJ21hcHBlZENvbHVtblByb3BlcnRpZXMnLCAnaGFzQ2hpbGRDb2x1bW5zJywgJ3RvQ29sRGVmJywgJ2NyZWF0ZUNvbERlZkZyb21HcmlkQ29sdW1uJ1xuICAgIF07XG4gICAgcmV0dXJuIFByb3BlcnR5S2V5cztcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2Fzc2lnbiRoID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiRoID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fcmVhZCRuID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIF9fc3ByZWFkJGggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3NwcmVhZCkgfHwgZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhciA9IGFyLmNvbmNhdChfX3JlYWQkbihhcmd1bWVudHNbaV0pKTtcbiAgICByZXR1cm4gYXI7XG59O1xudmFyIENvbXBvbmVudFV0aWwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29tcG9uZW50VXRpbCgpIHtcbiAgICB9XG4gICAgQ29tcG9uZW50VXRpbC5nZXRFdmVudENhbGxiYWNrcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFDb21wb25lbnRVdGlsLkVWRU5UX0NBTExCQUNLUykge1xuICAgICAgICAgICAgQ29tcG9uZW50VXRpbC5FVkVOVF9DQUxMQkFDS1MgPSBDb21wb25lbnRVdGlsLkVWRU5UUy5tYXAoZnVuY3Rpb24gKGV2ZW50KSB7IHJldHVybiBDb21wb25lbnRVdGlsLmdldENhbGxiYWNrRm9yRXZlbnQoZXZlbnQpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQ29tcG9uZW50VXRpbC5FVkVOVF9DQUxMQkFDS1M7XG4gICAgfTtcbiAgICBDb21wb25lbnRVdGlsLmNvcHlBdHRyaWJ1dGVzVG9HcmlkT3B0aW9ucyA9IGZ1bmN0aW9uIChncmlkT3B0aW9ucywgY29tcG9uZW50LCBza2lwRXZlbnREZXByZWNhdGlvbkNoZWNrKSB7XG4gICAgICAgIC8vIGNyZWF0ZSBlbXB0eSBncmlkIG9wdGlvbnMgaWYgbm9uZSB3ZXJlIHBhc3NlZFxuICAgICAgICBpZiAodHlwZW9mIGdyaWRPcHRpb25zICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgZ3JpZE9wdGlvbnMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0byBhbGxvdyBhcnJheSBzdHlsZSBsb29rdXAgaW4gVHlwZVNjcmlwdCwgdGFrZSB0eXBlIGF3YXkgZnJvbSAndGhpcycgYW5kICdncmlkT3B0aW9ucydcbiAgICAgICAgdmFyIHBHcmlkT3B0aW9ucyA9IGdyaWRPcHRpb25zO1xuICAgICAgICB2YXIga2V5RXhpc3RzID0gZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gdHlwZW9mIGNvbXBvbmVudFtrZXldICE9PSAndW5kZWZpbmVkJzsgfTtcbiAgICAgICAgLy8gaWYgZ3JvdXBBZ2dGaWx0ZXJpbmcgZXhpc3RzIGFuZCBpc24ndCBhIGZ1bmN0aW9uLCBoYW5kbGUgYXMgYSBib29sZWFuLlxuICAgICAgICBpZiAoa2V5RXhpc3RzKCdncm91cEFnZ0ZpbHRlcmluZycpICYmIHR5cGVvZiBjb21wb25lbnQuZ3JvdXBBZ2dGaWx0ZXJpbmcgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHBHcmlkT3B0aW9ucy5ncm91cEFnZ0ZpbHRlcmluZyA9IENvbXBvbmVudFV0aWwudG9Cb29sZWFuKGNvbXBvbmVudC5ncm91cEFnZ0ZpbHRlcmluZyk7XG4gICAgICAgICAgICBkZWxldGUgY29tcG9uZW50Lmdyb3VwQWdnRmlsdGVyaW5nO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFkZCBpbiBhbGwgdGhlIHNpbXBsZSBwcm9wZXJ0aWVzXG4gICAgICAgIF9fc3ByZWFkJGgoQ29tcG9uZW50VXRpbC5BUlJBWV9QUk9QRVJUSUVTLCBDb21wb25lbnRVdGlsLlNUUklOR19QUk9QRVJUSUVTLCBDb21wb25lbnRVdGlsLk9CSkVDVF9QUk9QRVJUSUVTLCBDb21wb25lbnRVdGlsLkZVTkNUSU9OX1BST1BFUlRJRVMsIENvbXBvbmVudFV0aWwuZ2V0RXZlbnRDYWxsYmFja3MoKSkuZmlsdGVyKGtleUV4aXN0cylcbiAgICAgICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIHBHcmlkT3B0aW9uc1trZXldID0gY29tcG9uZW50W2tleV07IH0pO1xuICAgICAgICBDb21wb25lbnRVdGlsLkJPT0xFQU5fUFJPUEVSVElFU1xuICAgICAgICAgICAgLmZpbHRlcihrZXlFeGlzdHMpXG4gICAgICAgICAgICAuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBwR3JpZE9wdGlvbnNba2V5XSA9IENvbXBvbmVudFV0aWwudG9Cb29sZWFuKGNvbXBvbmVudFtrZXldKTsgfSk7XG4gICAgICAgIENvbXBvbmVudFV0aWwuTlVNQkVSX1BST1BFUlRJRVNcbiAgICAgICAgICAgIC5maWx0ZXIoa2V5RXhpc3RzKVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gcEdyaWRPcHRpb25zW2tleV0gPSBDb21wb25lbnRVdGlsLnRvTnVtYmVyKGNvbXBvbmVudFtrZXldKTsgfSk7XG4gICAgICAgIHJldHVybiBncmlkT3B0aW9ucztcbiAgICB9O1xuICAgIENvbXBvbmVudFV0aWwuZ2V0Q2FsbGJhY2tGb3JFdmVudCA9IGZ1bmN0aW9uIChldmVudE5hbWUpIHtcbiAgICAgICAgaWYgKCFldmVudE5hbWUgfHwgZXZlbnROYW1lLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHJldHVybiBldmVudE5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdvbicgKyBldmVudE5hbWVbMF0udG9VcHBlckNhc2UoKSArIGV2ZW50TmFtZS5zdWJzdHIoMSk7XG4gICAgfTtcbiAgICBDb21wb25lbnRVdGlsLnByb2Nlc3NPbkNoYW5nZSA9IGZ1bmN0aW9uIChjaGFuZ2VzLCBncmlkT3B0aW9ucywgYXBpLCBjb2x1bW5BcGkpIHtcbiAgICAgICAgaWYgKCFjaGFuZ2VzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNoYW5nZXNUb0FwcGx5ID0gX19hc3NpZ24kaCh7fSwgY2hhbmdlcyk7XG4gICAgICAgIC8vIHRvIGFsbG93IGFycmF5IHN0eWxlIGxvb2t1cCBpbiBUeXBlU2NyaXB0LCB0YWtlIHR5cGUgYXdheSBmcm9tICd0aGlzJyBhbmQgJ2dyaWRPcHRpb25zJ1xuICAgICAgICB2YXIgcEdyaWRPcHRpb25zID0gZ3JpZE9wdGlvbnM7XG4gICAgICAgIHZhciBrZXlFeGlzdHMgPSBmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBjaGFuZ2VzVG9BcHBseVtrZXldOyB9O1xuICAgICAgICAvLyBpZiBncm91cEFnZ0ZpbHRlcmluZyBleGlzdHMgYW5kIGlzbid0IGEgZnVuY3Rpb24sIGhhbmRsZSBhcyBhIGJvb2xlYW4uXG4gICAgICAgIGlmIChrZXlFeGlzdHMoJ2dyb3VwQWdnRmlsdGVyaW5nJykpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2hhbmdlc1RvQXBwbHkuZ3JvdXBBZ2dGaWx0ZXJpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBwR3JpZE9wdGlvbnMuZ3JvdXBBZ2dGaWx0ZXJpbmcgPSBjaGFuZ2VzVG9BcHBseS5ncm91cEFnZ0ZpbHRlcmluZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHBHcmlkT3B0aW9ucy5ncm91cEFnZ0ZpbHRlcmluZyA9IENvbXBvbmVudFV0aWwudG9Cb29sZWFuKGNoYW5nZXNUb0FwcGx5Lmdyb3VwQWdnRmlsdGVyaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VzVG9BcHBseS5ncm91cEFnZ0ZpbHRlcmluZztcbiAgICAgICAgfVxuICAgICAgICBpZiAoa2V5RXhpc3RzKCdncm91cERpc3BsYXlUeXBlJykpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2hhbmdlc1RvQXBwbHkuZ3JvdXBEaXNwbGF5VHlwZS5jdXJyZW50VmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgYXBpLnNldEdyb3VwRGlzcGxheVR5cGUoY2hhbmdlc1RvQXBwbHkuZ3JvdXBEaXNwbGF5VHlwZS5jdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VzVG9BcHBseS5ncm91cERpc3BsYXlUeXBlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHdlIG5lZWQgdG8gZG8gdGhpcyBiZWZvcmUgdGhlIGdlbmVyaWMgaGFuZGxpbmcsIG90aGVyd2lzZSB2YWx1ZSBnZXRzIHNldCBiZWZvcmUgd2VcbiAgICAgICAgLy8gdHJ5IHRvIHNldCBpdCwgYW5kIHRoZSBncmlkIHRoZW4gZG9lc24ndCByZWZyZXNoIHRoZSByb3dzIGFzIGl0IGRvZXNuJ3Qgc2VlIGFueSBjaGFuZ2UuXG4gICAgICAgIC8vIGFsc28gaXQncyBwb3NzaWJsZSB3ZSB1c2UgdGhlIGdlbmVyaWMgY29kZSBzZXRYWFggYmVsb3cgYW5kIHB1dCBpdCB1cCB0aGVyZSBpbnN0ZWFkLFxuICAgICAgICAvLyBjb3ZlciBhbGwgY2FzZXMuXG4gICAgICAgIGlmIChjaGFuZ2VzVG9BcHBseS5yb3dDbGFzcykge1xuICAgICAgICAgICAgYXBpLnNldFJvd0NsYXNzKGNoYW5nZXNUb0FwcGx5LnJvd0NsYXNzLmN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICBkZWxldGUgY2hhbmdlc1RvQXBwbHkucm93Q2xhc3M7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2hlY2sgaWYgYW55IGNoYW5nZSBmb3IgdGhlIHNpbXBsZSB0eXBlcywgYW5kIGlmIHNvLCB0aGVuIGp1c3QgY29weSBpbiB0aGUgbmV3IHZhbHVlXG4gICAgICAgIF9fc3ByZWFkJGgoQ29tcG9uZW50VXRpbC5BUlJBWV9QUk9QRVJUSUVTLCBDb21wb25lbnRVdGlsLk9CSkVDVF9QUk9QRVJUSUVTLCBDb21wb25lbnRVdGlsLlNUUklOR19QUk9QRVJUSUVTLCBDb21wb25lbnRVdGlsLmdldEV2ZW50Q2FsbGJhY2tzKCkpLmZpbHRlcihrZXlFeGlzdHMpXG4gICAgICAgICAgICAuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBwR3JpZE9wdGlvbnNba2V5XSA9IGNoYW5nZXNUb0FwcGx5W2tleV0uY3VycmVudFZhbHVlOyB9KTtcbiAgICAgICAgQ29tcG9uZW50VXRpbC5CT09MRUFOX1BST1BFUlRJRVNcbiAgICAgICAgICAgIC5maWx0ZXIoa2V5RXhpc3RzKVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gcEdyaWRPcHRpb25zW2tleV0gPSBDb21wb25lbnRVdGlsLnRvQm9vbGVhbihjaGFuZ2VzVG9BcHBseVtrZXldLmN1cnJlbnRWYWx1ZSk7IH0pO1xuICAgICAgICBDb21wb25lbnRVdGlsLk5VTUJFUl9QUk9QRVJUSUVTXG4gICAgICAgICAgICAuZmlsdGVyKGtleUV4aXN0cylcbiAgICAgICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIHBHcmlkT3B0aW9uc1trZXldID0gQ29tcG9uZW50VXRpbC50b051bWJlcihjaGFuZ2VzVG9BcHBseVtrZXldLmN1cnJlbnRWYWx1ZSk7IH0pO1xuICAgICAgICBpZiAoY2hhbmdlc1RvQXBwbHkuZW5hYmxlQ2VsbFRleHRTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIGFwaS5zZXRFbmFibGVDZWxsVGV4dFNlbGVjdGlvbihDb21wb25lbnRVdGlsLnRvQm9vbGVhbihjaGFuZ2VzVG9BcHBseS5lbmFibGVDZWxsVGV4dFNlbGVjdGlvbi5jdXJyZW50VmFsdWUpKTtcbiAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VzVG9BcHBseS5lbmFibGVDZWxsVGV4dFNlbGVjdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlc1RvQXBwbHkucXVpY2tGaWx0ZXJUZXh0KSB7XG4gICAgICAgICAgICBhcGkuc2V0UXVpY2tGaWx0ZXIoY2hhbmdlc1RvQXBwbHkucXVpY2tGaWx0ZXJUZXh0LmN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICBkZWxldGUgY2hhbmdlc1RvQXBwbHkucXVpY2tGaWx0ZXJUZXh0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VzVG9BcHBseS5hdXRvR3JvdXBDb2x1bW5EZWYpIHtcbiAgICAgICAgICAgIGFwaS5zZXRBdXRvR3JvdXBDb2x1bW5EZWYoY2hhbmdlc1RvQXBwbHkuYXV0b0dyb3VwQ29sdW1uRGVmLmN1cnJlbnRWYWx1ZSwgXCJncmlkT3B0aW9uc0NoYW5nZWRcIik7XG4gICAgICAgICAgICBkZWxldGUgY2hhbmdlc1RvQXBwbHkuYXV0b0dyb3VwQ29sdW1uRGVmO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VzVG9BcHBseS5jb2x1bW5EZWZzKSB7XG4gICAgICAgICAgICBhcGkuc2V0Q29sdW1uRGVmcyhjaGFuZ2VzVG9BcHBseS5jb2x1bW5EZWZzLmN1cnJlbnRWYWx1ZSwgXCJncmlkT3B0aW9uc0NoYW5nZWRcIik7XG4gICAgICAgICAgICBkZWxldGUgY2hhbmdlc1RvQXBwbHkuY29sdW1uRGVmcztcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlc1RvQXBwbHkuZGVmYXVsdENvbERlZikge1xuICAgICAgICAgICAgYXBpLnNldERlZmF1bHRDb2xEZWYoY2hhbmdlc1RvQXBwbHkuZGVmYXVsdENvbERlZi5jdXJyZW50VmFsdWUsIFwiZ3JpZE9wdGlvbnNDaGFuZ2VkXCIpO1xuICAgICAgICAgICAgZGVsZXRlIGNoYW5nZXNUb0FwcGx5LmRlZmF1bHRDb2xEZWY7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXNUb0FwcGx5LnBhZ2luYXRpb25QYWdlU2l6ZSkge1xuICAgICAgICAgICAgYXBpLnBhZ2luYXRpb25TZXRQYWdlU2l6ZShDb21wb25lbnRVdGlsLnRvTnVtYmVyKGNoYW5nZXNUb0FwcGx5LnBhZ2luYXRpb25QYWdlU2l6ZS5jdXJyZW50VmFsdWUpKTtcbiAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VzVG9BcHBseS5wYWdpbmF0aW9uUGFnZVNpemU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXNUb0FwcGx5LnBpdm90TW9kZSkge1xuICAgICAgICAgICAgY29sdW1uQXBpLnNldFBpdm90TW9kZShDb21wb25lbnRVdGlsLnRvQm9vbGVhbihjaGFuZ2VzVG9BcHBseS5waXZvdE1vZGUuY3VycmVudFZhbHVlKSk7XG4gICAgICAgICAgICBkZWxldGUgY2hhbmdlc1RvQXBwbHkucGl2b3RNb2RlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VzVG9BcHBseS5ncm91cFJlbW92ZVNpbmdsZUNoaWxkcmVuKSB7XG4gICAgICAgICAgICBhcGkuc2V0R3JvdXBSZW1vdmVTaW5nbGVDaGlsZHJlbihDb21wb25lbnRVdGlsLnRvQm9vbGVhbihjaGFuZ2VzVG9BcHBseS5ncm91cFJlbW92ZVNpbmdsZUNoaWxkcmVuLmN1cnJlbnRWYWx1ZSkpO1xuICAgICAgICAgICAgZGVsZXRlIGNoYW5nZXNUb0FwcGx5Lmdyb3VwUmVtb3ZlU2luZ2xlQ2hpbGRyZW47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXNUb0FwcGx5LnN1cHByZXNzUm93RHJhZykge1xuICAgICAgICAgICAgYXBpLnNldFN1cHByZXNzUm93RHJhZyhDb21wb25lbnRVdGlsLnRvQm9vbGVhbihjaGFuZ2VzVG9BcHBseS5zdXBwcmVzc1Jvd0RyYWcuY3VycmVudFZhbHVlKSk7XG4gICAgICAgICAgICBkZWxldGUgY2hhbmdlc1RvQXBwbHkuc3VwcHJlc3NSb3dEcmFnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VzVG9BcHBseS5zdXBwcmVzc01vdmVXaGVuUm93RHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIGFwaS5zZXRTdXBwcmVzc01vdmVXaGVuUm93RHJhZ2dpbmcoQ29tcG9uZW50VXRpbC50b0Jvb2xlYW4oY2hhbmdlc1RvQXBwbHkuc3VwcHJlc3NNb3ZlV2hlblJvd0RyYWdnaW5nLmN1cnJlbnRWYWx1ZSkpO1xuICAgICAgICAgICAgZGVsZXRlIGNoYW5nZXNUb0FwcGx5LnN1cHByZXNzTW92ZVdoZW5Sb3dEcmFnZ2luZztcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlc1RvQXBwbHkuc3VwcHJlc3NSb3dDbGlja1NlbGVjdGlvbikge1xuICAgICAgICAgICAgYXBpLnNldFN1cHByZXNzUm93Q2xpY2tTZWxlY3Rpb24oQ29tcG9uZW50VXRpbC50b0Jvb2xlYW4oY2hhbmdlc1RvQXBwbHkuc3VwcHJlc3NSb3dDbGlja1NlbGVjdGlvbi5jdXJyZW50VmFsdWUpKTtcbiAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VzVG9BcHBseS5zdXBwcmVzc1Jvd0NsaWNrU2VsZWN0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaGFuZ2VzVG9BcHBseS5zdXBwcmVzc0NsaXBib2FyZFBhc3RlKSB7XG4gICAgICAgICAgICBhcGkuc2V0U3VwcHJlc3NDbGlwYm9hcmRQYXN0ZShDb21wb25lbnRVdGlsLnRvQm9vbGVhbihjaGFuZ2VzVG9BcHBseS5zdXBwcmVzc0NsaXBib2FyZFBhc3RlLmN1cnJlbnRWYWx1ZSkpO1xuICAgICAgICAgICAgZGVsZXRlIGNoYW5nZXNUb0FwcGx5LnN1cHByZXNzQ2xpcGJvYXJkUGFzdGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXNUb0FwcGx5LmhlYWRlckhlaWdodCkge1xuICAgICAgICAgICAgYXBpLnNldEhlYWRlckhlaWdodChDb21wb25lbnRVdGlsLnRvTnVtYmVyKGNoYW5nZXNUb0FwcGx5LmhlYWRlckhlaWdodC5jdXJyZW50VmFsdWUpKTtcbiAgICAgICAgICAgIGRlbGV0ZSBjaGFuZ2VzVG9BcHBseS5oZWFkZXJIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYW55IHJlbWFpbmluZyBwcm9wZXJ0aWVzIGNhbiBiZSBzZXQgaW4gYSBnZW5lcmljIHdheVxuICAgICAgICAvLyBpZSB0aGUgc2V0dGVyIHRha2VzIHRoZSBmb3JtIG9mIHNldFhYWCBhbmQgdGhlIGFyZ3VtZW50IHJlcXVpcmVzIG5vIGZvcm1hdHRpbmcvdHJhbnNsYXRpb24gZmlyc3RcbiAgICAgICAgdmFyIGR5bmFtaWNBcGkgPSBhcGk7XG4gICAgICAgIE9iamVjdC5rZXlzKGNoYW5nZXNUb0FwcGx5KVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgICAgICB2YXIgc2V0dGVyTmFtZSA9IFwic2V0XCIgKyBwcm9wZXJ0eS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHByb3BlcnR5LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgIGlmIChkeW5hbWljQXBpW3NldHRlck5hbWVdKSB7XG4gICAgICAgICAgICAgICAgZHluYW1pY0FwaVtzZXR0ZXJOYW1lXShjaGFuZ2VzW3Byb3BlcnR5XS5jdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gY29weSBjaGFuZ2VzIGludG8gYW4gZXZlbnQgZm9yIGRpc3BhdGNoXG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DT01QT05FTlRfU1RBVEVfQ0hBTkdFRFxuICAgICAgICB9O1xuICAgICAgICBpdGVyYXRlT2JqZWN0KGNoYW5nZXMsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICBldmVudFtrZXldID0gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgICBhcGkuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBDb21wb25lbnRVdGlsLnRvQm9vbGVhbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gZm9yIGJvb2xlYW4sIGNvbXBhcmUgdG8gZW1wdHkgU3RyaW5nIHRvIGFsbG93IGF0dHJpYnV0ZXMgYXBwZWFyaW5nIHdpdGhcbiAgICAgICAgICAgIC8vIG5vIHZhbHVlIHRvIGJlIHRyZWF0ZWQgYXMgJ3RydWUnXG4gICAgICAgICAgICByZXR1cm4gdmFsdWUudG9VcHBlckNhc2UoKSA9PT0gJ1RSVUUnIHx8IHZhbHVlID09ICcnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIENvbXBvbmVudFV0aWwudG9OdW1iZXIgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIE51bWJlcih2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGFsbCB0aGUgZXZlbnRzIGFyZSBwb3B1bGF0ZWQgaW4gaGVyZSBBRlRFUiB0aGlzIGNsYXNzIChhdCB0aGUgYm90dG9tIG9mIHRoZSBmaWxlKS5cbiAgICBDb21wb25lbnRVdGlsLkVWRU5UUyA9IFtdO1xuICAgIC8vIGV2ZW50cyB0aGF0IGFyZSBhdmFpbGFibGUgZm9yIHVzZSBieSB1c2VycyBvZiBBRyBHcmlkIGFuZCBzbyBzaG91bGQgYmUgZG9jdW1lbnRlZFxuICAgIENvbXBvbmVudFV0aWwuUFVCTElDX0VWRU5UUyA9IFtdO1xuICAgIC8vIGV2ZW50cyB0aGF0IGFyZSBpbnRlcm5hbCB0byBBRyBHcmlkIGFuZCBzaG91bGQgbm90IGJlIGV4cG9zZWQgdG8gdXNlcnMgdmlhIGRvY3VtZW50YXRpb24gb3IgZ2VuZXJhdGVkIGZyYW1ld29yayBjb21wb25lbnRzXG4gICAgQ29tcG9uZW50VXRpbC5FWENMVURFRF9JTlRFUk5BTF9FVkVOVFMgPSBbXTtcbiAgICBDb21wb25lbnRVdGlsLlNUUklOR19QUk9QRVJUSUVTID0gUHJvcGVydHlLZXlzLlNUUklOR19QUk9QRVJUSUVTO1xuICAgIENvbXBvbmVudFV0aWwuT0JKRUNUX1BST1BFUlRJRVMgPSBQcm9wZXJ0eUtleXMuT0JKRUNUX1BST1BFUlRJRVM7XG4gICAgQ29tcG9uZW50VXRpbC5BUlJBWV9QUk9QRVJUSUVTID0gUHJvcGVydHlLZXlzLkFSUkFZX1BST1BFUlRJRVM7XG4gICAgQ29tcG9uZW50VXRpbC5OVU1CRVJfUFJPUEVSVElFUyA9IFByb3BlcnR5S2V5cy5OVU1CRVJfUFJPUEVSVElFUztcbiAgICBDb21wb25lbnRVdGlsLkJPT0xFQU5fUFJPUEVSVElFUyA9IFByb3BlcnR5S2V5cy5CT09MRUFOX1BST1BFUlRJRVM7XG4gICAgQ29tcG9uZW50VXRpbC5GVU5DVElPTl9QUk9QRVJUSUVTID0gUHJvcGVydHlLZXlzLkZVTkNUSU9OX1BST1BFUlRJRVM7XG4gICAgQ29tcG9uZW50VXRpbC5BTExfUFJPUEVSVElFUyA9IFByb3BlcnR5S2V5cy5BTExfUFJPUEVSVElFUztcbiAgICByZXR1cm4gQ29tcG9uZW50VXRpbDtcbn0oKSk7XG5Db21wb25lbnRVdGlsLkVWRU5UUyA9IHZhbHVlcyhFdmVudHMpO1xuLyoqIEV4Y2x1ZGUgdGhlIGZvbGxvd2luZyBpbnRlcm5hbCBldmVudHMgZnJvbSBjb2RlIGdlbmVyYXRpb24gdG8gcHJldmVudCBleHBvc2luZyB0aGVzZSBldmVudHMgdmlhIGZyYW1ld29yayBjb21wb25lbnRzICovXG5Db21wb25lbnRVdGlsLkVYQ0xVREVEX0lOVEVSTkFMX0VWRU5UUyA9IFtcbiAgICBFdmVudHMuRVZFTlRfU0NST0xMQkFSX1dJRFRIX0NIQU5HRUQsXG4gICAgRXZlbnRzLkVWRU5UX0NIRUNLQk9YX0NIQU5HRUQsXG4gICAgRXZlbnRzLkVWRU5UX0hFSUdIVF9TQ0FMRV9DSEFOR0VELFxuICAgIEV2ZW50cy5FVkVOVF9CT0RZX0hFSUdIVF9DSEFOR0VELFxuICAgIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19XSURUSF9DSEFOR0VELFxuICAgIEV2ZW50cy5FVkVOVF9TQ1JPTExfVklTSUJJTElUWV9DSEFOR0VELFxuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fSE9WRVJfQ0hBTkdFRCxcbiAgICBFdmVudHMuRVZFTlRfRkxBU0hfQ0VMTFMsXG4gICAgRXZlbnRzLkVWRU5UX1BBR0lOQVRJT05fUElYRUxfT0ZGU0VUX0NIQU5HRUQsXG4gICAgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9ST1dTX0NIQU5HRUQsXG4gICAgRXZlbnRzLkVWRU5UX0xFRlRfUElOTkVEX1dJRFRIX0NIQU5HRUQsXG4gICAgRXZlbnRzLkVWRU5UX1JJR0hUX1BJTk5FRF9XSURUSF9DSEFOR0VELFxuICAgIEV2ZW50cy5FVkVOVF9ST1dfQ09OVEFJTkVSX0hFSUdIVF9DSEFOR0VELFxuICAgIEV2ZW50cy5FVkVOVF9QT1BVUF9UT19GUk9OVCxcbiAgICBFdmVudHMuRVZFTlRfS0VZQk9BUkRfRk9DVVMsXG4gICAgRXZlbnRzLkVWRU5UX01PVVNFX0ZPQ1VTLFxuICAgIEV2ZW50cy5FVkVOVF9TVE9SRV9VUERBVEVELFxuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUEFORUxfSVRFTV9EUkFHX1NUQVJULFxuICAgIEV2ZW50cy5FVkVOVF9DT0xVTU5fUEFORUxfSVRFTV9EUkFHX0VORCxcbiAgICBFdmVudHMuRVZFTlRfRklMTF9TVEFSVCxcbiAgICBFdmVudHMuRVZFTlRfRklMTF9FTkQsXG4gICAgRXZlbnRzLkVWRU5UX0tFWV9TSE9SVENVVF9DSEFOR0VEX0NFTExfU1RBUlQsXG4gICAgRXZlbnRzLkVWRU5UX0tFWV9TSE9SVENVVF9DSEFOR0VEX0NFTExfRU5ELFxuICAgIEV2ZW50cy5FVkVOVF9GVUxMX1dJRFRIX1JPV19GT0NVU0VELFxuICAgIEV2ZW50cy5FVkVOVF9IRUFERVJfSEVJR0hUX0NIQU5HRUQsXG4gICAgRXZlbnRzLkVWRU5UX0NPTFVNTl9IRUFERVJfSEVJR0hUX0NIQU5HRURcbl07XG4vKiogRVZFTlRTIHRoYXQgc2hvdWxkIGJlIGV4cG9zZWQgdmlhIGNvZGUgZ2VuZXJhdGlvbiBmb3IgdGhlIGZyYW1ld29yayBjb21wb25lbnRzLiAgKi9cbkNvbXBvbmVudFV0aWwuUFVCTElDX0VWRU5UUyA9IENvbXBvbmVudFV0aWwuRVZFTlRTLmZpbHRlcihmdW5jdGlvbiAoZSkgeyByZXR1cm4gIWluY2x1ZGVzKENvbXBvbmVudFV0aWwuRVhDTFVERURfSU5URVJOQUxfRVZFTlRTLCBlKTsgfSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBTaWRlQmFyRGVmUGFyc2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNpZGVCYXJEZWZQYXJzZXIoKSB7XG4gICAgfVxuICAgIFNpZGVCYXJEZWZQYXJzZXIucGFyc2UgPSBmdW5jdGlvbiAodG9QYXJzZSkge1xuICAgICAgICBpZiAoIXRvUGFyc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0b1BhcnNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHRvb2xQYW5lbHM6IFtcbiAgICAgICAgICAgICAgICAgICAgU2lkZUJhckRlZlBhcnNlci5ERUZBVUxUX0NPTFVNTl9DT01QLFxuICAgICAgICAgICAgICAgICAgICBTaWRlQmFyRGVmUGFyc2VyLkRFRkFVTFRfRklMVEVSX0NPTVAsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBkZWZhdWx0VG9vbFBhbmVsOiAnY29sdW1ucydcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB0b1BhcnNlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIFNpZGVCYXJEZWZQYXJzZXIucGFyc2UoW3RvUGFyc2VdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh0b1BhcnNlKSkge1xuICAgICAgICAgICAgdmFyIGNvbXBzXzEgPSBbXTtcbiAgICAgICAgICAgIHRvUGFyc2UuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGxvb2t1cFJlc3VsdCA9IFNpZGVCYXJEZWZQYXJzZXIuREVGQVVMVF9CWV9LRVlba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoIWxvb2t1cFJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiB0aGUga2V5IFwiICsga2V5ICsgXCIgaXMgbm90IGEgdmFsaWQga2V5IGZvciBzcGVjaWZ5aW5nIGEgdG9vbCBwYW5lbCwgdmFsaWQga2V5cyBhcmU6IFwiICsgT2JqZWN0LmtleXMoU2lkZUJhckRlZlBhcnNlci5ERUZBVUxUX0JZX0tFWSkuam9pbignLCcpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb21wc18xLnB1c2gobG9va3VwUmVzdWx0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKGNvbXBzXzEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHRvb2xQYW5lbHM6IGNvbXBzXzEsXG4gICAgICAgICAgICAgICAgZGVmYXVsdFRvb2xQYW5lbDogY29tcHNfMVswXS5pZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgICAgICAgdG9vbFBhbmVsczogU2lkZUJhckRlZlBhcnNlci5wYXJzZUNvbXBvbmVudHModG9QYXJzZS50b29sUGFuZWxzKSxcbiAgICAgICAgICAgIGRlZmF1bHRUb29sUGFuZWw6IHRvUGFyc2UuZGVmYXVsdFRvb2xQYW5lbCxcbiAgICAgICAgICAgIGhpZGRlbkJ5RGVmYXVsdDogdG9QYXJzZS5oaWRkZW5CeURlZmF1bHQsXG4gICAgICAgICAgICBwb3NpdGlvbjogdG9QYXJzZS5wb3NpdGlvblxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgU2lkZUJhckRlZlBhcnNlci5wYXJzZUNvbXBvbmVudHMgPSBmdW5jdGlvbiAoZnJvbSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIGlmICghZnJvbSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBmcm9tLmZvckVhY2goZnVuY3Rpb24gKGl0KSB7XG4gICAgICAgICAgICB2YXIgdG9BZGQgPSBudWxsO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBpdCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB2YXIgbG9va3VwUmVzdWx0ID0gU2lkZUJhckRlZlBhcnNlci5ERUZBVUxUX0JZX0tFWVtpdF07XG4gICAgICAgICAgICAgICAgaWYgKCFsb29rdXBSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogdGhlIGtleSBcIiArIGl0ICsgXCIgaXMgbm90IGEgdmFsaWQga2V5IGZvciBzcGVjaWZ5aW5nIGEgdG9vbCBwYW5lbCwgdmFsaWQga2V5cyBhcmU6IFwiICsgT2JqZWN0LmtleXMoU2lkZUJhckRlZlBhcnNlci5ERUZBVUxUX0JZX0tFWSkuam9pbignLCcpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0b0FkZCA9IGxvb2t1cFJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRvQWRkID0gaXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHQucHVzaCh0b0FkZCk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgU2lkZUJhckRlZlBhcnNlci5ERUZBVUxUX0NPTFVNTl9DT01QID0ge1xuICAgICAgICBpZDogJ2NvbHVtbnMnLFxuICAgICAgICBsYWJlbERlZmF1bHQ6ICdDb2x1bW5zJyxcbiAgICAgICAgbGFiZWxLZXk6ICdjb2x1bW5zJyxcbiAgICAgICAgaWNvbktleTogJ2NvbHVtbnMnLFxuICAgICAgICB0b29sUGFuZWw6ICdhZ0NvbHVtbnNUb29sUGFuZWwnLFxuICAgIH07XG4gICAgU2lkZUJhckRlZlBhcnNlci5ERUZBVUxUX0ZJTFRFUl9DT01QID0ge1xuICAgICAgICBpZDogJ2ZpbHRlcnMnLFxuICAgICAgICBsYWJlbERlZmF1bHQ6ICdGaWx0ZXJzJyxcbiAgICAgICAgbGFiZWxLZXk6ICdmaWx0ZXJzJyxcbiAgICAgICAgaWNvbktleTogJ2ZpbHRlcicsXG4gICAgICAgIHRvb2xQYW5lbDogJ2FnRmlsdGVyc1Rvb2xQYW5lbCcsXG4gICAgfTtcbiAgICBTaWRlQmFyRGVmUGFyc2VyLkRFRkFVTFRfQllfS0VZID0ge1xuICAgICAgICBjb2x1bW5zOiBTaWRlQmFyRGVmUGFyc2VyLkRFRkFVTFRfQ09MVU1OX0NPTVAsXG4gICAgICAgIGZpbHRlcnM6IFNpZGVCYXJEZWZQYXJzZXIuREVGQVVMVF9GSUxURVJfQ09NUFxuICAgIH07XG4gICAgcmV0dXJuIFNpZGVCYXJEZWZQYXJzZXI7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX192YWx1ZXMkNSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fdmFsdWVzKSB8fCBmdW5jdGlvbihvKSB7XG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcbiAgICBpZiAobyAmJiB0eXBlb2Ygby5sZW5ndGggPT09IFwibnVtYmVyXCIpIHJldHVybiB7XG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IocyA/IFwiT2JqZWN0IGlzIG5vdCBpdGVyYWJsZS5cIiA6IFwiU3ltYm9sLml0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcbn07XG4vKipcbiAqIFRoZXNlIHZhcmlhYmxlcyBhcmUgbGF6eSBsb2FkZWQsIGFzIG90aGVyd2lzZSB0aGV5IHRyeSBhbmQgZ2V0IGluaXRpYWxpc2VkIHdoZW4gd2UgYXJlIGxvYWRpbmdcbiAqIHVuaXQgdGVzdHMgYW5kIHdlIGRvbid0IGhhdmUgcmVmZXJlbmNlcyB0byB3aW5kb3cgb3IgZG9jdW1lbnQgaW4gdGhlIHVuaXQgdGVzdHNcbiAqIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy85ODQ3NTgwL2hvdy10by1kZXRlY3Qtc2FmYXJpLWNocm9tZS1pZS1maXJlZm94LWFuZC1vcGVyYS1icm93c2VyXG4gKi9cbnZhciBpc1NhZmFyaTtcbnZhciBpc0lFO1xudmFyIGlzRWRnZTtcbnZhciBpc0Nocm9tZTtcbnZhciBpc0ZpcmVmb3g7XG52YXIgaXNNYWNPcztcbnZhciBpc0lPUztcbnZhciBpbnZpc2libGVTY3JvbGxiYXI7XG52YXIgYnJvd3NlclNjcm9sbGJhcldpZHRoO1xudmFyIGJyb3dzZXJJbmZvO1xuLyoqXG4gKiBmcm9tIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNjkzODQ4MS8xMzg4MjMzXG4gKi9cbmZ1bmN0aW9uIGdldEJyb3dzZXJJbmZvKCkge1xuICAgIGlmIChicm93c2VySW5mbykge1xuICAgICAgICByZXR1cm4gYnJvd3NlckluZm87XG4gICAgfVxuICAgIHZhciB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICAgIHZhciBtYXRjaCA9IHVzZXJBZ2VudC5tYXRjaCgvKG9wZXJhfGNocm9tZXxzYWZhcml8ZmlyZWZveHxtc2llfHRyaWRlbnQoPz1cXC8pKVxcLz9cXHMqKFxcZCspL2kpIHx8IFtdO1xuICAgIHZhciB0ZW07XG4gICAgdmFyIHZlcnNpb247XG4gICAgaWYgKC90cmlkZW50L2kudGVzdChtYXRjaFsxXSkpIHtcbiAgICAgICAgdGVtID0gL1xcYnJ2WyA6XSsoXFxkKykvZy5leGVjKHVzZXJBZ2VudCkgfHwgW107XG4gICAgICAgIHZlcnNpb24gPSB0ZW1bMV0gIT0gbnVsbCA/IHBhcnNlRmxvYXQodGVtWzFdKSA6IDA7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuYW1lOiAnSUUnLFxuICAgICAgICAgICAgdmVyc2lvbjogdmVyc2lvblxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAobWF0Y2hbMV0gPT09ICdDaHJvbWUnKSB7XG4gICAgICAgIHRlbSA9IHVzZXJBZ2VudC5tYXRjaCgvXFxiT1BSfEVkZ2VcXC8oXFxkKykvKTtcbiAgICAgICAgaWYgKHRlbSAhPSBudWxsKSB7XG4gICAgICAgICAgICB2ZXJzaW9uID0gdGVtWzFdICE9IG51bGwgPyBwYXJzZUZsb2F0KHRlbVsxXSkgOiAwO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAnT3BlcmEnLFxuICAgICAgICAgICAgICAgIHZlcnNpb246IHZlcnNpb25cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgbWF0Y2ggPSBtYXRjaFsyXSA/IFttYXRjaFsxXSwgbWF0Y2hbMl1dIDogW25hdmlnYXRvci5hcHBOYW1lLCBuYXZpZ2F0b3IuYXBwVmVyc2lvbiwgJy0/J107XG4gICAgdGVtID0gdXNlckFnZW50Lm1hdGNoKC92ZXJzaW9uXFwvKFxcZCspL2kpO1xuICAgIGlmICh0ZW0gIT0gbnVsbCkge1xuICAgICAgICBtYXRjaC5zcGxpY2UoMSwgMSwgdGVtWzFdKTtcbiAgICB9XG4gICAgdmFyIG5hbWUgPSBtYXRjaFswXTtcbiAgICB2ZXJzaW9uID0gbWF0Y2hbMV0gIT0gbnVsbCA/IHBhcnNlRmxvYXQobWF0Y2hbMV0pIDogMDtcbiAgICBicm93c2VySW5mbyA9IHsgbmFtZTogbmFtZSwgdmVyc2lvbjogdmVyc2lvbiB9O1xuICAgIHJldHVybiBicm93c2VySW5mbztcbn1cbmZ1bmN0aW9uIGlzQnJvd3NlcklFKCkge1xuICAgIGlmIChpc0lFID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaXNJRSA9IC8qQGNjX29uIUAqLyAhIWRvY3VtZW50LmRvY3VtZW50TW9kZTsgLy8gQXQgbGVhc3QgSUU2XG4gICAgfVxuICAgIHJldHVybiBpc0lFO1xufVxuZnVuY3Rpb24gaXNCcm93c2VyRWRnZSgpIHtcbiAgICBpZiAoaXNFZGdlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaXNFZGdlID0gIWlzQnJvd3NlcklFKCkgJiYgISF3aW5kb3cuU3R5bGVNZWRpYTtcbiAgICB9XG4gICAgcmV0dXJuIGlzRWRnZTtcbn1cbmZ1bmN0aW9uIGlzQnJvd3NlclNhZmFyaSgpIHtcbiAgICBpZiAoaXNTYWZhcmkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyB0YWtlbiBmcm9tIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMzUyMjc1NS8xMzg4MjMzXG4gICAgICAgIGlzU2FmYXJpID0gL14oKD8hY2hyb21lfGFuZHJvaWQpLikqc2FmYXJpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGlzU2FmYXJpO1xufVxuZnVuY3Rpb24gaXNCcm93c2VyQ2hyb21lKCkge1xuICAgIGlmIChpc0Nocm9tZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciB3aW4gPSB3aW5kb3c7XG4gICAgICAgIGlzQ2hyb21lID0gKCEhd2luLmNocm9tZSAmJiAoISF3aW4uY2hyb21lLndlYnN0b3JlIHx8ICEhd2luLmNocm9tZS5ydW50aW1lKSkgfHxcbiAgICAgICAgICAgICgvQ2hyb21lLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpICYmIC9Hb29nbGUgSW5jLy50ZXN0KG5hdmlnYXRvci52ZW5kb3IpKTtcbiAgICB9XG4gICAgcmV0dXJuIGlzQ2hyb21lO1xufVxuZnVuY3Rpb24gaXNCcm93c2VyRmlyZWZveCgpIHtcbiAgICBpZiAoaXNGaXJlZm94ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIHdpbiA9IHdpbmRvdztcbiAgICAgICAgaXNGaXJlZm94ID0gdHlwZW9mIHdpbi5JbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgfVxuICAgIHJldHVybiBpc0ZpcmVmb3g7XG59XG5mdW5jdGlvbiBpc01hY09zVXNlckFnZW50KCkge1xuICAgIGlmIChpc01hY09zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaXNNYWNPcyA9IC8oTWFjfGlQaG9uZXxpUG9kfGlQYWQpL2kudGVzdChuYXZpZ2F0b3IucGxhdGZvcm0pO1xuICAgIH1cbiAgICByZXR1cm4gaXNNYWNPcztcbn1cbmZ1bmN0aW9uIGlzSU9TVXNlckFnZW50KCkge1xuICAgIGlmIChpc0lPUyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIHRha2VuIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzU4MDY0NDgxLzEzODgyMzNcbiAgICAgICAgaXNJT1MgPSAoL2lQYWR8aVBob25lfGlQb2QvLnRlc3QobmF2aWdhdG9yLnBsYXRmb3JtKSB8fFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICAobmF2aWdhdG9yLnBsYXRmb3JtID09PSAnTWFjSW50ZWwnICYmIG5hdmlnYXRvci5tYXhUb3VjaFBvaW50cyA+IDEpKSAmJlxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgIXdpbmRvdy5NU1N0cmVhbTtcbiAgICB9XG4gICAgcmV0dXJuIGlzSU9TO1xufVxuZnVuY3Rpb24gYnJvd3NlclN1cHBvcnRzUHJldmVudFNjcm9sbCgpIHtcbiAgICAvLyBhbGwgYnJvd3NlcnMgZXhjZXB0IHNhZmFyaSBzdXBwb3J0IGZvY3VzKHsgcHJldmVudFNjcm9sbDogdHJ1ZSB9KS5cbiAgICAvLyB0aGlzIGZlYXR1cmUgd2FzIGFkZGVkIG9uIFNhZmFyaSAxNStcbiAgICByZXR1cm4gIWlzQnJvd3NlclNhZmFyaSgpIHx8IGdldEJyb3dzZXJJbmZvKCkudmVyc2lvbiA+PSAxNTtcbn1cbmZ1bmN0aW9uIGdldFRhYkluZGV4KGVsKSB7XG4gICAgaWYgKCFlbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIG51bWJlclRhYkluZGV4ID0gZWwudGFiSW5kZXg7XG4gICAgdmFyIHRhYkluZGV4ID0gZWwuZ2V0QXR0cmlidXRlKCd0YWJJbmRleCcpO1xuICAgIGlmIChudW1iZXJUYWJJbmRleCA9PT0gLTEgJiYgKHRhYkluZGV4ID09PSBudWxsIHx8ICh0YWJJbmRleCA9PT0gJycgJiYgIWlzQnJvd3NlckZpcmVmb3goKSkpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gbnVtYmVyVGFiSW5kZXgudG9TdHJpbmcoKTtcbn1cbmZ1bmN0aW9uIGdldE1heERpdkhlaWdodCgpIHtcbiAgICBpZiAoIWRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgICB2YXIgcmVzID0gMTAwMDAwMDtcbiAgICAvLyBGRiByZXBvcnRzIHRoZSBoZWlnaHQgYmFjayBidXQgc3RpbGwgcmVuZGVycyBibGFuayBhZnRlciB+Nk0gcHhcbiAgICB2YXIgdGVzdFVwVG8gPSBuYXZpZ2F0b3IudXNlckFnZW50LnRvTG93ZXJDYXNlKCkubWF0Y2goL2ZpcmVmb3gvKSA/IDYwMDAwMDAgOiAxMDAwMDAwMDAwO1xuICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgdmFyIHRlc3QgPSByZXMgKiAyO1xuICAgICAgICBkaXYuc3R5bGUuaGVpZ2h0ID0gdGVzdCArICdweCc7XG4gICAgICAgIGlmICh0ZXN0ID4gdGVzdFVwVG8gfHwgZGl2LmNsaWVudEhlaWdodCAhPT0gdGVzdCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXMgPSB0ZXN0O1xuICAgICAgICB9XG4gICAgfVxuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gZ2V0U2Nyb2xsYmFyV2lkdGgoKSB7XG4gICAgaWYgKGJyb3dzZXJTY3JvbGxiYXJXaWR0aCA9PSBudWxsKSB7XG4gICAgICAgIGluaXRTY3JvbGxiYXJXaWR0aEFuZFZpc2liaWxpdHkoKTtcbiAgICB9XG4gICAgcmV0dXJuIGJyb3dzZXJTY3JvbGxiYXJXaWR0aDtcbn1cbmZ1bmN0aW9uIGluaXRTY3JvbGxiYXJXaWR0aEFuZFZpc2liaWxpdHkoKSB7XG4gICAgdmFyIGJvZHkgPSBkb2N1bWVudC5ib2R5O1xuICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBkaXYuc3R5bGUud2lkdGggPSBkaXYuc3R5bGUuaGVpZ2h0ID0gJzEwMHB4JztcbiAgICBkaXYuc3R5bGUub3BhY2l0eSA9ICcwJztcbiAgICBkaXYuc3R5bGUub3ZlcmZsb3cgPSAnc2Nyb2xsJztcbiAgICBkaXYuc3R5bGUubXNPdmVyZmxvd1N0eWxlID0gJ3Njcm9sbGJhcic7IC8vIG5lZWRlZCBmb3IgV2luSlMgYXBwc1xuICAgIGRpdi5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgYm9keS5hcHBlbmRDaGlsZChkaXYpO1xuICAgIHZhciB3aWR0aCA9IGRpdi5vZmZzZXRXaWR0aCAtIGRpdi5jbGllbnRXaWR0aDtcbiAgICAvLyBpZiB3aWR0aCBpcyAwIGFuZCBjbGllbnQgd2lkdGggaXMgMCwgbWVhbnMgdGhlIERPTSBpc24ndCByZWFkeVxuICAgIGlmICh3aWR0aCA9PT0gMCAmJiBkaXYuY2xpZW50V2lkdGggPT09IDApIHtcbiAgICAgICAgd2lkdGggPSBudWxsO1xuICAgIH1cbiAgICAvLyByZW1vdmUgZGl2XG4gICAgaWYgKGRpdi5wYXJlbnROb2RlKSB7XG4gICAgICAgIGRpdi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRpdik7XG4gICAgfVxuICAgIGlmICh3aWR0aCAhPSBudWxsKSB7XG4gICAgICAgIGJyb3dzZXJTY3JvbGxiYXJXaWR0aCA9IHdpZHRoO1xuICAgICAgICBpbnZpc2libGVTY3JvbGxiYXIgPSB3aWR0aCA9PT0gMDtcbiAgICB9XG59XG5mdW5jdGlvbiBpc0ludmlzaWJsZVNjcm9sbGJhcigpIHtcbiAgICBpZiAoaW52aXNpYmxlU2Nyb2xsYmFyID09IG51bGwpIHtcbiAgICAgICAgaW5pdFNjcm9sbGJhcldpZHRoQW5kVmlzaWJpbGl0eSgpO1xuICAgIH1cbiAgICByZXR1cm4gaW52aXNpYmxlU2Nyb2xsYmFyO1xufVxuLyoqIEBkZXByZWNhdGVkICovXG5mdW5jdGlvbiBoYXNPdmVyZmxvd1Njcm9sbGluZygpIHtcbiAgICB2YXIgZV8xLCBfYTtcbiAgICB2YXIgcHJlZml4ZXMgPSBbJ3dlYmtpdCcsICdtb3onLCAnbycsICdtcyddO1xuICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB2YXIgYm9keSA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdib2R5JylbMF07XG4gICAgdmFyIGZvdW5kID0gZmFsc2U7XG4gICAgdmFyIHA7XG4gICAgYm9keS5hcHBlbmRDaGlsZChkaXYpO1xuICAgIGRpdi5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgcHJlZml4ZXMubWFwKGZ1bmN0aW9uIChwcmVmaXgpIHsgcmV0dXJuIFwiLVwiICsgcHJlZml4ICsgXCItb3ZlcmZsb3ctc2Nyb2xsaW5nOiB0b3VjaFwiOyB9KS5jb25jYXQoJ292ZXJmbG93LXNjcm9sbGluZzogdG91Y2gnKS5qb2luKCc7JykpO1xuICAgIHZhciBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZGl2KTtcbiAgICBpZiAoY29tcHV0ZWRTdHlsZS5vdmVyZmxvd1Njcm9sbGluZyA9PT0gJ3RvdWNoJykge1xuICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgfVxuICAgIGlmICghZm91bmQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZvciAodmFyIHByZWZpeGVzXzEgPSBfX3ZhbHVlcyQ1KHByZWZpeGVzKSwgcHJlZml4ZXNfMV8xID0gcHJlZml4ZXNfMS5uZXh0KCk7ICFwcmVmaXhlc18xXzEuZG9uZTsgcHJlZml4ZXNfMV8xID0gcHJlZml4ZXNfMS5uZXh0KCkpIHtcbiAgICAgICAgICAgICAgICBwID0gcHJlZml4ZXNfMV8xLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChjb21wdXRlZFN0eWxlW3AgKyBcIk92ZXJmbG93U2Nyb2xsaW5nXCJdID09PSAndG91Y2gnKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlXzFfMSkgeyBlXzEgPSB7IGVycm9yOiBlXzFfMSB9OyB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAocHJlZml4ZXNfMV8xICYmICFwcmVmaXhlc18xXzEuZG9uZSAmJiAoX2EgPSBwcmVmaXhlc18xLnJldHVybikpIF9hLmNhbGwocHJlZml4ZXNfMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHsgaWYgKGVfMSkgdGhyb3cgZV8xLmVycm9yOyB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGRpdi5wYXJlbnROb2RlKSB7XG4gICAgICAgIGRpdi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRpdik7XG4gICAgfVxuICAgIHJldHVybiBmb3VuZDtcbn1cbi8qKlxuICogR2V0cyB0aGUgZG9jdW1lbnQgYm9keSB3aWR0aFxuICogZnJvbTogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xMDM4NzI3L2hvdy10by1nZXQtYnJvd3Nlci13aWR0aC11c2luZy1qYXZhc2NyaXB0LWNvZGVcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZ1bmN0aW9uIGdldEJvZHlXaWR0aCgpIHtcbiAgICBpZiAoZG9jdW1lbnQuYm9keSkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuYm9keS5jbGllbnRXaWR0aDtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy5pbm5lckhlaWdodCkge1xuICAgICAgICByZXR1cm4gd2luZG93LmlubmVyV2lkdGg7XG4gICAgfVxuICAgIGlmIChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgfVxuICAgIHJldHVybiAtMTtcbn1cbi8qKlxuICogR2V0cyB0aGUgYm9keSBoZWlnaHRcbiAqIGZyb206IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTAzODcyNy9ob3ctdG8tZ2V0LWJyb3dzZXItd2lkdGgtdXNpbmctamF2YXNjcmlwdC1jb2RlXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiBnZXRCb2R5SGVpZ2h0KCkge1xuICAgIGlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodDtcbiAgICB9XG4gICAgaWYgKHdpbmRvdy5pbm5lckhlaWdodCkge1xuICAgICAgICByZXR1cm4gd2luZG93LmlubmVySGVpZ2h0O1xuICAgIH1cbiAgICBpZiAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgfVxuICAgIHJldHVybiAtMTtcbn1cblxudmFyIEJyb3dzZXJVdGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgZ2V0QnJvd3NlckluZm86IGdldEJyb3dzZXJJbmZvLFxuICAgIGlzQnJvd3NlckVkZ2U6IGlzQnJvd3NlckVkZ2UsXG4gICAgaXNCcm93c2VyU2FmYXJpOiBpc0Jyb3dzZXJTYWZhcmksXG4gICAgaXNCcm93c2VyQ2hyb21lOiBpc0Jyb3dzZXJDaHJvbWUsXG4gICAgaXNCcm93c2VyRmlyZWZveDogaXNCcm93c2VyRmlyZWZveCxcbiAgICBpc01hY09zVXNlckFnZW50OiBpc01hY09zVXNlckFnZW50LFxuICAgIGlzSU9TVXNlckFnZW50OiBpc0lPU1VzZXJBZ2VudCxcbiAgICBicm93c2VyU3VwcG9ydHNQcmV2ZW50U2Nyb2xsOiBicm93c2VyU3VwcG9ydHNQcmV2ZW50U2Nyb2xsLFxuICAgIGdldFRhYkluZGV4OiBnZXRUYWJJbmRleCxcbiAgICBnZXRNYXhEaXZIZWlnaHQ6IGdldE1heERpdkhlaWdodCxcbiAgICBnZXRTY3JvbGxiYXJXaWR0aDogZ2V0U2Nyb2xsYmFyV2lkdGgsXG4gICAgaXNJbnZpc2libGVTY3JvbGxiYXI6IGlzSW52aXNpYmxlU2Nyb2xsYmFyLFxuICAgIGhhc092ZXJmbG93U2Nyb2xsaW5nOiBoYXNPdmVyZmxvd1Njcm9sbGluZyxcbiAgICBnZXRCb2R5V2lkdGg6IGdldEJvZHlXaWR0aCxcbiAgICBnZXRCb2R5SGVpZ2h0OiBnZXRCb2R5SGVpZ2h0XG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuZnVuY3Rpb24gZnV6enlDaGVja1N0cmluZ3MoaW5wdXRWYWx1ZXMsIHZhbGlkVmFsdWVzLCBhbGxTdWdnZXN0aW9ucykge1xuICAgIHZhciBmdXp6eU1hdGNoZXMgPSB7fTtcbiAgICB2YXIgaW52YWxpZElucHV0cyA9IGlucHV0VmFsdWVzLmZpbHRlcihmdW5jdGlvbiAoaW5wdXRWYWx1ZSkge1xuICAgICAgICByZXR1cm4gIXZhbGlkVmFsdWVzLnNvbWUoZnVuY3Rpb24gKHZhbGlkVmFsdWUpIHsgcmV0dXJuIHZhbGlkVmFsdWUgPT09IGlucHV0VmFsdWU7IH0pO1xuICAgIH0pO1xuICAgIGlmIChpbnZhbGlkSW5wdXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaW52YWxpZElucHV0cy5mb3JFYWNoKGZ1bmN0aW9uIChpbnZhbGlkSW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBmdXp6eU1hdGNoZXNbaW52YWxpZElucHV0XSA9IGZ1enp5U3VnZ2VzdGlvbnMoaW52YWxpZElucHV0LCBhbGxTdWdnZXN0aW9ucyk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gZnV6enlNYXRjaGVzO1xufVxuLyoqXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGlucHV0VmFsdWUgVGhlIHZhbHVlIHRvIGJlIGNvbXBhcmVkIGFnYWluc3QgYSBsaXN0IG9mIHN0cmluZ3NcbiAqIEBwYXJhbSBhbGxTdWdnZXN0aW9ucyBUaGUgbGlzdCBvZiBzdHJpbmdzIHRvIGJlIGNvbXBhcmVkIGFnYWluc3RcbiAqIEBwYXJhbSBoaWRlSXJyZWxldmFudCBCeSBkZWZhdWx0LCBmdXp6eSBzdWdnZXN0aW9ucyB3aWxsIGp1c3Qgc29ydCB0aGUgYWxsU3VnZ2VzdGlvbnMgbGlzdCwgc2V0IHRoaXMgdG8gdHJ1ZVxuICogICAgICAgIHRvIGZpbHRlciBvdXQgdGhlIGlycmVsZXZhbnQgdmFsdWVzXG4gKiBAcGFyYW0gd2VpZ2h0ZWQgU2V0IHRoaXMgdG8gdHJ1ZSwgdG8gbWFrZSBsZXR0ZXJzIG1hdGNoZWQgaW4gdGhlIG9yZGVyIHRoZXkgd2VyZSB0eXBlZCBoYXZlIHByaW9yaXR5IGluIHRoZSByZXN1bHRzLlxuICovXG5mdW5jdGlvbiBmdXp6eVN1Z2dlc3Rpb25zKGlucHV0VmFsdWUsIGFsbFN1Z2dlc3Rpb25zLCBoaWRlSXJyZWxldmFudCwgd2VpZ2h0ZWQpIHtcbiAgICB2YXIgc2VhcmNoID0gd2VpZ2h0ZWQgPyBzdHJpbmdfd2VpZ2h0ZWRfZGlzdGFuY2VzIDogc3RyaW5nX2Rpc3RhbmNlcztcbiAgICB2YXIgdGhpc1N1Z2dlc3Rpb25zID0gYWxsU3VnZ2VzdGlvbnMubWFwKGZ1bmN0aW9uICh0ZXh0KSB7IHJldHVybiAoe1xuICAgICAgICB2YWx1ZTogdGV4dCxcbiAgICAgICAgcmVsZXZhbmNlOiBzZWFyY2goaW5wdXRWYWx1ZS50b0xvd2VyQ2FzZSgpLCB0ZXh0LnRvTG9jYWxlTG93ZXJDYXNlKCkpXG4gICAgfSk7IH0pO1xuICAgIHRoaXNTdWdnZXN0aW9ucy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBiLnJlbGV2YW5jZSAtIGEucmVsZXZhbmNlOyB9KTtcbiAgICBpZiAoaGlkZUlycmVsZXZhbnQpIHtcbiAgICAgICAgdGhpc1N1Z2dlc3Rpb25zID0gdGhpc1N1Z2dlc3Rpb25zLmZpbHRlcihmdW5jdGlvbiAoc3VnZ2VzdGlvbikgeyByZXR1cm4gc3VnZ2VzdGlvbi5yZWxldmFuY2UgIT09IDA7IH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpc1N1Z2dlc3Rpb25zLm1hcChmdW5jdGlvbiAoc3VnZ2VzdGlvbikgeyByZXR1cm4gc3VnZ2VzdGlvbi52YWx1ZTsgfSk7XG59XG4vKipcbiAqIEFsZ29yaXRobSB0byBkbyBmdXp6eSBzZWFyY2hcbiAqIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjMzMDUwMDAvamF2YXNjcmlwdC1mdXp6eS1zZWFyY2gtdGhhdC1tYWtlcy1zZW5zZVxuICogQHBhcmFtIHtzdHJpbmd9IGZyb21cbiAqIEByZXR1cm4ge1tdfVxuICovXG5mdW5jdGlvbiBnZXRfYmlncmFtcyhmcm9tKSB7XG4gICAgdmFyIHMgPSBmcm9tLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFyIHYgPSBuZXcgQXJyYXkocy5sZW5ndGggLSAxKTtcbiAgICB2YXIgaTtcbiAgICB2YXIgajtcbiAgICB2YXIgcmVmO1xuICAgIGZvciAoaSA9IGogPSAwLCByZWYgPSB2Lmxlbmd0aDsgaiA8PSByZWY7IGkgPSBqICs9IDEpIHtcbiAgICAgICAgdltpXSA9IHMuc2xpY2UoaSwgaSArIDIpO1xuICAgIH1cbiAgICByZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIHN0cmluZ19kaXN0YW5jZXMoc3RyMSwgc3RyMikge1xuICAgIGlmIChzdHIxLmxlbmd0aCA9PT0gMCAmJiBzdHIyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgdmFyIHBhaXJzMSA9IGdldF9iaWdyYW1zKHN0cjEpO1xuICAgIHZhciBwYWlyczIgPSBnZXRfYmlncmFtcyhzdHIyKTtcbiAgICB2YXIgdW5pb24gPSBwYWlyczEubGVuZ3RoICsgcGFpcnMyLmxlbmd0aDtcbiAgICB2YXIgaGl0X2NvdW50ID0gMDtcbiAgICB2YXIgajtcbiAgICB2YXIgbGVuO1xuICAgIGZvciAoaiA9IDAsIGxlbiA9IHBhaXJzMS5sZW5ndGg7IGogPCBsZW47IGorKykge1xuICAgICAgICB2YXIgeCA9IHBhaXJzMVtqXTtcbiAgICAgICAgdmFyIGsgPSB2b2lkIDA7XG4gICAgICAgIHZhciBsZW4xID0gdm9pZCAwO1xuICAgICAgICBmb3IgKGsgPSAwLCBsZW4xID0gcGFpcnMyLmxlbmd0aDsgayA8IGxlbjE7IGsrKykge1xuICAgICAgICAgICAgdmFyIHkgPSBwYWlyczJba107XG4gICAgICAgICAgICBpZiAoeCA9PT0geSkge1xuICAgICAgICAgICAgICAgIGhpdF9jb3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBoaXRfY291bnQgPiAwID8gKDIgKiBoaXRfY291bnQpIC8gdW5pb24gOiAwO1xufVxuZnVuY3Rpb24gc3RyaW5nX3dlaWdodGVkX2Rpc3RhbmNlcyhzdHIxLCBzdHIyKSB7XG4gICAgdmFyIGEgPSBzdHIxLnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgdmFyIGIgPSBzdHIyLnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgdmFyIHdlaWdodCA9IDA7XG4gICAgdmFyIGxhc3RJbmRleCA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpZHggPSBiLmluZGV4T2YoYVtpXSwgbGFzdEluZGV4KTtcbiAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGxhc3RJbmRleCA9IGlkeDtcbiAgICAgICAgd2VpZ2h0ICs9ICgxMDAgLSAobGFzdEluZGV4ICogMTAwIC8gMTAwMDApICogMTAwKTtcbiAgICB9XG4gICAgcmV0dXJuIHdlaWdodDtcbn1cblxudmFyIEZ1enp5TWF0Y2hVdGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgZnV6enlDaGVja1N0cmluZ3M6IGZ1enp5Q2hlY2tTdHJpbmdzLFxuICAgIGZ1enp5U3VnZ2VzdGlvbnM6IGZ1enp5U3VnZ2VzdGlvbnMsXG4gICAgZ2V0X2JpZ3JhbXM6IGdldF9iaWdyYW1zLFxuICAgIHN0cmluZ19kaXN0YW5jZXM6IHN0cmluZ19kaXN0YW5jZXMsXG4gICAgc3RyaW5nX3dlaWdodGVkX2Rpc3RhbmNlczogc3RyaW5nX3dlaWdodGVkX2Rpc3RhbmNlc1xufSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbmZ1bmN0aW9uIHBhZFN0YXJ0V2lkdGhaZXJvcyh2YWx1ZSwgdG90YWxTdHJpbmdTaXplKSB7XG4gICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCkucGFkU3RhcnQodG90YWxTdHJpbmdTaXplLCAnMCcpO1xufVxuZnVuY3Rpb24gY3JlYXRlQXJyYXlPZk51bWJlcnMoZmlyc3QsIGxhc3QpIHtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgZm9yICh2YXIgaSA9IGZpcnN0OyBpIDw9IGxhc3Q7IGkrKykge1xuICAgICAgICByZXN1bHQucHVzaChpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbi8qKlxuICogQ2hlY2sgaWYgYSB2YWx1ZSBpcyBudW1lcmljXG4gKiBmcm9tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvOTcxNjQ2OC9pcy10aGVyZS1hbnktZnVuY3Rpb24tbGlrZS1pc251bWVyaWMtaW4tamF2YXNjcmlwdC10by12YWxpZGF0ZS1udW1iZXJzXG4gKiBAcGFyYW0ge2FueX0gdmFsdWVcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzTnVtZXJpYyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSAhPT0gJycgJiYgIWlzTmFOKHBhcnNlRmxvYXQodmFsdWUpKSAmJiBpc0Zpbml0ZSh2YWx1ZSk7XG59XG5mdW5jdGlvbiBjbGVhbk51bWJlcih2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhbHVlID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IodmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIGRlY1RvSGV4KG51bWJlciwgYnl0ZXMpIHtcbiAgICB2YXIgaGV4ID0gJyc7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlczsgaSsrKSB7XG4gICAgICAgIGhleCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG51bWJlciAmIDB4ZmYpO1xuICAgICAgICBudW1iZXIgPj4+PSA4O1xuICAgIH1cbiAgICByZXR1cm4gaGV4O1xufVxuZnVuY3Rpb24gZm9ybWF0TnVtYmVyVHdvRGVjaW1hbFBsYWNlc0FuZENvbW1hcyh2YWx1ZSwgdGhvdXNhbmRTZXBhcmF0b3IsIGRlY2ltYWxTZXBhcmF0b3IpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiBmb3JtYXROdW1iZXJDb21tYXMoTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCkgLyAxMDAsIHRob3VzYW5kU2VwYXJhdG9yLCBkZWNpbWFsU2VwYXJhdG9yKTtcbn1cbi8qKlxuICogdGhlIG5hdGl2ZSBtZXRob2QgbnVtYmVyLnRvTG9jYWxlU3RyaW5nKHVuZGVmaW5lZCwge21pbmltdW1GcmFjdGlvbkRpZ2l0czogMH0pXG4gKiBwdXRzIGluIGRlY2ltYWwgcGxhY2VzIGluIElFLCBzbyB3ZSB1c2UgdGhpcyBtZXRob2QgaW5zdGVhZFxuICogZnJvbTogaHR0cDovL2Jsb2cudG9tcGF3bGFrLm9yZy9udW1iZXItY3VycmVuY3ktZm9ybWF0dGluZy1qYXZhc2NyaXB0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGZvcm1hdE51bWJlckNvbW1hcyh2YWx1ZSwgdGhvdXNhbmRTZXBhcmF0b3IsIGRlY2ltYWxTZXBhcmF0b3IpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpLnJlcGxhY2UoJy4nLCBkZWNpbWFsU2VwYXJhdG9yKS5yZXBsYWNlKC8oXFxkKSg/PShcXGR7M30pKyg/IVxcZCkpL2csIFwiJDFcIiArIHRob3VzYW5kU2VwYXJhdG9yKTtcbn1cbmZ1bmN0aW9uIHN1bSh2YWx1ZXMpIHtcbiAgICByZXR1cm4gdmFsdWVzID09IG51bGwgPyBudWxsIDogdmFsdWVzLnJlZHVjZShmdW5jdGlvbiAodG90YWwsIHZhbHVlKSB7IHJldHVybiB0b3RhbCArIHZhbHVlOyB9LCAwKTtcbn1cblxudmFyIE51bWJlclV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBwYWRTdGFydFdpZHRoWmVyb3M6IHBhZFN0YXJ0V2lkdGhaZXJvcyxcbiAgICBjcmVhdGVBcnJheU9mTnVtYmVyczogY3JlYXRlQXJyYXlPZk51bWJlcnMsXG4gICAgaXNOdW1lcmljOiBpc051bWVyaWMsXG4gICAgY2xlYW5OdW1iZXI6IGNsZWFuTnVtYmVyLFxuICAgIGRlY1RvSGV4OiBkZWNUb0hleCxcbiAgICBmb3JtYXROdW1iZXJUd29EZWNpbWFsUGxhY2VzQW5kQ29tbWFzOiBmb3JtYXROdW1iZXJUd29EZWNpbWFsUGxhY2VzQW5kQ29tbWFzLFxuICAgIGZvcm1hdE51bWJlckNvbW1hczogZm9ybWF0TnVtYmVyQ29tbWFzLFxuICAgIHN1bTogc3VtXG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fYXNzaWduJGcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2Fzc2lnbikgfHwgZnVuY3Rpb24gKCkge1xuICAgIF9fYXNzaWduJGcgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduJGcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgX19kZWNvcmF0ZSQydiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcGFyYW0kOCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcGFyYW0pIHx8IGZ1bmN0aW9uIChwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cbn07XG52YXIgX19yZWFkJG0gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgX19zcHJlYWQkZyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCRtKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG52YXIgREVGQVVMVF9ST1dfSEVJR0hUID0gMjU7XG52YXIgREVGQVVMVF9ERVRBSUxfUk9XX0hFSUdIVCA9IDMwMDtcbnZhciBERUZBVUxUX1ZJRVdQT1JUX1JPV19NT0RFTF9QQUdFX1NJWkUgPSA1O1xudmFyIERFRkFVTFRfVklFV1BPUlRfUk9XX01PREVMX0JVRkZFUl9TSVpFID0gNTtcbnZhciBERUZBVUxUX0tFRVBfREVUQUlMX1JPV19DT1VOVCA9IDEwO1xuZnVuY3Rpb24gaXNUcnVlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSB0cnVlIHx8IHZhbHVlID09PSAndHJ1ZSc7XG59XG5mdW5jdGlvbiB0b051bWJlcih2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlID09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUludCh2YWx1ZSwgMTApO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHplcm9PckdyZWF0ZXIodmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgIGlmICh2YWx1ZSA+PSAwKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgLy8gemVybyBnZXRzIHJldHVybmVkIGlmIG51bWJlciBpcyBtaXNzaW5nIG9yIHRoZSB3cm9uZyB0eXBlXG4gICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbn1cbmZ1bmN0aW9uIG9uZU9yR3JlYXRlcih2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgdmFyIHZhbHVlTnVtYmVyID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICBpZiAoaXNOdW1lcmljKHZhbHVlTnVtYmVyKSAmJiB2YWx1ZU51bWJlciA+IDApIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlTnVtYmVyO1xuICAgIH1cbiAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xufVxudmFyIEdyaWRPcHRpb25zV3JhcHBlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBHcmlkT3B0aW9uc1dyYXBwZXIoKSB7XG4gICAgICAgIHRoaXMucHJvcGVydHlFdmVudFNlcnZpY2UgPSBuZXcgRXZlbnRTZXJ2aWNlKCk7XG4gICAgICAgIHRoaXMuZG9tRGF0YUtleSA9ICdfX0FHXycgKyBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgfVxuICAgIEdyaWRPcHRpb25zV3JhcHBlcl8xID0gR3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuYWdXaXJlID0gZnVuY3Rpb24gKGdyaWRBcGksIGNvbHVtbkFwaSkge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zLmFwaSA9IGdyaWRBcGk7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnMuY29sdW1uQXBpID0gY29sdW1uQXBpO1xuICAgICAgICB0aGlzLmNoZWNrRm9yRGVwcmVjYXRlZCgpO1xuICAgICAgICB0aGlzLmNoZWNrRm9yVmlvbGF0aW9ucygpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBuZWVkIHRvIHJlbW92ZSB0aGVzZSwgYXMgd2UgZG9uJ3Qgb3duIHRoZSBsaWZlY3ljbGUgb2YgdGhlIGdyaWRPcHRpb25zLCB3ZSBuZWVkIHRvXG4gICAgICAgIC8vIHJlbW92ZSB0aGUgcmVmZXJlbmNlcyBpbiBjYXNlIHRoZSB1c2VyIGtlZXBzIHRoZSBncmlkIG9wdGlvbnMsIHdlIHdhbnQgdGhlIHJlc3RcbiAgICAgICAgLy8gb2YgdGhlIGdyaWQgdG8gYmUgcGlja2VkIHVwIGJ5IHRoZSBnYXJiYWdlIGNvbGxlY3RvclxuICAgICAgICB0aGlzLmdyaWRPcHRpb25zLmFwaSA9IG51bGw7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnMuY29sdW1uQXBpID0gbnVsbDtcbiAgICAgICAgdGhpcy5kZXN0cm95ZWQgPSB0cnVlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc1Byb3BlcnR5TmFtZXNDaGVjayAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5jaGVja0dyaWRPcHRpb25zUHJvcGVydGllcygpO1xuICAgICAgICAgICAgdGhpcy5jaGVja0NvbHVtbkRlZlByb3BlcnRpZXMoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwYXJzZSBzaWRlIGJhciBvcHRpb25zIGludG8gY29ycmVjdCBmb3JtYXRcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMuc2lkZUJhciAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmdyaWRPcHRpb25zLnNpZGVCYXIgPSBTaWRlQmFyRGVmUGFyc2VyLnBhcnNlKHRoaXMuZ3JpZE9wdGlvbnMuc2lkZUJhcik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFzeW5jID0gdGhpcy51c2VBc3luY0V2ZW50cygpO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5hZGRHbG9iYWxMaXN0ZW5lcih0aGlzLmdsb2JhbEV2ZW50SGFuZGxlci5iaW5kKHRoaXMpLCBhc3luYyk7XG4gICAgICAgIGlmICh0aGlzLmlzR3JvdXBTZWxlY3RzQ2hpbGRyZW4oKSAmJiB0aGlzLmlzU3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2RlcygpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiAnZ3JvdXBTZWxlY3RzQ2hpbGRyZW4nIGRvZXMgbm90IHdvcmsgd2l0aCAnc3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2RlcycsIHRoaXMgc2VsZWN0aW9uIG1ldGhvZCBuZWVkcyB0aGUgcGFydCBpbiByb3dOb2RlIHRvIHdvcmtcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNHcm91cFNlbGVjdHNDaGlsZHJlbigpKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNSb3dTZWxlY3Rpb25NdWx0aSgpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogcm93U2VsZWN0aW9uIG11c3QgYmUgJ211bHRpcGxlJyBmb3IgZ3JvdXBTZWxlY3RzQ2hpbGRyZW4gdG8gbWFrZSBzZW5zZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlzUm93TW9kZWxTZXJ2ZXJTaWRlKCkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGdyb3VwIHNlbGVjdHMgY2hpbGRyZW4gaXMgTk9UIHN1cHBvcnQgZm9yIFNlcnZlciBTaWRlIFJvdyBNb2RlbC4gJyArXG4gICAgICAgICAgICAgICAgICAgICdUaGlzIGlzIGJlY2F1c2UgdGhlIHJvd3MgYXJlIGxhenkgbG9hZGVkLCBzbyBzZWxlY3RpbmcgYSBncm91cCBpcyBub3QgcG9zc2libGUgYXMnICtcbiAgICAgICAgICAgICAgICAgICAgJ3RoZSBncmlkIGhhcyBubyB3YXkgb2Yga25vd2luZyB3aGF0IHRoZSBjaGlsZHJlbiBhcmUuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNHcm91cFJlbW92ZVNpbmdsZUNoaWxkcmVuKCkgJiYgdGhpcy5pc0dyb3VwSGlkZU9wZW5QYXJlbnRzKCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGdyb3VwUmVtb3ZlU2luZ2xlQ2hpbGRyZW4gYW5kIGdyb3VwSGlkZU9wZW5QYXJlbnRzIGRvIG5vdCB3b3JrIHdpdGggZWFjaCBvdGhlciwgeW91IG5lZWQgdG8gcGljayBvbmUuIEFuZCBkb24ndCBhc2sgdXMgaG93IHRvIHVzZSB0aGVzZSB0b2dldGhlciBvbiBvdXIgc3VwcG9ydCBmb3J1bSBlaXRoZXIsIHlvdSB3aWxsIGdldCB0aGUgc2FtZSBhbnN3ZXIhXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzUm93TW9kZWxTZXJ2ZXJTaWRlKCkpIHtcbiAgICAgICAgICAgIHZhciBtc2cgPSBmdW5jdGlvbiAocHJvcCkgeyByZXR1cm4gXCJBRyBHcmlkOiAnXCIgKyBwcm9wICsgXCInIGlzIG5vdCBzdXBwb3J0ZWQgb24gdGhlIFNlcnZlci1TaWRlIFJvdyBNb2RlbFwiOyB9O1xuICAgICAgICAgICAgaWYgKGV4aXN0cyh0aGlzLmdyaWRPcHRpb25zLmdyb3VwRGVmYXVsdEV4cGFuZGVkKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2Fybihtc2coJ2dyb3VwRGVmYXVsdEV4cGFuZGVkJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGV4aXN0cyh0aGlzLmdyaWRPcHRpb25zLmdyb3VwRGVmYXVsdEV4cGFuZGVkKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2Fybihtc2coJ2dyb3VwSW5jbHVkZUZvb3RlcicpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChleGlzdHModGhpcy5ncmlkT3B0aW9ucy5ncm91cERlZmF1bHRFeHBhbmRlZCkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4obXNnKCdncm91cEluY2x1ZGVUb3RhbEZvb3RlcicpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUmFuZ2VTZWxlY3Rpb24pKSB7XG4gICAgICAgICAgICBNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLlJhbmdlU2VsZWN0aW9uTW9kdWxlLCAnZW5hYmxlUmFuZ2VTZWxlY3Rpb24nKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLmlzRW5hYmxlUmFuZ2VIYW5kbGUoKSB8fCB0aGlzLmlzRW5hYmxlRmlsbEhhbmRsZSgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiAnZW5hYmxlUmFuZ2VIYW5kbGUnIG9yICdlbmFibGVGaWxsSGFuZGxlJyB3aWxsIG5vdCB3b3JrIHVubGVzcyAnZW5hYmxlUmFuZ2VTZWxlY3Rpb24nIGlzIHNldCB0byB0cnVlXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzR3JvdXBSb3dzU3RpY2t5KCkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzR3JvdXBIaWRlT3BlblBhcmVudHMoKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGdyb3VwUm93c1N0aWNreSBhbmQgZ3JvdXBIaWRlT3BlblBhcmVudHMgZG8gbm90IHdvcmsgd2l0aCBlYWNoIG90aGVyLCB5b3UgbmVlZCB0byBwaWNrIG9uZS5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc01hc3RlckRldGFpbCgpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogZ3JvdXBSb3dzU3RpY2t5IGFuZCBtYXN0ZXJEZXRhaWwgZG8gbm90IHdvcmsgd2l0aCBlYWNoIG90aGVyLCB5b3UgbmVlZCB0byBwaWNrIG9uZS5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5pc1BhZ2luYXRpb24oKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGdyb3VwUm93c1N0aWNreSBhbmQgcGFnaW5hdGlvbiBkbyBub3Qgd29yayB3aXRoIGVhY2ggb3RoZXIsIHlvdSBuZWVkIHRvIHBpY2sgb25lLlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgd2Fybk9mRGVwcmVjYXJlZEljb24gPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmdyaWRPcHRpb25zLmljb25zICYmIF90aGlzLmdyaWRPcHRpb25zLmljb25zW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiZ3JpZE9wdGlvbnMuaWNvbnMuXCIgKyBuYW1lICsgXCIgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZC4gRm9yIGluZm9ybWF0aW9uIG9uIGhvdyB0byBzdHlsZSBjaGVja2JveGVzIGFuZCByYWRpbyBidXR0b25zLCBzZWUgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vamF2YXNjcmlwdC1ncmlkLWljb25zL1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgd2Fybk9mRGVwcmVjYXJlZEljb24oJ3JhZGlvQnV0dG9uT2ZmJyk7XG4gICAgICAgIHdhcm5PZkRlcHJlY2FyZWRJY29uKCdyYWRpb0J1dHRvbk9uJyk7XG4gICAgICAgIHdhcm5PZkRlcHJlY2FyZWRJY29uKCdjaGVja2JveENoZWNrZWQnKTtcbiAgICAgICAgd2Fybk9mRGVwcmVjYXJlZEljb24oJ2NoZWNrYm94VW5jaGVja2VkJyk7XG4gICAgICAgIHdhcm5PZkRlcHJlY2FyZWRJY29uKCdjaGVja2JveEluZGV0ZXJtaW5hdGUnKTtcbiAgICAgICAgLy8gc2V0cyBhbiBpbml0aWFsIGNhbGN1bGF0aW9uIGZvciB0aGUgc2Nyb2xsYmFyIHdpZHRoXG4gICAgICAgIHRoaXMuZ2V0U2Nyb2xsYmFyV2lkdGgoKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuY2hlY2tDb2x1bW5EZWZQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5jb2x1bW5EZWZzID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdyaWRPcHRpb25zLmNvbHVtbkRlZnMuZm9yRWFjaChmdW5jdGlvbiAoY29sRGVmKSB7XG4gICAgICAgICAgICB2YXIgdXNlclByb3BlcnRpZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhjb2xEZWYpO1xuICAgICAgICAgICAgdmFyIHZhbGlkUHJvcGVydGllcyA9IF9fc3ByZWFkJGcoQ29sRGVmVXRpbC5BTExfUFJPUEVSVElFUywgQ29sRGVmVXRpbC5GUkFNRVdPUktfUFJPUEVSVElFUyk7XG4gICAgICAgICAgICBfdGhpcy5jaGVja1Byb3BlcnRpZXModXNlclByb3BlcnRpZXMsIHZhbGlkUHJvcGVydGllcywgdmFsaWRQcm9wZXJ0aWVzLCAnY29sRGVmJywgJ2h0dHBzOi8vd3d3LmFnLWdyaWQuY29tL2phdmFzY3JpcHQtZ3JpZC1jb2x1bW4tcHJvcGVydGllcy8nKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmNoZWNrR3JpZE9wdGlvbnNQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdXNlclByb3BlcnRpZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzLmdyaWRPcHRpb25zKTtcbiAgICAgICAgdmFyIHZhbGlkUHJvcGVydGllcyA9IF9fc3ByZWFkJGcoUHJvcGVydHlLZXlzLkFMTF9QUk9QRVJUSUVTLCBQcm9wZXJ0eUtleXMuRlJBTUVXT1JLX1BST1BFUlRJRVMsIHZhbHVlcyhFdmVudHMpLm1hcChmdW5jdGlvbiAoZXZlbnQpIHsgcmV0dXJuIENvbXBvbmVudFV0aWwuZ2V0Q2FsbGJhY2tGb3JFdmVudChldmVudCk7IH0pKTtcbiAgICAgICAgdmFyIHZhbGlkUHJvcGVydGllc0FuZEV4Y2VwdGlvbnMgPSBfX3NwcmVhZCRnKHZhbGlkUHJvcGVydGllcywgWydhcGknLCAnY29sdW1uQXBpJ10pO1xuICAgICAgICB0aGlzLmNoZWNrUHJvcGVydGllcyh1c2VyUHJvcGVydGllcywgdmFsaWRQcm9wZXJ0aWVzQW5kRXhjZXB0aW9ucywgdmFsaWRQcm9wZXJ0aWVzLCAnZ3JpZE9wdGlvbnMnLCAnaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vamF2YXNjcmlwdC1kYXRhLWdyaWQvZ3JpZC1vcHRpb25zLycpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5jaGVja1Byb3BlcnRpZXMgPSBmdW5jdGlvbiAodXNlclByb3BlcnRpZXMsIHZhbGlkUHJvcGVydGllc0FuZEV4Y2VwdGlvbnMsIHZhbGlkUHJvcGVydGllcywgY29udGFpbmVyTmFtZSwgZG9jc1VybCkge1xuICAgICAgICB2YXIgaW52YWxpZFByb3BlcnRpZXMgPSBmdXp6eUNoZWNrU3RyaW5ncyh1c2VyUHJvcGVydGllcywgdmFsaWRQcm9wZXJ0aWVzQW5kRXhjZXB0aW9ucywgdmFsaWRQcm9wZXJ0aWVzKTtcbiAgICAgICAgaXRlcmF0ZU9iamVjdChpbnZhbGlkUHJvcGVydGllcywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcImFnLWdyaWQ6IGludmFsaWQgXCIgKyBjb250YWluZXJOYW1lICsgXCIgcHJvcGVydHkgJ1wiICsga2V5ICsgXCInIGRpZCB5b3UgbWVhbiBhbnkgb2YgdGhlc2U6IFwiICsgdmFsdWUuc2xpY2UoMCwgOCkuam9pbihcIiwgXCIpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhpbnZhbGlkUHJvcGVydGllcykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiYWctZ3JpZDogdG8gc2VlIGFsbCB0aGUgdmFsaWQgXCIgKyBjb250YWluZXJOYW1lICsgXCIgcHJvcGVydGllcyBwbGVhc2UgY2hlY2s6IFwiICsgZG9jc1VybCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKlxuICAgICogV3JhcCB0aGUgdXNlciBjYWxsYmFjayBhbmQgYXR0YWNoIHRoZSBhcGksIGNvbHVtbkFwaSBhbmQgY29udGV4dCB0byB0aGUgcGFyYW1zIG9iamVjdCBvbiB0aGUgd2F5IHRocm91Z2guXG4gICAgKiBAcGFyYW0gY2FsbGJhY2sgVXNlciBwcm92aWRlZCBjYWxsYmFja1xuICAgICogQHJldHVybnMgV3JhcHBlZCBjYWxsYmFjayB3aGVyZSB0aGUgcGFyYW1zIG9iamVjdCBub3QgcmVxdWlyZSBhcGksIGNvbHVtbkFwaSBhbmQgY29udGV4dFxuICAgICovXG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5tZXJnZUdyaWRDb21tb25QYXJhbXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgd3JhcHBlZCA9IGZ1bmN0aW9uIChjYWxsYmFja1BhcmFtcykge1xuICAgICAgICAgICAgICAgIHZhciBtZXJnZWRQYXJhbXMgPSBfX2Fzc2lnbiRnKF9fYXNzaWduJGcoe30sIGNhbGxiYWNrUGFyYW1zKSwgeyBhcGk6IF90aGlzLmdldEFwaSgpLCBjb2x1bW5BcGk6IF90aGlzLmdldENvbHVtbkFwaSgpLCBjb250ZXh0OiBfdGhpcy5nZXRDb250ZXh0KCkgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG1lcmdlZFBhcmFtcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIHdyYXBwZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXREb21EYXRhS2V5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kb21EYXRhS2V5O1xuICAgIH07XG4gICAgLy8gcmV0dXJucyB0aGUgZG9tIGRhdGEsIG9yIHVuZGVmaW5lZCBpZiBub3QgZm91bmRcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldERvbURhdGEgPSBmdW5jdGlvbiAoZWxlbWVudCwga2V5KSB7XG4gICAgICAgIHZhciBkb21EYXRhID0gZWxlbWVudFt0aGlzLmdldERvbURhdGFLZXkoKV07XG4gICAgICAgIHJldHVybiBkb21EYXRhID8gZG9tRGF0YVtrZXldIDogdW5kZWZpbmVkO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5zZXREb21EYXRhID0gZnVuY3Rpb24gKGVsZW1lbnQsIGtleSwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGRvbURhdGFLZXkgPSB0aGlzLmdldERvbURhdGFLZXkoKTtcbiAgICAgICAgdmFyIGRvbURhdGEgPSBlbGVtZW50W2RvbURhdGFLZXldO1xuICAgICAgICBpZiAobWlzc2luZyhkb21EYXRhKSkge1xuICAgICAgICAgICAgZG9tRGF0YSA9IHt9O1xuICAgICAgICAgICAgZWxlbWVudFtkb21EYXRhS2V5XSA9IGRvbURhdGE7XG4gICAgICAgIH1cbiAgICAgICAgZG9tRGF0YVtrZXldID0gdmFsdWU7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzUm93U2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5yb3dTZWxlY3Rpb24gPT09ICdzaW5nbGUnIHx8IHRoaXMuZ3JpZE9wdGlvbnMucm93U2VsZWN0aW9uID09PSAnbXVsdGlwbGUnO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzUm93RGVzZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc1Jvd0Rlc2VsZWN0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSb3dTZWxlY3Rpb25NdWx0aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucm93U2VsZWN0aW9uID09PSAnbXVsdGlwbGUnO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1Jvd011bHRpU2VsZWN0V2l0aENsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMucm93TXVsdGlTZWxlY3RXaXRoQ2xpY2spO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRDb250ZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5jb250ZXh0O1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1Bpdm90TW9kZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnBpdm90TW9kZSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NFeHBhbmRhYmxlUGl2b3RHcm91cHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0V4cGFuZGFibGVQaXZvdEdyb3Vwcyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFBpdm90Q29sdW1uR3JvdXBUb3RhbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnBpdm90Q29sdW1uR3JvdXBUb3RhbHM7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFBpdm90Um93VG90YWxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5waXZvdFJvd1RvdGFscztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSb3dNb2RlbEluZmluaXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5yb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9JTkZJTklURTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSb3dNb2RlbFZpZXdwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5yb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9WSUVXUE9SVDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSb3dNb2RlbFNlcnZlclNpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnJvd01vZGVsVHlwZSA9PT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX1NFUlZFUl9TSURFO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1Jvd01vZGVsRGVmYXVsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIChtaXNzaW5nKHRoaXMuZ3JpZE9wdGlvbnMucm93TW9kZWxUeXBlKSB8fFxuICAgICAgICAgICAgdGhpcy5ncmlkT3B0aW9ucy5yb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRnVsbFJvd0VkaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmVkaXRUeXBlID09PSAnZnVsbFJvdyc7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NGb2N1c0FmdGVyUmVmcmVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzRm9jdXNBZnRlclJlZnJlc2gpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQnJvd3NlclJlc2l6ZU9ic2VydmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NCcm93c2VyUmVzaXplT2JzZXJ2ZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzTWFpbnRhaW5VbnNvcnRlZE9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NNYWludGFpblVuc29ydGVkT3JkZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQ2xlYXJPbkZpbGxSZWR1Y3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0NsZWFyT25GaWxsUmVkdWN0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTaG93VG9vbFBhbmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc2lkZUJhciAmJiBBcnJheS5pc0FycmF5KHRoaXMuZ2V0U2lkZUJhcigpLnRvb2xQYW5lbHMpKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0U2lkZUJhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuc2lkZUJhcjtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc1RvdWNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NUb3VjaCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzTWFpbnRhaW5Db2x1bW5PcmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLm1haW50YWluQ29sdW1uT3JkZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzUm93VHJhbnNmb3JtID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NSb3dUcmFuc2Zvcm0pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQ29sdW1uU3RhdGVFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0NvbHVtblN0YXRlRXZlbnRzKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNBbGxvd0RyYWdGcm9tQ29sdW1uc1Rvb2xQYW5lbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmFsbG93RHJhZ0Zyb21Db2x1bW5zVG9vbFBhbmVsKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUudXNlQXN5bmNFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NBc3luY0V2ZW50cyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRW5hYmxlQ2VsbENoYW5nZUZsYXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2VsbENoYW5nZUZsYXNoKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Q2VsbEZsYXNoRGVsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmNlbGxGbGFzaERlbGF5IHx8IDUwMDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Q2VsbEZhZGVEZWxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuY2VsbEZhZGVEZWxheSB8fCAxMDAwO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0dyb3VwU2VsZWN0c0NoaWxkcmVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZ3JvdXBTZWxlY3RzQ2hpbGRyZW4pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzUm93SG92ZXJIaWdobGlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc1Jvd0hvdmVySGlnaGxpZ2h0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNDb2x1bW5Ib3ZlckhpZ2hsaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmNvbHVtbkhvdmVySGlnaGxpZ2h0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cFNlbGVjdHNGaWx0ZXJlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmdyb3VwU2VsZWN0c0ZpbHRlcmVkKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cEhpZGVPcGVuUGFyZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmdyb3VwSGlkZU9wZW5QYXJlbnRzKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cE1haW50YWluT3JkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5ncm91cE1haW50YWluT3JkZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRBdXRvR3JvdXBDb2x1bW5EZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmF1dG9Hcm91cENvbHVtbkRlZjtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNDb2x1bW5zU29ydGluZ0NvdXBsZWRUb0dyb3VwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHZhciBhdXRvR3JvdXBDb2x1bW5EZWYgPSB0aGlzLmdldEF1dG9Hcm91cENvbHVtbkRlZigpO1xuICAgICAgICB2YXIgaXNDbGllbnRTaWRlUm93TW9kZWwgPSB0aGlzLmlzUm93TW9kZWxEZWZhdWx0KCk7XG4gICAgICAgIHJldHVybiBpc0NsaWVudFNpZGVSb3dNb2RlbCAmJiAhKChfYSA9IGF1dG9Hcm91cENvbHVtbkRlZikgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNvbXBhcmF0b3IpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0dyb3VwTXVsdGlBdXRvQ29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5ncm91cERpc3BsYXlUeXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXRjaGVzR3JvdXBEaXNwbGF5VHlwZSgnbXVsdGlwbGVDb2x1bW5zJywgdGhpcy5ncmlkT3B0aW9ucy5ncm91cERpc3BsYXlUeXBlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB3ZSBhcmUgZG9pbmcgaGlkZU9wZW5QYXJlbnRzIHdlIGFsc28gc2hvdyBtdWx0aXBsZSBjb2x1bW5zLCBvdGhlcndpc2UgaGlkZU9wZW5QYXJlbnRzIHdvdWxkIG5vdCB3b3JrXG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5ncm91cEhpZGVPcGVuUGFyZW50cyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzR3JvdXBVc2VFbnRpcmVSb3cgPSBmdW5jdGlvbiAocGl2b3RNb2RlKSB7XG4gICAgICAgIC8vIHdlIG5ldmVyIGFsbG93IGdyb3VwVXNlRW50aXJlUm93IGlmIGluIHBpdm90IG1vZGUsIG90aGVyd2lzZSB3ZSB3b24ndCBzZWUgdGhlIHBpdm90IHZhbHVlcy5cbiAgICAgICAgaWYgKHBpdm90TW9kZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmdyb3VwRGlzcGxheVR5cGUgP1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzR3JvdXBEaXNwbGF5VHlwZSgnZ3JvdXBSb3dzJywgdGhpcy5ncmlkT3B0aW9ucy5ncm91cERpc3BsYXlUeXBlKSA6IGZhbHNlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1Jvd0dyb3VwUGFuZWxTdXBwcmVzc1NvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5yb3dHcm91cFBhbmVsU3VwcHJlc3NTb3J0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cFJvd3NTdGlja3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5ncm91cFJvd3NTdGlja3kpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0dyb3VwU3VwcHJlc3NBdXRvQ29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNDdXN0b21Sb3dHcm91cHMgPSB0aGlzLmdyaWRPcHRpb25zLmdyb3VwRGlzcGxheVR5cGUgP1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzR3JvdXBEaXNwbGF5VHlwZSgnY3VzdG9tJywgdGhpcy5ncmlkT3B0aW9ucy5ncm91cERpc3BsYXlUeXBlKSA6IGZhbHNlO1xuICAgICAgICBpZiAoaXNDdXN0b21Sb3dHcm91cHMpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnRyZWVEYXRhRGlzcGxheVR5cGUgP1xuICAgICAgICAgICAgdGhpcy5tYXRjaGVzVHJlZURhdGFEaXNwbGF5VHlwZSgnY3VzdG9tJywgdGhpcy5ncmlkT3B0aW9ucy50cmVlRGF0YURpc3BsYXlUeXBlKSA6IGZhbHNlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0dyb3VwUmVtb3ZlU2luZ2xlQ2hpbGRyZW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5ncm91cFJlbW92ZVNpbmdsZUNoaWxkcmVuKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cFJlbW92ZUxvd2VzdFNpbmdsZUNoaWxkcmVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZ3JvdXBSZW1vdmVMb3dlc3RTaW5nbGVDaGlsZHJlbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzR3JvdXBJbmNsdWRlRm9vdGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZ3JvdXBJbmNsdWRlRm9vdGVyKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cEluY2x1ZGVUb3RhbEZvb3RlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmdyb3VwSW5jbHVkZVRvdGFsRm9vdGVyKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNHcm91cFN1cHByZXNzQmxhbmtIZWFkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5ncm91cFN1cHByZXNzQmxhbmtIZWFkZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzUm93Q2xpY2tTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc1Jvd0NsaWNrU2VsZWN0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc0NlbGxGb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzQ2VsbEZvY3VzKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc011bHRpU29ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzTXVsdGlTb3J0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNBbHdheXNNdWx0aVNvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5hbHdheXNNdWx0aVNvcnQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc011bHRpU29ydEtleUN0cmwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLm11bHRpU29ydEtleSA9PT0gJ2N0cmwnO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1Bpdm90U3VwcHJlc3NBdXRvQ29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMucGl2b3RTdXBwcmVzc0F1dG9Db2x1bW4pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzRHJhZ0xlYXZlSGlkZXNDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NEcmFnTGVhdmVIaWRlc0NvbHVtbnMpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzUm93R3JvdXBIaWRlc0NvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc1Jvd0dyb3VwSGlkZXNDb2x1bW5zKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc1Njcm9sbE9uTmV3RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzU2Nyb2xsT25OZXdEYXRhKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc1Njcm9sbFdoZW5Qb3B1cHNBcmVPcGVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NTY3JvbGxXaGVuUG9wdXBzQXJlT3Blbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzUm93RHJhZ0VudGlyZVJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnJvd0RyYWdFbnRpcmVSb3cpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRSb3dEcmFnVGV4dCA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgdmFyIGNvbERlZiA9IGNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgICAgIGlmIChjb2xEZWYucm93RHJhZ1RleHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29sRGVmLnJvd0RyYWdUZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnJvd0RyYWdUZXh0O1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzUm93RHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzUm93RHJhZyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzUm93RHJhZ01hbmFnZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5yb3dEcmFnTWFuYWdlZCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NNb3ZlV2hlblJvd0RyYWdnaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NNb3ZlV2hlblJvd0RyYWdnaW5nKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSb3dEcmFnTXVsdGlSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5yb3dEcmFnTXVsdGlSb3cpO1xuICAgIH07XG4gICAgLy8gcmV0dXJucyBlaXRoZXIgJ3ByaW50JywgJ2F1dG9IZWlnaHQnIG9yICdub3JtYWwnIChub3JtYWwgaXMgdGhlIGRlZmF1bHQpXG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXREb21MYXlvdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkb21MYXlvdXQgPSB0aGlzLmdyaWRPcHRpb25zLmRvbUxheW91dCB8fCBDb25zdGFudHMuRE9NX0xBWU9VVF9OT1JNQUw7XG4gICAgICAgIHZhciB2YWxpZExheW91dHMgPSBbXG4gICAgICAgICAgICBDb25zdGFudHMuRE9NX0xBWU9VVF9QUklOVCxcbiAgICAgICAgICAgIENvbnN0YW50cy5ET01fTEFZT1VUX0FVVE9fSEVJR0hULFxuICAgICAgICAgICAgQ29uc3RhbnRzLkRPTV9MQVlPVVRfTk9STUFMXG4gICAgICAgIF07XG4gICAgICAgIGlmICh2YWxpZExheW91dHMuaW5kZXhPZihkb21MYXlvdXQpID09PSAtMSkge1xuICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29uc29sZS53YXJuKFwiQUcgR3JpZDogXCIgKyBkb21MYXlvdXQgKyBcIiBpcyBub3QgdmFsaWQgZm9yIERPTSBMYXlvdXQsIHZhbGlkIHZhbHVlcyBhcmUgXCIgKyBDb25zdGFudHMuRE9NX0xBWU9VVF9OT1JNQUwgKyBcIiwgXCIgKyBDb25zdGFudHMuRE9NX0xBWU9VVF9BVVRPX0hFSUdIVCArIFwiIGFuZCBcIiArIENvbnN0YW50cy5ET01fTEFZT1VUX1BSSU5UKTtcbiAgICAgICAgICAgIH0sICd3YXJuIGFib3V0IGRvbSBsYXlvdXQgdmFsdWVzJyk7XG4gICAgICAgICAgICByZXR1cm4gQ29uc3RhbnRzLkRPTV9MQVlPVVRfTk9STUFMO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkb21MYXlvdXQ7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NIb3Jpem9udGFsU2Nyb2xsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NIb3Jpem9udGFsU2Nyb2xsKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc01heFJlbmRlcmVkUm93UmVzdHJpY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc01heFJlbmRlcmVkUm93UmVzdHJpY3Rpb24pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0V4Y2x1ZGVDaGlsZHJlbldoZW5UcmVlRGF0YUZpbHRlcmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmV4Y2x1ZGVDaGlsZHJlbldoZW5UcmVlRGF0YUZpbHRlcmluZyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzQWx3YXlzU2hvd0hvcml6b250YWxTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5hbHdheXNTaG93SG9yaXpvbnRhbFNjcm9sbCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzQWx3YXlzU2hvd1ZlcnRpY2FsU2Nyb2xsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuYWx3YXlzU2hvd1ZlcnRpY2FsU2Nyb2xsKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNEZWJvdW5jZVZlcnRpY2FsU2Nyb2xsYmFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZGVib3VuY2VWZXJ0aWNhbFNjcm9sbGJhcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NMb2FkaW5nT3ZlcmxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzTG9hZGluZ092ZXJsYXkpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzTm9Sb3dzT3ZlcmxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzTm9Sb3dzT3ZlcmxheSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NGaWVsZERvdE5vdGF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NGaWVsZERvdE5vdGF0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0UGlubmVkVG9wUm93RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucGlubmVkVG9wUm93RGF0YTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0UGlubmVkQm90dG9tUm93RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucGlubmVkQm90dG9tUm93RGF0YTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNGdW5jdGlvbnNQYXNzaXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZnVuY3Rpb25zUGFzc2l2ZSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NDaGFuZ2VEZXRlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0NoYW5nZURldGVjdGlvbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NBbmltYXRpb25GcmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzQW5pbWF0aW9uRnJhbWUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRRdWlja0ZpbHRlclRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnF1aWNrRmlsdGVyVGV4dDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNDYWNoZVF1aWNrRmlsdGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuY2FjaGVRdWlja0ZpbHRlcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzVW5Tb3J0SWNvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnVuU29ydEljb24pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzTWVudUhpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc01lbnVIaWRlKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbnRlck1vdmVzRG93bkFmdGVyRWRpdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmVudGVyTW92ZXNEb3duQWZ0ZXJFZGl0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbnRlck1vdmVzRG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmVudGVyTW92ZXNEb3duKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNVbmRvUmVkb0NlbGxFZGl0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMudW5kb1JlZG9DZWxsRWRpdGluZyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFVuZG9SZWRvQ2VsbEVkaXRpbmdMaW1pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRvTnVtYmVyKHRoaXMuZ3JpZE9wdGlvbnMudW5kb1JlZG9DZWxsRWRpdGluZ0xpbWl0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbmFibGVDZWxsRWRpdGluZ09uQmFja3NwYWNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2VsbEVkaXRpbmdPbkJhY2tzcGFjZSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFJvd1N0eWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5yb3dTdHlsZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Um93Q2xhc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnJvd0NsYXNzO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRSb3dTdHlsZUZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLmdldFJvd1N0eWxlKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Um93Q2xhc3NGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5nZXRSb3dDbGFzcyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLnJvd0NsYXNzUnVsZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnJvd0NsYXNzUnVsZXM7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU2VydmVyU2lkZUluZmluaXRlU2Nyb2xsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc2VydmVyU2lkZUluZmluaXRlU2Nyb2xsKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxQYXJhbXNGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5nZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFBhcmFtcyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENyZWF0ZUNoYXJ0Q29udGFpbmVyRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMuY3JlYXRlQ2hhcnRDb250YWluZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQb3B1cFBhcmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucG9wdXBQYXJlbnQ7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEJsb2NrTG9hZERlYm91bmNlTWlsbGlzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5ibG9ja0xvYWREZWJvdW5jZU1pbGxpcztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0UG9zdFByb2Nlc3NQb3B1cEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLnBvc3RQcm9jZXNzUG9wdXApO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQYWdpbmF0aW9uTnVtYmVyRm9ybWF0dGVyRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMucGFnaW5hdGlvbk51bWJlckZvcm1hdHRlcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENoaWxkQ291bnRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5nZXRDaGlsZENvdW50O1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRJc0FwcGx5U2VydmVyU2lkZVRyYW5zYWN0aW9uRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMuaXNBcHBseVNlcnZlclNpZGVUcmFuc2FjdGlvbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEluaXRpYWxHcm91cE9yZGVyQ29tcGFyYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5ncmlkT3B0aW9ucywgaW5pdGlhbEdyb3VwT3JkZXJDb21wYXJhdG9yID0gX2EuaW5pdGlhbEdyb3VwT3JkZXJDb21wYXJhdG9yLCBkZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3IgPSBfYS5kZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3I7XG4gICAgICAgIGlmIChpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyhpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3IpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGRlcHJlY2F0ZWQgd2F5LCBzbyBwcm92aWRlIGEgcHJveHkgdG8gbWFrZSBpdCBjb21wYXRpYmxlXG4gICAgICAgIGlmIChkZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAocGFyYW1zKSB7IHJldHVybiBkZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3IocGFyYW1zLm5vZGVBLCBwYXJhbXMubm9kZUIpOyB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldElzRnVsbFdpZHRoQ2VsbEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuZ3JpZE9wdGlvbnMsIGlzRnVsbFdpZHRoUm93ID0gX2EuaXNGdWxsV2lkdGhSb3csIGlzRnVsbFdpZHRoQ2VsbCA9IF9hLmlzRnVsbFdpZHRoQ2VsbDtcbiAgICAgICAgaWYgKGlzRnVsbFdpZHRoUm93KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXMoaXNGdWxsV2lkdGhSb3cpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGRlcHJlY2F0ZWQgd2F5LCBzbyBwcm92aWRlIGEgcHJveHkgdG8gbWFrZSBpdCBjb21wYXRpYmxlXG4gICAgICAgIGlmIChpc0Z1bGxXaWR0aENlbGwpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAocGFyYW1zKSB7IHJldHVybiBpc0Z1bGxXaWR0aENlbGwocGFyYW1zLnJvd05vZGUpOyB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEZ1bGxXaWR0aENlbGxSZW5kZXJlclBhcmFtcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuZnVsbFdpZHRoQ2VsbFJlbmRlcmVyUGFyYW1zO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0VtYmVkRnVsbFdpZHRoUm93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmVtYmVkRnVsbFdpZHRoUm93cykgfHwgaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZGVwcmVjYXRlZEVtYmVkRnVsbFdpZHRoUm93cyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRGV0YWlsUm93QXV0b0hlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmRldGFpbFJvd0F1dG9IZWlnaHQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRTdXBwcmVzc0tleWJvYXJkRXZlbnRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0tleWJvYXJkRXZlbnQ7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEJ1c2luZXNzS2V5Rm9yTm9kZUZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmdldEJ1c2luZXNzS2V5Rm9yTm9kZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0QXBpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5hcGk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENvbHVtbkFwaSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuY29sdW1uQXBpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1JlYWRPbmx5RWRpdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnJlYWRPbmx5RWRpdCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzSW1tdXRhYmxlRGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2UgdXNlZCB0byBoYXZlIGEgcHJvcGVydHkgaW1tdXRhYmxlRGF0YSBmb3IgdGhpcy4gaG93ZXZlciB0aGlzIHdhcyBkZXByZWNhdGVkXG4gICAgICAgIC8vIGluIGZhdm91ciBvZiBoYXZpbmcgSW1tdXRhYmxlIERhdGEgb24gYnkgZGVmYXVsdCB3aGVuIGdldFJvd0lkIGlzIHByb3ZpZGVkXG4gICAgICAgIHZhciBnZXRSb3dJZFByb3ZpZGVkID0gdGhpcy5ncmlkT3B0aW9ucy5nZXRSb3dJZCAhPSBudWxsO1xuICAgICAgICB2YXIgaW1tdXRhYmxlRGF0YSA9IGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmltbXV0YWJsZURhdGEpO1xuICAgICAgICAvLyB0aGlzIHByb3BlcnR5IGlzIGEgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgcHJvcGVydHksIGZvciB0aG9zZSB3aG8gd2FudFxuICAgICAgICAvLyB0aGUgb2xkIGJlaGF2aW91ciBvZiBSb3cgSUQncyBidXQgTk9UIEltbXV0YWJsZSBEYXRhLlxuICAgICAgICB2YXIgcmVzZXRSb3dEYXRhT25VcGRhdGUgPSBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5yZXNldFJvd0RhdGFPblVwZGF0ZSk7XG4gICAgICAgIGlmIChyZXNldFJvd0RhdGFPblVwZGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnZXRSb3dJZFByb3ZpZGVkIHx8IGltbXV0YWJsZURhdGE7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRW5zdXJlRG9tT3JkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5lbnN1cmVEb21PcmRlcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRW5hYmxlQ2hhcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2hhcnRzKSkge1xuICAgICAgICAgICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuR3JpZENoYXJ0c01vZHVsZSwgJ2VuYWJsZUNoYXJ0cycpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbmFibGVDaGFydFRvb2xQYW5lbHNCdXR0b24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVDaGFydFRvb2xQYW5lbHNCdXR0b24pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRDb2xSZXNpemVEZWZhdWx0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5jb2xSZXNpemVEZWZhdWx0O1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1NpbmdsZUNsaWNrRWRpdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnNpbmdsZUNsaWNrRWRpdCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NDbGlja0VkaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0NsaWNrRWRpdCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3RvcEVkaXRpbmdXaGVuQ2VsbHNMb3NlRm9jdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdG9wRWRpdGluZ1doZW5DZWxsc0xvc2VGb2N1cyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEdyb3VwRGVmYXVsdEV4cGFuZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5ncm91cERlZmF1bHRFeHBhbmRlZDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0TWF4Q29uY3VycmVudERhdGFzb3VyY2VSZXF1ZXN0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlcyA9IHRvTnVtYmVyKHRoaXMuZ3JpZE9wdGlvbnMubWF4Q29uY3VycmVudERhdGFzb3VyY2VSZXF1ZXN0cyk7XG4gICAgICAgIGlmIChyZXMgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIDI7XG4gICAgICAgIH0gLy8gMiBpcyB0aGUgZGVmYXVsdFxuICAgICAgICBpZiAocmVzIDw9IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSAvLyBuZWdhdGl2ZSBudW1iZXIsIGVnIC0xLCBtZWFucyBubyBtYXggcmVzdHJpY3Rpb25cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0TWF4QmxvY2tzSW5DYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMubWF4QmxvY2tzSW5DYWNoZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Q2FjaGVPdmVyZmxvd1NpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmNhY2hlT3ZlcmZsb3dTaXplO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQYWdpbmF0aW9uUGFnZVNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0b051bWJlcih0aGlzLmdyaWRPcHRpb25zLnBhZ2luYXRpb25QYWdlU2l6ZSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzUGFnaW5hdGVDaGlsZFJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzaG91bGRQYWdpbmF0ZSA9IHRoaXMuaXNHcm91cFJlbW92ZVNpbmdsZUNoaWxkcmVuKCkgfHwgdGhpcy5pc0dyb3VwUmVtb3ZlTG93ZXN0U2luZ2xlQ2hpbGRyZW4oKTtcbiAgICAgICAgaWYgKHNob3VsZFBhZ2luYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMucGFnaW5hdGVDaGlsZFJvd3MpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRDYWNoZUJsb2NrU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG9uZU9yR3JlYXRlcih0aGlzLmdyaWRPcHRpb25zLmNhY2hlQmxvY2tTaXplKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SW5maW5pdGVJbml0aWFsUm93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmluZmluaXRlSW5pdGlhbFJvd0NvdW50O1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRTZXJ2ZXJTaWRlSW5pdGlhbFJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93Q291bnQgPSB0aGlzLmdyaWRPcHRpb25zLnNlcnZlclNpZGVJbml0aWFsUm93Q291bnQ7XG4gICAgICAgIGlmICh0eXBlb2Ygcm93Q291bnQgPT09ICdudW1iZXInICYmIHJvd0NvdW50ID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHJvd0NvdW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAxO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1B1cmdlQ2xvc2VkUm93Tm9kZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5wdXJnZUNsb3NlZFJvd05vZGVzKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc1BhZ2luYXRpb25QYW5lbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzUGFnaW5hdGlvblBhbmVsKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Um93RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucm93RGF0YTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbmFibGVSdGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVSdGwpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRSb3dHcm91cFBhbmVsU2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucm93R3JvdXBQYW5lbFNob3c7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFBpdm90UGFuZWxTaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5waXZvdFBhbmVsU2hvdztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNBbmd1bGFyQ29tcGlsZVJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5hbmd1bGFyQ29tcGlsZVJvd3MpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0FuZ3VsYXJDb21waWxlRmlsdGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmFuZ3VsYXJDb21waWxlRmlsdGVycyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRGVidWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5kZWJ1Zyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENvbHVtbkRlZnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmNvbHVtbkRlZnM7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENvbHVtblR5cGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5jb2x1bW5UeXBlcztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0RGF0YXNvdXJjZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuZGF0YXNvdXJjZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Vmlld3BvcnREYXRhc291cmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy52aWV3cG9ydERhdGFzb3VyY2U7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFNlcnZlclNpZGVEYXRhc291cmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5zZXJ2ZXJTaWRlRGF0YXNvdXJjZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNBY2NlbnRlZFNvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5hY2NlbnRlZFNvcnQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0VuYWJsZUJyb3dzZXJUb29sdGlwcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmVuYWJsZUJyb3dzZXJUb29sdGlwcyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRW5hYmxlQ2VsbEV4cHJlc3Npb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2VsbEV4cHJlc3Npb25zKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbmFibGVHcm91cEVkaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVHcm91cEVkaXQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzTWlkZGxlQ2xpY2tTY3JvbGxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NNaWRkbGVDbGlja1Njcm9sbHMpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1ByZXZlbnREZWZhdWx0T25Db250ZXh0TWVudSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnByZXZlbnREZWZhdWx0T25Db250ZXh0TWVudSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NQcmV2ZW50RGVmYXVsdE9uTW91c2VXaGVlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzUHJldmVudERlZmF1bHRPbk1vdXNlV2hlZWwpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQ29sdW1uVmlydHVhbGlzYXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0NvbHVtblZpcnR1YWxpc2F0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc1Jvd1ZpcnR1YWxpc2F0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NSb3dWaXJ0dWFsaXNhdGlvbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NDb250ZXh0TWVudSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzQ29udGV4dE1lbnUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0FsbG93Q29udGV4dE1lbnVXaXRoQ29udHJvbEtleSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmFsbG93Q29udGV4dE1lbnVXaXRoQ29udHJvbEtleSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NDb3B5Um93c1RvQ2xpcGJvYXJkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NDb3B5Um93c1RvQ2xpcGJvYXJkKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc0NvcHlTaW5nbGVDZWxsUmFuZ2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NDb3B5U2luZ2xlQ2VsbFJhbmdlcyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzQ29weUhlYWRlcnNUb0NsaXBib2FyZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmNvcHlIZWFkZXJzVG9DbGlwYm9hcmQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0NvcHlHcm91cEhlYWRlcnNUb0NsaXBib2FyZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmNvcHlHcm91cEhlYWRlcnNUb0NsaXBib2FyZCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NDbGlwYm9hcmRQYXN0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzQ2xpcGJvYXJkUGFzdGUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzTGFzdEVtcHR5TGluZU9uUGFzdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0xhc3RFbXB0eUxpbmVPblBhc3RlKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNQYWdpbmF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMucGFnaW5hdGlvbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NFbnRlcnByaXNlUmVzZXRPbk5ld0NvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0VudGVycHJpc2VSZXNldE9uTmV3Q29sdW1ucyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFByb2Nlc3NEYXRhRnJvbUNsaXBib2FyZEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLnByb2Nlc3NEYXRhRnJvbUNsaXBib2FyZCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEFzeW5jVHJhbnNhY3Rpb25XYWl0TWlsbGlzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZXhpc3RzKHRoaXMuZ3JpZE9wdGlvbnMuYXN5bmNUcmFuc2FjdGlvbldhaXRNaWxsaXMpID8gdGhpcy5ncmlkT3B0aW9ucy5hc3luY1RyYW5zYWN0aW9uV2FpdE1pbGxpcyA6IENvbnN0YW50cy5CQVRDSF9XQUlUX01JTExJUztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc01vdmFibGVDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NNb3ZhYmxlQ29sdW1ucyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzQW5pbWF0ZVJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIG5ldmVyIGFsbG93IGFuaW1hdGluZyBpZiBlbmZvcmNpbmcgdGhlIHJvdyBvcmRlclxuICAgICAgICBpZiAodGhpcy5pc0Vuc3VyZURvbU9yZGVyKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuYW5pbWF0ZVJvd3MpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQ29sdW1uTW92ZUFuaW1hdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzQ29sdW1uTW92ZUFuaW1hdGlvbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NBZ2dGdW5jSW5IZWFkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0FnZ0Z1bmNJbkhlYWRlcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NBZ2dBdFJvb3RMZXZlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzQWdnQXRSb290TGV2ZWwpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQWdnRmlsdGVyZWRPbmx5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNHcm91cEFnZ0ZpbHRlcmluZyA9IHRoaXMuZ2V0R3JvdXBBZ2dGaWx0ZXJpbmcoKSAhPT0gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gaXNHcm91cEFnZ0ZpbHRlcmluZyB8fCBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0FnZ0ZpbHRlcmVkT25seSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzUmVtb3ZlUGl2b3RIZWFkZXJSb3dXaGVuU2luZ2xlVmFsdWVDb2x1bW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5yZW1vdmVQaXZvdEhlYWRlclJvd1doZW5TaW5nbGVWYWx1ZUNvbHVtbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU2hvd09wZW5lZEdyb3VwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc2hvd09wZW5lZEdyb3VwKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSZWFjdFVpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMucmVhY3RVaSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NSZWFjdFVpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NSZWFjdFVpKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFbmFibGVSYW5nZVNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5SYW5nZVNlbGVjdGlvbk1vZHVsZSkgJiYgaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUmFuZ2VTZWxlY3Rpb24pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0VuYWJsZVJhbmdlSGFuZGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlUmFuZ2VIYW5kbGUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0VuYWJsZUZpbGxIYW5kbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVGaWxsSGFuZGxlKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0RmlsbEhhbmRsZURpcmVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRpcmVjdGlvbiA9IHRoaXMuZ3JpZE9wdGlvbnMuZmlsbEhhbmRsZURpcmVjdGlvbjtcbiAgICAgICAgaWYgKCFkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgIHJldHVybiAneHknO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaXJlY3Rpb24gIT09ICd4JyAmJiBkaXJlY3Rpb24gIT09ICd5JyAmJiBkaXJlY3Rpb24gIT09ICd4eScpIHtcbiAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiB2YWxpZCB2YWx1ZXMgZm9yIGZpbGxIYW5kbGVEaXJlY3Rpb24gYXJlICd4JywgJ3knIGFuZCAneHknLiBEZWZhdWx0IHRvICd4eScuXCIpOyB9LCAnd2FybiBpbnZhbGlkIGZpbGwgZGlyZWN0aW9uJyk7XG4gICAgICAgICAgICByZXR1cm4gJ3h5JztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlyZWN0aW9uO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRGaWxsT3BlcmF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5maWxsT3BlcmF0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc011bHRpUmFuZ2VTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc011bHRpUmFuZ2VTZWxlY3Rpb24pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1BhZ2luYXRpb25BdXRvUGFnZVNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5wYWdpbmF0aW9uQXV0b1BhZ2VTaXplKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNSZW1lbWJlckdyb3VwU3RhdGVXaGVuTmV3RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnJlbWVtYmVyR3JvdXBTdGF0ZVdoZW5OZXdEYXRhKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SWNvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmljb25zO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRHcm91cEFnZ0ZpbHRlcmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHVzZXJWYWx1ZSA9IHRoaXMuZ3JpZE9wdGlvbnMuZ3JvdXBBZ2dGaWx0ZXJpbmc7XG4gICAgICAgIGlmICh0eXBlb2YgdXNlclZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModXNlclZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNUcnVlKHVzZXJWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEFnZ0Z1bmNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5hZ2dGdW5jcztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0U29ydGluZ09yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5zb3J0aW5nT3JkZXI7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEFsaWduZWRHcmlkcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuYWxpZ25lZEdyaWRzO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc01hc3RlckRldGFpbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1hc3RlckRldGFpbCA9IGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLm1hc3RlckRldGFpbCk7XG4gICAgICAgIGlmIChtYXN0ZXJEZXRhaWwpIHtcbiAgICAgICAgICAgIHJldHVybiBNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLk1hc3RlckRldGFpbE1vZHVsZSwgJ21hc3RlckRldGFpbCcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzS2VlcERldGFpbFJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5rZWVwRGV0YWlsUm93cyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEtlZXBEZXRhaWxSb3dzQ291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBrZWVwRGV0YWlsUm93c0NvdW50ID0gdGhpcy5ncmlkT3B0aW9ucy5rZWVwRGV0YWlsUm93c0NvdW50O1xuICAgICAgICBpZiAoZXhpc3RzKGtlZXBEZXRhaWxSb3dzQ291bnQpICYmIGtlZXBEZXRhaWxSb3dzQ291bnQgPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5rZWVwRGV0YWlsUm93c0NvdW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBERUZBVUxUX0tFRVBfREVUQUlMX1JPV19DT1VOVDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SXNSb3dNYXN0ZXJGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5pc1Jvd01hc3RlcjtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SXNSb3dTZWxlY3RhYmxlRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuaXNSb3dTZWxlY3RhYmxlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRHcm91cFJvd1JlbmRlcmVyUGFyYW1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5ncm91cFJvd1JlbmRlcmVyUGFyYW1zO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRPdmVybGF5TG9hZGluZ1RlbXBsYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5vdmVybGF5TG9hZGluZ1RlbXBsYXRlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRPdmVybGF5Tm9Sb3dzVGVtcGxhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLm92ZXJsYXlOb1Jvd3NUZW1wbGF0ZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc0F1dG9TaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NBdXRvU2l6ZSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRW5hYmxlQ2VsbFRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5lbmFibGVDZWxsVGV4dFNlbGVjdGlvbik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2RlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzUGFyZW50c0luUm93Tm9kZXMpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzQ2xpcGJvYXJkQXBpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc3VwcHJlc3NDbGlwYm9hcmRBcGkpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0Z1bmN0aW9uc1JlYWRPbmx5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZnVuY3Rpb25zUmVhZE9ubHkpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0VuYWJsZUNlbGxUZXh0U2VsZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuZW5hYmxlQ2VsbFRleHRTZWxlY3Rpb24pO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXREZWZhdWx0Q29sRGVmID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5kZWZhdWx0Q29sRGVmO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXREZWZhdWx0Q29sR3JvdXBEZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmRlZmF1bHRDb2xHcm91cERlZjtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0RGVmYXVsdEV4cG9ydFBhcmFtcyA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLmRlZmF1bHRFeHBvcnRQYXJhbXMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IFNpbmNlIHYyNS4yIGBkZWZhdWx0RXhwb3J0UGFyYW1zYCAgaGFzIGJlZW4gcmVwbGFjZWQgYnkgYGRlZmF1bHRcIiArIGNhcGl0YWxpc2UodHlwZSkgKyBcIkV4cG9ydFBhcmFtc2AnXCIpO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdjc3YnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuZGVmYXVsdEV4cG9ydFBhcmFtcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmRlZmF1bHRFeHBvcnRQYXJhbXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdjc3YnICYmIHRoaXMuZ3JpZE9wdGlvbnMuZGVmYXVsdENzdkV4cG9ydFBhcmFtcykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuZGVmYXVsdENzdkV4cG9ydFBhcmFtcztcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2V4Y2VsJyAmJiB0aGlzLmdyaWRPcHRpb25zLmRlZmF1bHRFeGNlbEV4cG9ydFBhcmFtcykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuZGVmYXVsdEV4Y2VsRXhwb3J0UGFyYW1zO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NDc3ZFeHBvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc0NzdkV4cG9ydCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzQWxsb3dTaG93Q2hhbmdlQWZ0ZXJGaWx0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5hbGxvd1Nob3dDaGFuZ2VBZnRlckZpbHRlcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU3VwcHJlc3NFeGNlbEV4cG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzRXhjZWxFeHBvcnQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1N1cHByZXNzTWFrZUNvbHVtblZpc2libGVBZnRlclVuR3JvdXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zdXBwcmVzc01ha2VDb2x1bW5WaXNpYmxlQWZ0ZXJVbkdyb3VwKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0RGF0YVBhdGhGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5nZXREYXRhUGF0aDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SXNTZXJ2ZXJTaWRlR3JvdXBGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5pc1NlcnZlclNpZGVHcm91cDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SXNTZXJ2ZXJTaWRlR3JvdXBPcGVuQnlEZWZhdWx0RnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMuaXNTZXJ2ZXJTaWRlR3JvdXBPcGVuQnlEZWZhdWx0KTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SXNHcm91cE9wZW5CeURlZmF1bHRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5pc0dyb3VwT3BlbkJ5RGVmYXVsdCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFNlcnZlclNpZGVHcm91cEtleUZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmdldFNlcnZlclNpZGVHcm91cEtleTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0R3JvdXBSb3dBZ2dGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmdyaWRPcHRpb25zLCBnZXRHcm91cFJvd0FnZyA9IF9hLmdldEdyb3VwUm93QWdnLCBncm91cFJvd0FnZ05vZGVzID0gX2EuZ3JvdXBSb3dBZ2dOb2RlcztcbiAgICAgICAgaWYgKGdldEdyb3VwUm93QWdnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXMoZ2V0R3JvdXBSb3dBZ2cpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGRlcHJlY2F0ZWQgd2F5LCBzbyBwcm92aWRlIGEgcHJveHkgdG8gbWFrZSBpdCBjb21wYXRpYmxlXG4gICAgICAgIGlmIChncm91cFJvd0FnZ05vZGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHBhcmFtcykgeyByZXR1cm4gZ3JvdXBSb3dBZ2dOb2RlcyhwYXJhbXMubm9kZXMpOyB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENvbnRleHRNZW51SXRlbXNGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5nZXRDb250ZXh0TWVudUl0ZW1zKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0TWFpbk1lbnVJdGVtc0Z1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLmdldE1haW5NZW51SXRlbXMpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRSb3dJZEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuZ3JpZE9wdGlvbnMsIGdldFJvd0lkID0gX2EuZ2V0Um93SWQsIGdldFJvd05vZGVJZCA9IF9hLmdldFJvd05vZGVJZDtcbiAgICAgICAgaWYgKGdldFJvd0lkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXMoZ2V0Um93SWQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGRlcHJlY2F0ZWQgd2F5LCBzbyBwcm92aWRlIGEgcHJveHkgdG8gbWFrZSBpdCBjb21wYXRpYmxlXG4gICAgICAgIGlmIChnZXRSb3dOb2RlSWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAocGFyYW1zKSB7IHJldHVybiBnZXRSb3dOb2RlSWQocGFyYW1zLmRhdGEpOyB9O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldE5hdmlnYXRlVG9OZXh0SGVhZGVyRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMubmF2aWdhdGVUb05leHRIZWFkZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRUYWJUb05leHRIZWFkZXJGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy50YWJUb05leHRIZWFkZXIpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXROYXZpZ2F0ZVRvTmV4dENlbGxGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5uYXZpZ2F0ZVRvTmV4dENlbGwpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRUYWJUb05leHRDZWxsRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMudGFiVG9OZXh0Q2VsbCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEdyaWRUYWJJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLmdyaWRPcHRpb25zLnRhYkluZGV4IHx8IDApLnRvU3RyaW5nKCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzVHJlZURhdGEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB1c2luZ1RyZWVEYXRhID0gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMudHJlZURhdGEpO1xuICAgICAgICBpZiAodXNpbmdUcmVlRGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuUm93R3JvdXBpbmdNb2R1bGUsICdUcmVlIERhdGEnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzVmFsdWVDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnZhbHVlQ2FjaGUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc1ZhbHVlQ2FjaGVOZXZlckV4cGlyZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy52YWx1ZUNhY2hlTmV2ZXJFeHBpcmVzKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNEZWx0YVNvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5kZWx0YVNvcnQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5pc0FnZ3JlZ2F0ZU9ubHlDaGFuZ2VkQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLmFnZ3JlZ2F0ZU9ubHlDaGFuZ2VkQ29sdW1ucyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFByb2Nlc3NQaXZvdFJlc3VsdENvbERlZkZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnByb2Nlc3NQaXZvdFJlc3VsdENvbERlZiB8fCB0aGlzLmdyaWRPcHRpb25zLnByb2Nlc3NTZWNvbmRhcnlDb2xEZWY7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFByb2Nlc3NQaXZvdFJlc3VsdENvbEdyb3VwRGVmRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucHJvY2Vzc1Bpdm90UmVzdWx0Q29sR3JvdXBEZWYgfHwgdGhpcy5ncmlkT3B0aW9ucy5wcm9jZXNzU2Vjb25kYXJ5Q29sR3JvdXBEZWY7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFNlbmRUb0NsaXBib2FyZEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLnNlbmRUb0NsaXBib2FyZCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFByb2Nlc3NSb3dQb3N0Q3JlYXRlRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMucHJvY2Vzc1Jvd1Bvc3RDcmVhdGUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQcm9jZXNzQ2VsbEZvckNsaXBib2FyZEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLnByb2Nlc3NDZWxsRm9yQ2xpcGJvYXJkKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0UHJvY2Vzc0hlYWRlckZvckNsaXBib2FyZEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyh0aGlzLmdyaWRPcHRpb25zLnByb2Nlc3NIZWFkZXJGb3JDbGlwYm9hcmQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQcm9jZXNzR3JvdXBIZWFkZXJGb3JDbGlwYm9hcmRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5wcm9jZXNzR3JvdXBIZWFkZXJGb3JDbGlwYm9hcmQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQcm9jZXNzQ2VsbEZyb21DbGlwYm9hcmRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5wcm9jZXNzQ2VsbEZyb21DbGlwYm9hcmQpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRWaWV3cG9ydFJvd01vZGVsUGFnZVNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBvbmVPckdyZWF0ZXIodGhpcy5ncmlkT3B0aW9ucy52aWV3cG9ydFJvd01vZGVsUGFnZVNpemUsIERFRkFVTFRfVklFV1BPUlRfUk9XX01PREVMX1BBR0VfU0laRSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFZpZXdwb3J0Um93TW9kZWxCdWZmZXJTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gemVyb09yR3JlYXRlcih0aGlzLmdyaWRPcHRpb25zLnZpZXdwb3J0Um93TW9kZWxCdWZmZXJTaXplLCBERUZBVUxUX1ZJRVdQT1JUX1JPV19NT0RFTF9CVUZGRVJfU0laRSk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU2VydmVyU2lkZVNvcnRBbGxMZXZlbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc0VuYWJsZWQgPSBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zZXJ2ZXJTaWRlU29ydEFsbExldmVscyk7XG4gICAgICAgIGlmICghdGhpcy5pc1Jvd01vZGVsU2VydmVyU2lkZSgpICYmIGlzRW5hYmxlZCkge1xuICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogVGhlIGBzZXJ2ZXJTaWRlU29ydEFsbExldmVsc2AgcHJvcGVydHkgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIHRoZSBzZXJ2ZXIgc2lkZSByb3cgbW9kZWwuJyk7IH0sICdzZXJ2ZXJTaWRlU29ydEFsbExldmVscycpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0VuYWJsZWQ7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU2VydmVyU2lkZUZpbHRlckFsbExldmVscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlzRW5hYmxlZCA9IGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnNlcnZlclNpZGVGaWx0ZXJBbGxMZXZlbHMpO1xuICAgICAgICBpZiAoIXRoaXMuaXNSb3dNb2RlbFNlcnZlclNpZGUoKSAmJiBpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZSBgc2VydmVyU2lkZUZpbHRlckFsbExldmVsc2AgcHJvcGVydHkgY2FuIG9ubHkgYmUgdXNlZCB3aXRoIHRoZSBzZXJ2ZXIgc2lkZSByb3cgbW9kZWwuJyk7IH0sICdzZXJ2ZXJTaWRlRmlsdGVyQWxsTGV2ZWxzJyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzRW5hYmxlZDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTZXJ2ZXJTaWRlU29ydE9uU2VydmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNFbmFibGVkID0gaXNUcnVlKHRoaXMuZ3JpZE9wdGlvbnMuc2VydmVyU2lkZVNvcnRPblNlcnZlcik7XG4gICAgICAgIGlmICghdGhpcy5pc1Jvd01vZGVsU2VydmVyU2lkZSgpICYmIGlzRW5hYmxlZCkge1xuICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogVGhlIGBzZXJ2ZXJTaWRlU29ydE9uU2VydmVyYCBwcm9wZXJ0eSBjYW4gb25seSBiZSB1c2VkIHdpdGggdGhlIHNlcnZlciBzaWRlIHJvdyBtb2RlbC4nKTsgfSwgJ3NlcnZlclNpZGVTb3J0T25TZXJ2ZXJSb3dNb2RlbCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzVHJlZURhdGEoKSAmJiBpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZSBgc2VydmVyU2lkZVNvcnRPblNlcnZlcmAgcHJvcGVydHkgY2Fubm90IGJlIHVzZWQgd2hpbGUgdXNpbmcgdHJlZSBkYXRhLicpOyB9LCAnc2VydmVyU2lkZVNvcnRPblNlcnZlclRyZWVEYXRhJyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzRW5hYmxlZDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTZXJ2ZXJTaWRlRmlsdGVyT25TZXJ2ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc0VuYWJsZWQgPSBpc1RydWUodGhpcy5ncmlkT3B0aW9ucy5zZXJ2ZXJTaWRlRmlsdGVyT25TZXJ2ZXIpO1xuICAgICAgICBpZiAoIXRoaXMuaXNSb3dNb2RlbFNlcnZlclNpZGUoKSAmJiBpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZSBgc2VydmVyU2lkZUZpbHRlck9uU2VydmVyYCBwcm9wZXJ0eSBjYW4gb25seSBiZSB1c2VkIHdpdGggdGhlIHNlcnZlciBzaWRlIHJvdyBtb2RlbC4nKTsgfSwgJ3NlcnZlclNpZGVGaWx0ZXJPblNlcnZlclJvd01vZGVsJyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNUcmVlRGF0YSgpICYmIGlzRW5hYmxlZCkge1xuICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogVGhlIGBzZXJ2ZXJTaWRlRmlsdGVyT25TZXJ2ZXJgIHByb3BlcnR5IGNhbm5vdCBiZSB1c2VkIHdoaWxlIHVzaW5nIHRyZWUgZGF0YS4nKTsgfSwgJ3NlcnZlclNpZGVGaWx0ZXJPblNlcnZlclRyZWVEYXRhJyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzRW5hYmxlZDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0UG9zdFNvcnRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmdyaWRPcHRpb25zLCBwb3N0U29ydFJvd3MgPSBfYS5wb3N0U29ydFJvd3MsIHBvc3RTb3J0ID0gX2EucG9zdFNvcnQ7XG4gICAgICAgIGlmIChwb3N0U29ydFJvd3MpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1lcmdlR3JpZENvbW1vblBhcmFtcyhwb3N0U29ydFJvd3MpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGRlcHJlY2F0ZWQgd2F5LCBzbyBwcm92aWRlIGEgcHJveHkgdG8gbWFrZSBpdCBjb21wYXRpYmxlXG4gICAgICAgIGlmIChwb3N0U29ydCkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChwYXJhbXMpIHsgcmV0dXJuIHBvc3RTb3J0KHBhcmFtcy5ub2Rlcyk7IH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Q2hhcnRUb29sYmFySXRlbXNGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZUdyaWRDb21tb25QYXJhbXModGhpcy5ncmlkT3B0aW9ucy5nZXRDaGFydFRvb2xiYXJJdGVtcyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldENoYXJ0VGhlbWVPdmVycmlkZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmNoYXJ0VGhlbWVPdmVycmlkZXM7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEN1c3RvbUNoYXJ0VGhlbWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5jdXN0b21DaGFydFRoZW1lcztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Q2hhcnRUaGVtZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHJldHVybiBkZWZhdWx0IHRoZW1lcyBpZiB1c2VyIGhhc24ndCBzdXBwbGllZCBhbnlcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuY2hhcnRUaGVtZXMgfHwgWydhZy1kZWZhdWx0JywgJ2FnLW1hdGVyaWFsJywgJ2FnLXBhc3RlbCcsICdhZy12aXZpZCcsICdhZy1zb2xhciddO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRDaGFydFRvb2xQYW5lbHNEZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmNoYXJ0VG9vbFBhbmVsc0RlZjtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Q2xpcGJvYXJkRGVsaW1pdGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZXhpc3RzKHRoaXMuZ3JpZE9wdGlvbnMuY2xpcGJvYXJkRGVsaW1pdGVyKSA/IHRoaXMuZ3JpZE9wdGlvbnMuY2xpcGJvYXJkRGVsaW1pdGVyIDogJ1xcdCc7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLnNldFByb3BlcnR5ID0gZnVuY3Rpb24gKGtleSwgdmFsdWUsIGZvcmNlKSB7XG4gICAgICAgIGlmIChmb3JjZSA9PT0gdm9pZCAwKSB7IGZvcmNlID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSB0aGlzLmdyaWRPcHRpb25zW2tleV07XG4gICAgICAgIGlmIChmb3JjZSB8fCBwcmV2aW91c1ZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICB2YXIgZXZlbnRfMSA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBrZXksXG4gICAgICAgICAgICAgICAgY3VycmVudFZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlOiBwcmV2aW91c1ZhbHVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5wcm9wZXJ0eUV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50XzEpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoa2V5LCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLnByb3BlcnR5RXZlbnRTZXJ2aWNlLmFkZEV2ZW50TGlzdGVuZXIoa2V5LCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoa2V5LCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLnByb3BlcnR5RXZlbnRTZXJ2aWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoa2V5LCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzU2tpcEhlYWRlck9uQXV0b1NpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuZ3JpZE9wdGlvbnMuc2tpcEhlYWRlck9uQXV0b1NpemU7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEF1dG9TaXplUGFkZGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5ncmlkT3B0aW9ucy5hdXRvU2l6ZVBhZGRpbmc7XG4gICAgICAgIHJldHVybiB2YWx1ZSAhPSBudWxsICYmIHZhbHVlID49IDAgPyB2YWx1ZSA6IDIwO1xuICAgIH07XG4gICAgLy8gcHJvcGVydGllc1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0SGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZ3JpZE9wdGlvbnMuaGVhZGVySGVpZ2h0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuaGVhZGVySGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldEZyb21UaGVtZSgyNSwgJ2hlYWRlckhlaWdodCcpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRGbG9hdGluZ0ZpbHRlcnNIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5ncmlkT3B0aW9ucy5mbG9hdGluZ0ZpbHRlcnNIZWlnaHQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5mbG9hdGluZ0ZpbHRlcnNIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RnJvbVRoZW1lKDI1LCAnaGVhZGVySGVpZ2h0Jyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldEdyb3VwSGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZ3JpZE9wdGlvbnMuZ3JvdXBIZWFkZXJIZWlnaHQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5ncm91cEhlYWRlckhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRIZWFkZXJIZWlnaHQoKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0UGl2b3RIZWFkZXJIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5ncmlkT3B0aW9ucy5waXZvdEhlYWRlckhlaWdodCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnBpdm90SGVhZGVySGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldEhlYWRlckhlaWdodCgpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRQaXZvdEdyb3VwSGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZ3JpZE9wdGlvbnMucGl2b3RHcm91cEhlYWRlckhlaWdodCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLnBpdm90R3JvdXBIZWFkZXJIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0R3JvdXBIZWFkZXJIZWlnaHQoKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNFeHRlcm5hbEZpbHRlclByZXNlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5ncmlkT3B0aW9ucy5pc0V4dGVybmFsRmlsdGVyUHJlc2VudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMuaXNFeHRlcm5hbEZpbHRlclByZXNlbnQoeyBhcGk6IHRoaXMuZ2V0QXBpKCksIGNvbHVtbkFwaTogdGhpcy5nZXRDb2x1bW5BcGkoKSwgY29udGV4dDogdGhpcy5nZXRDb250ZXh0KCkgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5kb2VzRXh0ZXJuYWxGaWx0ZXJQYXNzID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmdyaWRPcHRpb25zLmRvZXNFeHRlcm5hbEZpbHRlclBhc3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLmRvZXNFeHRlcm5hbEZpbHRlclBhc3Mobm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRUb29sdGlwRGVsYXkgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmdyaWRPcHRpb25zLCB0b29sdGlwU2hvd0RlbGF5ID0gX2EudG9vbHRpcFNob3dEZWxheSwgdG9vbHRpcEhpZGVEZWxheSA9IF9hLnRvb2x0aXBIaWRlRGVsYXk7XG4gICAgICAgIHZhciBkZWxheSA9IHR5cGUgPT09ICdzaG93JyA/IHRvb2x0aXBTaG93RGVsYXkgOiB0b29sdGlwSGlkZURlbGF5O1xuICAgICAgICB2YXIgY2FwaXRhbGlzZWRUeXBlID0gY2FwaXRhbGlzZSh0eXBlKTtcbiAgICAgICAgaWYgKGV4aXN0cyhkZWxheSkpIHtcbiAgICAgICAgICAgIGlmIChkZWxheSA8IDApIHtcbiAgICAgICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKFwiYWctZ3JpZDogdG9vbHRpcFwiICsgY2FwaXRhbGlzZWRUeXBlICsgXCJEZWxheSBzaG91bGQgbm90IGJlIGxvd2VyIHRoYW4gMFwiKTsgfSwgXCJ0b29sdGlwXCIgKyBjYXBpdGFsaXNlZFR5cGUgKyBcIkRlbGF5V2FyblwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCgyMDAsIGRlbGF5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNUb29sdGlwTW91c2VUcmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnRvb2x0aXBNb3VzZVRyYWNrKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNTdXBwcmVzc01vZGVsVXBkYXRlQWZ0ZXJVcGRhdGVUcmFuc2FjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVHJ1ZSh0aGlzLmdyaWRPcHRpb25zLnN1cHByZXNzTW9kZWxVcGRhdGVBZnRlclVwZGF0ZVRyYW5zYWN0aW9uKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0RG9jdW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGlmIHVzZXIgaXMgcHJvdmlkaW5nIGRvY3VtZW50LCB3ZSB1c2UgdGhlIHVzZXJzIG9uZSxcbiAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIHVzZSB0aGUgZG9jdW1lbnQgb24gdGhlIGdsb2JhbCBuYW1lc3BhY2UuXG4gICAgICAgIHZhciByZXN1bHQgPSBudWxsO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5nZXREb2N1bWVudCAmJiBleGlzdHModGhpcy5ncmlkT3B0aW9ucy5nZXREb2N1bWVudCkpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuZ3JpZE9wdGlvbnMuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLmVHcmlkRGl2KSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmVHcmlkRGl2Lm93bmVyRG9jdW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdCAmJiBleGlzdHMocmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZG9jdW1lbnQ7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldE1pbkNvbFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWluQ29sV2lkdGggPSB0aGlzLmdyaWRPcHRpb25zLm1pbkNvbFdpZHRoO1xuICAgICAgICBpZiAoZXhpc3RzKG1pbkNvbFdpZHRoKSAmJiBtaW5Db2xXaWR0aCA+IEdyaWRPcHRpb25zV3JhcHBlcl8xLk1JTl9DT0xfV0lEVEgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLm1pbkNvbFdpZHRoO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtZWFzdXJlZE1pbiA9IHRoaXMuZ2V0RnJvbVRoZW1lKG51bGwsICdoZWFkZXJDZWxsTWluV2lkdGgnKTtcbiAgICAgICAgcmV0dXJuIGV4aXN0cyhtZWFzdXJlZE1pbikgPyBNYXRoLm1heChtZWFzdXJlZE1pbiwgR3JpZE9wdGlvbnNXcmFwcGVyXzEuTUlOX0NPTF9XSURUSCkgOiBHcmlkT3B0aW9uc1dyYXBwZXJfMS5NSU5fQ09MX1dJRFRIO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRNYXhDb2xXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnMubWF4Q29sV2lkdGggJiYgdGhpcy5ncmlkT3B0aW9ucy5tYXhDb2xXaWR0aCA+IEdyaWRPcHRpb25zV3JhcHBlcl8xLk1JTl9DT0xfV0lEVEgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zLm1heENvbFdpZHRoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRDb2xXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmdyaWRPcHRpb25zLmNvbFdpZHRoICE9PSAnbnVtYmVyJyB8fCB0aGlzLmdyaWRPcHRpb25zLmNvbFdpZHRoIDwgR3JpZE9wdGlvbnNXcmFwcGVyXzEuTUlOX0NPTF9XSURUSCkge1xuICAgICAgICAgICAgcmV0dXJuIDIwMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5jb2xXaWR0aDtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Um93QnVmZmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93QnVmZmVyID0gdGhpcy5ncmlkT3B0aW9ucy5yb3dCdWZmZXI7XG4gICAgICAgIGlmICh0eXBlb2Ygcm93QnVmZmVyID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgaWYgKHJvd0J1ZmZlciA8IDApIHtcbiAgICAgICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKFwiQUcgR3JpZDogcm93QnVmZmVyIHNob3VsZCBub3QgYmUgbmVnYXRpdmVcIik7IH0sICd3YXJuIHJvd0J1ZmZlciBuZWdhdGl2ZScpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ3JpZE9wdGlvbnMucm93QnVmZmVyID0gcm93QnVmZmVyID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJvd0J1ZmZlciA9IENvbnN0YW50cy5ST1dfQlVGRkVSX1NJWkU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd0J1ZmZlcjtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0Um93QnVmZmVySW5QaXhlbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dzVG9CdWZmZXIgPSB0aGlzLmdldFJvd0J1ZmZlcigpO1xuICAgICAgICB2YXIgZGVmYXVsdFJvd0hlaWdodCA9IHRoaXMuZ2V0Um93SGVpZ2h0QXNOdW1iZXIoKTtcbiAgICAgICAgcmV0dXJuIHJvd3NUb0J1ZmZlciAqIGRlZmF1bHRSb3dIZWlnaHQ7XG4gICAgfTtcbiAgICAvLyB0aGUgdXNlciBtaWdodCBiZSB1c2luZyBzb21lIG5vbi1zdGFuZGFyZCBzY3JvbGxiYXIsIGVnIGEgc2Nyb2xsYmFyIHRoYXQgaGFzIHplcm9cbiAgICAvLyB3aWR0aCBhbmQgb3ZlcmxheXMgKGxpa2UgdGhlIFNhZmFyaSBzY3JvbGxiYXIsIGJ1dCBwcmVzZW50ZWQgaW4gQ2hyb21lKS4gc28gd2VcbiAgICAvLyBhbGxvdyB0aGUgdXNlciB0byBwcm92aWRlIHRoZSBzY3JvbGwgd2lkdGggYmVmb3JlIHdlIHdvcmsgaXQgb3V0LlxuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0U2Nyb2xsYmFyV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnNjcm9sbGJhcldpZHRoID09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciB1c2VHcmlkT3B0aW9ucyA9IHR5cGVvZiB0aGlzLmdyaWRPcHRpb25zLnNjcm9sbGJhcldpZHRoID09PSAnbnVtYmVyJyAmJiB0aGlzLmdyaWRPcHRpb25zLnNjcm9sbGJhcldpZHRoID49IDA7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsYmFyV2lkdGggPSB1c2VHcmlkT3B0aW9ucyA/IHRoaXMuZ3JpZE9wdGlvbnMuc2Nyb2xsYmFyV2lkdGggOiBnZXRTY3JvbGxiYXJXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKHNjcm9sbGJhcldpZHRoICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbGJhcldpZHRoID0gc2Nyb2xsYmFyV2lkdGg7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9TQ1JPTExCQVJfV0lEVEhfQ0hBTkdFRFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNjcm9sbGJhcldpZHRoO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5jaGVja0ZvckRlcHJlY2F0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGNhc3RpbmcgdG8gZ2VuZXJpYyBvYmplY3QsIHNvIHR5cGVzY3JpcHQgY29tcGlsZXMgZXZlbiB0aG91Z2hcbiAgICAgICAgLy8gd2UgYXJlIGxvb2tpbmcgZm9yIGF0dHJpYnV0ZXMgdGhhdCBkb24ndCBleGlzdFxuICAgICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuZ3JpZE9wdGlvbnM7XG4gICAgICAgIGlmIChvcHRpb25zLmRlcHJlY2F0ZWRFbWJlZEZ1bGxXaWR0aFJvd3MpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHNpbmNlIHYyMS4yLCBkZXByZWNhdGVkRW1iZWRGdWxsV2lkdGhSb3dzIGhhcyBiZWVuIHJlcGxhY2VkIHdpdGggZW1iZWRGdWxsV2lkdGhSb3dzLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5yb3dEZXNlbGVjdGlvbikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjQueCwgcm93RGVzZWxlY3Rpb24gaXMgZGVwcmVjYXRlZCBhbmQgdGhlIGJlaGF2aW91ciBpcyB0cnVlIGJ5IGRlZmF1bHQuIFBsZWFzZSB1c2UgYHN1cHByZXNzUm93RGVzZWxlY3Rpb25gIHRvIHByZXZlbnQgcm93cyBmcm9tIGJlaW5nIGRlc2VsZWN0ZWQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuZW5hYmxlTXVsdGlSb3dEcmFnZ2luZykge1xuICAgICAgICAgICAgb3B0aW9ucy5yb3dEcmFnTXVsdGlSb3cgPSB0cnVlO1xuICAgICAgICAgICAgZGVsZXRlIG9wdGlvbnMuZW5hYmxlTXVsdGlSb3dEcmFnZ2luZztcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjI2LjEsIGBlbmFibGVNdWx0aVJvd0RyYWdnaW5nYCBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIGByb3dEcmFnTXVsdGlSb3dgLicpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjaGVja1JlbmFtZWRQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvbGRQcm9wLCBuZXdQcm9wLCB2ZXJzaW9uKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9uc1tvbGRQcm9wXSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2luY2UgdmVyc2lvbiBcIiArIHZlcnNpb24gKyBcIiwgJ1wiICsgb2xkUHJvcCArIFwiJyBpcyBkZXByZWNhdGVkIC8gcmVuYW1lZCwgcGxlYXNlIHVzZSB0aGUgbmV3IHByb3BlcnR5IG5hbWUgJ1wiICsgbmV3UHJvcCArIFwiJyBpbnN0ZWFkLlwiKTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9uc1tuZXdQcm9wXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnNbbmV3UHJvcF0gPSBvcHRpb25zW29sZFByb3BdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY2hlY2tSZW5hbWVkUHJvcGVydHkoJ2JhdGNoVXBkYXRlV2FpdE1pbGxpcycsICdhc3luY1RyYW5zYWN0aW9uV2FpdE1pbGxpcycsICcyMy4xLngnKTtcbiAgICAgICAgY2hlY2tSZW5hbWVkUHJvcGVydHkoJ2RlbHRhUm93RGF0YU1vZGUnLCAnaW1tdXRhYmxlRGF0YScsICcyMy4xLngnKTtcbiAgICAgICAgY2hlY2tSZW5hbWVkUHJvcGVydHkoJ3NlcnZlclNpZGVGaWx0ZXJpbmdBbHdheXNSZXNldHMnLCAnc2VydmVyU2lkZUZpbHRlckFsbExldmVscycsICcyOC4wLjAnKTtcbiAgICAgICAgY2hlY2tSZW5hbWVkUHJvcGVydHkoJ3NlcnZlclNpZGVTb3J0aW5nQWx3YXlzUmVzZXRzJywgJ3NlcnZlclNpZGVTb3J0QWxsTGV2ZWxzJywgJzI4LjAuMCcpO1xuICAgICAgICBpZiAob3B0aW9ucy5pbW11dGFibGVDb2x1bW5zIHx8IG9wdGlvbnMuZGVsdGFDb2x1bW5Nb2RlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyNC4wLCBpbW11dGFibGVDb2x1bW5zIGFuZCBkZWx0YUNvbHVtbk1vZGUgcHJvcGVydGllcyBhcmUgZ29uZS4gVGhlIGdyaWQgbm93IHdvcmtzIGxpa2UgdGhpcyBhcyBkZWZhdWx0LiBUbyBrZWVwIGNvbHVtbiBvcmRlciBtYWludGFpbmVkLCBzZXQgZ3JpZCBwcm9wZXJ0eSBhcHBseUNvbHVtbkRlZk9yZGVyPXRydWUnKTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja1JlbmFtZWRQcm9wZXJ0eSgnc3VwcHJlc3NTZXRDb2x1bW5TdGF0ZUV2ZW50cycsICdzdXBwcmVzc0NvbHVtblN0YXRlRXZlbnRzJywgJzI0LjAueCcpO1xuICAgICAgICBpZiAob3B0aW9ucy5ncm91cFJvd0lubmVyUmVuZGVyZXIgfHwgb3B0aW9ucy5ncm91cFJvd0lubmVyUmVuZGVyZXJQYXJhbXMgfHwgb3B0aW9ucy5ncm91cFJvd0lubmVyUmVuZGVyZXJGcmFtZXdvcmspIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjI0LjAsIGdyaWQgcHJvcGVydGllcyBncm91cFJvd0lubmVyUmVuZGVyZXIsIGdyb3VwUm93SW5uZXJSZW5kZXJlckZyYW1ld29yayBhbmQgZ3JvdXBSb3dJbm5lclJlbmRlcmVyUGFyYW1zIGFyZSBubyBsb25nZXIgdXNlZC4nKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignICBJbnN0ZWFkIHVzZSB0aGUgZ3JpZCBwcm9wZXJ0aWVzIGdyb3VwUm93UmVuZGVyZXJQYXJhbXMuaW5uZXJSZW5kZXJlciwgZ3JvdXBSb3dSZW5kZXJlclBhcmFtcy5pbm5lclJlbmRlcmVyRnJhbWV3b3JrIGFuZCBncm91cFJvd1JlbmRlcmVyUGFyYW1zLmlubmVyUmVuZGVyZXJQYXJhbXMuJyk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJyAgRm9yIGV4YW1wbGUgaW5zdGVhZCBvZiB0aGlzOicpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCcgICAgZ3JvdXBSb3dJbm5lclJlbmRlcmVyOiBcIm15UmVuZGVyZXJcIicpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCcgICAgZ3JvdXBSb3dJbm5lclJlbmRlcmVyUGFyYW1zOiB7eDogYX0nKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignICBSZXBsYWNlIHdpdGggdGhpczonKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignICAgIGdyb3VwUm93UmVuZGVyZXJQYXJhbXM6IHsnKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignICAgICAgaW5uZXJSZW5kZXJlcjogXCJteVJlbmRlcmVyXCIsJyk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJyAgICAgIGlubmVyUmVuZGVyZXJQYXJhbXM6IHt4OiBhfScpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCcgICAgfScpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCcgIFdlIGhhdmUgY29waWVkIHRoZSBwcm9wZXJ0aWVzIG92ZXIgZm9yIHlvdS4gSG93ZXZlciB0byBzdG9wIHRoaXMgZXJyb3IgbWVzc2FnZSwgcGxlYXNlIGNoYW5nZSB5b3VyIGFwcGxpY2F0aW9uIGNvZGUuJyk7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMuZ3JvdXBSb3dSZW5kZXJlclBhcmFtcykge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuZ3JvdXBSb3dSZW5kZXJlclBhcmFtcyA9IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG9wdGlvbnMuZ3JvdXBSb3dSZW5kZXJlclBhcmFtcztcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmdyb3VwUm93SW5uZXJSZW5kZXJlcikge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5pbm5lclJlbmRlcmVyID0gb3B0aW9ucy5ncm91cFJvd0lubmVyUmVuZGVyZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5ncm91cFJvd0lubmVyUmVuZGVyZXJQYXJhbXMpIHtcbiAgICAgICAgICAgICAgICBwYXJhbXMuaW5uZXJSZW5kZXJlclBhcmFtcyA9IG9wdGlvbnMuZ3JvdXBSb3dJbm5lclJlbmRlcmVyUGFyYW1zO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZ3JvdXBSb3dJbm5lclJlbmRlcmVyRnJhbWV3b3JrKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zLmlubmVyUmVuZGVyZXJGcmFtZXdvcmsgPSBvcHRpb25zLmdyb3VwUm93SW5uZXJSZW5kZXJlckZyYW1ld29yaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5yZW1lbWJlckdyb3VwU3RhdGVXaGVuTmV3RGF0YSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjQuMCwgZ3JpZCBwcm9wZXJ0eSByZW1lbWJlckdyb3VwU3RhdGVXaGVuTmV3RGF0YSBpcyBkZXByZWNhdGVkLiBUaGlzIGZlYXR1cmUgd2FzIHByb3ZpZGVkIGJlZm9yZSBUcmFuc2FjdGlvbiBVcGRhdGVzIHdvcmtlZCAod2hpY2gga2VlcCBncm91cCBzdGF0ZSkuIE5vdyB0aGF0IHRyYW5zYWN0aW9uIHVwZGF0ZXMgYXJlIHBvc3NpYmxlIGFuZCB0aGV5IGtlZXAgZ3JvdXAgc3RhdGUsIHRoaXMgZmVhdHVyZSBpcyBubyBsb25nZXIgbmVlZGVkLicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmRldGFpbENlbGxSZW5kZXJlclBhcmFtcyAmJiBvcHRpb25zLmRldGFpbENlbGxSZW5kZXJlclBhcmFtcy5hdXRvSGVpZ2h0KSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyNC4xLCBncmlkIHByb3BlcnR5IGRldGFpbENlbGxSZW5kZXJlclBhcmFtcy5hdXRvSGVpZ2h0IGlzIHJlcGxhY2VkIHdpdGggZ3JpZCBwcm9wZXJ0eSBkZXRhaWxSb3dBdXRvSGVpZ2h0LiBUaGlzIGFsbG93cyB0aGlzIGZlYXR1cmUgdG8gd29yayB3aGVuIHlvdSBwcm92aWRlIGEgY3VzdG9tIERldGFpbENlbGxSZW5kZXJlcicpO1xuICAgICAgICAgICAgb3B0aW9ucy5kZXRhaWxSb3dBdXRvSGVpZ2h0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5zdXBwcmVzc0tleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHNpbmNlIHYyNC4xIHN1cHByZXNzS2V5Ym9hcmRFdmVudCBpbiB0aGUgZ3JpZE9wdGlvbnMgaGFzIGJlZW4gZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluXFxuICAgICAgICAgICAgICAgICBmdXR1cmUgdmVyc2lvbnMgb2YgQUcgR3JpZC4gSWYgeW91IG5lZWQgdGhpcyB0byBiZSBzZXQgZm9yIGV2ZXJ5IGNvbHVtbiB1c2UgdGhlIGRlZmF1bHRDb2xEZWYgcHJvcGVydHkuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLnN1cHByZXNzRW50ZXJwcmlzZVJlc2V0T25OZXdDb2x1bW5zKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyNSwgZ3JpZCBwcm9wZXJ0eSBzdXBwcmVzc0VudGVycHJpc2VSZXNldE9uTmV3Q29sdW1ucyBpcyBkZXByZWNhdGVkLiBUaGlzIHdhcyBhIHRlbXBvcmFyeSBwcm9wZXJ0eSB0byBhbGxvdyBjaGFuZ2luZyBjb2x1bW5zIGluIFNlcnZlciBTaWRlIFJvdyBNb2RlbCB3aXRob3V0IHRyaWdnZXJpbmcgYSByZWxvYWQuIE5vdyB0aGF0IGl0IGlzIHBvc3NpYmxlIHRvIGR5bmFtaWNhbGx5IGNoYW5nZSBjb2x1bW5zIGluIHRoZSBncmlkLCB0aGlzIGlzIG5vIGxvbmdlciBuZWVkZWQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuc3VwcHJlc3NDb2x1bW5TdGF0ZUV2ZW50cykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjUsIGdyaWQgcHJvcGVydHkgc3VwcHJlc3NDb2x1bW5TdGF0ZUV2ZW50cyBubyBsb25nZXIgd29ya3MgZHVlIHRvIGEgcmVmYWN0b3IgdGhhdCB3ZSBkaWQuIEl0IHNob3VsZCBiZSBwb3NzaWJsZSB0byBhY2hpZXZlIHNpbWlsYXIgdXNpbmcgZXZlbnQuc291cmNlLCB3aGljaCB3b3VsZCBiZSBcImFwaVwiIGlmIHRoZSBldmVudCB3YXMgZHVlIHRvIHNldHRpbmcgY29sdW1uIHN0YXRlIHZpYSB0aGUgQVBJJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdEV4cG9ydFBhcmFtcykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjUuMiwgdGhlIGdyaWQgcHJvcGVydHkgYGRlZmF1bHRFeHBvcnRQYXJhbXNgIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IGBkZWZhdWx0Q3N2RXhwb3J0UGFyYW1zYCBhbmQgYGRlZmF1bHRFeGNlbEV4cG9ydFBhcmFtc2AuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuc3RvcEVkaXRpbmdXaGVuR3JpZExvc2VzRm9jdXMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjI1LjIuMiwgdGhlIGdyaWQgcHJvcGVydHkgYHN0b3BFZGl0aW5nV2hlbkdyaWRMb3Nlc0ZvY3VzYCBoYXMgYmVlbiByZXBsYWNlZCBieSBgc3RvcEVkaXRpbmdXaGVuQ2VsbHNMb3NlRm9jdXNgLicpO1xuICAgICAgICAgICAgb3B0aW9ucy5zdG9wRWRpdGluZ1doZW5DZWxsc0xvc2VGb2N1cyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuYXBwbHlDb2x1bW5EZWZPcmRlcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjYuMCwgdGhlIGdyaWQgcHJvcGVydHkgYGFwcGx5Q29sdW1uRGVmT3JkZXJgIGlzIG5vIGxvbmdlciBuZWVkZWQsIGFzIHRoaXMgaXMgdGhlIGRlZmF1bHQgYmVoYXZpb3VyLiBUbyB0dXJuIHRoaXMgYmVoYXZpb3VyIG9mZiwgc2V0IG1haW50YWluQ29sdW1uT3JkZXI9dHJ1ZScpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmdyb3VwTXVsdGlBdXRvQ29sdW1uKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBzaW5jZSB2MjYuMCwgdGhlIGdyaWQgcHJvcGVydHkgYGdyb3VwTXVsdGlBdXRvQ29sdW1uYCBoYXMgYmVlbiByZXBsYWNlZCBieSBgZ3JvdXBEaXNwbGF5VHlwZSA9ICdtdWx0aXBsZUNvbHVtbnMnYFwiKTtcbiAgICAgICAgICAgIG9wdGlvbnMuZ3JvdXBEaXNwbGF5VHlwZSA9ICdtdWx0aXBsZUNvbHVtbnMnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmdyb3VwVXNlRW50aXJlUm93KSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBzaW5jZSB2MjYuMCwgdGhlIGdyaWQgcHJvcGVydHkgYGdyb3VwVXNlRW50aXJlUm93YCBoYXMgYmVlbiByZXBsYWNlZCBieSBgZ3JvdXBEaXNwbGF5VHlwZSA9ICdncm91cFJvd3MnYFwiKTtcbiAgICAgICAgICAgIG9wdGlvbnMuZ3JvdXBEaXNwbGF5VHlwZSA9ICdncm91cFJvd3MnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmdyb3VwU3VwcHJlc3NBdXRvQ29sdW1uKSB7XG4gICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBvcHRpb25zLnRyZWVEYXRhID8gJ3RyZWVEYXRhRGlzcGxheVR5cGUnIDogJ2dyb3VwRGlzcGxheVR5cGUnO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2luY2UgdjI2LjAsIHRoZSBncmlkIHByb3BlcnR5IGBncm91cFN1cHByZXNzQXV0b0NvbHVtbmAgaGFzIGJlZW4gcmVwbGFjZWQgYnkgYFwiICsgcHJvcE5hbWUgKyBcIiA9ICdjdXN0b20nYFwiKTtcbiAgICAgICAgICAgIG9wdGlvbnMuZ3JvdXBEaXNwbGF5VHlwZSA9ICdjdXN0b20nO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRHcm91cE9yZGVyQ29tcGFyYXRvcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2luY2UgdjI3LjIsIHRoZSBncmlkIHByb3BlcnR5IGBkZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3JgIGlzIGRlcHJlY2F0ZWQgYW5kIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IGBpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3JgIGFuZCBub3cgcmVjZWl2ZXMgYSBzaW5nbGUgcGFyYW1zIG9iamVjdC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdEdyb3VwU29ydENvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHNpbmNlIHYyNi4wLCB0aGUgZ3JpZCBwcm9wZXJ0eSBgZGVmYXVsdEdyb3VwU29ydENvbXBhcmF0b3JgIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IGBpbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3JgXCIpO1xuICAgICAgICAgICAgb3B0aW9ucy5kZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3IgPSBvcHRpb25zLmRlZmF1bHRHcm91cFNvcnRDb21wYXJhdG9yO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmdyb3VwUm93QWdnTm9kZXMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHNpbmNlIHYyNy4yLCB0aGUgZ3JpZCBwcm9wZXJ0eSBgZ3JvdXBSb3dBZ2dOb2Rlc2AgaXMgZGVwcmVjYXRlZCBhbmQgaGFzIGJlZW4gcmVwbGFjZWQgYnkgYGdldEdyb3VwUm93QWdnYCBhbmQgbm93IHJlY2VpdmVzIGEgc2luZ2xlIHBhcmFtcyBvYmplY3QuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLnBvc3RTb3J0KSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBzaW5jZSB2MjcuMiwgdGhlIGdyaWQgcHJvcGVydHkgYHBvc3RTb3J0YCBpcyBkZXByZWNhdGVkIGFuZCBoYXMgYmVlbiByZXBsYWNlZCBieSBgcG9zdFNvcnRSb3dzYCBhbmQgbm93IHJlY2VpdmVzIGEgc2luZ2xlIHBhcmFtcyBvYmplY3QuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmlzRnVsbFdpZHRoQ2VsbCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2luY2UgdjI3LjIsIHRoZSBncmlkIHByb3BlcnR5IGBpc0Z1bGxXaWR0aENlbGxgIGlzIGRlcHJlY2F0ZWQgYW5kIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IGBpc0Z1bGxXaWR0aFJvd2AgYW5kIG5vdyByZWNlaXZlcyBhIHNpbmdsZSBwYXJhbXMgb2JqZWN0LlwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5sb2NhbGVUZXh0RnVuYykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2luY2UgdjI3LjIsIHRoZSBncmlkIHByb3BlcnR5IGBsb2NhbGVUZXh0RnVuY2AgaXMgZGVwcmVjYXRlZCBhbmQgaGFzIGJlZW4gcmVwbGFjZWQgYnkgYGdldExvY2FsZVRleHRgIGFuZCBub3cgcmVjZWl2ZXMgYSBzaW5nbGUgcGFyYW1zIG9iamVjdC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuY29sV2lkdGgpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjI2LjEsIHRoZSBncmlkIHByb3BlcnR5IGBjb2xXaWR0aGAgaXMgZGVwcmVjYXRlZCBhbmQgc2hvdWxkIGJlIHNldCB2aWEgYGRlZmF1bHRDb2xEZWYud2lkdGhgLicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLm1pbkNvbFdpZHRoKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyNi4xLCB0aGUgZ3JpZCBwcm9wZXJ0eSBgbWluQ29sV2lkdGhgIGlzIGRlcHJlY2F0ZWQgYW5kIHNob3VsZCBiZSBzZXQgdmlhIGBkZWZhdWx0Q29sRGVmLm1pbldpZHRoYC4nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5tYXhDb2xXaWR0aCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjYuMSwgdGhlIGdyaWQgcHJvcGVydHkgYG1heENvbFdpZHRoYCBpcyBkZXByZWNhdGVkIGFuZCBzaG91bGQgYmUgc2V0IHZpYSBgZGVmYXVsdENvbERlZi5tYXhXaWR0aGAuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMucmVhY3RVaSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjcuMCwgUmVhY3QgVUkgaXMgb24gYnkgZGVmYXVsdCwgc28gbm8gbmVlZCBmb3IgcmVhY3RVaT10cnVlLiBUbyB0dXJuIGl0IG9mZiwgc2V0IHN1cHByZXNzUmVhY3RVaT10cnVlLicpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLnN1cHByZXNzUmVhY3RVaSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBUaGUgbGVnYWN5IFJlYWN0IHJlbmRlcmluZyBlbmdpbmUgaXMgZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0IG1ham9yIHZlcnNpb24gb2YgdGhlIGdyaWQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuc3VwcHJlc3NDZWxsU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyNy4wLCBgc3VwcHJlc3NDZWxsU2VsZWN0aW9uYCBoYXMgYmVlbiByZXBsYWNlZCBieSBgc3VwcHJlc3NDZWxsRm9jdXNgLicpO1xuICAgICAgICAgICAgb3B0aW9ucy5zdXBwcmVzc0NlbGxGb2N1cyA9IG9wdGlvbnMuc3VwcHJlc3NDZWxsU2VsZWN0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmdldFJvd05vZGVJZCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjcuMSwgYGdldFJvd05vZGVJZGAgaXMgZGVwcmVjYXRlZCBhbmQgaGFzIGJlZW4gcmVwbGFjZWQgYnkgYGdldFJvd0lkYC4gVGhlIGRpZmZlcmVuY2U6IGlmIGdldFJvd0lkKCkgaXMgaW1wbGVtZW50ZWQgdGhlbiBpbW11dGFibGUgZGF0YSBpcyBlbmFibGVkIGJ5IGRlZmF1bHQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMuaW1tdXRhYmxlRGF0YSkge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZ2V0Um93SWQpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYyNy4xLCBgaW1tdXRhYmxlRGF0YWAgaXMgZGVwcmVjYXRlZC4gV2l0aCB0aGUgYGdldFJvd0lkYCBjYWxsYmFjayBpbXBsZW1lbnRlZCwgaW1tdXRhYmxlIGRhdGEgaXMgZW5hYmxlZCBieSBkZWZhdWx0IHNvIHlvdSBjYW4gcmVtb3ZlIGBpbW11dGFibGVEYXRhPXRydWVgLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjcuMSwgYGltbXV0YWJsZURhdGFgIGlzIGRlcHJlY2F0ZWQuIFRvIGVuYWJsZSBpbW11dGFibGUgZGF0YSB5b3UgbXVzdCBpbXBsZW1lbnQgdGhlIGBnZXRSb3dJZCgpYCBjYWxsYmFjay4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5jbGlwYm9hcmREZWxpbWluYXRvcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MjcuMSwgYGNsaXBib2FyZERlbGltaW5hdG9yYCBoYXMgYmVlbiByZXBsYWNlZCBieSBgY2xpcGJvYXJkRGVsaW1pdGVyYC4nKTtcbiAgICAgICAgICAgIG9wdGlvbnMuY2xpcGJvYXJkRGVsaW1pdGVyID0gb3B0aW9ucy5jbGlwYm9hcmREZWxpbWluYXRvcjtcbiAgICAgICAgfVxuICAgICAgICBjaGVja1JlbmFtZWRQcm9wZXJ0eSgncHJvY2Vzc1NlY29uZGFyeUNvbERlZicsICdwcm9jZXNzUGl2b3RSZXN1bHRDb2xEZWYnLCAnMjguMC54Jyk7XG4gICAgICAgIGNoZWNrUmVuYW1lZFByb3BlcnR5KCdwcm9jZXNzU2Vjb25kYXJ5Q29sR3JvdXBEZWYnLCAncHJvY2Vzc1Bpdm90UmVzdWx0Q29sR3JvdXBEZWYnLCAnMjguMC54Jyk7XG4gICAgICAgIGlmIChvcHRpb25zLnNlcnZlclNpZGVTdG9yZVR5cGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjI4LjAsIGBzZXJ2ZXJTaWRlU3RvcmVUeXBlYCBoYXMgYmVlbiByZXBsYWNlZCBieSBgc2VydmVyU2lkZUluZmluaXRlU2Nyb2xsYC4gU2V0IHRvIHRydWUgdG8gdXNlIFBhcnRpYWwgU3RvcmUsIGFuZCBmYWxzZSB0byB1c2UgRnVsbCBTdG9yZS4nKTtcbiAgICAgICAgICAgIG9wdGlvbnMuc2VydmVyU2lkZUluZmluaXRlU2Nyb2xsID0gb3B0aW9ucy5zZXJ2ZXJTaWRlU3RvcmVUeXBlID09PSAncGFydGlhbCc7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2tSZW5hbWVkUHJvcGVydHkoJ2dldFNlcnZlclNpZGVTdG9yZVBhcmFtcycsICdnZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFBhcmFtcycsICcyOC4wLngnKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuY2hlY2tGb3JWaW9sYXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1RyZWVEYXRhKCkpIHtcbiAgICAgICAgICAgIHRoaXMudHJlZURhdGFWaW9sYXRpb25zKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUudHJlZURhdGFWaW9sYXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Jvd01vZGVsRGVmYXVsdCgpKSB7XG4gICAgICAgICAgICBpZiAobWlzc2luZyh0aGlzLmdldERhdGFQYXRoRnVuYygpKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogcHJvcGVydHkgdXNpbmdUcmVlRGF0YT10cnVlIHdpdGggcm93TW9kZWw9Y2xpZW50U2lkZSwgYnV0IHlvdSBkaWQgbm90ICcgK1xuICAgICAgICAgICAgICAgICAgICAncHJvdmlkZSBnZXREYXRhUGF0aCBmdW5jdGlvbiwgcGxlYXNlIHByb3ZpZGUgZ2V0RGF0YVBhdGggZnVuY3Rpb24gaWYgdXNpbmcgdHJlZSBkYXRhLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzUm93TW9kZWxTZXJ2ZXJTaWRlKCkpIHtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nKHRoaXMuZ2V0SXNTZXJ2ZXJTaWRlR3JvdXBGdW5jKCkpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBwcm9wZXJ0eSB1c2luZ1RyZWVEYXRhPXRydWUgd2l0aCByb3dNb2RlbD1zZXJ2ZXJTaWRlLCBidXQgeW91IGRpZCBub3QgJyArXG4gICAgICAgICAgICAgICAgICAgICdwcm92aWRlIGlzU2VydmVyU2lkZUdyb3VwIGZ1bmN0aW9uLCBwbGVhc2UgcHJvdmlkZSBpc1NlcnZlclNpZGVHcm91cCBmdW5jdGlvbiBpZiB1c2luZyB0cmVlIGRhdGEuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWlzc2luZyh0aGlzLmdldFNlcnZlclNpZGVHcm91cEtleUZ1bmMoKSkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHByb3BlcnR5IHVzaW5nVHJlZURhdGE9dHJ1ZSB3aXRoIHJvd01vZGVsPXNlcnZlclNpZGUsIGJ1dCB5b3UgZGlkIG5vdCAnICtcbiAgICAgICAgICAgICAgICAgICAgJ3Byb3ZpZGUgZ2V0U2VydmVyU2lkZUdyb3VwS2V5IGZ1bmN0aW9uLCBwbGVhc2UgcHJvdmlkZSBnZXRTZXJ2ZXJTaWRlR3JvdXBLZXkgZnVuY3Rpb24gaWYgdXNpbmcgdHJlZSBkYXRhLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldExvY2FsZVRleHRGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmdyaWRPcHRpb25zLCBsb2NhbGVUZXh0ID0gX2EubG9jYWxlVGV4dCwgZ2V0TG9jYWxlVGV4dCA9IF9hLmdldExvY2FsZVRleHQsIGxvY2FsZVRleHRGdW5jID0gX2EubG9jYWxlVGV4dEZ1bmM7XG4gICAgICAgIGlmIChnZXRMb2NhbGVUZXh0KSB7XG4gICAgICAgICAgICAvL2tleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU6IHN0cmluZywgdmFyaWFibGVWYWx1ZXM/OiBzdHJpbmdbXVxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChrZXksIGRlZmF1bHRWYWx1ZSwgdmFyaWFibGVWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiBkZWZhdWx0VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlVmFsdWVzOiB2YXJpYWJsZVZhbHVlcyxcbiAgICAgICAgICAgICAgICAgICAgYXBpOiBfdGhpcy5nZXRBcGkoKSxcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQXBpOiBfdGhpcy5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDogX3RoaXMuZ2V0Q29udGV4dCgpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TG9jYWxlVGV4dChwYXJhbXMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9jYWxlVGV4dEZ1bmMpIHtcbiAgICAgICAgICAgIHJldHVybiBsb2NhbGVUZXh0RnVuYztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGtleSwgZGVmYXVsdFZhbHVlLCB2YXJpYWJsZVZhbHVlcykge1xuICAgICAgICAgICAgdmFyIGxvY2FsaXNlZFRleHQgPSBsb2NhbGVUZXh0ICYmIGxvY2FsZVRleHRba2V5XTtcbiAgICAgICAgICAgIGlmIChsb2NhbGlzZWRUZXh0ICYmIHZhcmlhYmxlVmFsdWVzICYmIHZhcmlhYmxlVmFsdWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IDA7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvdW5kID49IHZhcmlhYmxlVmFsdWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkeCA9IGxvY2FsaXNlZFRleHQuaW5kZXhPZignJHt2YXJpYWJsZX0nKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxvY2FsaXNlZFRleHQgPSBsb2NhbGlzZWRUZXh0LnJlcGxhY2UoJyR7dmFyaWFibGV9JywgdmFyaWFibGVWYWx1ZXNbZm91bmQrK10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAobG9jYWxpc2VkVGV4dCAhPT0gbnVsbCAmJiBsb2NhbGlzZWRUZXh0ICE9PSB2b2lkIDAgPyBsb2NhbGlzZWRUZXh0IDogZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIC8vIHJlc3BvbnNpYmxlIGZvciBjYWxsaW5nIHRoZSBvblhYWCBmdW5jdGlvbnMgb24gZ3JpZE9wdGlvbnNcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdsb2JhbEV2ZW50SGFuZGxlciA9IGZ1bmN0aW9uIChldmVudE5hbWUsIGV2ZW50KSB7XG4gICAgICAgIC8vIHByZXZlbnQgZXZlbnRzIGZyb20gYmVpbmcgZmlyZWQgX2FmdGVyXyB0aGUgZ3JpZCBoYXMgYmVlbiBkZXN0cm95ZWRcbiAgICAgICAgaWYgKHRoaXMuZGVzdHJveWVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNhbGxiYWNrTWV0aG9kTmFtZSA9IENvbXBvbmVudFV0aWwuZ2V0Q2FsbGJhY2tGb3JFdmVudChldmVudE5hbWUpO1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZ3JpZE9wdGlvbnNbY2FsbGJhY2tNZXRob2ROYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1tjYWxsYmFja01ldGhvZE5hbWVdKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5zZXRSb3dIZWlnaHRWYXJpYWJsZSA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgdmFyIG9sZFJvd0hlaWdodCA9IHRoaXMuZUdyaWREaXYuc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnLS1hZy1saW5lLWhlaWdodCcpLnRyaW0oKTtcbiAgICAgICAgdmFyIG5ld1Jvd0hlaWdodCA9IGhlaWdodCArIFwicHhcIjtcbiAgICAgICAgaWYgKG9sZFJvd0hlaWdodCAhPSBuZXdSb3dIZWlnaHQpIHtcbiAgICAgICAgICAgIHRoaXMuZUdyaWREaXYuc3R5bGUuc2V0UHJvcGVydHkoJy0tYWctbGluZS1oZWlnaHQnLCBuZXdSb3dIZWlnaHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyB3ZSBkb24ndCBhbGxvdyBkeW5hbWljIHJvdyBoZWlnaHQgZm9yIHZpcnR1YWwgcGFnaW5nXG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRSb3dIZWlnaHRBc051bWJlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zLnJvd0hlaWdodCB8fCBtaXNzaW5nKHRoaXMuZ3JpZE9wdGlvbnMucm93SGVpZ2h0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RGVmYXVsdFJvd0hlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dIZWlnaHQgPSB0aGlzLmdyaWRPcHRpb25zLnJvd0hlaWdodDtcbiAgICAgICAgaWYgKHJvd0hlaWdodCAmJiB0aGlzLmlzTnVtZXJpYyhyb3dIZWlnaHQpKSB7XG4gICAgICAgICAgICB0aGlzLnNldFJvd0hlaWdodFZhcmlhYmxlKHJvd0hlaWdodCk7XG4gICAgICAgICAgICByZXR1cm4gcm93SGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZCByb3cgaGVpZ2h0IG11c3QgYmUgYSBudW1iZXIgaWYgbm90IHVzaW5nIHN0YW5kYXJkIHJvdyBtb2RlbCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXREZWZhdWx0Um93SGVpZ2h0KCk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzR2V0Um93SGVpZ2h0RnVuY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdGhpcy5ncmlkT3B0aW9ucy5nZXRSb3dIZWlnaHQgPT09ICdmdW5jdGlvbic7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmdldFJvd0hlaWdodEZvck5vZGUgPSBmdW5jdGlvbiAocm93Tm9kZSwgYWxsb3dFc3RpbWF0ZSwgZGVmYXVsdFJvd0hlaWdodCkge1xuICAgICAgICBpZiAoYWxsb3dFc3RpbWF0ZSA9PT0gdm9pZCAwKSB7IGFsbG93RXN0aW1hdGUgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoZGVmYXVsdFJvd0hlaWdodCA9PSBudWxsKSB7XG4gICAgICAgICAgICBkZWZhdWx0Um93SGVpZ2h0ID0gdGhpcy5nZXREZWZhdWx0Um93SGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2hlY2sgdGhlIGZ1bmN0aW9uIGZpcnN0LCBpbiBjYXNlIHVzZSBzZXQgYm90aCBmdW5jdGlvbiBhbmRcbiAgICAgICAgLy8gbnVtYmVyLCB3aGVuIHVzaW5nIHZpcnR1YWwgcGFnaW5hdGlvbiB0aGVuIGZ1bmN0aW9uIGNhbiBiZVxuICAgICAgICAvLyB1c2VkIGZvciBwaW5uZWQgcm93cyBhbmQgdGhlIG51bWJlciBmb3IgdGhlIGJvZHkgcm93cy5cbiAgICAgICAgaWYgKHRoaXMuaXNHZXRSb3dIZWlnaHRGdW5jdGlvbigpKSB7XG4gICAgICAgICAgICBpZiAoYWxsb3dFc3RpbWF0ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGhlaWdodDogZGVmYXVsdFJvd0hlaWdodCwgZXN0aW1hdGVkOiB0cnVlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgIG5vZGU6IHJvd05vZGUsXG4gICAgICAgICAgICAgICAgZGF0YTogcm93Tm9kZS5kYXRhXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGhlaWdodCA9IHRoaXMubWVyZ2VHcmlkQ29tbW9uUGFyYW1zKHRoaXMuZ3JpZE9wdGlvbnMuZ2V0Um93SGVpZ2h0KShwYXJhbXMpO1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNOdW1lcmljKGhlaWdodCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGVpZ2h0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZSByZXR1cm4gb2YgYGdldFJvd0hlaWdodGAgY2Fubm90IGJlIHplcm8uIElmIHRoZSBpbnRlbnRpb24gaXMgdG8gaGlkZSByb3dzLCB1c2UgYSBmaWx0ZXIgaW5zdGVhZC4nKTsgfSwgJ2ludmFsaWRSb3dIZWlnaHQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgaGVpZ2h0OiBNYXRoLm1heCgxLCBoZWlnaHQpLCBlc3RpbWF0ZWQ6IGZhbHNlIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJvd05vZGUuZGV0YWlsICYmIHRoaXMuaXNNYXN0ZXJEZXRhaWwoKSkge1xuICAgICAgICAgICAgLy8gaWYgYXV0b0hlaWdodCwgd2Ugd2FudCB0aGUgaGVpZ2h0IHRvIGdyb3cgdG8gdGhlIG5ldyBoZWlnaHQgc3RhcnRpbmcgYXQgMSwgYXMgb3RoZXJ3aXNlIGEgZmxpY2tlciB3b3VsZCBoYXBwZW4sXG4gICAgICAgICAgICAvLyBhcyB0aGUgZGV0YWlsIGdvZXMgdG8gdGhlIGRlZmF1bHQgKGVnIDIwMHB4KSBhbmQgdGhlbiBpbW1lZGlhdGVseSBzaHJpbmsgdXAvZG93biB0byB0aGUgbmV3IG1lYXN1cmVkIGhlaWdodFxuICAgICAgICAgICAgLy8gKGR1ZSB0byBhdXRvIGhlaWdodCkgd2hpY2ggbG9va3MgYmFkLCBlc3BlY2lhbGx5IGlmIGRvaW5nIHJvdyBhbmltYXRpb24uXG4gICAgICAgICAgICBpZiAodGhpcy5pc0RldGFpbFJvd0F1dG9IZWlnaHQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGhlaWdodDogMSwgZXN0aW1hdGVkOiBmYWxzZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuaXNOdW1lcmljKHRoaXMuZ3JpZE9wdGlvbnMuZGV0YWlsUm93SGVpZ2h0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IGhlaWdodDogdGhpcy5ncmlkT3B0aW9ucy5kZXRhaWxSb3dIZWlnaHQsIGVzdGltYXRlZDogZmFsc2UgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7IGhlaWdodDogREVGQVVMVF9ERVRBSUxfUk9XX0hFSUdIVCwgZXN0aW1hdGVkOiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dIZWlnaHQgPSB0aGlzLmdyaWRPcHRpb25zLnJvd0hlaWdodCAmJiB0aGlzLmlzTnVtZXJpYyh0aGlzLmdyaWRPcHRpb25zLnJvd0hlaWdodCkgPyB0aGlzLmdyaWRPcHRpb25zLnJvd0hlaWdodCA6IGRlZmF1bHRSb3dIZWlnaHQ7XG4gICAgICAgIHJldHVybiB7IGhlaWdodDogcm93SGVpZ2h0LCBlc3RpbWF0ZWQ6IGZhbHNlIH07XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmlzRHluYW1pY1Jvd0hlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB0aGlzLmdyaWRPcHRpb25zLmdldFJvd0hlaWdodCA9PT0gJ2Z1bmN0aW9uJztcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0TGlzdEl0ZW1IZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEZyb21UaGVtZSgyMCwgJ2xpc3RJdGVtSGVpZ2h0Jyk7XG4gICAgfTtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLmNoYXJ0TWVudVBhbmVsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVudmlyb25tZW50LmNoYXJ0TWVudVBhbmVsV2lkdGgoKTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuaXNOdW1lcmljID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiAhaXNOYU4odmFsdWUpICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgaXNGaW5pdGUodmFsdWUpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5nZXRGcm9tVGhlbWUgPSBmdW5jdGlvbiAoZGVmYXVsdFZhbHVlLCBzYXNzVmFyaWFibGVOYW1lKSB7XG4gICAgICAgIHZhciB0aGVtZSA9IHRoaXMuZW52aXJvbm1lbnQuZ2V0VGhlbWUoKS50aGVtZTtcbiAgICAgICAgaWYgKHRoZW1lICYmIHRoZW1lLmluZGV4T2YoJ2FnLXRoZW1lJykgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVudmlyb25tZW50LmdldFNhc3NWYXJpYWJsZSh0aGVtZSwgc2Fzc1ZhcmlhYmxlTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbiAgICB9O1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUuZ2V0RGVmYXVsdFJvd0hlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RnJvbVRoZW1lKERFRkFVTFRfUk9XX0hFSUdIVCwgJ3Jvd0hlaWdodCcpO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5tYXRjaGVzR3JvdXBEaXNwbGF5VHlwZSA9IGZ1bmN0aW9uICh0b01hdGNoLCBzdXBwbGllZCkge1xuICAgICAgICB2YXIgZ3JvdXBEaXNwbGF5VHlwZVZhbHVlcyA9IFsnZ3JvdXBSb3dzJywgJ211bHRpcGxlQ29sdW1ucycsICdjdXN0b20nLCAnc2luZ2xlQ29sdW1uJ107XG4gICAgICAgIGlmIChncm91cERpc3BsYXlUeXBlVmFsdWVzLmluZGV4T2Yoc3VwcGxpZWQpIDwgMCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogJ1wiICsgc3VwcGxpZWQgKyBcIicgaXMgbm90IGEgdmFsaWQgZ3JvdXBEaXNwbGF5VHlwZSB2YWx1ZSAtIHBvc3NpYmxlIHZhbHVlcyBhcmU6ICdcIiArIGdyb3VwRGlzcGxheVR5cGVWYWx1ZXMuam9pbihcIicsICdcIikgKyBcIidcIik7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1cHBsaWVkID09PSB0b01hdGNoO1xuICAgIH07XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZS5tYXRjaGVzVHJlZURhdGFEaXNwbGF5VHlwZSA9IGZ1bmN0aW9uICh0b01hdGNoLCBzdXBwbGllZCkge1xuICAgICAgICB2YXIgdHJlZURhdGFEaXNwbGF5VHlwZVZhbHVlcyA9IFsnYXV0bycsICdjdXN0b20nXTtcbiAgICAgICAgaWYgKHRyZWVEYXRhRGlzcGxheVR5cGVWYWx1ZXMuaW5kZXhPZihzdXBwbGllZCkgPCAwKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiAnXCIgKyBzdXBwbGllZCArIFwiJyBpcyBub3QgYSB2YWxpZCB0cmVlRGF0YURpc3BsYXlUeXBlIHZhbHVlIC0gcG9zc2libGUgdmFsdWVzIGFyZTogJ1wiICsgdHJlZURhdGFEaXNwbGF5VHlwZVZhbHVlcy5qb2luKFwiJywgJ1wiKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VwcGxpZWQgPT09IHRvTWF0Y2g7XG4gICAgfTtcbiAgICB2YXIgR3JpZE9wdGlvbnNXcmFwcGVyXzE7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLk1JTl9DT0xfV0lEVEggPSAxMDtcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9IRUFERVJfSEVJR0hUID0gJ2hlYWRlckhlaWdodCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR1JPVVBfUkVNT1ZFX1NJTkdMRV9DSElMRFJFTiA9ICdncm91cFJlbW92ZVNpbmdsZUNoaWxkcmVuJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9SRU1PVkVfTE9XRVNUX1NJTkdMRV9DSElMRFJFTiA9ICdncm91cFJlbW92ZUxvd2VzdFNpbmdsZUNoaWxkcmVuJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9ESVNQTEFZX1RZUEUgPSAnZ3JvdXBEaXNwbGF5VHlwZSc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUElWT1RfSEVBREVSX0hFSUdIVCA9ICdwaXZvdEhlYWRlckhlaWdodCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfU1VQUFJFU1NfQ0xJUEJPQVJEX1BBU1RFID0gJ3N1cHByZXNzQ2xpcGJvYXJkUGFzdGUnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dST1VQX0hFQURFUl9IRUlHSFQgPSAnZ3JvdXBIZWFkZXJIZWlnaHQnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1BJVk9UX0dST1VQX0hFQURFUl9IRUlHSFQgPSAncGl2b3RHcm91cEhlYWRlckhlaWdodCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfTkFWSUdBVEVfVE9fTkVYVF9DRUxMID0gJ25hdmlnYXRlVG9OZXh0Q2VsbCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfVEFCX1RPX05FWFRfQ0VMTCA9ICd0YWJUb05leHRDZWxsJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9OQVZJR0FURV9UT19ORVhUX0hFQURFUiA9ICduYXZpZ2F0ZVRvTmV4dEhlYWRlcic7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfVEFCX1RPX05FWFRfSEVBREVSID0gJ3RhYlRvTmV4dEhlYWRlcic7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfSVNfRVhURVJOQUxfRklMVEVSX1BSRVNFTlQgPSAnaXNFeHRlcm5hbEZpbHRlclByZXNlbnQnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0RPRVNfRVhURVJOQUxfRklMVEVSX1BBU1MgPSAnZG9lc0V4dGVybmFsRmlsdGVyUGFzcyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfRkxPQVRJTkdfRklMVEVSU19IRUlHSFQgPSAnZmxvYXRpbmdGaWx0ZXJzSGVpZ2h0JztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9TVVBQUkVTU19ST1dfQ0xJQ0tfU0VMRUNUSU9OID0gJ3N1cHByZXNzUm93Q2xpY2tTZWxlY3Rpb24nO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1NVUFBSRVNTX1JPV19EUkFHID0gJ3N1cHByZXNzUm93RHJhZyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfU1VQUFJFU1NfTU9WRV9XSEVOX1JPV19EUkFHID0gJ3N1cHByZXNzTW92ZVdoZW5Sb3dEcmFnZ2luZyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1JPV19DTEFTUyA9ICdnZXRSb3dDbGFzcyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1JPV19TVFlMRSA9ICdnZXRSb3dTdHlsZSc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1JPV19IRUlHSFQgPSAnZ2V0Um93SGVpZ2h0JztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QT1BVUF9QQVJFTlQgPSAncG9wdXBQYXJlbnQnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0RPTV9MQVlPVVQgPSAnZG9tTGF5b3V0JztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ST1dfQ0xBU1MgPSAncm93Q2xhc3MnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0ZJTExfSEFORExFX0RJUkVDVElPTiA9ICdmaWxsSGFuZGxlRGlyZWN0aW9uJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9ST1dfQUdHX05PREVTID0gJ2dyb3VwUm93QWdnTm9kZXMnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9HUk9VUF9ST1dfQUdHID0gJ2dldEdyb3VwUm93QWdnJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HRVRfQlVTSU5FU1NfS0VZX0ZPUl9OT0RFID0gJ2dldEJ1c2luZXNzS2V5Rm9yTm9kZSc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX0NISUxEX0NPVU5UID0gJ2dldENoaWxkQ291bnQnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1BST0NFU1NfUk9XX1BPU1RfQ1JFQVRFID0gJ3Byb2Nlc3NSb3dQb3N0Q3JlYXRlJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HRVRfUk9XX05PREVfSUQgPSAnZ2V0Um93Tm9kZUlkJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HRVRfUk9XX0lEID0gJ2dldFJvd0lkJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19GVUxMX1dJRFRIX0NFTEwgPSAnaXNGdWxsV2lkdGhDZWxsJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19GVUxMX1dJRFRIX1JPVyA9ICdpc0Z1bGxXaWR0aFJvdyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfSVNfUk9XX1NFTEVDVEFCTEUgPSAnaXNSb3dTZWxlY3RhYmxlJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19ST1dfTUFTVEVSID0gJ2lzUm93TWFzdGVyJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QT1NUX1NPUlQgPSAncG9zdFNvcnQnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1BPU1RfU09SVF9ST1dTID0gJ3Bvc3RTb3J0Um93cyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX0RPQ1VNRU5UID0gJ2dldERvY3VtZW50JztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QT1NUX1BST0NFU1NfUE9QVVAgPSAncG9zdFByb2Nlc3NQb3B1cCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfREVGQVVMVF9HUk9VUF9PUkRFUl9DT01QQVJBVE9SID0gJ2RlZmF1bHRHcm91cE9yZGVyQ29tcGFyYXRvcic7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfSU5JVElBTF9HUk9VUF9PUkRFUl9DT01QQVJBVE9SID0gJ2luaXRpYWxHcm91cE9yZGVyQ29tcGFyYXRvcic7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUEFHSU5BVElPTl9OVU1CRVJfRk9STUFUVEVSID0gJ3BhZ2luYXRpb25OdW1iZXJGb3JtYXR0ZXInO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9DT05URVhUX01FTlVfSVRFTVMgPSAnZ2V0Q29udGV4dE1lbnVJdGVtcyc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX01BSU5fTUVOVV9JVEVNUyA9ICdnZXRNYWluTWVudUl0ZW1zJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QUk9DRVNTX0NFTExfRk9SX0NMSVBCT0FSRCA9ICdwcm9jZXNzQ2VsbEZvckNsaXBib2FyZCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUFJPQ0VTU19DRUxMX0ZST01fQ0xJUEJPQVJEID0gJ3Byb2Nlc3NDZWxsRnJvbUNsaXBib2FyZCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfU0VORF9UT19DTElQQk9BUkQgPSAnc2VuZFRvQ2xpcGJvYXJkJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QUk9DRVNTX1BJVk9UX1JFU1VMVF9DT0xfREVGID0gJ3Byb2Nlc3NQaXZvdFJlc3VsdENvbERlZic7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUFJPQ0VTU19QSVZPVF9SRVNVTFRfQ09MX0dST1VQX0RFRiA9ICdwcm9jZXNzUGl2b3RSZXN1bHRDb2xHcm91cERlZic7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX0NIQVJUX1RPT0xCQVJfSVRFTVMgPSAnZ2V0Q2hhcnRUb29sYmFySXRlbXMnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9TRVJWRVJfU0lERV9HUk9VUF9QQVJBTVMgPSAnZ2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxQYXJhbXMnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0lTX1NFUlZFUl9TSURFX0dST1VQU19PUEVOX0JZX0RFRkFVTFQgPSAnaXNTZXJ2ZXJTaWRlR3JvdXBPcGVuQnlEZWZhdWx0JztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19BUFBMWV9TRVJWRVJfU0lERV9UUkFOU0FDVElPTiA9ICdpc0FwcGx5U2VydmVyU2lkZVRyYW5zYWN0aW9uJztcbiAgICBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19TRVJWRVJfU0lERV9HUk9VUCA9ICdpc1NlcnZlclNpZGVHcm91cCc7XG4gICAgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1NFUlZFUl9TSURFX0dST1VQX0tFWSA9ICdnZXRTZXJ2ZXJTaWRlR3JvdXBLZXknO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0FVVE9fR1JPVVBfQ09MVU1OX0RFRiA9ICdhdXRvR3JvdXBDb2x1bW5EZWYnO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0RFRkFVTFRfQ09MX0RFRiA9ICdkZWZhdWx0Q29sRGVmJztcbiAgICBfX2RlY29yYXRlJDJ2KFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkT3B0aW9ucycpXG4gICAgXSwgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZSwgXCJncmlkT3B0aW9uc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnYoW1xuICAgICAgICBBdXRvd2lyZWQoJ2V2ZW50U2VydmljZScpXG4gICAgXSwgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZSwgXCJldmVudFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ2KFtcbiAgICAgICAgQXV0b3dpcmVkKCdlbnZpcm9ubWVudCcpXG4gICAgXSwgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZSwgXCJlbnZpcm9ubWVudFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnYoW1xuICAgICAgICBBdXRvd2lyZWQoJ2VHcmlkRGl2JylcbiAgICBdLCBHcmlkT3B0aW9uc1dyYXBwZXIucHJvdG90eXBlLCBcImVHcmlkRGl2XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydihbXG4gICAgICAgIF9fcGFyYW0kOCgwLCBRdWFsaWZpZXIoJ2dyaWRBcGknKSksIF9fcGFyYW0kOCgxLCBRdWFsaWZpZXIoJ2NvbHVtbkFwaScpKVxuICAgIF0sIEdyaWRPcHRpb25zV3JhcHBlci5wcm90b3R5cGUsIFwiYWdXaXJlXCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMnYoW1xuICAgICAgICBQcmVEZXN0cm95XG4gICAgXSwgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZSwgXCJkZXN0cm95XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMnYoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgR3JpZE9wdGlvbnNXcmFwcGVyLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIEdyaWRPcHRpb25zV3JhcHBlciA9IEdyaWRPcHRpb25zV3JhcHBlcl8xID0gX19kZWNvcmF0ZSQydihbXG4gICAgICAgIEJlYW4oJ2dyaWRPcHRpb25zV3JhcHBlcicpXG4gICAgXSwgR3JpZE9wdGlvbnNXcmFwcGVyKTtcbiAgICByZXR1cm4gR3JpZE9wdGlvbnNXcmFwcGVyO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyVCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMnUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3BhcmFtJDcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3BhcmFtKSB8fCBmdW5jdGlvbiAocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XG59O1xudmFyIF9fcmVzdCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVzdCkgfHwgZnVuY3Rpb24gKHMsIGUpIHtcbiAgICB2YXIgdCA9IHt9O1xuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxuICAgICAgICB0W3BdID0gc1twXTtcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcbiAgICAgICAgfVxuICAgIHJldHVybiB0O1xufTtcbnZhciBfX3ZhbHVlcyQ0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX192YWx1ZXMpIHx8IGZ1bmN0aW9uKG8pIHtcbiAgICB2YXIgcyA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wuaXRlcmF0b3IsIG0gPSBzICYmIG9bc10sIGkgPSAwO1xuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xufTtcbnZhciBfX3JlYWQkbCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCRmID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJGwoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBDb2x1bW5Nb2RlbCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMlQoQ29sdW1uTW9kZWwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ29sdW1uTW9kZWwoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICAvLyBoZWFkZXIgcm93IGNvdW50LCBiYXNlZCBvbiB1c2VyIHByb3ZpZGVkIGNvbHVtbnNcbiAgICAgICAgX3RoaXMucHJpbWFyeUhlYWRlclJvd0NvdW50ID0gMDtcbiAgICAgICAgX3RoaXMuc2Vjb25kYXJ5SGVhZGVyUm93Q291bnQgPSAwO1xuICAgICAgICAvLyBoZWFkZXIgcm93IGNvdW50LCBlaXRoZXIgYWJvdmUsIG9yIGJhc2VkIG9uIHBpdm90aW5nIGlmIHdlIGFyZSBwaXZvdGluZ1xuICAgICAgICBfdGhpcy5ncmlkSGVhZGVyUm93Q291bnQgPSAwO1xuICAgICAgICAvLyBsZWF2ZSBsZXZlbCBjb2x1bW5zIG9mIHRoZSBkaXNwbGF5ZWQgdHJlZXNcbiAgICAgICAgX3RoaXMuZGlzcGxheWVkQ29sdW1uc0xlZnQgPSBbXTtcbiAgICAgICAgX3RoaXMuZGlzcGxheWVkQ29sdW1uc1JpZ2h0ID0gW107XG4gICAgICAgIF90aGlzLmRpc3BsYXllZENvbHVtbnNDZW50ZXIgPSBbXTtcbiAgICAgICAgLy8gYWxsIHRocmVlIGxpc3RzIGFib3ZlIGNvbWJpbmVkXG4gICAgICAgIF90aGlzLmRpc3BsYXllZENvbHVtbnMgPSBbXTtcbiAgICAgICAgLy8gZm9yIGZhc3QgbG9va3VwLCB0byBzZWUgaWYgYSBjb2x1bW4gb3IgZ3JvdXAgaXMgc3RpbGwgZGlzcGxheWVkXG4gICAgICAgIF90aGlzLmRpc3BsYXllZENvbHVtbnNBbmRHcm91cHNNYXAgPSB7fTtcbiAgICAgICAgLy8gYWxsIGNvbHVtbnMgdG8gYmUgcmVuZGVyZWRcbiAgICAgICAgX3RoaXMudmlld3BvcnRDb2x1bW5zID0gW107XG4gICAgICAgIC8vIEEgaGFzaCBrZXkgdG8ga2VlcCB0cmFjayBvZiBjaGFuZ2VzIGluIHZpZXdwb3J0IGNvbHVtbnNcbiAgICAgICAgX3RoaXMudmlld3BvcnRDb2x1bW5zSGFzaCA9ICcnO1xuICAgICAgICAvLyBzYW1lIGFzIHZpZXdwb3J0Q29sdW1ucywgZXhjZXB0IHdlIGFsd2F5cyBpbmNsdWRlIGNvbHVtbnMgd2l0aCBoZWFkZXJBdXRvSGVpZ2h0XG4gICAgICAgIF90aGlzLmhlYWRlclZpZXdwb3J0Q29sdW1ucyA9IFtdO1xuICAgICAgICAvLyBhbGwgY29sdW1ucyB0byBiZSByZW5kZXJlZCBpbiB0aGUgY2VudHJlXG4gICAgICAgIF90aGlzLnZpZXdwb3J0Q29sdW1uc0NlbnRlciA9IFtdO1xuICAgICAgICAvLyBzYW1lIGFzIHZpZXdwb3J0Q29sdW1uc0NlbnRlciwgZXhjZXB0IHdlIGFsd2F5cyBpbmNsdWRlIGNvbHVtbnMgd2l0aCBoZWFkZXJBdXRvSGVpZ2h0XG4gICAgICAgIF90aGlzLmhlYWRlclZpZXdwb3J0Q29sdW1uc0NlbnRlciA9IFtdO1xuICAgICAgICBfdGhpcy5hdXRvSGVpZ2h0QWN0aXZlQXRMZWFzdE9uY2UgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMucm93R3JvdXBDb2x1bW5zID0gW107XG4gICAgICAgIF90aGlzLnZhbHVlQ29sdW1ucyA9IFtdO1xuICAgICAgICBfdGhpcy5waXZvdENvbHVtbnMgPSBbXTtcbiAgICAgICAgX3RoaXMucmVhZHkgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuYXV0b0dyb3Vwc05lZWRCdWlsZGluZyA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5mb3JjZVJlY3JlYXRlQXV0b0dyb3VwcyA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5waXZvdE1vZGUgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuYm9keVdpZHRoID0gMDtcbiAgICAgICAgX3RoaXMubGVmdFdpZHRoID0gMDtcbiAgICAgICAgX3RoaXMucmlnaHRXaWR0aCA9IDA7XG4gICAgICAgIF90aGlzLmJvZHlXaWR0aERpcnR5ID0gdHJ1ZTtcbiAgICAgICAgX3RoaXMuZmxleENvbHNDYWxjdWxhdGVkQXRMZXN0T25jZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnN1cHByZXNzQ29sdW1uVmlydHVhbGlzYXRpb24gPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ29sdW1uVmlydHVhbGlzYXRpb24oKTtcbiAgICAgICAgdmFyIHBpdm90TW9kZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIGlmICh0aGlzLmlzUGl2b3RTZXR0aW5nQWxsb3dlZChwaXZvdE1vZGUpKSB7XG4gICAgICAgICAgICB0aGlzLnBpdm90TW9kZSA9IHBpdm90TW9kZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVzaW5nVHJlZURhdGEgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1RyZWVEYXRhKCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9ESVNQTEFZX1RZUEUsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uQXV0b0dyb3VwQ29sdW1uRGVmQ2hhbmdlZCgpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0FVVE9fR1JPVVBfQ09MVU1OX0RFRiwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25BdXRvR3JvdXBDb2x1bW5EZWZDaGFuZ2VkKCk7IH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfREVGQVVMVF9DT0xfREVGLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vbkRlZmF1bHRDb2xEZWZDaGFuZ2VkKCk7IH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLm9uQXV0b0dyb3VwQ29sdW1uRGVmQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hdXRvR3JvdXBzTmVlZEJ1aWxkaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5mb3JjZVJlY3JlYXRlQXV0b0dyb3VwcyA9IHRydWU7XG4gICAgICAgIHRoaXMudXBkYXRlR3JpZENvbHVtbnMoKTtcbiAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5ZWRDb2x1bW5zKCdncmlkT3B0aW9uc0NoYW5nZWQnKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5vbkRlZmF1bHRDb2xEZWZDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBsaWtld2lzZSBmb3IgYXV0b0dyb3VwQ29sLCB0aGUgZGVmYXVsdCBjb2wgZGVmIGltcGFjdHMgdGhpc1xuICAgICAgICB0aGlzLmZvcmNlUmVjcmVhdGVBdXRvR3JvdXBzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5jcmVhdGVDb2x1bW5zRnJvbUNvbHVtbkRlZnModHJ1ZSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0Q29sdW1uRGVmcyA9IGZ1bmN0aW9uIChjb2x1bW5EZWZzLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9ICdhcGknOyB9XG4gICAgICAgIHZhciBjb2xzUHJldmlvdXNseUV4aXN0ZWQgPSAhIXRoaXMuY29sdW1uRGVmcztcbiAgICAgICAgdGhpcy5jb2x1bW5EZWZzID0gY29sdW1uRGVmcztcbiAgICAgICAgdGhpcy5jcmVhdGVDb2x1bW5zRnJvbUNvbHVtbkRlZnMoY29sc1ByZXZpb3VzbHlFeGlzdGVkLCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmNyZWF0ZUNvbHVtbnNGcm9tQ29sdW1uRGVmcyA9IGZ1bmN0aW9uIChjb2xzUHJldmlvdXNseUV4aXN0ZWQsIHNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gJ2FwaSc7IH1cbiAgICAgICAgLy8gb25seSBuZWVkIHRvIHJhaXNlIGJlZm9yZS9hZnRlciBldmVudHMgaWYgdXBkYXRpbmcgY29sdW1ucywgbmV2ZXIgaWYgc2V0dGluZyBjb2x1bW5zIGZvciBmaXJzdCB0aW1lXG4gICAgICAgIHZhciByYWlzZUV2ZW50c0Z1bmMgPSBjb2xzUHJldmlvdXNseUV4aXN0ZWQgPyB0aGlzLmNvbXBhcmVDb2x1bW5TdGF0ZXNBbmRSYWlzZUV2ZW50cyhzb3VyY2UpIDogdW5kZWZpbmVkO1xuICAgICAgICAvLyBhbHdheXMgaW52YWxpZGF0ZSBjYWNoZSBvbiBjaGFuZ2luZyBjb2x1bW5zLCBhcyB0aGUgY29sdW1uIGlkJ3MgZm9yIHRoZSBuZXcgY29sdW1uc1xuICAgICAgICAvLyBjb3VsZCBvdmVybGFwIHdpdGggdGhlIG9sZCBpZCdzLCBzbyB0aGUgY2FjaGUgd291bGQgcmV0dXJuIG9sZCB2YWx1ZXMgZm9yIG5ldyBjb2x1bW5zLlxuICAgICAgICB0aGlzLnZhbHVlQ2FjaGUuZXhwaXJlKCk7XG4gICAgICAgIC8vIE5PVEUgPT09PT09PT09PT09PT09PT09XG4gICAgICAgIC8vIHdlIHNob3VsZCBiZSBkZXN0cm95aW5nIHRoZSBleGlzdGluZyBjb2x1bW5zIGFuZCBncm91cHMgaWYgdGhleSBleGlzdCwgZm9yIGV4YW1wbGUsIHRoZSBvcmlnaW5hbCBjb2x1bW5cbiAgICAgICAgLy8gZ3JvdXAgYWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBjb2x1bW5zLCBpdCBzaG91bGQgYmUgYWxzbyByZW1vdmluZyB0aGUgbGlzdGVuZXJzXG4gICAgICAgIHRoaXMuYXV0b0dyb3Vwc05lZWRCdWlsZGluZyA9IHRydWU7XG4gICAgICAgIHZhciBvbGRQcmltYXJ5Q29sdW1ucyA9IHRoaXMucHJpbWFyeUNvbHVtbnM7XG4gICAgICAgIHZhciBvbGRQcmltYXJ5VHJlZSA9IHRoaXMucHJpbWFyeUNvbHVtblRyZWU7XG4gICAgICAgIHZhciBiYWxhbmNlZFRyZWVSZXN1bHQgPSB0aGlzLmNvbHVtbkZhY3RvcnkuY3JlYXRlQ29sdW1uVHJlZSh0aGlzLmNvbHVtbkRlZnMsIHRydWUsIG9sZFByaW1hcnlUcmVlKTtcbiAgICAgICAgdGhpcy5wcmltYXJ5Q29sdW1uVHJlZSA9IGJhbGFuY2VkVHJlZVJlc3VsdC5jb2x1bW5UcmVlO1xuICAgICAgICB0aGlzLnByaW1hcnlIZWFkZXJSb3dDb3VudCA9IGJhbGFuY2VkVHJlZVJlc3VsdC50cmVlRGVwdCArIDE7XG4gICAgICAgIHRoaXMucHJpbWFyeUNvbHVtbnMgPSB0aGlzLmdldENvbHVtbnNGcm9tVHJlZSh0aGlzLnByaW1hcnlDb2x1bW5UcmVlKTtcbiAgICAgICAgdGhpcy5wcmltYXJ5Q29sdW1uc01hcCA9IHt9O1xuICAgICAgICB0aGlzLnByaW1hcnlDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gX3RoaXMucHJpbWFyeUNvbHVtbnNNYXBbY29sLmdldElkKCldID0gY29sOyB9KTtcbiAgICAgICAgdGhpcy5leHRyYWN0Um93R3JvdXBDb2x1bW5zKHNvdXJjZSwgb2xkUHJpbWFyeUNvbHVtbnMpO1xuICAgICAgICB0aGlzLmV4dHJhY3RQaXZvdENvbHVtbnMoc291cmNlLCBvbGRQcmltYXJ5Q29sdW1ucyk7XG4gICAgICAgIHRoaXMuZXh0cmFjdFZhbHVlQ29sdW1ucyhzb3VyY2UsIG9sZFByaW1hcnlDb2x1bW5zKTtcbiAgICAgICAgdGhpcy5yZWFkeSA9IHRydWU7XG4gICAgICAgIC8vIGlmIHdlIGFyZSBzaG93aW5nIHNlY29uZGFyeSBjb2x1bW5zLCB0aGVuIG5vIG5lZWQgdG8gdXBkYXRlIGdyaWQgY29sdW1uc1xuICAgICAgICAvLyBhdCB0aGlzIHBvaW50LCBhcyBpdCdzIHRoZSBwaXZvdCBzZXJ2aWNlIHJlc3BvbnNpYmlsaXR5IHRvIGNoYW5nZSB0aGVzZVxuICAgICAgICAvLyBpZiB3ZSBhcmUgbm8gbG9uZ2VyIHBpdm90aW5nIChpZSBhbmQgbmVlZCB0byByZXZlcnQgYmFjayB0byBwcmltYXJ5LCBvdGhlcndpc2VcbiAgICAgICAgLy8gd2Ugc2hvdWxkbid0IGJlIHRvdWNoaW5nIHRoZSBwcmltYXJ5KS5cbiAgICAgICAgdmFyIGdyaWRDb2xzTm90UHJvY2Vzc2VkID0gdGhpcy5ncmlkQ29sc0FyZVByaW1hcnkgPT09IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIHByb2Nlc3NHcmlkQ29scyA9IHRoaXMuZ3JpZENvbHNBcmVQcmltYXJ5IHx8IGdyaWRDb2xzTm90UHJvY2Vzc2VkO1xuICAgICAgICBpZiAocHJvY2Vzc0dyaWRDb2xzKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUdyaWRDb2x1bW5zKCk7XG4gICAgICAgICAgICBpZiAoY29sc1ByZXZpb3VzbHlFeGlzdGVkICYmICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc01haW50YWluQ29sdW1uT3JkZXIoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMub3JkZXJHcmlkQ29sdW1uc0xpa2VQcmltYXJ5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXllZENvbHVtbnMoc291cmNlKTtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tWaWV3cG9ydENvbHVtbnMoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGlzIGV2ZW50IGlzIG5vdCB1c2VkIGJ5IEFHIEdyaWQsIGJ1dCBsZWZ0IGhlcmUgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LFxuICAgICAgICAvLyBpbiBjYXNlIGFwcGxpY2F0aW9ucyB1c2UgaXRcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZXJ5dGhpbmdDaGFuZ2VkKHNvdXJjZSk7XG4gICAgICAgIGlmIChyYWlzZUV2ZW50c0Z1bmMpIHtcbiAgICAgICAgICAgIHJhaXNlRXZlbnRzRnVuYygpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hOZXdDb2x1bW5zTG9hZGVkKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZGlzcGF0Y2hOZXdDb2x1bW5zTG9hZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbmV3Q29sdW1uc0xvYWRlZEV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX05FV19DT0xVTU5TX0xPQURFRFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KG5ld0NvbHVtbnNMb2FkZWRFdmVudCk7XG4gICAgfTtcbiAgICAvLyB0aGlzIGV2ZW50IGlzIGxlZ2FjeSwgbm8gZ3JpZCBjb2RlIGxpc3RlbnMgdG8gaXQuIGluc3RlYWQgdGhlIGdyaWQgbGlzdGVucyB0byBOZXcgQ29sdW1ucyBMb2FkZWRcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZGlzcGF0Y2hFdmVyeXRoaW5nQ2hhbmdlZCA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9ICdhcGknOyB9XG4gICAgICAgIHZhciBldmVudEV2ZXJ5dGhpbmdDaGFuZ2VkID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0NPTFVNTl9FVkVSWVRISU5HX0NIQU5HRUQsXG4gICAgICAgICAgICBzb3VyY2U6IHNvdXJjZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50RXZlcnl0aGluZ0NoYW5nZWQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLm9yZGVyR3JpZENvbHVtbnNMaWtlUHJpbWFyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHByaW1hcnlDb2x1bW5zID0gdGhpcy5wcmltYXJ5Q29sdW1ucztcbiAgICAgICAgaWYgKCFwcmltYXJ5Q29sdW1ucykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ3JpZENvbHVtbnMuc29ydChmdW5jdGlvbiAoY29sQSwgY29sQikge1xuICAgICAgICAgICAgdmFyIHByaW1hcnlJbmRleEEgPSBwcmltYXJ5Q29sdW1ucy5pbmRleE9mKGNvbEEpO1xuICAgICAgICAgICAgdmFyIHByaW1hcnlJbmRleEIgPSBwcmltYXJ5Q29sdW1ucy5pbmRleE9mKGNvbEIpO1xuICAgICAgICAgICAgLy8gaWYgYm90aCBjb2xzIGFyZSBwcmVzZW50IGluIHByaW1hcnksIHRoZW4gd2UganVzdCByZXR1cm4gdGhlIHBvc2l0aW9uLFxuICAgICAgICAgICAgLy8gc28gcG9zaXRpb24gaXMgbWFpbnRhaW5lZC5cbiAgICAgICAgICAgIHZhciBpbmRleEFQcmVzZW50ID0gcHJpbWFyeUluZGV4QSA+PSAwO1xuICAgICAgICAgICAgdmFyIGluZGV4QlByZXNlbnQgPSBwcmltYXJ5SW5kZXhCID49IDA7XG4gICAgICAgICAgICBpZiAoaW5kZXhBUHJlc2VudCAmJiBpbmRleEJQcmVzZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByaW1hcnlJbmRleEEgLSBwcmltYXJ5SW5kZXhCO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluZGV4QVByZXNlbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBCIGlzIGF1dG8gZ3JvdXAgY29sdW1uLCBzbyBwdXQgQiBmaXJzdFxuICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluZGV4QlByZXNlbnQpIHtcbiAgICAgICAgICAgICAgICAvLyBBIGlzIGF1dG8gZ3JvdXAgY29sdW1uLCBzbyBwdXQgQSBmaXJzdFxuICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSBib3RoIEEgYW5kIEIgYXJlIGF1dG8tZ3JvdXAgY29sdW1ucy4gc28gd2UganVzdCBrZWVwIHRoZSBvcmRlclxuICAgICAgICAgICAgLy8gYXMgdGhleSB3ZXJlIGFscmVhZHkgaW4uXG4gICAgICAgICAgICB2YXIgZ3JpZEluZGV4QSA9IF90aGlzLmdyaWRDb2x1bW5zLmluZGV4T2YoY29sQSk7XG4gICAgICAgICAgICB2YXIgZ3JpZEluZGV4QiA9IF90aGlzLmdyaWRDb2x1bW5zLmluZGV4T2YoY29sQik7XG4gICAgICAgICAgICByZXR1cm4gZ3JpZEluZGV4QSAtIGdyaWRJbmRleEI7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmdyaWRDb2x1bW5zID0gdGhpcy5wbGFjZUxvY2tlZENvbHVtbnModGhpcy5ncmlkQ29sdW1ucyk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0QWxsRGlzcGxheWVkQXV0b0hlaWdodENvbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpc3BsYXllZEF1dG9IZWlnaHRDb2xzO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldFZpZXdwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKSkge1xuICAgICAgICAgICAgdGhpcy52aWV3cG9ydExlZnQgPSB0aGlzLmJvZHlXaWR0aCAtIHRoaXMuc2Nyb2xsUG9zaXRpb24gLSB0aGlzLnNjcm9sbFdpZHRoO1xuICAgICAgICAgICAgdGhpcy52aWV3cG9ydFJpZ2h0ID0gdGhpcy5ib2R5V2lkdGggLSB0aGlzLnNjcm9sbFBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52aWV3cG9ydExlZnQgPSB0aGlzLnNjcm9sbFBvc2l0aW9uO1xuICAgICAgICAgICAgdGhpcy52aWV3cG9ydFJpZ2h0ID0gdGhpcy5zY3JvbGxXaWR0aCArIHRoaXMuc2Nyb2xsUG9zaXRpb247XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHVzZWQgYnkgY2xpcGJvYXJkIHNlcnZpY2UsIHRvIGtub3cgd2hhdCBjb2x1bW5zIHRvIHBhc3RlIGludG9cbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkQ29sdW1uc1N0YXJ0aW5nQXQgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHZhciBjdXJyZW50Q29sdW1uID0gY29sdW1uO1xuICAgICAgICB2YXIgY29sdW1ucyA9IFtdO1xuICAgICAgICB3aGlsZSAoY3VycmVudENvbHVtbiAhPSBudWxsKSB7XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2goY3VycmVudENvbHVtbik7XG4gICAgICAgICAgICBjdXJyZW50Q29sdW1uID0gdGhpcy5nZXREaXNwbGF5ZWRDb2xBZnRlcihjdXJyZW50Q29sdW1uKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sdW1ucztcbiAgICB9O1xuICAgIC8vIGNoZWNrcyB3aGF0IGNvbHVtbnMgYXJlIGN1cnJlbnRseSBkaXNwbGF5ZWQgZHVlIHRvIGNvbHVtbiB2aXJ0dWFsaXNhdGlvbi4gZmlyZXMgYW4gZXZlbnRcbiAgICAvLyBpZiB0aGUgbGlzdCBvZiBjb2x1bW5zIGhhcyBjaGFuZ2VkLlxuICAgIC8vICsgc2V0Q29sdW1uV2lkdGgoKSwgc2V0Vmlld3BvcnRQb3NpdGlvbigpLCBzZXRDb2x1bW5EZWZzKCksIHNpemVDb2x1bW5zVG9GaXQoKVxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5jaGVja1ZpZXdwb3J0Q29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gY2hlY2sgZGlzcGxheUNlbnRlckNvbHVtblRyZWUgZXhpc3RzIGZpcnN0LCBhcyBpdCB3b24ndCBleGlzdCB3aGVuIGdyaWQgaXMgaW5pdGlhbGlzaW5nXG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXllZENvbHVtbnNDZW50ZXIgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2aWV3cG9ydENvbHVtbnNDaGFuZ2VkID0gdGhpcy5leHRyYWN0Vmlld3BvcnQoKTtcbiAgICAgICAgaWYgKCF2aWV3cG9ydENvbHVtbnNDaGFuZ2VkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX1ZJUlRVQUxfQ09MVU1OU19DSEFOR0VEXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldFZpZXdwb3J0UG9zaXRpb24gPSBmdW5jdGlvbiAoc2Nyb2xsV2lkdGgsIHNjcm9sbFBvc2l0aW9uKSB7XG4gICAgICAgIGlmIChzY3JvbGxXaWR0aCAhPT0gdGhpcy5zY3JvbGxXaWR0aCB8fCBzY3JvbGxQb3NpdGlvbiAhPT0gdGhpcy5zY3JvbGxQb3NpdGlvbiB8fCB0aGlzLmJvZHlXaWR0aERpcnR5KSB7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFdpZHRoID0gc2Nyb2xsV2lkdGg7XG4gICAgICAgICAgICB0aGlzLnNjcm9sbFBvc2l0aW9uID0gc2Nyb2xsUG9zaXRpb247XG4gICAgICAgICAgICAvLyB3ZSBuZWVkIHRvIGNhbGwgc2V0VmlydHVhbFZpZXdwb3J0TGVmdEFuZFJpZ2h0KCkgYXQgbGVhc3Qgb25jZSBhZnRlciB0aGUgYm9keSB3aWR0aCBjaGFuZ2VzLFxuICAgICAgICAgICAgLy8gYXMgdGhlIHZpZXdwb3J0IGNhbiBzdGF5IHRoZSBzYW1lLCBidXQgaW4gUlRMLCBpZiBib2R5IHdpZHRoIGNoYW5nZXMsIHdlIG5lZWQgdG8gd29yayBvdXQgdGhlXG4gICAgICAgICAgICAvLyB2aXJ0dWFsIGNvbHVtbnMgYWdhaW5cbiAgICAgICAgICAgIHRoaXMuYm9keVdpZHRoRGlydHkgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zZXRWaWV3cG9ydCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMucmVhZHkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNoZWNrVmlld3BvcnRDb2x1bW5zKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5pc1Bpdm90TW9kZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGl2b3RNb2RlO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmlzUGl2b3RTZXR0aW5nQWxsb3dlZCA9IGZ1bmN0aW9uIChwaXZvdCkge1xuICAgICAgICBpZiAocGl2b3QgJiYgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNUcmVlRGF0YSgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBQaXZvdCBtb2RlIG5vdCBhdmFpbGFibGUgaW4gY29uanVuY3Rpb24gVHJlZSBEYXRhIGkuZS4gJ2dyaWRPcHRpb25zLnRyZWVEYXRhOiB0cnVlJ1wiKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXRQaXZvdE1vZGUgPSBmdW5jdGlvbiAocGl2b3RNb2RlLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9ICdhcGknOyB9XG4gICAgICAgIGlmIChwaXZvdE1vZGUgPT09IHRoaXMucGl2b3RNb2RlIHx8ICF0aGlzLmlzUGl2b3RTZXR0aW5nQWxsb3dlZCh0aGlzLnBpdm90TW9kZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBpdm90TW9kZSA9IHBpdm90TW9kZTtcbiAgICAgICAgLy8gd2UgbmVlZCB0byB1cGRhdGUgZ3JpZCBjb2x1bW5zIHRvIGNvdmVyIHRoZSBzY2VuYXJpbyB3aGVyZSB1c2VyIGhhcyBncm91cFN1cHByZXNzQXV0b0NvbHVtbj10cnVlLCBhc1xuICAgICAgICAvLyB0aGlzIG1lYW5zIHdlIGRvbid0IHVzZSBhdXRvIGdyb3VwIGNvbHVtbiBVTkxFU1Mgd2UgYXJlIGluIHBpdm90IG1vZGUgKGl0J3MgbWFuZGF0b3J5IGluIHBpdm90IG1vZGUpLFxuICAgICAgICAvLyBzbyBuZWVkIHRvIHVwZGF0ZUdyaWRDb2x1bW4oKSB0byBjaGVjayBpdCBhdXRvR3JvdXBDb2wgbmVlZHMgdG8gYmUgYWRkZWQgLyByZW1vdmVkXG4gICAgICAgIHRoaXMuYXV0b0dyb3Vwc05lZWRCdWlsZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMudXBkYXRlR3JpZENvbHVtbnMoKTtcbiAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5ZWRDb2x1bW5zKHNvdXJjZSk7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DT0xVTU5fUElWT1RfTU9ERV9DSEFOR0VEXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldFNlY29uZGFyeVBpdm90Q29sdW1uID0gZnVuY3Rpb24gKHBpdm90S2V5cywgdmFsdWVDb2xLZXkpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy5zZWNvbmRhcnlDb2x1bW5zKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHZhbHVlQ29sdW1uVG9GaW5kID0gdGhpcy5nZXRQcmltYXJ5Q29sdW1uKHZhbHVlQ29sS2V5KTtcbiAgICAgICAgdmFyIGZvdW5kQ29sdW1uID0gbnVsbDtcbiAgICAgICAgdGhpcy5zZWNvbmRhcnlDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgdmFyIHRoaXNQaXZvdEtleXMgPSBjb2x1bW4uZ2V0Q29sRGVmKCkucGl2b3RLZXlzO1xuICAgICAgICAgICAgdmFyIHBpdm90VmFsdWVDb2x1bW4gPSBjb2x1bW4uZ2V0Q29sRGVmKCkucGl2b3RWYWx1ZUNvbHVtbjtcbiAgICAgICAgICAgIHZhciBwaXZvdEtleU1hdGNoZXMgPSBhcmVFcXVhbCh0aGlzUGl2b3RLZXlzLCBwaXZvdEtleXMpO1xuICAgICAgICAgICAgdmFyIHBpdm90VmFsdWVNYXRjaGVzID0gcGl2b3RWYWx1ZUNvbHVtbiA9PT0gdmFsdWVDb2x1bW5Ub0ZpbmQ7XG4gICAgICAgICAgICBpZiAocGl2b3RLZXlNYXRjaGVzICYmIHBpdm90VmFsdWVNYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgZm91bmRDb2x1bW4gPSBjb2x1bW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZm91bmRDb2x1bW47XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0QmVhbnMgPSBmdW5jdGlvbiAobG9nZ2VyRmFjdG9yeSkge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlckZhY3RvcnkuY3JlYXRlKCdjb2x1bW5Nb2RlbCcpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldEZpcnN0UmlnaHRBbmRMYXN0TGVmdFBpbm5lZCA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdmFyIGxhc3RMZWZ0O1xuICAgICAgICB2YXIgZmlyc3RSaWdodDtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkpIHtcbiAgICAgICAgICAgIGxhc3RMZWZ0ID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdCA/IHRoaXMuZGlzcGxheWVkQ29sdW1uc0xlZnRbMF0gOiBudWxsO1xuICAgICAgICAgICAgZmlyc3RSaWdodCA9IHRoaXMuZGlzcGxheWVkQ29sdW1uc1JpZ2h0ID8gbGFzdCh0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodCkgOiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbGFzdExlZnQgPSB0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0ID8gbGFzdCh0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0KSA6IG51bGw7XG4gICAgICAgICAgICBmaXJzdFJpZ2h0ID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zUmlnaHQgPyB0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodFswXSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ncmlkQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbHVtbi5zZXRMYXN0TGVmdFBpbm5lZChjb2x1bW4gPT09IGxhc3RMZWZ0LCBzb3VyY2UpO1xuICAgICAgICAgICAgY29sdW1uLnNldEZpcnN0UmlnaHRQaW5uZWQoY29sdW1uID09PSBmaXJzdFJpZ2h0LCBzb3VyY2UpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5hdXRvU2l6ZUNvbHVtbnMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb2x1bW5zID0gcGFyYW1zLmNvbHVtbnMsIHNraXBIZWFkZXIgPSBwYXJhbXMuc2tpcEhlYWRlciwgc2tpcEhlYWRlckdyb3VwcyA9IHBhcmFtcy5za2lwSGVhZGVyR3JvdXBzLCBzdG9wQXRHcm91cCA9IHBhcmFtcy5zdG9wQXRHcm91cCwgX2EgPSBwYXJhbXMuc291cmNlLCBzb3VyY2UgPSBfYSA9PT0gdm9pZCAwID8gJ2FwaScgOiBfYTtcbiAgICAgICAgLy8gYmVjYXVzZSBvZiBjb2x1bW4gdmlydHVhbGlzYXRpb24sIHdlIGNhbiBvbmx5IGRvIHRoaXMgZnVuY3Rpb24gb24gY29sdW1ucyB0aGF0IGFyZVxuICAgICAgICAvLyBhY3R1YWxseSByZW5kZXJlZCwgYXMgbm9uLXJlbmRlcmVkIGNvbHVtbnMgKG91dHNpZGUgdGhlIHZpZXdwb3J0IGFuZCBub3QgcmVuZGVyZWRcbiAgICAgICAgLy8gZHVlIHRvIGNvbHVtbiB2aXJ0dWFsaXNhdGlvbikgYXJlIG5vdCBwcmVzZW50LiB0aGlzIGNhbiByZXN1bHQgaW4gYWxsIHJlbmRlcmVkIGNvbHVtbnNcbiAgICAgICAgLy8gZ2V0dGluZyBuYXJyb3dlZCwgd2hpY2ggaW4gdHVybiBpbnRyb2R1Y2VzIG1vcmUgcmVuZGVyZWQgY29sdW1ucyBvbiB0aGUgUkhTIHdoaWNoXG4gICAgICAgIC8vIGRpZCBub3QgZ2V0IGF1dG9zaXplZCBpbiB0aGUgb3JpZ2luYWwgcnVuLCBsZWF2aW5nIHRoZSB2aXNpYmxlIGdyaWQgd2l0aCBjb2x1bW5zIG9uXG4gICAgICAgIC8vIHRoZSBMSFMgc2l6ZWQsIGJ1dCBSSFMgbm8uIHNvIHdlIGtlZXAgbG9vcGluZyB0aHJvdWdoIHRoZSB2aXNpYmxlIGNvbHVtbnMgdW50aWxcbiAgICAgICAgLy8gbm8gbW9yZSBjb2xzIGFyZSBhdmFpbGFibGUgKHJlbmRlcmVkKSB0byBiZSByZXNpemVkXG4gICAgICAgIC8vIHdlIGF1dG9zaXplIGFmdGVyIGFuaW1hdGlvbiBmcmFtZXMgZmluaXNoIGluIGNhc2UgYW55IGNlbGwgcmVuZGVyZXJzIG5lZWQgdG8gY29tcGxldGUgZmlyc3QuIHRoaXMgY2FuXG4gICAgICAgIC8vIGhhcHBlbiBlZyBpZiBjbGllbnQgY29kZSBpcyBjYWxsaW5nIGFwaS5hdXRvU2l6ZUFsbENvbHVtbnMoKSBzdHJhaWdodCBhZnRlciBncmlkIGlzIGluaXRpYWxpc2VkLCBidXQgZ3JpZFxuICAgICAgICAvLyBoYXNuJ3QgZnVsbHkgZHJhd24gb3V0IGFsbCB0aGUgY2VsbHMgeWV0IChkdWUgdG8gY2VsbCByZW5kZXJlcnMgaW4gYW5pbWF0aW9uIGZyYW1lcykuXG4gICAgICAgIHRoaXMuYW5pbWF0aW9uRnJhbWVTZXJ2aWNlLmZsdXNoQWxsRnJhbWVzKCk7XG4gICAgICAgIC8vIGtlZXAgdHJhY2sgb2Ygd2hpY2ggY29scyB3ZSBoYXZlIHJlc2l6ZWQgaW4gaGVyZVxuICAgICAgICB2YXIgY29sdW1uc0F1dG9zaXplZCA9IFtdO1xuICAgICAgICAvLyBpbml0aWFsaXNlIHdpdGggYW55dGhpbmcgZXhjZXB0IDAgc28gdGhhdCB3aGlsZSBsb29wIGV4ZWN1dGVzIGF0IGxlYXN0IG9uY2VcbiAgICAgICAgdmFyIGNoYW5nZXNUaGlzVGltZUFyb3VuZCA9IC0xO1xuICAgICAgICB2YXIgc2hvdWxkU2tpcEhlYWRlciA9IHNraXBIZWFkZXIgIT0gbnVsbCA/IHNraXBIZWFkZXIgOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1NraXBIZWFkZXJPbkF1dG9TaXplKCk7XG4gICAgICAgIHZhciBzaG91bGRTa2lwSGVhZGVyR3JvdXBzID0gc2tpcEhlYWRlckdyb3VwcyAhPSBudWxsID8gc2tpcEhlYWRlckdyb3VwcyA6IHNob3VsZFNraXBIZWFkZXI7XG4gICAgICAgIHdoaWxlIChjaGFuZ2VzVGhpc1RpbWVBcm91bmQgIT09IDApIHtcbiAgICAgICAgICAgIGNoYW5nZXNUaGlzVGltZUFyb3VuZCA9IDA7XG4gICAgICAgICAgICB0aGlzLmFjdGlvbk9uR3JpZENvbHVtbnMoY29sdW1ucywgZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgICAgIC8vIGlmIGFscmVhZHkgYXV0b3NpemVkLCBza2lwIGl0XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbnNBdXRvc2l6ZWQuaW5kZXhPZihjb2x1bW4pID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBnZXQgaG93IHdpZGUgdGhpcyBjb2wgc2hvdWxkIGJlXG4gICAgICAgICAgICAgICAgdmFyIHByZWZlcnJlZFdpZHRoID0gX3RoaXMuYXV0b1dpZHRoQ2FsY3VsYXRvci5nZXRQcmVmZXJyZWRXaWR0aEZvckNvbHVtbihjb2x1bW4sIHNob3VsZFNraXBIZWFkZXIpO1xuICAgICAgICAgICAgICAgIC8vIHByZWZlcnJlZFdpZHRoID0gLTEgaWYgdGhpcyBjb2wgaXMgbm90IG9uIHRoZSBzY3JlZW5cbiAgICAgICAgICAgICAgICBpZiAocHJlZmVycmVkV2lkdGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdXaWR0aCA9IF90aGlzLm5vcm1hbGlzZUNvbHVtbldpZHRoKGNvbHVtbiwgcHJlZmVycmVkV2lkdGgpO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4uc2V0QWN0dWFsV2lkdGgobmV3V2lkdGgsIHNvdXJjZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbnNBdXRvc2l6ZWQucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VzVGhpc1RpbWVBcm91bmQrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LCBzb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc2hvdWxkU2tpcEhlYWRlckdyb3Vwcykge1xuICAgICAgICAgICAgdGhpcy5hdXRvU2l6ZUNvbHVtbkdyb3Vwc0J5Q29sdW1ucyhjb2x1bW5zLCBzdG9wQXRHcm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5maXJlQ29sdW1uUmVzaXplZEV2ZW50KGNvbHVtbnNBdXRvc2l6ZWQsIHRydWUsICdhdXRvc2l6ZUNvbHVtbnMnKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5maXJlQ29sdW1uUmVzaXplZEV2ZW50ID0gZnVuY3Rpb24gKGNvbHVtbnMsIGZpbmlzaGVkLCBzb3VyY2UsIGZsZXhDb2x1bW5zKSB7XG4gICAgICAgIGlmIChmbGV4Q29sdW1ucyA9PT0gdm9pZCAwKSB7IGZsZXhDb2x1bW5zID0gbnVsbDsgfVxuICAgICAgICBpZiAoY29sdW1ucyAmJiBjb2x1bW5zLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGV2ZW50XzEgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0NPTFVNTl9SRVNJWkVELFxuICAgICAgICAgICAgICAgIGNvbHVtbnM6IGNvbHVtbnMsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW5zLmxlbmd0aCA9PT0gMSA/IGNvbHVtbnNbMF0gOiBudWxsLFxuICAgICAgICAgICAgICAgIGZsZXhDb2x1bW5zOiBmbGV4Q29sdW1ucyxcbiAgICAgICAgICAgICAgICBmaW5pc2hlZDogZmluaXNoZWQsXG4gICAgICAgICAgICAgICAgc291cmNlOiBzb3VyY2VcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50XzEpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYXV0b1NpemVDb2x1bW4gPSBmdW5jdGlvbiAoa2V5LCBza2lwSGVhZGVyLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgdGhpcy5hdXRvU2l6ZUNvbHVtbnMoeyBjb2x1bW5zOiBba2V5XSwgc2tpcEhlYWRlcjogc2tpcEhlYWRlciwgc2tpcEhlYWRlckdyb3VwczogdHJ1ZSwgc291cmNlOiBzb3VyY2UgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5hdXRvU2l6ZUNvbHVtbkdyb3Vwc0J5Q29sdW1ucyA9IGZ1bmN0aW9uIChrZXlzLCBzdG9wQXRHcm91cCkge1xuICAgICAgICB2YXIgZV8xLCBfYSwgZV8yLCBfYjtcbiAgICAgICAgdmFyIGNvbHVtbkdyb3VwcyA9IG5ldyBTZXQoKTtcbiAgICAgICAgdmFyIGNvbHVtbnMgPSB0aGlzLmdldEdyaWRDb2x1bW5zKGtleXMpO1xuICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgdmFyIHBhcmVudCA9IGNvbC5nZXRQYXJlbnQoKTtcbiAgICAgICAgICAgIHdoaWxlIChwYXJlbnQgJiYgcGFyZW50ICE9IHN0b3BBdEdyb3VwKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFwYXJlbnQuaXNQYWRkaW5nKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uR3JvdXBzLmFkZChwYXJlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQuZ2V0UGFyZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgaGVhZGVyR3JvdXBDdHJsO1xuICAgICAgICB2YXIgcmVzaXplZENvbHVtbnMgPSBbXTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZvciAodmFyIGNvbHVtbkdyb3Vwc18xID0gX192YWx1ZXMkNChjb2x1bW5Hcm91cHMpLCBjb2x1bW5Hcm91cHNfMV8xID0gY29sdW1uR3JvdXBzXzEubmV4dCgpOyAhY29sdW1uR3JvdXBzXzFfMS5kb25lOyBjb2x1bW5Hcm91cHNfMV8xID0gY29sdW1uR3JvdXBzXzEubmV4dCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbkdyb3VwID0gY29sdW1uR3JvdXBzXzFfMS52YWx1ZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBfYyA9IChlXzIgPSB2b2lkIDAsIF9fdmFsdWVzJDQodGhpcy5jdHJsc1NlcnZpY2UuZ2V0SGVhZGVyUm93Q29udGFpbmVyQ3RybHMoKSkpLCBfZCA9IF9jLm5leHQoKTsgIV9kLmRvbmU7IF9kID0gX2MubmV4dCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaGVhZGVyQ29udGFpbmVyQ3RybCA9IF9kLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyR3JvdXBDdHJsID0gaGVhZGVyQ29udGFpbmVyQ3RybC5nZXRIZWFkZXJDdHJsRm9yQ29sdW1uKGNvbHVtbkdyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoZWFkZXJHcm91cEN0cmwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZV8yXzEpIHsgZV8yID0geyBlcnJvcjogZV8yXzEgfTsgfVxuICAgICAgICAgICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9kICYmICFfZC5kb25lICYmIChfYiA9IF9jLnJldHVybikpIF9iLmNhbGwoX2MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZpbmFsbHkgeyBpZiAoZV8yKSB0aHJvdyBlXzIuZXJyb3I7IH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRlckdyb3VwQ3RybCkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXJHcm91cEN0cmwucmVzaXplTGVhZkNvbHVtbnNUb0ZpdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZV8xXzEpIHsgZV8xID0geyBlcnJvcjogZV8xXzEgfTsgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbkdyb3Vwc18xXzEgJiYgIWNvbHVtbkdyb3Vwc18xXzEuZG9uZSAmJiAoX2EgPSBjb2x1bW5Hcm91cHNfMS5yZXR1cm4pKSBfYS5jYWxsKGNvbHVtbkdyb3Vwc18xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkgeyBpZiAoZV8xKSB0aHJvdyBlXzEuZXJyb3I7IH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzaXplZENvbHVtbnM7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYXV0b1NpemVBbGxDb2x1bW5zID0gZnVuY3Rpb24gKHNraXBIZWFkZXIsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIgYWxsRGlzcGxheWVkQ29sdW1ucyA9IHRoaXMuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucygpO1xuICAgICAgICB0aGlzLmF1dG9TaXplQ29sdW1ucyh7IGNvbHVtbnM6IGFsbERpc3BsYXllZENvbHVtbnMsIHNraXBIZWFkZXI6IHNraXBIZWFkZXIsIHNvdXJjZTogc291cmNlIH0pO1xuICAgIH07XG4gICAgLy8gUG9zc2libGUgY2FuZGlkYXRlIGZvciByZXVzZSAoYWxvdCBvZiByZWN1cnNpdmUgdHJhdmVyc2FsIGR1cGxpY2F0aW9uKVxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRDb2x1bW5zRnJvbVRyZWUgPSBmdW5jdGlvbiAocm9vdENvbHVtbnMpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIgcmVjdXJzaXZlRmluZENvbHVtbnMgPSBmdW5jdGlvbiAoY2hpbGRDb2x1bW5zKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkQ29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkQ29sdW1uc1tpXTtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goY2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChjaGlsZCBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjdXJzaXZlRmluZENvbHVtbnMoY2hpbGQuZ2V0Q2hpbGRyZW4oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZWN1cnNpdmVGaW5kQ29sdW1ucyhyb290Q29sdW1ucyk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0QWxsRGlzcGxheWVkVHJlZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXllZFRyZWVMZWZ0ICYmIHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0ICYmIHRoaXMuZGlzcGxheWVkVHJlZUNlbnRyZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheWVkVHJlZUxlZnRcbiAgICAgICAgICAgICAgICAuY29uY2F0KHRoaXMuZGlzcGxheWVkVHJlZUNlbnRyZSlcbiAgICAgICAgICAgICAgICAuY29uY2F0KHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIC8vICsgY29sdW1uU2VsZWN0UGFuZWxcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0UHJpbWFyeUNvbHVtblRyZWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW1hcnlDb2x1bW5UcmVlO1xuICAgIH07XG4gICAgLy8gKyBncmlkUGFuZWwgLT4gZm9yIHJlc2l6aW5nIHRoZSBib2R5IGFuZCBzZXR0aW5nIHRvcCBtYXJnaW5cbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0SGVhZGVyUm93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRIZWFkZXJSb3dDb3VudDtcbiAgICB9O1xuICAgIC8vICsgaGVhZGVyUmVuZGVyZXIgLT4gc2V0dGluZyBwaW5uZWQgYm9keSB3aWR0aFxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRUcmVlTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheWVkVHJlZUxlZnQ7XG4gICAgfTtcbiAgICAvLyArIGhlYWRlclJlbmRlcmVyIC0+IHNldHRpbmcgcGlubmVkIGJvZHkgd2lkdGhcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkVHJlZVJpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRUcmVlUmlnaHQ7XG4gICAgfTtcbiAgICAvLyArIGhlYWRlclJlbmRlcmVyIC0+IHNldHRpbmcgcGlubmVkIGJvZHkgd2lkdGhcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkVHJlZUNlbnRyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheWVkVHJlZUNlbnRyZTtcbiAgICB9O1xuICAgIC8vIGdyaWRQYW5lbCAtPiBlbnN1cmVDb2x1bW5WaXNpYmxlXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmlzQ29sdW1uRGlzcGxheWVkID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCkuaW5kZXhPZihjb2x1bW4pID49IDA7XG4gICAgfTtcbiAgICAvLyArIGNzdkNyZWF0b3JcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheWVkQ29sdW1ucztcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRWaWV3cG9ydENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdwb3J0Q29sdW1ucztcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRMZWZ0Q29sdW1uc0ZvclJvdyA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIGlmICghdGhpcy5jb2xTcGFuQWN0aXZlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXREaXNwbGF5ZWRDb2x1bW5zRm9yUm93KHJvd05vZGUsIHRoaXMuZGlzcGxheWVkQ29sdW1uc0xlZnQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldERpc3BsYXllZFJpZ2h0Q29sdW1uc0ZvclJvdyA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIGlmICghdGhpcy5jb2xTcGFuQWN0aXZlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zUmlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RGlzcGxheWVkQ29sdW1uc0ZvclJvdyhyb3dOb2RlLCB0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkQ29sdW1uc0ZvclJvdyA9IGZ1bmN0aW9uIChyb3dOb2RlLCBkaXNwbGF5ZWRDb2x1bW5zLCBmaWx0ZXJDYWxsYmFjaywgZW1wdHlTcGFjZUJlZm9yZUNvbHVtbikge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBsYXN0Q29uc2lkZXJlZENvbCA9IG51bGw7XG4gICAgICAgIHZhciBfbG9vcF8xID0gZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgIHZhciBjb2wgPSBkaXNwbGF5ZWRDb2x1bW5zW2ldO1xuICAgICAgICAgICAgdmFyIG1heEFsbG93ZWRDb2xTcGFuID0gZGlzcGxheWVkQ29sdW1ucy5sZW5ndGggLSBpO1xuICAgICAgICAgICAgdmFyIGNvbFNwYW4gPSBNYXRoLm1pbihjb2wuZ2V0Q29sU3Bhbihyb3dOb2RlKSwgbWF4QWxsb3dlZENvbFNwYW4pO1xuICAgICAgICAgICAgdmFyIGNvbHVtbnNUb0NoZWNrRmlsdGVyID0gW2NvbF07XG4gICAgICAgICAgICBpZiAoY29sU3BhbiA+IDEpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29sc1RvUmVtb3ZlID0gY29sU3BhbiAtIDE7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDE7IGogPD0gY29sc1RvUmVtb3ZlOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uc1RvQ2hlY2tGaWx0ZXIucHVzaChkaXNwbGF5ZWRDb2x1bW5zW2kgKyBqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGkgKz0gY29sc1RvUmVtb3ZlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gc2VlIHdoaWNoIGNvbHMgd2Ugc2hvdWxkIHRha2Ugb3V0IGZvciBjb2x1bW4gdmlydHVhbGlzYXRpb25cbiAgICAgICAgICAgIHZhciBmaWx0ZXJQYXNzZXM7XG4gICAgICAgICAgICBpZiAoZmlsdGVyQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB1c2VyIHByb3ZpZGVkIGEgY2FsbGJhY2ssIG1lYW5zIHNvbWUgY29sdW1ucyBtYXkgbm90IGJlIGluIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgICAgICAgICAvLyB0aGUgdXNlciB3aWxsIE5PVCBwcm92aWRlIGEgY2FsbGJhY2sgaWYgd2UgYXJlIHRhbGtpbmcgYWJvdXQgcGlubmVkIGFyZWFzLFxuICAgICAgICAgICAgICAgIC8vIGFzIHBpbm5lZCBhcmVhcyBoYXZlIG5vIGhvcml6b250YWwgc2Nyb2xsIGFuZCBkbyBub3QgdmlydHVhbGlzZSB0aGUgY29sdW1ucy5cbiAgICAgICAgICAgICAgICAvLyBpZiBsb3RzIG9mIGNvbHVtbnMsIHRoYXQgbWVhbnMgY29sdW1uIHNwYW5uaW5nLCBhbmQgd2Ugc2V0IGZpbHRlclBhc3NlcyA9IHRydWVcbiAgICAgICAgICAgICAgICAvLyBpZiBvbmUgb3IgbW9yZSBvZiB0aGUgY29sdW1ucyBzcGFubmVkIHBhc3MgdGhlIGZpbHRlci5cbiAgICAgICAgICAgICAgICBmaWx0ZXJQYXNzZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjb2x1bW5zVG9DaGVja0ZpbHRlci5mb3JFYWNoKGZ1bmN0aW9uIChjb2xGb3JGaWx0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpbHRlckNhbGxiYWNrKGNvbEZvckZpbHRlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlclBhc3NlcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZpbHRlclBhc3NlcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlsdGVyUGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDAgJiYgbGFzdENvbnNpZGVyZWRDb2wpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGdhcEJlZm9yZUNvbHVtbiA9IGVtcHR5U3BhY2VCZWZvcmVDb2x1bW4gPyBlbXB0eVNwYWNlQmVmb3JlQ29sdW1uKGNvbCkgOiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdhcEJlZm9yZUNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gobGFzdENvbnNpZGVyZWRDb2wpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGNvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0Q29uc2lkZXJlZENvbCA9IGNvbDtcbiAgICAgICAgICAgIG91dF9pXzEgPSBpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgb3V0X2lfMTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkaXNwbGF5ZWRDb2x1bW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBfbG9vcF8xKGkpO1xuICAgICAgICAgICAgaSA9IG91dF9pXzE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIC8vICsgcm93UmVuZGVyZXJcbiAgICAvLyBpZiB3ZSBhcmUgbm90IGNvbHVtbiBzcGFubmluZywgdGhpcyBqdXN0IHJldHVybnMgYmFjayB0aGUgdmlydHVhbCBjZW50cmUgY29sdW1ucyxcbiAgICAvLyBob3dldmVyIGlmIHdlIGFyZSBjb2x1bW4gc3Bhbm5pbmcsIHRoZW4gZGlmZmVyZW50IHJvd3MgY2FuIGhhdmUgZGlmZmVyZW50IHZpcnR1YWxcbiAgICAvLyBjb2x1bW5zLCBzbyB3ZSBoYXZlIHRvIHdvcmsgb3V0IHRoZSBsaXN0IGZvciBlYWNoIGluZGl2aWR1YWwgcm93LlxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRWaWV3cG9ydENlbnRlckNvbHVtbnNGb3JSb3cgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuY29sU3BhbkFjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmlld3BvcnRDb2x1bW5zQ2VudGVyO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlbXB0eVNwYWNlQmVmb3JlQ29sdW1uID0gZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgdmFyIGxlZnQgPSBjb2wuZ2V0TGVmdCgpO1xuICAgICAgICAgICAgcmV0dXJuIGV4aXN0cyhsZWZ0KSAmJiBsZWZ0ID4gX3RoaXMudmlld3BvcnRMZWZ0O1xuICAgICAgICB9O1xuICAgICAgICAvLyBpZiBkb2luZyBjb2x1bW4gdmlydHVhbGlzYXRpb24sIHRoZW4gd2UgZmlsdGVyIGJhc2VkIG9uIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgdmFyIGZpbHRlckNhbGxiYWNrID0gdGhpcy5zdXBwcmVzc0NvbHVtblZpcnR1YWxpc2F0aW9uID8gbnVsbCA6IHRoaXMuaXNDb2x1bW5JblJvd1ZpZXdwb3J0LmJpbmQodGhpcyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldERpc3BsYXllZENvbHVtbnNGb3JSb3cocm93Tm9kZSwgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyLCBmaWx0ZXJDYWxsYmFjaywgZW1wdHlTcGFjZUJlZm9yZUNvbHVtbik7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0QXJpYUNvbHVtbkluZGV4ID0gZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRBbGxHcmlkQ29sdW1ucygpLmluZGV4T2YoY29sKSArIDE7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuaXNDb2x1bW5JbkhlYWRlclZpZXdwb3J0ID0gZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAvLyBmb3IgaGVhZGVycywgd2UgbmV2ZXIgZmlsdGVyIG91dCBhdXRvSGVhZGVySGVpZ2h0IGNvbHVtbnMsIGlmIGNhbGN1bGF0aW5nXG4gICAgICAgIGlmIChjb2wuaXNBdXRvSGVhZGVySGVpZ2h0KCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmlzQ29sdW1uSW5Sb3dWaWV3cG9ydChjb2wpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmlzQ29sdW1uSW5Sb3dWaWV3cG9ydCA9IGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgLy8gd2UgbmV2ZXIgZmlsdGVyIG91dCBhdXRvSGVpZ2h0IGNvbHVtbnMsIGFzIHdlIG5lZWQgdGhlbSBpbiB0aGUgRE9NIGZvciBjYWxjdWxhdGluZyBBdXRvIEhlaWdodFxuICAgICAgICBpZiAoY29sLmlzQXV0b0hlaWdodCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sdW1uTGVmdCA9IGNvbC5nZXRMZWZ0KCkgfHwgMDtcbiAgICAgICAgdmFyIGNvbHVtblJpZ2h0ID0gY29sdW1uTGVmdCArIGNvbC5nZXRBY3R1YWxXaWR0aCgpO1xuICAgICAgICAvLyBhZGRpbmcgMjAwIGZvciBidWZmZXIgc2l6ZSwgc28gc29tZSBjb2xzIG9mZiB2aWV3cG9ydCBhcmUgcmVuZGVyZWQuXG4gICAgICAgIC8vIHRoaXMgaGVscHMgaG9yaXpvbnRhbCBzY3JvbGxpbmcgc28gdXNlciByYXJlbHkgc2VlcyB3aGl0ZSBzcGFjZSAodW5sZXNzXG4gICAgICAgIC8vIHRoZXkgc2Nyb2xsIGhvcml6b250YWxseSBmYXN0KS4gaG93ZXZlciB3ZSBhcmUgY29uc2VydmF0aXZlLCBhcyB0aGUgbW9yZVxuICAgICAgICAvLyBidWZmZXIgdGhlIHNsb3dlciB0aGUgdmVydGljYWwgcmVkcmF3IHNwZWVkXG4gICAgICAgIHZhciBsZWZ0Qm91bmRzID0gdGhpcy52aWV3cG9ydExlZnQgLSAyMDA7XG4gICAgICAgIHZhciByaWdodEJvdW5kcyA9IHRoaXMudmlld3BvcnRSaWdodCArIDIwMDtcbiAgICAgICAgdmFyIGNvbHVtblRvTXVjaExlZnQgPSBjb2x1bW5MZWZ0IDwgbGVmdEJvdW5kcyAmJiBjb2x1bW5SaWdodCA8IGxlZnRCb3VuZHM7XG4gICAgICAgIHZhciBjb2x1bW5Ub011Y2hSaWdodCA9IGNvbHVtbkxlZnQgPiByaWdodEJvdW5kcyAmJiBjb2x1bW5SaWdodCA+IHJpZ2h0Qm91bmRzO1xuICAgICAgICByZXR1cm4gIWNvbHVtblRvTXVjaExlZnQgJiYgIWNvbHVtblRvTXVjaFJpZ2h0O1xuICAgIH07XG4gICAgLy8gdXNlZCBieTpcbiAgICAvLyArIGFuZ3VsYXJHcmlkIC0+IHNldHRpbmcgcGlubmVkIGJvZHkgd2lkdGhcbiAgICAvLyBub3RlOiB0aGlzIHNob3VsZCBiZSBjYWNoZWRcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkQ29sdW1uc0xlZnRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0V2lkdGhPZkNvbHNJbkxpc3QodGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdCk7XG4gICAgfTtcbiAgICAvLyBub3RlOiB0aGlzIHNob3VsZCBiZSBjYWNoZWRcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkQ29sdW1uc1JpZ2h0V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFdpZHRoT2ZDb2xzSW5MaXN0KHRoaXMuZGlzcGxheWVkQ29sdW1uc1JpZ2h0KTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS51cGRhdGVQcmltYXJ5Q29sdW1uTGlzdCA9IGZ1bmN0aW9uIChrZXlzLCBtYXN0ZXJMaXN0LCBhY3Rpb25Jc0FkZCwgY29sdW1uQ2FsbGJhY2ssIGV2ZW50VHlwZSwgc291cmNlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmICgha2V5cyB8fCBtaXNzaW5nT3JFbXB0eShrZXlzKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhdExlYXN0T25lID0gZmFsc2U7XG4gICAgICAgIGtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uVG9BZGQgPSBfdGhpcy5nZXRQcmltYXJ5Q29sdW1uKGtleSk7XG4gICAgICAgICAgICBpZiAoIWNvbHVtblRvQWRkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFjdGlvbklzQWRkKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1hc3Rlckxpc3QuaW5kZXhPZihjb2x1bW5Ub0FkZCkgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1hc3Rlckxpc3QucHVzaChjb2x1bW5Ub0FkZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAobWFzdGVyTGlzdC5pbmRleE9mKGNvbHVtblRvQWRkKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkobWFzdGVyTGlzdCwgY29sdW1uVG9BZGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29sdW1uQ2FsbGJhY2soY29sdW1uVG9BZGQpO1xuICAgICAgICAgICAgYXRMZWFzdE9uZSA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWF0TGVhc3RPbmUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5hdXRvR3JvdXBzTmVlZEJ1aWxkaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUdyaWRDb2x1bW5zKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5ZWRDb2x1bW5zKHNvdXJjZSk7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IGV2ZW50VHlwZSxcbiAgICAgICAgICAgIGNvbHVtbnM6IG1hc3Rlckxpc3QsXG4gICAgICAgICAgICBjb2x1bW46IG1hc3Rlckxpc3QubGVuZ3RoID09PSAxID8gbWFzdGVyTGlzdFswXSA6IG51bGwsXG4gICAgICAgICAgICBzb3VyY2U6IHNvdXJjZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXRSb3dHcm91cENvbHVtbnMgPSBmdW5jdGlvbiAoY29sS2V5cywgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMuYXV0b0dyb3Vwc05lZWRCdWlsZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuc2V0UHJpbWFyeUNvbHVtbkxpc3QoY29sS2V5cywgdGhpcy5yb3dHcm91cENvbHVtbnMsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIHRoaXMuc2V0Um93R3JvdXBBY3RpdmUuYmluZCh0aGlzKSwgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXRSb3dHcm91cEFjdGl2ZSA9IGZ1bmN0aW9uIChhY3RpdmUsIGNvbHVtbiwgc291cmNlKSB7XG4gICAgICAgIGlmIChhY3RpdmUgPT09IGNvbHVtbi5pc1Jvd0dyb3VwQWN0aXZlKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb2x1bW4uc2V0Um93R3JvdXBBY3RpdmUoYWN0aXZlLCBzb3VyY2UpO1xuICAgICAgICBpZiAoYWN0aXZlICYmICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzUm93R3JvdXBIaWRlc0NvbHVtbnMoKSkge1xuICAgICAgICAgICAgdGhpcy5zZXRDb2x1bW5WaXNpYmxlKGNvbHVtbiwgZmFsc2UsIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFhY3RpdmUgJiYgIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NNYWtlQ29sdW1uVmlzaWJsZUFmdGVyVW5Hcm91cCgpKSB7XG4gICAgICAgICAgICB0aGlzLnNldENvbHVtblZpc2libGUoY29sdW1uLCB0cnVlLCBzb3VyY2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYWRkUm93R3JvdXBDb2x1bW4gPSBmdW5jdGlvbiAoa2V5LCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgdGhpcy5hZGRSb3dHcm91cENvbHVtbnMoW2tleV0sIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5hZGRSb3dHcm91cENvbHVtbnMgPSBmdW5jdGlvbiAoa2V5cywgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMuYXV0b0dyb3Vwc05lZWRCdWlsZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMudXBkYXRlUHJpbWFyeUNvbHVtbkxpc3Qoa2V5cywgdGhpcy5yb3dHcm91cENvbHVtbnMsIHRydWUsIHRoaXMuc2V0Um93R3JvdXBBY3RpdmUuYmluZCh0aGlzLCB0cnVlKSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9ST1dfR1JPVVBfQ0hBTkdFRCwgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5yZW1vdmVSb3dHcm91cENvbHVtbnMgPSBmdW5jdGlvbiAoa2V5cywgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMuYXV0b0dyb3Vwc05lZWRCdWlsZGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMudXBkYXRlUHJpbWFyeUNvbHVtbkxpc3Qoa2V5cywgdGhpcy5yb3dHcm91cENvbHVtbnMsIGZhbHNlLCB0aGlzLnNldFJvd0dyb3VwQWN0aXZlLmJpbmQodGhpcywgZmFsc2UpLCBFdmVudHMuRVZFTlRfQ09MVU1OX1JPV19HUk9VUF9DSEFOR0VELCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlbW92ZVJvd0dyb3VwQ29sdW1uID0gZnVuY3Rpb24gKGtleSwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlUm93R3JvdXBDb2x1bW5zKFtrZXldLCBzb3VyY2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYWRkUGl2b3RDb2x1bW5zID0gZnVuY3Rpb24gKGtleXMsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB0aGlzLnVwZGF0ZVByaW1hcnlDb2x1bW5MaXN0KGtleXMsIHRoaXMucGl2b3RDb2x1bW5zLCB0cnVlLCBmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiBjb2x1bW4uc2V0UGl2b3RBY3RpdmUodHJ1ZSwgc291cmNlKTsgfSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9DSEFOR0VELCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldFBpdm90Q29sdW1ucyA9IGZ1bmN0aW9uIChjb2xLZXlzLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy5zZXRQcmltYXJ5Q29sdW1uTGlzdChjb2xLZXlzLCB0aGlzLnBpdm90Q29sdW1ucywgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9DSEFOR0VELCBmdW5jdGlvbiAoYWRkZWQsIGNvbHVtbikge1xuICAgICAgICAgICAgY29sdW1uLnNldFBpdm90QWN0aXZlKGFkZGVkLCBzb3VyY2UpO1xuICAgICAgICB9LCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmFkZFBpdm90Q29sdW1uID0gZnVuY3Rpb24gKGtleSwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMuYWRkUGl2b3RDb2x1bW5zKFtrZXldLCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlbW92ZVBpdm90Q29sdW1ucyA9IGZ1bmN0aW9uIChrZXlzLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy51cGRhdGVQcmltYXJ5Q29sdW1uTGlzdChrZXlzLCB0aGlzLnBpdm90Q29sdW1ucywgZmFsc2UsIGZ1bmN0aW9uIChjb2x1bW4pIHsgcmV0dXJuIGNvbHVtbi5zZXRQaXZvdEFjdGl2ZShmYWxzZSwgc291cmNlKTsgfSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9DSEFOR0VELCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlbW92ZVBpdm90Q29sdW1uID0gZnVuY3Rpb24gKGtleSwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMucmVtb3ZlUGl2b3RDb2x1bW5zKFtrZXldLCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldFByaW1hcnlDb2x1bW5MaXN0ID0gZnVuY3Rpb24gKGNvbEtleXMsIG1hc3Rlckxpc3QsIGV2ZW50TmFtZSwgY29sdW1uQ2FsbGJhY2ssIHNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBtYXN0ZXJMaXN0Lmxlbmd0aCA9IDA7XG4gICAgICAgIGlmIChleGlzdHMoY29sS2V5cykpIHtcbiAgICAgICAgICAgIGNvbEtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF90aGlzLmdldFByaW1hcnlDb2x1bW4oa2V5KTtcbiAgICAgICAgICAgICAgICBpZiAoY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hc3Rlckxpc3QucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgICh0aGlzLnByaW1hcnlDb2x1bW5zIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHZhciBhZGRlZCA9IG1hc3Rlckxpc3QuaW5kZXhPZihjb2x1bW4pID49IDA7XG4gICAgICAgICAgICBjb2x1bW5DYWxsYmFjayhhZGRlZCwgY29sdW1uKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLmF1dG9Hcm91cHNOZWVkQnVpbGRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlR3JpZENvbHVtbnMoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXllZENvbHVtbnMoc291cmNlKTtcbiAgICAgICAgdGhpcy5maXJlQ29sdW1uRXZlbnQoZXZlbnROYW1lLCBtYXN0ZXJMaXN0LCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldFZhbHVlQ29sdW1ucyA9IGZ1bmN0aW9uIChjb2xLZXlzLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy5zZXRQcmltYXJ5Q29sdW1uTGlzdChjb2xLZXlzLCB0aGlzLnZhbHVlQ29sdW1ucywgRXZlbnRzLkVWRU5UX0NPTFVNTl9WQUxVRV9DSEFOR0VELCB0aGlzLnNldFZhbHVlQWN0aXZlLmJpbmQodGhpcyksIHNvdXJjZSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0VmFsdWVBY3RpdmUgPSBmdW5jdGlvbiAoYWN0aXZlLCBjb2x1bW4sIHNvdXJjZSkge1xuICAgICAgICBpZiAoYWN0aXZlID09PSBjb2x1bW4uaXNWYWx1ZUFjdGl2ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29sdW1uLnNldFZhbHVlQWN0aXZlKGFjdGl2ZSwgc291cmNlKTtcbiAgICAgICAgaWYgKGFjdGl2ZSAmJiAhY29sdW1uLmdldEFnZ0Z1bmMoKSkge1xuICAgICAgICAgICAgdmFyIGluaXRpYWxBZ2dGdW5jID0gdGhpcy5hZ2dGdW5jU2VydmljZS5nZXREZWZhdWx0QWdnRnVuYyhjb2x1bW4pO1xuICAgICAgICAgICAgY29sdW1uLnNldEFnZ0Z1bmMoaW5pdGlhbEFnZ0Z1bmMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYWRkVmFsdWVDb2x1bW5zID0gZnVuY3Rpb24gKGtleXMsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB0aGlzLnVwZGF0ZVByaW1hcnlDb2x1bW5MaXN0KGtleXMsIHRoaXMudmFsdWVDb2x1bW5zLCB0cnVlLCB0aGlzLnNldFZhbHVlQWN0aXZlLmJpbmQodGhpcywgdHJ1ZSksIEV2ZW50cy5FVkVOVF9DT0xVTU5fVkFMVUVfQ0hBTkdFRCwgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5hZGRWYWx1ZUNvbHVtbiA9IGZ1bmN0aW9uIChjb2xLZXksIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICBpZiAoY29sS2V5KSB7XG4gICAgICAgICAgICB0aGlzLmFkZFZhbHVlQ29sdW1ucyhbY29sS2V5XSwgc291cmNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlbW92ZVZhbHVlQ29sdW1uID0gZnVuY3Rpb24gKGNvbEtleSwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMucmVtb3ZlVmFsdWVDb2x1bW5zKFtjb2xLZXldLCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlbW92ZVZhbHVlQ29sdW1ucyA9IGZ1bmN0aW9uIChrZXlzLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy51cGRhdGVQcmltYXJ5Q29sdW1uTGlzdChrZXlzLCB0aGlzLnZhbHVlQ29sdW1ucywgZmFsc2UsIHRoaXMuc2V0VmFsdWVBY3RpdmUuYmluZCh0aGlzLCBmYWxzZSksIEV2ZW50cy5FVkVOVF9DT0xVTU5fVkFMVUVfQ0hBTkdFRCwgc291cmNlKTtcbiAgICB9O1xuICAgIC8vIHJldHVybnMgdGhlIHdpZHRoIHdlIGNhbiBzZXQgdG8gdGhpcyBjb2wsIHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gbWluIGFuZCBtYXggd2lkdGhzXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLm5vcm1hbGlzZUNvbHVtbldpZHRoID0gZnVuY3Rpb24gKGNvbHVtbiwgbmV3V2lkdGgpIHtcbiAgICAgICAgdmFyIG1pbldpZHRoID0gY29sdW1uLmdldE1pbldpZHRoKCk7XG4gICAgICAgIGlmIChleGlzdHMobWluV2lkdGgpICYmIG5ld1dpZHRoIDwgbWluV2lkdGgpIHtcbiAgICAgICAgICAgIG5ld1dpZHRoID0gbWluV2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1heFdpZHRoID0gY29sdW1uLmdldE1heFdpZHRoKCk7XG4gICAgICAgIGlmIChleGlzdHMobWF4V2lkdGgpICYmIGNvbHVtbi5pc0dyZWF0ZXJUaGFuTWF4KG5ld1dpZHRoKSkge1xuICAgICAgICAgICAgbmV3V2lkdGggPSBtYXhXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3V2lkdGg7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0UHJpbWFyeU9yR3JpZENvbHVtbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuZ2V0UHJpbWFyeUNvbHVtbihrZXkpO1xuICAgICAgICByZXR1cm4gY29sdW1uIHx8IHRoaXMuZ2V0R3JpZENvbHVtbihrZXkpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldENvbHVtbldpZHRocyA9IGZ1bmN0aW9uIChjb2x1bW5XaWR0aHMsIHNoaWZ0S2V5LCAvLyBAdGFrZUZyb21BZGphY2VudCAtIGlmIHVzZXIgaGFzICdzaGlmdCcgcHJlc3NlZCwgdGhlbiBwaXhlbHMgYXJlIHRha2VuIGZyb20gYWRqYWNlbnQgY29sdW1uXG4gICAgZmluaXNoZWQsIC8vIEBmaW5pc2hlZCAtIGVuZHMgdXAgaW4gdGhlIGV2ZW50LCB0ZWxscyB0aGUgdXNlciBpZiBtb3JlIGV2ZW50cyBhcmUgdG8gY29tZVxuICAgIHNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIgc2V0cyA9IFtdO1xuICAgICAgICBjb2x1bW5XaWR0aHMuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uV2lkdGgpIHtcbiAgICAgICAgICAgIHZhciBjb2wgPSBfdGhpcy5nZXRQcmltYXJ5T3JHcmlkQ29sdW1uKGNvbHVtbldpZHRoLmtleSk7XG4gICAgICAgICAgICBpZiAoIWNvbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNldHMucHVzaCh7XG4gICAgICAgICAgICAgICAgd2lkdGg6IGNvbHVtbldpZHRoLm5ld1dpZHRoLFxuICAgICAgICAgICAgICAgIHJhdGlvczogWzFdLFxuICAgICAgICAgICAgICAgIGNvbHVtbnM6IFtjb2xdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIGlmIHVzZXIgd2FudHMgdG8gZG8gc2hpZnQgcmVzaXplIGJ5IGRlZmF1bHQsIHRoZW4gd2UgaW52ZXJ0IHRoZSBzaGlmdCBvcGVyYXRpb25cbiAgICAgICAgICAgIHZhciBkZWZhdWx0SXNTaGlmdCA9IF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2xSZXNpemVEZWZhdWx0KCkgPT09ICdzaGlmdCc7XG4gICAgICAgICAgICBpZiAoZGVmYXVsdElzU2hpZnQpIHtcbiAgICAgICAgICAgICAgICBzaGlmdEtleSA9ICFzaGlmdEtleTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzaGlmdEtleSkge1xuICAgICAgICAgICAgICAgIHZhciBvdGhlckNvbCA9IF90aGlzLmdldERpc3BsYXllZENvbEFmdGVyKGNvbCk7XG4gICAgICAgICAgICAgICAgaWYgKCFvdGhlckNvbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB3aWR0aERpZmYgPSBjb2wuZ2V0QWN0dWFsV2lkdGgoKSAtIGNvbHVtbldpZHRoLm5ld1dpZHRoO1xuICAgICAgICAgICAgICAgIHZhciBvdGhlckNvbFdpZHRoID0gb3RoZXJDb2wuZ2V0QWN0dWFsV2lkdGgoKSArIHdpZHRoRGlmZjtcbiAgICAgICAgICAgICAgICBzZXRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogb3RoZXJDb2xXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgcmF0aW9zOiBbMV0sXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbnM6IFtvdGhlckNvbF1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChzZXRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzaXplQ29sdW1uU2V0cyh7XG4gICAgICAgICAgICByZXNpemVTZXRzOiBzZXRzLFxuICAgICAgICAgICAgZmluaXNoZWQ6IGZpbmlzaGVkLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2VcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuY2hlY2tNaW5BbmRNYXhXaWR0aHNGb3JTZXQgPSBmdW5jdGlvbiAoY29sdW1uUmVzaXplU2V0KSB7XG4gICAgICAgIHZhciBjb2x1bW5zID0gY29sdW1uUmVzaXplU2V0LmNvbHVtbnMsIHdpZHRoID0gY29sdW1uUmVzaXplU2V0LndpZHRoO1xuICAgICAgICAvLyBldmVyeSBjb2wgaGFzIGEgbWluIHdpZHRoLCBzbyBzdW0gdGhlbSBhbGwgdXAgYW5kIHNlZSBpZiB3ZSBoYXZlIGVub3VnaCByb29tXG4gICAgICAgIC8vIGZvciBhbGwgdGhlIG1pbiB3aWR0aHNcbiAgICAgICAgdmFyIG1pbldpZHRoQWNjdW11bGF0ZWQgPSAwO1xuICAgICAgICB2YXIgbWF4V2lkdGhBY2N1bXVsYXRlZCA9IDA7XG4gICAgICAgIHZhciBtYXhXaWR0aEFjdGl2ZSA9IHRydWU7XG4gICAgICAgIGNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICB2YXIgbWluV2lkdGggPSBjb2wuZ2V0TWluV2lkdGgoKTtcbiAgICAgICAgICAgIG1pbldpZHRoQWNjdW11bGF0ZWQgKz0gbWluV2lkdGggfHwgMDtcbiAgICAgICAgICAgIHZhciBtYXhXaWR0aCA9IGNvbC5nZXRNYXhXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKGV4aXN0cyhtYXhXaWR0aCkgJiYgbWF4V2lkdGggPiAwKSB7XG4gICAgICAgICAgICAgICAgbWF4V2lkdGhBY2N1bXVsYXRlZCArPSBtYXhXaWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGlmIGF0IGxlYXN0IG9uZSBjb2x1bW5zIGhhcyBubyBtYXggd2lkdGgsIGl0IG1lYW5zIHRoZSBncm91cCBvZiBjb2x1bW5zXG4gICAgICAgICAgICAgICAgLy8gdGhlbiBoYXMgbm8gbWF4IHdpZHRoLCBhcyBhdCBsZWFzdCBvbmUgY29sdW1uIGNhbiB0YWtlIGFzIG11Y2ggd2lkdGggYXMgcG9zc2libGVcbiAgICAgICAgICAgICAgICBtYXhXaWR0aEFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIG1pbldpZHRoUGFzc2VzID0gd2lkdGggPj0gbWluV2lkdGhBY2N1bXVsYXRlZDtcbiAgICAgICAgdmFyIG1heFdpZHRoUGFzc2VzID0gIW1heFdpZHRoQWN0aXZlIHx8ICh3aWR0aCA8PSBtYXhXaWR0aEFjY3VtdWxhdGVkKTtcbiAgICAgICAgcmV0dXJuIG1pbldpZHRoUGFzc2VzICYmIG1heFdpZHRoUGFzc2VzO1xuICAgIH07XG4gICAgLy8gbWV0aG9kIHRha2VzIHNldHMgb2YgY29sdW1ucyBhbmQgcmVzaXplcyB0aGVtLiBlaXRoZXIgYWxsIHNldHMgd2lsbCBiZSByZXNpemVkLCBvciBub3RoaW5nXG4gICAgLy8gYmUgcmVzaXplZC4gdGhpcyBpcyB1c2VkIGZvciBleGFtcGxlIHdoZW4gdXNlciB0cmllcyB0byByZXNpemUgYSBncm91cCBhbmQgaG9sZHMgc2hpZnQga2V5LFxuICAgIC8vIHRoZW4gYm90aCB0aGUgY3VycmVudCBncm91cCAoZ3Jvd3MpLCBhbmQgdGhlIGFkamFjZW50IGdyb3VwIChzaHJpbmtzKSwgd2lsbCBnZXQgcmVzaXplZCxcbiAgICAvLyBzbyB0aGF0J3MgdHdvIHNldHMgZm9yIHRoaXMgbWV0aG9kLlxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5yZXNpemVDb2x1bW5TZXRzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVzaXplU2V0cyA9IHBhcmFtcy5yZXNpemVTZXRzLCBmaW5pc2hlZCA9IHBhcmFtcy5maW5pc2hlZCwgc291cmNlID0gcGFyYW1zLnNvdXJjZTtcbiAgICAgICAgdmFyIHBhc3NNaW5NYXhDaGVjayA9ICFyZXNpemVTZXRzIHx8IHJlc2l6ZVNldHMuZXZlcnkoZnVuY3Rpb24gKGNvbHVtblJlc2l6ZVNldCkgeyByZXR1cm4gX3RoaXMuY2hlY2tNaW5BbmRNYXhXaWR0aHNGb3JTZXQoY29sdW1uUmVzaXplU2V0KTsgfSk7XG4gICAgICAgIGlmICghcGFzc01pbk1heENoZWNrKSB7XG4gICAgICAgICAgICAvLyBldmVuIHRob3VnaCB3ZSBhcmUgbm90IGdvaW5nIHRvIHJlc2l6ZSBiZXlvbmQgbWluL21heCBzaXplLCB3ZSBzdGlsbCBuZWVkIHRvIHJhaXNlIGV2ZW50IHdoZW4gZmluaXNoZWRcbiAgICAgICAgICAgIGlmIChmaW5pc2hlZCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW5zID0gcmVzaXplU2V0cyAmJiByZXNpemVTZXRzLmxlbmd0aCA+IDAgPyByZXNpemVTZXRzWzBdLmNvbHVtbnMgOiBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNvbHVtblJlc2l6ZWRFdmVudChjb2x1bW5zLCBmaW5pc2hlZCwgc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjsgLy8gZG9uJ3QgcmVzaXplIVxuICAgICAgICB9XG4gICAgICAgIHZhciBjaGFuZ2VkQ29scyA9IFtdO1xuICAgICAgICB2YXIgYWxsUmVzaXplZENvbHMgPSBbXTtcbiAgICAgICAgcmVzaXplU2V0cy5mb3JFYWNoKGZ1bmN0aW9uIChzZXQpIHtcbiAgICAgICAgICAgIHZhciB3aWR0aCA9IHNldC53aWR0aCwgY29sdW1ucyA9IHNldC5jb2x1bW5zLCByYXRpb3MgPSBzZXQucmF0aW9zO1xuICAgICAgICAgICAgLy8ga2VlcCB0cmFjayBvZiBwaXhlbHMgdXNlZCwgYW5kIGxhc3QgY29sdW1uIGdldHMgdGhlIHJlbWFpbmluZyxcbiAgICAgICAgICAgIC8vIHRvIGNhdGVyIGZvciByb3VuZGluZyBlcnJvcnMsIGFuZCBtaW4gd2lkdGggYWRqdXN0bWVudHNcbiAgICAgICAgICAgIHZhciBuZXdXaWR0aHMgPSB7fTtcbiAgICAgICAgICAgIHZhciBmaW5pc2hlZENvbHMgPSB7fTtcbiAgICAgICAgICAgIGNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBhbGxSZXNpemVkQ29scy5wdXNoKGNvbCk7IH0pO1xuICAgICAgICAgICAgLy8gdGhlIGxvb3AgYmVsb3cgZ29lcyB0aHJvdWdoIGVhY2ggY29sLiBpZiBhIGNvbCBleGNlZWRzIGl0J3MgbWluL21heCB3aWR0aCxcbiAgICAgICAgICAgIC8vIGl0IHRoZW4gZ2V0cyBzZXQgdG8gaXRzIG1pbi9tYXggd2lkdGggYW5kIHRoZSBjb2x1bW4gaXMgcmVtb3ZlZCBtYXJrZWQgYXMgJ2ZpbmlzaGVkJ1xuICAgICAgICAgICAgLy8gYW5kIHRoZSBjYWxjdWxhdGlvbiBpcyBkb25lIGFnYWluIGxlYXZpbmcgdGhpcyBjb2x1bW4gb3V0LiB0YWtlIGZvciBleGFtcGxlIGNvbHVtbnNcbiAgICAgICAgICAgIC8vIHtBLCB3aWR0aDogNTAsIG1heFdpZHRoOiAxMDB9XG4gICAgICAgICAgICAvLyB7Qiwgd2lkdGg6IDUwfVxuICAgICAgICAgICAgLy8ge0MsIHdpZHRoOiA1MH1cbiAgICAgICAgICAgIC8vIGFuZCB0aGVuIHRoZSBzZXQgaXMgc2V0IHRvIHdpZHRoIDYwMCAtIG9uIHRoZSBmaXJzdCBwYXNzIHRoZSBncmlkIHRyaWVzIHRvIHNldCBlYWNoIGNvbHVtblxuICAgICAgICAgICAgLy8gdG8gMjAwLiBpdCBjaGVja3MgQSBhbmQgc2VlcyAyMDAgPiAxMDAgYW5kIHNvIHNldHMgdGhlIHdpZHRoIHRvIDEwMC4gY29sIEEgaXMgdGhlbiBtYXJrZWRcbiAgICAgICAgICAgIC8vIGFzICdmaW5pc2hlZCcgYW5kIHRoZSBjYWxjdWxhdGlvbiBpcyBkb25lIGFnYWluIHdpdGggdGhlIHJlbWFpbmluZyBjb2xzIEIgYW5kIEMsIHdoaWNoIGVuZCB1cFxuICAgICAgICAgICAgLy8gc3BsaXR0aW5nIHRoZSByZW1haW5pbmcgNTAwIHBpeGVscy5cbiAgICAgICAgICAgIHZhciBmaW5pc2hlZENvbHNHcmV3ID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBsb29wQ291bnQgPSAwO1xuICAgICAgICAgICAgdmFyIF9sb29wXzIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgbG9vcENvdW50Kys7XG4gICAgICAgICAgICAgICAgaWYgKGxvb3BDb3VudCA+IDEwMDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCBidXQgaW4gdGhlIGZ1dHVyZSwgc29tZW9uZSBtaWdodCBpbnRyb2R1Y2UgYSBidWcgaGVyZSxcbiAgICAgICAgICAgICAgICAgICAgLy8gc28gd2Ugc3RvcCB0aGUgYnJvd3NlciBmcm9tIGhhbmdpbmcgYW5kIHJlcG9ydCBidWcgcHJvcGVybHlcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogaW5maW5pdGUgbG9vcCBpbiByZXNpemVDb2x1bW5TZXRzJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImJyZWFrXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpbmlzaGVkQ29sc0dyZXcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgc3Vic2V0Q29scyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzdWJzZXRSYXRpb1RvdGFsID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcGl4ZWxzVG9EaXN0cmlidXRlID0gd2lkdGg7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aGlzQ29sRmluaXNoZWQgPSBmaW5pc2hlZENvbHNbY29sLmdldElkKCldO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpc0NvbEZpbmlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwaXhlbHNUb0Rpc3RyaWJ1dGUgLT0gbmV3V2lkdGhzW2NvbC5nZXRJZCgpXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnNldENvbHMucHVzaChjb2wpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhdGlvVGhpc0NvbCA9IHJhdGlvc1tpbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXRSYXRpb1RvdGFsICs9IHJhdGlvVGhpc0NvbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2Ugd2UgYXJlIG5vdCB1c2luZyBhbGwgb2YgdGhlIHJhdGlvcyAoY29scyBjYW4gYmUgbWlzc2luZyksXG4gICAgICAgICAgICAgICAgLy8gd2Ugc2NhbGUgdGhlIHJhdGlvLiBpZiBhbGwgY29sdW1ucyBhcmUgaW5jbHVkZWQsIHRoZW4gc3Vic2V0UmF0aW9Ub3RhbD0xLFxuICAgICAgICAgICAgICAgIC8vIGFuZCBzbyB0aGUgcmF0aW9TY2FsZSB3aWxsIGJlIDEuXG4gICAgICAgICAgICAgICAgdmFyIHJhdGlvU2NhbGUgPSAxIC8gc3Vic2V0UmF0aW9Ub3RhbDtcbiAgICAgICAgICAgICAgICBzdWJzZXRDb2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxhc3RDb2wgPSBpbmRleCA9PT0gKHN1YnNldENvbHMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb2xOZXdXaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RDb2wpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbE5ld1dpZHRoID0gcGl4ZWxzVG9EaXN0cmlidXRlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sTmV3V2lkdGggPSBNYXRoLnJvdW5kKHJhdGlvc1tpbmRleF0gKiB3aWR0aCAqIHJhdGlvU2NhbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcGl4ZWxzVG9EaXN0cmlidXRlIC09IGNvbE5ld1dpZHRoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBtaW5XaWR0aCA9IGNvbC5nZXRNaW5XaWR0aCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF4V2lkdGggPSBjb2wuZ2V0TWF4V2lkdGgoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4aXN0cyhtaW5XaWR0aCkgJiYgY29sTmV3V2lkdGggPCBtaW5XaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sTmV3V2lkdGggPSBtaW5XaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmlzaGVkQ29sc1tjb2wuZ2V0SWQoKV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmluaXNoZWRDb2xzR3JldyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZXhpc3RzKG1heFdpZHRoKSAmJiBtYXhXaWR0aCA+IDAgJiYgY29sTmV3V2lkdGggPiBtYXhXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sTmV3V2lkdGggPSBtYXhXaWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbmlzaGVkQ29sc1tjb2wuZ2V0SWQoKV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgZmluaXNoZWRDb2xzR3JldyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbmV3V2lkdGhzW2NvbC5nZXRJZCgpXSA9IGNvbE5ld1dpZHRoO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHdoaWxlIChmaW5pc2hlZENvbHNHcmV3KSB7XG4gICAgICAgICAgICAgICAgdmFyIHN0YXRlXzEgPSBfbG9vcF8yKCk7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlXzEgPT09IFwiYnJlYWtcIilcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgIHZhciBuZXdXaWR0aCA9IG5ld1dpZHRoc1tjb2wuZ2V0SWQoKV07XG4gICAgICAgICAgICAgICAgdmFyIGFjdHVhbFdpZHRoID0gY29sLmdldEFjdHVhbFdpZHRoKCk7XG4gICAgICAgICAgICAgICAgaWYgKGFjdHVhbFdpZHRoICE9PSBuZXdXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICBjb2wuc2V0QWN0dWFsV2lkdGgobmV3V2lkdGgsIHNvdXJjZSk7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZWRDb2xzLnB1c2goY29sKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGlmIG5vIGNvbHMgY2hhbmdlZCwgdGhlbiBubyBuZWVkIHRvIHVwZGF0ZSBtb3JlIG9yIHNlbmQgZXZlbnQuXG4gICAgICAgIHZhciBhdExlYXN0T25lQ29sQ2hhbmdlZCA9IGNoYW5nZWRDb2xzLmxlbmd0aCA+IDA7XG4gICAgICAgIHZhciBmbGV4ZWRDb2xzID0gW107XG4gICAgICAgIGlmIChhdExlYXN0T25lQ29sQ2hhbmdlZCkge1xuICAgICAgICAgICAgZmxleGVkQ29scyA9IHRoaXMucmVmcmVzaEZsZXhlZENvbHVtbnMoeyByZXNpemluZ0NvbHM6IGFsbFJlc2l6ZWRDb2xzLCBza2lwU2V0TGVmdDogdHJ1ZSB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0TGVmdFZhbHVlcyhzb3VyY2UpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVCb2R5V2lkdGhzKCk7XG4gICAgICAgICAgICB0aGlzLmNoZWNrVmlld3BvcnRDb2x1bW5zKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2hlY2sgZm9yIGNoYW5nZSBmaXJzdCwgdG8gYXZvaWQgdW5uZWNlc3NhcnkgZmlyaW5nIG9mIGV2ZW50c1xuICAgICAgICAvLyBob3dldmVyIHdlIGFsd2F5cyBmaXJlICdmaW5pc2hlZCcgZXZlbnRzLiB0aGlzIGlzIGltcG9ydGFudFxuICAgICAgICAvLyB3aGVuIGdyb3VwcyBhcmUgcmVzaXplZCwgYXMgaWYgdGhlIGdyb3VwIGlzIGNoYW5naW5nIHNsb3dseSxcbiAgICAgICAgLy8gZWcgMSBwaXhlbCBhdCBhIHRpbWUsIHRoZW4gZWFjaCBjaGFuZ2Ugd2lsbCBmaXJlIGNoYW5nZSBldmVudHNcbiAgICAgICAgLy8gaW4gYWxsIHRoZSBjb2x1bW5zIGluIHRoZSBncm91cCwgYnV0IG9ubHkgb25lIHdpdGggZ2V0IHRoZSBwaXhlbC5cbiAgICAgICAgdmFyIGNvbHNGb3JFdmVudCA9IGFsbFJlc2l6ZWRDb2xzLmNvbmNhdChmbGV4ZWRDb2xzKTtcbiAgICAgICAgaWYgKGF0TGVhc3RPbmVDb2xDaGFuZ2VkIHx8IGZpbmlzaGVkKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmVDb2x1bW5SZXNpemVkRXZlbnQoY29sc0ZvckV2ZW50LCBmaW5pc2hlZCwgc291cmNlLCBmbGV4ZWRDb2xzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldENvbHVtbkFnZ0Z1bmMgPSBmdW5jdGlvbiAoa2V5LCBhZ2dGdW5jLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKCFrZXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5nZXRQcmltYXJ5Q29sdW1uKGtleSk7XG4gICAgICAgIGlmICghY29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29sdW1uLnNldEFnZ0Z1bmMoYWdnRnVuYyk7XG4gICAgICAgIHRoaXMuZmlyZUNvbHVtbkV2ZW50KEV2ZW50cy5FVkVOVF9DT0xVTU5fVkFMVUVfQ0hBTkdFRCwgW2NvbHVtbl0sIHNvdXJjZSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZmlyZUNvbHVtbkV2ZW50ID0gZnVuY3Rpb24gKHR5cGUsIGNvbHVtbnMsIHNvdXJjZSkge1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgY29sdW1uczogY29sdW1ucyxcbiAgICAgICAgICAgIGNvbHVtbjogKGNvbHVtbnMgJiYgY29sdW1ucy5sZW5ndGggPT0gMSkgPyBjb2x1bW5zWzBdIDogbnVsbCxcbiAgICAgICAgICAgIHNvdXJjZTogc291cmNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLm1vdmVSb3dHcm91cENvbHVtbiA9IGZ1bmN0aW9uIChmcm9tSW5kZXgsIHRvSW5kZXgsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5yb3dHcm91cENvbHVtbnNbZnJvbUluZGV4XTtcbiAgICAgICAgdGhpcy5yb3dHcm91cENvbHVtbnMuc3BsaWNlKGZyb21JbmRleCwgMSk7XG4gICAgICAgIHRoaXMucm93R3JvdXBDb2x1bW5zLnNwbGljZSh0b0luZGV4LCAwLCBjb2x1bW4pO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfQ09MVU1OX1JPV19HUk9VUF9DSEFOR0VELFxuICAgICAgICAgICAgY29sdW1uczogdGhpcy5yb3dHcm91cENvbHVtbnMsXG4gICAgICAgICAgICBjb2x1bW46IHRoaXMucm93R3JvdXBDb2x1bW5zLmxlbmd0aCA9PT0gMSA/IHRoaXMucm93R3JvdXBDb2x1bW5zWzBdIDogbnVsbCxcbiAgICAgICAgICAgIHNvdXJjZTogc291cmNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLm1vdmVDb2x1bW5zID0gZnVuY3Rpb24gKGNvbHVtbnNUb01vdmVLZXlzLCB0b0luZGV4LCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy5jb2x1bW5BbmltYXRpb25TZXJ2aWNlLnN0YXJ0KCk7XG4gICAgICAgIGlmICh0b0luZGV4ID4gdGhpcy5ncmlkQ29sdW1ucy5sZW5ndGggLSBjb2x1bW5zVG9Nb3ZlS2V5cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogdHJpZWQgdG8gaW5zZXJ0IGNvbHVtbnMgaW4gaW52YWxpZCBsb2NhdGlvbiwgdG9JbmRleCA9ICcgKyB0b0luZGV4KTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogcmVtZW1iZXIgdGhhdCB5b3Ugc2hvdWxkIG5vdCBjb3VudCB0aGUgbW92aW5nIGNvbHVtbnMgd2hlbiBjYWxjdWxhdGluZyB0aGUgbmV3IGluZGV4Jyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2Ugd2FudCB0byBwdWxsIGFsbCB0aGUgY29sdW1ucyBvdXQgZmlyc3QgYW5kIHB1dCB0aGVtIGludG8gYW4gb3JkZXJlZCBsaXN0XG4gICAgICAgIHZhciBjb2x1bW5zVG9Nb3ZlID0gdGhpcy5nZXRHcmlkQ29sdW1ucyhjb2x1bW5zVG9Nb3ZlS2V5cyk7XG4gICAgICAgIHZhciBmYWlsZWRSdWxlcyA9ICF0aGlzLmRvZXNNb3ZlUGFzc1J1bGVzKGNvbHVtbnNUb01vdmUsIHRvSW5kZXgpO1xuICAgICAgICBpZiAoZmFpbGVkUnVsZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBtb3ZlSW5BcnJheSh0aGlzLmdyaWRDb2x1bW5zLCBjb2x1bW5zVG9Nb3ZlLCB0b0luZGV4KTtcbiAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5ZWRDb2x1bW5zKHNvdXJjZSk7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQsXG4gICAgICAgICAgICBjb2x1bW5zOiBjb2x1bW5zVG9Nb3ZlLFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW5zVG9Nb3ZlLmxlbmd0aCA9PT0gMSA/IGNvbHVtbnNUb01vdmVbMF0gOiBudWxsLFxuICAgICAgICAgICAgdG9JbmRleDogdG9JbmRleCxcbiAgICAgICAgICAgIHNvdXJjZTogc291cmNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICB0aGlzLmNvbHVtbkFuaW1hdGlvblNlcnZpY2UuZmluaXNoKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZG9lc01vdmVQYXNzUnVsZXMgPSBmdW5jdGlvbiAoY29sdW1uc1RvTW92ZSwgdG9JbmRleCkge1xuICAgICAgICAvLyBtYWtlIGEgY29weSBvZiB3aGF0IHRoZSBncmlkIGNvbHVtbnMgd291bGQgbG9vayBsaWtlIGFmdGVyIHRoZSBtb3ZlXG4gICAgICAgIHZhciBwcm9wb3NlZENvbHVtbk9yZGVyID0gdGhpcy5nZXRQcm9wb3NlZENvbHVtbk9yZGVyKGNvbHVtbnNUb01vdmUsIHRvSW5kZXgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kb2VzT3JkZXJQYXNzUnVsZXMocHJvcG9zZWRDb2x1bW5PcmRlcik7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZG9lc09yZGVyUGFzc1J1bGVzID0gZnVuY3Rpb24gKGdyaWRPcmRlcikge1xuICAgICAgICBpZiAoIXRoaXMuZG9lc01vdmVQYXNzTWFycnlDaGlsZHJlbihncmlkT3JkZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmRvZXNNb3ZlUGFzc0xvY2tlZFBvc2l0aW9ucyhncmlkT3JkZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0UHJvcG9zZWRDb2x1bW5PcmRlciA9IGZ1bmN0aW9uIChjb2x1bW5zVG9Nb3ZlLCB0b0luZGV4KSB7XG4gICAgICAgIHZhciBwcm9wb3NlZENvbHVtbk9yZGVyID0gdGhpcy5ncmlkQ29sdW1ucy5zbGljZSgpO1xuICAgICAgICBtb3ZlSW5BcnJheShwcm9wb3NlZENvbHVtbk9yZGVyLCBjb2x1bW5zVG9Nb3ZlLCB0b0luZGV4KTtcbiAgICAgICAgcmV0dXJuIHByb3Bvc2VkQ29sdW1uT3JkZXI7XG4gICAgfTtcbiAgICAvLyByZXR1cm5zIHRoZSBwcm92aWRlZCBjb2xzIHNvcnRlZCBpbiBzYW1lIG9yZGVyIGFzIHRoZXkgYXBwZWFyIGluIGdyaWQgY29sdW1ucy4gZWcgaWYgZ3JpZCBjb2x1bW5zXG4gICAgLy8gY29udGFpbnMgW2EsYixjLGQsZV0gYW5kIGNvbCBwYXNzZWQgaXMgW2UsYV0gdGhlbiB0aGUgcGFzc2VkIGNvbHMgYXJlIHNvcnRlZCBpbnRvIFthLGVdXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNvcnRDb2x1bW5zTGlrZUdyaWRDb2x1bW5zID0gZnVuY3Rpb24gKGNvbHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFjb2xzIHx8IGNvbHMubGVuZ3RoIDw9IDEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbm90QWxsQ29sc0luR3JpZENvbHVtbnMgPSBjb2xzLmZpbHRlcihmdW5jdGlvbiAoYykgeyByZXR1cm4gX3RoaXMuZ3JpZENvbHVtbnMuaW5kZXhPZihjKSA8IDA7IH0pLmxlbmd0aCA+IDA7XG4gICAgICAgIGlmIChub3RBbGxDb2xzSW5HcmlkQ29sdW1ucykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgdmFyIGluZGV4QSA9IF90aGlzLmdyaWRDb2x1bW5zLmluZGV4T2YoYSk7XG4gICAgICAgICAgICB2YXIgaW5kZXhCID0gX3RoaXMuZ3JpZENvbHVtbnMuaW5kZXhPZihiKTtcbiAgICAgICAgICAgIHJldHVybiBpbmRleEEgLSBpbmRleEI7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmRvZXNNb3ZlUGFzc0xvY2tlZFBvc2l0aW9ucyA9IGZ1bmN0aW9uIChwcm9wb3NlZENvbHVtbk9yZGVyKSB7XG4gICAgICAgIC8vIFBsYWNlbWVudCBpcyBhIG51bWJlciBpbmRpY2F0aW5nICdsZWZ0JyAnY2VudGVyJyBvciAncmlnaHQnIGFzIDAgMSAyXG4gICAgICAgIHZhciBsYXN0UGxhY2VtZW50ID0gMDtcbiAgICAgICAgdmFyIHJ1bGVQYXNzZWQgPSB0cnVlO1xuICAgICAgICB2YXIgbG9ja1Bvc2l0aW9uVG9QbGFjZW1lbnQgPSBmdW5jdGlvbiAocG9zaXRpb24pIHtcbiAgICAgICAgICAgIGlmICghcG9zaXRpb24pIHsgLy8gZmFsc2Ugb3IgdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwb3NpdGlvbiA9PT0gJ2xlZnQnID8gMCA6IDI7IC8vIE90aGVyd2lzZSAncmlnaHQnXG4gICAgICAgIH07XG4gICAgICAgIHByb3Bvc2VkQ29sdW1uT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICB2YXIgcGxhY2VtZW50ID0gbG9ja1Bvc2l0aW9uVG9QbGFjZW1lbnQoY29sLmdldENvbERlZigpLmxvY2tQb3NpdGlvbik7XG4gICAgICAgICAgICBpZiAocGxhY2VtZW50IDwgbGFzdFBsYWNlbWVudCkgeyAvLyBJZiBwbGFjZW1lbnQgZ29lcyBkb3duLCB3ZSdyZSBub3QgaW4gdGhlIGNvcnJlY3Qgb3JkZXJcbiAgICAgICAgICAgICAgICBydWxlUGFzc2VkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0UGxhY2VtZW50ID0gcGxhY2VtZW50O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJ1bGVQYXNzZWQ7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZG9lc01vdmVQYXNzTWFycnlDaGlsZHJlbiA9IGZ1bmN0aW9uIChhbGxDb2x1bW5zQ29weSkge1xuICAgICAgICB2YXIgcnVsZVBhc3NlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuY29sdW1uVXRpbHMuZGVwdGhGaXJzdE9yaWdpbmFsVHJlZVNlYXJjaChudWxsLCB0aGlzLmdyaWRCYWxhbmNlZFRyZWUsIGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgICAgICAgaWYgKCEoY2hpbGQgaW5zdGFuY2VvZiBQcm92aWRlZENvbHVtbkdyb3VwKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjb2x1bW5Hcm91cCA9IGNoaWxkO1xuICAgICAgICAgICAgdmFyIGNvbEdyb3VwRGVmID0gY29sdW1uR3JvdXAuZ2V0Q29sR3JvdXBEZWYoKTtcbiAgICAgICAgICAgIHZhciBtYXJyeUNoaWxkcmVuID0gY29sR3JvdXBEZWYgJiYgY29sR3JvdXBEZWYubWFycnlDaGlsZHJlbjtcbiAgICAgICAgICAgIGlmICghbWFycnlDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBuZXdJbmRleGVzID0gW107XG4gICAgICAgICAgICBjb2x1bW5Hcm91cC5nZXRMZWFmQ29sdW1ucygpLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgIHZhciBuZXdDb2xJbmRleCA9IGFsbENvbHVtbnNDb3B5LmluZGV4T2YoY29sKTtcbiAgICAgICAgICAgICAgICBuZXdJbmRleGVzLnB1c2gobmV3Q29sSW5kZXgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBNYXRoLm1heC5hcHBseShNYXRoLCBuZXdJbmRleGVzKTtcbiAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IE1hdGgubWluLmFwcGx5KE1hdGgsIG5ld0luZGV4ZXMpO1xuICAgICAgICAgICAgLy8gc3ByZWFkIGlzIGhvdyBmYXIgdGhlIGZpcnN0IGNvbHVtbiBpbiB0aGlzIGdyb3VwIGlzIGF3YXkgZnJvbSB0aGUgbGFzdCBjb2x1bW5cbiAgICAgICAgICAgIHZhciBzcHJlYWQgPSBtYXhJbmRleCAtIG1pbkluZGV4O1xuICAgICAgICAgICAgdmFyIG1heFNwcmVhZCA9IGNvbHVtbkdyb3VwLmdldExlYWZDb2x1bW5zKCkubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIC8vIGlmIHRoZSBjb2x1bW5zXG4gICAgICAgICAgICBpZiAoc3ByZWFkID4gbWF4U3ByZWFkKSB7XG4gICAgICAgICAgICAgICAgcnVsZVBhc3NlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYG1heEluZGV4ID0gJHttYXhJbmRleH0sIG1pbkluZGV4ID0gJHttaW5JbmRleH0sIHNwcmVhZCA9ICR7c3ByZWFkfSwgbWF4U3ByZWFkID0gJHttYXhTcHJlYWR9LCBmYWlsID0gJHtzcHJlYWQgPiAoY291bnQtMSl9YClcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKGFsbENvbHVtbnNDb3B5Lm1hcCggY29sID0+IGNvbC5nZXRDb2xEZWYoKS5maWVsZCkuam9pbignLCcpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBydWxlUGFzc2VkO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLm1vdmVDb2x1bW4gPSBmdW5jdGlvbiAoa2V5LCB0b0luZGV4LCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdGhpcy5tb3ZlQ29sdW1ucyhba2V5XSwgdG9JbmRleCwgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5tb3ZlQ29sdW1uQnlJbmRleCA9IGZ1bmN0aW9uIChmcm9tSW5kZXgsIHRvSW5kZXgsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5ncmlkQ29sdW1uc1tmcm9tSW5kZXhdO1xuICAgICAgICB0aGlzLm1vdmVDb2x1bW4oY29sdW1uLCB0b0luZGV4LCBzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldENvbHVtbkRlZnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5wcmltYXJ5Q29sdW1ucykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2xzID0gdGhpcy5wcmltYXJ5Q29sdW1ucy5zbGljZSgpO1xuICAgICAgICBpZiAodGhpcy5ncmlkQ29sc0FyZVByaW1hcnkpIHtcbiAgICAgICAgICAgIGNvbHMuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gX3RoaXMuZ3JpZENvbHVtbnMuaW5kZXhPZihhKSAtIF90aGlzLmdyaWRDb2x1bW5zLmluZGV4T2YoYik7IH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMubGFzdFByaW1hcnlPcmRlcikge1xuICAgICAgICAgICAgY29scy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBfdGhpcy5sYXN0UHJpbWFyeU9yZGVyLmluZGV4T2YoYSkgLSBfdGhpcy5sYXN0UHJpbWFyeU9yZGVyLmluZGV4T2YoYik7IH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbHVtbkRlZkZhY3RvcnkuYnVpbGRDb2x1bW5EZWZzKGNvbHMsIHRoaXMucm93R3JvdXBDb2x1bW5zLCB0aGlzLnBpdm90Q29sdW1ucyk7XG4gICAgfTtcbiAgICAvLyB1c2VkIGJ5OlxuICAgIC8vICsgYW5ndWxhckdyaWQgLT4gZm9yIHNldHRpbmcgYm9keSB3aWR0aFxuICAgIC8vICsgcm93Q29udHJvbGxlciAtPiBzZXR0aW5nIG1haW4gcm93IHdpZHRocyAod2hlbiBpbnNlcnRpbmcgYW5kIHJlc2l6aW5nKVxuICAgIC8vIG5lZWQgdG8gY2FjaGUgdGhpc1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRCb2R5Q29udGFpbmVyV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvZHlXaWR0aDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRDb250YWluZXJXaWR0aCA9IGZ1bmN0aW9uIChwaW5uZWQpIHtcbiAgICAgICAgc3dpdGNoIChwaW5uZWQpIHtcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9MRUZUOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxlZnRXaWR0aDtcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yaWdodFdpZHRoO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5ib2R5V2lkdGg7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGFmdGVyIHNldENvbHVtbldpZHRoIG9yIHVwZGF0ZUdyb3Vwc0FuZERpc3BsYXllZENvbHVtbnNcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUudXBkYXRlQm9keVdpZHRocyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5ld0JvZHlXaWR0aCA9IHRoaXMuZ2V0V2lkdGhPZkNvbHNJbkxpc3QodGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyKTtcbiAgICAgICAgdmFyIG5ld0xlZnRXaWR0aCA9IHRoaXMuZ2V0V2lkdGhPZkNvbHNJbkxpc3QodGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdCk7XG4gICAgICAgIHZhciBuZXdSaWdodFdpZHRoID0gdGhpcy5nZXRXaWR0aE9mQ29sc0luTGlzdCh0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodCk7XG4gICAgICAgIC8vIHRoaXMgaXMgdXNlZCBieSB2aXJ0dWFsIGNvbCBjYWxjdWxhdGlvbiwgZm9yIFJUTCBvbmx5LCBhcyBhIGNoYW5nZSB0byBib2R5IHdpZHRoIGNhbiBpbXBhY3QgZGlzcGxheWVkXG4gICAgICAgIC8vIGNvbHVtbnMsIGR1ZSB0byBSVEwgaW52ZXJ0aW5nIHRoZSB5IGNvb3JkaW5hdGVzXG4gICAgICAgIHRoaXMuYm9keVdpZHRoRGlydHkgPSB0aGlzLmJvZHlXaWR0aCAhPT0gbmV3Qm9keVdpZHRoO1xuICAgICAgICB2YXIgYXRMZWFzdE9uZUNoYW5nZWQgPSB0aGlzLmJvZHlXaWR0aCAhPT0gbmV3Qm9keVdpZHRoIHx8IHRoaXMubGVmdFdpZHRoICE9PSBuZXdMZWZ0V2lkdGggfHwgdGhpcy5yaWdodFdpZHRoICE9PSBuZXdSaWdodFdpZHRoO1xuICAgICAgICBpZiAoYXRMZWFzdE9uZUNoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYm9keVdpZHRoID0gbmV3Qm9keVdpZHRoO1xuICAgICAgICAgICAgdGhpcy5sZWZ0V2lkdGggPSBuZXdMZWZ0V2lkdGg7XG4gICAgICAgICAgICB0aGlzLnJpZ2h0V2lkdGggPSBuZXdSaWdodFdpZHRoO1xuICAgICAgICAgICAgLy8gd2hlbiB0aGlzIGZpcmVzLCBpdCBpcyBwaWNrZWQgdXAgYnkgdGhlIGdyaWRQYW5lbCwgd2hpY2ggZW5kcyB1cCBpblxuICAgICAgICAgICAgLy8gZ3JpZFBhbmVsIGNhbGxpbmcgc2V0V2lkdGhBbmRTY3JvbGxQb3NpdGlvbigpLCB3aGljaCBpbiB0dXJuIGNhbGxzIHNldFZpZXdwb3J0UG9zaXRpb24oKVxuICAgICAgICAgICAgdmFyIGV2ZW50XzIgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX1dJRFRIX0NIQU5HRUQsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8yKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gKyByb3dDb250cm9sbGVyXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldFZhbHVlQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVDb2x1bW5zID8gdGhpcy52YWx1ZUNvbHVtbnMgOiBbXTtcbiAgICB9O1xuICAgIC8vICsgcm93Q29udHJvbGxlclxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRQaXZvdENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpdm90Q29sdW1ucyA/IHRoaXMucGl2b3RDb2x1bW5zIDogW107XG4gICAgfTtcbiAgICAvLyArIGNsaWVudFNpZGVSb3dNb2RlbFxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5pc1Bpdm90QWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waXZvdENvbHVtbnMgJiYgdGhpcy5waXZvdENvbHVtbnMubGVuZ3RoID4gMCAmJiB0aGlzLnBpdm90TW9kZTtcbiAgICB9O1xuICAgIC8vICsgdG9vbFBhbmVsXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldFJvd0dyb3VwQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93R3JvdXBDb2x1bW5zID8gdGhpcy5yb3dHcm91cENvbHVtbnMgOiBbXTtcbiAgICB9O1xuICAgIC8vICsgcm93Q29udHJvbGxlciAtPiB3aGlsZSBpbnNlcnRpbmcgcm93c1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRDZW50ZXJDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyO1xuICAgIH07XG4gICAgLy8gKyByb3dDb250cm9sbGVyIC0+IHdoaWxlIGluc2VydGluZyByb3dzXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldERpc3BsYXllZExlZnRDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRSaWdodENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRDb2x1bW5zID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfTEVGVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXREaXNwbGF5ZWRMZWZ0Q29sdW1ucygpO1xuICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX1JJR0hUOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldERpc3BsYXllZFJpZ2h0Q29sdW1ucygpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXREaXNwbGF5ZWRDZW50ZXJDb2x1bW5zKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHVzZWQgYnk6XG4gICAgLy8gKyBjbGllbnRTaWRlUm93Q29udHJvbGxlciAtPiBzb3J0aW5nLCBidWlsZGluZyBxdWljayBmaWx0ZXIgdGV4dFxuICAgIC8vICsgaGVhZGVyUmVuZGVyZXIgLT4gc29ydGluZyAoY2xlYXJpbmcgaWNvbilcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0QWxsUHJpbWFyeUNvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW1hcnlDb2x1bW5zID8gdGhpcy5wcmltYXJ5Q29sdW1ucy5zbGljZSgpIDogbnVsbDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRTZWNvbmRhcnlDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWNvbmRhcnlDb2x1bW5zID8gdGhpcy5zZWNvbmRhcnlDb2x1bW5zLnNsaWNlKCkgOiBudWxsO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldEFsbENvbHVtbnNGb3JRdWlja0ZpbHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uc0ZvclF1aWNrRmlsdGVyO1xuICAgIH07XG4gICAgLy8gKyBtb3ZlQ29sdW1uQ29udHJvbGxlclxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRBbGxHcmlkQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZENvbHVtbnM7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuaXNFbXB0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG1pc3NpbmdPckVtcHR5KHRoaXMuZ3JpZENvbHVtbnMpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmlzUm93R3JvdXBFbXB0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG1pc3NpbmdPckVtcHR5KHRoaXMucm93R3JvdXBDb2x1bW5zKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXRDb2x1bW5WaXNpYmxlID0gZnVuY3Rpb24gKGtleSwgdmlzaWJsZSwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMuc2V0Q29sdW1uc1Zpc2libGUoW2tleV0sIHZpc2libGUsIHNvdXJjZSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0Q29sdW1uc1Zpc2libGUgPSBmdW5jdGlvbiAoa2V5cywgdmlzaWJsZSwgc291cmNlKSB7XG4gICAgICAgIGlmICh2aXNpYmxlID09PSB2b2lkIDApIHsgdmlzaWJsZSA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMuYXBwbHlDb2x1bW5TdGF0ZSh7XG4gICAgICAgICAgICBzdGF0ZToga2V5cy5tYXAoZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gKHtcbiAgICAgICAgICAgICAgICBjb2xJZDogdHlwZW9mIGtleSA9PT0gJ3N0cmluZycgPyBrZXkgOiBrZXkuZ2V0Q29sSWQoKSxcbiAgICAgICAgICAgICAgICBoaWRlOiAhdmlzaWJsZSxcbiAgICAgICAgICAgIH0pOyB9KSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0Q29sdW1uUGlubmVkID0gZnVuY3Rpb24gKGtleSwgcGlubmVkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgdGhpcy5zZXRDb2x1bW5zUGlubmVkKFtrZXldLCBwaW5uZWQsIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXRDb2x1bW5zUGlubmVkID0gZnVuY3Rpb24gKGtleXMsIHBpbm5lZCwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21MYXlvdXQoKSA9PT0gJ3ByaW50Jykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQ2hhbmdpbmcgdGhlIGNvbHVtbiBwaW5uaW5nIHN0YXR1cyBpcyBub3QgYWxsb3dlZCB3aXRoIGRvbUxheW91dD0ncHJpbnQnXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29sdW1uQW5pbWF0aW9uU2VydmljZS5zdGFydCgpO1xuICAgICAgICB2YXIgYWN0dWFsUGlubmVkO1xuICAgICAgICBpZiAocGlubmVkID09PSB0cnVlIHx8IHBpbm5lZCA9PT0gQ29uc3RhbnRzLlBJTk5FRF9MRUZUKSB7XG4gICAgICAgICAgICBhY3R1YWxQaW5uZWQgPSBDb25zdGFudHMuUElOTkVEX0xFRlQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX1JJR0hUKSB7XG4gICAgICAgICAgICBhY3R1YWxQaW5uZWQgPSBDb25zdGFudHMuUElOTkVEX1JJR0hUO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYWN0dWFsUGlubmVkID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdGlvbk9uR3JpZENvbHVtbnMoa2V5cywgZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgaWYgKGNvbC5nZXRQaW5uZWQoKSAhPT0gYWN0dWFsUGlubmVkKSB7XG4gICAgICAgICAgICAgICAgY29sLnNldFBpbm5lZChhY3R1YWxQaW5uZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9LCBzb3VyY2UsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfQ09MVU1OX1BJTk5FRCxcbiAgICAgICAgICAgICAgICBwaW5uZWQ6IGFjdHVhbFBpbm5lZCxcbiAgICAgICAgICAgICAgICBjb2x1bW46IG51bGwsXG4gICAgICAgICAgICAgICAgY29sdW1uczogbnVsbCxcbiAgICAgICAgICAgICAgICBzb3VyY2U6IHNvdXJjZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiBldmVudDtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY29sdW1uQW5pbWF0aW9uU2VydmljZS5maW5pc2goKTtcbiAgICB9O1xuICAgIC8vIGRvZXMgYW4gYWN0aW9uIG9uIGEgc2V0IG9mIGNvbHVtbnMuIHByb3ZpZGVzIGNvbW1vbiBmdW5jdGlvbmFsaXR5IGZvciBsb29raW5nIHVwIHRoZVxuICAgIC8vIGNvbHVtbnMgYmFzZWQgb24ga2V5LCBnZXR0aW5nIGEgbGlzdCBvZiBlZmZlY3RlZCBjb2x1bW5zLCBhbmQgdGhlbiB1cGRhdGVkIHRoZSBldmVudFxuICAgIC8vIHdpdGggZWl0aGVyIG9uZSBjb2x1bW4gKGlmIGl0IHdhcyBqdXN0IG9uZSBjb2wpIG9yIGEgbGlzdCBvZiBjb2x1bW5zXG4gICAgLy8gdXNlZCBieTogYXV0b1Jlc2l6ZSwgc2V0VmlzaWJsZSwgc2V0UGlubmVkXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmFjdGlvbk9uR3JpZENvbHVtbnMgPSBmdW5jdGlvbiAoLy8gdGhlIGNvbHVtbiBrZXlzIHRoaXMgYWN0aW9uIHdpbGwgYmUgb25cbiAgICBrZXlzLCBcbiAgICAvLyB0aGUgYWN0aW9uIHRvIGRvIC0gaWYgdGhpcyByZXR1cm5zIGZhbHNlLCB0aGUgY29sdW1uIHdhcyBza2lwcGVkXG4gICAgLy8gYW5kIHdvbid0IGJlIGluY2x1ZGVkIGluIHRoZSBldmVudFxuICAgIGFjdGlvbiwgXG4gICAgLy8gc2hvdWxkIHJldHVybiBiYWNrIGEgY29sdW1uIGV2ZW50IG9mIHRoZSByaWdodCB0eXBlXG4gICAgc291cmNlLCBjcmVhdGVFdmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAobWlzc2luZ09yRW1wdHkoa2V5cykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXBkYXRlZENvbHVtbnMgPSBbXTtcbiAgICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpcy5nZXRHcmlkQ29sdW1uKGtleSk7XG4gICAgICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG5lZWQgdG8gY2hlY2sgZm9yIGZhbHNlIHdpdGggdHlwZSAoaWUgIT09IGluc3RlYWQgb2YgIT0pXG4gICAgICAgICAgICAvLyBhcyBub3QgcmV0dXJuaW5nIGFueXRoaW5nICh1bmRlZmluZWQpIHdvdWxkIGFsc28gYmUgZmFsc2VcbiAgICAgICAgICAgIHZhciByZXN1bHRPZkFjdGlvbiA9IGFjdGlvbihjb2x1bW4pO1xuICAgICAgICAgICAgaWYgKHJlc3VsdE9mQWN0aW9uICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIHVwZGF0ZWRDb2x1bW5zLnB1c2goY29sdW1uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghdXBkYXRlZENvbHVtbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVEaXNwbGF5ZWRDb2x1bW5zKHNvdXJjZSk7XG4gICAgICAgIGlmIChleGlzdHMoY3JlYXRlRXZlbnQpICYmIGNyZWF0ZUV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgZXZlbnRfMyA9IGNyZWF0ZUV2ZW50KCk7XG4gICAgICAgICAgICBldmVudF8zLmNvbHVtbnMgPSB1cGRhdGVkQ29sdW1ucztcbiAgICAgICAgICAgIGV2ZW50XzMuY29sdW1uID0gdXBkYXRlZENvbHVtbnMubGVuZ3RoID09PSAxID8gdXBkYXRlZENvbHVtbnNbMF0gOiBudWxsO1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8zKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldERpc3BsYXllZENvbEJlZm9yZSA9IGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgdmFyIGFsbERpc3BsYXllZENvbHVtbnMgPSB0aGlzLmdldEFsbERpc3BsYXllZENvbHVtbnMoKTtcbiAgICAgICAgdmFyIG9sZEluZGV4ID0gYWxsRGlzcGxheWVkQ29sdW1ucy5pbmRleE9mKGNvbCk7XG4gICAgICAgIGlmIChvbGRJbmRleCA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiBhbGxEaXNwbGF5ZWRDb2x1bW5zW29sZEluZGV4IC0gMV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvLyB1c2VkIGJ5OlxuICAgIC8vICsgcm93UmVuZGVyZXIgLT4gZm9yIG5hdmlnYXRpb25cbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0RGlzcGxheWVkQ29sQWZ0ZXIgPSBmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgIHZhciBhbGxEaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7XG4gICAgICAgIHZhciBvbGRJbmRleCA9IGFsbERpc3BsYXllZENvbHVtbnMuaW5kZXhPZihjb2wpO1xuICAgICAgICBpZiAob2xkSW5kZXggPCAoYWxsRGlzcGxheWVkQ29sdW1ucy5sZW5ndGggLSAxKSkge1xuICAgICAgICAgICAgcmV0dXJuIGFsbERpc3BsYXllZENvbHVtbnNbb2xkSW5kZXggKyAxXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRHcm91cEFmdGVyID0gZnVuY3Rpb24gKGNvbHVtbkdyb3VwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldERpc3BsYXllZEdyb3VwQXREaXJlY3Rpb24oY29sdW1uR3JvdXAsICdBZnRlcicpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldERpc3BsYXllZEdyb3VwQmVmb3JlID0gZnVuY3Rpb24gKGNvbHVtbkdyb3VwKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldERpc3BsYXllZEdyb3VwQXREaXJlY3Rpb24oY29sdW1uR3JvdXAsICdCZWZvcmUnKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRHcm91cEF0RGlyZWN0aW9uID0gZnVuY3Rpb24gKGNvbHVtbkdyb3VwLCBkaXJlY3Rpb24pIHtcbiAgICAgICAgLy8gcGljayB0aGUgbGFzdCBkaXNwbGF5ZWQgY29sdW1uIGluIHRoaXMgZ3JvdXBcbiAgICAgICAgdmFyIHJlcXVpcmVkTGV2ZWwgPSBjb2x1bW5Hcm91cC5nZXRQcm92aWRlZENvbHVtbkdyb3VwKCkuZ2V0TGV2ZWwoKSArIGNvbHVtbkdyb3VwLmdldFBhZGRpbmdMZXZlbCgpO1xuICAgICAgICB2YXIgY29sR3JvdXBMZWFmQ29sdW1ucyA9IGNvbHVtbkdyb3VwLmdldERpc3BsYXllZExlYWZDb2x1bW5zKCk7XG4gICAgICAgIHZhciBjb2wgPSBkaXJlY3Rpb24gPT09ICdBZnRlcicgPyBsYXN0KGNvbEdyb3VwTGVhZkNvbHVtbnMpIDogY29sR3JvdXBMZWFmQ29sdW1uc1swXTtcbiAgICAgICAgdmFyIGdldERpc3BsYXlDb2xNZXRob2QgPSBcImdldERpc3BsYXllZENvbFwiICsgZGlyZWN0aW9uO1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgLy8ga2VlcCBtb3ZpbmcgdG8gdGhlIG5leHQgY29sLCB1bnRpbCB3ZSBnZXQgdG8gYW5vdGhlciBncm91cFxuICAgICAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXNbZ2V0RGlzcGxheUNvbE1ldGhvZF0oY29sKTtcbiAgICAgICAgICAgIGlmICghY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZ3JvdXBQb2ludGVyID0gdGhpcy5nZXRDb2x1bW5Hcm91cEF0TGV2ZWwoY29sdW1uLCByZXF1aXJlZExldmVsKTtcbiAgICAgICAgICAgIGlmIChncm91cFBvaW50ZXIgIT09IGNvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdyb3VwUG9pbnRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldENvbHVtbkdyb3VwQXRMZXZlbCA9IGZ1bmN0aW9uIChjb2x1bW4sIGxldmVsKSB7XG4gICAgICAgIC8vIGdldCBncm91cCBhdCBzYW1lIGxldmVsIGFzIHRoZSBvbmUgd2UgYXJlIGxvb2tpbmcgZm9yXG4gICAgICAgIHZhciBncm91cFBvaW50ZXIgPSBjb2x1bW4uZ2V0UGFyZW50KCk7XG4gICAgICAgIHZhciBvcmlnaW5hbEdyb3VwTGV2ZWw7XG4gICAgICAgIHZhciBncm91cFBvaW50ZXJMZXZlbDtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgIHZhciBncm91cFBvaW50ZXJQcm92aWRlZENvbHVtbkdyb3VwID0gZ3JvdXBQb2ludGVyLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoKTtcbiAgICAgICAgICAgIG9yaWdpbmFsR3JvdXBMZXZlbCA9IGdyb3VwUG9pbnRlclByb3ZpZGVkQ29sdW1uR3JvdXAuZ2V0TGV2ZWwoKTtcbiAgICAgICAgICAgIGdyb3VwUG9pbnRlckxldmVsID0gZ3JvdXBQb2ludGVyLmdldFBhZGRpbmdMZXZlbCgpO1xuICAgICAgICAgICAgaWYgKG9yaWdpbmFsR3JvdXBMZXZlbCArIGdyb3VwUG9pbnRlckxldmVsIDw9IGxldmVsKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBncm91cFBvaW50ZXIgPSBncm91cFBvaW50ZXIuZ2V0UGFyZW50KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdyb3VwUG9pbnRlcjtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5pc1Bpbm5pbmdMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdC5sZW5ndGggPiAwO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmlzUGlubmluZ1JpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zUmlnaHQubGVuZ3RoID4gMDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5QW5kQXV0b0NvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgcmV0dXJuIChfYSA9IFtdKS5jb25jYXQuYXBwbHkoX2EsIF9fc3ByZWFkJGYoW1xuICAgICAgICAgICAgdGhpcy5wcmltYXJ5Q29sdW1ucyB8fCBbXSxcbiAgICAgICAgICAgIHRoaXMuZ3JvdXBBdXRvQ29sdW1ucyB8fCBbXSxcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5Q29sdW1ucyB8fCBbXSxcbiAgICAgICAgXSkpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldFByaW1hcnlBbmRBdXRvR3JvdXBDb2xzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHJldHVybiAoX2EgPSBbXSkuY29uY2F0LmFwcGx5KF9hLCBfX3NwcmVhZCRmKFtcbiAgICAgICAgICAgIHRoaXMucHJpbWFyeUNvbHVtbnMgfHwgW10sXG4gICAgICAgICAgICB0aGlzLmdyb3VwQXV0b0NvbHVtbnMgfHwgW10sXG4gICAgICAgIF0pKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5Q29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICByZXR1cm4gKF9hID0gW10pLmNvbmNhdC5hcHBseShfYSwgX19zcHJlYWQkZihbXG4gICAgICAgICAgICB0aGlzLnByaW1hcnlDb2x1bW5zIHx8IFtdLFxuICAgICAgICAgICAgdGhpcy5zZWNvbmRhcnlDb2x1bW5zIHx8IFtdLFxuICAgICAgICBdKSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuY3JlYXRlU3RhdGVJdGVtRnJvbUNvbHVtbiA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgdmFyIHJvd0dyb3VwSW5kZXggPSBjb2x1bW4uaXNSb3dHcm91cEFjdGl2ZSgpID8gdGhpcy5yb3dHcm91cENvbHVtbnMuaW5kZXhPZihjb2x1bW4pIDogbnVsbDtcbiAgICAgICAgdmFyIHBpdm90SW5kZXggPSBjb2x1bW4uaXNQaXZvdEFjdGl2ZSgpID8gdGhpcy5waXZvdENvbHVtbnMuaW5kZXhPZihjb2x1bW4pIDogbnVsbDtcbiAgICAgICAgdmFyIGFnZ0Z1bmMgPSBjb2x1bW4uaXNWYWx1ZUFjdGl2ZSgpID8gY29sdW1uLmdldEFnZ0Z1bmMoKSA6IG51bGw7XG4gICAgICAgIHZhciBzb3J0ID0gY29sdW1uLmdldFNvcnQoKSAhPSBudWxsID8gY29sdW1uLmdldFNvcnQoKSA6IG51bGw7XG4gICAgICAgIHZhciBzb3J0SW5kZXggPSBjb2x1bW4uZ2V0U29ydEluZGV4KCkgIT0gbnVsbCA/IGNvbHVtbi5nZXRTb3J0SW5kZXgoKSA6IG51bGw7XG4gICAgICAgIHZhciBmbGV4ID0gY29sdW1uLmdldEZsZXgoKSAhPSBudWxsICYmIGNvbHVtbi5nZXRGbGV4KCkgPiAwID8gY29sdW1uLmdldEZsZXgoKSA6IG51bGw7XG4gICAgICAgIHZhciByZXMgPSB7XG4gICAgICAgICAgICBjb2xJZDogY29sdW1uLmdldENvbElkKCksXG4gICAgICAgICAgICB3aWR0aDogY29sdW1uLmdldEFjdHVhbFdpZHRoKCksXG4gICAgICAgICAgICBoaWRlOiAhY29sdW1uLmlzVmlzaWJsZSgpLFxuICAgICAgICAgICAgcGlubmVkOiBjb2x1bW4uZ2V0UGlubmVkKCksXG4gICAgICAgICAgICBzb3J0OiBzb3J0LFxuICAgICAgICAgICAgc29ydEluZGV4OiBzb3J0SW5kZXgsXG4gICAgICAgICAgICBhZ2dGdW5jOiBhZ2dGdW5jLFxuICAgICAgICAgICAgcm93R3JvdXA6IGNvbHVtbi5pc1Jvd0dyb3VwQWN0aXZlKCksXG4gICAgICAgICAgICByb3dHcm91cEluZGV4OiByb3dHcm91cEluZGV4LFxuICAgICAgICAgICAgcGl2b3Q6IGNvbHVtbi5pc1Bpdm90QWN0aXZlKCksXG4gICAgICAgICAgICBwaXZvdEluZGV4OiBwaXZvdEluZGV4LFxuICAgICAgICAgICAgZmxleDogZmxleFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldENvbHVtblN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAobWlzc2luZyh0aGlzLnByaW1hcnlDb2x1bW5zKSB8fCAhdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sc0ZvclN0YXRlID0gdGhpcy5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5QW5kQXV0b0NvbHVtbnMoKTtcbiAgICAgICAgdmFyIHJlcyA9IGNvbHNGb3JTdGF0ZS5tYXAodGhpcy5jcmVhdGVTdGF0ZUl0ZW1Gcm9tQ29sdW1uLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm9yZGVyQ29sdW1uU3RhdGVMaXN0KHJlcyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUub3JkZXJDb2x1bW5TdGF0ZUxpc3QgPSBmdW5jdGlvbiAoY29sdW1uU3RhdGVMaXN0KSB7XG4gICAgICAgIC8vIGZvciBmYXN0IGxvb2tpbmcsIHN0b3JlIHRoZSBpbmRleCBvZiBlYWNoIGNvbHVtblxuICAgICAgICB2YXIgY29sSWRUb0dyaWRJbmRleE1hcCA9IGNvbnZlcnRUb01hcCh0aGlzLmdyaWRDb2x1bW5zLm1hcChmdW5jdGlvbiAoY29sLCBpbmRleCkgeyByZXR1cm4gW2NvbC5nZXRDb2xJZCgpLCBpbmRleF07IH0pKTtcbiAgICAgICAgY29sdW1uU3RhdGVMaXN0LnNvcnQoZnVuY3Rpb24gKGl0ZW1BLCBpdGVtQikge1xuICAgICAgICAgICAgdmFyIHBvc0EgPSBjb2xJZFRvR3JpZEluZGV4TWFwLmhhcyhpdGVtQS5jb2xJZCkgPyBjb2xJZFRvR3JpZEluZGV4TWFwLmdldChpdGVtQS5jb2xJZCkgOiAtMTtcbiAgICAgICAgICAgIHZhciBwb3NCID0gY29sSWRUb0dyaWRJbmRleE1hcC5oYXMoaXRlbUIuY29sSWQpID8gY29sSWRUb0dyaWRJbmRleE1hcC5nZXQoaXRlbUIuY29sSWQpIDogLTE7XG4gICAgICAgICAgICByZXR1cm4gcG9zQSAtIHBvc0I7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlc2V0Q29sdW1uU3RhdGUgPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICAgIC8vIE5PVEUgPSB0aGVyZSBpcyBvbmUgYnVnIGhlcmUgdGhhdCBubyBjdXN0b21lciBoYXMgbm90aWNlZCAtIGlmIGEgY29sdW1uIGhhcyBjb2xEZWYubG9ja1Bvc2l0aW9uLFxuICAgICAgICAvLyB0aGlzIGlzIGlnbm9yZWQgIGJlbG93IHdoZW4gb3JkZXJpbmcgdGhlIGNvbHMuIHRvIHdvcmssIHdlIHNob3VsZCBhbHdheXMgcHV0IGxvY2tQb3NpdGlvbiBjb2xzIGZpcnN0LlxuICAgICAgICAvLyBBcyBhIHdvcmsgYXJvdW5kLCBkZXZlbG9wZXJzIHNob3VsZCBqdXN0IHB1dCBsb2NrUG9zaXRpb24gY29sdW1ucyBmaXJzdCBpbiB0aGVpciBjb2xEZWYgbGlzdC5cbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgLy8gd2UgY2FuJ3QgdXNlICdhbGxDb2x1bW5zJyBhcyB0aGUgb3JkZXIgbWlnaHQgb2YgbWVzc2VkIHVwLCBzbyBnZXQgdGhlIHByaW1hcnkgb3JkZXJlZCBsaXN0XG4gICAgICAgIHZhciBwcmltYXJ5Q29sdW1ucyA9IHRoaXMuZ2V0Q29sdW1uc0Zyb21UcmVlKHRoaXMucHJpbWFyeUNvbHVtblRyZWUpO1xuICAgICAgICB2YXIgY29sdW1uU3RhdGVzID0gW107XG4gICAgICAgIC8vIHdlIHN0YXJ0IGF0IDEwMDAsIHNvIGlmIHVzZXIgaGFzIG1peCBvZiByb3dHcm91cCBhbmQgZ3JvdXAgc3BlY2lmaWVkLCBpdCB3aWxsIHdvcmsgd2l0aCBib3RoLlxuICAgICAgICAvLyBlZyBJRiB1c2VyIGhhcyBDb2xBLnJvd0dyb3VwSW5kZXg9MCwgQ29sQi5yb3dHcm91cEluZGV4PTEsIENvbEMucm93R3JvdXA9dHJ1ZSxcbiAgICAgICAgLy8gVEhFTiByZXN1bHQgd2lsbCBiZSBDb2xBLnJvd0dyb3VwSW5kZXg9MCwgQ29sQi5yb3dHcm91cEluZGV4PTEsIENvbEMucm93R3JvdXA9MTAwMFxuICAgICAgICB2YXIgbGV0Um93R3JvdXBJbmRleCA9IDEwMDA7XG4gICAgICAgIHZhciBsZXRQaXZvdEluZGV4ID0gMTAwMDtcbiAgICAgICAgdmFyIGNvbHNUb1Byb2Nlc3MgPSBbXTtcbiAgICAgICAgaWYgKHRoaXMuZ3JvdXBBdXRvQ29sdW1ucykge1xuICAgICAgICAgICAgY29sc1RvUHJvY2VzcyA9IGNvbHNUb1Byb2Nlc3MuY29uY2F0KHRoaXMuZ3JvdXBBdXRvQ29sdW1ucyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByaW1hcnlDb2x1bW5zKSB7XG4gICAgICAgICAgICBjb2xzVG9Qcm9jZXNzID0gY29sc1RvUHJvY2Vzcy5jb25jYXQocHJpbWFyeUNvbHVtbnMpO1xuICAgICAgICB9XG4gICAgICAgIGNvbHNUb1Byb2Nlc3MuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgICB2YXIgZ2V0VmFsdWVPck51bGwgPSBmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYSAhPSBudWxsID8gYSA6IGIgIT0gbnVsbCA/IGIgOiBudWxsOyB9O1xuICAgICAgICAgICAgdmFyIGNvbERlZiA9IGNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgICAgIHZhciBzb3J0ID0gZ2V0VmFsdWVPck51bGwoY29sRGVmLnNvcnQsIGNvbERlZi5pbml0aWFsU29ydCk7XG4gICAgICAgICAgICB2YXIgc29ydEluZGV4ID0gZ2V0VmFsdWVPck51bGwoY29sRGVmLnNvcnRJbmRleCwgY29sRGVmLmluaXRpYWxTb3J0SW5kZXgpO1xuICAgICAgICAgICAgdmFyIGhpZGUgPSBnZXRWYWx1ZU9yTnVsbChjb2xEZWYuaGlkZSwgY29sRGVmLmluaXRpYWxIaWRlKTtcbiAgICAgICAgICAgIHZhciBwaW5uZWQgPSBnZXRWYWx1ZU9yTnVsbChjb2xEZWYucGlubmVkLCBjb2xEZWYuaW5pdGlhbFBpbm5lZCk7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSBnZXRWYWx1ZU9yTnVsbChjb2xEZWYud2lkdGgsIGNvbERlZi5pbml0aWFsV2lkdGgpO1xuICAgICAgICAgICAgdmFyIGZsZXggPSBnZXRWYWx1ZU9yTnVsbChjb2xEZWYuZmxleCwgY29sRGVmLmluaXRpYWxGbGV4KTtcbiAgICAgICAgICAgIHZhciByb3dHcm91cEluZGV4ID0gZ2V0VmFsdWVPck51bGwoY29sRGVmLnJvd0dyb3VwSW5kZXgsIGNvbERlZi5pbml0aWFsUm93R3JvdXBJbmRleCk7XG4gICAgICAgICAgICB2YXIgcm93R3JvdXAgPSBnZXRWYWx1ZU9yTnVsbChjb2xEZWYucm93R3JvdXAsIGNvbERlZi5pbml0aWFsUm93R3JvdXApO1xuICAgICAgICAgICAgaWYgKHJvd0dyb3VwSW5kZXggPT0gbnVsbCAmJiAocm93R3JvdXAgPT0gbnVsbCB8fCByb3dHcm91cCA9PSBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICByb3dHcm91cEluZGV4ID0gbnVsbDtcbiAgICAgICAgICAgICAgICByb3dHcm91cCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcGl2b3RJbmRleCA9IGdldFZhbHVlT3JOdWxsKGNvbERlZi5waXZvdEluZGV4LCBjb2xEZWYuaW5pdGlhbFBpdm90SW5kZXgpO1xuICAgICAgICAgICAgdmFyIHBpdm90ID0gZ2V0VmFsdWVPck51bGwoY29sRGVmLnBpdm90LCBjb2xEZWYuaW5pdGlhbFBpdm90KTtcbiAgICAgICAgICAgIGlmIChwaXZvdEluZGV4ID09IG51bGwgJiYgKHBpdm90ID09IG51bGwgfHwgcGl2b3QgPT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgcGl2b3RJbmRleCA9IG51bGw7XG4gICAgICAgICAgICAgICAgcGl2b3QgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGFnZ0Z1bmMgPSBnZXRWYWx1ZU9yTnVsbChjb2xEZWYuYWdnRnVuYywgY29sRGVmLmluaXRpYWxBZ2dGdW5jKTtcbiAgICAgICAgICAgIHZhciBzdGF0ZUl0ZW0gPSB7XG4gICAgICAgICAgICAgICAgY29sSWQ6IGNvbHVtbi5nZXRDb2xJZCgpLFxuICAgICAgICAgICAgICAgIHNvcnQ6IHNvcnQsXG4gICAgICAgICAgICAgICAgc29ydEluZGV4OiBzb3J0SW5kZXgsXG4gICAgICAgICAgICAgICAgaGlkZTogaGlkZSxcbiAgICAgICAgICAgICAgICBwaW5uZWQ6IHBpbm5lZCxcbiAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgICAgICAgZmxleDogZmxleCxcbiAgICAgICAgICAgICAgICByb3dHcm91cDogcm93R3JvdXAsXG4gICAgICAgICAgICAgICAgcm93R3JvdXBJbmRleDogcm93R3JvdXBJbmRleCxcbiAgICAgICAgICAgICAgICBwaXZvdDogcGl2b3QsXG4gICAgICAgICAgICAgICAgcGl2b3RJbmRleDogcGl2b3RJbmRleCxcbiAgICAgICAgICAgICAgICBhZ2dGdW5jOiBhZ2dGdW5jLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nKHJvd0dyb3VwSW5kZXgpICYmIHJvd0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgc3RhdGVJdGVtLnJvd0dyb3VwSW5kZXggPSBsZXRSb3dHcm91cEluZGV4Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWlzc2luZyhwaXZvdEluZGV4KSAmJiBwaXZvdCkge1xuICAgICAgICAgICAgICAgIHN0YXRlSXRlbS5waXZvdEluZGV4ID0gbGV0UGl2b3RJbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29sdW1uU3RhdGVzLnB1c2goc3RhdGVJdGVtKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYXBwbHlDb2x1bW5TdGF0ZSh7IHN0YXRlOiBjb2x1bW5TdGF0ZXMsIGFwcGx5T3JkZXI6IHRydWUgfSwgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5hcHBseUNvbHVtblN0YXRlID0gZnVuY3Rpb24gKHBhcmFtcywgc291cmNlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIGlmIChtaXNzaW5nT3JFbXB0eSh0aGlzLnByaW1hcnlDb2x1bW5zKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLnN0YXRlICYmICFwYXJhbXMuc3RhdGUuZm9yRWFjaCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBhcHBseUNvbHVtblN0YXRlKCkgLSB0aGUgc3RhdGUgYXR0cmlidXRlIHNob3VsZCBiZSBhbiBhcnJheSwgaG93ZXZlciBhbiBhcnJheSB3YXMgbm90IGZvdW5kLiBQbGVhc2UgcHJvdmlkZSBhbiBhcnJheSBvZiBpdGVtcyAob25lIGZvciBlYWNoIGNvbCB5b3Ugd2FudCB0byBjaGFuZ2UpIGZvciBzdGF0ZS4nKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYXBwbHlTdGF0ZXMgPSBmdW5jdGlvbiAoc3RhdGVzLCBleGlzdGluZ0NvbHVtbnMsIGdldEJ5SWQpIHtcbiAgICAgICAgICAgIHZhciByYWlzZUV2ZW50c0Z1bmMgPSBfdGhpcy5jb21wYXJlQ29sdW1uU3RhdGVzQW5kUmFpc2VFdmVudHMoc291cmNlKTtcbiAgICAgICAgICAgIF90aGlzLmF1dG9Hcm91cHNOZWVkQnVpbGRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgLy8gYXQgdGhlIGVuZCBiZWxvdywgdGhpcyBsaXN0IHdpbGwgaGF2ZSBhbGwgY29sdW1ucyB3ZSBnb3Qgbm8gc3RhdGUgZm9yXG4gICAgICAgICAgICB2YXIgY29sdW1uc1dpdGhOb1N0YXRlID0gZXhpc3RpbmdDb2x1bW5zLnNsaWNlKCk7XG4gICAgICAgICAgICB2YXIgcm93R3JvdXBJbmRleGVzID0ge307XG4gICAgICAgICAgICB2YXIgcGl2b3RJbmRleGVzID0ge307XG4gICAgICAgICAgICB2YXIgYXV0b0dyb3VwQ29sdW1uU3RhdGVzID0gW107XG4gICAgICAgICAgICAvLyBJZiBwaXZvdGluZyBpcyBtb2RpZmllZCwgdGhlc2UgYXJlIHRoZSBzdGF0ZXMgd2UgdHJ5IHRvIHJlYXBwbHkgYWZ0ZXJcbiAgICAgICAgICAgIC8vIHRoZSBzZWNvbmRhcnkgY29sdW1ucyBhcmUgcmUtZ2VuZXJhdGVkXG4gICAgICAgICAgICB2YXIgdW5tYXRjaGVkQW5kQXV0b1N0YXRlcyA9IFtdO1xuICAgICAgICAgICAgdmFyIHVubWF0Y2hlZENvdW50ID0gMDtcbiAgICAgICAgICAgIHZhciBwcmV2aW91c1Jvd0dyb3VwQ29scyA9IF90aGlzLnJvd0dyb3VwQ29sdW1ucy5zbGljZSgpO1xuICAgICAgICAgICAgdmFyIHByZXZpb3VzUGl2b3RDb2xzID0gX3RoaXMucGl2b3RDb2x1bW5zLnNsaWNlKCk7XG4gICAgICAgICAgICBzdGF0ZXMuZm9yRWFjaChmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29sSWQgPSBzdGF0ZS5jb2xJZCB8fCAnJztcbiAgICAgICAgICAgICAgICAvLyBhdXRvIGdyb3VwIGNvbHVtbnMgYXJlIHJlLWNyZWF0ZWQgc28gZGVmZXJyaW5nIHN5bmNpbmcgd2l0aCBDb2x1bW5TdGF0ZVxuICAgICAgICAgICAgICAgIHZhciBpc0F1dG9Hcm91cENvbHVtbiA9IGNvbElkLnN0YXJ0c1dpdGgoQ29uc3RhbnRzLkdST1VQX0FVVE9fQ09MVU1OX0lEKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNBdXRvR3JvdXBDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgYXV0b0dyb3VwQ29sdW1uU3RhdGVzLnB1c2goc3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB1bm1hdGNoZWRBbmRBdXRvU3RhdGVzLnB1c2goc3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBnZXRCeUlkKGNvbElkKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICB1bm1hdGNoZWRBbmRBdXRvU3RhdGVzLnB1c2goc3RhdGUpO1xuICAgICAgICAgICAgICAgICAgICB1bm1hdGNoZWRDb3VudCArPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuc3luY0NvbHVtbldpdGhTdGF0ZUl0ZW0oY29sdW1uLCBzdGF0ZSwgcGFyYW1zLmRlZmF1bHRTdGF0ZSwgcm93R3JvdXBJbmRleGVzLCBwaXZvdEluZGV4ZXMsIGZhbHNlLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkoY29sdW1uc1dpdGhOb1N0YXRlLCBjb2x1bW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gYW55dGhpbmcgbGVmdCBvdmVyLCB3ZSBnb3Qgbm8gZGF0YSBmb3IsIHNvIGFkZCBpbiB0aGUgY29sdW1uIGFzIG5vbi12YWx1ZSwgbm9uLXJvd0dyb3VwIGFuZCBoaWRkZW5cbiAgICAgICAgICAgIHZhciBhcHBseURlZmF1bHRzRnVuYyA9IGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMuc3luY0NvbHVtbldpdGhTdGF0ZUl0ZW0oY29sLCBudWxsLCBwYXJhbXMuZGVmYXVsdFN0YXRlLCByb3dHcm91cEluZGV4ZXMsIHBpdm90SW5kZXhlcywgZmFsc2UsIHNvdXJjZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29sdW1uc1dpdGhOb1N0YXRlLmZvckVhY2goYXBwbHlEZWZhdWx0c0Z1bmMpO1xuICAgICAgICAgICAgLy8gc29ydCB0aGUgbGlzdHMgYWNjb3JkaW5nIHRvIHRoZSBpbmRleGVzIHRoYXQgd2VyZSBwcm92aWRlZFxuICAgICAgICAgICAgdmFyIGNvbXBhcmF0b3IgPSBmdW5jdGlvbiAoaW5kZXhlcywgb2xkTGlzdCwgY29sQSwgY29sQikge1xuICAgICAgICAgICAgICAgIHZhciBpbmRleEEgPSBpbmRleGVzW2NvbEEuZ2V0SWQoKV07XG4gICAgICAgICAgICAgICAgdmFyIGluZGV4QiA9IGluZGV4ZXNbY29sQi5nZXRJZCgpXTtcbiAgICAgICAgICAgICAgICB2YXIgYUhhc0luZGV4ID0gaW5kZXhBICE9IG51bGw7XG4gICAgICAgICAgICAgICAgdmFyIGJIYXNJbmRleCA9IGluZGV4QiAhPSBudWxsO1xuICAgICAgICAgICAgICAgIGlmIChhSGFzSW5kZXggJiYgYkhhc0luZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGJvdGggYSBhbmQgYiBhcmUgbmV3IGNvbHMgd2l0aCBpbmRleCwgc28gc29ydCBvbiBpbmRleFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5kZXhBIC0gaW5kZXhCO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYUhhc0luZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGEgaGFzIGFuIGluZGV4LCBzbyBpdCBzaG91bGQgYmUgYmVmb3JlIGFcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYkhhc0luZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGIgaGFzIGFuIGluZGV4LCBzbyBpdCBzaG91bGQgYmUgYmVmb3JlIGFcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBvbGRJbmRleEEgPSBvbGRMaXN0LmluZGV4T2YoY29sQSk7XG4gICAgICAgICAgICAgICAgdmFyIG9sZEluZGV4QiA9IG9sZExpc3QuaW5kZXhPZihjb2xCKTtcbiAgICAgICAgICAgICAgICB2YXIgYUhhc09sZEluZGV4ID0gb2xkSW5kZXhBID49IDA7XG4gICAgICAgICAgICAgICAgdmFyIGJIYXNPbGRJbmRleCA9IG9sZEluZGV4QiA+PSAwO1xuICAgICAgICAgICAgICAgIGlmIChhSGFzT2xkSW5kZXggJiYgYkhhc09sZEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGJvdGggYSBhbmQgYiBhcmUgb2xkIGNvbHMsIHNvIHNvcnQgYmFzZWQgb24gbGFzdCBvcmRlclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2xkSW5kZXhBIC0gb2xkSW5kZXhCO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYUhhc09sZEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGEgaXMgb2xkLCBiIGlzIG5ldywgc28gYiBpcyBmaXJzdFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIHRoaXMgYml0IGRvZXMgbWF0dGVyLCBtZWFucyBib3RoIGFyZSBuZXcgY29sc1xuICAgICAgICAgICAgICAgIC8vIGJ1dCB3aXRob3V0IGluZGV4IG9yIHRoYXQgYiBpcyBvbGQgYW5kIGEgaXMgbmV3XG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX3RoaXMucm93R3JvdXBDb2x1bW5zLnNvcnQoY29tcGFyYXRvci5iaW5kKF90aGlzLCByb3dHcm91cEluZGV4ZXMsIHByZXZpb3VzUm93R3JvdXBDb2xzKSk7XG4gICAgICAgICAgICBfdGhpcy5waXZvdENvbHVtbnMuc29ydChjb21wYXJhdG9yLmJpbmQoX3RoaXMsIHBpdm90SW5kZXhlcywgcHJldmlvdXNQaXZvdENvbHMpKTtcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZUdyaWRDb2x1bW5zKCk7XG4gICAgICAgICAgICAvLyBzeW5jIG5ld2x5IGNyZWF0ZWQgYXV0byBncm91cCBjb2x1bW5zIHdpdGggQ29sdW1uU3RhdGVcbiAgICAgICAgICAgIHZhciBhdXRvR3JvdXBDb2xzQ29weSA9IF90aGlzLmdyb3VwQXV0b0NvbHVtbnMgPyBfdGhpcy5ncm91cEF1dG9Db2x1bW5zLnNsaWNlKCkgOiBbXTtcbiAgICAgICAgICAgIGF1dG9Hcm91cENvbHVtblN0YXRlcy5mb3JFYWNoKGZ1bmN0aW9uIChzdGF0ZUl0ZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgYXV0b0NvbCA9IF90aGlzLmdldEF1dG9Db2x1bW4oc3RhdGVJdGVtLmNvbElkKTtcbiAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkoYXV0b0dyb3VwQ29sc0NvcHksIGF1dG9Db2wpO1xuICAgICAgICAgICAgICAgIF90aGlzLnN5bmNDb2x1bW5XaXRoU3RhdGVJdGVtKGF1dG9Db2wsIHN0YXRlSXRlbSwgcGFyYW1zLmRlZmF1bHRTdGF0ZSwgbnVsbCwgbnVsbCwgdHJ1ZSwgc291cmNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gYXV0b2dyb3VwIGNvbHMgd2l0aCBub3RoaW5nIGVsc2UsIGFwcGx5IHRoZSBkZWZhdWx0XG4gICAgICAgICAgICBhdXRvR3JvdXBDb2xzQ29weS5mb3JFYWNoKGFwcGx5RGVmYXVsdHNGdW5jKTtcbiAgICAgICAgICAgIF90aGlzLmFwcGx5T3JkZXJBZnRlckFwcGx5U3RhdGUocGFyYW1zKTtcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZURpc3BsYXllZENvbHVtbnMoc291cmNlKTtcbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoRXZlcnl0aGluZ0NoYW5nZWQoc291cmNlKTtcbiAgICAgICAgICAgIHJhaXNlRXZlbnRzRnVuYygpOyAvLyBXaWxsIHRyaWdnZXIgc2Vjb25kYXJ5IGNvbHVtbiBjaGFuZ2VzIGlmIHBpdm90aW5nIG1vZGlmaWVkXG4gICAgICAgICAgICByZXR1cm4geyB1bm1hdGNoZWRBbmRBdXRvU3RhdGVzOiB1bm1hdGNoZWRBbmRBdXRvU3RhdGVzLCB1bm1hdGNoZWRDb3VudDogdW5tYXRjaGVkQ291bnQgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jb2x1bW5BbmltYXRpb25TZXJ2aWNlLnN0YXJ0KCk7XG4gICAgICAgIHZhciBfYSA9IGFwcGx5U3RhdGVzKHBhcmFtcy5zdGF0ZSB8fCBbXSwgdGhpcy5wcmltYXJ5Q29sdW1ucyB8fCBbXSwgZnVuY3Rpb24gKGlkKSB7IHJldHVybiBfdGhpcy5nZXRQcmltYXJ5Q29sdW1uKGlkKTsgfSksIHVubWF0Y2hlZEFuZEF1dG9TdGF0ZXMgPSBfYS51bm1hdGNoZWRBbmRBdXRvU3RhdGVzLCB1bm1hdGNoZWRDb3VudCA9IF9hLnVubWF0Y2hlZENvdW50O1xuICAgICAgICAvLyBJZiB0aGVyZSBhcmUgc3RpbGwgc3RhdGVzIGxlZnQgb3Zlciwgc2VlIGlmIHdlIGNhbiBhcHBseSB0aGVtIHRvIG5ld2x5IGdlbmVyYXRlZFxuICAgICAgICAvLyBzZWNvbmRhcnkgb3IgYXV0byBjb2x1bW5zLiBBbHNvIGlmIGRlZmF1bHRzIGV4aXN0LCBlbnN1cmUgdGhleSBhcmUgYXBwbGllZCB0byBzZWNvbmRhcnkgY29sc1xuICAgICAgICBpZiAodW5tYXRjaGVkQW5kQXV0b1N0YXRlcy5sZW5ndGggPiAwIHx8IGV4aXN0cyhwYXJhbXMuZGVmYXVsdFN0YXRlKSkge1xuICAgICAgICAgICAgdW5tYXRjaGVkQ291bnQgPSBhcHBseVN0YXRlcyh1bm1hdGNoZWRBbmRBdXRvU3RhdGVzLCB0aGlzLnNlY29uZGFyeUNvbHVtbnMgfHwgW10sIGZ1bmN0aW9uIChpZCkgeyByZXR1cm4gX3RoaXMuZ2V0U2Vjb25kYXJ5Q29sdW1uKGlkKTsgfSkudW5tYXRjaGVkQ291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb2x1bW5BbmltYXRpb25TZXJ2aWNlLmZpbmlzaCgpO1xuICAgICAgICByZXR1cm4gdW5tYXRjaGVkQ291bnQgPT09IDA7IC8vIFN1Y2Nlc3NmdWwgaWYgbm8gc3RhdGVzIHVuYWNjb3VudGVkIGZvclxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmFwcGx5T3JkZXJBZnRlckFwcGx5U3RhdGUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghcGFyYW1zLmFwcGx5T3JkZXIgfHwgIXBhcmFtcy5zdGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXdPcmRlciA9IFtdO1xuICAgICAgICB2YXIgcHJvY2Vzc2VkQ29sSWRzID0ge307XG4gICAgICAgIHBhcmFtcy5zdGF0ZS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgICAgICBpZiAoIWl0ZW0uY29sSWQgfHwgcHJvY2Vzc2VkQ29sSWRzW2l0ZW0uY29sSWRdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNvbCA9IF90aGlzLmdyaWRDb2x1bW5zTWFwW2l0ZW0uY29sSWRdO1xuICAgICAgICAgICAgaWYgKGNvbCkge1xuICAgICAgICAgICAgICAgIG5ld09yZGVyLnB1c2goY29sKTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRDb2xJZHNbaXRlbS5jb2xJZF0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gYWRkIGluIGFsbCBvdGhlciBjb2x1bW5zXG4gICAgICAgIHZhciBhdXRvR3JvdXBJbnNlcnRJbmRleCA9IDA7XG4gICAgICAgIHRoaXMuZ3JpZENvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICB2YXIgY29sSWQgPSBjb2wuZ2V0Q29sSWQoKTtcbiAgICAgICAgICAgIHZhciBhbHJlYWR5UHJvY2Vzc2VkID0gcHJvY2Vzc2VkQ29sSWRzW2NvbElkXSAhPSBudWxsO1xuICAgICAgICAgICAgaWYgKGFscmVhZHlQcm9jZXNzZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaXNBdXRvR3JvdXBDb2wgPSBjb2xJZC5zdGFydHNXaXRoKENvbnN0YW50cy5HUk9VUF9BVVRPX0NPTFVNTl9JRCk7XG4gICAgICAgICAgICBpZiAoaXNBdXRvR3JvdXBDb2wpIHtcbiAgICAgICAgICAgICAgICAvLyBhdXRvIGdyb3VwIGNvbHVtbnMsIGlmIG1pc3NpbmcgZnJvbSBzdGF0ZSBsaXN0LCBhcmUgYWRkZWQgdG8gdGhlIHN0YXJ0LlxuICAgICAgICAgICAgICAgIC8vIGl0J3MgY29tbW9uIHRvIGhhdmUgYXV0b0dyb3VwIG1pc3NpbmcsIGFzIGdyb3VwaW5nIGNvdWxkIGJlIG9uIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgICAgICAvLyBvbiBhIGNvbHVtbiwgYnV0IHRoZSB1c2VyIGNvdWxkIG9mIHNpbmNlIHJlbW92ZWQgdGhlIGdyb3VwaW5nIHZpYSB0aGUgVUkuXG4gICAgICAgICAgICAgICAgLy8gaWYgd2UgZG9uJ3QgaW5jIHRoZSBpbnNlcnQgaW5kZXgsIGF1dG9Hcm91cHMgd2lsbCBiZSBpbnNlcnRlZCBpbiByZXZlcnNlIG9yZGVyXG4gICAgICAgICAgICAgICAgaW5zZXJ0SW50b0FycmF5KG5ld09yZGVyLCBjb2wsIGF1dG9Hcm91cEluc2VydEluZGV4KyspO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gbm9ybWFsIGNvbHVtbnMsIGlmIG1pc3NpbmcgZnJvbSBzdGF0ZSBsaXN0LCBhcmUgYWRkZWQgYXQgdGhlIGVuZFxuICAgICAgICAgICAgICAgIG5ld09yZGVyLnB1c2goY29sKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHRoaXMgaXMgYWxyZWFkeSBkb25lIGluIHVwZGF0ZUdyaWRDb2x1bW5zLCBob3dldmVyIHdlIGNoYW5nZWQgdGhlIG9yZGVyIGFib3ZlICh0byBtYXRjaCB0aGUgb3JkZXIgb2YgdGhlIHN0YXRlXG4gICAgICAgIC8vIGNvbHVtbnMpIHNvIHdlIG5lZWQgdG8gZG8gaXQgYWdhaW4uIHdlIGNvdWxkIG9mIHB1dCBsb2dpYyBpbnRvIHRoZSBvcmRlciBhYm92ZSB0byB0YWtlIGludG8gYWNjb3VudCBmaXhlZFxuICAgICAgICAvLyBjb2x1bW5zLCBob3dldmVyIGlmIHdlIGRpZCB0aGVuIHdlIHdvdWxkIGhhdmUgbG9naWMgZm9yIHVwZGF0aW5nIGZpeGVkIGNvbHVtbnMgdHdpY2UuIHJldXNpbmcgdGhlIGxvZ2ljIGhlcmVcbiAgICAgICAgLy8gaXMgbGVzcyBzZXh5IGZvciB0aGUgY29kZSBoZXJlLCBidXQgaXQga2VlcHMgY29uc2lzdGVuY3kuXG4gICAgICAgIG5ld09yZGVyID0gdGhpcy5wbGFjZUxvY2tlZENvbHVtbnMobmV3T3JkZXIpO1xuICAgICAgICBpZiAoIXRoaXMuZG9lc01vdmVQYXNzTWFycnlDaGlsZHJlbihuZXdPcmRlcikpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogQXBwbHlpbmcgY29sdW1uIG9yZGVyIGJyb2tlIGEgZ3JvdXAgd2hlcmUgY29sdW1ucyBzaG91bGQgYmUgbWFycmllZCB0b2dldGhlci4gQXBwbHlpbmcgbmV3IG9yZGVyIGhhcyBiZWVuIGRpc2NhcmRlZC4nKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdyaWRDb2x1bW5zID0gbmV3T3JkZXI7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuY29tcGFyZUNvbHVtblN0YXRlc0FuZFJhaXNlRXZlbnRzID0gZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgc3RhcnRTdGF0ZSA9IHtcbiAgICAgICAgICAgIHJvd0dyb3VwQ29sdW1uczogdGhpcy5yb3dHcm91cENvbHVtbnMuc2xpY2UoKSxcbiAgICAgICAgICAgIHBpdm90Q29sdW1uczogdGhpcy5waXZvdENvbHVtbnMuc2xpY2UoKSxcbiAgICAgICAgICAgIHZhbHVlQ29sdW1uczogdGhpcy52YWx1ZUNvbHVtbnMuc2xpY2UoKVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29sdW1uU3RhdGVCZWZvcmUgPSB0aGlzLmdldENvbHVtblN0YXRlKCk7XG4gICAgICAgIHZhciBjb2x1bW5TdGF0ZUJlZm9yZU1hcCA9IHt9O1xuICAgICAgICBjb2x1bW5TdGF0ZUJlZm9yZS5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIGNvbHVtblN0YXRlQmVmb3JlTWFwW2NvbC5jb2xJZF0gPSBjb2w7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ29sdW1uU3RhdGVFdmVudHMoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjb2xzRm9yU3RhdGUgPSBfdGhpcy5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5QW5kQXV0b0NvbHVtbnMoKTtcbiAgICAgICAgICAgIC8vIHJhaXNlcyBnZW5lcmljIENvbHVtbkV2ZW50cyB3aGVyZSBhbGwgY29sdW1ucyBhcmUgcmV0dXJuZWQgcmF0aGVyIHRoYW4gd2hhdCBoYXMgY2hhbmdlZFxuICAgICAgICAgICAgdmFyIHJhaXNlV2hlbkxpc3RzRGlmZmVyZW50ID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgY29sc0JlZm9yZSwgY29sc0FmdGVyLCBpZE1hcHBlcikge1xuICAgICAgICAgICAgICAgIHZhciBiZWZvcmVMaXN0ID0gY29sc0JlZm9yZS5tYXAoaWRNYXBwZXIpO1xuICAgICAgICAgICAgICAgIHZhciBhZnRlckxpc3QgPSBjb2xzQWZ0ZXIubWFwKGlkTWFwcGVyKTtcbiAgICAgICAgICAgICAgICB2YXIgdW5jaGFuZ2VkID0gYXJlRXF1YWwoYmVmb3JlTGlzdCwgYWZ0ZXJMaXN0KTtcbiAgICAgICAgICAgICAgICBpZiAodW5jaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gcmV0dXJuaW5nIGFsbCBjb2x1bW5zIHJhdGhlciB0aGFuIHdoYXQgaGFzIGNoYW5nZWQhXG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBldmVudFR5cGUsXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbnM6IGNvbHNBZnRlcixcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uOiBjb2xzQWZ0ZXIubGVuZ3RoID09PSAxID8gY29sc0FmdGVyWzBdIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlOiBzb3VyY2VcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIF90aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBkZXRlcm1pbmVzIHdoaWNoIGNvbHVtbnMgaGF2ZSBjaGFuZ2VkIGFjY29yZGluZyB0byBzdXBwbGllZCBwcmVkaWNhdGVcbiAgICAgICAgICAgIHZhciBnZXRDaGFuZ2VkQ29sdW1ucyA9IGZ1bmN0aW9uIChjaGFuZ2VkUHJlZGljYXRlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoYW5nZWRDb2x1bW5zID0gW107XG4gICAgICAgICAgICAgICAgY29sc0ZvclN0YXRlLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29sU3RhdGVCZWZvcmUgPSBjb2x1bW5TdGF0ZUJlZm9yZU1hcFtjb2x1bW4uZ2V0Q29sSWQoKV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2xTdGF0ZUJlZm9yZSAmJiBjaGFuZ2VkUHJlZGljYXRlKGNvbFN0YXRlQmVmb3JlLCBjb2x1bW4pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGFuZ2VkQ29sdW1ucy5wdXNoKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2hhbmdlZENvbHVtbnM7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGNvbHVtbklkTWFwcGVyID0gZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGMuZ2V0Q29sSWQoKTsgfTtcbiAgICAgICAgICAgIHJhaXNlV2hlbkxpc3RzRGlmZmVyZW50KEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIHN0YXJ0U3RhdGUucm93R3JvdXBDb2x1bW5zLCBfdGhpcy5yb3dHcm91cENvbHVtbnMsIGNvbHVtbklkTWFwcGVyKTtcbiAgICAgICAgICAgIHJhaXNlV2hlbkxpc3RzRGlmZmVyZW50KEV2ZW50cy5FVkVOVF9DT0xVTU5fUElWT1RfQ0hBTkdFRCwgc3RhcnRTdGF0ZS5waXZvdENvbHVtbnMsIF90aGlzLnBpdm90Q29sdW1ucywgY29sdW1uSWRNYXBwZXIpO1xuICAgICAgICAgICAgdmFyIHZhbHVlQ2hhbmdlUHJlZGljYXRlID0gZnVuY3Rpb24gKGNzLCBjKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9sZEFjdGl2ZSA9IGNzLmFnZ0Z1bmMgIT0gbnVsbDtcbiAgICAgICAgICAgICAgICB2YXIgYWN0aXZlQ2hhbmdlZCA9IG9sZEFjdGl2ZSAhPSBjLmlzVmFsdWVBY3RpdmUoKTtcbiAgICAgICAgICAgICAgICAvLyB3ZSBvbmx5IGNoZWNrIGFnZ0Z1bmMgaWYgdGhlIGFnZyBpcyBhY3RpdmVcbiAgICAgICAgICAgICAgICB2YXIgYWdnRnVuY0NoYW5nZWQgPSBvbGRBY3RpdmUgJiYgY3MuYWdnRnVuYyAhPSBjLmdldEFnZ0Z1bmMoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWN0aXZlQ2hhbmdlZCB8fCBhZ2dGdW5jQ2hhbmdlZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgY2hhbmdlZFZhbHVlcyA9IGdldENoYW5nZWRDb2x1bW5zKHZhbHVlQ2hhbmdlUHJlZGljYXRlKTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VkVmFsdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSBwYXNzIGFsbCB2YWx1ZSBjb2x1bW5zLCBub3cgdGhlIG9uZXMgdGhhdCBjaGFuZ2VkLiB0aGlzIGlzIHRoZSBzYW1lXG4gICAgICAgICAgICAgICAgLy8gYXMgcGl2b3QgYW5kIHJvd0dyb3VwIGNvbHMsIGJ1dCBkaWZmZXJlbnQgdG8gYWxsIG90aGVyIHByb3BlcnRpZXMgYmVsb3cuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBpcyBtb3JlIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgYXMgaXQncyBhbHdheXMgYmVlbiB0aGlzIHdheS5cbiAgICAgICAgICAgICAgICAvLyByZWFsbHkgaXQgc2hvdWxkIGJlIHRoZSBvdGhlciB3YXksIGFzIHRoZSBvcmRlciBvZiB0aGUgY29scyBtYWtlcyBubyBkaWZmZXJlbmNlXG4gICAgICAgICAgICAgICAgLy8gZm9yIHZhbHVlQ29sdW1ucyAoYXBhcnQgZnJvbSBkaXNwbGF5aW5nIHRoZW0gaW4gdGhlIHRvb2wgcGFuZWwpLlxuICAgICAgICAgICAgICAgIF90aGlzLmZpcmVDb2x1bW5FdmVudChFdmVudHMuRVZFTlRfQ09MVU1OX1ZBTFVFX0NIQU5HRUQsIF90aGlzLnZhbHVlQ29sdW1ucywgc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciByZXNpemVDaGFuZ2VQcmVkaWNhdGUgPSBmdW5jdGlvbiAoY3MsIGMpIHsgcmV0dXJuIGNzLndpZHRoICE9IGMuZ2V0QWN0dWFsV2lkdGgoKTsgfTtcbiAgICAgICAgICAgIF90aGlzLmZpcmVDb2x1bW5SZXNpemVkRXZlbnQoZ2V0Q2hhbmdlZENvbHVtbnMocmVzaXplQ2hhbmdlUHJlZGljYXRlKSwgdHJ1ZSwgc291cmNlKTtcbiAgICAgICAgICAgIHZhciBwaW5uZWRDaGFuZ2VQcmVkaWNhdGUgPSBmdW5jdGlvbiAoY3MsIGMpIHsgcmV0dXJuIGNzLnBpbm5lZCAhPSBjLmdldFBpbm5lZCgpOyB9O1xuICAgICAgICAgICAgX3RoaXMucmFpc2VDb2x1bW5QaW5uZWRFdmVudChnZXRDaGFuZ2VkQ29sdW1ucyhwaW5uZWRDaGFuZ2VQcmVkaWNhdGUpLCBzb3VyY2UpO1xuICAgICAgICAgICAgdmFyIHZpc2liaWxpdHlDaGFuZ2VQcmVkaWNhdGUgPSBmdW5jdGlvbiAoY3MsIGMpIHsgcmV0dXJuIGNzLmhpZGUgPT0gYy5pc1Zpc2libGUoKTsgfTtcbiAgICAgICAgICAgIF90aGlzLnJhaXNlQ29sdW1uVmlzaWJsZUV2ZW50KGdldENoYW5nZWRDb2x1bW5zKHZpc2liaWxpdHlDaGFuZ2VQcmVkaWNhdGUpLCBzb3VyY2UpO1xuICAgICAgICAgICAgdmFyIHNvcnRDaGFuZ2VQcmVkaWNhdGUgPSBmdW5jdGlvbiAoY3MsIGMpIHsgcmV0dXJuIGNzLnNvcnQgIT0gYy5nZXRTb3J0KCkgfHwgY3Muc29ydEluZGV4ICE9IGMuZ2V0U29ydEluZGV4KCk7IH07XG4gICAgICAgICAgICBpZiAoZ2V0Q2hhbmdlZENvbHVtbnMoc29ydENoYW5nZVByZWRpY2F0ZSkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNvcnRDb250cm9sbGVyLmRpc3BhdGNoU29ydENoYW5nZWRFdmVudHMoc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHNwZWNpYWwgaGFuZGxpbmcgZm9yIG1vdmVkIGNvbHVtbiBldmVudHNcbiAgICAgICAgICAgIF90aGlzLnJhaXNlQ29sdW1uTW92ZWRFdmVudChjb2x1bW5TdGF0ZUJlZm9yZSwgc291cmNlKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5yYWlzZUNvbHVtblBpbm5lZEV2ZW50ID0gZnVuY3Rpb24gKGNoYW5nZWRDb2x1bW5zLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKCFjaGFuZ2VkQ29sdW1ucy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBqdXN0IG9uZSBjb2x1bW4sIHdlIHVzZSB0aGlzLCBvdGhlcndpc2Ugd2UgZG9uJ3QgaW5jbHVkZSB0aGUgY29sXG4gICAgICAgIHZhciBjb2x1bW4gPSBjaGFuZ2VkQ29sdW1ucy5sZW5ndGggPT09IDEgPyBjaGFuZ2VkQ29sdW1uc1swXSA6IG51bGw7XG4gICAgICAgIC8vIG9ubHkgaW5jbHVkZSB2aXNpYmxlIGlmIGl0J3MgY29tbW9uIGluIGFsbCBjb2x1bW5zXG4gICAgICAgIHZhciBwaW5uZWQgPSB0aGlzLmdldENvbW1vblZhbHVlKGNoYW5nZWRDb2x1bW5zLCBmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuZ2V0UGlubmVkKCk7IH0pO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfQ09MVU1OX1BJTk5FRCxcbiAgICAgICAgICAgIC8vIG1pc3Rha2UgaW4gdHlwaW5nLCAndW5kZWZpbmVkJyBzaG91bGQgYmUgYWxsb3dlZCwgYXMgJ251bGwnIG1lYW5zICdub3QgcGlubmVkJ1xuICAgICAgICAgICAgcGlubmVkOiBwaW5uZWQgIT0gbnVsbCA/IHBpbm5lZCA6IG51bGwsXG4gICAgICAgICAgICBjb2x1bW5zOiBjaGFuZ2VkQ29sdW1ucyxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2VcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0Q29tbW9uVmFsdWUgPSBmdW5jdGlvbiAoY29scywgdmFsdWVHZXR0ZXIpIHtcbiAgICAgICAgaWYgKCFjb2xzIHx8IGNvbHMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY29tcGFyZSBlYWNoIHZhbHVlIHRvIHRoZSBmaXJzdCB2YWx1ZS4gaWYgbm90aGluZyBkaWZmZXJzLCB0aGVuIHZhbHVlIGlzIGNvbW1vbiBzbyByZXR1cm4gaXQuXG4gICAgICAgIHZhciBmaXJzdFZhbHVlID0gdmFsdWVHZXR0ZXIoY29sc1swXSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgY29scy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGZpcnN0VmFsdWUgIT09IHZhbHVlR2V0dGVyKGNvbHNbaV0pKSB7XG4gICAgICAgICAgICAgICAgLy8gdmFsdWVzIGRpZmZlciwgbm8gY29tbW9uIHZhbHVlXG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmlyc3RWYWx1ZTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5yYWlzZUNvbHVtblZpc2libGVFdmVudCA9IGZ1bmN0aW9uIChjaGFuZ2VkQ29sdW1ucywgc291cmNlKSB7XG4gICAgICAgIGlmICghY2hhbmdlZENvbHVtbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYganVzdCBvbmUgY29sdW1uLCB3ZSB1c2UgdGhpcywgb3RoZXJ3aXNlIHdlIGRvbid0IGluY2x1ZGUgdGhlIGNvbFxuICAgICAgICB2YXIgY29sdW1uID0gY2hhbmdlZENvbHVtbnMubGVuZ3RoID09PSAxID8gY2hhbmdlZENvbHVtbnNbMF0gOiBudWxsO1xuICAgICAgICAvLyBvbmx5IGluY2x1ZGUgdmlzaWJsZSBpZiBpdCdzIGNvbW1vbiBpbiBhbGwgY29sdW1uc1xuICAgICAgICB2YXIgdmlzaWJsZSA9IHRoaXMuZ2V0Q29tbW9uVmFsdWUoY2hhbmdlZENvbHVtbnMsIGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5pc1Zpc2libGUoKTsgfSk7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DT0xVTU5fVklTSUJMRSxcbiAgICAgICAgICAgIHZpc2libGU6IHZpc2libGUsXG4gICAgICAgICAgICBjb2x1bW5zOiBjaGFuZ2VkQ29sdW1ucyxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2VcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUucmFpc2VDb2x1bW5Nb3ZlZEV2ZW50ID0gZnVuY3Rpb24gKGNvbFN0YXRlQmVmb3JlLCBzb3VyY2UpIHtcbiAgICAgICAgLy8gd2UgYXJlIG9ubHkgaW50ZXJlc3RlZCBpbiBjb2x1bW5zIHRoYXQgd2VyZSBib3RoIHByZXNlbnQgYW5kIHZpc2libGUgYmVmb3JlIGFuZCBhZnRlclxuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29sU3RhdGVBZnRlciA9IHRoaXMuZ2V0Q29sdW1uU3RhdGUoKTtcbiAgICAgICAgdmFyIGNvbFN0YXRlQWZ0ZXJNYXBwZWQgPSB7fTtcbiAgICAgICAgY29sU3RhdGVBZnRlci5mb3JFYWNoKGZ1bmN0aW9uIChzKSB7IHJldHVybiBjb2xTdGF0ZUFmdGVyTWFwcGVkW3MuY29sSWRdID0gczsgfSk7XG4gICAgICAgIC8vIGdldCBpZCdzIG9mIGNvbHMgaW4gYm90aCBiZWZvcmUgYW5kIGFmdGVyIGxpc3RzXG4gICAgICAgIHZhciBjb2xzSW50ZXJzZWN0SWRzID0ge307XG4gICAgICAgIGNvbFN0YXRlQmVmb3JlLmZvckVhY2goZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgIGlmIChjb2xTdGF0ZUFmdGVyTWFwcGVkW3MuY29sSWRdKSB7XG4gICAgICAgICAgICAgICAgY29sc0ludGVyc2VjdElkc1tzLmNvbElkXSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBmaWx0ZXIgc3RhdGUgbGlzdHMsIHNvIHdlIG9ubHkgaGF2ZSBjb2xzIHRoYXQgd2VyZSBwcmVzZW50IGJlZm9yZSBhbmQgYWZ0ZXJcbiAgICAgICAgdmFyIGJlZm9yZUZpbHRlcmVkID0gY29sU3RhdGVCZWZvcmUuZmlsdGVyKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjb2xzSW50ZXJzZWN0SWRzW2MuY29sSWRdOyB9KTtcbiAgICAgICAgdmFyIGFmdGVyRmlsdGVyZWQgPSBjb2xTdGF0ZUFmdGVyLmZpbHRlcihmdW5jdGlvbiAoYykgeyByZXR1cm4gY29sc0ludGVyc2VjdElkc1tjLmNvbElkXTsgfSk7XG4gICAgICAgIC8vIHNlZSBpZiBhbnkgY29scyBhcmUgaW4gYSBkaWZmZXJlbnQgbG9jYXRpb25cbiAgICAgICAgdmFyIG1vdmVkQ29sdW1ucyA9IFtdO1xuICAgICAgICBhZnRlckZpbHRlcmVkLmZvckVhY2goZnVuY3Rpb24gKGNzQWZ0ZXIsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgY3NCZWZvcmUgPSBiZWZvcmVGaWx0ZXJlZCAmJiBiZWZvcmVGaWx0ZXJlZFtpbmRleF07XG4gICAgICAgICAgICBpZiAoY3NCZWZvcmUgJiYgY3NCZWZvcmUuY29sSWQgIT09IGNzQWZ0ZXIuY29sSWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JpZENvbCA9IF90aGlzLmdldEdyaWRDb2x1bW4oY3NCZWZvcmUuY29sSWQpO1xuICAgICAgICAgICAgICAgIGlmIChncmlkQ29sKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vdmVkQ29sdW1ucy5wdXNoKGdyaWRDb2wpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghbW92ZWRDb2x1bW5zLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQsXG4gICAgICAgICAgICBjb2x1bW5zOiBtb3ZlZENvbHVtbnMsXG4gICAgICAgICAgICBjb2x1bW46IG51bGwsXG4gICAgICAgICAgICBzb3VyY2U6IHNvdXJjZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zeW5jQ29sdW1uV2l0aFN0YXRlSXRlbSA9IGZ1bmN0aW9uIChjb2x1bW4sIHN0YXRlSXRlbSwgZGVmYXVsdFN0YXRlLCByb3dHcm91cEluZGV4ZXMsIHBpdm90SW5kZXhlcywgYXV0b0NvbCwgc291cmNlKSB7XG4gICAgICAgIGlmICghY29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGdldFZhbHVlID0gZnVuY3Rpb24gKGtleTEsIGtleTIpIHtcbiAgICAgICAgICAgIHZhciBvYmogPSB7IHZhbHVlMTogdW5kZWZpbmVkLCB2YWx1ZTI6IHVuZGVmaW5lZCB9O1xuICAgICAgICAgICAgdmFyIGNhbGN1bGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzdGF0ZUl0ZW0pIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGVJdGVtW2tleTFdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqLnZhbHVlMSA9IHN0YXRlSXRlbVtrZXkxXTtcbiAgICAgICAgICAgICAgICAgICAgY2FsY3VsYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChleGlzdHMoa2V5MikgJiYgc3RhdGVJdGVtW2tleTJdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqLnZhbHVlMiA9IHN0YXRlSXRlbVtrZXkyXTtcbiAgICAgICAgICAgICAgICAgICAgY2FsY3VsYXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFjYWxjdWxhdGVkICYmIGRlZmF1bHRTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmIChkZWZhdWx0U3RhdGVba2V5MV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBvYmoudmFsdWUxID0gZGVmYXVsdFN0YXRlW2tleTFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RzKGtleTIpICYmIGRlZmF1bHRTdGF0ZVtrZXkyXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iai52YWx1ZTIgPSBkZWZhdWx0U3RhdGVba2V5Ml07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gZm9sbG93aW5nIGVuc3VyZXMgd2UgYXJlIGxlZnQgd2l0aCBib29sZWFuIHRydWUgb3IgZmFsc2UsIGVnIGNvbnZlcnRzIChudWxsLCB1bmRlZmluZWQsIDApIGFsbCB0byB0cnVlXG4gICAgICAgIHZhciBoaWRlID0gZ2V0VmFsdWUoJ2hpZGUnKS52YWx1ZTE7XG4gICAgICAgIGlmIChoaWRlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbHVtbi5zZXRWaXNpYmxlKCFoaWRlLCBzb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHNldHMgcGlubmVkIHRvICdsZWZ0JyBvciAncmlnaHQnXG4gICAgICAgIHZhciBwaW5uZWQgPSBnZXRWYWx1ZSgncGlubmVkJykudmFsdWUxO1xuICAgICAgICBpZiAocGlubmVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbHVtbi5zZXRQaW5uZWQocGlubmVkKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB3aWR0aCBwcm92aWRlZCBhbmQgdmFsaWQsIHVzZSBpdCwgb3RoZXJ3aXNlIHN0aWNrIHdpdGggdGhlIG9sZCB3aWR0aFxuICAgICAgICB2YXIgbWluQ29sV2lkdGggPSB0aGlzLmNvbHVtblV0aWxzLmNhbGN1bGF0ZUNvbE1pbldpZHRoKGNvbHVtbi5nZXRDb2xEZWYoKSk7XG4gICAgICAgIC8vIGZsZXhcbiAgICAgICAgdmFyIGZsZXggPSBnZXRWYWx1ZSgnZmxleCcpLnZhbHVlMTtcbiAgICAgICAgaWYgKGZsZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY29sdW1uLnNldEZsZXgoZmxleCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2lkdGggLSB3ZSBvbmx5IHNldCB3aWR0aCBpZiBjb2x1bW4gaXMgbm90IGZsZXhpbmdcbiAgICAgICAgdmFyIG5vRmxleFRoaXNDb2wgPSBjb2x1bW4uZ2V0RmxleCgpIDw9IDA7XG4gICAgICAgIGlmIChub0ZsZXhUaGlzQ29sKSB7XG4gICAgICAgICAgICAvLyBib3RoIG51bGwgYW5kIHVuZGVmaW5lZCBtZWFucyB3ZSBza2lwLCBhcyBpdCdzIG5vdCBwb3NzaWJsZSB0byAnY2xlYXInIHdpZHRoIChhIGNvbHVtbiBtdXN0IGhhdmUgYSB3aWR0aClcbiAgICAgICAgICAgIHZhciB3aWR0aCA9IGdldFZhbHVlKCd3aWR0aCcpLnZhbHVlMTtcbiAgICAgICAgICAgIGlmICh3aWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1pbkNvbFdpZHRoICE9IG51bGwgJiYgd2lkdGggPj0gbWluQ29sV2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldEFjdHVhbFdpZHRoKHdpZHRoLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgc29ydCA9IGdldFZhbHVlKCdzb3J0JykudmFsdWUxO1xuICAgICAgICBpZiAoc29ydCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZiAoc29ydCA9PT0gQ29uc3RhbnRzLlNPUlRfREVTQyB8fCBzb3J0ID09PSBDb25zdGFudHMuU09SVF9BU0MpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW4uc2V0U29ydChzb3J0LCBzb3VyY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29sdW1uLnNldFNvcnQodW5kZWZpbmVkLCBzb3VyY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBzb3J0SW5kZXggPSBnZXRWYWx1ZSgnc29ydEluZGV4JykudmFsdWUxO1xuICAgICAgICBpZiAoc29ydEluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbHVtbi5zZXRTb3J0SW5kZXgoc29ydEluZGV4KTtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBkbyBub3QgZG8gYWdnRnVuYywgcm93R3JvdXAgb3IgcGl2b3QgZm9yIGF1dG8gY29scyBvciBzZWNvbmRhcnkgY29sc1xuICAgICAgICBpZiAoYXV0b0NvbCB8fCAhY29sdW1uLmlzUHJpbWFyeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFnZ0Z1bmMgPSBnZXRWYWx1ZSgnYWdnRnVuYycpLnZhbHVlMTtcbiAgICAgICAgaWYgKGFnZ0Z1bmMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBhZ2dGdW5jID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGNvbHVtbi5zZXRBZ2dGdW5jKGFnZ0Z1bmMpO1xuICAgICAgICAgICAgICAgIGlmICghY29sdW1uLmlzVmFsdWVBY3RpdmUoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4uc2V0VmFsdWVBY3RpdmUodHJ1ZSwgc291cmNlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZUNvbHVtbnMucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChleGlzdHMoYWdnRnVuYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzdGF0ZUl0ZW0uYWdnRnVuYyBtdXN0IGJlIGEgc3RyaW5nLiBpZiB1c2luZyB5b3VyIG93biBhZ2dyZWdhdGlvbiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdmdW5jdGlvbnMsIHJlZ2lzdGVyIHRoZSBmdW5jdGlvbnMgZmlyc3QgYmVmb3JlIHVzaW5nIHRoZW0gaW4gZ2V0L3NldCBzdGF0ZS4gVGhpcyBpcyBiZWNhdXNlIGl0IGlzICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2ludGVuZGVkIGZvciB0aGUgY29sdW1uIHN0YXRlIHRvIGJlIHN0b3JlZCBhbmQgcmV0cmlldmVkIGFzIHNpbXBsZSBKU09OLicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBOb3RlOiB3ZSBkbyBub3QgY2FsbCBjb2x1bW4uc2V0QWdnRnVuYyhudWxsKSwgc28gdGhhdCBuZXh0IHRpbWUgd2UgYWdncmVnYXRlXG4gICAgICAgICAgICAgICAgLy8gYnkgdGhpcyBjb2x1bW4gKGVnIGRyYWcgdGhlIGNvbHVtbiB0byB0aGUgYWdnIHNlY3Rpb24gaW50IGhlIHRvb2xwYW5lbCkgaXQgd2lsbFxuICAgICAgICAgICAgICAgIC8vIGRlZmF1bHQgdG8gdGhlIGxhc3QgYWdncmVnYXRpb24gZnVuY3Rpb24uXG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi5pc1ZhbHVlQWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldFZhbHVlQWN0aXZlKGZhbHNlLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkodGhpcy52YWx1ZUNvbHVtbnMsIGNvbHVtbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBfYSA9IGdldFZhbHVlKCdyb3dHcm91cCcsICdyb3dHcm91cEluZGV4JyksIHJvd0dyb3VwID0gX2EudmFsdWUxLCByb3dHcm91cEluZGV4ID0gX2EudmFsdWUyO1xuICAgICAgICBpZiAocm93R3JvdXAgIT09IHVuZGVmaW5lZCB8fCByb3dHcm91cEluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygcm93R3JvdXBJbmRleCA9PT0gJ251bWJlcicgfHwgcm93R3JvdXApIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbi5pc1Jvd0dyb3VwQWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldFJvd0dyb3VwQWN0aXZlKHRydWUsIHNvdXJjZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucm93R3JvdXBDb2x1bW5zLnB1c2goY29sdW1uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJvd0dyb3VwSW5kZXhlcyAmJiB0eXBlb2Ygcm93R3JvdXBJbmRleCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93R3JvdXBJbmRleGVzW2NvbHVtbi5nZXRJZCgpXSA9IHJvd0dyb3VwSW5kZXg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi5pc1Jvd0dyb3VwQWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldFJvd0dyb3VwQWN0aXZlKGZhbHNlLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkodGhpcy5yb3dHcm91cENvbHVtbnMsIGNvbHVtbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBfYiA9IGdldFZhbHVlKCdwaXZvdCcsICdwaXZvdEluZGV4JyksIHBpdm90ID0gX2IudmFsdWUxLCBwaXZvdEluZGV4ID0gX2IudmFsdWUyO1xuICAgICAgICBpZiAocGl2b3QgIT09IHVuZGVmaW5lZCB8fCBwaXZvdEluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcGl2b3RJbmRleCA9PT0gJ251bWJlcicgfHwgcGl2b3QpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbi5pc1Bpdm90QWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldFBpdm90QWN0aXZlKHRydWUsIHNvdXJjZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGl2b3RDb2x1bW5zLnB1c2goY29sdW1uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHBpdm90SW5kZXhlcyAmJiB0eXBlb2YgcGl2b3RJbmRleCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgcGl2b3RJbmRleGVzW2NvbHVtbi5nZXRJZCgpXSA9IHBpdm90SW5kZXg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbi5pc1Bpdm90QWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldFBpdm90QWN0aXZlKGZhbHNlLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkodGhpcy5waXZvdENvbHVtbnMsIGNvbHVtbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0R3JpZENvbHVtbnMgPSBmdW5jdGlvbiAoa2V5cykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW5zKGtleXMsIHRoaXMuZ2V0R3JpZENvbHVtbi5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRDb2x1bW5zID0gZnVuY3Rpb24gKGtleXMsIGNvbHVtbkxvb2t1cENhbGxiYWNrKSB7XG4gICAgICAgIHZhciBmb3VuZENvbHVtbnMgPSBbXTtcbiAgICAgICAgaWYgKGtleXMpIHtcbiAgICAgICAgICAgIGtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IGNvbHVtbkxvb2t1cENhbGxiYWNrKGtleSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBmb3VuZENvbHVtbnMucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb3VuZENvbHVtbnM7XG4gICAgfTtcbiAgICAvLyB1c2VkIGJ5IGdyb3dHcm91cFBhbmVsXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldENvbHVtbldpdGhWYWxpZGF0aW9uID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmdldEdyaWRDb2x1bW4oa2V5KTtcbiAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY291bGQgbm90IGZpbmQgY29sdW1uICcgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2x1bW47XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0UHJpbWFyeUNvbHVtbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgaWYgKCF0aGlzLnByaW1hcnlDb2x1bW5zKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW4oa2V5LCB0aGlzLnByaW1hcnlDb2x1bW5zLCB0aGlzLnByaW1hcnlDb2x1bW5zTWFwKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRHcmlkQ29sdW1uID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW4oa2V5LCB0aGlzLmdyaWRDb2x1bW5zLCB0aGlzLmdyaWRDb2x1bW5zTWFwKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRTZWNvbmRhcnlDb2x1bW4gPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGlmICghdGhpcy5zZWNvbmRhcnlDb2x1bW5zKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW4oa2V5LCB0aGlzLnNlY29uZGFyeUNvbHVtbnMsIHRoaXMuc2Vjb25kYXJ5Q29sdW1uc01hcCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0Q29sdW1uID0gZnVuY3Rpb24gKGtleSwgY29sdW1uTGlzdCwgY29sdW1uTWFwKSB7XG4gICAgICAgIGlmICgha2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvLyBtb3N0IG9mIHRoZSB0aW1lIHRoaXMgbWV0aG9kIGdldHMgY2FsbGVkIHRoZSBrZXkgaXMgYSBzdHJpbmcsIHNvIHdlIHB1dCB0aGlzIHNob3J0Y3V0IGluXG4gICAgICAgIC8vIGZvciBwZXJmb3JtYW5jZSByZWFzb25zLCB0byBzZWUgaWYgd2UgY2FuIG1hdGNoIGZvciBJRCAoaXQgZG9lc24ndCBkbyBhdXRvIGNvbHVtbnMsIHRoYXQncyBkb25lIGJlbG93KVxuICAgICAgICBpZiAodHlwZW9mIGtleSA9PSAnc3RyaW5nJyAmJiBjb2x1bW5NYXBba2V5XSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbk1hcFtrZXldO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29sdW1uTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29sdW1uc01hdGNoKGNvbHVtbkxpc3RbaV0sIGtleSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29sdW1uTGlzdFtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRBdXRvQ29sdW1uKGtleSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0U291cmNlQ29sdW1uc0Zvckdyb3VwQ29sdW1uID0gZnVuY3Rpb24gKGdyb3VwQ29sKSB7XG4gICAgICAgIHZhciBzb3VyY2VDb2x1bW5JZCA9IGdyb3VwQ29sLmdldENvbERlZigpLnNob3dSb3dHcm91cDtcbiAgICAgICAgaWYgKCFzb3VyY2VDb2x1bW5JZCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNvdXJjZUNvbHVtbklkID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dHcm91cENvbHVtbnMuc2xpY2UoMCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuZ2V0UHJpbWFyeUNvbHVtbihzb3VyY2VDb2x1bW5JZCk7XG4gICAgICAgIHJldHVybiBjb2x1bW4gPyBbY29sdW1uXSA6IG51bGw7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0QXV0b0NvbHVtbiA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmdyb3VwQXV0b0NvbHVtbnMgfHxcbiAgICAgICAgICAgICFleGlzdHModGhpcy5ncm91cEF1dG9Db2x1bW5zKSB8fFxuICAgICAgICAgICAgbWlzc2luZyh0aGlzLmdyb3VwQXV0b0NvbHVtbnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5ncm91cEF1dG9Db2x1bW5zLmZpbmQoZnVuY3Rpb24gKGdyb3VwQ29sKSB7IHJldHVybiBfdGhpcy5jb2x1bW5zTWF0Y2goZ3JvdXBDb2wsIGtleSk7IH0pIHx8IG51bGw7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuY29sdW1uc01hdGNoID0gZnVuY3Rpb24gKGNvbHVtbiwga2V5KSB7XG4gICAgICAgIHZhciBjb2x1bW5NYXRjaGVzID0gY29sdW1uID09PSBrZXk7XG4gICAgICAgIHZhciBjb2xEZWZNYXRjaGVzID0gY29sdW1uLmdldENvbERlZigpID09PSBrZXk7XG4gICAgICAgIHZhciBpZE1hdGNoZXMgPSBjb2x1bW4uZ2V0Q29sSWQoKSA9PSBrZXk7XG4gICAgICAgIHJldHVybiBjb2x1bW5NYXRjaGVzIHx8IGNvbERlZk1hdGNoZXMgfHwgaWRNYXRjaGVzO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldERpc3BsYXlOYW1lRm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbiwgbG9jYXRpb24sIGluY2x1ZGVBZ2dGdW5jKSB7XG4gICAgICAgIGlmIChpbmNsdWRlQWdnRnVuYyA9PT0gdm9pZCAwKSB7IGluY2x1ZGVBZ2dGdW5jID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoZWFkZXJOYW1lID0gdGhpcy5nZXRIZWFkZXJOYW1lKGNvbHVtbi5nZXRDb2xEZWYoKSwgY29sdW1uLCBudWxsLCBudWxsLCBsb2NhdGlvbik7XG4gICAgICAgIGlmIChpbmNsdWRlQWdnRnVuYykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud3JhcEhlYWRlck5hbWVXaXRoQWdnRnVuYyhjb2x1bW4sIGhlYWRlck5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoZWFkZXJOYW1lO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldERpc3BsYXlOYW1lRm9yUHJvdmlkZWRDb2x1bW5Hcm91cCA9IGZ1bmN0aW9uIChjb2x1bW5Hcm91cCwgcHJvdmlkZWRDb2x1bW5Hcm91cCwgbG9jYXRpb24pIHtcbiAgICAgICAgdmFyIGNvbEdyb3VwRGVmID0gcHJvdmlkZWRDb2x1bW5Hcm91cCA/IHByb3ZpZGVkQ29sdW1uR3JvdXAuZ2V0Q29sR3JvdXBEZWYoKSA6IG51bGw7XG4gICAgICAgIGlmIChjb2xHcm91cERlZikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SGVhZGVyTmFtZShjb2xHcm91cERlZiwgbnVsbCwgY29sdW1uR3JvdXAsIHByb3ZpZGVkQ29sdW1uR3JvdXAsIGxvY2F0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXREaXNwbGF5TmFtZUZvckNvbHVtbkdyb3VwID0gZnVuY3Rpb24gKGNvbHVtbkdyb3VwLCBsb2NhdGlvbikge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXREaXNwbGF5TmFtZUZvclByb3ZpZGVkQ29sdW1uR3JvdXAoY29sdW1uR3JvdXAsIGNvbHVtbkdyb3VwLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoKSwgbG9jYXRpb24pO1xuICAgIH07XG4gICAgLy8gbG9jYXRpb24gaXMgd2hlcmUgdGhlIGNvbHVtbiBpcyBnb2luZyB0byBhcHBlYXIsIGllIHdobyBpcyBjYWxsaW5nIHVzXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldEhlYWRlck5hbWUgPSBmdW5jdGlvbiAoY29sRGVmLCBjb2x1bW4sIGNvbHVtbkdyb3VwLCBwcm92aWRlZENvbHVtbkdyb3VwLCBsb2NhdGlvbikge1xuICAgICAgICB2YXIgaGVhZGVyVmFsdWVHZXR0ZXIgPSBjb2xEZWYuaGVhZGVyVmFsdWVHZXR0ZXI7XG4gICAgICAgIGlmIChoZWFkZXJWYWx1ZUdldHRlcikge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICBjb2xEZWY6IGNvbERlZixcbiAgICAgICAgICAgICAgICBjb2x1bW46IGNvbHVtbixcbiAgICAgICAgICAgICAgICBjb2x1bW5Hcm91cDogY29sdW1uR3JvdXAsXG4gICAgICAgICAgICAgICAgcHJvdmlkZWRDb2x1bW5Hcm91cDogcHJvdmlkZWRDb2x1bW5Hcm91cCxcbiAgICAgICAgICAgICAgICBsb2NhdGlvbjogbG9jYXRpb24sXG4gICAgICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaGVhZGVyVmFsdWVHZXR0ZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAvLyB2YWx1ZUdldHRlciBpcyBhIGZ1bmN0aW9uLCBzbyBqdXN0IGNhbGwgaXRcbiAgICAgICAgICAgICAgICByZXR1cm4gaGVhZGVyVmFsdWVHZXR0ZXIocGFyYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBoZWFkZXJWYWx1ZUdldHRlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAvLyB2YWx1ZUdldHRlciBpcyBhbiBleHByZXNzaW9uLCBzbyBleGVjdXRlIHRoZSBleHByZXNzaW9uXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhwcmVzc2lvblNlcnZpY2UuZXZhbHVhdGUoaGVhZGVyVmFsdWVHZXR0ZXIsIHBhcmFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ2FnLWdyaWQ6IGhlYWRlclZhbHVlR2V0dGVyIG11c3QgYmUgYSBmdW5jdGlvbiBvciBhIHN0cmluZycpO1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbERlZi5oZWFkZXJOYW1lICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBjb2xEZWYuaGVhZGVyTmFtZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb2xEZWYuZmllbGQpIHtcbiAgICAgICAgICAgIHJldHVybiBjYW1lbENhc2VUb0h1bWFuVGV4dChjb2xEZWYuZmllbGQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS53cmFwSGVhZGVyTmFtZVdpdGhBZ2dGdW5jID0gZnVuY3Rpb24gKGNvbHVtbiwgaGVhZGVyTmFtZSkge1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0FnZ0Z1bmNJbkhlYWRlcigpKSB7XG4gICAgICAgICAgICByZXR1cm4gaGVhZGVyTmFtZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvbmx5IGNvbHVtbnMgd2l0aCBhZ2dyZWdhdGlvbiBhY3RpdmUgY2FuIGhhdmUgYWdncmVnYXRpb25zXG4gICAgICAgIHZhciBwaXZvdFZhbHVlQ29sdW1uID0gY29sdW1uLmdldENvbERlZigpLnBpdm90VmFsdWVDb2x1bW47XG4gICAgICAgIHZhciBwaXZvdEFjdGl2ZU9uVGhpc0NvbHVtbiA9IGV4aXN0cyhwaXZvdFZhbHVlQ29sdW1uKTtcbiAgICAgICAgdmFyIGFnZ0Z1bmMgPSBudWxsO1xuICAgICAgICB2YXIgYWdnRnVuY0ZvdW5kO1xuICAgICAgICAvLyBvdGhlcndpc2Ugd2UgaGF2ZSBhIG1lYXN1cmUgdGhhdCBpcyBhY3RpdmUsIGFuZCB3ZSBhcmUgZG9pbmcgYWdncmVnYXRpb24gb24gaXRcbiAgICAgICAgaWYgKHBpdm90QWN0aXZlT25UaGlzQ29sdW1uKSB7XG4gICAgICAgICAgICB2YXIgaXNDb2xsYXBzZWRIZWFkZXJFbmFibGVkID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSZW1vdmVQaXZvdEhlYWRlclJvd1doZW5TaW5nbGVWYWx1ZUNvbHVtbigpICYmIHRoaXMudmFsdWVDb2x1bW5zLmxlbmd0aCA9PT0gMTtcbiAgICAgICAgICAgIHZhciBpc1RvdGFsQ29sdW1uID0gY29sdW1uLmdldENvbERlZigpLnBpdm90VG90YWxDb2x1bW5JZHMgIT09IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChpc0NvbGxhcHNlZEhlYWRlckVuYWJsZWQgJiYgIWlzVG90YWxDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaGVhZGVyTmFtZTsgLy8gU2tpcCBkZWNvcmF0aW5nIHRoZSBoZWFkZXIgLSBpbiB0aGlzIGNhc2UgdGhlIGxhYmVsIGlzIHRoZSBwaXZvdCBrZXksIG5vdCB0aGUgdmFsdWUgY29sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZ2dGdW5jID0gcGl2b3RWYWx1ZUNvbHVtbiA/IHBpdm90VmFsdWVDb2x1bW4uZ2V0QWdnRnVuYygpIDogbnVsbDtcbiAgICAgICAgICAgIGFnZ0Z1bmNGb3VuZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgbWVhc3VyZUFjdGl2ZSA9IGNvbHVtbi5pc1ZhbHVlQWN0aXZlKCk7XG4gICAgICAgICAgICB2YXIgYWdncmVnYXRpb25QcmVzZW50ID0gdGhpcy5waXZvdE1vZGUgfHwgIXRoaXMuaXNSb3dHcm91cEVtcHR5KCk7XG4gICAgICAgICAgICBpZiAobWVhc3VyZUFjdGl2ZSAmJiBhZ2dyZWdhdGlvblByZXNlbnQpIHtcbiAgICAgICAgICAgICAgICBhZ2dGdW5jID0gY29sdW1uLmdldEFnZ0Z1bmMoKTtcbiAgICAgICAgICAgICAgICBhZ2dGdW5jRm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYWdnRnVuY0ZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFnZ0Z1bmNGb3VuZCkge1xuICAgICAgICAgICAgdmFyIGFnZ0Z1bmNTdHJpbmcgPSAodHlwZW9mIGFnZ0Z1bmMgPT09ICdzdHJpbmcnKSA/IGFnZ0Z1bmMgOiAnZnVuYyc7XG4gICAgICAgICAgICB2YXIgbG9jYWxlVGV4dEZ1bmMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMb2NhbGVUZXh0RnVuYygpO1xuICAgICAgICAgICAgdmFyIGFnZ0Z1bmNTdHJpbmdUcmFuc2xhdGVkID0gbG9jYWxlVGV4dEZ1bmMoYWdnRnVuY1N0cmluZywgYWdnRnVuY1N0cmluZyk7XG4gICAgICAgICAgICByZXR1cm4gYWdnRnVuY1N0cmluZ1RyYW5zbGF0ZWQgKyBcIihcIiArIGhlYWRlck5hbWUgKyBcIilcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGVhZGVyTmFtZTtcbiAgICB9O1xuICAgIC8vIHJldHVybnMgdGhlIGdyb3VwIHdpdGggbWF0Y2hpbmcgY29sSWQgYW5kIGluc3RhbmNlSWQuIElmIGluc3RhbmNlSWQgaXMgbWlzc2luZyxcbiAgICAvLyBtYXRjaGVzIG9ubHkgb24gdGhlIGNvbElkLlxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRDb2x1bW5Hcm91cCA9IGZ1bmN0aW9uIChjb2xJZCwgaW5zdGFuY2VJZCkge1xuICAgICAgICBpZiAoIWNvbElkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29sSWQgaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbElkO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhbGxDb2x1bW5Hcm91cHMgPSB0aGlzLmdldEFsbERpc3BsYXllZFRyZWVzKCk7XG4gICAgICAgIHZhciBjaGVja0luc3RhbmNlSWQgPSB0eXBlb2YgaW5zdGFuY2VJZCA9PT0gJ251bWJlcic7XG4gICAgICAgIHZhciByZXN1bHQgPSBudWxsO1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RBbGxDb2x1bW5UcmVlU2VhcmNoKGFsbENvbHVtbkdyb3VwcywgZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW5Hcm91cCA9IGNoaWxkO1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVkID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgIGlmIChjaGVja0luc3RhbmNlSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlZCA9IGNvbElkID09PSBjb2x1bW5Hcm91cC5nZXRHcm91cElkKCkgJiYgaW5zdGFuY2VJZCA9PT0gY29sdW1uR3JvdXAuZ2V0SW5zdGFuY2VJZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlZCA9IGNvbElkID09PSBjb2x1bW5Hcm91cC5nZXRHcm91cElkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtYXRjaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNvbHVtbkdyb3VwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuaXNSZWFkeSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVhZHk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZXh0cmFjdFZhbHVlQ29sdW1ucyA9IGZ1bmN0aW9uIChzb3VyY2UsIG9sZFByaW1hcnlDb2x1bW5zKSB7XG4gICAgICAgIHRoaXMudmFsdWVDb2x1bW5zID0gdGhpcy5leHRyYWN0Q29sdW1ucyhvbGRQcmltYXJ5Q29sdW1ucywgdGhpcy52YWx1ZUNvbHVtbnMsIGZ1bmN0aW9uIChjb2wsIGZsYWcpIHsgcmV0dXJuIGNvbC5zZXRWYWx1ZUFjdGl2ZShmbGFnLCBzb3VyY2UpOyB9LCBcbiAgICAgICAgLy8gYWdnRnVuYyBkb2Vzbid0IGhhdmUgaW5kZXggdmFyaWFudCwgY29zIG9yZGVyIG9mIHZhbHVlIGNvbHMgZG9lc24ndCBtYXR0ZXIsIHNvIGFsd2F5cyByZXR1cm4gbnVsbFxuICAgICAgICBmdW5jdGlvbiAoKSB7IHJldHVybiB1bmRlZmluZWQ7IH0sIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSwgXG4gICAgICAgIC8vIGFnZ0Z1bmMgaXMgYSBzdHJpbmcsIHNvIHJldHVybiBpdCdzIGV4aXN0ZW5jZVxuICAgICAgICBmdW5jdGlvbiAoY29sRGVmKSB7XG4gICAgICAgICAgICB2YXIgYWdnRnVuYyA9IGNvbERlZi5hZ2dGdW5jO1xuICAgICAgICAgICAgLy8gbnVsbCBvciBlbXB0eSBzdHJpbmcgbWVhbnMgY2xlYXJcbiAgICAgICAgICAgIGlmIChhZ2dGdW5jID09PSBudWxsIHx8IGFnZ0Z1bmMgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYWdnRnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICEhYWdnRnVuYztcbiAgICAgICAgfSwgZnVuY3Rpb24gKGNvbERlZikge1xuICAgICAgICAgICAgLy8gcmV0dXJuIGZhbHNlIGlmIGFueSBvZiB0aGUgZm9sbG93aW5nOiBudWxsLCB1bmRlZmluZWQsIGVtcHR5IHN0cmluZ1xuICAgICAgICAgICAgcmV0dXJuIGNvbERlZi5pbml0aWFsQWdnRnVuYyAhPSBudWxsICYmIGNvbERlZi5pbml0aWFsQWdnRnVuYyAhPSAnJztcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGFsbCBuZXcgY29sdW1ucyBhZGRlZCB3aWxsIGhhdmUgYWdnRnVuYyBtaXNzaW5nLCBzbyBzZXQgaXQgdG8gd2hhdCBpcyBpbiB0aGUgY29sRGVmXG4gICAgICAgIHRoaXMudmFsdWVDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgdmFyIGNvbERlZiA9IGNvbC5nZXRDb2xEZWYoKTtcbiAgICAgICAgICAgIC8vIGlmIGFnZ0Z1bmMgcHJvdmlkZWQsIHdlIGFsd2F5cyBvdmVycmlkZSwgYXMgcmVhY3RpdmUgcHJvcGVydHlcbiAgICAgICAgICAgIGlmIChjb2xEZWYuYWdnRnVuYyAhPSBudWxsICYmIGNvbERlZi5hZ2dGdW5jICE9ICcnKSB7XG4gICAgICAgICAgICAgICAgY29sLnNldEFnZ0Z1bmMoY29sRGVmLmFnZ0Z1bmMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIHVzZSBpbml0aWFsQWdnRnVuYyBvbmx5IGlmIG5vIGFnZyBmdW5jIHNldCAtIHdoaWNoIGhhcHBlbnMgd2hlbiBuZXcgY29sdW1uIG9ubHlcbiAgICAgICAgICAgICAgICBpZiAoIWNvbC5nZXRBZ2dGdW5jKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sLnNldEFnZ0Z1bmMoY29sRGVmLmluaXRpYWxBZ2dGdW5jKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmV4dHJhY3RSb3dHcm91cENvbHVtbnMgPSBmdW5jdGlvbiAoc291cmNlLCBvbGRQcmltYXJ5Q29sdW1ucykge1xuICAgICAgICB0aGlzLnJvd0dyb3VwQ29sdW1ucyA9IHRoaXMuZXh0cmFjdENvbHVtbnMob2xkUHJpbWFyeUNvbHVtbnMsIHRoaXMucm93R3JvdXBDb2x1bW5zLCBmdW5jdGlvbiAoY29sLCBmbGFnKSB7IHJldHVybiBjb2wuc2V0Um93R3JvdXBBY3RpdmUoZmxhZywgc291cmNlKTsgfSwgZnVuY3Rpb24gKGNvbERlZikgeyByZXR1cm4gY29sRGVmLnJvd0dyb3VwSW5kZXg7IH0sIGZ1bmN0aW9uIChjb2xEZWYpIHsgcmV0dXJuIGNvbERlZi5pbml0aWFsUm93R3JvdXBJbmRleDsgfSwgZnVuY3Rpb24gKGNvbERlZikgeyByZXR1cm4gY29sRGVmLnJvd0dyb3VwOyB9LCBmdW5jdGlvbiAoY29sRGVmKSB7IHJldHVybiBjb2xEZWYuaW5pdGlhbFJvd0dyb3VwOyB9KTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5leHRyYWN0Q29sdW1ucyA9IGZ1bmN0aW9uIChvbGRQcmltYXJ5Q29sdW1ucywgcHJldmlvdXNDb2xzLCBzZXRGbGFnRnVuYywgZ2V0SW5kZXhGdW5jLCBnZXRJbml0aWFsSW5kZXhGdW5jLCBnZXRWYWx1ZUZ1bmMsIGdldEluaXRpYWxWYWx1ZUZ1bmMpIHtcbiAgICAgICAgaWYgKG9sZFByaW1hcnlDb2x1bW5zID09PSB2b2lkIDApIHsgb2xkUHJpbWFyeUNvbHVtbnMgPSBbXTsgfVxuICAgICAgICBpZiAocHJldmlvdXNDb2xzID09PSB2b2lkIDApIHsgcHJldmlvdXNDb2xzID0gW107IH1cbiAgICAgICAgdmFyIGNvbHNXaXRoSW5kZXggPSBbXTtcbiAgICAgICAgdmFyIGNvbHNXaXRoVmFsdWUgPSBbXTtcbiAgICAgICAgLy8gZ28gdGhvdWdoIGFsbCBjb2xzLlxuICAgICAgICAvLyBpZiB2YWx1ZSwgY2hhbmdlXG4gICAgICAgIC8vIGlmIGRlZmF1bHQgb25seSwgY2hhbmdlIG9ubHkgaWYgbmV3XG4gICAgICAgICh0aGlzLnByaW1hcnlDb2x1bW5zIHx8IFtdKS5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIHZhciBjb2xJc05ldyA9IG9sZFByaW1hcnlDb2x1bW5zLmluZGV4T2YoY29sKSA8IDA7XG4gICAgICAgICAgICB2YXIgY29sRGVmID0gY29sLmdldENvbERlZigpO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gYXR0clRvQm9vbGVhbihnZXRWYWx1ZUZ1bmMoY29sRGVmKSk7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbFZhbHVlID0gYXR0clRvQm9vbGVhbihnZXRJbml0aWFsVmFsdWVGdW5jKGNvbERlZikpO1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gYXR0clRvTnVtYmVyKGdldEluZGV4RnVuYyhjb2xEZWYpKTtcbiAgICAgICAgICAgIHZhciBpbml0aWFsSW5kZXggPSBhdHRyVG9OdW1iZXIoZ2V0SW5pdGlhbEluZGV4RnVuYyhjb2xEZWYpKTtcbiAgICAgICAgICAgIHZhciBpbmNsdWRlO1xuICAgICAgICAgICAgdmFyIHZhbHVlUHJlc2VudCA9IHZhbHVlICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB2YXIgaW5kZXhQcmVzZW50ID0gaW5kZXggIT09IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHZhciBpbml0aWFsVmFsdWVQcmVzZW50ID0gaW5pdGlhbFZhbHVlICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB2YXIgaW5pdGlhbEluZGV4UHJlc2VudCA9IGluaXRpYWxJbmRleCAhPT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKHZhbHVlUHJlc2VudCkge1xuICAgICAgICAgICAgICAgIGluY2x1ZGUgPSB2YWx1ZTsgLy8gYm9vbGVhbiB2YWx1ZSBpcyBndWFyYW50ZWVkIGFzIGF0dHJUb0Jvb2xlYW4oKSBpcyB1c2VkIGFib3ZlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpbmRleFByZXNlbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgY29sIGlzIG5ldyB3ZSBkb24ndCB3YW50IHRvIHVzZSB0aGUgZGVmYXVsdCAvIGluaXRpYWwgaWYgaW5kZXggaXMgc2V0IHRvIG51bGwuIFNpbWlsYXJseSxcbiAgICAgICAgICAgICAgICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byBpbmNsdWRlIHRoZSBwcm9wZXJ0eSBmb3IgZXhpc3RpbmcgY29sdW1ucywgaS5lLiB3ZSB3YW50IHRvICdjbGVhcicgaXQuXG4gICAgICAgICAgICAgICAgICAgIGluY2x1ZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG5vdGUgdGhhdCAnbnVsbCA+PSAwJyBldmFsdWF0ZXMgdG8gdHJ1ZSB3aGljaCBtZWFucyAncm93R3JvdXBJbmRleCA9IG51bGwnIHdvdWxkIGVuYWJsZSByb3dcbiAgICAgICAgICAgICAgICAgICAgLy8gZ3JvdXBpbmcgaWYgdGhlIG51bGwgY2hlY2sgZGlkbid0IGV4aXN0IGFib3ZlLlxuICAgICAgICAgICAgICAgICAgICBpbmNsdWRlID0gaW5kZXggPj0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoY29sSXNOZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYXMgbm8gdmFsdWUgb3IgaW5kZXggaXMgJ3ByZXNlbnQnIHdlIHVzZSB0aGUgZGVmYXVsdCAvIGluaXRpYWwgd2hlbiBjb2wgaXMgbmV3XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbml0aWFsVmFsdWVQcmVzZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlID0gaW5pdGlhbFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGluaXRpYWxJbmRleFByZXNlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGUgPSBpbml0aWFsSW5kZXggIT0gbnVsbCAmJiBpbml0aWFsSW5kZXggPj0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGluY2x1ZGUgaXQgaWYgaW5jbHVkZWQgbGFzdCB0aW1lLCBlLmcuIGlmIHdlIGFyZSBleHRyYWN0aW5nIHJvdyBncm91cCBjb2xzIGFuZCB0aGlzIGNvbFxuICAgICAgICAgICAgICAgICAgICAvLyBpcyBhbiBleGlzdGluZyByb3cgZ3JvdXAgY29sIChpLmUuIGl0IGV4aXN0cyBpbiAncHJldmlvdXNDb2xzJykgdGhlbiB3ZSBzaG91bGQgaW5jbHVkZSBpdC5cbiAgICAgICAgICAgICAgICAgICAgaW5jbHVkZSA9IHByZXZpb3VzQ29scy5pbmRleE9mKGNvbCkgPj0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5jbHVkZSkge1xuICAgICAgICAgICAgICAgIHZhciB1c2VJbmRleCA9IGNvbElzTmV3ID8gKGluZGV4ICE9IG51bGwgfHwgaW5pdGlhbEluZGV4ICE9IG51bGwpIDogaW5kZXggIT0gbnVsbDtcbiAgICAgICAgICAgICAgICB1c2VJbmRleCA/IGNvbHNXaXRoSW5kZXgucHVzaChjb2wpIDogY29sc1dpdGhWYWx1ZS5wdXNoKGNvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgZ2V0SW5kZXhGb3JDb2wgPSBmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICB2YXIgaW5kZXggPSBnZXRJbmRleEZ1bmMoY29sLmdldENvbERlZigpKTtcbiAgICAgICAgICAgIHZhciBkZWZhdWx0SW5kZXggPSBnZXRJbml0aWFsSW5kZXhGdW5jKGNvbC5nZXRDb2xEZWYoKSk7XG4gICAgICAgICAgICByZXR1cm4gaW5kZXggIT0gbnVsbCA/IGluZGV4IDogZGVmYXVsdEluZGV4O1xuICAgICAgICB9O1xuICAgICAgICAvLyBzb3J0IGNvbHMgd2l0aCBpbmRleCwgYW5kIGFkZCB0aGVzZSBmaXJzdFxuICAgICAgICBjb2xzV2l0aEluZGV4LnNvcnQoZnVuY3Rpb24gKGNvbEEsIGNvbEIpIHtcbiAgICAgICAgICAgIHZhciBpbmRleEEgPSBnZXRJbmRleEZvckNvbChjb2xBKTtcbiAgICAgICAgICAgIHZhciBpbmRleEIgPSBnZXRJbmRleEZvckNvbChjb2xCKTtcbiAgICAgICAgICAgIGlmIChpbmRleEEgPT09IGluZGV4Qikge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluZGV4QSA8IGluZGV4Qikge1xuICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHJlcyA9IFtdLmNvbmNhdChjb2xzV2l0aEluZGV4KTtcbiAgICAgICAgLy8gc2Vjb25kIGFkZCBjb2x1bW5zIHRoYXQgd2VyZSB0aGVyZSBiZWZvcmUgYW5kIGluIHRoZSBzYW1lIG9yZGVyIGFzIHRoZXkgd2VyZSBiZWZvcmUsXG4gICAgICAgIC8vIHNvIHdlIGFyZSBwcmVzZXJ2aW5nIG9yZGVyIG9mIGN1cnJlbnQgZ3JvdXBpbmcgb2YgY29sdW1ucyB0aGF0IHNpbXBseSBoYXZlIHJvd0dyb3VwPXRydWVcbiAgICAgICAgcHJldmlvdXNDb2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgaWYgKGNvbHNXaXRoVmFsdWUuaW5kZXhPZihjb2wpID49IDApIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChjb2wpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gbGFzdGx5IHB1dCBpbiBhbGwgcmVtYWluaW5nIGNvbHNcbiAgICAgICAgY29sc1dpdGhWYWx1ZS5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIGlmIChyZXMuaW5kZXhPZihjb2wpIDwgMCkge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGNvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBzZXQgZmxhZz1mYWxzZSBmb3IgcmVtb3ZlZCBjb2xzXG4gICAgICAgIHByZXZpb3VzQ29scy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIGlmIChyZXMuaW5kZXhPZihjb2wpIDwgMCkge1xuICAgICAgICAgICAgICAgIHNldEZsYWdGdW5jKGNvbCwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gc2V0IGZsYWc9dHJ1ZSBmb3IgbmV3bHkgYWRkZWQgY29sc1xuICAgICAgICByZXMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICBpZiAocHJldmlvdXNDb2xzLmluZGV4T2YoY29sKSA8IDApIHtcbiAgICAgICAgICAgICAgICBzZXRGbGFnRnVuYyhjb2wsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5leHRyYWN0UGl2b3RDb2x1bW5zID0gZnVuY3Rpb24gKHNvdXJjZSwgb2xkUHJpbWFyeUNvbHVtbnMpIHtcbiAgICAgICAgdGhpcy5waXZvdENvbHVtbnMgPSB0aGlzLmV4dHJhY3RDb2x1bW5zKG9sZFByaW1hcnlDb2x1bW5zLCB0aGlzLnBpdm90Q29sdW1ucywgZnVuY3Rpb24gKGNvbCwgZmxhZykgeyByZXR1cm4gY29sLnNldFBpdm90QWN0aXZlKGZsYWcsIHNvdXJjZSk7IH0sIGZ1bmN0aW9uIChjb2xEZWYpIHsgcmV0dXJuIGNvbERlZi5waXZvdEluZGV4OyB9LCBmdW5jdGlvbiAoY29sRGVmKSB7IHJldHVybiBjb2xEZWYuaW5pdGlhbFBpdm90SW5kZXg7IH0sIGZ1bmN0aW9uIChjb2xEZWYpIHsgcmV0dXJuIGNvbERlZi5waXZvdDsgfSwgZnVuY3Rpb24gKGNvbERlZikgeyByZXR1cm4gY29sRGVmLmluaXRpYWxQaXZvdDsgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUucmVzZXRDb2x1bW5Hcm91cFN0YXRlID0gZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIgc3RhdGVJdGVtcyA9IFtdO1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RPcmlnaW5hbFRyZWVTZWFyY2gobnVsbCwgdGhpcy5wcmltYXJ5Q29sdW1uVHJlZSwgZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBQcm92aWRlZENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbEdyb3VwRGVmID0gY2hpbGQuZ2V0Q29sR3JvdXBEZWYoKTtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBTdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBJZDogY2hpbGQuZ2V0R3JvdXBJZCgpLFxuICAgICAgICAgICAgICAgICAgICBvcGVuOiAhY29sR3JvdXBEZWYgPyB1bmRlZmluZWQgOiBjb2xHcm91cERlZi5vcGVuQnlEZWZhdWx0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBzdGF0ZUl0ZW1zLnB1c2goZ3JvdXBTdGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNldENvbHVtbkdyb3VwU3RhdGUoc3RhdGVJdGVtcywgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRDb2x1bW5Hcm91cFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sdW1uR3JvdXBTdGF0ZSA9IFtdO1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RPcmlnaW5hbFRyZWVTZWFyY2gobnVsbCwgdGhpcy5ncmlkQmFsYW5jZWRUcmVlLCBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBQcm92aWRlZENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgY29sdW1uR3JvdXBTdGF0ZS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBJZDogbm9kZS5nZXRHcm91cElkKCksXG4gICAgICAgICAgICAgICAgICAgIG9wZW46IG5vZGUuaXNFeHBhbmRlZCgpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29sdW1uR3JvdXBTdGF0ZTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXRDb2x1bW5Hcm91cFN0YXRlID0gZnVuY3Rpb24gKHN0YXRlSXRlbXMsIHNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB0aGlzLmNvbHVtbkFuaW1hdGlvblNlcnZpY2Uuc3RhcnQoKTtcbiAgICAgICAgdmFyIGltcGFjdGVkR3JvdXBzID0gW107XG4gICAgICAgIHN0YXRlSXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoc3RhdGVJdGVtKSB7XG4gICAgICAgICAgICB2YXIgZ3JvdXBLZXkgPSBzdGF0ZUl0ZW0uZ3JvdXBJZDtcbiAgICAgICAgICAgIHZhciBuZXdWYWx1ZSA9IHN0YXRlSXRlbS5vcGVuO1xuICAgICAgICAgICAgdmFyIHByb3ZpZGVkQ29sdW1uR3JvdXAgPSBfdGhpcy5nZXRQcm92aWRlZENvbHVtbkdyb3VwKGdyb3VwS2V5KTtcbiAgICAgICAgICAgIGlmICghcHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwcm92aWRlZENvbHVtbkdyb3VwLmlzRXhwYW5kZWQoKSA9PT0gbmV3VmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nKCdjb2x1bW5Hcm91cE9wZW5lZCgnICsgcHJvdmlkZWRDb2x1bW5Hcm91cC5nZXRHcm91cElkKCkgKyAnLCcgKyBuZXdWYWx1ZSArICcpJyk7XG4gICAgICAgICAgICBwcm92aWRlZENvbHVtbkdyb3VwLnNldEV4cGFuZGVkKG5ld1ZhbHVlKTtcbiAgICAgICAgICAgIGltcGFjdGVkR3JvdXBzLnB1c2gocHJvdmlkZWRDb2x1bW5Hcm91cCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnVwZGF0ZUdyb3Vwc0FuZERpc3BsYXllZENvbHVtbnMoc291cmNlKTtcbiAgICAgICAgdGhpcy5zZXRGaXJzdFJpZ2h0QW5kTGFzdExlZnRQaW5uZWQoc291cmNlKTtcbiAgICAgICAgaW1wYWN0ZWRHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAocHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DT0xVTU5fR1JPVVBfT1BFTkVELFxuICAgICAgICAgICAgICAgIGNvbHVtbkdyb3VwOiBwcm92aWRlZENvbHVtbkdyb3VwXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX3RoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jb2x1bW5BbmltYXRpb25TZXJ2aWNlLmZpbmlzaCgpO1xuICAgIH07XG4gICAgLy8gY2FsbGVkIGJ5IGhlYWRlclJlbmRlcmVyIC0gd2hlbiBhIGhlYWRlciBpcyBvcGVuZWQgb3IgY2xvc2VkXG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldENvbHVtbkdyb3VwT3BlbmVkID0gZnVuY3Rpb24gKGtleSwgbmV3VmFsdWUsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICB2YXIga2V5QXNTdHJpbmc7XG4gICAgICAgIGlmIChrZXkgaW5zdGFuY2VvZiBQcm92aWRlZENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICBrZXlBc1N0cmluZyA9IGtleS5nZXRJZCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAga2V5QXNTdHJpbmcgPSBrZXkgfHwgJyc7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRDb2x1bW5Hcm91cFN0YXRlKFt7IGdyb3VwSWQ6IGtleUFzU3RyaW5nLCBvcGVuOiBuZXdWYWx1ZSB9XSwgc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRQcm92aWRlZENvbHVtbkdyb3VwID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAvLyBpZiAoa2V5IGluc3RhbmNlb2YgUHJvdmlkZWRDb2x1bW5Hcm91cCkgeyByZXR1cm4ga2V5OyB9XG4gICAgICAgIGlmICh0eXBlb2Yga2V5ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogZ3JvdXAga2V5IG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UsIHNlYXJjaCBmb3IgdGhlIGNvbHVtbiBncm91cCBieSBpZFxuICAgICAgICB2YXIgcmVzID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb2x1bW5VdGlscy5kZXB0aEZpcnN0T3JpZ2luYWxUcmVlU2VhcmNoKG51bGwsIHRoaXMuZ3JpZEJhbGFuY2VkVHJlZSwgZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgUHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmdldElkKCkgPT09IGtleSkge1xuICAgICAgICAgICAgICAgICAgICByZXMgPSBub2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuY2FsY3VsYXRlQ29sdW1uc0ZvckRpc3BsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb2x1bW5zRm9yRGlzcGxheTtcbiAgICAgICAgaWYgKHRoaXMucGl2b3RNb2RlICYmIG1pc3NpbmcodGhpcy5zZWNvbmRhcnlDb2x1bW5zKSkge1xuICAgICAgICAgICAgLy8gcGl2b3QgbW9kZSBpcyBvbiwgYnV0IHdlIGFyZSBub3QgcGl2b3RpbmcsIHNvIHdlIG9ubHlcbiAgICAgICAgICAgIC8vIHNob3cgY29sdW1ucyB3ZSBhcmUgYWdncmVnYXRpbmcgb25cbiAgICAgICAgICAgIGNvbHVtbnNGb3JEaXNwbGF5ID0gdGhpcy5ncmlkQ29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgICAgIHZhciBpc0F1dG9Hcm91cENvbCA9IF90aGlzLmdyb3VwQXV0b0NvbHVtbnMgJiYgaW5jbHVkZXMoX3RoaXMuZ3JvdXBBdXRvQ29sdW1ucywgY29sdW1uKTtcbiAgICAgICAgICAgICAgICB2YXIgaXNWYWx1ZUNvbCA9IF90aGlzLnZhbHVlQ29sdW1ucyAmJiBpbmNsdWRlcyhfdGhpcy52YWx1ZUNvbHVtbnMsIGNvbHVtbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzQXV0b0dyb3VwQ29sIHx8IGlzVmFsdWVDb2w7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSBjb250aW51ZSBhcyBub3JtYWwuIHRoaXMgY2FuIGJlIHdvcmtpbmcgb24gdGhlIHByaW1hcnlcbiAgICAgICAgICAgIC8vIG9yIHNlY29uZGFyeSBjb2x1bW5zLCB3aGF0ZXZlciB0aGUgZ3JpZENvbHVtbnMgYXJlIHNldCB0b1xuICAgICAgICAgICAgY29sdW1uc0ZvckRpc3BsYXkgPSB0aGlzLmdyaWRDb2x1bW5zLmZpbHRlcihmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgLy8ga2VlcCBjb2wgaWYgYSkgaXQncyBhdXRvLWdyb3VwIG9yIGIpIGl0J3MgdmlzaWJsZVxuICAgICAgICAgICAgICAgIHZhciBpc0F1dG9Hcm91cENvbCA9IF90aGlzLmdyb3VwQXV0b0NvbHVtbnMgJiYgaW5jbHVkZXMoX3RoaXMuZ3JvdXBBdXRvQ29sdW1ucywgY29sdW1uKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNBdXRvR3JvdXBDb2wgfHwgY29sdW1uLmlzVmlzaWJsZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbHVtbnNGb3JEaXNwbGF5O1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmNoZWNrQ29sU3BhbkFjdGl2ZUluQ29scyA9IGZ1bmN0aW9uIChjb2x1bW5zKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIGlmIChleGlzdHMoY29sLmdldENvbERlZigpLmNvbFNwYW4pKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuY2FsY3VsYXRlQ29sdW1uc0Zvckdyb3VwRGlzcGxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5ncm91cERpc3BsYXlDb2x1bW5zID0gW107XG4gICAgICAgIHRoaXMuZ3JvdXBEaXNwbGF5Q29sdW1uc01hcCA9IHt9O1xuICAgICAgICB2YXIgY2hlY2tGdW5jID0gZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgdmFyIGNvbERlZiA9IGNvbC5nZXRDb2xEZWYoKTtcbiAgICAgICAgICAgIHZhciB1bmRlcmx5aW5nQ29sdW1uID0gY29sRGVmLnNob3dSb3dHcm91cDtcbiAgICAgICAgICAgIGlmIChjb2xEZWYgJiYgZXhpc3RzKHVuZGVybHlpbmdDb2x1bW4pKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ3JvdXBEaXNwbGF5Q29sdW1ucy5wdXNoKGNvbCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1bmRlcmx5aW5nQ29sdW1uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5ncm91cERpc3BsYXlDb2x1bW5zTWFwW3VuZGVybHlpbmdDb2x1bW5dID0gY29sO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh1bmRlcmx5aW5nQ29sdW1uID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmdldFJvd0dyb3VwQ29sdW1ucygpLmZvckVhY2goZnVuY3Rpb24gKHJvd0dyb3VwQ29sKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5ncm91cERpc3BsYXlDb2x1bW5zTWFwW3Jvd0dyb3VwQ29sLmdldElkKCldID0gY29sO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ3JpZENvbHVtbnMuZm9yRWFjaChjaGVja0Z1bmMpO1xuICAgICAgICBpZiAodGhpcy5ncm91cEF1dG9Db2x1bW5zKSB7XG4gICAgICAgICAgICB0aGlzLmdyb3VwQXV0b0NvbHVtbnMuZm9yRWFjaChjaGVja0Z1bmMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0R3JvdXBEaXNwbGF5Q29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JvdXBEaXNwbGF5Q29sdW1ucztcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRHcm91cERpc3BsYXlDb2x1bW5Gb3JHcm91cCA9IGZ1bmN0aW9uIChyb3dHcm91cENvbHVtbklkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyb3VwRGlzcGxheUNvbHVtbnNNYXBbcm93R3JvdXBDb2x1bW5JZF07XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUudXBkYXRlRGlzcGxheWVkQ29sdW1ucyA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdmFyIGNvbHVtbnNGb3JEaXNwbGF5ID0gdGhpcy5jYWxjdWxhdGVDb2x1bW5zRm9yRGlzcGxheSgpO1xuICAgICAgICB0aGlzLmJ1aWxkRGlzcGxheWVkVHJlZXMoY29sdW1uc0ZvckRpc3BsYXkpO1xuICAgICAgICB0aGlzLmNhbGN1bGF0ZUNvbHVtbnNGb3JHcm91cERpc3BsYXkoKTtcbiAgICAgICAgLy8gYWxzbyBjYWxsZWQgd2hlbiBncm91cCBvcGVuZWQvY2xvc2VkXG4gICAgICAgIHRoaXMudXBkYXRlR3JvdXBzQW5kRGlzcGxheWVkQ29sdW1ucyhzb3VyY2UpO1xuICAgICAgICAvLyBhbHNvIGNhbGxlZCB3aGVuIGdyb3VwIG9wZW5lZC9jbG9zZWRcbiAgICAgICAgdGhpcy5zZXRGaXJzdFJpZ2h0QW5kTGFzdExlZnRQaW5uZWQoc291cmNlKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5pc1NlY29uZGFyeUNvbHVtbnNQcmVzZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZXhpc3RzKHRoaXMuc2Vjb25kYXJ5Q29sdW1ucyk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0U2Vjb25kYXJ5Q29sdW1ucyA9IGZ1bmN0aW9uIChjb2xEZWZzLCBzb3VyY2UpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgdmFyIG5ld0NvbHNQcmVzZW50ID0gY29sRGVmcyAmJiBjb2xEZWZzLmxlbmd0aCA+IDA7XG4gICAgICAgIC8vIGlmIG5vdCBjb2xzIHBhc3NlZCwgYW5kIHdlIGhhZCBubyBjb2xzIGFueXdheSwgdGhlbiBkbyBub3RoaW5nXG4gICAgICAgIGlmICghbmV3Q29sc1ByZXNlbnQgJiYgbWlzc2luZyh0aGlzLnNlY29uZGFyeUNvbHVtbnMpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5ld0NvbHNQcmVzZW50KSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NTZWNvbmRhcnlDb2x1bW5EZWZpbml0aW9ucyhjb2xEZWZzKTtcbiAgICAgICAgICAgIHZhciBiYWxhbmNlZFRyZWVSZXN1bHQgPSB0aGlzLmNvbHVtbkZhY3RvcnkuY3JlYXRlQ29sdW1uVHJlZShjb2xEZWZzLCBmYWxzZSwgdGhpcy5zZWNvbmRhcnlCYWxhbmNlZFRyZWUgfHwgdGhpcy5wcmV2aW91c1NlY29uZGFyeUNvbHVtbnMgfHwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5QmFsYW5jZWRUcmVlID0gYmFsYW5jZWRUcmVlUmVzdWx0LmNvbHVtblRyZWU7XG4gICAgICAgICAgICB0aGlzLnNlY29uZGFyeUhlYWRlclJvd0NvdW50ID0gYmFsYW5jZWRUcmVlUmVzdWx0LnRyZWVEZXB0ICsgMTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5Q29sdW1ucyA9IHRoaXMuZ2V0Q29sdW1uc0Zyb21UcmVlKHRoaXMuc2Vjb25kYXJ5QmFsYW5jZWRUcmVlKTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5Q29sdW1uc01hcCA9IHt9O1xuICAgICAgICAgICAgdGhpcy5zZWNvbmRhcnlDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gX3RoaXMuc2Vjb25kYXJ5Q29sdW1uc01hcFtjb2wuZ2V0SWQoKV0gPSBjb2w7IH0pO1xuICAgICAgICAgICAgdGhpcy5wcmV2aW91c1NlY29uZGFyeUNvbHVtbnMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wcmV2aW91c1NlY29uZGFyeUNvbHVtbnMgPSB0aGlzLnNlY29uZGFyeUJhbGFuY2VkVHJlZTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5QmFsYW5jZWRUcmVlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5SGVhZGVyUm93Q291bnQgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5Q29sdW1ucyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnNlY29uZGFyeUNvbHVtbnNNYXAgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZUdyaWRDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMudXBkYXRlRGlzcGxheWVkQ29sdW1ucyhzb3VyY2UpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnByb2Nlc3NTZWNvbmRhcnlDb2x1bW5EZWZpbml0aW9ucyA9IGZ1bmN0aW9uIChjb2xEZWZzKSB7XG4gICAgICAgIHZhciBjb2x1bW5DYWxsYmFjayA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFByb2Nlc3NQaXZvdFJlc3VsdENvbERlZkZ1bmMoKTtcbiAgICAgICAgdmFyIGdyb3VwQ2FsbGJhY2sgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRQcm9jZXNzUGl2b3RSZXN1bHRDb2xHcm91cERlZkZ1bmMoKTtcbiAgICAgICAgaWYgKCFjb2x1bW5DYWxsYmFjayAmJiAhZ3JvdXBDYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2VhcmNoRm9yQ29sRGVmcyA9IGZ1bmN0aW9uIChjb2xEZWZzMikge1xuICAgICAgICAgICAgY29sRGVmczIuZm9yRWFjaChmdW5jdGlvbiAoYWJzdHJhY3RDb2xEZWYpIHtcbiAgICAgICAgICAgICAgICB2YXIgaXNHcm91cCA9IGV4aXN0cyhhYnN0cmFjdENvbERlZi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgaWYgKGlzR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbEdyb3VwRGVmID0gYWJzdHJhY3RDb2xEZWY7XG4gICAgICAgICAgICAgICAgICAgIGlmIChncm91cENhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cENhbGxiYWNrKGNvbEdyb3VwRGVmKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZWFyY2hGb3JDb2xEZWZzKGNvbEdyb3VwRGVmLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb2xEZWYgPSBhYnN0cmFjdENvbERlZjtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbHVtbkNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5DYWxsYmFjayhjb2xEZWYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGlmIChjb2xEZWZzKSB7XG4gICAgICAgICAgICBzZWFyY2hGb3JDb2xEZWZzKGNvbERlZnMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBjYWxsZWQgZnJvbTogc2V0Q29sdW1uU3RhdGUsIHNldENvbHVtbkRlZnMsIHNldFNlY29uZGFyeUNvbHVtbnNcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUudXBkYXRlR3JpZENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwcmV2R3JpZENvbHMgPSB0aGlzLmdyaWRCYWxhbmNlZFRyZWU7XG4gICAgICAgIGlmICh0aGlzLmdyaWRDb2xzQXJlUHJpbWFyeSkge1xuICAgICAgICAgICAgdGhpcy5sYXN0UHJpbWFyeU9yZGVyID0gdGhpcy5ncmlkQ29sdW1ucztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMubGFzdFNlY29uZGFyeU9yZGVyID0gdGhpcy5ncmlkQ29sdW1ucztcbiAgICAgICAgfVxuICAgICAgICB2YXIgc29ydE9yZGVyVG9SZWNvdmVyID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAodGhpcy5zZWNvbmRhcnlDb2x1bW5zICYmIHRoaXMuc2Vjb25kYXJ5QmFsYW5jZWRUcmVlKSB7XG4gICAgICAgICAgICB2YXIgaGFzU2FtZUNvbHVtbnMgPSB0aGlzLnNlY29uZGFyeUNvbHVtbnMuZXZlcnkoZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5ncmlkQ29sdW1uc01hcFtjb2wuZ2V0Q29sSWQoKV0gIT09IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5ncmlkQmFsYW5jZWRUcmVlID0gdGhpcy5zZWNvbmRhcnlCYWxhbmNlZFRyZWUuc2xpY2UoKTtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEhlYWRlclJvd0NvdW50ID0gdGhpcy5zZWNvbmRhcnlIZWFkZXJSb3dDb3VudDtcbiAgICAgICAgICAgIHRoaXMuZ3JpZENvbHVtbnMgPSB0aGlzLnNlY29uZGFyeUNvbHVtbnMuc2xpY2UoKTtcbiAgICAgICAgICAgIHRoaXMuZ3JpZENvbHNBcmVQcmltYXJ5ID0gZmFsc2U7XG4gICAgICAgICAgICAvLyBJZiB0aGUgY3VycmVudCBjb2x1bW5zIGFyZSB0aGUgc2FtZSBvciBhIHN1YnNldCBvZiB0aGUgcHJldmlvdXNcbiAgICAgICAgICAgIC8vIHdlIGtlZXAgdGhlIHByZXZpb3VzIG9yZGVyLCBvdGhlcndpc2Ugd2UgZ28gYmFjayB0byB0aGUgb3JkZXIgdGhlIHBpdm90XG4gICAgICAgICAgICAvLyBjb2xzIGFyZSBnZW5lcmF0ZWQgaW5cbiAgICAgICAgICAgIGlmIChoYXNTYW1lQ29sdW1ucykge1xuICAgICAgICAgICAgICAgIHNvcnRPcmRlclRvUmVjb3ZlciA9IHRoaXMubGFzdFNlY29uZGFyeU9yZGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMucHJpbWFyeUNvbHVtbnMpIHtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEJhbGFuY2VkVHJlZSA9IHRoaXMucHJpbWFyeUNvbHVtblRyZWUuc2xpY2UoKTtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEhlYWRlclJvd0NvdW50ID0gdGhpcy5wcmltYXJ5SGVhZGVyUm93Q291bnQ7XG4gICAgICAgICAgICB0aGlzLmdyaWRDb2x1bW5zID0gdGhpcy5wcmltYXJ5Q29sdW1ucy5zbGljZSgpO1xuICAgICAgICAgICAgdGhpcy5ncmlkQ29sc0FyZVByaW1hcnkgPSB0cnVlO1xuICAgICAgICAgICAgLy8gdXBkYXRlR3JpZENvbHVtbnMgZ2V0cyBjYWxsZWQgYWZ0ZXIgdXNlciBhZGRzIGEgcm93IGdyb3VwLiB3ZSB3YW50IHRvIG1haW50YWluIHRoZSBvcmRlciBvZiB0aGUgY29sdW1uc1xuICAgICAgICAgICAgLy8gd2hlbiB0aGlzIGhhcHBlbnMgKGVnIGlmIHVzZXIgbW92ZWQgYSBjb2x1bW4pIHJhdGhlciB0aGFuIHJldmVydCBiYWNrIHRvIHRoZSBvcmlnaW5hbCBjb2x1bW4gb3JkZXIuXG4gICAgICAgICAgICAvLyBsaWtld2lzZSBpZiBjaGFuZ2luZyBpbi9vdXQgb2YgcGl2b3QgbW9kZSwgd2Ugd2FudCB0byBtYWludGFpbiB0aGUgb3JkZXIgb2YgdGhlIGNvbHNcbiAgICAgICAgICAgIHNvcnRPcmRlclRvUmVjb3ZlciA9IHRoaXMubGFzdFByaW1hcnlPcmRlcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBjcmVhdGUgdGhlIG5ldyBhdXRvIGNvbHVtbnNcbiAgICAgICAgdmFyIGFyZUF1dG9Db2xzQ2hhbmdlZCA9IHRoaXMuY3JlYXRlR3JvdXBBdXRvQ29sdW1uc0lmTmVlZGVkKCk7XG4gICAgICAgIC8vIGlmIGF1dG8gZ3JvdXAgY29scyBoYXZlIGNoYW5nZWQsIGFuZCB3ZSBoYXZlIGEgc29ydCBvcmRlciwgd2UgbmVlZCB0byBtb3ZlIGF1dG8gY29scyB0byB0aGUgc3RhcnRcbiAgICAgICAgaWYgKGFyZUF1dG9Db2xzQ2hhbmdlZCAmJiBzb3J0T3JkZXJUb1JlY292ZXIpIHtcbiAgICAgICAgICAgIHZhciBncm91cEF1dG9Db2xzTWFwXzEgPSBjb252ZXJ0VG9NYXAodGhpcy5ncm91cEF1dG9Db2x1bW5zLm1hcChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBbY29sLCB0cnVlXTsgfSkpO1xuICAgICAgICAgICAgLy8gaWYgZ3JvdXAgY29sdW1ucyBoYXMgY2hhbmdlZCwgd2UgZG9uJ3QgcHJlc2VydmUgdGhlIGdyb3VwIGNvbHVtbiBvcmRlciwgc28gcmVtb3ZlIHRoZW0gZnJvbSB0aGUgb2xkIG9yZGVyXG4gICAgICAgICAgICBzb3J0T3JkZXJUb1JlY292ZXIgPSBzb3J0T3JkZXJUb1JlY292ZXIuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGdyb3VwQXV0b0NvbHNNYXBfMS5oYXMoY29sKTsgfSk7XG4gICAgICAgICAgICAvLyBhbmQgYWRkIHRoZW0gdG8gdGhlIHN0YXJ0IG9mIHRoZSBvcmRlclxuICAgICAgICAgICAgc29ydE9yZGVyVG9SZWNvdmVyID0gX19zcHJlYWQkZih0aGlzLmdyb3VwQXV0b0NvbHVtbnMsIHNvcnRPcmRlclRvUmVjb3Zlcik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZGRBdXRvR3JvdXBUb0dyaWRDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMub3JkZXJHcmlkQ29sc0xpa2Uoc29ydE9yZGVyVG9SZWNvdmVyKTtcbiAgICAgICAgdGhpcy5ncmlkQ29sdW1ucyA9IHRoaXMucGxhY2VMb2NrZWRDb2x1bW5zKHRoaXMuZ3JpZENvbHVtbnMpO1xuICAgICAgICB0aGlzLnNldHVwUXVpY2tGaWx0ZXJDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMuY2xlYXJEaXNwbGF5ZWRBbmRWaWV3cG9ydENvbHVtbnMoKTtcbiAgICAgICAgdGhpcy5jb2xTcGFuQWN0aXZlID0gdGhpcy5jaGVja0NvbFNwYW5BY3RpdmVJbkNvbHModGhpcy5ncmlkQ29sdW1ucyk7XG4gICAgICAgIHRoaXMuZ3JpZENvbHVtbnNNYXAgPSB7fTtcbiAgICAgICAgdGhpcy5ncmlkQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIF90aGlzLmdyaWRDb2x1bW5zTWFwW2NvbC5nZXRJZCgpXSA9IGNvbDsgfSk7XG4gICAgICAgIHRoaXMuc2V0QXV0b0hlaWdodEFjdGl2ZSgpO1xuICAgICAgICBpZiAoIWFyZUVxdWFsKHByZXZHcmlkQ29scywgdGhpcy5ncmlkQmFsYW5jZWRUcmVlKSkge1xuICAgICAgICAgICAgdmFyIGV2ZW50XzQgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0dSSURfQ09MVU1OU19DSEFOR0VEXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF80KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldEF1dG9IZWlnaHRBY3RpdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYXV0b0hlaWdodEFjdGl2ZSA9IHRoaXMuZ3JpZENvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5pc0F1dG9IZWlnaHQoKTsgfSkubGVuZ3RoID4gMDtcbiAgICAgICAgaWYgKHRoaXMuYXV0b0hlaWdodEFjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5hdXRvSGVpZ2h0QWN0aXZlQXRMZWFzdE9uY2UgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIHJvd01vZGVsVHlwZSA9IHRoaXMucm93TW9kZWwuZ2V0VHlwZSgpO1xuICAgICAgICAgICAgdmFyIHN1cHBvcnRlZFJvd01vZGVsID0gcm93TW9kZWxUeXBlID09PSBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfQ0xJRU5UX1NJREUgfHwgcm93TW9kZWxUeXBlID09PSBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfU0VSVkVSX1NJREU7XG4gICAgICAgICAgICBpZiAoIXN1cHBvcnRlZFJvd01vZGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VfMSA9ICdBRyBHcmlkIC0gYXV0b0hlaWdodCBjb2x1bW5zIG9ubHkgd29yayB3aXRoIENsaWVudCBTaWRlIFJvdyBNb2RlbCBhbmQgU2VydmVyIFNpZGUgUm93IE1vZGVsLic7XG4gICAgICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybihtZXNzYWdlXzEpOyB9LCAnYXV0b0hlaWdodEFjdGl2ZS53cm9uZ1Jvd01vZGVsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5vcmRlckdyaWRDb2xzTGlrZSA9IGZ1bmN0aW9uIChjb2xzT3JkZXIpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcoY29sc09yZGVyKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsYXN0T3JkZXJNYXBwZWQgPSBjb252ZXJ0VG9NYXAoY29sc09yZGVyLm1hcChmdW5jdGlvbiAoY29sLCBpbmRleCkgeyByZXR1cm4gW2NvbCwgaW5kZXhdOyB9KSk7XG4gICAgICAgIC8vIG9ubHkgZG8gdGhlIHNvcnQgaWYgYXQgbGVhc3Qgb25lIGNvbHVtbiBpcyBhY2NvdW50ZWQgZm9yLiBjb2x1bW5zIHdpbGwgYmUgbm90IGFjY291bnRlZCBmb3JcbiAgICAgICAgLy8gaWYgY2hhbmdpbmcgZnJvbSBzZWNvbmRhcnkgdG8gcHJpbWFyeSBjb2x1bW5zXG4gICAgICAgIHZhciBub0NvbHNGb3VuZCA9IHRydWU7XG4gICAgICAgIHRoaXMuZ3JpZENvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICBpZiAobGFzdE9yZGVyTWFwcGVkLmhhcyhjb2wpKSB7XG4gICAgICAgICAgICAgICAgbm9Db2xzRm91bmQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChub0NvbHNGb3VuZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIG9yZGVyIGNvbHMgaW4gdGhlIHNhbWUgb3JkZXIgYXMgYmVmb3JlLiB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGFsbFxuICAgICAgICAvLyBjb2xzIHN0aWxsIGV4aXN0cywgc28gZmlsdGVyIG91dCBhbnkgdGhhdCBubyBsb25nZXIgZXhpc3QuXG4gICAgICAgIHZhciBncmlkQ29sc01hcCA9IGNvbnZlcnRUb01hcCh0aGlzLmdyaWRDb2x1bW5zLm1hcChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBbY29sLCB0cnVlXTsgfSkpO1xuICAgICAgICB2YXIgb2xkQ29sc09yZGVyZWQgPSBjb2xzT3JkZXIuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGdyaWRDb2xzTWFwLmhhcyhjb2wpOyB9KTtcbiAgICAgICAgdmFyIG9sZENvbHNNYXAgPSBjb252ZXJ0VG9NYXAob2xkQ29sc09yZGVyZWQubWFwKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIFtjb2wsIHRydWVdOyB9KSk7XG4gICAgICAgIHZhciBuZXdDb2xzT3JkZXJlZCA9IHRoaXMuZ3JpZENvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuICFvbGRDb2xzTWFwLmhhcyhjb2wpOyB9KTtcbiAgICAgICAgLy8gYWRkIGluIHRoZSBuZXcgY29sdW1ucywgYXQgdGhlIGVuZCAoaWYgbm8gZ3JvdXApLCBvciBhdCB0aGUgZW5kIG9mIHRoZSBncm91cCAoaWYgYSBncm91cClcbiAgICAgICAgdmFyIG5ld0dyaWRDb2x1bW5zID0gb2xkQ29sc09yZGVyZWQuc2xpY2UoKTtcbiAgICAgICAgbmV3Q29sc09yZGVyZWQuZm9yRWFjaChmdW5jdGlvbiAobmV3Q29sKSB7XG4gICAgICAgICAgICB2YXIgcGFyZW50ID0gbmV3Q29sLmdldE9yaWdpbmFsUGFyZW50KCk7XG4gICAgICAgICAgICAvLyBpZiBubyBwYXJlbnQsIG1lYW5zIHdlIGFyZSBub3QgZ3JvdXBpbmcsIHNvIGp1c3QgYWRkIHRoZSBjb2x1bW4gdG8gdGhlIGVuZFxuICAgICAgICAgICAgaWYgKCFwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBuZXdHcmlkQ29sdW1ucy5wdXNoKG5ld0NvbCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZmluZCB0aGUgZ3JvdXAgdGhlIGNvbHVtbiBiZWxvbmdzIHRvLiBpZiBubyBzaWJsaW5ncyBhdCB0aGUgY3VycmVudCBsZXZlbCAoZWcgY29sIGluIGdyb3VwIG9uIGl0J3NcbiAgICAgICAgICAgIC8vIG93bikgdGhlbiBnbyB1cCBvbmUgbGV2ZWwgYW5kIGxvb2sgZm9yIHNpYmxpbmdzIHRoZXJlLlxuICAgICAgICAgICAgdmFyIHNpYmxpbmdzID0gW107XG4gICAgICAgICAgICB3aGlsZSAoIXNpYmxpbmdzLmxlbmd0aCAmJiBwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGVhZkNvbHMgPSBwYXJlbnQuZ2V0TGVhZkNvbHVtbnMoKTtcbiAgICAgICAgICAgICAgICBsZWFmQ29scy5mb3JFYWNoKGZ1bmN0aW9uIChsZWFmQ29sKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmVzZW50SW5OZXdHcmlDb2x1bW5zID0gbmV3R3JpZENvbHVtbnMuaW5kZXhPZihsZWFmQ29sKSA+PSAwO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9ZZXRJblNpYmxpbmdzID0gc2libGluZ3MuaW5kZXhPZihsZWFmQ29sKSA8IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcmVzZW50SW5OZXdHcmlDb2x1bW5zICYmIG5vWWV0SW5TaWJsaW5ncykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2libGluZ3MucHVzaChsZWFmQ29sKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5nZXRPcmlnaW5hbFBhcmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgbm8gc2libGluZ3MgZXhpc3QgYXQgYW55IGxldmVsLCB0aGlzIG1lYW5zIHRoZSBjb2wgaXMgaW4gYSBncm91cCAob3IgcGFyZW50IGdyb3Vwcykgb24gaXQncyBvd25cbiAgICAgICAgICAgIGlmICghc2libGluZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbmV3R3JpZENvbHVtbnMucHVzaChuZXdDb2wpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGZpbmQgaW5kZXggb2YgbGFzdCBjb2x1bW4gaW4gdGhlIGdyb3VwXG4gICAgICAgICAgICB2YXIgaW5kZXhlcyA9IHNpYmxpbmdzLm1hcChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBuZXdHcmlkQ29sdW1ucy5pbmRleE9mKGNvbCk7IH0pO1xuICAgICAgICAgICAgdmFyIGxhc3RJbmRleCA9IE1hdGgubWF4LmFwcGx5KE1hdGgsIF9fc3ByZWFkJGYoaW5kZXhlcykpO1xuICAgICAgICAgICAgaW5zZXJ0SW50b0FycmF5KG5ld0dyaWRDb2x1bW5zLCBuZXdDb2wsIGxhc3RJbmRleCArIDEpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ncmlkQ29sdW1ucyA9IG5ld0dyaWRDb2x1bW5zO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmlzUHJpbWFyeUNvbHVtbkdyb3Vwc1ByZXNlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW1hcnlIZWFkZXJSb3dDb3VudCA+IDE7XG4gICAgfTtcbiAgICAvLyBpZiB3ZSBhcmUgdXNpbmcgYXV0b0dyb3VwQ29scywgdGhlbiB0aGV5IHNob3VsZCBiZSBpbmNsdWRlZCBmb3IgcXVpY2sgZmlsdGVyLiB0aGlzIGNvdmVycyB0aGVcbiAgICAvLyBmb2xsb3dpbmcgc2NlbmFyaW9zOlxuICAgIC8vIGEpIHVzZXIgcHJvdmlkZXMgJ2ZpZWxkJyBpbnRvIGF1dG9Hcm91cENvbCBvZiBub3JtYWwgZ3JpZCwgc28gbm93IGJlY2F1c2UgYSB2YWxpZCBjb2wgdG8gZmlsdGVyIGxlYWZzIG9uXG4gICAgLy8gYikgdXNpbmcgdHJlZSBkYXRhIGFuZCB1c2VyIGRlcGVuZHMgb24gYXV0b0dyb3VwQ29sIGZvciBmaXJzdCBjb2wsIGFuZCB3ZSBhbHNvIHdhbnQgdG8gZmlsdGVyIG9uIHRoaXNcbiAgICAvLyAgICAodHJlZSBkYXRhIGlzIGEgYml0IGRpZmZlcmVudCwgYXMgcGFyZW50IHJvd3MgY2FuIGJlIGZpbHRlcmVkIG9uLCB1bmxpa2Ugcm93IGdyb3VwaW5nKVxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zZXR1cFF1aWNrRmlsdGVyQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZ3JvdXBBdXRvQ29sdW1ucykge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5zRm9yUXVpY2tGaWx0ZXIgPSAodGhpcy5wcmltYXJ5Q29sdW1ucyB8fCBbXSkuY29uY2F0KHRoaXMuZ3JvdXBBdXRvQ29sdW1ucyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5wcmltYXJ5Q29sdW1ucykge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5zRm9yUXVpY2tGaWx0ZXIgPSB0aGlzLnByaW1hcnlDb2x1bW5zO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUucGxhY2VMb2NrZWRDb2x1bW5zID0gZnVuY3Rpb24gKGNvbHMpIHtcbiAgICAgICAgdmFyIGxlZnQgPSBbXTtcbiAgICAgICAgdmFyIG5vcm1hbCA9IFtdO1xuICAgICAgICB2YXIgcmlnaHQgPSBbXTtcbiAgICAgICAgY29scy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIHZhciBwb3NpdGlvbiA9IGNvbC5nZXRDb2xEZWYoKS5sb2NrUG9zaXRpb247XG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICByaWdodC5wdXNoKGNvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2xlZnQnIHx8IHBvc2l0aW9uID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgbGVmdC5wdXNoKGNvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBub3JtYWwucHVzaChjb2wpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIF9fc3ByZWFkJGYobGVmdCwgbm9ybWFsLCByaWdodCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYWRkQXV0b0dyb3VwVG9HcmlkQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy5ncm91cEF1dG9Db2x1bW5zKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ3JpZENvbHVtbnMgPSB0aGlzLmdyb3VwQXV0b0NvbHVtbnMgPyB0aGlzLmdyb3VwQXV0b0NvbHVtbnMuY29uY2F0KHRoaXMuZ3JpZENvbHVtbnMpIDogdGhpcy5ncmlkQ29sdW1ucztcbiAgICAgICAgdmFyIGF1dG9Db2xCYWxhbmNlZFRyZWUgPSB0aGlzLmNvbHVtbkZhY3RvcnkuY3JlYXRlRm9yQXV0b0dyb3Vwcyh0aGlzLmdyb3VwQXV0b0NvbHVtbnMsIHRoaXMuZ3JpZEJhbGFuY2VkVHJlZSk7XG4gICAgICAgIHRoaXMuZ3JpZEJhbGFuY2VkVHJlZSA9IGF1dG9Db2xCYWxhbmNlZFRyZWUuY29uY2F0KHRoaXMuZ3JpZEJhbGFuY2VkVHJlZSk7XG4gICAgfTtcbiAgICAvLyBnZXRzIGNhbGxlZCBhZnRlciB3ZSBjb3B5IGRvd24gZ3JpZCBjb2x1bW5zLCB0byBtYWtlIHN1cmUgYW55IHBhcnQgb2YgdGhlIGd1aVxuICAgIC8vIHRoYXQgdHJpZXMgdG8gZHJhdywgZWcgdGhlIGhlYWRlciwgaXQgd2lsbCBnZXQgZW1wdHkgbGlzdHMgb2YgY29sdW1ucyByYXRoZXJcbiAgICAvLyB0aGFuIHN0YWxlIGNvbHVtbnMuIGZvciBleGFtcGxlLCB0aGUgaGVhZGVyIHdpbGwgcmVjZWl2ZWQgZ3JpZENvbHVtbnNDaGFuZ2VkXG4gICAgLy8gZXZlbnQsIHNvIHdpbGwgdHJ5IGFuZCBkcmF3LCBidXQgaXQgd2lsbCBkcmF3IHN1Y2Nlc3NmdWxseSB3aGVuIGl0IGFjdHMgb24gdGhlXG4gICAgLy8gdmlydHVhbENvbHVtbnNDaGFuZ2VkIGV2ZW50XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmNsZWFyRGlzcGxheWVkQW5kVmlld3BvcnRDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BsYXllZFRyZWVMZWZ0ID0gW107XG4gICAgICAgIHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0ID0gW107XG4gICAgICAgIHRoaXMuZGlzcGxheWVkVHJlZUNlbnRyZSA9IFtdO1xuICAgICAgICB0aGlzLnZpZXdwb3J0Um93TGVmdCA9IHt9O1xuICAgICAgICB0aGlzLnZpZXdwb3J0Um93UmlnaHQgPSB7fTtcbiAgICAgICAgdGhpcy52aWV3cG9ydFJvd0NlbnRlciA9IHt9O1xuICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0ID0gW107XG4gICAgICAgIHRoaXMuZGlzcGxheWVkQ29sdW1uc1JpZ2h0ID0gW107XG4gICAgICAgIHRoaXMuZGlzcGxheWVkQ29sdW1uc0NlbnRlciA9IFtdO1xuICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMgPSBbXTtcbiAgICAgICAgdGhpcy52aWV3cG9ydENvbHVtbnMgPSBbXTtcbiAgICAgICAgdGhpcy5oZWFkZXJWaWV3cG9ydENvbHVtbnMgPSBbXTtcbiAgICAgICAgdGhpcy52aWV3cG9ydENvbHVtbnNIYXNoID0gJyc7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUudXBkYXRlR3JvdXBzQW5kRGlzcGxheWVkQ29sdW1ucyA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdGhpcy51cGRhdGVPcGVuQ2xvc2VkVmlzaWJpbGl0eUluQ29sdW1uR3JvdXBzKCk7XG4gICAgICAgIHRoaXMuZGVyaXZlRGlzcGxheWVkQ29sdW1ucyhzb3VyY2UpO1xuICAgICAgICB0aGlzLnJlZnJlc2hGbGV4ZWRDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMuZXh0cmFjdFZpZXdwb3J0KCk7XG4gICAgICAgIHRoaXMudXBkYXRlQm9keVdpZHRocygpO1xuICAgICAgICAvLyB0aGlzIGV2ZW50IGlzIHBpY2tlZCB1cCBieSB0aGUgZ3VpLCBoZWFkZXJSZW5kZXJlciBhbmQgcm93UmVuZGVyZXIsIHRvIHJlY2FsY3VsYXRlIHdoYXQgY29sdW1ucyB0byBkaXNwbGF5XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19DSEFOR0VEXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmRlcml2ZURpc3BsYXllZENvbHVtbnMgPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICAgIHRoaXMuZGVyaXZlZERpc3BsYXllZENvbHVtbnNGcm9tRGlzcGxheWVkVHJlZSh0aGlzLmRpc3BsYXllZFRyZWVMZWZ0LCB0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0KTtcbiAgICAgICAgdGhpcy5kZXJpdmVkRGlzcGxheWVkQ29sdW1uc0Zyb21EaXNwbGF5ZWRUcmVlKHRoaXMuZGlzcGxheWVkVHJlZUNlbnRyZSwgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyKTtcbiAgICAgICAgdGhpcy5kZXJpdmVkRGlzcGxheWVkQ29sdW1uc0Zyb21EaXNwbGF5ZWRUcmVlKHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0LCB0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodCk7XG4gICAgICAgIHRoaXMuam9pbkRpc3BsYXllZENvbHVtbnMoKTtcbiAgICAgICAgdGhpcy5zZXRMZWZ0VmFsdWVzKHNvdXJjZSk7XG4gICAgICAgIHRoaXMuZGlzcGxheWVkQXV0b0hlaWdodENvbHMgPSB0aGlzLmRpc3BsYXllZENvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5pc0F1dG9IZWlnaHQoKTsgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuaXNBdXRvUm93SGVpZ2h0QWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRvSGVpZ2h0QWN0aXZlO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLndhc0F1dG9Sb3dIZWlnaHRFdmVyQWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRvSGVpZ2h0QWN0aXZlQXRMZWFzdE9uY2U7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuam9pbkRpc3BsYXllZENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMgPSB0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodFxuICAgICAgICAgICAgICAgIC5jb25jYXQodGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyKVxuICAgICAgICAgICAgICAgIC5jb25jYXQodGhpcy5kaXNwbGF5ZWRDb2x1bW5zTGVmdCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMgPSB0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0XG4gICAgICAgICAgICAgICAgLmNvbmNhdCh0aGlzLmRpc3BsYXllZENvbHVtbnNDZW50ZXIpXG4gICAgICAgICAgICAgICAgLmNvbmNhdCh0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHNldHMgdGhlIGxlZnQgcGl4ZWwgcG9zaXRpb24gb2YgZWFjaCBjb2x1bW5cbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0TGVmdFZhbHVlcyA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdGhpcy5zZXRMZWZ0VmFsdWVzT2ZDb2x1bW5zKHNvdXJjZSk7XG4gICAgICAgIHRoaXMuc2V0TGVmdFZhbHVlc09mR3JvdXBzKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuc2V0TGVmdFZhbHVlc09mQ29sdW1ucyA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLnByaW1hcnlDb2x1bW5zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gZ28gdGhyb3VnaCBlYWNoIGxpc3Qgb2YgZGlzcGxheWVkIGNvbHVtbnNcbiAgICAgICAgdmFyIGFsbENvbHVtbnMgPSB0aGlzLnByaW1hcnlDb2x1bW5zLnNsaWNlKDApO1xuICAgICAgICAvLyBsZXQgdG90YWxDb2x1bW5XaWR0aCA9IHRoaXMuZ2V0V2lkdGhPZkNvbHNJbkxpc3QoKVxuICAgICAgICB2YXIgZG9pbmdSdGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICBbXG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0LFxuICAgICAgICAgICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zUmlnaHQsXG4gICAgICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnNDZW50ZXJcbiAgICAgICAgXS5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5zKSB7XG4gICAgICAgICAgICBpZiAoZG9pbmdSdGwpIHtcbiAgICAgICAgICAgICAgICAvLyB3aGVuIGRvaW5nIFJUTCwgd2Ugc3RhcnQgYXQgdGhlIHRvcCBtb3N0IHBpeGVsIChpZSBSSFMpIGFuZCB3b3JrIGJhY2t3YXJkc1xuICAgICAgICAgICAgICAgIHZhciBsZWZ0XzEgPSBfdGhpcy5nZXRXaWR0aE9mQ29sc0luTGlzdChjb2x1bW5zKTtcbiAgICAgICAgICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0XzEgLT0gY29sdW1uLmdldEFjdHVhbFdpZHRoKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbi5zZXRMZWZ0KGxlZnRfMSwgc291cmNlKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIG90aGVyd2lzZSBub3JtYWwgTFRSLCB3ZSBzdGFydCBhdCB6ZXJvXG4gICAgICAgICAgICAgICAgdmFyIGxlZnRfMiA9IDA7XG4gICAgICAgICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnNldExlZnQobGVmdF8yLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICBsZWZ0XzIgKz0gY29sdW1uLmdldEFjdHVhbFdpZHRoKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZW1vdmVBbGxGcm9tQXJyYXkoYWxsQ29sdW1ucywgY29sdW1ucyk7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBpdGVtcyBsZWZ0IGluIGFsbENvbHVtbnMgYXJlIGNvbHVtbnMgbm90IGRpc3BsYXllZCwgc28gcmVtb3ZlIHRoZSBsZWZ0IHBvc2l0aW9uLiB0aGlzIGlzXG4gICAgICAgIC8vIGltcG9ydGFudCBmb3IgdGhlIHJvd3MsIGFzIGlmIGEgY29sIGlzIG1hZGUgdmlzaWJsZSwgdGhlbiB0YWtlbiBvdXQsIHRoZW4gbWFkZSB2aXNpYmxlIGFnYWluLFxuICAgICAgICAvLyB3ZSBkb24ndCB3YW50IHRoZSBhbmltYXRpb24gb2YgdGhlIGNlbGwgZmxvYXRpbmcgaW4gZnJvbSB0aGUgb2xkIHBvc2l0aW9uLCB3aGF0ZXZlciB0aGF0IHdhcy5cbiAgICAgICAgYWxsQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbHVtbi5zZXRMZWZ0KG51bGwsIHNvdXJjZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldExlZnRWYWx1ZXNPZkdyb3VwcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gYSBncm91cHMgbGVmdCB2YWx1ZSBpcyB0aGUgbGVzdCBsZWZ0IHZhbHVlIG9mIGl0J3MgY2hpbGRyZW5cbiAgICAgICAgW1xuICAgICAgICAgICAgdGhpcy5kaXNwbGF5ZWRUcmVlTGVmdCxcbiAgICAgICAgICAgIHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0LFxuICAgICAgICAgICAgdGhpcy5kaXNwbGF5ZWRUcmVlQ2VudHJlXG4gICAgICAgIF0uZm9yRWFjaChmdW5jdGlvbiAoY29sdW1ucykge1xuICAgICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBpZiAoY29sdW1uIGluc3RhbmNlb2YgQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbkdyb3VwID0gY29sdW1uO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Hcm91cC5jaGVja0xlZnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZGVyaXZlZERpc3BsYXllZENvbHVtbnNGcm9tRGlzcGxheWVkVHJlZSA9IGZ1bmN0aW9uICh0cmVlLCBjb2x1bW5zKSB7XG4gICAgICAgIGNvbHVtbnMubGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5jb2x1bW5VdGlscy5kZXB0aEZpcnN0RGlzcGxheWVkQ29sdW1uVHJlZVNlYXJjaCh0cmVlLCBmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIENvbHVtbikge1xuICAgICAgICAgICAgICAgIGNvbHVtbnMucHVzaChjaGlsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmV4dHJhY3RWaWV3cG9ydENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnN1cHByZXNzQ29sdW1uVmlydHVhbGlzYXRpb24pIHtcbiAgICAgICAgICAgIC8vIG5vIHZpcnR1YWxpc2F0aW9uLCBzbyBkb24ndCBmaWx0ZXJcbiAgICAgICAgICAgIHRoaXMudmlld3BvcnRDb2x1bW5zQ2VudGVyID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyO1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJWaWV3cG9ydENvbHVtbnNDZW50ZXIgPSB0aGlzLmRpc3BsYXllZENvbHVtbnNDZW50ZXI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBmaWx0ZXIgb3V0IHdoYXQgc2hvdWxkIGJlIHZpc2libGVcbiAgICAgICAgICAgIHRoaXMudmlld3BvcnRDb2x1bW5zQ2VudGVyID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyLmZpbHRlcih0aGlzLmlzQ29sdW1uSW5Sb3dWaWV3cG9ydC5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyVmlld3BvcnRDb2x1bW5zQ2VudGVyID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyLmZpbHRlcih0aGlzLmlzQ29sdW1uSW5IZWFkZXJWaWV3cG9ydC5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZpZXdwb3J0Q29sdW1ucyA9IHRoaXMudmlld3BvcnRDb2x1bW5zQ2VudGVyXG4gICAgICAgICAgICAuY29uY2F0KHRoaXMuZGlzcGxheWVkQ29sdW1uc0xlZnQpXG4gICAgICAgICAgICAuY29uY2F0KHRoaXMuZGlzcGxheWVkQ29sdW1uc1JpZ2h0KTtcbiAgICAgICAgdGhpcy5oZWFkZXJWaWV3cG9ydENvbHVtbnMgPSB0aGlzLmhlYWRlclZpZXdwb3J0Q29sdW1uc0NlbnRlclxuICAgICAgICAgICAgLmNvbmNhdCh0aGlzLmRpc3BsYXllZENvbHVtbnNMZWZ0KVxuICAgICAgICAgICAgLmNvbmNhdCh0aGlzLmRpc3BsYXllZENvbHVtbnNSaWdodCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0VmlydHVhbEhlYWRlckdyb3VwUm93ID0gZnVuY3Rpb24gKHR5cGUsIGRlcHQpIHtcbiAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfTEVGVDpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnZpZXdwb3J0Um93TGVmdFtkZXB0XTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnZpZXdwb3J0Um93UmlnaHRbZGVwdF07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMudmlld3BvcnRSb3dDZW50ZXJbZGVwdF07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1pc3NpbmcocmVzdWx0KSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5jYWxjdWxhdGVIZWFkZXJSb3dzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBnbyB0aHJvdWdoIGVhY2ggZ3JvdXAsIHNlZSBpZiBhbnkgb2YgaXQncyBjb2xzIGFyZSBkaXNwbGF5ZWQsIGFuZCBpZiB5ZXMsXG4gICAgICAgIC8vIHRoZW4gdGhpcyBncm91cCBpcyBpbmNsdWRlZFxuICAgICAgICB0aGlzLnZpZXdwb3J0Um93TGVmdCA9IHt9O1xuICAgICAgICB0aGlzLnZpZXdwb3J0Um93UmlnaHQgPSB7fTtcbiAgICAgICAgdGhpcy52aWV3cG9ydFJvd0NlbnRlciA9IHt9O1xuICAgICAgICAvLyBmb3IgZWFzeSBsb29rdXAgd2hlbiBidWlsZGluZyB0aGUgZ3JvdXBzLlxuICAgICAgICB2YXIgdmlydHVhbENvbElkcyA9IHt9O1xuICAgICAgICB0aGlzLmhlYWRlclZpZXdwb3J0Q29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIHZpcnR1YWxDb2xJZHNbY29sLmdldElkKCldID0gdHJ1ZTsgfSk7XG4gICAgICAgIHZhciB0ZXN0R3JvdXAgPSBmdW5jdGlvbiAoY2hpbGRyZW4sIHJlc3VsdCwgZGVwdCkge1xuICAgICAgICAgICAgdmFyIHJldHVyblZhbHVlID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gc2VlIGlmIHRoaXMgaXRlbSBpcyB3aXRoaW4gdmlld3BvcnRcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICB2YXIgYWRkVGhpc0l0ZW0gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yIGNvbHVtbiwgdGVzdCBpZiBjb2x1bW4gaXMgaW5jbHVkZWRcbiAgICAgICAgICAgICAgICAgICAgYWRkVGhpc0l0ZW0gPSB2aXJ0dWFsQ29sSWRzW2NoaWxkLmdldElkKCldID09PSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgZ3JvdXAsIGJhc2UgZGVjaXNpb24gb24gY2hpbGRyZW5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbkdyb3VwID0gY2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXNwbGF5ZWRDaGlsZHJlbiA9IGNvbHVtbkdyb3VwLmdldERpc3BsYXllZENoaWxkcmVuKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkaXNwbGF5ZWRDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkVGhpc0l0ZW0gPSB0ZXN0R3JvdXAoZGlzcGxheWVkQ2hpbGRyZW4sIHJlc3VsdCwgZGVwdCArIDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhZGRUaGlzSXRlbSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcmVzdWx0W2RlcHRdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRbZGVwdF0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXN1bHRbZGVwdF0ucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgICAgICB9O1xuICAgICAgICB0ZXN0R3JvdXAodGhpcy5kaXNwbGF5ZWRUcmVlTGVmdCwgdGhpcy52aWV3cG9ydFJvd0xlZnQsIDApO1xuICAgICAgICB0ZXN0R3JvdXAodGhpcy5kaXNwbGF5ZWRUcmVlUmlnaHQsIHRoaXMudmlld3BvcnRSb3dSaWdodCwgMCk7XG4gICAgICAgIHRlc3RHcm91cCh0aGlzLmRpc3BsYXllZFRyZWVDZW50cmUsIHRoaXMudmlld3BvcnRSb3dDZW50ZXIsIDApO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmV4dHJhY3RWaWV3cG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGhhc2hDb2x1bW4gPSBmdW5jdGlvbiAoYykgeyByZXR1cm4gYy5nZXRJZCgpICsgXCItXCIgKyAoYy5nZXRQaW5uZWQoKSB8fCAnbm9ybWFsJyk7IH07XG4gICAgICAgIHRoaXMuZXh0cmFjdFZpZXdwb3J0Q29sdW1ucygpO1xuICAgICAgICB2YXIgbmV3SGFzaCA9IHRoaXMudmlld3BvcnRDb2x1bW5zLm1hcChoYXNoQ29sdW1uKS5qb2luKCcjJyk7XG4gICAgICAgIHZhciBjaGFuZ2VkID0gdGhpcy52aWV3cG9ydENvbHVtbnNIYXNoICE9PSBuZXdIYXNoO1xuICAgICAgICBpZiAoY2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy52aWV3cG9ydENvbHVtbnNIYXNoID0gbmV3SGFzaDtcbiAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlSGVhZGVyUm93cygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaGFuZ2VkO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnJlZnJlc2hGbGV4ZWRDb2x1bW5zID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAocGFyYW1zID09PSB2b2lkIDApIHsgcGFyYW1zID0ge307IH1cbiAgICAgICAgdmFyIHNvdXJjZSA9IHBhcmFtcy5zb3VyY2UgPyBwYXJhbXMuc291cmNlIDogJ2ZsZXgnO1xuICAgICAgICBpZiAocGFyYW1zLnZpZXdwb3J0V2lkdGggIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5mbGV4Vmlld3BvcnRXaWR0aCA9IHBhcmFtcy52aWV3cG9ydFdpZHRoO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5mbGV4Vmlld3BvcnRXaWR0aCkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHRoZSBncmlkIGhhcyBsZWZ0LW92ZXIgc3BhY2UsIGRpdmlkZSBpdCBiZXR3ZWVuIGZsZXhpbmcgY29sdW1ucyBpbiBwcm9wb3J0aW9uIHRvIHRoZWlyIGZsZXggdmFsdWUuXG4gICAgICAgIC8vIEEgXCJmbGV4aW5nIGNvbHVtblwiIGlzIG9uZSB0aGF0IGhhcyBhICdmbGV4JyB2YWx1ZSBzZXQgYW5kIGlzIG5vdCBjdXJyZW50bHkgYmVpbmcgY29uc3RyYWluZWQgYnkgaXRzXG4gICAgICAgIC8vIG1pbldpZHRoIG9yIG1heFdpZHRoIHJ1bGVzLlxuICAgICAgICB2YXIgZmxleEFmdGVyRGlzcGxheUluZGV4ID0gLTE7XG4gICAgICAgIGlmIChwYXJhbXMucmVzaXppbmdDb2xzKSB7XG4gICAgICAgICAgICBwYXJhbXMucmVzaXppbmdDb2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgIHZhciBpbmRleE9mQ29sID0gX3RoaXMuZGlzcGxheWVkQ29sdW1uc0NlbnRlci5pbmRleE9mKGNvbCk7XG4gICAgICAgICAgICAgICAgaWYgKGZsZXhBZnRlckRpc3BsYXlJbmRleCA8IGluZGV4T2ZDb2wpIHtcbiAgICAgICAgICAgICAgICAgICAgZmxleEFmdGVyRGlzcGxheUluZGV4ID0gaW5kZXhPZkNvbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNDb2xGbGV4ID0gZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgdmFyIGFmdGVyUmVzaXppbmdDb2xzID0gX3RoaXMuZGlzcGxheWVkQ29sdW1uc0NlbnRlci5pbmRleE9mKGNvbCkgPiBmbGV4QWZ0ZXJEaXNwbGF5SW5kZXg7XG4gICAgICAgICAgICByZXR1cm4gY29sLmdldEZsZXgoKSAmJiBhZnRlclJlc2l6aW5nQ29scztcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGtub3duV2lkdGhDb2x1bW5zID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQ2VudGVyLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiAhaXNDb2xGbGV4KGNvbCk7IH0pO1xuICAgICAgICB2YXIgZmxleGluZ0NvbHVtbnMgPSB0aGlzLmRpc3BsYXllZENvbHVtbnNDZW50ZXIuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGlzQ29sRmxleChjb2wpOyB9KTtcbiAgICAgICAgdmFyIGNoYW5nZWRDb2x1bW5zID0gW107XG4gICAgICAgIGlmICghZmxleGluZ0NvbHVtbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZsZXhpbmdDb2x1bW5TaXplcyA9IFtdO1xuICAgICAgICB2YXIgc3BhY2VGb3JGbGV4aW5nQ29sdW1ucztcbiAgICAgICAgb3V0ZXI6IHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICB2YXIgdG90YWxGbGV4ID0gZmxleGluZ0NvbHVtbnMucmVkdWNlKGZ1bmN0aW9uIChjb3VudCwgY29sKSB7IHJldHVybiBjb3VudCArIGNvbC5nZXRGbGV4KCk7IH0sIDApO1xuICAgICAgICAgICAgc3BhY2VGb3JGbGV4aW5nQ29sdW1ucyA9IHRoaXMuZmxleFZpZXdwb3J0V2lkdGggLSB0aGlzLmdldFdpZHRoT2ZDb2xzSW5MaXN0KGtub3duV2lkdGhDb2x1bW5zKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmxleGluZ0NvbHVtbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY29sID0gZmxleGluZ0NvbHVtbnNbaV07XG4gICAgICAgICAgICAgICAgdmFyIHdpZHRoQnlGbGV4UnVsZSA9IHNwYWNlRm9yRmxleGluZ0NvbHVtbnMgKiBjb2wuZ2V0RmxleCgpIC8gdG90YWxGbGV4O1xuICAgICAgICAgICAgICAgIHZhciBjb25zdHJhaW5lZFdpZHRoID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWluV2lkdGggPSBjb2wuZ2V0TWluV2lkdGgoKTtcbiAgICAgICAgICAgICAgICB2YXIgbWF4V2lkdGggPSBjb2wuZ2V0TWF4V2lkdGgoKTtcbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RzKG1pbldpZHRoKSAmJiB3aWR0aEJ5RmxleFJ1bGUgPCBtaW5XaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW5lZFdpZHRoID0gbWluV2lkdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGV4aXN0cyhtYXhXaWR0aCkgJiYgd2lkdGhCeUZsZXhSdWxlID4gbWF4V2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3RyYWluZWRXaWR0aCA9IG1heFdpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY29uc3RyYWluZWRXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGNvbHVtbiBpcyBub3QgaW4gZmFjdCBmbGV4aW5nIGFzIGl0IGlzIGJlaW5nIGNvbnN0cmFpbmVkIHRvIGEgc3BlY2lmaWMgc2l6ZVxuICAgICAgICAgICAgICAgICAgICAvLyBzbyByZW1vdmUgaXQgZnJvbSB0aGUgbGlzdCBvZiBmbGV4aW5nIGNvbHVtbnMgYW5kIHN0YXJ0IGFnYWluXG4gICAgICAgICAgICAgICAgICAgIGNvbC5zZXRBY3R1YWxXaWR0aChjb25zdHJhaW5lZFdpZHRoLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkoZmxleGluZ0NvbHVtbnMsIGNvbCk7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZWRDb2x1bW5zLnB1c2goY29sKTtcbiAgICAgICAgICAgICAgICAgICAga25vd25XaWR0aENvbHVtbnMucHVzaChjb2wpO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZmxleGluZ0NvbHVtblNpemVzW2ldID0gTWF0aC5yb3VuZCh3aWR0aEJ5RmxleFJ1bGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlbWFpbmluZ1NwYWNlID0gc3BhY2VGb3JGbGV4aW5nQ29sdW1ucztcbiAgICAgICAgZmxleGluZ0NvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sLCBpKSB7XG4gICAgICAgICAgICBjb2wuc2V0QWN0dWFsV2lkdGgoTWF0aC5taW4oZmxleGluZ0NvbHVtblNpemVzW2ldLCByZW1haW5pbmdTcGFjZSksIHNvdXJjZSk7XG4gICAgICAgICAgICBjaGFuZ2VkQ29sdW1ucy5wdXNoKGNvbCk7XG4gICAgICAgICAgICByZW1haW5pbmdTcGFjZSAtPSBmbGV4aW5nQ29sdW1uU2l6ZXNbaV07XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIXBhcmFtcy5za2lwU2V0TGVmdCkge1xuICAgICAgICAgICAgdGhpcy5zZXRMZWZ0VmFsdWVzKHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy51cGRhdGVCb2R5V2lkdGhzKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUJvZHlXaWR0aHMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zLmZpcmVSZXNpemVkRXZlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuZmlyZUNvbHVtblJlc2l6ZWRFdmVudChjaGFuZ2VkQ29sdW1ucywgdHJ1ZSwgc291cmNlLCBmbGV4aW5nQ29sdW1ucyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgdGhlIHVzZXIgc2V0cyByb3dEYXRhIGRpcmVjdGx5IGludG8gR3JpZE9wdGlvbnMsIHRoZW4gdGhlIHJvdyBkYXRhIGlzIHNldCBiZWZvcmVcbiAgICAgICAgLy8gZ3JpZCBpcyBhdHRhY2hlZCB0byB0aGUgRE9NLiB0aGlzIG1lYW5zIHRoZSBjb2x1bW5zIGFyZSBub3QgZmxleGVkLCBhbmQgdGhlbiB0aGUgcm93c1xuICAgICAgICAvLyBoYXZlIHRoZSB3cm9uZyBoZWlnaHQgKGFzIHRoZXkgZGVwZW5kIG9uIGNvbHVtbiB3aWR0aHMpLiBzbyBvbmNlIHRoZSBjb2x1bW5zIGhhdmVcbiAgICAgICAgLy8gYmVlbiBmbGV4ZWQgZm9yIHRoZSBmaXJzdCB0aW1lIChvbmx5IGhhcHBlbnMgb25jZSBncmlkIGlzIGF0dGFjaGVkIHRvIERPTSwgYXMgZGVwZW5kZW5jeVxuICAgICAgICAvLyBvbiBnZXR0aW5nIHRoZSBncmlkIHdpZHRoLCB3aGljaCBvbmx5IGhhcHBlbnMgYWZ0ZXIgYXR0YWNoZWQgYWZ0ZXIgUmVzaXplT2JzZXJ2ZXIgZmlyZXMpXG4gICAgICAgIC8vIHdlIGdldCBnZXQgcm93cyB0byByZS1jYWxjIHRoZWlyIGhlaWdodHMuXG4gICAgICAgIGlmICghdGhpcy5mbGV4Q29sc0NhbGN1bGF0ZWRBdExlc3RPbmNlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSb3dNb2RlbERlZmF1bHQoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMucm93TW9kZWwucmVzZXRSb3dIZWlnaHRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmZsZXhDb2xzQ2FsY3VsYXRlZEF0TGVzdE9uY2UgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmbGV4aW5nQ29sdW1ucztcbiAgICB9O1xuICAgIC8vIGNhbGxlZCBmcm9tIGFwaVxuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5zaXplQ29sdW1uc1RvRml0ID0gZnVuY3Rpb24gKGdyaWRXaWR0aCwgc291cmNlLCBzaWxlbnQsIHBhcmFtcykge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJzaXplQ29sdW1uc1RvRml0XCI7IH1cbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2YsIF9nLCBfaCwgX2osIF9rLCBfbDtcbiAgICAgICAgdmFyIGxpbWl0c01hcCA9IHt9O1xuICAgICAgICBpZiAocGFyYW1zKSB7XG4gICAgICAgICAgICAoX2IgPSAoX2EgPSBwYXJhbXMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jb2x1bW5MaW1pdHMpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5mb3JFYWNoKGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBfYS5rZXksIGRpbWVuc2lvbnMgPSBfX3Jlc3QoX2EsIFtcImtleVwiXSk7XG4gICAgICAgICAgICAgICAgbGltaXRzTWFwW3R5cGVvZiBrZXkgPT09ICdzdHJpbmcnID8ga2V5IDoga2V5LmdldENvbElkKCldID0gZGltZW5zaW9ucztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIGF2b2lkIGRpdmlkZSBieSB6ZXJvXG4gICAgICAgIHZhciBhbGxEaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7XG4gICAgICAgIHZhciBkb0NvbHVtbnNBbHJlYWR5Rml0ID0gZ3JpZFdpZHRoID09PSB0aGlzLmdldFdpZHRoT2ZDb2xzSW5MaXN0KGFsbERpc3BsYXllZENvbHVtbnMpO1xuICAgICAgICBpZiAoZ3JpZFdpZHRoIDw9IDAgfHwgIWFsbERpc3BsYXllZENvbHVtbnMubGVuZ3RoIHx8IGRvQ29sdW1uc0FscmVhZHlGaXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sc1RvU3ByZWFkID0gW107XG4gICAgICAgIHZhciBjb2xzVG9Ob3RTcHJlYWQgPSBbXTtcbiAgICAgICAgYWxsRGlzcGxheWVkQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIGlmIChjb2x1bW4uZ2V0Q29sRGVmKCkuc3VwcHJlc3NTaXplVG9GaXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2xzVG9Ob3RTcHJlYWQucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29sc1RvU3ByZWFkLnB1c2goY29sdW1uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIG1ha2UgYSBjb3B5IG9mIHRoZSBjb2xzIHRoYXQgYXJlIGdvaW5nIHRvIGJlIHJlc2l6ZWRcbiAgICAgICAgdmFyIGNvbHNUb0ZpcmVFdmVudEZvciA9IGNvbHNUb1NwcmVhZC5zbGljZSgwKTtcbiAgICAgICAgdmFyIGZpbmlzaGVkUmVzaXppbmcgPSBmYWxzZTtcbiAgICAgICAgdmFyIG1vdmVUb05vdFNwcmVhZCA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHJlbW92ZUZyb21BcnJheShjb2xzVG9TcHJlYWQsIGNvbHVtbik7XG4gICAgICAgICAgICBjb2xzVG9Ob3RTcHJlYWQucHVzaChjb2x1bW4pO1xuICAgICAgICB9O1xuICAgICAgICAvLyByZXNldHRpbmcgY29scyB0byB0aGVpciBvcmlnaW5hbCB3aWR0aCBtYWtlcyB0aGUgc2l6ZUNvbHVtbnNUb0ZpdCBtb3JlIGRldGVybWluaXN0aWMsXG4gICAgICAgIC8vIHJhdGhlciB0aGFuIGRlcGVuZGluZyBvbiB0aGUgY3VycmVudCBzaXplIG9mIHRoZSBjb2x1bW5zLiBtb3N0IHVzZXJzIGNhbGwgc2l6ZUNvbHVtbnNUb0ZpdFxuICAgICAgICAvLyBpbW1lZGlhdGVseSBhZnRlciBncmlkIGlzIGNyZWF0ZWQsIHNvIHdpbGwgbWFrZSBubyBkaWZmZXJlbmNlLiBob3dldmVyIGlmIGFwcGxpY2F0aW9uIGlzIGNhbGxpbmdcbiAgICAgICAgLy8gc2l6ZUNvbHVtbnNUb0ZpdCByZXBlYXRlZGx5IChlZyBhZnRlciBjb2x1bW4gZ3JvdXAgaXMgb3BlbmVkIC8gY2xvc2VkIHJlcGVhdGVkbHkpIHdlIGRvbid0IHdhbnRcbiAgICAgICAgLy8gdGhlIGNvbHVtbnMgdG8gc3RhcnQgc2hyaW5raW5nIC8gZ3Jvd2luZyBvdmVyIHRpbWUuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIE5PVEU6IHRoZSBwcm9jZXNzIGJlbG93IHdpbGwgYXNzaWduIHZhbHVlcyB0byBgdGhpcy5hY3R1YWxXaWR0aGAgb2YgZWFjaCBjb2x1bW4gd2l0aG91dCBmaXJpbmcgZXZlbnRzXG4gICAgICAgIC8vIGZvciB0aGlzIHJlYXNvbiB3ZSBuZWVkIHRvIG1hbnVhbGx5IGZpcmUgcmVzaXplIGV2ZW50cyBhZnRlciB0aGUgcmVzaXplIGhhcyBiZWVuIGRvbmUgZm9yIGVhY2ggY29sdW1uLlxuICAgICAgICBjb2xzVG9TcHJlYWQuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiBjb2x1bW4ucmVzZXRBY3R1YWxXaWR0aChzb3VyY2UpOyB9KTtcbiAgICAgICAgd2hpbGUgKCFmaW5pc2hlZFJlc2l6aW5nKSB7XG4gICAgICAgICAgICBmaW5pc2hlZFJlc2l6aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBhdmFpbGFibGVQaXhlbHMgPSBncmlkV2lkdGggLSB0aGlzLmdldFdpZHRoT2ZDb2xzSW5MaXN0KGNvbHNUb05vdFNwcmVhZCk7XG4gICAgICAgICAgICBpZiAoYXZhaWxhYmxlUGl4ZWxzIDw9IDApIHtcbiAgICAgICAgICAgICAgICAvLyBubyB3aWR0aCwgc2V0IGV2ZXJ5dGhpbmcgdG8gbWluaW11bVxuICAgICAgICAgICAgICAgIGNvbHNUb1NwcmVhZC5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kO1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2lkdGhPdmVycmlkZSA9IChfYyA9IChfYiA9IChfYSA9IGxpbWl0c01hcCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hW2NvbHVtbi5nZXRJZCgpXSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLm1pbldpZHRoLCAoX2MgIT09IG51bGwgJiYgX2MgIT09IHZvaWQgMCA/IF9jIDogKF9kID0gcGFyYW1zKSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QuZGVmYXVsdE1pbldpZHRoKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygd2lkdGhPdmVycmlkZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbi5zZXRBY3R1YWxXaWR0aCh3aWR0aE92ZXJyaWRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb2x1bW4uc2V0TWluaW11bShzb3VyY2UpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjYWxlID0gYXZhaWxhYmxlUGl4ZWxzIC8gdGhpcy5nZXRXaWR0aE9mQ29sc0luTGlzdChjb2xzVG9TcHJlYWQpO1xuICAgICAgICAgICAgICAgIC8vIHdlIHNldCB0aGUgcGl4ZWxzIGZvciB0aGUgbGFzdCBjb2wgYmFzZWQgb24gd2hhdCdzIGxlZnQsIGFzIG90aGVyd2lzZVxuICAgICAgICAgICAgICAgIC8vIHdlIGNvdWxkIGJlIGEgcGl4ZWwgb3IgdHdvIHNob3J0IG9yIGV4dHJhIGJlY2F1c2Ugb2Ygcm91bmRpbmcgZXJyb3JzLlxuICAgICAgICAgICAgICAgIHZhciBwaXhlbHNGb3JMYXN0Q29sID0gYXZhaWxhYmxlUGl4ZWxzO1xuICAgICAgICAgICAgICAgIC8vIGJhY2t3YXJkcyB0aHJvdWdoIGxvb3AsIGFzIHdlIGFyZSByZW1vdmluZyBpdGVtcyBhcyB3ZSBnb1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSBjb2xzVG9TcHJlYWQubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IGNvbHNUb1NwcmVhZFtpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdpZHRoT3ZlcnJpZGUgPSAoX2MgPSBsaW1pdHNNYXApID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfY1tjb2x1bW4uZ2V0SWQoKV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBtaW5PdmVycmlkZSA9IChfZSA9IChfZCA9IHdpZHRoT3ZlcnJpZGUpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5taW5XaWR0aCwgKF9lICE9PSBudWxsICYmIF9lICE9PSB2b2lkIDAgPyBfZSA6IChfZiA9IHBhcmFtcykgPT09IG51bGwgfHwgX2YgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9mLmRlZmF1bHRNaW5XaWR0aCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF4T3ZlcnJpZGUgPSAoX2ggPSAoX2cgPSB3aWR0aE92ZXJyaWRlKSA9PT0gbnVsbCB8fCBfZyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2cubWF4V2lkdGgsIChfaCAhPT0gbnVsbCAmJiBfaCAhPT0gdm9pZCAwID8gX2ggOiAoX2ogPSBwYXJhbXMpID09PSBudWxsIHx8IF9qID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfai5kZWZhdWx0TWF4V2lkdGgpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbE1pbldpZHRoID0gKF9rID0gY29sdW1uLmdldE1pbldpZHRoKCksIChfayAhPT0gbnVsbCAmJiBfayAhPT0gdm9pZCAwID8gX2sgOiAwKSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb2xNYXhXaWR0aCA9IChfbCA9IGNvbHVtbi5nZXRNYXhXaWR0aCgpLCAoX2wgIT09IG51bGwgJiYgX2wgIT09IHZvaWQgMCA/IF9sIDogTnVtYmVyLk1BWF9WQUxVRSkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWluV2lkdGggPSB0eXBlb2YgbWluT3ZlcnJpZGUgPT09ICdudW1iZXInICYmIG1pbk92ZXJyaWRlID4gY29sTWluV2lkdGggPyBtaW5PdmVycmlkZSA6IGNvbHVtbi5nZXRNaW5XaWR0aCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF4V2lkdGggPSB0eXBlb2YgbWF4T3ZlcnJpZGUgPT09ICdudW1iZXInICYmIG1heE92ZXJyaWRlIDwgY29sTWF4V2lkdGggPyBtYXhPdmVycmlkZSA6IGNvbHVtbi5nZXRNYXhXaWR0aCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3V2lkdGggPSBNYXRoLnJvdW5kKGNvbHVtbi5nZXRBY3R1YWxXaWR0aCgpICogc2NhbGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhpc3RzKG1pbldpZHRoKSAmJiBuZXdXaWR0aCA8IG1pbldpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdXaWR0aCA9IG1pbldpZHRoO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZVRvTm90U3ByZWFkKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5pc2hlZFJlc2l6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoZXhpc3RzKG1heFdpZHRoKSAmJiBuZXdXaWR0aCA+IG1heFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdXaWR0aCA9IG1heFdpZHRoO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZVRvTm90U3ByZWFkKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaW5pc2hlZFJlc2l6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoaSA9PT0gMCkgeyAvLyBpZiB0aGlzIGlzIHRoZSBsYXN0IGNvbHVtblxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3V2lkdGggPSBwaXhlbHNGb3JMYXN0Q29sO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbi5zZXRBY3R1YWxXaWR0aChuZXdXaWR0aCwgc291cmNlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxzRm9yTGFzdENvbCAtPSBuZXdXaWR0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gc2VlIG5vdGVzIGFib3ZlXG4gICAgICAgIGNvbHNUb0ZpcmVFdmVudEZvci5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIGNvbC5maXJlQ29sdW1uV2lkdGhDaGFuZ2VkRXZlbnQoc291cmNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc2V0TGVmdFZhbHVlcyhzb3VyY2UpO1xuICAgICAgICB0aGlzLnVwZGF0ZUJvZHlXaWR0aHMoKTtcbiAgICAgICAgaWYgKHNpbGVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZmlyZUNvbHVtblJlc2l6ZWRFdmVudChjb2xzVG9GaXJlRXZlbnRGb3IsIHRydWUsIHNvdXJjZSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuYnVpbGREaXNwbGF5ZWRUcmVlcyA9IGZ1bmN0aW9uICh2aXNpYmxlQ29sdW1ucykge1xuICAgICAgICB2YXIgbGVmdFZpc2libGVDb2x1bW5zID0gW107XG4gICAgICAgIHZhciByaWdodFZpc2libGVDb2x1bW5zID0gW107XG4gICAgICAgIHZhciBjZW50ZXJWaXNpYmxlQ29sdW1ucyA9IFtdO1xuICAgICAgICB2aXNpYmxlQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHN3aXRjaCAoY29sdW1uLmdldFBpbm5lZCgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcImxlZnRcIjpcbiAgICAgICAgICAgICAgICAgICAgbGVmdFZpc2libGVDb2x1bW5zLnB1c2goY29sdW1uKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcInJpZ2h0XCI6XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0VmlzaWJsZUNvbHVtbnMucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBjZW50ZXJWaXNpYmxlQ29sdW1ucy5wdXNoKGNvbHVtbik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGdyb3VwSW5zdGFuY2VJZENyZWF0b3IgPSBuZXcgR3JvdXBJbnN0YW5jZUlkQ3JlYXRvcigpO1xuICAgICAgICB0aGlzLmRpc3BsYXllZFRyZWVMZWZ0ID0gdGhpcy5kaXNwbGF5ZWRHcm91cENyZWF0b3IuY3JlYXRlRGlzcGxheWVkR3JvdXBzKGxlZnRWaXNpYmxlQ29sdW1ucywgdGhpcy5ncmlkQmFsYW5jZWRUcmVlLCBncm91cEluc3RhbmNlSWRDcmVhdG9yLCBDb25zdGFudHMuUElOTkVEX0xFRlQsIHRoaXMuZGlzcGxheWVkVHJlZUxlZnQpO1xuICAgICAgICB0aGlzLmRpc3BsYXllZFRyZWVSaWdodCA9IHRoaXMuZGlzcGxheWVkR3JvdXBDcmVhdG9yLmNyZWF0ZURpc3BsYXllZEdyb3VwcyhyaWdodFZpc2libGVDb2x1bW5zLCB0aGlzLmdyaWRCYWxhbmNlZFRyZWUsIGdyb3VwSW5zdGFuY2VJZENyZWF0b3IsIENvbnN0YW50cy5QSU5ORURfUklHSFQsIHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0KTtcbiAgICAgICAgdGhpcy5kaXNwbGF5ZWRUcmVlQ2VudHJlID0gdGhpcy5kaXNwbGF5ZWRHcm91cENyZWF0b3IuY3JlYXRlRGlzcGxheWVkR3JvdXBzKGNlbnRlclZpc2libGVDb2x1bW5zLCB0aGlzLmdyaWRCYWxhbmNlZFRyZWUsIGdyb3VwSW5zdGFuY2VJZENyZWF0b3IsIG51bGwsIHRoaXMuZGlzcGxheWVkVHJlZUNlbnRyZSk7XG4gICAgICAgIHRoaXMudXBkYXRlRGlzcGxheWVkTWFwKCk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUudXBkYXRlRGlzcGxheWVkTWFwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnNBbmRHcm91cHNNYXAgPSB7fTtcbiAgICAgICAgdmFyIGZ1bmMgPSBmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIF90aGlzLmRpc3BsYXllZENvbHVtbnNBbmRHcm91cHNNYXBbY2hpbGQuZ2V0VW5pcXVlSWQoKV0gPSBjaGlsZDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jb2x1bW5VdGlscy5kZXB0aEZpcnN0QWxsQ29sdW1uVHJlZVNlYXJjaCh0aGlzLmRpc3BsYXllZFRyZWVDZW50cmUsIGZ1bmMpO1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RBbGxDb2x1bW5UcmVlU2VhcmNoKHRoaXMuZGlzcGxheWVkVHJlZUxlZnQsIGZ1bmMpO1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RBbGxDb2x1bW5UcmVlU2VhcmNoKHRoaXMuZGlzcGxheWVkVHJlZVJpZ2h0LCBmdW5jKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5pc0Rpc3BsYXllZCA9IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIHZhciBmcm9tTWFwID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zQW5kR3JvdXBzTWFwW2l0ZW0uZ2V0VW5pcXVlSWQoKV07XG4gICAgICAgIC8vIGNoZWNrIGZvciByZWZlcmVuY2UsIGluIGNhc2UgbmV3IGNvbHVtbiAvIGdyb3VwIHdpdGggc2FtZSBpZCBpcyBub3cgcHJlc2VudFxuICAgICAgICByZXR1cm4gZnJvbU1hcCA9PT0gaXRlbTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS51cGRhdGVPcGVuQ2xvc2VkVmlzaWJpbGl0eUluQ29sdW1uR3JvdXBzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYWxsQ29sdW1uR3JvdXBzID0gdGhpcy5nZXRBbGxEaXNwbGF5ZWRUcmVlcygpO1xuICAgICAgICB0aGlzLmNvbHVtblV0aWxzLmRlcHRoRmlyc3RBbGxDb2x1bW5UcmVlU2VhcmNoKGFsbENvbHVtbkdyb3VwcywgZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW5Hcm91cCA9IGNoaWxkO1xuICAgICAgICAgICAgICAgIGNvbHVtbkdyb3VwLmNhbGN1bGF0ZURpc3BsYXllZENvbHVtbnMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5Nb2RlbC5wcm90b3R5cGUuZ2V0R3JvdXBBdXRvQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JvdXBBdXRvQ29sdW1ucztcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgbmV3IGF1dG8gZ3JvdXAgY29sdW1ucyBpZiByZXF1aXJlZFxuICAgICAqIEByZXR1cm5zIHdoZXRoZXIgYXV0byBjb2xzIGhhdmUgY2hhbmdlZFxuICAgICAqL1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5jcmVhdGVHcm91cEF1dG9Db2x1bW5zSWZOZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5hdXRvR3JvdXBzTmVlZEJ1aWxkaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hdXRvR3JvdXBzTmVlZEJ1aWxkaW5nID0gZmFsc2U7XG4gICAgICAgIHZhciBncm91cEZ1bGxXaWR0aFJvdyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBVc2VFbnRpcmVSb3codGhpcy5waXZvdE1vZGUpO1xuICAgICAgICAvLyB3ZSBuZWVkIHRvIGFsbG93IHN1cHByZXNzaW5nIGF1dG8tY29sdW1uIHNlcGFyYXRlbHkgZm9yIGdyb3VwIGFuZCBwaXZvdCBhcyB0aGUgbm9ybWFsIHNpdHVhdGlvblxuICAgICAgICAvLyBpcyBDU1JNIGFuZCB1c2VyIHByb3ZpZGVzIGdyb3VwIGNvbHVtbiB0aGVtc2VsdmVzIGZvciBub3JtYWwgdmlldywgYnV0IHdoZW4gdGhleSBnbyBpbnRvIHBpdm90IHRoZVxuICAgICAgICAvLyBjb2x1bW5zIGFyZSBnZW5lcmF0ZWQgYnkgdGhlIGdyaWQgc28gbm8gb3Bwb3J0dW5pdHkgZm9yIHVzZXIgdG8gcHJvdmlkZSBncm91cCBjb2x1bW4uIHNvIG5lZWQgYSB3YXlcbiAgICAgICAgLy8gdG8gc3VwcHJlc3MgYXV0by1jb2wgZm9yIGdyb3VwaW5nIG9ubHksIGFuZCBub3QgcGl2b3QuXG4gICAgICAgIC8vIGhvd2V2ZXIgaWYgdXNpbmcgVmlld3BvcnQgUk0gb3IgU1NSTSBhbmQgdXNlciBpcyBwcm92aWRpbmcgdGhlIGNvbHVtbnMsIHRoZSB1c2VyIG1heSB3aXNoIGZ1bGwgY29udHJvbFxuICAgICAgICAvLyBvZiB0aGUgZ3JvdXAgY29sdW1uIGluIHRoaXMgaW5zdGFuY2UuXG4gICAgICAgIHZhciBzdXBwcmVzc0F1dG9Db2x1bW4gPSB0aGlzLnBpdm90TW9kZSA/XG4gICAgICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Bpdm90U3VwcHJlc3NBdXRvQ29sdW1uKCkgOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU3VwcHJlc3NBdXRvQ29sdW1uKCk7XG4gICAgICAgIHZhciBncm91cGluZ0FjdGl2ZSA9IHRoaXMucm93R3JvdXBDb2x1bW5zLmxlbmd0aCA+IDAgfHwgdGhpcy51c2luZ1RyZWVEYXRhO1xuICAgICAgICB2YXIgbmVlZEF1dG9Db2x1bW5zID0gZ3JvdXBpbmdBY3RpdmUgJiYgIXN1cHByZXNzQXV0b0NvbHVtbiAmJiAhZ3JvdXBGdWxsV2lkdGhSb3c7XG4gICAgICAgIGlmIChuZWVkQXV0b0NvbHVtbnMpIHtcbiAgICAgICAgICAgIHZhciBleGlzdGluZ0NvbHMgPSB0aGlzLmdyb3VwQXV0b0NvbHVtbnMgfHwgW107XG4gICAgICAgICAgICB2YXIgbmV3QXV0b0dyb3VwQ29scyA9IHRoaXMuYXV0b0dyb3VwQ29sU2VydmljZS5jcmVhdGVBdXRvR3JvdXBDb2x1bW5zKGV4aXN0aW5nQ29scywgdGhpcy5yb3dHcm91cENvbHVtbnMpO1xuICAgICAgICAgICAgdmFyIGF1dG9Db2xzRGlmZmVyZW50ID0gIXRoaXMuYXV0b0NvbHNFcXVhbChuZXdBdXRvR3JvdXBDb2xzLCB0aGlzLmdyb3VwQXV0b0NvbHVtbnMpO1xuICAgICAgICAgICAgLy8gd2UgZm9yY2UgcmVjcmVhdGUgd2hlbiBzdXBwcmVzc0NvbHVtblN0YXRlRXZlbnRzIGNoYW5nZXMsIHNvIG5ldyBncm91cCBjb2xzIHBpY2sgdXAgdGhlIG5ld1xuICAgICAgICAgICAgLy8gZGVmaW5pdGlvbnMuIG90aGVyd2lzZSB3ZSBjb3VsZCBpZ25vcmUgdGhlIG5ldyBjb2xzIGJlY2F1c2UgdGhleSBhcHBlYXIgdG8gYmUgdGhlIHNhbWUuXG4gICAgICAgICAgICBpZiAoYXV0b0NvbHNEaWZmZXJlbnQgfHwgdGhpcy5mb3JjZVJlY3JlYXRlQXV0b0dyb3Vwcykge1xuICAgICAgICAgICAgICAgIHRoaXMuZ3JvdXBBdXRvQ29sdW1ucyA9IG5ld0F1dG9Hcm91cENvbHM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmdyb3VwQXV0b0NvbHVtbnMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5hdXRvQ29sc0VxdWFsID0gZnVuY3Rpb24gKGNvbHNBLCBjb2xzQikge1xuICAgICAgICByZXR1cm4gYXJlRXF1YWwoY29sc0EsIGNvbHNCLCBmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYS5nZXRDb2xJZCgpID09PSBiLmdldENvbElkKCk7IH0pO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldFdpZHRoT2ZDb2xzSW5MaXN0ID0gZnVuY3Rpb24gKGNvbHVtbkxpc3QpIHtcbiAgICAgICAgcmV0dXJuIGNvbHVtbkxpc3QucmVkdWNlKGZ1bmN0aW9uICh3aWR0aCwgY29sKSB7IHJldHVybiB3aWR0aCArIGNvbC5nZXRBY3R1YWxXaWR0aCgpOyB9LCAwKTtcbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRHcmlkQmFsYW5jZWRUcmVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkQmFsYW5jZWRUcmVlO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmhhc0Zsb2F0aW5nRmlsdGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRDb2x1bW5zKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlcyA9IHRoaXMuZ3JpZENvbHVtbnMuc29tZShmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuZ2V0Q29sRGVmKCkuZmxvYXRpbmdGaWx0ZXI7IH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldEZpcnN0RGlzcGxheWVkQ29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICB2YXIgcXVlcnlPcmRlciA9IFtcbiAgICAgICAgICAgICdnZXREaXNwbGF5ZWRMZWZ0Q29sdW1ucycsXG4gICAgICAgICAgICAnZ2V0RGlzcGxheWVkQ2VudGVyQ29sdW1ucycsXG4gICAgICAgICAgICAnZ2V0RGlzcGxheWVkUmlnaHRDb2x1bW5zJ1xuICAgICAgICBdO1xuICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgIHF1ZXJ5T3JkZXIucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcXVlcnlPcmRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXNbcXVlcnlPcmRlcltpXV0oKTtcbiAgICAgICAgICAgIGlmIChjb250YWluZXIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzUnRsID8gbGFzdChjb250YWluZXIpIDogY29udGFpbmVyWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLnNldENvbHVtbkhlYWRlckhlaWdodCA9IGZ1bmN0aW9uIChjb2wsIGhlaWdodCkge1xuICAgICAgICB2YXIgY2hhbmdlZCA9IGNvbC5zZXRBdXRvSGVhZGVySGVpZ2h0KGhlaWdodCk7XG4gICAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgICAgICB2YXIgZXZlbnRfNSA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfQ09MVU1OX0hFQURFUl9IRUlHSFRfQ0hBTkdFRCxcbiAgICAgICAgICAgICAgICBjb2x1bW46IGNvbCxcbiAgICAgICAgICAgICAgICBjb2x1bW5zOiBbY29sXSxcbiAgICAgICAgICAgICAgICBzb3VyY2U6ICdhdXRvc2l6ZUNvbHVtbkhlYWRlckhlaWdodCcsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF81KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uTW9kZWwucHJvdG90eXBlLmdldENvbHVtbkdyb3VwSGVhZGVyUm93SGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Bpdm90TW9kZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0UGl2b3RHcm91cEhlYWRlckhlaWdodCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEdyb3VwSGVhZGVySGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENvbHVtbk1vZGVsLnByb3RvdHlwZS5nZXRDb2x1bW5IZWFkZXJSb3dIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkZWZhdWx0SGVpZ2h0ID0gKHRoaXMuaXNQaXZvdE1vZGUoKSA/XG4gICAgICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRQaXZvdEhlYWRlckhlaWdodCgpIDpcbiAgICAgICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEhlYWRlckhlaWdodCgpKTtcbiAgICAgICAgdmFyIGRpc3BsYXllZEhlaWdodHMgPSB0aGlzLmdldEFsbERpc3BsYXllZENvbHVtbnMoKVxuICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuaXNBdXRvSGVhZGVySGVpZ2h0KCk7IH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5nZXRBdXRvSGVhZGVySGVpZ2h0KCkgfHwgMDsgfSk7XG4gICAgICAgIHJldHVybiBNYXRoLm1heC5hcHBseShNYXRoLCBfX3NwcmVhZCRmKFtkZWZhdWx0SGVpZ2h0XSwgZGlzcGxheWVkSGVpZ2h0cykpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEF1dG93aXJlZCgnZXhwcmVzc2lvblNlcnZpY2UnKVxuICAgIF0sIENvbHVtbk1vZGVsLnByb3RvdHlwZSwgXCJleHByZXNzaW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnUoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbkZhY3RvcnknKVxuICAgIF0sIENvbHVtbk1vZGVsLnByb3RvdHlwZSwgXCJjb2x1bW5GYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEF1dG93aXJlZCgnZGlzcGxheWVkR3JvdXBDcmVhdG9yJylcbiAgICBdLCBDb2x1bW5Nb2RlbC5wcm90b3R5cGUsIFwiZGlzcGxheWVkR3JvdXBDcmVhdG9yXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEF1dG93aXJlZCgnY3RybHNTZXJ2aWNlJylcbiAgICBdLCBDb2x1bW5Nb2RlbC5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEF1dG93aXJlZCgnYXV0b1dpZHRoQ2FsY3VsYXRvcicpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcImF1dG9XaWR0aENhbGN1bGF0b3JcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ1KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5VdGlscycpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcImNvbHVtblV0aWxzXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uQW5pbWF0aW9uU2VydmljZScpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcImNvbHVtbkFuaW1hdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ1KFtcbiAgICAgICAgQXV0b3dpcmVkKCdhdXRvR3JvdXBDb2xTZXJ2aWNlJylcbiAgICBdLCBDb2x1bW5Nb2RlbC5wcm90b3R5cGUsIFwiYXV0b0dyb3VwQ29sU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnUoW1xuICAgICAgICBPcHRpb25hbCgnYWdnRnVuY1NlcnZpY2UnKVxuICAgIF0sIENvbHVtbk1vZGVsLnByb3RvdHlwZSwgXCJhZ2dGdW5jU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnUoW1xuICAgICAgICBPcHRpb25hbCgndmFsdWVDYWNoZScpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcInZhbHVlQ2FjaGVcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ1KFtcbiAgICAgICAgT3B0aW9uYWwoJ2FuaW1hdGlvbkZyYW1lU2VydmljZScpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcImFuaW1hdGlvbkZyYW1lU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBDb2x1bW5Nb2RlbC5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ1KFtcbiAgICAgICAgQXV0b3dpcmVkKCdzb3J0Q29udHJvbGxlcicpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcInNvcnRDb250cm9sbGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uRGVmRmFjdG9yeScpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcImNvbHVtbkRlZkZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJ1KFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIENvbHVtbk1vZGVsLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMnUoW1xuICAgICAgICBfX3BhcmFtJDcoMCwgUXVhbGlmaWVyKCdsb2dnZXJGYWN0b3J5JykpXG4gICAgXSwgQ29sdW1uTW9kZWwucHJvdG90eXBlLCBcInNldEJlYW5zXCIsIG51bGwpO1xuICAgIENvbHVtbk1vZGVsID0gX19kZWNvcmF0ZSQydShbXG4gICAgICAgIEJlYW4oJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBDb2x1bW5Nb2RlbCk7XG4gICAgcmV0dXJuIENvbHVtbk1vZGVsO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJTID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQydCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xuLy8gdGFrZXMgaW4gYSBsaXN0IG9mIGNvbHVtbnMsIGFzIHNwZWNpZmllZCBieSB0aGUgY29sdW1uIGRlZmluaXRpb25zLCBhbmQgcmV0dXJucyBjb2x1bW4gZ3JvdXBzXG52YXIgQ29sdW1uVXRpbHMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJTKENvbHVtblV0aWxzLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbHVtblV0aWxzKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIENvbHVtblV0aWxzLnByb3RvdHlwZS5jYWxjdWxhdGVDb2xNaW5XaWR0aCA9IGZ1bmN0aW9uIChjb2xEZWYpIHtcbiAgICAgICAgcmV0dXJuIGNvbERlZi5taW5XaWR0aCAhPSBudWxsID8gY29sRGVmLm1pbldpZHRoIDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TWluQ29sV2lkdGgoKTtcbiAgICB9O1xuICAgIENvbHVtblV0aWxzLnByb3RvdHlwZS5jYWxjdWxhdGVDb2xNYXhXaWR0aCA9IGZ1bmN0aW9uIChjb2xEZWYpIHtcbiAgICAgICAgcmV0dXJuIGNvbERlZi5tYXhXaWR0aCAhPSBudWxsID8gY29sRGVmLm1heFdpZHRoIDogKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldE1heENvbFdpZHRoKCkgfHwgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpO1xuICAgIH07XG4gICAgQ29sdW1uVXRpbHMucHJvdG90eXBlLmNhbGN1bGF0ZUNvbEluaXRpYWxXaWR0aCA9IGZ1bmN0aW9uIChjb2xEZWYpIHtcbiAgICAgICAgdmFyIG1pbkNvbFdpZHRoID0gdGhpcy5jYWxjdWxhdGVDb2xNaW5XaWR0aChjb2xEZWYpO1xuICAgICAgICB2YXIgbWF4Q29sV2lkdGggPSB0aGlzLmNhbGN1bGF0ZUNvbE1heFdpZHRoKGNvbERlZik7XG4gICAgICAgIHZhciB3aWR0aDtcbiAgICAgICAgdmFyIGNvbERlZldpZHRoID0gYXR0clRvTnVtYmVyKGNvbERlZi53aWR0aCk7XG4gICAgICAgIHZhciBjb2xEZWZJbml0aWFsV2lkdGggPSBhdHRyVG9OdW1iZXIoY29sRGVmLmluaXRpYWxXaWR0aCk7XG4gICAgICAgIGlmIChjb2xEZWZXaWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICB3aWR0aCA9IGNvbERlZldpZHRoO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvbERlZkluaXRpYWxXaWR0aCAhPSBudWxsKSB7XG4gICAgICAgICAgICB3aWR0aCA9IGNvbERlZkluaXRpYWxXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHdpZHRoID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sV2lkdGgoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWF0aC5tYXgoTWF0aC5taW4od2lkdGgsIG1heENvbFdpZHRoKSwgbWluQ29sV2lkdGgpO1xuICAgIH07XG4gICAgQ29sdW1uVXRpbHMucHJvdG90eXBlLmdldE9yaWdpbmFsUGF0aEZvckNvbHVtbiA9IGZ1bmN0aW9uIChjb2x1bW4sIG9yaWdpbmFsQmFsYW5jZWRUcmVlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdmFyIGZvdW5kID0gZmFsc2U7XG4gICAgICAgIHZhciByZWN1cnNlUGF0aCA9IGZ1bmN0aW9uIChiYWxhbmNlZENvbHVtblRyZWUsIGRlcHQpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmFsYW5jZWRDb2x1bW5UcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gcXVpdCB0aGUgc2VhcmNoLCBzbyAncmVzdWx0JyBpcyBrZXB0IHdpdGggdGhlIGZvdW5kIHJlc3VsdFxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gYmFsYW5jZWRDb2x1bW5UcmVlW2ldO1xuICAgICAgICAgICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgUHJvdmlkZWRDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dE5vZGUgPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICByZWN1cnNlUGF0aChuZXh0Tm9kZS5nZXRDaGlsZHJlbigpLCBkZXB0ICsgMSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtkZXB0XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5vZGUgPT09IGNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZWN1cnNlUGF0aChvcmlnaW5hbEJhbGFuY2VkVHJlZSwgMCk7XG4gICAgICAgIC8vIHdlIHNob3VsZCBhbHdheXMgZmluZCB0aGUgcGF0aCwgYnV0IGluIGNhc2UgdGhlcmUgaXMgYSBidWcgc29tZXdoZXJlLCByZXR1cm5pbmcgbnVsbFxuICAgICAgICAvLyB3aWxsIG1ha2UgaXQgZmFpbCByYXRoZXIgdGhhbiBwcm92aWRlIGEgJ2hhcmQgdG8gdHJhY2sgZG93bicgYnVnXG4gICAgICAgIHJldHVybiBmb3VuZCA/IHJlc3VsdCA6IG51bGw7XG4gICAgfTtcbiAgICBDb2x1bW5VdGlscy5wcm90b3R5cGUuZGVwdGhGaXJzdE9yaWdpbmFsVHJlZVNlYXJjaCA9IGZ1bmN0aW9uIChwYXJlbnQsIHRyZWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdHJlZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyZWUuZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kZXB0aEZpcnN0T3JpZ2luYWxUcmVlU2VhcmNoKGNoaWxkLCBjaGlsZC5nZXRDaGlsZHJlbigpLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhjaGlsZCwgcGFyZW50KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5VdGlscy5wcm90b3R5cGUuZGVwdGhGaXJzdEFsbENvbHVtblRyZWVTZWFyY2ggPSBmdW5jdGlvbiAodHJlZSwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0cmVlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJlZS5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgICAgICAgaWYgKGNoaWxkIGluc3RhbmNlb2YgQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kZXB0aEZpcnN0QWxsQ29sdW1uVHJlZVNlYXJjaChjaGlsZC5nZXRDaGlsZHJlbigpLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayhjaGlsZCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29sdW1uVXRpbHMucHJvdG90eXBlLmRlcHRoRmlyc3REaXNwbGF5ZWRDb2x1bW5UcmVlU2VhcmNoID0gZnVuY3Rpb24gKHRyZWUsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdHJlZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyZWUuZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIENvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZGVwdGhGaXJzdERpc3BsYXllZENvbHVtblRyZWVTZWFyY2goY2hpbGQuZ2V0RGlzcGxheWVkQ2hpbGRyZW4oKSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbGJhY2soY2hpbGQpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbHVtblV0aWxzID0gX19kZWNvcmF0ZSQydChbXG4gICAgICAgIEJlYW4oJ2NvbHVtblV0aWxzJylcbiAgICBdLCBDb2x1bW5VdGlscyk7XG4gICAgcmV0dXJuIENvbHVtblV0aWxzO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJSID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQycyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xuLy8gdGFrZXMgaW4gYSBsaXN0IG9mIGNvbHVtbnMsIGFzIHNwZWNpZmllZCBieSB0aGUgY29sdW1uIGRlZmluaXRpb25zLCBhbmQgcmV0dXJucyBjb2x1bW4gZ3JvdXBzXG52YXIgRGlzcGxheWVkR3JvdXBDcmVhdG9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyUihEaXNwbGF5ZWRHcm91cENyZWF0b3IsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGlzcGxheWVkR3JvdXBDcmVhdG9yKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIERpc3BsYXllZEdyb3VwQ3JlYXRvci5wcm90b3R5cGUuY3JlYXRlRGlzcGxheWVkR3JvdXBzID0gZnVuY3Rpb24gKFxuICAgIC8vIGFsbCBkaXNwbGF5ZWQgY29sdW1ucyBzb3J0ZWQgLSB0aGlzIGlzIHRoZSBjb2x1bW5zIHRoZSBncmlkIHNob3VsZCBzaG93XG4gICAgc29ydGVkVmlzaWJsZUNvbHVtbnMsIFxuICAgIC8vIHRoZSB0cmVlIG9mIGNvbHVtbnMsIGFzIHByb3ZpZGVkIGJ5IHRoZSB1c2VycywgdXNlZCB0byBrbm93IHdoYXQgZ3JvdXBzIGNvbHVtbnMgcm9sbCB1cCBpbnRvXG4gICAgYmFsYW5jZWRDb2x1bW5UcmVlLCBcbiAgICAvLyBjcmVhdGVzIHVuaXF1ZSBpZCdzIGZvciB0aGUgZ3JvdXBcbiAgICBncm91cEluc3RhbmNlSWRDcmVhdG9yLCBcbiAgICAvLyB3aGV0aGVyIGl0J3MgbGVmdCwgcmlnaHQgb3IgY2VudGVyIGNvbFxuICAgIHBpbm5lZCwgXG4gICAgLy8gd2UgdHJ5IHRvIHJldXNlIG9sZCBncm91cHMgaWYgd2UgY2FuLCB0byBhbGxvdyBndWkgdG8gZG8gYW5pbWF0aW9uXG4gICAgb2xkRGlzcGxheWVkR3JvdXBzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdmFyIHByZXZpb3VzUmVhbFBhdGg7XG4gICAgICAgIHZhciBwcmV2aW91c09yaWdpbmFsUGF0aDtcbiAgICAgICAgdmFyIG9sZENvbHVtbnNNYXBwZWQgPSB0aGlzLm1hcE9sZEdyb3Vwc0J5SWQob2xkRGlzcGxheWVkR3JvdXBzKTtcbiAgICAgICAgLy8gZ28gdGhyb3VnaCBlYWNoIGNvbHVtbiwgdGhlbiBkbyBhIGJvdHRvbSB1cCBjb21wYXJpc29uIHRvIHRoZSBwcmV2aW91cyBjb2x1bW4sIGFuZCBzdGFydFxuICAgICAgICAvLyB0byBzaGFyZSBncm91cHMgaWYgdGhleSBjb252ZXJnZSBhdCBhbnkgcG9pbnQuXG4gICAgICAgIHNvcnRlZFZpc2libGVDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGN1cnJlbnRDb2x1bW4pIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50T3JpZ2luYWxQYXRoID0gX3RoaXMuZ2V0T3JpZ2luYWxQYXRoRm9yQ29sdW1uKGJhbGFuY2VkQ29sdW1uVHJlZSwgY3VycmVudENvbHVtbik7XG4gICAgICAgICAgICB2YXIgY3VycmVudFJlYWxQYXRoID0gW107XG4gICAgICAgICAgICB2YXIgZmlyc3RDb2x1bW4gPSAhcHJldmlvdXNPcmlnaW5hbFBhdGg7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGN1cnJlbnRPcmlnaW5hbFBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RDb2x1bW4gfHwgY3VycmVudE9yaWdpbmFsUGF0aFtpXSAhPT0gcHJldmlvdXNPcmlnaW5hbFBhdGhbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbmV3IGdyb3VwIG5lZWRlZFxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3R3JvdXAgPSBfdGhpcy5jcmVhdGVDb2x1bW5Hcm91cChjdXJyZW50T3JpZ2luYWxQYXRoW2ldLCBncm91cEluc3RhbmNlSWRDcmVhdG9yLCBvbGRDb2x1bW5zTWFwcGVkLCBwaW5uZWQpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50UmVhbFBhdGhbaV0gPSBuZXdHcm91cDtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdG9wIGxldmVsLCBhZGQgdG8gcmVzdWx0LCBvdGhlcndpc2UgYWRkIHRvIHBhcmVudFxuICAgICAgICAgICAgICAgICAgICBpZiAoaSA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChuZXdHcm91cCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50UmVhbFBhdGhbaSAtIDFdLmFkZENoaWxkKG5ld0dyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcmV1c2Ugb2xkIGdyb3VwXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRSZWFsUGF0aFtpXSA9IHByZXZpb3VzUmVhbFBhdGhbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG5vQ29sdW1uR3JvdXBzID0gY3VycmVudFJlYWxQYXRoLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgICAgIGlmIChub0NvbHVtbkdyb3Vwcykge1xuICAgICAgICAgICAgICAgIC8vIGlmIHdlIGFyZSBub3QgZ3JvdXBpbmcsIHRoZW4gdGhlIHJlc3VsdCBvZiB0aGUgYWJvdmUgaXMgYW4gZW1wdHlcbiAgICAgICAgICAgICAgICAvLyBwYXRoIChubyBncm91cHMpLCBhbmQgd2UganVzdCBhZGQgdGhlIGNvbHVtbiB0byB0aGUgcm9vdCBsaXN0LlxuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnRDb2x1bW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGxlYWZHcm91cCA9IGxhc3QoY3VycmVudFJlYWxQYXRoKTtcbiAgICAgICAgICAgICAgICBsZWFmR3JvdXAuYWRkQ2hpbGQoY3VycmVudENvbHVtbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2aW91c1JlYWxQYXRoID0gY3VycmVudFJlYWxQYXRoO1xuICAgICAgICAgICAgcHJldmlvdXNPcmlnaW5hbFBhdGggPSBjdXJyZW50T3JpZ2luYWxQYXRoO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zZXR1cFBhcmVudHNJbnRvQ29sdW1ucyhyZXN1bHQsIG51bGwpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgRGlzcGxheWVkR3JvdXBDcmVhdG9yLnByb3RvdHlwZS5jcmVhdGVDb2x1bW5Hcm91cCA9IGZ1bmN0aW9uIChwcm92aWRlZEdyb3VwLCBncm91cEluc3RhbmNlSWRDcmVhdG9yLCBvbGRDb2x1bW5zTWFwcGVkLCBwaW5uZWQpIHtcbiAgICAgICAgdmFyIGdyb3VwSWQgPSBwcm92aWRlZEdyb3VwLmdldEdyb3VwSWQoKTtcbiAgICAgICAgdmFyIGluc3RhbmNlSWQgPSBncm91cEluc3RhbmNlSWRDcmVhdG9yLmdldEluc3RhbmNlSWRGb3JLZXkoZ3JvdXBJZCk7XG4gICAgICAgIHZhciB1bmlxdWVJZCA9IENvbHVtbkdyb3VwLmNyZWF0ZVVuaXF1ZUlkKGdyb3VwSWQsIGluc3RhbmNlSWQpO1xuICAgICAgICB2YXIgY29sdW1uR3JvdXAgPSBvbGRDb2x1bW5zTWFwcGVkW3VuaXF1ZUlkXTtcbiAgICAgICAgLy8gaWYgdGhlIHVzZXIgaXMgc2V0dGluZyBuZXcgY29sRGVmcywgaXQgaXMgcG9zc2libGUgdGhhdCB0aGUgaWQncyBvdmVybGFwLCBhbmQgd2VcbiAgICAgICAgLy8gd291bGQgaGF2ZSBhIGZhbHNlIG1hdGNoIGZyb20gYWJvdmUuIHNvIHdlIGRvdWJsZSBjaGVjayB3ZSBhcmUgdGFsa2luZyBhYm91dCB0aGVcbiAgICAgICAgLy8gc2FtZSBvcmlnaW5hbCBjb2x1bW4gZ3JvdXAuXG4gICAgICAgIGlmIChjb2x1bW5Hcm91cCAmJiBjb2x1bW5Hcm91cC5nZXRQcm92aWRlZENvbHVtbkdyb3VwKCkgIT09IHByb3ZpZGVkR3JvdXApIHtcbiAgICAgICAgICAgIGNvbHVtbkdyb3VwID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhpc3RzKGNvbHVtbkdyb3VwKSkge1xuICAgICAgICAgICAgLy8gY2xlYW4gb3V0IHRoZSBvbGQgY29sdW1uIGdyb3VwIGhlcmUsIGFzIHdlIHdpbGwgYmUgYWRkaW5nIGNoaWxkcmVuIGludG8gaXQgYWdhaW5cbiAgICAgICAgICAgIGNvbHVtbkdyb3VwLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb2x1bW5Hcm91cCA9IG5ldyBDb2x1bW5Hcm91cChwcm92aWRlZEdyb3VwLCBncm91cElkLCBpbnN0YW5jZUlkLCBwaW5uZWQpO1xuICAgICAgICAgICAgdGhpcy5jb250ZXh0LmNyZWF0ZUJlYW4oY29sdW1uR3JvdXApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2x1bW5Hcm91cDtcbiAgICB9O1xuICAgIC8vIHJldHVybnMgYmFjayBhIDJkIG1hcCBvZiBDb2x1bW5Hcm91cCBhcyBmb2xsb3dzOiBncm91cElkIC0+IGluc3RhbmNlSWQgLT4gQ29sdW1uR3JvdXBcbiAgICBEaXNwbGF5ZWRHcm91cENyZWF0b3IucHJvdG90eXBlLm1hcE9sZEdyb3Vwc0J5SWQgPSBmdW5jdGlvbiAoZGlzcGxheWVkR3JvdXBzKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgICAgdmFyIHJlY3Vyc2l2ZSA9IGZ1bmN0aW9uIChjb2x1bW5zT3JHcm91cHMpIHtcbiAgICAgICAgICAgIGNvbHVtbnNPckdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5Pckdyb3VwKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbHVtbk9yR3JvdXAgaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29sdW1uR3JvdXAgPSBjb2x1bW5Pckdyb3VwO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbY29sdW1uT3JHcm91cC5nZXRVbmlxdWVJZCgpXSA9IGNvbHVtbkdyb3VwO1xuICAgICAgICAgICAgICAgICAgICByZWN1cnNpdmUoY29sdW1uR3JvdXAuZ2V0Q2hpbGRyZW4oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGlmIChkaXNwbGF5ZWRHcm91cHMpIHtcbiAgICAgICAgICAgIHJlY3Vyc2l2ZShkaXNwbGF5ZWRHcm91cHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBEaXNwbGF5ZWRHcm91cENyZWF0b3IucHJvdG90eXBlLnNldHVwUGFyZW50c0ludG9Db2x1bW5zID0gZnVuY3Rpb24gKGNvbHVtbnNPckdyb3VwcywgcGFyZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGNvbHVtbnNPckdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5zT3JHcm91cCkge1xuICAgICAgICAgICAgY29sdW1uc09yR3JvdXAuc2V0UGFyZW50KHBhcmVudCk7XG4gICAgICAgICAgICBpZiAoY29sdW1uc09yR3JvdXAgaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW5Hcm91cCA9IGNvbHVtbnNPckdyb3VwO1xuICAgICAgICAgICAgICAgIF90aGlzLnNldHVwUGFyZW50c0ludG9Db2x1bW5zKGNvbHVtbkdyb3VwLmdldENoaWxkcmVuKCksIGNvbHVtbkdyb3VwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBEaXNwbGF5ZWRHcm91cENyZWF0b3IucHJvdG90eXBlLmdldE9yaWdpbmFsUGF0aEZvckNvbHVtbiA9IGZ1bmN0aW9uIChiYWxhbmNlZENvbHVtblRyZWUsIGNvbHVtbikge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgICAgICB2YXIgcmVjdXJzZVBhdGggPSBmdW5jdGlvbiAoY29sdW1uVHJlZSwgZGVwdCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb2x1bW5UcmVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gcXVpdCB0aGUgc2VhcmNoLCBzbyAncmVzdWx0JyBpcyBrZXB0IHdpdGggdGhlIGZvdW5kIHJlc3VsdFxuICAgICAgICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gY29sdW1uVHJlZVtpXTtcbiAgICAgICAgICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIFByb3ZpZGVkQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjdXJzZVBhdGgobm9kZS5nZXRDaGlsZHJlbigpLCBkZXB0ICsgMSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtkZXB0XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG5vZGUgPT09IGNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZWN1cnNlUGF0aChiYWxhbmNlZENvbHVtblRyZWUsIDApO1xuICAgICAgICAvLyBpdCdzIHBvc3NpYmxlIHdlIGRpZG4ndCBmaW5kIGEgcGF0aC4gdGhpcyBoYXBwZW5zIGlmIHRoZSBjb2x1bW4gaXMgZ2VuZXJhdGVkXG4gICAgICAgIC8vIGJ5IHRoZSBncmlkIChhdXRvLWdyb3VwKSwgaW4gdGhhdCB0aGUgZGVmaW5pdGlvbiBkaWRuJ3QgY29tZSBmcm9tIHRoZSBjbGllbnQuIGluIHRoaXMgY2FzZSxcbiAgICAgICAgLy8gd2UgY3JlYXRlIGEgZmFrZSBvcmlnaW5hbCBwYXRoLlxuICAgICAgICBpZiAoZm91bmQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjb3VsZCBub3QgZ2V0IHBhdGgnKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBEaXNwbGF5ZWRHcm91cENyZWF0b3IgPSBfX2RlY29yYXRlJDJzKFtcbiAgICAgICAgQmVhbignZGlzcGxheWVkR3JvdXBDcmVhdG9yJylcbiAgICBdLCBEaXNwbGF5ZWRHcm91cENyZWF0b3IpO1xuICAgIHJldHVybiBEaXNwbGF5ZWRHcm91cENyZWF0b3I7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMlEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMlEoQWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ1N0YWNrQ29tcG9uZW50c1JlZ2lzdHJ5KCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY29tcG9uZW50c01hcHBlZEJ5TmFtZSA9IHt9O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnU3RhY2tDb21wb25lbnRzUmVnaXN0cnkucHJvdG90eXBlLnNldHVwQ29tcG9uZW50cyA9IGZ1bmN0aW9uIChjb21wb25lbnRzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChjb21wb25lbnRzKSB7XG4gICAgICAgICAgICBjb21wb25lbnRzLmZvckVhY2goZnVuY3Rpb24gKGNvbXBvbmVudE1ldGEpIHsgcmV0dXJuIF90aGlzLmFkZENvbXBvbmVudChjb21wb25lbnRNZXRhKTsgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnU3RhY2tDb21wb25lbnRzUmVnaXN0cnkucHJvdG90eXBlLmFkZENvbXBvbmVudCA9IGZ1bmN0aW9uIChjb21wb25lbnRNZXRhKSB7XG4gICAgICAgIC8vIGdldCBuYW1lIG9mIHRoZSBjbGFzcyBhcyBhIHN0cmluZ1xuICAgICAgICAvLyBsZXQgY2xhc3NOYW1lID0gZ2V0TmFtZU9mQ2xhc3MoQ29tcG9uZW50Q2xhc3MpO1xuICAgICAgICAvLyBpbnNlcnQgYSBkYXNoIGFmdGVyIGV2ZXJ5IGNhcGl0YWwgbGV0dGVyXG4gICAgICAgIC8vIGxldCBjbGFzc0VzY2FwZWQgPSBjbGFzc05hbWUucmVwbGFjZSgvKFtBLVpdKS9nLCBcIi0kMVwiKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgY2xhc3NFc2NhcGVkID0gY29tcG9uZW50TWV0YS5jb21wb25lbnROYW1lLnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csIFwiJDEtJDJcIikudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgLy8gcHV0IGFsbCB0byB1cHBlciBjYXNlXG4gICAgICAgIHZhciBjbGFzc1VwcGVyQ2FzZSA9IGNsYXNzRXNjYXBlZC50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAvLyBmaW5hbGx5IHN0b3JlXG4gICAgICAgIHRoaXMuY29tcG9uZW50c01hcHBlZEJ5TmFtZVtjbGFzc1VwcGVyQ2FzZV0gPSBjb21wb25lbnRNZXRhLmNvbXBvbmVudENsYXNzO1xuICAgIH07XG4gICAgQWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeS5wcm90b3R5cGUuZ2V0Q29tcG9uZW50Q2xhc3MgPSBmdW5jdGlvbiAoaHRtbFRhZykge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21wb25lbnRzTWFwcGVkQnlOYW1lW2h0bWxUYWddO1xuICAgIH07XG4gICAgQWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeSA9IF9fZGVjb3JhdGUkMnIoW1xuICAgICAgICBCZWFuKCdhZ1N0YWNrQ29tcG9uZW50c1JlZ2lzdHJ5JylcbiAgICBdLCBBZ1N0YWNrQ29tcG9uZW50c1JlZ2lzdHJ5KTtcbiAgICByZXR1cm4gQWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fcmVhZCRrID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIENvbG9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIC8qKlxuICAgICAqIEV2ZXJ5IGNvbG9yIGNvbXBvbmVudCBzaG91bGQgYmUgaW4gdGhlIFswLCAxXSByYW5nZS5cbiAgICAgKiBTb21lIGVhc2luZyBmdW5jdGlvbnMgKHN1Y2ggYXMgZWxhc3RpYyBlYXNpbmcpIGNhbiBvdmVyc2hvb3QgdGhlIHRhcmdldCB2YWx1ZSBieSBzb21lIGFtb3VudC5cbiAgICAgKiBTbywgd2hlbiBhbmltYXRpbmcgY29sb3JzLCBpZiB0aGUgc291cmNlIG9yIHRhcmdldCBjb2xvciBjb21wb25lbnRzIGFyZSBhbHJlYWR5IG5lYXJcbiAgICAgKiBvciBhdCB0aGUgZWRnZSBvZiB0aGUgYWxsb3dlZCBbMCwgMV0gcmFuZ2UsIGl0IGlzIHBvc3NpYmxlIGZvciB0aGUgaW50ZXJtZWRpYXRlIGNvbG9yXG4gICAgICogY29tcG9uZW50IHZhbHVlIHRvIGVuZCB1cCBvdXRzaWRlIG9mIHRoYXQgcmFuZ2UgbWlkLWFuaW1hdGlvbi4gRm9yIHRoaXMgcmVhc29uIHRoZSBjb25zdHJ1Y3RvclxuICAgICAqIHBlcmZvcm1zIHJhbmdlIGNoZWNraW5nL2NvbnN0cmFpbmluZy5cbiAgICAgKiBAcGFyYW0gciBSZWQgY29tcG9uZW50LlxuICAgICAqIEBwYXJhbSBnIEdyZWVuIGNvbXBvbmVudC5cbiAgICAgKiBAcGFyYW0gYiBCbHVlIGNvbXBvbmVudC5cbiAgICAgKiBAcGFyYW0gYSBBbHBoYSAob3BhY2l0eSkgY29tcG9uZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIENvbG9yKHIsIGcsIGIsIGEpIHtcbiAgICAgICAgaWYgKGEgPT09IHZvaWQgMCkgeyBhID0gMTsgfVxuICAgICAgICAvLyBOYU4gaXMgdHJlYXRlZCBhcyAwLlxuICAgICAgICB0aGlzLnIgPSBNYXRoLm1pbigxLCBNYXRoLm1heCgwLCByIHx8IDApKTtcbiAgICAgICAgdGhpcy5nID0gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgZyB8fCAwKSk7XG4gICAgICAgIHRoaXMuYiA9IE1hdGgubWluKDEsIE1hdGgubWF4KDAsIGIgfHwgMCkpO1xuICAgICAgICB0aGlzLmEgPSBNYXRoLm1pbigxLCBNYXRoLm1heCgwLCBhIHx8IDApKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIGdpdmVuIHN0cmluZyBjYW4gYmUgaW4gb25lIG9mIHRoZSBmb2xsb3dpbmcgZm9ybWF0czpcbiAgICAgKiAtICNyZ2JcbiAgICAgKiAtICNycmdnYmJcbiAgICAgKiAtIHJnYihyLCBnLCBiKVxuICAgICAqIC0gcmdiYShyLCBnLCBiLCBhKVxuICAgICAqIC0gQ1NTIGNvbG9yIG5hbWUgc3VjaCBhcyAnd2hpdGUnLCAnb3JhbmdlJywgJ2N5YW4nLCBldGMuXG4gICAgICogQHBhcmFtIHN0clxuICAgICAqL1xuICAgIENvbG9yLmZyb21TdHJpbmcgPSBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgIC8vIGhleGFkZWNpbWFsIG5vdGF0aW9uXG4gICAgICAgIGlmIChzdHIuaW5kZXhPZignIycpID49IDApIHsgLy8gdGhlcmUgY2FuIGJlIHNvbWUgbGVhZGluZyB3aGl0ZXNwYWNlXG4gICAgICAgICAgICByZXR1cm4gQ29sb3IuZnJvbUhleFN0cmluZyhzdHIpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbG9yIG5hbWVcbiAgICAgICAgdmFyIGhleCA9IENvbG9yLm5hbWVUb0hleFtzdHJdO1xuICAgICAgICBpZiAoaGV4KSB7XG4gICAgICAgICAgICByZXR1cm4gQ29sb3IuZnJvbUhleFN0cmluZyhoZXgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHJnYihhKSBub3RhdGlvblxuICAgICAgICBpZiAoc3RyLmluZGV4T2YoJ3JnYicpID49IDApIHtcbiAgICAgICAgICAgIHJldHVybiBDb2xvci5mcm9tUmdiYVN0cmluZyhzdHIpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgY29sb3Igc3RyaW5nOiAnXCIgKyBzdHIgKyBcIidcIik7XG4gICAgfTtcbiAgICAvLyBTZWUgaHR0cHM6Ly9kcmFmdHMuY3Nzd2cub3JnL2Nzcy1jb2xvci8jaGV4LW5vdGF0aW9uXG4gICAgQ29sb3IucGFyc2VIZXggPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKC8gL2csICcnKS5zbGljZSgxKTtcbiAgICAgICAgdmFyIHBhcnRzO1xuICAgICAgICBzd2l0Y2ggKGlucHV0Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgICAgIHBhcnRzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnB1dC5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0cy5wdXNoKHBhcnNlSW50KFwiXCIgKyBpbnB1dFtpXSArIGlucHV0W2kgKyAxXSwgMTYpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgcGFydHMgPSBpbnB1dC5zcGxpdCgnJykubWFwKGZ1bmN0aW9uIChwKSB7IHJldHVybiBwYXJzZUludChwLCAxNik7IH0pLm1hcChmdW5jdGlvbiAocCkgeyByZXR1cm4gcCArIHAgKiAxNjsgfSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnRzLmxlbmd0aCA+PSAzKSB7XG4gICAgICAgICAgICBpZiAocGFydHMuZXZlcnkoZnVuY3Rpb24gKHApIHsgcmV0dXJuIHAgPj0gMDsgfSkpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFydHMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnRzLnB1c2goMjU1KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2xvci5mcm9tSGV4U3RyaW5nID0gZnVuY3Rpb24gKHN0cikge1xuICAgICAgICB2YXIgdmFsdWVzID0gQ29sb3IucGFyc2VIZXgoc3RyKTtcbiAgICAgICAgaWYgKHZhbHVlcykge1xuICAgICAgICAgICAgdmFyIF9hID0gX19yZWFkJGsodmFsdWVzLCA0KSwgciA9IF9hWzBdLCBnID0gX2FbMV0sIGIgPSBfYVsyXSwgYSA9IF9hWzNdO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihyIC8gMjU1LCBnIC8gMjU1LCBiIC8gMjU1LCBhIC8gMjU1KTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNYWxmb3JtZWQgaGV4YWRlY2ltYWwgY29sb3Igc3RyaW5nOiAnXCIgKyBzdHIgKyBcIidcIik7XG4gICAgfTtcbiAgICBDb2xvci5zdHJpbmdUb1JnYmEgPSBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgIC8vIEZpbmQgcG9zaXRpb25zIG9mIG9wZW5pbmcgYW5kIGNsb3NpbmcgcGFyZW50aGVzZXMuXG4gICAgICAgIHZhciBfYSA9IF9fcmVhZCRrKFtOYU4sIE5hTl0sIDIpLCBwbyA9IF9hWzBdLCBwYyA9IF9hWzFdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGMgPSBzdHJbaV07XG4gICAgICAgICAgICBpZiAoIXBvICYmIGMgPT09ICcoJykge1xuICAgICAgICAgICAgICAgIHBvID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGMgPT09ICcpJykge1xuICAgICAgICAgICAgICAgIHBjID0gaTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgY29udGVudHMgPSBwbyAmJiBwYyAmJiBzdHIuc3Vic3RyaW5nKHBvICsgMSwgcGMpO1xuICAgICAgICBpZiAoIWNvbnRlbnRzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcnRzID0gY29udGVudHMuc3BsaXQoJywnKTtcbiAgICAgICAgdmFyIHJnYmEgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IHBhcnNlRmxvYXQocGFydCk7XG4gICAgICAgICAgICBpZiAoaXNOYU4odmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcnQuaW5kZXhPZignJScpID49IDApIHsgLy8gcGVyY2VudGFnZSByLCBnLCBvciBiIHZhbHVlXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxMDAsIHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgdmFsdWUgLz0gMTAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPT09IDMpIHsgLy8gYWxwaGEgY29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgdmFsdWUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7IC8vIGFic29sdXRlIHIsIGcsIG9yIGIgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyNTUsIHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlIC89IDI1NTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZ2JhLnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZ2JhO1xuICAgIH07XG4gICAgQ29sb3IuZnJvbVJnYmFTdHJpbmcgPSBmdW5jdGlvbiAoc3RyKSB7XG4gICAgICAgIHZhciByZ2JhID0gQ29sb3Iuc3RyaW5nVG9SZ2JhKHN0cik7XG4gICAgICAgIGlmIChyZ2JhKSB7XG4gICAgICAgICAgICBpZiAocmdiYS5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKHJnYmFbMF0sIHJnYmFbMV0sIHJnYmFbMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocmdiYS5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENvbG9yKHJnYmFbMF0sIHJnYmFbMV0sIHJnYmFbMl0sIHJnYmFbM10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1hbGZvcm1lZCByZ2IvcmdiYSBjb2xvciBzdHJpbmc6ICdcIiArIHN0ciArIFwiJ1wiKTtcbiAgICB9O1xuICAgIENvbG9yLmZyb21BcnJheSA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgICAgICAgaWYgKGFyci5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQ29sb3IoYXJyWzBdLCBhcnJbMV0sIGFyclsyXSwgYXJyWzNdKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXJyLmxlbmd0aCA9PT0gMykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2xvcihhcnJbMF0sIGFyclsxXSwgYXJyWzJdKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBnaXZlbiBhcnJheSBzaG91bGQgY29udGFpbiAzIG9yIDQgY29sb3IgY29tcG9uZW50cyAobnVtYmVycykuJyk7XG4gICAgfTtcbiAgICBDb2xvci5mcm9tSFNCID0gZnVuY3Rpb24gKGgsIHMsIGIsIGFscGhhKSB7XG4gICAgICAgIGlmIChhbHBoYSA9PT0gdm9pZCAwKSB7IGFscGhhID0gMTsgfVxuICAgICAgICB2YXIgcmdiID0gQ29sb3IuSFNCdG9SR0IoaCwgcywgYik7XG4gICAgICAgIHJldHVybiBuZXcgQ29sb3IocmdiWzBdLCByZ2JbMV0sIHJnYlsyXSwgYWxwaGEpO1xuICAgIH07XG4gICAgQ29sb3IucGFkSGV4ID0gZnVuY3Rpb24gKHN0cikge1xuICAgICAgICAvLyBDYW4ndCB1c2UgYHBhZFN0YXJ0KDIsICcwJylgIGhlcmUgYmVjYXVzZSBvZiBJRS5cbiAgICAgICAgcmV0dXJuIHN0ci5sZW5ndGggPT09IDEgPyAnMCcgKyBzdHIgOiBzdHI7XG4gICAgfTtcbiAgICBDb2xvci5wcm90b3R5cGUudG9IZXhTdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBoZXggPSAnIydcbiAgICAgICAgICAgICsgQ29sb3IucGFkSGV4KE1hdGgucm91bmQodGhpcy5yICogMjU1KS50b1N0cmluZygxNikpXG4gICAgICAgICAgICArIENvbG9yLnBhZEhleChNYXRoLnJvdW5kKHRoaXMuZyAqIDI1NSkudG9TdHJpbmcoMTYpKVxuICAgICAgICAgICAgKyBDb2xvci5wYWRIZXgoTWF0aC5yb3VuZCh0aGlzLmIgKiAyNTUpLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgIGlmICh0aGlzLmEgPCAxKSB7XG4gICAgICAgICAgICBoZXggKz0gQ29sb3IucGFkSGV4KE1hdGgucm91bmQodGhpcy5hICogMjU1KS50b1N0cmluZygxNikpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoZXg7XG4gICAgfTtcbiAgICBDb2xvci5wcm90b3R5cGUudG9SZ2JhU3RyaW5nID0gZnVuY3Rpb24gKGZyYWN0aW9uRGlnaXRzKSB7XG4gICAgICAgIGlmIChmcmFjdGlvbkRpZ2l0cyA9PT0gdm9pZCAwKSB7IGZyYWN0aW9uRGlnaXRzID0gMzsgfVxuICAgICAgICB2YXIgY29tcG9uZW50cyA9IFtcbiAgICAgICAgICAgIE1hdGgucm91bmQodGhpcy5yICogMjU1KSxcbiAgICAgICAgICAgIE1hdGgucm91bmQodGhpcy5nICogMjU1KSxcbiAgICAgICAgICAgIE1hdGgucm91bmQodGhpcy5iICogMjU1KVxuICAgICAgICBdO1xuICAgICAgICB2YXIgayA9IE1hdGgucG93KDEwLCBmcmFjdGlvbkRpZ2l0cyk7XG4gICAgICAgIGlmICh0aGlzLmEgIT09IDEpIHtcbiAgICAgICAgICAgIGNvbXBvbmVudHMucHVzaChNYXRoLnJvdW5kKHRoaXMuYSAqIGspIC8gayk7XG4gICAgICAgICAgICByZXR1cm4gXCJyZ2JhKFwiICsgY29tcG9uZW50cy5qb2luKCcsICcpICsgXCIpXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFwicmdiKFwiICsgY29tcG9uZW50cy5qb2luKCcsICcpICsgXCIpXCI7XG4gICAgfTtcbiAgICBDb2xvci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmEgPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvSGV4U3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMudG9SZ2JhU3RyaW5nKCk7XG4gICAgfTtcbiAgICBDb2xvci5wcm90b3R5cGUudG9IU0IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBDb2xvci5SR0J0b0hTQih0aGlzLnIsIHRoaXMuZywgdGhpcy5iKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBnaXZlbiBSR0IgdHJpcGxlIHRvIGFuIGFycmF5IG9mIEhTQiAoSFNWKSBjb21wb25lbnRzLlxuICAgICAqIFRoZSBodWUgY29tcG9uZW50IHdpbGwgYmUgYE5hTmAgZm9yIGFjaHJvbWF0aWMgY29sb3JzLlxuICAgICAqL1xuICAgIENvbG9yLlJHQnRvSFNCID0gZnVuY3Rpb24gKHIsIGcsIGIpIHtcbiAgICAgICAgdmFyIG1pbiA9IE1hdGgubWluKHIsIGcsIGIpO1xuICAgICAgICB2YXIgbWF4ID0gTWF0aC5tYXgociwgZywgYik7XG4gICAgICAgIHZhciBTID0gbWF4ICE9PSAwID8gKG1heCAtIG1pbikgLyBtYXggOiAwO1xuICAgICAgICB2YXIgSCA9IE5hTjtcbiAgICAgICAgLy8gbWluID09IG1heCwgbWVhbnMgYWxsIGNvbXBvbmVudHMgYXJlIHRoZSBzYW1lXG4gICAgICAgIC8vIGFuZCB0aGUgY29sb3IgaXMgYSBzaGFkZSBvZiBncmF5IHdpdGggbm8gaHVlIChIIGlzIE5hTilcbiAgICAgICAgaWYgKG1pbiAhPT0gbWF4KSB7XG4gICAgICAgICAgICB2YXIgZGVsdGEgPSBtYXggLSBtaW47XG4gICAgICAgICAgICB2YXIgcmMgPSAobWF4IC0gcikgLyBkZWx0YTtcbiAgICAgICAgICAgIHZhciBnYyA9IChtYXggLSBnKSAvIGRlbHRhO1xuICAgICAgICAgICAgdmFyIGJjID0gKG1heCAtIGIpIC8gZGVsdGE7XG4gICAgICAgICAgICBpZiAociA9PT0gbWF4KSB7XG4gICAgICAgICAgICAgICAgSCA9IGJjIC0gZ2M7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChnID09PSBtYXgpIHtcbiAgICAgICAgICAgICAgICBIID0gMi4wICsgcmMgLSBiYztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIEggPSA0LjAgKyBnYyAtIHJjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgSCAvPSA2LjA7XG4gICAgICAgICAgICBpZiAoSCA8IDApIHtcbiAgICAgICAgICAgICAgICBIID0gSCArIDEuMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW0ggKiAzNjAsIFMsIG1heF07XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gSFNCIChIU1YpIHRyaXBsZSB0byBhbiBhcnJheSBvZiBSR0IgY29tcG9uZW50cy5cbiAgICAgKi9cbiAgICBDb2xvci5IU0J0b1JHQiA9IGZ1bmN0aW9uIChILCBTLCBCKSB7XG4gICAgICAgIGlmIChpc05hTihIKSkge1xuICAgICAgICAgICAgSCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgSCA9ICgoKEggJSAzNjApICsgMzYwKSAlIDM2MCkgLyAzNjA7IC8vIG5vcm1hbGl6ZSBodWUgdG8gWzAsIDM2MF0gaW50ZXJ2YWwsIHRoZW4gc2NhbGUgdG8gWzAsIDFdXG4gICAgICAgIHZhciByID0gMDtcbiAgICAgICAgdmFyIGcgPSAwO1xuICAgICAgICB2YXIgYiA9IDA7XG4gICAgICAgIGlmIChTID09PSAwKSB7XG4gICAgICAgICAgICByID0gZyA9IGIgPSBCO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGggPSAoSCAtIE1hdGguZmxvb3IoSCkpICogNjtcbiAgICAgICAgICAgIHZhciBmID0gaCAtIE1hdGguZmxvb3IoaCk7XG4gICAgICAgICAgICB2YXIgcCA9IEIgKiAoMSAtIFMpO1xuICAgICAgICAgICAgdmFyIHEgPSBCICogKDEgLSBTICogZik7XG4gICAgICAgICAgICB2YXIgdCA9IEIgKiAoMSAtIChTICogKDEgLSBmKSkpO1xuICAgICAgICAgICAgc3dpdGNoIChoID4+IDApIHsgLy8gZGlzY2FyZCB0aGUgZmxvYXRpbmcgcG9pbnQgcGFydCBvZiB0aGUgbnVtYmVyXG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByID0gQjtcbiAgICAgICAgICAgICAgICAgICAgZyA9IHQ7XG4gICAgICAgICAgICAgICAgICAgIGIgPSBwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIHIgPSBxO1xuICAgICAgICAgICAgICAgICAgICBnID0gQjtcbiAgICAgICAgICAgICAgICAgICAgYiA9IHA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgciA9IHA7XG4gICAgICAgICAgICAgICAgICAgIGcgPSBCO1xuICAgICAgICAgICAgICAgICAgICBiID0gdDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByID0gcDtcbiAgICAgICAgICAgICAgICAgICAgZyA9IHE7XG4gICAgICAgICAgICAgICAgICAgIGIgPSBCO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIHIgPSB0O1xuICAgICAgICAgICAgICAgICAgICBnID0gcDtcbiAgICAgICAgICAgICAgICAgICAgYiA9IEI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgciA9IEI7XG4gICAgICAgICAgICAgICAgICAgIGcgPSBwO1xuICAgICAgICAgICAgICAgICAgICBiID0gcTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtyLCBnLCBiXTtcbiAgICB9O1xuICAgIENvbG9yLnByb3RvdHlwZS5kZXJpdmUgPSBmdW5jdGlvbiAoaHVlU2hpZnQsIHNhdHVyYXRpb25GYWN0b3IsIGJyaWdodG5lc3NGYWN0b3IsIG9wYWNpdHlGYWN0b3IpIHtcbiAgICAgICAgdmFyIGhzYiA9IENvbG9yLlJHQnRvSFNCKHRoaXMuciwgdGhpcy5nLCB0aGlzLmIpO1xuICAgICAgICB2YXIgYiA9IGhzYlsyXTtcbiAgICAgICAgaWYgKGIgPT0gMCAmJiBicmlnaHRuZXNzRmFjdG9yID4gMS4wKSB7XG4gICAgICAgICAgICBiID0gMC4wNTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaCA9ICgoKGhzYlswXSArIGh1ZVNoaWZ0KSAlIDM2MCkgKyAzNjApICUgMzYwO1xuICAgICAgICB2YXIgcyA9IE1hdGgubWF4KE1hdGgubWluKGhzYlsxXSAqIHNhdHVyYXRpb25GYWN0b3IsIDEuMCksIDAuMCk7XG4gICAgICAgIGIgPSBNYXRoLm1heChNYXRoLm1pbihiICogYnJpZ2h0bmVzc0ZhY3RvciwgMS4wKSwgMC4wKTtcbiAgICAgICAgdmFyIGEgPSBNYXRoLm1heChNYXRoLm1pbih0aGlzLmEgKiBvcGFjaXR5RmFjdG9yLCAxLjApLCAwLjApO1xuICAgICAgICB2YXIgcmdiYSA9IENvbG9yLkhTQnRvUkdCKGgsIHMsIGIpO1xuICAgICAgICByZ2JhLnB1c2goYSk7XG4gICAgICAgIHJldHVybiBDb2xvci5mcm9tQXJyYXkocmdiYSk7XG4gICAgfTtcbiAgICBDb2xvci5wcm90b3R5cGUuYnJpZ2h0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRlcml2ZSgwLCAxLjAsIDEuMCAvIDAuNywgMS4wKTtcbiAgICB9O1xuICAgIENvbG9yLnByb3RvdHlwZS5kYXJrZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRlcml2ZSgwLCAxLjAsIDAuNywgMS4wKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIENTUyBDb2xvciBNb2R1bGUgTGV2ZWwgNDpcbiAgICAgKiBodHRwczovL2RyYWZ0cy5jc3N3Zy5vcmcvY3NzLWNvbG9yLyNuYW1lZC1jb2xvcnNcbiAgICAgKi9cbiAgICBDb2xvci5uYW1lVG9IZXggPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgYWxpY2VibHVlOiAnI0YwRjhGRicsXG4gICAgICAgIGFudGlxdWV3aGl0ZTogJyNGQUVCRDcnLFxuICAgICAgICBhcXVhOiAnIzAwRkZGRicsXG4gICAgICAgIGFxdWFtYXJpbmU6ICcjN0ZGRkQ0JyxcbiAgICAgICAgYXp1cmU6ICcjRjBGRkZGJyxcbiAgICAgICAgYmVpZ2U6ICcjRjVGNURDJyxcbiAgICAgICAgYmlzcXVlOiAnI0ZGRTRDNCcsXG4gICAgICAgIGJsYWNrOiAnIzAwMDAwMCcsXG4gICAgICAgIGJsYW5jaGVkYWxtb25kOiAnI0ZGRUJDRCcsXG4gICAgICAgIGJsdWU6ICcjMDAwMEZGJyxcbiAgICAgICAgYmx1ZXZpb2xldDogJyM4QTJCRTInLFxuICAgICAgICBicm93bjogJyNBNTJBMkEnLFxuICAgICAgICBidXJseXdvb2Q6ICcjREVCODg3JyxcbiAgICAgICAgY2FkZXRibHVlOiAnIzVGOUVBMCcsXG4gICAgICAgIGNoYXJ0cmV1c2U6ICcjN0ZGRjAwJyxcbiAgICAgICAgY2hvY29sYXRlOiAnI0QyNjkxRScsXG4gICAgICAgIGNvcmFsOiAnI0ZGN0Y1MCcsXG4gICAgICAgIGNvcm5mbG93ZXJibHVlOiAnIzY0OTVFRCcsXG4gICAgICAgIGNvcm5zaWxrOiAnI0ZGRjhEQycsXG4gICAgICAgIGNyaW1zb246ICcjREMxNDNDJyxcbiAgICAgICAgY3lhbjogJyMwMEZGRkYnLFxuICAgICAgICBkYXJrYmx1ZTogJyMwMDAwOEInLFxuICAgICAgICBkYXJrY3lhbjogJyMwMDhCOEInLFxuICAgICAgICBkYXJrZ29sZGVucm9kOiAnI0I4ODYwQicsXG4gICAgICAgIGRhcmtncmF5OiAnI0E5QTlBOScsXG4gICAgICAgIGRhcmtncmVlbjogJyMwMDY0MDAnLFxuICAgICAgICBkYXJrZ3JleTogJyNBOUE5QTknLFxuICAgICAgICBkYXJra2hha2k6ICcjQkRCNzZCJyxcbiAgICAgICAgZGFya21hZ2VudGE6ICcjOEIwMDhCJyxcbiAgICAgICAgZGFya29saXZlZ3JlZW46ICcjNTU2QjJGJyxcbiAgICAgICAgZGFya29yYW5nZTogJyNGRjhDMDAnLFxuICAgICAgICBkYXJrb3JjaGlkOiAnIzk5MzJDQycsXG4gICAgICAgIGRhcmtyZWQ6ICcjOEIwMDAwJyxcbiAgICAgICAgZGFya3NhbG1vbjogJyNFOTk2N0EnLFxuICAgICAgICBkYXJrc2VhZ3JlZW46ICcjOEZCQzhGJyxcbiAgICAgICAgZGFya3NsYXRlYmx1ZTogJyM0ODNEOEInLFxuICAgICAgICBkYXJrc2xhdGVncmF5OiAnIzJGNEY0RicsXG4gICAgICAgIGRhcmtzbGF0ZWdyZXk6ICcjMkY0RjRGJyxcbiAgICAgICAgZGFya3R1cnF1b2lzZTogJyMwMENFRDEnLFxuICAgICAgICBkYXJrdmlvbGV0OiAnIzk0MDBEMycsXG4gICAgICAgIGRlZXBwaW5rOiAnI0ZGMTQ5MycsXG4gICAgICAgIGRlZXBza3libHVlOiAnIzAwQkZGRicsXG4gICAgICAgIGRpbWdyYXk6ICcjNjk2OTY5JyxcbiAgICAgICAgZGltZ3JleTogJyM2OTY5NjknLFxuICAgICAgICBkb2RnZXJibHVlOiAnIzFFOTBGRicsXG4gICAgICAgIGZpcmVicmljazogJyNCMjIyMjInLFxuICAgICAgICBmbG9yYWx3aGl0ZTogJyNGRkZBRjAnLFxuICAgICAgICBmb3Jlc3RncmVlbjogJyMyMjhCMjInLFxuICAgICAgICBmdWNoc2lhOiAnI0ZGMDBGRicsXG4gICAgICAgIGdhaW5zYm9ybzogJyNEQ0RDREMnLFxuICAgICAgICBnaG9zdHdoaXRlOiAnI0Y4RjhGRicsXG4gICAgICAgIGdvbGQ6ICcjRkZENzAwJyxcbiAgICAgICAgZ29sZGVucm9kOiAnI0RBQTUyMCcsXG4gICAgICAgIGdyYXk6ICcjODA4MDgwJyxcbiAgICAgICAgZ3JlZW46ICcjMDA4MDAwJyxcbiAgICAgICAgZ3JlZW55ZWxsb3c6ICcjQURGRjJGJyxcbiAgICAgICAgZ3JleTogJyM4MDgwODAnLFxuICAgICAgICBob25leWRldzogJyNGMEZGRjAnLFxuICAgICAgICBob3RwaW5rOiAnI0ZGNjlCNCcsXG4gICAgICAgIGluZGlhbnJlZDogJyNDRDVDNUMnLFxuICAgICAgICBpbmRpZ286ICcjNEIwMDgyJyxcbiAgICAgICAgaXZvcnk6ICcjRkZGRkYwJyxcbiAgICAgICAga2hha2k6ICcjRjBFNjhDJyxcbiAgICAgICAgbGF2ZW5kZXI6ICcjRTZFNkZBJyxcbiAgICAgICAgbGF2ZW5kZXJibHVzaDogJyNGRkYwRjUnLFxuICAgICAgICBsYXduZ3JlZW46ICcjN0NGQzAwJyxcbiAgICAgICAgbGVtb25jaGlmZm9uOiAnI0ZGRkFDRCcsXG4gICAgICAgIGxpZ2h0Ymx1ZTogJyNBREQ4RTYnLFxuICAgICAgICBsaWdodGNvcmFsOiAnI0YwODA4MCcsXG4gICAgICAgIGxpZ2h0Y3lhbjogJyNFMEZGRkYnLFxuICAgICAgICBsaWdodGdvbGRlbnJvZHllbGxvdzogJyNGQUZBRDInLFxuICAgICAgICBsaWdodGdyYXk6ICcjRDNEM0QzJyxcbiAgICAgICAgbGlnaHRncmVlbjogJyM5MEVFOTAnLFxuICAgICAgICBsaWdodGdyZXk6ICcjRDNEM0QzJyxcbiAgICAgICAgbGlnaHRwaW5rOiAnI0ZGQjZDMScsXG4gICAgICAgIGxpZ2h0c2FsbW9uOiAnI0ZGQTA3QScsXG4gICAgICAgIGxpZ2h0c2VhZ3JlZW46ICcjMjBCMkFBJyxcbiAgICAgICAgbGlnaHRza3libHVlOiAnIzg3Q0VGQScsXG4gICAgICAgIGxpZ2h0c2xhdGVncmF5OiAnIzc3ODg5OScsXG4gICAgICAgIGxpZ2h0c2xhdGVncmV5OiAnIzc3ODg5OScsXG4gICAgICAgIGxpZ2h0c3RlZWxibHVlOiAnI0IwQzRERScsXG4gICAgICAgIGxpZ2h0eWVsbG93OiAnI0ZGRkZFMCcsXG4gICAgICAgIGxpbWU6ICcjMDBGRjAwJyxcbiAgICAgICAgbGltZWdyZWVuOiAnIzMyQ0QzMicsXG4gICAgICAgIGxpbmVuOiAnI0ZBRjBFNicsXG4gICAgICAgIG1hZ2VudGE6ICcjRkYwMEZGJyxcbiAgICAgICAgbWFyb29uOiAnIzgwMDAwMCcsXG4gICAgICAgIG1lZGl1bWFxdWFtYXJpbmU6ICcjNjZDREFBJyxcbiAgICAgICAgbWVkaXVtYmx1ZTogJyMwMDAwQ0QnLFxuICAgICAgICBtZWRpdW1vcmNoaWQ6ICcjQkE1NUQzJyxcbiAgICAgICAgbWVkaXVtcHVycGxlOiAnIzkzNzBEQicsXG4gICAgICAgIG1lZGl1bXNlYWdyZWVuOiAnIzNDQjM3MScsXG4gICAgICAgIG1lZGl1bXNsYXRlYmx1ZTogJyM3QjY4RUUnLFxuICAgICAgICBtZWRpdW1zcHJpbmdncmVlbjogJyMwMEZBOUEnLFxuICAgICAgICBtZWRpdW10dXJxdW9pc2U6ICcjNDhEMUNDJyxcbiAgICAgICAgbWVkaXVtdmlvbGV0cmVkOiAnI0M3MTU4NScsXG4gICAgICAgIG1pZG5pZ2h0Ymx1ZTogJyMxOTE5NzAnLFxuICAgICAgICBtaW50Y3JlYW06ICcjRjVGRkZBJyxcbiAgICAgICAgbWlzdHlyb3NlOiAnI0ZGRTRFMScsXG4gICAgICAgIG1vY2Nhc2luOiAnI0ZGRTRCNScsXG4gICAgICAgIG5hdmFqb3doaXRlOiAnI0ZGREVBRCcsXG4gICAgICAgIG5hdnk6ICcjMDAwMDgwJyxcbiAgICAgICAgb2xkbGFjZTogJyNGREY1RTYnLFxuICAgICAgICBvbGl2ZTogJyM4MDgwMDAnLFxuICAgICAgICBvbGl2ZWRyYWI6ICcjNkI4RTIzJyxcbiAgICAgICAgb3JhbmdlOiAnI0ZGQTUwMCcsXG4gICAgICAgIG9yYW5nZXJlZDogJyNGRjQ1MDAnLFxuICAgICAgICBvcmNoaWQ6ICcjREE3MEQ2JyxcbiAgICAgICAgcGFsZWdvbGRlbnJvZDogJyNFRUU4QUEnLFxuICAgICAgICBwYWxlZ3JlZW46ICcjOThGQjk4JyxcbiAgICAgICAgcGFsZXR1cnF1b2lzZTogJyNBRkVFRUUnLFxuICAgICAgICBwYWxldmlvbGV0cmVkOiAnI0RCNzA5MycsXG4gICAgICAgIHBhcGF5YXdoaXA6ICcjRkZFRkQ1JyxcbiAgICAgICAgcGVhY2hwdWZmOiAnI0ZGREFCOScsXG4gICAgICAgIHBlcnU6ICcjQ0Q4NTNGJyxcbiAgICAgICAgcGluazogJyNGRkMwQ0InLFxuICAgICAgICBwbHVtOiAnI0REQTBERCcsXG4gICAgICAgIHBvd2RlcmJsdWU6ICcjQjBFMEU2JyxcbiAgICAgICAgcHVycGxlOiAnIzgwMDA4MCcsXG4gICAgICAgIHJlYmVjY2FwdXJwbGU6ICcjNjYzMzk5JyxcbiAgICAgICAgcmVkOiAnI0ZGMDAwMCcsXG4gICAgICAgIHJvc3licm93bjogJyNCQzhGOEYnLFxuICAgICAgICByb3lhbGJsdWU6ICcjNDE2OUUxJyxcbiAgICAgICAgc2FkZGxlYnJvd246ICcjOEI0NTEzJyxcbiAgICAgICAgc2FsbW9uOiAnI0ZBODA3MicsXG4gICAgICAgIHNhbmR5YnJvd246ICcjRjRBNDYwJyxcbiAgICAgICAgc2VhZ3JlZW46ICcjMkU4QjU3JyxcbiAgICAgICAgc2Vhc2hlbGw6ICcjRkZGNUVFJyxcbiAgICAgICAgc2llbm5hOiAnI0EwNTIyRCcsXG4gICAgICAgIHNpbHZlcjogJyNDMEMwQzAnLFxuICAgICAgICBza3libHVlOiAnIzg3Q0VFQicsXG4gICAgICAgIHNsYXRlYmx1ZTogJyM2QTVBQ0QnLFxuICAgICAgICBzbGF0ZWdyYXk6ICcjNzA4MDkwJyxcbiAgICAgICAgc2xhdGVncmV5OiAnIzcwODA5MCcsXG4gICAgICAgIHNub3c6ICcjRkZGQUZBJyxcbiAgICAgICAgc3ByaW5nZ3JlZW46ICcjMDBGRjdGJyxcbiAgICAgICAgc3RlZWxibHVlOiAnIzQ2ODJCNCcsXG4gICAgICAgIHRhbjogJyNEMkI0OEMnLFxuICAgICAgICB0ZWFsOiAnIzAwODA4MCcsXG4gICAgICAgIHRoaXN0bGU6ICcjRDhCRkQ4JyxcbiAgICAgICAgdG9tYXRvOiAnI0ZGNjM0NycsXG4gICAgICAgIHR1cnF1b2lzZTogJyM0MEUwRDAnLFxuICAgICAgICB2aW9sZXQ6ICcjRUU4MkVFJyxcbiAgICAgICAgd2hlYXQ6ICcjRjVERUIzJyxcbiAgICAgICAgd2hpdGU6ICcjRkZGRkZGJyxcbiAgICAgICAgd2hpdGVzbW9rZTogJyNGNUY1RjUnLFxuICAgICAgICB5ZWxsb3c6ICcjRkZGRjAwJyxcbiAgICAgICAgeWVsbG93Z3JlZW46ICcjOUFDRDMyJ1xuICAgIH0pO1xuICAgIHJldHVybiBDb2xvcjtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbi8vIEJhc2VkIG9uIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNDk5MTc5N1xuLy8gVGhpcyB3aWxsIHBhcnNlIGEgZGVsaW1pdGVkIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIGFycmF5cy5cbmZ1bmN0aW9uIHN0cmluZ1RvQXJyYXkoc3RyRGF0YSwgZGVsaW1pdGVyKSB7XG4gICAgaWYgKGRlbGltaXRlciA9PT0gdm9pZCAwKSB7IGRlbGltaXRlciA9ICcsJzsgfVxuICAgIHZhciBkYXRhID0gW107XG4gICAgdmFyIGlzTmV3bGluZSA9IGZ1bmN0aW9uIChjaGFyKSB7IHJldHVybiBjaGFyID09PSAnXFxyJyB8fCBjaGFyID09PSAnXFxuJzsgfTtcbiAgICB2YXIgaW5zaWRlUXVvdGVkRmllbGQgPSBmYWxzZTtcbiAgICBpZiAoc3RyRGF0YSA9PT0gJycpIHtcbiAgICAgICAgcmV0dXJuIFtbJyddXTtcbiAgICB9XG4gICAgdmFyIF9sb29wXzEgPSBmdW5jdGlvbiAocm93LCBjb2x1bW4sIHBvc2l0aW9uKSB7XG4gICAgICAgIHZhciBwcmV2aW91c0NoYXIgPSBzdHJEYXRhW3Bvc2l0aW9uIC0gMV07XG4gICAgICAgIHZhciBjdXJyZW50Q2hhciA9IHN0ckRhdGFbcG9zaXRpb25dO1xuICAgICAgICB2YXIgbmV4dENoYXIgPSBzdHJEYXRhW3Bvc2l0aW9uICsgMV07XG4gICAgICAgIHZhciBlbnN1cmVEYXRhRXhpc3RzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFkYXRhW3Jvd10pIHtcbiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgcm93IGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgICAgICAgICBkYXRhW3Jvd10gPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghZGF0YVtyb3ddW2NvbHVtbl0pIHtcbiAgICAgICAgICAgICAgICAvLyBjcmVhdGUgY29sdW1uIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgICAgICAgICAgICBkYXRhW3Jvd11bY29sdW1uXSA9ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBlbnN1cmVEYXRhRXhpc3RzKCk7XG4gICAgICAgIGlmIChjdXJyZW50Q2hhciA9PT0gJ1wiJykge1xuICAgICAgICAgICAgaWYgKGluc2lkZVF1b3RlZEZpZWxkKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5leHRDaGFyID09PSAnXCInKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHVuZXNjYXBlIGRvdWJsZSBxdW90ZVxuICAgICAgICAgICAgICAgICAgICBkYXRhW3Jvd11bY29sdW1uXSArPSAnXCInO1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZXhpdCBxdW90ZWQgZmllbGRcbiAgICAgICAgICAgICAgICAgICAgaW5zaWRlUXVvdGVkRmllbGQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dF9yb3dfMSA9IHJvdywgb3V0X2NvbHVtbl8xID0gY29sdW1uLCBvdXRfcG9zaXRpb25fMSA9IHBvc2l0aW9uLCBcImNvbnRpbnVlXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChwcmV2aW91c0NoYXIgPT09IHVuZGVmaW5lZCB8fCBwcmV2aW91c0NoYXIgPT09IGRlbGltaXRlciB8fCBpc05ld2xpbmUocHJldmlvdXNDaGFyKSkge1xuICAgICAgICAgICAgICAgIC8vIGVudGVyIHF1b3RlZCBmaWVsZFxuICAgICAgICAgICAgICAgIGluc2lkZVF1b3RlZEZpZWxkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3V0X3Jvd18xID0gcm93LCBvdXRfY29sdW1uXzEgPSBjb2x1bW4sIG91dF9wb3NpdGlvbl8xID0gcG9zaXRpb24sIFwiY29udGludWVcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWluc2lkZVF1b3RlZEZpZWxkKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudENoYXIgPT09IGRlbGltaXRlcikge1xuICAgICAgICAgICAgICAgIC8vIG1vdmUgdG8gbmV4dCBjb2x1bW5cbiAgICAgICAgICAgICAgICBjb2x1bW4rKztcbiAgICAgICAgICAgICAgICBlbnN1cmVEYXRhRXhpc3RzKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dF9yb3dfMSA9IHJvdywgb3V0X2NvbHVtbl8xID0gY29sdW1uLCBvdXRfcG9zaXRpb25fMSA9IHBvc2l0aW9uLCBcImNvbnRpbnVlXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpc05ld2xpbmUoY3VycmVudENoYXIpKSB7XG4gICAgICAgICAgICAgICAgLy8gbW92ZSB0byBuZXh0IHJvd1xuICAgICAgICAgICAgICAgIGNvbHVtbiA9IDA7XG4gICAgICAgICAgICAgICAgcm93Kys7XG4gICAgICAgICAgICAgICAgZW5zdXJlRGF0YUV4aXN0cygpO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Q2hhciA9PT0gJ1xccicgJiYgbmV4dENoYXIgPT09ICdcXG4nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHNraXAgb3ZlciBzZWNvbmQgbmV3bGluZSBjaGFyYWN0ZXIgaWYgaXQgZXhpc3RzXG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBvdXRfcm93XzEgPSByb3csIG91dF9jb2x1bW5fMSA9IGNvbHVtbiwgb3V0X3Bvc2l0aW9uXzEgPSBwb3NpdGlvbiwgXCJjb250aW51ZVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGFkZCBjdXJyZW50IGNoYXJhY3RlciB0byBjdXJyZW50IGNvbHVtblxuICAgICAgICBkYXRhW3Jvd11bY29sdW1uXSArPSBjdXJyZW50Q2hhcjtcbiAgICAgICAgb3V0X3Jvd18xID0gcm93O1xuICAgICAgICBvdXRfY29sdW1uXzEgPSBjb2x1bW47XG4gICAgICAgIG91dF9wb3NpdGlvbl8xID0gcG9zaXRpb247XG4gICAgfTtcbiAgICB2YXIgb3V0X3Jvd18xLCBvdXRfY29sdW1uXzEsIG91dF9wb3NpdGlvbl8xO1xuICAgIC8vIGl0ZXJhdGUgb3ZlciBlYWNoIGNoYXJhY3Rlciwga2VlcCB0cmFjayBvZiBjdXJyZW50IHJvdyBhbmQgY29sdW1uIChvZiB0aGUgcmV0dXJuZWQgYXJyYXkpXG4gICAgZm9yICh2YXIgcm93ID0gMCwgY29sdW1uID0gMCwgcG9zaXRpb24gPSAwOyBwb3NpdGlvbiA8IHN0ckRhdGEubGVuZ3RoOyBwb3NpdGlvbisrKSB7XG4gICAgICAgIF9sb29wXzEocm93LCBjb2x1bW4sIHBvc2l0aW9uKTtcbiAgICAgICAgcm93ID0gb3V0X3Jvd18xO1xuICAgICAgICBjb2x1bW4gPSBvdXRfY29sdW1uXzE7XG4gICAgICAgIHBvc2l0aW9uID0gb3V0X3Bvc2l0aW9uXzE7XG4gICAgfVxuICAgIHJldHVybiBkYXRhO1xufVxuXG52YXIgQ3N2VXRpbHMgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIHN0cmluZ1RvQXJyYXk6IHN0cmluZ1RvQXJyYXlcbn0pO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgcnRsTmVnYXRpdmVTY3JvbGw7XG4vKipcbiAqIFRoaXMgbWV0aG9kIGFkZHMgYSBjbGFzcyB0byBhbiBlbGVtZW50IGFuZCByZW1vdmUgdGhhdCBjbGFzcyBmcm9tIGFsbCBzaWJsaW5ncy5cbiAqIFVzZWZ1bCBmb3IgdG9nZ2xpbmcgc3RhdGUuXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50IHRvIHJlY2VpdmUgdGhlIGNsYXNzXG4gKiBAcGFyYW0ge3N0cmluZ30gZWxlbWVudENsYXNzIFRoZSBjbGFzcyB0byBiZSBhc3NpZ25lZCB0byB0aGUgZWxlbWVudFxuICogQHBhcmFtIHtib29sZWFufSBvdGhlckVsZW1lbnRDbGFzcyBUaGUgY2xhc3MgdG8gYmUgYXNzaWduZWQgdG8gc2libGluZ3Mgb2YgdGhlIGVsZW1lbnQsIGJ1dCBub3QgdGhlIGVsZW1lbnQgaXRzZWxmXG4gKi9cbmZ1bmN0aW9uIHJhZGlvQ3NzQ2xhc3MoZWxlbWVudCwgZWxlbWVudENsYXNzLCBvdGhlckVsZW1lbnRDbGFzcykge1xuICAgIHZhciBwYXJlbnQgPSBlbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgdmFyIHNpYmxpbmcgPSBwYXJlbnQgJiYgcGFyZW50LmZpcnN0Q2hpbGQ7XG4gICAgd2hpbGUgKHNpYmxpbmcpIHtcbiAgICAgICAgaWYgKGVsZW1lbnRDbGFzcykge1xuICAgICAgICAgICAgc2libGluZy5jbGFzc0xpc3QudG9nZ2xlKGVsZW1lbnRDbGFzcywgc2libGluZyA9PT0gZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG90aGVyRWxlbWVudENsYXNzKSB7XG4gICAgICAgICAgICBzaWJsaW5nLmNsYXNzTGlzdC50b2dnbGUob3RoZXJFbGVtZW50Q2xhc3MsIHNpYmxpbmcgIT09IGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIHNpYmxpbmcgPSBzaWJsaW5nLm5leHRTaWJsaW5nO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGlzRm9jdXNhYmxlRm9ybUZpZWxkKGVsZW1lbnQpIHtcbiAgICB2YXIgbWF0Y2hlcyA9IEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXMgfHwgRWxlbWVudC5wcm90b3R5cGUubXNNYXRjaGVzU2VsZWN0b3I7XG4gICAgdmFyIGlzRm9jdXNhYmxlID0gbWF0Y2hlcy5jYWxsKGVsZW1lbnQsIENvbnN0YW50cy5JTlBVVF9TRUxFQ1RPUik7XG4gICAgdmFyIGlzTm90Rm9jdXNhYmxlID0gbWF0Y2hlcy5jYWxsKGVsZW1lbnQsIENvbnN0YW50cy5GT0NVU0FCTEVfRVhDTFVERSk7XG4gICAgdmFyIGlzRWxlbWVudFZpc2libGUgPSBpc1Zpc2libGUoZWxlbWVudCk7XG4gICAgdmFyIGZvY3VzYWJsZSA9IGlzRm9jdXNhYmxlICYmICFpc05vdEZvY3VzYWJsZSAmJiBpc0VsZW1lbnRWaXNpYmxlO1xuICAgIHJldHVybiBmb2N1c2FibGU7XG59XG5mdW5jdGlvbiBzZXREaXNwbGF5ZWQoZWxlbWVudCwgZGlzcGxheWVkKSB7XG4gICAgZWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKCdhZy1oaWRkZW4nLCAhZGlzcGxheWVkKTtcbn1cbmZ1bmN0aW9uIHNldFZpc2libGUoZWxlbWVudCwgdmlzaWJsZSkge1xuICAgIGVsZW1lbnQuY2xhc3NMaXN0LnRvZ2dsZSgnYWctaW52aXNpYmxlJywgIXZpc2libGUpO1xufVxuZnVuY3Rpb24gc2V0RGlzYWJsZWQoZWxlbWVudCwgZGlzYWJsZWQpIHtcbiAgICB2YXIgYXR0cmlidXRlTmFtZSA9ICdkaXNhYmxlZCc7XG4gICAgdmFyIGFkZE9yUmVtb3ZlRGlzYWJsZWRBdHRyaWJ1dGUgPSBkaXNhYmxlZCA/XG4gICAgICAgIGZ1bmN0aW9uIChlKSB7IHJldHVybiBlLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lLCAnJyk7IH0gOlxuICAgICAgICBmdW5jdGlvbiAoZSkgeyByZXR1cm4gZS5yZW1vdmVBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSk7IH07XG4gICAgYWRkT3JSZW1vdmVEaXNhYmxlZEF0dHJpYnV0ZShlbGVtZW50KTtcbiAgICBub2RlTGlzdEZvckVhY2goZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dCcpLCBmdW5jdGlvbiAoaW5wdXQpIHsgcmV0dXJuIGFkZE9yUmVtb3ZlRGlzYWJsZWRBdHRyaWJ1dGUoaW5wdXQpOyB9KTtcbn1cbmZ1bmN0aW9uIGlzRWxlbWVudENoaWxkT2ZDbGFzcyhlbGVtZW50LCBjbHMsIG1heE5lc3QpIHtcbiAgICB2YXIgY291bnRlciA9IDA7XG4gICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNscykpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIGlmICh0eXBlb2YgbWF4TmVzdCA9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgaWYgKCsrY291bnRlciA+IG1heE5lc3QpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChlbGVtZW50ID09PSBtYXhOZXN0KSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG4vLyByZXR1cm5zIGJhY2sgc2l6ZXMgYXMgZG91YmxlcyBpbnN0ZWFkIG9mIHN0cmluZ3MuIHNpbWlsYXIgdG9cbi8vIGdldEJvdW5kaW5nQ2xpZW50UmVjdCwgaG93ZXZlciBnZXRCb3VuZGluZ0NsaWVudFJlY3QgZG9lcyBub3Q6XG4vLyBhKSB3b3JrIHdpdGggZnJhY3Rpb25zIChlZyBicm93c2VyIGlzIHpvb21pbmcpXG4vLyBiKSBoYXMgQ1NTIHRyYW5zaXRpb25zIGFwcGxpZWQgKGVnIENTUyBzY2FsZSwgYnJvd3NlciB6b29tKSwgd2hpY2ggd2UgZG9uJ3Qgd2FudCwgd2Ugd2FudCB0aGUgdW4tdHJhbnNpdGlvbmVkIHZhbHVlc1xuZnVuY3Rpb24gZ2V0RWxlbWVudFNpemUoZWwpIHtcbiAgICB2YXIgX2EgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCksIGhlaWdodCA9IF9hLmhlaWdodCwgd2lkdGggPSBfYS53aWR0aCwgcGFkZGluZ1RvcCA9IF9hLnBhZGRpbmdUb3AsIHBhZGRpbmdSaWdodCA9IF9hLnBhZGRpbmdSaWdodCwgcGFkZGluZ0JvdHRvbSA9IF9hLnBhZGRpbmdCb3R0b20sIHBhZGRpbmdMZWZ0ID0gX2EucGFkZGluZ0xlZnQsIG1hcmdpblRvcCA9IF9hLm1hcmdpblRvcCwgbWFyZ2luUmlnaHQgPSBfYS5tYXJnaW5SaWdodCwgbWFyZ2luQm90dG9tID0gX2EubWFyZ2luQm90dG9tLCBtYXJnaW5MZWZ0ID0gX2EubWFyZ2luTGVmdCwgYm94U2l6aW5nID0gX2EuYm94U2l6aW5nO1xuICAgIHJldHVybiB7XG4gICAgICAgIGhlaWdodDogcGFyc2VGbG9hdChoZWlnaHQpLFxuICAgICAgICB3aWR0aDogcGFyc2VGbG9hdCh3aWR0aCksXG4gICAgICAgIHBhZGRpbmdUb3A6IHBhcnNlRmxvYXQocGFkZGluZ1RvcCksXG4gICAgICAgIHBhZGRpbmdSaWdodDogcGFyc2VGbG9hdChwYWRkaW5nUmlnaHQpLFxuICAgICAgICBwYWRkaW5nQm90dG9tOiBwYXJzZUZsb2F0KHBhZGRpbmdCb3R0b20pLFxuICAgICAgICBwYWRkaW5nTGVmdDogcGFyc2VGbG9hdChwYWRkaW5nTGVmdCksXG4gICAgICAgIG1hcmdpblRvcDogcGFyc2VGbG9hdChtYXJnaW5Ub3ApLFxuICAgICAgICBtYXJnaW5SaWdodDogcGFyc2VGbG9hdChtYXJnaW5SaWdodCksXG4gICAgICAgIG1hcmdpbkJvdHRvbTogcGFyc2VGbG9hdChtYXJnaW5Cb3R0b20pLFxuICAgICAgICBtYXJnaW5MZWZ0OiBwYXJzZUZsb2F0KG1hcmdpbkxlZnQpLFxuICAgICAgICBib3hTaXppbmc6IGJveFNpemluZ1xuICAgIH07XG59XG5mdW5jdGlvbiBnZXRJbm5lckhlaWdodChlbCkge1xuICAgIHZhciBzaXplID0gZ2V0RWxlbWVudFNpemUoZWwpO1xuICAgIGlmIChzaXplLmJveFNpemluZyA9PT0gJ2JvcmRlci1ib3gnKSB7XG4gICAgICAgIHJldHVybiBzaXplLmhlaWdodCAtIHNpemUucGFkZGluZ1RvcCAtIHNpemUucGFkZGluZ0JvdHRvbTtcbiAgICB9XG4gICAgcmV0dXJuIHNpemUuaGVpZ2h0O1xufVxuZnVuY3Rpb24gZ2V0SW5uZXJXaWR0aChlbCkge1xuICAgIHZhciBzaXplID0gZ2V0RWxlbWVudFNpemUoZWwpO1xuICAgIGlmIChzaXplLmJveFNpemluZyA9PT0gJ2JvcmRlci1ib3gnKSB7XG4gICAgICAgIHJldHVybiBzaXplLndpZHRoIC0gc2l6ZS5wYWRkaW5nTGVmdCAtIHNpemUucGFkZGluZ1JpZ2h0O1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZS53aWR0aDtcbn1cbmZ1bmN0aW9uIGdldEFic29sdXRlSGVpZ2h0KGVsKSB7XG4gICAgdmFyIHNpemUgPSBnZXRFbGVtZW50U2l6ZShlbCk7XG4gICAgdmFyIG1hcmdpblJpZ2h0ID0gc2l6ZS5tYXJnaW5Cb3R0b20gKyBzaXplLm1hcmdpblRvcDtcbiAgICByZXR1cm4gTWF0aC5jZWlsKGVsLm9mZnNldEhlaWdodCArIG1hcmdpblJpZ2h0KTtcbn1cbmZ1bmN0aW9uIGdldEFic29sdXRlV2lkdGgoZWwpIHtcbiAgICB2YXIgc2l6ZSA9IGdldEVsZW1lbnRTaXplKGVsKTtcbiAgICB2YXIgbWFyZ2luV2lkdGggPSBzaXplLm1hcmdpbkxlZnQgKyBzaXplLm1hcmdpblJpZ2h0O1xuICAgIHJldHVybiBNYXRoLmNlaWwoZWwub2Zmc2V0V2lkdGggKyBtYXJnaW5XaWR0aCk7XG59XG5mdW5jdGlvbiBpc1J0bE5lZ2F0aXZlU2Nyb2xsKCkge1xuICAgIGlmICh0eXBlb2YgcnRsTmVnYXRpdmVTY3JvbGwgPT09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgIHJldHVybiBydGxOZWdhdGl2ZVNjcm9sbDtcbiAgICB9XG4gICAgdmFyIHRlbXBsYXRlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgdGVtcGxhdGUuc3R5bGUuZGlyZWN0aW9uID0gJ3J0bCc7XG4gICAgdGVtcGxhdGUuc3R5bGUud2lkdGggPSAnMXB4JztcbiAgICB0ZW1wbGF0ZS5zdHlsZS5oZWlnaHQgPSAnMXB4JztcbiAgICB0ZW1wbGF0ZS5zdHlsZS5wb3NpdGlvbiA9ICdmaXhlZCc7XG4gICAgdGVtcGxhdGUuc3R5bGUudG9wID0gJzBweCc7XG4gICAgdGVtcGxhdGUuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICB0ZW1wbGF0ZS5kaXIgPSAncnRsJztcbiAgICB0ZW1wbGF0ZS5pbm5lckhUTUwgPSAvKiBodG1sICovXG4gICAgICAgIFwiPGRpdiBzdHlsZT1cXFwid2lkdGg6IDJweFxcXCI+XFxuICAgICAgICAgICAgPHNwYW4gc3R5bGU9XFxcImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2lkdGg6IDFweFxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDxzcGFuIHN0eWxlPVxcXCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHdpZHRoOiAxcHhcXFwiPjwvc3Bhbj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGVtcGxhdGUpO1xuICAgIHRlbXBsYXRlLnNjcm9sbExlZnQgPSAxO1xuICAgIHJ0bE5lZ2F0aXZlU2Nyb2xsID0gTWF0aC5mbG9vcih0ZW1wbGF0ZS5zY3JvbGxMZWZ0KSA9PT0gMDtcbiAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKHRlbXBsYXRlKTtcbiAgICByZXR1cm4gcnRsTmVnYXRpdmVTY3JvbGw7XG59XG5mdW5jdGlvbiBnZXRTY3JvbGxMZWZ0KGVsZW1lbnQsIHJ0bCkge1xuICAgIHZhciBzY3JvbGxMZWZ0ID0gZWxlbWVudC5zY3JvbGxMZWZ0O1xuICAgIGlmIChydGwpIHtcbiAgICAgICAgLy8gQWJzb2x1dGUgdmFsdWUgLSBmb3IgRkYgdGhhdCByZXBvcnRzIFJUTCBzY3JvbGxzIGluIG5lZ2F0aXZlIG51bWJlcnNcbiAgICAgICAgc2Nyb2xsTGVmdCA9IE1hdGguYWJzKHNjcm9sbExlZnQpO1xuICAgICAgICBpZiAoaXNCcm93c2VyQ2hyb21lKCkgJiYgIWlzUnRsTmVnYXRpdmVTY3JvbGwoKSkge1xuICAgICAgICAgICAgc2Nyb2xsTGVmdCA9IGVsZW1lbnQuc2Nyb2xsV2lkdGggLSBlbGVtZW50LmNsaWVudFdpZHRoIC0gc2Nyb2xsTGVmdDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc2Nyb2xsTGVmdDtcbn1cbmZ1bmN0aW9uIHNldFNjcm9sbExlZnQoZWxlbWVudCwgdmFsdWUsIHJ0bCkge1xuICAgIGlmIChydGwpIHtcbiAgICAgICAgLy8gQ2hyb21lIGFuZCBTYWZhcmkgd2hlbiBkb2luZyBSVEwgaGF2ZSB0aGUgRU5EIHBvc2l0aW9uIG9mIHRoZSBzY3JvbGwgYXMgemVybywgbm90IHRoZSBzdGFydFxuICAgICAgICBpZiAoaXNSdGxOZWdhdGl2ZVNjcm9sbCgpKSB7XG4gICAgICAgICAgICB2YWx1ZSAqPSAtMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc0Jyb3dzZXJTYWZhcmkoKSB8fCBpc0Jyb3dzZXJDaHJvbWUoKSkge1xuICAgICAgICAgICAgdmFsdWUgPSBlbGVtZW50LnNjcm9sbFdpZHRoIC0gZWxlbWVudC5jbGllbnRXaWR0aCAtIHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsZW1lbnQuc2Nyb2xsTGVmdCA9IHZhbHVlO1xufVxuZnVuY3Rpb24gY2xlYXJFbGVtZW50KGVsKSB7XG4gICAgd2hpbGUgKGVsICYmIGVsLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgZWwucmVtb3ZlQ2hpbGQoZWwuZmlyc3RDaGlsZCk7XG4gICAgfVxufVxuLyoqIEBkZXByZWNhdGVkICovXG5mdW5jdGlvbiByZW1vdmVFbGVtZW50KHBhcmVudCwgY3NzU2VsZWN0b3IpIHtcbiAgICByZW1vdmVGcm9tUGFyZW50KHBhcmVudC5xdWVyeVNlbGVjdG9yKGNzc1NlbGVjdG9yKSk7XG59XG5mdW5jdGlvbiByZW1vdmVGcm9tUGFyZW50KG5vZGUpIHtcbiAgICBpZiAobm9kZSAmJiBub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGlzVmlzaWJsZShlbGVtZW50KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQub2Zmc2V0UGFyZW50ICE9PSBudWxsO1xufVxuLyoqXG4gKiBMb2FkcyB0aGUgdGVtcGxhdGUgYW5kIHJldHVybnMgaXQgYXMgYW4gZWxlbWVudC4gbWFrZXMgdXAgZm9yIG5vIHNpbXBsZSB3YXkgaW5cbiAqIHRoZSBkb20gYXBpIHRvIGxvYWQgaHRtbCBkaXJlY3RseSwgZWcgd2UgY2Fubm90IGRvIHRoaXM6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGVtcGxhdGUpXG4gKiBAcGFyYW0ge3N0cmluZ30gdGVtcGxhdGVcbiAqIEByZXR1cm5zIHtIVE1MRWxlbWVudH1cbiAqL1xuZnVuY3Rpb24gbG9hZFRlbXBsYXRlKHRlbXBsYXRlKSB7XG4gICAgdmFyIHRlbXBEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB0ZW1wRGl2LmlubmVySFRNTCA9ICh0ZW1wbGF0ZSB8fCAnJykudHJpbSgpO1xuICAgIHJldHVybiB0ZW1wRGl2LmZpcnN0Q2hpbGQ7XG59XG5mdW5jdGlvbiBhcHBlbmRIdG1sKGVDb250YWluZXIsIGh0bWxUZW1wbGF0ZSkge1xuICAgIGlmIChlQ29udGFpbmVyLmxhc3RDaGlsZCkge1xuICAgICAgICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRWxlbWVudC9pbnNlcnRBZGphY2VudEhUTUxcbiAgICAgICAgLy8gd2UgcHV0IHRoZSBpdGVtcyBhdCB0aGUgc3RhcnQsIHNvIG5ldyBpdGVtcyBhcHBlYXIgdW5kZXJuZWF0aCBvbGQgaXRlbXMsXG4gICAgICAgIC8vIHNvIHdoZW4gZXhwYW5kaW5nL2NvbGxhcHNpbmcgZ3JvdXBzLCB0aGUgbmV3IHJvd3MgZG9uJ3QgZ28gb24gdG9wIG9mIHRoZVxuICAgICAgICAvLyByb3dzIGJlbG93IHRoYXQgYXJlIG1vdmluZyBvdXIgb2YgdGhlIHdheVxuICAgICAgICBlQ29udGFpbmVyLmluc2VydEFkamFjZW50SFRNTCgnYWZ0ZXJiZWdpbicsIGh0bWxUZW1wbGF0ZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBlQ29udGFpbmVyLmlubmVySFRNTCA9IGh0bWxUZW1wbGF0ZTtcbiAgICB9XG59XG4vKiogQGRlcHJlY2F0ZWQgKi9cbmZ1bmN0aW9uIGdldEVsZW1lbnRBdHRyaWJ1dGUoZWxlbWVudCwgYXR0cmlidXRlTmFtZSkge1xuICAgIGlmIChlbGVtZW50LmF0dHJpYnV0ZXMgJiYgZWxlbWVudC5hdHRyaWJ1dGVzW2F0dHJpYnV0ZU5hbWVdKSB7XG4gICAgICAgIHZhciBhdHRyaWJ1dGUgPSBlbGVtZW50LmF0dHJpYnV0ZXNbYXR0cmlidXRlTmFtZV07XG4gICAgICAgIHJldHVybiBhdHRyaWJ1dGUudmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gb2Zmc2V0SGVpZ2h0KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gZWxlbWVudCAmJiBlbGVtZW50LmNsaWVudEhlaWdodCA/IGVsZW1lbnQuY2xpZW50SGVpZ2h0IDogMDtcbn1cbmZ1bmN0aW9uIG9mZnNldFdpZHRoKGVsZW1lbnQpIHtcbiAgICByZXR1cm4gZWxlbWVudCAmJiBlbGVtZW50LmNsaWVudFdpZHRoID8gZWxlbWVudC5jbGllbnRXaWR0aCA6IDA7XG59XG5mdW5jdGlvbiBlbnN1cmVEb21PcmRlcihlQ29udGFpbmVyLCBlQ2hpbGQsIGVDaGlsZEJlZm9yZSkge1xuICAgIC8vIGlmIGFscmVhZHkgaW4gcmlnaHQgb3JkZXIsIGRvIG5vdGhpbmdcbiAgICBpZiAoZUNoaWxkQmVmb3JlICYmIGVDaGlsZEJlZm9yZS5uZXh0U2libGluZyA9PT0gZUNoaWxkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGZvY3VzZWRFbCA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG4gICAgdmFyIGVDaGlsZEhhc0ZvY3VzID0gZUNoaWxkLmNvbnRhaW5zKGZvY3VzZWRFbCk7XG4gICAgaWYgKGVDaGlsZEJlZm9yZSkge1xuICAgICAgICBpZiAoZUNoaWxkQmVmb3JlLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgICAvLyBpbnNlcnQgYmV0d2VlbiB0aGUgZVJvd0JlZm9yZSBhbmQgdGhlIHJvdyBhZnRlciBpdFxuICAgICAgICAgICAgZUNvbnRhaW5lci5pbnNlcnRCZWZvcmUoZUNoaWxkLCBlQ2hpbGRCZWZvcmUubmV4dFNpYmxpbmcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgbmV4dFNpYmxpbmcgaXMgbWlzc2luZywgbWVhbnMgb3RoZXIgcm93IGlzIGF0IGVuZCwgc28ganVzdCBhcHBlbmQgbmV3IHJvdyBhdCB0aGUgZW5kXG4gICAgICAgICAgICBlQ29udGFpbmVyLmFwcGVuZENoaWxkKGVDaGlsZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIG90aGVyd2lzZSBwdXQgYXQgc3RhcnRcbiAgICAgICAgaWYgKGVDb250YWluZXIuZmlyc3RDaGlsZCAmJiBlQ29udGFpbmVyLmZpcnN0Q2hpbGQgIT09IGVDaGlsZCkge1xuICAgICAgICAgICAgLy8gaW5zZXJ0IGl0IGF0IHRoZSBmaXJzdCBsb2NhdGlvblxuICAgICAgICAgICAgZUNvbnRhaW5lci5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyYmVnaW4nLCBlQ2hpbGQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChlQ2hpbGRIYXNGb2N1cyAmJiBmb2N1c2VkRWwgJiYgYnJvd3NlclN1cHBvcnRzUHJldmVudFNjcm9sbCgpKSB7XG4gICAgICAgIGZvY3VzZWRFbC5mb2N1cyh7IHByZXZlbnRTY3JvbGw6IHRydWUgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gc2V0RG9tQ2hpbGRPcmRlcihlQ29udGFpbmVyLCBvcmRlcmVkQ2hpbGRyZW4pIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyZWRDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY29ycmVjdENlbGxBdEluZGV4ID0gb3JkZXJlZENoaWxkcmVuW2ldO1xuICAgICAgICB2YXIgYWN0dWFsQ2VsbEF0SW5kZXggPSBlQ29udGFpbmVyLmNoaWxkcmVuW2ldO1xuICAgICAgICBpZiAoYWN0dWFsQ2VsbEF0SW5kZXggIT09IGNvcnJlY3RDZWxsQXRJbmRleCkge1xuICAgICAgICAgICAgZUNvbnRhaW5lci5pbnNlcnRCZWZvcmUoY29ycmVjdENlbGxBdEluZGV4LCBhY3R1YWxDZWxsQXRJbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5mdW5jdGlvbiBpbnNlcnRXaXRoRG9tT3JkZXIoZUNvbnRhaW5lciwgZVRvSW5zZXJ0LCBlQ2hpbGRCZWZvcmUpIHtcbiAgICBpZiAoZUNoaWxkQmVmb3JlKSB7XG4gICAgICAgIC8vIGlmIHByZXZpb3VzIGVsZW1lbnQgZXhpc3RzLCBqdXN0IHNsb3QgaW4gYWZ0ZXIgdGhlIHByZXZpb3VzIGVsZW1lbnRcbiAgICAgICAgZUNoaWxkQmVmb3JlLmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJlbmQnLCBlVG9JbnNlcnQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYgKGVDb250YWluZXIuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgLy8gaW5zZXJ0IGl0IGF0IHRoZSBmaXJzdCBsb2NhdGlvblxuICAgICAgICAgICAgZUNvbnRhaW5lci5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyYmVnaW4nLCBlVG9JbnNlcnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGVDb250YWluZXIgaXMgZW1wdHksIHNvIGp1c3QgYXBwZW5kIGl0XG4gICAgICAgICAgICBlQ29udGFpbmVyLmFwcGVuZENoaWxkKGVUb0luc2VydCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4vKiogQGRlcHJlY2F0ZWQgKi9cbmZ1bmN0aW9uIHByZXBlbmREQyhwYXJlbnQsIGRvY3VtZW50RnJhZ21lbnQpIHtcbiAgICBpZiAoZXhpc3RzKHBhcmVudC5maXJzdENoaWxkKSkge1xuICAgICAgICBwYXJlbnQuaW5zZXJ0QmVmb3JlKGRvY3VtZW50RnJhZ21lbnQsIHBhcmVudC5maXJzdENoaWxkKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChkb2N1bWVudEZyYWdtZW50KTtcbiAgICB9XG59XG5mdW5jdGlvbiBhZGRTdHlsZXNUb0VsZW1lbnQoZUVsZW1lbnQsIHN0eWxlcykge1xuICAgIGlmICghc3R5bGVzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoc3R5bGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgdmFyIGtleUNhbWVsQ2FzZSA9IGh5cGhlblRvQ2FtZWxDYXNlKGtleSk7XG4gICAgICAgIGlmIChrZXlDYW1lbENhc2UpIHtcbiAgICAgICAgICAgIGVFbGVtZW50LnN0eWxlW2tleUNhbWVsQ2FzZV0gPSBzdHlsZXNba2V5XTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuZnVuY3Rpb24gaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZyhlbGVtZW50KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQuY2xpZW50V2lkdGggPCBlbGVtZW50LnNjcm9sbFdpZHRoO1xufVxuZnVuY3Rpb24gaXNWZXJ0aWNhbFNjcm9sbFNob3dpbmcoZWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50LmNsaWVudEhlaWdodCA8IGVsZW1lbnQuc2Nyb2xsSGVpZ2h0O1xufVxuZnVuY3Rpb24gc2V0RWxlbWVudFdpZHRoKGVsZW1lbnQsIHdpZHRoKSB7XG4gICAgaWYgKHdpZHRoID09PSAnZmxleCcpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnd2lkdGgnKTtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnbWluV2lkdGgnKTtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnbWF4V2lkdGgnKTtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5mbGV4ID0gJzEgMSBhdXRvJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldEZpeGVkV2lkdGgoZWxlbWVudCwgd2lkdGgpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHNldEZpeGVkV2lkdGgoZWxlbWVudCwgd2lkdGgpIHtcbiAgICB3aWR0aCA9IGZvcm1hdFNpemUod2lkdGgpO1xuICAgIGVsZW1lbnQuc3R5bGUud2lkdGggPSB3aWR0aC50b1N0cmluZygpO1xuICAgIGVsZW1lbnQuc3R5bGUubWF4V2lkdGggPSB3aWR0aC50b1N0cmluZygpO1xuICAgIGVsZW1lbnQuc3R5bGUubWluV2lkdGggPSB3aWR0aC50b1N0cmluZygpO1xufVxuZnVuY3Rpb24gc2V0RWxlbWVudEhlaWdodChlbGVtZW50LCBoZWlnaHQpIHtcbiAgICBpZiAoaGVpZ2h0ID09PSAnZmxleCcpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnaGVpZ2h0Jyk7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUucmVtb3ZlUHJvcGVydHkoJ21pbkhlaWdodCcpO1xuICAgICAgICBlbGVtZW50LnN0eWxlLnJlbW92ZVByb3BlcnR5KCdtYXhIZWlnaHQnKTtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5mbGV4ID0gJzEgMSBhdXRvJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNldEZpeGVkSGVpZ2h0KGVsZW1lbnQsIGhlaWdodCk7XG4gICAgfVxufVxuZnVuY3Rpb24gc2V0Rml4ZWRIZWlnaHQoZWxlbWVudCwgaGVpZ2h0KSB7XG4gICAgaGVpZ2h0ID0gZm9ybWF0U2l6ZShoZWlnaHQpO1xuICAgIGVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0LnRvU3RyaW5nKCk7XG4gICAgZWxlbWVudC5zdHlsZS5tYXhIZWlnaHQgPSBoZWlnaHQudG9TdHJpbmcoKTtcbiAgICBlbGVtZW50LnN0eWxlLm1pbkhlaWdodCA9IGhlaWdodC50b1N0cmluZygpO1xufVxuZnVuY3Rpb24gZm9ybWF0U2l6ZShzaXplKSB7XG4gICAgaWYgKHR5cGVvZiBzaXplID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gc2l6ZSArIFwicHhcIjtcbiAgICB9XG4gICAgcmV0dXJuIHNpemU7XG59XG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiBpdCBpcyBhIERPTSBub2RlXG4gKiB0YWtlbiBmcm9tOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM4NDI4Ni9qYXZhc2NyaXB0LWlzZG9tLWhvdy1kby15b3UtY2hlY2staWYtYS1qYXZhc2NyaXB0LW9iamVjdC1pcy1hLWRvbS1vYmplY3RcbiAqIEBwYXJhbSB7YW55fSBvXG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc05vZGUobykge1xuICAgIHJldHVybiAodHlwZW9mIE5vZGUgPT09ICdmdW5jdGlvbidcbiAgICAgICAgPyBvIGluc3RhbmNlb2YgTm9kZVxuICAgICAgICA6IG8gJiYgdHlwZW9mIG8gPT09ICdvYmplY3QnICYmIHR5cGVvZiBvLm5vZGVUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2Ygby5ub2RlTmFtZSA9PT0gJ3N0cmluZycpO1xufVxuLy9cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGl0IGlzIGEgRE9NIGVsZW1lbnRcbiAqIHRha2VuIGZyb206IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzg0Mjg2L2phdmFzY3JpcHQtaXNkb20taG93LWRvLXlvdS1jaGVjay1pZi1hLWphdmFzY3JpcHQtb2JqZWN0LWlzLWEtZG9tLW9iamVjdFxuICogQHBhcmFtIHthbnl9IG9cbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc0VsZW1lbnQobykge1xuICAgIHJldHVybiAodHlwZW9mIEhUTUxFbGVtZW50ID09PSAnZnVuY3Rpb24nXG4gICAgICAgID8gbyBpbnN0YW5jZW9mIEhUTUxFbGVtZW50IC8vRE9NMlxuICAgICAgICA6IG8gJiYgaXNOb25OdWxsT2JqZWN0KG8pICYmIG8ubm9kZVR5cGUgPT09IDEgJiYgdHlwZW9mIG8ubm9kZU5hbWUgPT09ICdzdHJpbmcnKTtcbn1cbmZ1bmN0aW9uIGlzTm9kZU9yRWxlbWVudChvKSB7XG4gICAgcmV0dXJuIGlzTm9kZShvKSB8fCBpc0VsZW1lbnQobyk7XG59XG4vKipcbiAqIE1ha2VzIGEgY29weSBvZiBhIG5vZGUgbGlzdCBpbnRvIGEgbGlzdFxuICogQHBhcmFtIHtOb2RlTGlzdH0gbm9kZUxpc3RcbiAqIEByZXR1cm5zIHtOb2RlW119XG4gKi9cbmZ1bmN0aW9uIGNvcHlOb2RlTGlzdChub2RlTGlzdCkge1xuICAgIGlmIChub2RlTGlzdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIG5vZGVMaXN0Rm9yRWFjaChub2RlTGlzdCwgZnVuY3Rpb24gKG5vZGUpIHsgcmV0dXJuIHJlc3VsdC5wdXNoKG5vZGUpOyB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gaXRlcmF0ZU5hbWVkTm9kZU1hcChtYXAsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCFtYXApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hcC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXR0ciA9IG1hcFtpXTtcbiAgICAgICAgY2FsbGJhY2soYXR0ci5uYW1lLCBhdHRyLnZhbHVlKTtcbiAgICB9XG59XG4vKiogQGRlcHJlY2F0ZWQgKi9cbmZ1bmN0aW9uIHNldENoZWNrYm94U3RhdGUoZUNoZWNrYm94LCBzdGF0ZSkge1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09ICdib29sZWFuJykge1xuICAgICAgICBlQ2hlY2tib3guY2hlY2tlZCA9IHN0YXRlO1xuICAgICAgICBlQ2hlY2tib3guaW5kZXRlcm1pbmF0ZSA9IGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8gaXNOb2RlU2VsZWN0ZWQgcmV0dXJucyBiYWNrIHVuZGVmaW5lZCBpZiBpdCdzIGEgZ3JvdXAgYW5kIHRoZSBjaGlsZHJlblxuICAgICAgICAvLyBhcmUgYSBtaXggb2Ygc2VsZWN0ZWQgYW5kIHVuc2VsZWN0ZWRcbiAgICAgICAgZUNoZWNrYm94LmluZGV0ZXJtaW5hdGUgPSB0cnVlO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFkZE9yUmVtb3ZlQXR0cmlidXRlKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZS50b1N0cmluZygpKTtcbiAgICB9XG59XG5mdW5jdGlvbiBub2RlTGlzdEZvckVhY2gobm9kZUxpc3QsIGFjdGlvbikge1xuICAgIGlmIChub2RlTGlzdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2RlTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBhY3Rpb24obm9kZUxpc3RbaV0pO1xuICAgIH1cbn1cblxudmFyIERvbVV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICByYWRpb0Nzc0NsYXNzOiByYWRpb0Nzc0NsYXNzLFxuICAgIGlzRm9jdXNhYmxlRm9ybUZpZWxkOiBpc0ZvY3VzYWJsZUZvcm1GaWVsZCxcbiAgICBzZXREaXNwbGF5ZWQ6IHNldERpc3BsYXllZCxcbiAgICBzZXRWaXNpYmxlOiBzZXRWaXNpYmxlLFxuICAgIHNldERpc2FibGVkOiBzZXREaXNhYmxlZCxcbiAgICBpc0VsZW1lbnRDaGlsZE9mQ2xhc3M6IGlzRWxlbWVudENoaWxkT2ZDbGFzcyxcbiAgICBnZXRFbGVtZW50U2l6ZTogZ2V0RWxlbWVudFNpemUsXG4gICAgZ2V0SW5uZXJIZWlnaHQ6IGdldElubmVySGVpZ2h0LFxuICAgIGdldElubmVyV2lkdGg6IGdldElubmVyV2lkdGgsXG4gICAgZ2V0QWJzb2x1dGVIZWlnaHQ6IGdldEFic29sdXRlSGVpZ2h0LFxuICAgIGdldEFic29sdXRlV2lkdGg6IGdldEFic29sdXRlV2lkdGgsXG4gICAgaXNSdGxOZWdhdGl2ZVNjcm9sbDogaXNSdGxOZWdhdGl2ZVNjcm9sbCxcbiAgICBnZXRTY3JvbGxMZWZ0OiBnZXRTY3JvbGxMZWZ0LFxuICAgIHNldFNjcm9sbExlZnQ6IHNldFNjcm9sbExlZnQsXG4gICAgY2xlYXJFbGVtZW50OiBjbGVhckVsZW1lbnQsXG4gICAgcmVtb3ZlRWxlbWVudDogcmVtb3ZlRWxlbWVudCxcbiAgICByZW1vdmVGcm9tUGFyZW50OiByZW1vdmVGcm9tUGFyZW50LFxuICAgIGlzVmlzaWJsZTogaXNWaXNpYmxlLFxuICAgIGxvYWRUZW1wbGF0ZTogbG9hZFRlbXBsYXRlLFxuICAgIGFwcGVuZEh0bWw6IGFwcGVuZEh0bWwsXG4gICAgZ2V0RWxlbWVudEF0dHJpYnV0ZTogZ2V0RWxlbWVudEF0dHJpYnV0ZSxcbiAgICBvZmZzZXRIZWlnaHQ6IG9mZnNldEhlaWdodCxcbiAgICBvZmZzZXRXaWR0aDogb2Zmc2V0V2lkdGgsXG4gICAgZW5zdXJlRG9tT3JkZXI6IGVuc3VyZURvbU9yZGVyLFxuICAgIHNldERvbUNoaWxkT3JkZXI6IHNldERvbUNoaWxkT3JkZXIsXG4gICAgaW5zZXJ0V2l0aERvbU9yZGVyOiBpbnNlcnRXaXRoRG9tT3JkZXIsXG4gICAgcHJlcGVuZERDOiBwcmVwZW5kREMsXG4gICAgYWRkU3R5bGVzVG9FbGVtZW50OiBhZGRTdHlsZXNUb0VsZW1lbnQsXG4gICAgaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZzogaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZyxcbiAgICBpc1ZlcnRpY2FsU2Nyb2xsU2hvd2luZzogaXNWZXJ0aWNhbFNjcm9sbFNob3dpbmcsXG4gICAgc2V0RWxlbWVudFdpZHRoOiBzZXRFbGVtZW50V2lkdGgsXG4gICAgc2V0Rml4ZWRXaWR0aDogc2V0Rml4ZWRXaWR0aCxcbiAgICBzZXRFbGVtZW50SGVpZ2h0OiBzZXRFbGVtZW50SGVpZ2h0LFxuICAgIHNldEZpeGVkSGVpZ2h0OiBzZXRGaXhlZEhlaWdodCxcbiAgICBmb3JtYXRTaXplOiBmb3JtYXRTaXplLFxuICAgIGlzTm9kZTogaXNOb2RlLFxuICAgIGlzRWxlbWVudDogaXNFbGVtZW50LFxuICAgIGlzTm9kZU9yRWxlbWVudDogaXNOb2RlT3JFbGVtZW50LFxuICAgIGNvcHlOb2RlTGlzdDogY29weU5vZGVMaXN0LFxuICAgIGl0ZXJhdGVOYW1lZE5vZGVNYXA6IGl0ZXJhdGVOYW1lZE5vZGVNYXAsXG4gICAgc2V0Q2hlY2tib3hTdGF0ZTogc2V0Q2hlY2tib3hTdGF0ZSxcbiAgICBhZGRPclJlbW92ZUF0dHJpYnV0ZTogYWRkT3JSZW1vdmVBdHRyaWJ1dGUsXG4gICAgbm9kZUxpc3RGb3JFYWNoOiBub2RlTGlzdEZvckVhY2hcbn0pO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG4vKiogQGRlcHJlY2F0ZWQgKi9cbmZ1bmN0aW9uIGdldE5hbWVPZkNsYXNzKHRoZUNsYXNzKSB7XG4gICAgdmFyIGZ1bmNOYW1lUmVnZXggPSAvZnVuY3Rpb24gKC57MSx9KVxcKC87XG4gICAgdmFyIGZ1bmNBc1N0cmluZyA9IHRoZUNsYXNzLnRvU3RyaW5nKCk7XG4gICAgdmFyIHJlc3VsdHMgPSBmdW5jTmFtZVJlZ2V4LmV4ZWMoZnVuY0FzU3RyaW5nKTtcbiAgICByZXR1cm4gcmVzdWx0cyAmJiByZXN1bHRzLmxlbmd0aCA+IDEgPyByZXN1bHRzWzFdIDogXCJcIjtcbn1cbmZ1bmN0aW9uIGZpbmRMaW5lQnlMZWFzdFNxdWFyZXModmFsdWVzKSB7XG4gICAgdmFyIGxlbiA9IHZhbHVlcy5sZW5ndGg7XG4gICAgdmFyIG1heERlY2ltYWxzID0gMDtcbiAgICBpZiAobGVuIDw9IDEpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlcztcbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgICB2YXIgc3BsaXRFeHBvbmVudCA9IHZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoJ2UtJyk7XG4gICAgICAgIGlmIChzcGxpdEV4cG9uZW50Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIG1heERlY2ltYWxzID0gTWF0aC5tYXgobWF4RGVjaW1hbHMsIHBhcnNlSW50KHNwbGl0RXhwb25lbnRbMV0sIDEwKSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBtYXhEZWNpbWFscyA9IE1hdGgubWF4KG1heERlY2ltYWxzLCB2YWx1ZS50b1N0cmluZygpLnNwbGl0KCcuJylbMV0ubGVuZ3RoKTtcbiAgICB9XG4gICAgdmFyIHN1bV94ID0gMDtcbiAgICB2YXIgc3VtX3kgPSAwO1xuICAgIHZhciBzdW1feHkgPSAwO1xuICAgIHZhciBzdW1feHggPSAwO1xuICAgIHZhciB5ID0gMDtcbiAgICBmb3IgKHZhciB4ID0gMDsgeCA8IGxlbjsgeCsrKSB7XG4gICAgICAgIHkgPSB2YWx1ZXNbeF07XG4gICAgICAgIHN1bV94ICs9IHg7XG4gICAgICAgIHN1bV95ICs9IHk7XG4gICAgICAgIHN1bV94eCArPSB4ICogeDtcbiAgICAgICAgc3VtX3h5ICs9IHggKiB5O1xuICAgIH1cbiAgICB2YXIgbSA9IChsZW4gKiBzdW1feHkgLSBzdW1feCAqIHN1bV95KSAvIChsZW4gKiBzdW1feHggLSBzdW1feCAqIHN1bV94KTtcbiAgICB2YXIgYiA9IChzdW1feSAvIGxlbikgLSAobSAqIHN1bV94KSAvIGxlbjtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgZm9yICh2YXIgeCA9IDA7IHggPD0gbGVuOyB4KyspIHtcbiAgICAgICAgcmVzdWx0LnB1c2gocGFyc2VGbG9hdCgoeCAqIG0gKyBiKS50b0ZpeGVkKG1heERlY2ltYWxzKSkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuLyoqXG4gKiBDb252ZXJ0cyBhIENTUyBvYmplY3QgaW50byBzdHJpbmdcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZXNUb1VzZSBhbiBvYmplY3QgZWc6IHtjb2xvcjogJ2JsYWNrJywgdG9wOiAnMjVweCd9XG4gKiBAcmV0dXJuIHtzdHJpbmd9IEEgc3RyaW5nIGxpa2UgXCJjb2xvcjogYmxhY2s7IHRvcDogMjVweDtcIiBmb3IgaHRtbFxuICovXG5mdW5jdGlvbiBjc3NTdHlsZU9iamVjdFRvTWFya3VwKHN0eWxlc1RvVXNlKSB7XG4gICAgaWYgKCFzdHlsZXNUb1VzZSkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHZhciByZXNQYXJ0cyA9IFtdO1xuICAgIGl0ZXJhdGVPYmplY3Qoc3R5bGVzVG9Vc2UsIGZ1bmN0aW9uIChzdHlsZUtleSwgc3R5bGVWYWx1ZSkge1xuICAgICAgICB2YXIgc3R5bGVLZXlEYXNoZWQgPSBjYW1lbENhc2VUb0h5cGhlbihzdHlsZUtleSk7XG4gICAgICAgIHJlc1BhcnRzLnB1c2goc3R5bGVLZXlEYXNoZWQgKyBcIjogXCIgKyBzdHlsZVZhbHVlICsgXCI7XCIpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXNQYXJ0cy5qb2luKCcgJyk7XG59XG4vKipcbiAqIERpc3BsYXlzIGEgbWVzc2FnZSB0byB0aGUgYnJvd3Nlci4gdGhpcyBpcyB1c2VmdWwgaW4gaVBhZCwgd2hlcmUgeW91IGNhbid0IGVhc2lseSBzZWUgdGhlIGNvbnNvbGUuXG4gKiBzbyB0aGUgamF2YXNjcmlwdCBjb2RlIGNhbiB1c2UgdGhpcyB0byBnaXZlIGZlZWRiYWNrLiB0aGlzIGlzIE5PVCBpbnRlbmRlZCB0byBiZSBjYWxsZWQgaW4gcHJvZHVjdGlvbi5cbiAqIGl0IGlzIGludGVuZGVkIHRoZSBBRyBHcmlkIGRldmVsb3BlciBjYWxscyB0aGlzIHRvIHRyb3VibGVzaG9vdCwgYnV0IHRoZW4gdGFrZXMgb3V0IHRoZSBjYWxscyBiZWZvcmVcbiAqIGNoZWNraW5nIGluLlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZ1xuICovXG5mdW5jdGlvbiBtZXNzYWdlKG1zZykge1xuICAgIHZhciBlTWVzc2FnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHZhciBlQm94ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI19fYWdfX21lc3NhZ2UnKTtcbiAgICBlTWVzc2FnZS5pbm5lckhUTUwgPSBtc2c7XG4gICAgaWYgKCFlQm94KSB7XG4gICAgICAgIHZhciB0ZW1wbGF0ZSA9IFwiPGRpdiBpZD1cXFwiX19hZ19fbWVzc2FnZVxcXCIgc3R5bGU9XFxcImRpc3BsYXk6IGlubGluZS1ibG9jazsgcG9zaXRpb246IGFic29sdXRlOyB0b3A6IDBweDsgbGVmdDogMHB4OyBjb2xvcjogd2hpdGU7IGJhY2tncm91bmQtY29sb3I6IGJsYWNrOyB6LWluZGV4OiAyMDsgcGFkZGluZzogMnB4OyBib3JkZXI6IDFweCBzb2xpZCBkYXJrcmVkOyBoZWlnaHQ6IDIwMHB4OyBvdmVyZmxvdy15OiBhdXRvO1xcXCI+PC9kaXY+XCI7XG4gICAgICAgIGVCb3ggPSBsb2FkVGVtcGxhdGUodGVtcGxhdGUpO1xuICAgICAgICBpZiAoZG9jdW1lbnQuYm9keSkge1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChlQm94KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlQm94Lmluc2VydEJlZm9yZShlTWVzc2FnZSwgZUJveC5jaGlsZHJlblswXSk7XG59XG4vKipcbiAqIGNlbGwgcmVuZGVyZXJzIGFyZSB1c2VkIGluIGEgZmV3IHBsYWNlcy4gdGhleSBiaW5kIHRvIGRvbSBzbGlnaHRseSBkaWZmZXJlbnRseSB0byBvdGhlciBjZWxsIHJlbmRlcmVzIGFzIHRoZXlcbiAqIGNhbiByZXR1cm4gYmFjayBzdHJpbmdzIChpbnN0ZWFkIG9mIGh0bWwgZWxlbW50KSBpbiB0aGUgZ2V0R3VpKCkgbWV0aG9kLiBjb21tb24gY29kZSBwbGFjZWQgaGVyZSB0byBoYW5kbGUgdGhhdC5cbiAqIEBwYXJhbSB7QWdQcm9taXNlPElDZWxsUmVuZGVyZXJDb21wPn0gY2VsbFJlbmRlcmVyUHJvbWlzZVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZVRhcmdldFxuICovXG5mdW5jdGlvbiBiaW5kQ2VsbFJlbmRlcmVyVG9IdG1sRWxlbWVudChjZWxsUmVuZGVyZXJQcm9taXNlLCBlVGFyZ2V0KSB7XG4gICAgY2VsbFJlbmRlcmVyUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChjZWxsUmVuZGVyZXIpIHtcbiAgICAgICAgdmFyIGd1aSA9IGNlbGxSZW5kZXJlci5nZXRHdWkoKTtcbiAgICAgICAgaWYgKGd1aSAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGd1aSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICBlVGFyZ2V0LmFwcGVuZENoaWxkKGd1aSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlVGFyZ2V0LmlubmVySFRNTCA9IGd1aTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG52YXIgR2VuZXJhbFV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBnZXROYW1lT2ZDbGFzczogZ2V0TmFtZU9mQ2xhc3MsXG4gICAgZmluZExpbmVCeUxlYXN0U3F1YXJlczogZmluZExpbmVCeUxlYXN0U3F1YXJlcyxcbiAgICBjc3NTdHlsZU9iamVjdFRvTWFya3VwOiBjc3NTdHlsZU9iamVjdFRvTWFya3VwLFxuICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgYmluZENlbGxSZW5kZXJlclRvSHRtbEVsZW1lbnQ6IGJpbmRDZWxsUmVuZGVyZXJUb0h0bWxFbGVtZW50XG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuLy8gQVJJQSBIRUxQRVIgRlVOQ1RJT05TXG5mdW5jdGlvbiBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsIGF0dHJpYnV0ZSwgdmFsdWUpIHtcbiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShhcmlhQXR0cmlidXRlTmFtZShhdHRyaWJ1dGUpLCB2YWx1ZS50b1N0cmluZygpKTtcbn1cbmZ1bmN0aW9uIHJlbW92ZUFyaWFBdHRyaWJ1dGUoZWxlbWVudCwgYXR0cmlidXRlKSB7XG4gICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoYXJpYUF0dHJpYnV0ZU5hbWUoYXR0cmlidXRlKSk7XG59XG5mdW5jdGlvbiBhcmlhQXR0cmlidXRlTmFtZShhdHRyaWJ1dGUpIHtcbiAgICByZXR1cm4gXCJhcmlhLVwiICsgYXR0cmlidXRlO1xufVxuZnVuY3Rpb24gc2V0QXJpYVJvbGUoZWxlbWVudCwgcm9sZSkge1xuICAgIGlmIChyb2xlKSB7XG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdyb2xlJywgcm9sZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgncm9sZScpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGdldEFyaWFTb3J0U3RhdGUoY29sdW1uKSB7XG4gICAgdmFyIHNvcnQ7XG4gICAgaWYgKGNvbHVtbi5pc1NvcnRBc2NlbmRpbmcoKSkge1xuICAgICAgICBzb3J0ID0gJ2FzY2VuZGluZyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKGNvbHVtbi5pc1NvcnREZXNjZW5kaW5nKCkpIHtcbiAgICAgICAgc29ydCA9ICdkZXNjZW5kaW5nJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNvcnQgPSAnbm9uZSc7XG4gICAgfVxuICAgIHJldHVybiBzb3J0O1xufVxuLy8gQVJJQSBBVFRSSUJVVEUgR0VUVEVSU1xuZnVuY3Rpb24gZ2V0QXJpYUxldmVsKGVsZW1lbnQpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2FyaWEtbGV2ZWwnKSwgMTApO1xufVxuZnVuY3Rpb24gZ2V0QXJpYVBvc0luU2V0KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2FyaWEtcG9zaW5zZXQnKSwgMTApO1xufVxuZnVuY3Rpb24gZ2V0QXJpYURlc2NyaWJlZEJ5KGVsZW1lbnQpIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2FyaWEtZGVzY3JpYmVkYnknKSB8fCAnJztcbn1cbi8vIEFSSUEgQVRUUklCVVRFIFNFVFRFUlNcbmZ1bmN0aW9uIHNldEFyaWFMYWJlbChlbGVtZW50LCBsYWJlbCkge1xuICAgIHZhciBrZXkgPSAnbGFiZWwnO1xuICAgIGlmIChsYWJlbCkge1xuICAgICAgICBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsIGtleSwgbGFiZWwpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmVtb3ZlQXJpYUF0dHJpYnV0ZShlbGVtZW50LCBrZXkpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHNldEFyaWFMYWJlbGxlZEJ5KGVsZW1lbnQsIGxhYmVsbGVkQnkpIHtcbiAgICB2YXIga2V5ID0gJ2xhYmVsbGVkYnknO1xuICAgIGlmIChsYWJlbGxlZEJ5KSB7XG4gICAgICAgIHNldEFyaWFBdHRyaWJ1dGUoZWxlbWVudCwga2V5LCBsYWJlbGxlZEJ5KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJlbW92ZUFyaWFBdHRyaWJ1dGUoZWxlbWVudCwga2V5KTtcbiAgICB9XG59XG5mdW5jdGlvbiBzZXRBcmlhRGVzY3JpcHRpb24oZWxlbWVudCwgZGVzY3JpcHRpb24pIHtcbiAgICB2YXIga2V5ID0gJ2Rlc2NyaXB0aW9uJztcbiAgICBpZiAoZGVzY3JpcHRpb24pIHtcbiAgICAgICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCBrZXksIGRlc2NyaXB0aW9uKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJlbW92ZUFyaWFBdHRyaWJ1dGUoZWxlbWVudCwga2V5KTtcbiAgICB9XG59XG5mdW5jdGlvbiBzZXRBcmlhRGVzY3JpYmVkQnkoZWxlbWVudCwgZGVzY3JpYmVkYnkpIHtcbiAgICB2YXIga2V5ID0gJ2Rlc2NyaWJlZGJ5JztcbiAgICBpZiAoZGVzY3JpYmVkYnkpIHtcbiAgICAgICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCBrZXksIGRlc2NyaWJlZGJ5KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJlbW92ZUFyaWFBdHRyaWJ1dGUoZWxlbWVudCwga2V5KTtcbiAgICB9XG59XG5mdW5jdGlvbiBzZXRBcmlhTGV2ZWwoZWxlbWVudCwgbGV2ZWwpIHtcbiAgICBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsICdsZXZlbCcsIGxldmVsKTtcbn1cbmZ1bmN0aW9uIHNldEFyaWFEaXNhYmxlZChlbGVtZW50LCBkaXNhYmxlZCkge1xuICAgIHNldEFyaWFBdHRyaWJ1dGUoZWxlbWVudCwgJ2Rpc2FibGVkJywgZGlzYWJsZWQpO1xufVxuZnVuY3Rpb24gc2V0QXJpYUV4cGFuZGVkKGVsZW1lbnQsIGV4cGFuZGVkKSB7XG4gICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCAnZXhwYW5kZWQnLCBleHBhbmRlZCk7XG59XG5mdW5jdGlvbiByZW1vdmVBcmlhRXhwYW5kZWQoZWxlbWVudCkge1xuICAgIHJlbW92ZUFyaWFBdHRyaWJ1dGUoZWxlbWVudCwgJ2V4cGFuZGVkJyk7XG59XG5mdW5jdGlvbiBzZXRBcmlhU2V0U2l6ZShlbGVtZW50LCBzZXRzaXplKSB7XG4gICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCAnc2V0c2l6ZScsIHNldHNpemUpO1xufVxuZnVuY3Rpb24gc2V0QXJpYVBvc0luU2V0KGVsZW1lbnQsIHBvc2l0aW9uKSB7XG4gICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCAncG9zaW5zZXQnLCBwb3NpdGlvbik7XG59XG5mdW5jdGlvbiBzZXRBcmlhTXVsdGlTZWxlY3RhYmxlKGVsZW1lbnQsIG11bHRpU2VsZWN0YWJsZSkge1xuICAgIHNldEFyaWFBdHRyaWJ1dGUoZWxlbWVudCwgJ211bHRpc2VsZWN0YWJsZScsIG11bHRpU2VsZWN0YWJsZSk7XG59XG5mdW5jdGlvbiBzZXRBcmlhUm93Q291bnQoZWxlbWVudCwgcm93Q291bnQpIHtcbiAgICBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsICdyb3djb3VudCcsIHJvd0NvdW50KTtcbn1cbmZ1bmN0aW9uIHNldEFyaWFSb3dJbmRleChlbGVtZW50LCByb3dJbmRleCkge1xuICAgIHNldEFyaWFBdHRyaWJ1dGUoZWxlbWVudCwgJ3Jvd2luZGV4Jywgcm93SW5kZXgpO1xufVxuZnVuY3Rpb24gc2V0QXJpYUNvbENvdW50KGVsZW1lbnQsIGNvbENvdW50KSB7XG4gICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCAnY29sY291bnQnLCBjb2xDb3VudCk7XG59XG5mdW5jdGlvbiBzZXRBcmlhQ29sSW5kZXgoZWxlbWVudCwgY29sSW5kZXgpIHtcbiAgICBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsICdjb2xpbmRleCcsIGNvbEluZGV4KTtcbn1cbmZ1bmN0aW9uIHNldEFyaWFDb2xTcGFuKGVsZW1lbnQsIGNvbFNwYW4pIHtcbiAgICBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsICdjb2xzcGFuJywgY29sU3Bhbik7XG59XG5mdW5jdGlvbiBzZXRBcmlhU29ydChlbGVtZW50LCBzb3J0KSB7XG4gICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCAnc29ydCcsIHNvcnQpO1xufVxuZnVuY3Rpb24gcmVtb3ZlQXJpYVNvcnQoZWxlbWVudCkge1xuICAgIHJlbW92ZUFyaWFBdHRyaWJ1dGUoZWxlbWVudCwgJ3NvcnQnKTtcbn1cbmZ1bmN0aW9uIHNldEFyaWFTZWxlY3RlZChlbGVtZW50LCBzZWxlY3RlZCkge1xuICAgIHZhciBhdHRyaWJ1dGVOYW1lID0gJ3NlbGVjdGVkJztcbiAgICBpZiAoc2VsZWN0ZWQpIHtcbiAgICAgICAgc2V0QXJpYUF0dHJpYnV0ZShlbGVtZW50LCBhdHRyaWJ1dGVOYW1lLCBzZWxlY3RlZCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZW1vdmVBcmlhQXR0cmlidXRlKGVsZW1lbnQsIGF0dHJpYnV0ZU5hbWUpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHNldEFyaWFDaGVja2VkKGVsZW1lbnQsIGNoZWNrZWQpIHtcbiAgICBzZXRBcmlhQXR0cmlidXRlKGVsZW1lbnQsICdjaGVja2VkJywgY2hlY2tlZCA9PT0gdW5kZWZpbmVkID8gJ21peGVkJyA6IGNoZWNrZWQpO1xufVxuXG52YXIgQXJpYVV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBzZXRBcmlhUm9sZTogc2V0QXJpYVJvbGUsXG4gICAgZ2V0QXJpYVNvcnRTdGF0ZTogZ2V0QXJpYVNvcnRTdGF0ZSxcbiAgICBnZXRBcmlhTGV2ZWw6IGdldEFyaWFMZXZlbCxcbiAgICBnZXRBcmlhUG9zSW5TZXQ6IGdldEFyaWFQb3NJblNldCxcbiAgICBnZXRBcmlhRGVzY3JpYmVkQnk6IGdldEFyaWFEZXNjcmliZWRCeSxcbiAgICBzZXRBcmlhTGFiZWw6IHNldEFyaWFMYWJlbCxcbiAgICBzZXRBcmlhTGFiZWxsZWRCeTogc2V0QXJpYUxhYmVsbGVkQnksXG4gICAgc2V0QXJpYURlc2NyaXB0aW9uOiBzZXRBcmlhRGVzY3JpcHRpb24sXG4gICAgc2V0QXJpYURlc2NyaWJlZEJ5OiBzZXRBcmlhRGVzY3JpYmVkQnksXG4gICAgc2V0QXJpYUxldmVsOiBzZXRBcmlhTGV2ZWwsXG4gICAgc2V0QXJpYURpc2FibGVkOiBzZXRBcmlhRGlzYWJsZWQsXG4gICAgc2V0QXJpYUV4cGFuZGVkOiBzZXRBcmlhRXhwYW5kZWQsXG4gICAgcmVtb3ZlQXJpYUV4cGFuZGVkOiByZW1vdmVBcmlhRXhwYW5kZWQsXG4gICAgc2V0QXJpYVNldFNpemU6IHNldEFyaWFTZXRTaXplLFxuICAgIHNldEFyaWFQb3NJblNldDogc2V0QXJpYVBvc0luU2V0LFxuICAgIHNldEFyaWFNdWx0aVNlbGVjdGFibGU6IHNldEFyaWFNdWx0aVNlbGVjdGFibGUsXG4gICAgc2V0QXJpYVJvd0NvdW50OiBzZXRBcmlhUm93Q291bnQsXG4gICAgc2V0QXJpYVJvd0luZGV4OiBzZXRBcmlhUm93SW5kZXgsXG4gICAgc2V0QXJpYUNvbENvdW50OiBzZXRBcmlhQ29sQ291bnQsXG4gICAgc2V0QXJpYUNvbEluZGV4OiBzZXRBcmlhQ29sSW5kZXgsXG4gICAgc2V0QXJpYUNvbFNwYW46IHNldEFyaWFDb2xTcGFuLFxuICAgIHNldEFyaWFTb3J0OiBzZXRBcmlhU29ydCxcbiAgICByZW1vdmVBcmlhU29ydDogcmVtb3ZlQXJpYVNvcnQsXG4gICAgc2V0QXJpYVNlbGVjdGVkOiBzZXRBcmlhU2VsZWN0ZWQsXG4gICAgc2V0QXJpYUNoZWNrZWQ6IHNldEFyaWFDaGVja2VkXG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fcmVhZCRqID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xuLyoqXG4gKiBTZXJpYWxpc2VzIGEgRGF0ZSB0byBhIHN0cmluZyBvZiBmb3JtYXQgYHl5eXktTU0tZGQgSEg6bW06c3NgLlxuICogQW4gYWx0ZXJuYXRpdmUgc2VwYXJhdG9yIGNhbiBiZSBwcm92aWRlZCB0byBiZSB1c2VkIGluc3RlYWQgb2YgaHlwaGVucy5cbiAqIEBwYXJhbSBkYXRlIFRoZSBkYXRlIHRvIHNlcmlhbGlzZVxuICogQHBhcmFtIGluY2x1ZGVUaW1lIFdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgdGltZSBpbiB0aGUgc2VyaWFsaXNlZCBzdHJpbmdcbiAqIEBwYXJhbSBzZXBhcmF0b3IgVGhlIHNlcGFyYXRvciB0byB1c2UgYmV0d2VlbiBkYXRlIHBhcnRzXG4gKi9cbmZ1bmN0aW9uIHNlcmlhbGlzZURhdGUoZGF0ZSwgaW5jbHVkZVRpbWUsIHNlcGFyYXRvcikge1xuICAgIGlmIChpbmNsdWRlVGltZSA9PT0gdm9pZCAwKSB7IGluY2x1ZGVUaW1lID0gdHJ1ZTsgfVxuICAgIGlmIChzZXBhcmF0b3IgPT09IHZvaWQgMCkgeyBzZXBhcmF0b3IgPSAnLSc7IH1cbiAgICBpZiAoIWRhdGUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciBzZXJpYWxpc2VkID0gW2RhdGUuZ2V0RnVsbFllYXIoKSwgZGF0ZS5nZXRNb250aCgpICsgMSwgZGF0ZS5nZXREYXRlKCldLm1hcChmdW5jdGlvbiAocGFydCkgeyByZXR1cm4gcGFkU3RhcnRXaWR0aFplcm9zKHBhcnQsIDIpOyB9KS5qb2luKHNlcGFyYXRvcik7XG4gICAgaWYgKGluY2x1ZGVUaW1lKSB7XG4gICAgICAgIHNlcmlhbGlzZWQgKz0gJyAnICsgW2RhdGUuZ2V0SG91cnMoKSwgZGF0ZS5nZXRNaW51dGVzKCksIGRhdGUuZ2V0U2Vjb25kcygpXS5tYXAoZnVuY3Rpb24gKHBhcnQpIHsgcmV0dXJuIHBhZFN0YXJ0V2lkdGhaZXJvcyhwYXJ0LCAyKTsgfSkuam9pbignOicpO1xuICAgIH1cbiAgICByZXR1cm4gc2VyaWFsaXNlZDtcbn1cbnZhciBjYWxjdWxhdGVPcmRpbmFsID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID4gMyAmJiB2YWx1ZSA8IDIxKSB7XG4gICAgICAgIHJldHVybiAndGgnO1xuICAgIH1cbiAgICB2YXIgcmVtYWluZGVyID0gdmFsdWUgJSAxMDtcbiAgICBzd2l0Y2ggKHJlbWFpbmRlcikge1xuICAgICAgICBjYXNlIDE6IHJldHVybiBcInN0XCI7XG4gICAgICAgIGNhc2UgMjogcmV0dXJuIFwibmRcIjtcbiAgICAgICAgY2FzZSAzOiByZXR1cm4gXCJyZFwiO1xuICAgIH1cbiAgICByZXR1cm4gJ3RoJztcbn07XG4vKipcbiAqIFNlcmlhbGlzZXMgYSBEYXRlIHRvIGEgc3RyaW5nIG9mIGZvcm1hdCB0aGUgZGVmaW5lZCBmb3JtYXQsIGRvZXMgbm90IGluY2x1ZGUgdGltZS5cbiAqIEBwYXJhbSBkYXRlIFRoZSBkYXRlIHRvIHNlcmlhbGlzZVxuICogQHBhcmFtIGZvcm1hdCBUaGUgc3RyaW5nIHRvIGZvcm1hdCB0aGUgZGF0ZSB0bywgZGVmYXVsdHMgdG8gWVlZWS1NTS1ERFxuICovXG5mdW5jdGlvbiBkYXRlVG9Gb3JtYXR0ZWRTdHJpbmcoZGF0ZSwgZm9ybWF0KSB7XG4gICAgaWYgKGZvcm1hdCA9PT0gdm9pZCAwKSB7IGZvcm1hdCA9ICdZWVlZLU1NLUREJzsgfVxuICAgIHZhciBmdWxsWWVhciA9IHBhZFN0YXJ0V2lkdGhaZXJvcyhkYXRlLmdldEZ1bGxZZWFyKCksIDQpO1xuICAgIHZhciBtb250aHMgPSBbXG4gICAgICAgICdKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgJ0p1bHknLCAnQXVndXN0JywgJ1NlcHRlbWJlcicsICdPY3RvYmVyJywgJ05vdmVtYmVyJywgJ0RlY2VtYmVyJyxcbiAgICBdO1xuICAgIHZhciBkYXlzID0gW1xuICAgICAgICAnU3VuZGF5JywgJ01vbmRheScsICdUdWVzZGF5JywgJ1dlZG5lc2RheScsICdUaHVyc2RheScsICdGcmlkYXknLCAnU2F0dXJkYXknLFxuICAgIF07XG4gICAgdmFyIHJlcGxhY2UgPSB7XG4gICAgICAgIFlZWVk6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGZ1bGxZZWFyLnNsaWNlKGZ1bGxZZWFyLmxlbmd0aCAtIDQsIGZ1bGxZZWFyLmxlbmd0aCk7IH0sXG4gICAgICAgIFlZOiBmdW5jdGlvbiAoKSB7IHJldHVybiBmdWxsWWVhci5zbGljZShmdWxsWWVhci5sZW5ndGggLSAyLCBmdWxsWWVhci5sZW5ndGgpOyB9LFxuICAgICAgICBZOiBmdW5jdGlvbiAoKSB7IHJldHVybiBcIlwiICsgZGF0ZS5nZXRGdWxsWWVhcigpOyB9LFxuICAgICAgICBNTU1NOiBmdW5jdGlvbiAoKSB7IHJldHVybiBtb250aHNbZGF0ZS5nZXRNb250aCgpXTsgfSxcbiAgICAgICAgTU1NOiBmdW5jdGlvbiAoKSB7IHJldHVybiBtb250aHNbZGF0ZS5nZXRNb250aCgpXS5zbGljZSgwLCAzKTsgfSxcbiAgICAgICAgTU06IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHBhZFN0YXJ0V2lkdGhaZXJvcyhkYXRlLmdldE1vbnRoKCkgKyAxLCAyKTsgfSxcbiAgICAgICAgTW86IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFwiXCIgKyAoZGF0ZS5nZXRNb250aCgpICsgMSkgKyBjYWxjdWxhdGVPcmRpbmFsKGRhdGUuZ2V0TW9udGgoKSArIDEpOyB9LFxuICAgICAgICBNOiBmdW5jdGlvbiAoKSB7IHJldHVybiBcIlwiICsgKGRhdGUuZ2V0TW9udGgoKSArIDEpOyB9LFxuICAgICAgICBEbzogZnVuY3Rpb24gKCkgeyByZXR1cm4gXCJcIiArIGRhdGUuZ2V0RGF0ZSgpICsgY2FsY3VsYXRlT3JkaW5hbChkYXRlLmdldERhdGUoKSk7IH0sXG4gICAgICAgIEREOiBmdW5jdGlvbiAoKSB7IHJldHVybiBwYWRTdGFydFdpZHRoWmVyb3MoZGF0ZS5nZXREYXRlKCksIDIpOyB9LFxuICAgICAgICBEOiBmdW5jdGlvbiAoKSB7IHJldHVybiBcIlwiICsgZGF0ZS5nZXREYXRlKCk7IH0sXG4gICAgICAgIGRkZGQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGRheXNbZGF0ZS5nZXREYXkoKV07IH0sXG4gICAgICAgIGRkZDogZnVuY3Rpb24gKCkgeyByZXR1cm4gZGF5c1tkYXRlLmdldERheSgpXS5zbGljZSgwLCAzKTsgfSxcbiAgICAgICAgZGQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGRheXNbZGF0ZS5nZXREYXkoKV0uc2xpY2UoMCwgMik7IH0sXG4gICAgICAgIGRvOiBmdW5jdGlvbiAoKSB7IHJldHVybiBcIlwiICsgZGF0ZS5nZXREYXkoKSArIGNhbGN1bGF0ZU9yZGluYWwoZGF0ZS5nZXREYXkoKSk7IH0sXG4gICAgICAgIGQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFwiXCIgKyBkYXRlLmdldERheSgpOyB9LFxuICAgIH07XG4gICAgdmFyIHJlZ2V4cCA9IG5ldyBSZWdFeHAoT2JqZWN0LmtleXMocmVwbGFjZSkuam9pbignfCcpLCAnZycpO1xuICAgIHJldHVybiBmb3JtYXQucmVwbGFjZShyZWdleHAsIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICBpZiAobWF0Y2ggaW4gcmVwbGFjZSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VbbWF0Y2hdKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH0pO1xufVxuLyoqXG4gKiBQYXJzZXMgYSBkYXRlIGFuZCB0aW1lIGZyb20gYSBzdHJpbmcgaW4gdGhlIGZvcm1hdCBgeXl5eS1NTS1kZCBISDptbTpzc2BcbiAqL1xuZnVuY3Rpb24gcGFyc2VEYXRlVGltZUZyb21TdHJpbmcodmFsdWUpIHtcbiAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB2YXIgX2EgPSBfX3JlYWQkaih2YWx1ZS5zcGxpdCgnICcpLCAyKSwgZGF0ZVN0ciA9IF9hWzBdLCB0aW1lU3RyID0gX2FbMV07XG4gICAgaWYgKCFkYXRlU3RyKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB2YXIgZmllbGRzID0gZGF0ZVN0ci5zcGxpdCgnLScpLm1hcChmdW5jdGlvbiAoZikgeyByZXR1cm4gcGFyc2VJbnQoZiwgMTApOyB9KTtcbiAgICBpZiAoZmllbGRzLmZpbHRlcihmdW5jdGlvbiAoZikgeyByZXR1cm4gIWlzTmFOKGYpOyB9KS5sZW5ndGggIT09IDMpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciBfYiA9IF9fcmVhZCRqKGZpZWxkcywgMyksIHllYXIgPSBfYlswXSwgbW9udGggPSBfYlsxXSwgZGF5ID0gX2JbMl07XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZSh5ZWFyLCBtb250aCAtIDEsIGRheSk7XG4gICAgaWYgKGRhdGUuZ2V0RnVsbFllYXIoKSAhPT0geWVhciB8fFxuICAgICAgICBkYXRlLmdldE1vbnRoKCkgIT09IG1vbnRoIC0gMSB8fFxuICAgICAgICBkYXRlLmdldERhdGUoKSAhPT0gZGF5KSB7XG4gICAgICAgIC8vIGRhdGUgd2FzIG5vdCBwYXJzZWQgYXMgZXhwZWN0ZWQgc28gbXVzdCBoYXZlIGJlZW4gaW52YWxpZFxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgaWYgKCF0aW1lU3RyIHx8IHRpbWVTdHIgPT09ICcwMDowMDowMCcpIHtcbiAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuICAgIHZhciBfYyA9IF9fcmVhZCRqKHRpbWVTdHIuc3BsaXQoJzonKS5tYXAoZnVuY3Rpb24gKHBhcnQpIHsgcmV0dXJuIHBhcnNlSW50KHBhcnQsIDEwKTsgfSksIDMpLCBob3VycyA9IF9jWzBdLCBtaW51dGVzID0gX2NbMV0sIHNlY29uZHMgPSBfY1syXTtcbiAgICBpZiAoaG91cnMgPj0gMCAmJiBob3VycyA8IDI0KSB7XG4gICAgICAgIGRhdGUuc2V0SG91cnMoaG91cnMpO1xuICAgIH1cbiAgICBpZiAobWludXRlcyA+PSAwICYmIG1pbnV0ZXMgPCA2MCkge1xuICAgICAgICBkYXRlLnNldE1pbnV0ZXMobWludXRlcyk7XG4gICAgfVxuICAgIGlmIChzZWNvbmRzID49IDAgJiYgc2Vjb25kcyA8IDYwKSB7XG4gICAgICAgIGRhdGUuc2V0U2Vjb25kcyhzZWNvbmRzKTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGU7XG59XG5cbnZhciBEYXRlVXRpbHMgPSAvKiNfX1BVUkVfXyovT2JqZWN0LmZyZWV6ZSh7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIHNlcmlhbGlzZURhdGU6IHNlcmlhbGlzZURhdGUsXG4gICAgZGF0ZVRvRm9ybWF0dGVkU3RyaW5nOiBkYXRlVG9Gb3JtYXR0ZWRTdHJpbmcsXG4gICAgcGFyc2VEYXRlVGltZUZyb21TdHJpbmc6IHBhcnNlRGF0ZVRpbWVGcm9tU3RyaW5nXG59KTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuLy9cbi8vIElNUE9SVEFOVCBOT1RFIVxuLy9cbi8vIElmIHlvdSBjaGFuZ2UgdGhlIGxpc3QgYmVsb3csIGNvcHkvcGFzdGUgdGhlIG5ldyBjb250ZW50IGludG8gdGhlIGRvY3MgcGFnZSBqYXZhc2NyaXB0LWdyaWQtaWNvbnNcbi8vXG52YXIgaWNvbk5hbWVDbGFzc01hcCA9IHtcbiAgICAvLyBoZWFkZXIgY29sdW1uIGdyb3VwIHNob3duIHdoZW4gZXhwYW5kZWQgKGNsaWNrIHRvIGNvbnRyYWN0KVxuICAgIGNvbHVtbkdyb3VwT3BlbmVkOiAnZXhwYW5kZWQnLFxuICAgIC8vIGhlYWRlciBjb2x1bW4gZ3JvdXAgc2hvd24gd2hlbiBjb250cmFjdGVkIChjbGljayB0byBleHBhbmQpXG4gICAgY29sdW1uR3JvdXBDbG9zZWQ6ICdjb250cmFjdGVkJyxcbiAgICAvLyB0b29sIHBhbmVsIGNvbHVtbiBncm91cCBjb250cmFjdGVkIChjbGljayB0byBleHBhbmQpXG4gICAgY29sdW1uU2VsZWN0Q2xvc2VkOiAndHJlZS1jbG9zZWQnLFxuICAgIC8vIHRvb2wgcGFuZWwgY29sdW1uIGdyb3VwIGV4cGFuZGVkIChjbGljayB0byBjb250cmFjdClcbiAgICBjb2x1bW5TZWxlY3RPcGVuOiAndHJlZS1vcGVuJyxcbiAgICAvLyBjb2x1bW4gdG9vbCBwYW5lbCBoZWFkZXIgZXhwYW5kL2NvbGxhcHNlIGFsbCBidXR0b24sIHNob3duIHdoZW4gc29tZSBjaGlsZHJlbiBhcmUgZXhwYW5kZWQgYW5kXG4gICAgLy8gICAgIG90aGVycyBhcmUgY29sbGFwc2VkXG4gICAgY29sdW1uU2VsZWN0SW5kZXRlcm1pbmF0ZTogJ3RyZWUtaW5kZXRlcm1pbmF0ZScsXG4gICAgLy8gc2hvd24gb24gZ2hvc3QgaWNvbiB3aGlsZSBkcmFnZ2luZyBjb2x1bW4gdG8gdGhlIHNpZGUgb2YgdGhlIGdyaWQgdG8gcGluXG4gICAgY29sdW1uTW92ZVBpbjogJ3BpbicsXG4gICAgLy8gc2hvd24gb24gZ2hvc3QgaWNvbiB3aGlsZSBkcmFnZ2luZyBvdmVyIHBhcnQgb2YgdGhlIHBhZ2UgdGhhdCBpcyBub3QgYSBkcm9wIHpvbmVcbiAgICBjb2x1bW5Nb3ZlSGlkZTogJ2V5ZS1zbGFzaCcsXG4gICAgLy8gc2hvd24gb24gZ2hvc3QgaWNvbiB3aGlsZSBkcmFnZ2luZyBjb2x1bW5zIHRvIHJlb3JkZXJcbiAgICBjb2x1bW5Nb3ZlTW92ZTogJ2Fycm93cycsXG4gICAgLy8gYW5pbWF0aW5nIGljb24gc2hvd24gd2hlbiBkcmFnZ2luZyBhIGNvbHVtbiB0byB0aGUgcmlnaHQgb2YgdGhlIGdyaWQgY2F1c2VzIGhvcml6b250YWwgc2Nyb2xsaW5nXG4gICAgY29sdW1uTW92ZUxlZnQ6ICdsZWZ0JyxcbiAgICAvLyBhbmltYXRpbmcgaWNvbiBzaG93biB3aGVuIGRyYWdnaW5nIGEgY29sdW1uIHRvIHRoZSBsZWZ0IG9mIHRoZSBncmlkIGNhdXNlcyBob3Jpem9udGFsIHNjcm9sbGluZ1xuICAgIGNvbHVtbk1vdmVSaWdodDogJ3JpZ2h0JyxcbiAgICAvLyBzaG93biBvbiBnaG9zdCBpY29uIHdoaWxlIGRyYWdnaW5nIG92ZXIgUm93IEdyb3VwcyBkcm9wIHpvbmVcbiAgICBjb2x1bW5Nb3ZlR3JvdXA6ICdncm91cCcsXG4gICAgLy8gc2hvd24gb24gZ2hvc3QgaWNvbiB3aGlsZSBkcmFnZ2luZyBvdmVyIFZhbHVlcyBkcm9wIHpvbmVcbiAgICBjb2x1bW5Nb3ZlVmFsdWU6ICdhZ2dyZWdhdGlvbicsXG4gICAgLy8gc2hvd24gb24gZ2hvc3QgaWNvbiB3aGlsZSBkcmFnZ2luZyBvdmVyIHBpdm90IGRyb3Agem9uZVxuICAgIGNvbHVtbk1vdmVQaXZvdDogJ3Bpdm90JyxcbiAgICAvLyBzaG93biBvbiBnaG9zdCBpY29uIHdoaWxlIGRyYWdnaW5nIG92ZXIgZHJvcCB6b25lIHRoYXQgZG9lc24ndCBzdXBwb3J0IGl0LCBlLmcuXG4gICAgLy8gICAgIHN0cmluZyBjb2x1bW4gb3ZlciBhZ2dyZWdhdGlvbiBkcm9wIHpvbmVcbiAgICBkcm9wTm90QWxsb3dlZDogJ25vdC1hbGxvd2VkJyxcbiAgICAvLyBzaG93biBvbiByb3cgZ3JvdXAgd2hlbiBjb250cmFjdGVkIChjbGljayB0byBleHBhbmQpXG4gICAgZ3JvdXBDb250cmFjdGVkOiAndHJlZS1jbG9zZWQnLFxuICAgIC8vIHNob3duIG9uIHJvdyBncm91cCB3aGVuIGV4cGFuZGVkIChjbGljayB0byBjb250cmFjdClcbiAgICBncm91cEV4cGFuZGVkOiAndHJlZS1vcGVuJyxcbiAgICAvLyBjb250ZXh0IG1lbnUgY2hhcnQgaXRlbVxuICAgIGNoYXJ0OiAnY2hhcnQnLFxuICAgIC8vIGNoYXJ0IHdpbmRvdyB0aXRsZSBiYXJcbiAgICBjbG9zZTogJ2Nyb3NzJyxcbiAgICAvLyBYIChyZW1vdmUpIG9uIGNvbHVtbiAncGlsbCcgYWZ0ZXIgYWRkaW5nIGl0IHRvIGEgZHJvcCB6b25lIGxpc3RcbiAgICBjYW5jZWw6ICdjYW5jZWwnLFxuICAgIC8vIGluZGljYXRlcyB0aGUgY3VycmVudGx5IGFjdGl2ZSBwaW4gc3RhdGUgaW4gdGhlIFwiUGluIGNvbHVtblwiIHN1Yi1tZW51IG9mIHRoZSBjb2x1bW4gbWVudVxuICAgIGNoZWNrOiAndGljaycsXG4gICAgLy8gXCJnbyB0byBmaXJzdFwiIGJ1dHRvbiBpbiBwYWdpbmF0aW9uIGNvbnRyb2xzXG4gICAgZmlyc3Q6ICdmaXJzdCcsXG4gICAgLy8gXCJnbyB0byBwcmV2aW91c1wiIGJ1dHRvbiBpbiBwYWdpbmF0aW9uIGNvbnRyb2xzXG4gICAgcHJldmlvdXM6ICdwcmV2aW91cycsXG4gICAgLy8gXCJnbyB0byBuZXh0XCIgYnV0dG9uIGluIHBhZ2luYXRpb24gY29udHJvbHNcbiAgICBuZXh0OiAnbmV4dCcsXG4gICAgLy8gXCJnbyB0byBsYXN0XCIgYnV0dG9uIGluIHBhZ2luYXRpb24gY29udHJvbHNcbiAgICBsYXN0OiAnbGFzdCcsXG4gICAgLy8gc2hvd24gb24gdG9wIHJpZ2h0IG9mIGNoYXJ0IHdoZW4gY2hhcnQgaXMgbGlua2VkIHRvIHJhbmdlIGRhdGEgKGNsaWNrIHRvIHVubGluaylcbiAgICBsaW5rZWQ6ICdsaW5rZWQnLFxuICAgIC8vIHNob3duIG9uIHRvcCByaWdodCBvZiBjaGFydCB3aGVuIGNoYXJ0IGlzIG5vdCBsaW5rZWQgdG8gcmFuZ2UgZGF0YSAoY2xpY2sgdG8gbGluaylcbiAgICB1bmxpbmtlZDogJ3VubGlua2VkJyxcbiAgICAvLyBcIkNob29zZSBjb2xvdXJcIiBidXR0b24gb24gY2hhcnQgc2V0dGluZ3MgdGFiXG4gICAgY29sb3JQaWNrZXI6ICdjb2xvci1waWNrZXInLFxuICAgIC8vIHJvdGF0aW5nIHNwaW5uZXIgc2hvd24gYnkgdGhlIGxvYWRpbmcgY2VsbCByZW5kZXJlclxuICAgIGdyb3VwTG9hZGluZzogJ2xvYWRpbmcnLFxuICAgIC8vIGJ1dHRvbiB0byBsYXVuY2ggZW50ZXJwcmlzZSBjb2x1bW4gbWVudVxuICAgIG1lbnU6ICdtZW51JyxcbiAgICAvLyBmaWx0ZXIgdG9vbCBwYW5lbCB0YWJcbiAgICBmaWx0ZXI6ICdmaWx0ZXInLFxuICAgIC8vIGNvbHVtbiB0b29sIHBhbmVsIHRhYlxuICAgIGNvbHVtbnM6ICdjb2x1bW5zJyxcbiAgICAvLyBidXR0b24gaW4gY2hhcnQgcmVndWxhciBzaXplIHdpbmRvdyB0aXRsZSBiYXIgKGNsaWNrIHRvIG1heGltaXNlKVxuICAgIG1heGltaXplOiAnbWF4aW1pemUnLFxuICAgIC8vIGJ1dHRvbiBpbiBjaGFydCBtYXhpbWlzZWQgd2luZG93IHRpdGxlIGJhciAoY2xpY2sgdG8gbWFrZSByZWd1bGFyIHNpemUpXG4gICAgbWluaW1pemU6ICdtaW5pbWl6ZScsXG4gICAgLy8gXCJQaW4gY29sdW1uXCIgaXRlbSBpbiBjb2x1bW4gaGVhZGVyIG1lbnVcbiAgICBtZW51UGluOiAncGluJyxcbiAgICAvLyBcIlZhbHVlIGFnZ3JlZ2F0aW9uXCIgY29sdW1uIG1lbnUgaXRlbSAoc2hvd24gb24gbnVtZXJpYyBjb2x1bW5zIHdoZW4gZ3JvdXBpbmcgaXMgYWN0aXZlKVwiXG4gICAgbWVudVZhbHVlOiAnYWdncmVnYXRpb24nLFxuICAgIC8vIFwiR3JvdXAgYnkge2NvbHVtbi1uYW1lfVwiIGl0ZW0gaW4gY29sdW1uIGhlYWRlciBtZW51XG4gICAgbWVudUFkZFJvd0dyb3VwOiAnZ3JvdXAnLFxuICAgIC8vIFwiVW4tR3JvdXAgYnkge2NvbHVtbi1uYW1lfVwiIGl0ZW0gaW4gY29sdW1uIGhlYWRlciBtZW51XG4gICAgbWVudVJlbW92ZVJvd0dyb3VwOiAnZ3JvdXAnLFxuICAgIC8vIGNvbnRleHQgbWVudSBjb3B5IGl0ZW1cbiAgICBjbGlwYm9hcmRDb3B5OiAnY29weScsXG4gICAgLy8gY29udGV4dCBtZW51IHBhc3RlIGl0ZW1cbiAgICBjbGlwYm9hcmRQYXN0ZTogJ3Bhc3RlJyxcbiAgICAvLyBpZGVudGlmaWVzIHRoZSBwaXZvdCBkcm9wIHpvbmVcbiAgICBwaXZvdFBhbmVsOiAncGl2b3QnLFxuICAgIC8vIFwiUm93IGdyb3Vwc1wiIGRyb3Agem9uZSBpbiBjb2x1bW4gdG9vbCBwYW5lbFxuICAgIHJvd0dyb3VwUGFuZWw6ICdncm91cCcsXG4gICAgLy8gY29sdW1ucyB0b29sIHBhbmVsIFZhbHVlcyBkcm9wIHpvbmVcbiAgICB2YWx1ZVBhbmVsOiAnYWdncmVnYXRpb24nLFxuICAgIC8vIGRyYWcgaGFuZGxlIHVzZWQgdG8gcGljayB1cCBkcmFnZ2FibGUgY29sdW1uc1xuICAgIGNvbHVtbkRyYWc6ICdncmlwJyxcbiAgICAvLyBkcmFnIGhhbmRsZSB1c2VkIHRvIHBpY2sgdXAgZHJhZ2dhYmxlIHJvd3NcbiAgICByb3dEcmFnOiAnZ3JpcCcsXG4gICAgLy8gY29udGV4dCBtZW51IGV4cG9ydCBpdGVtXG4gICAgc2F2ZTogJ3NhdmUnLFxuICAgIC8vIGNzdiBleHBvcnRcbiAgICBjc3ZFeHBvcnQ6ICdjc3YnLFxuICAgIC8vIGV4Y2VsIGV4cG9ydCxcbiAgICBleGNlbEV4cG9ydDogJ2V4Y2VsJyxcbiAgICAvLyBpY29uIG9uIGRyb3Bkb3duIGVkaXRvcnNcbiAgICBzbWFsbERvd246ICdzbWFsbC1kb3duJyxcbiAgICAvLyB2ZXJzaW9uIG9mIHNtYWxsLXJpZ2h0IHVzZWQgaW4gUlRMIG1vZGVcbiAgICBzbWFsbExlZnQ6ICdzbWFsbC1sZWZ0JyxcbiAgICAvLyBzZXBhcmF0ZXIgYmV0d2VlbiBjb2x1bW4gJ3BpbGxzJyB3aGVuIHlvdSBhZGQgbXVsdGlwbGUgY29sdW1ucyB0byB0aGUgaGVhZGVyIGRyb3Agem9uZVxuICAgIHNtYWxsUmlnaHQ6ICdzbWFsbC1yaWdodCcsXG4gICAgc21hbGxVcDogJ3NtYWxsLXVwJyxcbiAgICAvLyBzaG93IG9uIGNvbHVtbiBoZWFkZXIgd2hlbiBjb2x1bW4gaXMgc29ydGVkIGFzY2VuZGluZ1xuICAgIHNvcnRBc2NlbmRpbmc6ICdhc2MnLFxuICAgIC8vIHNob3cgb24gY29sdW1uIGhlYWRlciB3aGVuIGNvbHVtbiBpcyBzb3J0ZWQgZGVzY2VuZGluZ1xuICAgIHNvcnREZXNjZW5kaW5nOiAnZGVzYycsXG4gICAgLy8gc2hvdyBvbiBjb2x1bW4gaGVhZGVyIHdoZW4gY29sdW1uIGhhcyBubyBzb3J0LCBvbmx5IHdoZW4gZW5hYmxlZCB3aXRoIGdyaWRPcHRpb25zLnVuU29ydEljb249dHJ1ZVxuICAgIHNvcnRVblNvcnQ6ICdub25lJ1xufTtcbi8qKlxuICogSWYgaWNvbiBwcm92aWRlZCwgdXNlIHRoaXMgKGVpdGhlciBhIHN0cmluZywgb3IgYSBmdW5jdGlvbiBjYWxsYmFjaykuXG4gKiBpZiBub3QsIHRoZW4gdXNlIHRoZSBkZWZhdWx0IGljb24gZnJvbSB0aGUgdGhlbWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBpY29uTmFtZVxuICogQHBhcmFtIHtHcmlkT3B0aW9uc1dyYXBwZXJ9IGdyaWRPcHRpb25zV3JhcHBlclxuICogQHBhcmFtIHtDb2x1bW4gfCBudWxsfSBbY29sdW1uXVxuICogQHJldHVybnMge0hUTUxFbGVtZW50fVxuICovXG5mdW5jdGlvbiBjcmVhdGVJY29uKGljb25OYW1lLCBncmlkT3B0aW9uc1dyYXBwZXIsIGNvbHVtbikge1xuICAgIHZhciBpY29uQ29udGVudHMgPSBjcmVhdGVJY29uTm9TcGFuKGljb25OYW1lLCBncmlkT3B0aW9uc1dyYXBwZXIsIGNvbHVtbik7XG4gICAgaWYgKGljb25Db250ZW50cyAmJiBpY29uQ29udGVudHMuY2xhc3NOYW1lLmluZGV4T2YoJ2FnLWljb24nKSA+IC0xKSB7XG4gICAgICAgIHJldHVybiBpY29uQ29udGVudHM7XG4gICAgfVxuICAgIHZhciBlUmVzdWx0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgIGVSZXN1bHQuYXBwZW5kQ2hpbGQoaWNvbkNvbnRlbnRzKTtcbiAgICByZXR1cm4gZVJlc3VsdDtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUljb25Ob1NwYW4oaWNvbk5hbWUsIGdyaWRPcHRpb25zV3JhcHBlciwgY29sdW1uLCBmb3JjZUNyZWF0ZSkge1xuICAgIHZhciB1c2VyUHJvdmlkZWRJY29uID0gbnVsbDtcbiAgICAvLyBjaGVjayBjb2wgZm9yIGljb24gZmlyc3RcbiAgICB2YXIgaWNvbnMgPSBjb2x1bW4gJiYgY29sdW1uLmdldENvbERlZigpLmljb25zO1xuICAgIGlmIChpY29ucykge1xuICAgICAgICB1c2VyUHJvdmlkZWRJY29uID0gaWNvbnNbaWNvbk5hbWVdO1xuICAgIH1cbiAgICAvLyBpZiBub3QgaW4gY29sLCB0cnkgZ3JpZCBvcHRpb25zXG4gICAgaWYgKGdyaWRPcHRpb25zV3JhcHBlciAmJiAhdXNlclByb3ZpZGVkSWNvbikge1xuICAgICAgICB2YXIgb3B0aW9uc0ljb25zID0gZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEljb25zKCk7XG4gICAgICAgIGlmIChvcHRpb25zSWNvbnMpIHtcbiAgICAgICAgICAgIHVzZXJQcm92aWRlZEljb24gPSBvcHRpb25zSWNvbnNbaWNvbk5hbWVdO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIG5vdyBpZiB1c2VyIHByb3ZpZGVkLCB1c2UgaXRcbiAgICBpZiAodXNlclByb3ZpZGVkSWNvbikge1xuICAgICAgICB2YXIgcmVuZGVyZXJSZXN1bHQgPSB2b2lkIDA7XG4gICAgICAgIGlmICh0eXBlb2YgdXNlclByb3ZpZGVkSWNvbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmVuZGVyZXJSZXN1bHQgPSB1c2VyUHJvdmlkZWRJY29uKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHVzZXJQcm92aWRlZEljb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZW5kZXJlclJlc3VsdCA9IHVzZXJQcm92aWRlZEljb247XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ljb24gZnJvbSBncmlkIG9wdGlvbnMgbmVlZHMgdG8gYmUgYSBzdHJpbmcgb3IgYSBmdW5jdGlvbicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcmVuZGVyZXJSZXN1bHQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9hZFRlbXBsYXRlKHJlbmRlcmVyUmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOb2RlT3JFbGVtZW50KHJlbmRlcmVyUmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVyUmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogaWNvblJlbmRlcmVyIHNob3VsZCByZXR1cm4gYmFjayBhIHN0cmluZyBvciBhIGRvbSBvYmplY3QnKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBzcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgICAgICB2YXIgY3NzQ2xhc3MgPSBpY29uTmFtZUNsYXNzTWFwW2ljb25OYW1lXTtcbiAgICAgICAgaWYgKCFjc3NDbGFzcykge1xuICAgICAgICAgICAgaWYgKCFmb3JjZUNyZWF0ZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IERpZCBub3QgZmluZCBpY29uIFwiICsgaWNvbk5hbWUpO1xuICAgICAgICAgICAgICAgIGNzc0NsYXNzID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjc3NDbGFzcyA9IGljb25OYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNwYW4uc2V0QXR0cmlidXRlKCdjbGFzcycsIFwiYWctaWNvbiBhZy1pY29uLVwiICsgY3NzQ2xhc3MpO1xuICAgICAgICBzcGFuLnNldEF0dHJpYnV0ZSgndW5zZWxlY3RhYmxlJywgJ29uJyk7XG4gICAgICAgIHNldEFyaWFSb2xlKHNwYW4sICdwcmVzZW50YXRpb24nKTtcbiAgICAgICAgcmV0dXJuIHNwYW47XG4gICAgfVxufVxuXG52YXIgSWNvblV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBpY29uTmFtZUNsYXNzTWFwOiBpY29uTmFtZUNsYXNzTWFwLFxuICAgIGNyZWF0ZUljb246IGNyZWF0ZUljb24sXG4gICAgY3JlYXRlSWNvbk5vU3BhbjogY3JlYXRlSWNvbk5vU3BhblxufSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBLZXlDb2RlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEtleUNvZGUoKSB7XG4gICAgfVxuICAgIEtleUNvZGUuQkFDS1NQQUNFID0gJ0JhY2tzcGFjZSc7XG4gICAgS2V5Q29kZS5UQUIgPSAnVGFiJztcbiAgICBLZXlDb2RlLkVOVEVSID0gJ0VudGVyJztcbiAgICBLZXlDb2RlLkVTQ0FQRSA9ICdFc2NhcGUnO1xuICAgIEtleUNvZGUuU1BBQ0UgPSAnICc7XG4gICAgS2V5Q29kZS5MRUZUID0gJ0Fycm93TGVmdCc7XG4gICAgS2V5Q29kZS5VUCA9ICdBcnJvd1VwJztcbiAgICBLZXlDb2RlLlJJR0hUID0gJ0Fycm93UmlnaHQnO1xuICAgIEtleUNvZGUuRE9XTiA9ICdBcnJvd0Rvd24nO1xuICAgIEtleUNvZGUuREVMRVRFID0gJ0RlbGV0ZSc7XG4gICAgS2V5Q29kZS5GMiA9ICdGMic7XG4gICAgS2V5Q29kZS5QQUdFX1VQID0gJ1BhZ2VVcCc7XG4gICAgS2V5Q29kZS5QQUdFX0RPV04gPSAnUGFnZURvd24nO1xuICAgIEtleUNvZGUuUEFHRV9IT01FID0gJ0hvbWUnO1xuICAgIEtleUNvZGUuUEFHRV9FTkQgPSAnRW5kJztcbiAgICAvLyB0aGVzZSBzaG91bGQgYmUgdXNlZCB3aXRoIGBldmVudC5jb2RlYCBpbnN0ZWFkIG9mIGBldmVudC5rZXlgXG4gICAgLy8gYXMgYGV2ZW50LmtleWAgY2hhbmdlcyB3aGVuIG5vbi1sYXRpbiBrZXlib2FyZHMgYXJlIHVzZWRcbiAgICBLZXlDb2RlLkEgPSAnS2V5QSc7XG4gICAgS2V5Q29kZS5DID0gJ0tleUMnO1xuICAgIEtleUNvZGUuViA9ICdLZXlWJztcbiAgICBLZXlDb2RlLkQgPSAnS2V5RCc7XG4gICAgS2V5Q29kZS5aID0gJ0tleVonO1xuICAgIEtleUNvZGUuWSA9ICdLZXlZJztcbiAgICByZXR1cm4gS2V5Q29kZTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBOVU1QQURfREVMX05VTUxPQ0tfT05fS0VZID0gJ0RlbCc7XG4vLyBVc2luZyBsZWdhY3kgdmFsdWVzIHRvIG1hdGNoIEFaRVJUWSBrZXlib2FyZHNcbnZhciBOVU1QQURfREVMX05VTUxPQ0tfT05fS0VZQ09ERSA9IDQ2O1xudmFyIEFfS0VZQ09ERSA9IDY1O1xudmFyIENfS0VZQ09ERSA9IDY3O1xudmFyIFZfS0VZQ09ERSA9IDg2O1xudmFyIERfS0VZQ09ERSA9IDY4O1xudmFyIFpfS0VZQ09ERSA9IDkwO1xudmFyIFlfS0VZQ09ERSA9IDg5O1xuZnVuY3Rpb24gaXNFdmVudEZyb21QcmludGFibGVDaGFyYWN0ZXIoZXZlbnQpIHtcbiAgICAvLyBubyBhbGxvd2VkIHByaW50YWJsZSBjaGFycyBoYXZlIGFsdCBvciBjdHJsIGtleSBjb21iaW5hdGlvbnNcbiAgICBpZiAoZXZlbnQuYWx0S2V5IHx8IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIGlmIGtleSBpcyBsZW5ndGggMSwgZWcgaWYgaXQgaXMgJ2EnIGZvciB0aGUgYSBrZXksIG9yICcyJyBmb3IgdGhlICcyJyBrZXkuXG4gICAgLy8gbm9uLXByaW50YWJsZSBjaGFyYWN0ZXJzIGhhdmUgbmFtZXMsIGVnICdFbnRlcicgb3IgJ0JhY2tzcGFjZScuXG4gICAgdmFyIHByaW50YWJsZUNoYXJhY3RlciA9IGV2ZW50LmtleS5sZW5ndGggPT09IDE7XG4gICAgLy8gSUUxMSAmIEVkZ2UgdHJlYXQgdGhlIG51bXBhZCBkZWwga2V5IGRpZmZlcmVudGx5IC0gd2l0aCBudW1sb2NrIG9uIHdlIGdldCBcIkRlbFwiIGZvciBrZXksXG4gICAgLy8gc28gdGhpcyBhZGRpdGlvbiBjaGVja3MgaWYgaXRzIElFMTEvRWRnZSBhbmQgaGFuZGxlcyB0aGF0IHNwZWNpZmljIGNhc2UgdGhlIHNhbWUgd2FzIGFzIGFsbCBvdGhlciBicm93c2Vyc1xuICAgIHZhciBudW1wYWREZWxXaXRoTnVtbG9ja09uRm9yRWRnZU9ySWUgPSBpc051bXBhZERlbFdpdGhOdW1Mb2NrT25Gb3JFZGdlKGV2ZW50KTtcbiAgICByZXR1cm4gcHJpbnRhYmxlQ2hhcmFjdGVyIHx8IG51bXBhZERlbFdpdGhOdW1sb2NrT25Gb3JFZGdlT3JJZTtcbn1cbi8qKlxuICogQWxsb3dzIHVzZXIgdG8gdGVsbCB0aGUgZ3JpZCB0byBza2lwIHNwZWNpZmljIGtleWJvYXJkIGV2ZW50c1xuICogQHBhcmFtIHtHcmlkT3B0aW9uc1dyYXBwZXJ9IGdyaWRPcHRpb25zV3JhcHBlclxuICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBrZXlib2FyZEV2ZW50XG4gKiBAcGFyYW0ge1Jvd05vZGV9IHJvd05vZGVcbiAqIEBwYXJhbSB7Q29sdW1ufSBjb2x1bW5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZWRpdGluZ1xuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzVXNlclN1cHByZXNzaW5nS2V5Ym9hcmRFdmVudChncmlkT3B0aW9uc1dyYXBwZXIsIGtleWJvYXJkRXZlbnQsIHJvd05vZGUsIGNvbHVtbiwgZWRpdGluZykge1xuICAgIHZhciBncmlkT3B0aW9uc0Z1bmMgPSBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0U3VwcHJlc3NLZXlib2FyZEV2ZW50RnVuYygpO1xuICAgIHZhciBjb2xEZWZGdW5jID0gY29sdW1uID8gY29sdW1uLmdldENvbERlZigpLnN1cHByZXNzS2V5Ym9hcmRFdmVudCA6IHVuZGVmaW5lZDtcbiAgICAvLyBpZiBubyBjYWxsYmFja3MgcHJvdmlkZWQgYnkgdXNlciwgdGhlbiBkbyBub3RoaW5nXG4gICAgaWYgKCFncmlkT3B0aW9uc0Z1bmMgJiYgIWNvbERlZkZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBldmVudDoga2V5Ym9hcmRFdmVudCxcbiAgICAgICAgZWRpdGluZzogZWRpdGluZyxcbiAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgIGFwaTogZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICBub2RlOiByb3dOb2RlLFxuICAgICAgICBkYXRhOiByb3dOb2RlLmRhdGEsXG4gICAgICAgIGNvbERlZjogY29sdW1uLmdldENvbERlZigpLFxuICAgICAgICBjb250ZXh0OiBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICBjb2x1bW5BcGk6IGdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKVxuICAgIH07XG4gICAgLy8gY29sRGVmIGdldCBmaXJzdCBwcmVmZXJlbmNlIG9uIHN1cHByZXNzaW5nIGV2ZW50c1xuICAgIGlmIChjb2xEZWZGdW5jKSB7XG4gICAgICAgIHZhciBjb2xEZWZGdW5jUmVzdWx0ID0gY29sRGVmRnVuYyhwYXJhbXMpO1xuICAgICAgICAvLyBpZiBjb2xEZWYgZnVuYyBzdXBwcmVzc2VkLCB0aGVuIHJldHVybiBub3csIG5vIG5lZWQgdG8gY2FsbCBncmlkT3B0aW9uIGZ1bmNcbiAgICAgICAgaWYgKGNvbERlZkZ1bmNSZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChncmlkT3B0aW9uc0Z1bmMpIHtcbiAgICAgICAgLy8gaWYgZ3JpZE9wdGlvbiBmdW5jLCByZXR1cm4gdGhlIHJlc3VsdFxuICAgICAgICByZXR1cm4gZ3JpZE9wdGlvbnNGdW5jKHBhcmFtcyk7XG4gICAgfVxuICAgIC8vIG90aGVyd2lzZSByZXR1cm4gZmFsc2UsIGRvbid0IHN1cHByZXNzLCBhcyBjb2xEZWYgZGlkbid0IHN1cHByZXNzIGFuZCBubyBmdW5jIG9uIGdyaWRPcHRpb25zXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gaXNVc2VyU3VwcHJlc3NpbmdIZWFkZXJLZXlib2FyZEV2ZW50KGdyaWRPcHRpb25zV3JhcHBlciwga2V5Ym9hcmRFdmVudCwgaGVhZGVyUm93SW5kZXgsIGNvbHVtbikge1xuICAgIHZhciBjb2xEZWYgPSBjb2x1bW4uZ2V0RGVmaW5pdGlvbigpO1xuICAgIHZhciBjb2xEZWZGdW5jID0gY29sRGVmICYmIGNvbERlZi5zdXBwcmVzc0hlYWRlcktleWJvYXJkRXZlbnQ7XG4gICAgaWYgKCFleGlzdHMoY29sRGVmRnVuYykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICBhcGk6IGdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgY29sdW1uQXBpOiBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgIGNvbnRleHQ6IGdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgIGNvbERlZjogY29sRGVmLFxuICAgICAgICBjb2x1bW46IGNvbHVtbixcbiAgICAgICAgaGVhZGVyUm93SW5kZXg6IGhlYWRlclJvd0luZGV4LFxuICAgICAgICBldmVudDoga2V5Ym9hcmRFdmVudFxuICAgIH07XG4gICAgcmV0dXJuICEhY29sRGVmRnVuYyhwYXJhbXMpO1xufVxuZnVuY3Rpb24gaXNOdW1wYWREZWxXaXRoTnVtTG9ja09uRm9yRWRnZShldmVudCkge1xuICAgIHJldHVybiAoaXNCcm93c2VyRWRnZSgpKSAmJlxuICAgICAgICBldmVudC5rZXkgPT09IE5VTVBBRF9ERUxfTlVNTE9DS19PTl9LRVkgJiZcbiAgICAgICAgZXZlbnQuY2hhckNvZGUgPT09IE5VTVBBRF9ERUxfTlVNTE9DS19PTl9LRVlDT0RFO1xufVxuZnVuY3Rpb24gbm9ybWFsaXNlUXdlcnR5QXplcnR5KGtleWJvYXJkRXZlbnQpIHtcbiAgICB2YXIga2V5Q29kZSA9IGtleWJvYXJkRXZlbnQua2V5Q29kZTtcbiAgICB2YXIgY29kZTtcbiAgICBzd2l0Y2ggKGtleUNvZGUpIHtcbiAgICAgICAgY2FzZSBBX0tFWUNPREU6XG4gICAgICAgICAgICBjb2RlID0gS2V5Q29kZS5BO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgQ19LRVlDT0RFOlxuICAgICAgICAgICAgY29kZSA9IEtleUNvZGUuQztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFZfS0VZQ09ERTpcbiAgICAgICAgICAgIGNvZGUgPSBLZXlDb2RlLlY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBEX0tFWUNPREU6XG4gICAgICAgICAgICBjb2RlID0gS2V5Q29kZS5EO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgWl9LRVlDT0RFOlxuICAgICAgICAgICAgY29kZSA9IEtleUNvZGUuWjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFlfS0VZQ09ERTpcbiAgICAgICAgICAgIGNvZGUgPSBLZXlDb2RlLlk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNvZGUgPSBrZXlib2FyZEV2ZW50LmNvZGU7XG4gICAgfVxuICAgIHJldHVybiBjb2RlO1xufVxuZnVuY3Rpb24gaXNEZWxldGVLZXkoa2V5LCBhbHdheXNSZXR1cm5GYWxzZU9uQmFja3NwYWNlKSB7XG4gICAgaWYgKGFsd2F5c1JldHVybkZhbHNlT25CYWNrc3BhY2UgPT09IHZvaWQgMCkgeyBhbHdheXNSZXR1cm5GYWxzZU9uQmFja3NwYWNlID0gZmFsc2U7IH1cbiAgICBpZiAoa2V5ID09PSBLZXlDb2RlLkRFTEVURSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKCFhbHdheXNSZXR1cm5GYWxzZU9uQmFja3NwYWNlICYmIGtleSA9PT0gS2V5Q29kZS5CQUNLU1BBQ0UpIHtcbiAgICAgICAgcmV0dXJuIGlzTWFjT3NVc2VyQWdlbnQoKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG52YXIgS2V5Ym9hcmRVdGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgaXNFdmVudEZyb21QcmludGFibGVDaGFyYWN0ZXI6IGlzRXZlbnRGcm9tUHJpbnRhYmxlQ2hhcmFjdGVyLFxuICAgIGlzVXNlclN1cHByZXNzaW5nS2V5Ym9hcmRFdmVudDogaXNVc2VyU3VwcHJlc3NpbmdLZXlib2FyZEV2ZW50LFxuICAgIGlzVXNlclN1cHByZXNzaW5nSGVhZGVyS2V5Ym9hcmRFdmVudDogaXNVc2VyU3VwcHJlc3NpbmdIZWFkZXJLZXlib2FyZEV2ZW50LFxuICAgIG5vcm1hbGlzZVF3ZXJ0eUF6ZXJ0eTogbm9ybWFsaXNlUXdlcnR5QXplcnR5LFxuICAgIGlzRGVsZXRlS2V5OiBpc0RlbGV0ZUtleVxufSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbi8qKlxuICogYFRydWVgIGlmIHRoZSBldmVudCBpcyBjbG9zZSB0byB0aGUgb3JpZ2luYWwgZXZlbnQgYnkgWCBwaXhlbHMgZWl0aGVyIHZlcnRpY2FsbHkgb3IgaG9yaXpvbnRhbGx5LlxuICogd2Ugb25seSBzdGFydCBkcmFnZ2luZyBhZnRlciBYIHBpeGVscyBzbyB0aGlzIGFsbG93cyB1cyB0byBrbm93IGlmIHdlIHNob3VsZCBzdGFydCBkcmFnZ2luZyB5ZXQuXG4gKiBAcGFyYW0ge01vdXNlRXZlbnQgfCBUb3VjaEV2ZW50fSBlMVxuICogQHBhcmFtIHtNb3VzZUV2ZW50IHwgVG91Y2hFdmVudH0gZTJcbiAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbENvdW50XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gYXJlRXZlbnRzTmVhcihlMSwgZTIsIHBpeGVsQ291bnQpIHtcbiAgICAvLyBieSBkZWZhdWx0LCB3ZSB3YWl0IDQgcGl4ZWxzIGJlZm9yZSBzdGFydGluZyB0aGUgZHJhZ1xuICAgIGlmIChwaXhlbENvdW50ID09PSAwKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdmFyIGRpZmZYID0gTWF0aC5hYnMoZTEuY2xpZW50WCAtIGUyLmNsaWVudFgpO1xuICAgIHZhciBkaWZmWSA9IE1hdGguYWJzKGUxLmNsaWVudFkgLSBlMi5jbGllbnRZKTtcbiAgICByZXR1cm4gTWF0aC5tYXgoZGlmZlgsIGRpZmZZKSA8PSBwaXhlbENvdW50O1xufVxuXG52YXIgTW91c2VVdGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgYXJlRXZlbnRzTmVhcjogYXJlRXZlbnRzTmVhclxufSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbi8qKlxuICogR2V0cyBjYWxsZWQgYnk6IGEpIENsaWVudFNpZGVOb2RlTWFuYWdlciBhbmQgYikgR3JvdXBTdGFnZSB0byBkbyBzb3J0aW5nLlxuICogd2hlbiBpbiBDbGllbnRTaWRlTm9kZU1hbmFnZXIgd2UgYWx3YXlzIGhhdmUgaW5kZXhlcyAoYXMgdGhpcyBzb3J0cyB0aGUgaXRlbXMgdGhlXG4gKiB1c2VyIHByb3ZpZGVkKSBidXQgd2hlbiBpbiBHcm91cFN0YWdlLCB0aGUgbm9kZXMgY2FuIGNvbnRhaW4gZmlsbGVyIG5vZGVzIHRoYXRcbiAqIGRvbid0IGhhdmUgb3JkZXIgaWQnc1xuICogQHBhcmFtIHtSb3dOb2RlW119IHJvd05vZGVzXG4gKiBAcGFyYW0ge09iamVjdH0gcm93Tm9kZU9yZGVyXG4gKlxuICogQHJldHVybnMgYSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIG5vZGVzIHdlcmUgcmVvcmRlcmVkXG4gKi9cbmZ1bmN0aW9uIHNvcnRSb3dOb2Rlc0J5T3JkZXIocm93Tm9kZXMsIHJvd05vZGVPcmRlcikge1xuICAgIGlmICghcm93Tm9kZXMpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB2YXIgY29tcGFyYXRvciA9IGZ1bmN0aW9uIChub2RlQSwgbm9kZUIpIHtcbiAgICAgICAgdmFyIHBvc2l0aW9uQSA9IHJvd05vZGVPcmRlcltub2RlQS5pZF07XG4gICAgICAgIHZhciBwb3NpdGlvbkIgPSByb3dOb2RlT3JkZXJbbm9kZUIuaWRdO1xuICAgICAgICB2YXIgYUhhc0luZGV4ID0gcG9zaXRpb25BICE9PSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciBiSGFzSW5kZXggPSBwb3NpdGlvbkIgIT09IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIGJvdGhOb2Rlc0FyZVVzZXJOb2RlcyA9IGFIYXNJbmRleCAmJiBiSGFzSW5kZXg7XG4gICAgICAgIHZhciBib3RoTm9kZXNBcmVGaWxsZXJOb2RlcyA9ICFhSGFzSW5kZXggJiYgIWJIYXNJbmRleDtcbiAgICAgICAgaWYgKGJvdGhOb2Rlc0FyZVVzZXJOb2Rlcykge1xuICAgICAgICAgICAgLy8gd2hlbiBjb21wYXJpbmcgdHdvIG5vZGVzIHRoZSB1c2VyIGhhcyBwcm92aWRlZCwgdGhleSBhbHdheXNcbiAgICAgICAgICAgIC8vIGhhdmUgaW5kZXhlc1xuICAgICAgICAgICAgcmV0dXJuIHBvc2l0aW9uQSAtIHBvc2l0aW9uQjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYm90aE5vZGVzQXJlRmlsbGVyTm9kZXMpIHtcbiAgICAgICAgICAgIC8vIHdoZW4gY29tcGFyaW5nIHR3byBmaWxsZXIgbm9kZXMsIHdlIGhhdmUgbm8gaW5kZXggdG8gY29tcGFyZSB0aGVtXG4gICAgICAgICAgICAvLyBhZ2FpbnN0LCBob3dldmVyIHdlIHdhbnQgdGhpcyBzb3J0aW5nIHRvIGJlIGRldGVybWluaXN0aWMsIHNvIHRoYXRcbiAgICAgICAgICAgIC8vIHRoZSByb3dzIGRvbid0IGp1bXAgYXJvdW5kIGFzIHRoZSB1c2VyIGRvZXMgZGVsdGEgdXBkYXRlcy4gc28gd2VcbiAgICAgICAgICAgIC8vIHdhbnQgdGhlIHNhbWUgc29ydCByZXN1bHQuIHNvIHdlIHVzZSB0aGUgX19vYmplY3RJZCAtIHdoaWNoIGRvZXNuJ3QgbWFrZSBzZW5zZVxuICAgICAgICAgICAgLy8gZnJvbSBhIHNvcnRpbmcgcG9pbnQgb2YgdmlldywgYnV0IGRvZXMgZ2l2ZSBjb25zaXN0ZW50IGJlaGF2aW91ciBiZXR3ZWVuXG4gICAgICAgICAgICAvLyBjYWxscy4gb3RoZXJ3aXNlIGdyb3VwcyBqdW1wIGFyb3VuZCBhcyBkZWx0YSB1cGRhdGVzIGFyZSBkb25lLlxuICAgICAgICAgICAgLy8gbm90ZTogcHJldmlvdXNseSBoZXJlIHdlIHVzZWQgbm9kZUlkLCBob3dldmVyIHRoaXMgZ2F2ZSBhIHN0cmFuZ2Ugb3JkZXJcbiAgICAgICAgICAgIC8vIGFzIHN0cmluZyBvcmRlcmluZyBvZiBudW1iZXJzIGlzIHdyb25nLCBzbyB1c2luZyBpZCBiYXNlZCBvbiBjcmVhdGlvbiBvcmRlclxuICAgICAgICAgICAgLy8gYXMgbGVhc3QgZ2l2ZXMgYmV0dGVyIGxvb2tpbmcgb3JkZXIuXG4gICAgICAgICAgICByZXR1cm4gbm9kZUEuX19vYmplY3RJZCAtIG5vZGVCLl9fb2JqZWN0SWQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFIYXNJbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH07XG4gICAgLy8gY2hlY2sgaWYgdGhlIGxpc3QgZmlyc3QgbmVlZHMgc29ydGluZ1xuICAgIHZhciByb3dOb2RlQTtcbiAgICB2YXIgcm93Tm9kZUI7XG4gICAgdmFyIGF0TGVhc3RPbmVPdXRPZk9yZGVyID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dOb2Rlcy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgcm93Tm9kZUEgPSByb3dOb2Rlc1tpXTtcbiAgICAgICAgcm93Tm9kZUIgPSByb3dOb2Rlc1tpICsgMV07XG4gICAgICAgIGlmIChjb21wYXJhdG9yKHJvd05vZGVBLCByb3dOb2RlQikgPiAwKSB7XG4gICAgICAgICAgICBhdExlYXN0T25lT3V0T2ZPcmRlciA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYXRMZWFzdE9uZU91dE9mT3JkZXIpIHtcbiAgICAgICAgcm93Tm9kZXMuc29ydChjb21wYXJhdG9yKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIHRyYXZlcnNlTm9kZXNXaXRoS2V5KG5vZGVzLCBjYWxsYmFjaykge1xuICAgIHZhciBrZXlQYXJ0cyA9IFtdO1xuICAgIHJlY3Vyc2l2ZVNlYXJjaE5vZGVzKG5vZGVzKTtcbiAgICBmdW5jdGlvbiByZWN1cnNpdmVTZWFyY2hOb2RlcyhjdXJyZW50Tm9kZXMpIHtcbiAgICAgICAgaWYgKCFjdXJyZW50Tm9kZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50Tm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgLy8gYWxzbyBjaGVja2luZyBmb3IgY2hpbGRyZW4gZm9yIHRyZWUgZGF0YVxuICAgICAgICAgICAgaWYgKG5vZGUuZ3JvdXAgfHwgbm9kZS5oYXNDaGlsZHJlbigpKSB7XG4gICAgICAgICAgICAgICAga2V5UGFydHMucHVzaChub2RlLmtleSk7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGtleVBhcnRzLmpvaW4oJ3wnKTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhub2RlLCBrZXkpO1xuICAgICAgICAgICAgICAgIHJlY3Vyc2l2ZVNlYXJjaE5vZGVzKG5vZGUuY2hpbGRyZW5BZnRlckdyb3VwKTtcbiAgICAgICAgICAgICAgICBrZXlQYXJ0cy5wb3AoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG52YXIgUm93Tm9kZVV0aWxzID0gLyojX19QVVJFX18qL09iamVjdC5mcmVlemUoe1xuICAgIF9fcHJvdG9fXzogbnVsbCxcbiAgICBzb3J0Um93Tm9kZXNCeU9yZGVyOiBzb3J0Um93Tm9kZXNCeU9yZGVyLFxuICAgIHRyYXZlcnNlTm9kZXNXaXRoS2V5OiB0cmF2ZXJzZU5vZGVzV2l0aEtleVxufSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUb1NldChsaXN0KSB7XG4gICAgdmFyIHNldCA9IG5ldyBTZXQoKTtcbiAgICBsaXN0LmZvckVhY2goZnVuY3Rpb24gKHgpIHsgcmV0dXJuIHNldC5hZGQoeCk7IH0pO1xuICAgIHJldHVybiBzZXQ7XG59XG5cbnZhciBTZXRVdGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgY29udmVydFRvU2V0OiBjb252ZXJ0VG9TZXRcbn0pO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19hc3NpZ24kZiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fYXNzaWduKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgX19hc3NpZ24kZiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24kZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufTtcbnZhciB1dGlscyA9IF9fYXNzaWduJGYoX19hc3NpZ24kZihfX2Fzc2lnbiRmKF9fYXNzaWduJGYoX19hc3NpZ24kZihfX2Fzc2lnbiRmKF9fYXNzaWduJGYoX19hc3NpZ24kZihfX2Fzc2lnbiRmKF9fYXNzaWduJGYoX19hc3NpZ24kZihfX2Fzc2lnbiRmKF9fYXNzaWduJGYoX19hc3NpZ24kZihfX2Fzc2lnbiRmKF9fYXNzaWduJGYoX19hc3NpZ24kZihfX2Fzc2lnbiRmKF9fYXNzaWduJGYoX19hc3NpZ24kZih7fSwgR2VuZXJhbFV0aWxzKSwgQXJpYVV0aWxzKSwgQXJyYXlVdGlscyksIEJyb3dzZXJVdGlscyksIENzdlV0aWxzKSwgRGF0ZVV0aWxzKSwgRG9tVXRpbHMpLCBFdmVudFV0aWxzKSwgRnVuY3Rpb25VdGlscyksIEZ1enp5TWF0Y2hVdGlscyksIEdlbmVyaWNVdGlscyksIEljb25VdGlscyksIEtleWJvYXJkVXRpbHMpLCBNYXBVdGlscyksIE1vdXNlVXRpbHMpLCBOdW1iZXJVdGlscyksIE9iamVjdFV0aWxzKSwgUm93Tm9kZVV0aWxzKSwgU2V0VXRpbHMpLCBTdHJpbmdVdGlscyk7XG52YXIgXyA9IHV0aWxzO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgTnVtYmVyU2VxdWVuY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTnVtYmVyU2VxdWVuY2UoaW5pdFZhbHVlLCBzdGVwKSB7XG4gICAgICAgIGlmIChpbml0VmFsdWUgPT09IHZvaWQgMCkgeyBpbml0VmFsdWUgPSAwOyB9XG4gICAgICAgIGlmIChzdGVwID09PSB2b2lkIDApIHsgc3RlcCA9IDE7IH1cbiAgICAgICAgdGhpcy5uZXh0VmFsdWUgPSBpbml0VmFsdWU7XG4gICAgICAgIHRoaXMuc3RlcCA9IHN0ZXA7XG4gICAgfVxuICAgIE51bWJlclNlcXVlbmNlLnByb3RvdHlwZS5uZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmFsVG9SZXR1cm4gPSB0aGlzLm5leHRWYWx1ZTtcbiAgICAgICAgdGhpcy5uZXh0VmFsdWUgKz0gdGhpcy5zdGVwO1xuICAgICAgICByZXR1cm4gdmFsVG9SZXR1cm47XG4gICAgfTtcbiAgICBOdW1iZXJTZXF1ZW5jZS5wcm90b3R5cGUucGVlayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV4dFZhbHVlO1xuICAgIH07XG4gICAgTnVtYmVyU2VxdWVuY2UucHJvdG90eXBlLnNraXAgPSBmdW5jdGlvbiAoY291bnQpIHtcbiAgICAgICAgdGhpcy5uZXh0VmFsdWUgKz0gY291bnQ7XG4gICAgfTtcbiAgICByZXR1cm4gTnVtYmVyU2VxdWVuY2U7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgQWdQcm9taXNlU3RhdHVzO1xuKGZ1bmN0aW9uIChBZ1Byb21pc2VTdGF0dXMpIHtcbiAgICBBZ1Byb21pc2VTdGF0dXNbQWdQcm9taXNlU3RhdHVzW1wiSU5fUFJPR1JFU1NcIl0gPSAwXSA9IFwiSU5fUFJPR1JFU1NcIjtcbiAgICBBZ1Byb21pc2VTdGF0dXNbQWdQcm9taXNlU3RhdHVzW1wiUkVTT0xWRURcIl0gPSAxXSA9IFwiUkVTT0xWRURcIjtcbn0pKEFnUHJvbWlzZVN0YXR1cyB8fCAoQWdQcm9taXNlU3RhdHVzID0ge30pKTtcbnZhciBBZ1Byb21pc2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQWdQcm9taXNlKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3RhdHVzID0gQWdQcm9taXNlU3RhdHVzLklOX1BST0dSRVNTO1xuICAgICAgICB0aGlzLnJlc29sdXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLndhaXRlcnMgPSBbXTtcbiAgICAgICAgY2FsbGJhY2soZnVuY3Rpb24gKHZhbHVlKSB7IHJldHVybiBfdGhpcy5vbkRvbmUodmFsdWUpOyB9LCBmdW5jdGlvbiAocGFyYW1zKSB7IHJldHVybiBfdGhpcy5vblJlamVjdChwYXJhbXMpOyB9KTtcbiAgICB9XG4gICAgQWdQcm9taXNlLmFsbCA9IGZ1bmN0aW9uIChwcm9taXNlcykge1xuICAgICAgICByZXR1cm4gbmV3IEFnUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgdmFyIHJlbWFpbmluZ1RvUmVzb2x2ZSA9IHByb21pc2VzLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBjb21iaW5lZFZhbHVlcyA9IG5ldyBBcnJheShyZW1haW5pbmdUb1Jlc29sdmUpO1xuICAgICAgICAgICAgcHJvbWlzZXMuZm9yRWFjaChmdW5jdGlvbiAocHJvbWlzZSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbWJpbmVkVmFsdWVzW2luZGV4XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5pbmdUb1Jlc29sdmUtLTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbWFpbmluZ1RvUmVzb2x2ZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShjb21iaW5lZFZhbHVlcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFnUHJvbWlzZS5yZXNvbHZlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7IHZhbHVlID0gbnVsbDsgfVxuICAgICAgICByZXR1cm4gbmV3IEFnUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXR1cm4gcmVzb2x2ZSh2YWx1ZSk7IH0pO1xuICAgIH07XG4gICAgQWdQcm9taXNlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24gKGZ1bmMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIG5ldyBBZ1Byb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5zdGF0dXMgPT09IEFnUHJvbWlzZVN0YXR1cy5SRVNPTFZFRCkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZnVuYyhfdGhpcy5yZXNvbHV0aW9uKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpcy53YWl0ZXJzLnB1c2goZnVuY3Rpb24gKHZhbHVlKSB7IHJldHVybiByZXNvbHZlKGZ1bmModmFsdWUpKTsgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQWdQcm9taXNlLnByb3RvdHlwZS5yZXNvbHZlTm93ID0gZnVuY3Rpb24gKGlmTm90UmVzb2x2ZWRWYWx1ZSwgaWZSZXNvbHZlZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0dXMgPT09IEFnUHJvbWlzZVN0YXR1cy5SRVNPTFZFRCA/IGlmUmVzb2x2ZWQodGhpcy5yZXNvbHV0aW9uKSA6IGlmTm90UmVzb2x2ZWRWYWx1ZTtcbiAgICB9O1xuICAgIEFnUHJvbWlzZS5wcm90b3R5cGUub25Eb25lID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuc3RhdHVzID0gQWdQcm9taXNlU3RhdHVzLlJFU09MVkVEO1xuICAgICAgICB0aGlzLnJlc29sdXRpb24gPSB2YWx1ZTtcbiAgICAgICAgdGhpcy53YWl0ZXJzLmZvckVhY2goZnVuY3Rpb24gKHdhaXRlcikgeyByZXR1cm4gd2FpdGVyKHZhbHVlKTsgfSk7XG4gICAgfTtcbiAgICBBZ1Byb21pc2UucHJvdG90eXBlLm9uUmVqZWN0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ1RCSScpO1xuICAgIH07XG4gICAgcmV0dXJuIEFnUHJvbWlzZTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbi8qKlxuICogQSBVdGlsIENsYXNzIG9ubHkgdXNlZCB3aGVuIGRlYnVnZ2luZyBmb3IgcHJpbnRpbmcgdGltZSB0byBjb25zb2xlXG4gKi9cbnZhciBUaW1lciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUaW1lcigpIHtcbiAgICAgICAgdGhpcy50aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICB9XG4gICAgVGltZXIucHJvdG90eXBlLnByaW50ID0gZnVuY3Rpb24gKG1zZykge1xuICAgICAgICB2YXIgZHVyYXRpb24gPSAobmV3IERhdGUoKS5nZXRUaW1lKCkpIC0gdGhpcy50aW1lc3RhbXA7XG4gICAgICAgIGNvbnNvbGUuaW5mbyhtc2cgKyBcIiA9IFwiICsgZHVyYXRpb24pO1xuICAgICAgICB0aGlzLnRpbWVzdGFtcCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIH07XG4gICAgcmV0dXJuIFRpbWVyO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyUCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXNzaWduJGUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2Fzc2lnbikgfHwgZnVuY3Rpb24gKCkge1xuICAgIF9fYXNzaWduJGUgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduJGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgX19kZWNvcmF0ZSQycSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFRvb2x0aXBTdGF0ZXM7XG4oZnVuY3Rpb24gKFRvb2x0aXBTdGF0ZXMpIHtcbiAgICBUb29sdGlwU3RhdGVzW1Rvb2x0aXBTdGF0ZXNbXCJOT1RISU5HXCJdID0gMF0gPSBcIk5PVEhJTkdcIjtcbiAgICBUb29sdGlwU3RhdGVzW1Rvb2x0aXBTdGF0ZXNbXCJXQUlUSU5HX1RPX1NIT1dcIl0gPSAxXSA9IFwiV0FJVElOR19UT19TSE9XXCI7XG4gICAgVG9vbHRpcFN0YXRlc1tUb29sdGlwU3RhdGVzW1wiU0hPV0lOR1wiXSA9IDJdID0gXCJTSE9XSU5HXCI7XG59KShUb29sdGlwU3RhdGVzIHx8IChUb29sdGlwU3RhdGVzID0ge30pKTtcbnZhciBDdXN0b21Ub29sdGlwRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMlAoQ3VzdG9tVG9vbHRpcEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ3VzdG9tVG9vbHRpcEZlYXR1cmUocGFyZW50Q29tcCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5ERUZBVUxUX1NIT1dfVE9PTFRJUF9ERUxBWSA9IDIwMDA7XG4gICAgICAgIF90aGlzLkRFRkFVTFRfSElERV9UT09MVElQX0RFTEFZID0gMTAwMDA7XG4gICAgICAgIF90aGlzLlNIT1dfUVVJQ0tfVE9PTFRJUF9ESUZGID0gMTAwMDtcbiAgICAgICAgX3RoaXMuRkFERV9PVVRfVE9PTFRJUF9USU1FT1VUID0gMTAwMDtcbiAgICAgICAgX3RoaXMuc3RhdGUgPSBUb29sdGlwU3RhdGVzLk5PVEhJTkc7XG4gICAgICAgIC8vIHdoZW4gc2hvd2luZyB0aGUgdG9vbHRpcCwgd2UgbmVlZCB0byBtYWtlIHN1cmUgaXQncyB0aGUgbW9zdCByZWNlbnQgaW5zdGFuY2Ugd2UgcmVxdWVzdCwgYXMgZHVlIHRvXG4gICAgICAgIC8vIGFzeW5jIHdlIGNvdWxkIHJlcXVlc3QgdHdvIHRvb2x0aXBzIGJlZm9yZSB0aGUgZmlyc3QgaW5zdGFuY2UgcmV0dXJucywgaW4gd2hpY2ggY2FzZSB3ZSBzaG91bGRcbiAgICAgICAgLy8gZGlzcmVnYXJkIHRoZSBzZWNvbmQgaW5zdGFuY2UuXG4gICAgICAgIF90aGlzLnRvb2x0aXBJbnN0YW5jZUNvdW50ID0gMDtcbiAgICAgICAgX3RoaXMudG9vbHRpcE1vdXNlVHJhY2sgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMucGFyZW50Q29tcCA9IHBhcmVudENvbXA7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQ3VzdG9tVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9vbHRpcFNob3dEZWxheSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFRvb2x0aXBEZWxheSgnc2hvdycpIHx8IHRoaXMuREVGQVVMVF9TSE9XX1RPT0xUSVBfREVMQVk7XG4gICAgICAgIHRoaXMudG9vbHRpcEhpZGVEZWxheSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFRvb2x0aXBEZWxheSgnaGlkZScpIHx8IHRoaXMuREVGQVVMVF9ISURFX1RPT0xUSVBfREVMQVk7XG4gICAgICAgIHRoaXMudG9vbHRpcE1vdXNlVHJhY2sgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Rvb2x0aXBNb3VzZVRyYWNrKCk7XG4gICAgICAgIHZhciBlbCA9IHRoaXMucGFyZW50Q29tcC5nZXRHdWkoKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZWwsICdtb3VzZWVudGVyJywgdGhpcy5vbk1vdXNlRW50ZXIuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGVsLCAnbW91c2VsZWF2ZScsIHRoaXMub25Nb3VzZUxlYXZlLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlbCwgJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGVsLCAnbW91c2Vkb3duJywgdGhpcy5vbk1vdXNlRG93bi5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZWwsICdrZXlkb3duJywgdGhpcy5vbktleURvd24uYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gaWYgdGhpcyBjb21wb25lbnQgZ2V0cyBkZXN0cm95ZWQgd2hpbGUgdG9vbHRpcCBpcyBzaG93aW5nLCBuZWVkIHRvIG1ha2Ugc3VyZVxuICAgICAgICAvLyB3ZSBkb24ndCBlbmQgd2l0aCBubyBtb3VzZUxlYXZlIGV2ZW50IHJlc3VsdGluZyBpbiB6b21iaWUgdG9vbHRpcFxuICAgICAgICB0aGlzLnNldFRvRG9Ob3RoaW5nKCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgQ3VzdG9tVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLm9uTW91c2VFbnRlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmIChpc0lPU1VzZXJBZ2VudCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gZXZlcnkgbW91c2VlbnRlciBzaG91bGQgYmUgZm9sbG93aW5nIGJ5IGEgbW91c2VsZWF2ZSwgaG93ZXZlciBmb3Igc29tZSB1bmtvbnduLCBpdCdzIHBvc3NpYmxlIGZvclxuICAgICAgICAvLyBtb3VzZWVudGVyIHRvIGJlIGNhbGxlZCB0d2ljZSBpbiBhIHJvdywgd2hpY2ggY2FuIGhhcHBlbiBpZiBlZGl0aW5nIHRoZSBjZWxsLiB0aGlzIHdhcyByZXBvcnRlZFxuICAgICAgICAvLyBpbiBodHRwczovL2FnLWdyaWQuYXRsYXNzaWFuLm5ldC9icm93c2UvQUctNDQyMi4gdG8gZ2V0IGFyb3VuZCB0aGlzLCB3ZSBjaGVjayB0aGUgc3RhdGUsIGFuZCBpZlxuICAgICAgICAvLyBzdGF0ZSBpcyAhPW5vdGhpbmcsIHRoZW4gd2Uga25vdyBtb3VzZWVudGVyIHdhcyBhbHJlYWR5IHJlY2VpdmVkLlxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPSBUb29sdGlwU3RhdGVzLk5PVEhJTkcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBhbm90aGVyIHRvb2x0aXAgd2FzIGhpZGRlbiB2ZXJ5IHJlY2VudGx5LCB3ZSBvbmx5IHdhaXQgMjAwbXMgdG8gc2hvdywgbm90IHRoZSBub3JtYWwgd2FpdGluZyB0aW1lXG4gICAgICAgIHZhciBkZWxheSA9IHRoaXMuaXNMYXN0VG9vbHRpcEhpZGRlblJlY2VudGx5KCkgPyAyMDAgOiB0aGlzLnRvb2x0aXBTaG93RGVsYXk7XG4gICAgICAgIHRoaXMuc2hvd1Rvb2x0aXBUaW1lb3V0SWQgPSB3aW5kb3cuc2V0VGltZW91dCh0aGlzLnNob3dUb29sdGlwLmJpbmQodGhpcyksIGRlbGF5KTtcbiAgICAgICAgdGhpcy5sYXN0TW91c2VFdmVudCA9IGU7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBUb29sdGlwU3RhdGVzLldBSVRJTkdfVE9fU0hPVztcbiAgICB9O1xuICAgIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZS5vbk1vdXNlTGVhdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0VG9Eb05vdGhpbmcoKTtcbiAgICB9O1xuICAgIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZS5vbktleURvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0VG9Eb05vdGhpbmcoKTtcbiAgICB9O1xuICAgIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZS5zZXRUb0RvTm90aGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUgPT09IFRvb2x0aXBTdGF0ZXMuU0hPV0lORykge1xuICAgICAgICAgICAgdGhpcy5oaWRlVG9vbHRpcCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xlYXJUaW1lb3V0cygpO1xuICAgICAgICB0aGlzLnN0YXRlID0gVG9vbHRpcFN0YXRlcy5OT1RISU5HO1xuICAgIH07XG4gICAgQ3VzdG9tVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLm9uTW91c2VNb3ZlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgLy8gdGhlcmUgaXMgYSBkZWxheSBmcm9tIHRoZSB0aW1lIHdlIG1vdXNlT3ZlciBhIGNvbXBvbmVudCBhbmQgdGhlIHRpbWUgdGhlXG4gICAgICAgIC8vIHRvb2x0aXAgaXMgZGlzcGxheWVkLCBzbyB3ZSBuZWVkIHRvIHRyYWNrIG1vdXNlbW92ZSB0byBiZSBhYmxlIHRvIGNvcnJlY3RseVxuICAgICAgICAvLyBwb3NpdGlvbiB0aGUgdG9vbHRpcCB3aGVuIHNob3dUb29sdGlwIGlzIGNhbGxlZC5cbiAgICAgICAgdGhpcy5sYXN0TW91c2VFdmVudCA9IGU7XG4gICAgICAgIGlmICh0aGlzLnRvb2x0aXBNb3VzZVRyYWNrICYmXG4gICAgICAgICAgICB0aGlzLnN0YXRlID09PSBUb29sdGlwU3RhdGVzLlNIT1dJTkcgJiZcbiAgICAgICAgICAgIHRoaXMudG9vbHRpcENvbXApIHtcbiAgICAgICAgICAgIHRoaXMucG9zaXRpb25Ub29sdGlwVW5kZXJMYXN0TW91c2VFdmVudCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUub25Nb3VzZURvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0VG9Eb05vdGhpbmcoKTtcbiAgICB9O1xuICAgIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZS5oaWRlVG9vbHRpcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gY2hlY2sgaWYgY29tcCBleGlzdHMgLSBkdWUgdG8gYXN5bmMsIGFsdGhvdWdoIHdlIGFza2VkIGZvclxuICAgICAgICAvLyBvbmUsIHRoZSBpbnN0YW5jZSBtYXkgbm90IGJlIGJhY2sgeWV0XG4gICAgICAgIGlmICh0aGlzLnRvb2x0aXBDb21wKSB7XG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3lUb29sdGlwQ29tcCgpO1xuICAgICAgICAgICAgQ3VzdG9tVG9vbHRpcEZlYXR1cmUubGFzdFRvb2x0aXBIaWRlVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RhdGUgPSBUb29sdGlwU3RhdGVzLk5PVEhJTkc7XG4gICAgfTtcbiAgICBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUuZGVzdHJveVRvb2x0aXBDb21wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBhZGQgY2xhc3MgdG8gZmFkZSBvdXQgdGhlIHRvb2x0aXBcbiAgICAgICAgdGhpcy50b29sdGlwQ29tcC5nZXRHdWkoKS5jbGFzc0xpc3QuYWRkKCdhZy10b29sdGlwLWhpZGluZycpO1xuICAgICAgICAvLyBtYWtlIGxvY2FsIGNvcGllcyBvZiB0aGVzZSB2YXJpYWJsZXMsIGFzIHdlIHVzZSB0aGVtIGluIHRoZSBhc3luYyBmdW5jdGlvbiBiZWxvdyxcbiAgICAgICAgLy8gYW5kIHdlIGNsZWFyIHRoZW4gdG8gJ3VuZGVmaW5lZCcgbGF0ZXIsIHNvIG5lZWQgdG8gdGFrZSBhIGNvcHkgYmVmb3JlIHRoZXkgYXJlIHVuZGVmaW5lZC5cbiAgICAgICAgdmFyIHRvb2x0aXBQb3B1cERlc3Ryb3lGdW5jID0gdGhpcy50b29sdGlwUG9wdXBEZXN0cm95RnVuYztcbiAgICAgICAgdmFyIHRvb2x0aXBDb21wID0gdGhpcy50b29sdGlwQ29tcDtcbiAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdG9vbHRpcFBvcHVwRGVzdHJveUZ1bmMoKTtcbiAgICAgICAgICAgIF90aGlzLmdldENvbnRleHQoKS5kZXN0cm95QmVhbih0b29sdGlwQ29tcCk7XG4gICAgICAgIH0sIHRoaXMuRkFERV9PVVRfVE9PTFRJUF9USU1FT1VUKTtcbiAgICAgICAgdGhpcy50b29sdGlwUG9wdXBEZXN0cm95RnVuYyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy50b29sdGlwQ29tcCA9IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZS5pc0xhc3RUb29sdGlwSGlkZGVuUmVjZW50bHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHJldHVybiB0cnVlIGlmIDwxMDAwbXMgc2luY2UgbGFzdCB0aW1lIHdlIGhpZCBhIHRvb2x0aXBcbiAgICAgICAgdmFyIG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICB2YXIgdGhlbiA9IEN1c3RvbVRvb2x0aXBGZWF0dXJlLmxhc3RUb29sdGlwSGlkZVRpbWU7XG4gICAgICAgIHJldHVybiAobm93IC0gdGhlbikgPCB0aGlzLlNIT1dfUVVJQ0tfVE9PTFRJUF9ESUZGO1xuICAgIH07XG4gICAgQ3VzdG9tVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLnNob3dUb29sdGlwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyYW1zID0gX19hc3NpZ24kZSh7fSwgdGhpcy5wYXJlbnRDb21wLmdldFRvb2x0aXBQYXJhbXMoKSk7XG4gICAgICAgIGlmICghZXhpc3RzKHBhcmFtcy52YWx1ZSkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0VG9Eb05vdGhpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlID0gVG9vbHRpcFN0YXRlcy5TSE9XSU5HO1xuICAgICAgICB0aGlzLnRvb2x0aXBJbnN0YW5jZUNvdW50Kys7XG4gICAgICAgIC8vIHdlIHBhc3MgaW4gdG9vbHRpcEluc3RhbmNlQ291bnQgc28gdGhlIGNhbGxiYWNrIGtub3dzIHdoYXQgdGhlIGNvdW50IHdhcyB3aGVuXG4gICAgICAgIC8vIHdlIHJlcXVlc3RlZCB0aGUgdG9vbHRpcCwgc28gaWYgYW5vdGhlciB0b29sdGlwIHdhcyByZXF1ZXN0ZWQgaW4gdGhlIG1lYW4gdGltZVxuICAgICAgICAvLyB3ZSBkaXNyZWdhcmQgaXRcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gdGhpcy5uZXdUb29sdGlwQ29tcG9uZW50Q2FsbGJhY2suYmluZCh0aGlzLCB0aGlzLnRvb2x0aXBJbnN0YW5jZUNvdW50KTtcbiAgICAgICAgdmFyIHVzZXJEZXRhaWxzID0gdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeS5nZXRUb29sdGlwQ29tcERldGFpbHMocGFyYW1zKTtcbiAgICAgICAgdXNlckRldGFpbHMubmV3QWdTdGFja0luc3RhbmNlKCkudGhlbihjYWxsYmFjayk7XG4gICAgfTtcbiAgICBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUubmV3VG9vbHRpcENvbXBvbmVudENhbGxiYWNrID0gZnVuY3Rpb24gKHRvb2x0aXBJbnN0YW5jZUNvcHksIHRvb2x0aXBDb21wKSB7XG4gICAgICAgIHZhciBjb21wTm9Mb25nZXJOZWVkZWQgPSB0aGlzLnN0YXRlICE9PSBUb29sdGlwU3RhdGVzLlNIT1dJTkcgfHwgdGhpcy50b29sdGlwSW5zdGFuY2VDb3VudCAhPT0gdG9vbHRpcEluc3RhbmNlQ29weTtcbiAgICAgICAgaWYgKGNvbXBOb0xvbmdlck5lZWRlZCkge1xuICAgICAgICAgICAgdGhpcy5nZXRDb250ZXh0KCkuZGVzdHJveUJlYW4odG9vbHRpcENvbXApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlR3VpID0gdG9vbHRpcENvbXAuZ2V0R3VpKCk7XG4gICAgICAgIHRoaXMudG9vbHRpcENvbXAgPSB0b29sdGlwQ29tcDtcbiAgICAgICAgaWYgKCFlR3VpLmNsYXNzTGlzdC5jb250YWlucygnYWctdG9vbHRpcCcpKSB7XG4gICAgICAgICAgICBlR3VpLmNsYXNzTGlzdC5hZGQoJ2FnLXRvb2x0aXAtY3VzdG9tJyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBhZGRQb3B1cFJlcyA9IHRoaXMucG9wdXBTZXJ2aWNlLmFkZFBvcHVwKHtcbiAgICAgICAgICAgIGVDaGlsZDogZUd1aSxcbiAgICAgICAgICAgIGFyaWFMYWJlbDogdHJhbnNsYXRlKCdhcmlhTGFiZWxUb29sdGlwJywgJ1Rvb2x0aXAnKVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGFkZFBvcHVwUmVzKSB7XG4gICAgICAgICAgICB0aGlzLnRvb2x0aXBQb3B1cERlc3Ryb3lGdW5jID0gYWRkUG9wdXBSZXMuaGlkZUZ1bmM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhpcy50b29sdGlwUG9wdXBEZXN0cm95RnVuYyA9IHRoaXMucG9wdXBTZXJ2aWNlLmFkZFBvcHVwKGZhbHNlLCBlR3VpLCBmYWxzZSk7XG4gICAgICAgIHRoaXMucG9zaXRpb25Ub29sdGlwVW5kZXJMYXN0TW91c2VFdmVudCgpO1xuICAgICAgICB0aGlzLmhpZGVUb29sdGlwVGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQodGhpcy5oaWRlVG9vbHRpcC5iaW5kKHRoaXMpLCB0aGlzLnRvb2x0aXBIaWRlRGVsYXkpO1xuICAgIH07XG4gICAgQ3VzdG9tVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLnBvc2l0aW9uVG9vbHRpcFVuZGVyTGFzdE1vdXNlRXZlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucG9wdXBTZXJ2aWNlLnBvc2l0aW9uUG9wdXBVbmRlck1vdXNlRXZlbnQoe1xuICAgICAgICAgICAgdHlwZTogJ3Rvb2x0aXAnLFxuICAgICAgICAgICAgbW91c2VFdmVudDogdGhpcy5sYXN0TW91c2VFdmVudCxcbiAgICAgICAgICAgIGVQb3B1cDogdGhpcy50b29sdGlwQ29tcC5nZXRHdWkoKSxcbiAgICAgICAgICAgIG51ZGdlWTogMThcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUuY2xlYXJUaW1lb3V0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2hvd1Rvb2x0aXBUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5zaG93VG9vbHRpcFRpbWVvdXRJZCk7XG4gICAgICAgICAgICB0aGlzLnNob3dUb29sdGlwVGltZW91dElkID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmhpZGVUb29sdGlwVGltZW91dElkKSB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMuaGlkZVRvb2x0aXBUaW1lb3V0SWQpO1xuICAgICAgICAgICAgdGhpcy5oaWRlVG9vbHRpcFRpbWVvdXRJZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQycShbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUsIFwicG9wdXBTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQycShbXG4gICAgICAgIEF1dG93aXJlZCgndXNlckNvbXBvbmVudEZhY3RvcnknKVxuICAgIF0sIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZSwgXCJ1c2VyQ29tcG9uZW50RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbkFwaScpXG4gICAgXSwgQ3VzdG9tVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLCBcImNvbHVtbkFwaVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMnEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRBcGknKVxuICAgIF0sIEN1c3RvbVRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZSwgXCJncmlkQXBpXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQycShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBDdXN0b21Ub29sdGlwRmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gQ3VzdG9tVG9vbHRpcEZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBDc3NDbGFzc01hbmFnZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ3NzQ2xhc3NNYW5hZ2VyKGdldEd1aSkge1xuICAgICAgICAvLyB0byBtaW5pbWlzZSBET00gaGl0cywgd2Ugb25seSBhcHBseSBDU1MgY2xhc3NlcyBpZiB0aGV5IGhhdmUgY2hhbmdlZC4gYXMgYWRkaW5nIGEgQ1NTIGNsYXNzIHRoYXQgaXMgYWxyZWFkeVxuICAgICAgICAvLyB0aGVyZSwgb3IgcmVtb3Zpbmcgb25lIHRoYXQgd2Fzbid0IHByZXNlbnQsIGFsbCB0YWtlcyBDUFUuXG4gICAgICAgIHRoaXMuY3NzQ2xhc3NTdGF0ZXMgPSB7fTtcbiAgICAgICAgdGhpcy5nZXRHdWkgPSBnZXRHdWk7XG4gICAgfVxuICAgIENzc0NsYXNzTWFuYWdlci5wcm90b3R5cGUuYWRkQ3NzQ2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBsaXN0ID0gKGNsYXNzTmFtZSB8fCAnJykuc3BsaXQoJyAnKTtcbiAgICAgICAgaWYgKGxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgbGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChjbHMpIHsgcmV0dXJuIF90aGlzLmFkZENzc0NsYXNzKGNscyk7IH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1cGRhdGVOZWVkZWQgPSB0aGlzLmNzc0NsYXNzU3RhdGVzW2NsYXNzTmFtZV0gIT09IHRydWU7XG4gICAgICAgIGlmICh1cGRhdGVOZWVkZWQgJiYgY2xhc3NOYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5nZXRHdWkoKS5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgICAgICAgICB0aGlzLmNzc0NsYXNzU3RhdGVzW2NsYXNzTmFtZV0gPSB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDc3NDbGFzc01hbmFnZXIucHJvdG90eXBlLnJlbW92ZUNzc0NsYXNzID0gZnVuY3Rpb24gKGNsYXNzTmFtZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbGlzdCA9IChjbGFzc05hbWUgfHwgJycpLnNwbGl0KCcgJyk7XG4gICAgICAgIGlmIChsaXN0Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGxpc3QuZm9yRWFjaChmdW5jdGlvbiAoY2xzKSB7IHJldHVybiBfdGhpcy5yZW1vdmVDc3NDbGFzcyhjbHMpOyB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXBkYXRlTmVlZGVkID0gdGhpcy5jc3NDbGFzc1N0YXRlc1tjbGFzc05hbWVdICE9PSBmYWxzZTtcbiAgICAgICAgaWYgKHVwZGF0ZU5lZWRlZCAmJiBjbGFzc05hbWUubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmdldEd1aSgpLmNsYXNzTGlzdC5yZW1vdmUoY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIHRoaXMuY3NzQ2xhc3NTdGF0ZXNbY2xhc3NOYW1lXSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDc3NDbGFzc01hbmFnZXIucHJvdG90eXBlLmNvbnRhaW5zQ3NzQ2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEd1aSgpLmNsYXNzTGlzdC5jb250YWlucyhjbGFzc05hbWUpO1xuICAgIH07XG4gICAgQ3NzQ2xhc3NNYW5hZ2VyLnByb3RvdHlwZS5hZGRPclJlbW92ZUNzc0NsYXNzID0gZnVuY3Rpb24gKGNsYXNzTmFtZSwgYWRkT3JSZW1vdmUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFjbGFzc05hbWUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBjaGVjayBmb3Igc3BhY2VzIGJlZm9yZSBkb2luZyB0aGUgc3BsaXQsIGFzIGRvaW5nIHRoZSBzcGxpdFxuICAgICAgICAvLyBjcmVhdGVkIGEgcGVyZm9ybWFuY2UgcHJvYmxlbSAob24gd2luZG93cyBvbmx5LCBzZWUgQUctNjc2NSlcbiAgICAgICAgaWYgKGNsYXNzTmFtZS5pbmRleE9mKCcgJykgPj0gMCkge1xuICAgICAgICAgICAgdmFyIGxpc3QgPSAoY2xhc3NOYW1lIHx8ICcnKS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgaWYgKGxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIGxpc3QuZm9yRWFjaChmdW5jdGlvbiAoY2xzKSB7IHJldHVybiBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKGNscywgYWRkT3JSZW1vdmUpOyB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHVwZGF0ZU5lZWRlZCA9IHRoaXMuY3NzQ2xhc3NTdGF0ZXNbY2xhc3NOYW1lXSAhPT0gYWRkT3JSZW1vdmU7XG4gICAgICAgIGlmICh1cGRhdGVOZWVkZWQgJiYgY2xhc3NOYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5nZXRHdWkoKS5jbGFzc0xpc3QudG9nZ2xlKGNsYXNzTmFtZSwgYWRkT3JSZW1vdmUpO1xuICAgICAgICAgICAgdGhpcy5jc3NDbGFzc1N0YXRlc1tjbGFzc05hbWVdID0gYWRkT3JSZW1vdmU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBDc3NDbGFzc01hbmFnZXI7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJPID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQycCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIGNvbXBJZFNlcXVlbmNlID0gbmV3IE51bWJlclNlcXVlbmNlKCk7XG52YXIgQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyTyhDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ29tcG9uZW50KHRlbXBsYXRlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIC8vIGlmIGZhbHNlLCB0aGVuIENTUyBjbGFzcyBcImFnLWhpZGRlblwiIGlzIGFwcGxpZWQsIHdoaWNoIHNldHMgXCJkaXNwbGF5OiBub25lXCJcbiAgICAgICAgX3RoaXMuZGlzcGxheWVkID0gdHJ1ZTtcbiAgICAgICAgLy8gaWYgZmFsc2UsIHRoZW4gQ1NTIGNsYXNzIFwiYWctaW52aXNpYmxlXCIgaXMgYXBwbGllZCwgd2hpY2ggc2V0cyBcInZpc2liaWxpdHk6IGhpZGRlblwiXG4gICAgICAgIF90aGlzLnZpc2libGUgPSB0cnVlO1xuICAgICAgICAvLyB1bmlxdWUgaWQgZm9yIHRoaXMgcm93IGNvbXBvbmVudC4gdGhpcyBpcyB1c2VkIGZvciBnZXR0aW5nIGEgcmVmZXJlbmNlIHRvIHRoZSBIVE1MIGRvbS5cbiAgICAgICAgLy8gd2UgY2Fubm90IHVzZSB0aGUgUm93Tm9kZSBpZCBhcyB0aGlzIGlzIG5vdCB1bmlxdWUgKGR1ZSB0byBhbmltYXRpb24sIG9sZCByb3dzIGNhbiBiZSBseWluZ1xuICAgICAgICAvLyBhcm91bmQgYXMgd2UgY3JlYXRlIGEgbmV3IHJvd0NvbXAgaW5zdGFuY2UgZm9yIHRoZSBzYW1lIHJvdyBub2RlKS5cbiAgICAgICAgX3RoaXMuY29tcElkID0gY29tcElkU2VxdWVuY2UubmV4dCgpO1xuICAgICAgICBfdGhpcy5jc3NDbGFzc01hbmFnZXIgPSBuZXcgQ3NzQ2xhc3NNYW5hZ2VyKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmVHdWk7IH0pO1xuICAgICAgICBpZiAodGVtcGxhdGUpIHtcbiAgICAgICAgICAgIF90aGlzLnNldFRlbXBsYXRlKHRlbXBsYXRlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENvbXBvbmVudC5wcm90b3R5cGUucHJlQ29uc3RydWN0T25Db21wb25lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudXNpbmdCcm93c2VyVG9vbHRpcHMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUJyb3dzZXJUb29sdGlwcygpO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5nZXRDb21wSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbXBJZDtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuZ2V0VG9vbHRpcFBhcmFtcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLnRvb2x0aXBUZXh0LFxuICAgICAgICAgICAgbG9jYXRpb246ICdVTktOT1dOJ1xuICAgICAgICB9O1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5zZXRUb29sdGlwID0gZnVuY3Rpb24gKG5ld1Rvb2x0aXBUZXh0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciByZW1vdmVUb29sdGlwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLnVzaW5nQnJvd3NlclRvb2x0aXBzKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkucmVtb3ZlQXR0cmlidXRlKCd0aXRsZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgX3RoaXMudG9vbHRpcEZlYXR1cmUgPSBfdGhpcy5kZXN0cm95QmVhbihfdGhpcy50b29sdGlwRmVhdHVyZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBhZGRUb29sdGlwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLnVzaW5nQnJvd3NlclRvb2x0aXBzKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkuc2V0QXR0cmlidXRlKCd0aXRsZScsIF90aGlzLnRvb2x0aXBUZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIF90aGlzLnRvb2x0aXBGZWF0dXJlID0gX3RoaXMuY3JlYXRlQmVhbihuZXcgQ3VzdG9tVG9vbHRpcEZlYXR1cmUoX3RoaXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRoaXMudG9vbHRpcFRleHQgIT0gbmV3VG9vbHRpcFRleHQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRvb2x0aXBUZXh0KSB7XG4gICAgICAgICAgICAgICAgcmVtb3ZlVG9vbHRpcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5ld1Rvb2x0aXBUZXh0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRvb2x0aXBUZXh0ID0gbmV3VG9vbHRpcFRleHQ7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudG9vbHRpcFRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkVG9vbHRpcCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZm9yIHJlZ2lzdGVyZWQgY29tcG9uZW50cyBvbmx5LCBlZyBjcmVhdGVzIEFnQ2hlY2tib3ggaW5zdGFuY2UgZnJvbSBhZy1jaGVja2JveCBIVE1MIHRhZ1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuY3JlYXRlQ2hpbGRDb21wb25lbnRzRnJvbVRhZ3MgPSBmdW5jdGlvbiAocGFyZW50Tm9kZSwgcGFyYW1zTWFwKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIHdlIE1VU1QgdGFrZSBhIGNvcHkgb2YgdGhlIGxpc3QgZmlyc3QsIGFzIHRoZSAnc3dhcENvbXBvbmVudEZvck5vZGUnIGFkZHMgY29tbWVudHMgaW50byB0aGUgRE9NXG4gICAgICAgIC8vIHdoaWNoIG1lc3NlcyB1cCB0aGUgdHJhdmVyc2FsIG9yZGVyIG9mIHRoZSBjaGlsZHJlbi5cbiAgICAgICAgdmFyIGNoaWxkTm9kZUxpc3QgPSBjb3B5Tm9kZUxpc3QocGFyZW50Tm9kZS5jaGlsZE5vZGVzKTtcbiAgICAgICAgY2hpbGROb2RlTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgIGlmICghKGNoaWxkTm9kZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjaGlsZENvbXAgPSBfdGhpcy5jcmVhdGVDb21wb25lbnRGcm9tRWxlbWVudChjaGlsZE5vZGUsIGZ1bmN0aW9uIChjaGlsZENvbXApIHtcbiAgICAgICAgICAgICAgICAvLyBjb3B5IG92ZXIgYWxsIGF0dHJpYnV0ZXMsIGluY2x1ZGluZyBjc3MgY2xhc3Nlcywgc28gYW55IGF0dHJpYnV0ZXMgdXNlciBwdXQgb24gdGhlIHRhZ1xuICAgICAgICAgICAgICAgIC8vIHdsbCBiZSBjYXJyaWVkIGFjcm9zc1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZEd1aSA9IGNoaWxkQ29tcC5nZXRHdWkoKTtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRHdWkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29weUF0dHJpYnV0ZXNGcm9tTm9kZShjaGlsZE5vZGUsIGNoaWxkQ29tcC5nZXRHdWkoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgcGFyYW1zTWFwKTtcbiAgICAgICAgICAgIGlmIChjaGlsZENvbXApIHtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRDb21wLmFkZEl0ZW1zICYmIGNoaWxkTm9kZS5jaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY3JlYXRlQ2hpbGRDb21wb25lbnRzRnJvbVRhZ3MoY2hpbGROb2RlLCBwYXJhbXNNYXApO1xuICAgICAgICAgICAgICAgICAgICAvLyBjb252ZXJ0aW5nIGZyb20gSFRNTENvbGxlY3Rpb24gdG8gQXJyYXlcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1zID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoY2hpbGROb2RlLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRDb21wLmFkZEl0ZW1zKGl0ZW1zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gcmVwbGFjZSB0aGUgdGFnIChlZyBhZy1jaGVja2JveCkgd2l0aCB0aGUgcHJvcGVyIEhUTUxFbGVtZW50IChlZyAnZGl2JykgaW4gdGhlIGRvbVxuICAgICAgICAgICAgICAgIF90aGlzLnN3YXBDb21wb25lbnRGb3JOb2RlKGNoaWxkQ29tcCwgcGFyZW50Tm9kZSwgY2hpbGROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNoaWxkTm9kZS5jaGlsZE5vZGVzKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY3JlYXRlQ2hpbGRDb21wb25lbnRzRnJvbVRhZ3MoY2hpbGROb2RlLCBwYXJhbXNNYXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuY3JlYXRlQ29tcG9uZW50RnJvbUVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudCwgYWZ0ZXJQcmVDcmVhdGVDYWxsYmFjaywgcGFyYW1zTWFwKSB7XG4gICAgICAgIHZhciBrZXkgPSBlbGVtZW50Lm5vZGVOYW1lO1xuICAgICAgICB2YXIgY29tcG9uZW50UGFyYW1zID0gcGFyYW1zTWFwID8gcGFyYW1zTWFwW2VsZW1lbnQuZ2V0QXR0cmlidXRlKCdyZWYnKV0gOiB1bmRlZmluZWQ7XG4gICAgICAgIHZhciBDb21wb25lbnRDbGFzcyA9IHRoaXMuYWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeS5nZXRDb21wb25lbnRDbGFzcyhrZXkpO1xuICAgICAgICBpZiAoQ29tcG9uZW50Q2xhc3MpIHtcbiAgICAgICAgICAgIENvbXBvbmVudC5lbGVtZW50R2V0dGluZ0NyZWF0ZWQgPSBlbGVtZW50O1xuICAgICAgICAgICAgdmFyIG5ld0NvbXBvbmVudCA9IG5ldyBDb21wb25lbnRDbGFzcyhjb21wb25lbnRQYXJhbXMpO1xuICAgICAgICAgICAgbmV3Q29tcG9uZW50LnNldFBhcmVudENvbXBvbmVudCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQmVhbihuZXdDb21wb25lbnQsIG51bGwsIGFmdGVyUHJlQ3JlYXRlQ2FsbGJhY2spO1xuICAgICAgICAgICAgcmV0dXJuIG5ld0NvbXBvbmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuY29weUF0dHJpYnV0ZXNGcm9tTm9kZSA9IGZ1bmN0aW9uIChzb3VyY2UsIGRlc3QpIHtcbiAgICAgICAgaXRlcmF0ZU5hbWVkTm9kZU1hcChzb3VyY2UuYXR0cmlidXRlcywgZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7IHJldHVybiBkZXN0LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSk7IH0pO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5zd2FwQ29tcG9uZW50Rm9yTm9kZSA9IGZ1bmN0aW9uIChuZXdDb21wb25lbnQsIHBhcmVudE5vZGUsIGNoaWxkTm9kZSkge1xuICAgICAgICB2YXIgZUNvbXBvbmVudCA9IG5ld0NvbXBvbmVudC5nZXRHdWkoKTtcbiAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoZUNvbXBvbmVudCwgY2hpbGROb2RlKTtcbiAgICAgICAgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoZG9jdW1lbnQuY3JlYXRlQ29tbWVudChjaGlsZE5vZGUubm9kZU5hbWUpLCBlQ29tcG9uZW50KTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyh0aGlzLmRlc3Ryb3lCZWFuLmJpbmQodGhpcywgbmV3Q29tcG9uZW50KSk7XG4gICAgICAgIHRoaXMuc3dhcEluQ29tcG9uZW50Rm9yUXVlcnlTZWxlY3RvcnMobmV3Q29tcG9uZW50LCBjaGlsZE5vZGUpO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5zd2FwSW5Db21wb25lbnRGb3JRdWVyeVNlbGVjdG9ycyA9IGZ1bmN0aW9uIChuZXdDb21wb25lbnQsIGNoaWxkTm9kZSkge1xuICAgICAgICB2YXIgdGhpc05vVHlwZSA9IHRoaXM7XG4gICAgICAgIHRoaXMuaXRlcmF0ZU92ZXJRdWVyeVNlbGVjdG9ycyhmdW5jdGlvbiAocXVlcnlTZWxlY3Rvcikge1xuICAgICAgICAgICAgaWYgKHRoaXNOb1R5cGVbcXVlcnlTZWxlY3Rvci5hdHRyaWJ1dGVOYW1lXSA9PT0gY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgdGhpc05vVHlwZVtxdWVyeVNlbGVjdG9yLmF0dHJpYnV0ZU5hbWVdID0gbmV3Q29tcG9uZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuaXRlcmF0ZU92ZXJRdWVyeVNlbGVjdG9ycyA9IGZ1bmN0aW9uIChhY3Rpb24pIHtcbiAgICAgICAgdmFyIHRoaXNQcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcyk7XG4gICAgICAgIHdoaWxlICh0aGlzUHJvdG90eXBlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBtZXRhRGF0YSA9IHRoaXNQcm90b3R5cGUuX19hZ0NvbXBvbmVudE1ldGFEYXRhO1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRQcm90b05hbWUgPSBnZXRGdW5jdGlvbk5hbWUodGhpc1Byb3RvdHlwZS5jb25zdHJ1Y3Rvcik7XG4gICAgICAgICAgICBpZiAobWV0YURhdGEgJiYgbWV0YURhdGFbY3VycmVudFByb3RvTmFtZV0gJiYgbWV0YURhdGFbY3VycmVudFByb3RvTmFtZV0ucXVlcnlTZWxlY3RvcnMpIHtcbiAgICAgICAgICAgICAgICBtZXRhRGF0YVtjdXJyZW50UHJvdG9OYW1lXS5xdWVyeVNlbGVjdG9ycy5mb3JFYWNoKGZ1bmN0aW9uIChxdWVyeVNlbGVjdG9yKSB7IHJldHVybiBhY3Rpb24ocXVlcnlTZWxlY3Rvcik7IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpc1Byb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzUHJvdG90eXBlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5zZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uICh0ZW1wbGF0ZSwgcGFyYW1zTWFwKSB7XG4gICAgICAgIHZhciBlR3VpID0gbG9hZFRlbXBsYXRlKHRlbXBsYXRlKTtcbiAgICAgICAgdGhpcy5zZXRUZW1wbGF0ZUZyb21FbGVtZW50KGVHdWksIHBhcmFtc01hcCk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnNldFRlbXBsYXRlRnJvbUVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudCwgcGFyYW1zTWFwKSB7XG4gICAgICAgIHRoaXMuZUd1aSA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuZUd1aS5fX2FnQ29tcG9uZW50ID0gdGhpcztcbiAgICAgICAgdGhpcy53aXJlUXVlcnlTZWxlY3RvcnMoKTtcbiAgICAgICAgLy8gY29udGV4dCB3aWxsIG5vdCBiZSBhdmFpbGFibGUgd2hlbiB1c2VyIHNldHMgdGVtcGxhdGUgaW4gY29uc3RydWN0b3JcbiAgICAgICAgaWYgKCEhdGhpcy5nZXRDb250ZXh0KCkpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQ2hpbGRDb21wb25lbnRzRnJvbVRhZ3ModGhpcy5nZXRHdWkoKSwgcGFyYW1zTWFwKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5jcmVhdGVDaGlsZENvbXBvbmVudHNQcmVDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHVpIGV4aXN0cyBpZiB1c2VyIHNldHMgdGVtcGxhdGUgaW4gY29uc3RydWN0b3IuIHdoZW4gdGhpcyBoYXBwZW5zLCB3ZSBoYXZlIHRvIHdhaXQgZm9yIHRoZSBjb250ZXh0XG4gICAgICAgIC8vIHRvIGJlIGF1dG9XaXJlZCBmaXJzdCBiZWZvcmUgd2UgY2FuIGNyZWF0ZSBjaGlsZCBjb21wb25lbnRzLlxuICAgICAgICBpZiAoISF0aGlzLmdldEd1aSgpKSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZUNoaWxkQ29tcG9uZW50c0Zyb21UYWdzKHRoaXMuZ2V0R3VpKCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLndpcmVRdWVyeVNlbGVjdG9ycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmVHdWkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdGhpc05vVHlwZSA9IHRoaXM7XG4gICAgICAgIHRoaXMuaXRlcmF0ZU92ZXJRdWVyeVNlbGVjdG9ycyhmdW5jdGlvbiAocXVlcnlTZWxlY3Rvcikge1xuICAgICAgICAgICAgdmFyIHNldFJlc3VsdCA9IGZ1bmN0aW9uIChyZXN1bHQpIHsgcmV0dXJuIHRoaXNOb1R5cGVbcXVlcnlTZWxlY3Rvci5hdHRyaWJ1dGVOYW1lXSA9IHJlc3VsdDsgfTtcbiAgICAgICAgICAgIC8vIGlmIGl0J3MgYSByZWYgc2VsZWN0b3IsIGFuZCBtYXRjaCBpcyBvbiB0b3AgbGV2ZWwgY29tcG9uZW50LCB3ZSByZXR1cm5cbiAgICAgICAgICAgIC8vIHRoZSBlbGVtZW50LiBvdGhlcndpc2Ugbm8gd2F5IG9mIGNvbXBvbmVudHMgcHV0dGluZyByZWY9eHh4IG9uIHRoZSB0b3BcbiAgICAgICAgICAgIC8vIGxldmVsIGVsZW1lbnQgYXMgcXVlcnlTZWxlY3RvciBvbmx5IGxvb2tzIGF0IGNoaWxkcmVuLlxuICAgICAgICAgICAgdmFyIHRvcExldmVsUmVmTWF0Y2ggPSBxdWVyeVNlbGVjdG9yLnJlZlNlbGVjdG9yXG4gICAgICAgICAgICAgICAgJiYgX3RoaXMuZUd1aS5nZXRBdHRyaWJ1dGUoJ3JlZicpID09PSBxdWVyeVNlbGVjdG9yLnJlZlNlbGVjdG9yO1xuICAgICAgICAgICAgaWYgKHRvcExldmVsUmVmTWF0Y2gpIHtcbiAgICAgICAgICAgICAgICBzZXRSZXN1bHQoX3RoaXMuZUd1aSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgdXNlIHF1ZXJ5U2VsZWN0b3IsIHdoaWNoIGxvb2tzIGF0IGNoaWxkcmVuXG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdE9mUXVlcnkgPSBfdGhpcy5lR3VpLnF1ZXJ5U2VsZWN0b3IocXVlcnlTZWxlY3Rvci5xdWVyeVNlbGVjdG9yKTtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0T2ZRdWVyeSkge1xuICAgICAgICAgICAgICAgICAgICBzZXRSZXN1bHQocmVzdWx0T2ZRdWVyeS5fX2FnQ29tcG9uZW50IHx8IHJlc3VsdE9mUXVlcnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmdldEd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUd1aTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuZ2V0Rm9jdXNhYmxlRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUd1aTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuc2V0UGFyZW50Q29tcG9uZW50ID0gZnVuY3Rpb24gKGNvbXBvbmVudCkge1xuICAgICAgICB0aGlzLnBhcmVudENvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUuZ2V0UGFyZW50Q29tcG9uZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnRDb21wb25lbnQ7XG4gICAgfTtcbiAgICAvLyB0aGlzIG1ldGhvZCBpcyBmb3Igb2xkZXIgY29kZSwgdGhhdCB3YW50cyB0byBwcm92aWRlIHRoZSBndWkgZWxlbWVudCxcbiAgICAvLyBpdCBpcyBub3QgaW50ZW5kZWQgZm9yIHRoaXMgdG8gYmUgaW4gYWctU3RhY2tcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnNldEd1aSA9IGZ1bmN0aW9uIChlR3VpKSB7XG4gICAgICAgIHRoaXMuZUd1aSA9IGVHdWk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnF1ZXJ5Rm9ySHRtbEVsZW1lbnQgPSBmdW5jdGlvbiAoY3NzU2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUd1aS5xdWVyeVNlbGVjdG9yKGNzc1NlbGVjdG9yKTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUucXVlcnlGb3JIdG1sSW5wdXRFbGVtZW50ID0gZnVuY3Rpb24gKGNzc1NlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVHdWkucXVlcnlTZWxlY3Rvcihjc3NTZWxlY3Rvcik7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmFwcGVuZENoaWxkID0gZnVuY3Rpb24gKG5ld0NoaWxkLCBjb250YWluZXIpIHtcbiAgICAgICAgaWYgKG5ld0NoaWxkID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbnRhaW5lcikge1xuICAgICAgICAgICAgY29udGFpbmVyID0gdGhpcy5lR3VpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc05vZGVPckVsZW1lbnQobmV3Q2hpbGQpKSB7XG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQobmV3Q2hpbGQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGNoaWxkQ29tcG9uZW50ID0gbmV3Q2hpbGQ7XG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoY2hpbGRDb21wb25lbnQuZ2V0R3VpKCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmlzRGlzcGxheWVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5ZWQ7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnNldFZpc2libGUgPSBmdW5jdGlvbiAodmlzaWJsZSkge1xuICAgICAgICBpZiAodmlzaWJsZSAhPT0gdGhpcy52aXNpYmxlKSB7XG4gICAgICAgICAgICB0aGlzLnZpc2libGUgPSB2aXNpYmxlO1xuICAgICAgICAgICAgc2V0VmlzaWJsZSh0aGlzLmVHdWksIHZpc2libGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLnNldERpc3BsYXllZCA9IGZ1bmN0aW9uIChkaXNwbGF5ZWQpIHtcbiAgICAgICAgaWYgKGRpc3BsYXllZCAhPT0gdGhpcy5kaXNwbGF5ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGxheWVkID0gZGlzcGxheWVkO1xuICAgICAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZUd1aSwgZGlzcGxheWVkKTtcbiAgICAgICAgICAgIHZhciBldmVudF8xID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IENvbXBvbmVudC5FVkVOVF9ESVNQTEFZRURfQ0hBTkdFRCxcbiAgICAgICAgICAgICAgICB2aXNpYmxlOiB0aGlzLmRpc3BsYXllZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy50b29sdGlwRmVhdHVyZSkge1xuICAgICAgICAgICAgdGhpcy50b29sdGlwRmVhdHVyZSA9IHRoaXMuZGVzdHJveUJlYW4odGhpcy50b29sdGlwRmVhdHVyZSk7XG4gICAgICAgIH1cbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmFkZEd1aUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZUd1aS5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZUd1aS5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7IH0pO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5hZGRDc3NDbGFzcyA9IGZ1bmN0aW9uIChjbGFzc05hbWUpIHtcbiAgICAgICAgdGhpcy5jc3NDbGFzc01hbmFnZXIuYWRkQ3NzQ2xhc3MoY2xhc3NOYW1lKTtcbiAgICB9O1xuICAgIENvbXBvbmVudC5wcm90b3R5cGUucmVtb3ZlQ3NzQ2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7XG4gICAgICAgIHRoaXMuY3NzQ2xhc3NNYW5hZ2VyLnJlbW92ZUNzc0NsYXNzKGNsYXNzTmFtZSk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmNvbnRhaW5zQ3NzQ2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNzc0NsYXNzTWFuYWdlci5jb250YWluc0Nzc0NsYXNzKGNsYXNzTmFtZSk7XG4gICAgfTtcbiAgICBDb21wb25lbnQucHJvdG90eXBlLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lLCBhZGRPclJlbW92ZSkge1xuICAgICAgICB0aGlzLmNzc0NsYXNzTWFuYWdlci5hZGRPclJlbW92ZUNzc0NsYXNzKGNsYXNzTmFtZSwgYWRkT3JSZW1vdmUpO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5nZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5lR3VpO1xuICAgICAgICByZXR1cm4gZUd1aSA/IGVHdWkuZ2V0QXR0cmlidXRlKGtleSkgOiBudWxsO1xuICAgIH07XG4gICAgQ29tcG9uZW50LnByb3RvdHlwZS5nZXRSZWZFbGVtZW50ID0gZnVuY3Rpb24gKHJlZk5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVlcnlGb3JIdG1sRWxlbWVudChcIltyZWY9XFxcIlwiICsgcmVmTmFtZSArIFwiXFxcIl1cIik7XG4gICAgfTtcbiAgICBDb21wb25lbnQuRVZFTlRfRElTUExBWUVEX0NIQU5HRUQgPSAnZGlzcGxheWVkQ2hhbmdlZCc7XG4gICAgX19kZWNvcmF0ZSQycChbXG4gICAgICAgIEF1dG93aXJlZCgnYWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeScpXG4gICAgXSwgQ29tcG9uZW50LnByb3RvdHlwZSwgXCJhZ1N0YWNrQ29tcG9uZW50c1JlZ2lzdHJ5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQycChbXG4gICAgICAgIFByZUNvbnN0cnVjdFxuICAgIF0sIENvbXBvbmVudC5wcm90b3R5cGUsIFwicHJlQ29uc3RydWN0T25Db21wb25lbnRcIiwgbnVsbCk7XG4gICAgX19kZWNvcmF0ZSQycChbXG4gICAgICAgIFByZUNvbnN0cnVjdFxuICAgIF0sIENvbXBvbmVudC5wcm90b3R5cGUsIFwiY3JlYXRlQ2hpbGRDb21wb25lbnRzUHJlQ29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBDb21wb25lbnQ7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbmZ1bmN0aW9uIFF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpIHtcbiAgICByZXR1cm4gcXVlcnlTZWxlY3RvckZ1bmMuYmluZCh0aGlzLCBzZWxlY3RvciwgdW5kZWZpbmVkKTtcbn1cbmZ1bmN0aW9uIFJlZlNlbGVjdG9yKHJlZikge1xuICAgIHJldHVybiBxdWVyeVNlbGVjdG9yRnVuYy5iaW5kKHRoaXMsIFwiW3JlZj1cIiArIHJlZiArIFwiXVwiLCByZWYpO1xufVxuZnVuY3Rpb24gcXVlcnlTZWxlY3RvckZ1bmMoc2VsZWN0b3IsIHJlZlNlbGVjdG9yLCBjbGFzc1Byb3RvdHlwZSwgbWV0aG9kT3JBdHRyaWJ1dGVOYW1lLCBpbmRleCkge1xuICAgIGlmIChzZWxlY3RvciA9PT0gbnVsbCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBRdWVyeVNlbGVjdG9yIHNlbGVjdG9yIHNob3VsZCBub3QgYmUgbnVsbCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0eXBlb2YgaW5kZXggPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IFF1ZXJ5U2VsZWN0b3Igc2hvdWxkIGJlIG9uIGFuIGF0dHJpYnV0ZScpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGFkZFRvT2JqZWN0UHJvcHMoY2xhc3NQcm90b3R5cGUsICdxdWVyeVNlbGVjdG9ycycsIHtcbiAgICAgICAgYXR0cmlidXRlTmFtZTogbWV0aG9kT3JBdHRyaWJ1dGVOYW1lLFxuICAgICAgICBxdWVyeVNlbGVjdG9yOiBzZWxlY3RvcixcbiAgICAgICAgcmVmU2VsZWN0b3I6IHJlZlNlbGVjdG9yXG4gICAgfSk7XG59XG4vLyAvLyB0aGluayB3ZSBzaG91bGQgdGFrZSB0aGlzIG91dCwgcHV0IHByb3BlcnR5IGJpbmRpbmdzIG9uIHRoZVxuLy8gZXhwb3J0IGZ1bmN0aW9uIE1ldGhvZChldmVudE5hbWU/OiBzdHJpbmcpOiBGdW5jdGlvbiB7XG4vLyAgICAgcmV0dXJuIG1ldGhvZEZ1bmMuYmluZCh0aGlzLCBldmVudE5hbWUpO1xuLy8gfVxuLy9cbi8vIGZ1bmN0aW9uIG1ldGhvZEZ1bmMoYWxpYXM6IHN0cmluZywgdGFyZ2V0OiBPYmplY3QsIG1ldGhvZE5hbWU6IHN0cmluZykge1xuLy8gICAgIGlmIChhbGlhcyA9PT0gbnVsbCkge1xuLy8gICAgICAgICBjb25zb2xlLmVycm9yKFwiQUcgR3JpZDogRXZlbnRMaXN0ZW5lciBldmVudE5hbWUgc2hvdWxkIG5vdCBiZSBudWxsXCIpO1xuLy8gICAgICAgICByZXR1cm47XG4vLyAgICAgfVxuLy9cbi8vICAgICBhZGRUb09iamVjdFByb3BzKHRhcmdldCwgJ21ldGhvZHMnLCB7XG4vLyAgICAgICAgIG1ldGhvZE5hbWU6IG1ldGhvZE5hbWUsXG4vLyAgICAgICAgIGFsaWFzOiBhbGlhc1xuLy8gICAgIH0pO1xuLy8gfVxuZnVuY3Rpb24gYWRkVG9PYmplY3RQcm9wcyh0YXJnZXQsIGtleSwgdmFsdWUpIHtcbiAgICAvLyBpdCdzIGFuIGF0dHJpYnV0ZSBvbiB0aGUgY2xhc3NcbiAgICB2YXIgcHJvcHMgPSBnZXRPckNyZWF0ZVByb3BzKHRhcmdldCwgZ2V0RnVuY3Rpb25OYW1lKHRhcmdldC5jb25zdHJ1Y3RvcikpO1xuICAgIGlmICghcHJvcHNba2V5XSkge1xuICAgICAgICBwcm9wc1trZXldID0gW107XG4gICAgfVxuICAgIHByb3BzW2tleV0ucHVzaCh2YWx1ZSk7XG59XG5mdW5jdGlvbiBnZXRPckNyZWF0ZVByb3BzKHRhcmdldCwgaW5zdGFuY2VOYW1lKSB7XG4gICAgaWYgKCF0YXJnZXQuX19hZ0NvbXBvbmVudE1ldGFEYXRhKSB7XG4gICAgICAgIHRhcmdldC5fX2FnQ29tcG9uZW50TWV0YURhdGEgPSB7fTtcbiAgICB9XG4gICAgaWYgKCF0YXJnZXQuX19hZ0NvbXBvbmVudE1ldGFEYXRhW2luc3RhbmNlTmFtZV0pIHtcbiAgICAgICAgdGFyZ2V0Ll9fYWdDb21wb25lbnRNZXRhRGF0YVtpbnN0YW5jZU5hbWVdID0ge307XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQuX19hZ0NvbXBvbmVudE1ldGFEYXRhW2luc3RhbmNlTmFtZV07XG59XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMk4gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJvID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG4vLyBvcHRpb25hbCBmbG9hdGluZyBmaWx0ZXIgZm9yIHVzZXIgcHJvdmlkZWQgZmlsdGVycyAtIGluc3RlYWQgb2YgcHJvdmlkaW5nIGEgZmxvYXRpbmcgZmlsdGVyLFxuLy8gdGhleSBjYW4gcHJvdmlkZSBhIGdldE1vZGVsQXNTdHJpbmcoKSBtZXRob2Qgb24gdGhlIGZpbHRlciBpbnN0ZWFkLiB0aGlzIGNsYXNzIGp1c3QgZGlzcGxheXNcbi8vIHRoZSBzdHJpbmcgcmV0dXJuZWQgZnJvbSBnZXRNb2RlbEFzU3RyaW5nKClcbnZhciBSZWFkT25seUZsb2F0aW5nRmlsdGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyTihSZWFkT25seUZsb2F0aW5nRmlsdGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJlYWRPbmx5RmxvYXRpbmdGaWx0ZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCAvKiBodG1sICovIFwiXFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmxvYXRpbmctZmlsdGVyLWlucHV0XFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgICAgICA8YWctaW5wdXQtdGV4dC1maWVsZCByZWY9XFxcImVGbG9hdGluZ0ZpbHRlclRleHRcXFwiPjwvYWctaW5wdXQtdGV4dC1maWVsZD5cXG4gICAgICAgICAgICA8L2Rpdj5cIikgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gdGhpcyBpcyBhIHVzZXIgY29tcG9uZW50LCBhbmQgSUNvbXBvbmVudCBoYXMgXCJwdWJsaWMgZGVzdHJveSgpXCIgYXMgcGFydCBvZiB0aGUgaW50ZXJmYWNlLlxuICAgIC8vIHNvIHdlIG5lZWQgdG8gb3ZlcnJpZGUgZGVzdHJveSgpIGp1c3QgdG8gbWFrZSB0aGUgbWV0aG9kIHB1YmxpYy5cbiAgICBSZWFkT25seUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIFJlYWRPbmx5RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICB2YXIgZGlzcGxheU5hbWUgPSB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXlOYW1lRm9yQ29sdW1uKHBhcmFtcy5jb2x1bW4sICdoZWFkZXInLCB0cnVlKTtcbiAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHRoaXMuZUZsb2F0aW5nRmlsdGVyVGV4dFxuICAgICAgICAgICAgLnNldERpc2FibGVkKHRydWUpXG4gICAgICAgICAgICAuc2V0SW5wdXRBcmlhTGFiZWwoZGlzcGxheU5hbWUgKyBcIiBcIiArIHRyYW5zbGF0ZSgnYXJpYUZpbHRlcklucHV0JywgJ0ZpbHRlciBJbnB1dCcpKTtcbiAgICB9O1xuICAgIFJlYWRPbmx5RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLm9uUGFyZW50TW9kZWxDaGFuZ2VkID0gZnVuY3Rpb24gKHBhcmVudE1vZGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghcGFyZW50TW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuZUZsb2F0aW5nRmlsdGVyVGV4dC5zZXRWYWx1ZSgnJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXJhbXMucGFyZW50RmlsdGVySW5zdGFuY2UoZnVuY3Rpb24gKGZpbHRlckluc3RhbmNlKSB7XG4gICAgICAgICAgICAvLyBpdCB3b3VsZCBiZSBuaWNlIHRvIGNoZWNrIGlmIGdldE1vZGVsQXNTdHJpbmcgd2FzIHByZXNlbnQgYmVmb3JlIGNyZWF0aW5nIHRoaXMgY29tcG9uZW50LFxuICAgICAgICAgICAgLy8gaG93ZXZlciB0aGF0IGlzIG5vdCBwb3NzaWJsZSwgYXMgUmVhY3QgSG9va3MgYW5kIFZ1ZUpTIGRvbid0IGF0dGFjaGVkIHRoZSBtZXRob2RzIHRvIHRoZSBGaWx0ZXIgdW50aWxcbiAgICAgICAgICAgIC8vIEFGVEVSIHRoZSBmaWx0ZXIgaXMgY3JlYXRlZCwgbm90IGFsbG93aW5nIGluc3BlY3Rpb24gYmVmb3JlIHRoaXMgKHdlIGNyZWF0ZSBmbG9hdGluZyBmaWx0ZXJzIGFzIGNvbHVtbnNcbiAgICAgICAgICAgIC8vIGFyZSBkcmF3biwgYnV0IHRoZSBwYXJlbnQgZmlsdGVycyBhcmUgb25seSBjcmVhdGVkIHdoZW4gbmVlZGVkKS5cbiAgICAgICAgICAgIGlmIChmaWx0ZXJJbnN0YW5jZS5nZXRNb2RlbEFzU3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1vZGVsQXNTdHJpbmcgPSBmaWx0ZXJJbnN0YW5jZS5nZXRNb2RlbEFzU3RyaW5nKHBhcmVudE1vZGVsKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lRmxvYXRpbmdGaWx0ZXJUZXh0LnNldFZhbHVlKG1vZGVsQXNTdHJpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMm8oW1xuICAgICAgICBSZWZTZWxlY3RvcignZUZsb2F0aW5nRmlsdGVyVGV4dCcpXG4gICAgXSwgUmVhZE9ubHlGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUsIFwiZUZsb2F0aW5nRmlsdGVyVGV4dFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMm8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBSZWFkT25seUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIHJldHVybiBSZWFkT25seUZsb2F0aW5nRmlsdGVyO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuLyoqIFByb3ZpZGVzIHN5bmMgYWNjZXNzIHRvIGFzeW5jIGNvbXBvbmVudC4gRGF0ZSBjb21wb25lbnQgY2FuIGJlIGxhenkgY3JlYXRlZCAtIHRoaXMgY2xhc3MgZW5jYXBzdWxhdGVzXG4gKiB0aGlzIGJ5IGtlZXBpbmcgdmFsdWUgbG9jYWxseSB1bnRpbCBEYXRlQ29tcCBoYXMgbG9hZGVkLCB0aGVuIHBhc3NpbmcgRGF0ZUNvbXAgdGhlIHZhbHVlLiAqL1xudmFyIERhdGVDb21wV3JhcHBlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEYXRlQ29tcFdyYXBwZXIoY29udGV4dCwgdXNlckNvbXBvbmVudEZhY3RvcnksIGRhdGVDb21wb25lbnRQYXJhbXMsIGVQYXJlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hbGl2ZSA9IHRydWU7XG4gICAgICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIHRoaXMuZVBhcmVudCA9IGVQYXJlbnQ7XG4gICAgICAgIHZhciBjb21wRGV0YWlscyA9IHVzZXJDb21wb25lbnRGYWN0b3J5LmdldERhdGVDb21wRGV0YWlscyhkYXRlQ29tcG9uZW50UGFyYW1zKTtcbiAgICAgICAgdmFyIHByb21pc2UgPSBjb21wRGV0YWlscy5uZXdBZ1N0YWNrSW5zdGFuY2UoKTtcbiAgICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChkYXRlQ29tcCkge1xuICAgICAgICAgICAgLy8gYmVjYXVzZSBhc3luYywgY2hlY2sgdGhlIGZpbHRlciBzdGlsbCBleGlzdHMgYWZ0ZXIgY29tcG9uZW50IGNvbWVzIGJhY2tcbiAgICAgICAgICAgIGlmICghX3RoaXMuYWxpdmUpIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmRlc3Ryb3lCZWFuKGRhdGVDb21wKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5kYXRlQ29tcCA9IGRhdGVDb21wO1xuICAgICAgICAgICAgaWYgKCFkYXRlQ29tcCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVQYXJlbnQuYXBwZW5kQ2hpbGQoZGF0ZUNvbXAuZ2V0R3VpKCkpO1xuICAgICAgICAgICAgaWYgKGRhdGVDb21wLmFmdGVyR3VpQXR0YWNoZWQpIHtcbiAgICAgICAgICAgICAgICBkYXRlQ29tcC5hZnRlckd1aUF0dGFjaGVkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3RoaXMudGVtcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgZGF0ZUNvbXAuc2V0RGF0ZShfdGhpcy50ZW1wVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmRpc2FibGVkICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXREYXRlQ29tcERpc2FibGVkKF90aGlzLmRpc2FibGVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIERhdGVDb21wV3JhcHBlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hbGl2ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRhdGVDb21wID0gdGhpcy5jb250ZXh0LmRlc3Ryb3lCZWFuKHRoaXMuZGF0ZUNvbXApO1xuICAgIH07XG4gICAgRGF0ZUNvbXBXcmFwcGVyLnByb3RvdHlwZS5nZXREYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRlQ29tcCA/IHRoaXMuZGF0ZUNvbXAuZ2V0RGF0ZSgpIDogdGhpcy50ZW1wVmFsdWU7XG4gICAgfTtcbiAgICBEYXRlQ29tcFdyYXBwZXIucHJvdG90eXBlLnNldERhdGUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMuZGF0ZUNvbXApIHtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUNvbXAuc2V0RGF0ZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnRlbXBWYWx1ZSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlQ29tcFdyYXBwZXIucHJvdG90eXBlLnNldERpc2FibGVkID0gZnVuY3Rpb24gKGRpc2FibGVkKSB7XG4gICAgICAgIGlmICh0aGlzLmRhdGVDb21wKSB7XG4gICAgICAgICAgICB0aGlzLnNldERhdGVDb21wRGlzYWJsZWQoZGlzYWJsZWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGRpc2FibGVkO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEYXRlQ29tcFdyYXBwZXIucHJvdG90eXBlLnNldERpc3BsYXllZCA9IGZ1bmN0aW9uIChkaXNwbGF5ZWQpIHtcbiAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZVBhcmVudCwgZGlzcGxheWVkKTtcbiAgICB9O1xuICAgIERhdGVDb21wV3JhcHBlci5wcm90b3R5cGUuc2V0SW5wdXRQbGFjZWhvbGRlciA9IGZ1bmN0aW9uIChwbGFjZWhvbGRlcikge1xuICAgICAgICBpZiAodGhpcy5kYXRlQ29tcCAmJiB0aGlzLmRhdGVDb21wLnNldElucHV0UGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUNvbXAuc2V0SW5wdXRQbGFjZWhvbGRlcihwbGFjZWhvbGRlcik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERhdGVDb21wV3JhcHBlci5wcm90b3R5cGUuc2V0SW5wdXRBcmlhTGFiZWwgPSBmdW5jdGlvbiAobGFiZWwpIHtcbiAgICAgICAgaWYgKHRoaXMuZGF0ZUNvbXAgJiYgdGhpcy5kYXRlQ29tcC5zZXRJbnB1dEFyaWFMYWJlbCkge1xuICAgICAgICAgICAgdGhpcy5kYXRlQ29tcC5zZXRJbnB1dEFyaWFMYWJlbChsYWJlbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERhdGVDb21wV3JhcHBlci5wcm90b3R5cGUuYWZ0ZXJHdWlBdHRhY2hlZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuZGF0ZUNvbXAgJiYgdHlwZW9mIHRoaXMuZGF0ZUNvbXAuYWZ0ZXJHdWlBdHRhY2hlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy5kYXRlQ29tcC5hZnRlckd1aUF0dGFjaGVkKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERhdGVDb21wV3JhcHBlci5wcm90b3R5cGUuc2V0RGF0ZUNvbXBEaXNhYmxlZCA9IGZ1bmN0aW9uIChkaXNhYmxlZCkge1xuICAgICAgICBpZiAodGhpcy5kYXRlQ29tcCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZGF0ZUNvbXAuc2V0RGlzYWJsZWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGF0ZUNvbXAuc2V0RGlzYWJsZWQoZGlzYWJsZWQpO1xuICAgIH07XG4gICAgcmV0dXJuIERhdGVDb21wV3JhcHBlcjtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2Fzc2lnbiRkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiRkID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiRkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xuLyogQ29tbW9uIGxvZ2ljIGZvciBvcHRpb25zLCB1c2VkIGJ5IGJvdGggZmlsdGVycyBhbmQgZmxvYXRpbmcgZmlsdGVycy4gKi9cbnZhciBPcHRpb25zRmFjdG9yeSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBPcHRpb25zRmFjdG9yeSgpIHtcbiAgICAgICAgdGhpcy5jdXN0b21GaWx0ZXJPcHRpb25zID0ge307XG4gICAgfVxuICAgIE9wdGlvbnNGYWN0b3J5LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKHBhcmFtcywgZGVmYXVsdE9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5maWx0ZXJPcHRpb25zID0gcGFyYW1zLmZpbHRlck9wdGlvbnMgfHwgZGVmYXVsdE9wdGlvbnM7XG4gICAgICAgIHRoaXMubWFwQ3VzdG9tT3B0aW9ucygpO1xuICAgICAgICB0aGlzLnNlbGVjdERlZmF1bHRJdGVtKHBhcmFtcyk7XG4gICAgICAgIHRoaXMuY2hlY2tGb3JEZXByZWNhdGVkUGFyYW1zKCk7XG4gICAgfTtcbiAgICBPcHRpb25zRmFjdG9yeS5wcm90b3R5cGUuY2hlY2tGb3JEZXByZWNhdGVkUGFyYW1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5maWx0ZXJPcHRpb25zLnNvbWUoZnVuY3Rpb24gKG9wdCkgeyByZXR1cm4gdHlwZW9mIG9wdCAhPSAnc3RyaW5nJyAmJiBvcHQudGVzdCAhPSBudWxsOyB9KSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogW0lGaWx0ZXJPcHRpb25EZWZdIHNpbmNlIHYyNi4yLjAsIHRlc3QoKSBoYXMgYmVlbiByZXBsYWNlZCB3aXRoIHByZWRpY2F0ZSgpLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5maWx0ZXJPcHRpb25zLnNvbWUoZnVuY3Rpb24gKG9wdCkgeyByZXR1cm4gdHlwZW9mIG9wdCAhPSAnc3RyaW5nJyAmJiBvcHQuaGlkZUZpbHRlcklucHV0ICE9IG51bGw7IH0pKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBbSUZpbHRlck9wdGlvbkRlZl0gc2luY2UgdjI2LjIuMCwgdXNlT2ZIaWRlRmlsdGVySW5wdXQgaGFzIGJlZW4gcmVwbGFjZWQgd2l0aCBudW1iZXJPZklucHV0cy5cIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE9wdGlvbnNGYWN0b3J5LnByb3RvdHlwZS5nZXRGaWx0ZXJPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5maWx0ZXJPcHRpb25zO1xuICAgIH07XG4gICAgT3B0aW9uc0ZhY3RvcnkucHJvdG90eXBlLm1hcEN1c3RvbU9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5maWx0ZXJPcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5maWx0ZXJPcHRpb25zLmZvckVhY2goZnVuY3Rpb24gKGZpbHRlck9wdGlvbikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmaWx0ZXJPcHRpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlcXVpcmVkUHJvcGVydGllcyA9IFtbJ2Rpc3BsYXlLZXknXSwgWydkaXNwbGF5TmFtZSddLCBbJ3ByZWRpY2F0ZScsICd0ZXN0J11dO1xuICAgICAgICAgICAgdmFyIHByb3BlcnR5Q2hlY2sgPSBmdW5jdGlvbiAoa2V5cykge1xuICAgICAgICAgICAgICAgIGlmICgha2V5cy5zb21lKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIGZpbHRlck9wdGlvbltrZXldICE9IG51bGw7IH0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGlnbm9yaW5nIEZpbHRlck9wdGlvbkRlZiBhcyBpdCBkb2Vzbid0IGNvbnRhaW4gb25lIG9mICdcIiArIGtleXMgKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKCFyZXF1aXJlZFByb3BlcnRpZXMuZXZlcnkocHJvcGVydHlDaGVjaykpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5maWx0ZXJPcHRpb25zID0gX3RoaXMuZmlsdGVyT3B0aW9ucy5maWx0ZXIoZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHYgPT09IGZpbHRlck9wdGlvbjsgfSkgfHwgW107XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHRlc3QgPSBmaWx0ZXJPcHRpb24udGVzdDtcbiAgICAgICAgICAgIHZhciBtdXRhdGVkRmlsdGVyT3B0aW9ucyA9IF9fYXNzaWduJGQoe30sIGZpbHRlck9wdGlvbik7XG4gICAgICAgICAgICBpZiAodGVzdCAhPSBudWxsICYmIGZpbHRlck9wdGlvbi5wcmVkaWNhdGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG11dGF0ZWRGaWx0ZXJPcHRpb25zLnByZWRpY2F0ZSA9IGZ1bmN0aW9uICh2LCBjdikgeyByZXR1cm4gdGVzdCh2WzBdLCBjdik7IH07XG4gICAgICAgICAgICAgICAgZGVsZXRlIG11dGF0ZWRGaWx0ZXJPcHRpb25zLnRlc3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobXV0YXRlZEZpbHRlck9wdGlvbnMuaGlkZUZpbHRlcklucHV0ICYmIG11dGF0ZWRGaWx0ZXJPcHRpb25zLm51bWJlck9mSW5wdXRzID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBtdXRhdGVkRmlsdGVyT3B0aW9ucy5udW1iZXJPZklucHV0cyA9IDA7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG11dGF0ZWRGaWx0ZXJPcHRpb25zLmhpZGVGaWx0ZXJJbnB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmN1c3RvbUZpbHRlck9wdGlvbnNbZmlsdGVyT3B0aW9uLmRpc3BsYXlLZXldID0gbXV0YXRlZEZpbHRlck9wdGlvbnM7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT3B0aW9uc0ZhY3RvcnkucHJvdG90eXBlLnNlbGVjdERlZmF1bHRJdGVtID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zLmRlZmF1bHRPcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZGVmYXVsdE9wdGlvbiA9IHBhcmFtcy5kZWZhdWx0T3B0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZmlsdGVyT3B0aW9ucy5sZW5ndGggPj0gMSkge1xuICAgICAgICAgICAgdmFyIGZpcnN0RmlsdGVyT3B0aW9uID0gdGhpcy5maWx0ZXJPcHRpb25zWzBdO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmaXJzdEZpbHRlck9wdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRPcHRpb24gPSBmaXJzdEZpbHRlck9wdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGZpcnN0RmlsdGVyT3B0aW9uLmRpc3BsYXlLZXkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRPcHRpb24gPSBmaXJzdEZpbHRlck9wdGlvbi5kaXNwbGF5S2V5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogaW52YWxpZCBGaWx0ZXJPcHRpb25EZWYgc3VwcGxpZWQgYXMgaXQgZG9lc24ndCBjb250YWluIGEgJ2Rpc3BsYXlLZXknXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBubyBmaWx0ZXIgb3B0aW9ucyBmb3IgZmlsdGVyJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE9wdGlvbnNGYWN0b3J5LnByb3RvdHlwZS5nZXREZWZhdWx0T3B0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kZWZhdWx0T3B0aW9uO1xuICAgIH07XG4gICAgT3B0aW9uc0ZhY3RvcnkucHJvdG90eXBlLmdldEN1c3RvbU9wdGlvbiA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1c3RvbUZpbHRlck9wdGlvbnNbbmFtZV07XG4gICAgfTtcbiAgICByZXR1cm4gT3B0aW9uc0ZhY3Rvcnk7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgREVGQVVMVF9GSUxURVJfTE9DQUxFX1RFWFQgPSB7XG4gICAgYXBwbHlGaWx0ZXI6ICdBcHBseScsXG4gICAgY2xlYXJGaWx0ZXI6ICdDbGVhcicsXG4gICAgcmVzZXRGaWx0ZXI6ICdSZXNldCcsXG4gICAgY2FuY2VsRmlsdGVyOiAnQ2FuY2VsJyxcbiAgICB0ZXh0RmlsdGVyOiAnVGV4dCBGaWx0ZXInLFxuICAgIG51bWJlckZpbHRlcjogJ051bWJlciBGaWx0ZXInLFxuICAgIGRhdGVGaWx0ZXI6ICdEYXRlIEZpbHRlcicsXG4gICAgc2V0RmlsdGVyOiAnU2V0IEZpbHRlcicsXG4gICAgZmlsdGVyT29vOiAnRmlsdGVyLi4uJyxcbiAgICBlbXB0eTogJ0Nob29zZSBPbmUnLFxuICAgIGVxdWFsczogJ0VxdWFscycsXG4gICAgbm90RXF1YWw6ICdOb3QgZXF1YWwnLFxuICAgIGxlc3NUaGFuOiAnTGVzcyB0aGFuJyxcbiAgICBncmVhdGVyVGhhbjogJ0dyZWF0ZXIgdGhhbicsXG4gICAgaW5SYW5nZTogJ0luIHJhbmdlJyxcbiAgICBpblJhbmdlU3RhcnQ6ICdGcm9tJyxcbiAgICBpblJhbmdlRW5kOiAnVG8nLFxuICAgIGxlc3NUaGFuT3JFcXVhbDogJ0xlc3MgdGhhbiBvciBlcXVhbHMnLFxuICAgIGdyZWF0ZXJUaGFuT3JFcXVhbDogJ0dyZWF0ZXIgdGhhbiBvciBlcXVhbHMnLFxuICAgIGNvbnRhaW5zOiAnQ29udGFpbnMnLFxuICAgIG5vdENvbnRhaW5zOiAnTm90IGNvbnRhaW5zJyxcbiAgICBzdGFydHNXaXRoOiAnU3RhcnRzIHdpdGgnLFxuICAgIGVuZHNXaXRoOiAnRW5kcyB3aXRoJyxcbiAgICBibGFuazogJ0JsYW5rJyxcbiAgICBub3RCbGFuazogJ05vdCBibGFuaycsXG4gICAgYW5kQ29uZGl0aW9uOiAnQU5EJyxcbiAgICBvckNvbmRpdGlvbjogJ09SJyxcbiAgICBkYXRlRm9ybWF0T29vOiAneXl5eS1tbS1kZCcsXG59O1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJNID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19hc3NpZ24kYyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fYXNzaWduKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgX19hc3NpZ24kYyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24kYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufTtcbnZhciBfX2RlY29yYXRlJDJuID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgTWFuYWdlZEZvY3VzRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMk0oTWFuYWdlZEZvY3VzRmVhdHVyZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBNYW5hZ2VkRm9jdXNGZWF0dXJlKGVGb2N1c2FibGVFbGVtZW50LCBjYWxsYmFja3MpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrcyA9PT0gdm9pZCAwKSB7IGNhbGxiYWNrcyA9IHt9OyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmVGb2N1c2FibGVFbGVtZW50ID0gZUZvY3VzYWJsZUVsZW1lbnQ7XG4gICAgICAgIF90aGlzLmNhbGxiYWNrcyA9IGNhbGxiYWNrcztcbiAgICAgICAgX3RoaXMuY2FsbGJhY2tzID0gX19hc3NpZ24kYyh7IHNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uOiBmdW5jdGlvbiAoKSB7IHJldHVybiBmYWxzZTsgfSwgb25UYWJLZXlEb3duOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGlmIChlLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbmV4dFJvb3QgPSBfdGhpcy5mb2N1c1NlcnZpY2UuZmluZE5leHRGb2N1c2FibGVFbGVtZW50KF90aGlzLmVGb2N1c2FibGVFbGVtZW50LCBmYWxzZSwgZS5zaGlmdEtleSk7XG4gICAgICAgICAgICAgICAgaWYgKCFuZXh0Um9vdCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG5leHRSb290LmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfSB9LCBjYWxsYmFja3MpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE1hbmFnZWRGb2N1c0ZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZUZvY3VzYWJsZUVsZW1lbnQuY2xhc3NMaXN0LmFkZChNYW5hZ2VkRm9jdXNGZWF0dXJlLkZPQ1VTX01BTkFHRURfQ0xBU1MpO1xuICAgICAgICB0aGlzLmFkZEtleURvd25MaXN0ZW5lcnModGhpcy5lRm9jdXNhYmxlRWxlbWVudCk7XG4gICAgICAgIGlmICh0aGlzLmNhbGxiYWNrcy5vbkZvY3VzSW4pIHtcbiAgICAgICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUZvY3VzYWJsZUVsZW1lbnQsICdmb2N1c2luJywgdGhpcy5jYWxsYmFja3Mub25Gb2N1c0luKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5jYWxsYmFja3Mub25Gb2N1c091dCkge1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lRm9jdXNhYmxlRWxlbWVudCwgJ2ZvY3Vzb3V0JywgdGhpcy5jYWxsYmFja3Mub25Gb2N1c091dCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE1hbmFnZWRGb2N1c0ZlYXR1cmUucHJvdG90eXBlLmFkZEtleURvd25MaXN0ZW5lcnMgPSBmdW5jdGlvbiAoZUd1aSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlR3VpLCAna2V5ZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBpZiAoZS5kZWZhdWx0UHJldmVudGVkIHx8IGlzU3RvcFByb3BhZ2F0aW9uRm9yQWdHcmlkKGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmNhbGxiYWNrcy5zaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvbihlKSkge1xuICAgICAgICAgICAgICAgIHN0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChlKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZS5rZXkgPT09IEtleUNvZGUuVEFCKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2FsbGJhY2tzLm9uVGFiS2V5RG93bihlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKF90aGlzLmNhbGxiYWNrcy5oYW5kbGVLZXlEb3duKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2FsbGJhY2tzLmhhbmRsZUtleURvd24oZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgTWFuYWdlZEZvY3VzRmVhdHVyZS5GT0NVU19NQU5BR0VEX0NMQVNTID0gJ2FnLWZvY3VzLW1hbmFnZWQnO1xuICAgIF9fZGVjb3JhdGUkMm4oW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZvY3VzU2VydmljZScpXG4gICAgXSwgTWFuYWdlZEZvY3VzRmVhdHVyZS5wcm90b3R5cGUsIFwiZm9jdXNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQybihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBNYW5hZ2VkRm9jdXNGZWF0dXJlLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBNYW5hZ2VkRm9jdXNGZWF0dXJlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJMID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQybSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xuLyoqXG4gKiBDb250YWlucyBjb21tb24gbG9naWMgdG8gYWxsIHByb3ZpZGVkIGZpbHRlcnMgKGFwcGx5IGJ1dHRvbiwgY2xlYXIgYnV0dG9uLCBldGMpLlxuICogQWxsIHRoZSBmaWx0ZXJzIHRoYXQgY29tZSB3aXRoIEFHIEdyaWQgZXh0ZW5kIHRoaXMgY2xhc3MuIFVzZXIgZmlsdGVycyBkbyBub3RcbiAqIGV4dGVuZCB0aGlzIGNsYXNzLlxuICpcbiAqIEBwYXJhbSBNIHR5cGUgb2YgZmlsdGVyLW1vZGVsIG1hbmFnZWQgYnkgdGhlIGNvbmNyZXRlIHN1Yi1jbGFzcyB0aGF0IGV4dGVuZHMgdGhpcyB0eXBlXG4gKiBAcGFyYW0gViB0eXBlIG9mIHZhbHVlIG1hbmFnZWQgYnkgdGhlIGNvbmNyZXRlIHN1Yi1jbGFzcyB0aGF0IGV4dGVuZHMgdGhpcyB0eXBlXG4gKi9cbnZhciBQcm92aWRlZEZpbHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkwoUHJvdmlkZWRGaWx0ZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUHJvdmlkZWRGaWx0ZXIoZmlsdGVyTmFtZUtleSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5maWx0ZXJOYW1lS2V5ID0gZmlsdGVyTmFtZUtleTtcbiAgICAgICAgX3RoaXMuYXBwbHlBY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaGlkZVBvcHVwID0gbnVsbDtcbiAgICAgICAgLy8gYWZ0ZXIgdGhlIHVzZXIgaGl0cyAnYXBwbHknIHRoZSBtb2RlbCBnZXRzIGNvcGllZCB0byBoZXJlLiB0aGlzIGlzIHRoZW4gdGhlIG1vZGVsIHRoYXQgd2UgdXNlIGZvclxuICAgICAgICAvLyBhbGwgZmlsdGVyaW5nLiBzbyBpZiB1c2VyIGNoYW5nZXMgVUkgYnV0IGRvZXNuJ3QgaGl0IGFwcGx5LCB0aGVuIHRoZSBVSSB3aWxsIGJlIG91dCBvZiBzeW5jIHdpdGggdGhpcyBtb2RlbC5cbiAgICAgICAgLy8gdGhpcyBpcyB3aGF0IHdlIHdhbnQsIGFzIHRoZSBVSSBzaG91bGQgb25seSBiZWNvbWUgdGhlICdhY3RpdmUnIGZpbHRlciBvbmNlIGl0J3MgYXBwbGllZC4gd2hlbiBhcHBseSBpc1xuICAgICAgICAvLyBpbmFjdGl2ZSwgdGhpcyBtb2RlbCB3aWxsIGJlIGluIHN5bmMgKGZvbGxvd2luZyB0aGUgZGVib3VuY2UgbXMpLiBpZiB0aGUgVUkgaXMgbm90IGEgdmFsaWQgZmlsdGVyXG4gICAgICAgIC8vIChlZyB0aGUgdmFsdWUgaXMgbWlzc2luZyBzbyBub3RoaW5nIHRvIGZpbHRlciBvbiwgb3IgZm9yIHNldCBmaWx0ZXIgYWxsIGNoZWNrYm94ZXMgYXJlIGNoZWNrZWQgc28gZmlsdGVyXG4gICAgICAgIC8vIG5vdCBhY3RpdmUpIHRoZW4gdGhpcyBhcHBsaWVkTW9kZWwgd2lsbCBiZSBudWxsL3VuZGVmaW5lZC5cbiAgICAgICAgX3RoaXMuYXBwbGllZE1vZGVsID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZXNldFRlbXBsYXRlKCk7IC8vIGRvIHRoaXMgZmlyc3QgdG8gY3JlYXRlIHRoZSBET01cbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgTWFuYWdlZEZvY3VzRmVhdHVyZSh0aGlzLmdldEZvY3VzYWJsZUVsZW1lbnQoKSwge1xuICAgICAgICAgICAgaGFuZGxlS2V5RG93bjogdGhpcy5oYW5kbGVLZXlEb3duLmJpbmQodGhpcylcbiAgICAgICAgfSkpO1xuICAgIH07XG4gICAgLy8gb3ZlcnJpZGVcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUuaGFuZGxlS2V5RG93biA9IGZ1bmN0aW9uIChlKSB7IH07XG4gICAgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLmdldEZpbHRlclRpdGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGUodGhpcy5maWx0ZXJOYW1lS2V5KTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5pc0ZpbHRlckFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gZmlsdGVyIGlzIGFjdGl2ZSBpZiB3ZSBoYXZlIGEgdmFsaWQgYXBwbGllZCBtb2RlbFxuICAgICAgICByZXR1cm4gISF0aGlzLmFwcGxpZWRNb2RlbDtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5yZXNldFRlbXBsYXRlID0gZnVuY3Rpb24gKHBhcmFtc01hcCkge1xuICAgICAgICB2YXIgdGVtcGxhdGVTdHJpbmcgPSAvKiBodG1sICovIFwiXFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmlsdGVyLXdyYXBwZXJcXFwiPlxcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1maWx0ZXItYm9keS13cmFwcGVyIGFnLVwiICsgdGhpcy5nZXRDc3NJZGVudGlmaWVyKCkgKyBcIi1ib2R5LXdyYXBwZXJcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgXCIgKyB0aGlzLmNyZWF0ZUJvZHlUZW1wbGF0ZSgpICsgXCJcXG4gICAgICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XCI7XG4gICAgICAgIHRoaXMuc2V0VGVtcGxhdGUodGVtcGxhdGVTdHJpbmcsIHBhcmFtc01hcCk7XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUuaXNSZWFkT25seSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5wcm92aWRlZEZpbHRlclBhcmFtcy5yZWFkT25seTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnNldFBhcmFtcyhwYXJhbXMpO1xuICAgICAgICB0aGlzLnJlc2V0VWlUb0RlZmF1bHRzKHRydWUpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMudXBkYXRlVWlWaXNpYmlsaXR5KCk7XG4gICAgICAgICAgICBfdGhpcy5zZXR1cE9uQnRBcHBseURlYm91bmNlKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLnNldFBhcmFtcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5wcm92aWRlZEZpbHRlclBhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgdGhpcy5hcHBseUFjdGl2ZSA9IFByb3ZpZGVkRmlsdGVyLmlzVXNlQXBwbHlCdXR0b24ocGFyYW1zKTtcbiAgICAgICAgdGhpcy5jcmVhdGVCdXR0b25QYW5lbCgpO1xuICAgIH07XG4gICAgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLmNyZWF0ZUJ1dHRvblBhbmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgYnV0dG9ucyA9IHRoaXMucHJvdmlkZWRGaWx0ZXJQYXJhbXMuYnV0dG9ucztcbiAgICAgICAgaWYgKCFidXR0b25zIHx8IGJ1dHRvbnMubGVuZ3RoIDwgMSB8fCB0aGlzLmlzUmVhZE9ubHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlQnV0dG9uc1BhbmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGVCdXR0b25zUGFuZWwuY2xhc3NMaXN0LmFkZCgnYWctZmlsdGVyLWFwcGx5LXBhbmVsJyk7XG4gICAgICAgIHZhciBhZGRCdXR0b24gPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICAgICAgdmFyIHRleHQ7XG4gICAgICAgICAgICB2YXIgY2xpY2tMaXN0ZW5lcjtcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2FwcGx5JzpcbiAgICAgICAgICAgICAgICAgICAgdGV4dCA9IF90aGlzLnRyYW5zbGF0ZSgnYXBwbHlGaWx0ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpY2tMaXN0ZW5lciA9IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkJ0QXBwbHkoZmFsc2UsIGZhbHNlLCBlKTsgfTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xlYXInOlxuICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gX3RoaXMudHJhbnNsYXRlKCdjbGVhckZpbHRlcicpO1xuICAgICAgICAgICAgICAgICAgICBjbGlja0xpc3RlbmVyID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25CdENsZWFyKCk7IH07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3Jlc2V0JzpcbiAgICAgICAgICAgICAgICAgICAgdGV4dCA9IF90aGlzLnRyYW5zbGF0ZSgncmVzZXRGaWx0ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpY2tMaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uQnRSZXNldCgpOyB9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjYW5jZWwnOlxuICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gX3RoaXMudHJhbnNsYXRlKCdjYW5jZWxGaWx0ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpY2tMaXN0ZW5lciA9IGZ1bmN0aW9uIChlKSB7IF90aGlzLm9uQnRDYW5jZWwoZSk7IH07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogVW5rbm93biBidXR0b24gdHlwZSBzcGVjaWZpZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGJ1dHRvbiA9IGxvYWRUZW1wbGF0ZShcbiAgICAgICAgICAgIC8qIGh0bWwgKi9cbiAgICAgICAgICAgIFwiPGJ1dHRvblxcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cXFwiYnV0dG9uXFxcIlxcbiAgICAgICAgICAgICAgICAgICAgcmVmPVxcXCJcIiArIHR5cGUgKyBcIkZpbHRlckJ1dHRvblxcXCJcXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVxcXCJhZy1zdGFuZGFyZC1idXR0b24gYWctZmlsdGVyLWFwcGx5LXBhbmVsLWJ1dHRvblxcXCJcXG4gICAgICAgICAgICAgICAgPlwiICsgdGV4dCArIFwiXFxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlwiKTtcbiAgICAgICAgICAgIGVCdXR0b25zUGFuZWwuYXBwZW5kQ2hpbGQoYnV0dG9uKTtcbiAgICAgICAgICAgIF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihidXR0b24sICdjbGljaycsIGNsaWNrTGlzdGVuZXIpO1xuICAgICAgICB9O1xuICAgICAgICBjb252ZXJ0VG9TZXQoYnV0dG9ucykuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkgeyByZXR1cm4gYWRkQnV0dG9uKHR5cGUpOyB9KTtcbiAgICAgICAgdGhpcy5nZXRHdWkoKS5hcHBlbmRDaGlsZChlQnV0dG9uc1BhbmVsKTtcbiAgICB9O1xuICAgIC8vIHN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgdG8gcHJvdmlkZSBhbHRlcm5hdGl2ZSBkZWJvdW5jZSBkZWZhdWx0c1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5nZXREZWZhdWx0RGVib3VuY2VNcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUuc2V0dXBPbkJ0QXBwbHlEZWJvdW5jZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRlYm91bmNlTXMgPSBQcm92aWRlZEZpbHRlci5nZXREZWJvdW5jZU1zKHRoaXMucHJvdmlkZWRGaWx0ZXJQYXJhbXMsIHRoaXMuZ2V0RGVmYXVsdERlYm91bmNlTXMoKSk7XG4gICAgICAgIHRoaXMub25CdEFwcGx5RGVib3VuY2UgPSBkZWJvdW5jZSh0aGlzLm9uQnRBcHBseS5iaW5kKHRoaXMpLCBkZWJvdW5jZU1zKTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5nZXRNb2RlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXBwbGllZE1vZGVsID8gdGhpcy5hcHBsaWVkTW9kZWwgOiBudWxsO1xuICAgIH07XG4gICAgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLnNldE1vZGVsID0gZnVuY3Rpb24gKG1vZGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwcm9taXNlID0gbW9kZWwgIT0gbnVsbCA/IHRoaXMuc2V0TW9kZWxJbnRvVWkobW9kZWwpIDogdGhpcy5yZXNldFVpVG9EZWZhdWx0cygpO1xuICAgICAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZVVpVmlzaWJpbGl0eSgpO1xuICAgICAgICAgICAgLy8gd2Ugc2V0IHRoZSBtb2RlbCBmcm9tIHRoZSBHVUksIHJhdGhlciB0aGFuIHRoZSBwcm92aWRlZCBtb2RlbCxcbiAgICAgICAgICAgIC8vIHNvIHRoZSBtb2RlbCBpcyBjb25zaXN0ZW50LCBlLmcuIGhhbmRsaW5nIG9mIG51bGwvdW5kZWZpbmVkIHdpbGwgYmUgdGhlIHNhbWUsXG4gICAgICAgICAgICAvLyBvciBpZiBtb2RlbCBpcyBjYXNlIGluc2Vuc2l0aXZlLCB0aGVuIGNhc2luZyBpcyByZW1vdmVkLlxuICAgICAgICAgICAgX3RoaXMuYXBwbHlNb2RlbCgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5vbkJ0Q2FuY2VsID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGN1cnJlbnRNb2RlbCA9IHRoaXMuZ2V0TW9kZWwoKTtcbiAgICAgICAgdmFyIGFmdGVyQXBwbGllZEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5vblVpQ2hhbmdlZChmYWxzZSwgJ3ByZXZlbnQnKTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5wcm92aWRlZEZpbHRlclBhcmFtcy5jbG9zZU9uQXBwbHkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbG9zZShlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGN1cnJlbnRNb2RlbCAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNldE1vZGVsSW50b1VpKGN1cnJlbnRNb2RlbCkudGhlbihhZnRlckFwcGxpZWRGdW5jKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVzZXRVaVRvRGVmYXVsdHMoKS50aGVuKGFmdGVyQXBwbGllZEZ1bmMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUub25CdENsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlc2V0VWlUb0RlZmF1bHRzKCkudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vblVpQ2hhbmdlZCgpOyB9KTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5vbkJ0UmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub25CdENsZWFyKCk7XG4gICAgICAgIHRoaXMub25CdEFwcGx5KCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIGNoYW5nZXMgbWFkZSBpbiB0aGUgVUkgdG8gdGhlIGZpbHRlciwgYW5kIHJldHVybnMgdHJ1ZSBpZiB0aGUgbW9kZWwgaGFzIGNoYW5nZWQuXG4gICAgICovXG4gICAgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLmFwcGx5TW9kZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBuZXdNb2RlbCA9IHRoaXMuZ2V0TW9kZWxGcm9tVWkoKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzTW9kZWxWYWxpZChuZXdNb2RlbCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJldmlvdXNNb2RlbCA9IHRoaXMuYXBwbGllZE1vZGVsO1xuICAgICAgICB0aGlzLmFwcGxpZWRNb2RlbCA9IG5ld01vZGVsO1xuICAgICAgICAvLyBtb2RlbHMgY2FuIGJlIHNhbWUgaWYgdXNlciBwYXN0ZWQgc2FtZSBjb250ZW50IGludG8gdGV4dCBmaWVsZCwgb3IgbWF5YmUganVzdCBjaGFuZ2VkIHRoZSBjYXNlXG4gICAgICAgIC8vIGFuZCBpdCdzIGEgY2FzZSBpbnNlbnNpdGl2ZSBmaWx0ZXJcbiAgICAgICAgcmV0dXJuICF0aGlzLmFyZU1vZGVsc0VxdWFsKHByZXZpb3VzTW9kZWwsIG5ld01vZGVsKTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5pc01vZGVsVmFsaWQgPSBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUub25CdEFwcGx5ID0gZnVuY3Rpb24gKGFmdGVyRmxvYXRpbmdGaWx0ZXIsIGFmdGVyRGF0YUNoYW5nZSwgZSkge1xuICAgICAgICBpZiAoYWZ0ZXJGbG9hdGluZ0ZpbHRlciA9PT0gdm9pZCAwKSB7IGFmdGVyRmxvYXRpbmdGaWx0ZXIgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoYWZ0ZXJEYXRhQ2hhbmdlID09PSB2b2lkIDApIHsgYWZ0ZXJEYXRhQ2hhbmdlID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKHRoaXMuYXBwbHlNb2RlbCgpKSB7XG4gICAgICAgICAgICAvLyB0aGUgZmxvYXRpbmcgZmlsdGVyIHVzZXMgJ2FmdGVyRmxvYXRpbmdGaWx0ZXInIGluZm8sIHNvIGl0IGRvZXNuJ3QgcmVmcmVzaCBhZnRlciBmaWx0ZXIgY2hhbmdlZCBpZiBjaGFuZ2VcbiAgICAgICAgICAgIC8vIGNhbWUgZnJvbSBmbG9hdGluZyBmaWx0ZXJcbiAgICAgICAgICAgIHRoaXMucHJvdmlkZWRGaWx0ZXJQYXJhbXMuZmlsdGVyQ2hhbmdlZENhbGxiYWNrKHsgYWZ0ZXJGbG9hdGluZ0ZpbHRlcjogYWZ0ZXJGbG9hdGluZ0ZpbHRlciwgYWZ0ZXJEYXRhQ2hhbmdlOiBhZnRlckRhdGFDaGFuZ2UgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNsb3NlT25BcHBseSA9IHRoaXMucHJvdmlkZWRGaWx0ZXJQYXJhbXMuY2xvc2VPbkFwcGx5O1xuICAgICAgICAvLyBvbmx5IGNsb3NlIGlmIGFuIGFwcGx5IGJ1dHRvbiBpcyB2aXNpYmxlLCBvdGhlcndpc2Ugd2UnZCBiZSBjbG9zaW5nIGV2ZXJ5IHRpbWUgYSBjaGFuZ2Ugd2FzIG1hZGUhXG4gICAgICAgIGlmIChjbG9zZU9uQXBwbHkgJiYgdGhpcy5hcHBseUFjdGl2ZSAmJiAhYWZ0ZXJGbG9hdGluZ0ZpbHRlciAmJiAhYWZ0ZXJEYXRhQ2hhbmdlKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlKGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUub25OZXdSb3dzTG9hZGVkID0gZnVuY3Rpb24gKCkge1xuICAgIH07XG4gICAgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmhpZGVQb3B1cCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBrZXlib2FyZEV2ZW50ID0gZTtcbiAgICAgICAgdmFyIGtleSA9IGtleWJvYXJkRXZlbnQgJiYga2V5Ym9hcmRFdmVudC5rZXk7XG4gICAgICAgIHZhciBwYXJhbXM7XG4gICAgICAgIGlmIChrZXkgPT09ICdFbnRlcicgfHwga2V5ID09PSAnU3BhY2UnKSB7XG4gICAgICAgICAgICBwYXJhbXMgPSB7IGtleWJvYXJkRXZlbnQ6IGtleWJvYXJkRXZlbnQgfTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmhpZGVQb3B1cChwYXJhbXMpO1xuICAgICAgICB0aGlzLmhpZGVQb3B1cCA9IG51bGw7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBCeSBkZWZhdWx0LCBpZiB0aGUgY2hhbmdlIGNhbWUgZnJvbSBhIGZsb2F0aW5nIGZpbHRlciBpdCB3aWxsIGJlIGFwcGxpZWQgaW1tZWRpYXRlbHksIG90aGVyd2lzZSBpZiB0aGVyZSBpcyBub1xuICAgICAqIGFwcGx5IGJ1dHRvbiBpdCB3aWxsIGJlIGFwcGxpZWQgYWZ0ZXIgYSBkZWJvdW5jZSwgb3RoZXJ3aXNlIGl0IHdpbGwgbm90IGJlIGFwcGxpZWQgYXQgYWxsLiBUaGlzIGJlaGF2aW91ciBjYW5cbiAgICAgKiBiZSBhZGp1c3RlZCBieSB1c2luZyB0aGUgYXBwbHkgcGFyYW1ldGVyLlxuICAgICAqL1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS5vblVpQ2hhbmdlZCA9IGZ1bmN0aW9uIChmcm9tRmxvYXRpbmdGaWx0ZXIsIGFwcGx5KSB7XG4gICAgICAgIGlmIChmcm9tRmxvYXRpbmdGaWx0ZXIgPT09IHZvaWQgMCkgeyBmcm9tRmxvYXRpbmdGaWx0ZXIgPSBmYWxzZTsgfVxuICAgICAgICB0aGlzLnVwZGF0ZVVpVmlzaWJpbGl0eSgpO1xuICAgICAgICB0aGlzLnByb3ZpZGVkRmlsdGVyUGFyYW1zLmZpbHRlck1vZGlmaWVkQ2FsbGJhY2soKTtcbiAgICAgICAgaWYgKHRoaXMuYXBwbHlBY3RpdmUgJiYgIXRoaXMuaXNSZWFkT25seSkge1xuICAgICAgICAgICAgdmFyIGlzVmFsaWQgPSB0aGlzLmlzTW9kZWxWYWxpZCh0aGlzLmdldE1vZGVsRnJvbVVpKCkpO1xuICAgICAgICAgICAgc2V0RGlzYWJsZWQodGhpcy5nZXRSZWZFbGVtZW50KCdhcHBseUZpbHRlckJ1dHRvbicpLCAhaXNWYWxpZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChmcm9tRmxvYXRpbmdGaWx0ZXIgJiYgIWFwcGx5KSB8fCBhcHBseSA9PT0gJ2ltbWVkaWF0ZWx5Jykge1xuICAgICAgICAgICAgdGhpcy5vbkJ0QXBwbHkoZnJvbUZsb2F0aW5nRmlsdGVyKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgoIXRoaXMuYXBwbHlBY3RpdmUgJiYgIWFwcGx5KSB8fCBhcHBseSA9PT0gJ2RlYm91bmNlJykge1xuICAgICAgICAgICAgdGhpcy5vbkJ0QXBwbHlEZWJvdW5jZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUuYWZ0ZXJHdWlBdHRhY2hlZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5oaWRlUG9wdXAgPSBwYXJhbXMuaGlkZVBvcHVwO1xuICAgIH07XG4gICAgLy8gc3RhdGljLCBhcyB1c2VkIGJ5IGZsb2F0aW5nIGZpbHRlciBhbHNvXG4gICAgUHJvdmlkZWRGaWx0ZXIuZ2V0RGVib3VuY2VNcyA9IGZ1bmN0aW9uIChwYXJhbXMsIGRlYm91bmNlRGVmYXVsdCkge1xuICAgICAgICBpZiAoUHJvdmlkZWRGaWx0ZXIuaXNVc2VBcHBseUJ1dHRvbihwYXJhbXMpKSB7XG4gICAgICAgICAgICBpZiAocGFyYW1zLmRlYm91bmNlTXMgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZGVib3VuY2VNcyBpcyBpZ25vcmVkIHdoZW4gYXBwbHkgYnV0dG9uIGlzIHByZXNlbnQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJhbXMuZGVib3VuY2VNcyAhPSBudWxsID8gcGFyYW1zLmRlYm91bmNlTXMgOiBkZWJvdW5jZURlZmF1bHQ7XG4gICAgfTtcbiAgICAvLyBzdGF0aWMsIGFzIHVzZWQgYnkgZmxvYXRpbmcgZmlsdGVyIGFsc29cbiAgICBQcm92aWRlZEZpbHRlci5pc1VzZUFwcGx5QnV0dG9uID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gISFwYXJhbXMuYnV0dG9ucyAmJiBwYXJhbXMuYnV0dG9ucy5pbmRleE9mKCdhcHBseScpID49IDA7XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5oaWRlUG9wdXAgPSBudWxsO1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZS50cmFuc2xhdGUgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHZhciB0cmFuc2xhdGUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMb2NhbGVUZXh0RnVuYygpO1xuICAgICAgICByZXR1cm4gdHJhbnNsYXRlKGtleSwgREVGQVVMVF9GSUxURVJfTE9DQUxFX1RFWFRba2V5XSk7XG4gICAgfTtcbiAgICBQcm92aWRlZEZpbHRlci5wcm90b3R5cGUuZ2V0Q2VsbFZhbHVlID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5wcm92aWRlZEZpbHRlclBhcmFtcywgYXBpID0gX2EuYXBpLCBjb2xEZWYgPSBfYS5jb2xEZWYsIGNvbHVtbiA9IF9hLmNvbHVtbiwgY29sdW1uQXBpID0gX2EuY29sdW1uQXBpLCBjb250ZXh0ID0gX2EuY29udGV4dDtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvdmlkZWRGaWx0ZXJQYXJhbXMudmFsdWVHZXR0ZXIoe1xuICAgICAgICAgICAgYXBpOiBhcGksXG4gICAgICAgICAgICBjb2xEZWY6IGNvbERlZixcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgY29sdW1uQXBpOiBjb2x1bW5BcGksXG4gICAgICAgICAgICBjb250ZXh0OiBjb250ZXh0LFxuICAgICAgICAgICAgZGF0YTogcm93Tm9kZS5kYXRhLFxuICAgICAgICAgICAgZ2V0VmFsdWU6IGZ1bmN0aW9uIChmaWVsZCkgeyByZXR1cm4gcm93Tm9kZS5kYXRhW2ZpZWxkXTsgfSxcbiAgICAgICAgICAgIG5vZGU6IHJvd05vZGUsXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQybShbXG4gICAgICAgIEF1dG93aXJlZCgncm93TW9kZWwnKVxuICAgIF0sIFByb3ZpZGVkRmlsdGVyLnByb3RvdHlwZSwgXCJyb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMm0oW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlU2VydmljZScpXG4gICAgXSwgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLCBcInZhbHVlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMm0oW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUHJvdmlkZWRGaWx0ZXIucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFByb3ZpZGVkRmlsdGVyO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQySyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMmwgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBBZ0Fic3RyYWN0TGFiZWwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJLKEFnQWJzdHJhY3RMYWJlbCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ0Fic3RyYWN0TGFiZWwoY29uZmlnLCB0ZW1wbGF0ZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0ZW1wbGF0ZSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMubGFiZWxTZXBhcmF0b3IgPSAnJztcbiAgICAgICAgX3RoaXMubGFiZWxBbGlnbm1lbnQgPSAnbGVmdCc7XG4gICAgICAgIF90aGlzLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmxhYmVsID0gJyc7XG4gICAgICAgIF90aGlzLmNvbmZpZyA9IGNvbmZpZyB8fCB7fTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBZ0Fic3RyYWN0TGFiZWwucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkQ3NzQ2xhc3MoJ2FnLWxhYmVsZWQnKTtcbiAgICAgICAgdGhpcy5lTGFiZWwuY2xhc3NMaXN0LmFkZCgnYWctbGFiZWwnKTtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb25maWcsIGxhYmVsU2VwYXJhdG9yID0gX2EubGFiZWxTZXBhcmF0b3IsIGxhYmVsID0gX2EubGFiZWwsIGxhYmVsV2lkdGggPSBfYS5sYWJlbFdpZHRoLCBsYWJlbEFsaWdubWVudCA9IF9hLmxhYmVsQWxpZ25tZW50O1xuICAgICAgICBpZiAobGFiZWxTZXBhcmF0b3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zZXRMYWJlbFNlcGFyYXRvcihsYWJlbFNlcGFyYXRvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxhYmVsICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0TGFiZWwobGFiZWwpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsYWJlbFdpZHRoICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0TGFiZWxXaWR0aChsYWJlbFdpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldExhYmVsQWxpZ25tZW50KGxhYmVsQWxpZ25tZW50IHx8IHRoaXMubGFiZWxBbGlnbm1lbnQpO1xuICAgICAgICB0aGlzLnJlZnJlc2hMYWJlbCgpO1xuICAgIH07XG4gICAgQWdBYnN0cmFjdExhYmVsLnByb3RvdHlwZS5yZWZyZXNoTGFiZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNsZWFyRWxlbWVudCh0aGlzLmVMYWJlbCk7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5sYWJlbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRoaXMuZUxhYmVsLmlubmVyVGV4dCA9IHRoaXMubGFiZWwgKyB0aGlzLmxhYmVsU2VwYXJhdG9yO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMubGFiZWwpIHtcbiAgICAgICAgICAgIHRoaXMuZUxhYmVsLmFwcGVuZENoaWxkKHRoaXMubGFiZWwpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmxhYmVsID09PSAnJykge1xuICAgICAgICAgICAgdGhpcy5lTGFiZWwuY2xhc3NMaXN0LmFkZCgnYWctaGlkZGVuJyk7XG4gICAgICAgICAgICBzZXRBcmlhUm9sZSh0aGlzLmVMYWJlbCwgJ3ByZXNlbnRhdGlvbicpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lTGFiZWwuY2xhc3NMaXN0LnJlbW92ZSgnYWctaGlkZGVuJyk7XG4gICAgICAgICAgICBzZXRBcmlhUm9sZSh0aGlzLmVMYWJlbCwgbnVsbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQWJzdHJhY3RMYWJlbC5wcm90b3R5cGUuc2V0TGFiZWxTZXBhcmF0b3IgPSBmdW5jdGlvbiAobGFiZWxTZXBhcmF0b3IpIHtcbiAgICAgICAgaWYgKHRoaXMubGFiZWxTZXBhcmF0b3IgPT09IGxhYmVsU2VwYXJhdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhYmVsU2VwYXJhdG9yID0gbGFiZWxTZXBhcmF0b3I7XG4gICAgICAgIGlmICh0aGlzLmxhYmVsICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaExhYmVsKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0TGFiZWwucHJvdG90eXBlLmdldExhYmVsSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZUxhYmVsLmlkID0gdGhpcy5lTGFiZWwuaWQgfHwgXCJhZy1cIiArIHRoaXMuZ2V0Q29tcElkKCkgKyBcIi1sYWJlbFwiO1xuICAgICAgICByZXR1cm4gdGhpcy5lTGFiZWwuaWQ7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0TGFiZWwucHJvdG90eXBlLmdldExhYmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sYWJlbDtcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RMYWJlbC5wcm90b3R5cGUuc2V0TGFiZWwgPSBmdW5jdGlvbiAobGFiZWwpIHtcbiAgICAgICAgaWYgKHRoaXMubGFiZWwgPT09IGxhYmVsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhYmVsID0gbGFiZWw7XG4gICAgICAgIHRoaXMucmVmcmVzaExhYmVsKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdBYnN0cmFjdExhYmVsLnByb3RvdHlwZS5zZXRMYWJlbEFsaWdubWVudCA9IGZ1bmN0aW9uIChhbGlnbm1lbnQpIHtcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICB2YXIgZUd1aUNsYXNzTGlzdCA9IGVHdWkuY2xhc3NMaXN0O1xuICAgICAgICBlR3VpQ2xhc3NMaXN0LnRvZ2dsZSgnYWctbGFiZWwtYWxpZ24tbGVmdCcsIGFsaWdubWVudCA9PT0gJ2xlZnQnKTtcbiAgICAgICAgZUd1aUNsYXNzTGlzdC50b2dnbGUoJ2FnLWxhYmVsLWFsaWduLXJpZ2h0JywgYWxpZ25tZW50ID09PSAncmlnaHQnKTtcbiAgICAgICAgZUd1aUNsYXNzTGlzdC50b2dnbGUoJ2FnLWxhYmVsLWFsaWduLXRvcCcsIGFsaWdubWVudCA9PT0gJ3RvcCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RMYWJlbC5wcm90b3R5cGUuc2V0TGFiZWxXaWR0aCA9IGZ1bmN0aW9uICh3aWR0aCkge1xuICAgICAgICBpZiAodGhpcy5sYWJlbCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBzZXRFbGVtZW50V2lkdGgodGhpcy5lTGFiZWwsIHdpZHRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0TGFiZWwucHJvdG90eXBlLnNldERpc2FibGVkID0gZnVuY3Rpb24gKGRpc2FibGVkKSB7XG4gICAgICAgIGRpc2FibGVkID0gISFkaXNhYmxlZDtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICBzZXREaXNhYmxlZChlbGVtZW50LCBkaXNhYmxlZCk7XG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LnRvZ2dsZSgnYWctZGlzYWJsZWQnLCBkaXNhYmxlZCk7XG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSBkaXNhYmxlZDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0TGFiZWwucHJvdG90eXBlLmlzRGlzYWJsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuZGlzYWJsZWQ7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDJsKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIEFnQWJzdHJhY3RMYWJlbC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gQWdBYnN0cmFjdExhYmVsO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQySiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIEFnQWJzdHJhY3RGaWVsZCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkooQWdBYnN0cmFjdEZpZWxkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnQWJzdHJhY3RGaWVsZChjb25maWcsIHRlbXBsYXRlLCBjbGFzc05hbWUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY29uZmlnLCB0ZW1wbGF0ZSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnQWJzdHJhY3RGaWVsZC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0LmNhbGwodGhpcyk7XG4gICAgICAgIGlmICh0aGlzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgdGhpcy5hZGRDc3NDbGFzcyh0aGlzLmNsYXNzTmFtZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQWJzdHJhY3RGaWVsZC5wcm90b3R5cGUub25WYWx1ZUNoYW5nZSA9IGZ1bmN0aW9uIChjYWxsYmFja0ZuKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMsIEFnQWJzdHJhY3RGaWVsZC5FVkVOVF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7IHJldHVybiBjYWxsYmFja0ZuKF90aGlzLmdldFZhbHVlKCkpOyB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0RmllbGQucHJvdG90eXBlLmdldFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRHdWkoKS5jbGllbnRXaWR0aDtcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RGaWVsZC5wcm90b3R5cGUuc2V0V2lkdGggPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICAgICAgc2V0Rml4ZWRXaWR0aCh0aGlzLmdldEd1aSgpLCB3aWR0aCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdBYnN0cmFjdEZpZWxkLnByb3RvdHlwZS5nZXRQcmV2aW91c1ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wcmV2aW91c1ZhbHVlO1xuICAgIH07XG4gICAgQWdBYnN0cmFjdEZpZWxkLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0RmllbGQucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBzaWxlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMudmFsdWUgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByZXZpb3VzVmFsdWUgPSB0aGlzLnZhbHVlO1xuICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIGlmICghc2lsZW50KSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBBZ0Fic3RyYWN0RmllbGQuRVZFTlRfQ0hBTkdFRCB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RGaWVsZC5FVkVOVF9DSEFOR0VEID0gJ3ZhbHVlQ2hhbmdlJztcbiAgICByZXR1cm4gQWdBYnN0cmFjdEZpZWxkO1xufShBZ0Fic3RyYWN0TGFiZWwpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQySSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMmsgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBBZ1BpY2tlckZpZWxkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQySShBZ1BpY2tlckZpZWxkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnUGlja2VyRmllbGQoY29uZmlnLCBjbGFzc05hbWUsIHBpY2tlckljb24sIGFyaWFSb2xlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNvbmZpZywgXG4gICAgICAgIC8qIGh0bWwgKi8gXCI8ZGl2IGNsYXNzPVxcXCJhZy1waWNrZXItZmllbGRcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlTGFiZWxcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZVdyYXBwZXJcXFwiXFxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cXFwiYWctd3JhcHBlciBhZy1waWNrZXItZmllbGQtd3JhcHBlclxcXCJcXG4gICAgICAgICAgICAgICAgICAgIHRhYkluZGV4PVxcXCItMVxcXCJcXG4gICAgICAgICAgICAgICAgICAgIGFyaWEtZXhwYW5kZWQ9XFxcImZhbHNlXFxcIlxcbiAgICAgICAgICAgICAgICAgICAgXCIgKyAoYXJpYVJvbGUgPyBcInJvbGU9XFxcIlwiICsgYXJpYVJvbGUgKyBcIlxcXCJcIiA6ICcnKSArIFwiXFxuICAgICAgICAgICAgICAgID5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlRGlzcGxheUZpZWxkXFxcIiBjbGFzcz1cXFwiYWctcGlja2VyLWZpZWxkLWRpc3BsYXlcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgICAgICAgICAgPGRpdiByZWY9XFxcImVJY29uXFxcIiBjbGFzcz1cXFwiYWctcGlja2VyLWZpZWxkLWljb25cXFwiIGFyaWEtaGlkZGVuPVxcXCJ0cnVlXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XCIsIGNsYXNzTmFtZSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucGlja2VySWNvbiA9IHBpY2tlckljb247XG4gICAgICAgIF90aGlzLmlzUGlja2VyRGlzcGxheWVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmlzRGVzdHJveWluZ1BpY2tlciA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5za2lwQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBZ1BpY2tlckZpZWxkLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QuY2FsbCh0aGlzKTtcbiAgICAgICAgdmFyIGRpc3BsYXlJZCA9IHRoaXMuZ2V0Q29tcElkKCkgKyBcIi1kaXNwbGF5XCI7XG4gICAgICAgIHRoaXMuZURpc3BsYXlGaWVsZC5zZXRBdHRyaWJ1dGUoJ2lkJywgZGlzcGxheUlkKTtcbiAgICAgICAgc2V0QXJpYURlc2NyaWJlZEJ5KHRoaXMuZVdyYXBwZXIsIGRpc3BsYXlJZCk7XG4gICAgICAgIHZhciBjbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuc2tpcENsaWNrKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2tpcENsaWNrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmlzRGlzYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLnBpY2tlckNvbXBvbmVudCA9IF90aGlzLnNob3dQaWNrZXIoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlR3VpLCAnbW91c2Vkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmICghX3RoaXMuc2tpcENsaWNrICYmXG4gICAgICAgICAgICAgICAgX3RoaXMucGlja2VyQ29tcG9uZW50ICYmXG4gICAgICAgICAgICAgICAgX3RoaXMucGlja2VyQ29tcG9uZW50LmlzQWxpdmUoKSAmJlxuICAgICAgICAgICAgICAgIGlzVmlzaWJsZShfdGhpcy5waWNrZXJDb21wb25lbnQuZ2V0R3VpKCkpICYmXG4gICAgICAgICAgICAgICAgZUd1aS5jb250YWlucyhlLnRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5za2lwQ2xpY2sgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZUd1aSwgJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgc3dpdGNoIChlLmtleSkge1xuICAgICAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5VUDpcbiAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuRE9XTjpcbiAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuRU5URVI6XG4gICAgICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlNQQUNFOlxuICAgICAgICAgICAgICAgICAgICBjbGlja0hhbmRsZXIoKTtcbiAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuRVNDQVBFOlxuICAgICAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNQaWNrZXJEaXNwbGF5ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZVdyYXBwZXIsICdjbGljaycsIGNsaWNrSGFuZGxlcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUxhYmVsLCAnY2xpY2snLCBjbGlja0hhbmRsZXIpO1xuICAgICAgICBpZiAodGhpcy5waWNrZXJJY29uKSB7XG4gICAgICAgICAgICB2YXIgaWNvbiA9IGNyZWF0ZUljb25Ob1NwYW4odGhpcy5waWNrZXJJY29uLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlcik7XG4gICAgICAgICAgICBpZiAoaWNvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuZUljb24uYXBwZW5kQ2hpbGQoaWNvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnUGlja2VyRmllbGQucHJvdG90eXBlLnJlZnJlc2hMYWJlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGV4aXN0cyh0aGlzLmdldExhYmVsKCkpKSB7XG4gICAgICAgICAgICBzZXRBcmlhTGFiZWxsZWRCeSh0aGlzLmVXcmFwcGVyLCB0aGlzLmdldExhYmVsSWQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVXcmFwcGVyLnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1sYWJlbGxlZGJ5Jyk7XG4gICAgICAgIH1cbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZWZyZXNoTGFiZWwuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIEFnUGlja2VyRmllbGQucHJvdG90eXBlLnNldEFyaWFMYWJlbCA9IGZ1bmN0aW9uIChsYWJlbCkge1xuICAgICAgICBzZXRBcmlhTGFiZWwodGhpcy5lV3JhcHBlciwgbGFiZWwpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnUGlja2VyRmllbGQucHJvdG90eXBlLnNldElucHV0V2lkdGggPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICAgICAgc2V0RWxlbWVudFdpZHRoKHRoaXMuZVdyYXBwZXIsIHdpZHRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ1BpY2tlckZpZWxkLnByb3RvdHlwZS5nZXRGb2N1c2FibGVFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lV3JhcHBlcjtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMmsoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUxhYmVsJylcbiAgICBdLCBBZ1BpY2tlckZpZWxkLnByb3RvdHlwZSwgXCJlTGFiZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJrKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VXcmFwcGVyJylcbiAgICBdLCBBZ1BpY2tlckZpZWxkLnByb3RvdHlwZSwgXCJlV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmsoW1xuICAgICAgICBSZWZTZWxlY3RvcignZURpc3BsYXlGaWVsZCcpXG4gICAgXSwgQWdQaWNrZXJGaWVsZC5wcm90b3R5cGUsIFwiZURpc3BsYXlGaWVsZFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmsoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUljb24nKVxuICAgIF0sIEFnUGlja2VyRmllbGQucHJvdG90eXBlLCBcImVJY29uXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIEFnUGlja2VyRmllbGQ7XG59KEFnQWJzdHJhY3RGaWVsZCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJIID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQyaiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEFnTGlzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkgoQWdMaXN0LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnTGlzdChjc3NJZGVudGlmaWVyKSB7XG4gICAgICAgIGlmIChjc3NJZGVudGlmaWVyID09PSB2b2lkIDApIHsgY3NzSWRlbnRpZmllciA9ICdkZWZhdWx0JzsgfVxuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCAvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiYWctbGlzdCBhZy1cIiArIGNzc0lkZW50aWZpZXIgKyBcIi1saXN0XFxcIiByb2xlPVxcXCJsaXN0Ym94XFxcIj48L2Rpdj5cIikgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY3NzSWRlbnRpZmllciA9IGNzc0lkZW50aWZpZXI7XG4gICAgICAgIF90aGlzLm9wdGlvbnMgPSBbXTtcbiAgICAgICAgX3RoaXMuaXRlbUVscyA9IFtdO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnTGlzdC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5nZXRHdWkoKSwgJ2tleWRvd24nLCB0aGlzLmhhbmRsZUtleURvd24uYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBBZ0xpc3QucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIga2V5ID0gZS5rZXk7XG4gICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuRU5URVI6XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmhpZ2hsaWdodGVkRWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRWYWx1ZSh0aGlzLmdldFZhbHVlKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IHRoaXMuaXRlbUVscy5pbmRleE9mKHRoaXMuaGlnaGxpZ2h0ZWRFbCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0VmFsdWVCeUluZGV4KHBvcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRPV046XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuVVA6XG4gICAgICAgICAgICAgICAgdmFyIGlzRG93biA9IGtleSA9PT0gS2V5Q29kZS5ET1dOO1xuICAgICAgICAgICAgICAgIHZhciBpdGVtVG9IaWdobGlnaHQgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5oaWdobGlnaHRlZEVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGl0ZW1Ub0hpZ2hsaWdodCA9IHRoaXMuaXRlbUVsc1tpc0Rvd24gPyAwIDogdGhpcy5pdGVtRWxzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJZHggPSB0aGlzLml0ZW1FbHMuaW5kZXhPZih0aGlzLmhpZ2hsaWdodGVkRWwpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dFBvcyA9IGN1cnJlbnRJZHggKyAoaXNEb3duID8gMSA6IC0xKTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dFBvcyA9IE1hdGgubWluKE1hdGgubWF4KG5leHRQb3MsIDApLCB0aGlzLml0ZW1FbHMubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgIGl0ZW1Ub0hpZ2hsaWdodCA9IHRoaXMuaXRlbUVsc1tuZXh0UG9zXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRJdGVtKGl0ZW1Ub0hpZ2hsaWdodCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTGlzdC5wcm90b3R5cGUuYWRkT3B0aW9ucyA9IGZ1bmN0aW9uIChsaXN0T3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBsaXN0T3B0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uIChsaXN0T3B0aW9uKSB7IHJldHVybiBfdGhpcy5hZGRPcHRpb24obGlzdE9wdGlvbik7IH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnTGlzdC5wcm90b3R5cGUuYWRkT3B0aW9uID0gZnVuY3Rpb24gKGxpc3RPcHRpb24pIHtcbiAgICAgICAgdmFyIHZhbHVlID0gbGlzdE9wdGlvbi52YWx1ZSwgdGV4dCA9IGxpc3RPcHRpb24udGV4dDtcbiAgICAgICAgdmFyIHNhbml0aXNlZFRleHQgPSBlc2NhcGVTdHJpbmcodGV4dCB8fCB2YWx1ZSk7XG4gICAgICAgIHRoaXMub3B0aW9ucy5wdXNoKHsgdmFsdWU6IHZhbHVlLCB0ZXh0OiBzYW5pdGlzZWRUZXh0IH0pO1xuICAgICAgICB0aGlzLnJlbmRlck9wdGlvbih2YWx1ZSwgc2FuaXRpc2VkVGV4dCk7XG4gICAgICAgIHRoaXMudXBkYXRlSW5kaWNlcygpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnTGlzdC5wcm90b3R5cGUudXBkYXRlSW5kaWNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLmdldEd1aSgpLnF1ZXJ5U2VsZWN0b3JBbGwoJy5hZy1saXN0LWl0ZW0nKTtcbiAgICAgICAgb3B0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uIChvcHRpb24sIGlkeCkge1xuICAgICAgICAgICAgc2V0QXJpYVBvc0luU2V0KG9wdGlvbiwgaWR4ICsgMSk7XG4gICAgICAgICAgICBzZXRBcmlhU2V0U2l6ZShvcHRpb24sIG9wdGlvbnMubGVuZ3RoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBZ0xpc3QucHJvdG90eXBlLnJlbmRlck9wdGlvbiA9IGZ1bmN0aW9uICh2YWx1ZSwgdGV4dCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgaXRlbUVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHNldEFyaWFSb2xlKGl0ZW1FbCwgJ29wdGlvbicpO1xuICAgICAgICBpdGVtRWwuY2xhc3NMaXN0LmFkZCgnYWctbGlzdC1pdGVtJywgXCJhZy1cIiArIHRoaXMuY3NzSWRlbnRpZmllciArIFwiLWxpc3QtaXRlbVwiKTtcbiAgICAgICAgaXRlbUVsLmlubmVySFRNTCA9IFwiPHNwYW4+XCIgKyB0ZXh0ICsgXCI8L3NwYW4+XCI7XG4gICAgICAgIGl0ZW1FbC50YWJJbmRleCA9IC0xO1xuICAgICAgICB0aGlzLml0ZW1FbHMucHVzaChpdGVtRWwpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihpdGVtRWwsICdtb3VzZW92ZXInLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5oaWdobGlnaHRJdGVtKGl0ZW1FbCk7IH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihpdGVtRWwsICdtb3VzZWxlYXZlJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY2xlYXJIaWdobGlnaHRlZCgpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoaXRlbUVsLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5zZXRWYWx1ZSh2YWx1ZSk7IH0pO1xuICAgICAgICB0aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKGl0ZW1FbCk7XG4gICAgfTtcbiAgICBBZ0xpc3QucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBzaWxlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMudmFsdWUgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmZpcmVJdGVtU2VsZWN0ZWQoKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaWR4ID0gdGhpcy5vcHRpb25zLmZpbmRJbmRleChmdW5jdGlvbiAob3B0aW9uKSB7IHJldHVybiBvcHRpb24udmFsdWUgPT09IHZhbHVlOyB9KTtcbiAgICAgICAgaWYgKGlkeCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHZhciBvcHRpb24gPSB0aGlzLm9wdGlvbnNbaWR4XTtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBvcHRpb24udmFsdWU7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXlWYWx1ZSA9IG9wdGlvbi50ZXh0ICE9IG51bGwgPyBvcHRpb24udGV4dCA6IG9wdGlvbi52YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0SXRlbSh0aGlzLml0ZW1FbHNbaWR4XSk7XG4gICAgICAgICAgICBpZiAoIXNpbGVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyZUNoYW5nZUV2ZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0xpc3QucHJvdG90eXBlLnNldFZhbHVlQnlJbmRleCA9IGZ1bmN0aW9uIChpZHgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0VmFsdWUodGhpcy5vcHRpb25zW2lkeF0udmFsdWUpO1xuICAgIH07XG4gICAgQWdMaXN0LnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfTtcbiAgICBBZ0xpc3QucHJvdG90eXBlLmdldERpc3BsYXlWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheVZhbHVlO1xuICAgIH07XG4gICAgQWdMaXN0LnByb3RvdHlwZS5yZWZyZXNoSGlnaGxpZ2h0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY2xlYXJIaWdobGlnaHRlZCgpO1xuICAgICAgICB2YXIgaWR4ID0gdGhpcy5vcHRpb25zLmZpbmRJbmRleChmdW5jdGlvbiAob3B0aW9uKSB7IHJldHVybiBvcHRpb24udmFsdWUgPT09IF90aGlzLnZhbHVlOyB9KTtcbiAgICAgICAgaWYgKGlkeCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuaGlnaGxpZ2h0SXRlbSh0aGlzLml0ZW1FbHNbaWR4XSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTGlzdC5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSBudWxsO1xuICAgICAgICB0aGlzLmRpc3BsYXlWYWx1ZSA9IG51bGw7XG4gICAgICAgIHRoaXMuY2xlYXJIaWdobGlnaHRlZCgpO1xuICAgICAgICB0aGlzLmZpcmVDaGFuZ2VFdmVudCgpO1xuICAgIH07XG4gICAgQWdMaXN0LnByb3RvdHlwZS5oaWdobGlnaHRJdGVtID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIGlmICghZWwub2Zmc2V0UGFyZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGVhckhpZ2hsaWdodGVkKCk7XG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbCA9IGVsO1xuICAgICAgICB0aGlzLmhpZ2hsaWdodGVkRWwuY2xhc3NMaXN0LmFkZChBZ0xpc3QuQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgc2V0QXJpYVNlbGVjdGVkKHRoaXMuaGlnaGxpZ2h0ZWRFbCwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbC5mb2N1cygpO1xuICAgIH07XG4gICAgQWdMaXN0LnByb3RvdHlwZS5jbGVhckhpZ2hsaWdodGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaGlnaGxpZ2h0ZWRFbCB8fCAhdGhpcy5oaWdobGlnaHRlZEVsLm9mZnNldFBhcmVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbC5jbGFzc0xpc3QucmVtb3ZlKEFnTGlzdC5BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICBzZXRBcmlhU2VsZWN0ZWQodGhpcy5oaWdobGlnaHRlZEVsLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWRFbCA9IG51bGw7XG4gICAgfTtcbiAgICBBZ0xpc3QucHJvdG90eXBlLmZpcmVDaGFuZ2VFdmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHsgdHlwZTogQWdBYnN0cmFjdEZpZWxkLkVWRU5UX0NIQU5HRUQgfSk7XG4gICAgICAgIHRoaXMuZmlyZUl0ZW1TZWxlY3RlZCgpO1xuICAgIH07XG4gICAgQWdMaXN0LnByb3RvdHlwZS5maXJlSXRlbVNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBBZ0xpc3QuRVZFTlRfSVRFTV9TRUxFQ1RFRCB9KTtcbiAgICB9O1xuICAgIEFnTGlzdC5FVkVOVF9JVEVNX1NFTEVDVEVEID0gJ3NlbGVjdGVkSXRlbSc7XG4gICAgQWdMaXN0LkFDVElWRV9DTEFTUyA9ICdhZy1hY3RpdmUtaXRlbSc7XG4gICAgX19kZWNvcmF0ZSQyaihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBZ0xpc3QucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEFnTGlzdDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMkcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJpID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdTZWxlY3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJHKEFnU2VsZWN0LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnU2VsZWN0KGNvbmZpZykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgY29uZmlnLCAnYWctc2VsZWN0JywgJ3NtYWxsRG93bicsICdsaXN0Ym94JykgfHwgdGhpcztcbiAgICB9XG4gICAgQWdTZWxlY3QucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMubGlzdENvbXBvbmVudCA9IHRoaXMuY3JlYXRlQmVhbihuZXcgQWdMaXN0KCdzZWxlY3QnKSk7XG4gICAgICAgIHRoaXMubGlzdENvbXBvbmVudC5zZXRQYXJlbnRDb21wb25lbnQodGhpcyk7XG4gICAgICAgIHRoaXMuZVdyYXBwZXIudGFiSW5kZXggPSAwO1xuICAgICAgICB0aGlzLmxpc3RDb21wb25lbnQuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMubGlzdENvbXBvbmVudCwgQWdMaXN0LkVWRU5UX0lURU1fU0VMRUNURUQsIGZ1bmN0aW9uICgpIHsgaWYgKF90aGlzLmhpZGVMaXN0KSB7XG4gICAgICAgICAgICBfdGhpcy5oaWRlTGlzdCgpO1xuICAgICAgICB9IH0pO1xuICAgICAgICB0aGlzLmxpc3RDb21wb25lbnQuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMubGlzdENvbXBvbmVudCwgQWdBYnN0cmFjdEZpZWxkLkVWRU5UX0NIQU5HRUQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLnNldFZhbHVlKF90aGlzLmxpc3RDb21wb25lbnQuZ2V0VmFsdWUoKSwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgaWYgKF90aGlzLmhpZGVMaXN0KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGlkZUxpc3QoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBZ1NlbGVjdC5wcm90b3R5cGUuc2hvd1BpY2tlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGxpc3RHdWkgPSB0aGlzLmxpc3RDb21wb25lbnQuZ2V0R3VpKCk7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgZGVzdHJveU1vdXNlV2hlZWxGdW5jID0gdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZURvY3VtZW50LmJvZHksICd3aGVlbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBpZiAoIWxpc3RHdWkuY29udGFpbnMoZS50YXJnZXQpICYmIF90aGlzLmhpZGVMaXN0KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGlkZUxpc3QoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBkZXN0cm95Rm9jdXNPdXRGdW5jID0gdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIobGlzdEd1aSwgJ2ZvY3Vzb3V0JywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmICghbGlzdEd1aS5jb250YWlucyhlLnJlbGF0ZWRUYXJnZXQpICYmIF90aGlzLmhpZGVMaXN0KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGlkZUxpc3QoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciB0cmFuc2xhdGUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMb2NhbGVUZXh0RnVuYygpO1xuICAgICAgICB2YXIgYWRkUG9wdXBSZXMgPSB0aGlzLnBvcHVwU2VydmljZS5hZGRQb3B1cCh7XG4gICAgICAgICAgICBtb2RhbDogdHJ1ZSxcbiAgICAgICAgICAgIGVDaGlsZDogbGlzdEd1aSxcbiAgICAgICAgICAgIGNsb3NlT25Fc2M6IHRydWUsXG4gICAgICAgICAgICBjbG9zZWRDYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmhpZGVMaXN0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc1BpY2tlckRpc3BsYXllZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lGb2N1c091dEZ1bmMoKTtcbiAgICAgICAgICAgICAgICBkZXN0cm95TW91c2VXaGVlbEZ1bmMoKTtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNBbGl2ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEFyaWFFeHBhbmRlZChfdGhpcy5lV3JhcHBlciwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5nZXRGb2N1c2FibGVFbGVtZW50KCkuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYXJpYUxhYmVsOiB0cmFuc2xhdGUoJ2FyaWFMYWJlbFNlbGVjdEZpZWxkJywgJ1NlbGVjdCBGaWVsZCcpXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWRkUG9wdXBSZXMpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZUxpc3QgPSBhZGRQb3B1cFJlcy5oaWRlRnVuYztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmlzUGlja2VyRGlzcGxheWVkID0gdHJ1ZTtcbiAgICAgICAgc2V0RWxlbWVudFdpZHRoKGxpc3RHdWksIGdldEFic29sdXRlV2lkdGgodGhpcy5lV3JhcHBlcikpO1xuICAgICAgICBzZXRBcmlhRXhwYW5kZWQodGhpcy5lV3JhcHBlciwgdHJ1ZSk7XG4gICAgICAgIGxpc3RHdWkuc3R5bGUubWF4SGVpZ2h0ID0gZ2V0SW5uZXJIZWlnaHQodGhpcy5wb3B1cFNlcnZpY2UuZ2V0UG9wdXBQYXJlbnQoKSkgKyAncHgnO1xuICAgICAgICBsaXN0R3VpLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgdGhpcy5wb3B1cFNlcnZpY2UucG9zaXRpb25Qb3B1cFVuZGVyQ29tcG9uZW50KHtcbiAgICAgICAgICAgIHR5cGU6ICdhZy1saXN0JyxcbiAgICAgICAgICAgIGV2ZW50U291cmNlOiB0aGlzLmVXcmFwcGVyLFxuICAgICAgICAgICAgZVBvcHVwOiBsaXN0R3VpLFxuICAgICAgICAgICAga2VlcFdpdGhpbkJvdW5kczogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5saXN0Q29tcG9uZW50LnJlZnJlc2hIaWdobGlnaHRlZCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5saXN0Q29tcG9uZW50O1xuICAgIH07XG4gICAgQWdTZWxlY3QucHJvdG90eXBlLmFkZE9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBvcHRpb25zLmZvckVhY2goZnVuY3Rpb24gKG9wdGlvbikgeyByZXR1cm4gX3RoaXMuYWRkT3B0aW9uKG9wdGlvbik7IH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnU2VsZWN0LnByb3RvdHlwZS5hZGRPcHRpb24gPSBmdW5jdGlvbiAob3B0aW9uKSB7XG4gICAgICAgIHRoaXMubGlzdENvbXBvbmVudC5hZGRPcHRpb24ob3B0aW9uKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ1NlbGVjdC5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUsIHNpbGVudCwgZnJvbVBpY2tlcikge1xuICAgICAgICBpZiAodGhpcy52YWx1ZSA9PT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZnJvbVBpY2tlcikge1xuICAgICAgICAgICAgdGhpcy5saXN0Q29tcG9uZW50LnNldFZhbHVlKHZhbHVlLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV3VmFsdWUgPSB0aGlzLmxpc3RDb21wb25lbnQuZ2V0VmFsdWUoKTtcbiAgICAgICAgaWYgKG5ld1ZhbHVlID09PSB0aGlzLmdldFZhbHVlKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZURpc3BsYXlGaWVsZC5pbm5lckhUTUwgPSB0aGlzLmxpc3RDb21wb25lbnQuZ2V0RGlzcGxheVZhbHVlKCk7XG4gICAgICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLnNldFZhbHVlLmNhbGwodGhpcywgdmFsdWUsIHNpbGVudCk7XG4gICAgfTtcbiAgICBBZ1NlbGVjdC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGlkZUxpc3QpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZUxpc3QoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlc3Ryb3lCZWFuKHRoaXMubGlzdENvbXBvbmVudCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQyaShbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBBZ1NlbGVjdC5wcm90b3R5cGUsIFwicG9wdXBTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyaShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBZ1NlbGVjdC5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICByZXR1cm4gQWdTZWxlY3Q7XG59KEFnUGlja2VyRmllbGQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyRiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMmggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBBZ0Fic3RyYWN0SW5wdXRGaWVsZCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkYoQWdBYnN0cmFjdElucHV0RmllbGQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdBYnN0cmFjdElucHV0RmllbGQoY29uZmlnLCBjbGFzc05hbWUsIGlucHV0VHlwZSwgZGlzcGxheUZpZWxkVGFnKSB7XG4gICAgICAgIGlmIChpbnB1dFR5cGUgPT09IHZvaWQgMCkgeyBpbnB1dFR5cGUgPSAndGV4dCc7IH1cbiAgICAgICAgaWYgKGRpc3BsYXlGaWVsZFRhZyA9PT0gdm9pZCAwKSB7IGRpc3BsYXlGaWVsZFRhZyA9ICdpbnB1dCc7IH1cbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY29uZmlnLCAvKiBodG1sICovIFwiXFxuICAgICAgICAgICAgPGRpdiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZUxhYmVsXFxcIiBjbGFzcz1cXFwiYWctaW5wdXQtZmllbGQtbGFiZWxcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZVdyYXBwZXJcXFwiIGNsYXNzPVxcXCJhZy13cmFwcGVyIGFnLWlucHV0LXdyYXBwZXJcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgICAgICA8XCIgKyBkaXNwbGF5RmllbGRUYWcgKyBcIiByZWY9XFxcImVJbnB1dFxcXCIgY2xhc3M9XFxcImFnLWlucHV0LWZpZWxkLWlucHV0XFxcIj48L1wiICsgZGlzcGxheUZpZWxkVGFnICsgXCI+XFxuICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDwvZGl2PlwiLCBjbGFzc05hbWUpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmlucHV0VHlwZSA9IGlucHV0VHlwZTtcbiAgICAgICAgX3RoaXMuZGlzcGxheUZpZWxkVGFnID0gZGlzcGxheUZpZWxkVGFnO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnQWJzdHJhY3RJbnB1dEZpZWxkLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QuY2FsbCh0aGlzKTtcbiAgICAgICAgdGhpcy5zZXRJbnB1dFR5cGUoKTtcbiAgICAgICAgdGhpcy5lTGFiZWwuY2xhc3NMaXN0LmFkZCh0aGlzLmNsYXNzTmFtZSArIFwiLWxhYmVsXCIpO1xuICAgICAgICB0aGlzLmVXcmFwcGVyLmNsYXNzTGlzdC5hZGQodGhpcy5jbGFzc05hbWUgKyBcIi1pbnB1dC13cmFwcGVyXCIpO1xuICAgICAgICB0aGlzLmVJbnB1dC5jbGFzc0xpc3QuYWRkKHRoaXMuY2xhc3NOYW1lICsgXCItaW5wdXRcIik7XG4gICAgICAgIHRoaXMuYWRkQ3NzQ2xhc3MoJ2FnLWlucHV0LWZpZWxkJyk7XG4gICAgICAgIHRoaXMuZUlucHV0LmlkID0gdGhpcy5lSW5wdXQuaWQgfHwgXCJhZy1cIiArIHRoaXMuZ2V0Q29tcElkKCkgKyBcIi1pbnB1dFwiO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbmZpZywgd2lkdGggPSBfYS53aWR0aCwgdmFsdWUgPSBfYS52YWx1ZTtcbiAgICAgICAgaWYgKHdpZHRoICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0V2lkdGgod2lkdGgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZElucHV0TGlzdGVuZXJzKCk7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUucmVmcmVzaExhYmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoZXhpc3RzKHRoaXMuZ2V0TGFiZWwoKSkpIHtcbiAgICAgICAgICAgIHNldEFyaWFMYWJlbGxlZEJ5KHRoaXMuZUlucHV0LCB0aGlzLmdldExhYmVsSWQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVJbnB1dC5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtbGFiZWxsZWRieScpO1xuICAgICAgICB9XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucmVmcmVzaExhYmVsLmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUuYWRkSW5wdXRMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUlucHV0LCAnaW5wdXQnLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMuc2V0VmFsdWUoZS50YXJnZXQudmFsdWUpOyB9KTtcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RJbnB1dEZpZWxkLnByb3RvdHlwZS5zZXRJbnB1dFR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXlGaWVsZFRhZyA9PT0gJ2lucHV0Jykge1xuICAgICAgICAgICAgdGhpcy5lSW5wdXQuc2V0QXR0cmlidXRlKCd0eXBlJywgdGhpcy5pbnB1dFR5cGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUuZ2V0SW5wdXRFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lSW5wdXQ7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUuc2V0SW5wdXRXaWR0aCA9IGZ1bmN0aW9uICh3aWR0aCkge1xuICAgICAgICBzZXRFbGVtZW50V2lkdGgodGhpcy5lV3JhcHBlciwgd2lkdGgpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RJbnB1dEZpZWxkLnByb3RvdHlwZS5zZXRJbnB1dE5hbWUgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB0aGlzLmdldElucHV0RWxlbWVudCgpLnNldEF0dHJpYnV0ZSgnbmFtZScsIG5hbWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQWJzdHJhY3RJbnB1dEZpZWxkLnByb3RvdHlwZS5nZXRGb2N1c2FibGVFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lSW5wdXQ7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUuc2V0TWF4TGVuZ3RoID0gZnVuY3Rpb24gKGxlbmd0aCkge1xuICAgICAgICB2YXIgZUlucHV0ID0gdGhpcy5lSW5wdXQ7XG4gICAgICAgIGVJbnB1dC5tYXhMZW5ndGggPSBsZW5ndGg7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdBYnN0cmFjdElucHV0RmllbGQucHJvdG90eXBlLnNldElucHV0UGxhY2Vob2xkZXIgPSBmdW5jdGlvbiAocGxhY2Vob2xkZXIpIHtcbiAgICAgICAgYWRkT3JSZW1vdmVBdHRyaWJ1dGUodGhpcy5lSW5wdXQsICdwbGFjZWhvbGRlcicsIHBsYWNlaG9sZGVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUuc2V0SW5wdXRBcmlhTGFiZWwgPSBmdW5jdGlvbiAobGFiZWwpIHtcbiAgICAgICAgc2V0QXJpYUxhYmVsKHRoaXMuZUlucHV0LCBsYWJlbCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdBYnN0cmFjdElucHV0RmllbGQucHJvdG90eXBlLnNldERpc2FibGVkID0gZnVuY3Rpb24gKGRpc2FibGVkKSB7XG4gICAgICAgIHNldERpc2FibGVkKHRoaXMuZUlucHV0LCBkaXNhYmxlZCk7XG4gICAgICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLnNldERpc2FibGVkLmNhbGwodGhpcywgZGlzYWJsZWQpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQyaChbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlTGFiZWwnKVxuICAgIF0sIEFnQWJzdHJhY3RJbnB1dEZpZWxkLnByb3RvdHlwZSwgXCJlTGFiZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJoKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VXcmFwcGVyJylcbiAgICBdLCBBZ0Fic3RyYWN0SW5wdXRGaWVsZC5wcm90b3R5cGUsIFwiZVdyYXBwZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJoKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VJbnB1dCcpXG4gICAgXSwgQWdBYnN0cmFjdElucHV0RmllbGQucHJvdG90eXBlLCBcImVJbnB1dFwiLCB2b2lkIDApO1xuICAgIHJldHVybiBBZ0Fic3RyYWN0SW5wdXRGaWVsZDtcbn0oQWdBYnN0cmFjdEZpZWxkKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMkUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJnID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ29uZGl0aW9uUG9zaXRpb247XG4oZnVuY3Rpb24gKENvbmRpdGlvblBvc2l0aW9uKSB7XG4gICAgQ29uZGl0aW9uUG9zaXRpb25bQ29uZGl0aW9uUG9zaXRpb25bXCJPbmVcIl0gPSAwXSA9IFwiT25lXCI7XG4gICAgQ29uZGl0aW9uUG9zaXRpb25bQ29uZGl0aW9uUG9zaXRpb25bXCJUd29cIl0gPSAxXSA9IFwiVHdvXCI7XG59KShDb25kaXRpb25Qb3NpdGlvbiB8fCAoQ29uZGl0aW9uUG9zaXRpb24gPSB7fSkpO1xuLyoqXG4gKiBFdmVyeSBmaWx0ZXIgd2l0aCBhIGRyb3Bkb3duIHdoZXJlIHRoZSB1c2VyIGNhbiBzcGVjaWZ5IGEgY29tcGFyaW5nIHR5cGUgYWdhaW5zdCB0aGUgZmlsdGVyIHZhbHVlcy5cbiAqXG4gKiBAcGFyYW0gTSB0eXBlIG9mIGZpbHRlci1tb2RlbCBtYW5hZ2VkIGJ5IHRoZSBjb25jcmV0ZSBzdWItY2xhc3MgdGhhdCBleHRlbmRzIHRoaXMgdHlwZVxuICogQHBhcmFtIFYgdHlwZSBvZiB2YWx1ZSBtYW5hZ2VkIGJ5IHRoZSBjb25jcmV0ZSBzdWItY2xhc3MgdGhhdCBleHRlbmRzIHRoaXMgdHlwZVxuICogQHBhcmFtIEUgdHlwZSBvZiBVSSBlbGVtZW50IHVzZWQgZm9yIGNvbGxlY3RpbmcgdXNlci1pbnB1dFxuICovXG52YXIgU2ltcGxlRmlsdGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyRShTaW1wbGVGaWx0ZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2ltcGxlRmlsdGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuZ2V0TnVtYmVyT2ZJbnB1dHMgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICB2YXIgY3VzdG9tT3B0cyA9IHRoaXMub3B0aW9uc0ZhY3RvcnkuZ2V0Q3VzdG9tT3B0aW9uKHR5cGUpO1xuICAgICAgICBpZiAoY3VzdG9tT3B0cykge1xuICAgICAgICAgICAgdmFyIG51bWJlck9mSW5wdXRzID0gY3VzdG9tT3B0cy5udW1iZXJPZklucHV0cztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJPZklucHV0cyAhPSBudWxsID8gbnVtYmVyT2ZJbnB1dHMgOiAxO1xuICAgICAgICB9XG4gICAgICAgIHZhciB6ZXJvSW5wdXRUeXBlcyA9IFtcbiAgICAgICAgICAgIFNpbXBsZUZpbHRlci5FTVBUWSwgU2ltcGxlRmlsdGVyLk5PVF9CTEFOSywgU2ltcGxlRmlsdGVyLkJMQU5LLFxuICAgICAgICBdO1xuICAgICAgICBpZiAodHlwZSAmJiB6ZXJvSW5wdXRUeXBlcy5pbmRleE9mKHR5cGUpID49IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGUgPT09IFNpbXBsZUZpbHRlci5JTl9SQU5HRSkge1xuICAgICAgICAgICAgcmV0dXJuIDI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfTtcbiAgICAvLyBmbG9hdGluZyBmaWx0ZXIgY2FsbHMgdGhpcyB3aGVuIHVzZXIgYXBwbGllcyBmaWx0ZXIgZnJvbSBmbG9hdGluZyBmaWx0ZXJcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLm9uRmxvYXRpbmdGaWx0ZXJDaGFuZ2VkID0gZnVuY3Rpb24gKHR5cGUsIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuc2V0VHlwZUZyb21GbG9hdGluZ0ZpbHRlcih0eXBlKTtcbiAgICAgICAgdGhpcy5zZXRWYWx1ZUZyb21GbG9hdGluZ0ZpbHRlcih2YWx1ZSk7XG4gICAgICAgIHRoaXMub25VaUNoYW5nZWQodHJ1ZSk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLnNldFR5cGVGcm9tRmxvYXRpbmdGaWx0ZXIgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICB0aGlzLmVUeXBlMS5zZXRWYWx1ZSh0eXBlKTtcbiAgICAgICAgdGhpcy5lVHlwZTIuc2V0VmFsdWUodGhpcy5vcHRpb25zRmFjdG9yeS5nZXREZWZhdWx0T3B0aW9uKCkpO1xuICAgICAgICAodGhpcy5pc0RlZmF1bHRPcGVyYXRvcignQU5EJykgPyB0aGlzLmVKb2luT3BlcmF0b3JBbmQgOiB0aGlzLmVKb2luT3BlcmF0b3JPcikuc2V0VmFsdWUodHJ1ZSk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmdldE1vZGVsRnJvbVVpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNDb25kaXRpb25VaUNvbXBsZXRlKENvbmRpdGlvblBvc2l0aW9uLk9uZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzQWxsb3dUd29Db25kaXRpb25zKCkgJiYgdGhpcy5pc0NvbmRpdGlvblVpQ29tcGxldGUoQ29uZGl0aW9uUG9zaXRpb24uVHdvKSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmaWx0ZXJUeXBlOiB0aGlzLmdldEZpbHRlclR5cGUoKSxcbiAgICAgICAgICAgICAgICBvcGVyYXRvcjogdGhpcy5nZXRKb2luT3BlcmF0b3IoKSxcbiAgICAgICAgICAgICAgICBjb25kaXRpb24xOiB0aGlzLmNyZWF0ZUNvbmRpdGlvbihDb25kaXRpb25Qb3NpdGlvbi5PbmUpLFxuICAgICAgICAgICAgICAgIGNvbmRpdGlvbjI6IHRoaXMuY3JlYXRlQ29uZGl0aW9uKENvbmRpdGlvblBvc2l0aW9uLlR3bylcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlQ29uZGl0aW9uKENvbmRpdGlvblBvc2l0aW9uLk9uZSk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmdldENvbmRpdGlvblR5cGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgdGhpcy5lVHlwZTEuZ2V0VmFsdWUoKSxcbiAgICAgICAgICAgIHRoaXMuZVR5cGUyLmdldFZhbHVlKCksXG4gICAgICAgIF07XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmdldEpvaW5PcGVyYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUpvaW5PcGVyYXRvck9yLmdldFZhbHVlKCkgPT09IHRydWUgPyAnT1InIDogJ0FORCc7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmFyZU1vZGVsc0VxdWFsID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgLy8gYm90aCBhcmUgbWlzc2luZ1xuICAgICAgICBpZiAoIWEgJiYgIWIpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIG9uZSBpcyBtaXNzaW5nLCBvdGhlciBwcmVzZW50XG4gICAgICAgIGlmICgoIWEgJiYgYikgfHwgKGEgJiYgIWIpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb25lIGlzIGNvbWJpbmVkLCB0aGUgb3RoZXIgaXMgbm90XG4gICAgICAgIHZhciBhSXNTaW1wbGUgPSAhYS5vcGVyYXRvcjtcbiAgICAgICAgdmFyIGJJc1NpbXBsZSA9ICFiLm9wZXJhdG9yO1xuICAgICAgICB2YXIgb25lU2ltcGxlT25lQ29tYmluZWQgPSAoIWFJc1NpbXBsZSAmJiBiSXNTaW1wbGUpIHx8IChhSXNTaW1wbGUgJiYgIWJJc1NpbXBsZSk7XG4gICAgICAgIGlmIChvbmVTaW1wbGVPbmVDb21iaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXM7XG4gICAgICAgIC8vIG90aGVyd2lzZSBib3RoIHByZXNlbnQsIHNvIGNvbXBhcmVcbiAgICAgICAgaWYgKGFJc1NpbXBsZSkge1xuICAgICAgICAgICAgdmFyIGFTaW1wbGUgPSBhO1xuICAgICAgICAgICAgdmFyIGJTaW1wbGUgPSBiO1xuICAgICAgICAgICAgcmVzID0gdGhpcy5hcmVTaW1wbGVNb2RlbHNFcXVhbChhU2ltcGxlLCBiU2ltcGxlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBhQ29tYmluZWQgPSBhO1xuICAgICAgICAgICAgdmFyIGJDb21iaW5lZCA9IGI7XG4gICAgICAgICAgICByZXMgPSBhQ29tYmluZWQub3BlcmF0b3IgPT09IGJDb21iaW5lZC5vcGVyYXRvclxuICAgICAgICAgICAgICAgICYmIHRoaXMuYXJlU2ltcGxlTW9kZWxzRXF1YWwoYUNvbWJpbmVkLmNvbmRpdGlvbjEsIGJDb21iaW5lZC5jb25kaXRpb24xKVxuICAgICAgICAgICAgICAgICYmIHRoaXMuYXJlU2ltcGxlTW9kZWxzRXF1YWwoYUNvbWJpbmVkLmNvbmRpdGlvbjIsIGJDb21iaW5lZC5jb25kaXRpb24yKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5zZXRNb2RlbEludG9VaSA9IGZ1bmN0aW9uIChtb2RlbCkge1xuICAgICAgICB2YXIgaXNDb21iaW5lZCA9IG1vZGVsLm9wZXJhdG9yO1xuICAgICAgICBpZiAoaXNDb21iaW5lZCkge1xuICAgICAgICAgICAgdmFyIGNvbWJpbmVkTW9kZWwgPSBtb2RlbDtcbiAgICAgICAgICAgIHZhciBvckNoZWNrZWQgPSBjb21iaW5lZE1vZGVsLm9wZXJhdG9yID09PSAnT1InO1xuICAgICAgICAgICAgdGhpcy5lSm9pbk9wZXJhdG9yQW5kLnNldFZhbHVlKCFvckNoZWNrZWQpO1xuICAgICAgICAgICAgdGhpcy5lSm9pbk9wZXJhdG9yT3Iuc2V0VmFsdWUob3JDaGVja2VkKTtcbiAgICAgICAgICAgIHRoaXMuZVR5cGUxLnNldFZhbHVlKGNvbWJpbmVkTW9kZWwuY29uZGl0aW9uMS50eXBlKTtcbiAgICAgICAgICAgIHRoaXMuZVR5cGUyLnNldFZhbHVlKGNvbWJpbmVkTW9kZWwuY29uZGl0aW9uMi50eXBlKTtcbiAgICAgICAgICAgIHRoaXMuc2V0Q29uZGl0aW9uSW50b1VpKGNvbWJpbmVkTW9kZWwuY29uZGl0aW9uMSwgQ29uZGl0aW9uUG9zaXRpb24uT25lKTtcbiAgICAgICAgICAgIHRoaXMuc2V0Q29uZGl0aW9uSW50b1VpKGNvbWJpbmVkTW9kZWwuY29uZGl0aW9uMiwgQ29uZGl0aW9uUG9zaXRpb24uVHdvKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBzaW1wbGVNb2RlbCA9IG1vZGVsO1xuICAgICAgICAgICAgdGhpcy5lSm9pbk9wZXJhdG9yQW5kLnNldFZhbHVlKHRoaXMuaXNEZWZhdWx0T3BlcmF0b3IoJ0FORCcpKTtcbiAgICAgICAgICAgIHRoaXMuZUpvaW5PcGVyYXRvck9yLnNldFZhbHVlKHRoaXMuaXNEZWZhdWx0T3BlcmF0b3IoJ09SJykpO1xuICAgICAgICAgICAgdGhpcy5lVHlwZTEuc2V0VmFsdWUoc2ltcGxlTW9kZWwudHlwZSk7XG4gICAgICAgICAgICB0aGlzLmVUeXBlMi5zZXRWYWx1ZSh0aGlzLm9wdGlvbnNGYWN0b3J5LmdldERlZmF1bHRPcHRpb24oKSk7XG4gICAgICAgICAgICB0aGlzLnNldENvbmRpdGlvbkludG9VaShzaW1wbGVNb2RlbCwgQ29uZGl0aW9uUG9zaXRpb24uT25lKTtcbiAgICAgICAgICAgIHRoaXMuc2V0Q29uZGl0aW9uSW50b1VpKG51bGwsIENvbmRpdGlvblBvc2l0aW9uLlR3byk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEFnUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmRvZXNGaWx0ZXJQYXNzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbW9kZWwgPSB0aGlzLmdldE1vZGVsKCk7XG4gICAgICAgIGlmIChtb2RlbCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3BlcmF0b3IgPSBtb2RlbC5vcGVyYXRvcjtcbiAgICAgICAgdmFyIG1vZGVscyA9IFtdO1xuICAgICAgICBpZiAob3BlcmF0b3IpIHtcbiAgICAgICAgICAgIHZhciBjb21iaW5lZE1vZGVsID0gbW9kZWw7XG4gICAgICAgICAgICBtb2RlbHMucHVzaChjb21iaW5lZE1vZGVsLmNvbmRpdGlvbjEsIGNvbWJpbmVkTW9kZWwuY29uZGl0aW9uMik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtb2RlbHMucHVzaChtb2RlbCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbWJpbmVGdW5jdGlvbiA9IG9wZXJhdG9yICYmIG9wZXJhdG9yID09PSAnT1InID8gJ3NvbWUnIDogJ2V2ZXJ5JztcbiAgICAgICAgcmV0dXJuIG1vZGVsc1tjb21iaW5lRnVuY3Rpb25dKGZ1bmN0aW9uIChtKSB7IHJldHVybiBfdGhpcy5pbmRpdmlkdWFsQ29uZGl0aW9uUGFzc2VzKHBhcmFtcywgbSk7IH0pO1xuICAgIH07XG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5zZXRQYXJhbXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuc2V0UGFyYW1zLmNhbGwodGhpcywgcGFyYW1zKTtcbiAgICAgICAgdGhpcy5vcHRpb25zRmFjdG9yeSA9IG5ldyBPcHRpb25zRmFjdG9yeSgpO1xuICAgICAgICB0aGlzLm9wdGlvbnNGYWN0b3J5LmluaXQocGFyYW1zLCB0aGlzLmdldERlZmF1bHRGaWx0ZXJPcHRpb25zKCkpO1xuICAgICAgICB0aGlzLmFsbG93VHdvQ29uZGl0aW9ucyA9ICFwYXJhbXMuc3VwcHJlc3NBbmRPckNvbmRpdGlvbjtcbiAgICAgICAgdGhpcy5hbHdheXNTaG93Qm90aENvbmRpdGlvbnMgPSAhIXBhcmFtcy5hbHdheXNTaG93Qm90aENvbmRpdGlvbnM7XG4gICAgICAgIHRoaXMuZGVmYXVsdEpvaW5PcGVyYXRvciA9IHRoaXMuZ2V0RGVmYXVsdEpvaW5PcGVyYXRvcihwYXJhbXMuZGVmYXVsdEpvaW5PcGVyYXRvcik7XG4gICAgICAgIHRoaXMucHV0T3B0aW9uc0ludG9Ecm9wZG93bigpO1xuICAgICAgICB0aGlzLmFkZENoYW5nZWRMaXN0ZW5lcnMoKTtcbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuZ2V0RGVmYXVsdEpvaW5PcGVyYXRvciA9IGZ1bmN0aW9uIChkZWZhdWx0Sm9pbk9wZXJhdG9yKSB7XG4gICAgICAgIHJldHVybiBpbmNsdWRlcyhbJ0FORCcsICdPUiddLCBkZWZhdWx0Sm9pbk9wZXJhdG9yKSA/IGRlZmF1bHRKb2luT3BlcmF0b3IgOiAnQU5EJztcbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUucHV0T3B0aW9uc0ludG9Ecm9wZG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGZpbHRlck9wdGlvbnMgPSB0aGlzLm9wdGlvbnNGYWN0b3J5LmdldEZpbHRlck9wdGlvbnMoKTtcbiAgICAgICAgdmFyIGVUeXBlcyA9IFt0aGlzLmVUeXBlMSwgdGhpcy5lVHlwZTJdO1xuICAgICAgICAvLyBBZGQgc3BlY2lmaWVkIG9wdGlvbnMgdG8gYWxsIGNvbmRpdGlvbiBkcm9wLWRvd25zLlxuICAgICAgICBmaWx0ZXJPcHRpb25zLmZvckVhY2goZnVuY3Rpb24gKG9wdGlvbikge1xuICAgICAgICAgICAgdmFyIGxpc3RPcHRpb24gPSB0eXBlb2Ygb3B0aW9uID09PSAnc3RyaW5nJyA/XG4gICAgICAgICAgICAgICAgX3RoaXMuY3JlYXRlQm9pbGVycGxhdGVMaXN0T3B0aW9uKG9wdGlvbikgOlxuICAgICAgICAgICAgICAgIF90aGlzLmNyZWF0ZUN1c3RvbUxpc3RPcHRpb24ob3B0aW9uKTtcbiAgICAgICAgICAgIGVUeXBlcy5mb3JFYWNoKGZ1bmN0aW9uIChlVHlwZSkgeyByZXR1cm4gZVR5cGUuYWRkT3B0aW9uKGxpc3RPcHRpb24pOyB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIE1ha2UgZHJvcC1kb3ducyByZWFkLW9ubHkgaWYgdGhlcmUgaXMgb25seSBvbmUgb3B0aW9uLlxuICAgICAgICBlVHlwZXMuZm9yRWFjaChmdW5jdGlvbiAoZVR5cGUpIHsgcmV0dXJuIGVUeXBlLnNldERpc2FibGVkKGZpbHRlck9wdGlvbnMubGVuZ3RoIDw9IDEpOyB9KTtcbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuY3JlYXRlQm9pbGVycGxhdGVMaXN0T3B0aW9uID0gZnVuY3Rpb24gKG9wdGlvbikge1xuICAgICAgICByZXR1cm4geyB2YWx1ZTogb3B0aW9uLCB0ZXh0OiB0aGlzLnRyYW5zbGF0ZShvcHRpb24pIH07XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmNyZWF0ZUN1c3RvbUxpc3RPcHRpb24gPSBmdW5jdGlvbiAob3B0aW9uKSB7XG4gICAgICAgIHZhciBkaXNwbGF5S2V5ID0gb3B0aW9uLmRpc3BsYXlLZXk7XG4gICAgICAgIHZhciBjdXN0b21PcHRpb24gPSB0aGlzLm9wdGlvbnNGYWN0b3J5LmdldEN1c3RvbU9wdGlvbihvcHRpb24uZGlzcGxheUtleSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogZGlzcGxheUtleSxcbiAgICAgICAgICAgIHRleHQ6IGN1c3RvbU9wdGlvbiA/XG4gICAgICAgICAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKShjdXN0b21PcHRpb24uZGlzcGxheUtleSwgY3VzdG9tT3B0aW9uLmRpc3BsYXlOYW1lKSA6XG4gICAgICAgICAgICAgICAgdGhpcy50cmFuc2xhdGUoZGlzcGxheUtleSksXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmlzQWxsb3dUd29Db25kaXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hbGxvd1R3b0NvbmRpdGlvbnM7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmNyZWF0ZUJvZHlUZW1wbGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIC8qIGh0bWwgKi8gXCJcXG4gICAgICAgICAgICA8YWctc2VsZWN0IGNsYXNzPVxcXCJhZy1maWx0ZXItc2VsZWN0XFxcIiByZWY9XFxcImVPcHRpb25zMVxcXCI+PC9hZy1zZWxlY3Q+XFxuICAgICAgICAgICAgXCIgKyB0aGlzLmNyZWF0ZVZhbHVlVGVtcGxhdGUoQ29uZGl0aW9uUG9zaXRpb24uT25lKSArIFwiXFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmlsdGVyLWNvbmRpdGlvblxcXCIgcmVmPVxcXCJlSm9pbk9wZXJhdG9yUGFuZWxcXFwiPlxcbiAgICAgICAgICAgICAgIDxhZy1yYWRpby1idXR0b24gcmVmPVxcXCJlSm9pbk9wZXJhdG9yQW5kXFxcIiBjbGFzcz1cXFwiYWctZmlsdGVyLWNvbmRpdGlvbi1vcGVyYXRvciBhZy1maWx0ZXItY29uZGl0aW9uLW9wZXJhdG9yLWFuZFxcXCI+PC9hZy1yYWRpby1idXR0b24+XFxuICAgICAgICAgICAgICAgPGFnLXJhZGlvLWJ1dHRvbiByZWY9XFxcImVKb2luT3BlcmF0b3JPclxcXCIgY2xhc3M9XFxcImFnLWZpbHRlci1jb25kaXRpb24tb3BlcmF0b3IgYWctZmlsdGVyLWNvbmRpdGlvbi1vcGVyYXRvci1vclxcXCI+PC9hZy1yYWRpby1idXR0b24+XFxuICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgICAgPGFnLXNlbGVjdCBjbGFzcz1cXFwiYWctZmlsdGVyLXNlbGVjdFxcXCIgcmVmPVxcXCJlT3B0aW9uczJcXFwiPjwvYWctc2VsZWN0PlxcbiAgICAgICAgICAgIFwiICsgdGhpcy5jcmVhdGVWYWx1ZVRlbXBsYXRlKENvbmRpdGlvblBvc2l0aW9uLlR3byk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmdldENzc0lkZW50aWZpZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnc2ltcGxlLWZpbHRlcic7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLnVwZGF0ZVVpVmlzaWJpbGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGVsZW1lbnRDb25kaXRpb25Hcm91cHMgPSBbXG4gICAgICAgICAgICBbdGhpcy5lVHlwZTFdLFxuICAgICAgICAgICAgW3RoaXMuZVR5cGUyLCB0aGlzLmVKb2luT3BlcmF0b3JQYW5lbCwgdGhpcy5lSm9pbk9wZXJhdG9yQW5kLCB0aGlzLmVKb2luT3BlcmF0b3JPcl0sXG4gICAgICAgIF07XG4gICAgICAgIHZhciBlbGVtZW50Qm9kaWVzID0gW3RoaXMuZUNvbmRpdGlvbjFCb2R5LCB0aGlzLmVDb25kaXRpb24yQm9keV07XG4gICAgICAgIGVsZW1lbnRDb25kaXRpb25Hcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZ3JvdXAsIHBvc2l0aW9uKSB7XG4gICAgICAgICAgICB2YXIgdmlzaWJsZSA9IF90aGlzLmlzQ29uZGl0aW9uVmlzaWJsZShwb3NpdGlvbik7XG4gICAgICAgICAgICB2YXIgZGlzYWJsZWQgPSBfdGhpcy5pc0NvbmRpdGlvbkRpc2FibGVkKHBvc2l0aW9uKTtcbiAgICAgICAgICAgIGdyb3VwLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCBpbnN0YW5jZW9mIEFnQWJzdHJhY3RJbnB1dEZpZWxkIHx8IGVsZW1lbnQgaW5zdGFuY2VvZiBBZ1NlbGVjdCkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldERpc2FibGVkKGRpc2FibGVkKTtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXREaXNwbGF5ZWQodmlzaWJsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzZXREaXNhYmxlZChlbGVtZW50LCBkaXNhYmxlZCk7XG4gICAgICAgICAgICAgICAgICAgIHNldERpc3BsYXllZChlbGVtZW50LCB2aXNpYmxlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGVsZW1lbnRCb2RpZXMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHNldERpc3BsYXllZChlbGVtZW50LCBfdGhpcy5pc0NvbmRpdGlvbkJvZHlWaXNpYmxlKGluZGV4KSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmZvckVhY2hJbnB1dChmdW5jdGlvbiAoZWxlbWVudCwgaW5kZXgsIHBvc2l0aW9uLCBudW1iZXJPZklucHV0cykge1xuICAgICAgICAgICAgX3RoaXMuc2V0RWxlbWVudERpc3BsYXllZChlbGVtZW50LCBpbmRleCA8IG51bWJlck9mSW5wdXRzKTtcbiAgICAgICAgICAgIF90aGlzLnNldEVsZW1lbnREaXNhYmxlZChlbGVtZW50LCBfdGhpcy5pc0NvbmRpdGlvbkRpc2FibGVkKHBvc2l0aW9uKSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJlc2V0UGxhY2Vob2xkZXIoKTtcbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuYWZ0ZXJHdWlBdHRhY2hlZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5hZnRlckd1aUF0dGFjaGVkLmNhbGwodGhpcywgcGFyYW1zKTtcbiAgICAgICAgdGhpcy5yZXNldFBsYWNlaG9sZGVyKCk7XG4gICAgICAgIGlmICghcGFyYW1zIHx8ICghcGFyYW1zLnN1cHByZXNzRm9jdXMgJiYgIXRoaXMuaXNSZWFkT25seSgpKSkge1xuICAgICAgICAgICAgdmFyIGZpcnN0SW5wdXQgPSB0aGlzLmdldElucHV0cygpWzBdWzBdO1xuICAgICAgICAgICAgaWYgKCFmaXJzdElucHV0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpcnN0SW5wdXQgaW5zdGFuY2VvZiBBZ0Fic3RyYWN0SW5wdXRGaWVsZCkge1xuICAgICAgICAgICAgICAgIGZpcnN0SW5wdXQuZ2V0SW5wdXRFbGVtZW50KCkuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gYWxsb3cgc3ViLWNsYXNzZXMgdG8gcmVzZXQgSFRNTCBwbGFjZWhvbGRlcnMgYWZ0ZXIgVUkgdXBkYXRlLlxuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUucmVzZXRQbGFjZWhvbGRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGdsb2JhbFRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHRoaXMuZm9yRWFjaElucHV0KGZ1bmN0aW9uIChlbGVtZW50LCBpbmRleCwgXywgbnVtYmVyT2ZJbnB1dHMpIHtcbiAgICAgICAgICAgIGlmICghKGVsZW1lbnQgaW5zdGFuY2VvZiBBZ0Fic3RyYWN0SW5wdXRGaWVsZCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcGxhY2Vob2xkZXIgPSBpbmRleCA9PT0gMCAmJiBudW1iZXJPZklucHV0cyA+IDEgPyAnaW5SYW5nZVN0YXJ0JyA6XG4gICAgICAgICAgICAgICAgaW5kZXggPT09IDAgPyAnZmlsdGVyT29vJyA6XG4gICAgICAgICAgICAgICAgICAgICdpblJhbmdlRW5kJztcbiAgICAgICAgICAgIHZhciBhcmlhTGFiZWwgPSBpbmRleCA9PT0gMCAmJiBudW1iZXJPZklucHV0cyA+IDEgPyBnbG9iYWxUcmFuc2xhdGUoJ2FyaWFGaWx0ZXJGcm9tVmFsdWUnLCAnRmlsdGVyIGZyb20gdmFsdWUnKSA6XG4gICAgICAgICAgICAgICAgaW5kZXggPT09IDAgPyBnbG9iYWxUcmFuc2xhdGUoJ2FyaWFGaWx0ZXJWYWx1ZScsICdGaWx0ZXIgVmFsdWUnKSA6XG4gICAgICAgICAgICAgICAgICAgIGdsb2JhbFRyYW5zbGF0ZSgnYXJpYUZpbHRlclRvVmFsdWUnLCAnRmlsdGVyIHRvIFZhbHVlJyk7XG4gICAgICAgICAgICBlbGVtZW50LnNldElucHV0UGxhY2Vob2xkZXIoX3RoaXMudHJhbnNsYXRlKHBsYWNlaG9sZGVyKSk7XG4gICAgICAgICAgICBlbGVtZW50LnNldElucHV0QXJpYUxhYmVsKGFyaWFMYWJlbCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5zZXRFbGVtZW50VmFsdWUgPSBmdW5jdGlvbiAoZWxlbWVudCwgdmFsdWUsIHNpbGVudCkge1xuICAgICAgICBpZiAoZWxlbWVudCBpbnN0YW5jZW9mIEFnQWJzdHJhY3RJbnB1dEZpZWxkKSB7XG4gICAgICAgICAgICBlbGVtZW50LnNldFZhbHVlKHZhbHVlICE9IG51bGwgPyBTdHJpbmcodmFsdWUpIDogbnVsbCwgc2lsZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5zZXRFbGVtZW50RGlzcGxheWVkID0gZnVuY3Rpb24gKGVsZW1lbnQsIGRpc3BsYXllZCkge1xuICAgICAgICBpZiAoZWxlbWVudCBpbnN0YW5jZW9mIENvbXBvbmVudCkge1xuICAgICAgICAgICAgc2V0RGlzcGxheWVkKGVsZW1lbnQuZ2V0R3VpKCksIGRpc3BsYXllZCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuc2V0RWxlbWVudERpc2FibGVkID0gZnVuY3Rpb24gKGVsZW1lbnQsIGRpc2FibGVkKSB7XG4gICAgICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgQ29tcG9uZW50KSB7XG4gICAgICAgICAgICBzZXREaXNhYmxlZChlbGVtZW50LmdldEd1aSgpLCBkaXNhYmxlZCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuYXR0YWNoRWxlbWVudE9uQ2hhbmdlID0gZnVuY3Rpb24gKGVsZW1lbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgQWdBYnN0cmFjdElucHV0RmllbGQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQub25WYWx1ZUNoYW5nZShsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuZm9yRWFjaElucHV0ID0gZnVuY3Rpb24gKGNiKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBpbnB1dHMgPSB0aGlzLmdldElucHV0cygpO1xuICAgICAgICB0aGlzLmdldENvbmRpdGlvblR5cGVzKCkuZm9yRWFjaChmdW5jdGlvbiAodHlwZSwgcG9zaXRpb24pIHtcbiAgICAgICAgICAgIHZhciBudW1iZXJPZklucHV0cyA9IF90aGlzLmdldE51bWJlck9mSW5wdXRzKHR5cGUpO1xuICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGlucHV0c1twb3NpdGlvbl0ubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gaW5wdXRzW3Bvc2l0aW9uXVtpbmRleF07XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2IoaW5wdXQsIGluZGV4LCBwb3NpdGlvbiwgbnVtYmVyT2ZJbnB1dHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmlzQ29uZGl0aW9uVmlzaWJsZSA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IC8vIFBvc2l0aW9uIDAgc2hvdWxkIGFsd2F5cyBiZSB2aXNpYmxlLlxuICAgICAgICBpZiAoIXRoaXMuYWxsb3dUd29Db25kaXRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gLy8gU2hvcnQtY2lyY3VpdCBpZiBubyB0YWlsIGNvbmRpdGlvbnMuXG4gICAgICAgIGlmICh0aGlzLmlzUmVhZE9ubHkoKSkge1xuICAgICAgICAgICAgLy8gT25seSBkaXNwbGF5IGEgY29uZGl0aW9uIHdoZW4gcmVhZC1vbmx5IGlmIHRoZSBjb25kaXRpb24gaXMgY29tcGxldGUuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pc0NvbmRpdGlvblVpQ29tcGxldGUocG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmFsd2F5c1Nob3dCb3RoQ29uZGl0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gT25seSBkaXNwbGF5IGEgMm5kIG9yIGxhdGVyIGNvbmRpdGlvbiB3aGVuIHRoZSBwcmV2aW91cyBjb25kaXRpb24gaXMgY29tcGxldGUuXG4gICAgICAgIHJldHVybiB0aGlzLmlzQ29uZGl0aW9uVWlDb21wbGV0ZShwb3NpdGlvbiAtIDEpO1xuICAgIH07XG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5pc0NvbmRpdGlvbkRpc2FibGVkID0gZnVuY3Rpb24gKHBvc2l0aW9uKSB7XG4gICAgICAgIGlmICh0aGlzLmlzUmVhZE9ubHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gLy8gUmVhZC1vbmx5IG1vZGUgdHJ1bXBzIGV2ZXJ5dGhpbmcuXG4gICAgICAgIGlmICghdGhpcy5pc0NvbmRpdGlvblZpc2libGUocG9zaXRpb24pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSAvLyBJbnZpc2libGUgaW1wbGllcyBkaXNhYmxlZC5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gLy8gUG9zaXRpb24gMCBzaG91bGQgdHlwaWNhbGx5IGJlIGVkaXRhYmxlLlxuICAgICAgICAvLyBPbmx5IGFsbG93IGVkaXRpbmcgb2YgYSAybmQgb3IgbGF0ZXIgY29uZGl0aW9uIGlmIHRoZSBwcmV2aW91cyBjb25kaXRpb24gaXMgY29tcGxldGUuXG4gICAgICAgIHJldHVybiAhdGhpcy5pc0NvbmRpdGlvblVpQ29tcGxldGUocG9zaXRpb24gLSAxKTtcbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuaXNDb25kaXRpb25Cb2R5VmlzaWJsZSA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICBpZiAoIXRoaXMuaXNDb25kaXRpb25WaXNpYmxlKHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIHRoYXQgdGhlIGNvbmRpdGlvbiBuZWVkcyBpbnB1dHMuXG4gICAgICAgIHZhciB0eXBlID0gdGhpcy5nZXRDb25kaXRpb25UeXBlcygpW3Bvc2l0aW9uXTtcbiAgICAgICAgdmFyIG51bWJlck9mSW5wdXRzID0gdGhpcy5nZXROdW1iZXJPZklucHV0cyh0eXBlKTtcbiAgICAgICAgcmV0dXJuIG51bWJlck9mSW5wdXRzID4gMDtcbiAgICB9O1xuICAgIC8vIHJldHVybnMgdHJ1ZSBpZiB0aGUgVUkgcmVwcmVzZW50cyBhIHdvcmtpbmcgZmlsdGVyLCBlZyBhbGwgcGFydHMgYXJlIGZpbGxlZCBvdXQuXG4gICAgLy8gZWcgaWYgdGV4dCBmaWx0ZXIgYW5kIHRleHRmaWVsZCBibGFuayB0aGVuIHJldHVybnMgZmFsc2UuXG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5pc0NvbmRpdGlvblVpQ29tcGxldGUgPSBmdW5jdGlvbiAocG9zaXRpb24pIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0aGlzLmdldENvbmRpdGlvblR5cGVzKClbcG9zaXRpb25dO1xuICAgICAgICBpZiAodHlwZSA9PT0gU2ltcGxlRmlsdGVyLkVNUFRZKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZ2V0VmFsdWVzKHBvc2l0aW9uKS5zb21lKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2ID09IG51bGw7IH0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLnJlc2V0VWlUb0RlZmF1bHRzID0gZnVuY3Rpb24gKHNpbGVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIGZpbHRlcmluZ0xhYmVsID0gdHJhbnNsYXRlKCdhcmlhRmlsdGVyaW5nT3BlcmF0b3InLCAnRmlsdGVyaW5nIG9wZXJhdG9yJyk7XG4gICAgICAgIHZhciB1bmlxdWVHcm91cElkID0gJ2FnLXNpbXBsZS1maWx0ZXItYW5kLW9yLScgKyB0aGlzLmdldENvbXBJZCgpO1xuICAgICAgICB2YXIgZGVmYXVsdE9wdGlvbiA9IHRoaXMub3B0aW9uc0ZhY3RvcnkuZ2V0RGVmYXVsdE9wdGlvbigpO1xuICAgICAgICB0aGlzLmVUeXBlMVxuICAgICAgICAgICAgLnNldFZhbHVlKGRlZmF1bHRPcHRpb24sIHNpbGVudClcbiAgICAgICAgICAgIC5zZXRBcmlhTGFiZWwoZmlsdGVyaW5nTGFiZWwpXG4gICAgICAgICAgICAuc2V0RGlzYWJsZWQodGhpcy5pc1JlYWRPbmx5KCkpO1xuICAgICAgICB0aGlzLmVUeXBlMlxuICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMub3B0aW9uc0ZhY3RvcnkuZ2V0RGVmYXVsdE9wdGlvbigpLCBzaWxlbnQpXG4gICAgICAgICAgICAuc2V0QXJpYUxhYmVsKGZpbHRlcmluZ0xhYmVsKVxuICAgICAgICAgICAgLnNldERpc2FibGVkKHRoaXMuaXNSZWFkT25seSgpKTtcbiAgICAgICAgdGhpcy5lSm9pbk9wZXJhdG9yQW5kXG4gICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5pc0RlZmF1bHRPcGVyYXRvcignQU5EJyksIHNpbGVudClcbiAgICAgICAgICAgIC5zZXROYW1lKHVuaXF1ZUdyb3VwSWQpXG4gICAgICAgICAgICAuc2V0TGFiZWwodGhpcy50cmFuc2xhdGUoJ2FuZENvbmRpdGlvbicpKVxuICAgICAgICAgICAgLnNldERpc2FibGVkKHRoaXMuaXNSZWFkT25seSgpKTtcbiAgICAgICAgdGhpcy5lSm9pbk9wZXJhdG9yT3JcbiAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLmlzRGVmYXVsdE9wZXJhdG9yKCdPUicpLCBzaWxlbnQpXG4gICAgICAgICAgICAuc2V0TmFtZSh1bmlxdWVHcm91cElkKVxuICAgICAgICAgICAgLnNldExhYmVsKHRoaXMudHJhbnNsYXRlKCdvckNvbmRpdGlvbicpKVxuICAgICAgICAgICAgLnNldERpc2FibGVkKHRoaXMuaXNSZWFkT25seSgpKTtcbiAgICAgICAgdGhpcy5mb3JFYWNoSW5wdXQoZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIF90aGlzLnNldEVsZW1lbnRWYWx1ZShlbGVtZW50LCBudWxsLCBzaWxlbnQpO1xuICAgICAgICAgICAgX3RoaXMuc2V0RWxlbWVudERpc2FibGVkKGVsZW1lbnQsIF90aGlzLmlzUmVhZE9ubHkoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJlc2V0UGxhY2Vob2xkZXIoKTtcbiAgICAgICAgcmV0dXJuIEFnUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfTtcbiAgICAvLyBwdXRzIG1vZGVsIHZhbHVlcyBpbnRvIHRoZSBVSVxuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuc2V0Q29uZGl0aW9uSW50b1VpID0gZnVuY3Rpb24gKG1vZGVsLCBwb3NpdGlvbikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdmFsdWVzID0gdGhpcy5tYXBWYWx1ZXNGcm9tTW9kZWwobW9kZWwpO1xuICAgICAgICB0aGlzLmZvckVhY2hJbnB1dChmdW5jdGlvbiAoZWxlbWVudCwgaW5kZXgsIGVsUG9zaXRpb24sIF8pIHtcbiAgICAgICAgICAgIGlmIChlbFBvc2l0aW9uICE9PSBwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLnNldEVsZW1lbnRWYWx1ZShlbGVtZW50LCB2YWx1ZXNbaW5kZXhdICE9IG51bGwgPyB2YWx1ZXNbaW5kZXhdIDogbnVsbCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gYWZ0ZXIgZmxvYXRpbmcgZmlsdGVyIGNoYW5nZXMsIHRoaXMgc2V0cyB0aGUgJ3ZhbHVlJyBzZWN0aW9uLiB0aGlzIGlzIGltcGxlbWVudGVkIGJ5IHRoZSBiYXNlIGNsYXNzXG4gICAgLy8gKGFzIHRoYXQncyB3aGVyZSB2YWx1ZSBpcyBjb250cm9sbGVkKSwgdGhlICd0eXBlJyBwYXJ0IGZyb20gdGhlIGZsb2F0aW5nIGZpbHRlciBpcyBkZWFsdCB3aXRoIGluIHRoaXMgY2xhc3MuXG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5zZXRWYWx1ZUZyb21GbG9hdGluZ0ZpbHRlciA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmZvckVhY2hJbnB1dChmdW5jdGlvbiAoZWxlbWVudCwgaW5kZXgsIHBvc2l0aW9uLCBfKSB7XG4gICAgICAgICAgICBfdGhpcy5zZXRFbGVtZW50VmFsdWUoZWxlbWVudCwgaW5kZXggPT09IDAgJiYgcG9zaXRpb24gPT09IDAgPyB2YWx1ZSA6IG51bGwpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFNpbXBsZUZpbHRlci5wcm90b3R5cGUuaXNEZWZhdWx0T3BlcmF0b3IgPSBmdW5jdGlvbiAob3BlcmF0b3IpIHtcbiAgICAgICAgcmV0dXJuIG9wZXJhdG9yID09PSB0aGlzLmRlZmF1bHRKb2luT3BlcmF0b3I7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmFkZENoYW5nZWRMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLmlzUmVhZE9ubHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uVWlDaGFuZ2VkKCk7IH07XG4gICAgICAgIHRoaXMuZVR5cGUxLm9uVmFsdWVDaGFuZ2UobGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmVUeXBlMi5vblZhbHVlQ2hhbmdlKGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5lSm9pbk9wZXJhdG9yT3Iub25WYWx1ZUNoYW5nZShsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuZUpvaW5PcGVyYXRvckFuZC5vblZhbHVlQ2hhbmdlKGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5mb3JFYWNoSW5wdXQoZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIF90aGlzLmF0dGFjaEVsZW1lbnRPbkNoYW5nZShlbGVtZW50LCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLyoqIHJldHVybnMgdHJ1ZSBpZiB0aGUgcm93IHBhc3NlcyB0aGUgc2FpZCBjb25kaXRpb24gKi9cbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmluZGl2aWR1YWxDb25kaXRpb25QYXNzZXMgPSBmdW5jdGlvbiAocGFyYW1zLCBmaWx0ZXJNb2RlbCkge1xuICAgICAgICB2YXIgY2VsbFZhbHVlID0gdGhpcy5nZXRDZWxsVmFsdWUocGFyYW1zLm5vZGUpO1xuICAgICAgICB2YXIgdmFsdWVzID0gdGhpcy5tYXBWYWx1ZXNGcm9tTW9kZWwoZmlsdGVyTW9kZWwpO1xuICAgICAgICB2YXIgY3VzdG9tRmlsdGVyT3B0aW9uID0gdGhpcy5vcHRpb25zRmFjdG9yeS5nZXRDdXN0b21PcHRpb24oZmlsdGVyTW9kZWwudHlwZSk7XG4gICAgICAgIHZhciBjdXN0b21GaWx0ZXJSZXN1bHQgPSB0aGlzLmV2YWx1YXRlQ3VzdG9tRmlsdGVyKGN1c3RvbUZpbHRlck9wdGlvbiwgdmFsdWVzLCBjZWxsVmFsdWUpO1xuICAgICAgICBpZiAoY3VzdG9tRmlsdGVyUmVzdWx0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBjdXN0b21GaWx0ZXJSZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNlbGxWYWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ldmFsdWF0ZU51bGxWYWx1ZShmaWx0ZXJNb2RlbC50eXBlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5ldmFsdWF0ZU5vbk51bGxWYWx1ZSh2YWx1ZXMsIGNlbGxWYWx1ZSwgZmlsdGVyTW9kZWwsIHBhcmFtcyk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLmV2YWx1YXRlQ3VzdG9tRmlsdGVyID0gZnVuY3Rpb24gKGN1c3RvbUZpbHRlck9wdGlvbiwgdmFsdWVzLCBjZWxsVmFsdWUpIHtcbiAgICAgICAgaWYgKGN1c3RvbUZpbHRlck9wdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByZWRpY2F0ZSA9IGN1c3RvbUZpbHRlck9wdGlvbi5wcmVkaWNhdGU7XG4gICAgICAgIC8vIG9ubHkgZXhlY3V0ZSB0aGUgY3VzdG9tIGZpbHRlciBpZiBhIHZhbHVlIGV4aXN0cyBvciBhIHZhbHVlIGlzbid0IHJlcXVpcmVkLCBpLmUuIGlucHV0IGlzIGhpZGRlblxuICAgICAgICBpZiAocHJlZGljYXRlICE9IG51bGwgJiYgIXZhbHVlcy5zb21lKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2ID09IG51bGw7IH0pKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZGljYXRlKHZhbHVlcywgY2VsbFZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBObyBjdXN0b20gZmlsdGVyIGludm9jYXRpb24sIGluZGljYXRlIHRoYXQgdG8gdGhlIGNhbGxlci5cbiAgICAgICAgcmV0dXJuO1xuICAgIH07XG4gICAgU2ltcGxlRmlsdGVyLnByb3RvdHlwZS5pc0JsYW5rID0gZnVuY3Rpb24gKGNlbGxWYWx1ZSkge1xuICAgICAgICByZXR1cm4gY2VsbFZhbHVlID09IG51bGwgfHxcbiAgICAgICAgICAgICh0eXBlb2YgY2VsbFZhbHVlID09PSAnc3RyaW5nJyAmJiBjZWxsVmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCk7XG4gICAgfTtcbiAgICBTaW1wbGVGaWx0ZXIuRU1QVFkgPSAnZW1wdHknO1xuICAgIFNpbXBsZUZpbHRlci5CTEFOSyA9ICdibGFuayc7XG4gICAgU2ltcGxlRmlsdGVyLk5PVF9CTEFOSyA9ICdub3RCbGFuayc7XG4gICAgU2ltcGxlRmlsdGVyLkVRVUFMUyA9ICdlcXVhbHMnO1xuICAgIFNpbXBsZUZpbHRlci5OT1RfRVFVQUwgPSAnbm90RXF1YWwnO1xuICAgIFNpbXBsZUZpbHRlci5MRVNTX1RIQU4gPSAnbGVzc1RoYW4nO1xuICAgIFNpbXBsZUZpbHRlci5MRVNTX1RIQU5fT1JfRVFVQUwgPSAnbGVzc1RoYW5PckVxdWFsJztcbiAgICBTaW1wbGVGaWx0ZXIuR1JFQVRFUl9USEFOID0gJ2dyZWF0ZXJUaGFuJztcbiAgICBTaW1wbGVGaWx0ZXIuR1JFQVRFUl9USEFOX09SX0VRVUFMID0gJ2dyZWF0ZXJUaGFuT3JFcXVhbCc7XG4gICAgU2ltcGxlRmlsdGVyLklOX1JBTkdFID0gJ2luUmFuZ2UnO1xuICAgIFNpbXBsZUZpbHRlci5DT05UQUlOUyA9ICdjb250YWlucyc7XG4gICAgU2ltcGxlRmlsdGVyLk5PVF9DT05UQUlOUyA9ICdub3RDb250YWlucyc7XG4gICAgU2ltcGxlRmlsdGVyLlNUQVJUU19XSVRIID0gJ3N0YXJ0c1dpdGgnO1xuICAgIFNpbXBsZUZpbHRlci5FTkRTX1dJVEggPSAnZW5kc1dpdGgnO1xuICAgIF9fZGVjb3JhdGUkMmcoW1xuICAgICAgICBSZWZTZWxlY3RvcignZU9wdGlvbnMxJylcbiAgICBdLCBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLCBcImVUeXBlMVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmcoW1xuICAgICAgICBSZWZTZWxlY3RvcignZU9wdGlvbnMyJylcbiAgICBdLCBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLCBcImVUeXBlMlwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmcoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUpvaW5PcGVyYXRvclBhbmVsJylcbiAgICBdLCBTaW1wbGVGaWx0ZXIucHJvdG90eXBlLCBcImVKb2luT3BlcmF0b3JQYW5lbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmcoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUpvaW5PcGVyYXRvckFuZCcpXG4gICAgXSwgU2ltcGxlRmlsdGVyLnByb3RvdHlwZSwgXCJlSm9pbk9wZXJhdG9yQW5kXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyZyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlSm9pbk9wZXJhdG9yT3InKVxuICAgIF0sIFNpbXBsZUZpbHRlci5wcm90b3R5cGUsIFwiZUpvaW5PcGVyYXRvck9yXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyZyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ29uZGl0aW9uMUJvZHknKVxuICAgIF0sIFNpbXBsZUZpbHRlci5wcm90b3R5cGUsIFwiZUNvbmRpdGlvbjFCb2R5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyZyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ29uZGl0aW9uMkJvZHknKVxuICAgIF0sIFNpbXBsZUZpbHRlci5wcm90b3R5cGUsIFwiZUNvbmRpdGlvbjJCb2R5XCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIFNpbXBsZUZpbHRlcjtcbn0oUHJvdmlkZWRGaWx0ZXIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyRCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIFNjYWxhckZpbHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkQoU2NhbGFyRmlsdGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNjYWxhckZpbHRlcigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBTY2FsYXJGaWx0ZXIucHJvdG90eXBlLnNldFBhcmFtcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5zZXRQYXJhbXMuY2FsbCh0aGlzLCBwYXJhbXMpO1xuICAgICAgICB0aGlzLnNjYWxhckZpbHRlclBhcmFtcyA9IHBhcmFtcztcbiAgICB9O1xuICAgIFNjYWxhckZpbHRlci5wcm90b3R5cGUuZXZhbHVhdGVOdWxsVmFsdWUgPSBmdW5jdGlvbiAoZmlsdGVyVHlwZSkge1xuICAgICAgICBzd2l0Y2ggKGZpbHRlclR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgU2NhbGFyRmlsdGVyLkVRVUFMUzpcbiAgICAgICAgICAgIGNhc2UgU2NhbGFyRmlsdGVyLk5PVF9FUVVBTDpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zY2FsYXJGaWx0ZXJQYXJhbXMuaW5jbHVkZUJsYW5rc0luRXF1YWxzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgU2NhbGFyRmlsdGVyLkdSRUFURVJfVEhBTjpcbiAgICAgICAgICAgIGNhc2UgU2NhbGFyRmlsdGVyLkdSRUFURVJfVEhBTl9PUl9FUVVBTDpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zY2FsYXJGaWx0ZXJQYXJhbXMuaW5jbHVkZUJsYW5rc0luR3JlYXRlclRoYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuTEVTU19USEFOOlxuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuTEVTU19USEFOX09SX0VRVUFMOlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNjYWxhckZpbHRlclBhcmFtcy5pbmNsdWRlQmxhbmtzSW5MZXNzVGhhbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFNjYWxhckZpbHRlci5JTl9SQU5HRTpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zY2FsYXJGaWx0ZXJQYXJhbXMuaW5jbHVkZUJsYW5rc0luUmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuQkxBTks6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBjYXNlIFNjYWxhckZpbHRlci5OT1RfQkxBTks6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFNjYWxhckZpbHRlci5wcm90b3R5cGUuZXZhbHVhdGVOb25OdWxsVmFsdWUgPSBmdW5jdGlvbiAodmFsdWVzLCBjZWxsVmFsdWUsIGZpbHRlck1vZGVsKSB7XG4gICAgICAgIHZhciBjb21wYXJhdG9yID0gdGhpcy5jb21wYXJhdG9yKCk7XG4gICAgICAgIHZhciBjb21wYXJlUmVzdWx0ID0gdmFsdWVzWzBdICE9IG51bGwgPyBjb21wYXJhdG9yKHZhbHVlc1swXSwgY2VsbFZhbHVlKSA6IDA7XG4gICAgICAgIHN3aXRjaCAoZmlsdGVyTW9kZWwudHlwZSkge1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuRVFVQUxTOlxuICAgICAgICAgICAgICAgIHJldHVybiBjb21wYXJlUmVzdWx0ID09PSAwO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuTk9UX0VRVUFMOlxuICAgICAgICAgICAgICAgIHJldHVybiBjb21wYXJlUmVzdWx0ICE9PSAwO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuR1JFQVRFUl9USEFOOlxuICAgICAgICAgICAgICAgIHJldHVybiBjb21wYXJlUmVzdWx0ID4gMDtcbiAgICAgICAgICAgIGNhc2UgU2NhbGFyRmlsdGVyLkdSRUFURVJfVEhBTl9PUl9FUVVBTDpcbiAgICAgICAgICAgICAgICByZXR1cm4gY29tcGFyZVJlc3VsdCA+PSAwO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuTEVTU19USEFOOlxuICAgICAgICAgICAgICAgIHJldHVybiBjb21wYXJlUmVzdWx0IDwgMDtcbiAgICAgICAgICAgIGNhc2UgU2NhbGFyRmlsdGVyLkxFU1NfVEhBTl9PUl9FUVVBTDpcbiAgICAgICAgICAgICAgICByZXR1cm4gY29tcGFyZVJlc3VsdCA8PSAwO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuSU5fUkFOR0U6IHtcbiAgICAgICAgICAgICAgICB2YXIgY29tcGFyZVRvUmVzdWx0ID0gY29tcGFyYXRvcih2YWx1ZXNbMV0sIGNlbGxWYWx1ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2NhbGFyRmlsdGVyUGFyYW1zLmluUmFuZ2VJbmNsdXNpdmUgP1xuICAgICAgICAgICAgICAgICAgICBjb21wYXJlUmVzdWx0ID49IDAgJiYgY29tcGFyZVRvUmVzdWx0IDw9IDAgOlxuICAgICAgICAgICAgICAgICAgICBjb21wYXJlUmVzdWx0ID4gMCAmJiBjb21wYXJlVG9SZXN1bHQgPCAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuQkxBTks6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNCbGFuayhjZWxsVmFsdWUpO1xuICAgICAgICAgICAgY2FzZSBTY2FsYXJGaWx0ZXIuTk9UX0JMQU5LOlxuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5pc0JsYW5rKGNlbGxWYWx1ZSk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogVW5leHBlY3RlZCB0eXBlIG9mIGZpbHRlciBcIicgKyBmaWx0ZXJNb2RlbC50eXBlICsgJ1wiLCBpdCBsb29rcyBsaWtlIHRoZSBmaWx0ZXIgd2FzIGNvbmZpZ3VyZWQgd2l0aCBpbmNvcnJlY3QgRmlsdGVyIE9wdGlvbnMnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFNjYWxhckZpbHRlcjtcbn0oU2ltcGxlRmlsdGVyKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMkMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiRiID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiRiID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiRiLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fZGVjb3JhdGUkMmYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBERUZBVUxUX01JTl9ZRUFSID0gMTAwMDtcbnZhciBERUZBVUxUX01BWF9ZRUFSID0gSW5maW5pdHk7XG52YXIgRGF0ZUZpbHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkMoRGF0ZUZpbHRlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEYXRlRmlsdGVyKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCAnZGF0ZUZpbHRlcicpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLm1pblZhbGlkWWVhciA9IERFRkFVTFRfTUlOX1lFQVI7XG4gICAgICAgIF90aGlzLm1heFZhbGlkWWVhciA9IERFRkFVTFRfTUFYX1lFQVI7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUuYWZ0ZXJHdWlBdHRhY2hlZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5hZnRlckd1aUF0dGFjaGVkLmNhbGwodGhpcywgcGFyYW1zKTtcbiAgICAgICAgdGhpcy5kYXRlQ29uZGl0aW9uMUZyb21Db21wLmFmdGVyR3VpQXR0YWNoZWQocGFyYW1zKTtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLm1hcFZhbHVlc0Zyb21Nb2RlbCA9IGZ1bmN0aW9uIChmaWx0ZXJNb2RlbCkge1xuICAgICAgICAvLyB1bmxpa2UgdGhlIG90aGVyIGZpbHRlcnMsIHdlIGRvIHR3byB0aGluZ3MgaGVyZTpcbiAgICAgICAgLy8gMSkgYWxsb3cgZm9yIGRpZmZlcmVudCBhdHRyaWJ1dGUgbmFtZXMgKHNhbWUgYXMgZG9uZSBmb3Igb3RoZXIgZmlsdGVycykgKGVnIHRoZSAnZnJvbScgYW5kICd0bydcbiAgICAgICAgLy8gICAgYXJlIGluIGRpZmZlcmVudCBsb2NhdGlvbnMgaW4gRGF0ZSBhbmQgTnVtYmVyIGZpbHRlciBtb2RlbHMpXG4gICAgICAgIC8vIDIpIGNvbnZlcnQgdGhlIHR5cGUgKGJlY2F1c2UgRGF0ZSBmaWx0ZXIgdXNlcyBEYXRlcywgaG93ZXZlciBtb2RlbCBpcyAnc3RyaW5nJylcbiAgICAgICAgLy9cbiAgICAgICAgLy8gTk9URTogVGhlIGNvbnZlcnNpb24gb2Ygc3RyaW5nIHRvIGRhdGUgYWxzbyByZW1vdmVzIHRoZSB0aW1lem9uZSAtIGkuZS4gd2hlbiB1c2VyIHBpY2tzXG4gICAgICAgIC8vICAgICAgIGEgZGF0ZSBmcm9tIHRoZSBVSSwgaXQgd2lsbCBoYXZlIHRpbWV6b25lIGluZm8gaW4gaXQuIFRoaXMgaXMgbG9zdCB3aGVuIGNyZWF0aW5nXG4gICAgICAgIC8vICAgICAgIHRoZSBtb2RlbC4gV2hlbiB3ZSByZWNyZWF0ZSB0aGUgZGF0ZSBhZ2FpbiBoZXJlLCBpdCdzIHdpdGhvdXQgYSB0aW1lem9uZS5cbiAgICAgICAgdmFyIF9hID0gZmlsdGVyTW9kZWwgfHwge30sIGRhdGVGcm9tID0gX2EuZGF0ZUZyb20sIGRhdGVUbyA9IF9hLmRhdGVUbywgdHlwZSA9IF9hLnR5cGU7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBkYXRlRnJvbSAmJiBwYXJzZURhdGVUaW1lRnJvbVN0cmluZyhkYXRlRnJvbSkgfHwgbnVsbCxcbiAgICAgICAgICAgIGRhdGVUbyAmJiBwYXJzZURhdGVUaW1lRnJvbVN0cmluZyhkYXRlVG8pIHx8IG51bGwsXG4gICAgICAgIF0uc2xpY2UoMCwgdGhpcy5nZXROdW1iZXJPZklucHV0cyh0eXBlKSk7XG4gICAgfTtcbiAgICBEYXRlRmlsdGVyLnByb3RvdHlwZS5jb21wYXJhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRlRmlsdGVyUGFyYW1zLmNvbXBhcmF0b3IgPyB0aGlzLmRhdGVGaWx0ZXJQYXJhbXMuY29tcGFyYXRvciA6IHRoaXMuZGVmYXVsdENvbXBhcmF0b3IuYmluZCh0aGlzKTtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLmRlZmF1bHRDb21wYXJhdG9yID0gZnVuY3Rpb24gKGZpbHRlckRhdGUsIGNlbGxWYWx1ZSkge1xuICAgICAgICAvLyBUaGUgZGVmYXVsdCBjb21wYXJhdG9yIGFzc3VtZXMgdGhhdCB0aGUgY2VsbFZhbHVlIGlzIGEgZGF0ZVxuICAgICAgICB2YXIgY2VsbEFzRGF0ZSA9IGNlbGxWYWx1ZTtcbiAgICAgICAgaWYgKGNlbGxWYWx1ZSA9PSBudWxsIHx8IGNlbGxBc0RhdGUgPCBmaWx0ZXJEYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNlbGxBc0RhdGUgPiBmaWx0ZXJEYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLnNldFBhcmFtcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5zZXRQYXJhbXMuY2FsbCh0aGlzLCBwYXJhbXMpO1xuICAgICAgICB0aGlzLmRhdGVGaWx0ZXJQYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIHZhciB5ZWFyUGFyc2VyID0gZnVuY3Rpb24gKHBhcmFtLCBmYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKHBhcmFtc1twYXJhbV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICghaXNOYU4ocGFyYW1zW3BhcmFtXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmFtc1twYXJhbV0gPT0gbnVsbCA/IGZhbGxiYWNrIDogTnVtYmVyKHBhcmFtc1twYXJhbV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogRGF0ZUZpbHRlciBcIiArIHBhcmFtICsgXCIgaXMgbm90IGEgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxsYmFjaztcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5taW5WYWxpZFllYXIgPSB5ZWFyUGFyc2VyKCdtaW5WYWxpZFllYXInLCBERUZBVUxUX01JTl9ZRUFSKTtcbiAgICAgICAgdGhpcy5tYXhWYWxpZFllYXIgPSB5ZWFyUGFyc2VyKCdtYXhWYWxpZFllYXInLCBERUZBVUxUX01BWF9ZRUFSKTtcbiAgICAgICAgaWYgKHRoaXMubWluVmFsaWRZZWFyID4gdGhpcy5tYXhWYWxpZFllYXIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IERhdGVGaWx0ZXIgbWluVmFsaWRZZWFyIHNob3VsZCBiZSA8PSBtYXhWYWxpZFllYXJcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVEYXRlQ29tcG9uZW50cygpO1xuICAgIH07XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUuY3JlYXRlRGF0ZUNvbXBvbmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjcmVhdGVEYXRlQ29tcFdyYXBwZXIgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBEYXRlQ29tcFdyYXBwZXIoX3RoaXMuZ2V0Q29udGV4dCgpLCBfdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeSwge1xuICAgICAgICAgICAgICAgIG9uRGF0ZUNoYW5nZWQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uVWlDaGFuZ2VkKCk7IH0sXG4gICAgICAgICAgICAgICAgZmlsdGVyUGFyYW1zOiBfdGhpcy5kYXRlRmlsdGVyUGFyYW1zXG4gICAgICAgICAgICB9LCBlbGVtZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kYXRlQ29uZGl0aW9uMUZyb21Db21wID0gY3JlYXRlRGF0ZUNvbXBXcmFwcGVyKHRoaXMuZUNvbmRpdGlvbjFQYW5lbEZyb20pO1xuICAgICAgICB0aGlzLmRhdGVDb25kaXRpb24xVG9Db21wID0gY3JlYXRlRGF0ZUNvbXBXcmFwcGVyKHRoaXMuZUNvbmRpdGlvbjFQYW5lbFRvKTtcbiAgICAgICAgdGhpcy5kYXRlQ29uZGl0aW9uMkZyb21Db21wID0gY3JlYXRlRGF0ZUNvbXBXcmFwcGVyKHRoaXMuZUNvbmRpdGlvbjJQYW5lbEZyb20pO1xuICAgICAgICB0aGlzLmRhdGVDb25kaXRpb24yVG9Db21wID0gY3JlYXRlRGF0ZUNvbXBXcmFwcGVyKHRoaXMuZUNvbmRpdGlvbjJQYW5lbFRvKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5mb3JFYWNoSW5wdXQoZnVuY3Rpb24gKGVsZW1lbnQpIHsgcmV0dXJuIGVsZW1lbnQuZGVzdHJveSgpOyB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBEYXRlRmlsdGVyLnByb3RvdHlwZS5zZXRFbGVtZW50VmFsdWUgPSBmdW5jdGlvbiAoZWxlbWVudCwgdmFsdWUsIHNpbGVudCkge1xuICAgICAgICBlbGVtZW50LnNldERhdGUodmFsdWUpO1xuICAgIH07XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUuc2V0RWxlbWVudERpc3BsYXllZCA9IGZ1bmN0aW9uIChlbGVtZW50LCBkaXNwbGF5ZWQpIHtcbiAgICAgICAgZWxlbWVudC5zZXREaXNwbGF5ZWQoZGlzcGxheWVkKTtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLnNldEVsZW1lbnREaXNhYmxlZCA9IGZ1bmN0aW9uIChlbGVtZW50LCBkaXNhYmxlZCkge1xuICAgICAgICBlbGVtZW50LnNldERpc2FibGVkKGRpc2FibGVkKTtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLmdldERlZmF1bHRGaWx0ZXJPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gRGF0ZUZpbHRlci5ERUZBVUxUX0ZJTFRFUl9PUFRJT05TO1xuICAgIH07XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUuY3JlYXRlVmFsdWVUZW1wbGF0ZSA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24gPT09IENvbmRpdGlvblBvc2l0aW9uLk9uZSA/ICcxJyA6ICcyJztcbiAgICAgICAgcmV0dXJuIC8qIGh0bWwgKi8gXCJcXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1maWx0ZXItYm9keVxcXCIgcmVmPVxcXCJlQ29uZGl0aW9uXCIgKyBwb3MgKyBcIkJvZHlcXFwiPlxcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1maWx0ZXItZnJvbSBhZy1maWx0ZXItZGF0ZS1mcm9tXFxcIiByZWY9XFxcImVDb25kaXRpb25cIiArIHBvcyArIFwiUGFuZWxGcm9tXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmlsdGVyLXRvIGFnLWZpbHRlci1kYXRlLXRvXFxcIiByZWY9XFxcImVDb25kaXRpb25cIiArIHBvcyArIFwiUGFuZWxUb1xcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XCI7XG4gICAgfTtcbiAgICBEYXRlRmlsdGVyLnByb3RvdHlwZS5pc0NvbmRpdGlvblVpQ29tcGxldGUgPSBmdW5jdGlvbiAocG9zaXRpb24pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFfc3VwZXIucHJvdG90eXBlLmlzQ29uZGl0aW9uVWlDb21wbGV0ZS5jYWxsKHRoaXMsIHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpc1ZhbGlkRGF0ZSA9IGZ1bmN0aW9uICh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgIT0gbnVsbFxuICAgICAgICAgICAgJiYgdmFsdWUuZ2V0VVRDRnVsbFllYXIoKSA+PSBfdGhpcy5taW5WYWxpZFllYXJcbiAgICAgICAgICAgICYmIHZhbHVlLmdldFVUQ0Z1bGxZZWFyKCkgPD0gX3RoaXMubWF4VmFsaWRZZWFyOyB9O1xuICAgICAgICB2YXIgdmFsaWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmZvckVhY2hJbnB1dChmdW5jdGlvbiAoZWxlbWVudCwgaW5kZXgsIGVsUG9zaXRpb24sIG51bWJlck9mSW5wdXRzKSB7XG4gICAgICAgICAgICBpZiAoZWxQb3NpdGlvbiAhPT0gcG9zaXRpb24gfHwgIXZhbGlkIHx8IGluZGV4ID49IG51bWJlck9mSW5wdXRzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFsaWQgPSB2YWxpZCAmJiBpc1ZhbGlkRGF0ZShlbGVtZW50LmdldERhdGUoKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdmFsaWQ7XG4gICAgfTtcbiAgICBEYXRlRmlsdGVyLnByb3RvdHlwZS5hcmVTaW1wbGVNb2RlbHNFcXVhbCA9IGZ1bmN0aW9uIChhU2ltcGxlLCBiU2ltcGxlKSB7XG4gICAgICAgIHJldHVybiBhU2ltcGxlLmRhdGVGcm9tID09PSBiU2ltcGxlLmRhdGVGcm9tXG4gICAgICAgICAgICAmJiBhU2ltcGxlLmRhdGVUbyA9PT0gYlNpbXBsZS5kYXRlVG9cbiAgICAgICAgICAgICYmIGFTaW1wbGUudHlwZSA9PT0gYlNpbXBsZS50eXBlO1xuICAgIH07XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUuZ2V0RmlsdGVyVHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICdkYXRlJztcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLmNyZWF0ZUNvbmRpdGlvbiA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICB2YXIgdHlwZSA9IHRoaXMuZ2V0Q29uZGl0aW9uVHlwZXMoKVtwb3NpdGlvbl07XG4gICAgICAgIHZhciBtb2RlbCA9IHt9O1xuICAgICAgICB2YXIgdmFsdWVzID0gdGhpcy5nZXRWYWx1ZXMocG9zaXRpb24pO1xuICAgICAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIG1vZGVsLmRhdGVGcm9tID0gc2VyaWFsaXNlRGF0ZSh2YWx1ZXNbMF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgbW9kZWwuZGF0ZVRvID0gc2VyaWFsaXNlRGF0ZSh2YWx1ZXNbMV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfX2Fzc2lnbiRiKHsgZGF0ZUZyb206IG51bGwsIGRhdGVUbzogbnVsbCwgZmlsdGVyVHlwZTogdGhpcy5nZXRGaWx0ZXJUeXBlKCksIHR5cGU6IHR5cGUgfSwgbW9kZWwpO1xuICAgIH07XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUucmVzZXRQbGFjZWhvbGRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGdsb2JhbFRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBwbGFjZWhvbGRlciA9IHRoaXMudHJhbnNsYXRlKCdkYXRlRm9ybWF0T29vJyk7XG4gICAgICAgIHZhciBhcmlhTGFiZWwgPSBnbG9iYWxUcmFuc2xhdGUoJ2FyaWFGaWx0ZXJWYWx1ZScsICdGaWx0ZXIgVmFsdWUnKTtcbiAgICAgICAgdGhpcy5mb3JFYWNoSW5wdXQoZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0SW5wdXRQbGFjZWhvbGRlcihwbGFjZWhvbGRlcik7XG4gICAgICAgICAgICBlbGVtZW50LnNldElucHV0QXJpYUxhYmVsKGFyaWFMYWJlbCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRGF0ZUZpbHRlci5wcm90b3R5cGUuZ2V0SW5wdXRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgW3RoaXMuZGF0ZUNvbmRpdGlvbjFGcm9tQ29tcCwgdGhpcy5kYXRlQ29uZGl0aW9uMVRvQ29tcF0sXG4gICAgICAgICAgICBbdGhpcy5kYXRlQ29uZGl0aW9uMkZyb21Db21wLCB0aGlzLmRhdGVDb25kaXRpb24yVG9Db21wXSxcbiAgICAgICAgXTtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIucHJvdG90eXBlLmdldFZhbHVlcyA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHRoaXMuZm9yRWFjaElucHV0KGZ1bmN0aW9uIChlbGVtZW50LCBpbmRleCwgZWxQb3NpdGlvbiwgbnVtYmVyT2ZJbnB1dHMpIHtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gZWxQb3NpdGlvbiAmJiBpbmRleCA8IG51bWJlck9mSW5wdXRzKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goZWxlbWVudC5nZXREYXRlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIERhdGVGaWx0ZXIuREVGQVVMVF9GSUxURVJfT1BUSU9OUyA9IFtcbiAgICAgICAgU2NhbGFyRmlsdGVyLkVRVUFMUyxcbiAgICAgICAgU2NhbGFyRmlsdGVyLkdSRUFURVJfVEhBTixcbiAgICAgICAgU2NhbGFyRmlsdGVyLkxFU1NfVEhBTixcbiAgICAgICAgU2NhbGFyRmlsdGVyLk5PVF9FUVVBTCxcbiAgICAgICAgU2NhbGFyRmlsdGVyLklOX1JBTkdFLFxuICAgICAgICBTY2FsYXJGaWx0ZXIuQkxBTkssXG4gICAgICAgIFNjYWxhckZpbHRlci5OT1RfQkxBTkssXG4gICAgXTtcbiAgICBfX2RlY29yYXRlJDJmKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VDb25kaXRpb24xUGFuZWxGcm9tJylcbiAgICBdLCBEYXRlRmlsdGVyLnByb3RvdHlwZSwgXCJlQ29uZGl0aW9uMVBhbmVsRnJvbVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmYoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUNvbmRpdGlvbjFQYW5lbFRvJylcbiAgICBdLCBEYXRlRmlsdGVyLnByb3RvdHlwZSwgXCJlQ29uZGl0aW9uMVBhbmVsVG9cIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJmKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VDb25kaXRpb24yUGFuZWxGcm9tJylcbiAgICBdLCBEYXRlRmlsdGVyLnByb3RvdHlwZSwgXCJlQ29uZGl0aW9uMlBhbmVsRnJvbVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmYoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUNvbmRpdGlvbjJQYW5lbFRvJylcbiAgICBdLCBEYXRlRmlsdGVyLnByb3RvdHlwZSwgXCJlQ29uZGl0aW9uMlBhbmVsVG9cIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJmKFtcbiAgICAgICAgQXV0b3dpcmVkKCd1c2VyQ29tcG9uZW50RmFjdG9yeScpXG4gICAgXSwgRGF0ZUZpbHRlci5wcm90b3R5cGUsIFwidXNlckNvbXBvbmVudEZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gRGF0ZUZpbHRlcjtcbn0oU2NhbGFyRmlsdGVyKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMkIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBTaW1wbGVGbG9hdGluZ0ZpbHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMkIoU2ltcGxlRmxvYXRpbmdGaWx0ZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2ltcGxlRmxvYXRpbmdGaWx0ZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgU2ltcGxlRmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmdldERlZmF1bHREZWJvdW5jZU1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9O1xuICAgIC8vIHRoaXMgaXMgYSB1c2VyIGNvbXBvbmVudCwgYW5kIElDb21wb25lbnQgaGFzIFwicHVibGljIGRlc3Ryb3koKVwiIGFzIHBhcnQgb2YgdGhlIGludGVyZmFjZS5cbiAgICAvLyBzbyB3ZSBuZWVkIHRvIG92ZXJyaWRlIGRlc3Ryb3koKSBqdXN0IHRvIG1ha2UgdGhlIG1ldGhvZCBwdWJsaWMuXG4gICAgU2ltcGxlRmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgLy8gdXNlZCBieTpcbiAgICAvLyAxKSBOdW1iZXJGbG9hdGluZ0ZpbHRlciAmIFRleHRGbG9hdGluZ0ZpbHRlcjogQWx3YXlzLCBmb3IgYm90aCB3aGVuIGVkaXRhYmxlIGFuZCByZWFkIG9ubHkuXG4gICAgLy8gMikgRGF0ZUZsb2F0aW5nRmlsdGVyOiBPbmx5IHdoZW4gcmVhZCBvbmx5IChhcyB3ZSBzaG93IHRleHQgcmF0aGVyIHRoYW4gYSBkYXRlIHBpY2tlciB3aGVuIHJlYWQgb25seSlcbiAgICBTaW1wbGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuZ2V0VGV4dEZyb21Nb2RlbCA9IGZ1bmN0aW9uIChtb2RlbCkge1xuICAgICAgICBpZiAoIW1vZGVsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNDb21iaW5lZCA9IG1vZGVsLm9wZXJhdG9yICE9IG51bGw7XG4gICAgICAgIGlmIChpc0NvbWJpbmVkKSB7XG4gICAgICAgICAgICB2YXIgY29tYmluZWRNb2RlbCA9IG1vZGVsO1xuICAgICAgICAgICAgdmFyIF9hID0gY29tYmluZWRNb2RlbCB8fCB7fSwgY29uZGl0aW9uMSA9IF9hLmNvbmRpdGlvbjEsIGNvbmRpdGlvbjIgPSBfYS5jb25kaXRpb24yO1xuICAgICAgICAgICAgdmFyIGN1c3RvbU9wdGlvbjEgPSB0aGlzLmdldFRleHRGcm9tTW9kZWwoY29uZGl0aW9uMSk7XG4gICAgICAgICAgICB2YXIgY3VzdG9tT3B0aW9uMiA9IHRoaXMuZ2V0VGV4dEZyb21Nb2RlbChjb25kaXRpb24yKTtcbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgY3VzdG9tT3B0aW9uMSxcbiAgICAgICAgICAgICAgICBjb21iaW5lZE1vZGVsLm9wZXJhdG9yLFxuICAgICAgICAgICAgICAgIGN1c3RvbU9wdGlvbjIsXG4gICAgICAgICAgICBdLmpvaW4oJyAnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBjb25kaXRpb24gPSBtb2RlbDtcbiAgICAgICAgICAgIHZhciBjdXN0b21PcHRpb24gPSB0aGlzLm9wdGlvbnNGYWN0b3J5LmdldEN1c3RvbU9wdGlvbihjb25kaXRpb24udHlwZSk7XG4gICAgICAgICAgICAvLyBGb3IgY3VzdG9tIGZpbHRlciBvcHRpb25zIHdlIGRpc3BsYXkgdGhlIE5hbWUgb2YgdGhlIGZpbHRlciBpbnN0ZWFkXG4gICAgICAgICAgICAvLyBvZiBkaXNwbGF5aW5nIHRoZSBgZnJvbWAgdmFsdWUsIGFzIGl0IHdvdWxkbid0IGJlIHJlbGV2YW50XG4gICAgICAgICAgICB2YXIgX2IgPSBjdXN0b21PcHRpb24gfHwge30sIGRpc3BsYXlLZXkgPSBfYi5kaXNwbGF5S2V5LCBkaXNwbGF5TmFtZSA9IF9iLmRpc3BsYXlOYW1lLCBudW1iZXJPZklucHV0cyA9IF9iLm51bWJlck9mSW5wdXRzO1xuICAgICAgICAgICAgaWYgKGRpc3BsYXlLZXkgJiYgZGlzcGxheU5hbWUgJiYgbnVtYmVyT2ZJbnB1dHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMb2NhbGVUZXh0RnVuYygpKGRpc3BsYXlLZXksIGRpc3BsYXlOYW1lKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlzcGxheU5hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25kaXRpb25Ub1N0cmluZyhjb25kaXRpb24sIGN1c3RvbU9wdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNpbXBsZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5pc0V2ZW50RnJvbUZsb2F0aW5nRmlsdGVyID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHJldHVybiBldmVudCAmJiBldmVudC5hZnRlckZsb2F0aW5nRmlsdGVyO1xuICAgIH07XG4gICAgU2ltcGxlRmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmdldExhc3RUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0VHlwZTtcbiAgICB9O1xuICAgIFNpbXBsZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5pc1JlYWRPbmx5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWFkT25seTtcbiAgICB9O1xuICAgIFNpbXBsZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5zZXRMYXN0VHlwZUZyb21Nb2RlbCA9IGZ1bmN0aW9uIChtb2RlbCkge1xuICAgICAgICAvLyBpZiBubyBtb2RlbCBwcm92aWRlZCBieSB0aGUgcGFyZW50IGZpbHRlciB1c2UgZGVmYXVsdFxuICAgICAgICBpZiAoIW1vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RUeXBlID0gdGhpcy5vcHRpb25zRmFjdG9yeS5nZXREZWZhdWx0T3B0aW9uKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGlzQ29tYmluZWQgPSBtb2RlbC5vcGVyYXRvcjtcbiAgICAgICAgdmFyIGNvbmRpdGlvbjtcbiAgICAgICAgaWYgKGlzQ29tYmluZWQpIHtcbiAgICAgICAgICAgIHZhciBjb21iaW5lZE1vZGVsID0gbW9kZWw7XG4gICAgICAgICAgICBjb25kaXRpb24gPSBjb21iaW5lZE1vZGVsLmNvbmRpdGlvbjE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25kaXRpb24gPSBtb2RlbDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhc3RUeXBlID0gY29uZGl0aW9uLnR5cGU7XG4gICAgfTtcbiAgICBTaW1wbGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuY2FuV2VFZGl0QWZ0ZXJNb2RlbEZyb21QYXJlbnRGaWx0ZXIgPSBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgaWYgKCFtb2RlbCkge1xuICAgICAgICAgICAgLy8gaWYgbm8gbW9kZWwsIHRoZW4gd2UgY2FuIGVkaXQgYXMgbG9uZyBhcyB0aGUgbGFzdFR5cGUgaXMgc29tZXRoaW5nIHdlIGNhbiBlZGl0LCBhcyB0aGlzXG4gICAgICAgICAgICAvLyBpcyB0aGUgdHlwZSB3ZSB3aWxsIHByb3ZpZGUgdG8gdGhlIHBhcmVudCBmaWx0ZXIgaWYgdGhlIHVzZXIgZGVjaWRlcyB0byB1c2UgdGhlIGZsb2F0aW5nIGZpbHRlci5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmlzVHlwZUVkaXRhYmxlKHRoaXMubGFzdFR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5ldmVyIGFsbG93IGVkaXRpbmcgaWYgdGhlIGZpbHRlciBpcyBjb21iaW5lZCAoaWUgaGFzIHR3byBwYXJ0cylcbiAgICAgICAgdmFyIGlzQ29tYmluZWQgPSBtb2RlbC5vcGVyYXRvcjtcbiAgICAgICAgaWYgKGlzQ29tYmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2ltcGxlTW9kZWwgPSBtb2RlbDtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNUeXBlRWRpdGFibGUoc2ltcGxlTW9kZWwudHlwZSk7XG4gICAgfTtcbiAgICBTaW1wbGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zRmFjdG9yeSA9IG5ldyBPcHRpb25zRmFjdG9yeSgpO1xuICAgICAgICB0aGlzLm9wdGlvbnNGYWN0b3J5LmluaXQocGFyYW1zLmZpbHRlclBhcmFtcywgdGhpcy5nZXREZWZhdWx0RmlsdGVyT3B0aW9ucygpKTtcbiAgICAgICAgdGhpcy5sYXN0VHlwZSA9IHRoaXMub3B0aW9uc0ZhY3RvcnkuZ2V0RGVmYXVsdE9wdGlvbigpO1xuICAgICAgICAvLyByZWFkT25seSBpcyBhIHByb3BlcnR5IG9mIElQcm92aWRlZEZpbHRlclBhcmFtcyAtIHdlIG5lZWQgdG8gZmluZCBhIGJldHRlciAodHlwZS1zYWZlKVxuICAgICAgICAvLyB3YXkgdG8gc3VwcG9ydCByZWFkaW5nIHRoaXMgaW4gdGhlIGZ1dHVyZS5cbiAgICAgICAgdGhpcy5yZWFkT25seSA9ICEhcGFyYW1zLmZpbHRlclBhcmFtcy5yZWFkT25seTtcbiAgICAgICAgLy8gd2UgYXJlIGVkaXRhYmxlIGlmOlxuICAgICAgICAvLyAxKSB0aGVyZSBpcyBhIHR5cGUgKHVzZXIgaGFzIGNvbmZpZ3VyZWQgZmlsdGVyIHdyb25nIGlmIG5vdCB0eXBlKVxuICAgICAgICAvLyAgQU5EXG4gICAgICAgIC8vIDIpIHRoZSBkZWZhdWx0IHR5cGUgaXMgbm90ICdpbiByYW5nZSdcbiAgICAgICAgdmFyIGVkaXRhYmxlID0gdGhpcy5pc1R5cGVFZGl0YWJsZSh0aGlzLmxhc3RUeXBlKTtcbiAgICAgICAgdGhpcy5zZXRFZGl0YWJsZShlZGl0YWJsZSk7XG4gICAgfTtcbiAgICBTaW1wbGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuZG9lc0ZpbHRlckhhdmVTaW5nbGVJbnB1dCA9IGZ1bmN0aW9uIChmaWx0ZXJUeXBlKSB7XG4gICAgICAgIHZhciBjdXN0b21GaWx0ZXJPcHRpb24gPSB0aGlzLm9wdGlvbnNGYWN0b3J5LmdldEN1c3RvbU9wdGlvbihmaWx0ZXJUeXBlKTtcbiAgICAgICAgdmFyIG51bWJlck9mSW5wdXRzID0gKGN1c3RvbUZpbHRlck9wdGlvbiB8fCB7fSkubnVtYmVyT2ZJbnB1dHM7XG4gICAgICAgIHJldHVybiBudW1iZXJPZklucHV0cyA9PSBudWxsIHx8IG51bWJlck9mSW5wdXRzID09IDE7XG4gICAgfTtcbiAgICBTaW1wbGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuaXNUeXBlRWRpdGFibGUgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICB2YXIgdW5lZGl0YWJsZVR5cGVzID0gW1xuICAgICAgICAgICAgU2ltcGxlRmlsdGVyLklOX1JBTkdFLCBTaW1wbGVGaWx0ZXIuRU1QVFksIFNpbXBsZUZpbHRlci5CTEFOSywgU2ltcGxlRmlsdGVyLk5PVF9CTEFOSyxcbiAgICAgICAgXTtcbiAgICAgICAgcmV0dXJuICEhdHlwZSAmJlxuICAgICAgICAgICAgIXRoaXMuaXNSZWFkT25seSgpICYmXG4gICAgICAgICAgICB0aGlzLmRvZXNGaWx0ZXJIYXZlU2luZ2xlSW5wdXQodHlwZSkgJiZcbiAgICAgICAgICAgIHVuZWRpdGFibGVUeXBlcy5pbmRleE9mKHR5cGUpIDwgMDtcbiAgICB9O1xuICAgIHJldHVybiBTaW1wbGVGbG9hdGluZ0ZpbHRlcjtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMkEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJlID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgRGF0ZUZsb2F0aW5nRmlsdGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyQShEYXRlRmxvYXRpbmdGaWx0ZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGF0ZUZsb2F0aW5nRmlsdGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgLyogaHRtbCAqLyBcIlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLWZsb2F0aW5nLWZpbHRlci1pbnB1dFxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj5cXG4gICAgICAgICAgICAgICAgPGFnLWlucHV0LXRleHQtZmllbGQgcmVmPVxcXCJlUmVhZE9ubHlUZXh0XFxcIj48L2FnLWlucHV0LXRleHQtZmllbGQ+XFxuICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlRGF0ZVdyYXBwZXJcXFwiIHN0eWxlPVxcXCJkaXNwbGF5OiBmbGV4O1xcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XCIpIHx8IHRoaXM7XG4gICAgfVxuICAgIERhdGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuZ2V0RGVmYXVsdEZpbHRlck9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBEYXRlRmlsdGVyLkRFRkFVTFRfRklMVEVSX09QVElPTlM7XG4gICAgfTtcbiAgICBEYXRlRmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmNvbmRpdGlvblRvU3RyaW5nID0gZnVuY3Rpb24gKGNvbmRpdGlvbiwgb3B0aW9ucykge1xuICAgICAgICB2YXIgdHlwZSA9IGNvbmRpdGlvbi50eXBlO1xuICAgICAgICB2YXIgbnVtYmVyT2ZJbnB1dHMgPSAob3B0aW9ucyB8fCB7fSkubnVtYmVyT2ZJbnB1dHM7XG4gICAgICAgIHZhciBpc1JhbmdlID0gdHlwZSA9PSBTaW1wbGVGaWx0ZXIuSU5fUkFOR0UgfHwgbnVtYmVyT2ZJbnB1dHMgPT09IDI7XG4gICAgICAgIHZhciBkYXRlRnJvbSA9IHBhcnNlRGF0ZVRpbWVGcm9tU3RyaW5nKGNvbmRpdGlvbi5kYXRlRnJvbSk7XG4gICAgICAgIHZhciBkYXRlVG8gPSBwYXJzZURhdGVUaW1lRnJvbVN0cmluZyhjb25kaXRpb24uZGF0ZVRvKTtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuZmlsdGVyUGFyYW1zLmluUmFuZ2VGbG9hdGluZ0ZpbHRlckRhdGVGb3JtYXQ7XG4gICAgICAgIGlmIChpc1JhbmdlKSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0dGVkRnJvbSA9IGRhdGVGcm9tICE9PSBudWxsID8gZGF0ZVRvRm9ybWF0dGVkU3RyaW5nKGRhdGVGcm9tLCBmb3JtYXQpIDogJ251bGwnO1xuICAgICAgICAgICAgdmFyIGZvcm1hdHRlZFRvID0gZGF0ZVRvICE9PSBudWxsID8gZGF0ZVRvRm9ybWF0dGVkU3RyaW5nKGRhdGVUbywgZm9ybWF0KSA6ICdudWxsJztcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZWRGcm9tICsgXCItXCIgKyBmb3JtYXR0ZWRUbztcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZUZyb20gIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGVUb0Zvcm1hdHRlZFN0cmluZyhkYXRlRnJvbSwgZm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjYXRlciBmb3Igd2hlbiB0aGUgdHlwZSBkb2Vzbid0IG5lZWQgYSB2YWx1ZVxuICAgICAgICByZXR1cm4gXCJcIiArIHR5cGU7XG4gICAgfTtcbiAgICBEYXRlRmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuaW5pdC5jYWxsKHRoaXMsIHBhcmFtcyk7XG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICB0aGlzLmZpbHRlclBhcmFtcyA9IHBhcmFtcy5maWx0ZXJQYXJhbXM7XG4gICAgICAgIHRoaXMuY3JlYXRlRGF0ZUNvbXBvbmVudCgpO1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdGhpcy5lUmVhZE9ubHlUZXh0XG4gICAgICAgICAgICAuc2V0RGlzYWJsZWQodHJ1ZSlcbiAgICAgICAgICAgIC5zZXRJbnB1dEFyaWFMYWJlbCh0cmFuc2xhdGUoJ2FyaWFEYXRlRmlsdGVySW5wdXQnLCAnRGF0ZSBGaWx0ZXIgSW5wdXQnKSk7XG4gICAgfTtcbiAgICBEYXRlRmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLnNldEVkaXRhYmxlID0gZnVuY3Rpb24gKGVkaXRhYmxlKSB7XG4gICAgICAgIHNldERpc3BsYXllZCh0aGlzLmVEYXRlV3JhcHBlciwgZWRpdGFibGUpO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lUmVhZE9ubHlUZXh0LmdldEd1aSgpLCAhZWRpdGFibGUpO1xuICAgIH07XG4gICAgRGF0ZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5vblBhcmVudE1vZGVsQ2hhbmdlZCA9IGZ1bmN0aW9uIChtb2RlbCwgZXZlbnQpIHtcbiAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byB1cGRhdGUgdGhlIGZsb2F0aW5nIGZpbHRlciBpZiB0aGUgZmxvYXRpbmcgZmlsdGVyIGNhdXNlZCB0aGUgY2hhbmdlLFxuICAgICAgICAvLyBiZWNhdXNlIHRoZSBVSSBpcyBhbHJlYWR5IGluIHN5bmMuIGlmIHdlIGRpZG4ndCBkbyB0aGlzLCB0aGUgVUkgd291bGQgYmVoYXZlIHN0cmFuZ2VseVxuICAgICAgICAvLyBhcyBpdCB3b3VsZCBiZSB1cGRhdGluZyBhcyB0aGUgdXNlciBpcyB0eXBpbmdcbiAgICAgICAgaWYgKHRoaXMuaXNFdmVudEZyb21GbG9hdGluZ0ZpbHRlcihldmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnNldExhc3RUeXBlRnJvbU1vZGVsLmNhbGwodGhpcywgbW9kZWwpO1xuICAgICAgICB2YXIgYWxsb3dFZGl0aW5nID0gIXRoaXMuaXNSZWFkT25seSgpICYmXG4gICAgICAgICAgICB0aGlzLmNhbldlRWRpdEFmdGVyTW9kZWxGcm9tUGFyZW50RmlsdGVyKG1vZGVsKTtcbiAgICAgICAgdGhpcy5zZXRFZGl0YWJsZShhbGxvd0VkaXRpbmcpO1xuICAgICAgICBpZiAoYWxsb3dFZGl0aW5nKSB7XG4gICAgICAgICAgICBpZiAobW9kZWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0ZU1vZGVsID0gbW9kZWw7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlQ29tcC5zZXREYXRlKHBhcnNlRGF0ZVRpbWVGcm9tU3RyaW5nKGRhdGVNb2RlbC5kYXRlRnJvbSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlQ29tcC5zZXREYXRlKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lUmVhZE9ubHlUZXh0LnNldFZhbHVlKCcnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZVJlYWRPbmx5VGV4dC5zZXRWYWx1ZSh0aGlzLmdldFRleHRGcm9tTW9kZWwobW9kZWwpKTtcbiAgICAgICAgICAgIHRoaXMuZGF0ZUNvbXAuc2V0RGF0ZShudWxsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGF0ZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5vbkRhdGVDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZmlsdGVyVmFsdWVEYXRlID0gdGhpcy5kYXRlQ29tcC5nZXREYXRlKCk7XG4gICAgICAgIHZhciBmaWx0ZXJWYWx1ZVRleHQgPSBzZXJpYWxpc2VEYXRlKGZpbHRlclZhbHVlRGF0ZSk7XG4gICAgICAgIHRoaXMucGFyYW1zLnBhcmVudEZpbHRlckluc3RhbmNlKGZ1bmN0aW9uIChmaWx0ZXJJbnN0YW5jZSkge1xuICAgICAgICAgICAgaWYgKGZpbHRlckluc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRhdGUgPSBwYXJzZURhdGVUaW1lRnJvbVN0cmluZyhmaWx0ZXJWYWx1ZVRleHQpO1xuICAgICAgICAgICAgICAgIGZpbHRlckluc3RhbmNlLm9uRmxvYXRpbmdGaWx0ZXJDaGFuZ2VkKF90aGlzLmdldExhc3RUeXBlKCkgfHwgbnVsbCwgZGF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRGF0ZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5jcmVhdGVEYXRlQ29tcG9uZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZGVib3VuY2VNcyA9IFByb3ZpZGVkRmlsdGVyLmdldERlYm91bmNlTXModGhpcy5wYXJhbXMuZmlsdGVyUGFyYW1zLCB0aGlzLmdldERlZmF1bHREZWJvdW5jZU1zKCkpO1xuICAgICAgICB2YXIgZGF0ZUNvbXBvbmVudFBhcmFtcyA9IHtcbiAgICAgICAgICAgIG9uRGF0ZUNoYW5nZWQ6IGRlYm91bmNlKHRoaXMub25EYXRlQ2hhbmdlZC5iaW5kKHRoaXMpLCBkZWJvdW5jZU1zKSxcbiAgICAgICAgICAgIGZpbHRlclBhcmFtczogdGhpcy5wYXJhbXMuY29sdW1uLmdldENvbERlZigpLmZpbHRlclBhcmFtc1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmRhdGVDb21wID0gbmV3IERhdGVDb21wV3JhcHBlcih0aGlzLmdldENvbnRleHQoKSwgdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeSwgZGF0ZUNvbXBvbmVudFBhcmFtcywgdGhpcy5lRGF0ZVdyYXBwZXIpO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmRhdGVDb21wLmRlc3Ryb3koKTsgfSk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDJlKFtcbiAgICAgICAgQXV0b3dpcmVkKCd1c2VyQ29tcG9uZW50RmFjdG9yeScpXG4gICAgXSwgRGF0ZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZSwgXCJ1c2VyQ29tcG9uZW50RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVJlYWRPbmx5VGV4dCcpXG4gICAgXSwgRGF0ZUZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZSwgXCJlUmVhZE9ubHlUZXh0XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyZShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlRGF0ZVdyYXBwZXInKVxuICAgIF0sIERhdGVGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUsIFwiZURhdGVXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIERhdGVGbG9hdGluZ0ZpbHRlcjtcbn0oU2ltcGxlRmxvYXRpbmdGaWx0ZXIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyeiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMmQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBEZWZhdWx0RGF0ZUNvbXBvbmVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMnooRGVmYXVsdERhdGVDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRGVmYXVsdERhdGVDb21wb25lbnQoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCAvKiBodG1sICovIFwiXFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmlsdGVyLWZpbHRlclxcXCI+XFxuICAgICAgICAgICAgICAgIDxhZy1pbnB1dC10ZXh0LWZpZWxkIGNsYXNzPVxcXCJhZy1kYXRlLWZpbHRlclxcXCIgcmVmPVxcXCJlRGF0ZUlucHV0XFxcIj48L2FnLWlucHV0LXRleHQtZmllbGQ+XFxuICAgICAgICAgICAgPC9kaXY+XCIpIHx8IHRoaXM7XG4gICAgfVxuICAgIC8vIHRoaXMgaXMgYSB1c2VyIGNvbXBvbmVudCwgYW5kIElDb21wb25lbnQgaGFzIFwicHVibGljIGRlc3Ryb3koKVwiIGFzIHBhcnQgb2YgdGhlIGludGVyZmFjZS5cbiAgICAvLyBzbyB3ZSBuZWVkIHRvIG92ZXJyaWRlIGRlc3Ryb3koKSBqdXN0IHRvIG1ha2UgdGhlIG1ldGhvZCBwdWJsaWMuXG4gICAgRGVmYXVsdERhdGVDb21wb25lbnQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgRGVmYXVsdERhdGVDb21wb25lbnQucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgaW5wdXRFbGVtZW50ID0gdGhpcy5lRGF0ZUlucHV0LmdldElucHV0RWxlbWVudCgpO1xuICAgICAgICBpZiAodGhpcy5zaG91bGRVc2VCcm93c2VyRGF0ZVBpY2tlcihwYXJhbXMpKSB7XG4gICAgICAgICAgICBpbnB1dEVsZW1lbnQudHlwZSA9ICdkYXRlJztcbiAgICAgICAgfVxuICAgICAgICAvLyBlbnN1cmVzIHRoYXQgdGhlIGlucHV0IGVsZW1lbnQgaXMgZm9jdXNzZWQgd2hlbiBhIGNsZWFyIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGlucHV0RWxlbWVudCwgJ21vdXNlZG93bicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5lRGF0ZUlucHV0LmlzRGlzYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlucHV0RWxlbWVudC5mb2N1cygpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoaW5wdXRFbGVtZW50LCAnaW5wdXQnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgaWYgKGUudGFyZ2V0ICE9PSBlRG9jdW1lbnQuYWN0aXZlRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfdGhpcy5lRGF0ZUlucHV0LmlzRGlzYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmFtcy5vbkRhdGVDaGFuZ2VkKCk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgX2EgPSBwYXJhbXMuZmlsdGVyUGFyYW1zIHx8IHt9LCBtaW5WYWxpZFllYXIgPSBfYS5taW5WYWxpZFllYXIsIG1heFZhbGlkWWVhciA9IF9hLm1heFZhbGlkWWVhcjtcbiAgICAgICAgaWYgKG1pblZhbGlkWWVhcikge1xuICAgICAgICAgICAgaW5wdXRFbGVtZW50Lm1pbiA9IG1pblZhbGlkWWVhciArIFwiLTAxLTAxXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1heFZhbGlkWWVhcikge1xuICAgICAgICAgICAgaW5wdXRFbGVtZW50Lm1heCA9IG1heFZhbGlkWWVhciArIFwiLTEyLTMxXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERlZmF1bHREYXRlQ29tcG9uZW50LnByb3RvdHlwZS5nZXREYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcGFyc2VEYXRlVGltZUZyb21TdHJpbmcodGhpcy5lRGF0ZUlucHV0LmdldFZhbHVlKCkpO1xuICAgIH07XG4gICAgRGVmYXVsdERhdGVDb21wb25lbnQucHJvdG90eXBlLnNldERhdGUgPSBmdW5jdGlvbiAoZGF0ZSkge1xuICAgICAgICB0aGlzLmVEYXRlSW5wdXQuc2V0VmFsdWUoc2VyaWFsaXNlRGF0ZShkYXRlLCBmYWxzZSkpO1xuICAgIH07XG4gICAgRGVmYXVsdERhdGVDb21wb25lbnQucHJvdG90eXBlLnNldElucHV0UGxhY2Vob2xkZXIgPSBmdW5jdGlvbiAocGxhY2Vob2xkZXIpIHtcbiAgICAgICAgdGhpcy5lRGF0ZUlucHV0LnNldElucHV0UGxhY2Vob2xkZXIocGxhY2Vob2xkZXIpO1xuICAgIH07XG4gICAgRGVmYXVsdERhdGVDb21wb25lbnQucHJvdG90eXBlLnNldERpc2FibGVkID0gZnVuY3Rpb24gKGRpc2FibGVkKSB7XG4gICAgICAgIHRoaXMuZURhdGVJbnB1dC5zZXREaXNhYmxlZChkaXNhYmxlZCk7XG4gICAgfTtcbiAgICBEZWZhdWx0RGF0ZUNvbXBvbmVudC5wcm90b3R5cGUuYWZ0ZXJHdWlBdHRhY2hlZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCFwYXJhbXMgfHwgIXBhcmFtcy5zdXBwcmVzc0ZvY3VzKSB7XG4gICAgICAgICAgICB0aGlzLmVEYXRlSW5wdXQuZ2V0SW5wdXRFbGVtZW50KCkuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRGVmYXVsdERhdGVDb21wb25lbnQucHJvdG90eXBlLnNob3VsZFVzZUJyb3dzZXJEYXRlUGlja2VyID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zLmZpbHRlclBhcmFtcyAmJiBwYXJhbXMuZmlsdGVyUGFyYW1zLmJyb3dzZXJEYXRlUGlja2VyICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJhbXMuZmlsdGVyUGFyYW1zLmJyb3dzZXJEYXRlUGlja2VyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0Jyb3dzZXJDaHJvbWUoKSB8fCBpc0Jyb3dzZXJGaXJlZm94KCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDJkKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VEYXRlSW5wdXQnKVxuICAgIF0sIERlZmF1bHREYXRlQ29tcG9uZW50LnByb3RvdHlwZSwgXCJlRGF0ZUlucHV0XCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIERlZmF1bHREYXRlQ29tcG9uZW50O1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyeSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMmMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBOdW1iZXJGaWx0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJ5KE51bWJlckZpbHRlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBOdW1iZXJGaWx0ZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCAnbnVtYmVyRmlsdGVyJykgfHwgdGhpcztcbiAgICB9XG4gICAgTnVtYmVyRmlsdGVyLnByb3RvdHlwZS5tYXBWYWx1ZXNGcm9tTW9kZWwgPSBmdW5jdGlvbiAoZmlsdGVyTW9kZWwpIHtcbiAgICAgICAgdmFyIF9hID0gZmlsdGVyTW9kZWwgfHwge30sIGZpbHRlciA9IF9hLmZpbHRlciwgZmlsdGVyVG8gPSBfYS5maWx0ZXJUbywgdHlwZSA9IF9hLnR5cGU7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBmaWx0ZXIgPT0gbnVsbCA/IG51bGwgOiBmaWx0ZXIsXG4gICAgICAgICAgICBmaWx0ZXJUbyA9PSBudWxsID8gbnVsbCA6IGZpbHRlclRvLFxuICAgICAgICBdLnNsaWNlKDAsIHRoaXMuZ2V0TnVtYmVyT2ZJbnB1dHModHlwZSkpO1xuICAgIH07XG4gICAgTnVtYmVyRmlsdGVyLnByb3RvdHlwZS5nZXREZWZhdWx0RGVib3VuY2VNcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIDUwMDtcbiAgICB9O1xuICAgIE51bWJlckZpbHRlci5wcm90b3R5cGUuY29tcGFyYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgaWYgKGxlZnQgPT09IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbGVmdCA8IHJpZ2h0ID8gMSA6IC0xO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgTnVtYmVyRmlsdGVyLnByb3RvdHlwZS5zZXRQYXJhbXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMubnVtYmVyRmlsdGVyUGFyYW1zID0gcGFyYW1zO1xuICAgICAgICB2YXIgYWxsb3dlZENoYXJQYXR0ZXJuID0gdGhpcy5nZXRBbGxvd2VkQ2hhclBhdHRlcm4oKTtcbiAgICAgICAgaWYgKGFsbG93ZWRDaGFyUGF0dGVybikge1xuICAgICAgICAgICAgdmFyIGNvbmZpZyA9IHsgYWxsb3dlZENoYXJQYXR0ZXJuOiBhbGxvd2VkQ2hhclBhdHRlcm4gfTtcbiAgICAgICAgICAgIHRoaXMucmVzZXRUZW1wbGF0ZSh7XG4gICAgICAgICAgICAgICAgJ2VWYWx1ZS1pbmRleDAtMSc6IGNvbmZpZyxcbiAgICAgICAgICAgICAgICAnZVZhbHVlLWluZGV4MS0xJzogY29uZmlnLFxuICAgICAgICAgICAgICAgICdlVmFsdWUtaW5kZXgwLTInOiBjb25maWcsXG4gICAgICAgICAgICAgICAgJ2VWYWx1ZS1pbmRleDEtMic6IGNvbmZpZyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuc2V0UGFyYW1zLmNhbGwodGhpcywgcGFyYW1zKTtcbiAgICB9O1xuICAgIE51bWJlckZpbHRlci5wcm90b3R5cGUuZ2V0RGVmYXVsdEZpbHRlck9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBOdW1iZXJGaWx0ZXIuREVGQVVMVF9GSUxURVJfT1BUSU9OUztcbiAgICB9O1xuICAgIE51bWJlckZpbHRlci5wcm90b3R5cGUuY3JlYXRlVmFsdWVUZW1wbGF0ZSA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24gPT09IENvbmRpdGlvblBvc2l0aW9uLk9uZSA/ICcxJyA6ICcyJztcbiAgICAgICAgdmFyIGFsbG93ZWRDaGFyUGF0dGVybiA9IHRoaXMuZ2V0QWxsb3dlZENoYXJQYXR0ZXJuKCk7XG4gICAgICAgIHZhciBhZ0VsZW1lbnRUYWcgPSBhbGxvd2VkQ2hhclBhdHRlcm4gPyAnYWctaW5wdXQtdGV4dC1maWVsZCcgOiAnYWctaW5wdXQtbnVtYmVyLWZpZWxkJztcbiAgICAgICAgcmV0dXJuIC8qIGh0bWwgKi8gXCJcXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1maWx0ZXItYm9keVxcXCIgcmVmPVxcXCJlQ29uZGl0aW9uXCIgKyBwb3MgKyBcIkJvZHlcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxcIiArIGFnRWxlbWVudFRhZyArIFwiIGNsYXNzPVxcXCJhZy1maWx0ZXItZnJvbSBhZy1maWx0ZXItZmlsdGVyXFxcIiByZWY9XFxcImVWYWx1ZS1pbmRleDAtXCIgKyBwb3MgKyBcIlxcXCI+PC9cIiArIGFnRWxlbWVudFRhZyArIFwiPlxcbiAgICAgICAgICAgICAgICA8XCIgKyBhZ0VsZW1lbnRUYWcgKyBcIiBjbGFzcz1cXFwiYWctZmlsdGVyLXRvIGFnLWZpbHRlci1maWx0ZXJcXFwiIHJlZj1cXFwiZVZhbHVlLWluZGV4MS1cIiArIHBvcyArIFwiXFxcIj48L1wiICsgYWdFbGVtZW50VGFnICsgXCI+XFxuICAgICAgICAgICAgPC9kaXY+XCI7XG4gICAgfTtcbiAgICBOdW1iZXJGaWx0ZXIucHJvdG90eXBlLmdldFZhbHVlcyA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHRoaXMuZm9yRWFjaElucHV0KGZ1bmN0aW9uIChlbGVtZW50LCBpbmRleCwgZWxQb3NpdGlvbiwgbnVtYmVyT2ZJbnB1dHMpIHtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gZWxQb3NpdGlvbiAmJiBpbmRleCA8IG51bWJlck9mSW5wdXRzKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goX3RoaXMuc3RyaW5nVG9GbG9hdChlbGVtZW50LmdldFZhbHVlKCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBOdW1iZXJGaWx0ZXIucHJvdG90eXBlLmFyZVNpbXBsZU1vZGVsc0VxdWFsID0gZnVuY3Rpb24gKGFTaW1wbGUsIGJTaW1wbGUpIHtcbiAgICAgICAgcmV0dXJuIGFTaW1wbGUuZmlsdGVyID09PSBiU2ltcGxlLmZpbHRlclxuICAgICAgICAgICAgJiYgYVNpbXBsZS5maWx0ZXJUbyA9PT0gYlNpbXBsZS5maWx0ZXJUb1xuICAgICAgICAgICAgJiYgYVNpbXBsZS50eXBlID09PSBiU2ltcGxlLnR5cGU7XG4gICAgfTtcbiAgICBOdW1iZXJGaWx0ZXIucHJvdG90eXBlLmdldEZpbHRlclR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnbnVtYmVyJztcbiAgICB9O1xuICAgIE51bWJlckZpbHRlci5wcm90b3R5cGUuc3RyaW5nVG9GbG9hdCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmaWx0ZXJUZXh0ID0gbWFrZU51bGwodmFsdWUpO1xuICAgICAgICBpZiAoZmlsdGVyVGV4dCAhPSBudWxsICYmIGZpbHRlclRleHQudHJpbSgpID09PSAnJykge1xuICAgICAgICAgICAgZmlsdGVyVGV4dCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubnVtYmVyRmlsdGVyUGFyYW1zLm51bWJlclBhcnNlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtYmVyRmlsdGVyUGFyYW1zLm51bWJlclBhcnNlcihmaWx0ZXJUZXh0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmlsdGVyVGV4dCA9PSBudWxsIHx8IGZpbHRlclRleHQudHJpbSgpID09PSAnLScgPyBudWxsIDogcGFyc2VGbG9hdChmaWx0ZXJUZXh0KTtcbiAgICB9O1xuICAgIE51bWJlckZpbHRlci5wcm90b3R5cGUuY3JlYXRlQ29uZGl0aW9uID0gZnVuY3Rpb24gKHBvc2l0aW9uKSB7XG4gICAgICAgIHZhciB0eXBlID0gdGhpcy5nZXRDb25kaXRpb25UeXBlcygpW3Bvc2l0aW9uXTtcbiAgICAgICAgdmFyIG1vZGVsID0ge1xuICAgICAgICAgICAgZmlsdGVyVHlwZTogdGhpcy5nZXRGaWx0ZXJUeXBlKCksXG4gICAgICAgICAgICB0eXBlOiB0eXBlXG4gICAgICAgIH07XG4gICAgICAgIHZhciB2YWx1ZXMgPSB0aGlzLmdldFZhbHVlcyhwb3NpdGlvbik7XG4gICAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgbW9kZWwuZmlsdGVyID0gdmFsdWVzWzBdO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgbW9kZWwuZmlsdGVyVG8gPSB2YWx1ZXNbMV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1vZGVsO1xuICAgIH07XG4gICAgTnVtYmVyRmlsdGVyLnByb3RvdHlwZS5nZXRJbnB1dHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBbdGhpcy5lVmFsdWVGcm9tMSwgdGhpcy5lVmFsdWVUbzFdLFxuICAgICAgICAgICAgW3RoaXMuZVZhbHVlRnJvbTIsIHRoaXMuZVZhbHVlVG8yXSxcbiAgICAgICAgXTtcbiAgICB9O1xuICAgIE51bWJlckZpbHRlci5wcm90b3R5cGUuZ2V0QWxsb3dlZENoYXJQYXR0ZXJuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYWxsb3dlZENoYXJQYXR0ZXJuID0gKHRoaXMubnVtYmVyRmlsdGVyUGFyYW1zIHx8IHt9KS5hbGxvd2VkQ2hhclBhdHRlcm47XG4gICAgICAgIGlmIChhbGxvd2VkQ2hhclBhdHRlcm4pIHtcbiAgICAgICAgICAgIHJldHVybiBhbGxvd2VkQ2hhclBhdHRlcm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0Jyb3dzZXJDaHJvbWUoKSAmJiAhaXNCcm93c2VyRWRnZSgpKSB7XG4gICAgICAgICAgICAvLyBvbmx5IENocm9tZSBhbmQgRWRnZSBzdXBwb3J0IHRoZSBIVE1MNSBudW1iZXIgZmllbGQsIHNvIGZvciBvdGhlciBicm93c2VycyB3ZSBwcm92aWRlIGFuIGVxdWl2YWxlbnRcbiAgICAgICAgICAgIC8vIGNvbnN0cmFpbnQgaW5zdGVhZFxuICAgICAgICAgICAgcmV0dXJuICdcXFxcZFxcXFwtXFxcXC4nO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgTnVtYmVyRmlsdGVyLkRFRkFVTFRfRklMVEVSX09QVElPTlMgPSBbXG4gICAgICAgIFNjYWxhckZpbHRlci5FUVVBTFMsXG4gICAgICAgIFNjYWxhckZpbHRlci5OT1RfRVFVQUwsXG4gICAgICAgIFNjYWxhckZpbHRlci5MRVNTX1RIQU4sXG4gICAgICAgIFNjYWxhckZpbHRlci5MRVNTX1RIQU5fT1JfRVFVQUwsXG4gICAgICAgIFNjYWxhckZpbHRlci5HUkVBVEVSX1RIQU4sXG4gICAgICAgIFNjYWxhckZpbHRlci5HUkVBVEVSX1RIQU5fT1JfRVFVQUwsXG4gICAgICAgIFNjYWxhckZpbHRlci5JTl9SQU5HRSxcbiAgICAgICAgU2NhbGFyRmlsdGVyLkJMQU5LLFxuICAgICAgICBTY2FsYXJGaWx0ZXIuTk9UX0JMQU5LLFxuICAgIF07XG4gICAgX19kZWNvcmF0ZSQyYyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVmFsdWUtaW5kZXgwLTEnKVxuICAgIF0sIE51bWJlckZpbHRlci5wcm90b3R5cGUsIFwiZVZhbHVlRnJvbTFcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJjKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VWYWx1ZS1pbmRleDEtMScpXG4gICAgXSwgTnVtYmVyRmlsdGVyLnByb3RvdHlwZSwgXCJlVmFsdWVUbzFcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDJjKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VWYWx1ZS1pbmRleDAtMicpXG4gICAgXSwgTnVtYmVyRmlsdGVyLnByb3RvdHlwZSwgXCJlVmFsdWVGcm9tMlwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmMoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVZhbHVlLWluZGV4MS0yJylcbiAgICBdLCBOdW1iZXJGaWx0ZXIucHJvdG90eXBlLCBcImVWYWx1ZVRvMlwiLCB2b2lkIDApO1xuICAgIHJldHVybiBOdW1iZXJGaWx0ZXI7XG59KFNjYWxhckZpbHRlcikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJ4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19hc3NpZ24kYSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fYXNzaWduKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgX19hc3NpZ24kYSA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24kYS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufTtcbnZhciBfX2RlY29yYXRlJDJiID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgVGV4dEZpbHRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMngoVGV4dEZpbHRlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBUZXh0RmlsdGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgJ3RleHRGaWx0ZXInKSB8fCB0aGlzO1xuICAgIH1cbiAgICBUZXh0RmlsdGVyLnRyaW1JbnB1dCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgdHJpbW1lZElucHV0ID0gdmFsdWUgJiYgdmFsdWUudHJpbSgpO1xuICAgICAgICAvLyB0cmltIHRoZSBpbnB1dCwgdW5sZXNzIGl0IGlzIGFsbCB3aGl0ZXNwYWNlICh0aGlzIGlzIGNvbnNpc3RlbnQgd2l0aCBFeGNlbCBiZWhhdmlvdXIpXG4gICAgICAgIHJldHVybiB0cmltbWVkSW5wdXQgPT09ICcnID8gdmFsdWUgOiB0cmltbWVkSW5wdXQ7XG4gICAgfTtcbiAgICBUZXh0RmlsdGVyLnByb3RvdHlwZS5nZXREZWZhdWx0RGVib3VuY2VNcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIDUwMDtcbiAgICB9O1xuICAgIFRleHRGaWx0ZXIucHJvdG90eXBlLnNldFBhcmFtcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5zZXRQYXJhbXMuY2FsbCh0aGlzLCBwYXJhbXMpO1xuICAgICAgICB0aGlzLnRleHRGaWx0ZXJQYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIHRoaXMubWF0Y2hlciA9IHRoaXMuZ2V0VGV4dE1hdGNoZXIoKTtcbiAgICAgICAgdGhpcy5mb3JtYXR0ZXIgPSB0aGlzLnRleHRGaWx0ZXJQYXJhbXMudGV4dEZvcm1hdHRlciB8fFxuICAgICAgICAgICAgKHRoaXMudGV4dEZpbHRlclBhcmFtcy5jYXNlU2Vuc2l0aXZlID8gVGV4dEZpbHRlci5ERUZBVUxUX0ZPUk1BVFRFUiA6IFRleHRGaWx0ZXIuREVGQVVMVF9MT1dFUkNBU0VfRk9STUFUVEVSKTtcbiAgICB9O1xuICAgIFRleHRGaWx0ZXIucHJvdG90eXBlLmdldFRleHRNYXRjaGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGVnYWN5Q29tcGFyYXRvciA9IHRoaXMudGV4dEZpbHRlclBhcmFtcy50ZXh0Q3VzdG9tQ29tcGFyYXRvcjtcbiAgICAgICAgaWYgKGxlZ2FjeUNvbXBhcmF0b3IpIHtcbiAgICAgICAgICAgIF8uZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZCAtIHRleHRDdXN0b21Db21wYXJhdG9yIGlzIGRlcHJlY2F0ZWQsIHVzZSB0ZXh0TWF0Y2hlciBpbnN0ZWFkLicpOyB9LCAndGV4dEN1c3RvbUNvbXBhcmF0b3IuZGVwcmVjYXRlZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHZhciBmaWx0ZXJPcHRpb24gPSBfYS5maWx0ZXJPcHRpb24sIHZhbHVlID0gX2EudmFsdWUsIGZpbHRlclRleHQgPSBfYS5maWx0ZXJUZXh0O1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWdhY3lDb21wYXJhdG9yKGZpbHRlck9wdGlvbiwgdmFsdWUsIGZpbHRlclRleHQpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy50ZXh0RmlsdGVyUGFyYW1zLnRleHRNYXRjaGVyIHx8IFRleHRGaWx0ZXIuREVGQVVMVF9NQVRDSEVSO1xuICAgIH07XG4gICAgVGV4dEZpbHRlci5wcm90b3R5cGUuY3JlYXRlQ29uZGl0aW9uID0gZnVuY3Rpb24gKHBvc2l0aW9uKSB7XG4gICAgICAgIHZhciB0eXBlID0gdGhpcy5nZXRDb25kaXRpb25UeXBlcygpW3Bvc2l0aW9uXTtcbiAgICAgICAgdmFyIG1vZGVsID0ge1xuICAgICAgICAgICAgZmlsdGVyVHlwZTogdGhpcy5nZXRGaWx0ZXJUeXBlKCksXG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICB9O1xuICAgICAgICB2YXIgdmFsdWVzID0gdGhpcy5nZXRWYWx1ZXMocG9zaXRpb24pO1xuICAgICAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIG1vZGVsLmZpbHRlciA9IHZhbHVlc1swXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIG1vZGVsLmZpbHRlclRvID0gdmFsdWVzWzFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtb2RlbDtcbiAgICB9O1xuICAgIFRleHRGaWx0ZXIucHJvdG90eXBlLmdldEZpbHRlclR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAndGV4dCc7XG4gICAgfTtcbiAgICBUZXh0RmlsdGVyLnByb3RvdHlwZS5hcmVTaW1wbGVNb2RlbHNFcXVhbCA9IGZ1bmN0aW9uIChhU2ltcGxlLCBiU2ltcGxlKSB7XG4gICAgICAgIHJldHVybiBhU2ltcGxlLmZpbHRlciA9PT0gYlNpbXBsZS5maWx0ZXIgJiZcbiAgICAgICAgICAgIGFTaW1wbGUuZmlsdGVyVG8gPT09IGJTaW1wbGUuZmlsdGVyVG8gJiZcbiAgICAgICAgICAgIGFTaW1wbGUudHlwZSA9PT0gYlNpbXBsZS50eXBlO1xuICAgIH07XG4gICAgVGV4dEZpbHRlci5wcm90b3R5cGUuZ2V0SW5wdXRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgW3RoaXMuZVZhbHVlRnJvbTEsIHRoaXMuZVZhbHVlVG8xXSxcbiAgICAgICAgICAgIFt0aGlzLmVWYWx1ZUZyb20yLCB0aGlzLmVWYWx1ZVRvMl0sXG4gICAgICAgIF07XG4gICAgfTtcbiAgICBUZXh0RmlsdGVyLnByb3RvdHlwZS5nZXRWYWx1ZXMgPSBmdW5jdGlvbiAocG9zaXRpb24pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB0aGlzLmZvckVhY2hJbnB1dChmdW5jdGlvbiAoZWxlbWVudCwgaW5kZXgsIGVsUG9zaXRpb24sIG51bWJlck9mSW5wdXRzKSB7XG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IGVsUG9zaXRpb24gJiYgaW5kZXggPCBudW1iZXJPZklucHV0cykge1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IG1ha2VOdWxsKGVsZW1lbnQuZ2V0VmFsdWUoKSk7XG4gICAgICAgICAgICAgICAgdmFyIGNsZWFuVmFsdWUgPSAoX3RoaXMudGV4dEZpbHRlclBhcmFtcy50cmltSW5wdXQgPyBUZXh0RmlsdGVyLnRyaW1JbnB1dCh2YWx1ZSkgOiB2YWx1ZSkgfHwgbnVsbDtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChjbGVhblZhbHVlKTtcbiAgICAgICAgICAgICAgICBlbGVtZW50LnNldFZhbHVlKGNsZWFuVmFsdWUsIHRydWUpOyAvLyBlbnN1cmUgY2xlYW4gdmFsdWUgaXMgdmlzaWJsZVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIFRleHRGaWx0ZXIucHJvdG90eXBlLmdldERlZmF1bHRGaWx0ZXJPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gVGV4dEZpbHRlci5ERUZBVUxUX0ZJTFRFUl9PUFRJT05TO1xuICAgIH07XG4gICAgVGV4dEZpbHRlci5wcm90b3R5cGUuY3JlYXRlVmFsdWVUZW1wbGF0ZSA9IGZ1bmN0aW9uIChwb3NpdGlvbikge1xuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24gPT09IENvbmRpdGlvblBvc2l0aW9uLk9uZSA/ICcxJyA6ICcyJztcbiAgICAgICAgcmV0dXJuIC8qIGh0bWwgKi8gXCJcXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1maWx0ZXItYm9keVxcXCIgcmVmPVxcXCJlQ29uZGl0aW9uXCIgKyBwb3MgKyBcIkJvZHlcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxhZy1pbnB1dC10ZXh0LWZpZWxkIGNsYXNzPVxcXCIuYWctZmlsdGVyLWZyb20gYWctZmlsdGVyLWZpbHRlclxcXCIgcmVmPVxcXCJlVmFsdWUtaW5kZXgwLVwiICsgcG9zICsgXCJcXFwiPjwvYWctaW5wdXQtdGV4dC1maWVsZD5cXG4gICAgICAgICAgICAgICAgPGFnLWlucHV0LXRleHQtZmllbGQgY2xhc3M9XFxcImFnLWZpbHRlci10byBhZy1maWx0ZXItZmlsdGVyXFxcIiByZWY9XFxcImVWYWx1ZS1pbmRleDEtXCIgKyBwb3MgKyBcIlxcXCI+PC9hZy1pbnB1dC10ZXh0LWZpZWxkPlxcbiAgICAgICAgICAgIDwvZGl2PlwiO1xuICAgIH07XG4gICAgVGV4dEZpbHRlci5wcm90b3R5cGUubWFwVmFsdWVzRnJvbU1vZGVsID0gZnVuY3Rpb24gKGZpbHRlck1vZGVsKSB7XG4gICAgICAgIHZhciBfYSA9IGZpbHRlck1vZGVsIHx8IHt9LCBmaWx0ZXIgPSBfYS5maWx0ZXIsIGZpbHRlclRvID0gX2EuZmlsdGVyVG8sIHR5cGUgPSBfYS50eXBlO1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgZmlsdGVyIHx8IG51bGwsXG4gICAgICAgICAgICBmaWx0ZXJUbyB8fCBudWxsLFxuICAgICAgICBdLnNsaWNlKDAsIHRoaXMuZ2V0TnVtYmVyT2ZJbnB1dHModHlwZSkpO1xuICAgIH07XG4gICAgVGV4dEZpbHRlci5wcm90b3R5cGUuZXZhbHVhdGVOdWxsVmFsdWUgPSBmdW5jdGlvbiAoZmlsdGVyVHlwZSkge1xuICAgICAgICB2YXIgZmlsdGVyVHlwZXNBbGxvd051bGxzID0gW1xuICAgICAgICAgICAgU2ltcGxlRmlsdGVyLk5PVF9FUVVBTCwgU2ltcGxlRmlsdGVyLk5PVF9DT05UQUlOUywgU2ltcGxlRmlsdGVyLkJMQU5LLFxuICAgICAgICBdO1xuICAgICAgICByZXR1cm4gZmlsdGVyVHlwZSA/IGZpbHRlclR5cGVzQWxsb3dOdWxscy5pbmRleE9mKGZpbHRlclR5cGUpID49IDAgOiBmYWxzZTtcbiAgICB9O1xuICAgIFRleHRGaWx0ZXIucHJvdG90eXBlLmV2YWx1YXRlTm9uTnVsbFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlcywgY2VsbFZhbHVlLCBmaWx0ZXJNb2RlbCwgcGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBmb3JtYXR0ZWRWYWx1ZXMgPSB2YWx1ZXMubWFwKGZ1bmN0aW9uICh2KSB7IHJldHVybiBfdGhpcy5mb3JtYXR0ZXIodik7IH0pIHx8IFtdO1xuICAgICAgICB2YXIgY2VsbFZhbHVlRm9ybWF0dGVkID0gdGhpcy5mb3JtYXR0ZXIoY2VsbFZhbHVlKTtcbiAgICAgICAgdmFyIF9hID0gdGhpcy50ZXh0RmlsdGVyUGFyYW1zLCBhcGkgPSBfYS5hcGksIGNvbERlZiA9IF9hLmNvbERlZiwgY29sdW1uID0gX2EuY29sdW1uLCBjb2x1bW5BcGkgPSBfYS5jb2x1bW5BcGksIGNvbnRleHQgPSBfYS5jb250ZXh0LCB0ZXh0Rm9ybWF0dGVyID0gX2EudGV4dEZvcm1hdHRlcjtcbiAgICAgICAgaWYgKGZpbHRlck1vZGVsLnR5cGUgPT09IFNpbXBsZUZpbHRlci5CTEFOSykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNCbGFuayhjZWxsVmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGZpbHRlck1vZGVsLnR5cGUgPT09IFNpbXBsZUZpbHRlci5OT1RfQkxBTkspIHtcbiAgICAgICAgICAgIHJldHVybiAhdGhpcy5pc0JsYW5rKGNlbGxWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hdGNoZXJQYXJhbXMgPSB7XG4gICAgICAgICAgICBhcGk6IGFwaSxcbiAgICAgICAgICAgIGNvbERlZjogY29sRGVmLFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICBjb2x1bW5BcGk6IGNvbHVtbkFwaSxcbiAgICAgICAgICAgIGNvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgICAgICBub2RlOiBwYXJhbXMubm9kZSxcbiAgICAgICAgICAgIGRhdGE6IHBhcmFtcy5kYXRhLFxuICAgICAgICAgICAgZmlsdGVyT3B0aW9uOiBmaWx0ZXJNb2RlbC50eXBlLFxuICAgICAgICAgICAgdmFsdWU6IGNlbGxWYWx1ZUZvcm1hdHRlZCxcbiAgICAgICAgICAgIHRleHRGb3JtYXR0ZXI6IHRleHRGb3JtYXR0ZXIsXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBmb3JtYXR0ZWRWYWx1ZXMuc29tZShmdW5jdGlvbiAodikgeyByZXR1cm4gX3RoaXMubWF0Y2hlcihfX2Fzc2lnbiRhKF9fYXNzaWduJGEoe30sIG1hdGNoZXJQYXJhbXMpLCB7IGZpbHRlclRleHQ6IHYgfSkpOyB9KTtcbiAgICB9O1xuICAgIFRleHRGaWx0ZXIuREVGQVVMVF9GSUxURVJfT1BUSU9OUyA9IFtcbiAgICAgICAgU2ltcGxlRmlsdGVyLkNPTlRBSU5TLFxuICAgICAgICBTaW1wbGVGaWx0ZXIuTk9UX0NPTlRBSU5TLFxuICAgICAgICBTaW1wbGVGaWx0ZXIuRVFVQUxTLFxuICAgICAgICBTaW1wbGVGaWx0ZXIuTk9UX0VRVUFMLFxuICAgICAgICBTaW1wbGVGaWx0ZXIuU1RBUlRTX1dJVEgsXG4gICAgICAgIFNpbXBsZUZpbHRlci5FTkRTX1dJVEgsXG4gICAgICAgIFNpbXBsZUZpbHRlci5CTEFOSyxcbiAgICAgICAgU2ltcGxlRmlsdGVyLk5PVF9CTEFOSyxcbiAgICBdO1xuICAgIFRleHRGaWx0ZXIuREVGQVVMVF9GT1JNQVRURVIgPSBmdW5jdGlvbiAoZnJvbSkgeyByZXR1cm4gZnJvbTsgfTtcbiAgICBUZXh0RmlsdGVyLkRFRkFVTFRfTE9XRVJDQVNFX0ZPUk1BVFRFUiA9IGZ1bmN0aW9uIChmcm9tKSB7IHJldHVybiBmcm9tID09IG51bGwgPyBudWxsIDogZnJvbS50b1N0cmluZygpLnRvTG93ZXJDYXNlKCk7IH07XG4gICAgVGV4dEZpbHRlci5ERUZBVUxUX01BVENIRVIgPSBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgdmFyIGZpbHRlck9wdGlvbiA9IF9hLmZpbHRlck9wdGlvbiwgdmFsdWUgPSBfYS52YWx1ZSwgZmlsdGVyVGV4dCA9IF9hLmZpbHRlclRleHQ7XG4gICAgICAgIGlmIChmaWx0ZXJUZXh0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKGZpbHRlck9wdGlvbikge1xuICAgICAgICAgICAgY2FzZSBUZXh0RmlsdGVyLkNPTlRBSU5TOlxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5pbmRleE9mKGZpbHRlclRleHQpID49IDA7XG4gICAgICAgICAgICBjYXNlIFRleHRGaWx0ZXIuTk9UX0NPTlRBSU5TOlxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5pbmRleE9mKGZpbHRlclRleHQpIDwgMDtcbiAgICAgICAgICAgIGNhc2UgVGV4dEZpbHRlci5FUVVBTFM6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlID09PSBmaWx0ZXJUZXh0O1xuICAgICAgICAgICAgY2FzZSBUZXh0RmlsdGVyLk5PVF9FUVVBTDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUgIT0gZmlsdGVyVGV4dDtcbiAgICAgICAgICAgIGNhc2UgVGV4dEZpbHRlci5TVEFSVFNfV0lUSDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuaW5kZXhPZihmaWx0ZXJUZXh0KSA9PT0gMDtcbiAgICAgICAgICAgIGNhc2UgVGV4dEZpbHRlci5FTkRTX1dJVEg6XG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gdmFsdWUubGFzdEluZGV4T2YoZmlsdGVyVGV4dCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGV4ID49IDAgJiYgaW5kZXggPT09ICh2YWx1ZS5sZW5ndGggLSBmaWx0ZXJUZXh0Lmxlbmd0aCk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQyYihbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVmFsdWUtaW5kZXgwLTEnKVxuICAgIF0sIFRleHRGaWx0ZXIucHJvdG90eXBlLCBcImVWYWx1ZUZyb20xXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyYihbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVmFsdWUtaW5kZXgxLTEnKVxuICAgIF0sIFRleHRGaWx0ZXIucHJvdG90eXBlLCBcImVWYWx1ZVRvMVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmIoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVZhbHVlLWluZGV4MC0yJylcbiAgICBdLCBUZXh0RmlsdGVyLnByb3RvdHlwZSwgXCJlVmFsdWVGcm9tMlwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmIoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVZhbHVlLWluZGV4MS0yJylcbiAgICBdLCBUZXh0RmlsdGVyLnByb3RvdHlwZSwgXCJlVmFsdWVUbzJcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gVGV4dEZpbHRlcjtcbn0oU2ltcGxlRmlsdGVyKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMncgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDJhID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgVGV4dElucHV0RmxvYXRpbmdGaWx0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJ3KFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlc2V0VGVtcGxhdGUoKTtcbiAgICB9O1xuICAgIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5yZXNldFRlbXBsYXRlID0gZnVuY3Rpb24gKHBhcmFtc01hcCkge1xuICAgICAgICB0aGlzLnNldFRlbXBsYXRlKC8qIGh0bWwgKi8gXCJcXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1mbG9hdGluZy1maWx0ZXItaW5wdXRcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxhZy1pbnB1dC10ZXh0LWZpZWxkIHJlZj1cXFwiZUZsb2F0aW5nRmlsdGVySW5wdXRcXFwiPjwvYWctaW5wdXQtdGV4dC1maWVsZD5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgIFwiLCBwYXJhbXNNYXApO1xuICAgIH07XG4gICAgVGV4dElucHV0RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmdldERlZmF1bHREZWJvdW5jZU1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gNTAwO1xuICAgIH07XG4gICAgVGV4dElucHV0RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLm9uUGFyZW50TW9kZWxDaGFuZ2VkID0gZnVuY3Rpb24gKG1vZGVsLCBldmVudCkge1xuICAgICAgICBpZiAodGhpcy5pc0V2ZW50RnJvbUZsb2F0aW5nRmlsdGVyKGV2ZW50KSkge1xuICAgICAgICAgICAgLy8gaWYgdGhlIGZsb2F0aW5nIGZpbHRlciB0cmlnZ2VyZWQgdGhlIGNoYW5nZSwgaXQgaXMgYWxyZWFkeSBpbiBzeW5jXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRMYXN0VHlwZUZyb21Nb2RlbChtb2RlbCk7XG4gICAgICAgIHRoaXMuZUZsb2F0aW5nRmlsdGVySW5wdXQuc2V0VmFsdWUodGhpcy5nZXRUZXh0RnJvbU1vZGVsKG1vZGVsKSk7XG4gICAgICAgIHRoaXMuc2V0RWRpdGFibGUodGhpcy5jYW5XZUVkaXRBZnRlck1vZGVsRnJvbVBhcmVudEZpbHRlcihtb2RlbCkpO1xuICAgIH07XG4gICAgVGV4dElucHV0RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuaW5pdC5jYWxsKHRoaXMsIHBhcmFtcyk7XG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICB0aGlzLmFwcGx5QWN0aXZlID0gUHJvdmlkZWRGaWx0ZXIuaXNVc2VBcHBseUJ1dHRvbih0aGlzLnBhcmFtcy5maWx0ZXJQYXJhbXMpO1xuICAgICAgICB2YXIgYWxsb3dlZENoYXJQYXR0ZXJuID0gdGhpcy5wYXJhbXMuZmlsdGVyUGFyYW1zLmFsbG93ZWRDaGFyUGF0dGVybjtcbiAgICAgICAgaWYgKGFsbG93ZWRDaGFyUGF0dGVybiAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0VGVtcGxhdGUoeyBlRmxvYXRpbmdGaWx0ZXJJbnB1dDogeyBhbGxvd2VkQ2hhclBhdHRlcm46IGFsbG93ZWRDaGFyUGF0dGVybiB9IH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5pc1JlYWRPbmx5KCkpIHtcbiAgICAgICAgICAgIHZhciBkZWJvdW5jZU1zID0gUHJvdmlkZWRGaWx0ZXIuZ2V0RGVib3VuY2VNcyh0aGlzLnBhcmFtcy5maWx0ZXJQYXJhbXMsIHRoaXMuZ2V0RGVmYXVsdERlYm91bmNlTXMoKSk7XG4gICAgICAgICAgICB2YXIgdG9EZWJvdW5jZSA9IGRlYm91bmNlKHRoaXMuc3luY1VwV2l0aFBhcmVudEZpbHRlci5iaW5kKHRoaXMpLCBkZWJvdW5jZU1zKTtcbiAgICAgICAgICAgIHZhciBmaWx0ZXJHdWkgPSB0aGlzLmVGbG9hdGluZ0ZpbHRlcklucHV0LmdldEd1aSgpO1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZmlsdGVyR3VpLCAnaW5wdXQnLCB0b0RlYm91bmNlKTtcbiAgICAgICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGZpbHRlckd1aSwgJ2tleXByZXNzJywgdG9EZWJvdW5jZSk7XG4gICAgICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihmaWx0ZXJHdWksICdrZXlkb3duJywgdG9EZWJvdW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbHVtbkRlZiA9IHBhcmFtcy5jb2x1bW4uZ2V0RGVmaW5pdGlvbigpO1xuICAgICAgICBpZiAodGhpcy5pc1JlYWRPbmx5KCkgfHwgKGNvbHVtbkRlZi5maWx0ZXJQYXJhbXMgJiZcbiAgICAgICAgICAgIGNvbHVtbkRlZi5maWx0ZXJQYXJhbXMuZmlsdGVyT3B0aW9ucyAmJlxuICAgICAgICAgICAgY29sdW1uRGVmLmZpbHRlclBhcmFtcy5maWx0ZXJPcHRpb25zLmxlbmd0aCA9PT0gMSAmJlxuICAgICAgICAgICAgY29sdW1uRGVmLmZpbHRlclBhcmFtcy5maWx0ZXJPcHRpb25zWzBdID09PSAnaW5SYW5nZScpKSB7XG4gICAgICAgICAgICB0aGlzLmVGbG9hdGluZ0ZpbHRlcklucHV0LnNldERpc2FibGVkKHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkaXNwbGF5TmFtZSA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW4ocGFyYW1zLmNvbHVtbiwgJ2hlYWRlcicsIHRydWUpO1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdGhpcy5lRmxvYXRpbmdGaWx0ZXJJbnB1dC5zZXRJbnB1dEFyaWFMYWJlbChkaXNwbGF5TmFtZSArIFwiIFwiICsgdHJhbnNsYXRlKCdhcmlhRmlsdGVySW5wdXQnLCAnRmlsdGVyIElucHV0JykpO1xuICAgIH07XG4gICAgVGV4dElucHV0RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLnN5bmNVcFdpdGhQYXJlbnRGaWx0ZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZW50ZXJLZXlQcmVzc2VkID0gZS5rZXkgPT09IEtleUNvZGUuRU5URVI7XG4gICAgICAgIGlmICh0aGlzLmFwcGx5QWN0aXZlICYmICFlbnRlcktleVByZXNzZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLmVGbG9hdGluZ0ZpbHRlcklucHV0LmdldFZhbHVlKCk7XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5maWx0ZXJQYXJhbXMudHJpbUlucHV0KSB7XG4gICAgICAgICAgICB2YWx1ZSA9IFRleHRGaWx0ZXIudHJpbUlucHV0KHZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuZUZsb2F0aW5nRmlsdGVySW5wdXQuc2V0VmFsdWUodmFsdWUsIHRydWUpOyAvLyBlbnN1cmUgdmlzaWJsZSB2YWx1ZSBpcyB0cmltbWVkXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYXJhbXMucGFyZW50RmlsdGVySW5zdGFuY2UoZnVuY3Rpb24gKGZpbHRlckluc3RhbmNlKSB7XG4gICAgICAgICAgICBpZiAoZmlsdGVySW5zdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBmaWx0ZXJJbnN0YW5jZS5vbkZsb2F0aW5nRmlsdGVyQ2hhbmdlZChfdGhpcy5nZXRMYXN0VHlwZSgpIHx8IG51bGwsIHZhbHVlIHx8IG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5jb25kaXRpb25Ub1N0cmluZyA9IGZ1bmN0aW9uIChjb25kaXRpb24sIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIG51bWJlck9mSW5wdXRzID0gKG9wdGlvbnMgfHwge30pLm51bWJlck9mSW5wdXRzO1xuICAgICAgICB2YXIgaXNSYW5nZSA9IGNvbmRpdGlvbi50eXBlID09IFNpbXBsZUZpbHRlci5JTl9SQU5HRSB8fCBudW1iZXJPZklucHV0cyA9PT0gMjtcbiAgICAgICAgaWYgKGlzUmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25kaXRpb24uZmlsdGVyICsgXCItXCIgKyBjb25kaXRpb24uZmlsdGVyVG87XG4gICAgICAgIH1cbiAgICAgICAgLy8gY2F0ZXIgZm9yIHdoZW4gdGhlIHR5cGUgZG9lc24ndCBuZWVkIGEgdmFsdWVcbiAgICAgICAgaWYgKGNvbmRpdGlvbi5maWx0ZXIgIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCIgKyBjb25kaXRpb24uZmlsdGVyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBcIlwiICsgY29uZGl0aW9uLnR5cGU7XG4gICAgfTtcbiAgICBUZXh0SW5wdXRGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuc2V0RWRpdGFibGUgPSBmdW5jdGlvbiAoZWRpdGFibGUpIHtcbiAgICAgICAgdGhpcy5lRmxvYXRpbmdGaWx0ZXJJbnB1dC5zZXREaXNhYmxlZCghZWRpdGFibGUpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQyYShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmEoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUZsb2F0aW5nRmlsdGVySW5wdXQnKVxuICAgIF0sIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZSwgXCJlRmxvYXRpbmdGaWx0ZXJJbnB1dFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMmEoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgVGV4dElucHV0RmxvYXRpbmdGaWx0ZXIucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFRleHRJbnB1dEZsb2F0aW5nRmlsdGVyO1xufShTaW1wbGVGbG9hdGluZ0ZpbHRlcikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJ2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgTnVtYmVyRmxvYXRpbmdGaWx0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJ2KE51bWJlckZsb2F0aW5nRmlsdGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIE51bWJlckZsb2F0aW5nRmlsdGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIE51bWJlckZsb2F0aW5nRmlsdGVyLnByb3RvdHlwZS5nZXREZWZhdWx0RmlsdGVyT3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlckZpbHRlci5ERUZBVUxUX0ZJTFRFUl9PUFRJT05TO1xuICAgIH07XG4gICAgcmV0dXJuIE51bWJlckZsb2F0aW5nRmlsdGVyO1xufShUZXh0SW5wdXRGbG9hdGluZ0ZpbHRlcikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJ1ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgVGV4dEZsb2F0aW5nRmlsdGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQydShUZXh0RmxvYXRpbmdGaWx0ZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVGV4dEZsb2F0aW5nRmlsdGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFRleHRGbG9hdGluZ0ZpbHRlci5wcm90b3R5cGUuZ2V0RGVmYXVsdEZpbHRlck9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBUZXh0RmlsdGVyLkRFRkFVTFRfRklMVEVSX09QVElPTlM7XG4gICAgfTtcbiAgICByZXR1cm4gVGV4dEZsb2F0aW5nRmlsdGVyO1xufShUZXh0SW5wdXRGbG9hdGluZ0ZpbHRlcikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgVG91Y2hMaXN0ZW5lciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUb3VjaExpc3RlbmVyKGVFbGVtZW50LCBwcmV2ZW50TW91c2VDbGljaykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAocHJldmVudE1vdXNlQ2xpY2sgPT09IHZvaWQgMCkgeyBwcmV2ZW50TW91c2VDbGljayA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMuZGVzdHJveUZ1bmNzID0gW107XG4gICAgICAgIHRoaXMudG91Y2hpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UgPSBuZXcgRXZlbnRTZXJ2aWNlKCk7XG4gICAgICAgIHRoaXMuZUVsZW1lbnQgPSBlRWxlbWVudDtcbiAgICAgICAgdGhpcy5wcmV2ZW50TW91c2VDbGljayA9IHByZXZlbnRNb3VzZUNsaWNrO1xuICAgICAgICB2YXIgc3RhcnRMaXN0ZW5lciA9IHRoaXMub25Ub3VjaFN0YXJ0LmJpbmQodGhpcyk7XG4gICAgICAgIHZhciBtb3ZlTGlzdGVuZXIgPSB0aGlzLm9uVG91Y2hNb3ZlLmJpbmQodGhpcyk7XG4gICAgICAgIHZhciBlbmRMaXN0ZW5lciA9IHRoaXMub25Ub3VjaEVuZC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJ0b3VjaHN0YXJ0XCIsIHN0YXJ0TGlzdGVuZXIsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgdGhpcy5lRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFwidG91Y2htb3ZlXCIsIG1vdmVMaXN0ZW5lciwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgICAvLyB3ZSBzZXQgcGFzc2l2ZT1mYWxzZSwgYXMgd2Ugd2FudCB0byBwcmV2ZW50IGRlZmF1bHQgb24gdGhpcyBldmVudFxuICAgICAgICB0aGlzLmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJ0b3VjaGVuZFwiLCBlbmRMaXN0ZW5lciwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICAgICAgdGhpcy5kZXN0cm95RnVuY3MucHVzaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5lRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwidG91Y2hzdGFydFwiLCBzdGFydExpc3RlbmVyLCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gICAgICAgICAgICBfdGhpcy5lRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwidG91Y2htb3ZlXCIsIG1vdmVMaXN0ZW5lciwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgICAgICAgX3RoaXMuZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInRvdWNoZW5kXCIsIGVuZExpc3RlbmVyLCB7IHBhc3NpdmU6IGZhbHNlIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgVG91Y2hMaXN0ZW5lci5wcm90b3R5cGUuZ2V0QWN0aXZlVG91Y2ggPSBmdW5jdGlvbiAodG91Y2hMaXN0KSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdG91Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IHRvdWNoTGlzdFtpXS5pZGVudGlmaWVyID09PSB0aGlzLnRvdWNoU3RhcnQuaWRlbnRpZmllcjtcbiAgICAgICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvdWNoTGlzdFtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIFRvdWNoTGlzdGVuZXIucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5hZGRFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgVG91Y2hMaXN0ZW5lci5wcm90b3R5cGUucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBUb3VjaExpc3RlbmVyLnByb3RvdHlwZS5vblRvdWNoU3RhcnQgPSBmdW5jdGlvbiAodG91Y2hFdmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBvbmx5IGxvb2tpbmcgYXQgb25lIHRvdWNoIHBvaW50IGF0IGFueSB0aW1lXG4gICAgICAgIGlmICh0aGlzLnRvdWNoaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3VjaFN0YXJ0ID0gdG91Y2hFdmVudC50b3VjaGVzWzBdO1xuICAgICAgICB0aGlzLnRvdWNoaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tb3ZlZCA9IGZhbHNlO1xuICAgICAgICB2YXIgdG91Y2hTdGFydENvcHkgPSB0aGlzLnRvdWNoU3RhcnQ7XG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciB0b3VjaGVzTWF0Y2ggPSBfdGhpcy50b3VjaFN0YXJ0ID09PSB0b3VjaFN0YXJ0Q29weTtcbiAgICAgICAgICAgIGlmIChfdGhpcy50b3VjaGluZyAmJiB0b3VjaGVzTWF0Y2ggJiYgIV90aGlzLm1vdmVkKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMubW92ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBldmVudF8xID0ge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBUb3VjaExpc3RlbmVyLkVWRU5UX0xPTkdfVEFQLFxuICAgICAgICAgICAgICAgICAgICB0b3VjaFN0YXJ0OiBfdGhpcy50b3VjaFN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICB0b3VjaEV2ZW50OiB0b3VjaEV2ZW50XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBfdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgNTAwKTtcbiAgICB9O1xuICAgIFRvdWNoTGlzdGVuZXIucHJvdG90eXBlLm9uVG91Y2hNb3ZlID0gZnVuY3Rpb24gKHRvdWNoRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRvdWNoaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRvdWNoID0gdGhpcy5nZXRBY3RpdmVUb3VjaCh0b3VjaEV2ZW50LnRvdWNoZXMpO1xuICAgICAgICBpZiAoIXRvdWNoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50SXNGYXJBd2F5ID0gIWFyZUV2ZW50c05lYXIodG91Y2gsIHRoaXMudG91Y2hTdGFydCwgNCk7XG4gICAgICAgIGlmIChldmVudElzRmFyQXdheSkge1xuICAgICAgICAgICAgdGhpcy5tb3ZlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFRvdWNoTGlzdGVuZXIucHJvdG90eXBlLm9uVG91Y2hFbmQgPSBmdW5jdGlvbiAodG91Y2hFdmVudCkge1xuICAgICAgICBpZiAoIXRoaXMudG91Y2hpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMubW92ZWQpIHtcbiAgICAgICAgICAgIHZhciBldmVudF8yID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IFRvdWNoTGlzdGVuZXIuRVZFTlRfVEFQLFxuICAgICAgICAgICAgICAgIHRvdWNoU3RhcnQ6IHRoaXMudG91Y2hTdGFydFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnRfMik7XG4gICAgICAgICAgICB0aGlzLmNoZWNrRm9yRG91YmxlVGFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc3RvcHMgdGhlIHRhcCBmcm9tIGFsc28gYmVlbiBwcm9jZXNzZWQgYXMgYSBtb3VzZSBjbGlja1xuICAgICAgICBpZiAodGhpcy5wcmV2ZW50TW91c2VDbGljayAmJiB0b3VjaEV2ZW50LmNhbmNlbGFibGUpIHtcbiAgICAgICAgICAgIHRvdWNoRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRvdWNoaW5nID0gZmFsc2U7XG4gICAgfTtcbiAgICBUb3VjaExpc3RlbmVyLnByb3RvdHlwZS5jaGVja0ZvckRvdWJsZVRhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICBpZiAodGhpcy5sYXN0VGFwVGltZSAmJiB0aGlzLmxhc3RUYXBUaW1lID4gMCkge1xuICAgICAgICAgICAgLy8gaWYgcHJldmlvdXMgdGFwLCBzZWUgaWYgZHVyYXRpb24gaXMgc2hvcnQgZW5vdWdoIHRvIGJlIGNvbnNpZGVyZWQgZG91YmxlIHRhcFxuICAgICAgICAgICAgdmFyIGludGVydmFsID0gbm93IC0gdGhpcy5sYXN0VGFwVGltZTtcbiAgICAgICAgICAgIGlmIChpbnRlcnZhbCA+IFRvdWNoTGlzdGVuZXIuRE9VQkxFX1RBUF9NSUxMSVMpIHtcbiAgICAgICAgICAgICAgICAvLyBkaXNwYXRjaCBkb3VibGUgdGFwIGV2ZW50XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50XzMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IFRvdWNoTGlzdGVuZXIuRVZFTlRfRE9VQkxFX1RBUCxcbiAgICAgICAgICAgICAgICAgICAgdG91Y2hTdGFydDogdGhpcy50b3VjaFN0YXJ0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50XzMpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgc3RvcHMgYSB0cmlwcGxlIHRhcCBlbmRpbmcgdXAgYXMgdHdvIGRvdWJsZSB0YXBzXG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0VGFwVGltZSA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RUYXBUaW1lID0gbm93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sYXN0VGFwVGltZSA9IG5vdztcbiAgICAgICAgfVxuICAgIH07XG4gICAgVG91Y2hMaXN0ZW5lci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kZXN0cm95RnVuY3MuZm9yRWFjaChmdW5jdGlvbiAoZnVuYykgeyByZXR1cm4gZnVuYygpOyB9KTtcbiAgICB9O1xuICAgIFRvdWNoTGlzdGVuZXIuRVZFTlRfVEFQID0gXCJ0YXBcIjtcbiAgICBUb3VjaExpc3RlbmVyLkVWRU5UX0RPVUJMRV9UQVAgPSBcImRvdWJsZVRhcFwiO1xuICAgIFRvdWNoTGlzdGVuZXIuRVZFTlRfTE9OR19UQVAgPSBcImxvbmdUYXBcIjtcbiAgICBUb3VjaExpc3RlbmVyLkRPVUJMRV9UQVBfTUlMTElTID0gNTAwO1xuICAgIHJldHVybiBUb3VjaExpc3RlbmVyO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQydCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMjkgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBTb3J0SW5kaWNhdG9yQ29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMnQoU29ydEluZGljYXRvckNvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU29ydEluZGljYXRvckNvbXAoc2tpcFRlbXBsYXRlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIGlmICghc2tpcFRlbXBsYXRlKSB7XG4gICAgICAgICAgICBfdGhpcy5zZXRUZW1wbGF0ZShTb3J0SW5kaWNhdG9yQ29tcC5URU1QTEFURSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTb3J0SW5kaWNhdG9yQ29tcC5wcm90b3R5cGUuYXR0YWNoQ3VzdG9tRWxlbWVudHMgPSBmdW5jdGlvbiAoZVNvcnRPcmRlciwgZVNvcnRBc2MsIGVTb3J0RGVzYywgZVNvcnRNaXhlZCwgZVNvcnROb25lKSB7XG4gICAgICAgIHRoaXMuZVNvcnRPcmRlciA9IGVTb3J0T3JkZXI7XG4gICAgICAgIHRoaXMuZVNvcnRBc2MgPSBlU29ydEFzYztcbiAgICAgICAgdGhpcy5lU29ydERlc2MgPSBlU29ydERlc2M7XG4gICAgICAgIHRoaXMuZVNvcnRNaXhlZCA9IGVTb3J0TWl4ZWQ7XG4gICAgICAgIHRoaXMuZVNvcnROb25lID0gZVNvcnROb25lO1xuICAgIH07XG4gICAgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLnNldHVwU29ydCA9IGZ1bmN0aW9uIChjb2x1bW4sIHN1cHByZXNzT3JkZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHN1cHByZXNzT3JkZXIgPT09IHZvaWQgMCkgeyBzdXBwcmVzc09yZGVyID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIHRoaXMuc3VwcHJlc3NPcmRlciA9IHN1cHByZXNzT3JkZXI7XG4gICAgICAgIHRoaXMuc2V0dXBNdWx0aVNvcnRJbmRpY2F0b3IoKTtcbiAgICAgICAgdmFyIGNhblNvcnQgPSAhIXRoaXMuY29sdW1uLmdldENvbERlZigpLnNvcnRhYmxlO1xuICAgICAgICBpZiAoIWNhblNvcnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZEluSWNvbignc29ydEFzY2VuZGluZycsIHRoaXMuZVNvcnRBc2MsIGNvbHVtbik7XG4gICAgICAgIHRoaXMuYWRkSW5JY29uKCdzb3J0RGVzY2VuZGluZycsIHRoaXMuZVNvcnREZXNjLCBjb2x1bW4pO1xuICAgICAgICB0aGlzLmFkZEluSWNvbignc29ydFVuU29ydCcsIHRoaXMuZVNvcnROb25lLCBjb2x1bW4pO1xuICAgICAgICAvLyBXYXRjaCBnbG9iYWwgZXZlbnRzLCBhcyByb3cgZ3JvdXAgY29sdW1ucyBjYW4gZWZmZWN0IHRoZWlyIGRpc3BsYXkgY29sdW1uLlxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1NPUlRfQ0hBTkdFRCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25Tb3J0Q2hhbmdlZCgpOyB9KTtcbiAgICAgICAgLy8gd2hlbiBncm91cGluZyBjaGFuZ2VzIHNvIGNhbiBzb3J0IGluZGV4ZXMgYW5kIGljb25zXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1JPV19HUk9VUF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vblNvcnRDaGFuZ2VkKCk7IH0pO1xuICAgICAgICB0aGlzLm9uU29ydENoYW5nZWQoKTtcbiAgICB9O1xuICAgIFNvcnRJbmRpY2F0b3JDb21wLnByb3RvdHlwZS5hZGRJbkljb24gPSBmdW5jdGlvbiAoaWNvbk5hbWUsIGVQYXJlbnQsIGNvbHVtbikge1xuICAgICAgICBpZiAoZVBhcmVudCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVJY29uID0gY3JlYXRlSWNvbk5vU3BhbihpY29uTmFtZSwgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIGNvbHVtbik7XG4gICAgICAgIGlmIChlSWNvbikge1xuICAgICAgICAgICAgZVBhcmVudC5hcHBlbmRDaGlsZChlSWNvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNvcnRJbmRpY2F0b3JDb21wLnByb3RvdHlwZS5vblNvcnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUljb25zKCk7XG4gICAgICAgIGlmICghdGhpcy5zdXBwcmVzc09yZGVyKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNvcnRPcmRlcigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTb3J0SW5kaWNhdG9yQ29tcC5wcm90b3R5cGUudXBkYXRlSWNvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzb3J0RGlyZWN0aW9uID0gdGhpcy5zb3J0Q29udHJvbGxlci5nZXREaXNwbGF5U29ydEZvckNvbHVtbih0aGlzLmNvbHVtbik7XG4gICAgICAgIGlmICh0aGlzLmVTb3J0QXNjKSB7XG4gICAgICAgICAgICB2YXIgaXNBc2NlbmRpbmcgPSBzb3J0RGlyZWN0aW9uID09PSAnYXNjJztcbiAgICAgICAgICAgIHRoaXMuZVNvcnRBc2MuY2xhc3NMaXN0LnRvZ2dsZSgnYWctaGlkZGVuJywgIWlzQXNjZW5kaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5lU29ydERlc2MpIHtcbiAgICAgICAgICAgIHZhciBpc0Rlc2NlbmRpbmcgPSBzb3J0RGlyZWN0aW9uID09PSAnZGVzYyc7XG4gICAgICAgICAgICB0aGlzLmVTb3J0RGVzYy5jbGFzc0xpc3QudG9nZ2xlKCdhZy1oaWRkZW4nLCAhaXNEZXNjZW5kaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5lU29ydE5vbmUpIHtcbiAgICAgICAgICAgIHZhciBhbHdheXNIaWRlTm9Tb3J0ID0gIXRoaXMuY29sdW1uLmdldENvbERlZigpLnVuU29ydEljb24gJiYgIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVW5Tb3J0SWNvbigpO1xuICAgICAgICAgICAgdmFyIGlzTm9uZSA9IHNvcnREaXJlY3Rpb24gPT09IG51bGwgfHwgc29ydERpcmVjdGlvbiA9PT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5lU29ydE5vbmUuY2xhc3NMaXN0LnRvZ2dsZSgnYWctaGlkZGVuJywgKGFsd2F5c0hpZGVOb1NvcnQgfHwgIWlzTm9uZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTb3J0SW5kaWNhdG9yQ29tcC5wcm90b3R5cGUuc2V0dXBNdWx0aVNvcnRJbmRpY2F0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkSW5JY29uKCdzb3J0VW5Tb3J0JywgdGhpcy5lU29ydE1peGVkLCB0aGlzLmNvbHVtbik7XG4gICAgICAgIHZhciBpc0NvbHVtblNob3dpbmdSb3dHcm91cCA9IHRoaXMuY29sdW1uLmdldENvbERlZigpLnNob3dSb3dHcm91cDtcbiAgICAgICAgdmFyIGFyZUdyb3Vwc0NvdXBsZWQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0NvbHVtbnNTb3J0aW5nQ291cGxlZFRvR3JvdXAoKTtcbiAgICAgICAgaWYgKGFyZUdyb3Vwc0NvdXBsZWQgJiYgaXNDb2x1bW5TaG93aW5nUm93R3JvdXApIHtcbiAgICAgICAgICAgIC8vIFdhdGNoIGdsb2JhbCBldmVudHMsIGFzIHJvdyBncm91cCBjb2x1bW5zIGNhbiBlZmZlY3QgdGhlaXIgZGlzcGxheSBjb2x1bW4uXG4gICAgICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1NPUlRfQ0hBTkdFRCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudXBkYXRlTXVsdGlTb3J0SW5kaWNhdG9yKCk7IH0pO1xuICAgICAgICAgICAgLy8gd2hlbiBncm91cGluZyBjaGFuZ2VzIHNvIGNhbiBzb3J0IGluZGV4ZXMgYW5kIGljb25zXG4gICAgICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9ST1dfR1JPVVBfQ0hBTkdFRCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudXBkYXRlTXVsdGlTb3J0SW5kaWNhdG9yKCk7IH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVNdWx0aVNvcnRJbmRpY2F0b3IoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLnVwZGF0ZU11bHRpU29ydEluZGljYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZVNvcnRNaXhlZCkge1xuICAgICAgICAgICAgdmFyIGlzTWl4ZWRTb3J0ID0gdGhpcy5zb3J0Q29udHJvbGxlci5nZXREaXNwbGF5U29ydEZvckNvbHVtbih0aGlzLmNvbHVtbikgPT09ICdtaXhlZCc7XG4gICAgICAgICAgICB0aGlzLmVTb3J0TWl4ZWQuY2xhc3NMaXN0LnRvZ2dsZSgnYWctaGlkZGVuJywgIWlzTWl4ZWRTb3J0KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gd2UgbGlzdGVuIGhlcmUgZm9yIGdsb2JhbCBzb3J0IGV2ZW50cywgTk9UIGNvbHVtbiBzb3J0IGV2ZW50cywgYXMgd2Ugd2FudCB0byBkbyB0aGlzXG4gICAgLy8gd2hlbiBzb3J0aW5nIGhhcyBiZWVuIHNldCBvbiBhbGwgY29sdW1uIChpZiB3ZSBsaXN0ZW5lZCBqdXN0IGZvciBvdXIgY29sICh3aGVyZSB3ZVxuICAgIC8vIHNldCB0aGUgYXNjIC8gZGVzYyBpY29ucykgdGhlbiBpdCdzIHBvc3NpYmxlIG90aGVyIGNvbHMgYXJlIHlldCB0byBnZXQgdGhlaXIgc29ydGluZyBzdGF0ZS5cbiAgICBTb3J0SW5kaWNhdG9yQ29tcC5wcm90b3R5cGUudXBkYXRlU29ydE9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIGlmICghdGhpcy5lU29ydE9yZGVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFsbENvbHVtbnNXaXRoU29ydGluZyA9IHRoaXMuc29ydENvbnRyb2xsZXIuZ2V0Q29sdW1uc1dpdGhTb3J0aW5nT3JkZXJlZCgpO1xuICAgICAgICB2YXIgaW5kZXhUaGlzQ29sID0gKF9hID0gdGhpcy5zb3J0Q29udHJvbGxlci5nZXREaXNwbGF5U29ydEluZGV4Rm9yQ29sdW1uKHRoaXMuY29sdW1uKSwgKF9hICE9PSBudWxsICYmIF9hICE9PSB2b2lkIDAgPyBfYSA6IC0xKSk7XG4gICAgICAgIHZhciBtb3JlVGhhbk9uZUNvbFNvcnRpbmcgPSBhbGxDb2x1bW5zV2l0aFNvcnRpbmcuc29tZShmdW5jdGlvbiAoY29sKSB7IHZhciBfYTsgcmV0dXJuIF9hID0gX3RoaXMuc29ydENvbnRyb2xsZXIuZ2V0RGlzcGxheVNvcnRJbmRleEZvckNvbHVtbihjb2wpLCAoX2EgIT09IG51bGwgJiYgX2EgIT09IHZvaWQgMCA/IF9hIDogLTEgPj0gMSk7IH0pO1xuICAgICAgICB2YXIgc2hvd0luZGV4ID0gaW5kZXhUaGlzQ29sID49IDAgJiYgbW9yZVRoYW5PbmVDb2xTb3J0aW5nO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lU29ydE9yZGVyLCBzaG93SW5kZXgpO1xuICAgICAgICBpZiAoaW5kZXhUaGlzQ29sID49IDApIHtcbiAgICAgICAgICAgIHRoaXMuZVNvcnRPcmRlci5pbm5lckhUTUwgPSAoaW5kZXhUaGlzQ29sICsgMSkudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsZWFyRWxlbWVudCh0aGlzLmVTb3J0T3JkZXIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTb3J0SW5kaWNhdG9yQ29tcC5URU1QTEFURSA9IFwiPHNwYW4gY2xhc3M9XFxcImFnLXNvcnQtaW5kaWNhdG9yLWNvbnRhaW5lclxcXCI+XFxuICAgICAgICAgICAgPHNwYW4gcmVmPVxcXCJlU29ydE9yZGVyXFxcIiBjbGFzcz1cXFwiYWctc29ydC1pbmRpY2F0b3ItaWNvbiBhZy1zb3J0LW9yZGVyIGFnLWhpZGRlblxcXCIgYXJpYS1oaWRkZW49XFxcInRydWVcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8c3BhbiByZWY9XFxcImVTb3J0QXNjXFxcIiBjbGFzcz1cXFwiYWctc29ydC1pbmRpY2F0b3ItaWNvbiBhZy1zb3J0LWFzY2VuZGluZy1pY29uIGFnLWhpZGRlblxcXCIgYXJpYS1oaWRkZW49XFxcInRydWVcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8c3BhbiByZWY9XFxcImVTb3J0RGVzY1xcXCIgY2xhc3M9XFxcImFnLXNvcnQtaW5kaWNhdG9yLWljb24gYWctc29ydC1kZXNjZW5kaW5nLWljb24gYWctaGlkZGVuXFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDxzcGFuIHJlZj1cXFwiZVNvcnRNaXhlZFxcXCIgY2xhc3M9XFxcImFnLXNvcnQtaW5kaWNhdG9yLWljb24gYWctc29ydC1taXhlZC1pY29uIGFnLWhpZGRlblxcXCIgYXJpYS1oaWRkZW49XFxcInRydWVcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8c3BhbiByZWY9XFxcImVTb3J0Tm9uZVxcXCIgY2xhc3M9XFxcImFnLXNvcnQtaW5kaWNhdG9yLWljb24gYWctc29ydC1ub25lLWljb24gYWctaGlkZGVuXFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+PC9zcGFuPlxcbiAgICAgICAgPC9zcGFuPlwiO1xuICAgIF9fZGVjb3JhdGUkMjkoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVNvcnRPcmRlcicpXG4gICAgXSwgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLCBcImVTb3J0T3JkZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI5KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0QXNjJylcbiAgICBdLCBTb3J0SW5kaWNhdG9yQ29tcC5wcm90b3R5cGUsIFwiZVNvcnRBc2NcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI5KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0RGVzYycpXG4gICAgXSwgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLCBcImVTb3J0RGVzY1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjkoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVNvcnRNaXhlZCcpXG4gICAgXSwgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLCBcImVTb3J0TWl4ZWRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI5KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0Tm9uZScpXG4gICAgXSwgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLCBcImVTb3J0Tm9uZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjkoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBTb3J0SW5kaWNhdG9yQ29tcC5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI5KFtcbiAgICAgICAgQXV0b3dpcmVkKCdzb3J0Q29udHJvbGxlcicpXG4gICAgXSwgU29ydEluZGljYXRvckNvbXAucHJvdG90eXBlLCBcInNvcnRDb250cm9sbGVyXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIFNvcnRJbmRpY2F0b3JDb21wO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQycyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMjggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBIZWFkZXJDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQycyhIZWFkZXJDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlckNvbXAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5sYXN0TW92aW5nQ2hhbmdlZCA9IDA7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgLy8gdGhpcyBpcyBhIHVzZXIgY29tcG9uZW50LCBhbmQgSUNvbXBvbmVudCBoYXMgXCJwdWJsaWMgZGVzdHJveSgpXCIgYXMgcGFydCBvZiB0aGUgaW50ZXJmYWNlLlxuICAgIC8vIHNvIHdlIG5lZWQgdG8gb3ZlcnJpZGUgZGVzdHJveSgpIGp1c3QgdG8gbWFrZSB0aGUgbWV0aG9kIHB1YmxpYy5cbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIEhlYWRlckNvbXAucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICAvLyBpZiB0ZW1wbGF0ZSBjaGFuZ2VkLCB0aGVuIHJlY3JlYXRlIHRoZSB3aG9sZSBjb21wLCB0aGUgY29kZSByZXF1aXJlZCB0byBtYW5hZ2VcbiAgICAgICAgLy8gYSBjaGFuZ2luZyB0ZW1wbGF0ZSBpcyB0byBkaWZmaWN1bHQgZm9yIHdoYXQgaXQncyB3b3J0aC5cbiAgICAgICAgaWYgKHRoaXMud29ya091dFRlbXBsYXRlKCkgIT0gdGhpcy5jdXJyZW50VGVtcGxhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy53b3JrT3V0U2hvd01lbnUoKSAhPSB0aGlzLmN1cnJlbnRTaG93TWVudSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLndvcmtPdXRTb3J0KCkgIT0gdGhpcy5jdXJyZW50U29ydCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0RGlzcGxheU5hbWUocGFyYW1zKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS53b3JrT3V0VGVtcGxhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0ZW1wbGF0ZSA9IGZpcnN0RXhpc3RpbmdWYWx1ZSh0aGlzLnBhcmFtcy50ZW1wbGF0ZSwgSGVhZGVyQ29tcC5URU1QTEFURSk7XG4gICAgICAgIC8vIHRha2UgYWNjb3VudCBvZiBhbnkgbmV3bGluZXMgJiB3aGl0ZXNwYWNlIGJlZm9yZS9hZnRlciB0aGUgYWN0dWFsIHRlbXBsYXRlXG4gICAgICAgIHRlbXBsYXRlID0gdGVtcGxhdGUgJiYgdGVtcGxhdGUudHJpbSA/IHRlbXBsYXRlLnRyaW0oKSA6IHRlbXBsYXRlO1xuICAgICAgICByZXR1cm4gdGVtcGxhdGU7XG4gICAgfTtcbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB0aGlzLnBhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgdGhpcy5jdXJyZW50VGVtcGxhdGUgPSB0aGlzLndvcmtPdXRUZW1wbGF0ZSgpO1xuICAgICAgICB0aGlzLnNldFRlbXBsYXRlKHRoaXMuY3VycmVudFRlbXBsYXRlKTtcbiAgICAgICAgdGhpcy5zZXR1cFRhcCgpO1xuICAgICAgICB0aGlzLnNldHVwSWNvbnMocGFyYW1zLmNvbHVtbik7XG4gICAgICAgIHRoaXMuc2V0TWVudSgpO1xuICAgICAgICB0aGlzLnNldHVwU29ydCgpO1xuICAgICAgICB0aGlzLnNldHVwRmlsdGVySWNvbigpO1xuICAgICAgICB0aGlzLnNldERpc3BsYXlOYW1lKHBhcmFtcyk7XG4gICAgfTtcbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS5zZXREaXNwbGF5TmFtZSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudERpc3BsYXlOYW1lICE9IHBhcmFtcy5kaXNwbGF5TmFtZSkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50RGlzcGxheU5hbWUgPSBwYXJhbXMuZGlzcGxheU5hbWU7XG4gICAgICAgICAgICB2YXIgZGlzcGxheU5hbWVTYW5pdGlzZWQgPSBlc2NhcGVTdHJpbmcodGhpcy5jdXJyZW50RGlzcGxheU5hbWUpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZVRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVUZXh0LmlubmVySFRNTCA9IGRpc3BsYXlOYW1lU2FuaXRpc2VkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS5zZXR1cEljb25zID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICB0aGlzLmFkZEluSWNvbignbWVudScsIHRoaXMuZU1lbnUsIGNvbHVtbik7XG4gICAgICAgIHRoaXMuYWRkSW5JY29uKCdmaWx0ZXInLCB0aGlzLmVGaWx0ZXIsIGNvbHVtbik7XG4gICAgfTtcbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS5hZGRJbkljb24gPSBmdW5jdGlvbiAoaWNvbk5hbWUsIGVQYXJlbnQsIGNvbHVtbikge1xuICAgICAgICBpZiAoZVBhcmVudCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVJY29uID0gY3JlYXRlSWNvbk5vU3BhbihpY29uTmFtZSwgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIGNvbHVtbik7XG4gICAgICAgIGlmIChlSWNvbikge1xuICAgICAgICAgICAgZVBhcmVudC5hcHBlbmRDaGlsZChlSWNvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlckNvbXAucHJvdG90eXBlLnNldHVwVGFwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgb3B0aW9ucyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICBpZiAob3B0aW9ucy5pc1N1cHByZXNzVG91Y2goKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0b3VjaExpc3RlbmVyID0gbmV3IFRvdWNoTGlzdGVuZXIodGhpcy5nZXRHdWkoKSwgdHJ1ZSk7XG4gICAgICAgIHZhciBzdXBwcmVzc01lbnVIaWRlID0gb3B0aW9ucy5pc1N1cHByZXNzTWVudUhpZGUoKTtcbiAgICAgICAgdmFyIHRhcE1lbnVCdXR0b24gPSBzdXBwcmVzc01lbnVIaWRlICYmIGV4aXN0cyh0aGlzLmVNZW51KTtcbiAgICAgICAgdmFyIG1lbnVUb3VjaExpc3RlbmVyID0gdGFwTWVudUJ1dHRvbiA/IG5ldyBUb3VjaExpc3RlbmVyKHRoaXMuZU1lbnUsIHRydWUpIDogdG91Y2hMaXN0ZW5lcjtcbiAgICAgICAgaWYgKHRoaXMucGFyYW1zLmVuYWJsZU1lbnUpIHtcbiAgICAgICAgICAgIHZhciBldmVudFR5cGUgPSB0YXBNZW51QnV0dG9uID8gJ0VWRU5UX1RBUCcgOiAnRVZFTlRfTE9OR19UQVAnO1xuICAgICAgICAgICAgdmFyIHNob3dNZW51Rm4gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zLmdldEFwaSgpLnNob3dDb2x1bW5NZW51QWZ0ZXJNb3VzZUNsaWNrKF90aGlzLnBhcmFtcy5jb2x1bW4sIGV2ZW50LnRvdWNoU3RhcnQpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKG1lbnVUb3VjaExpc3RlbmVyLCBUb3VjaExpc3RlbmVyW2V2ZW50VHlwZV0sIHNob3dNZW51Rm4pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5lbmFibGVTb3J0aW5nKSB7XG4gICAgICAgICAgICB2YXIgdGFwTGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZXZlbnQudG91Y2hTdGFydC50YXJnZXQ7XG4gICAgICAgICAgICAgICAgLy8gV2hlbiBzdXBwcmVzc01lbnVIaWRlIGlzIHRydWUsIGEgdGFwIG9uIHRoZSBtZW51IGljb24gd2lsbCBidWJibGUgdXBcbiAgICAgICAgICAgICAgICAvLyB0byB0aGUgaGVhZGVyIGNvbnRhaW5lciwgaW4gdGhhdCBjYXNlIHdlIHNob3VsZCBub3Qgc29ydFxuICAgICAgICAgICAgICAgIGlmIChzdXBwcmVzc01lbnVIaWRlICYmIF90aGlzLmVNZW51LmNvbnRhaW5zKHRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5zb3J0Q29udHJvbGxlci5wcm9ncmVzc1NvcnQoX3RoaXMucGFyYW1zLmNvbHVtbiwgZmFsc2UsIFwidWlDb2x1bW5Tb3J0ZWRcIik7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodG91Y2hMaXN0ZW5lciwgVG91Y2hMaXN0ZW5lci5FVkVOVF9UQVAsIHRhcExpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0YXBNZW51QnV0dG9uIGlzIHRydWUgYHRvdWNoTGlzdGVuZXJgIGFuZCBgbWVudVRvdWNoTGlzdGVuZXJgIGFyZSBkaWZmZXJlbnRcbiAgICAgICAgLy8gc28gd2UgbmVlZCB0byBtYWtlIHN1cmUgdG8gZGVzdHJveSBib3RoIGxpc3RlbmVycyBoZXJlXG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gdG91Y2hMaXN0ZW5lci5kZXN0cm95KCk7IH0pO1xuICAgICAgICBpZiAodGFwTWVudUJ1dHRvbikge1xuICAgICAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBtZW51VG91Y2hMaXN0ZW5lci5kZXN0cm95KCk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDb21wLnByb3RvdHlwZS53b3JrT3V0U2hvd01lbnUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHdlIGRvbid0IHNob3cgdGhlIG1lbnUgaWYgb24gYW4gaVBhZC9pUGhvbmUsIGFzIHRoZSB1c2VyIGNhbm5vdCBoYXZlIGEgcG9pbnRlciBkZXZpY2UvXG4gICAgICAgIC8vIEhvd2V2ZXIgaWYgc3VwcHJlc3NNZW51SGlkZSBpcyBzZXQgdG8gdHJ1ZSB0aGUgbWVudSB3aWxsIGJlIGRpc3BsYXllZCBhbHdhc3lzLCBzbyBpdCdzIG9rXG4gICAgICAgIC8vIHRvIHNob3cgaXQgb24gaVBhZCBpbiB0aGlzIGNhc2UgKGFzIGhvdmVyIGlzbid0IG5lZWRlZCkuIElmIHN1cHByZXNzTWVudUhpZGVcbiAgICAgICAgLy8gaXMgZmFsc2UgKGRlZmF1bHQpIHVzZXIgd2lsbCBuZWVkIHRvIHVzZSBsb25ncHJlc3MgdG8gZGlzcGxheSB0aGUgbWVudS5cbiAgICAgICAgdmFyIG1lbnVIaWRlcyA9ICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTWVudUhpZGUoKTtcbiAgICAgICAgdmFyIG9uSXBhZEFuZE1lbnVIaWRlcyA9IGlzSU9TVXNlckFnZW50KCkgJiYgbWVudUhpZGVzO1xuICAgICAgICB2YXIgc2hvd01lbnUgPSB0aGlzLnBhcmFtcy5lbmFibGVNZW51ICYmICFvbklwYWRBbmRNZW51SGlkZXM7XG4gICAgICAgIHJldHVybiBzaG93TWVudTtcbiAgICB9O1xuICAgIEhlYWRlckNvbXAucHJvdG90eXBlLnNldE1lbnUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIGlmIG5vIG1lbnUgcHJvdmlkZWQgaW4gdGVtcGxhdGUsIGRvIG5vdGhpbmdcbiAgICAgICAgaWYgKCF0aGlzLmVNZW51KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdXJyZW50U2hvd01lbnUgPSB0aGlzLndvcmtPdXRTaG93TWVudSgpO1xuICAgICAgICBpZiAoIXRoaXMuY3VycmVudFNob3dNZW51KSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tUGFyZW50KHRoaXMuZU1lbnUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzdXBwcmVzc01lbnVIaWRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc01lbnVIaWRlKCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZU1lbnUsICdjbGljaycsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnNob3dNZW51KF90aGlzLmVNZW51KTsgfSk7XG4gICAgICAgIHRoaXMuZU1lbnUuY2xhc3NMaXN0LnRvZ2dsZSgnYWctaGVhZGVyLW1lbnUtYWx3YXlzLXNob3cnLCBzdXBwcmVzc01lbnVIaWRlKTtcbiAgICB9O1xuICAgIEhlYWRlckNvbXAucHJvdG90eXBlLnNob3dNZW51ID0gZnVuY3Rpb24gKGV2ZW50U291cmNlKSB7XG4gICAgICAgIGlmICghZXZlbnRTb3VyY2UpIHtcbiAgICAgICAgICAgIGV2ZW50U291cmNlID0gdGhpcy5lTWVudTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1lbnVGYWN0b3J5LnNob3dNZW51QWZ0ZXJCdXR0b25DbGljayh0aGlzLnBhcmFtcy5jb2x1bW4sIGV2ZW50U291cmNlLCAnY29sdW1uTWVudScpO1xuICAgIH07XG4gICAgSGVhZGVyQ29tcC5wcm90b3R5cGUud29ya091dFNvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmFtcy5lbmFibGVTb3J0aW5nO1xuICAgIH07XG4gICAgSGVhZGVyQ29tcC5wcm90b3R5cGUuc2V0dXBTb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmN1cnJlbnRTb3J0ID0gdGhpcy5wYXJhbXMuZW5hYmxlU29ydGluZztcbiAgICAgICAgLy8gZVNvcnRJbmRpY2F0b3Igd2lsbCBub3QgYmUgcHJlc2VudCB3aGVuIGN1c3RvbWVycyBwcm92aWRlZCBjdXN0b20gaGVhZGVyXG4gICAgICAgIC8vIHRlbXBsYXRlcywgaW4gdGhhdCBjYXNlLCB3ZSBuZWVkIHRvIGxvb2sgZm9yIHByb3ZpZGVkIHNvcnQgZWxlbWVudHMgYW5kXG4gICAgICAgIC8vIG1hbnVhbGx5IGNyZWF0ZSBlU29ydEluZGljYXRvci5cbiAgICAgICAgaWYgKCF0aGlzLmVTb3J0SW5kaWNhdG9yKSB7XG4gICAgICAgICAgICB0aGlzLmVTb3J0SW5kaWNhdG9yID0gdGhpcy5jb250ZXh0LmNyZWF0ZUJlYW4obmV3IFNvcnRJbmRpY2F0b3JDb21wKHRydWUpKTtcbiAgICAgICAgICAgIHRoaXMuZVNvcnRJbmRpY2F0b3IuYXR0YWNoQ3VzdG9tRWxlbWVudHModGhpcy5lU29ydE9yZGVyLCB0aGlzLmVTb3J0QXNjLCB0aGlzLmVTb3J0RGVzYywgdGhpcy5lU29ydE1peGVkLCB0aGlzLmVTb3J0Tm9uZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lU29ydEluZGljYXRvci5zZXR1cFNvcnQodGhpcy5wYXJhbXMuY29sdW1uKTtcbiAgICAgICAgLy8gd2Ugc2V0IHVwIHRoZSBpbmRpY2F0b3IgcHJpb3IgdG8gdGhlIGNoZWNrIGZvciB3aGV0aGVyIHRoaXMgY29sdW1uIGlzIHNvcnRhYmxlLCBhcyBpdCBhbGxvd3MgdGhlIGluZGljYXRvciB0b1xuICAgICAgICAvLyBzZXQgdXAgdGhlIG11bHRpIHNvcnQgaW5kaWNhdG9yIHdoaWNoIGNhbiBhcHBlYXIgaXJyZWxldmFudCBvZiB3aGV0aGVyIHRoaXMgY29sdW1uIGNhbiBpdHNlbGYgYmUgc29ydGVkLlxuICAgICAgICAvLyB0aGlzIGNhbiBvY2N1ciBpbiB0aGUgY2FzZSBvZiBhIG5vbi1zb3J0YWJsZSBncm91cCBkaXNwbGF5IGNvbHVtbi5cbiAgICAgICAgaWYgKCF0aGlzLmN1cnJlbnRTb3J0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNvcnRVc2luZ0N0cmwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc011bHRpU29ydEtleUN0cmwoKTtcbiAgICAgICAgLy8ga2VlcCB0cmFjayBvZiBsYXN0IHRpbWUgdGhlIG1vdmluZyBjaGFuZ2VkIGZsYWcgd2FzIHNldFxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnBhcmFtcy5jb2x1bW4sIENvbHVtbi5FVkVOVF9NT1ZJTkdfQ0hBTkdFRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMubGFzdE1vdmluZ0NoYW5nZWQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGFkZCB0aGUgZXZlbnQgb24gdGhlIGhlYWRlciwgc28gd2hlbiBjbGlja2VkLCB3ZSBkbyBzb3J0aW5nXG4gICAgICAgIGlmICh0aGlzLmVMYWJlbCkge1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lTGFiZWwsICdjbGljaycsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIC8vIHNvbWV0aW1lcyB3aGVuIG1vdmluZyBhIGNvbHVtbiB2aWEgZHJhZ2dpbmcsIHRoaXMgd2FzIGFsc28gZmlyaW5nIGEgY2xpY2tlZCBldmVudC5cbiAgICAgICAgICAgICAgICAvLyBoZXJlIGlzIGlzc3VlIHJhaXNlZCBieSB1c2VyOiBodHRwczovL2FnLWdyaWQuemVuZGVzay5jb20vYWdlbnQvdGlja2V0cy8xMDc2XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBjaGVjayBzdG9wcyBzb3J0IGlmIGEpIGNvbHVtbiBpcyBtb3Zpbmcgb3IgYikgY29sdW1uIG1vdmVkIGxlc3MgdGhhbiAyMDBtcyBhZ28gKHNvIGNhdGVycyBmb3IgcmFjZSBjb25kaXRpb24pXG4gICAgICAgICAgICAgICAgdmFyIG1vdmluZyA9IF90aGlzLnBhcmFtcy5jb2x1bW4uaXNNb3ZpbmcoKTtcbiAgICAgICAgICAgICAgICB2YXIgbm93VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICAgICAgICAgIC8vIHR5cGljYWxseSB0aGVyZSBpcyA8Mm1zIGlmIG1vdmluZyBmbGFnIHdhcyBzZXQgcmVjZW50bHksIGFzIGl0IHdvdWxkIGJlIGRvbmUgaW4gc2FtZSBWTSB0dXJuXG4gICAgICAgICAgICAgICAgdmFyIG1vdmVkUmVjZW50bHkgPSAobm93VGltZSAtIF90aGlzLmxhc3RNb3ZpbmdDaGFuZ2VkKSA8IDUwO1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW5Nb3ZpbmcgPSBtb3ZpbmcgfHwgbW92ZWRSZWNlbnRseTtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbk1vdmluZykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbXVsdGlTb3J0ID0gc29ydFVzaW5nQ3RybCA/IChldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkpIDogZXZlbnQuc2hpZnRLZXk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnBhcmFtcy5wcm9ncmVzc1NvcnQobXVsdGlTb3J0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb25Tb3J0aW5nQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWhlYWRlci1jZWxsLXNvcnRlZC1hc2MnLCBfdGhpcy5wYXJhbXMuY29sdW1uLmlzU29ydEFzY2VuZGluZygpKTtcbiAgICAgICAgICAgIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWhlYWRlci1jZWxsLXNvcnRlZC1kZXNjJywgX3RoaXMucGFyYW1zLmNvbHVtbi5pc1NvcnREZXNjZW5kaW5nKCkpO1xuICAgICAgICAgICAgX3RoaXMuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctaGVhZGVyLWNlbGwtc29ydGVkLW5vbmUnLCBfdGhpcy5wYXJhbXMuY29sdW1uLmlzU29ydE5vbmUoKSk7XG4gICAgICAgICAgICBpZiAoX3RoaXMucGFyYW1zLmNvbHVtbi5nZXRDb2xEZWYoKS5zaG93Um93R3JvdXApIHtcbiAgICAgICAgICAgICAgICB2YXIgc291cmNlQ29sdW1ucyA9IF90aGlzLmNvbHVtbk1vZGVsLmdldFNvdXJjZUNvbHVtbnNGb3JHcm91cENvbHVtbihfdGhpcy5wYXJhbXMuY29sdW1uKTtcbiAgICAgICAgICAgICAgICAvLyB0aGlzID09IGlzIGludGVudGlvbmFsLCBhcyBpdCBhbGxvd3MgbnVsbCBhbmQgdW5kZWZpbmVkIHRvIG1hdGNoLCB3aGljaCBhcmUgYm90aCB1bnNvcnRlZCBzdGF0ZXNcbiAgICAgICAgICAgICAgICB2YXIgc29ydERpcmVjdGlvbnNNYXRjaCA9IChfYSA9IHNvdXJjZUNvbHVtbnMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5ldmVyeShmdW5jdGlvbiAoc291cmNlQ29sKSB7IHJldHVybiBfdGhpcy5wYXJhbXMuY29sdW1uLmdldFNvcnQoKSA9PSBzb3VyY2VDb2wuZ2V0U29ydCgpOyB9KTtcbiAgICAgICAgICAgICAgICB2YXIgaXNNdWx0aVNvcnRpbmcgPSAhc29ydERpcmVjdGlvbnNNYXRjaDtcbiAgICAgICAgICAgICAgICBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1oZWFkZXItY2VsbC1zb3J0ZWQtbWl4ZWQnLCBpc011bHRpU29ydGluZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfU09SVF9DSEFOR0VELCBvblNvcnRpbmdDaGFuZ2VkKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIG9uU29ydGluZ0NoYW5nZWQpO1xuICAgIH07XG4gICAgSGVhZGVyQ29tcC5wcm90b3R5cGUuc2V0dXBGaWx0ZXJJY29uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuZUZpbHRlcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucGFyYW1zLmNvbHVtbiwgQ29sdW1uLkVWRU5UX0ZJTFRFUl9DSEFOR0VELCB0aGlzLm9uRmlsdGVyQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5vbkZpbHRlckNoYW5nZWQoKTtcbiAgICB9O1xuICAgIEhlYWRlckNvbXAucHJvdG90eXBlLm9uRmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZpbHRlclByZXNlbnQgPSB0aGlzLnBhcmFtcy5jb2x1bW4uaXNGaWx0ZXJBY3RpdmUoKTtcbiAgICAgICAgdGhpcy5lRmlsdGVyLmNsYXNzTGlzdC50b2dnbGUoJ2FnLWhpZGRlbicsICFmaWx0ZXJQcmVzZW50KTtcbiAgICB9O1xuICAgIEhlYWRlckNvbXAuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWNlbGwtbGFiZWwtY29udGFpbmVyXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgIDxzcGFuIHJlZj1cXFwiZU1lbnVcXFwiIGNsYXNzPVxcXCJhZy1oZWFkZXItaWNvbiBhZy1oZWFkZXItY2VsbC1tZW51LWJ1dHRvblxcXCIgYXJpYS1oaWRkZW49XFxcInRydWVcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZUxhYmVsXFxcIiBjbGFzcz1cXFwiYWctaGVhZGVyLWNlbGwtbGFiZWxcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxzcGFuIHJlZj1cXFwiZVRleHRcXFwiIGNsYXNzPVxcXCJhZy1oZWFkZXItY2VsbC10ZXh0XFxcIj48L3NwYW4+XFxuICAgICAgICAgICAgICAgIDxzcGFuIHJlZj1cXFwiZUZpbHRlclxcXCIgY2xhc3M9XFxcImFnLWhlYWRlci1pY29uIGFnLWhlYWRlci1sYWJlbC1pY29uIGFnLWZpbHRlci1pY29uXFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgICAgICA8YWctc29ydC1pbmRpY2F0b3IgcmVmPVxcXCJlU29ydEluZGljYXRvclxcXCI+PC9hZy1zb3J0LWluZGljYXRvcj5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkMjgoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NvcnRDb250cm9sbGVyJylcbiAgICBdLCBIZWFkZXJDb21wLnByb3RvdHlwZSwgXCJzb3J0Q29udHJvbGxlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjgoW1xuICAgICAgICBBdXRvd2lyZWQoJ21lbnVGYWN0b3J5JylcbiAgICBdLCBIZWFkZXJDb21wLnByb3RvdHlwZSwgXCJtZW51RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjgoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBIZWFkZXJDb21wLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjgoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUZpbHRlcicpXG4gICAgXSwgSGVhZGVyQ29tcC5wcm90b3R5cGUsIFwiZUZpbHRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjgoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVNvcnRJbmRpY2F0b3InKVxuICAgIF0sIEhlYWRlckNvbXAucHJvdG90eXBlLCBcImVTb3J0SW5kaWNhdG9yXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyOChbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlTWVudScpXG4gICAgXSwgSGVhZGVyQ29tcC5wcm90b3R5cGUsIFwiZU1lbnVcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI4KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VMYWJlbCcpXG4gICAgXSwgSGVhZGVyQ29tcC5wcm90b3R5cGUsIFwiZUxhYmVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyOChbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVGV4dCcpXG4gICAgXSwgSGVhZGVyQ29tcC5wcm90b3R5cGUsIFwiZVRleHRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI4KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0T3JkZXInKVxuICAgIF0sIEhlYWRlckNvbXAucHJvdG90eXBlLCBcImVTb3J0T3JkZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI4KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0QXNjJylcbiAgICBdLCBIZWFkZXJDb21wLnByb3RvdHlwZSwgXCJlU29ydEFzY1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjgoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVNvcnREZXNjJylcbiAgICBdLCBIZWFkZXJDb21wLnByb3RvdHlwZSwgXCJlU29ydERlc2NcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI4KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0TWl4ZWQnKVxuICAgIF0sIEhlYWRlckNvbXAucHJvdG90eXBlLCBcImVTb3J0TWl4ZWRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI4KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VTb3J0Tm9uZScpXG4gICAgXSwgSGVhZGVyQ29tcC5wcm90b3R5cGUsIFwiZVNvcnROb25lXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIEhlYWRlckNvbXA7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQyNyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEhlYWRlckdyb3VwQ29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMnIoSGVhZGVyR3JvdXBDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlckdyb3VwQ29tcCgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIEhlYWRlckdyb3VwQ29tcC5URU1QTEFURSkgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gdGhpcyBpcyBhIHVzZXIgY29tcG9uZW50LCBhbmQgSUNvbXBvbmVudCBoYXMgXCJwdWJsaWMgZGVzdHJveSgpXCIgYXMgcGFydCBvZiB0aGUgaW50ZXJmYWNlLlxuICAgIC8vIHNvIHdlIG5lZWQgdG8gb3ZlcnJpZGUgZGVzdHJveSgpIGp1c3QgdG8gbWFrZSB0aGUgbWV0aG9kIHB1YmxpYy5cbiAgICBIZWFkZXJHcm91cENvbXAucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDb21wLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB0aGlzLnBhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgdGhpcy5jaGVja1dhcm5pbmdzKCk7XG4gICAgICAgIHRoaXMuc2V0dXBMYWJlbCgpO1xuICAgICAgICB0aGlzLmFkZEdyb3VwRXhwYW5kSWNvbigpO1xuICAgICAgICB0aGlzLnNldHVwRXhwYW5kSWNvbnMoKTtcbiAgICB9O1xuICAgIEhlYWRlckdyb3VwQ29tcC5wcm90b3R5cGUuY2hlY2tXYXJuaW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHBhcmFtc0FueSA9IHRoaXMucGFyYW1zO1xuICAgICAgICBpZiAocGFyYW1zQW55LnRlbXBsYXRlKSB7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZV8xID0gXCJBRyBHcmlkOiBBIHRlbXBsYXRlIHdhcyBwcm92aWRlZCBmb3IgSGVhZGVyIEdyb3VwIENvbXAgLSB0ZW1wbGF0ZXMgYXJlIG9ubHkgc3VwcG9ydGVkIGZvciBIZWFkZXIgQ29tcHMgKG5vdCBncm91cHMpXCI7XG4gICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKG1lc3NhZ2VfMSk7IH0sICdIZWFkZXJHcm91cENvbXAudGVtcGxhdGVOb3RTdXBwb3J0ZWQnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDb21wLnByb3RvdHlwZS5zZXR1cEV4cGFuZEljb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFkZEluSWNvbihcImNvbHVtbkdyb3VwT3BlbmVkXCIsIFwiYWdPcGVuZWRcIik7XG4gICAgICAgIHRoaXMuYWRkSW5JY29uKFwiY29sdW1uR3JvdXBDbG9zZWRcIiwgXCJhZ0Nsb3NlZFwiKTtcbiAgICAgICAgdmFyIGV4cGFuZEFjdGlvbiA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKGlzU3RvcFByb3BhZ2F0aW9uRm9yQWdHcmlkKGV2ZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBuZXdFeHBhbmRlZFZhbHVlID0gIV90aGlzLnBhcmFtcy5jb2x1bW5Hcm91cC5pc0V4cGFuZGVkKCk7XG4gICAgICAgICAgICBfdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5Hcm91cE9wZW5lZChfdGhpcy5wYXJhbXMuY29sdW1uR3JvdXAuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCgpLCBuZXdFeHBhbmRlZFZhbHVlLCBcInVpQ29sdW1uRXhwYW5kZWRcIik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkVG91Y2hBbmRDbGlja0xpc3RlbmVycyh0aGlzLmVDbG9zZUljb24sIGV4cGFuZEFjdGlvbik7XG4gICAgICAgIHRoaXMuYWRkVG91Y2hBbmRDbGlja0xpc3RlbmVycyh0aGlzLmVPcGVuSWNvbiwgZXhwYW5kQWN0aW9uKTtcbiAgICAgICAgdmFyIHN0b3BQcm9wYWdhdGlvbkFjdGlvbiA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgc3RvcFByb3BhZ2F0aW9uRm9yQWdHcmlkKGV2ZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gYWRkaW5nIHN0b3BQcm9wYWdhdGlvbiB0byB0aGUgZG91YmxlIGNsaWNrIGZvciB0aGUgaWNvbnMgcHJldmVudHMgZG91YmxlIGNsaWNrIGFjdGlvbiBoYXBwZW5pbmdcbiAgICAgICAgLy8gd2hlbiB0aGUgaWNvbnMgYXJlIGNsaWNrZWQuIGlmIHRoZSBpY29ucyBhcmUgZG91YmxlIGNsaWNrZWQsIHRoZW4gdGhlIGdyb3VwcyBzaG91bGQgb3BlbiBhbmRcbiAgICAgICAgLy8gdGhlbiBjbG9zZSBhZ2FpbiBzdHJhaWdodCBhd2F5LiBpZiB3ZSBhbHNvIGxpc3RlbmVkIHRvIGRvdWJsZSBjbGljaywgdGhlbiB0aGUgZ3JvdXAgd291bGQgb3BlbixcbiAgICAgICAgLy8gY2xvc2UsIHRoZW4gb3Blbiwgd2hpY2ggaXMgbm90IHdoYXQgd2Ugd2FudC4gZG91YmxlIGNsaWNrIHNob3VsZCBvbmx5IGFjdGlvbiBpZiB0aGUgdXNlciBkb3VibGVcbiAgICAgICAgLy8gY2xpY2tzIG91dHNpZGUgb2YgdGhlIGljb25zLlxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVDbG9zZUljb24sIFwiZGJsY2xpY2tcIiwgc3RvcFByb3BhZ2F0aW9uQWN0aW9uKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lT3Blbkljb24sIFwiZGJsY2xpY2tcIiwgc3RvcFByb3BhZ2F0aW9uQWN0aW9uKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5nZXRHdWkoKSwgXCJkYmxjbGlja1wiLCBleHBhbmRBY3Rpb24pO1xuICAgICAgICB0aGlzLnVwZGF0ZUljb25WaXNpYmlsaXR5KCk7XG4gICAgICAgIHZhciBwcm92aWRlZENvbHVtbkdyb3VwID0gdGhpcy5wYXJhbXMuY29sdW1uR3JvdXAuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCgpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihwcm92aWRlZENvbHVtbkdyb3VwLCBQcm92aWRlZENvbHVtbkdyb3VwLkVWRU5UX0VYUEFOREVEX0NIQU5HRUQsIHRoaXMudXBkYXRlSWNvblZpc2liaWxpdHkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHByb3ZpZGVkQ29sdW1uR3JvdXAsIFByb3ZpZGVkQ29sdW1uR3JvdXAuRVZFTlRfRVhQQU5EQUJMRV9DSEFOR0VELCB0aGlzLnVwZGF0ZUljb25WaXNpYmlsaXR5LmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDb21wLnByb3RvdHlwZS5hZGRUb3VjaEFuZENsaWNrTGlzdGVuZXJzID0gZnVuY3Rpb24gKGVFbGVtZW50LCBhY3Rpb24pIHtcbiAgICAgICAgdmFyIHRvdWNoTGlzdGVuZXIgPSBuZXcgVG91Y2hMaXN0ZW5lcihlRWxlbWVudCwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRvdWNoTGlzdGVuZXIsIFRvdWNoTGlzdGVuZXIuRVZFTlRfVEFQLCBhY3Rpb24pO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRvdWNoTGlzdGVuZXIuZGVzdHJveSgpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZUVsZW1lbnQsIFwiY2xpY2tcIiwgYWN0aW9uKTtcbiAgICB9O1xuICAgIEhlYWRlckdyb3VwQ29tcC5wcm90b3R5cGUudXBkYXRlSWNvblZpc2liaWxpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb2x1bW5Hcm91cCA9IHRoaXMucGFyYW1zLmNvbHVtbkdyb3VwO1xuICAgICAgICBpZiAoY29sdW1uR3JvdXAuaXNFeHBhbmRhYmxlKCkpIHtcbiAgICAgICAgICAgIHZhciBleHBhbmRlZCA9IHRoaXMucGFyYW1zLmNvbHVtbkdyb3VwLmlzRXhwYW5kZWQoKTtcbiAgICAgICAgICAgIHNldERpc3BsYXllZCh0aGlzLmVPcGVuSWNvbiwgZXhwYW5kZWQpO1xuICAgICAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZUNsb3NlSWNvbiwgIWV4cGFuZGVkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldERpc3BsYXllZCh0aGlzLmVPcGVuSWNvbiwgZmFsc2UpO1xuICAgICAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZUNsb3NlSWNvbiwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENvbXAucHJvdG90eXBlLmFkZEluSWNvbiA9IGZ1bmN0aW9uIChpY29uTmFtZSwgcmVmTmFtZSkge1xuICAgICAgICB2YXIgZUljb24gPSBjcmVhdGVJY29uTm9TcGFuKGljb25OYW1lLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCk7XG4gICAgICAgIGlmIChlSWNvbikge1xuICAgICAgICAgICAgdGhpcy5nZXRSZWZFbGVtZW50KHJlZk5hbWUpLmFwcGVuZENoaWxkKGVJY29uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDb21wLnByb3RvdHlwZS5hZGRHcm91cEV4cGFuZEljb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5wYXJhbXMuY29sdW1uR3JvdXAuaXNFeHBhbmRhYmxlKCkpIHtcbiAgICAgICAgICAgIHNldERpc3BsYXllZCh0aGlzLmVPcGVuSWNvbiwgZmFsc2UpO1xuICAgICAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZUNsb3NlSWNvbiwgZmFsc2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENvbXAucHJvdG90eXBlLnNldHVwTGFiZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIG5vIHJlbmRlcmVyLCBkZWZhdWx0IHRleHQgcmVuZGVyXG4gICAgICAgIHZhciBkaXNwbGF5TmFtZSA9IHRoaXMucGFyYW1zLmRpc3BsYXlOYW1lO1xuICAgICAgICBpZiAoZXhpc3RzKGRpc3BsYXlOYW1lKSkge1xuICAgICAgICAgICAgdmFyIGRpc3BsYXlOYW1lU2FuaXRpc2VkID0gZXNjYXBlU3RyaW5nKGRpc3BsYXlOYW1lKTtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVmRWxlbWVudCgnYWdMYWJlbCcpLmlubmVySFRNTCA9IGRpc3BsYXlOYW1lU2FuaXRpc2VkO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENvbXAuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWhlYWRlci1ncm91cC1jZWxsLWxhYmVsXFxcIiByZWY9XFxcImFnQ29udGFpbmVyXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgIDxzcGFuIHJlZj1cXFwiYWdMYWJlbFxcXCIgY2xhc3M9XFxcImFnLWhlYWRlci1ncm91cC10ZXh0XFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8c3BhbiByZWY9XFxcImFnT3BlbmVkXFxcIiBjbGFzcz1cXFwiYWctaGVhZGVyLWljb24gYWctaGVhZGVyLWV4cGFuZC1pY29uIGFnLWhlYWRlci1leHBhbmQtaWNvbi1leHBhbmRlZFxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDxzcGFuIHJlZj1cXFwiYWdDbG9zZWRcXFwiIGNsYXNzPVxcXCJhZy1oZWFkZXItaWNvbiBhZy1oZWFkZXItZXhwYW5kLWljb24gYWctaGVhZGVyLWV4cGFuZC1pY29uLWNvbGxhcHNlZFxcXCI+PC9zcGFuPlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgX19kZWNvcmF0ZSQyNyhbXG4gICAgICAgIEF1dG93aXJlZChcImNvbHVtbk1vZGVsXCIpXG4gICAgXSwgSGVhZGVyR3JvdXBDb21wLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjcoW1xuICAgICAgICBSZWZTZWxlY3RvcihcImFnT3BlbmVkXCIpXG4gICAgXSwgSGVhZGVyR3JvdXBDb21wLnByb3RvdHlwZSwgXCJlT3Blbkljb25cIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDI3KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoXCJhZ0Nsb3NlZFwiKVxuICAgIF0sIEhlYWRlckdyb3VwQ29tcC5wcm90b3R5cGUsIFwiZUNsb3NlSWNvblwiLCB2b2lkIDApO1xuICAgIHJldHVybiBIZWFkZXJHcm91cENvbXA7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJxID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgUG9wdXBDb21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJxKFBvcHVwQ29tcG9uZW50LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFBvcHVwQ29tcG9uZW50KCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFBvcHVwQ29tcG9uZW50LnByb3RvdHlwZS5pc1BvcHVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIFBvcHVwQ29tcG9uZW50LnByb3RvdHlwZS5zZXRQYXJlbnRDb21wb25lbnQgPSBmdW5jdGlvbiAoY29udGFpbmVyKSB7XG4gICAgICAgIGNvbnRhaW5lci5hZGRDc3NDbGFzcygnYWctaGFzLXBvcHVwJyk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuc2V0UGFyZW50Q29tcG9uZW50LmNhbGwodGhpcywgY29udGFpbmVyKTtcbiAgICB9O1xuICAgIFBvcHVwQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyZW50Q29tcCA9IHRoaXMucGFyZW50Q29tcG9uZW50O1xuICAgICAgICB2YXIgaGFzUGFyZW50ID0gcGFyZW50Q29tcCAmJiBwYXJlbnRDb21wLmlzQWxpdmUoKTtcbiAgICAgICAgaWYgKGhhc1BhcmVudCkge1xuICAgICAgICAgICAgcGFyZW50Q29tcC5nZXRHdWkoKS5jbGFzc0xpc3QucmVtb3ZlKCdhZy1oYXMtcG9wdXAnKTtcbiAgICAgICAgfVxuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIHJldHVybiBQb3B1cENvbXBvbmVudDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMnAgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDI2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgTGFyZ2VUZXh0Q2VsbEVkaXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMnAoTGFyZ2VUZXh0Q2VsbEVkaXRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBMYXJnZVRleHRDZWxsRWRpdG9yKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgTGFyZ2VUZXh0Q2VsbEVkaXRvci5URU1QTEFURSkgfHwgdGhpcztcbiAgICB9XG4gICAgTGFyZ2VUZXh0Q2VsbEVkaXRvci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5wYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIHRoaXMuZm9jdXNBZnRlckF0dGFjaGVkID0gcGFyYW1zLmNlbGxTdGFydGVkRWRpdDtcbiAgICAgICAgdGhpcy5lVGV4dEFyZWFcbiAgICAgICAgICAgIC5zZXRNYXhMZW5ndGgocGFyYW1zLm1heExlbmd0aCB8fCAyMDApXG4gICAgICAgICAgICAuc2V0Q29scyhwYXJhbXMuY29scyB8fCA2MClcbiAgICAgICAgICAgIC5zZXRSb3dzKHBhcmFtcy5yb3dzIHx8IDEwKTtcbiAgICAgICAgaWYgKGV4aXN0cyhwYXJhbXMudmFsdWUpKSB7XG4gICAgICAgICAgICB0aGlzLmVUZXh0QXJlYS5zZXRWYWx1ZShwYXJhbXMudmFsdWUudG9TdHJpbmcoKSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZGRHdWlFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5vbktleURvd24uYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBMYXJnZVRleHRDZWxsRWRpdG9yLnByb3RvdHlwZS5vbktleURvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGtleSA9IGV2ZW50LmtleTtcbiAgICAgICAgaWYgKGtleSA9PT0gS2V5Q29kZS5MRUZUIHx8XG4gICAgICAgICAgICBrZXkgPT09IEtleUNvZGUuVVAgfHxcbiAgICAgICAgICAgIGtleSA9PT0gS2V5Q29kZS5SSUdIVCB8fFxuICAgICAgICAgICAga2V5ID09PSBLZXlDb2RlLkRPV04gfHxcbiAgICAgICAgICAgIChldmVudC5zaGlmdEtleSAmJiBrZXkgPT09IEtleUNvZGUuRU5URVIpKSB7IC8vIHNoaWZ0K2VudGVyIGFsbG93cyBmb3IgbmV3bGluZXNcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBMYXJnZVRleHRDZWxsRWRpdG9yLnByb3RvdHlwZS5hZnRlckd1aUF0dGFjaGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdGhpcy5lVGV4dEFyZWEuc2V0SW5wdXRBcmlhTGFiZWwodHJhbnNsYXRlKCdhcmlhSW5wdXRFZGl0b3InLCAnSW5wdXQgRWRpdG9yJykpO1xuICAgICAgICBpZiAodGhpcy5mb2N1c0FmdGVyQXR0YWNoZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZVRleHRBcmVhLmdldEZvY3VzYWJsZUVsZW1lbnQoKS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBMYXJnZVRleHRDZWxsRWRpdG9yLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyYW1zLnBhcnNlVmFsdWUodGhpcy5lVGV4dEFyZWEuZ2V0VmFsdWUoKSk7XG4gICAgfTtcbiAgICBMYXJnZVRleHRDZWxsRWRpdG9yLlRFTVBMQVRFID0gXCI8ZGl2IGNsYXNzPVxcXCJhZy1sYXJnZS10ZXh0XFxcIiB0YWJpbmRleD1cXFwiMFxcXCI+XFxuICAgICAgICAgICAgPGFnLWlucHV0LXRleHQtYXJlYSByZWY9XFxcImVUZXh0QXJlYVxcXCIgY2xhc3M9XFxcImFnLWxhcmdlLXRleHQtaW5wdXRcXFwiPjwvYWctaW5wdXQtdGV4dC1hcmVhPlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgX19kZWNvcmF0ZSQyNihbXG4gICAgICAgIFJlZlNlbGVjdG9yKFwiZVRleHRBcmVhXCIpXG4gICAgXSwgTGFyZ2VUZXh0Q2VsbEVkaXRvci5wcm90b3R5cGUsIFwiZVRleHRBcmVhXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIExhcmdlVGV4dENlbGxFZGl0b3I7XG59KFBvcHVwQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMm8gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDI1ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgU2VsZWN0Q2VsbEVkaXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMm8oU2VsZWN0Q2VsbEVkaXRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTZWxlY3RDZWxsRWRpdG9yKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCAnPGRpdiBjbGFzcz1cImFnLWNlbGwtZWRpdC13cmFwcGVyXCI+PGFnLXNlbGVjdCBjbGFzcz1cImFnLWNlbGwtZWRpdG9yXCIgcmVmPVwiZVNlbGVjdFwiPjwvYWctc2VsZWN0PjwvZGl2PicpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnN0YXJ0ZWRCeUVudGVyID0gZmFsc2U7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU2VsZWN0Q2VsbEVkaXRvci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5mb2N1c0FmdGVyQXR0YWNoZWQgPSBwYXJhbXMuY2VsbFN0YXJ0ZWRFZGl0O1xuICAgICAgICBpZiAobWlzc2luZyhwYXJhbXMudmFsdWVzKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBubyB2YWx1ZXMgZm91bmQgZm9yIHNlbGVjdCBjZWxsRWRpdG9yJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGFydGVkQnlFbnRlciA9IHBhcmFtcy5ldmVudEtleSAhPSBudWxsID8gcGFyYW1zLmV2ZW50S2V5ID09PSBLZXlDb2RlLkVOVEVSIDogZmFsc2U7XG4gICAgICAgIHZhciBoYXNWYWx1ZSA9IGZhbHNlO1xuICAgICAgICBwYXJhbXMudmFsdWVzLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgb3B0aW9uID0geyB2YWx1ZTogdmFsdWUgfTtcbiAgICAgICAgICAgIHZhciB2YWx1ZUZvcm1hdHRlZCA9IF90aGlzLnZhbHVlRm9ybWF0dGVyU2VydmljZS5mb3JtYXRWYWx1ZShwYXJhbXMuY29sdW1uLCBudWxsLCB2YWx1ZSk7XG4gICAgICAgICAgICB2YXIgdmFsdWVGb3JtYXR0ZWRFeGl0cyA9IHZhbHVlRm9ybWF0dGVkICE9PSBudWxsICYmIHZhbHVlRm9ybWF0dGVkICE9PSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBvcHRpb24udGV4dCA9IHZhbHVlRm9ybWF0dGVkRXhpdHMgPyB2YWx1ZUZvcm1hdHRlZCA6IHZhbHVlO1xuICAgICAgICAgICAgX3RoaXMuZVNlbGVjdC5hZGRPcHRpb24ob3B0aW9uKTtcbiAgICAgICAgICAgIGhhc1ZhbHVlID0gaGFzVmFsdWUgfHwgcGFyYW1zLnZhbHVlID09PSB2YWx1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChoYXNWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5lU2VsZWN0LnNldFZhbHVlKHBhcmFtcy52YWx1ZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocGFyYW1zLnZhbHVlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuZVNlbGVjdC5zZXRWYWx1ZShwYXJhbXMudmFsdWVzWzBdLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBkb24ndCB3YW50IHRvIGFkZCB0aGlzIGlmIGZ1bGwgcm93IGVkaXRpbmcsIG90aGVyd2lzZSBzZWxlY3Rpbmcgd2lsbCBzdG9wIHRoZVxuICAgICAgICAvLyBmdWxsIHJvdyBlZGl0aW5nLlxuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRnVsbFJvd0VkaXQoKSkge1xuICAgICAgICAgICAgdGhpcy5lU2VsZWN0Lm9uVmFsdWVDaGFuZ2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gcGFyYW1zLnN0b3BFZGl0aW5nKCk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTZWxlY3RDZWxsRWRpdG9yLnByb3RvdHlwZS5hZnRlckd1aUF0dGFjaGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5mb2N1c0FmdGVyQXR0YWNoZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZVNlbGVjdC5nZXRGb2N1c2FibGVFbGVtZW50KCkuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zdGFydGVkQnlFbnRlcikge1xuICAgICAgICAgICAgdGhpcy5lU2VsZWN0LnNob3dQaWNrZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2VsZWN0Q2VsbEVkaXRvci5wcm90b3R5cGUuZm9jdXNJbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5lU2VsZWN0LmdldEZvY3VzYWJsZUVsZW1lbnQoKS5mb2N1cygpO1xuICAgIH07XG4gICAgU2VsZWN0Q2VsbEVkaXRvci5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVTZWxlY3QuZ2V0VmFsdWUoKTtcbiAgICB9O1xuICAgIFNlbGVjdENlbGxFZGl0b3IucHJvdG90eXBlLmlzUG9wdXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMjUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlRm9ybWF0dGVyU2VydmljZScpXG4gICAgXSwgU2VsZWN0Q2VsbEVkaXRvci5wcm90b3R5cGUsIFwidmFsdWVGb3JtYXR0ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyNShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlU2VsZWN0JylcbiAgICBdLCBTZWxlY3RDZWxsRWRpdG9yLnByb3RvdHlwZSwgXCJlU2VsZWN0XCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIFNlbGVjdENlbGxFZGl0b3I7XG59KFBvcHVwQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMm4gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBQb3B1cFNlbGVjdENlbGxFZGl0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJuKFBvcHVwU2VsZWN0Q2VsbEVkaXRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBQb3B1cFNlbGVjdENlbGxFZGl0b3IoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZSBQb3B1cFNlbGVjdENlbGxFZGl0b3IgKGFnUG9wdXBTZWxlY3RDZWxsRWRpdG9yKSBpcyBkZXByZWNhdGVkLiBJbnN0ZWFkIHVzZSB7Y2VsbEVkaXRvcjogXCJhZ1NlbGVjdENlbGxFZGl0b3JcIiwgY2VsbEVkaXRvclBvcHVwOiB0cnVlfSAnKTsgfSwgJ1BvcHVwU2VsZWN0Q2VsbEVkaXRvci5kZXByZWNhdGVkJyk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUG9wdXBTZWxlY3RDZWxsRWRpdG9yLnByb3RvdHlwZS5pc1BvcHVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIHJldHVybiBQb3B1cFNlbGVjdENlbGxFZGl0b3I7XG59KFNlbGVjdENlbGxFZGl0b3IpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQybSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMjQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBUZXh0Q2VsbEVkaXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMm0oVGV4dENlbGxFZGl0b3IsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVGV4dENlbGxFZGl0b3IoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBUZXh0Q2VsbEVkaXRvci5URU1QTEFURSkgfHwgdGhpcztcbiAgICB9XG4gICAgVGV4dENlbGxFZGl0b3IucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICB2YXIgZUlucHV0ID0gdGhpcy5lSW5wdXQ7XG4gICAgICAgIHZhciBzdGFydFZhbHVlO1xuICAgICAgICAvLyBjZWxsU3RhcnRlZEVkaXQgaXMgb25seSBmYWxzZSBpZiB3ZSBhcmUgZG9pbmcgZnVsbFJvdyBlZGl0aW5nXG4gICAgICAgIGlmIChwYXJhbXMuY2VsbFN0YXJ0ZWRFZGl0KSB7XG4gICAgICAgICAgICB0aGlzLmZvY3VzQWZ0ZXJBdHRhY2hlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAocGFyYW1zLmV2ZW50S2V5ID09PSBLZXlDb2RlLkJBQ0tTUEFDRSB8fCBwYXJhbXMuZXZlbnRLZXkgPT09IEtleUNvZGUuREVMRVRFKSB7XG4gICAgICAgICAgICAgICAgc3RhcnRWYWx1ZSA9ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocGFyYW1zLmNoYXJQcmVzcykge1xuICAgICAgICAgICAgICAgIHN0YXJ0VmFsdWUgPSBwYXJhbXMuY2hhclByZXNzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RhcnRWYWx1ZSA9IHRoaXMuZ2V0U3RhcnRWYWx1ZShwYXJhbXMpO1xuICAgICAgICAgICAgICAgIGlmIChwYXJhbXMuZXZlbnRLZXkgIT09IEtleUNvZGUuRjIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRBbGxPbkZvY3VzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmZvY3VzQWZ0ZXJBdHRhY2hlZCA9IGZhbHNlO1xuICAgICAgICAgICAgc3RhcnRWYWx1ZSA9IHRoaXMuZ2V0U3RhcnRWYWx1ZShwYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGFydFZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgIGVJbnB1dC5zZXRWYWx1ZShzdGFydFZhbHVlLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlSW5wdXQuZ2V0R3VpKCksICdrZXlkb3duJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gZXZlbnQua2V5O1xuICAgICAgICAgICAgaWYgKGtleSA9PT0gS2V5Q29kZS5QQUdFX1VQIHx8IGtleSA9PT0gS2V5Q29kZS5QQUdFX0RPV04pIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFRleHRDZWxsRWRpdG9yLnByb3RvdHlwZS5hZnRlckd1aUF0dGFjaGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIGVJbnB1dCA9IHRoaXMuZUlucHV0O1xuICAgICAgICBlSW5wdXQuc2V0SW5wdXRBcmlhTGFiZWwodHJhbnNsYXRlKCdhcmlhSW5wdXRFZGl0b3InLCAnSW5wdXQgRWRpdG9yJykpO1xuICAgICAgICBpZiAoIXRoaXMuZm9jdXNBZnRlckF0dGFjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gQWRkZWQgZm9yIEFHLTMyMzguIFdlIGNhbid0IHJlbW92ZSB0aGlzIGV4cGxpY2l0IGZvY3VzKCkgYmVjYXVzZSBDaHJvbWUgcmVxdWlyZXMgYW4gaW5wdXRcbiAgICAgICAgLy8gdG8gYmUgZm9jdXNlZCBiZWZvcmUgc2V0U2VsZWN0aW9uUmFuZ2Ugd2lsbCB3b3JrLiBCdXQgaXQgdHJpZ2dlcnMgYSBidWcgaW4gU2FmYXJpIHdoZXJlXG4gICAgICAgIC8vIGV4cGxpY2l0bHkgZm9jdXNpbmcgdGhlbiBibHVycmluZyBhbiBlbXB0eSBmaWVsZCB3aWxsIGNhdXNlIHRoZSBwYXJlbnQgY29udGFpbmVyIHRvIHNjcm9sbC5cbiAgICAgICAgaWYgKCFpc0Jyb3dzZXJTYWZhcmkoKSkge1xuICAgICAgICAgICAgZUlucHV0LmdldEZvY3VzYWJsZUVsZW1lbnQoKS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbnB1dEVsID0gZUlucHV0LmdldElucHV0RWxlbWVudCgpO1xuICAgICAgICBpZiAodGhpcy5oaWdobGlnaHRBbGxPbkZvY3VzKSB7XG4gICAgICAgICAgICBpbnB1dEVsLnNlbGVjdCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gd2hlbiB3ZSBzdGFydGVkIGVkaXRpbmcsIHdlIHdhbnQgdGhlIGNhcmV0IGF0IHRoZSBlbmQsIG5vdCB0aGUgc3RhcnQuXG4gICAgICAgICAgICAvLyB0aGlzIGNvbWVzIGludG8gcGxheSBpbiB0d28gc2NlbmFyaW9zOlxuICAgICAgICAgICAgLy8gICBhKSB3aGVuIHVzZXIgaGl0cyBGMlxuICAgICAgICAgICAgLy8gICBiKSB3aGVuIHVzZXIgaGl0cyBhIHByaW50YWJsZSBjaGFyYWN0ZXJcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IGVJbnB1dC5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgdmFyIGxlbiA9IChleGlzdHModmFsdWUpICYmIHZhbHVlLmxlbmd0aCkgfHwgMDtcbiAgICAgICAgICAgIGlmIChsZW4pIHtcbiAgICAgICAgICAgICAgICBpbnB1dEVsLnNldFNlbGVjdGlvblJhbmdlKGxlbiwgbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZ2V0cyBjYWxsZWQgd2hlbiB0YWJiaW5nIHRyb3VnaCBjZWxscyBhbmQgaW4gZnVsbCByb3cgZWRpdCBtb2RlXG4gICAgVGV4dENlbGxFZGl0b3IucHJvdG90eXBlLmZvY3VzSW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlSW5wdXQgPSB0aGlzLmVJbnB1dDtcbiAgICAgICAgdmFyIGZvY3VzRWwgPSBlSW5wdXQuZ2V0Rm9jdXNhYmxlRWxlbWVudCgpO1xuICAgICAgICB2YXIgaW5wdXRFbCA9IGVJbnB1dC5nZXRJbnB1dEVsZW1lbnQoKTtcbiAgICAgICAgZm9jdXNFbC5mb2N1cygpO1xuICAgICAgICBpbnB1dEVsLnNlbGVjdCgpO1xuICAgIH07XG4gICAgVGV4dENlbGxFZGl0b3IucHJvdG90eXBlLmdldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZUlucHV0ID0gdGhpcy5lSW5wdXQ7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmFtcy5wYXJzZVZhbHVlKGVJbnB1dC5nZXRWYWx1ZSgpKTtcbiAgICB9O1xuICAgIFRleHRDZWxsRWRpdG9yLnByb3RvdHlwZS5nZXRTdGFydFZhbHVlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgZm9ybWF0VmFsdWUgPSBwYXJhbXMudXNlRm9ybWF0dGVyIHx8IHBhcmFtcy5jb2x1bW4uZ2V0Q29sRGVmKCkucmVmRGF0YTtcbiAgICAgICAgcmV0dXJuIGZvcm1hdFZhbHVlID8gcGFyYW1zLmZvcm1hdFZhbHVlKHBhcmFtcy52YWx1ZSkgOiBwYXJhbXMudmFsdWU7XG4gICAgfTtcbiAgICBUZXh0Q2VsbEVkaXRvci5wcm90b3R5cGUuaXNQb3B1cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgVGV4dENlbGxFZGl0b3IuVEVNUExBVEUgPSAnPGRpdiBjbGFzcz1cImFnLWNlbGwtZWRpdC13cmFwcGVyXCI+PGFnLWlucHV0LXRleHQtZmllbGQgY2xhc3M9XCJhZy1jZWxsLWVkaXRvclwiIHJlZj1cImVJbnB1dFwiPjwvYWctaW5wdXQtdGV4dC1maWVsZD48L2Rpdj4nO1xuICAgIF9fZGVjb3JhdGUkMjQoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUlucHV0JylcbiAgICBdLCBUZXh0Q2VsbEVkaXRvci5wcm90b3R5cGUsIFwiZUlucHV0XCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIFRleHRDZWxsRWRpdG9yO1xufShQb3B1cENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJsID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgUG9wdXBUZXh0Q2VsbEVkaXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmwoUG9wdXBUZXh0Q2VsbEVkaXRvciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBQb3B1cFRleHRDZWxsRWRpdG9yKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBUaGUgUG9wdXBUZXh0Q2VsbEVkaXRvciAoYWdQb3B1cFRleHRDZWxsRWRpdG9yKSBpcyBkZXByZWNhdGVkLiBJbnN0ZWFkIHVzZSB7Y2VsbEVkaXRvcjogXCJhZ1RleHRDZWxsRWRpdG9yXCIsIGNlbGxFZGl0b3JQb3B1cDogdHJ1ZX0gJyk7IH0sICdQb3B1cFRleHRDZWxsRWRpdG9yLmRlcHJlY2F0ZWQnKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBQb3B1cFRleHRDZWxsRWRpdG9yLnByb3RvdHlwZS5pc1BvcHVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIHJldHVybiBQb3B1cFRleHRDZWxsRWRpdG9yO1xufShUZXh0Q2VsbEVkaXRvcikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJrID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQyMyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEFSUk9XX1VQID0gJ1xcdTIxOTEnO1xudmFyIEFSUk9XX0RPV04gPSAnXFx1MjE5Myc7XG52YXIgQW5pbWF0ZVNob3dDaGFuZ2VDZWxsUmVuZGVyZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJrKEFuaW1hdGVTaG93Q2hhbmdlQ2VsbFJlbmRlcmVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFuaW1hdGVTaG93Q2hhbmdlQ2VsbFJlbmRlcmVyKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlci5URU1QTEFURSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucmVmcmVzaENvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgLy8gdGhpcy5wYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIHRoaXMuZVZhbHVlID0gdGhpcy5xdWVyeUZvckh0bWxFbGVtZW50KCcuYWctdmFsdWUtY2hhbmdlLXZhbHVlJyk7XG4gICAgICAgIHRoaXMuZURlbHRhID0gdGhpcy5xdWVyeUZvckh0bWxFbGVtZW50KCcuYWctdmFsdWUtY2hhbmdlLWRlbHRhJyk7XG4gICAgICAgIHRoaXMucmVmcmVzaChwYXJhbXMpO1xuICAgIH07XG4gICAgQW5pbWF0ZVNob3dDaGFuZ2VDZWxsUmVuZGVyZXIucHJvdG90eXBlLnNob3dEZWx0YSA9IGZ1bmN0aW9uIChwYXJhbXMsIGRlbHRhKSB7XG4gICAgICAgIHZhciBhYnNEZWx0YSA9IE1hdGguYWJzKGRlbHRhKTtcbiAgICAgICAgdmFyIHZhbHVlRm9ybWF0dGVkID0gcGFyYW1zLmZvcm1hdFZhbHVlKGFic0RlbHRhKTtcbiAgICAgICAgdmFyIHZhbHVlVG9Vc2UgPSBleGlzdHModmFsdWVGb3JtYXR0ZWQpID8gdmFsdWVGb3JtYXR0ZWQgOiBhYnNEZWx0YTtcbiAgICAgICAgdmFyIGRlbHRhVXAgPSAoZGVsdGEgPj0gMCk7XG4gICAgICAgIGlmIChkZWx0YVVwKSB7XG4gICAgICAgICAgICB0aGlzLmVEZWx0YS5pbm5lckhUTUwgPSBBUlJPV19VUCArIHZhbHVlVG9Vc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBiZWNhdXNlIG5lZ2F0aXZlLCB1c2UgQUJTIHRvIHJlbW92ZSBzaWduXG4gICAgICAgICAgICB0aGlzLmVEZWx0YS5pbm5lckhUTUwgPSBBUlJPV19ET1dOICsgdmFsdWVUb1VzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVEZWx0YS5jbGFzc0xpc3QudG9nZ2xlKCdhZy12YWx1ZS1jaGFuZ2UtZGVsdGEtdXAnLCBkZWx0YVVwKTtcbiAgICAgICAgdGhpcy5lRGVsdGEuY2xhc3NMaXN0LnRvZ2dsZSgnYWctdmFsdWUtY2hhbmdlLWRlbHRhLWRvd24nLCAhZGVsdGFVcCk7XG4gICAgfTtcbiAgICBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlci5wcm90b3R5cGUuc2V0VGltZXJUb1JlbW92ZURlbHRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyB0aGUgcmVmcmVzaENvdW50IG1ha2VzIHN1cmUgdGhhdCBpZiB0aGUgdmFsdWUgdXBkYXRlcyBhZ2FpbiB3aGlsZVxuICAgICAgICAvLyB0aGUgYmVsb3cgdGltZXIgaXMgd2FpdGluZywgdGhlbiB0aGUgYmVsb3cgdGltZXIgd2lsbCByZWFsaXNlIGl0XG4gICAgICAgIC8vIGlzIG5vdCB0aGUgbW9zdCByZWNlbnQgYW5kIHdpbGwgbm90IHRyeSB0byByZW1vdmUgdGhlIGRlbHRhIHZhbHVlLlxuICAgICAgICB0aGlzLnJlZnJlc2hDb3VudCsrO1xuICAgICAgICB2YXIgcmVmcmVzaENvdW50Q29weSA9IHRoaXMucmVmcmVzaENvdW50O1xuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAocmVmcmVzaENvdW50Q29weSA9PT0gX3RoaXMucmVmcmVzaENvdW50KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGlkZURlbHRhVmFsdWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgMjAwMCk7XG4gICAgfTtcbiAgICBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlci5wcm90b3R5cGUuaGlkZURlbHRhVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZVZhbHVlLmNsYXNzTGlzdC5yZW1vdmUoJ2FnLXZhbHVlLWNoYW5nZS12YWx1ZS1oaWdobGlnaHQnKTtcbiAgICAgICAgY2xlYXJFbGVtZW50KHRoaXMuZURlbHRhKTtcbiAgICB9O1xuICAgIEFuaW1hdGVTaG93Q2hhbmdlQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgdmFsdWUgPSBwYXJhbXMudmFsdWU7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdGhpcy5sYXN0VmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhpc3RzKHBhcmFtcy52YWx1ZUZvcm1hdHRlZCkpIHtcbiAgICAgICAgICAgIHRoaXMuZVZhbHVlLmlubmVySFRNTCA9IHBhcmFtcy52YWx1ZUZvcm1hdHRlZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChleGlzdHMocGFyYW1zLnZhbHVlKSkge1xuICAgICAgICAgICAgdGhpcy5lVmFsdWUuaW5uZXJIVE1MID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjbGVhckVsZW1lbnQodGhpcy5lVmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIGRvbid0IHNob3cgdGhlIGRlbHRhIGlmIHdlIGFyZSBpbiB0aGUgbWlkZGxlIG9mIGEgZmlsdGVyLiBzZWUgY29tbWVudCBvbiBGaWx0ZXJNYW5hZ2VyXG4gICAgICAgIC8vIHdpdGggcmVnYXJkcyBwcm9jZXNzaW5nRmlsdGVyQ2hhbmdlXG4gICAgICAgIGlmICh0aGlzLmZpbHRlck1hbmFnZXIuaXNTdXBwcmVzc0ZsYXNoaW5nQ2VsbHNCZWNhdXNlRmlsdGVyaW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgdGhpcy5sYXN0VmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB2YXIgZGVsdGEgPSB2YWx1ZSAtIHRoaXMubGFzdFZhbHVlO1xuICAgICAgICAgICAgdGhpcy5zaG93RGVsdGEocGFyYW1zLCBkZWx0YSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaGlnaGxpZ2h0IHRoZSBjdXJyZW50IHZhbHVlLCBidXQgb25seSBpZiBpdCdzIG5vdCBuZXcsIG90aGVyd2lzZSBpdFxuICAgICAgICAvLyB3b3VsZCBnZXQgaGlnaGxpZ2h0ZWQgZmlyc3QgdGltZSB0aGUgdmFsdWUgaXMgc2hvd25cbiAgICAgICAgaWYgKHRoaXMubGFzdFZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmVWYWx1ZS5jbGFzc0xpc3QuYWRkKCdhZy12YWx1ZS1jaGFuZ2UtdmFsdWUtaGlnaGxpZ2h0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRUaW1lclRvUmVtb3ZlRGVsdGEoKTtcbiAgICAgICAgdGhpcy5sYXN0VmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlci5URU1QTEFURSA9ICc8c3Bhbj4nICtcbiAgICAgICAgJzxzcGFuIGNsYXNzPVwiYWctdmFsdWUtY2hhbmdlLWRlbHRhXCI+PC9zcGFuPicgK1xuICAgICAgICAnPHNwYW4gY2xhc3M9XCJhZy12YWx1ZS1jaGFuZ2UtdmFsdWVcIj48L3NwYW4+JyArXG4gICAgICAgICc8L3NwYW4+JztcbiAgICBfX2RlY29yYXRlJDIzKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlci5wcm90b3R5cGUsIFwiZmlsdGVyTWFuYWdlclwiLCB2b2lkIDApO1xuICAgIHJldHVybiBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlcjtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMmogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDIyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyaihBbmltYXRlU2xpZGVDZWxsUmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBBbmltYXRlU2xpZGVDZWxsUmVuZGVyZXIuVEVNUExBVEUpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnJlZnJlc2hDb3VudCA9IDA7XG4gICAgICAgIF90aGlzLmVDdXJyZW50ID0gX3RoaXMucXVlcnlGb3JIdG1sRWxlbWVudCgnLmFnLXZhbHVlLXNsaWRlLWN1cnJlbnQnKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBbmltYXRlU2xpZGVDZWxsUmVuZGVyZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMucmVmcmVzaChwYXJhbXMpO1xuICAgIH07XG4gICAgQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5hZGRTbGlkZUFuaW1hdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5yZWZyZXNoQ291bnQrKztcbiAgICAgICAgLy8gYmVsb3cgd2Uga2VlcCBjaGVja2luZyB0aGlzLCBhbmQgc3RvcCB3b3JraW5nIG9uIHRoZSBhbmltYXRpb25cbiAgICAgICAgLy8gaWYgaXQgbm8gbG9uZ2VyIG1hdGNoZXMgLSB0aGlzIG1lYW5zIGFub3RoZXIgYW5pbWF0aW9uIGhhcyBzdGFydGVkXG4gICAgICAgIC8vIGFuZCB0aGlzIG9uZSBpcyBzdGFsZS5cbiAgICAgICAgdmFyIHJlZnJlc2hDb3VudENvcHkgPSB0aGlzLnJlZnJlc2hDb3VudDtcbiAgICAgICAgLy8gaWYgb2xkIGFuaW1hdGlvbiwgcmVtb3ZlIGl0XG4gICAgICAgIGlmICh0aGlzLmVQcmV2aW91cykge1xuICAgICAgICAgICAgdGhpcy5nZXRHdWkoKS5yZW1vdmVDaGlsZCh0aGlzLmVQcmV2aW91cyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lUHJldmlvdXMgPSBsb2FkVGVtcGxhdGUoJzxzcGFuIGNsYXNzPVwiYWctdmFsdWUtc2xpZGUtcHJldmlvdXMgYWctdmFsdWUtc2xpZGUtb3V0XCI+PC9zcGFuPicpO1xuICAgICAgICB0aGlzLmVQcmV2aW91cy5pbm5lckhUTUwgPSB0aGlzLmVDdXJyZW50LmlubmVySFRNTDtcbiAgICAgICAgdGhpcy5nZXRHdWkoKS5pbnNlcnRCZWZvcmUodGhpcy5lUHJldmlvdXMsIHRoaXMuZUN1cnJlbnQpO1xuICAgICAgICAvLyBoYXZpbmcgdGltZW91dCBvZiAwIGFsbG93cyB1c2UgdG8gc2tpcCB0byB0aGUgbmV4dCBjc3MgdHVybixcbiAgICAgICAgLy8gc28gd2Uga25vdyB0aGUgcHJldmlvdXMgY3NzIGNsYXNzZXMgaGF2ZSBiZWVuIGFwcGxpZWQuIHNvIHRoZVxuICAgICAgICAvLyBjb21wbGV4IHNldCBvZiBzZXRUaW1lb3V0IGJlbG93IGNyZWF0ZXMgdGhlIGFuaW1hdGlvblxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAocmVmcmVzaENvdW50Q29weSAhPT0gX3RoaXMucmVmcmVzaENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZVByZXZpb3VzLmNsYXNzTGlzdC5hZGQoJ2FnLXZhbHVlLXNsaWRlLW91dC1lbmQnKTtcbiAgICAgICAgfSwgNTApO1xuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAocmVmcmVzaENvdW50Q29weSAhPT0gX3RoaXMucmVmcmVzaENvdW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkucmVtb3ZlQ2hpbGQoX3RoaXMuZVByZXZpb3VzKTtcbiAgICAgICAgICAgIF90aGlzLmVQcmV2aW91cyA9IG51bGw7XG4gICAgICAgIH0sIDMwMDApO1xuICAgIH07XG4gICAgQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgdmFsdWUgPSBwYXJhbXMudmFsdWU7XG4gICAgICAgIGlmIChtaXNzaW5nKHZhbHVlKSkge1xuICAgICAgICAgICAgdmFsdWUgPSAnJztcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWUgPT09IHRoaXMubGFzdFZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2UgZG9uJ3Qgc2hvdyB0aGUgZGVsdGEgaWYgd2UgYXJlIGluIHRoZSBtaWRkbGUgb2YgYSBmaWx0ZXIuIHNlZSBjb21tZW50IG9uIEZpbHRlck1hbmFnZXJcbiAgICAgICAgLy8gd2l0aCByZWdhcmRzIHByb2Nlc3NpbmdGaWx0ZXJDaGFuZ2VcbiAgICAgICAgaWYgKHRoaXMuZmlsdGVyTWFuYWdlci5pc1N1cHByZXNzRmxhc2hpbmdDZWxsc0JlY2F1c2VGaWx0ZXJpbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkU2xpZGVBbmltYXRpb24oKTtcbiAgICAgICAgdGhpcy5sYXN0VmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgaWYgKGV4aXN0cyhwYXJhbXMudmFsdWVGb3JtYXR0ZWQpKSB7XG4gICAgICAgICAgICB0aGlzLmVDdXJyZW50LmlubmVySFRNTCA9IHBhcmFtcy52YWx1ZUZvcm1hdHRlZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChleGlzdHMocGFyYW1zLnZhbHVlKSkge1xuICAgICAgICAgICAgdGhpcy5lQ3VycmVudC5pbm5lckhUTUwgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNsZWFyRWxlbWVudCh0aGlzLmVDdXJyZW50KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIEFuaW1hdGVTbGlkZUNlbGxSZW5kZXJlci5URU1QTEFURSA9IFwiPHNwYW4+XFxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImFnLXZhbHVlLXNsaWRlLWN1cnJlbnRcXFwiPjwvc3Bhbj5cXG4gICAgICAgIDwvc3Bhbj5cIjtcbiAgICBfX2RlY29yYXRlJDIyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBBbmltYXRlU2xpZGVDZWxsUmVuZGVyZXIucHJvdG90eXBlLCBcImZpbHRlck1hbmFnZXJcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIFJvd0hpZ2hsaWdodFBvc2l0aW9uO1xuKGZ1bmN0aW9uIChSb3dIaWdobGlnaHRQb3NpdGlvbikge1xuICAgIFJvd0hpZ2hsaWdodFBvc2l0aW9uW1Jvd0hpZ2hsaWdodFBvc2l0aW9uW1wiQWJvdmVcIl0gPSAwXSA9IFwiQWJvdmVcIjtcbiAgICBSb3dIaWdobGlnaHRQb3NpdGlvbltSb3dIaWdobGlnaHRQb3NpdGlvbltcIkJlbG93XCJdID0gMV0gPSBcIkJlbG93XCI7XG59KShSb3dIaWdobGlnaHRQb3NpdGlvbiB8fCAoUm93SGlnaGxpZ2h0UG9zaXRpb24gPSB7fSkpO1xudmFyIFJvd05vZGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUm93Tm9kZShiZWFucykge1xuICAgICAgICAvKiogVGhlIGN1cnJlbnQgcm93IGluZGV4LiBJZiB0aGUgcm93IGlzIGZpbHRlcmVkIG91dCBvciBpbiBhIGNvbGxhcHNlZCBncm91cCwgdGhpcyB2YWx1ZSB3aWxsIGJlIGBudWxsYC4gKi9cbiAgICAgICAgdGhpcy5yb3dJbmRleCA9IG51bGw7XG4gICAgICAgIC8qKiBUaGUga2V5IGZvciB0aGUgZ3JvdXAgZWcgSXJlbGFuZCwgVUssIFVTQSAqL1xuICAgICAgICB0aGlzLmtleSA9IG51bGw7XG4gICAgICAgIC8qKiBDaGlsZHJlbiBtYXBwZWQgYnkgdGhlIHBpdm90IGNvbHVtbnMuICovXG4gICAgICAgIHRoaXMuY2hpbGRyZW5NYXBwZWQgPSB7fTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgd2lsbCBiZSBgdHJ1ZWAgaWYgaXQgaGFzIGEgcm93SW5kZXggYXNzaWduZWQsIG90aGVyd2lzZSBgZmFsc2VgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5kaXNwbGF5ZWQgPSBmYWxzZTtcbiAgICAgICAgLyoqIFRoZSByb3cgdG9wIHBvc2l0aW9uIGluIHBpeGVscy4gKi9cbiAgICAgICAgdGhpcy5yb3dUb3AgPSBudWxsO1xuICAgICAgICAvKiogVGhlIHRvcCBwaXhlbCBmb3IgdGhpcyByb3cgbGFzdCB0aW1lLCBtYWtlcyBzZW5zZSBpZiBkYXRhIHNldCB3YXMgb3JkZXJlZCBvciBmaWx0ZXJlZCxcbiAgICAgICAgICogaXQgaXMgdXNlZCBzbyBuZXcgcm93cyBjYW4gYW5pbWF0ZSBpbiBmcm9tIHRoZWlyIG9sZCBwb3NpdGlvbi4gKi9cbiAgICAgICAgdGhpcy5vbGRSb3dUb3AgPSBudWxsO1xuICAgICAgICAvKiogYHRydWVgIGJ5IGRlZmF1bHQgLSBjYW4gYmUgb3ZlcnJpZGRlbiB2aWEgZ3JpZE9wdGlvbnMuaXNSb3dTZWxlY3RhYmxlKHJvd05vZGUpICovXG4gICAgICAgIHRoaXMuc2VsZWN0YWJsZSA9IHRydWU7XG4gICAgICAgIC8qKiBVc2VkIGJ5IHNvcnRpbmcgc2VydmljZSAtIHRvIGdpdmUgZGV0ZXJtaW5pc3RpYyBzb3J0IHRvIGdyb3Vwcy4gUHJldmlvdXNseSB3ZVxuICAgICAgICAgKiBqdXN0IGlkIGZvciB0aGlzLCBob3dldmVyIGlkIGlzIGEgc3RyaW5nIGFuZCBoYWQgc2xvd2VyIHNvcnRpbmcgY29tcGFyZWQgdG8gbnVtYmVycy4gKi9cbiAgICAgICAgdGhpcy5fX29iamVjdElkID0gUm93Tm9kZS5PQkpFQ1RfSURfU0VRVUVOQ0UrKztcbiAgICAgICAgLyoqIFdoZW4gb25lIG9yIG1vcmUgQ29sdW1ucyBhcmUgdXNpbmcgYXV0b0hlaWdodCwgdGhpcyBrZWVwcyB0cmFjayBvZiBoZWlnaHQgb2YgZWFjaCBhdXRvSGVpZ2h0IENlbGwsXG4gICAgICAgICAqIGluZGV4ZWQgYnkgdGhlIENvbHVtbiBJRC4gKi9cbiAgICAgICAgdGhpcy5fX2F1dG9IZWlnaHRzID0ge307XG4gICAgICAgIC8qKiBgdHJ1ZWAgd2hlbiBub2RlcyB3aXRoIHRoZSBzYW1lIGlkIGFyZSBiZWluZyByZW1vdmVkIGFuZCBhZGRlZCBhcyBwYXJ0IG9mIHRoZSBzYW1lIGJhdGNoIHRyYW5zYWN0aW9uICovXG4gICAgICAgIHRoaXMuYWxyZWFkeVJlbmRlcmVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWQgPSBudWxsO1xuICAgICAgICB0aGlzLnNlbGVjdGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYmVhbnMgPSBiZWFucztcbiAgICB9XG4gICAgLyoqIFJlcGxhY2VzIHRoZSBkYXRhIG9uIHRoZSBgcm93Tm9kZWAuIFdoZW4gY29tcGxldGUsIHRoZSBncmlkIHdpbGwgcmVmcmVzaCB0aGUgdGhlIGVudGlyZSByZW5kZXJlZCByb3cgaWYgaXQgaXMgc2hvd2luZy4gKi9cbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXREYXRhID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdGhpcy5zZXREYXRhQ29tbW9uKGRhdGEsIGZhbHNlKTtcbiAgICB9O1xuICAgIC8vIHNpbWlsYXIgdG8gc2V0Um93RGF0YSwgaG93ZXZlciBpdCBpcyBleHBlY3RlZCB0aGF0IHRoZSBkYXRhIGlzIHRoZSBzYW1lIGRhdGEgaXRlbS4gdGhpc1xuICAgIC8vIGlzIGludGVuZGVkIHRvIGJlIHVzZWQgd2l0aCBSZWR1eCB0eXBlIHN0b3Jlcywgd2hlcmUgdGhlIHdob2xlIGRhdGEgY2FuIGJlIGNoYW5nZWQuIHdlIGFyZVxuICAgIC8vIGd1YXJhbnRlZWQgdGhhdCB0aGUgZGF0YSBpcyB0aGUgc2FtZSBlbnRpdHkgKHNvIGdyaWQgZG9lc24ndCBuZWVkIHRvIHdvcnJ5IGFib3V0IHRoZSBpZCBvZiB0aGVcbiAgICAvLyB1bmRlcmx5aW5nIGRhdGEgY2hhbmdpbmcsIGhlbmNlIGRvZXNuJ3QgbmVlZCB0byB3b3JyeSBhYm91dCBzZWxlY3Rpb24pLiB0aGUgZ3JpZCwgdXBvbiByZWNlaXZpbmdcbiAgICAvLyBkYXRhQ2hhbmdlZCBldmVudCwgd2lsbCByZWZyZXNoIHRoZSBjZWxscyByYXRoZXIgdGhhbiByaXAgdGhlbSBhbGwgb3V0IChzbyB1c2VyIGNhbiBzaG93IHRyYW5zaXRpb25zKS5cbiAgICBSb3dOb2RlLnByb3RvdHlwZS51cGRhdGVEYXRhID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdGhpcy5zZXREYXRhQ29tbW9uKGRhdGEsIHRydWUpO1xuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0RGF0YUNvbW1vbiA9IGZ1bmN0aW9uIChkYXRhLCB1cGRhdGUpIHtcbiAgICAgICAgdmFyIG9sZERhdGEgPSB0aGlzLmRhdGE7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgICAgIHRoaXMuYmVhbnMudmFsdWVDYWNoZS5vbkRhdGFDaGFuZ2VkKCk7XG4gICAgICAgIHRoaXMudXBkYXRlRGF0YU9uRGV0YWlsTm9kZSgpO1xuICAgICAgICB0aGlzLmNoZWNrUm93U2VsZWN0YWJsZSgpO1xuICAgICAgICB2YXIgZXZlbnQgPSB0aGlzLmNyZWF0ZURhdGFDaGFuZ2VkRXZlbnQoZGF0YSwgb2xkRGF0YSwgdXBkYXRlKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaExvY2FsRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgLy8gd2hlbiB3ZSBhcmUgZG9pbmcgbWFzdGVyIC8gZGV0YWlsLCB0aGUgZGV0YWlsIG5vZGUgaXMgbGF6eSBjcmVhdGVkLCBidXQgdGhlbiBrZXB0IGFyb3VuZC5cbiAgICAvLyBzbyBpZiB3ZSBzaG93IC8gaGlkZSB0aGUgZGV0YWlsLCB0aGUgc2FtZSBkZXRhaWwgcm93Tm9kZSBpcyB1c2VkLiBzbyB3ZSBuZWVkIHRvIGtlZXAgdGhlIGRhdGFcbiAgICAvLyBpbiBzeW5jLCBvdGhlcndpc2UgZXhwYW5kL2NvbGxhcHNlIG9mIHRoZSBkZXRhaWwgd291bGQgc3RpbGwgc2hvdyB0aGUgb2xkIHZhbHVlcy5cbiAgICBSb3dOb2RlLnByb3RvdHlwZS51cGRhdGVEYXRhT25EZXRhaWxOb2RlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kZXRhaWxOb2RlKSB7XG4gICAgICAgICAgICB0aGlzLmRldGFpbE5vZGUuZGF0YSA9IHRoaXMuZGF0YTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuY3JlYXRlRGF0YUNoYW5nZWRFdmVudCA9IGZ1bmN0aW9uIChuZXdEYXRhLCBvbGREYXRhLCB1cGRhdGUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6IFJvd05vZGUuRVZFTlRfREFUQV9DSEFOR0VELFxuICAgICAgICAgICAgbm9kZTogdGhpcyxcbiAgICAgICAgICAgIG9sZERhdGE6IG9sZERhdGEsXG4gICAgICAgICAgICBuZXdEYXRhOiBuZXdEYXRhLFxuICAgICAgICAgICAgdXBkYXRlOiB1cGRhdGVcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmNyZWF0ZUxvY2FsUm93RXZlbnQgPSBmdW5jdGlvbiAodHlwZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIG5vZGU6IHRoaXNcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmdldFJvd0luZGV4U3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yb3dQaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfVE9QKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3QtJyArIHRoaXMucm93SW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucm93UGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX0JPVFRPTSkge1xuICAgICAgICAgICAgcmV0dXJuICdiLScgKyB0aGlzLnJvd0luZGV4O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJvd0luZGV4LnRvU3RyaW5nKCk7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5jcmVhdGVEYWVtb25Ob2RlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb2xkTm9kZSA9IG5ldyBSb3dOb2RlKHRoaXMuYmVhbnMpO1xuICAgICAgICAvLyBqdXN0IGNvcHkgdGhlIGlkIGFuZCBkYXRhLCB0aGlzIGlzIGVub3VnaCBmb3IgdGhlIG5vZGUgdG8gYmUgdXNlZFxuICAgICAgICAvLyBpbiB0aGUgc2VsZWN0aW9uIGNvbnRyb2xsZXIgKHRoZSBzZWxlY3Rpb24gY29udHJvbGxlciBpcyB0aGUgb25seVxuICAgICAgICAvLyBwbGFjZSB3aGVyZSBkYWVtb24gbm9kZXMgY2FuIGxpdmUpLlxuICAgICAgICBvbGROb2RlLmlkID0gdGhpcy5pZDtcbiAgICAgICAgb2xkTm9kZS5kYXRhID0gdGhpcy5kYXRhO1xuICAgICAgICBvbGROb2RlLmRhZW1vbiA9IHRydWU7XG4gICAgICAgIG9sZE5vZGUuc2VsZWN0ZWQgPSB0aGlzLnNlbGVjdGVkO1xuICAgICAgICBvbGROb2RlLmxldmVsID0gdGhpcy5sZXZlbDtcbiAgICAgICAgcmV0dXJuIG9sZE5vZGU7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXREYXRhQW5kSWQgPSBmdW5jdGlvbiAoZGF0YSwgaWQpIHtcbiAgICAgICAgdmFyIG9sZE5vZGUgPSBleGlzdHModGhpcy5pZCkgPyB0aGlzLmNyZWF0ZURhZW1vbk5vZGUoKSA6IG51bGw7XG4gICAgICAgIHZhciBvbGREYXRhID0gdGhpcy5kYXRhO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgICAgICB0aGlzLnVwZGF0ZURhdGFPbkRldGFpbE5vZGUoKTtcbiAgICAgICAgdGhpcy5zZXRJZChpZCk7XG4gICAgICAgIHRoaXMuYmVhbnMuc2VsZWN0aW9uU2VydmljZS5zeW5jSW5Sb3dOb2RlKHRoaXMsIG9sZE5vZGUpO1xuICAgICAgICB0aGlzLmNoZWNrUm93U2VsZWN0YWJsZSgpO1xuICAgICAgICB2YXIgZXZlbnQgPSB0aGlzLmNyZWF0ZURhdGFDaGFuZ2VkRXZlbnQoZGF0YSwgb2xkRGF0YSwgZmFsc2UpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoTG9jYWxFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5jaGVja1Jvd1NlbGVjdGFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc1Jvd1NlbGVjdGFibGVGdW5jID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0SXNSb3dTZWxlY3RhYmxlRnVuYygpO1xuICAgICAgICB0aGlzLnNldFJvd1NlbGVjdGFibGUoaXNSb3dTZWxlY3RhYmxlRnVuYyA/IGlzUm93U2VsZWN0YWJsZUZ1bmModGhpcykgOiB0cnVlKTtcbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldFJvd1NlbGVjdGFibGUgPSBmdW5jdGlvbiAobmV3VmFsKSB7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGFibGUgIT09IG5ld1ZhbCkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RhYmxlID0gbmV3VmFsO1xuICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9TRUxFQ1RBQkxFX0NIQU5HRUQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBpc0dyb3VwU2VsZWN0c0NoaWxkcmVuID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFNlbGVjdHNDaGlsZHJlbigpO1xuICAgICAgICAgICAgaWYgKGlzR3JvdXBTZWxlY3RzQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWQgPSB0aGlzLmNhbGN1bGF0ZVNlbGVjdGVkRnJvbUNoaWxkcmVuKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTZWxlY3RlZCgoc2VsZWN0ZWQgIT09IG51bGwgJiYgc2VsZWN0ZWQgIT09IHZvaWQgMCA/IHNlbGVjdGVkIDogZmFsc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0SWQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgLy8gc2VlIGlmIHVzZXIgaXMgcHJvdmlkaW5nIHRoZSBpZCdzXG4gICAgICAgIHZhciBnZXRSb3dJZEZ1bmMgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dJZEZ1bmMoKTtcbiAgICAgICAgaWYgKGdldFJvd0lkRnVuYykge1xuICAgICAgICAgICAgLy8gaWYgdXNlciBpcyBwcm92aWRpbmcgdGhlIGlkJ3MsIHRoZW4gd2Ugc2V0IHRoZSBpZCBvbmx5IGFmdGVyIHRoZSBkYXRhIGhhcyBiZWVuIHNldC5cbiAgICAgICAgICAgIC8vIHRoaXMgaXMgaW1wb3J0YW50IGZvciB2aXJ0dWFsIHBhZ2luYXRpb24gYW5kIHZpZXdwb3J0LCB3aGVyZSBlbXB0eSByb3dzIGV4aXN0LlxuICAgICAgICAgICAgaWYgKHRoaXMuZGF0YSkge1xuICAgICAgICAgICAgICAgIC8vIHdlIHBhc3MgJ3RydWUnIGFzIHdlIHNraXAgdGhpcyBsZXZlbCB3aGVuIGdlbmVyYXRpbmcga2V5cyxcbiAgICAgICAgICAgICAgICAvLyBhcyB3ZSBkb24ndCBhbHdheXMgaGF2ZSB0aGUga2V5IGZvciB0aGlzIGxldmVsIChlZyB3aGVuIHVwZGF0aW5nXG4gICAgICAgICAgICAgICAgLy8gZGF0YSB2aWEgdHJhbnNhY3Rpb24gb24gU1NSTSwgd2UgYXJlIGdldHRpbmcga2V5IHRvIGxvb2sgdXAgdGhlXG4gICAgICAgICAgICAgICAgLy8gUm93Tm9kZSwgZG9uJ3QgaGF2ZSB0aGUgUm93Tm9kZSB5ZXQsIHRodXMgbm8gd2F5IHRvIGdldCB0aGUgY3VycmVudCBrZXkpXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudEtleXMgPSB0aGlzLmdldEdyb3VwS2V5cyh0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gZ2V0Um93SWRGdW5jKHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogdGhpcy5kYXRhLFxuICAgICAgICAgICAgICAgICAgICBwYXJlbnRLZXlzOiBwYXJlbnRLZXlzLmxlbmd0aCA+IDAgPyBwYXJlbnRLZXlzIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICBsZXZlbDogdGhpcy5sZXZlbFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSBpZCBwcm92aWRlZCBkb2Vzbid0IHN0YXJ0IHdpdGggJ3Jvdy1ncm91cC0nIGFzIHRoaXMgaXMgcmVzZXJ2ZWQuIGFsc28gY2hlY2sgdGhhdFxuICAgICAgICAgICAgICAgIC8vIGl0IGhhcyAnc3RhcnRzV2l0aCcgaW4gY2FzZSB0aGUgdXNlciBwcm92aWRlZCBhIG51bWJlci5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pZCAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5pZCA9PT0gJ3N0cmluZycgJiYgdGhpcy5pZC5zdGFydHNXaXRoKFJvd05vZGUuSURfUFJFRklYX1JPV19HUk9VUCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkFHIEdyaWQ6IFJvdyBJRHMgY2Fubm90IHN0YXJ0IHdpdGggXCIgKyBSb3dOb2RlLklEX1BSRUZJWF9ST1dfR1JPVVAgKyBcIiwgdGhpcyBpcyBhIHJlc2VydmVkIHByZWZpeCBmb3IgQUcgR3JpZCdzIHJvdyBncm91cGluZyBmZWF0dXJlLlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gZm9yY2UgaWQgdG8gYmUgYSBzdHJpbmdcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pZCAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpcy5pZCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pZCA9ICcnICsgdGhpcy5pZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGNhbiBoYXBwZW4gaWYgdXNlciBoYXMgc2V0IGJsYW5rIGludG8gdGhlIHJvd05vZGUgYWZ0ZXIgdGhlIHJvdyBwcmV2aW91c2x5XG4gICAgICAgICAgICAgICAgLy8gaGF2aW5nIGRhdGEuIHRoaXMgaGFwcGVucyBpbiB2aXJ0dWFsIHBhZ2Ugcm93IG1vZGVsLCB3aGVuIGRhdGEgaXMgZGVsZXRlIGFuZFxuICAgICAgICAgICAgICAgIC8vIHRoZSBwYWdlIGlzIHJlZnJlc2hlZC5cbiAgICAgICAgICAgICAgICB0aGlzLmlkID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5nZXRHcm91cEtleXMgPSBmdW5jdGlvbiAoZXhjbHVkZVNlbGYpIHtcbiAgICAgICAgaWYgKGV4Y2x1ZGVTZWxmID09PSB2b2lkIDApIHsgZXhjbHVkZVNlbGYgPSBmYWxzZTsgfVxuICAgICAgICB2YXIga2V5cyA9IFtdO1xuICAgICAgICB2YXIgcG9pbnRlciA9IHRoaXM7XG4gICAgICAgIGlmIChleGNsdWRlU2VsZikge1xuICAgICAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIucGFyZW50O1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChwb2ludGVyICYmIHBvaW50ZXIubGV2ZWwgPj0gMCkge1xuICAgICAgICAgICAga2V5cy5wdXNoKHBvaW50ZXIua2V5KTtcbiAgICAgICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICBrZXlzLnJldmVyc2UoKTtcbiAgICAgICAgcmV0dXJuIGtleXM7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5pc1BpeGVsSW5SYW5nZSA9IGZ1bmN0aW9uIChwaXhlbCkge1xuICAgICAgICBpZiAoIWV4aXN0cyh0aGlzLnJvd1RvcCkgfHwgIWV4aXN0cyh0aGlzLnJvd0hlaWdodCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGl4ZWwgPj0gdGhpcy5yb3dUb3AgJiYgcGl4ZWwgPCAodGhpcy5yb3dUb3AgKyB0aGlzLnJvd0hlaWdodCk7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXRGaXJzdENoaWxkID0gZnVuY3Rpb24gKGZpcnN0Q2hpbGQpIHtcbiAgICAgICAgaWYgKHRoaXMuZmlyc3RDaGlsZCA9PT0gZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZmlyc3RDaGlsZCA9IGZpcnN0Q2hpbGQ7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9GSVJTVF9DSElMRF9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldExhc3RDaGlsZCA9IGZ1bmN0aW9uIChsYXN0Q2hpbGQpIHtcbiAgICAgICAgaWYgKHRoaXMubGFzdENoaWxkID09PSBsYXN0Q2hpbGQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhc3RDaGlsZCA9IGxhc3RDaGlsZDtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0xBU1RfQ0hJTERfQ0hBTkdFRCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXRDaGlsZEluZGV4ID0gZnVuY3Rpb24gKGNoaWxkSW5kZXgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2hpbGRJbmRleCA9PT0gY2hpbGRJbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2hpbGRJbmRleCA9IGNoaWxkSW5kZXg7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9DSElMRF9JTkRFWF9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldFJvd1RvcCA9IGZ1bmN0aW9uIChyb3dUb3ApIHtcbiAgICAgICAgdGhpcy5vbGRSb3dUb3AgPSB0aGlzLnJvd1RvcDtcbiAgICAgICAgaWYgKHRoaXMucm93VG9wID09PSByb3dUb3ApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd1RvcCA9IHJvd1RvcDtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX1RPUF9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXREaXNwbGF5ZWQocm93VG9wICE9PSBudWxsKTtcbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmNsZWFyUm93VG9wQW5kUm93SW5kZXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub2xkUm93VG9wID0gbnVsbDtcbiAgICAgICAgdGhpcy5zZXRSb3dUb3AobnVsbCk7XG4gICAgICAgIHRoaXMuc2V0Um93SW5kZXgobnVsbCk7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXREaXNwbGF5ZWQgPSBmdW5jdGlvbiAoZGlzcGxheWVkKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXllZCA9PT0gZGlzcGxheWVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwbGF5ZWQgPSBkaXNwbGF5ZWQ7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9ESVNQTEFZRURfQ0hBTkdFRCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXREcmFnZ2luZyA9IGZ1bmN0aW9uIChkcmFnZ2luZykge1xuICAgICAgICBpZiAodGhpcy5kcmFnZ2luZyA9PT0gZHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRyYWdnaW5nID0gZHJhZ2dpbmc7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9EUkFHR0lOR19DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldEhpZ2hsaWdodGVkID0gZnVuY3Rpb24gKGhpZ2hsaWdodGVkKSB7XG4gICAgICAgIGlmIChoaWdobGlnaHRlZCA9PT0gdGhpcy5oaWdobGlnaHRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGlnaGxpZ2h0ZWQgPSBoaWdobGlnaHRlZDtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0hJR0hMSUdIVF9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldEFsbENoaWxkcmVuQ291bnQgPSBmdW5jdGlvbiAoYWxsQ2hpbGRyZW5Db3VudCkge1xuICAgICAgICBpZiAodGhpcy5hbGxDaGlsZHJlbkNvdW50ID09PSBhbGxDaGlsZHJlbkNvdW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hbGxDaGlsZHJlbkNvdW50ID0gYWxsQ2hpbGRyZW5Db3VudDtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0FMTF9DSElMRFJFTl9DT1VOVF9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldE1hc3RlciA9IGZ1bmN0aW9uIChtYXN0ZXIpIHtcbiAgICAgICAgaWYgKHRoaXMubWFzdGVyID09PSBtYXN0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBjaGFuZ2luZyBBV0FZIGZyb20gbWFzdGVyLCB0aGVuIHVuZXhwYW5kLCBvdGhlcndpc2VcbiAgICAgICAgLy8gbmV4dCB0aW1lIGl0J3Mgc2hvd24gaXQgaXMgZXhwYW5kZWQgYWdhaW5cbiAgICAgICAgaWYgKHRoaXMubWFzdGVyICYmICFtYXN0ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1hc3RlciA9IG1hc3RlcjtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX01BU1RFUl9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldEdyb3VwID0gZnVuY3Rpb24gKGdyb3VwKSB7XG4gICAgICAgIGlmICh0aGlzLmdyb3VwID09PSBncm91cCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlIHVzZWQgdG8gYmUgYSBncm91cCwgYW5kIG5vIGxvbmdlciwgdGhlbiBjbG9zZSB0aGUgbm9kZVxuICAgICAgICBpZiAodGhpcy5ncm91cCAmJiAhZ3JvdXApIHtcbiAgICAgICAgICAgIHRoaXMuZXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdyb3VwID0gZ3JvdXA7XG4gICAgICAgIHRoaXMudXBkYXRlSGFzQ2hpbGRyZW4oKTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0dST1VQX0NIQU5HRUQpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgcm93IGhlaWdodC5cbiAgICAgKiBDYWxsIGlmIHlvdSB3YW50IHRvIGNoYW5nZSB0aGUgaGVpZ2h0IGluaXRpYWxseSBhc3NpZ25lZCB0byB0aGUgcm93LlxuICAgICAqIEFmdGVyIGNhbGxpbmcsIHlvdSBtdXN0IGNhbGwgYGFwaS5vblJvd0hlaWdodENoYW5nZWQoKWAgc28gdGhlIGdyaWQga25vd3MgaXQgbmVlZHMgdG8gd29yayBvdXQgdGhlIHBsYWNlbWVudCBvZiB0aGUgcm93cy4gKi9cbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXRSb3dIZWlnaHQgPSBmdW5jdGlvbiAocm93SGVpZ2h0LCBlc3RpbWF0ZWQpIHtcbiAgICAgICAgaWYgKGVzdGltYXRlZCA9PT0gdm9pZCAwKSB7IGVzdGltYXRlZCA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMucm93SGVpZ2h0ID0gcm93SGVpZ2h0O1xuICAgICAgICB0aGlzLnJvd0hlaWdodEVzdGltYXRlZCA9IGVzdGltYXRlZDtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0hFSUdIVF9DSEFOR0VEKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldFJvd0F1dG9IZWlnaHQgPSBmdW5jdGlvbiAoY2VsbEhlaWdodCwgY29sdW1uKSB7XG4gICAgICAgIGlmICghdGhpcy5fX2F1dG9IZWlnaHRzKSB7XG4gICAgICAgICAgICB0aGlzLl9fYXV0b0hlaWdodHMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYXV0b0hlaWdodHMgPSB0aGlzLl9fYXV0b0hlaWdodHM7XG4gICAgICAgIGF1dG9IZWlnaHRzW2NvbHVtbi5nZXRJZCgpXSA9IGNlbGxIZWlnaHQ7XG4gICAgICAgIGlmIChjZWxsSGVpZ2h0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNoZWNrQXV0b0hlaWdodHNEZWJvdW5jZWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tBdXRvSGVpZ2h0c0RlYm91bmNlZCA9IGRlYm91bmNlKHRoaXMuY2hlY2tBdXRvSGVpZ2h0cy5iaW5kKHRoaXMpLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY2hlY2tBdXRvSGVpZ2h0c0RlYm91bmNlZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5jaGVja0F1dG9IZWlnaHRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbm90QWxsUHJlc2VudCA9IGZhbHNlO1xuICAgICAgICB2YXIgbm9uZVByZXNlbnQgPSB0cnVlO1xuICAgICAgICB2YXIgbmV3Um93SGVpZ2h0ID0gMDtcbiAgICAgICAgdmFyIGF1dG9IZWlnaHRzID0gdGhpcy5fX2F1dG9IZWlnaHRzO1xuICAgICAgICBpZiAoYXV0b0hlaWdodHMgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkaXNwbGF5ZWRBdXRvSGVpZ2h0Q29scyA9IHRoaXMuYmVhbnMuY29sdW1uTW9kZWwuZ2V0QWxsRGlzcGxheWVkQXV0b0hlaWdodENvbHMoKTtcbiAgICAgICAgZGlzcGxheWVkQXV0b0hlaWdodENvbHMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICB2YXIgY2VsbEhlaWdodCA9IGF1dG9IZWlnaHRzW2NvbC5nZXRJZCgpXTtcbiAgICAgICAgICAgIGlmIChjZWxsSGVpZ2h0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBub3RBbGxQcmVzZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub25lUHJlc2VudCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGNlbGxIZWlnaHQgPiBuZXdSb3dIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBuZXdSb3dIZWlnaHQgPSBjZWxsSGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG5vdEFsbFByZXNlbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSB0YWtlIG1pbiBvZiAxMCwgc28gd2UgZG9uJ3QgYWRqdXN0IGZvciBlbXB0eSByb3dzLiBpZiA8MTAsIHdlIHB1dCB0byBkZWZhdWx0LlxuICAgICAgICAvLyB0aGlzIHByZXZlbnRzIHRoZSByb3cgc3RhcnRpbmcgdmVyeSBzbWFsbCB3aGVuIHdhaXRpbmcgZm9yIGFzeW5jIGNvbXBvbmVudHMsXG4gICAgICAgIC8vIHdoaWNoIHdvdWxkIHRoZW4gbWVhbiB0aGUgZ3JpZCBzcXVhc2hlcyBpbiBmYXIgdG8gbWFueSByb3dzIChhcyBzbWFsbCBoZWlnaHRzXG4gICAgICAgIC8vIG1lYW5zIG1vcmUgcm93cyBmaXQgaW4pIHdoaWNoIGxvb2tzIGNyYXAuIHNvIGJlc3QgaWdub3JlIHNtYWxsIHZhbHVlcyBhbmQgYXNzdW1lXG4gICAgICAgIC8vIHdlIGFyZSBzdGlsbCB3YWl0aW5nIGZvciB2YWx1ZXMgdG8gcmVuZGVyLlxuICAgICAgICBpZiAobm9uZVByZXNlbnQgfHwgbmV3Um93SGVpZ2h0IDwgMTApIHtcbiAgICAgICAgICAgIG5ld1Jvd0hlaWdodCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0hlaWdodEZvck5vZGUodGhpcykuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdSb3dIZWlnaHQgPT0gdGhpcy5yb3dIZWlnaHQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFJvd0hlaWdodChuZXdSb3dIZWlnaHQpO1xuICAgICAgICB2YXIgcm93TW9kZWwgPSB0aGlzLmJlYW5zLnJvd01vZGVsO1xuICAgICAgICBpZiAocm93TW9kZWwub25Sb3dIZWlnaHRDaGFuZ2VkRGVib3VuY2VkKSB7XG4gICAgICAgICAgICByb3dNb2RlbC5vblJvd0hlaWdodENoYW5nZWREZWJvdW5jZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0Um93SW5kZXggPSBmdW5jdGlvbiAocm93SW5kZXgpIHtcbiAgICAgICAgaWYgKHRoaXMucm93SW5kZXggPT09IHJvd0luZGV4KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yb3dJbmRleCA9IHJvd0luZGV4O1xuICAgICAgICBpZiAodGhpcy5ldmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVMb2NhbFJvd0V2ZW50KFJvd05vZGUuRVZFTlRfUk9XX0lOREVYX0NIQU5HRUQpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0VWlMZXZlbCA9IGZ1bmN0aW9uICh1aUxldmVsKSB7XG4gICAgICAgIGlmICh0aGlzLnVpTGV2ZWwgPT09IHVpTGV2ZWwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVpTGV2ZWwgPSB1aUxldmVsO1xuICAgICAgICBpZiAodGhpcy5ldmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQodGhpcy5jcmVhdGVMb2NhbFJvd0V2ZW50KFJvd05vZGUuRVZFTlRfVUlfTEVWRUxfQ0hBTkdFRCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGV4cGFuZGVkIHN0YXRlIG9mIHRoaXMgcm93Tm9kZS4gUGFzcyBgdHJ1ZWAgdG8gZXhwYW5kIGFuZCBgZmFsc2VgIHRvIGNvbGxhcHNlLlxuICAgICAqL1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldEV4cGFuZGVkID0gZnVuY3Rpb24gKGV4cGFuZGVkLCBlKSB7XG4gICAgICAgIGlmICh0aGlzLmV4cGFuZGVkID09PSBleHBhbmRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXhwYW5kZWQgPSBleHBhbmRlZDtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0VYUEFOREVEX0NIQU5HRUQpKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXZlbnQgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmNyZWF0ZUdsb2JhbFJvd0V2ZW50KEV2ZW50cy5FVkVOVF9ST1dfR1JPVVBfT1BFTkVEKSwge1xuICAgICAgICAgICAgZXhwYW5kZWQ6IGV4cGFuZGVkLFxuICAgICAgICAgICAgZXZlbnQ6IGUgfHwgbnVsbFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5iZWFucy5yb3dOb2RlRXZlbnRUaHJvdHRsZS5kaXNwYXRjaEV4cGFuZGVkKGV2ZW50KTtcbiAgICAgICAgLy8gd2hlbiB1c2luZyBmb290ZXJzIHdlIG5lZWQgdG8gcmVmcmVzaCB0aGUgZ3JvdXAgcm93LCBhcyB0aGUgYWdncmVnYXRpb25cbiAgICAgICAgLy8gdmFsdWVzIGp1bXAgYmV0d2VlbiBncm91cCBhbmQgZm9vdGVyXG4gICAgICAgIGlmICh0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwSW5jbHVkZUZvb3RlcigpKSB7XG4gICAgICAgICAgICB0aGlzLmJlYW5zLnJvd1JlbmRlcmVyLnJlZnJlc2hDZWxscyh7IHJvd05vZGVzOiBbdGhpc10gfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmNyZWF0ZUdsb2JhbFJvd0V2ZW50ID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICBub2RlOiB0aGlzLFxuICAgICAgICAgICAgZGF0YTogdGhpcy5kYXRhLFxuICAgICAgICAgICAgcm93SW5kZXg6IHRoaXMucm93SW5kZXgsXG4gICAgICAgICAgICByb3dQaW5uZWQ6IHRoaXMucm93UGlubmVkLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKClcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmRpc3BhdGNoTG9jYWxFdmVudCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAodGhpcy5ldmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXBsYWNlcyB0aGUgdmFsdWUgb24gdGhlIGByb3dOb2RlYCBmb3IgdGhlIHNwZWNpZmllZCBjb2x1bW4uIFdoZW4gY29tcGxldGUsXG4gICAgICogdGhlIGdyaWQgd2lsbCByZWZyZXNoIHRoZSByZW5kZXJlZCBjZWxsIG9uIHRoZSByZXF1aXJlZCByb3cgb25seS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBjb2xLZXkgVGhlIGNvbHVtbiB3aGVyZSB0aGUgdmFsdWUgc2hvdWxkIGJlIHVwZGF0ZWRcbiAgICAgKiBAcGFyYW0gbmV3VmFsdWUgVGhlIG5ldyB2YWx1ZVxuICAgICAqIEBwYXJhbSBldmVudFNvdXJjZSBUaGUgc291cmNlIG9mIHRoZSBldmVudFxuICAgICAqIEByZXR1cm5zIGBUcnVlYCBpZiB0aGUgdmFsdWUgd2FzIGNoYW5nZWQsIG90aGVyd2lzZSBgRmFsc2VgLlxuICAgICAqL1xuICAgIFJvd05vZGUucHJvdG90eXBlLnNldERhdGFWYWx1ZSA9IGZ1bmN0aW9uIChjb2xLZXksIG5ld1ZhbHVlLCBldmVudFNvdXJjZSkge1xuICAgICAgICAvLyBXaGVuIGl0IGlzIGRvbmUgdmlhIHRoZSBlZGl0b3JzLCBubyAnY2VsbCBjaGFuZ2VkJyBldmVudCBnZXRzIGZpcmVkLCBhcyBpdCdzIGFzc3VtZWQgdGhhdFxuICAgICAgICAvLyB0aGUgY2VsbCBrbm93cyBhYm91dCB0aGUgY2hhbmdlIGdpdmVuIGl0J3MgaW4gY2hhcmdlIG9mIHRoZSBlZGl0aW5nLlxuICAgICAgICAvLyB0aGlzIG1ldGhvZCBpcyBmb3IgdGhlIGNsaWVudCB0byBjYWxsLCBzbyB0aGUgY2VsbCBsaXN0ZW5zIGZvciB0aGUgY2hhbmdlXG4gICAgICAgIC8vIGV2ZW50LCBhbmQgYWxzbyBmbGFzaGVzIHRoZSBjZWxsIHdoZW4gdGhlIGNoYW5nZSBvY2N1cnMuXG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmJlYW5zLmNvbHVtbk1vZGVsLmdldFByaW1hcnlDb2x1bW4oY29sS2V5KTtcbiAgICAgICAgdmFyIG9sZFZhbHVlID0gdGhpcy5iZWFucy52YWx1ZVNlcnZpY2UuZ2V0VmFsdWUoY29sdW1uLCB0aGlzKTtcbiAgICAgICAgdmFyIHZhbHVlQ2hhbmdlZCA9IHRoaXMuYmVhbnMudmFsdWVTZXJ2aWNlLnNldFZhbHVlKHRoaXMsIGNvbHVtbiwgbmV3VmFsdWUsIGV2ZW50U291cmNlKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaENlbGxDaGFuZ2VkRXZlbnQoY29sdW1uLCBuZXdWYWx1ZSwgb2xkVmFsdWUpO1xuICAgICAgICB0aGlzLmNoZWNrUm93U2VsZWN0YWJsZSgpO1xuICAgICAgICByZXR1cm4gdmFsdWVDaGFuZ2VkO1xuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0R3JvdXBWYWx1ZSA9IGZ1bmN0aW9uIChjb2xLZXksIG5ld1ZhbHVlKSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmJlYW5zLmNvbHVtbk1vZGVsLmdldEdyaWRDb2x1bW4oY29sS2V5KTtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy5ncm91cERhdGEpKSB7XG4gICAgICAgICAgICB0aGlzLmdyb3VwRGF0YSA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2x1bW5JZCA9IGNvbHVtbi5nZXRDb2xJZCgpO1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLmdyb3VwRGF0YVtjb2x1bW5JZF07XG4gICAgICAgIGlmIChvbGRWYWx1ZSA9PT0gbmV3VmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdyb3VwRGF0YVtjb2x1bW5JZF0gPSBuZXdWYWx1ZTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaENlbGxDaGFuZ2VkRXZlbnQoY29sdW1uLCBuZXdWYWx1ZSwgb2xkVmFsdWUpO1xuICAgIH07XG4gICAgLy8gc2V0cyB0aGUgZGF0YSBmb3IgYW4gYWdncmVnYXRpb25cbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZXRBZ2dEYXRhID0gZnVuY3Rpb24gKG5ld0FnZ0RhdGEpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gZmluZCBvdXQgYWxsIGtleXMgdGhhdCBjb3VsZCBwb3RlbnRpYWxseSBjaGFuZ2VcbiAgICAgICAgdmFyIGNvbElkcyA9IGdldEFsbEtleXNJbk9iamVjdHMoW3RoaXMuYWdnRGF0YSwgbmV3QWdnRGF0YV0pO1xuICAgICAgICB2YXIgb2xkQWdnRGF0YSA9IHRoaXMuYWdnRGF0YTtcbiAgICAgICAgdGhpcy5hZ2dEYXRhID0gbmV3QWdnRGF0YTtcbiAgICAgICAgLy8gaWYgbm8gZXZlbnQgc2VydmljZSwgbm9ib2R5IGhhcyByZWdpc3RlcmVkIGZvciBldmVudHMsIHNvIG5vIG5lZWQgZmlyZSBldmVudFxuICAgICAgICBpZiAodGhpcy5ldmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgIGNvbElkcy5mb3JFYWNoKGZ1bmN0aW9uIChjb2xJZCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5nZXRHcmlkQ29sdW1uKGNvbElkKTtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBfdGhpcy5hZ2dEYXRhID8gX3RoaXMuYWdnRGF0YVtjb2xJZF0gOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdmFyIG9sZFZhbHVlID0gb2xkQWdnRGF0YSA/IG9sZEFnZ0RhdGFbY29sSWRdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoQ2VsbENoYW5nZWRFdmVudChjb2x1bW4sIHZhbHVlLCBvbGRWYWx1ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUudXBkYXRlSGFzQ2hpbGRyZW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHdlIG5lZWQgdG8gcmV0dXJuIHRydWUgd2hlbiB0aGlzLmdyb3VwPXRydWUsIGFzIHRoaXMgaXMgdXNlZCBieSBzZXJ2ZXIgc2lkZSByb3cgbW9kZWxcbiAgICAgICAgLy8gKGFzIGNoaWxkcmVuIGFyZSBsYXp5IGxvYWRlZCBhbmQgc3RvcmVkIGluIGEgY2FjaGUgYW55d2F5KS4gb3RoZXJ3aXNlIHdlIHJldHVybiB0cnVlXG4gICAgICAgIC8vIGlmIGNoaWxkcmVuIGV4aXN0LlxuICAgICAgICB2YXIgbmV3VmFsdWUgPSAodGhpcy5ncm91cCAmJiAhdGhpcy5mb290ZXIpIHx8ICh0aGlzLmNoaWxkcmVuQWZ0ZXJHcm91cCAmJiB0aGlzLmNoaWxkcmVuQWZ0ZXJHcm91cC5sZW5ndGggPiAwKTtcbiAgICAgICAgaWYgKG5ld1ZhbHVlICE9PSB0aGlzLl9faGFzQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHRoaXMuX19oYXNDaGlsZHJlbiA9ICEhbmV3VmFsdWU7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY3JlYXRlTG9jYWxSb3dFdmVudChSb3dOb2RlLkVWRU5UX0hBU19DSElMRFJFTl9DSEFOR0VEKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmhhc0NoaWxkcmVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5fX2hhc0NoaWxkcmVuID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSGFzQ2hpbGRyZW4oKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fX2hhc0NoaWxkcmVuO1xuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuaXNFbXB0eVJvd0dyb3VwTm9kZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JvdXAgJiYgbWlzc2luZ09yRW1wdHkodGhpcy5jaGlsZHJlbkFmdGVyR3JvdXApO1xuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuZGlzcGF0Y2hDZWxsQ2hhbmdlZEV2ZW50ID0gZnVuY3Rpb24gKGNvbHVtbiwgbmV3VmFsdWUsIG9sZFZhbHVlKSB7XG4gICAgICAgIHZhciBjZWxsQ2hhbmdlZEV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogUm93Tm9kZS5FVkVOVF9DRUxMX0NIQU5HRUQsXG4gICAgICAgICAgICBub2RlOiB0aGlzLFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICBvbGRWYWx1ZTogb2xkVmFsdWVcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaExvY2FsRXZlbnQoY2VsbENoYW5nZWRFdmVudCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBUaGUgZmlyc3QgdGltZSBgcXVpY2tGaWx0ZXJgIHJ1bnMsIHRoZSBncmlkIGNyZWF0ZXMgYSBvbmUtb2ZmIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgcm93LlxuICAgICAqIFRoaXMgc3RyaW5nIGlzIHRoZW4gdXNlZCBmb3IgdGhlIHF1aWNrIGZpbHRlciBpbnN0ZWFkIG9mIGhpdHRpbmcgZWFjaCBjb2x1bW4gc2VwYXJhdGVseS5cbiAgICAgKiBXaGVuIHlvdSBlZGl0LCB1c2luZyBncmlkIGVkaXRpbmcsIHRoaXMgc3RyaW5nIGdldHMgY2xlYXJlZCBkb3duLlxuICAgICAqIEhvd2V2ZXIgaWYgeW91IGVkaXQgd2l0aG91dCB1c2luZyBncmlkIGVkaXRpbmcsIHlvdSB3aWxsIG5lZWQgdG8gY2xlYXIgdGhpcyBzdHJpbmcgZG93biBmb3IgdGhlIHJvdyB0byBiZSB1cGRhdGVkIHdpdGggdGhlIG5ldyB2YWx1ZXMuXG4gICAgICogT3RoZXJ3aXNlIG5ldyB2YWx1ZXMgd2lsbCBub3Qgd29yayB3aXRoIHRoZSBgcXVpY2tGaWx0ZXJgLiAqL1xuICAgIFJvd05vZGUucHJvdG90eXBlLnJlc2V0UXVpY2tGaWx0ZXJBZ2dyZWdhdGVUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnF1aWNrRmlsdGVyQWdncmVnYXRlVGV4dCA9IG51bGw7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5pc0V4cGFuZGFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5oYXNDaGlsZHJlbigpICYmICF0aGlzLmZvb3RlcikgfHwgdGhpcy5tYXN0ZXIgPyB0cnVlIDogZmFsc2U7XG4gICAgfTtcbiAgICAvKiogUmV0dXJuczpcbiAgICAgKiAtIGB0cnVlYCBpZiBub2RlIGlzIHNlbGVjdGVkLFxuICAgICAqIC0gYGZhbHNlYCBpZiB0aGUgbm9kZSBpc24ndCBzZWxlY3RlZFxuICAgICAqIC0gYHVuZGVmaW5lZGAgaWYgaXQncyBwYXJ0aWFsbHkgc2VsZWN0ZWQgKGdyb3VwIHdoZXJlIG5vdCBhbGwgY2hpbGRyZW4gYXJlIHNlbGVjdGVkKS4gKi9cbiAgICBSb3dOb2RlLnByb3RvdHlwZS5pc1NlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBmb3IgZm9vdGVycywgd2UganVzdCByZXR1cm4gd2hhdCBvdXIgc2libGluZyBzZWxlY3RlZCBzdGF0ZSBpcywgYXMgY2Fubm90IHNlbGVjdCBhIGZvb3RlclxuICAgICAgICBpZiAodGhpcy5mb290ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpYmxpbmcuaXNTZWxlY3RlZCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkO1xuICAgIH07XG4gICAgLyoqIFBlcmZvcm0gYSBkZXB0aC1maXJzdCBzZWFyY2ggb2YgdGhpcyBub2RlIGFuZCBpdHMgY2hpbGRyZW4uICovXG4gICAgUm93Tm9kZS5wcm90b3R5cGUuZGVwdGhGaXJzdFNlYXJjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICBpZiAodGhpcy5jaGlsZHJlbkFmdGVyR3JvdXApIHtcbiAgICAgICAgICAgIHRoaXMuY2hpbGRyZW5BZnRlckdyb3VwLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7IHJldHVybiBjaGlsZC5kZXB0aEZpcnN0U2VhcmNoKGNhbGxiYWNrKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY2FsbGJhY2sodGhpcyk7XG4gICAgfTtcbiAgICAvLyArIHNlbGVjdGlvbkNvbnRyb2xsZXIuY2FsY3VsYXRlZFNlbGVjdGVkRm9yQWxsR3JvdXBOb2RlcygpXG4gICAgUm93Tm9kZS5wcm90b3R5cGUuY2FsY3VsYXRlU2VsZWN0ZWRGcm9tQ2hpbGRyZW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdmFyIGF0TGVhc3RPbmVTZWxlY3RlZCA9IGZhbHNlO1xuICAgICAgICB2YXIgYXRMZWFzdE9uZURlU2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGF0TGVhc3RPbmVNaXhlZCA9IGZhbHNlO1xuICAgICAgICBpZiAoISgoX2EgPSB0aGlzLmNoaWxkcmVuQWZ0ZXJHcm91cCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmxlbmd0aCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGFibGUgPyB0aGlzLnNlbGVjdGVkIDogbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY2hpbGRyZW5BZnRlckdyb3VwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGQgPSB0aGlzLmNoaWxkcmVuQWZ0ZXJHcm91cFtpXTtcbiAgICAgICAgICAgIHZhciBjaGlsZFN0YXRlID0gY2hpbGQuaXNTZWxlY3RlZCgpO1xuICAgICAgICAgICAgLy8gbm9uLXNlbGVjdGFibGUgbm9kZXMgbXVzdCBiZSBjYWxjdWxhdGVkIGZyb20gdGhlaXIgY2hpbGRyZW4sIG9yIGlnbm9yZWQgaWYgbm8gdmFsdWUgcmVzdWx0cy5cbiAgICAgICAgICAgIGlmICghY2hpbGQuc2VsZWN0YWJsZSkge1xuICAgICAgICAgICAgICAgIHZhciBzZWxlY3RhYmxlID0gY2hpbGQuY2FsY3VsYXRlU2VsZWN0ZWRGcm9tQ2hpbGRyZW4oKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0YWJsZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2hpbGRTdGF0ZSA9IHNlbGVjdGFibGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzd2l0Y2ggKGNoaWxkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIHRydWU6XG4gICAgICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVTZWxlY3RlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgZmFsc2U6XG4gICAgICAgICAgICAgICAgICAgIGF0TGVhc3RPbmVEZVNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgYXRMZWFzdE9uZU1peGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGF0TGVhc3RPbmVNaXhlZCB8fCAoYXRMZWFzdE9uZVNlbGVjdGVkICYmIGF0TGVhc3RPbmVEZVNlbGVjdGVkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChhdExlYXN0T25lU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGF0TGVhc3RPbmVEZVNlbGVjdGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXRoaXMuc2VsZWN0YWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RlZDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0U2VsZWN0ZWRJbml0aWFsVmFsdWUgPSBmdW5jdGlvbiAoc2VsZWN0ZWQpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZCA9IHNlbGVjdGVkO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogU2VsZWN0IChvciBkZXNlbGVjdCkgdGhlIG5vZGUuXG4gICAgICogQHBhcmFtIG5ld1ZhbHVlIC1gdHJ1ZWAgZm9yIHNlbGVjdGlvbiwgYGZhbHNlYCBmb3IgZGVzZWxlY3Rpb24uXG4gICAgICogQHBhcmFtIGNsZWFyU2VsZWN0aW9uIC0gSWYgc2VsZWN0aW5nLCB0aGVuIHBhc3NpbmcgYHRydWVgIHdpbGwgc2VsZWN0IHRoZSBub2RlIGV4Y2x1c2l2ZWx5IChpLmUuIE5PVCBkbyBtdWx0aSBzZWxlY3QpLiBJZiBkb2luZyBkZXNlbGVjdGlvbiwgYGNsZWFyU2VsZWN0aW9uYCBoYXMgbm8gaW1wYWN0LlxuICAgICAqIEBwYXJhbSBzdXBwcmVzc0ZpbmlzaEFjdGlvbnMgLSBQYXNzIGB0cnVlYCB0byBwcmV2ZW50IHRoZSBgc2VsZWN0aW9uQ2hhbmdlZGAgZnJvbSBiZWluZyBmaXJlZC4gTm90ZSB0aGF0IHRoZSBgcm93U2VsZWN0ZWRgIGV2ZW50IHdpbGwgc3RpbGwgYmUgZmlyZWQuXG4gICAgICovXG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0U2VsZWN0ZWQgPSBmdW5jdGlvbiAobmV3VmFsdWUsIGNsZWFyU2VsZWN0aW9uLCBzdXBwcmVzc0ZpbmlzaEFjdGlvbnMpIHtcbiAgICAgICAgaWYgKGNsZWFyU2VsZWN0aW9uID09PSB2b2lkIDApIHsgY2xlYXJTZWxlY3Rpb24gPSBmYWxzZTsgfVxuICAgICAgICBpZiAoc3VwcHJlc3NGaW5pc2hBY3Rpb25zID09PSB2b2lkIDApIHsgc3VwcHJlc3NGaW5pc2hBY3Rpb25zID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy5zZXRTZWxlY3RlZFBhcmFtcyh7XG4gICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICBjbGVhclNlbGVjdGlvbjogY2xlYXJTZWxlY3Rpb24sXG4gICAgICAgICAgICBzdXBwcmVzc0ZpbmlzaEFjdGlvbnM6IHN1cHByZXNzRmluaXNoQWN0aW9ucyxcbiAgICAgICAgICAgIHJhbmdlU2VsZWN0OiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFJvd05vZGUucHJvdG90eXBlLmlzUm93UGlubmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dQaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfVE9QIHx8IHRoaXMucm93UGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX0JPVFRPTTtcbiAgICB9O1xuICAgIC8vIHRvIG1ha2UgY2FsbGluZyBjb2RlIG1vcmUgcmVhZGFibGUsIHRoaXMgaXMgdGhlIHNhbWUgbWV0aG9kIGFzIHNldFNlbGVjdGVkIGV4Y2VwdCBpdCB0YWtlcyBuYW1lcyBwYXJhbWV0ZXJzXG4gICAgUm93Tm9kZS5wcm90b3R5cGUuc2V0U2VsZWN0ZWRQYXJhbXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdmFyIGdyb3VwU2VsZWN0c0NoaWxkcmVuID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFNlbGVjdHNDaGlsZHJlbigpO1xuICAgICAgICB2YXIgbmV3VmFsdWUgPSBwYXJhbXMubmV3VmFsdWUgPT09IHRydWU7XG4gICAgICAgIHZhciBjbGVhclNlbGVjdGlvbiA9IHBhcmFtcy5jbGVhclNlbGVjdGlvbiA9PT0gdHJ1ZTtcbiAgICAgICAgdmFyIHN1cHByZXNzRmluaXNoQWN0aW9ucyA9IHBhcmFtcy5zdXBwcmVzc0ZpbmlzaEFjdGlvbnMgPT09IHRydWU7XG4gICAgICAgIHZhciByYW5nZVNlbGVjdCA9IHBhcmFtcy5yYW5nZVNlbGVjdCA9PT0gdHJ1ZTtcbiAgICAgICAgLy8gZ3JvdXBTZWxlY3RzRmlsdGVyZWQgb25seSBtYWtlcyBzZW5zZSB3aGVuIGdyb3VwIHNlbGVjdHMgY2hpbGRyZW5cbiAgICAgICAgdmFyIGdyb3VwU2VsZWN0c0ZpbHRlcmVkID0gZ3JvdXBTZWxlY3RzQ2hpbGRyZW4gJiYgKHBhcmFtcy5ncm91cFNlbGVjdHNGaWx0ZXJlZCA9PT0gdHJ1ZSk7XG4gICAgICAgIGlmICh0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY2Fubm90IHNlbGVjdCBub2RlIHVudGlsIGlkIGZvciBub2RlIGlzIGtub3duJyk7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yb3dQaW5uZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY2Fubm90IHNlbGVjdCBwaW5uZWQgcm93cycpO1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgYXJlIGEgZm9vdGVyLCB3ZSBkb24ndCBkbyBzZWxlY3Rpb24sIGp1c3QgcGFzcyB0aGUgaW5mb1xuICAgICAgICAvLyB0byB0aGUgc2libGluZyAodGhlIHBhcmVudCBvZiB0aGUgZ3JvdXApXG4gICAgICAgIGlmICh0aGlzLmZvb3Rlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2libGluZy5zZXRTZWxlY3RlZFBhcmFtcyhwYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyYW5nZVNlbGVjdCAmJiB0aGlzLmJlYW5zLnNlbGVjdGlvblNlcnZpY2UuZ2V0TGFzdFNlbGVjdGVkTm9kZSgpKSB7XG4gICAgICAgICAgICB2YXIgbmV3Um93Q2xpY2tlZCA9IHRoaXMuYmVhbnMuc2VsZWN0aW9uU2VydmljZS5nZXRMYXN0U2VsZWN0ZWROb2RlKCkgIT09IHRoaXM7XG4gICAgICAgICAgICB2YXIgYWxsb3dNdWx0aVNlbGVjdCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93U2VsZWN0aW9uTXVsdGkoKTtcbiAgICAgICAgICAgIGlmIChuZXdSb3dDbGlja2VkICYmIGFsbG93TXVsdGlTZWxlY3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXNDaGFuZ2VkID0gdGhpcy5kb1Jvd1JhbmdlU2VsZWN0aW9uKHBhcmFtcy5uZXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5iZWFucy5zZWxlY3Rpb25TZXJ2aWNlLnNldExhc3RTZWxlY3RlZE5vZGUodGhpcyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzQ2hhbmdlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgdXBkYXRlZENvdW50ID0gMDtcbiAgICAgICAgLy8gd2hlbiBncm91cFNlbGVjdHNGaWx0ZXJlZCwgdGhlbiB0aGlzIG5vZGUgbWF5IGVuZCB1cCBpbnRlcm1lZGlhdGUgZGVzcGl0ZVxuICAgICAgICAvLyB0cnlpbmcgdG8gc2V0IGl0IHRvIHRydWUgLyBmYWxzZS4gdGhpcyBncm91cCB3aWxsIGJlIGNhbGN1bGF0ZWQgZnVydGhlciBvblxuICAgICAgICAvLyBkb3duIHdoZW4gd2UgY2FsbCBjYWxjdWxhdGVkU2VsZWN0ZWRGb3JBbGxHcm91cE5vZGVzKCkuIHdlIG5lZWQgdG8gc2tpcCBpdFxuICAgICAgICAvLyBoZXJlLCBvdGhlcndpc2UgdGhlIHVwZGF0ZWRDb3VudCB3b3VsZCBpbmNsdWRlIGl0LlxuICAgICAgICB2YXIgc2tpcFRoaXNOb2RlID0gZ3JvdXBTZWxlY3RzRmlsdGVyZWQgJiYgdGhpcy5ncm91cDtcbiAgICAgICAgaWYgKCFza2lwVGhpc05vZGUpIHtcbiAgICAgICAgICAgIHZhciB0aGlzTm9kZVdhc1NlbGVjdGVkID0gdGhpcy5zZWxlY3RUaGlzTm9kZShuZXdWYWx1ZSwgcGFyYW1zLmV2ZW50KTtcbiAgICAgICAgICAgIGlmICh0aGlzTm9kZVdhc1NlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlZENvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGdyb3VwU2VsZWN0c0NoaWxkcmVuICYmICgoX2EgPSB0aGlzLmNoaWxkcmVuQWZ0ZXJHcm91cCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmxlbmd0aCkpIHtcbiAgICAgICAgICAgIHVwZGF0ZWRDb3VudCArPSB0aGlzLnNlbGVjdENoaWxkTm9kZXMobmV3VmFsdWUsIGdyb3VwU2VsZWN0c0ZpbHRlcmVkKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjbGVhciBvdGhlciBub2RlcyBpZiBub3QgZG9pbmcgbXVsdGkgc2VsZWN0XG4gICAgICAgIGlmICghc3VwcHJlc3NGaW5pc2hBY3Rpb25zKSB7XG4gICAgICAgICAgICB2YXIgY2xlYXJPdGhlck5vZGVzID0gbmV3VmFsdWUgJiYgKGNsZWFyU2VsZWN0aW9uIHx8ICF0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd1NlbGVjdGlvbk11bHRpKCkpO1xuICAgICAgICAgICAgaWYgKGNsZWFyT3RoZXJOb2Rlcykge1xuICAgICAgICAgICAgICAgIHVwZGF0ZWRDb3VudCArPSB0aGlzLmJlYW5zLnNlbGVjdGlvblNlcnZpY2UuY2xlYXJPdGhlck5vZGVzKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gb25seSBpZiB3ZSBzZWxlY3RlZCBzb21ldGhpbmcsIHRoZW4gdXBkYXRlIGdyb3VwcyBhbmQgZmlyZSBldmVudHNcbiAgICAgICAgICAgIGlmICh1cGRhdGVkQ291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5iZWFucy5zZWxlY3Rpb25TZXJ2aWNlLnVwZGF0ZUdyb3Vwc0Zyb21DaGlsZHJlblNlbGVjdGlvbnMoKTtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB2ZXJ5IGVuZCBvZiB0aGUgJ2FjdGlvbiBub2RlJywgc28gd2UgYXJlIGZpbmlzaGVkIGFsbCB0aGUgdXBkYXRlcyxcbiAgICAgICAgICAgICAgICAvLyBpbmNsdWRlIGFueSBwYXJlbnQgLyBjaGlsZCBjaGFuZ2VzIHRoYXQgdGhpcyBtZXRob2QgY2F1c2VkXG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50XzEgPSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9TRUxFQ1RJT05fQ0hBTkdFRFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5iZWFucy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHNvIGlmIHVzZXIgbmV4dCBkb2VzIHNoaWZ0LXNlbGVjdCwgd2Uga25vdyB3aGVyZSB0byBzdGFydCB0aGUgc2VsZWN0aW9uIGZyb21cbiAgICAgICAgICAgIGlmIChuZXdWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYmVhbnMuc2VsZWN0aW9uU2VydmljZS5zZXRMYXN0U2VsZWN0ZWROb2RlKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1cGRhdGVkQ291bnQ7XG4gICAgfTtcbiAgICAvLyBzZWxlY3RzIGFsbCByb3dzIGJldHdlZW4gdGhpcyBub2RlIGFuZCB0aGUgbGFzdCBzZWxlY3RlZCBub2RlIChvciB0aGUgdG9wIGlmIHRoaXMgaXMgdGhlIGZpcnN0IHNlbGVjdGlvbikuXG4gICAgLy8gbm90IHRvIGJlIG1peGVkIHVwIHdpdGggJ2NlbGwgcmFuZ2Ugc2VsZWN0aW9uJyB3aGVyZSB5b3UgZHJhZyB0aGUgbW91c2UsIHRoaXMgaXMgcm93IHJhbmdlIHNlbGVjdGlvbiwgYnlcbiAgICAvLyBob2xkaW5nIGRvd24gJ3NoaWZ0Jy5cbiAgICBSb3dOb2RlLnByb3RvdHlwZS5kb1Jvd1JhbmdlU2VsZWN0aW9uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7IHZhbHVlID0gdHJ1ZTsgfVxuICAgICAgICB2YXIgZ3JvdXBzU2VsZWN0Q2hpbGRyZW4gPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU2VsZWN0c0NoaWxkcmVuKCk7XG4gICAgICAgIHZhciBsYXN0U2VsZWN0ZWROb2RlID0gdGhpcy5iZWFucy5zZWxlY3Rpb25TZXJ2aWNlLmdldExhc3RTZWxlY3RlZE5vZGUoKTtcbiAgICAgICAgdmFyIG5vZGVzVG9TZWxlY3QgPSB0aGlzLmJlYW5zLnJvd01vZGVsLmdldE5vZGVzSW5SYW5nZUZvclNlbGVjdGlvbih0aGlzLCBsYXN0U2VsZWN0ZWROb2RlKTtcbiAgICAgICAgdmFyIHVwZGF0ZWRDb3VudCA9IDA7XG4gICAgICAgIG5vZGVzVG9TZWxlY3QuZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHJvd05vZGUuZ3JvdXAgJiYgZ3JvdXBzU2VsZWN0Q2hpbGRyZW4gfHwgKHZhbHVlID09PSBmYWxzZSAmJiBfdGhpcyA9PT0gcm93Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbm9kZVdhc1NlbGVjdGVkID0gcm93Tm9kZS5zZWxlY3RUaGlzTm9kZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAobm9kZVdhc1NlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlZENvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmJlYW5zLnNlbGVjdGlvblNlcnZpY2UudXBkYXRlR3JvdXBzRnJvbUNoaWxkcmVuU2VsZWN0aW9ucygpO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfU0VMRUNUSU9OX0NIQU5HRURcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5iZWFucy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgICAgIHJldHVybiB1cGRhdGVkQ291bnQ7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5pc1BhcmVudE9mTm9kZSA9IGZ1bmN0aW9uIChwb3RlbnRpYWxQYXJlbnQpIHtcbiAgICAgICAgdmFyIHBhcmVudE5vZGUgPSB0aGlzLnBhcmVudDtcbiAgICAgICAgd2hpbGUgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIGlmIChwYXJlbnROb2RlID09PSBwb3RlbnRpYWxQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmVudE5vZGUgPSBwYXJlbnROb2RlLnBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZWxlY3RUaGlzTm9kZSA9IGZ1bmN0aW9uIChuZXdWYWx1ZSwgZSkge1xuICAgICAgICAvLyB3ZSBvbmx5IGNoZWNrIHNlbGVjdGFibGUgd2hlbiBuZXdWYWx1ZT10cnVlIChpZSBzZWxlY3RpbmcpIHRvIGFsbG93IHVuc2VsZWN0aW5nIHZhbHVlcyxcbiAgICAgICAgLy8gYXMgc2VsZWN0YWJsZSBpcyBkeW5hbWljLCBuZWVkIGEgd2F5IHRvIHVuc2VsZWN0IHJvd3Mgd2hlbiBzZWxlY3RhYmxlIGJlY29tZXMgZmFsc2UuXG4gICAgICAgIHZhciBzZWxlY3Rpb25Ob3RBbGxvd2VkID0gIXRoaXMuc2VsZWN0YWJsZSAmJiBuZXdWYWx1ZTtcbiAgICAgICAgdmFyIHNlbGVjdGlvbk5vdENoYW5nZWQgPSB0aGlzLnNlbGVjdGVkID09PSBuZXdWYWx1ZTtcbiAgICAgICAgaWYgKHNlbGVjdGlvbk5vdEFsbG93ZWQgfHwgc2VsZWN0aW9uTm90Q2hhbmdlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0ZWQgPSBuZXdWYWx1ZTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoTG9jYWxFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9ST1dfU0VMRUNURUQpKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXZlbnQgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmNyZWF0ZUdsb2JhbFJvd0V2ZW50KEV2ZW50cy5FVkVOVF9ST1dfU0VMRUNURUQpLCB7XG4gICAgICAgICAgICBldmVudDogZSB8fCBudWxsXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5zZWxlY3RDaGlsZE5vZGVzID0gZnVuY3Rpb24gKG5ld1ZhbHVlLCBncm91cFNlbGVjdHNGaWx0ZXJlZCkge1xuICAgICAgICB2YXIgY2hpbGRyZW4gPSBncm91cFNlbGVjdHNGaWx0ZXJlZCA/IHRoaXMuY2hpbGRyZW5BZnRlckFnZ0ZpbHRlciA6IHRoaXMuY2hpbGRyZW5BZnRlckdyb3VwO1xuICAgICAgICBpZiAobWlzc2luZyhjaGlsZHJlbikpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1cGRhdGVkQ291bnQgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB1cGRhdGVkQ291bnQgKz0gY2hpbGRyZW5baV0uc2V0U2VsZWN0ZWRQYXJhbXMoe1xuICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiBuZXdWYWx1ZSxcbiAgICAgICAgICAgICAgICBjbGVhclNlbGVjdGlvbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgc3VwcHJlc3NGaW5pc2hBY3Rpb25zOiB0cnVlLFxuICAgICAgICAgICAgICAgIGdyb3VwU2VsZWN0c0ZpbHRlcmVkOiBncm91cFNlbGVjdHNGaWx0ZXJlZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVwZGF0ZWRDb3VudDtcbiAgICB9O1xuICAgIC8qKiBBZGQgYW4gZXZlbnQgbGlzdGVuZXIuICovXG4gICAgUm93Tm9kZS5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghdGhpcy5ldmVudFNlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlID0gbmV3IEV2ZW50U2VydmljZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICAvKiogUmVtb3ZlIGV2ZW50IGxpc3RlbmVyLiAqL1xuICAgIFJvd05vZGUucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIXRoaXMuZXZlbnRTZXJ2aWNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRTZXJ2aWNlLm5vUmVnaXN0ZXJlZExpc3RlbmVyc0V4aXN0KCkpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUub25Nb3VzZUVudGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoTG9jYWxFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9NT1VTRV9FTlRFUikpO1xuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUub25Nb3VzZUxlYXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoTG9jYWxFdmVudCh0aGlzLmNyZWF0ZUxvY2FsUm93RXZlbnQoUm93Tm9kZS5FVkVOVF9NT1VTRV9MRUFWRSkpO1xuICAgIH07XG4gICAgUm93Tm9kZS5wcm90b3R5cGUuZ2V0Rmlyc3RDaGlsZE9mRmlyc3RDaGlsZCA9IGZ1bmN0aW9uIChyb3dHcm91cENvbHVtbikge1xuICAgICAgICB2YXIgY3VycmVudFJvd05vZGUgPSB0aGlzO1xuICAgICAgICB2YXIgaXNDYW5kaWRhdGUgPSB0cnVlO1xuICAgICAgICB2YXIgZm91bmRGaXJzdENoaWxkUGF0aCA9IGZhbHNlO1xuICAgICAgICB2YXIgbm9kZVRvU3dhcEluID0gbnVsbDtcbiAgICAgICAgLy8gaWYgd2UgYXJlIGhpZGluZyBncm91cHMsIHRoZW4gaWYgd2UgYXJlIHRoZSBmaXJzdCBjaGlsZCwgb2YgdGhlIGZpcnN0IGNoaWxkLFxuICAgICAgICAvLyBhbGwgdGhlIHdheSB1cCB0byB0aGUgY29sdW1uIHdlIGFyZSBpbnRlcmVzdGVkIGluLCB0aGVuIHdlIHNob3cgdGhlIGdyb3VwIGNlbGwuXG4gICAgICAgIHdoaWxlIChpc0NhbmRpZGF0ZSAmJiAhZm91bmRGaXJzdENoaWxkUGF0aCkge1xuICAgICAgICAgICAgdmFyIHBhcmVudFJvd05vZGUgPSBjdXJyZW50Um93Tm9kZS5wYXJlbnQ7XG4gICAgICAgICAgICB2YXIgZmlyc3RDaGlsZCA9IGV4aXN0cyhwYXJlbnRSb3dOb2RlKSAmJiBjdXJyZW50Um93Tm9kZS5maXJzdENoaWxkO1xuICAgICAgICAgICAgaWYgKGZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Um93Tm9kZS5yb3dHcm91cENvbHVtbiA9PT0gcm93R3JvdXBDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZm91bmRGaXJzdENoaWxkUGF0aCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVUb1N3YXBJbiA9IHBhcmVudFJvd05vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaXNDYW5kaWRhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRSb3dOb2RlID0gcGFyZW50Um93Tm9kZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZm91bmRGaXJzdENoaWxkUGF0aCA/IG5vZGVUb1N3YXBJbiA6IG51bGw7XG4gICAgfTtcbiAgICBSb3dOb2RlLnByb3RvdHlwZS5pc0Z1bGxXaWR0aENlbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc0Z1bGxXaWR0aENlbGxGdW5jID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0SXNGdWxsV2lkdGhDZWxsRnVuYygpO1xuICAgICAgICByZXR1cm4gaXNGdWxsV2lkdGhDZWxsRnVuYyA/IGlzRnVsbFdpZHRoQ2VsbEZ1bmMoeyByb3dOb2RlOiB0aGlzIH0pIDogZmFsc2U7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByb3V0ZSBvZiB0aGUgcm93IG5vZGUuIElmIHRoZSBSb3cgTm9kZSBpcyBhIGdyb3VwLCBpdCByZXR1cm5zIHRoZSByb3V0ZSB0byB0aGF0IFJvdyBOb2RlLlxuICAgICAqIElmIHRoZSBSb3cgTm9kZSBpcyBub3QgYSBncm91cCwgaXQgcmV0dXJucyBgdW5kZWZpbmVkYC5cbiAgICAgKi9cbiAgICBSb3dOb2RlLnByb3RvdHlwZS5nZXRSb3V0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMua2V5ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzID0gW107XG4gICAgICAgIHZhciBwb2ludGVyID0gdGhpcztcbiAgICAgICAgd2hpbGUgKHBvaW50ZXIua2V5ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKHBvaW50ZXIua2V5KTtcbiAgICAgICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzLnJldmVyc2UoKTtcbiAgICB9O1xuICAgIFJvd05vZGUuSURfUFJFRklYX1JPV19HUk9VUCA9ICdyb3ctZ3JvdXAtJztcbiAgICBSb3dOb2RlLklEX1BSRUZJWF9UT1BfUElOTkVEID0gJ3QtJztcbiAgICBSb3dOb2RlLklEX1BSRUZJWF9CT1RUT01fUElOTkVEID0gJ2ItJztcbiAgICBSb3dOb2RlLk9CSkVDVF9JRF9TRVFVRU5DRSA9IDA7XG4gICAgUm93Tm9kZS5FVkVOVF9ST1dfU0VMRUNURUQgPSAncm93U2VsZWN0ZWQnO1xuICAgIFJvd05vZGUuRVZFTlRfREFUQV9DSEFOR0VEID0gJ2RhdGFDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0NFTExfQ0hBTkdFRCA9ICdjZWxsQ2hhbmdlZCc7XG4gICAgUm93Tm9kZS5FVkVOVF9BTExfQ0hJTERSRU5fQ09VTlRfQ0hBTkdFRCA9ICdhbGxDaGlsZHJlbkNvdW50Q2hhbmdlZCc7XG4gICAgUm93Tm9kZS5FVkVOVF9NQVNURVJfQ0hBTkdFRCA9ICdtYXN0ZXJDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0dST1VQX0NIQU5HRUQgPSAnZ3JvdXBDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX01PVVNFX0VOVEVSID0gJ21vdXNlRW50ZXInO1xuICAgIFJvd05vZGUuRVZFTlRfTU9VU0VfTEVBVkUgPSAnbW91c2VMZWF2ZSc7XG4gICAgUm93Tm9kZS5FVkVOVF9IRUlHSFRfQ0hBTkdFRCA9ICdoZWlnaHRDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX1RPUF9DSEFOR0VEID0gJ3RvcENoYW5nZWQnO1xuICAgIFJvd05vZGUuRVZFTlRfRElTUExBWUVEX0NIQU5HRUQgPSAnZGlzcGxheWVkQ2hhbmdlZCc7XG4gICAgUm93Tm9kZS5FVkVOVF9GSVJTVF9DSElMRF9DSEFOR0VEID0gJ2ZpcnN0Q2hpbGRDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0xBU1RfQ0hJTERfQ0hBTkdFRCA9ICdsYXN0Q2hpbGRDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0NISUxEX0lOREVYX0NIQU5HRUQgPSAnY2hpbGRJbmRleENoYW5nZWQnO1xuICAgIFJvd05vZGUuRVZFTlRfUk9XX0lOREVYX0NIQU5HRUQgPSAncm93SW5kZXhDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0VYUEFOREVEX0NIQU5HRUQgPSAnZXhwYW5kZWRDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0hBU19DSElMRFJFTl9DSEFOR0VEID0gJ2hhc0NoaWxkcmVuQ2hhbmdlZCc7XG4gICAgUm93Tm9kZS5FVkVOVF9TRUxFQ1RBQkxFX0NIQU5HRUQgPSAnc2VsZWN0YWJsZUNoYW5nZWQnO1xuICAgIFJvd05vZGUuRVZFTlRfVUlfTEVWRUxfQ0hBTkdFRCA9ICd1aUxldmVsQ2hhbmdlZCc7XG4gICAgUm93Tm9kZS5FVkVOVF9ISUdITElHSFRfQ0hBTkdFRCA9ICdyb3dIaWdobGlnaHRDaGFuZ2VkJztcbiAgICBSb3dOb2RlLkVWRU5UX0RSQUdHSU5HX0NIQU5HRUQgPSAnZHJhZ2dpbmdDaGFuZ2VkJztcbiAgICByZXR1cm4gUm93Tm9kZTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMmkgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiQ5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiQ5ID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiQ5LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fZGVjb3JhdGUkMjEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmkoQ2hlY2tib3hTZWxlY3Rpb25Db21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ2hlY2tib3hTZWxlY3Rpb25Db21wb25lbnQoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCAvKiBodG1sKi8gXCJcXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1zZWxlY3Rpb24tY2hlY2tib3hcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxhZy1jaGVja2JveCByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiIHJlZj1cXFwiZUNoZWNrYm94XFxcIj48L2FnLWNoZWNrYm94PlxcbiAgICAgICAgICAgIDwvZGl2PlwiKSB8fCB0aGlzO1xuICAgIH1cbiAgICBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5lQ2hlY2tib3guc2V0UGFzc2l2ZSh0cnVlKTtcbiAgICB9O1xuICAgIENoZWNrYm94U2VsZWN0aW9uQ29tcG9uZW50LnByb3RvdHlwZS5nZXRDaGVja2JveElkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lQ2hlY2tib3guZ2V0SW5wdXRFbGVtZW50KCkuaWQ7XG4gICAgfTtcbiAgICBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudC5wcm90b3R5cGUub25EYXRhQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2hlbiByb3dzIGFyZSBsb2FkZWQgZm9yIHRoZSBzZWNvbmQgdGltZSwgdGhpcyBjYW4gaW1wYWN0IHRoZSBzZWxlY3Rpb24sIGFzIGEgcm93XG4gICAgICAgIC8vIGNvdWxkIGJlIGxvYWRlZCBhcyBhbHJlYWR5IHNlbGVjdGVkIChpZiB1c2VyIHNjcm9sbHMgZG93biwgYW5kIHRoZW4gdXAgYWdhaW4pLlxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZCgpO1xuICAgIH07XG4gICAgQ2hlY2tib3hTZWxlY3Rpb25Db21wb25lbnQucHJvdG90eXBlLm9uU2VsZWN0YWJsZUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2hvd09ySGlkZVNlbGVjdCgpO1xuICAgIH07XG4gICAgQ2hlY2tib3hTZWxlY3Rpb25Db21wb25lbnQucHJvdG90eXBlLm9uU2VsZWN0aW9uQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBzdGF0ZSA9IHRoaXMucm93Tm9kZS5pc1NlbGVjdGVkKCk7XG4gICAgICAgIHZhciBzdGF0ZU5hbWUgPSBzdGF0ZSA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IHRyYW5zbGF0ZSgnYXJpYUluZGV0ZXJtaW5hdGUnLCAnaW5kZXRlcm1pbmF0ZScpXG4gICAgICAgICAgICA6IChzdGF0ZSA9PT0gdHJ1ZVxuICAgICAgICAgICAgICAgID8gdHJhbnNsYXRlKCdhcmlhQ2hlY2tlZCcsICdjaGVja2VkJylcbiAgICAgICAgICAgICAgICA6IHRyYW5zbGF0ZSgnYXJpYVVuY2hlY2tlZCcsICd1bmNoZWNrZWQnKSk7XG4gICAgICAgIHZhciBhcmlhTGFiZWwgPSB0cmFuc2xhdGUoJ2FyaWFSb3dUb2dnbGVTZWxlY3Rpb24nLCAnUHJlc3MgU3BhY2UgdG8gdG9nZ2xlIHJvdyBzZWxlY3Rpb24nKTtcbiAgICAgICAgdGhpcy5lQ2hlY2tib3guc2V0VmFsdWUoc3RhdGUsIHRydWUpO1xuICAgICAgICB0aGlzLmVDaGVja2JveC5zZXRJbnB1dEFyaWFMYWJlbChhcmlhTGFiZWwgKyBcIiAoXCIgKyBzdGF0ZU5hbWUgKyBcIilcIik7XG4gICAgfTtcbiAgICBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudC5wcm90b3R5cGUub25DaGVja2VkQ2xpY2tlZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgZ3JvdXBTZWxlY3RzRmlsdGVyZWQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU2VsZWN0c0ZpbHRlcmVkKCk7XG4gICAgICAgIHZhciB1cGRhdGVkQ291bnQgPSB0aGlzLnJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoeyBuZXdWYWx1ZTogZmFsc2UsIHJhbmdlU2VsZWN0OiBldmVudC5zaGlmdEtleSwgZ3JvdXBTZWxlY3RzRmlsdGVyZWQ6IGdyb3VwU2VsZWN0c0ZpbHRlcmVkIH0pO1xuICAgICAgICByZXR1cm4gdXBkYXRlZENvdW50O1xuICAgIH07XG4gICAgQ2hlY2tib3hTZWxlY3Rpb25Db21wb25lbnQucHJvdG90eXBlLm9uVW5jaGVja2VkQ2xpY2tlZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgZ3JvdXBTZWxlY3RzRmlsdGVyZWQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU2VsZWN0c0ZpbHRlcmVkKCk7XG4gICAgICAgIHZhciB1cGRhdGVkQ291bnQgPSB0aGlzLnJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoeyBuZXdWYWx1ZTogdHJ1ZSwgcmFuZ2VTZWxlY3Q6IGV2ZW50LnNoaWZ0S2V5LCBncm91cFNlbGVjdHNGaWx0ZXJlZDogZ3JvdXBTZWxlY3RzRmlsdGVyZWQgfSk7XG4gICAgICAgIHJldHVybiB1cGRhdGVkQ291bnQ7XG4gICAgfTtcbiAgICBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5yb3dOb2RlID0gcGFyYW1zLnJvd05vZGU7XG4gICAgICAgIHRoaXMuY29sdW1uID0gcGFyYW1zLmNvbHVtbjtcbiAgICAgICAgdGhpcy5vdmVycmlkZXMgPSBwYXJhbXMub3ZlcnJpZGVzO1xuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZCgpO1xuICAgICAgICAvLyB3ZSBkb24ndCB3YW50IGRvdWJsZSBjbGljayBvbiB0aGlzIGljb24gdG8gb3BlbiBhIGdyb3VwXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUNoZWNrYm94LmdldElucHV0RWxlbWVudCgpLCAnZGJsY2xpY2snLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHN0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChldmVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVDaGVja2JveC5nZXRJbnB1dEVsZW1lbnQoKSwgJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAvLyB3ZSBkb24ndCB3YW50IHRoZSByb3cgY2xpY2tlZCBldmVudCB0byBmaXJlIHdoZW4gc2VsZWN0aW5nIHRoZSBjaGVja2JveCwgb3RoZXJ3aXNlIHRoZSByb3dcbiAgICAgICAgICAgIC8vIHdvdWxkIHBvc3NpYmx5IGdldCBzZWxlY3RlZCB0d2ljZVxuICAgICAgICAgICAgc3RvcFByb3BhZ2F0aW9uRm9yQWdHcmlkKGV2ZW50KTtcbiAgICAgICAgICAgIHZhciBpc1NlbGVjdGVkID0gX3RoaXMuZUNoZWNrYm94LmdldFZhbHVlKCk7XG4gICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IF90aGlzLmVDaGVja2JveC5nZXRQcmV2aW91c1ZhbHVlKCk7XG4gICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IGlzU2VsZWN0ZWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIC8vIEluZGV0ZXJtaW5hdGUgc3RhdGUgLSB0cnkgdG9nZ2xpbmcgY2hpbGRyZW4gdG8gZGV0ZXJtaW5lIGFjdGlvbi5cbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gX3RoaXMub25VbmNoZWNrZWRDbGlja2VkKGV2ZW50IHx8IHt9KTtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9uQ2hlY2tlZENsaWNrZWQoZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlzU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5vbkNoZWNrZWRDbGlja2VkKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIF90aGlzLm9uVW5jaGVja2VkQ2xpY2tlZChldmVudCB8fCB7fSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfUk9XX1NFTEVDVEVELCB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX0RBVEFfQ0hBTkdFRCwgdGhpcy5vbkRhdGFDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfU0VMRUNUQUJMRV9DSEFOR0VELCB0aGlzLm9uU2VsZWN0YWJsZUNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHZhciBpc1Jvd1NlbGVjdGFibGVGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0SXNSb3dTZWxlY3RhYmxlRnVuYygpO1xuICAgICAgICB2YXIgY2hlY2tib3hWaXNpYmxlSXNEeW5hbWljID0gaXNSb3dTZWxlY3RhYmxlRnVuYyB8fCB0eXBlb2YgdGhpcy5nZXRJc1Zpc2libGUoKSA9PT0gJ2Z1bmN0aW9uJztcbiAgICAgICAgaWYgKGNoZWNrYm94VmlzaWJsZUlzRHluYW1pYykge1xuICAgICAgICAgICAgdmFyIHNob3dPckhpZGVTZWxlY3RMaXN0ZW5lciA9IHRoaXMuc2hvd09ySGlkZVNlbGVjdC5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19DSEFOR0VELCBzaG93T3JIaWRlU2VsZWN0TGlzdGVuZXIpO1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX0RBVEFfQ0hBTkdFRCwgc2hvd09ySGlkZVNlbGVjdExpc3RlbmVyKTtcbiAgICAgICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9DRUxMX0NIQU5HRUQsIHNob3dPckhpZGVTZWxlY3RMaXN0ZW5lcik7XG4gICAgICAgICAgICB0aGlzLnNob3dPckhpZGVTZWxlY3QoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVDaGVja2JveC5nZXRJbnB1dEVsZW1lbnQoKS5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJy0xJyk7XG4gICAgfTtcbiAgICBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudC5wcm90b3R5cGUuc2hvd09ySGlkZVNlbGVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kO1xuICAgICAgICAvLyBpZiB0aGUgaXNSb3dTZWxlY3RhYmxlKCkgaXMgbm90IHByb3ZpZGVkIHRoZSByb3cgbm9kZSBpcyBzZWxlY3RhYmxlIGJ5IGRlZmF1bHRcbiAgICAgICAgdmFyIHNlbGVjdGFibGUgPSB0aGlzLnJvd05vZGUuc2VsZWN0YWJsZTtcbiAgICAgICAgLy8gY2hlY2tib3hTZWxlY3Rpb24gY2FsbGJhY2sgaXMgZGVlbWVkIGEgbGVnYWN5IHNvbHV0aW9uIGhvd2V2ZXIgd2Ugd2lsbCBzdGlsbCBjb25zaWRlciBpdCdzIHJlc3VsdC5cbiAgICAgICAgLy8gSWYgc2VsZWN0YWJsZSwgdGhlbiBhbHNvIGNoZWNrIHRoZSBjb2xEZWYgY2FsbGJhY2suIGlmIG5vdCBzZWxlY3RhYmxlLCB0aGlzIGl0IHNob3J0IGNpcmN1aXRzIC0gbm8gbmVlZFxuICAgICAgICAvLyB0byBjYWxsIHRoZSBjb2xEZWYgY2FsbGJhY2suXG4gICAgICAgIHZhciBpc1Zpc2libGUgPSB0aGlzLmdldElzVmlzaWJsZSgpO1xuICAgICAgICBpZiAoc2VsZWN0YWJsZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBpc1Zpc2libGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXh0cmFQYXJhbXMgPSAoX2EgPSB0aGlzLm92ZXJyaWRlcykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNhbGxiYWNrUGFyYW1zO1xuICAgICAgICAgICAgICAgIHZhciBwYXJhbXMgPSAoX2IgPSB0aGlzLmNvbHVtbikgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmNyZWF0ZUNvbHVtbkZ1bmN0aW9uQ2FsbGJhY2tQYXJhbXModGhpcy5yb3dOb2RlKTtcbiAgICAgICAgICAgICAgICBzZWxlY3RhYmxlID0gcGFyYW1zID8gaXNWaXNpYmxlKF9fYXNzaWduJDkoX19hc3NpZ24kOSh7fSwgZXh0cmFQYXJhbXMpLCBwYXJhbXMpKSA6IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0YWJsZSA9IChpc1Zpc2libGUgIT09IG51bGwgJiYgaXNWaXNpYmxlICE9PSB2b2lkIDAgPyBpc1Zpc2libGUgOiBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRpc2FibGVJbnN0ZWFkT2ZIaWRlID0gKF9jID0gdGhpcy5jb2x1bW4pID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5nZXRDb2xEZWYoKS5zaG93RGlzYWJsZWRDaGVja2JveGVzO1xuICAgICAgICBpZiAoZGlzYWJsZUluc3RlYWRPZkhpZGUpIHtcbiAgICAgICAgICAgIHRoaXMuZUNoZWNrYm94LnNldERpc2FibGVkKCFzZWxlY3RhYmxlKTtcbiAgICAgICAgICAgIHRoaXMuc2V0VmlzaWJsZSh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuc2V0RGlzcGxheWVkKHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoX2QgPSB0aGlzLm92ZXJyaWRlcykgPT09IG51bGwgfHwgX2QgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kLnJlbW92ZUhpZGRlbikge1xuICAgICAgICAgICAgdGhpcy5zZXREaXNwbGF5ZWQoc2VsZWN0YWJsZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRWaXNpYmxlKHNlbGVjdGFibGUpO1xuICAgIH07XG4gICAgQ2hlY2tib3hTZWxlY3Rpb25Db21wb25lbnQucHJvdG90eXBlLmdldElzVmlzaWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgaWYgKHRoaXMub3ZlcnJpZGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vdmVycmlkZXMuaXNWaXNpYmxlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbHVtbiB3aWxsIGJlIG1pc3NpbmcgaWYgZ3JvdXBVc2VFbnRpcmVSb3c9dHJ1ZVxuICAgICAgICByZXR1cm4gKF9iID0gKF9hID0gdGhpcy5jb2x1bW4pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5nZXRDb2xEZWYoKSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmNoZWNrYm94U2VsZWN0aW9uO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQyMShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ2hlY2tib3gnKVxuICAgIF0sIENoZWNrYm94U2VsZWN0aW9uQ29tcG9uZW50LnByb3RvdHlwZSwgXCJlQ2hlY2tib3hcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDIxKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIENoZWNrYm94U2VsZWN0aW9uQ29tcG9uZW50LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMmggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDIwID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX192YWx1ZXMkMyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fdmFsdWVzKSB8fCBmdW5jdGlvbihvKSB7XG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcbiAgICBpZiAobyAmJiB0eXBlb2Ygby5sZW5ndGggPT09IFwibnVtYmVyXCIpIHJldHVybiB7XG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IocyA/IFwiT2JqZWN0IGlzIG5vdCBpdGVyYWJsZS5cIiA6IFwiU3ltYm9sLml0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcbn07XG52YXIgRHJhZ1NvdXJjZVR5cGU7XG4oZnVuY3Rpb24gKERyYWdTb3VyY2VUeXBlKSB7XG4gICAgRHJhZ1NvdXJjZVR5cGVbRHJhZ1NvdXJjZVR5cGVbXCJUb29sUGFuZWxcIl0gPSAwXSA9IFwiVG9vbFBhbmVsXCI7XG4gICAgRHJhZ1NvdXJjZVR5cGVbRHJhZ1NvdXJjZVR5cGVbXCJIZWFkZXJDZWxsXCJdID0gMV0gPSBcIkhlYWRlckNlbGxcIjtcbiAgICBEcmFnU291cmNlVHlwZVtEcmFnU291cmNlVHlwZVtcIlJvd0RyYWdcIl0gPSAyXSA9IFwiUm93RHJhZ1wiO1xuICAgIERyYWdTb3VyY2VUeXBlW0RyYWdTb3VyY2VUeXBlW1wiQ2hhcnRQYW5lbFwiXSA9IDNdID0gXCJDaGFydFBhbmVsXCI7XG59KShEcmFnU291cmNlVHlwZSB8fCAoRHJhZ1NvdXJjZVR5cGUgPSB7fSkpO1xudmFyIFZlcnRpY2FsRGlyZWN0aW9uO1xuKGZ1bmN0aW9uIChWZXJ0aWNhbERpcmVjdGlvbikge1xuICAgIFZlcnRpY2FsRGlyZWN0aW9uW1ZlcnRpY2FsRGlyZWN0aW9uW1wiVXBcIl0gPSAwXSA9IFwiVXBcIjtcbiAgICBWZXJ0aWNhbERpcmVjdGlvbltWZXJ0aWNhbERpcmVjdGlvbltcIkRvd25cIl0gPSAxXSA9IFwiRG93blwiO1xufSkoVmVydGljYWxEaXJlY3Rpb24gfHwgKFZlcnRpY2FsRGlyZWN0aW9uID0ge30pKTtcbnZhciBIb3Jpem9udGFsRGlyZWN0aW9uO1xuKGZ1bmN0aW9uIChIb3Jpem9udGFsRGlyZWN0aW9uKSB7XG4gICAgSG9yaXpvbnRhbERpcmVjdGlvbltIb3Jpem9udGFsRGlyZWN0aW9uW1wiTGVmdFwiXSA9IDBdID0gXCJMZWZ0XCI7XG4gICAgSG9yaXpvbnRhbERpcmVjdGlvbltIb3Jpem9udGFsRGlyZWN0aW9uW1wiUmlnaHRcIl0gPSAxXSA9IFwiUmlnaHRcIjtcbn0pKEhvcml6b250YWxEaXJlY3Rpb24gfHwgKEhvcml6b250YWxEaXJlY3Rpb24gPSB7fSkpO1xudmFyIERyYWdBbmREcm9wU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmgoRHJhZ0FuZERyb3BTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERyYWdBbmREcm9wU2VydmljZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmRyYWdTb3VyY2VBbmRQYXJhbXNMaXN0ID0gW107XG4gICAgICAgIF90aGlzLmRyb3BUYXJnZXRzID0gW107XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlXzEgPSBEcmFnQW5kRHJvcFNlcnZpY2U7XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmVQaW5uZWRJY29uID0gY3JlYXRlSWNvbignY29sdW1uTW92ZVBpbicsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgdGhpcy5lSGlkZUljb24gPSBjcmVhdGVJY29uKCdjb2x1bW5Nb3ZlSGlkZScsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgdGhpcy5lTW92ZUljb24gPSBjcmVhdGVJY29uKCdjb2x1bW5Nb3ZlTW92ZScsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgdGhpcy5lTGVmdEljb24gPSBjcmVhdGVJY29uKCdjb2x1bW5Nb3ZlTGVmdCcsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgdGhpcy5lUmlnaHRJY29uID0gY3JlYXRlSWNvbignY29sdW1uTW92ZVJpZ2h0JywgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIG51bGwpO1xuICAgICAgICB0aGlzLmVHcm91cEljb24gPSBjcmVhdGVJY29uKCdjb2x1bW5Nb3ZlR3JvdXAnLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCk7XG4gICAgICAgIHRoaXMuZUFnZ3JlZ2F0ZUljb24gPSBjcmVhdGVJY29uKCdjb2x1bW5Nb3ZlVmFsdWUnLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCk7XG4gICAgICAgIHRoaXMuZVBpdm90SWNvbiA9IGNyZWF0ZUljb24oJ2NvbHVtbk1vdmVQaXZvdCcsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgdGhpcy5lRHJvcE5vdEFsbG93ZWRJY29uID0gY3JlYXRlSWNvbignZHJvcE5vdEFsbG93ZWQnLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCk7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLmFkZERyYWdTb3VyY2UgPSBmdW5jdGlvbiAoZHJhZ1NvdXJjZSwgYWxsb3dUb3VjaCkge1xuICAgICAgICBpZiAoYWxsb3dUb3VjaCA9PT0gdm9pZCAwKSB7IGFsbG93VG91Y2ggPSBmYWxzZTsgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZUVsZW1lbnQ6IGRyYWdTb3VyY2UuZUVsZW1lbnQsXG4gICAgICAgICAgICBkcmFnU3RhcnRQaXhlbHM6IGRyYWdTb3VyY2UuZHJhZ1N0YXJ0UGl4ZWxzLFxuICAgICAgICAgICAgb25EcmFnU3RhcnQ6IHRoaXMub25EcmFnU3RhcnQuYmluZCh0aGlzLCBkcmFnU291cmNlKSxcbiAgICAgICAgICAgIG9uRHJhZ1N0b3A6IHRoaXMub25EcmFnU3RvcC5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgb25EcmFnZ2luZzogdGhpcy5vbkRyYWdnaW5nLmJpbmQodGhpcylcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kcmFnU291cmNlQW5kUGFyYW1zTGlzdC5wdXNoKHsgcGFyYW1zOiBwYXJhbXMsIGRyYWdTb3VyY2U6IGRyYWdTb3VyY2UgfSk7XG4gICAgICAgIHRoaXMuZHJhZ1NlcnZpY2UuYWRkRHJhZ1NvdXJjZShwYXJhbXMsIGFsbG93VG91Y2gpO1xuICAgIH07XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZS5yZW1vdmVEcmFnU291cmNlID0gZnVuY3Rpb24gKGRyYWdTb3VyY2UpIHtcbiAgICAgICAgdmFyIHNvdXJjZUFuZFBhcmFtcyA9IHRoaXMuZHJhZ1NvdXJjZUFuZFBhcmFtc0xpc3QuZmluZChmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gaXRlbS5kcmFnU291cmNlID09PSBkcmFnU291cmNlOyB9KTtcbiAgICAgICAgaWYgKHNvdXJjZUFuZFBhcmFtcykge1xuICAgICAgICAgICAgdGhpcy5kcmFnU2VydmljZS5yZW1vdmVEcmFnU291cmNlKHNvdXJjZUFuZFBhcmFtcy5wYXJhbXMpO1xuICAgICAgICAgICAgcmVtb3ZlRnJvbUFycmF5KHRoaXMuZHJhZ1NvdXJjZUFuZFBhcmFtc0xpc3QsIHNvdXJjZUFuZFBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuY2xlYXJEcmFnU291cmNlUGFyYW1zTGlzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5kcmFnU291cmNlQW5kUGFyYW1zTGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChzb3VyY2VBbmRQYXJhbXMpIHsgcmV0dXJuIF90aGlzLmRyYWdTZXJ2aWNlLnJlbW92ZURyYWdTb3VyY2Uoc291cmNlQW5kUGFyYW1zLnBhcmFtcyk7IH0pO1xuICAgICAgICB0aGlzLmRyYWdTb3VyY2VBbmRQYXJhbXNMaXN0Lmxlbmd0aCA9IDA7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLm51ZGdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kcmFnZ2luZykge1xuICAgICAgICAgICAgdGhpcy5vbkRyYWdnaW5nKHRoaXMuZXZlbnRMYXN0VGltZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUub25EcmFnU3RhcnQgPSBmdW5jdGlvbiAoZHJhZ1NvdXJjZSwgbW91c2VFdmVudCkge1xuICAgICAgICB0aGlzLmRyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5kcmFnU291cmNlID0gZHJhZ1NvdXJjZTtcbiAgICAgICAgdGhpcy5ldmVudExhc3RUaW1lID0gbW91c2VFdmVudDtcbiAgICAgICAgdGhpcy5kcmFnSXRlbSA9IHRoaXMuZHJhZ1NvdXJjZS5nZXREcmFnSXRlbSgpO1xuICAgICAgICB0aGlzLmxhc3REcm9wVGFyZ2V0ID0gdGhpcy5kcmFnU291cmNlLmRyYWdTb3VyY2VEcm9wVGFyZ2V0O1xuICAgICAgICBpZiAodGhpcy5kcmFnU291cmNlLm9uRHJhZ1N0YXJ0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1NvdXJjZS5vbkRyYWdTdGFydGVkKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVHaG9zdCgpO1xuICAgIH07XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZS5vbkRyYWdTdG9wID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQpIHtcbiAgICAgICAgdGhpcy5ldmVudExhc3RUaW1lID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5kcmFnU291cmNlLm9uRHJhZ1N0b3BwZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZHJhZ1NvdXJjZS5vbkRyYWdTdG9wcGVkKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubGFzdERyb3BUYXJnZXQgJiYgdGhpcy5sYXN0RHJvcFRhcmdldC5vbkRyYWdTdG9wKSB7XG4gICAgICAgICAgICB2YXIgZHJhZ2dpbmdFdmVudCA9IHRoaXMuY3JlYXRlRHJvcFRhcmdldEV2ZW50KHRoaXMubGFzdERyb3BUYXJnZXQsIG1vdXNlRXZlbnQsIG51bGwsIG51bGwsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMubGFzdERyb3BUYXJnZXQub25EcmFnU3RvcChkcmFnZ2luZ0V2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhc3REcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnSXRlbSA9IG51bGw7XG4gICAgICAgIHRoaXMucmVtb3ZlR2hvc3QoKTtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUub25EcmFnZ2luZyA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50LCBmcm9tTnVkZ2UpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kO1xuICAgICAgICB2YXIgaERpcmVjdGlvbiA9IHRoaXMuZ2V0SG9yaXpvbnRhbERpcmVjdGlvbihtb3VzZUV2ZW50KTtcbiAgICAgICAgdmFyIHZEaXJlY3Rpb24gPSB0aGlzLmdldFZlcnRpY2FsRGlyZWN0aW9uKG1vdXNlRXZlbnQpO1xuICAgICAgICB0aGlzLmV2ZW50TGFzdFRpbWUgPSBtb3VzZUV2ZW50O1xuICAgICAgICB0aGlzLnBvc2l0aW9uR2hvc3QobW91c2VFdmVudCk7XG4gICAgICAgIC8vIGNoZWNrIGlmIG1vdXNlRXZlbnQgaW50ZXJzZWN0cyB3aXRoIGFueSBvZiB0aGUgZHJvcCB0YXJnZXRzXG4gICAgICAgIHZhciB2YWxpZERyb3BUYXJnZXRzID0gdGhpcy5kcm9wVGFyZ2V0cy5maWx0ZXIoZnVuY3Rpb24gKHRhcmdldCkgeyByZXR1cm4gX3RoaXMuaXNNb3VzZU9uRHJvcFRhcmdldChtb3VzZUV2ZW50LCB0YXJnZXQpOyB9KTtcbiAgICAgICAgdmFyIGRyb3BUYXJnZXQgPSB0aGlzLmZpbmRDdXJyZW50RHJvcFRhcmdldChtb3VzZUV2ZW50LCB2YWxpZERyb3BUYXJnZXRzKTtcbiAgICAgICAgaWYgKGRyb3BUYXJnZXQgIT09IHRoaXMubGFzdERyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIHRoaXMubGVhdmVMYXN0VGFyZ2V0SWZFeGlzdHMobW91c2VFdmVudCwgaERpcmVjdGlvbiwgdkRpcmVjdGlvbiwgZnJvbU51ZGdlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmxhc3REcm9wVGFyZ2V0ICE9PSBudWxsICYmIGRyb3BUYXJnZXQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAoX2IgPSAoX2EgPSB0aGlzLmRyYWdTb3VyY2UpLm9uR3JpZEV4aXQpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jYWxsKF9hLCB0aGlzLmRyYWdJdGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmxhc3REcm9wVGFyZ2V0ID09PSBudWxsICYmIGRyb3BUYXJnZXQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAoX2QgPSAoX2MgPSB0aGlzLmRyYWdTb3VyY2UpLm9uR3JpZEVudGVyKSA9PT0gbnVsbCB8fCBfZCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2QuY2FsbChfYywgdGhpcy5kcmFnSXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVudGVyRHJhZ1RhcmdldElmRXhpc3RzKGRyb3BUYXJnZXQsIG1vdXNlRXZlbnQsIGhEaXJlY3Rpb24sIHZEaXJlY3Rpb24sIGZyb21OdWRnZSk7XG4gICAgICAgICAgICB0aGlzLmxhc3REcm9wVGFyZ2V0ID0gZHJvcFRhcmdldDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkcm9wVGFyZ2V0ICYmIGRyb3BUYXJnZXQub25EcmFnZ2luZykge1xuICAgICAgICAgICAgdmFyIGRyYWdnaW5nRXZlbnQgPSB0aGlzLmNyZWF0ZURyb3BUYXJnZXRFdmVudChkcm9wVGFyZ2V0LCBtb3VzZUV2ZW50LCBoRGlyZWN0aW9uLCB2RGlyZWN0aW9uLCBmcm9tTnVkZ2UpO1xuICAgICAgICAgICAgZHJvcFRhcmdldC5vbkRyYWdnaW5nKGRyYWdnaW5nRXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLmdldEFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldCA9IGZ1bmN0aW9uIChkcm9wVGFyZ2V0KSB7XG4gICAgICAgIHZhciBzZWNvbmRhcnlDb250YWluZXJzID0gZHJvcFRhcmdldC5nZXRTZWNvbmRhcnlDb250YWluZXJzID8gZHJvcFRhcmdldC5nZXRTZWNvbmRhcnlDb250YWluZXJzKCkgOiBudWxsO1xuICAgICAgICB2YXIgY29udGFpbmVycyA9IFtbZHJvcFRhcmdldC5nZXRDb250YWluZXIoKV1dO1xuICAgICAgICByZXR1cm4gc2Vjb25kYXJ5Q29udGFpbmVycyA/IGNvbnRhaW5lcnMuY29uY2F0KHNlY29uZGFyeUNvbnRhaW5lcnMpIDogY29udGFpbmVycztcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuYWxsQ29udGFpbmVyc0ludGVyc2VjdCA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50LCBjb250YWluZXJzKSB7XG4gICAgICAgIHZhciBlXzEsIF9hO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yICh2YXIgY29udGFpbmVyc18xID0gX192YWx1ZXMkMyhjb250YWluZXJzKSwgY29udGFpbmVyc18xXzEgPSBjb250YWluZXJzXzEubmV4dCgpOyAhY29udGFpbmVyc18xXzEuZG9uZTsgY29udGFpbmVyc18xXzEgPSBjb250YWluZXJzXzEubmV4dCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5lciA9IGNvbnRhaW5lcnNfMV8xLnZhbHVlO1xuICAgICAgICAgICAgICAgIHZhciByZWN0ID0gY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgIC8vIGlmIGVsZW1lbnQgaXMgbm90IHZpc2libGUsIHRoZW4gd2lkdGggYW5kIGhlaWdodCBhcmUgemVyb1xuICAgICAgICAgICAgICAgIGlmIChyZWN0LndpZHRoID09PSAwIHx8IHJlY3QuaGVpZ2h0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGhvcml6b250YWxGaXQgPSBtb3VzZUV2ZW50LmNsaWVudFggPj0gcmVjdC5sZWZ0ICYmIG1vdXNlRXZlbnQuY2xpZW50WCA8IHJlY3QucmlnaHQ7XG4gICAgICAgICAgICAgICAgdmFyIHZlcnRpY2FsRml0ID0gbW91c2VFdmVudC5jbGllbnRZID49IHJlY3QudG9wICYmIG1vdXNlRXZlbnQuY2xpZW50WSA8IHJlY3QuYm90dG9tO1xuICAgICAgICAgICAgICAgIGlmICghaG9yaXpvbnRhbEZpdCB8fCAhdmVydGljYWxGaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZV8xXzEpIHsgZV8xID0geyBlcnJvcjogZV8xXzEgfTsgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRhaW5lcnNfMV8xICYmICFjb250YWluZXJzXzFfMS5kb25lICYmIChfYSA9IGNvbnRhaW5lcnNfMS5yZXR1cm4pKSBfYS5jYWxsKGNvbnRhaW5lcnNfMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHsgaWYgKGVfMSkgdGhyb3cgZV8xLmVycm9yOyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICAvLyBjaGVja3MgaWYgdGhlIG1vdXNlIGlzIG9uIHRoZSBkcm9wIHRhcmdldC4gaXQgY2hlY2tzIGVDb250YWluZXIgYW5kIGVTZWNvbmRhcnlDb250YWluZXJzXG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZS5pc01vdXNlT25Ecm9wVGFyZ2V0ID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQsIGRyb3BUYXJnZXQpIHtcbiAgICAgICAgdmFyIGVfMiwgX2E7XG4gICAgICAgIHZhciBhbGxDb250YWluZXJzRnJvbURyb3BUYXJnZXQgPSB0aGlzLmdldEFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldChkcm9wVGFyZ2V0KTtcbiAgICAgICAgdmFyIG1vdXNlT3ZlclRhcmdldCA9IGZhbHNlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yICh2YXIgYWxsQ29udGFpbmVyc0Zyb21Ecm9wVGFyZ2V0XzEgPSBfX3ZhbHVlcyQzKGFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldCksIGFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldF8xXzEgPSBhbGxDb250YWluZXJzRnJvbURyb3BUYXJnZXRfMS5uZXh0KCk7ICFhbGxDb250YWluZXJzRnJvbURyb3BUYXJnZXRfMV8xLmRvbmU7IGFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldF8xXzEgPSBhbGxDb250YWluZXJzRnJvbURyb3BUYXJnZXRfMS5uZXh0KCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudENvbnRhaW5lcnMgPSBhbGxDb250YWluZXJzRnJvbURyb3BUYXJnZXRfMV8xLnZhbHVlO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmFsbENvbnRhaW5lcnNJbnRlcnNlY3QobW91c2VFdmVudCwgY3VycmVudENvbnRhaW5lcnMpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vdXNlT3ZlclRhcmdldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZV8yXzEpIHsgZV8yID0geyBlcnJvcjogZV8yXzEgfTsgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKGFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldF8xXzEgJiYgIWFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldF8xXzEuZG9uZSAmJiAoX2EgPSBhbGxDb250YWluZXJzRnJvbURyb3BUYXJnZXRfMS5yZXR1cm4pKSBfYS5jYWxsKGFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldF8xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkgeyBpZiAoZV8yKSB0aHJvdyBlXzIuZXJyb3I7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZHJvcFRhcmdldC50YXJnZXRDb250YWluc1NvdXJjZSAmJiAhZHJvcFRhcmdldC5nZXRDb250YWluZXIoKS5jb250YWlucyh0aGlzLmRyYWdTb3VyY2UuZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1vdXNlT3ZlclRhcmdldCAmJiBkcm9wVGFyZ2V0LmlzSW50ZXJlc3RlZEluKHRoaXMuZHJhZ1NvdXJjZS50eXBlLCB0aGlzLmRyYWdTb3VyY2UuZUVsZW1lbnQpO1xuICAgIH07XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZS5maW5kQ3VycmVudERyb3BUYXJnZXQgPSBmdW5jdGlvbiAobW91c2VFdmVudCwgdmFsaWREcm9wVGFyZ2V0cykge1xuICAgICAgICB2YXIgZV8zLCBfYSwgZV80LCBfYjtcbiAgICAgICAgdmFyIGxlbiA9IHZhbGlkRHJvcFRhcmdldHMubGVuZ3RoO1xuICAgICAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGVuID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWREcm9wVGFyZ2V0c1swXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgLy8gZWxlbWVudHNGcm9tUG9pbnQgcmV0dXJuIGEgbGlzdCBvZiBlbGVtZW50cyB1bmRlclxuICAgICAgICAvLyB0aGUgbW91c2VFdmVudCBzb3J0ZWQgZnJvbSB0b3BNb3N0IHRvIGJvdHRvbU1vc3RcbiAgICAgICAgdmFyIGVsZW1lbnRTdGFjayA9IGVEb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludChtb3VzZUV2ZW50LmNsaWVudFgsIG1vdXNlRXZlbnQuY2xpZW50WSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBsb29wIG92ZXIgdGhlIHNvcnRlZCBlbGVtZW50U3RhY2sgdG8gZmluZCB3aGljaCBkcm9wVGFyZ2V0IGNvbWVzIGZpcnN0XG4gICAgICAgICAgICBmb3IgKHZhciBlbGVtZW50U3RhY2tfMSA9IF9fdmFsdWVzJDMoZWxlbWVudFN0YWNrKSwgZWxlbWVudFN0YWNrXzFfMSA9IGVsZW1lbnRTdGFja18xLm5leHQoKTsgIWVsZW1lbnRTdGFja18xXzEuZG9uZTsgZWxlbWVudFN0YWNrXzFfMSA9IGVsZW1lbnRTdGFja18xLm5leHQoKSkge1xuICAgICAgICAgICAgICAgIHZhciBlbCA9IGVsZW1lbnRTdGFja18xXzEudmFsdWU7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgdmFsaWREcm9wVGFyZ2V0c18xID0gKGVfNCA9IHZvaWQgMCwgX192YWx1ZXMkMyh2YWxpZERyb3BUYXJnZXRzKSksIHZhbGlkRHJvcFRhcmdldHNfMV8xID0gdmFsaWREcm9wVGFyZ2V0c18xLm5leHQoKTsgIXZhbGlkRHJvcFRhcmdldHNfMV8xLmRvbmU7IHZhbGlkRHJvcFRhcmdldHNfMV8xID0gdmFsaWREcm9wVGFyZ2V0c18xLm5leHQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRyb3BUYXJnZXQgPSB2YWxpZERyb3BUYXJnZXRzXzFfMS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJzID0gZmxhdHRlbih0aGlzLmdldEFsbENvbnRhaW5lcnNGcm9tRHJvcFRhcmdldChkcm9wVGFyZ2V0KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udGFpbmVycy5pbmRleE9mKGVsKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZHJvcFRhcmdldDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZV80XzEpIHsgZV80ID0geyBlcnJvcjogZV80XzEgfTsgfVxuICAgICAgICAgICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbGlkRHJvcFRhcmdldHNfMV8xICYmICF2YWxpZERyb3BUYXJnZXRzXzFfMS5kb25lICYmIChfYiA9IHZhbGlkRHJvcFRhcmdldHNfMS5yZXR1cm4pKSBfYi5jYWxsKHZhbGlkRHJvcFRhcmdldHNfMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZmluYWxseSB7IGlmIChlXzQpIHRocm93IGVfNC5lcnJvcjsgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZV8zXzEpIHsgZV8zID0geyBlcnJvcjogZV8zXzEgfTsgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnRTdGFja18xXzEgJiYgIWVsZW1lbnRTdGFja18xXzEuZG9uZSAmJiAoX2EgPSBlbGVtZW50U3RhY2tfMS5yZXR1cm4pKSBfYS5jYWxsKGVsZW1lbnRTdGFja18xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkgeyBpZiAoZV8zKSB0aHJvdyBlXzMuZXJyb3I7IH1cbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBzaG91bGQgbmV2ZXIgaGl0IHRoaXMgcG9pbnQgb2YgdGhlIGNvZGUgYmVjYXVzZSBvbmx5XG4gICAgICAgIC8vIHZhbGlkIGRyb3BUYXJnZXRzIHNob3VsZCBiZSBwcm92aWRlZCB0byB0aGlzIG1ldGhvZC5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLmVudGVyRHJhZ1RhcmdldElmRXhpc3RzID0gZnVuY3Rpb24gKGRyb3BUYXJnZXQsIG1vdXNlRXZlbnQsIGhEaXJlY3Rpb24sIHZEaXJlY3Rpb24sIGZyb21OdWRnZSkge1xuICAgICAgICBpZiAoIWRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZHJvcFRhcmdldC5vbkRyYWdFbnRlcikge1xuICAgICAgICAgICAgdmFyIGRyYWdFbnRlckV2ZW50ID0gdGhpcy5jcmVhdGVEcm9wVGFyZ2V0RXZlbnQoZHJvcFRhcmdldCwgbW91c2VFdmVudCwgaERpcmVjdGlvbiwgdkRpcmVjdGlvbiwgZnJvbU51ZGdlKTtcbiAgICAgICAgICAgIGRyb3BUYXJnZXQub25EcmFnRW50ZXIoZHJhZ0VudGVyRXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0R2hvc3RJY29uKGRyb3BUYXJnZXQuZ2V0SWNvbk5hbWUgPyBkcm9wVGFyZ2V0LmdldEljb25OYW1lKCkgOiBudWxsKTtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUubGVhdmVMYXN0VGFyZ2V0SWZFeGlzdHMgPSBmdW5jdGlvbiAobW91c2VFdmVudCwgaERpcmVjdGlvbiwgdkRpcmVjdGlvbiwgZnJvbU51ZGdlKSB7XG4gICAgICAgIGlmICghdGhpcy5sYXN0RHJvcFRhcmdldCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmxhc3REcm9wVGFyZ2V0Lm9uRHJhZ0xlYXZlKSB7XG4gICAgICAgICAgICB2YXIgZHJhZ0xlYXZlRXZlbnQgPSB0aGlzLmNyZWF0ZURyb3BUYXJnZXRFdmVudCh0aGlzLmxhc3REcm9wVGFyZ2V0LCBtb3VzZUV2ZW50LCBoRGlyZWN0aW9uLCB2RGlyZWN0aW9uLCBmcm9tTnVkZ2UpO1xuICAgICAgICAgICAgdGhpcy5sYXN0RHJvcFRhcmdldC5vbkRyYWdMZWF2ZShkcmFnTGVhdmVFdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRHaG9zdEljb24obnVsbCk7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLmFkZERyb3BUYXJnZXQgPSBmdW5jdGlvbiAoZHJvcFRhcmdldCkge1xuICAgICAgICB0aGlzLmRyb3BUYXJnZXRzLnB1c2goZHJvcFRhcmdldCk7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLnJlbW92ZURyb3BUYXJnZXQgPSBmdW5jdGlvbiAoZHJvcFRhcmdldCkge1xuICAgICAgICB0aGlzLmRyb3BUYXJnZXRzID0gdGhpcy5kcm9wVGFyZ2V0cy5maWx0ZXIoZnVuY3Rpb24gKHRhcmdldCkgeyByZXR1cm4gdGFyZ2V0LmdldENvbnRhaW5lcigpICE9PSBkcm9wVGFyZ2V0LmdldENvbnRhaW5lcigpOyB9KTtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuaGFzRXh0ZXJuYWxEcm9wWm9uZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRyb3BUYXJnZXRzLnNvbWUoZnVuY3Rpb24gKHpvbmVzKSB7IHJldHVybiB6b25lcy5leHRlcm5hbDsgfSk7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLmZpbmRFeHRlcm5hbFpvbmUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBleHRlcm5hbFRhcmdldHMgPSB0aGlzLmRyb3BUYXJnZXRzLmZpbHRlcihmdW5jdGlvbiAodGFyZ2V0KSB7IHJldHVybiB0YXJnZXQuZXh0ZXJuYWw7IH0pO1xuICAgICAgICByZXR1cm4gZXh0ZXJuYWxUYXJnZXRzLmZpbmQoZnVuY3Rpb24gKHpvbmUpIHsgcmV0dXJuIHpvbmUuZ2V0Q29udGFpbmVyKCkgPT09IHBhcmFtcy5nZXRDb250YWluZXIoKTsgfSkgfHwgbnVsbDtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuZ2V0SG9yaXpvbnRhbERpcmVjdGlvbiA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgY2xpZW50WCA9IHRoaXMuZXZlbnRMYXN0VGltZSAmJiB0aGlzLmV2ZW50TGFzdFRpbWUuY2xpZW50WDtcbiAgICAgICAgdmFyIGVDbGllbnRYID0gZXZlbnQuY2xpZW50WDtcbiAgICAgICAgaWYgKGNsaWVudFggPT09IGVDbGllbnRYKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2xpZW50WCA+IGVDbGllbnRYID8gSG9yaXpvbnRhbERpcmVjdGlvbi5MZWZ0IDogSG9yaXpvbnRhbERpcmVjdGlvbi5SaWdodDtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuZ2V0VmVydGljYWxEaXJlY3Rpb24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGNsaWVudFkgPSB0aGlzLmV2ZW50TGFzdFRpbWUgJiYgdGhpcy5ldmVudExhc3RUaW1lLmNsaWVudFk7XG4gICAgICAgIHZhciBlQ2xpZW50WSA9IGV2ZW50LmNsaWVudFk7XG4gICAgICAgIGlmIChjbGllbnRZID09PSBlQ2xpZW50WSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNsaWVudFkgPiBlQ2xpZW50WSA/IFZlcnRpY2FsRGlyZWN0aW9uLlVwIDogVmVydGljYWxEaXJlY3Rpb24uRG93bjtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuY3JlYXRlRHJvcFRhcmdldEV2ZW50ID0gZnVuY3Rpb24gKGRyb3BUYXJnZXQsIGV2ZW50LCBoRGlyZWN0aW9uLCB2RGlyZWN0aW9uLCBmcm9tTnVkZ2UpIHtcbiAgICAgICAgLy8gbG9jYWxpc2UgeCBhbmQgeSB0byB0aGUgdGFyZ2V0XG4gICAgICAgIHZhciBkcm9wWm9uZVRhcmdldCA9IGRyb3BUYXJnZXQuZ2V0Q29udGFpbmVyKCk7XG4gICAgICAgIHZhciByZWN0ID0gZHJvcFpvbmVUYXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBfYSA9IHRoaXMsIGFwaSA9IF9hLmdyaWRBcGksIGNvbHVtbkFwaSA9IF9hLmNvbHVtbkFwaSwgZHJhZ0l0ZW0gPSBfYS5kcmFnSXRlbSwgZHJhZ1NvdXJjZSA9IF9hLmRyYWdTb3VyY2U7XG4gICAgICAgIHZhciB4ID0gZXZlbnQuY2xpZW50WCAtIHJlY3QubGVmdDtcbiAgICAgICAgdmFyIHkgPSBldmVudC5jbGllbnRZIC0gcmVjdC50b3A7XG4gICAgICAgIHJldHVybiB7IGV2ZW50OiBldmVudCwgeDogeCwgeTogeSwgdkRpcmVjdGlvbjogdkRpcmVjdGlvbiwgaERpcmVjdGlvbjogaERpcmVjdGlvbiwgZHJhZ1NvdXJjZTogZHJhZ1NvdXJjZSwgZnJvbU51ZGdlOiBmcm9tTnVkZ2UsIGRyYWdJdGVtOiBkcmFnSXRlbSwgYXBpOiBhcGksIGNvbHVtbkFwaTogY29sdW1uQXBpLCBkcm9wWm9uZVRhcmdldDogZHJvcFpvbmVUYXJnZXQgfTtcbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUucG9zaXRpb25HaG9zdCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgZ2hvc3QgPSB0aGlzLmVHaG9zdDtcbiAgICAgICAgaWYgKCFnaG9zdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBnaG9zdFJlY3QgPSBnaG9zdC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIGdob3N0SGVpZ2h0ID0gZ2hvc3RSZWN0LmhlaWdodDtcbiAgICAgICAgLy8gZm9yIHNvbWUgcmVhc29uLCB3aXRob3V0IHRoZSAnLTInLCBpdCBzdGlsbCBvdmVybGFwcGVkIGJ5IDEgb3IgMiBwaXhlbHMsIHdoaWNoXG4gICAgICAgIC8vIHRoZW4gYnJvdWdodCBpbiBzY3JvbGxiYXJzIHRvIHRoZSBicm93c2VyLiBubyBpZGVhIHdoeSwgYnV0IHB1dHRpbmcgaW4gLTIgaGVyZVxuICAgICAgICAvLyB3b3JrcyBhcm91bmQgaXQgd2hpY2ggaXMgZ29vZCBlbm91Z2ggZm9yIG1lLlxuICAgICAgICB2YXIgYnJvd3NlcldpZHRoID0gZ2V0Qm9keVdpZHRoKCkgLSAyO1xuICAgICAgICB2YXIgYnJvd3NlckhlaWdodCA9IGdldEJvZHlIZWlnaHQoKSAtIDI7XG4gICAgICAgIHZhciB0b3AgPSBldmVudC5wYWdlWSAtIChnaG9zdEhlaWdodCAvIDIpO1xuICAgICAgICB2YXIgbGVmdCA9IGV2ZW50LnBhZ2VYIC0gMTA7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgd2luID0gKGVEb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3cpO1xuICAgICAgICB2YXIgd2luZG93U2Nyb2xsWSA9IHdpbi5wYWdlWU9mZnNldCB8fCBlRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcDtcbiAgICAgICAgdmFyIHdpbmRvd1Njcm9sbFggPSB3aW4ucGFnZVhPZmZzZXQgfHwgZURvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0O1xuICAgICAgICAvLyBjaGVjayBnaG9zdCBpcyBub3QgcG9zaXRpb25lZCBvdXRzaWRlIG9mIHRoZSBicm93c2VyXG4gICAgICAgIGlmIChicm93c2VyV2lkdGggPiAwICYmICgobGVmdCArIGdob3N0LmNsaWVudFdpZHRoKSA+IChicm93c2VyV2lkdGggKyB3aW5kb3dTY3JvbGxYKSkpIHtcbiAgICAgICAgICAgIGxlZnQgPSBicm93c2VyV2lkdGggKyB3aW5kb3dTY3JvbGxYIC0gZ2hvc3QuY2xpZW50V2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxlZnQgPCAwKSB7XG4gICAgICAgICAgICBsZWZ0ID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnJvd3NlckhlaWdodCA+IDAgJiYgKCh0b3AgKyBnaG9zdC5jbGllbnRIZWlnaHQpID4gKGJyb3dzZXJIZWlnaHQgKyB3aW5kb3dTY3JvbGxZKSkpIHtcbiAgICAgICAgICAgIHRvcCA9IGJyb3dzZXJIZWlnaHQgKyB3aW5kb3dTY3JvbGxZIC0gZ2hvc3QuY2xpZW50SGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0b3AgPCAwKSB7XG4gICAgICAgICAgICB0b3AgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGdob3N0LnN0eWxlLmxlZnQgPSBsZWZ0ICsgXCJweFwiO1xuICAgICAgICBnaG9zdC5zdHlsZS50b3AgPSB0b3AgKyBcInB4XCI7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLnJlbW92ZUdob3N0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5lR2hvc3QgJiYgdGhpcy5lR2hvc3RQYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuZUdob3N0UGFyZW50LnJlbW92ZUNoaWxkKHRoaXMuZUdob3N0KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVHaG9zdCA9IG51bGw7XG4gICAgfTtcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLmNyZWF0ZUdob3N0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmVHaG9zdCA9IGxvYWRUZW1wbGF0ZShEcmFnQW5kRHJvcFNlcnZpY2VfMS5HSE9TVF9URU1QTEFURSk7XG4gICAgICAgIHRoaXMubW91c2VFdmVudFNlcnZpY2Uuc3RhbXBUb3BMZXZlbEdyaWRDb21wV2l0aEdyaWRJbnN0YW5jZSh0aGlzLmVHaG9zdCk7XG4gICAgICAgIHZhciB0aGVtZSA9IHRoaXMuZW52aXJvbm1lbnQuZ2V0VGhlbWUoKS50aGVtZTtcbiAgICAgICAgaWYgKHRoZW1lKSB7XG4gICAgICAgICAgICB0aGlzLmVHaG9zdC5jbGFzc0xpc3QuYWRkKHRoZW1lKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVHaG9zdEljb24gPSB0aGlzLmVHaG9zdC5xdWVyeVNlbGVjdG9yKCcuYWctZG5kLWdob3N0LWljb24nKTtcbiAgICAgICAgdGhpcy5zZXRHaG9zdEljb24obnVsbCk7XG4gICAgICAgIHZhciBlVGV4dCA9IHRoaXMuZUdob3N0LnF1ZXJ5U2VsZWN0b3IoJy5hZy1kbmQtZ2hvc3QtbGFiZWwnKTtcbiAgICAgICAgdmFyIGRyYWdJdGVtTmFtZSA9IHRoaXMuZHJhZ1NvdXJjZS5kcmFnSXRlbU5hbWU7XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKGRyYWdJdGVtTmFtZSkpIHtcbiAgICAgICAgICAgIGRyYWdJdGVtTmFtZSA9IGRyYWdJdGVtTmFtZSgpO1xuICAgICAgICB9XG4gICAgICAgIGVUZXh0LmlubmVySFRNTCA9IGVzY2FwZVN0cmluZyhkcmFnSXRlbU5hbWUpIHx8ICcnO1xuICAgICAgICB0aGlzLmVHaG9zdC5zdHlsZS5oZWlnaHQgPSAnMjVweCc7XG4gICAgICAgIHRoaXMuZUdob3N0LnN0eWxlLnRvcCA9ICcyMHB4JztcbiAgICAgICAgdGhpcy5lR2hvc3Quc3R5bGUubGVmdCA9ICcyMHB4JztcbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIHZhciB0YXJnZXRFbCA9IG51bGw7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0YXJnZXRFbCA9IGVEb2N1bWVudC5mdWxsc2NyZWVuRWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gc29tZSBlbnZpcm9ubWVudHMgbGlrZSBTYWxlc0ZvcmNlIHdpbGwgdGhyb3cgZXJyb3JzXG4gICAgICAgICAgICAvLyBzaW1wbHkgYnkgdHJ5aW5nIHRvIHJlYWQgdGhlIGZ1bGxzY3JlZW5FbGVtZW50IHByb3BlcnR5XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICBpZiAoIXRhcmdldEVsKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0RWwgPSBlRG9jdW1lbnQucXVlcnlTZWxlY3RvcignYm9keScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZUdob3N0UGFyZW50ID0gdGFyZ2V0RWw7XG4gICAgICAgIGlmICghdGhpcy5lR2hvc3RQYXJlbnQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY291bGQgbm90IGZpbmQgZG9jdW1lbnQgYm9keSwgaXQgaXMgbmVlZGVkIGZvciBkcmFnZ2luZyBjb2x1bW5zJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVHaG9zdFBhcmVudC5hcHBlbmRDaGlsZCh0aGlzLmVHaG9zdCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUuc2V0R2hvc3RJY29uID0gZnVuY3Rpb24gKGljb25OYW1lLCBzaGFrZSkge1xuICAgICAgICBpZiAoc2hha2UgPT09IHZvaWQgMCkgeyBzaGFrZSA9IGZhbHNlOyB9XG4gICAgICAgIGNsZWFyRWxlbWVudCh0aGlzLmVHaG9zdEljb24pO1xuICAgICAgICB2YXIgZUljb24gPSBudWxsO1xuICAgICAgICBpZiAoIWljb25OYW1lKSB7XG4gICAgICAgICAgICBpY29uTmFtZSA9IHRoaXMuZHJhZ1NvdXJjZS5kZWZhdWx0SWNvbk5hbWUgfHwgRHJhZ0FuZERyb3BTZXJ2aWNlXzEuSUNPTl9OT1RfQUxMT1dFRDtcbiAgICAgICAgfVxuICAgICAgICBzd2l0Y2ggKGljb25OYW1lKSB7XG4gICAgICAgICAgICBjYXNlIERyYWdBbmREcm9wU2VydmljZV8xLklDT05fUElOTkVEOlxuICAgICAgICAgICAgICAgIGVJY29uID0gdGhpcy5lUGlubmVkSWNvbjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgRHJhZ0FuZERyb3BTZXJ2aWNlXzEuSUNPTl9NT1ZFOlxuICAgICAgICAgICAgICAgIGVJY29uID0gdGhpcy5lTW92ZUljb247XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERyYWdBbmREcm9wU2VydmljZV8xLklDT05fTEVGVDpcbiAgICAgICAgICAgICAgICBlSWNvbiA9IHRoaXMuZUxlZnRJY29uO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEcmFnQW5kRHJvcFNlcnZpY2VfMS5JQ09OX1JJR0hUOlxuICAgICAgICAgICAgICAgIGVJY29uID0gdGhpcy5lUmlnaHRJY29uO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEcmFnQW5kRHJvcFNlcnZpY2VfMS5JQ09OX0dST1VQOlxuICAgICAgICAgICAgICAgIGVJY29uID0gdGhpcy5lR3JvdXBJY29uO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBEcmFnQW5kRHJvcFNlcnZpY2VfMS5JQ09OX0FHR1JFR0FURTpcbiAgICAgICAgICAgICAgICBlSWNvbiA9IHRoaXMuZUFnZ3JlZ2F0ZUljb247XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERyYWdBbmREcm9wU2VydmljZV8xLklDT05fUElWT1Q6XG4gICAgICAgICAgICAgICAgZUljb24gPSB0aGlzLmVQaXZvdEljb247XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERyYWdBbmREcm9wU2VydmljZV8xLklDT05fTk9UX0FMTE9XRUQ6XG4gICAgICAgICAgICAgICAgZUljb24gPSB0aGlzLmVEcm9wTm90QWxsb3dlZEljb247XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERyYWdBbmREcm9wU2VydmljZV8xLklDT05fSElERTpcbiAgICAgICAgICAgICAgICBlSWNvbiA9IHRoaXMuZUhpZGVJY29uO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZUdob3N0SWNvbi5jbGFzc0xpc3QudG9nZ2xlKCdhZy1zaGFrZS1sZWZ0LXRvLXJpZ2h0Jywgc2hha2UpO1xuICAgICAgICBpZiAoZUljb24gPT09IHRoaXMuZUhpZGVJY29uICYmIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NEcmFnTGVhdmVIaWRlc0NvbHVtbnMoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlSWNvbikge1xuICAgICAgICAgICAgdGhpcy5lR2hvc3RJY29uLmFwcGVuZENoaWxkKGVJY29uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdmFyIERyYWdBbmREcm9wU2VydmljZV8xO1xuICAgIERyYWdBbmREcm9wU2VydmljZS5JQ09OX1BJTk5FRCA9ICdwaW5uZWQnO1xuICAgIERyYWdBbmREcm9wU2VydmljZS5JQ09OX01PVkUgPSAnbW92ZSc7XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fTEVGVCA9ICdsZWZ0JztcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9SSUdIVCA9ICdyaWdodCc7XG4gICAgRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fR1JPVVAgPSAnZ3JvdXAnO1xuICAgIERyYWdBbmREcm9wU2VydmljZS5JQ09OX0FHR1JFR0FURSA9ICdhZ2dyZWdhdGUnO1xuICAgIERyYWdBbmREcm9wU2VydmljZS5JQ09OX1BJVk9UID0gJ3Bpdm90JztcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9OT1RfQUxMT1dFRCA9ICdub3RBbGxvd2VkJztcbiAgICBEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9ISURFID0gJ2hpZGUnO1xuICAgIERyYWdBbmREcm9wU2VydmljZS5HSE9TVF9URU1QTEFURSA9IFwiPGRpdiBjbGFzcz1cXFwiYWctZG5kLWdob3N0IGFnLXVuc2VsZWN0YWJsZVxcXCI+XFxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImFnLWRuZC1naG9zdC1pY29uIGFnLXNoYWtlLWxlZnQtdG8tcmlnaHRcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1kbmQtZ2hvc3QtbGFiZWxcXFwiPjwvZGl2PlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgX19kZWNvcmF0ZSQyMChbXG4gICAgICAgIEF1dG93aXJlZCgnZHJhZ1NlcnZpY2UnKVxuICAgIF0sIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUsIFwiZHJhZ1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDIwKFtcbiAgICAgICAgQXV0b3dpcmVkKCdtb3VzZUV2ZW50U2VydmljZScpXG4gICAgXSwgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZSwgXCJtb3VzZUV2ZW50U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjAoW1xuICAgICAgICBBdXRvd2lyZWQoJ2Vudmlyb25tZW50JylcbiAgICBdLCBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLCBcImVudmlyb25tZW50XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyMChbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uQXBpJylcbiAgICBdLCBEcmFnQW5kRHJvcFNlcnZpY2UucHJvdG90eXBlLCBcImNvbHVtbkFwaVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjAoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRBcGknKVxuICAgIF0sIERyYWdBbmREcm9wU2VydmljZS5wcm90b3R5cGUsIFwiZ3JpZEFwaVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMjAoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMjAoW1xuICAgICAgICBQcmVEZXN0cm95XG4gICAgXSwgRHJhZ0FuZERyb3BTZXJ2aWNlLnByb3RvdHlwZSwgXCJjbGVhckRyYWdTb3VyY2VQYXJhbXNMaXN0XCIsIG51bGwpO1xuICAgIERyYWdBbmREcm9wU2VydmljZSA9IERyYWdBbmREcm9wU2VydmljZV8xID0gX19kZWNvcmF0ZSQyMChbXG4gICAgICAgIEJlYW4oJ2RyYWdBbmREcm9wU2VydmljZScpXG4gICAgXSwgRHJhZ0FuZERyb3BTZXJ2aWNlKTtcbiAgICByZXR1cm4gRHJhZ0FuZERyb3BTZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJnID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxJCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFJvd0RyYWdDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyZyhSb3dEcmFnQ29tcCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSb3dEcmFnQ29tcChjZWxsVmFsdWVGbiwgcm93Tm9kZSwgY29sdW1uLCBjdXN0b21HdWksIGRyYWdTdGFydFBpeGVscywgc3VwcHJlc3NWaXNpYmlsaXR5Q2hhbmdlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmNlbGxWYWx1ZUZuID0gY2VsbFZhbHVlRm47XG4gICAgICAgIF90aGlzLnJvd05vZGUgPSByb3dOb2RlO1xuICAgICAgICBfdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIF90aGlzLmN1c3RvbUd1aSA9IGN1c3RvbUd1aTtcbiAgICAgICAgX3RoaXMuZHJhZ1N0YXJ0UGl4ZWxzID0gZHJhZ1N0YXJ0UGl4ZWxzO1xuICAgICAgICBfdGhpcy5zdXBwcmVzc1Zpc2liaWxpdHlDaGFuZ2UgPSBzdXBwcmVzc1Zpc2liaWxpdHlDaGFuZ2U7XG4gICAgICAgIF90aGlzLmRyYWdTb3VyY2UgPSBudWxsO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFJvd0RyYWdDb21wLnByb3RvdHlwZS5pc0N1c3RvbUd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VzdG9tR3VpICE9IG51bGw7XG4gICAgfTtcbiAgICBSb3dEcmFnQ29tcC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmN1c3RvbUd1aSkge1xuICAgICAgICAgICAgdGhpcy5zZXRUZW1wbGF0ZSgvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiYWctZHJhZy1oYW5kbGUgYWctcm93LWRyYWdcXFwiIGFyaWEtaGlkZGVuPVxcXCJ0cnVlXFxcIj48L2Rpdj5cIik7XG4gICAgICAgICAgICB0aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKGNyZWF0ZUljb25Ob1NwYW4oJ3Jvd0RyYWcnLCB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCkpO1xuICAgICAgICAgICAgdGhpcy5hZGREcmFnU291cmNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldERyYWdFbGVtZW50KHRoaXMuY3VzdG9tR3VpLCB0aGlzLmRyYWdTdGFydFBpeGVscyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jaGVja0NvbXBhdGliaWxpdHkoKTtcbiAgICAgICAgaWYgKCF0aGlzLnN1cHByZXNzVmlzaWJpbGl0eUNoYW5nZSkge1xuICAgICAgICAgICAgdmFyIHN0cmF0ZWd5ID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSb3dEcmFnTWFuYWdlZCgpID9cbiAgICAgICAgICAgICAgICBuZXcgTWFuYWdlZFZpc2liaWxpdHlTdHJhdGVneSh0aGlzLCB0aGlzLmJlYW5zLCB0aGlzLnJvd05vZGUsIHRoaXMuY29sdW1uKSA6XG4gICAgICAgICAgICAgICAgbmV3IE5vbk1hbmFnZWRWaXNpYmlsaXR5U3RyYXRlZ3kodGhpcywgdGhpcy5iZWFucywgdGhpcy5yb3dOb2RlLCB0aGlzLmNvbHVtbik7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKHN0cmF0ZWd5LCB0aGlzLmJlYW5zLmNvbnRleHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dEcmFnQ29tcC5wcm90b3R5cGUuc2V0RHJhZ0VsZW1lbnQgPSBmdW5jdGlvbiAoZHJhZ0VsZW1lbnQsIGRyYWdTdGFydFBpeGVscykge1xuICAgICAgICB0aGlzLnNldFRlbXBsYXRlRnJvbUVsZW1lbnQoZHJhZ0VsZW1lbnQpO1xuICAgICAgICB0aGlzLmFkZERyYWdTb3VyY2UoZHJhZ1N0YXJ0UGl4ZWxzKTtcbiAgICB9O1xuICAgIFJvd0RyYWdDb21wLnByb3RvdHlwZS5nZXRTZWxlY3RlZE5vZGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNSb3dEcmFnTXVsdGlSb3cgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd0RyYWdNdWx0aVJvdygpO1xuICAgICAgICBpZiAoIWlzUm93RHJhZ011bHRpUm93KSB7XG4gICAgICAgICAgICByZXR1cm4gW3RoaXMucm93Tm9kZV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNlbGVjdGlvbiA9IHRoaXMuYmVhbnMuc2VsZWN0aW9uU2VydmljZS5nZXRTZWxlY3RlZE5vZGVzKCk7XG4gICAgICAgIHJldHVybiBzZWxlY3Rpb24uaW5kZXhPZih0aGlzLnJvd05vZGUpICE9PSAtMSA/IHNlbGVjdGlvbiA6IFt0aGlzLnJvd05vZGVdO1xuICAgIH07XG4gICAgLy8gcmV0dXJucyB0cnVlIGlmIGFsbCBjb21wYXRpYmlsaXR5IGl0ZW1zIHdvcmsgb3V0XG4gICAgUm93RHJhZ0NvbXAucHJvdG90eXBlLmNoZWNrQ29tcGF0aWJpbGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1hbmFnZWQgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd0RyYWdNYW5hZ2VkKCk7XG4gICAgICAgIHZhciB0cmVlRGF0YSA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKTtcbiAgICAgICAgaWYgKHRyZWVEYXRhICYmIG1hbmFnZWQpIHtcbiAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogSWYgdXNpbmcgcm93IGRyYWcgd2l0aCB0cmVlIGRhdGEsIHlvdSBjYW5ub3QgaGF2ZSByb3dEcmFnTWFuYWdlZD10cnVlJyk7XG4gICAgICAgICAgICB9LCAnUm93RHJhZ0NvbXAubWFuYWdlZEFuZFRyZWVEYXRhJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0RyYWdDb21wLnByb3RvdHlwZS5nZXREcmFnSXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvd05vZGU6IHRoaXMucm93Tm9kZSxcbiAgICAgICAgICAgIHJvd05vZGVzOiB0aGlzLmdldFNlbGVjdGVkTm9kZXMoKSxcbiAgICAgICAgICAgIGNvbHVtbnM6IHRoaXMuY29sdW1uID8gW3RoaXMuY29sdW1uXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGRlZmF1bHRUZXh0VmFsdWU6IHRoaXMuY2VsbFZhbHVlRm4oKSxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFJvd0RyYWdDb21wLnByb3RvdHlwZS5hZGREcmFnU291cmNlID0gZnVuY3Rpb24gKGRyYWdTdGFydFBpeGVscykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoZHJhZ1N0YXJ0UGl4ZWxzID09PSB2b2lkIDApIHsgZHJhZ1N0YXJ0UGl4ZWxzID0gNDsgfVxuICAgICAgICAvLyBpZiB0aGlzIGlzIGNoYW5naW5nIHRoZSBkcmFnIGVsZW1lbnQsIGRlbGV0ZSB0aGUgcHJldmlvdXMgZHJhZ1NvdXJjZVxuICAgICAgICBpZiAodGhpcy5kcmFnU291cmNlKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZURyYWdTb3VyY2UoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93RHJhZ1RleHQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dEcmFnVGV4dCh0aGlzLmNvbHVtbik7XG4gICAgICAgIHZhciB0cmFuc2xhdGUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMb2NhbGVUZXh0RnVuYygpO1xuICAgICAgICB0aGlzLmRyYWdTb3VyY2UgPSB7XG4gICAgICAgICAgICB0eXBlOiBEcmFnU291cmNlVHlwZS5Sb3dEcmFnLFxuICAgICAgICAgICAgZUVsZW1lbnQ6IHRoaXMuZ2V0R3VpKCksXG4gICAgICAgICAgICBkcmFnSXRlbU5hbWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgX2E7XG4gICAgICAgICAgICAgICAgdmFyIGRyYWdJdGVtID0gX3RoaXMuZ2V0RHJhZ0l0ZW0oKTtcbiAgICAgICAgICAgICAgICB2YXIgZHJhZ0l0ZW1Db3VudCA9ICgoX2EgPSBkcmFnSXRlbS5yb3dOb2RlcykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmxlbmd0aCkgfHwgMTtcbiAgICAgICAgICAgICAgICBpZiAocm93RHJhZ1RleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvd0RyYWdUZXh0KGRyYWdJdGVtLCBkcmFnSXRlbUNvdW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRyYWdJdGVtQ291bnQgPT09IDEgPyBfdGhpcy5jZWxsVmFsdWVGbigpIDogZHJhZ0l0ZW1Db3VudCArIFwiIFwiICsgdHJhbnNsYXRlKCdyb3dEcmFnUm93cycsICdyb3dzJyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0RHJhZ0l0ZW06IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmdldERyYWdJdGVtKCk7IH0sXG4gICAgICAgICAgICBkcmFnU3RhcnRQaXhlbHM6IGRyYWdTdGFydFBpeGVscyxcbiAgICAgICAgICAgIGRyYWdTb3VyY2VEb21EYXRhS2V5OiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21EYXRhS2V5KClcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5iZWFucy5kcmFnQW5kRHJvcFNlcnZpY2UuYWRkRHJhZ1NvdXJjZSh0aGlzLmRyYWdTb3VyY2UsIHRydWUpO1xuICAgIH07XG4gICAgUm93RHJhZ0NvbXAucHJvdG90eXBlLnJlbW92ZURyYWdTb3VyY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmRyYWdTb3VyY2UpIHtcbiAgICAgICAgICAgIHRoaXMuYmVhbnMuZHJhZ0FuZERyb3BTZXJ2aWNlLnJlbW92ZURyYWdTb3VyY2UodGhpcy5kcmFnU291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRyYWdTb3VyY2UgPSBudWxsO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxJChbXG4gICAgICAgIEF1dG93aXJlZCgnYmVhbnMnKVxuICAgIF0sIFJvd0RyYWdDb21wLnByb3RvdHlwZSwgXCJiZWFuc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMSQoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93RHJhZ0NvbXAucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgX19kZWNvcmF0ZSQxJChbXG4gICAgICAgIFByZURlc3Ryb3lcbiAgICBdLCBSb3dEcmFnQ29tcC5wcm90b3R5cGUsIFwicmVtb3ZlRHJhZ1NvdXJjZVwiLCBudWxsKTtcbiAgICByZXR1cm4gUm93RHJhZ0NvbXA7XG59KENvbXBvbmVudCkpO1xudmFyIFZpc2liaWxpdHlTdHJhdGVneSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmcoVmlzaWJpbGl0eVN0cmF0ZWd5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFZpc2liaWxpdHlTdHJhdGVneShwYXJlbnQsIHJvd05vZGUsIGNvbHVtbikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgIF90aGlzLnJvd05vZGUgPSByb3dOb2RlO1xuICAgICAgICBfdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVmlzaWJpbGl0eVN0cmF0ZWd5LnByb3RvdHlwZS5zZXREaXNwbGF5ZWRPclZpc2libGUgPSBmdW5jdGlvbiAobmV2ZXJEaXNwbGF5ZWQpIHtcbiAgICAgICAgaWYgKG5ldmVyRGlzcGxheWVkKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudC5zZXREaXNwbGF5ZWQoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHNob3duID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBpc1Nob3duU29tZXRpbWVzID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBzaG93biA9IHRoaXMuY29sdW1uLmlzUm93RHJhZyh0aGlzLnJvd05vZGUpIHx8IHRoaXMucGFyZW50LmlzQ3VzdG9tR3VpKCk7XG4gICAgICAgICAgICAgICAgaXNTaG93blNvbWV0aW1lcyA9IGlzRnVuY3Rpb24odGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCkucm93RHJhZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiBzaG93biBzb21ldGltZXMsIHRoZW0gc29tZSByb3dzIGNhbiBoYXZlIGRyYWcgaGFuZGxlIHdoaWxlIG90aGVyIGRvbid0LFxuICAgICAgICAgICAgLy8gc28gd2UgdXNlIHNldFZpc2libGUgdG8ga2VlcCB0aGUgaGFuZGxlcyBob3Jpem9udGFsbHkgYWxpZ25lZCAoYXMgc2V0VmlzaWJsZVxuICAgICAgICAgICAgLy8ga2VlcHMgdGhlIGVtcHR5IHNwYWNlLCB3aGVyZWFzIHNldERpc3BsYXllZCBsb29zZXMgdGhlIHNwYWNlKVxuICAgICAgICAgICAgaWYgKGlzU2hvd25Tb21ldGltZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5zZXREaXNwbGF5ZWQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQuc2V0VmlzaWJsZShzaG93bik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5zZXREaXNwbGF5ZWQoc2hvd24pO1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LnNldFZpc2libGUodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBWaXNpYmlsaXR5U3RyYXRlZ3k7XG59KEJlYW5TdHViKSk7XG4vLyB3aGVuIG5vbiBtYW5hZ2VkLCB0aGUgdmlzaWJpbGl0eSBkZXBlbmRzIG9uIHN1cHByZXNzUm93RHJhZyBwcm9wZXJ0eSBvbmx5XG52YXIgTm9uTWFuYWdlZFZpc2liaWxpdHlTdHJhdGVneSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmcoTm9uTWFuYWdlZFZpc2liaWxpdHlTdHJhdGVneSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBOb25NYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5KHBhcmVudCwgYmVhbnMsIHJvd05vZGUsIGNvbHVtbikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBwYXJlbnQsIHJvd05vZGUsIGNvbHVtbikgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuYmVhbnMgPSBiZWFucztcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBOb25NYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5LnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlciwgJ3N1cHByZXNzUm93RHJhZycsIHRoaXMub25TdXBwcmVzc1Jvd0RyYWcuYmluZCh0aGlzKSk7XG4gICAgICAgIC8vIGluIGNhc2UgZGF0YSBjaGFuZ2VzLCB0aGVuIHdlIG5lZWQgdG8gdXBkYXRlIHZpc2liaWxpdHkgb2YgZHJhZyBpdGVtXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9EQVRBX0NIQU5HRUQsIHRoaXMud29ya091dFZpc2liaWxpdHkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9DRUxMX0NIQU5HRUQsIHRoaXMud29ya091dFZpc2liaWxpdHkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9DRUxMX0NIQU5HRUQsIHRoaXMud29ya091dFZpc2liaWxpdHkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuYmVhbnMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTkVXX0NPTFVNTlNfTE9BREVELCB0aGlzLndvcmtPdXRWaXNpYmlsaXR5LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLndvcmtPdXRWaXNpYmlsaXR5KCk7XG4gICAgfTtcbiAgICBOb25NYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5LnByb3RvdHlwZS5vblN1cHByZXNzUm93RHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy53b3JrT3V0VmlzaWJpbGl0eSgpO1xuICAgIH07XG4gICAgTm9uTWFuYWdlZFZpc2liaWxpdHlTdHJhdGVneS5wcm90b3R5cGUud29ya091dFZpc2liaWxpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIG9ubHkgc2hvdyB0aGUgZHJhZyBpZiBib3RoIHNvcnQgYW5kIGZpbHRlciBhcmUgbm90IHByZXNlbnRcbiAgICAgICAgdmFyIG5ldmVyRGlzcGxheWVkID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1Jvd0RyYWcoKTtcbiAgICAgICAgdGhpcy5zZXREaXNwbGF5ZWRPclZpc2libGUobmV2ZXJEaXNwbGF5ZWQpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxJChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBOb25NYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBOb25NYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5O1xufShWaXNpYmlsaXR5U3RyYXRlZ3kpKTtcbi8vIHdoZW4gbWFuYWdlZCwgdGhlIHZpc2liaWxpdHkgZGVwZW5kcyBvbiBzb3J0LCBmaWx0ZXIgYW5kIHJvdyBncm91cCwgYXMgd2VsbCBhcyBzdXBwcmVzc1Jvd0RyYWcgcHJvcGVydHlcbnZhciBNYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyZyhNYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIE1hbmFnZWRWaXNpYmlsaXR5U3RyYXRlZ3kocGFyZW50LCBiZWFucywgcm93Tm9kZSwgY29sdW1uKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHBhcmVudCwgcm93Tm9kZSwgY29sdW1uKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5iZWFucyA9IGJlYW5zO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE1hbmFnZWRWaXNpYmlsaXR5U3RyYXRlZ3kucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHdlIGRvIG5vdCBzaG93IHRoZSBjb21wb25lbnQgaWYgc29ydCwgZmlsdGVyIG9yIGdyb3VwaW5nIGlzIGFjdGl2ZVxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmJlYW5zLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1NPUlRfQ0hBTkdFRCwgdGhpcy53b3JrT3V0VmlzaWJpbGl0eS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5iZWFucy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9GSUxURVJfQ0hBTkdFRCwgdGhpcy53b3JrT3V0VmlzaWJpbGl0eS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5iZWFucy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIHRoaXMud29ya091dFZpc2liaWxpdHkuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuYmVhbnMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTkVXX0NPTFVNTlNfTE9BREVELCB0aGlzLndvcmtPdXRWaXNpYmlsaXR5LmJpbmQodGhpcykpO1xuICAgICAgICAvLyBpbiBjYXNlIGRhdGEgY2hhbmdlcywgdGhlbiB3ZSBuZWVkIHRvIHVwZGF0ZSB2aXNpYmlsaXR5IG9mIGRyYWcgaXRlbVxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfREFUQV9DSEFOR0VELCB0aGlzLndvcmtPdXRWaXNpYmlsaXR5LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfQ0VMTF9DSEFOR0VELCB0aGlzLndvcmtPdXRWaXNpYmlsaXR5LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlciwgJ3N1cHByZXNzUm93RHJhZycsIHRoaXMub25TdXBwcmVzc1Jvd0RyYWcuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMud29ya091dFZpc2liaWxpdHkoKTtcbiAgICB9O1xuICAgIE1hbmFnZWRWaXNpYmlsaXR5U3RyYXRlZ3kucHJvdG90eXBlLm9uU3VwcHJlc3NSb3dEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLndvcmtPdXRWaXNpYmlsaXR5KCk7XG4gICAgfTtcbiAgICBNYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5LnByb3RvdHlwZS53b3JrT3V0VmlzaWJpbGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gb25seSBzaG93IHRoZSBkcmFnIGlmIGJvdGggc29ydCBhbmQgZmlsdGVyIGFyZSBub3QgcHJlc2VudFxuICAgICAgICB2YXIgZ3JpZEJvZHlDb24gPSB0aGlzLmJlYW5zLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgdmFyIHJvd0RyYWdGZWF0dXJlID0gZ3JpZEJvZHlDb24uZ2V0Um93RHJhZ0ZlYXR1cmUoKTtcbiAgICAgICAgdmFyIHNob3VsZFByZXZlbnRSb3dNb3ZlID0gcm93RHJhZ0ZlYXR1cmUgJiYgcm93RHJhZ0ZlYXR1cmUuc2hvdWxkUHJldmVudFJvd01vdmUoKTtcbiAgICAgICAgdmFyIHN1cHByZXNzUm93RHJhZyA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NSb3dEcmFnKCk7XG4gICAgICAgIHZhciBoYXNFeHRlcm5hbERyb3Bab25lcyA9IHRoaXMuYmVhbnMuZHJhZ0FuZERyb3BTZXJ2aWNlLmhhc0V4dGVybmFsRHJvcFpvbmVzKCk7XG4gICAgICAgIHZhciBuZXZlckRpc3BsYXllZCA9IChzaG91bGRQcmV2ZW50Um93TW92ZSAmJiAhaGFzRXh0ZXJuYWxEcm9wWm9uZXMpIHx8IHN1cHByZXNzUm93RHJhZztcbiAgICAgICAgdGhpcy5zZXREaXNwbGF5ZWRPclZpc2libGUobmV2ZXJEaXNwbGF5ZWQpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxJChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBNYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBNYW5hZ2VkVmlzaWJpbGl0eVN0cmF0ZWd5O1xufShWaXNpYmlsaXR5U3RyYXRlZ3kpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyZiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXNzaWduJDggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2Fzc2lnbikgfHwgZnVuY3Rpb24gKCkge1xuICAgIF9fYXNzaWduJDggPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduJDguYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgX19kZWNvcmF0ZSQxXyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmYoR3JvdXBDZWxsUmVuZGVyZXJDdHJsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybCgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoY29tcCwgZUd1aSwgZUNoZWNrYm94LCBlRXhwYW5kZWQsIGVDb250cmFjdGVkLCBjb21wQ2xhc3MsIHBhcmFtcykge1xuICAgICAgICB0aGlzLnBhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgdGhpcy5lR3VpID0gZUd1aTtcbiAgICAgICAgdGhpcy5lQ2hlY2tib3ggPSBlQ2hlY2tib3g7XG4gICAgICAgIHRoaXMuZUV4cGFuZGVkID0gZUV4cGFuZGVkO1xuICAgICAgICB0aGlzLmVDb250cmFjdGVkID0gZUNvbnRyYWN0ZWQ7XG4gICAgICAgIHRoaXMuY29tcCA9IGNvbXA7XG4gICAgICAgIHRoaXMuY29tcENsYXNzID0gY29tcENsYXNzO1xuICAgICAgICB2YXIgdG9wTGV2ZWxGb290ZXIgPSB0aGlzLmlzVG9wTGV2ZWxGb290ZXIoKTtcbiAgICAgICAgdmFyIGVtYmVkZGVkUm93TWlzbWF0Y2ggPSB0aGlzLmlzRW1iZWRkZWRSb3dNaXNtYXRjaCgpO1xuICAgICAgICAvLyBUaGlzIGFsbG93cyBmb3IgZW1wdHkgc3RyaW5ncyB0byBhcHBlYXIgYXMgZ3JvdXBzIHNpbmNlXG4gICAgICAgIC8vIGl0IHdpbGwgb25seSByZXR1cm4gZm9yIG51bGwgb3IgdW5kZWZpbmVkLlxuICAgICAgICB2YXIgbnVsbFZhbHVlID0gcGFyYW1zLnZhbHVlID09IG51bGw7XG4gICAgICAgIHZhciBza2lwQ2VsbCA9IGZhbHNlO1xuICAgICAgICAvLyBpZiB0aGUgZ3JvdXBDZWxsUmVuZGVyZXIgaXMgaW5zaWRlIG9mIGEgZm9vdGVyIGFuZCBncm91cEhpZGVPcGVuUGFyZW50cyBpcyB0cnVlXG4gICAgICAgIC8vIHdlIHNob3VsZCBvbmx5IGRpc3BsYXkgdGhlIGdyb3VwQ2VsbFJlbmRlcmVyIGlmIHRoZSBjdXJyZW50IGNvbHVtbiBpcyB0aGUgcm93R3JvdXBlZENvbHVtblxuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cEluY2x1ZGVGb290ZXIoKSAmJiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwSGlkZU9wZW5QYXJlbnRzKCkpIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gcGFyYW1zLm5vZGU7XG4gICAgICAgICAgICBpZiAobm9kZS5mb290ZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2hvd1Jvd0dyb3VwID0gcGFyYW1zLmNvbERlZiAmJiBwYXJhbXMuY29sRGVmLnNob3dSb3dHcm91cDtcbiAgICAgICAgICAgICAgICB2YXIgcm93R3JvdXBDb2x1bW5JZCA9IG5vZGUucm93R3JvdXBDb2x1bW4gJiYgbm9kZS5yb3dHcm91cENvbHVtbi5nZXRDb2xJZCgpO1xuICAgICAgICAgICAgICAgIHNraXBDZWxsID0gc2hvd1Jvd0dyb3VwICE9PSByb3dHcm91cENvbHVtbklkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2VsbElzQmxhbmsgPSB0b3BMZXZlbEZvb3RlciA/IGZhbHNlIDogKGVtYmVkZGVkUm93TWlzbWF0Y2ggfHwgbnVsbFZhbHVlIHx8IHNraXBDZWxsKTtcbiAgICAgICAgaWYgKHRoaXMuY2VsbElzQmxhbmspIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldHVwU2hvd2luZ1ZhbHVlRm9yT3BlbmVkUGFyZW50KCk7XG4gICAgICAgIHRoaXMuZmluZERpc3BsYXllZEdyb3VwTm9kZSgpO1xuICAgICAgICB0aGlzLmFkZEZ1bGxXaWR0aFJvd0RyYWdnZXJJZk5lZWRlZCgpO1xuICAgICAgICB0aGlzLmFkZEV4cGFuZEFuZENvbnRyYWN0KCk7XG4gICAgICAgIHRoaXMuYWRkQ2hlY2tib3hJZk5lZWRlZCgpO1xuICAgICAgICB0aGlzLmFkZFZhbHVlRWxlbWVudCgpO1xuICAgICAgICB0aGlzLnNldHVwSW5kZW50KCk7XG4gICAgICAgIHRoaXMucmVmcmVzaEFyaWFFeHBhbmRlZCgpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICAgICAgLy8gcHJvcGVydHkgY2xlYW51cCB0byBhdm9pZCBtZW1vcnkgbGVha3NcbiAgICAgICAgdGhpcy5leHBhbmRMaXN0ZW5lciA9IG51bGw7XG4gICAgfTtcbiAgICBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLnJlZnJlc2hBcmlhRXhwYW5kZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMucGFyYW1zLCBub2RlID0gX2Eubm9kZSwgZVBhcmVudE9mVmFsdWUgPSBfYS5lUGFyZW50T2ZWYWx1ZTtcbiAgICAgICAgaWYgKHRoaXMuZXhwYW5kTGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZXhwYW5kTGlzdGVuZXIgPSB0aGlzLmV4cGFuZExpc3RlbmVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmlzRXhwYW5kYWJsZSgpKSB7XG4gICAgICAgICAgICByZW1vdmVBcmlhRXhwYW5kZWQoZVBhcmVudE9mVmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIGZvciByZWFjdCwgd2UgZG9uJ3QgdXNlIEpTWCwgYXMgc2V0dGluZyBhdHRyaWJ1dGVzIHZpYSBqc3ggaXMgc2xvd2VyXG4gICAgICAgICAgICBzZXRBcmlhRXhwYW5kZWQoZVBhcmVudE9mVmFsdWUsICEhbm9kZS5leHBhbmRlZCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXhwYW5kTGlzdGVuZXIgPSB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihub2RlLCBSb3dOb2RlLkVWRU5UX0VYUEFOREVEX0NIQU5HRUQsIGxpc3RlbmVyKSB8fCBudWxsO1xuICAgICAgICBsaXN0ZW5lcigpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5pc1RvcExldmVsRm9vdGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBJbmNsdWRlVG90YWxGb290ZXIoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy52YWx1ZSAhPSBudWxsIHx8IHRoaXMucGFyYW1zLm5vZGUubGV2ZWwgIT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBhdCB0aGlzIHBvaW50LCB3ZSBrbm93IGl0J3MgdGhlIHJvb3Qgbm9kZSBhbmQgdGhlcmUgaXMgbm8gdmFsdWUgcHJlc2VudCwgc28gaXQncyBhIGZvb3RlciBjZWxsLlxuICAgICAgICAvLyB0aGUgb25seSB0aGluZyB0byB3b3JrIG91dCBpcyBpZiB3ZSBhcmUgZGlzcGxheWluZyBncm91cHMgIGFjcm9zcyBtdWx0aXBsZVxuICAgICAgICAvLyBjb2x1bW5zIChncm91cE11bHRpQXV0b0NvbHVtbj10cnVlKSwgd2Ugb25seSB3YW50ICd0b3RhbCcgdG8gYXBwZWFyIGluIHRoZSBmaXJzdCBjb2x1bW4uXG4gICAgICAgIHZhciBjb2xEZWYgPSB0aGlzLnBhcmFtcy5jb2xEZWY7XG4gICAgICAgIHZhciBkb2luZ0Z1bGxXaWR0aCA9IGNvbERlZiA9PSBudWxsO1xuICAgICAgICBpZiAoZG9pbmdGdWxsV2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb2xEZWYuc2hvd1Jvd0dyb3VwID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93R3JvdXBDb2xzID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRSb3dHcm91cENvbHVtbnMoKTtcbiAgICAgICAgLy8gdGhpcyBpcyBhIHNhbml0eSBjaGVjaywgcm93R3JvdXBDb2xzIHNob3VsZCBhbHdheXMgYmUgcHJlc2VudFxuICAgICAgICBpZiAoIXJvd0dyb3VwQ29scyB8fCByb3dHcm91cENvbHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmlyc3RSb3dHcm91cENvbCA9IHJvd0dyb3VwQ29sc1swXTtcbiAgICAgICAgcmV0dXJuIGZpcnN0Um93R3JvdXBDb2wuZ2V0SWQoKSA9PT0gY29sRGVmLnNob3dSb3dHcm91cDtcbiAgICB9O1xuICAgIC8vIGlmIHdlIGFyZSBkb2luZyBlbWJlZGRlZCBmdWxsIHdpZHRoIHJvd3MsIHdlIG9ubHkgc2hvdyB0aGUgcmVuZGVyZXIgd2hlblxuICAgIC8vIGluIHRoZSBib2R5LCBvciBpZiBwaW5uaW5nIGluIHRoZSBwaW5uZWQgc2VjdGlvbiwgb3IgaWYgcGlubmluZyBhbmQgUlRMLFxuICAgIC8vIGluIHRoZSByaWdodCBzZWN0aW9uLiBvdGhlcndpc2Ugd2Ugd291bGQgaGF2ZSB0aGUgY2VsbCByZXBlYXRlZCBpbiBlYWNoIHNlY3Rpb24uXG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5pc0VtYmVkZGVkUm93TWlzbWF0Y2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5wYXJhbXMuZnVsbFdpZHRoIHx8ICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VtYmVkRnVsbFdpZHRoUm93cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBpbm5lZExlZnRDZWxsID0gdGhpcy5wYXJhbXMucGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX0xFRlQ7XG4gICAgICAgIHZhciBwaW5uZWRSaWdodENlbGwgPSB0aGlzLnBhcmFtcy5waW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfUklHSFQ7XG4gICAgICAgIHZhciBib2R5Q2VsbCA9ICFwaW5uZWRMZWZ0Q2VsbCAmJiAhcGlubmVkUmlnaHRDZWxsO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29sdW1uTW9kZWwuaXNQaW5uaW5nTGVmdCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICFwaW5uZWRSaWdodENlbGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gIWJvZHlDZWxsO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbHVtbk1vZGVsLmlzUGlubmluZ0xlZnQoKSkge1xuICAgICAgICAgICAgcmV0dXJuICFwaW5uZWRMZWZ0Q2VsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gIWJvZHlDZWxsO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5maW5kRGlzcGxheWVkR3JvdXBOb2RlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5wYXJhbXMuY29sdW1uO1xuICAgICAgICB2YXIgcm93Tm9kZSA9IHRoaXMucGFyYW1zLm5vZGU7XG4gICAgICAgIGlmICh0aGlzLnNob3dpbmdWYWx1ZUZvck9wZW5lZFBhcmVudCkge1xuICAgICAgICAgICAgdmFyIHBvaW50ZXIgPSByb3dOb2RlLnBhcmVudDtcbiAgICAgICAgICAgIHdoaWxlIChwb2ludGVyICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAocG9pbnRlci5yb3dHcm91cENvbHVtbiAmJiBjb2x1bW4uaXNSb3dHcm91cERpc3BsYXllZChwb2ludGVyLnJvd0dyb3VwQ29sdW1uLmdldElkKCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlID0gcG9pbnRlcjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB3ZSBkaWRuJ3QgZmluZCBhIGRpc3BsYXllZCBncm91cCwgc2V0IGl0IHRvIHRoZSByb3cgbm9kZVxuICAgICAgICBpZiAobWlzc2luZyh0aGlzLmRpc3BsYXllZEdyb3VwTm9kZSkpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlID0gcm93Tm9kZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5zZXR1cFNob3dpbmdWYWx1ZUZvck9wZW5lZFBhcmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gbm90ZSAtIHRoaXMgY29kZSBkZXBlbmRzIG9uIHNvcnRTZXJ2aWNlLnVwZGF0ZUdyb3VwRGF0YUZvckhpZGRlbk9wZW5QYXJlbnRzLCB3aGVyZSBncm91cCBkYXRhXG4gICAgICAgIC8vIGlzIHVwZGF0ZWQgdG8gcmVmbGVjdCB0aGUgZHJhZ2dlZCBkb3duIHBhcmVudHNcbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLnBhcmFtcy5ub2RlO1xuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5wYXJhbXMuY29sdW1uO1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBIaWRlT3BlblBhcmVudHMoKSkge1xuICAgICAgICAgICAgdGhpcy5zaG93aW5nVmFsdWVGb3JPcGVuZWRQYXJlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBoaWRlT3BlblBhcmVudHMgbWVhbnMgcm93Tm9kZS5ncm91cERhdGEgY2FuIGhhdmUgZGF0YSBmb3IgdGhlIGdyb3VwIHRoaXMgY29sdW1uIGlzIGRpc3BsYXlpbmcsIGV2ZW4gdGhvdWdoXG4gICAgICAgIC8vIHRoaXMgcm93Tm9kZSBpc24ndCBncm91cGluZyBieSB0aGUgY29sdW1uIHdlIGFyZSBkaXNwbGF5aW5nXG4gICAgICAgIC8vIGlmIG5vIGdyb3VwRGF0YSBhdCBhbGwsIHdlIGFyZSBub3Qgc2hvd2luZyBhIHBhcmVudCB2YWx1ZVxuICAgICAgICBpZiAoIXJvd05vZGUuZ3JvdXBEYXRhKSB7XG4gICAgICAgICAgICB0aGlzLnNob3dpbmdWYWx1ZUZvck9wZW5lZFBhcmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIG5vcm1hbCBjYXNlLCBpbiB0aGF0IHdlIGFyZSBzaG93aW5nIGEgZ3JvdXAgZm9yIHdoaWNoIHRoaXMgY29sdW1uIGlzIGNvbmZpZ3VyZWQuIG5vdGUgdGhhdFxuICAgICAgICAvLyB0aGlzIG1lYW5zIHRoZSBSb3cgR3JvdXAgaXMgY2xvc2VkIChpZiBpdCB3YXMgb3Blbiwgd2Ugd291bGQgbm90IGJlIGRpc3BsYXlpbmcgaXQpXG4gICAgICAgIHZhciBzaG93aW5nR3JvdXBOb2RlID0gcm93Tm9kZS5yb3dHcm91cENvbHVtbiAhPSBudWxsO1xuICAgICAgICBpZiAoc2hvd2luZ0dyb3VwTm9kZSkge1xuICAgICAgICAgICAgdmFyIGtleU9mR3JvdXBpbmdDb2x1bW4gPSByb3dOb2RlLnJvd0dyb3VwQ29sdW1uLmdldElkKCk7XG4gICAgICAgICAgICB2YXIgY29uZmlndXJlZFRvU2hvd1RoaXNHcm91cExldmVsID0gY29sdW1uLmlzUm93R3JvdXBEaXNwbGF5ZWQoa2V5T2ZHcm91cGluZ0NvbHVtbik7XG4gICAgICAgICAgICAvLyBpZiBzaG93aW5nIGdyb3VwIGFzIG5vcm1hbCwgd2UgZGlkbid0IHRha2UgZ3JvdXAgaW5mbyBmcm9tIHBhcmVudFxuICAgICAgICAgICAgaWYgKGNvbmZpZ3VyZWRUb1Nob3dUaGlzR3JvdXBMZXZlbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2hvd2luZ1ZhbHVlRm9yT3BlbmVkUGFyZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHNlZSBpZiB3ZSBhcmUgc2hvd2luZyBhIEdyb3VwIFZhbHVlIGZvciB0aGUgRGlzcGxheWVkIEdyb3VwLiBpZiB3ZSBhcmUgc2hvd2luZyBhIGdyb3VwIHZhbHVlLCBhbmQgdGhpcyBSb3cgTm9kZVxuICAgICAgICAvLyBpcyBub3QgZ3JvdXBpbmcgYnkgdGhpcyBEaXNwbGF5ZWQgR3JvdXAsIHdlIG11c3Qgb2YgZ290dGVuIHRoZSB2YWx1ZSBmcm9tIGEgcGFyZW50IG5vZGVcbiAgICAgICAgdmFyIHZhbFByZXNlbnQgPSByb3dOb2RlLmdyb3VwRGF0YVtjb2x1bW4uZ2V0SWQoKV0gIT0gbnVsbDtcbiAgICAgICAgdGhpcy5zaG93aW5nVmFsdWVGb3JPcGVuZWRQYXJlbnQgPSB2YWxQcmVzZW50O1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5hZGRWYWx1ZUVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXllZEdyb3VwTm9kZS5mb290ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkRm9vdGVyVmFsdWUoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYWRkR3JvdXBWYWx1ZSgpO1xuICAgICAgICAgICAgdGhpcy5hZGRDaGlsZENvdW50KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUuYWRkR3JvdXBWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2UgdHJ5IGFuZCB1c2UgdGhlIGNlbGxSZW5kZXJlciBvZiB0aGUgY29sdW1uIHVzZWQgZm9yIHRoZSBncm91cGluZyBpZiB3ZSBjYW5cbiAgICAgICAgdmFyIHBhcmFtc0FkanVzdGVkID0gdGhpcy5hZGp1c3RQYXJhbXNXaXRoRGV0YWlsc0Zyb21SZWxhdGVkQ29sdW1uKCk7XG4gICAgICAgIHZhciBpbm5lckNvbXBEZXRhaWxzID0gdGhpcy5nZXRJbm5lckNvbXBEZXRhaWxzKHBhcmFtc0FkanVzdGVkKTtcbiAgICAgICAgdmFyIHZhbHVlRm9ybWF0dGVkID0gcGFyYW1zQWRqdXN0ZWQudmFsdWVGb3JtYXR0ZWQsIHZhbHVlID0gcGFyYW1zQWRqdXN0ZWQudmFsdWU7XG4gICAgICAgIHZhciB2YWx1ZVdoZW5Ob1JlbmRlcmVyID0gdmFsdWVGb3JtYXR0ZWQgIT0gbnVsbCA/IHZhbHVlRm9ybWF0dGVkIDogdmFsdWU7XG4gICAgICAgIHRoaXMuY29tcC5zZXRJbm5lclJlbmRlcmVyKGlubmVyQ29tcERldGFpbHMsIHZhbHVlV2hlbk5vUmVuZGVyZXIpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5hZGp1c3RQYXJhbXNXaXRoRGV0YWlsc0Zyb21SZWxhdGVkQ29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVsYXRlZENvbHVtbiA9IHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlLnJvd0dyb3VwQ29sdW1uO1xuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5wYXJhbXMuY29sdW1uO1xuICAgICAgICBpZiAoIXJlbGF0ZWRDb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtcztcbiAgICAgICAgfVxuICAgICAgICB2YXIgbm90RnVsbFdpZHRoID0gY29sdW1uICE9IG51bGw7XG4gICAgICAgIGlmIChub3RGdWxsV2lkdGgpIHtcbiAgICAgICAgICAgIHZhciBzaG93aW5nVGhpc1Jvd0dyb3VwID0gY29sdW1uLmlzUm93R3JvdXBEaXNwbGF5ZWQocmVsYXRlZENvbHVtbi5nZXRJZCgpKTtcbiAgICAgICAgICAgIGlmICghc2hvd2luZ1RoaXNSb3dHcm91cCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcmFtcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0gdGhpcy5wYXJhbXM7XG4gICAgICAgIHZhciBfYSA9IHRoaXMucGFyYW1zLCB2YWx1ZSA9IF9hLnZhbHVlLCBub2RlID0gX2Eubm9kZTtcbiAgICAgICAgdmFyIHZhbHVlRm9ybWF0dGVkID0gdGhpcy52YWx1ZUZvcm1hdHRlclNlcnZpY2UuZm9ybWF0VmFsdWUocmVsYXRlZENvbHVtbiwgbm9kZSwgdmFsdWUpO1xuICAgICAgICAvLyB3ZSBkb24ndCB1cGRhdGUgdGhlIG9yaWdpbmFsIHBhcmFtcywgYXMgdGhleSBjb3VsZCBvZiBjb21lIHRocm91Z2ggUmVhY3QsXG4gICAgICAgIC8vIGFzIHJlYWN0IGhhcyBSb3dHcm91cENlbGxSZW5kZXJlciwgd2hpY2ggbWVhbnMgdGhlIHBhcmFtcyBjb3VsZCBiZSBwcm9wcyB3aGljaFxuICAgICAgICAvLyB3b3VsZCBiZSByZWFkIG9ubHlcbiAgICAgICAgdmFyIHBhcmFtc0FkanVzdGVkID0gX19hc3NpZ24kOChfX2Fzc2lnbiQ4KHt9LCBwYXJhbXMpLCB7IHZhbHVlRm9ybWF0dGVkOiB2YWx1ZUZvcm1hdHRlZCB9KTtcbiAgICAgICAgcmV0dXJuIHBhcmFtc0FkanVzdGVkO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5hZGRGb290ZXJWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZvb3RlclZhbHVlR2V0dGVyID0gdGhpcy5wYXJhbXMuZm9vdGVyVmFsdWVHZXR0ZXI7XG4gICAgICAgIHZhciBmb290ZXJWYWx1ZSA9ICcnO1xuICAgICAgICBpZiAoZm9vdGVyVmFsdWVHZXR0ZXIpIHtcbiAgICAgICAgICAgIC8vIHBhcmFtcyBpcyBzYW1lIGFzIHdlIHdlcmUgZ2l2ZW4sIGV4Y2VwdCB3ZSBzZXQgdGhlIHZhbHVlIGFzIHRoZSBpdGVtIHRvIGRpc3BsYXlcbiAgICAgICAgICAgIHZhciBwYXJhbXNDbG9uZSA9IGNsb25lT2JqZWN0KHRoaXMucGFyYW1zKTtcbiAgICAgICAgICAgIHBhcmFtc0Nsb25lLnZhbHVlID0gdGhpcy5wYXJhbXMudmFsdWU7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGZvb3RlclZhbHVlR2V0dGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgZm9vdGVyVmFsdWUgPSBmb290ZXJWYWx1ZUdldHRlcihwYXJhbXNDbG9uZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgZm9vdGVyVmFsdWVHZXR0ZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgZm9vdGVyVmFsdWUgPSB0aGlzLmV4cHJlc3Npb25TZXJ2aWNlLmV2YWx1YXRlKGZvb3RlclZhbHVlR2V0dGVyLCBwYXJhbXNDbG9uZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGZvb3RlclZhbHVlR2V0dGVyIHNob3VsZCBiZSBlaXRoZXIgYSBmdW5jdGlvbiBvciBhIHN0cmluZyAoZXhwcmVzc2lvbiknKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvb3RlclZhbHVlID0gJ1RvdGFsICcgKyAodGhpcy5wYXJhbXMudmFsdWUgIT0gbnVsbCA/IHRoaXMucGFyYW1zLnZhbHVlIDogJycpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbm5lckNvbXBEZXRhaWxzID0gdGhpcy5nZXRJbm5lckNvbXBEZXRhaWxzKHRoaXMucGFyYW1zKTtcbiAgICAgICAgdGhpcy5jb21wLnNldElubmVyUmVuZGVyZXIoaW5uZXJDb21wRGV0YWlscywgZm9vdGVyVmFsdWUpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5nZXRJbm5lckNvbXBEZXRhaWxzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBmb3IgZnVsbCB3aWR0aCByb3dzLCB3ZSBkb24ndCBkbyBhbnkgb2YgdGhlIGJlbG93XG4gICAgICAgIGlmIChwYXJhbXMuZnVsbFdpZHRoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeS5nZXRGdWxsV2lkdGhHcm91cFJvd0lubmVyQ2VsbFJlbmRlcmVyKHRoaXMuZ3JpZE9wdGlvbnMuZ3JvdXBSb3dSZW5kZXJlclBhcmFtcywgcGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB3aGVuIGdyb3VwaW5nLCB0aGUgbm9ybWFsIGNhc2UgaXMgd2UgdXNlIHRoZSBjZWxsIHJlbmRlcmVyIG9mIHRoZSBncm91cGVkIGNvbHVtbi4gZWcgaWYgZ3JvdXBpbmcgYnkgY291bnRyeVxuICAgICAgICAvLyBhbmQgdGhlbiByYXRpbmcsIHdlIHdpbGwgdXNlIHRoZSBjb3VudHJ5IGNlbGwgcmVuZGVyZXIgZm9yIGVhY2ggY291bnRyeSBncm91cCByb3cgYW5kIGxpa2V3aXNlIHRoZSByYXRpbmdcbiAgICAgICAgLy8gY2VsbCByZW5kZXJlciBmb3IgZWFjaCByYXRpbmcgZ3JvdXAgcm93LlxuICAgICAgICAvL1xuICAgICAgICAvLyBob3dldmVyIGlmIHRoZSB1c2VyIGhhcyBpbm5lckNlbGxSZW5kZXJlciBkZWZpbmVkLCB0aGlzIGdldHMgcHJlZmVyZW5jZSBhbmQgd2UgZG9uJ3QgdXNlIGNlbGwgcmVuZGVyZXJzXG4gICAgICAgIC8vIG9mIHRoZSBncm91cGVkIGNvbHVtbnMuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIHNvIHdlIGNoZWNrIGFuZCB1c2UgaW4gdGhlIGZvbGxvd2luZyBvcmRlcjpcbiAgICAgICAgLy9cbiAgICAgICAgLy8gMSkgdGhpc0NvbERlZi5jZWxsUmVuZGVyZXJQYXJhbXMuaW5uZXJSZW5kZXJlciBvZiB0aGUgY29sdW1uIHNob3dpbmcgdGhlIGdyb3VwcyAoZWcgYXV0byBncm91cCBjb2x1bW4pXG4gICAgICAgIC8vIDIpIGdyb3VwZWRDb2xEZWYuY2VsbFJlbmRlcmVyIG9mIHRoZSBncm91cGVkIGNvbHVtblxuICAgICAgICAvLyAzKSBncm91cGVkQ29sRGVmLmNlbGxSZW5kZXJlclBhcmFtcy5pbm5lclJlbmRlcmVyXG4gICAgICAgIC8vIHdlIGNoZWNrIGlmIGNlbGwgcmVuZGVyZXIgcHJvdmlkZWQgZm9yIHRoZSBncm91cCBjZWxsIHJlbmRlcmVyLCBlZyBjb2xEZWYuY2VsbFJlbmRlcmVyUGFyYW1zLmlubmVyUmVuZGVyZXJcbiAgICAgICAgdmFyIGlubmVyQ29tcERldGFpbHMgPSB0aGlzLnVzZXJDb21wb25lbnRGYWN0b3J5XG4gICAgICAgICAgICAuZ2V0SW5uZXJSZW5kZXJlckRldGFpbHMocGFyYW1zLCBwYXJhbXMpO1xuICAgICAgICAvLyBhdm9pZCB1c2luZyBHcm91cENlbGxSZW5kZXJlciBhZ2Fpbiwgb3RoZXJ3aXNlIHN0YWNrIG92ZXJmbG93LCBhcyB3ZSBpbnNlcnQgc2FtZSByZW5kZXJlciBhZ2FpbiBhbmQgYWdhaW4uXG4gICAgICAgIC8vIHRoaXMgY292ZXJzIG9mZiBjaGFuY2UgdXNlciBpcyBncm91cGluZyBieSBhIGNvbHVtbiB0aGF0IGlzIGFsc28gY29uZmlndXJlZCB3aXRoIEdyb3VwQ2VsbFJlbmRlcmVyXG4gICAgICAgIHZhciBpc0dyb3VwUm93UmVuZGVyZXIgPSBmdW5jdGlvbiAoZGV0YWlscykgeyByZXR1cm4gZGV0YWlscyAmJiBkZXRhaWxzLmNvbXBvbmVudENsYXNzID09IF90aGlzLmNvbXBDbGFzczsgfTtcbiAgICAgICAgaWYgKGlubmVyQ29tcERldGFpbHMgJiYgIWlzR3JvdXBSb3dSZW5kZXJlcihpbm5lckNvbXBEZXRhaWxzKSkge1xuICAgICAgICAgICAgLy8gdXNlIHRoZSByZW5kZXJlciBkZWZpbmVkIGluIGNlbGxSZW5kZXJlclBhcmFtcy5pbm5lclJlbmRlcmVyXG4gICAgICAgICAgICByZXR1cm4gaW5uZXJDb21wRGV0YWlscztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVsYXRlZENvbHVtbiA9IHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlLnJvd0dyb3VwQ29sdW1uO1xuICAgICAgICB2YXIgcmVsYXRlZENvbERlZiA9IHJlbGF0ZWRDb2x1bW4gPyByZWxhdGVkQ29sdW1uLmdldENvbERlZigpIDogdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIXJlbGF0ZWRDb2xEZWYpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2Ugc2VlIGlmIHdlIGNhbiB1c2UgdGhlIGNlbGxSZW5kZXJlciBvZiB0aGUgY29sdW1uIHdlIGFyZSBncm91cGluZyBieVxuICAgICAgICB2YXIgcmVsYXRlZENvbXBEZXRhaWxzID0gdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeVxuICAgICAgICAgICAgLmdldENlbGxSZW5kZXJlckRldGFpbHMocmVsYXRlZENvbERlZiwgcGFyYW1zKTtcbiAgICAgICAgaWYgKHJlbGF0ZWRDb21wRGV0YWlscyAmJiAhaXNHcm91cFJvd1JlbmRlcmVyKHJlbGF0ZWRDb21wRGV0YWlscykpIHtcbiAgICAgICAgICAgIC8vIE9ubHkgaWYgdGhlIG9yaWdpbmFsIGNvbHVtbiBpcyB1c2luZyBhIHNwZWNpZmljIHJlbmRlcmVyLCBpdCBpdCBpcyBhIHVzaW5nIGEgREVGQVVMVCBvbmUgaWdub3JlIGl0XG4gICAgICAgICAgICByZXR1cm4gcmVsYXRlZENvbXBEZXRhaWxzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0dyb3VwUm93UmVuZGVyZXIocmVsYXRlZENvbXBEZXRhaWxzKSAmJlxuICAgICAgICAgICAgcmVsYXRlZENvbERlZi5jZWxsUmVuZGVyZXJQYXJhbXMgJiZcbiAgICAgICAgICAgIHJlbGF0ZWRDb2xEZWYuY2VsbFJlbmRlcmVyUGFyYW1zLmlubmVyUmVuZGVyZXIpIHtcbiAgICAgICAgICAgIC8vIGVkZ2UgY2FzZSAtIHRoaXMgY29tZXMgZnJvbSBhIGNvbHVtbiB3aGljaCBoYXMgYmVlbiBncm91cGVkIGR5bmFtaWNhbGx5LCB0aGF0IGhhcyBhIHJlbmRlcmVyICdncm91cCdcbiAgICAgICAgICAgIC8vIGFuZCBoYXMgYW4gaW5uZXIgY2VsbCByZW5kZXJlclxuICAgICAgICAgICAgdmFyIHJlcyA9IHRoaXMudXNlckNvbXBvbmVudEZhY3RvcnkuZ2V0SW5uZXJSZW5kZXJlckRldGFpbHMocmVsYXRlZENvbERlZi5jZWxsUmVuZGVyZXJQYXJhbXMsIHBhcmFtcyk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLmFkZENoaWxkQ291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIG9ubHkgaW5jbHVkZSB0aGUgY2hpbGQgY291bnQgaWYgaXQncyBpbmNsdWRlZCwgZWcgaWYgdXNlciBkb2luZyBjdXN0b20gYWdncmVnYXRpb24sXG4gICAgICAgIC8vIHRoZW4gdGhpcyBjb3VsZCBiZSBsZWZ0IG91dCwgb3Igc2V0IHRvIC0xLCBpZSBubyBjaGlsZCBjb3VudFxuICAgICAgICBpZiAodGhpcy5wYXJhbXMuc3VwcHJlc3NDb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlLCBSb3dOb2RlLkVWRU5UX0FMTF9DSElMRFJFTl9DT1VOVF9DSEFOR0VELCB0aGlzLnVwZGF0ZUNoaWxkQ291bnQuYmluZCh0aGlzKSk7XG4gICAgICAgIC8vIGZpbHRlcmluZyBjaGFuZ2VzIHRoZSBjaGlsZCBjb3VudCwgc28gbmVlZCB0byBjYXRlciBmb3IgaXRcbiAgICAgICAgdGhpcy51cGRhdGVDaGlsZENvdW50KCk7XG4gICAgfTtcbiAgICBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLnVwZGF0ZUNoaWxkQ291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhbGxDaGlsZHJlbkNvdW50ID0gdGhpcy5kaXNwbGF5ZWRHcm91cE5vZGUuYWxsQ2hpbGRyZW5Db3VudDtcbiAgICAgICAgdmFyIHNob3dpbmdHcm91cEZvclRoaXNOb2RlID0gdGhpcy5pc1Nob3dSb3dHcm91cEZvclRoaXNSb3coKTtcbiAgICAgICAgdmFyIHNob3dDb3VudCA9IHNob3dpbmdHcm91cEZvclRoaXNOb2RlICYmIGFsbENoaWxkcmVuQ291bnQgIT0gbnVsbCAmJiBhbGxDaGlsZHJlbkNvdW50ID49IDA7XG4gICAgICAgIHZhciBjb3VudFN0cmluZyA9IHNob3dDb3VudCA/IFwiKFwiICsgYWxsQ2hpbGRyZW5Db3VudCArIFwiKVwiIDogXCJcIjtcbiAgICAgICAgdGhpcy5jb21wLnNldENoaWxkQ291bnQoY291bnRTdHJpbmcpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5pc1Nob3dSb3dHcm91cEZvclRoaXNSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1RyZWVEYXRhKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dHcm91cENvbHVtbiA9IHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlLnJvd0dyb3VwQ29sdW1uO1xuICAgICAgICBpZiAoIXJvd0dyb3VwQ29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY29sdW1uIGlzIG51bGwgZm9yIGZ1bGxXaWR0aFJvd3NcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMucGFyYW1zLmNvbHVtbjtcbiAgICAgICAgdmFyIHRoaXNDb2x1bW5Jc0ludGVyZXN0ZWQgPSBjb2x1bW4gPT0gbnVsbCB8fCBjb2x1bW4uaXNSb3dHcm91cERpc3BsYXllZChyb3dHcm91cENvbHVtbi5nZXRJZCgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXNDb2x1bW5Jc0ludGVyZXN0ZWQ7XG4gICAgfTtcbiAgICBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLmFkZEV4cGFuZEFuZENvbnRyYWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyYW1zID0gdGhpcy5wYXJhbXM7XG4gICAgICAgIHZhciBlRXhwYW5kZWRJY29uID0gY3JlYXRlSWNvbk5vU3BhbignZ3JvdXBFeHBhbmRlZCcsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgdmFyIGVDb250cmFjdGVkSWNvbiA9IGNyZWF0ZUljb25Ob1NwYW4oJ2dyb3VwQ29udHJhY3RlZCcsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKTtcbiAgICAgICAgaWYgKGVFeHBhbmRlZEljb24pIHtcbiAgICAgICAgICAgIHRoaXMuZUV4cGFuZGVkLmFwcGVuZENoaWxkKGVFeHBhbmRlZEljb24pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlQ29udHJhY3RlZEljb24pIHtcbiAgICAgICAgICAgIHRoaXMuZUNvbnRyYWN0ZWQuYXBwZW5kQ2hpbGQoZUNvbnRyYWN0ZWRJY29uKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZUdyb3VwQ2VsbCA9IHBhcmFtcy5lR3JpZENlbGw7XG4gICAgICAgIC8vIGlmIGVkaXRpbmcgZ3JvdXBzLCB0aGVuIGRvdWJsZSBjbGljayBpcyB0byBzdGFydCBlZGl0aW5nXG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVHcm91cEVkaXQoKSAmJiB0aGlzLmlzRXhwYW5kYWJsZSgpICYmICFwYXJhbXMuc3VwcHJlc3NEb3VibGVDbGlja0V4cGFuZCkge1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZUdyb3VwQ2VsbCwgJ2RibGNsaWNrJywgdGhpcy5vbkNlbGxEYmxDbGlja2VkLmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUV4cGFuZGVkLCAnY2xpY2snLCB0aGlzLm9uRXhwYW5kQ2xpY2tlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lQ29udHJhY3RlZCwgJ2NsaWNrJywgdGhpcy5vbkV4cGFuZENsaWNrZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIC8vIGV4cGFuZCAvIGNvbnRyYWN0IGFzIHRoZSB1c2VyIGhpdHMgZW50ZXJcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZUdyb3VwQ2VsbCwgJ2tleWRvd24nLCB0aGlzLm9uS2V5RG93bi5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIocGFyYW1zLm5vZGUsIFJvd05vZGUuRVZFTlRfRVhQQU5ERURfQ0hBTkdFRCwgdGhpcy5zaG93RXhwYW5kQW5kQ29udHJhY3RJY29ucy5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5zaG93RXhwYW5kQW5kQ29udHJhY3RJY29ucygpO1xuICAgICAgICAvLyBiZWNhdXNlIHdlIGRvbid0IHNob3cgdGhlIGV4cGFuZCAvIGNvbnRyYWN0IHdoZW4gdGhlcmUgYXJlIG5vIGNoaWxkcmVuLCB3ZSBuZWVkIHRvIGNoZWNrIGV2ZXJ5IHRpbWVcbiAgICAgICAgLy8gdGhlIG51bWJlciBvZiBjaGlsZHJlbiBjaGFuZ2UuXG4gICAgICAgIHZhciBleHBhbmRhYmxlQ2hhbmdlZExpc3RlbmVyID0gdGhpcy5vblJvd05vZGVJc0V4cGFuZGFibGVDaGFuZ2VkLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZGlzcGxheWVkR3JvdXBOb2RlLCBSb3dOb2RlLkVWRU5UX0FMTF9DSElMRFJFTl9DT1VOVF9DSEFOR0VELCBleHBhbmRhYmxlQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5kaXNwbGF5ZWRHcm91cE5vZGUsIFJvd05vZGUuRVZFTlRfTUFTVEVSX0NIQU5HRUQsIGV4cGFuZGFibGVDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmRpc3BsYXllZEdyb3VwTm9kZSwgUm93Tm9kZS5FVkVOVF9HUk9VUF9DSEFOR0VELCBleHBhbmRhYmxlQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5kaXNwbGF5ZWRHcm91cE5vZGUsIFJvd05vZGUuRVZFTlRfSEFTX0NISUxEUkVOX0NIQU5HRUQsIGV4cGFuZGFibGVDaGFuZ2VkTGlzdGVuZXIpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5vbkV4cGFuZENsaWNrZWQgPSBmdW5jdGlvbiAobW91c2VFdmVudCkge1xuICAgICAgICBpZiAoaXNTdG9wUHJvcGFnYXRpb25Gb3JBZ0dyaWQobW91c2VFdmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBzbyBpZiB3ZSBleHBhbmQgYSBub2RlLCBpdCBkb2VzIG5vdCBhbHNvIGdldCBzZWxlY3RlZC5cbiAgICAgICAgc3RvcFByb3BhZ2F0aW9uRm9yQWdHcmlkKG1vdXNlRXZlbnQpO1xuICAgICAgICB0aGlzLm9uRXhwYW5kT3JDb250cmFjdChtb3VzZUV2ZW50KTtcbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUub25FeHBhbmRPckNvbnRyYWN0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgLy8gbXVzdCB1c2UgdGhlIGRpc3BsYXllZEdyb3VwLCBzbyBpZiBkYXRhIHdhcyBkcmFnZ2VkIGRvd24sIHdlIGV4cGFuZCB0aGUgcGFyZW50LCBub3QgdGhpcyByb3dcbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLmRpc3BsYXllZEdyb3VwTm9kZTtcbiAgICAgICAgdmFyIG5leHRFeHBhbmRTdGF0ZSA9ICFyb3dOb2RlLmV4cGFuZGVkO1xuICAgICAgICBpZiAoIW5leHRFeHBhbmRTdGF0ZSAmJiByb3dOb2RlLnN0aWNreSkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxUb1N0aWNreU5vZGUocm93Tm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcm93Tm9kZS5zZXRFeHBhbmRlZChuZXh0RXhwYW5kU3RhdGUsIGUpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5zY3JvbGxUb1N0aWNreU5vZGUgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICB2YXIgZ3JpZEJvZHlDdHJsID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgIHZhciBzY3JvbGxGZWF0dXJlID0gZ3JpZEJvZHlDdHJsLmdldFNjcm9sbEZlYXR1cmUoKTtcbiAgICAgICAgc2Nyb2xsRmVhdHVyZS5zZXRWZXJ0aWNhbFNjcm9sbFBvc2l0aW9uKHJvd05vZGUucm93VG9wIC0gcm93Tm9kZS5zdGlja3lSb3dUb3ApO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5pc0V4cGFuZGFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnNob3dpbmdWYWx1ZUZvck9wZW5lZFBhcmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLmRpc3BsYXllZEdyb3VwTm9kZTtcbiAgICAgICAgdmFyIHJlZHVjZWRMZWFmTm9kZSA9IHRoaXMuY29sdW1uTW9kZWwuaXNQaXZvdE1vZGUoKSAmJiByb3dOb2RlLmxlYWZHcm91cDtcbiAgICAgICAgdmFyIGV4cGFuZGFibGVHcm91cCA9IHJvd05vZGUuaXNFeHBhbmRhYmxlKCkgJiYgIXJvd05vZGUuZm9vdGVyICYmICFyZWR1Y2VkTGVhZk5vZGU7XG4gICAgICAgIGlmICghZXhwYW5kYWJsZUdyb3VwKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY29sdW1uIGlzIG51bGwgZm9yIGZ1bGxXaWR0aFJvd3NcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMucGFyYW1zLmNvbHVtbjtcbiAgICAgICAgdmFyIGRpc3BsYXlpbmdGb3JPbmVDb2x1bW5Pbmx5ID0gY29sdW1uICE9IG51bGwgJiYgdHlwZW9mIGNvbHVtbi5nZXRDb2xEZWYoKS5zaG93Um93R3JvdXAgPT09ICdzdHJpbmcnO1xuICAgICAgICBpZiAoZGlzcGxheWluZ0Zvck9uZUNvbHVtbk9ubHkpIHtcbiAgICAgICAgICAgIHZhciBzaG93aW5nID0gdGhpcy5pc1Nob3dSb3dHcm91cEZvclRoaXNSb3coKTtcbiAgICAgICAgICAgIHJldHVybiBzaG93aW5nO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5zaG93RXhwYW5kQW5kQ29udHJhY3RJY29ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgcGFyYW1zID0gX2EucGFyYW1zLCBkaXNwbGF5ZWRHcm91cCA9IF9hLmRpc3BsYXllZEdyb3VwTm9kZSwgY29sdW1uTW9kZWwgPSBfYS5jb2x1bW5Nb2RlbDtcbiAgICAgICAgdmFyIG5vZGUgPSBwYXJhbXMubm9kZTtcbiAgICAgICAgdmFyIGlzRXhwYW5kYWJsZSA9IHRoaXMuaXNFeHBhbmRhYmxlKCk7XG4gICAgICAgIGlmIChpc0V4cGFuZGFibGUpIHtcbiAgICAgICAgICAgIC8vIGlmIGV4cGFuZGFibGUsIHNob3cgb25lIGJhc2VkIG9uIGV4cGFuZCBzdGF0ZS5cbiAgICAgICAgICAgIC8vIGlmIHdlIHdlcmUgZHJhZ2dlZCBkb3duLCBtZWFucyBvdXIgcGFyZW50IGlzIGFsd2F5cyBleHBhbmRlZFxuICAgICAgICAgICAgdmFyIGV4cGFuZGVkID0gdGhpcy5zaG93aW5nVmFsdWVGb3JPcGVuZWRQYXJlbnQgPyB0cnVlIDogbm9kZS5leHBhbmRlZDtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXRFeHBhbmRlZERpc3BsYXllZChleHBhbmRlZCk7XG4gICAgICAgICAgICB0aGlzLmNvbXAuc2V0Q29udHJhY3RlZERpc3BsYXllZCghZXhwYW5kZWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gaXQgbm90IGV4cGFuZGFibGUsIHNob3cgbmVpdGhlclxuICAgICAgICAgICAgdGhpcy5jb21wLnNldEV4cGFuZGVkRGlzcGxheWVkKGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXRDb250cmFjdGVkRGlzcGxheWVkKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb21wZW5zYXRpb24gcGFkZGluZyBmb3IgbGVhZiBub2Rlcywgc28gdGhlcmUgaXMgYmxhbmsgc3BhY2UgaW5zdGVhZCBvZiB0aGUgZXhwYW5kIGljb25cbiAgICAgICAgdmFyIHBpdm90TW9kZSA9IGNvbHVtbk1vZGVsLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIHZhciBwaXZvdE1vZGVBbmRMZWFmR3JvdXAgPSBwaXZvdE1vZGUgJiYgZGlzcGxheWVkR3JvdXAubGVhZkdyb3VwO1xuICAgICAgICB2YXIgYWRkRXhwYW5kYWJsZUNzcyA9IGlzRXhwYW5kYWJsZSAmJiAhcGl2b3RNb2RlQW5kTGVhZkdyb3VwO1xuICAgICAgICB2YXIgaXNUb3RhbEZvb3Rlck5vZGUgPSBub2RlLmZvb3RlciAmJiBub2RlLmxldmVsID09PSAtMTtcbiAgICAgICAgdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWNlbGwtZXhwYW5kYWJsZScsIGFkZEV4cGFuZGFibGVDc3MpO1xuICAgICAgICB0aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LWdyb3VwJywgYWRkRXhwYW5kYWJsZUNzcyk7XG4gICAgICAgIGlmIChwaXZvdE1vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1waXZvdC1sZWFmLWdyb3VwJywgcGl2b3RNb2RlQW5kTGVhZkdyb3VwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaXNUb3RhbEZvb3Rlck5vZGUpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctZ3JvdXAtbGVhZi1pbmRlbnQnLCAhYWRkRXhwYW5kYWJsZUNzcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUub25Sb3dOb2RlSXNFeHBhbmRhYmxlQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gbWF5YmUgaWYgbm8gY2hpbGRyZW4gbm93LCB3ZSBzaG91bGQgaGlkZSB0aGUgZXhwYW5kIC8gY29udHJhY3QgaWNvbnNcbiAgICAgICAgdGhpcy5zaG93RXhwYW5kQW5kQ29udHJhY3RJY29ucygpO1xuICAgICAgICAvLyBpZiB3ZSBoYXZlIG5vIGNoaWxkcmVuLCB0aGlzIGltcGFjdHMgdGhlIGluZGVudFxuICAgICAgICB0aGlzLnNldEluZGVudCgpO1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhRXhwYW5kZWQoKTtcbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUuc2V0dXBJbmRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIG9ubHkgZG8gdGhpcyBpZiBhbiBpbmRlbnQgLSBhcyB0aGlzIG92ZXJ3cml0ZXMgdGhlIHBhZGRpbmcgdGhhdFxuICAgICAgICAvLyB0aGUgdGhlbWUgc2V0LCB3aGljaCB3aWxsIG1ha2UgdGhpbmdzIGxvb2sgJ25vdCBhbGlnbmVkJyBmb3IgdGhlXG4gICAgICAgIC8vIGZpcnN0IGdyb3VwIGxldmVsLlxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMucGFyYW1zLm5vZGU7XG4gICAgICAgIHZhciBzdXBwcmVzc1BhZGRpbmcgPSB0aGlzLnBhcmFtcy5zdXBwcmVzc1BhZGRpbmc7XG4gICAgICAgIGlmICghc3VwcHJlc3NQYWRkaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihub2RlLCBSb3dOb2RlLkVWRU5UX1VJX0xFVkVMX0NIQU5HRUQsIHRoaXMuc2V0SW5kZW50LmJpbmQodGhpcykpO1xuICAgICAgICAgICAgdGhpcy5zZXRJbmRlbnQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5zZXRJbmRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwSGlkZU9wZW5QYXJlbnRzKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0gdGhpcy5wYXJhbXM7XG4gICAgICAgIHZhciByb3dOb2RlID0gcGFyYW1zLm5vZGU7XG4gICAgICAgIC8vIGlmIHdlIGFyZSBvbmx5IHNob3dpbmcgb25lIGdyb3VwIGNvbHVtbiwgd2UgZG9uJ3Qgd2FudCB0byBiZSBpbmRlbnRpbmcgYmFzZWQgb24gbGV2ZWxcbiAgICAgICAgdmFyIGZ1bGxXaXRoUm93ID0gISFwYXJhbXMuY29sRGVmO1xuICAgICAgICB2YXIgdHJlZURhdGEgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1RyZWVEYXRhKCk7XG4gICAgICAgIHZhciBtYW55RGltZW5zaW9uVGhpc0NvbHVtbiA9ICFmdWxsV2l0aFJvdyB8fCB0cmVlRGF0YSB8fCBwYXJhbXMuY29sRGVmLnNob3dSb3dHcm91cCA9PT0gdHJ1ZTtcbiAgICAgICAgdmFyIHBhZGRpbmdDb3VudCA9IG1hbnlEaW1lbnNpb25UaGlzQ29sdW1uID8gcm93Tm9kZS51aUxldmVsIDogMDtcbiAgICAgICAgdmFyIHVzZXJQcm92aWRlZFBhZGRpbmdQaXhlbHNUaGVEZXByZWNhdGVkV2F5ID0gcGFyYW1zLnBhZGRpbmcgPj0gMDtcbiAgICAgICAgaWYgKHVzZXJQcm92aWRlZFBhZGRpbmdQaXhlbHNUaGVEZXByZWNhdGVkV2F5KSB7XG4gICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBjZWxsUmVuZGVyZXJQYXJhbXMucGFkZGluZyBubyBsb25nZXIgd29ya3MsIGl0IHdhcyBkZXByZWNhdGVkIGluIHNpbmNlIHYxNC4yIGFuZCByZW1vdmVkIGluIHYyNiwgY29uZmlndXJpbmcgcGFkZGluZyBmb3IgZ3JvdXBDZWxsUmVuZGVyZXIgc2hvdWxkIGJlIGRvbmUgd2l0aCBTYXNzIHZhcmlhYmxlcyBhbmQgdGhlbWVzLiBQbGVhc2Ugc2VlIHRoZSBBRyBHcmlkIGRvY3VtZW50YXRpb24gcGFnZSBmb3IgVGhlbWVzLCBpbiBwYXJ0aWN1bGFyIHRoZSBwcm9wZXJ0eSAkcm93LWdyb3VwLWluZGVudC1zaXplLicpOyB9LCAnZ3JvdXBDZWxsUmVuZGVyZXItPmRvRGVwcmVjYXRlZFdheScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmluZGVudENsYXNzKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyh0aGlzLmluZGVudENsYXNzLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbmRlbnRDbGFzcyA9ICdhZy1yb3ctZ3JvdXAtaW5kZW50LScgKyBwYWRkaW5nQ291bnQ7XG4gICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKHRoaXMuaW5kZW50Q2xhc3MsIHRydWUpO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZS5hZGRGdWxsV2lkdGhSb3dEcmFnZ2VySWZOZWVkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5wYXJhbXMuZnVsbFdpZHRoIHx8ICF0aGlzLnBhcmFtcy5yb3dEcmFnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd0RyYWdDb21wID0gbmV3IFJvd0RyYWdDb21wKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnBhcmFtcy52YWx1ZTsgfSwgdGhpcy5wYXJhbXMubm9kZSk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4ocm93RHJhZ0NvbXAsIHRoaXMuY29udGV4dCk7XG4gICAgICAgIHRoaXMuZUd1aS5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyYmVnaW4nLCByb3dEcmFnQ29tcC5nZXRHdWkoKSk7XG4gICAgfTtcbiAgICBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLmlzVXNlcldhbnRzU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwYXJhbXNDaGVja2JveCA9IHRoaXMucGFyYW1zLmNoZWNrYm94O1xuICAgICAgICAvLyBpZiBhIGZ1bmN0aW9uLCB3ZSBhbHdheXMgcmV0dXJuIHRydWUgYXMgY2hhbmdlIGRldGVjdGlvbiBjYW4gc2hvdyBvciBoaWRlIHRoZSBjaGVja2JveC5cbiAgICAgICAgcmV0dXJuIHR5cGVvZiBwYXJhbXNDaGVja2JveCA9PT0gJ2Z1bmN0aW9uJyB8fCBwYXJhbXNDaGVja2JveCA9PT0gdHJ1ZTtcbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUuYWRkQ2hlY2tib3hJZk5lZWRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLmRpc3BsYXllZEdyb3VwTm9kZTtcbiAgICAgICAgdmFyIGNoZWNrYm94TmVlZGVkID0gdGhpcy5pc1VzZXJXYW50c1NlbGVjdGVkKCkgJiZcbiAgICAgICAgICAgIC8vIGZvb3RlcnMgY2Fubm90IGJlIHNlbGVjdGVkXG4gICAgICAgICAgICAhcm93Tm9kZS5mb290ZXIgJiZcbiAgICAgICAgICAgIC8vIHBpbm5lZCByb3dzIGNhbm5vdCBiZSBzZWxlY3RlZFxuICAgICAgICAgICAgIXJvd05vZGUucm93UGlubmVkICYmXG4gICAgICAgICAgICAvLyBkZXRhaWxzIGNhbm5vdCBiZSBzZWxlY3RlZFxuICAgICAgICAgICAgIXJvd05vZGUuZGV0YWlsO1xuICAgICAgICBpZiAoY2hlY2tib3hOZWVkZWQpIHtcbiAgICAgICAgICAgIHZhciBjYlNlbGVjdGlvbkNvbXBvbmVudF8xID0gbmV3IENoZWNrYm94U2VsZWN0aW9uQ29tcG9uZW50KCk7XG4gICAgICAgICAgICB0aGlzLmdldENvbnRleHQoKS5jcmVhdGVCZWFuKGNiU2VsZWN0aW9uQ29tcG9uZW50XzEpO1xuICAgICAgICAgICAgY2JTZWxlY3Rpb25Db21wb25lbnRfMS5pbml0KHtcbiAgICAgICAgICAgICAgICByb3dOb2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgICAgIGNvbHVtbjogdGhpcy5wYXJhbXMuY29sdW1uLFxuICAgICAgICAgICAgICAgIG92ZXJyaWRlczoge1xuICAgICAgICAgICAgICAgICAgICBpc1Zpc2libGU6IHRoaXMucGFyYW1zLmNoZWNrYm94LFxuICAgICAgICAgICAgICAgICAgICBjYWxsYmFja1BhcmFtczogdGhpcy5wYXJhbXMsXG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZUhpZGRlbjogdHJ1ZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmVDaGVja2JveC5hcHBlbmRDaGlsZChjYlNlbGVjdGlvbkNvbXBvbmVudF8xLmdldEd1aSgpKTtcbiAgICAgICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZ2V0Q29udGV4dCgpLmRlc3Ryb3lCZWFuKGNiU2VsZWN0aW9uQ29tcG9uZW50XzEpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbXAuc2V0Q2hlY2tib3hWaXNpYmxlKGNoZWNrYm94TmVlZGVkKTtcbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUub25LZXlEb3duID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBlbnRlcktleVByZXNzZWQgPSBldmVudC5rZXkgPT09IEtleUNvZGUuRU5URVI7XG4gICAgICAgIGlmICghZW50ZXJLZXlQcmVzc2VkIHx8IHRoaXMucGFyYW1zLnN1cHByZXNzRW50ZXJFeHBhbmQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbEVkaXRhYmxlID0gdGhpcy5wYXJhbXMuY29sdW1uICYmIHRoaXMucGFyYW1zLmNvbHVtbi5pc0NlbGxFZGl0YWJsZSh0aGlzLnBhcmFtcy5ub2RlKTtcbiAgICAgICAgaWYgKGNlbGxFZGl0YWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub25FeHBhbmRPckNvbnRyYWN0KGV2ZW50KTtcbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUub25DZWxsRGJsQ2xpY2tlZCA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmIChpc1N0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChtb3VzZUV2ZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gYXZvaWQgYWN0aW5nIG9uIGRvdWJsZSBjbGljayBldmVudHMgb24gdGhlIGV4cGFuZCAvIGNvbnRyYWN0IGljb24sXG4gICAgICAgIC8vIGFzIHRoYXQgaWNvbnMgYWxyZWFkeSBoYXMgZXhwYW5kIC8gY29sbGFwc2UgZnVuY3Rpb25hbGl0eSBvbiBpdC4gb3RoZXJ3aXNlIGlmXG4gICAgICAgIC8vIHRoZSBpY29uIHdhcyBkb3VibGUgY2xpY2tlZCwgd2Ugd291bGQgZ2V0ICdjbGljaycsICdjbGljaycsICdkYmxjbGljaycgd2hpY2hcbiAgICAgICAgLy8gaXMgb3Blbi0+Y2xvc2UtPm9wZW4sIGhvd2V2ZXIgZG91YmxlIGNsaWNrIHNob3VsZCBiZSBvcGVuLT5jbG9zZSBvbmx5LlxuICAgICAgICB2YXIgdGFyZ2V0SXNFeHBhbmRJY29uID0gaXNFbGVtZW50SW5FdmVudFBhdGgodGhpcy5lRXhwYW5kZWQsIG1vdXNlRXZlbnQpXG4gICAgICAgICAgICB8fCBpc0VsZW1lbnRJbkV2ZW50UGF0aCh0aGlzLmVDb250cmFjdGVkLCBtb3VzZUV2ZW50KTtcbiAgICAgICAgaWYgKCF0YXJnZXRJc0V4cGFuZEljb24pIHtcbiAgICAgICAgICAgIHRoaXMub25FeHBhbmRPckNvbnRyYWN0KG1vdXNlRXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFfKFtcbiAgICAgICAgQXV0b3dpcmVkKCdleHByZXNzaW9uU2VydmljZScpXG4gICAgXSwgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZSwgXCJleHByZXNzaW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMV8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlRm9ybWF0dGVyU2VydmljZScpXG4gICAgXSwgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZSwgXCJ2YWx1ZUZvcm1hdHRlclNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFfKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMV8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3VzZXJDb21wb25lbnRGYWN0b3J5JylcbiAgICBdLCBHcm91cENlbGxSZW5kZXJlckN0cmwucHJvdG90eXBlLCBcInVzZXJDb21wb25lbnRGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxXyhbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZE9wdGlvbnMnKVxuICAgIF0sIEdyb3VwQ2VsbFJlbmRlcmVyQ3RybC5wcm90b3R5cGUsIFwiZ3JpZE9wdGlvbnNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFfKFtcbiAgICAgICAgQXV0b3dpcmVkKFwiY3RybHNTZXJ2aWNlXCIpXG4gICAgXSwgR3JvdXBDZWxsUmVuZGVyZXJDdHJsLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gR3JvdXBDZWxsUmVuZGVyZXJDdHJsO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJlID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxWiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEdyb3VwQ2VsbFJlbmRlcmVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyZShHcm91cENlbGxSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBHcm91cENlbGxSZW5kZXJlcigpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIEdyb3VwQ2VsbFJlbmRlcmVyLlRFTVBMQVRFKSB8fCB0aGlzO1xuICAgIH1cbiAgICBHcm91cENlbGxSZW5kZXJlci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNvbXBQcm94eSA9IHtcbiAgICAgICAgICAgIHNldElubmVyUmVuZGVyZXI6IGZ1bmN0aW9uIChjb21wRGV0YWlscywgdmFsdWVUb0Rpc3BsYXkpIHsgcmV0dXJuIF90aGlzLnNldFJlbmRlckRldGFpbHMoY29tcERldGFpbHMsIHZhbHVlVG9EaXNwbGF5KTsgfSxcbiAgICAgICAgICAgIHNldENoaWxkQ291bnQ6IGZ1bmN0aW9uIChjb3VudCkgeyByZXR1cm4gX3RoaXMuZUNoaWxkQ291bnQuaW5uZXJIVE1MID0gY291bnQ7IH0sXG4gICAgICAgICAgICBhZGRPclJlbW92ZUNzc0NsYXNzOiBmdW5jdGlvbiAoY3NzQ2xhc3MsIHZhbHVlKSB7IHJldHVybiBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKGNzc0NsYXNzLCB2YWx1ZSk7IH0sXG4gICAgICAgICAgICBzZXRDb250cmFjdGVkRGlzcGxheWVkOiBmdW5jdGlvbiAoZXhwYW5kZWQpIHsgcmV0dXJuIHNldERpc3BsYXllZChfdGhpcy5lQ29udHJhY3RlZCwgZXhwYW5kZWQpOyB9LFxuICAgICAgICAgICAgc2V0RXhwYW5kZWREaXNwbGF5ZWQ6IGZ1bmN0aW9uIChleHBhbmRlZCkgeyByZXR1cm4gc2V0RGlzcGxheWVkKF90aGlzLmVFeHBhbmRlZCwgZXhwYW5kZWQpOyB9LFxuICAgICAgICAgICAgc2V0Q2hlY2tib3hWaXNpYmxlOiBmdW5jdGlvbiAodmlzaWJsZSkgeyByZXR1cm4gX3RoaXMuZUNoZWNrYm94LmNsYXNzTGlzdC50b2dnbGUoJ2FnLWludmlzaWJsZScsICF2aXNpYmxlKTsgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY3RybCA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEdyb3VwQ2VsbFJlbmRlcmVyQ3RybCgpKTtcbiAgICAgICAgdmFyIGZ1bGxXaWR0aCA9ICFwYXJhbXMuY29sRGVmO1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIGN0cmwuaW5pdChjb21wUHJveHksIGVHdWksIHRoaXMuZUNoZWNrYm94LCB0aGlzLmVFeHBhbmRlZCwgdGhpcy5lQ29udHJhY3RlZCwgdGhpcy5jb25zdHJ1Y3RvciwgcGFyYW1zKTtcbiAgICAgICAgaWYgKGZ1bGxXaWR0aCkge1xuICAgICAgICAgICAgc2V0QXJpYVJvbGUoZUd1aSwgJ2dyaWRjZWxsJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyb3VwQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5zZXRSZW5kZXJEZXRhaWxzID0gZnVuY3Rpb24gKGNvbXBEZXRhaWxzLCB2YWx1ZVRvRGlzcGxheSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoY29tcERldGFpbHMpIHtcbiAgICAgICAgICAgIHZhciBjb21wb25lbnRQcm9taXNlID0gY29tcERldGFpbHMubmV3QWdTdGFja0luc3RhbmNlKCk7XG4gICAgICAgICAgICBpZiAoIWNvbXBvbmVudFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb21wb25lbnRQcm9taXNlLnRoZW4oZnVuY3Rpb24gKGNvbXApIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbXApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZGVzdHJveUNvbXAgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb250ZXh0LmRlc3Ryb3lCZWFuKGNvbXApOyB9O1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZVZhbHVlLmFwcGVuZENoaWxkKGNvbXAuZ2V0R3VpKCkpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5hZGREZXN0cm95RnVuYyhkZXN0cm95Q29tcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95Q29tcCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lVmFsdWUuaW5uZXJUZXh0ID0gdmFsdWVUb0Rpc3BsYXk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHRoaXMgaXMgYSB1c2VyIGNvbXBvbmVudCwgYW5kIElDb21wb25lbnQgaGFzIFwicHVibGljIGRlc3Ryb3koKVwiIGFzIHBhcnQgb2YgdGhlIGludGVyZmFjZS5cbiAgICAvLyBzbyB3ZSBuZWVkIHRvIGhhdmUgcHVibGljIGhlcmUgaW5zdGVhZCBvZiBwcml2YXRlIG9yIHByb3RlY3RlZFxuICAgIEdyb3VwQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmdldENvbnRleHQoKS5kZXN0cm95QmVhbih0aGlzLmlubmVyQ2VsbFJlbmRlcmVyKTtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBHcm91cENlbGxSZW5kZXJlci5wcm90b3R5cGUucmVmcmVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgR3JvdXBDZWxsUmVuZGVyZXIuVEVNUExBVEUgPSBcIjxzcGFuIGNsYXNzPVxcXCJhZy1jZWxsLXdyYXBwZXJcXFwiPlxcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJhZy1ncm91cC1leHBhbmRlZFxcXCIgcmVmPVxcXCJlRXhwYW5kZWRcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwiYWctZ3JvdXAtY29udHJhY3RlZFxcXCIgcmVmPVxcXCJlQ29udHJhY3RlZFxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJhZy1ncm91cC1jaGVja2JveCBhZy1pbnZpc2libGVcXFwiIHJlZj1cXFwiZUNoZWNrYm94XFxcIj48L3NwYW4+XFxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImFnLWdyb3VwLXZhbHVlXFxcIiByZWY9XFxcImVWYWx1ZVxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJhZy1ncm91cC1jaGlsZC1jb3VudFxcXCIgcmVmPVxcXCJlQ2hpbGRDb3VudFxcXCI+PC9zcGFuPlxcbiAgICAgICAgPC9zcGFuPlwiO1xuICAgIF9fZGVjb3JhdGUkMVooW1xuICAgICAgICBSZWZTZWxlY3RvcignZUV4cGFuZGVkJylcbiAgICBdLCBHcm91cENlbGxSZW5kZXJlci5wcm90b3R5cGUsIFwiZUV4cGFuZGVkXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxWihbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ29udHJhY3RlZCcpXG4gICAgXSwgR3JvdXBDZWxsUmVuZGVyZXIucHJvdG90eXBlLCBcImVDb250cmFjdGVkXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxWihbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ2hlY2tib3gnKVxuICAgIF0sIEdyb3VwQ2VsbFJlbmRlcmVyLnByb3RvdHlwZSwgXCJlQ2hlY2tib3hcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFaKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VWYWx1ZScpXG4gICAgXSwgR3JvdXBDZWxsUmVuZGVyZXIucHJvdG90eXBlLCBcImVWYWx1ZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVooW1xuICAgICAgICBSZWZTZWxlY3RvcignZUNoaWxkQ291bnQnKVxuICAgIF0sIEdyb3VwQ2VsbFJlbmRlcmVyLnByb3RvdHlwZSwgXCJlQ2hpbGRDb3VudFwiLCB2b2lkIDApO1xuICAgIHJldHVybiBHcm91cENlbGxSZW5kZXJlcjtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMmQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFZID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgTG9hZGluZ0NlbGxSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmQoTG9hZGluZ0NlbGxSZW5kZXJlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBMb2FkaW5nQ2VsbFJlbmRlcmVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgTG9hZGluZ0NlbGxSZW5kZXJlci5URU1QTEFURSkgfHwgdGhpcztcbiAgICB9XG4gICAgTG9hZGluZ0NlbGxSZW5kZXJlci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgcGFyYW1zLm5vZGUuZmFpbGVkTG9hZCA/IHRoaXMuc2V0dXBGYWlsZWQoKSA6IHRoaXMuc2V0dXBMb2FkaW5nKCk7XG4gICAgfTtcbiAgICBMb2FkaW5nQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5zZXR1cEZhaWxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5lTG9hZGluZ1RleHQuaW5uZXJUZXh0ID0gJ0VSUic7XG4gICAgfTtcbiAgICBMb2FkaW5nQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5zZXR1cExvYWRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlTG9hZGluZ0ljb24gPSBjcmVhdGVJY29uTm9TcGFuKCdncm91cExvYWRpbmcnLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCk7XG4gICAgICAgIGlmIChlTG9hZGluZ0ljb24pIHtcbiAgICAgICAgICAgIHRoaXMuZUxvYWRpbmdJY29uLmFwcGVuZENoaWxkKGVMb2FkaW5nSWNvbik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxvY2FsZVRleHRGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdGhpcy5lTG9hZGluZ1RleHQuaW5uZXJUZXh0ID0gbG9jYWxlVGV4dEZ1bmMoJ2xvYWRpbmdPb28nLCAnTG9hZGluZycpO1xuICAgIH07XG4gICAgTG9hZGluZ0NlbGxSZW5kZXJlci5wcm90b3R5cGUucmVmcmVzaCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgLy8gdGhpcyBpcyBhIHVzZXIgY29tcG9uZW50LCBhbmQgSUNvbXBvbmVudCBoYXMgXCJwdWJsaWMgZGVzdHJveSgpXCIgYXMgcGFydCBvZiB0aGUgaW50ZXJmYWNlLlxuICAgIC8vIHNvIHdlIG5lZWQgdG8gb3ZlcnJpZGUgZGVzdHJveSgpIGp1c3QgdG8gbWFrZSB0aGUgbWV0aG9kIHB1YmxpYy5cbiAgICBMb2FkaW5nQ2VsbFJlbmRlcmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIExvYWRpbmdDZWxsUmVuZGVyZXIuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWxvYWRpbmdcXFwiPlxcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJhZy1sb2FkaW5nLWljb25cXFwiIHJlZj1cXFwiZUxvYWRpbmdJY29uXFxcIj48L3NwYW4+XFxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImFnLWxvYWRpbmctdGV4dFxcXCIgcmVmPVxcXCJlTG9hZGluZ1RleHRcXFwiPjwvc3Bhbj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkMVkoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUxvYWRpbmdJY29uJylcbiAgICBdLCBMb2FkaW5nQ2VsbFJlbmRlcmVyLnByb3RvdHlwZSwgXCJlTG9hZGluZ0ljb25cIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFZKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VMb2FkaW5nVGV4dCcpXG4gICAgXSwgTG9hZGluZ0NlbGxSZW5kZXJlci5wcm90b3R5cGUsIFwiZUxvYWRpbmdUZXh0XCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIExvYWRpbmdDZWxsUmVuZGVyZXI7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDJjID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgTG9hZGluZ092ZXJsYXlDb21wb25lbnQkMSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmMoTG9hZGluZ092ZXJsYXlDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gTG9hZGluZ092ZXJsYXlDb21wb25lbnQoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIH1cbiAgICAvLyB0aGlzIGlzIGEgdXNlciBjb21wb25lbnQsIGFuZCBJQ29tcG9uZW50IGhhcyBcInB1YmxpYyBkZXN0cm95KClcIiBhcyBwYXJ0IG9mIHRoZSBpbnRlcmZhY2UuXG4gICAgLy8gc28gd2UgbmVlZCB0byBvdmVycmlkZSBkZXN0cm95KCkganVzdCB0byBtYWtlIHRoZSBtZXRob2QgcHVibGljLlxuICAgIExvYWRpbmdPdmVybGF5Q29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIExvYWRpbmdPdmVybGF5Q29tcG9uZW50LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgdGVtcGxhdGUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRPdmVybGF5TG9hZGluZ1RlbXBsYXRlKCkgP1xuICAgICAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0T3ZlcmxheUxvYWRpbmdUZW1wbGF0ZSgpIDogTG9hZGluZ092ZXJsYXlDb21wb25lbnQuREVGQVVMVF9MT0FESU5HX09WRVJMQVlfVEVNUExBVEU7XG4gICAgICAgIHZhciBsb2NhbGVUZXh0RnVuYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBsb2NhbGlzZWRUZW1wbGF0ZSA9IHRlbXBsYXRlLnJlcGxhY2UoJ1tMT0FESU5HLi4uXScsIGxvY2FsZVRleHRGdW5jKCdsb2FkaW5nT29vJywgJ0xvYWRpbmcuLi4nKSk7XG4gICAgICAgIHRoaXMuc2V0VGVtcGxhdGUobG9jYWxpc2VkVGVtcGxhdGUpO1xuICAgIH07XG4gICAgTG9hZGluZ092ZXJsYXlDb21wb25lbnQuREVGQVVMVF9MT0FESU5HX09WRVJMQVlfVEVNUExBVEUgPSAnPHNwYW4gY2xhc3M9XCJhZy1vdmVybGF5LWxvYWRpbmctY2VudGVyXCI+W0xPQURJTkcuLi5dPC9zcGFuPic7XG4gICAgcmV0dXJuIExvYWRpbmdPdmVybGF5Q29tcG9uZW50O1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyYiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIE5vUm93c092ZXJsYXlDb21wb25lbnQkMSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMmIoTm9Sb3dzT3ZlcmxheUNvbXBvbmVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBOb1Jvd3NPdmVybGF5Q29tcG9uZW50KCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gdGhpcyBpcyBhIHVzZXIgY29tcG9uZW50LCBhbmQgSUNvbXBvbmVudCBoYXMgXCJwdWJsaWMgZGVzdHJveSgpXCIgYXMgcGFydCBvZiB0aGUgaW50ZXJmYWNlLlxuICAgIC8vIHNvIHdlIG5lZWQgdG8gb3ZlcnJpZGUgZGVzdHJveSgpIGp1c3QgdG8gbWFrZSB0aGUgbWV0aG9kIHB1YmxpYy5cbiAgICBOb1Jvd3NPdmVybGF5Q29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIE5vUm93c092ZXJsYXlDb21wb25lbnQucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciB0ZW1wbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldE92ZXJsYXlOb1Jvd3NUZW1wbGF0ZSgpID9cbiAgICAgICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldE92ZXJsYXlOb1Jvd3NUZW1wbGF0ZSgpIDogTm9Sb3dzT3ZlcmxheUNvbXBvbmVudC5ERUZBVUxUX05PX1JPV1NfVEVNUExBVEU7XG4gICAgICAgIHZhciBsb2NhbGVUZXh0RnVuYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBsb2NhbGlzZWRUZW1wbGF0ZSA9IHRlbXBsYXRlLnJlcGxhY2UoJ1tOT19ST1dTX1RPX1NIT1ddJywgbG9jYWxlVGV4dEZ1bmMoJ25vUm93c1RvU2hvdycsICdObyBSb3dzIFRvIFNob3cnKSk7XG4gICAgICAgIHRoaXMuc2V0VGVtcGxhdGUobG9jYWxpc2VkVGVtcGxhdGUpO1xuICAgIH07XG4gICAgTm9Sb3dzT3ZlcmxheUNvbXBvbmVudC5ERUZBVUxUX05PX1JPV1NfVEVNUExBVEUgPSAnPHNwYW4gY2xhc3M9XCJhZy1vdmVybGF5LW5vLXJvd3MtY2VudGVyXCI+W05PX1JPV1NfVE9fU0hPV108L3NwYW4+JztcbiAgICByZXR1cm4gTm9Sb3dzT3ZlcmxheUNvbXBvbmVudDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMmEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBUb29sdGlwQ29tcG9uZW50JDEgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDJhKFRvb2x0aXBDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVG9vbHRpcENvbXBvbmVudCgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIC8qIGh0bWwgKi8gXCI8ZGl2IGNsYXNzPVxcXCJhZy10b29sdGlwXFxcIj48L2Rpdj5cIikgfHwgdGhpcztcbiAgICB9XG4gICAgLy8gd2lsbCBuZWVkIHRvIHR5cGUgcGFyYW1zXG4gICAgVG9vbHRpcENvbXBvbmVudC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gcGFyYW1zLnZhbHVlO1xuICAgICAgICB0aGlzLmdldEd1aSgpLmlubmVySFRNTCA9IGVzY2FwZVN0cmluZyh2YWx1ZSk7XG4gICAgfTtcbiAgICByZXR1cm4gVG9vbHRpcENvbXBvbmVudDtcbn0oUG9wdXBDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyOSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMVggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBVc2VyQ29tcG9uZW50UmVnaXN0cnkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDI5KFVzZXJDb21wb25lbnRSZWdpc3RyeSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBVc2VyQ29tcG9uZW50UmVnaXN0cnkoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5hZ0dyaWREZWZhdWx0cyA9IHtcbiAgICAgICAgICAgIC8vZGF0ZVxuICAgICAgICAgICAgYWdEYXRlSW5wdXQ6IERlZmF1bHREYXRlQ29tcG9uZW50LFxuICAgICAgICAgICAgLy9oZWFkZXJcbiAgICAgICAgICAgIGFnQ29sdW1uSGVhZGVyOiBIZWFkZXJDb21wLFxuICAgICAgICAgICAgYWdDb2x1bW5Hcm91cEhlYWRlcjogSGVhZGVyR3JvdXBDb21wLFxuICAgICAgICAgICAgYWdTb3J0SW5kaWNhdG9yOiBTb3J0SW5kaWNhdG9yQ29tcCxcbiAgICAgICAgICAgIC8vZmxvYXRpbmcgZmlsdGVyc1xuICAgICAgICAgICAgYWdUZXh0Q29sdW1uRmxvYXRpbmdGaWx0ZXI6IFRleHRGbG9hdGluZ0ZpbHRlcixcbiAgICAgICAgICAgIGFnTnVtYmVyQ29sdW1uRmxvYXRpbmdGaWx0ZXI6IE51bWJlckZsb2F0aW5nRmlsdGVyLFxuICAgICAgICAgICAgYWdEYXRlQ29sdW1uRmxvYXRpbmdGaWx0ZXI6IERhdGVGbG9hdGluZ0ZpbHRlcixcbiAgICAgICAgICAgIGFnUmVhZE9ubHlGbG9hdGluZ0ZpbHRlcjogUmVhZE9ubHlGbG9hdGluZ0ZpbHRlcixcbiAgICAgICAgICAgIC8vIHJlbmRlcmVyc1xuICAgICAgICAgICAgYWdBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlcjogQW5pbWF0ZVNob3dDaGFuZ2VDZWxsUmVuZGVyZXIsXG4gICAgICAgICAgICBhZ0FuaW1hdGVTbGlkZUNlbGxSZW5kZXJlcjogQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyLFxuICAgICAgICAgICAgYWdHcm91cENlbGxSZW5kZXJlcjogR3JvdXBDZWxsUmVuZGVyZXIsXG4gICAgICAgICAgICBhZ0dyb3VwUm93UmVuZGVyZXI6IEdyb3VwQ2VsbFJlbmRlcmVyLFxuICAgICAgICAgICAgYWdMb2FkaW5nQ2VsbFJlbmRlcmVyOiBMb2FkaW5nQ2VsbFJlbmRlcmVyLFxuICAgICAgICAgICAgLy9lZGl0b3JzXG4gICAgICAgICAgICBhZ0NlbGxFZGl0b3I6IFRleHRDZWxsRWRpdG9yLFxuICAgICAgICAgICAgYWdUZXh0Q2VsbEVkaXRvcjogVGV4dENlbGxFZGl0b3IsXG4gICAgICAgICAgICBhZ1NlbGVjdENlbGxFZGl0b3I6IFNlbGVjdENlbGxFZGl0b3IsXG4gICAgICAgICAgICBhZ1BvcHVwVGV4dENlbGxFZGl0b3I6IFBvcHVwVGV4dENlbGxFZGl0b3IsXG4gICAgICAgICAgICBhZ1BvcHVwU2VsZWN0Q2VsbEVkaXRvcjogUG9wdXBTZWxlY3RDZWxsRWRpdG9yLFxuICAgICAgICAgICAgYWdMYXJnZVRleHRDZWxsRWRpdG9yOiBMYXJnZVRleHRDZWxsRWRpdG9yLFxuICAgICAgICAgICAgLy9maWx0ZXJcbiAgICAgICAgICAgIGFnVGV4dENvbHVtbkZpbHRlcjogVGV4dEZpbHRlcixcbiAgICAgICAgICAgIGFnTnVtYmVyQ29sdW1uRmlsdGVyOiBOdW1iZXJGaWx0ZXIsXG4gICAgICAgICAgICBhZ0RhdGVDb2x1bW5GaWx0ZXI6IERhdGVGaWx0ZXIsXG4gICAgICAgICAgICAvL292ZXJsYXlzXG4gICAgICAgICAgICBhZ0xvYWRpbmdPdmVybGF5OiBMb2FkaW5nT3ZlcmxheUNvbXBvbmVudCQxLFxuICAgICAgICAgICAgYWdOb1Jvd3NPdmVybGF5OiBOb1Jvd3NPdmVybGF5Q29tcG9uZW50JDEsXG4gICAgICAgICAgICAvLyB0b29sdGlwc1xuICAgICAgICAgICAgYWdUb29sdGlwQ29tcG9uZW50OiBUb29sdGlwQ29tcG9uZW50JDFcbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuYWdEZXByZWNhdGVkTmFtZXMgPSB7XG4gICAgICAgICAgICBzZXQ6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdTZXRDb2x1bW5GaWx0ZXInLFxuICAgICAgICAgICAgICAgIHByb3BlcnR5SG9sZGVyOiAnZmlsdGVyJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRleHQ6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdUZXh0Q29sdW1uRmlsdGVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2ZpbHRlcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBudW1iZXI6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdOdW1iZXJDb2x1bW5GaWx0ZXInLFxuICAgICAgICAgICAgICAgIHByb3BlcnR5SG9sZGVyOiAnZmlsdGVyJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRhdGU6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdEYXRlQ29sdW1uRmlsdGVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2ZpbHRlcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBncm91cDoge1xuICAgICAgICAgICAgICAgIG5ld0NvbXBvbmVudE5hbWU6ICdhZ0dyb3VwQ2VsbFJlbmRlcmVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2NlbGxSZW5kZXJlcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbmltYXRlU2hvd0NoYW5nZToge1xuICAgICAgICAgICAgICAgIG5ld0NvbXBvbmVudE5hbWU6ICdhZ0FuaW1hdGVTaG93Q2hhbmdlQ2VsbFJlbmRlcmVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2NlbGxSZW5kZXJlcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbmltYXRlU2xpZGU6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdBbmltYXRlU2xpZGVDZWxsUmVuZGVyZXInLFxuICAgICAgICAgICAgICAgIHByb3BlcnR5SG9sZGVyOiAnY2VsbFJlbmRlcmVyJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlbGVjdDoge1xuICAgICAgICAgICAgICAgIG5ld0NvbXBvbmVudE5hbWU6ICdhZ1NlbGVjdENlbGxFZGl0b3InLFxuICAgICAgICAgICAgICAgIHByb3BlcnR5SG9sZGVyOiAnY2VsbEVkaXRvcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXJnZVRleHQ6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdMYXJnZVRleHRDZWxsRWRpdG9yJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2NlbGxFZGl0b3InXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcG9wdXBTZWxlY3Q6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdQb3B1cFNlbGVjdENlbGxFZGl0b3InLFxuICAgICAgICAgICAgICAgIHByb3BlcnR5SG9sZGVyOiAnY2VsbEVkaXRvcidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwb3B1cFRleHQ6IHtcbiAgICAgICAgICAgICAgICBuZXdDb21wb25lbnROYW1lOiAnYWdQb3B1cFRleHRDZWxsRWRpdG9yJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2NlbGxFZGl0b3InXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmljaFNlbGVjdDoge1xuICAgICAgICAgICAgICAgIG5ld0NvbXBvbmVudE5hbWU6ICdhZ1JpY2hTZWxlY3RDZWxsRWRpdG9yJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2NlbGxFZGl0b3InXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGVhZGVyQ29tcG9uZW50OiB7XG4gICAgICAgICAgICAgICAgbmV3Q29tcG9uZW50TmFtZTogJ2FnQ29sdW1uSGVhZGVyJyxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUhvbGRlcjogJ2hlYWRlckNvbXBvbmVudCdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuanNDb21wcyA9IHt9O1xuICAgICAgICBfdGhpcy5md0NvbXBzID0ge307XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVXNlckNvbXBvbmVudFJlZ2lzdHJ5LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5jb21wb25lbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgIGl0ZXJhdGVPYmplY3QodGhpcy5ncmlkT3B0aW9ucy5jb21wb25lbnRzLCBmdW5jdGlvbiAoa2V5LCBjb21wb25lbnQpIHsgcmV0dXJuIF90aGlzLnJlZ2lzdGVySnNDb21wb25lbnQoa2V5LCBjb21wb25lbnQpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucy5mcmFtZXdvcmtDb21wb25lbnRzICE9IG51bGwpIHtcbiAgICAgICAgICAgIGl0ZXJhdGVPYmplY3QodGhpcy5ncmlkT3B0aW9ucy5mcmFtZXdvcmtDb21wb25lbnRzLCBmdW5jdGlvbiAoa2V5LCBjb21wb25lbnQpIHsgcmV0dXJuIF90aGlzLnJlZ2lzdGVyRndDb21wb25lbnQoa2V5LCBjb21wb25lbnQpOyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVXNlckNvbXBvbmVudFJlZ2lzdHJ5LnByb3RvdHlwZS5yZWdpc3RlckRlZmF1bHRDb21wb25lbnQgPSBmdW5jdGlvbiAocmF3TmFtZSwgY29tcG9uZW50KSB7XG4gICAgICAgIHZhciBuYW1lID0gdGhpcy50cmFuc2xhdGVJZkRlcHJlY2F0ZWQocmF3TmFtZSk7XG4gICAgICAgIGlmICh0aGlzLmFnR3JpZERlZmF1bHRzW25hbWVdKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiVHJ5aW5nIHRvIG92ZXJ3cml0ZSBhIGRlZmF1bHQgY29tcG9uZW50LiBZb3Ugc2hvdWxkIGNhbGwgcmVnaXN0ZXJDb21wb25lbnRcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZ0dyaWREZWZhdWx0c1tuYW1lXSA9IGNvbXBvbmVudDtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRSZWdpc3RyeS5wcm90b3R5cGUucmVnaXN0ZXJKc0NvbXBvbmVudCA9IGZ1bmN0aW9uIChyYXdOYW1lLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIG5hbWUgPSB0aGlzLnRyYW5zbGF0ZUlmRGVwcmVjYXRlZChyYXdOYW1lKTtcbiAgICAgICAgaWYgKHRoaXMuZndDb21wc1tuYW1lXSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlRyeWluZyB0byByZWdpc3RlciBhIGNvbXBvbmVudCB0aGF0IHlvdSBoYXZlIGFscmVhZHkgcmVnaXN0ZXJlZCBmb3IgZnJhbWV3b3JrczogXCIgKyBuYW1lKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmpzQ29tcHNbbmFtZV0gPSBjb21wb25lbnQ7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBCIHRoZSBidXNpbmVzcyBpbnRlcmZhY2UgKGllIElIZWFkZXIpXG4gICAgICogQSB0aGUgYWdHcmlkQ29tcG9uZW50IGludGVyZmFjZSAoaWUgSUhlYWRlckNvbXApLiBUaGUgZmluYWwgb2JqZWN0IGFjY2VwdGFibGUgYnkgYWctZ3JpZFxuICAgICAqL1xuICAgIFVzZXJDb21wb25lbnRSZWdpc3RyeS5wcm90b3R5cGUucmVnaXN0ZXJGd0NvbXBvbmVudCA9IGZ1bmN0aW9uIChyYXdOYW1lLCBjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIHdhcm5pbmdNZXNzYWdlID0gXCJBRyBHcmlkOiBBcyBvZiB2MjcsIHJlZ2lzdGVyaW5nIGNvbXBvbmVudHMgdmlhIGdyaWQgcHJvcGVydHkgZnJhbWV3b3JrQ29tcG9uZW50cyBpcyBkZXByZWNhdGVkLiBJbnN0ZWFkIHJlZ2lzdGVyIGJvdGggSmF2YVNjcmlwdCBBTkQgRnJhbWV3b3JrIENvbXBvbmVudHMgdmlhIHRoZSBjb21wb25lbnRzIHByb3BlcnR5LlwiO1xuICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKHdhcm5pbmdNZXNzYWdlKTsgfSwgXCJVc2VyQ29tcG9uZW50UmVnaXN0cnkuZnJhbWV3b3JrQ29tcG9uZW50c0RlcHJlY2F0ZWRcIik7XG4gICAgICAgIHZhciBuYW1lID0gdGhpcy50cmFuc2xhdGVJZkRlcHJlY2F0ZWQocmF3TmFtZSk7XG4gICAgICAgIHRoaXMuZndDb21wc1tuYW1lXSA9IGNvbXBvbmVudDtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRSZWdpc3RyeS5wcm90b3R5cGUucmV0cmlldmUgPSBmdW5jdGlvbiAocmF3TmFtZSkge1xuICAgICAgICB2YXIgbmFtZSA9IHRoaXMudHJhbnNsYXRlSWZEZXByZWNhdGVkKHJhd05hbWUpO1xuICAgICAgICB2YXIgY3JlYXRlUmVzdWx0ID0gZnVuY3Rpb24gKGNvbXBvbmVudCwgY29tcG9uZW50RnJvbUZyYW1ld29yaykgeyByZXR1cm4gKHsgY29tcG9uZW50RnJvbUZyYW1ld29yazogY29tcG9uZW50RnJvbUZyYW1ld29yaywgY29tcG9uZW50OiBjb21wb25lbnQgfSk7IH07XG4gICAgICAgIC8vIEZyYW1ld29ya092ZXJyaWRlcy5mcmFtZXdvcmtDb21wb25lbnQoKSBpcyB1c2VkIGluIHR3byBsb2NhdGlvbnM6XG4gICAgICAgIC8vIDEpIGZvciBWdWUsIHVzZXIgcHJvdmlkZWQgY29tcG9uZW50cyBnZXQgcmVnaXN0ZXJlZCB2aWEgYSBmcmFtZXdvcmsgc3BlY2lmaWMgd2F5LlxuICAgICAgICAvLyAyKSBmb3IgUmVhY3QsIGl0J3MgaG93IHRoZSBSZWFjdCBVSSBwcm92aWRlcyBhbHRlcm5hdGl2ZSBkZWZhdWx0IGNvbXBvbmVudHMgKGVnIEdyb3VwQ2VsbFJlbmRlcmVyIGFuZCBEZXRhaWxDZWxsUmVuZGVyZXIpXG4gICAgICAgIHZhciByZWdpc3RlcmVkVmlhRnJhbWV3b3JrQ29tcCA9IHRoaXMuZ2V0RnJhbWV3b3JrT3ZlcnJpZGVzKCkuZnJhbWV3b3JrQ29tcG9uZW50KG5hbWUsIHRoaXMuZ3JpZE9wdGlvbnMuY29tcG9uZW50cyk7XG4gICAgICAgIGlmIChyZWdpc3RlcmVkVmlhRnJhbWV3b3JrQ29tcCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlUmVzdWx0KHJlZ2lzdGVyZWRWaWFGcmFtZXdvcmtDb21wLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZnJhbWV3b3JrQ29tcG9uZW50ID0gdGhpcy5md0NvbXBzW25hbWVdO1xuICAgICAgICBpZiAoZnJhbWV3b3JrQ29tcG9uZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlUmVzdWx0KGZyYW1ld29ya0NvbXBvbmVudCwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGpzQ29tcG9uZW50ID0gdGhpcy5qc0NvbXBzW25hbWVdO1xuICAgICAgICBpZiAoanNDb21wb25lbnQpIHtcbiAgICAgICAgICAgIHZhciBpc0Z3a0NvbXAgPSB0aGlzLmdldEZyYW1ld29ya092ZXJyaWRlcygpLmlzRnJhbWV3b3JrQ29tcG9uZW50KGpzQ29tcG9uZW50KTtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVSZXN1bHQoanNDb21wb25lbnQsIGlzRndrQ29tcCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRlZmF1bHRDb21wb25lbnQgPSB0aGlzLmFnR3JpZERlZmF1bHRzW25hbWVdO1xuICAgICAgICBpZiAoZGVmYXVsdENvbXBvbmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVJlc3VsdChkZWZhdWx0Q29tcG9uZW50LCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHRoaXMuYWdHcmlkRGVmYXVsdHMpLmluZGV4T2YobmFtZSkgPCAwKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBMb29raW5nIGZvciBjb21wb25lbnQgW1wiICsgbmFtZSArIFwiXSBidXQgaXQgd2Fzbid0IGZvdW5kLlwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRSZWdpc3RyeS5wcm90b3R5cGUudHJhbnNsYXRlSWZEZXByZWNhdGVkID0gZnVuY3Rpb24gKHJhdykge1xuICAgICAgICB2YXIgZGVwcmVjYXRlZEluZm8gPSB0aGlzLmFnRGVwcmVjYXRlZE5hbWVzW3Jhd107XG4gICAgICAgIGlmIChkZXByZWNhdGVkSW5mbyAhPSBudWxsKSB7XG4gICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcImFnLWdyaWQuIFNpbmNlIHYxNS4wIGNvbXBvbmVudCBuYW1lcyBoYXZlIGJlZW4gcmVuYW1lZCB0byBiZSBuYW1lc3BhY2VkLiBZb3Ugc2hvdWxkIHJlbmFtZSBcIiArIGRlcHJlY2F0ZWRJbmZvLnByb3BlcnR5SG9sZGVyICsgXCI6XCIgKyByYXcgKyBcIiB0byBcIiArIGRlcHJlY2F0ZWRJbmZvLnByb3BlcnR5SG9sZGVyICsgXCI6XCIgKyBkZXByZWNhdGVkSW5mby5uZXdDb21wb25lbnROYW1lKTtcbiAgICAgICAgICAgIH0sICdERVBSRUNBVEVfQ09NUE9ORU5UXycgKyByYXcpO1xuICAgICAgICAgICAgcmV0dXJuIGRlcHJlY2F0ZWRJbmZvLm5ld0NvbXBvbmVudE5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJhdztcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMVgoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRPcHRpb25zJylcbiAgICBdLCBVc2VyQ29tcG9uZW50UmVnaXN0cnkucHJvdG90eXBlLCBcImdyaWRPcHRpb25zXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxWChbXG4gICAgICAgIEF1dG93aXJlZCgnYWdDb21wb25lbnRVdGlscycpXG4gICAgXSwgVXNlckNvbXBvbmVudFJlZ2lzdHJ5LnByb3RvdHlwZSwgXCJhZ0NvbXBvbmVudFV0aWxzXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxWChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBVc2VyQ29tcG9uZW50UmVnaXN0cnkucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgVXNlckNvbXBvbmVudFJlZ2lzdHJ5ID0gX19kZWNvcmF0ZSQxWChbXG4gICAgICAgIEJlYW4oJ3VzZXJDb21wb25lbnRSZWdpc3RyeScpXG4gICAgXSwgVXNlckNvbXBvbmVudFJlZ2lzdHJ5KTtcbiAgICByZXR1cm4gVXNlckNvbXBvbmVudFJlZ2lzdHJ5O1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgRGF0ZUNvbXBvbmVudCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdkYXRlQ29tcG9uZW50JyxcbiAgICBjZWxsUmVuZGVyZXI6IGZhbHNlXG59O1xudmFyIEhlYWRlckNvbXBvbmVudCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdoZWFkZXJDb21wb25lbnQnLFxuICAgIGNlbGxSZW5kZXJlcjogZmFsc2Vcbn07XG52YXIgSGVhZGVyR3JvdXBDb21wb25lbnQgPSB7XG4gICAgcHJvcGVydHlOYW1lOiAnaGVhZGVyR3JvdXBDb21wb25lbnQnLFxuICAgIGNlbGxSZW5kZXJlcjogZmFsc2Vcbn07XG52YXIgQ2VsbFJlbmRlcmVyQ29tcG9uZW50ID0ge1xuICAgIHByb3BlcnR5TmFtZTogJ2NlbGxSZW5kZXJlcicsXG4gICAgY2VsbFJlbmRlcmVyOiB0cnVlXG59O1xudmFyIENlbGxFZGl0b3JDb21wb25lbnQgPSB7XG4gICAgcHJvcGVydHlOYW1lOiAnY2VsbEVkaXRvcicsXG4gICAgY2VsbFJlbmRlcmVyOiBmYWxzZVxufTtcbnZhciBJbm5lclJlbmRlcmVyQ29tcG9uZW50ID0ge1xuICAgIHByb3BlcnR5TmFtZTogJ2lubmVyUmVuZGVyZXInLFxuICAgIGNlbGxSZW5kZXJlcjogdHJ1ZVxufTtcbnZhciBMb2FkaW5nT3ZlcmxheUNvbXBvbmVudCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdsb2FkaW5nT3ZlcmxheUNvbXBvbmVudCcsXG4gICAgY2VsbFJlbmRlcmVyOiBmYWxzZVxufTtcbnZhciBOb1Jvd3NPdmVybGF5Q29tcG9uZW50ID0ge1xuICAgIHByb3BlcnR5TmFtZTogJ25vUm93c092ZXJsYXlDb21wb25lbnQnLFxuICAgIGNlbGxSZW5kZXJlcjogZmFsc2Vcbn07XG52YXIgVG9vbHRpcENvbXBvbmVudCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICd0b29sdGlwQ29tcG9uZW50JyxcbiAgICBjZWxsUmVuZGVyZXI6IGZhbHNlXG59O1xudmFyIEZpbHRlckNvbXBvbmVudCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdmaWx0ZXInLFxuICAgIGNlbGxSZW5kZXJlcjogZmFsc2Vcbn07XG52YXIgRmxvYXRpbmdGaWx0ZXJDb21wb25lbnQgPSB7XG4gICAgcHJvcGVydHlOYW1lOiAnZmxvYXRpbmdGaWx0ZXJDb21wb25lbnQnLFxuICAgIGNlbGxSZW5kZXJlcjogZmFsc2Vcbn07XG52YXIgVG9vbFBhbmVsQ29tcG9uZW50ID0ge1xuICAgIHByb3BlcnR5TmFtZTogJ3Rvb2xQYW5lbCcsXG4gICAgY2VsbFJlbmRlcmVyOiBmYWxzZVxufTtcbnZhciBTdGF0dXNQYW5lbENvbXBvbmVudCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdzdGF0dXNQYW5lbCcsXG4gICAgY2VsbFJlbmRlcmVyOiBmYWxzZVxufTtcbnZhciBGdWxsV2lkdGggPSB7XG4gICAgcHJvcGVydHlOYW1lOiAnZnVsbFdpZHRoQ2VsbFJlbmRlcmVyJyxcbiAgICBjZWxsUmVuZGVyZXI6IHRydWVcbn07XG52YXIgRnVsbFdpZHRoTG9hZGluZyA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdsb2FkaW5nQ2VsbFJlbmRlcmVyJyxcbiAgICBjZWxsUmVuZGVyZXI6IHRydWVcbn07XG52YXIgRnVsbFdpZHRoR3JvdXAgPSB7XG4gICAgcHJvcGVydHlOYW1lOiAnZ3JvdXBSb3dSZW5kZXJlcicsXG4gICAgY2VsbFJlbmRlcmVyOiB0cnVlXG59O1xudmFyIEZ1bGxXaWR0aERldGFpbCA9IHtcbiAgICBwcm9wZXJ0eU5hbWU6ICdkZXRhaWxDZWxsUmVuZGVyZXInLFxuICAgIGNlbGxSZW5kZXJlcjogdHJ1ZVxufTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIEZsb2F0aW5nRmlsdGVyTWFwcGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZsb2F0aW5nRmlsdGVyTWFwcGVyKCkge1xuICAgIH1cbiAgICBGbG9hdGluZ0ZpbHRlck1hcHBlci5nZXRGbG9hdGluZ0ZpbHRlclR5cGUgPSBmdW5jdGlvbiAoZmlsdGVyVHlwZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5maWx0ZXJUb0Zsb2F0aW5nRmlsdGVyTWFwcGluZ1tmaWx0ZXJUeXBlXTtcbiAgICB9O1xuICAgIEZsb2F0aW5nRmlsdGVyTWFwcGVyLmZpbHRlclRvRmxvYXRpbmdGaWx0ZXJNYXBwaW5nID0ge1xuICAgICAgICBzZXQ6ICdhZ1NldENvbHVtbkZsb2F0aW5nRmlsdGVyJyxcbiAgICAgICAgYWdTZXRDb2x1bW5GaWx0ZXI6ICdhZ1NldENvbHVtbkZsb2F0aW5nRmlsdGVyJyxcbiAgICAgICAgbXVsdGk6ICdhZ011bHRpQ29sdW1uRmxvYXRpbmdGaWx0ZXInLFxuICAgICAgICBhZ011bHRpQ29sdW1uRmlsdGVyOiAnYWdNdWx0aUNvbHVtbkZsb2F0aW5nRmlsdGVyJyxcbiAgICAgICAgbnVtYmVyOiAnYWdOdW1iZXJDb2x1bW5GbG9hdGluZ0ZpbHRlcicsXG4gICAgICAgIGFnTnVtYmVyQ29sdW1uRmlsdGVyOiAnYWdOdW1iZXJDb2x1bW5GbG9hdGluZ0ZpbHRlcicsXG4gICAgICAgIGRhdGU6ICdhZ0RhdGVDb2x1bW5GbG9hdGluZ0ZpbHRlcicsXG4gICAgICAgIGFnRGF0ZUNvbHVtbkZpbHRlcjogJ2FnRGF0ZUNvbHVtbkZsb2F0aW5nRmlsdGVyJyxcbiAgICAgICAgdGV4dDogJ2FnVGV4dENvbHVtbkZsb2F0aW5nRmlsdGVyJyxcbiAgICAgICAgYWdUZXh0Q29sdW1uRmlsdGVyOiAnYWdUZXh0Q29sdW1uRmxvYXRpbmdGaWx0ZXInXG4gICAgfTtcbiAgICByZXR1cm4gRmxvYXRpbmdGaWx0ZXJNYXBwZXI7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDI4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxVyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFVzZXJDb21wb25lbnRGYWN0b3J5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyOChVc2VyQ29tcG9uZW50RmFjdG9yeSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBVc2VyQ29tcG9uZW50RmFjdG9yeSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0SGVhZGVyQ29tcERldGFpbHMgPSBmdW5jdGlvbiAoY29sRGVmLCBwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHMoY29sRGVmLCBIZWFkZXJDb21wb25lbnQsICdhZ0NvbHVtbkhlYWRlcicsIHBhcmFtcyk7XG4gICAgfTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0SGVhZGVyR3JvdXBDb21wRGV0YWlscyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIGNvbEdyb3VwRGVmID0gcGFyYW1zLmNvbHVtbkdyb3VwLmdldENvbEdyb3VwRGVmKCk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKGNvbEdyb3VwRGVmLCBIZWFkZXJHcm91cENvbXBvbmVudCwgJ2FnQ29sdW1uR3JvdXBIZWFkZXInLCBwYXJhbXMpO1xuICAgIH07XG4gICAgLy8gdGhpcyBvbmUgaXMgdW51c3VhbCwgYXMgaXQgY2FuIGJlIExvYWRpbmdDZWxsUmVuZGVyZXIsIERldGFpbENlbGxSZW5kZXJlciwgRnVsbFdpZHRoQ2VsbFJlbmRlcmVyIG9yIEdyb3VwUm93UmVuZGVyZXIuXG4gICAgLy8gc28gd2UgaGF2ZSB0byBwYXNzIHRoZSB0eXBlIGluLlxuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5nZXRGdWxsV2lkdGhDZWxsUmVuZGVyZXJEZXRhaWxzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb21wRGV0YWlscyh0aGlzLmdyaWRPcHRpb25zLCBGdWxsV2lkdGgsIG51bGwsIHBhcmFtcywgdHJ1ZSk7XG4gICAgfTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0RnVsbFdpZHRoTG9hZGluZ0NlbGxSZW5kZXJlckRldGFpbHMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKHRoaXMuZ3JpZE9wdGlvbnMsIEZ1bGxXaWR0aExvYWRpbmcsICdhZ0xvYWRpbmdDZWxsUmVuZGVyZXInLCBwYXJhbXMsIHRydWUpO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldEZ1bGxXaWR0aEdyb3VwQ2VsbFJlbmRlcmVyRGV0YWlscyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHModGhpcy5ncmlkT3B0aW9ucywgRnVsbFdpZHRoR3JvdXAsICdhZ0dyb3VwUm93UmVuZGVyZXInLCBwYXJhbXMsIHRydWUpO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldEZ1bGxXaWR0aERldGFpbENlbGxSZW5kZXJlckRldGFpbHMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKHRoaXMuZ3JpZE9wdGlvbnMsIEZ1bGxXaWR0aERldGFpbCwgJ2FnRGV0YWlsQ2VsbFJlbmRlcmVyJywgcGFyYW1zLCB0cnVlKTtcbiAgICB9O1xuICAgIC8vIENFTEwgUkVOREVSRVJcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0SW5uZXJSZW5kZXJlckRldGFpbHMgPSBmdW5jdGlvbiAoZGVmLCBwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHMoZGVmLCBJbm5lclJlbmRlcmVyQ29tcG9uZW50LCBudWxsLCBwYXJhbXMpO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldEZ1bGxXaWR0aEdyb3VwUm93SW5uZXJDZWxsUmVuZGVyZXIgPSBmdW5jdGlvbiAoZGVmLCBwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHMoZGVmLCBJbm5lclJlbmRlcmVyQ29tcG9uZW50LCBudWxsLCBwYXJhbXMpO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldENlbGxSZW5kZXJlckRldGFpbHMgPSBmdW5jdGlvbiAoZGVmLCBwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHMoZGVmLCBDZWxsUmVuZGVyZXJDb21wb25lbnQsIG51bGwsIHBhcmFtcyk7XG4gICAgfTtcbiAgICAvLyBDRUxMIEVESVRPUlxuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5nZXRDZWxsRWRpdG9yRGV0YWlscyA9IGZ1bmN0aW9uIChkZWYsIHBhcmFtcykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb21wRGV0YWlscyhkZWYsIENlbGxFZGl0b3JDb21wb25lbnQsICdhZ0NlbGxFZGl0b3InLCBwYXJhbXMsIHRydWUpO1xuICAgIH07XG4gICAgLy8gRklMVEVSXG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldEZpbHRlckRldGFpbHMgPSBmdW5jdGlvbiAoZGVmLCBwYXJhbXMsIGRlZmF1bHRGaWx0ZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHMoZGVmLCBGaWx0ZXJDb21wb25lbnQsIGRlZmF1bHRGaWx0ZXIsIHBhcmFtcywgdHJ1ZSk7XG4gICAgfTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0RGF0ZUNvbXBEZXRhaWxzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb21wRGV0YWlscyh0aGlzLmdyaWRPcHRpb25zLCBEYXRlQ29tcG9uZW50LCAnYWdEYXRlSW5wdXQnLCBwYXJhbXMsIHRydWUpO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldExvYWRpbmdPdmVybGF5Q29tcERldGFpbHMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKHRoaXMuZ3JpZE9wdGlvbnMsIExvYWRpbmdPdmVybGF5Q29tcG9uZW50LCAnYWdMb2FkaW5nT3ZlcmxheScsIHBhcmFtcywgdHJ1ZSk7XG4gICAgfTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0Tm9Sb3dzT3ZlcmxheUNvbXBEZXRhaWxzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb21wRGV0YWlscyh0aGlzLmdyaWRPcHRpb25zLCBOb1Jvd3NPdmVybGF5Q29tcG9uZW50LCAnYWdOb1Jvd3NPdmVybGF5JywgcGFyYW1zLCB0cnVlKTtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5nZXRUb29sdGlwQ29tcERldGFpbHMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKHBhcmFtcy5jb2xEZWYsIFRvb2x0aXBDb21wb25lbnQsICdhZ1Rvb2x0aXBDb21wb25lbnQnLCBwYXJhbXMsIHRydWUpO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldFNldEZpbHRlckNlbGxSZW5kZXJlckRldGFpbHMgPSBmdW5jdGlvbiAoZGVmLCBwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29tcERldGFpbHMoZGVmLCBDZWxsUmVuZGVyZXJDb21wb25lbnQsIG51bGwsIHBhcmFtcyk7XG4gICAgfTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0RmxvYXRpbmdGaWx0ZXJDb21wRGV0YWlscyA9IGZ1bmN0aW9uIChkZWYsIHBhcmFtcywgZGVmYXVsdEZsb2F0aW5nRmlsdGVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKGRlZiwgRmxvYXRpbmdGaWx0ZXJDb21wb25lbnQsIGRlZmF1bHRGbG9hdGluZ0ZpbHRlciwgcGFyYW1zKTtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5nZXRUb29sUGFuZWxDb21wRGV0YWlscyA9IGZ1bmN0aW9uICh0b29sUGFuZWxEZWYsIHBhcmFtcykge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRDb21wRGV0YWlscyh0b29sUGFuZWxEZWYsIFRvb2xQYW5lbENvbXBvbmVudCwgbnVsbCwgcGFyYW1zLCB0cnVlKTtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5nZXRTdGF0dXNQYW5lbENvbXBEZXRhaWxzID0gZnVuY3Rpb24gKGRlZiwgcGFyYW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbXBEZXRhaWxzKGRlZiwgU3RhdHVzUGFuZWxDb21wb25lbnQsIG51bGwsIHBhcmFtcywgdHJ1ZSk7XG4gICAgfTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUuZ2V0Q29tcERldGFpbHMgPSBmdW5jdGlvbiAoZGVmT2JqZWN0LCB0eXBlLCBkZWZhdWx0TmFtZSwgcGFyYW1zLCBtYW5kYXRvcnkpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKG1hbmRhdG9yeSA9PT0gdm9pZCAwKSB7IG1hbmRhdG9yeSA9IGZhbHNlOyB9XG4gICAgICAgIHZhciBwcm9wZXJ0eU5hbWUgPSB0eXBlLnByb3BlcnR5TmFtZSwgY2VsbFJlbmRlcmVyID0gdHlwZS5jZWxsUmVuZGVyZXI7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuZ2V0Q29tcEtleXMoZGVmT2JqZWN0LCB0eXBlLCBwYXJhbXMpLCBjb21wTmFtZSA9IF9hLmNvbXBOYW1lLCBqc0NvbXAgPSBfYS5qc0NvbXAsIGZ3Q29tcCA9IF9hLmZ3Q29tcCwgcGFyYW1zRnJvbVNlbGVjdG9yID0gX2EucGFyYW1zRnJvbVNlbGVjdG9yLCBwb3B1cEZyb21TZWxlY3RvciA9IF9hLnBvcHVwRnJvbVNlbGVjdG9yLCBwb3B1cFBvc2l0aW9uRnJvbVNlbGVjdG9yID0gX2EucG9wdXBQb3NpdGlvbkZyb21TZWxlY3RvcjtcbiAgICAgICAgdmFyIGxvb2t1cEZyb21SZWdpc3RyeSA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gX3RoaXMudXNlckNvbXBvbmVudFJlZ2lzdHJ5LnJldHJpZXZlKGtleSk7XG4gICAgICAgICAgICBpZiAoaXRlbSkge1xuICAgICAgICAgICAgICAgIGpzQ29tcCA9ICFpdGVtLmNvbXBvbmVudEZyb21GcmFtZXdvcmsgPyBpdGVtLmNvbXBvbmVudCA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBmd0NvbXAgPSBpdGVtLmNvbXBvbmVudEZyb21GcmFtZXdvcmsgPyBpdGVtLmNvbXBvbmVudCA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLy8gaWYgY29tcE9wdGlvbiBpcyBhIHN0cmluZywgbWVhbnMgd2UgbmVlZCB0byBsb29rIHRoZSBpdGVtIHVwXG4gICAgICAgIGlmIChjb21wTmFtZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBsb29rdXBGcm9tUmVnaXN0cnkoY29tcE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGxvb2t1cCBicm91Z2h0IG5vdGhpbmcgYmFjaywgYW5kIHdlIGhhdmUgYSBkZWZhdWx0LCBsb29rdXAgdGhlIGRlZmF1bHRcbiAgICAgICAgaWYgKGpzQ29tcCA9PSBudWxsICYmIGZ3Q29tcCA9PSBudWxsICYmIGRlZmF1bHROYW1lICE9IG51bGwpIHtcbiAgICAgICAgICAgIGxvb2t1cEZyb21SZWdpc3RyeShkZWZhdWx0TmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgaGF2ZSBhIGNvbXAgb3B0aW9uLCBhbmQgaXQncyBhIGZ1bmN0aW9uLCByZXBsYWNlIGl0IHdpdGggYW4gb2JqZWN0IGVxdWl2YWxlbnQgYWRhcHRvclxuICAgICAgICBpZiAoanNDb21wICYmIGNlbGxSZW5kZXJlciAmJiAhdGhpcy5hZ0NvbXBvbmVudFV0aWxzLmRvZXNJbXBsZW1lbnRJQ29tcG9uZW50KGpzQ29tcCkpIHtcbiAgICAgICAgICAgIGpzQ29tcCA9IHRoaXMuYWdDb21wb25lbnRVdGlscy5hZGFwdEZ1bmN0aW9uKHByb3BlcnR5TmFtZSwganNDb21wKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWpzQ29tcCAmJiAhZndDb21wKSB7XG4gICAgICAgICAgICBpZiAobWFuZGF0b3J5KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBmaW5kIGNvbXBvbmVudCBcIiArIGNvbXBOYW1lICsgXCIsIGRpZCB5b3UgZm9yZ2V0IHRvIGNvbmZpZ3VyZSB0aGlzIGNvbXBvbmVudD9cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtc01lcmdlZCA9IHRoaXMubWVyZ2VQYXJhbXNXaXRoQXBwbGljYXRpb25Qcm92aWRlZFBhcmFtcyhkZWZPYmplY3QsIHR5cGUsIHBhcmFtcywgcGFyYW1zRnJvbVNlbGVjdG9yKTtcbiAgICAgICAgdmFyIGNvbXBvbmVudEZyb21GcmFtZXdvcmsgPSBqc0NvbXAgPT0gbnVsbDtcbiAgICAgICAgdmFyIGNvbXBvbmVudENsYXNzID0ganNDb21wID8ganNDb21wIDogZndDb21wO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29tcG9uZW50RnJvbUZyYW1ld29yazogY29tcG9uZW50RnJvbUZyYW1ld29yayxcbiAgICAgICAgICAgIGNvbXBvbmVudENsYXNzOiBjb21wb25lbnRDbGFzcyxcbiAgICAgICAgICAgIHBhcmFtczogcGFyYW1zTWVyZ2VkLFxuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIHBvcHVwRnJvbVNlbGVjdG9yOiBwb3B1cEZyb21TZWxlY3RvcixcbiAgICAgICAgICAgIHBvcHVwUG9zaXRpb25Gcm9tU2VsZWN0b3I6IHBvcHVwUG9zaXRpb25Gcm9tU2VsZWN0b3IsXG4gICAgICAgICAgICBuZXdBZ1N0YWNrSW5zdGFuY2U6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm5ld0FnU3RhY2tJbnN0YW5jZShjb21wb25lbnRDbGFzcywgY29tcG9uZW50RnJvbUZyYW1ld29yaywgcGFyYW1zTWVyZ2VkLCB0eXBlKTsgfVxuICAgICAgICB9O1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmdldENvbXBLZXlzID0gZnVuY3Rpb24gKGRlZk9iamVjdCwgdHlwZSwgcGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwcm9wZXJ0eU5hbWUgPSB0eXBlLnByb3BlcnR5TmFtZTtcbiAgICAgICAgdmFyIGNvbXBOYW1lO1xuICAgICAgICB2YXIganNDb21wO1xuICAgICAgICB2YXIgZndDb21wO1xuICAgICAgICB2YXIgcGFyYW1zRnJvbVNlbGVjdG9yO1xuICAgICAgICB2YXIgcG9wdXBGcm9tU2VsZWN0b3I7XG4gICAgICAgIHZhciBwb3B1cFBvc2l0aW9uRnJvbVNlbGVjdG9yO1xuICAgICAgICAvLyB0aGVyZSBhcmUgdHdvIHR5cGVzIG9mIGpzIGNvbXBzLCBjbGFzcyBiYXNlZCBhbmQgZnVuYyBiYXNlZC4gd2UgY2FuIG9ubHkgY2hlY2sgZm9yXG4gICAgICAgIC8vIGNsYXNzIGJhc2VkLCBieSBjaGVja2luZyBpZiBnZXRHdWkoKSBleGlzdHMuIG5vIHdheSB0byBkaWZmZXJlbnRpYXRlIGpzIGZ1bmMgYmFzZWQgdnMgZWcgcmVhY3QgZnVuYyBiYXNlZFxuICAgICAgICAvLyBjb25zdCBpc0pzQ2xhc3NDb21wID0gKGNvbXA6IGFueSkgPT4gdGhpcy5hZ0NvbXBvbmVudFV0aWxzLmRvZXNJbXBsZW1lbnRJQ29tcG9uZW50KGNvbXApO1xuICAgICAgICAvLyBjb25zdCBmd0FjdGl2ZSA9IHRoaXMuZnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlciAhPSBudWxsO1xuICAgICAgICAvLyBwdWxsIGZyb20gZGVmT2JqZWN0IGlmIGF2YWlsYWJsZVxuICAgICAgICBpZiAoZGVmT2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgZGVmT2JqZWN0QW55ID0gZGVmT2JqZWN0O1xuICAgICAgICAgICAgLy8gaWYgc2VsZWN0b3IsIHVzZSB0aGlzXG4gICAgICAgICAgICB2YXIgc2VsZWN0b3JGdW5jID0gZGVmT2JqZWN0QW55W3Byb3BlcnR5TmFtZSArICdTZWxlY3RvciddO1xuICAgICAgICAgICAgdmFyIHNlbGVjdG9yUmVzID0gc2VsZWN0b3JGdW5jID8gc2VsZWN0b3JGdW5jKHBhcmFtcykgOiBudWxsO1xuICAgICAgICAgICAgdmFyIGFzc2lnbkNvbXAgPSBmdW5jdGlvbiAocHJvdmlkZWRKc0NvbXAsIHByb3ZpZGVkRndDb21wKSB7XG4gICAgICAgICAgICAgICAgdmFyIHh4eEZyYW1ld29ya0RlcHJlY2F0ZWRXYXJuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FybmluZ01lc3NhZ2UgPSBcIkFHIEdyaWQ6IEFzIG9mIHYyNywgdGhlIHByb3BlcnR5IFwiICsgcHJvcGVydHlOYW1lICsgXCJGcmFtZXdvcmsgaXMgZGVwcmVjYXRlZC4gVGhlIHByb3BlcnR5IFwiICsgcHJvcGVydHlOYW1lICsgXCIgY2FuIG5vdyBiZSB1c2VkIGZvciBKYXZhU2NyaXB0IEFORCBGcmFtZXdvcmsgQ29tcG9uZW50cy5cIjtcbiAgICAgICAgICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2Fybih3YXJuaW5nTWVzc2FnZSk7IH0sIFwiVXNlckNvbXBvbmVudEZhY3RvcnkuXCIgKyBwcm9wZXJ0eU5hbWUgKyBcIkZyYW1ld29ya0RlcHJlY2F0ZWRcIik7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHByb3ZpZGVkSnNDb21wID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICBjb21wTmFtZSA9IHByb3ZpZGVkSnNDb21wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgcHJvdmlkZWRGd0NvbXAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHh4eEZyYW1ld29ya0RlcHJlY2F0ZWRXYXJuKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBOYW1lID0gcHJvdmlkZWRGd0NvbXA7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbXA9PT10cnVlIGZvciBmaWx0ZXJzLCB3aGljaCBtZWFucyB1c2UgdGhlIGRlZmF1bHQgY29tcFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChwcm92aWRlZEpzQ29tcCAhPSBudWxsICYmIHByb3ZpZGVkSnNDb21wICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc0Z3a0NvbXAgPSBfdGhpcy5nZXRGcmFtZXdvcmtPdmVycmlkZXMoKS5pc0ZyYW1ld29ya0NvbXBvbmVudChwcm92aWRlZEpzQ29tcCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0Z3a0NvbXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ3Q29tcCA9IHByb3ZpZGVkSnNDb21wO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAganNDb21wID0gcHJvdmlkZWRKc0NvbXA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAocHJvdmlkZWRGd0NvbXAgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB4eHhGcmFtZXdvcmtEZXByZWNhdGVkV2FybigpO1xuICAgICAgICAgICAgICAgICAgICBmd0NvbXAgPSBwcm92aWRlZEZ3Q29tcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKHNlbGVjdG9yUmVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdG9yUmVzLmZyYW1ld29ya0NvbXBvbmVudCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YXJuaW5nTWVzc2FnZV8xID0gXCJBRyBHcmlkOiBBcyBvZiB2MjcsIHRoZSByZXR1cm4gZm9yIFwiICsgcHJvcGVydHlOYW1lICsgXCJTZWxlY3RvciBoYXMgYXR0cmlidXRlcyBbY29tcG9uZW50LCBwYXJhbXNdIG9ubHkuIFRoZSBhdHRyaWJ1dGUgZnJhbWV3b3JrQ29tcG9uZW50IGlzIGRlcHJlY2F0ZWQuIFlvdSBzaG91bGQgbm93IHJldHVybiBiYWNrIEZyYW1ld29yayBDb21wb25lbnRzIHVzaW5nIHRoZSAnY29tcG9uZW50JyBhdHRyaWJ1dGUgYW5kIHRoZSBncmlkIHdvcmtzIG91dCBpZiBpdCdzIGEgZnJhbWV3b3JrIGNvbXBvbmVudCBvciBub3QuXCI7XG4gICAgICAgICAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4od2FybmluZ01lc3NhZ2VfMSk7IH0sIFwiVXNlckNvbXBvbmVudEZhY3RvcnkuXCIgKyBwcm9wZXJ0eU5hbWUgKyBcIkZyYW1ld29ya1NlbGVjdG9yRGVwcmVjYXRlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgYXNzaWduQ29tcChzZWxlY3RvclJlcy5mcmFtZXdvcmtDb21wb25lbnQsIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhc3NpZ25Db21wKHNlbGVjdG9yUmVzLmNvbXBvbmVudCwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcGFyYW1zRnJvbVNlbGVjdG9yID0gc2VsZWN0b3JSZXMucGFyYW1zO1xuICAgICAgICAgICAgICAgIHBvcHVwRnJvbVNlbGVjdG9yID0gc2VsZWN0b3JSZXMucG9wdXA7XG4gICAgICAgICAgICAgICAgcG9wdXBQb3NpdGlvbkZyb21TZWxlY3RvciA9IHNlbGVjdG9yUmVzLnBvcHVwUG9zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBpZiBubyBzZWxlY3Rvciwgb3IgcmVzdWx0IG9mIHNlbGVjdG9yIGlzIGVtcHR5LCB0YWtlIGZyb20gZGVmT2JqZWN0XG4gICAgICAgICAgICAgICAgYXNzaWduQ29tcChkZWZPYmplY3RBbnlbcHJvcGVydHlOYW1lXSwgZGVmT2JqZWN0QW55W3Byb3BlcnR5TmFtZSArICdGcmFtZXdvcmsnXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgY29tcE5hbWU6IGNvbXBOYW1lLCBqc0NvbXA6IGpzQ29tcCwgZndDb21wOiBmd0NvbXAsIHBhcmFtc0Zyb21TZWxlY3RvcjogcGFyYW1zRnJvbVNlbGVjdG9yLCBwb3B1cEZyb21TZWxlY3RvcjogcG9wdXBGcm9tU2VsZWN0b3IsIHBvcHVwUG9zaXRpb25Gcm9tU2VsZWN0b3I6IHBvcHVwUG9zaXRpb25Gcm9tU2VsZWN0b3IgfTtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5uZXdBZ1N0YWNrSW5zdGFuY2UgPSBmdW5jdGlvbiAoQ29tcG9uZW50Q2xhc3MsIGNvbXBvbmVudEZyb21GcmFtZXdvcmssIHBhcmFtcywgdHlwZSkge1xuICAgICAgICB2YXIgcHJvcGVydHlOYW1lID0gdHlwZS5wcm9wZXJ0eU5hbWU7XG4gICAgICAgIHZhciBqc0NvbXBvbmVudCA9ICFjb21wb25lbnRGcm9tRnJhbWV3b3JrO1xuICAgICAgICAvLyB1c2luZyBqYXZhc2NyaXB0IGNvbXBvbmVudFxuICAgICAgICB2YXIgaW5zdGFuY2U7XG4gICAgICAgIGlmIChqc0NvbXBvbmVudCkge1xuICAgICAgICAgICAgaW5zdGFuY2UgPSBuZXcgQ29tcG9uZW50Q2xhc3MoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFVzaW5nIGZyYW1ld29yayBjb21wb25lbnRcbiAgICAgICAgICAgIHZhciB0aGlzQ29tcG9uZW50Q29uZmlnID0gdGhpcy5jb21wb25lbnRNZXRhZGF0YVByb3ZpZGVyLnJldHJpZXZlKHByb3BlcnR5TmFtZSk7XG4gICAgICAgICAgICBpbnN0YW5jZSA9IHRoaXMuZnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlci53cmFwKENvbXBvbmVudENsYXNzLCB0aGlzQ29tcG9uZW50Q29uZmlnLm1hbmRhdG9yeU1ldGhvZExpc3QsIHRoaXNDb21wb25lbnRDb25maWcub3B0aW9uYWxNZXRob2RMaXN0LCB0eXBlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGVmZXJyZWRJbml0ID0gdGhpcy5pbml0Q29tcG9uZW50KGluc3RhbmNlLCBwYXJhbXMpO1xuICAgICAgICBpZiAoZGVmZXJyZWRJbml0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBBZ1Byb21pc2UucmVzb2x2ZShpbnN0YW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlZmVycmVkSW5pdC50aGVuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGluc3RhbmNlOyB9KTtcbiAgICB9O1xuICAgIC8vIHVzZWQgYnkgRmxvYXRpbmcgRmlsdGVyXG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLm1lcmdlUGFyYW1zV2l0aEFwcGxpY2F0aW9uUHJvdmlkZWRQYXJhbXMgPSBmdW5jdGlvbiAoZGVmT2JqZWN0LCB0eXBlLCBwYXJhbXNGcm9tR3JpZCwgcGFyYW1zRnJvbVNlbGVjdG9yKSB7XG4gICAgICAgIGlmIChwYXJhbXNGcm9tU2VsZWN0b3IgPT09IHZvaWQgMCkgeyBwYXJhbXNGcm9tU2VsZWN0b3IgPSBudWxsOyB9XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKVxuICAgICAgICB9O1xuICAgICAgICBtZXJnZURlZXAocGFyYW1zLCBwYXJhbXNGcm9tR3JpZCk7XG4gICAgICAgIC8vIHB1bGwgdXNlciBwYXJhbXMgZnJvbSBlaXRoZXIgdGhlIG9sZCBwcm9wIG5hbWUgYW5kIG5ldyBwcm9wIG5hbWVcbiAgICAgICAgLy8gZWcgZWl0aGVyIGNlbGxSZW5kZXJlclBhcmFtcyBhbmQgY2VsbENvbXBQYXJhbXNcbiAgICAgICAgdmFyIGRlZk9iamVjdEFueSA9IGRlZk9iamVjdDtcbiAgICAgICAgdmFyIHVzZXJQYXJhbXMgPSBkZWZPYmplY3RBbnkgJiYgZGVmT2JqZWN0QW55W3R5cGUucHJvcGVydHlOYW1lICsgJ1BhcmFtcyddO1xuICAgICAgICBpZiAodHlwZW9mIHVzZXJQYXJhbXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhciB1c2VyUGFyYW1zRnJvbUZ1bmMgPSB1c2VyUGFyYW1zKHBhcmFtc0Zyb21HcmlkKTtcbiAgICAgICAgICAgIG1lcmdlRGVlcChwYXJhbXMsIHVzZXJQYXJhbXNGcm9tRnVuYyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHVzZXJQYXJhbXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBtZXJnZURlZXAocGFyYW1zLCB1c2VyUGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICBtZXJnZURlZXAocGFyYW1zLCBwYXJhbXNGcm9tU2VsZWN0b3IpO1xuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH07XG4gICAgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLmluaXRDb21wb25lbnQgPSBmdW5jdGlvbiAoY29tcG9uZW50LCBwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5jb250ZXh0LmNyZWF0ZUJlYW4oY29tcG9uZW50KTtcbiAgICAgICAgaWYgKGNvbXBvbmVudC5pbml0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29tcG9uZW50LmluaXQocGFyYW1zKTtcbiAgICB9O1xuICAgIFVzZXJDb21wb25lbnRGYWN0b3J5LnByb3RvdHlwZS5nZXREZWZhdWx0RmxvYXRpbmdGaWx0ZXJUeXBlID0gZnVuY3Rpb24gKGRlZikge1xuICAgICAgICBpZiAoZGVmID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkZWZhdWx0RmxvYXRpbmdGaWx0ZXJUeXBlID0gbnVsbDtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5nZXRDb21wS2V5cyhkZWYsIEZpbHRlckNvbXBvbmVudCksIGNvbXBOYW1lID0gX2EuY29tcE5hbWUsIGpzQ29tcCA9IF9hLmpzQ29tcCwgZndDb21wID0gX2EuZndDb21wO1xuICAgICAgICBpZiAoY29tcE5hbWUpIHtcbiAgICAgICAgICAgIC8vIHdpbGwgYmUgdW5kZWZpbmVkIGlmIG5vdCBpbiB0aGUgbWFwXG4gICAgICAgICAgICBkZWZhdWx0RmxvYXRpbmdGaWx0ZXJUeXBlID0gRmxvYXRpbmdGaWx0ZXJNYXBwZXIuZ2V0RmxvYXRpbmdGaWx0ZXJUeXBlKGNvbXBOYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciB1c2luZ0RlZmF1bHRGaWx0ZXIgPSAoanNDb21wID09IG51bGwgJiYgZndDb21wID09IG51bGwpICYmIChkZWYuZmlsdGVyID09PSB0cnVlKTtcbiAgICAgICAgICAgIGlmICh1c2luZ0RlZmF1bHRGaWx0ZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2V0RmlsdGVyTW9kdWxlTG9hZGVkID0gTW9kdWxlUmVnaXN0cnkuaXNSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLlNldEZpbHRlck1vZHVsZSk7XG4gICAgICAgICAgICAgICAgZGVmYXVsdEZsb2F0aW5nRmlsdGVyVHlwZSA9IHNldEZpbHRlck1vZHVsZUxvYWRlZCA/ICdhZ1NldENvbHVtbkZsb2F0aW5nRmlsdGVyJyA6ICdhZ1RleHRDb2x1bW5GbG9hdGluZ0ZpbHRlcic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlZmF1bHRGbG9hdGluZ0ZpbHRlclR5cGU7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFXKFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkT3B0aW9ucycpXG4gICAgXSwgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLCBcImdyaWRPcHRpb25zXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxVyhbXG4gICAgICAgIEF1dG93aXJlZCgnYWdDb21wb25lbnRVdGlscycpXG4gICAgXSwgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLCBcImFnQ29tcG9uZW50VXRpbHNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFXKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb21wb25lbnRNZXRhZGF0YVByb3ZpZGVyJylcbiAgICBdLCBVc2VyQ29tcG9uZW50RmFjdG9yeS5wcm90b3R5cGUsIFwiY29tcG9uZW50TWV0YWRhdGFQcm92aWRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVcoW1xuICAgICAgICBBdXRvd2lyZWQoJ3VzZXJDb21wb25lbnRSZWdpc3RyeScpXG4gICAgXSwgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLCBcInVzZXJDb21wb25lbnRSZWdpc3RyeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVcoW1xuICAgICAgICBPcHRpb25hbCgnZnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlcicpXG4gICAgXSwgVXNlckNvbXBvbmVudEZhY3RvcnkucHJvdG90eXBlLCBcImZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXJcIiwgdm9pZCAwKTtcbiAgICBVc2VyQ29tcG9uZW50RmFjdG9yeSA9IF9fZGVjb3JhdGUkMVcoW1xuICAgICAgICBCZWFuKCd1c2VyQ29tcG9uZW50RmFjdG9yeScpXG4gICAgXSwgVXNlckNvbXBvbmVudEZhY3RvcnkpO1xuICAgIHJldHVybiBVc2VyQ29tcG9uZW50RmFjdG9yeTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuLy8gRXhjZWwgRXhwb3J0XG52YXIgRXhjZWxGYWN0b3J5TW9kZTtcbihmdW5jdGlvbiAoRXhjZWxGYWN0b3J5TW9kZSkge1xuICAgIEV4Y2VsRmFjdG9yeU1vZGVbRXhjZWxGYWN0b3J5TW9kZVtcIlNJTkdMRV9TSEVFVFwiXSA9IDBdID0gXCJTSU5HTEVfU0hFRVRcIjtcbiAgICBFeGNlbEZhY3RvcnlNb2RlW0V4Y2VsRmFjdG9yeU1vZGVbXCJNVUxUSV9TSEVFVFwiXSA9IDFdID0gXCJNVUxUSV9TSEVFVFwiO1xufSkoRXhjZWxGYWN0b3J5TW9kZSB8fCAoRXhjZWxGYWN0b3J5TW9kZSA9IHt9KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMjcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFWID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG4vKiogQWRkcyBkcmFnIGxpc3RlbmluZyBvbnRvIGFuIGVsZW1lbnQuIEluIEFHIEdyaWQgdGhpcyBpcyB1c2VkIHR3aWNlLCBmaXJzdCBpcyByZXNpemluZyBjb2x1bW5zLFxuICogc2Vjb25kIGlzIG1vdmluZyB0aGUgY29sdW1ucyBhbmQgY29sdW1uIGdyb3VwcyBhcm91bmQgKGllIHRoZSAnZHJhZycgcGFydCBvZiBEcmFnIGFuZCBEcm9wLiAqL1xudmFyIERyYWdTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyNyhEcmFnU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBEcmFnU2VydmljZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmRyYWdFbmRGdW5jdGlvbnMgPSBbXTtcbiAgICAgICAgX3RoaXMuZHJhZ1NvdXJjZXMgPSBbXTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSB0aGlzLmxvZ2dlckZhY3RvcnkuY3JlYXRlKCdEcmFnU2VydmljZScpO1xuICAgIH07XG4gICAgRHJhZ1NlcnZpY2UucHJvdG90eXBlLnJlbW92ZUFsbExpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kcmFnU291cmNlcy5mb3JFYWNoKHRoaXMucmVtb3ZlTGlzdGVuZXIuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuZHJhZ1NvdXJjZXMubGVuZ3RoID0gMDtcbiAgICB9O1xuICAgIERyYWdTZXJ2aWNlLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uIChkcmFnU291cmNlQW5kTGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSBkcmFnU291cmNlQW5kTGlzdGVuZXIuZHJhZ1NvdXJjZS5lRWxlbWVudDtcbiAgICAgICAgdmFyIG1vdXNlRG93bkxpc3RlbmVyID0gZHJhZ1NvdXJjZUFuZExpc3RlbmVyLm1vdXNlRG93bkxpc3RlbmVyO1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG1vdXNlRG93bkxpc3RlbmVyKTtcbiAgICAgICAgLy8gcmVtb3ZlIHRvdWNoIGxpc3RlbmVyIG9ubHkgaWYgaXQgZXhpc3RzXG4gICAgICAgIGlmIChkcmFnU291cmNlQW5kTGlzdGVuZXIudG91Y2hFbmFibGVkKSB7XG4gICAgICAgICAgICB2YXIgdG91Y2hTdGFydExpc3RlbmVyID0gZHJhZ1NvdXJjZUFuZExpc3RlbmVyLnRvdWNoU3RhcnRMaXN0ZW5lcjtcbiAgICAgICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRvdWNoU3RhcnRMaXN0ZW5lciwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUucmVtb3ZlRHJhZ1NvdXJjZSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIGRyYWdTb3VyY2VBbmRMaXN0ZW5lciA9IHRoaXMuZHJhZ1NvdXJjZXMuZmluZChmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gaXRlbS5kcmFnU291cmNlID09PSBwYXJhbXM7IH0pO1xuICAgICAgICBpZiAoIWRyYWdTb3VyY2VBbmRMaXN0ZW5lcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZHJhZ1NvdXJjZUFuZExpc3RlbmVyKTtcbiAgICAgICAgcmVtb3ZlRnJvbUFycmF5KHRoaXMuZHJhZ1NvdXJjZXMsIGRyYWdTb3VyY2VBbmRMaXN0ZW5lcik7XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUuaXNEcmFnZ2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZHJhZ2dpbmc7XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUuYWRkRHJhZ1NvdXJjZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGluY2x1ZGVUb3VjaCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoaW5jbHVkZVRvdWNoID09PSB2b2lkIDApIHsgaW5jbHVkZVRvdWNoID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIG1vdXNlTGlzdGVuZXIgPSB0aGlzLm9uTW91c2VEb3duLmJpbmQodGhpcywgcGFyYW1zKTtcbiAgICAgICAgcGFyYW1zLmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG1vdXNlTGlzdGVuZXIpO1xuICAgICAgICB2YXIgdG91Y2hMaXN0ZW5lciA9IG51bGw7XG4gICAgICAgIHZhciBzdXBwcmVzc1RvdWNoID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1RvdWNoKCk7XG4gICAgICAgIGlmIChpbmNsdWRlVG91Y2ggJiYgIXN1cHByZXNzVG91Y2gpIHtcbiAgICAgICAgICAgIHRvdWNoTGlzdGVuZXIgPSBmdW5jdGlvbiAodG91Y2hFdmVudCkge1xuICAgICAgICAgICAgICAgIGlmIChpc0ZvY3VzYWJsZUZvcm1GaWVsZCh0b3VjaEV2ZW50LnRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodG91Y2hFdmVudC5jYW5jZWxhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvdWNoRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMub25Ub3VjaFN0YXJ0KHBhcmFtcywgdG91Y2hFdmVudCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gd2Ugc2V0IHBhc3NpdmU9ZmFsc2UsIGFzIHdlIHdhbnQgdG8gcHJldmVudCBkZWZhdWx0IG9uIHRoaXMgZXZlbnRcbiAgICAgICAgICAgIHBhcmFtcy5lRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdG91Y2hMaXN0ZW5lciwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRyYWdTb3VyY2VzLnB1c2goe1xuICAgICAgICAgICAgZHJhZ1NvdXJjZTogcGFyYW1zLFxuICAgICAgICAgICAgbW91c2VEb3duTGlzdGVuZXI6IG1vdXNlTGlzdGVuZXIsXG4gICAgICAgICAgICB0b3VjaFN0YXJ0TGlzdGVuZXI6IHRvdWNoTGlzdGVuZXIsXG4gICAgICAgICAgICB0b3VjaEVuYWJsZWQ6IGluY2x1ZGVUb3VjaFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIGdldHMgY2FsbGVkIHdoZW5ldmVyIG1vdXNlIGRvd24gb24gYW55IGRyYWcgc291cmNlXG4gICAgRHJhZ1NlcnZpY2UucHJvdG90eXBlLm9uVG91Y2hTdGFydCA9IGZ1bmN0aW9uIChwYXJhbXMsIHRvdWNoRXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdXJyZW50RHJhZ1BhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgdGhpcy5kcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICB2YXIgdG91Y2ggPSB0b3VjaEV2ZW50LnRvdWNoZXNbMF07XG4gICAgICAgIHRoaXMudG91Y2hMYXN0VGltZSA9IHRvdWNoO1xuICAgICAgICB0aGlzLnRvdWNoU3RhcnQgPSB0b3VjaDtcbiAgICAgICAgdmFyIHRvdWNoTW92ZUV2ZW50ID0gZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uVG91Y2hNb3ZlKGUsIHBhcmFtcy5lRWxlbWVudCk7IH07XG4gICAgICAgIHZhciB0b3VjaEVuZEV2ZW50ID0gZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uVG91Y2hVcChlLCBwYXJhbXMuZUVsZW1lbnQpOyB9O1xuICAgICAgICB2YXIgZG9jdW1lbnRUb3VjaE1vdmUgPSBmdW5jdGlvbiAoZSkgeyBpZiAoZS5jYW5jZWxhYmxlKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0gfTtcbiAgICAgICAgdmFyIHRhcmdldCA9IHRvdWNoRXZlbnQudGFyZ2V0O1xuICAgICAgICB2YXIgZXZlbnRzID0gW1xuICAgICAgICAgICAgLy8gUHJldmVudHMgdGhlIHBhZ2UgZG9jdW1lbnQgZnJvbSBtb3Zpbmcgd2hpbGUgd2UgYXJlIGRyYWdnaW5nIGl0ZW1zIGFyb3VuZC5cbiAgICAgICAgICAgIC8vIHByZXZlbnREZWZhdWx0IG5lZWRzIHRvIGJlIGNhbGxlZCBpbiB0aGUgdG91Y2htb3ZlIGxpc3RlbmVyIGFuZCBuZXZlciBpbnNpZGUgdGhlXG4gICAgICAgICAgICAvLyB0b3VjaHN0YXJ0LCBiZWNhdXNlIHVzaW5nIHRvdWNoc3RhcnQgY2F1c2VzIHRoZSBjbGljayBldmVudCB0byBiZSBjYW5jZWxsZWQgb24gdG91Y2ggZGV2aWNlcy5cbiAgICAgICAgICAgIHsgdGFyZ2V0OiBkb2N1bWVudCwgdHlwZTogJ3RvdWNobW92ZScsIGxpc3RlbmVyOiBkb2N1bWVudFRvdWNoTW92ZSwgb3B0aW9uczogeyBwYXNzaXZlOiBmYWxzZSB9IH0sXG4gICAgICAgICAgICB7IHRhcmdldDogdGFyZ2V0LCB0eXBlOiAndG91Y2htb3ZlJywgbGlzdGVuZXI6IHRvdWNoTW92ZUV2ZW50LCBvcHRpb25zOiB7IHBhc3NpdmU6IHRydWUgfSB9LFxuICAgICAgICAgICAgeyB0YXJnZXQ6IHRhcmdldCwgdHlwZTogJ3RvdWNoZW5kJywgbGlzdGVuZXI6IHRvdWNoRW5kRXZlbnQsIG9wdGlvbnM6IHsgcGFzc2l2ZTogdHJ1ZSB9IH0sXG4gICAgICAgICAgICB7IHRhcmdldDogdGFyZ2V0LCB0eXBlOiAndG91Y2hjYW5jZWwnLCBsaXN0ZW5lcjogdG91Y2hFbmRFdmVudCwgb3B0aW9uczogeyBwYXNzaXZlOiB0cnVlIH0gfVxuICAgICAgICBdO1xuICAgICAgICAvLyB0ZW1wb3JhbGx5IGFkZCB0aGVzZSBsaXN0ZW5lcnMsIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIGRyYWdcbiAgICAgICAgdGhpcy5hZGRUZW1wb3JhcnlFdmVudHMoZXZlbnRzKTtcbiAgICAgICAgLy8gc2VlIGlmIHdlIHdhbnQgdG8gc3RhcnQgZHJhZ2dpbmcgc3RyYWlnaHQgYXdheVxuICAgICAgICBpZiAocGFyYW1zLmRyYWdTdGFydFBpeGVscyA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5vbkNvbW1vbk1vdmUodG91Y2gsIHRoaXMudG91Y2hTdGFydCwgcGFyYW1zLmVFbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZ2V0cyBjYWxsZWQgd2hlbmV2ZXIgbW91c2UgZG93biBvbiBhbnkgZHJhZyBzb3VyY2VcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUub25Nb3VzZURvd24gPSBmdW5jdGlvbiAocGFyYW1zLCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlID0gbW91c2VFdmVudDtcbiAgICAgICAgaWYgKHBhcmFtcy5za2lwTW91c2VFdmVudCAmJiBwYXJhbXMuc2tpcE1vdXNlRXZlbnQobW91c2VFdmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0aGVyZSBhcmUgdHdvIGVsZW1lbnRzIHdpdGggcGFyZW50IC8gY2hpbGQgcmVsYXRpb25zaGlwLCBhbmQgYm90aCBhcmUgZHJhZ2dhYmxlLFxuICAgICAgICAvLyB3aGVuIHdlIGRyYWcgdGhlIGNoaWxkLCB3ZSBzaG91bGQgTk9UIGRyYWcgdGhlIHBhcmVudC4gYW4gZXhhbXBsZSBvZiB0aGlzIGlzIHJvdyBtb3ZpbmdcbiAgICAgICAgLy8gYW5kIHJhbmdlIHNlbGVjdGlvbiAtIHJvdyBtb3Zpbmcgc2hvdWxkIGdldCBwcmVmZXJlbmNlIHdoZW4gdXNlIGRyYWdzIHRoZSByb3dEcmFnIGNvbXBvbmVudC5cbiAgICAgICAgaWYgKGUuX2FscmVhZHlQcm9jZXNzZWRCeURyYWdTZXJ2aWNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZS5fYWxyZWFkeVByb2Nlc3NlZEJ5RHJhZ1NlcnZpY2UgPSB0cnVlO1xuICAgICAgICAvLyBvbmx5IGludGVyZXN0ZWQgaW4gbGVmdCBidXR0b24gY2xpY2tzXG4gICAgICAgIGlmIChtb3VzZUV2ZW50LmJ1dHRvbiAhPT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3VycmVudERyYWdQYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIHRoaXMuZHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5tb3VzZVN0YXJ0RXZlbnQgPSBtb3VzZUV2ZW50O1xuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgdmFyIG1vdXNlTW92ZUV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7IHJldHVybiBfdGhpcy5vbk1vdXNlTW92ZShldmVudCwgcGFyYW1zLmVFbGVtZW50KTsgfTtcbiAgICAgICAgdmFyIG1vdXNlVXBFdmVudCA9IGZ1bmN0aW9uIChldmVudCkgeyByZXR1cm4gX3RoaXMub25Nb3VzZVVwKGV2ZW50LCBwYXJhbXMuZUVsZW1lbnQpOyB9O1xuICAgICAgICB2YXIgY29udGV4dEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7IHJldHVybiBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyB9O1xuICAgICAgICB2YXIgdGFyZ2V0ID0gZURvY3VtZW50O1xuICAgICAgICB2YXIgZXZlbnRzID0gW1xuICAgICAgICAgICAgeyB0YXJnZXQ6IHRhcmdldCwgdHlwZTogJ21vdXNlbW92ZScsIGxpc3RlbmVyOiBtb3VzZU1vdmVFdmVudCB9LFxuICAgICAgICAgICAgeyB0YXJnZXQ6IHRhcmdldCwgdHlwZTogJ21vdXNldXAnLCBsaXN0ZW5lcjogbW91c2VVcEV2ZW50IH0sXG4gICAgICAgICAgICB7IHRhcmdldDogdGFyZ2V0LCB0eXBlOiAnY29udGV4dG1lbnUnLCBsaXN0ZW5lcjogY29udGV4dEV2ZW50IH1cbiAgICAgICAgXTtcbiAgICAgICAgLy8gdGVtcG9yYWxseSBhZGQgdGhlc2UgbGlzdGVuZXJzLCBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSBkcmFnXG4gICAgICAgIHRoaXMuYWRkVGVtcG9yYXJ5RXZlbnRzKGV2ZW50cyk7XG4gICAgICAgIC8vc2VlIGlmIHdlIHdhbnQgdG8gc3RhcnQgZHJhZ2dpbmcgc3RyYWlnaHQgYXdheVxuICAgICAgICBpZiAocGFyYW1zLmRyYWdTdGFydFBpeGVscyA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5vbk1vdXNlTW92ZShtb3VzZUV2ZW50LCBwYXJhbXMuZUVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUuYWRkVGVtcG9yYXJ5RXZlbnRzID0gZnVuY3Rpb24gKGV2ZW50cykge1xuICAgICAgICBldmVudHMuZm9yRWFjaChmdW5jdGlvbiAoY3VycmVudEV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgdGFyZ2V0ID0gY3VycmVudEV2ZW50LnRhcmdldCwgdHlwZSA9IGN1cnJlbnRFdmVudC50eXBlLCBsaXN0ZW5lciA9IGN1cnJlbnRFdmVudC5saXN0ZW5lciwgb3B0aW9ucyA9IGN1cnJlbnRFdmVudC5vcHRpb25zO1xuICAgICAgICAgICAgdGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIsIG9wdGlvbnMpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5kcmFnRW5kRnVuY3Rpb25zLnB1c2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZXZlbnRzLmZvckVhY2goZnVuY3Rpb24gKGN1cnJlbnRFdmVudCkge1xuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSBjdXJyZW50RXZlbnQudGFyZ2V0LCB0eXBlID0gY3VycmVudEV2ZW50LnR5cGUsIGxpc3RlbmVyID0gY3VycmVudEV2ZW50Lmxpc3RlbmVyLCBvcHRpb25zID0gY3VycmVudEV2ZW50Lm9wdGlvbnM7XG4gICAgICAgICAgICAgICAgdGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIsIG9wdGlvbnMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gcmV0dXJucyB0cnVlIGlmIHRoZSBldmVudCBpcyBjbG9zZSB0byB0aGUgb3JpZ2luYWwgZXZlbnQgYnkgWCBwaXhlbHMgZWl0aGVyIHZlcnRpY2FsbHkgb3IgaG9yaXpvbnRhbGx5LlxuICAgIC8vIHdlIG9ubHkgc3RhcnQgZHJhZ2dpbmcgYWZ0ZXIgWCBwaXhlbHMgc28gdGhpcyBhbGxvd3MgdXMgdG8ga25vdyBpZiB3ZSBzaG91bGQgc3RhcnQgZHJhZ2dpbmcgeWV0LlxuICAgIERyYWdTZXJ2aWNlLnByb3RvdHlwZS5pc0V2ZW50TmVhclN0YXJ0RXZlbnQgPSBmdW5jdGlvbiAoY3VycmVudEV2ZW50LCBzdGFydEV2ZW50KSB7XG4gICAgICAgIC8vIGJ5IGRlZmF1bHQsIHdlIHdhaXQgNCBwaXhlbHMgYmVmb3JlIHN0YXJ0aW5nIHRoZSBkcmFnXG4gICAgICAgIHZhciBkcmFnU3RhcnRQaXhlbHMgPSB0aGlzLmN1cnJlbnREcmFnUGFyYW1zLmRyYWdTdGFydFBpeGVscztcbiAgICAgICAgdmFyIHJlcXVpcmVkUGl4ZWxEaWZmID0gZXhpc3RzKGRyYWdTdGFydFBpeGVscykgPyBkcmFnU3RhcnRQaXhlbHMgOiA0O1xuICAgICAgICByZXR1cm4gYXJlRXZlbnRzTmVhcihjdXJyZW50RXZlbnQsIHN0YXJ0RXZlbnQsIHJlcXVpcmVkUGl4ZWxEaWZmKTtcbiAgICB9O1xuICAgIERyYWdTZXJ2aWNlLnByb3RvdHlwZS5nZXRGaXJzdEFjdGl2ZVRvdWNoID0gZnVuY3Rpb24gKHRvdWNoTGlzdCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRvdWNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHRvdWNoTGlzdFtpXS5pZGVudGlmaWVyID09PSB0aGlzLnRvdWNoU3RhcnQuaWRlbnRpZmllcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b3VjaExpc3RbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUub25Db21tb25Nb3ZlID0gZnVuY3Rpb24gKGN1cnJlbnRFdmVudCwgc3RhcnRFdmVudCwgZWwpIHtcbiAgICAgICAgaWYgKCF0aGlzLmRyYWdnaW5nKSB7XG4gICAgICAgICAgICAvLyBpZiBtb3VzZSBoYXNuJ3QgdHJhdmVsbGVkIGZyb20gdGhlIHN0YXJ0IHBvc2l0aW9uIGVub3VnaCwgZG8gbm90aGluZ1xuICAgICAgICAgICAgaWYgKCF0aGlzLmRyYWdnaW5nICYmIHRoaXMuaXNFdmVudE5lYXJTdGFydEV2ZW50KGN1cnJlbnRFdmVudCwgc3RhcnRFdmVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBldmVudF8xID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9EUkFHX1NUQVJURUQsXG4gICAgICAgICAgICAgICAgdGFyZ2V0OiBlbFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnRfMSk7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnREcmFnUGFyYW1zLm9uRHJhZ1N0YXJ0KHN0YXJ0RXZlbnQpO1xuICAgICAgICAgICAgLy8gd2UgbmVlZCBPTkUgZHJhZyBhY3Rpb24gYXQgdGhlIHN0YXJ0RXZlbnQsIHNvIHRoYXQgd2UgYXJlIGd1YXJhbnRlZWQgdGhlIGRyb3AgdGFyZ2V0XG4gICAgICAgICAgICAvLyBhdCB0aGUgc3RhcnQgZ2V0cyBub3RpZmllZC4gdGhpcyBpcyBiZWNhdXNlIHRoZSBkcmFnIGNhbiBzdGFydCBvdXRzaWRlIG9mIHRoZSBlbGVtZW50XG4gICAgICAgICAgICAvLyB0aGF0IHN0YXJ0ZWQgaXQsIGFzIHRoZSBtb3VzZSBpcyBhbGxvd2VkIGRyYWcgYXdheSBmcm9tIHRoZSBtb3VzZSBkb3duIGJlZm9yZSBpdCdzXG4gICAgICAgICAgICAvLyBjb25zaWRlcmVkIGEgZHJhZyAodGhlIGlzRXZlbnROZWFyU3RhcnRFdmVudCgpIGFib3ZlKS4gaWYgd2UgZGlkbid0IGRvIHRoaXMsIHRoZW5cbiAgICAgICAgICAgIC8vIGl0IHdvdWxkIGJlIHBvc3NpYmxlIHRvIGNsaWNrIGEgY29sdW1uIGJ5IHRoZSBlZGdlLCB0aGVuIGRyYWcgb3V0c2lkZSBvZiB0aGUgZHJvcCB6b25lXG4gICAgICAgICAgICAvLyBpbiBsZXNzIHRoYW4gNCBwaXhlbHMgYW5kIHRoZSBkcmFnIG9mZmljaWFsbHkgc3RhcnRzIG91dHNpZGUgb2YgdGhlIGhlYWRlciBidXQgdGhlIGhlYWRlclxuICAgICAgICAgICAgLy8gd291bGRuJ3QgYmUgbm90aWZpZWQgb2YgdGhlIGRyYWdnaW5nLlxuICAgICAgICAgICAgdGhpcy5jdXJyZW50RHJhZ1BhcmFtcy5vbkRyYWdnaW5nKHN0YXJ0RXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3VycmVudERyYWdQYXJhbXMub25EcmFnZ2luZyhjdXJyZW50RXZlbnQpO1xuICAgIH07XG4gICAgRHJhZ1NlcnZpY2UucHJvdG90eXBlLm9uVG91Y2hNb3ZlID0gZnVuY3Rpb24gKHRvdWNoRXZlbnQsIGVsKSB7XG4gICAgICAgIHZhciB0b3VjaCA9IHRoaXMuZ2V0Rmlyc3RBY3RpdmVUb3VjaCh0b3VjaEV2ZW50LnRvdWNoZXMpO1xuICAgICAgICBpZiAoIXRvdWNoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhpcy5fX19zdGF0dXNQYW5lbC5zZXRJbmZvVGV4dChNYXRoLnJhbmRvbSgpICsgJyBvblRvdWNoTW92ZSBwcmV2ZW50RGVmYXVsdCBzdG9wUHJvcGFnYXRpb24nKTtcbiAgICAgICAgdGhpcy5vbkNvbW1vbk1vdmUodG91Y2gsIHRoaXMudG91Y2hTdGFydCwgZWwpO1xuICAgIH07XG4gICAgLy8gb25seSBnZXRzIGNhbGxlZCBhZnRlciBhIG1vdXNlIGRvd24gLSBhcyB0aGlzIGlzIG9ubHkgYWRkZWQgYWZ0ZXIgbW91c2VEb3duXG4gICAgLy8gYW5kIGlzIHJlbW92ZWQgd2hlbiBtb3VzZVVwIGhhcHBlbnNcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUub25Nb3VzZU1vdmUgPSBmdW5jdGlvbiAobW91c2VFdmVudCwgZWwpIHtcbiAgICAgICAgLy8gd2hlbiBgaXNFbmFibGVDZWxsVGV4dFNlbGVjdGAgaXMgYHRydWVgLCB3ZSBuZWVkIHRvIHByZXZlbnREZWZhdWx0IG9uIG1vdXNlTW92ZVxuICAgICAgICAvLyB0byBhdm9pZCB0aGUgZ3JpZCB0ZXh0IGJlaW5nIHNlbGVjdGVkIHdoaWxlIGRyYWdnaW5nIGNvbXBvbmVudHMuXG4gICAgICAgIC8vIE5vdGU6IFNhZmFyaSBhbHNvIGhhcyBhbiBpc3N1ZSwgd2hlcmUgYHVzZXItc2VsZWN0OiBub25lYCBpcyBub3QgYmVpbmcgcmVzcGVjdGVkLlxuICAgICAgICBpZiAoKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlQ2VsbFRleHRTZWxlY3QoKSB8fCBpc0Jyb3dzZXJTYWZhcmkoKSkgJiZcbiAgICAgICAgICAgIC8vIFRoZSBldmVudCB0eXBlIGNhbiBiZSBgbW91c2Vkb3duYCB3aGVuIGBkcmFnU3RhcnRQaXhlbHM9MGBcbiAgICAgICAgICAgIC8vIHdlIHNob3VsZCBvbmx5IHByZXZlbnREZWZhdWx0IG9uIGBtb3VzZW1vdmVgLlxuICAgICAgICAgICAgbW91c2VFdmVudC50eXBlID09PSAnbW91c2Vtb3ZlJyAmJlxuICAgICAgICAgICAgbW91c2VFdmVudC5jYW5jZWxhYmxlICYmXG4gICAgICAgICAgICB0aGlzLm1vdXNlRXZlbnRTZXJ2aWNlLmlzRXZlbnRGcm9tVGhpc0dyaWQobW91c2VFdmVudCkgJiZcbiAgICAgICAgICAgIC8vIHdlIHNob3VsZCBub3QgcHJldmVudCBtb3VzZU1vdmUgd2hlbiBhYm92ZSBhIGZvcm0gZmllbGRcbiAgICAgICAgICAgIC8vIGFzIHRoYXQgd291bGQgcHJldmVudCB0aGUgdGV4dCBpbiB0aGUgZmllbGQgZnJvbSBiZWluZyBzZWxlY3RlZFxuICAgICAgICAgICAgIXRoaXMuaXNPdmVyRm9ybUZpZWxkRWxlbWVudChtb3VzZUV2ZW50KSkge1xuICAgICAgICAgICAgbW91c2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub25Db21tb25Nb3ZlKG1vdXNlRXZlbnQsIHRoaXMubW91c2VTdGFydEV2ZW50LCBlbCk7XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUuaXNPdmVyRm9ybUZpZWxkRWxlbWVudCA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIHZhciBfYSwgX2I7XG4gICAgICAgIHZhciBlbCA9IG1vdXNlRXZlbnQudGFyZ2V0O1xuICAgICAgICB2YXIgdGFnTmFtZSA9IChfYSA9IGVsKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudGFnTmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICByZXR1cm4gISEoKF9iID0gdGFnTmFtZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLm1hdGNoKCdeYSR8dGV4dGFyZWF8aW5wdXR8c2VsZWN0fGJ1dHRvbicpKTtcbiAgICB9O1xuICAgIERyYWdTZXJ2aWNlLnByb3RvdHlwZS5vblRvdWNoVXAgPSBmdW5jdGlvbiAodG91Y2hFdmVudCwgZWwpIHtcbiAgICAgICAgdmFyIHRvdWNoID0gdGhpcy5nZXRGaXJzdEFjdGl2ZVRvdWNoKHRvdWNoRXZlbnQuY2hhbmdlZFRvdWNoZXMpO1xuICAgICAgICAvLyBpIGhhdmVuJ3Qgd29ya2VkIHRoaXMgb3V0IHlldCwgYnV0IHRoZXJlIGlzIG5vIG1hdGNoaW5nIHRvdWNoXG4gICAgICAgIC8vIHdoZW4gd2UgZ2V0IHRoZSB0b3VjaCB1cCBldmVudC4gdG8gZ2V0IGFyb3VuZCB0aGlzLCB3ZSBzd2FwIGluXG4gICAgICAgIC8vIHRoZSBsYXN0IHRvdWNoLiB0aGlzIGlzIGEgaGFjayB0byAnZ2V0IGl0IHdvcmtpbmcnIHdoaWxlIHdlXG4gICAgICAgIC8vIGZpZ3VyZSBvdXQgd2hhdCdzIGdvaW5nIG9uLCB3aHkgd2UgYXJlIG5vdCBnZXR0aW5nIGEgdG91Y2ggaW5cbiAgICAgICAgLy8gY3VycmVudCBldmVudC5cbiAgICAgICAgaWYgKCF0b3VjaCkge1xuICAgICAgICAgICAgdG91Y2ggPSB0aGlzLnRvdWNoTGFzdFRpbWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgbW91c2Ugd2FzIGxlZnQgdXAgYmVmb3JlIHdlIHN0YXJ0ZWQgdG8gbW92ZSwgdGhlbiB0aGlzIGlzIGEgdGFwLlxuICAgICAgICAvLyB3ZSBjaGVjayB0aGlzIGJlZm9yZSBvblVwQ29tbW9uIGFzIG9uVXBDb21tb24gcmVzZXRzIHRoZSBkcmFnZ2luZ1xuICAgICAgICAvLyBsZXQgdGFwID0gIXRoaXMuZHJhZ2dpbmc7XG4gICAgICAgIC8vIGxldCB0YXBUYXJnZXQgPSB0aGlzLmN1cnJlbnREcmFnUGFyYW1zLmVFbGVtZW50O1xuICAgICAgICB0aGlzLm9uVXBDb21tb24odG91Y2gsIGVsKTtcbiAgICAgICAgLy8gaWYgdGFwLCB0ZWxsIHVzZXJcbiAgICAgICAgLy8gY29uc29sZS5sb2coYCR7TWF0aC5yYW5kb20oKX0gdGFwID0gJHt0YXB9YCk7XG4gICAgICAgIC8vIGlmICh0YXApIHtcbiAgICAgICAgLy8gICAgIHRhcFRhcmdldC5jbGljaygpO1xuICAgICAgICAvLyB9XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUub25Nb3VzZVVwID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQsIGVsKSB7XG4gICAgICAgIHRoaXMub25VcENvbW1vbihtb3VzZUV2ZW50LCBlbCk7XG4gICAgfTtcbiAgICBEcmFnU2VydmljZS5wcm90b3R5cGUub25VcENvbW1vbiA9IGZ1bmN0aW9uIChldmVudE9yVG91Y2gsIGVsKSB7XG4gICAgICAgIGlmICh0aGlzLmRyYWdnaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnREcmFnUGFyYW1zLm9uRHJhZ1N0b3AoZXZlbnRPclRvdWNoKTtcbiAgICAgICAgICAgIHZhciBldmVudF8yID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9EUkFHX1NUT1BQRUQsXG4gICAgICAgICAgICAgICAgdGFyZ2V0OiBlbFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnRfMik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tb3VzZVN0YXJ0RXZlbnQgPSBudWxsO1xuICAgICAgICB0aGlzLnRvdWNoU3RhcnQgPSBudWxsO1xuICAgICAgICB0aGlzLnRvdWNoTGFzdFRpbWUgPSBudWxsO1xuICAgICAgICB0aGlzLmN1cnJlbnREcmFnUGFyYW1zID0gbnVsbDtcbiAgICAgICAgdGhpcy5kcmFnRW5kRnVuY3Rpb25zLmZvckVhY2goZnVuY3Rpb24gKGZ1bmMpIHsgcmV0dXJuIGZ1bmMoKTsgfSk7XG4gICAgICAgIHRoaXMuZHJhZ0VuZEZ1bmN0aW9ucy5sZW5ndGggPSAwO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxVihbXG4gICAgICAgIEF1dG93aXJlZCgnbG9nZ2VyRmFjdG9yeScpXG4gICAgXSwgRHJhZ1NlcnZpY2UucHJvdG90eXBlLCBcImxvZ2dlckZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFWKFtcbiAgICAgICAgQXV0b3dpcmVkKCdtb3VzZUV2ZW50U2VydmljZScpXG4gICAgXSwgRHJhZ1NlcnZpY2UucHJvdG90eXBlLCBcIm1vdXNlRXZlbnRTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxVihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBEcmFnU2VydmljZS5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJDFWKFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIERyYWdTZXJ2aWNlLnByb3RvdHlwZSwgXCJyZW1vdmVBbGxMaXN0ZW5lcnNcIiwgbnVsbCk7XG4gICAgRHJhZ1NlcnZpY2UgPSBfX2RlY29yYXRlJDFWKFtcbiAgICAgICAgQmVhbignZHJhZ1NlcnZpY2UnKVxuICAgIF0sIERyYWdTZXJ2aWNlKTtcbiAgICByZXR1cm4gRHJhZ1NlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMjYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiQ3ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiQ3ID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiQ3LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fZGVjb3JhdGUkMVUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBGaWx0ZXJNYW5hZ2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyNihGaWx0ZXJNYW5hZ2VyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEZpbHRlck1hbmFnZXIoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5hbGxDb2x1bW5GaWx0ZXJzID0gbmV3IE1hcCgpO1xuICAgICAgICBfdGhpcy5hY3RpdmVBZ2dyZWdhdGVGaWx0ZXJzID0gW107XG4gICAgICAgIF90aGlzLmFjdGl2ZUNvbHVtbkZpbHRlcnMgPSBbXTtcbiAgICAgICAgX3RoaXMucXVpY2tGaWx0ZXIgPSBudWxsO1xuICAgICAgICBfdGhpcy5xdWlja0ZpbHRlclBhcnRzID0gbnVsbDtcbiAgICAgICAgLy8gdGhpcyBpcyB0cnVlIHdoZW4gdGhlIGdyaWQgaXMgcHJvY2Vzc2luZyB0aGUgZmlsdGVyIGNoYW5nZS4gdGhpcyBpcyB1c2VkIGJ5IHRoZSBjZWxsIGNvbXBzLCBzbyB0aGF0IHRoZXlcbiAgICAgICAgLy8gZG9uJ3QgZmxhc2ggd2hlbiBkYXRhIGNoYW5nZXMgZHVlIHRvIGZpbHRlciBjaGFuZ2VzLiB0aGVyZSBpcyBubyBuZWVkIHRvIGZsYXNoIHdoZW4gZmlsdGVyIGNoYW5nZXMgYXMgdGhlXG4gICAgICAgIC8vIHVzZXIgaXMgaW4gY29udHJvbCwgc28gZG9lc24ndCBtYWtlIHNlbnNlIHRvIHNob3cgZmxhc2hpbmcgY2hhbmdlcy4gZm9yIGV4YW1wbGUsIGdvIHRvIG1haW4gZGVtbyB3aGVyZVxuICAgICAgICAvLyB0aGlzIGZlYXR1cmUgaXMgdHVybmVkIG9mZiAoaGFjayBjb2RlIHRvIGFsd2F5cyByZXR1cm4gZmFsc2UgZm9yIGlzU3VwcHJlc3NGbGFzaGluZ0NlbGxzQmVjYXVzZUZpbHRlcmluZygpLCBwdXQgaW4pXG4gICAgICAgIC8vIDEwMCwwMDAgcm93cyBhbmQgZ3JvdXAgYnkgY291bnRyeS4gdGhlbiBkbyBzb21lIGZpbHRlcmluZy4gYWxsIHRoZSBjZWxscyBmbGFzaCwgd2hpY2ggaXMgc2lsbHkuXG4gICAgICAgIF90aGlzLnByb2Nlc3NpbmdGaWx0ZXJDaGFuZ2UgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBGaWx0ZXJNYW5hZ2VyXzEgPSBGaWx0ZXJNYW5hZ2VyO1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfR1JJRF9DT0xVTU5TX0NIQU5HRUQsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uQ29sdW1uc0NoYW5nZWQoKTsgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1ZBTFVFX0NIQU5HRUQsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnJlZnJlc2hGaWx0ZXJzRm9yQWdncmVnYXRpb25zKCk7IH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5yZWZyZXNoRmlsdGVyc0ZvckFnZ3JlZ2F0aW9ucygpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUElWT1RfTU9ERV9DSEFOR0VELCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5yZWZyZXNoRmlsdGVyc0ZvckFnZ3JlZ2F0aW9ucygpOyB9KTtcbiAgICAgICAgdGhpcy5xdWlja0ZpbHRlciA9IHRoaXMucGFyc2VRdWlja0ZpbHRlcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRRdWlja0ZpbHRlclRleHQoKSk7XG4gICAgICAgIHRoaXMuc2V0UXVpY2tGaWx0ZXJQYXJ0cygpO1xuICAgICAgICB0aGlzLmFsbG93U2hvd0NoYW5nZUFmdGVyRmlsdGVyID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNBbGxvd1Nob3dDaGFuZ2VBZnRlckZpbHRlcigpO1xuICAgICAgICB0aGlzLmV4dGVybmFsRmlsdGVyUHJlc2VudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRXh0ZXJuYWxGaWx0ZXJQcmVzZW50KCk7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5zZXRRdWlja0ZpbHRlclBhcnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnF1aWNrRmlsdGVyUGFydHMgPSB0aGlzLnF1aWNrRmlsdGVyID8gdGhpcy5xdWlja0ZpbHRlci5zcGxpdCgnICcpIDogbnVsbDtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLnNldEZpbHRlck1vZGVsID0gZnVuY3Rpb24gKG1vZGVsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBhbGxQcm9taXNlcyA9IFtdO1xuICAgICAgICB2YXIgcHJldmlvdXNNb2RlbCA9IHRoaXMuZ2V0RmlsdGVyTW9kZWwoKTtcbiAgICAgICAgaWYgKG1vZGVsKSB7XG4gICAgICAgICAgICAvLyBtYXJrIHRoZSBmaWx0ZXJzIGFzIHdlIHNldCB0aGVtLCBzbyBhbnkgYWN0aXZlIGZpbHRlcnMgbGVmdCBvdmVyIHdlIHN0b3BcbiAgICAgICAgICAgIHZhciBtb2RlbEtleXNfMSA9IGNvbnZlcnRUb1NldChPYmplY3Qua2V5cyhtb2RlbCkpO1xuICAgICAgICAgICAgdGhpcy5hbGxDb2x1bW5GaWx0ZXJzLmZvckVhY2goZnVuY3Rpb24gKGZpbHRlcldyYXBwZXIsIGNvbElkKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld01vZGVsID0gbW9kZWxbY29sSWRdO1xuICAgICAgICAgICAgICAgIGFsbFByb21pc2VzLnB1c2goX3RoaXMuc2V0TW9kZWxPbkZpbHRlcldyYXBwZXIoZmlsdGVyV3JhcHBlci5maWx0ZXJQcm9taXNlLCBuZXdNb2RlbCkpO1xuICAgICAgICAgICAgICAgIG1vZGVsS2V5c18xLmRlbGV0ZShjb2xJZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIGF0IHRoaXMgcG9pbnQsIHByb2Nlc3NlZEZpZWxkcyBjb250YWlucyBkYXRhIGZvciB3aGljaCB3ZSBkb24ndCBoYXZlIGEgZmlsdGVyIHdvcmtpbmcgeWV0XG4gICAgICAgICAgICBtb2RlbEtleXNfMS5mb3JFYWNoKGZ1bmN0aW9uIChjb2xJZCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBfdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5Q29sdW1uKGNvbElkKSB8fCBfdGhpcy5jb2x1bW5Nb2RlbC5nZXRHcmlkQ29sdW1uKGNvbElkKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNldEZpbHRlck1vZGVsKCkgLSBubyBjb2x1bW4gZm91bmQgZm9yIGNvbElkOiAnICsgY29sSWQpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghY29sdW1uLmlzRmlsdGVyQWxsb3dlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2V0RmlsdGVyTW9kZWwoKSAtIHVuYWJsZSB0byBmdWxseSBhcHBseSBtb2RlbCwgZmlsdGVyaW5nIGRpc2FibGVkIGZvciBjb2xJZDogJyArIGNvbElkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZmlsdGVyV3JhcHBlciA9IF90aGlzLmdldE9yQ3JlYXRlRmlsdGVyV3JhcHBlcihjb2x1bW4sICdOT19VSScpO1xuICAgICAgICAgICAgICAgIGlmICghZmlsdGVyV3JhcHBlcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHLUdyaWQ6IHNldEZpbHRlck1vZGVsKCkgLSB1bmFibGUgdG8gZnVsbHkgYXBwbHkgbW9kZWwsIHVuYWJsZSB0byBjcmVhdGUgZmlsdGVyIGZvciBjb2xJZDogJyArIGNvbElkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhbGxQcm9taXNlcy5wdXNoKF90aGlzLnNldE1vZGVsT25GaWx0ZXJXcmFwcGVyKGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZSwgbW9kZWxbY29sSWRdKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYWxsQ29sdW1uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uIChmaWx0ZXJXcmFwcGVyKSB7XG4gICAgICAgICAgICAgICAgYWxsUHJvbWlzZXMucHVzaChfdGhpcy5zZXRNb2RlbE9uRmlsdGVyV3JhcHBlcihmaWx0ZXJXcmFwcGVyLmZpbHRlclByb21pc2UsIG51bGwpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIEFnUHJvbWlzZS5hbGwoYWxsUHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRNb2RlbCA9IF90aGlzLmdldEZpbHRlck1vZGVsKCk7XG4gICAgICAgICAgICB2YXIgY29sdW1ucyA9IFtdO1xuICAgICAgICAgICAgX3RoaXMuYWxsQ29sdW1uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uIChmaWx0ZXJXcmFwcGVyLCBjb2xJZCkge1xuICAgICAgICAgICAgICAgIHZhciBiZWZvcmUgPSBwcmV2aW91c01vZGVsID8gcHJldmlvdXNNb2RlbFtjb2xJZF0gOiBudWxsO1xuICAgICAgICAgICAgICAgIHZhciBhZnRlciA9IGN1cnJlbnRNb2RlbCA/IGN1cnJlbnRNb2RlbFtjb2xJZF0gOiBudWxsO1xuICAgICAgICAgICAgICAgIGlmICghXy5qc29uRXF1YWxzKGJlZm9yZSwgYWZ0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbnMucHVzaChmaWx0ZXJXcmFwcGVyLmNvbHVtbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoY29sdW1ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMub25GaWx0ZXJDaGFuZ2VkKHsgY29sdW1uczogY29sdW1ucyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5zZXRNb2RlbE9uRmlsdGVyV3JhcHBlciA9IGZ1bmN0aW9uIChmaWx0ZXJQcm9taXNlLCBuZXdNb2RlbCkge1xuICAgICAgICByZXR1cm4gbmV3IEFnUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgZmlsdGVyUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChmaWx0ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGZpbHRlci5zZXRNb2RlbCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGZpbHRlciBtaXNzaW5nIHNldE1vZGVsIG1ldGhvZCwgd2hpY2ggaXMgbmVlZGVkIGZvciBzZXRGaWx0ZXJNb2RlbCcpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIChmaWx0ZXIuc2V0TW9kZWwobmV3TW9kZWwpIHx8IEFnUHJvbWlzZS5yZXNvbHZlKCkpLnRoZW4oZnVuY3Rpb24gKCkgeyByZXR1cm4gcmVzb2x2ZSgpOyB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmdldEZpbHRlck1vZGVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIHRoaXMuYWxsQ29sdW1uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uIChmaWx0ZXJXcmFwcGVyLCBrZXkpIHtcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgdXNlciBjYW4gcHJvdmlkZSBmaWx0ZXJzLCB3ZSBwcm92aWRlIHVzZWZ1bCBlcnJvciBjaGVja2luZyBhbmQgbWVzc2FnZXNcbiAgICAgICAgICAgIHZhciBmaWx0ZXJQcm9taXNlID0gZmlsdGVyV3JhcHBlci5maWx0ZXJQcm9taXNlO1xuICAgICAgICAgICAgdmFyIGZpbHRlciA9IGZpbHRlclByb21pc2UucmVzb2x2ZU5vdyhudWxsLCBmdW5jdGlvbiAocHJvbWlzZUZpbHRlcikgeyByZXR1cm4gcHJvbWlzZUZpbHRlcjsgfSk7XG4gICAgICAgICAgICBpZiAoZmlsdGVyID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgZmlsdGVyLmdldE1vZGVsICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBmaWx0ZXIgQVBJIG1pc3NpbmcgZ2V0TW9kZWwgbWV0aG9kLCB3aGljaCBpcyBuZWVkZWQgZm9yIGdldEZpbHRlck1vZGVsJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG1vZGVsID0gZmlsdGVyLmdldE1vZGVsKCk7XG4gICAgICAgICAgICBpZiAoZXhpc3RzKG1vZGVsKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gbW9kZWw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuaXNDb2x1bW5GaWx0ZXJQcmVzZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmVDb2x1bW5GaWx0ZXJzLmxlbmd0aCA+IDA7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5pc0FnZ3JlZ2F0ZUZpbHRlclByZXNlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuYWN0aXZlQWdncmVnYXRlRmlsdGVycy5sZW5ndGg7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5pc0V4dGVybmFsRmlsdGVyUHJlc2VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXh0ZXJuYWxGaWx0ZXJQcmVzZW50O1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9BZ2dyZWdhdGVGaWx0ZXJzUGFzcyA9IGZ1bmN0aW9uIChub2RlLCBmaWx0ZXJUb1NraXApIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9Db2x1bW5GaWx0ZXJzUGFzcyhub2RlLCBmaWx0ZXJUb1NraXAsIHRydWUpO1xuICAgIH07XG4gICAgLy8gY2FsbGVkIGJ5OlxuICAgIC8vIDEpIG9uRmlsdGVyQ2hhbmdlZCgpXG4gICAgLy8gMikgb25OZXdSb3dzTG9hZGVkKClcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS51cGRhdGVBY3RpdmVGaWx0ZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFjdGl2ZUNvbHVtbkZpbHRlcnMubGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5hY3RpdmVBZ2dyZWdhdGVGaWx0ZXJzLmxlbmd0aCA9IDA7XG4gICAgICAgIHZhciBpc0ZpbHRlckFjdGl2ZSA9IGZ1bmN0aW9uIChmaWx0ZXIpIHtcbiAgICAgICAgICAgIGlmICghZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSAvLyB0aGlzIG5ldmVyIGhhcHBlbnMsIGluY2x1ZGluZyB0byBhdm9pZCBjb21waWxlIGVycm9yXG4gICAgICAgICAgICBpZiAoIWZpbHRlci5pc0ZpbHRlckFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogRmlsdGVyIGlzIG1pc3NpbmcgaXNGaWx0ZXJBY3RpdmUoKSBtZXRob2QnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmlsdGVyLmlzRmlsdGVyQWN0aXZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBncm91cEZpbHRlckVuYWJsZWQgPSAhIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEdyb3VwQWdnRmlsdGVyaW5nKCk7XG4gICAgICAgIHZhciBpc0FnZ0ZpbHRlciA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHZhciBpc1NlY29uZGFyeSA9ICFjb2x1bW4uaXNQcmltYXJ5KCk7XG4gICAgICAgICAgICAvLyB0aGUgb25seSBmaWx0ZXJzIHRoYXQgY2FuIGFwcGVhciBvbiBzZWNvbmRhcnkgY29sdW1ucyBhcmUgZ3JvdXBBZ2cgZmlsdGVyc1xuICAgICAgICAgICAgaWYgKGlzU2Vjb25kYXJ5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaXNTaG93aW5nUHJpbWFyeUNvbHVtbnMgPSAhX3RoaXMuY29sdW1uTW9kZWwuaXNQaXZvdEFjdGl2ZSgpO1xuICAgICAgICAgICAgdmFyIGlzVmFsdWVBY3RpdmUgPSBjb2x1bW4uaXNWYWx1ZUFjdGl2ZSgpO1xuICAgICAgICAgICAgLy8gcHJpbWFyeSBjb2x1bW5zIGFyZSBvbmx5IGV2ZXIgZ3JvdXBBZ2cgZmlsdGVycyBpZiBhKSB2YWx1ZSBpcyBhY3RpdmUgYW5kIGIpIHNob3dpbmcgcHJpbWFyeSBjb2x1bW5zXG4gICAgICAgICAgICBpZiAoIWlzVmFsdWVBY3RpdmUgfHwgIWlzU2hvd2luZ1ByaW1hcnlDb2x1bW5zKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZnJvbSBoZXJlIG9uIHdlIGtub3c6IGlzUHJpbWFyeT10cnVlLCBpc1ZhbHVlQWN0aXZlPXRydWUsIGlzU2hvd2luZ1ByaW1hcnlDb2x1bW5zPXRydWVcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90TW9kZSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gcHJpbWFyeSBjb2x1bW4gaXMgcHJldGVuZGluZyB0byBiZSBhIHBpdm90IGNvbHVtbiwgaWUgcGl2b3RNb2RlPXRydWUsIGJ1dCB3ZSBhcmVcbiAgICAgICAgICAgICAgICAvLyBzdGlsbCBzaG93aW5nIHByaW1hcnkgY29sdW1uc1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gd2UgYXJlIG5vdCBwaXZvdGluZywgc28gd2UgZ3JvdXBGaWx0ZXIgd2hlbiBpdCdzIGFuIGFnZyBjb2x1bW5cbiAgICAgICAgICAgICAgICByZXR1cm4gZ3JvdXBGaWx0ZXJFbmFibGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFsbENvbHVtbkZpbHRlcnMuZm9yRWFjaChmdW5jdGlvbiAoZmlsdGVyV3JhcHBlcikge1xuICAgICAgICAgICAgaWYgKGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZS5yZXNvbHZlTm93KGZhbHNlLCBpc0ZpbHRlckFjdGl2ZSkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmlsdGVyQ29tcCA9IGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZS5yZXNvbHZlTm93KG51bGwsIGZ1bmN0aW9uIChmaWx0ZXIpIHsgcmV0dXJuIGZpbHRlcjsgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzQWdnRmlsdGVyKGZpbHRlcldyYXBwZXIuY29sdW1uKSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5hY3RpdmVBZ2dyZWdhdGVGaWx0ZXJzLnB1c2goZmlsdGVyQ29tcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5hY3RpdmVDb2x1bW5GaWx0ZXJzLnB1c2goZmlsdGVyQ29tcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLnVwZGF0ZUZpbHRlckZsYWdJbkNvbHVtbnMgPSBmdW5jdGlvbiAoc291cmNlLCBhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKSB7XG4gICAgICAgIHRoaXMuYWxsQ29sdW1uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uIChmaWx0ZXJXcmFwcGVyKSB7XG4gICAgICAgICAgICB2YXIgaXNGaWx0ZXJBY3RpdmUgPSBmaWx0ZXJXcmFwcGVyLmZpbHRlclByb21pc2UucmVzb2x2ZU5vdyhmYWxzZSwgZnVuY3Rpb24gKGZpbHRlcikgeyByZXR1cm4gZmlsdGVyLmlzRmlsdGVyQWN0aXZlKCk7IH0pO1xuICAgICAgICAgICAgZmlsdGVyV3JhcHBlci5jb2x1bW4uc2V0RmlsdGVyQWN0aXZlKGlzRmlsdGVyQWN0aXZlLCBzb3VyY2UsIGFkZGl0aW9uYWxFdmVudEF0dHJpYnV0ZXMpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmlzQW55RmlsdGVyUHJlc2VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNRdWlja0ZpbHRlclByZXNlbnQoKSB8fCB0aGlzLmlzQ29sdW1uRmlsdGVyUHJlc2VudCgpIHx8IHRoaXMuaXNBZ2dyZWdhdGVGaWx0ZXJQcmVzZW50KCkgfHwgdGhpcy5pc0V4dGVybmFsRmlsdGVyUHJlc2VudCgpO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9Db2x1bW5GaWx0ZXJzUGFzcyA9IGZ1bmN0aW9uIChub2RlLCBmaWx0ZXJUb1NraXAsIHRhcmdldEFnZ3JlZ2F0ZXMpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBub2RlLmRhdGEsIGFnZ0RhdGEgPSBub2RlLmFnZ0RhdGE7XG4gICAgICAgIHZhciB0YXJnZXRlZEZpbHRlcnMgPSB0YXJnZXRBZ2dyZWdhdGVzID8gdGhpcy5hY3RpdmVBZ2dyZWdhdGVGaWx0ZXJzIDogdGhpcy5hY3RpdmVDb2x1bW5GaWx0ZXJzO1xuICAgICAgICB2YXIgdGFyZ2V0ZWREYXRhID0gdGFyZ2V0QWdncmVnYXRlcyA/IGFnZ0RhdGEgOiBkYXRhO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRhcmdldGVkRmlsdGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZpbHRlciA9IHRhcmdldGVkRmlsdGVyc1tpXTtcbiAgICAgICAgICAgIGlmIChmaWx0ZXIgPT0gbnVsbCB8fCBmaWx0ZXIgPT09IGZpbHRlclRvU2tpcCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBmaWx0ZXIuZG9lc0ZpbHRlclBhc3MgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHVzZXJzIGNhbiBkbyBjdXN0b20gZmlsdGVycywgZ2l2ZSBuaWNlIGVycm9yIG1lc3NhZ2VcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpbHRlciBpcyBtaXNzaW5nIG1ldGhvZCBkb2VzRmlsdGVyUGFzcycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFmaWx0ZXIuZG9lc0ZpbHRlclBhc3MoeyBub2RlOiBub2RlLCBkYXRhOiB0YXJnZXRlZERhdGEgfSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5wYXJzZVF1aWNrRmlsdGVyID0gZnVuY3Rpb24gKG5ld0ZpbHRlcikge1xuICAgICAgICBpZiAoIWV4aXN0cyhuZXdGaWx0ZXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxEZWZhdWx0KCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZCAtIFF1aWNrIGZpbHRlcmluZyBvbmx5IHdvcmtzIHdpdGggdGhlIENsaWVudC1TaWRlIFJvdyBNb2RlbCcpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ld0ZpbHRlci50b1VwcGVyQ2FzZSgpO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuc2V0UXVpY2tGaWx0ZXIgPSBmdW5jdGlvbiAobmV3RmlsdGVyKSB7XG4gICAgICAgIGlmIChuZXdGaWx0ZXIgIT0gbnVsbCAmJiB0eXBlb2YgbmV3RmlsdGVyICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZCAtIHNldFF1aWNrRmlsdGVyKCkgb25seSBzdXBwb3J0cyBzdHJpbmcgaW5wdXRzLCByZWNlaXZlZDogXCIgKyB0eXBlb2YgbmV3RmlsdGVyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyc2VkRmlsdGVyID0gdGhpcy5wYXJzZVF1aWNrRmlsdGVyKG5ld0ZpbHRlcik7XG4gICAgICAgIGlmICh0aGlzLnF1aWNrRmlsdGVyICE9PSBwYXJzZWRGaWx0ZXIpIHtcbiAgICAgICAgICAgIHRoaXMucXVpY2tGaWx0ZXIgPSBwYXJzZWRGaWx0ZXI7XG4gICAgICAgICAgICB0aGlzLnNldFF1aWNrRmlsdGVyUGFydHMoKTtcbiAgICAgICAgICAgIHRoaXMub25GaWx0ZXJDaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLnJlZnJlc2hGaWx0ZXJzRm9yQWdncmVnYXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNBZ2dGaWx0ZXJpbmcgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRHcm91cEFnZ0ZpbHRlcmluZygpO1xuICAgICAgICBpZiAoaXNBZ2dGaWx0ZXJpbmcpIHtcbiAgICAgICAgICAgIHRoaXMub25GaWx0ZXJDaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHNvbWV0aW1lcyAoZXNwZWNpYWxseSBpbiBSZWFjdCkgdGhlIGZpbHRlciBjYW4gY2FsbCBvbkZpbHRlckNoYW5nZWQgd2hlbiB3ZSBhcmUgaW4gdGhlIG1pZGRsZVxuICAgIC8vIG9mIGEgcmVuZGVyIGN5Y2xlLiB0aGlzIHdvdWxkIGJlIGJhZCwgc28gd2Ugd2FpdCBmb3IgcmVuZGVyIGN5Y2xlIHRvIGNvbXBsZXRlIHdoZW4gdGhpcyBoYXBwZW5zLlxuICAgIC8vIHRoaXMgaGFwcGVucyBpbiByZWFjdCB3aGVuIHdlIGNoYW5nZSBSZWFjdCBTdGF0ZSBpbiB0aGUgZ3JpZCAoZWcgc2V0dGluZyBSb3dDdHJsJ3MgaW4gUm93Q29udGFpbmVyKVxuICAgIC8vIHdoaWNoIHJlc3VsdHMgaW4gUmVhY3QgU3RhdGUgZ2V0dGluZyBhcHBsaWVkIGluIHRoZSBtYWluIGFwcGxpY2F0aW9uLCB0cmlnZ2VyaW5nIGEgdXNlRWZmZWN0KCkgdG9cbiAgICAvLyBiZSBraWNrZWQgb2ZmIGFkbiB0aGVuIHRoZSBhcHBsaWNhdGlvbiBjYWxsaW5nIHRoZSBncmlkJ3MgQVBJLiBpbiBBRy02NTU0LCB0aGUgY3VzdG9tIGZpbHRlciB3YXNcbiAgICAvLyBnZXR0aW5nIGl0J3MgdXNlRWZmZWN0KCkgdHJpZ2dlcmVkIGluIHRoaXMgd2F5LlxuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmNhbGxPbkZpbHRlckNoYW5nZWRPdXRzaWRlUmVuZGVyQ3ljbGUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChwYXJhbXMgPT09IHZvaWQgMCkgeyBwYXJhbXMgPSB7fTsgfVxuICAgICAgICB2YXIgYWN0aW9uID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25GaWx0ZXJDaGFuZ2VkKHBhcmFtcyk7IH07XG4gICAgICAgIGlmICh0aGlzLnJvd1JlbmRlcmVyLmlzUmVmcmVzaEluUHJvZ3Jlc3MoKSkge1xuICAgICAgICAgICAgc2V0VGltZW91dChhY3Rpb24sIDApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYWN0aW9uKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLm9uRmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PT0gdm9pZCAwKSB7IHBhcmFtcyA9IHt9OyB9XG4gICAgICAgIHZhciBmaWx0ZXJJbnN0YW5jZSA9IHBhcmFtcy5maWx0ZXJJbnN0YW5jZSwgYWRkaXRpb25hbEV2ZW50QXR0cmlidXRlcyA9IHBhcmFtcy5hZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzLCBjb2x1bW5zID0gcGFyYW1zLmNvbHVtbnM7XG4gICAgICAgIHRoaXMudXBkYXRlQWN0aXZlRmlsdGVycygpO1xuICAgICAgICB0aGlzLnVwZGF0ZUZpbHRlckZsYWdJbkNvbHVtbnMoJ2ZpbHRlckNoYW5nZWQnLCBhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKTtcbiAgICAgICAgdGhpcy5leHRlcm5hbEZpbHRlclByZXNlbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0V4dGVybmFsRmlsdGVyUHJlc2VudCgpO1xuICAgICAgICB0aGlzLmFsbENvbHVtbkZpbHRlcnMuZm9yRWFjaChmdW5jdGlvbiAoZmlsdGVyV3JhcHBlcikge1xuICAgICAgICAgICAgaWYgKCFmaWx0ZXJXcmFwcGVyLmZpbHRlclByb21pc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaWx0ZXJXcmFwcGVyLmZpbHRlclByb21pc2UudGhlbihmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZpbHRlciAmJiBmaWx0ZXIgIT09IGZpbHRlckluc3RhbmNlICYmIGZpbHRlci5vbkFueUZpbHRlckNoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyLm9uQW55RmlsdGVyQ2hhbmdlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGZpbHRlckNoYW5nZWRFdmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9GSUxURVJfQ0hBTkdFRCxcbiAgICAgICAgICAgIGNvbHVtbnM6IGNvbHVtbnMgfHwgW10sXG4gICAgICAgIH07XG4gICAgICAgIGlmIChhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICBtZXJnZURlZXAoZmlsdGVyQ2hhbmdlZEV2ZW50LCBhZGRpdGlvbmFsRXZlbnRBdHRyaWJ1dGVzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBiZWNhdXNlIGludGVybmFsIGV2ZW50cyBhcmUgbm90IGFzeW5jIGluIGFnLWdyaWQsIHdoZW4gdGhlIGRpc3BhdGNoRXZlbnRcbiAgICAgICAgLy8gbWV0aG9kIGNvbWVzIGJhY2ssIHdlIGtub3cgYWxsIGxpc3RlbmVycyBoYXZlIGZpbmlzaGVkIGV4ZWN1dGluZy5cbiAgICAgICAgdGhpcy5wcm9jZXNzaW5nRmlsdGVyQ2hhbmdlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChmaWx0ZXJDaGFuZ2VkRXZlbnQpO1xuICAgICAgICB0aGlzLnByb2Nlc3NpbmdGaWx0ZXJDaGFuZ2UgPSBmYWxzZTtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmlzU3VwcHJlc3NGbGFzaGluZ0NlbGxzQmVjYXVzZUZpbHRlcmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gaWYgdXNlciBoYXMgZWxlY3RlZCB0byBhbHdheXMgZmxhc2ggY2VsbCBjaGFuZ2VzLCB0aGVuIGFsd2F5cyByZXR1cm4gZmFsc2UsIG90aGVyd2lzZSB3ZSBzdXBwcmVzcyBmbGFzaGluZ1xuICAgICAgICAvLyBjaGFuZ2VzIHdoZW4gZmlsdGVyaW5nXG4gICAgICAgIHJldHVybiAhdGhpcy5hbGxvd1Nob3dDaGFuZ2VBZnRlckZpbHRlciAmJiB0aGlzLnByb2Nlc3NpbmdGaWx0ZXJDaGFuZ2U7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5pc1F1aWNrRmlsdGVyUHJlc2VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVpY2tGaWx0ZXIgIT09IG51bGw7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5kb2VzUm93UGFzc090aGVyRmlsdGVycyA9IGZ1bmN0aW9uIChmaWx0ZXJUb1NraXAsIG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9lc1Jvd1Bhc3NGaWx0ZXIoeyByb3dOb2RlOiBub2RlLCBmaWx0ZXJJbnN0YW5jZVRvU2tpcDogZmlsdGVyVG9Ta2lwIH0pO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9lc1Jvd1Bhc3NRdWlja0ZpbHRlck5vQ2FjaGUgPSBmdW5jdGlvbiAobm9kZSwgZmlsdGVyUGFydCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29sdW1ucyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsQ29sdW1uc0ZvclF1aWNrRmlsdGVyKCk7XG4gICAgICAgIHJldHVybiBjb2x1bW5zLnNvbWUoZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgdmFyIHBhcnQgPSBfdGhpcy5nZXRRdWlja0ZpbHRlclRleHRGb3JDb2x1bW4oY29sdW1uLCBub2RlKTtcbiAgICAgICAgICAgIHJldHVybiBleGlzdHMocGFydCkgJiYgcGFydC5pbmRleE9mKGZpbHRlclBhcnQpID49IDA7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9lc1Jvd1Bhc3NRdWlja0ZpbHRlckNhY2hlID0gZnVuY3Rpb24gKG5vZGUsIGZpbHRlclBhcnQpIHtcbiAgICAgICAgaWYgKCFub2RlLnF1aWNrRmlsdGVyQWdncmVnYXRlVGV4dCkge1xuICAgICAgICAgICAgdGhpcy5hZ2dyZWdhdGVSb3dGb3JRdWlja0ZpbHRlcihub2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbm9kZS5xdWlja0ZpbHRlckFnZ3JlZ2F0ZVRleHQuaW5kZXhPZihmaWx0ZXJQYXJ0KSA+PSAwO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9lc1Jvd1Bhc3NRdWlja0ZpbHRlciA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB1c2luZ0NhY2hlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNDYWNoZVF1aWNrRmlsdGVyKCk7XG4gICAgICAgIC8vIGVhY2ggcGFydCBtdXN0IHBhc3MsIGlmIGFueSBmYWlscywgdGhlbiB0aGUgd2hvbGUgZmlsdGVyIGZhaWxzXG4gICAgICAgIHJldHVybiB0aGlzLnF1aWNrRmlsdGVyUGFydHMuZXZlcnkoZnVuY3Rpb24gKHBhcnQpIHtcbiAgICAgICAgICAgIHJldHVybiB1c2luZ0NhY2hlID8gX3RoaXMuZG9lc1Jvd1Bhc3NRdWlja0ZpbHRlckNhY2hlKG5vZGUsIHBhcnQpIDogX3RoaXMuZG9lc1Jvd1Bhc3NRdWlja0ZpbHRlck5vQ2FjaGUobm9kZSwgcGFydCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9lc1Jvd1Bhc3NBZ2dyZWdhdGVGaWx0ZXJzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAodGhpcy5pc0FnZ3JlZ2F0ZUZpbHRlclByZXNlbnQoKSAmJiAhdGhpcy5kb0FnZ3JlZ2F0ZUZpbHRlcnNQYXNzKHBhcmFtcy5yb3dOb2RlLCBwYXJhbXMuZmlsdGVySW5zdGFuY2VUb1NraXApKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZ290IHRoaXMgZmFyLCBhbGwgZmlsdGVycyBwYXNzXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZG9lc1Jvd1Bhc3NGaWx0ZXIgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIC8vIHRoZSByb3cgbXVzdCBwYXNzIEFMTCBvZiB0aGUgZmlsdGVycywgc28gaWYgYW55IG9mIHRoZW0gZmFpbCxcbiAgICAgICAgLy8gd2UgcmV0dXJuIHRydWUuIHRoYXQgbWVhbnMgaWYgYSByb3cgcGFzc2VzIHRoZSBxdWljayBmaWx0ZXIsXG4gICAgICAgIC8vIGJ1dCBmYWlscyB0aGUgY29sdW1uIGZpbHRlciwgaXQgZmFpbHMgb3ZlcmFsbFxuICAgICAgICAvLyBmaXJzdCB1cCwgY2hlY2sgcXVpY2sgZmlsdGVyXG4gICAgICAgIGlmICh0aGlzLmlzUXVpY2tGaWx0ZXJQcmVzZW50KCkgJiYgIXRoaXMuZG9lc1Jvd1Bhc3NRdWlja0ZpbHRlcihwYXJhbXMucm93Tm9kZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBzZWNvbmRseSwgZ2l2ZSB0aGUgY2xpZW50IGEgY2hhbmNlIHRvIHJlamVjdCB0aGlzIHJvd1xuICAgICAgICBpZiAodGhpcy5pc0V4dGVybmFsRmlsdGVyUHJlc2VudCgpICYmICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5kb2VzRXh0ZXJuYWxGaWx0ZXJQYXNzKHBhcmFtcy5yb3dOb2RlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGxhc3RseSwgY2hlY2sgY29sdW1uIGZpbHRlclxuICAgICAgICBpZiAodGhpcy5pc0NvbHVtbkZpbHRlclByZXNlbnQoKSAmJiAhdGhpcy5kb0NvbHVtbkZpbHRlcnNQYXNzKHBhcmFtcy5yb3dOb2RlLCBwYXJhbXMuZmlsdGVySW5zdGFuY2VUb1NraXApKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZ290IHRoaXMgZmFyLCBhbGwgZmlsdGVycyBwYXNzXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZ2V0UXVpY2tGaWx0ZXJUZXh0Rm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbiwgbm9kZSkge1xuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLnZhbHVlU2VydmljZS5nZXRWYWx1ZShjb2x1bW4sIG5vZGUsIHRydWUpO1xuICAgICAgICB2YXIgY29sRGVmID0gY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICBpZiAoY29sRGVmLmdldFF1aWNrRmlsdGVyVGV4dCkge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgbm9kZTogbm9kZSxcbiAgICAgICAgICAgICAgICBkYXRhOiBub2RlLmRhdGEsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICAgICAgY29sRGVmOiBjb2xEZWYsXG4gICAgICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhbHVlID0gY29sRGVmLmdldFF1aWNrRmlsdGVyVGV4dChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBleGlzdHModmFsdWUpID8gdmFsdWUudG9TdHJpbmcoKS50b1VwcGVyQ2FzZSgpIDogbnVsbDtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmFnZ3JlZ2F0ZVJvd0ZvclF1aWNrRmlsdGVyID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHN0cmluZ1BhcnRzID0gW107XG4gICAgICAgIHZhciBjb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxDb2x1bW5zRm9yUXVpY2tGaWx0ZXIoKTtcbiAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHZhciBwYXJ0ID0gX3RoaXMuZ2V0UXVpY2tGaWx0ZXJUZXh0Rm9yQ29sdW1uKGNvbHVtbiwgbm9kZSk7XG4gICAgICAgICAgICBpZiAoZXhpc3RzKHBhcnQpKSB7XG4gICAgICAgICAgICAgICAgc3RyaW5nUGFydHMucHVzaChwYXJ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIG5vZGUucXVpY2tGaWx0ZXJBZ2dyZWdhdGVUZXh0ID0gc3RyaW5nUGFydHMuam9pbihGaWx0ZXJNYW5hZ2VyXzEuUVVJQ0tfRklMVEVSX1NFUEFSQVRPUik7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5vbk5ld1Jvd3NMb2FkZWQgPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgICAgIHRoaXMuYWxsQ29sdW1uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uIChmaWx0ZXJXcmFwcGVyKSB7XG4gICAgICAgICAgICBmaWx0ZXJXcmFwcGVyLmZpbHRlclByb21pc2UudGhlbihmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZpbHRlci5vbk5ld1Jvd3NMb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyLm9uTmV3Um93c0xvYWRlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy51cGRhdGVGaWx0ZXJGbGFnSW5Db2x1bW5zKHNvdXJjZSk7XG4gICAgICAgIHRoaXMudXBkYXRlQWN0aXZlRmlsdGVycygpO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuY3JlYXRlVmFsdWVHZXR0ZXIgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gX2Eubm9kZTtcbiAgICAgICAgICAgIHJldHVybiBfdGhpcy52YWx1ZVNlcnZpY2UuZ2V0VmFsdWUoY29sdW1uLCBub2RlLCB0cnVlKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmdldEZpbHRlckNvbXBvbmVudCA9IGZ1bmN0aW9uIChjb2x1bW4sIHNvdXJjZSwgY3JlYXRlSWZEb2VzTm90RXhpc3QpIHtcbiAgICAgICAgaWYgKGNyZWF0ZUlmRG9lc05vdEV4aXN0ID09PSB2b2lkIDApIHsgY3JlYXRlSWZEb2VzTm90RXhpc3QgPSB0cnVlOyB9XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgaWYgKGNyZWF0ZUlmRG9lc05vdEV4aXN0KSB7XG4gICAgICAgICAgICByZXR1cm4gKChfYSA9IHRoaXMuZ2V0T3JDcmVhdGVGaWx0ZXJXcmFwcGVyKGNvbHVtbiwgc291cmNlKSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmZpbHRlclByb21pc2UpIHx8IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZpbHRlcldyYXBwZXIgPSB0aGlzLmNhY2hlZEZpbHRlcihjb2x1bW4pO1xuICAgICAgICByZXR1cm4gZmlsdGVyV3JhcHBlciA/IGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZSA6IG51bGw7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5pc0ZpbHRlckFjdGl2ZSA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgdmFyIGZpbHRlcldyYXBwZXIgPSB0aGlzLmNhY2hlZEZpbHRlcihjb2x1bW4pO1xuICAgICAgICByZXR1cm4gISFmaWx0ZXJXcmFwcGVyICYmIGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZS5yZXNvbHZlTm93KGZhbHNlLCBmdW5jdGlvbiAoZmlsdGVyKSB7IHJldHVybiBmaWx0ZXIuaXNGaWx0ZXJBY3RpdmUoKTsgfSk7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5nZXRPckNyZWF0ZUZpbHRlcldyYXBwZXIgPSBmdW5jdGlvbiAoY29sdW1uLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKCFjb2x1bW4uaXNGaWx0ZXJBbGxvd2VkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmaWx0ZXJXcmFwcGVyID0gdGhpcy5jYWNoZWRGaWx0ZXIoY29sdW1uKTtcbiAgICAgICAgaWYgKCFmaWx0ZXJXcmFwcGVyKSB7XG4gICAgICAgICAgICBmaWx0ZXJXcmFwcGVyID0gdGhpcy5jcmVhdGVGaWx0ZXJXcmFwcGVyKGNvbHVtbiwgc291cmNlKTtcbiAgICAgICAgICAgIHRoaXMuYWxsQ29sdW1uRmlsdGVycy5zZXQoY29sdW1uLmdldENvbElkKCksIGZpbHRlcldyYXBwZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHNvdXJjZSAhPT0gJ05PX1VJJykge1xuICAgICAgICAgICAgdGhpcy5wdXRJbnRvR3VpKGZpbHRlcldyYXBwZXIsIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZpbHRlcldyYXBwZXI7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5jYWNoZWRGaWx0ZXIgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFsbENvbHVtbkZpbHRlcnMuZ2V0KGNvbHVtbi5nZXRDb2xJZCgpKTtcbiAgICB9O1xuICAgIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmNyZWF0ZUZpbHRlckluc3RhbmNlID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZGVmYXVsdEZpbHRlciA9IE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5TZXRGaWx0ZXJNb2R1bGUpID8gJ2FnU2V0Q29sdW1uRmlsdGVyJyA6ICdhZ1RleHRDb2x1bW5GaWx0ZXInO1xuICAgICAgICB2YXIgY29sRGVmID0gY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB2YXIgZmlsdGVySW5zdGFuY2U7XG4gICAgICAgIHZhciBwYXJhbXMgPSBfX2Fzc2lnbiQ3KF9fYXNzaWduJDcoe30sIHRoaXMuY3JlYXRlRmlsdGVyUGFyYW1zKGNvbHVtbiwgY29sRGVmKSksIHsgZmlsdGVyTW9kaWZpZWRDYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0ZJTFRFUl9NT0RJRklFRCxcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlckluc3RhbmNlOiBmaWx0ZXJJbnN0YW5jZVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgX3RoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgfSwgZmlsdGVyQ2hhbmdlZENhbGxiYWNrOiBmdW5jdGlvbiAoYWRkaXRpb25hbEV2ZW50QXR0cmlidXRlcykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJhbXMgPSB7IGZpbHRlckluc3RhbmNlOiBmaWx0ZXJJbnN0YW5jZSwgYWRkaXRpb25hbEV2ZW50QXR0cmlidXRlczogYWRkaXRpb25hbEV2ZW50QXR0cmlidXRlcywgY29sdW1uczogW2NvbHVtbl0gfTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jYWxsT25GaWx0ZXJDaGFuZ2VkT3V0c2lkZVJlbmRlckN5Y2xlKHBhcmFtcyk7XG4gICAgICAgICAgICB9LCBkb2VzUm93UGFzc090aGVyRmlsdGVyOiBmdW5jdGlvbiAobm9kZSkgeyByZXR1cm4gX3RoaXMuZG9lc1Jvd1Bhc3NPdGhlckZpbHRlcnMoZmlsdGVySW5zdGFuY2UsIG5vZGUpOyB9IH0pO1xuICAgICAgICB2YXIgY29tcERldGFpbHMgPSB0aGlzLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldEZpbHRlckRldGFpbHMoY29sRGVmLCBwYXJhbXMsIGRlZmF1bHRGaWx0ZXIpO1xuICAgICAgICBpZiAoIWNvbXBEZXRhaWxzKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tcG9uZW50UHJvbWlzZSA9IGNvbXBEZXRhaWxzLm5ld0FnU3RhY2tJbnN0YW5jZSgpO1xuICAgICAgICBpZiAoY29tcG9uZW50UHJvbWlzZSkge1xuICAgICAgICAgICAgY29tcG9uZW50UHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyKSB7IHJldHVybiBmaWx0ZXJJbnN0YW5jZSA9IHI7IH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb21wb25lbnRQcm9taXNlO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuY3JlYXRlRmlsdGVyUGFyYW1zID0gZnVuY3Rpb24gKGNvbHVtbiwgY29sRGVmKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgY29sRGVmOiBjbG9uZU9iamVjdChjb2xEZWYpLFxuICAgICAgICAgICAgcm93TW9kZWw6IHRoaXMucm93TW9kZWwsXG4gICAgICAgICAgICBmaWx0ZXJDaGFuZ2VkQ2FsbGJhY2s6IGZ1bmN0aW9uICgpIHsgfSxcbiAgICAgICAgICAgIGZpbHRlck1vZGlmaWVkQ2FsbGJhY2s6IGZ1bmN0aW9uICgpIHsgfSxcbiAgICAgICAgICAgIHZhbHVlR2V0dGVyOiB0aGlzLmNyZWF0ZVZhbHVlR2V0dGVyKGNvbHVtbiksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgICAgICBkb2VzUm93UGFzc090aGVyRmlsdGVyOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9LFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuY3JlYXRlRmlsdGVyV3JhcHBlciA9IGZ1bmN0aW9uIChjb2x1bW4sIHNvdXJjZSkge1xuICAgICAgICB2YXIgZmlsdGVyV3JhcHBlciA9IHtcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgZmlsdGVyUHJvbWlzZTogbnVsbCxcbiAgICAgICAgICAgIGNvbXBpbGVkRWxlbWVudDogbnVsbCxcbiAgICAgICAgICAgIGd1aVByb21pc2U6IEFnUHJvbWlzZS5yZXNvbHZlKG51bGwpXG4gICAgICAgIH07XG4gICAgICAgIGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZSA9IHRoaXMuY3JlYXRlRmlsdGVySW5zdGFuY2UoY29sdW1uKTtcbiAgICAgICAgaWYgKGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZSkge1xuICAgICAgICAgICAgdGhpcy5wdXRJbnRvR3VpKGZpbHRlcldyYXBwZXIsIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZpbHRlcldyYXBwZXI7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5wdXRJbnRvR3VpID0gZnVuY3Rpb24gKGZpbHRlcldyYXBwZXIsIHNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZUZpbHRlckd1aSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBlRmlsdGVyR3VpLmNsYXNzTmFtZSA9ICdhZy1maWx0ZXInO1xuICAgICAgICBmaWx0ZXJXcmFwcGVyLmd1aVByb21pc2UgPSBuZXcgQWdQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgICAgICBmaWx0ZXJXcmFwcGVyLmZpbHRlclByb21pc2UudGhlbihmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIGd1aUZyb21GaWx0ZXIgPSBmaWx0ZXIuZ2V0R3VpKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFleGlzdHMoZ3VpRnJvbUZpbHRlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogZ2V0R3VpIG1ldGhvZCBmcm9tIGZpbHRlciByZXR1cm5lZCBcIiArIGd1aUZyb21GaWx0ZXIgKyBcIiwgaXQgc2hvdWxkIGJlIGEgRE9NIGVsZW1lbnQgb3IgYW4gSFRNTCB0ZW1wbGF0ZSBzdHJpbmcuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgd2l0aCBBbmd1bGFyIDEgLSB3ZVxuICAgICAgICAgICAgICAgIC8vIHVzZWQgdG8gYWxsb3cgcHJvdmlkaW5nIGJhY2sgSFRNTCBmcm9tIGdldEd1aSgpLlxuICAgICAgICAgICAgICAgIC8vIG9uY2Ugd2UgbW92ZSBhd2F5IGZyb20gc3VwcG9ydGluZyBBbmd1bGFyIDFcbiAgICAgICAgICAgICAgICAvLyBkaXJlY3RseSwgd2UgY2FuIGNoYW5nZSB0aGlzLlxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZ3VpRnJvbUZpbHRlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3VpRnJvbUZpbHRlciA9IGxvYWRUZW1wbGF0ZShndWlGcm9tRmlsdGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZUZpbHRlckd1aS5hcHBlbmRDaGlsZChndWlGcm9tRmlsdGVyKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKGVGaWx0ZXJHdWkpO1xuICAgICAgICAgICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0ZJTFRFUl9PUEVORUQsXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbjogZmlsdGVyV3JhcHBlci5jb2x1bW4sXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZTogc291cmNlLFxuICAgICAgICAgICAgICAgICAgICBlR3VpOiBlRmlsdGVyR3VpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBfdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5vbkNvbHVtbnNDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29sdW1ucyA9IFtdO1xuICAgICAgICB0aGlzLmFsbENvbHVtbkZpbHRlcnMuZm9yRWFjaChmdW5jdGlvbiAod3JhcHBlciwgY29sSWQpIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50Q29sdW1uO1xuICAgICAgICAgICAgaWYgKHdyYXBwZXIuY29sdW1uLmlzUHJpbWFyeSgpKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudENvbHVtbiA9IF90aGlzLmNvbHVtbk1vZGVsLmdldFByaW1hcnlDb2x1bW4oY29sSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY3VycmVudENvbHVtbiA9IF90aGlzLmNvbHVtbk1vZGVsLmdldEdyaWRDb2x1bW4oY29sSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGN1cnJlbnRDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb2x1bW5zLnB1c2god3JhcHBlci5jb2x1bW4pO1xuICAgICAgICAgICAgX3RoaXMuZGlzcG9zZUZpbHRlcldyYXBwZXIod3JhcHBlciwgJ2ZpbHRlckRlc3Ryb3llZCcpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGNvbHVtbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5vbkZpbHRlckNoYW5nZWQoeyBjb2x1bW5zOiBjb2x1bW5zIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBkZXN0cm95cyB0aGUgZmlsdGVyLCBzbyBpdCBub3QgbG9uZ2VyIHRha2VzIHBhcnRcbiAgICBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5kZXN0cm95RmlsdGVyID0gZnVuY3Rpb24gKGNvbHVtbiwgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSAnYXBpJzsgfVxuICAgICAgICB2YXIgZmlsdGVyV3JhcHBlciA9IHRoaXMuYWxsQ29sdW1uRmlsdGVycy5nZXQoY29sdW1uLmdldENvbElkKCkpO1xuICAgICAgICBpZiAoZmlsdGVyV3JhcHBlcikge1xuICAgICAgICAgICAgdGhpcy5kaXNwb3NlRmlsdGVyV3JhcHBlcihmaWx0ZXJXcmFwcGVyLCBzb3VyY2UpO1xuICAgICAgICAgICAgdGhpcy5vbkZpbHRlckNoYW5nZWQoeyBjb2x1bW5zOiBbY29sdW1uXSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZGlzcG9zZUZpbHRlcldyYXBwZXIgPSBmdW5jdGlvbiAoZmlsdGVyV3JhcHBlciwgc291cmNlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGZpbHRlcldyYXBwZXIuZmlsdGVyUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChmaWx0ZXIpIHtcbiAgICAgICAgICAgIChmaWx0ZXIuc2V0TW9kZWwobnVsbCkgfHwgQWdQcm9taXNlLnJlc29sdmUoKSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0Q29udGV4dCgpLmRlc3Ryb3lCZWFuKGZpbHRlcik7XG4gICAgICAgICAgICAgICAgZmlsdGVyV3JhcHBlci5jb2x1bW4uc2V0RmlsdGVyQWN0aXZlKGZhbHNlLCBzb3VyY2UpO1xuICAgICAgICAgICAgICAgIF90aGlzLmFsbENvbHVtbkZpbHRlcnMuZGVsZXRlKGZpbHRlcldyYXBwZXIuY29sdW1uLmdldENvbElkKCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuYWxsQ29sdW1uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uIChmaWx0ZXJXcmFwcGVyKSB7IHJldHVybiBfdGhpcy5kaXNwb3NlRmlsdGVyV3JhcHBlcihmaWx0ZXJXcmFwcGVyLCAnZmlsdGVyRGVzdHJveWVkJyk7IH0pO1xuICAgIH07XG4gICAgdmFyIEZpbHRlck1hbmFnZXJfMTtcbiAgICBGaWx0ZXJNYW5hZ2VyLlFVSUNLX0ZJTFRFUl9TRVBBUkFUT1IgPSAnXFxuJztcbiAgICBfX2RlY29yYXRlJDFVKFtcbiAgICAgICAgQXV0b3dpcmVkKCd2YWx1ZVNlcnZpY2UnKVxuICAgIF0sIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLCBcInZhbHVlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVUoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZSwgXCJyb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3VzZXJDb21wb25lbnRGYWN0b3J5JylcbiAgICBdLCBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZSwgXCJ1c2VyQ29tcG9uZW50RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd1JlbmRlcmVyJylcbiAgICBdLCBGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZSwgXCJyb3dSZW5kZXJlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVUoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgRmlsdGVyTWFuYWdlci5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJDFVKFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIEZpbHRlck1hbmFnZXIucHJvdG90eXBlLCBcImRlc3Ryb3lcIiwgbnVsbCk7XG4gICAgRmlsdGVyTWFuYWdlciA9IEZpbHRlck1hbmFnZXJfMSA9IF9fZGVjb3JhdGUkMVUoW1xuICAgICAgICBCZWFuKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBGaWx0ZXJNYW5hZ2VyKTtcbiAgICByZXR1cm4gRmlsdGVyTWFuYWdlcjtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyNSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIEFic3RyYWN0SGVhZGVyQ2VsbENvbXAgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDI1KEFic3RyYWN0SGVhZGVyQ2VsbENvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWJzdHJhY3RIZWFkZXJDZWxsQ29tcCh0ZW1wbGF0ZSwgY3RybCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0ZW1wbGF0ZSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY3RybCA9IGN0cmw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWJzdHJhY3RIZWFkZXJDZWxsQ29tcC5wcm90b3R5cGUuZ2V0Q3RybCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3RybDtcbiAgICB9O1xuICAgIHJldHVybiBBYnN0cmFjdEhlYWRlckNlbGxDb21wO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyNCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMVQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBIZWFkZXJGaWx0ZXJDZWxsQ29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMjQoSGVhZGVyRmlsdGVyQ2VsbENvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gSGVhZGVyRmlsdGVyQ2VsbENvbXAoY3RybCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgSGVhZGVyRmlsdGVyQ2VsbENvbXAuVEVNUExBVEUsIGN0cmwpIHx8IHRoaXM7XG4gICAgfVxuICAgIEhlYWRlckZpbHRlckNlbGxDb21wLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIHZhciBjb21wUHJveHkgPSB7XG4gICAgICAgICAgICBhZGRPclJlbW92ZUNzc0NsYXNzOiBmdW5jdGlvbiAoY3NzQ2xhc3NOYW1lLCBvbikgeyByZXR1cm4gX3RoaXMuYWRkT3JSZW1vdmVDc3NDbGFzcyhjc3NDbGFzc05hbWUsIG9uKTsgfSxcbiAgICAgICAgICAgIGFkZE9yUmVtb3ZlQm9keUNzc0NsYXNzOiBmdW5jdGlvbiAoY3NzQ2xhc3NOYW1lLCBvbikgeyByZXR1cm4gX3RoaXMuZUZsb2F0aW5nRmlsdGVyQm9keS5jbGFzc0xpc3QudG9nZ2xlKGNzc0NsYXNzTmFtZSwgb24pOyB9LFxuICAgICAgICAgICAgYWRkT3JSZW1vdmVCdXR0b25XcmFwcGVyQ3NzQ2xhc3M6IGZ1bmN0aW9uIChjc3NDbGFzc05hbWUsIG9uKSB7IHJldHVybiBfdGhpcy5lQnV0dG9uV3JhcHBlci5jbGFzc0xpc3QudG9nZ2xlKGNzc0NsYXNzTmFtZSwgb24pOyB9LFxuICAgICAgICAgICAgc2V0Q29tcERldGFpbHM6IGZ1bmN0aW9uIChjb21wRGV0YWlscykgeyByZXR1cm4gX3RoaXMuc2V0Q29tcERldGFpbHMoY29tcERldGFpbHMpOyB9LFxuICAgICAgICAgICAgZ2V0RmxvYXRpbmdGaWx0ZXJDb21wOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb21wUHJvbWlzZTsgfSxcbiAgICAgICAgICAgIHNldFdpZHRoOiBmdW5jdGlvbiAod2lkdGgpIHsgcmV0dXJuIGVHdWkuc3R5bGUud2lkdGggPSB3aWR0aDsgfSxcbiAgICAgICAgICAgIHNldE1lbnVJY29uOiBmdW5jdGlvbiAoZUljb24pIHsgcmV0dXJuIF90aGlzLmVCdXR0b25TaG93TWFpbkZpbHRlci5hcHBlbmRDaGlsZChlSWNvbik7IH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jdHJsLnNldENvbXAoY29tcFByb3h5LCBlR3VpLCB0aGlzLmVCdXR0b25TaG93TWFpbkZpbHRlciwgdGhpcy5lRmxvYXRpbmdGaWx0ZXJCb2R5KTtcbiAgICB9O1xuICAgIEhlYWRlckZpbHRlckNlbGxDb21wLnByb3RvdHlwZS5zZXRDb21wRGV0YWlscyA9IGZ1bmN0aW9uIChjb21wRGV0YWlscykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBiZWNhdXNlIHdlIGFyZSBwcm92aWRpbmcgZGVmYXVsdEZsb2F0aW5nRmlsdGVyVHlwZSwgd2Uga25vdyBpdCB3aWxsIG5ldmVyIGJlIHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jb21wUHJvbWlzZSA9IGNvbXBEZXRhaWxzLm5ld0FnU3RhY2tJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLmNvbXBQcm9taXNlLnRoZW4oZnVuY3Rpb24gKGNvbXApIHsgcmV0dXJuIF90aGlzLmFmdGVyQ29tcENyZWF0ZWQoY29tcCk7IH0pO1xuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbENvbXAucHJvdG90eXBlLmFmdGVyQ29tcENyZWF0ZWQgPSBmdW5jdGlvbiAoY29tcCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIWNvbXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNvbnRleHQuZGVzdHJveUJlYW4oY29tcCk7IH0pO1xuICAgICAgICBpZiAoIXRoaXMuaXNBbGl2ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lRmxvYXRpbmdGaWx0ZXJCb2R5LmFwcGVuZENoaWxkKGNvbXAuZ2V0R3VpKCkpO1xuICAgICAgICBpZiAoY29tcC5hZnRlckd1aUF0dGFjaGVkKSB7XG4gICAgICAgICAgICBjb21wLmFmdGVyR3VpQXR0YWNoZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbENvbXAuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWhlYWRlci1jZWxsIGFnLWZsb2F0aW5nLWZpbHRlclxcXCIgcm9sZT1cXFwiZ3JpZGNlbGxcXFwiIHRhYmluZGV4PVxcXCItMVxcXCI+XFxuICAgICAgICAgICAgPGRpdiByZWY9XFxcImVGbG9hdGluZ0ZpbHRlckJvZHlcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmxvYXRpbmctZmlsdGVyLWJ1dHRvbiBhZy1oaWRkZW5cXFwiIHJlZj1cXFwiZUJ1dHRvbldyYXBwZXJcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBhcmlhLWxhYmVsPVxcXCJPcGVuIEZpbHRlciBNZW51XFxcIiBjbGFzcz1cXFwiYWctZmxvYXRpbmctZmlsdGVyLWJ1dHRvbi1idXR0b25cXFwiIHJlZj1cXFwiZUJ1dHRvblNob3dNYWluRmlsdGVyXFxcIiB0YWJpbmRleD1cXFwiLTFcXFwiPjwvYnV0dG9uPlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgX19kZWNvcmF0ZSQxVChbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlRmxvYXRpbmdGaWx0ZXJCb2R5JylcbiAgICBdLCBIZWFkZXJGaWx0ZXJDZWxsQ29tcC5wcm90b3R5cGUsIFwiZUZsb2F0aW5nRmlsdGVyQm9keVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVQoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUJ1dHRvbldyYXBwZXInKVxuICAgIF0sIEhlYWRlckZpbHRlckNlbGxDb21wLnByb3RvdHlwZSwgXCJlQnV0dG9uV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVQoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUJ1dHRvblNob3dNYWluRmlsdGVyJylcbiAgICBdLCBIZWFkZXJGaWx0ZXJDZWxsQ29tcC5wcm90b3R5cGUsIFwiZUJ1dHRvblNob3dNYWluRmlsdGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxVChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBIZWFkZXJGaWx0ZXJDZWxsQ29tcC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gSGVhZGVyRmlsdGVyQ2VsbENvbXA7XG59KEFic3RyYWN0SGVhZGVyQ2VsbENvbXApKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQyMyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMVMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBMYXlvdXRDc3NDbGFzc2VzO1xuKGZ1bmN0aW9uIChMYXlvdXRDc3NDbGFzc2VzKSB7XG4gICAgTGF5b3V0Q3NzQ2xhc3Nlc1tcIkFVVE9fSEVJR0hUXCJdID0gXCJhZy1sYXlvdXQtYXV0by1oZWlnaHRcIjtcbiAgICBMYXlvdXRDc3NDbGFzc2VzW1wiTk9STUFMXCJdID0gXCJhZy1sYXlvdXQtbm9ybWFsXCI7XG4gICAgTGF5b3V0Q3NzQ2xhc3Nlc1tcIlBSSU5UXCJdID0gXCJhZy1sYXlvdXQtcHJpbnRcIjtcbn0pKExheW91dENzc0NsYXNzZXMgfHwgKExheW91dENzc0NsYXNzZXMgPSB7fSkpO1xudmFyIExheW91dEZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDIzKExheW91dEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gTGF5b3V0RmVhdHVyZSh2aWV3KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnZpZXcgPSB2aWV3O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIExheW91dEZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET01fTEFZT1VULCB0aGlzLnVwZGF0ZUxheW91dENsYXNzZXMuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMudXBkYXRlTGF5b3V0Q2xhc3NlcygpO1xuICAgIH07XG4gICAgTGF5b3V0RmVhdHVyZS5wcm90b3R5cGUudXBkYXRlTGF5b3V0Q2xhc3NlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRvbUxheW91dCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvbUxheW91dCgpO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgYXV0b0hlaWdodDogZG9tTGF5b3V0ID09PSBDb25zdGFudHMuRE9NX0xBWU9VVF9BVVRPX0hFSUdIVCxcbiAgICAgICAgICAgIG5vcm1hbDogZG9tTGF5b3V0ID09PSBDb25zdGFudHMuRE9NX0xBWU9VVF9OT1JNQUwsXG4gICAgICAgICAgICBwcmludDogZG9tTGF5b3V0ID09PSBDb25zdGFudHMuRE9NX0xBWU9VVF9QUklOVFxuICAgICAgICB9O1xuICAgICAgICB2YXIgY3NzQ2xhc3MgPSBwYXJhbXMuYXV0b0hlaWdodCA/IExheW91dENzc0NsYXNzZXMuQVVUT19IRUlHSFQgOlxuICAgICAgICAgICAgcGFyYW1zLnByaW50ID8gTGF5b3V0Q3NzQ2xhc3Nlcy5QUklOVCA6IExheW91dENzc0NsYXNzZXMuTk9STUFMO1xuICAgICAgICB0aGlzLnZpZXcudXBkYXRlTGF5b3V0Q2xhc3Nlcyhjc3NDbGFzcywgcGFyYW1zKTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMVMoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRPcHRpb25zV3JhcHBlcicpXG4gICAgXSwgTGF5b3V0RmVhdHVyZS5wcm90b3R5cGUsIFwiZ3JpZE9wdGlvbnNXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUyhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBMYXlvdXRGZWF0dXJlLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBMYXlvdXRGZWF0dXJlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDIyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxUiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMjIoR3JpZEJvZHlTY3JvbGxGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZShlQm9keVZpZXdwb3J0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNjcm9sbExlZnQgPSAtMTtcbiAgICAgICAgX3RoaXMubmV4dFNjcm9sbFRvcCA9IC0xO1xuICAgICAgICBfdGhpcy5zY3JvbGxUb3AgPSAtMTtcbiAgICAgICAgX3RoaXMuZUJvZHlWaWV3cG9ydCA9IGVCb2R5Vmlld3BvcnQ7XG4gICAgICAgIF90aGlzLnJlc2V0TGFzdEhvcml6b250YWxTY3JvbGxFbGVtZW50RGVib3VuY2VkID0gZGVib3VuY2UoX3RoaXMucmVzZXRMYXN0SG9yaXpvbnRhbFNjcm9sbEVsZW1lbnQuYmluZChfdGhpcyksIDUwMCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmVuYWJsZVJ0bCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfV0lEVEhfQ0hBTkdFRCwgdGhpcy5vbkRpc3BsYXllZENvbHVtbnNXaWR0aENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLndoZW5SZWFkeShmdW5jdGlvbiAocCkge1xuICAgICAgICAgICAgX3RoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybCA9IHAuY2VudGVyUm93Q29udGFpbmVyQ3RybDtcbiAgICAgICAgICAgIF90aGlzLm9uRGlzcGxheWVkQ29sdW1uc1dpZHRoQ2hhbmdlZCgpO1xuICAgICAgICAgICAgX3RoaXMuYWRkU2Nyb2xsTGlzdGVuZXIoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLmFkZFNjcm9sbExpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmFrZUhTY3JvbGwgPSB0aGlzLmN0cmxzU2VydmljZS5nZXRGYWtlSFNjcm9sbEN0cmwoKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldFZpZXdwb3J0RWxlbWVudCgpLCAnc2Nyb2xsJywgdGhpcy5vbkNlbnRlclZpZXdwb3J0U2Nyb2xsLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihmYWtlSFNjcm9sbC5nZXRWaWV3cG9ydCgpLCAnc2Nyb2xsJywgdGhpcy5vbkZha2VIb3Jpem9udGFsU2Nyb2xsLmJpbmQodGhpcykpO1xuICAgICAgICB2YXIgb25WZXJ0aWNhbFNjcm9sbCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRGVib3VuY2VWZXJ0aWNhbFNjcm9sbGJhcigpID9cbiAgICAgICAgICAgIGRlYm91bmNlKHRoaXMub25WZXJ0aWNhbFNjcm9sbC5iaW5kKHRoaXMpLCAxMDApXG4gICAgICAgICAgICA6IHRoaXMub25WZXJ0aWNhbFNjcm9sbC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVCb2R5Vmlld3BvcnQsICdzY3JvbGwnLCBvblZlcnRpY2FsU2Nyb2xsKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUub25EaXNwbGF5ZWRDb2x1bW5zV2lkdGhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5lbmFibGVSdGwpIHtcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgUlRMIGlzIGFsbCBiYWNrd2FyZHMsIGEgY2hhbmdlIGluIHRoZSB3aWR0aCBvZiB0aGUgcm93XG4gICAgICAgICAgICAvLyBjYW4gY2F1c2UgYSBjaGFuZ2UgaW4gdGhlIHNjcm9sbCBwb3NpdGlvbiwgd2l0aG91dCBhIHNjcm9sbCBldmVudCxcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIHNjcm9sbCBwb3NpdGlvbiBpbiBSVEwgaXMgYSBmdW5jdGlvbiB0aGF0IGRlcGVuZHMgb25cbiAgICAgICAgICAgIC8vIHRoZSB3aWR0aC4gdG8gYmUgY29udmluY2VkIG9mIHRoaXMsIHRha2Ugb3V0IHRoaXMgbGluZSwgZW5hYmxlIFJUTCxcbiAgICAgICAgICAgIC8vIHNjcm9sbCBhbGwgdGhlIHdheSB0byB0aGUgbGVmdCBhbmQgdGhlbiByZXNpemUgYSBjb2x1bW5cbiAgICAgICAgICAgIHRoaXMuaG9yaXpvbnRhbGx5U2Nyb2xsSGVhZGVyQ2VudGVyQW5kRmxvYXRpbmdDZW50ZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5ob3Jpem9udGFsbHlTY3JvbGxIZWFkZXJDZW50ZXJBbmRGbG9hdGluZ0NlbnRlciA9IGZ1bmN0aW9uIChzY3JvbGxMZWZ0KSB7XG4gICAgICAgIC8vIHdoZW4gZG9pbmcgUlRMLCB0aGlzIG1ldGhvZCBnZXRzIGNhbGxlZCBvbmNlIHByZW1hdHVyZWx5XG4gICAgICAgIHZhciBub3RZZXRJbml0aWFsaXNlZCA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybCA9PSBudWxsO1xuICAgICAgICBpZiAobm90WWV0SW5pdGlhbGlzZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2Nyb2xsTGVmdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBzY3JvbGxMZWZ0ID0gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldENlbnRlclZpZXdwb3J0U2Nyb2xsTGVmdCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvZmZzZXQgPSB0aGlzLmVuYWJsZVJ0bCA/IHNjcm9sbExlZnQgOiAtc2Nyb2xsTGVmdDtcbiAgICAgICAgdmFyIHRvcENlbnRlckNvbnRhaW5lciA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldFRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwoKTtcbiAgICAgICAgdmFyIHN0aWNreVRvcENlbnRlckNvbnRhaW5lciA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldFN0aWNreVRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwoKTtcbiAgICAgICAgdmFyIGJvdHRvbUNlbnRlckNvbnRhaW5lciA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEJvdHRvbUNlbnRlclJvd0NvbnRhaW5lckN0cmwoKTtcbiAgICAgICAgdmFyIGZha2VIU2Nyb2xsID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0RmFrZUhTY3JvbGxDdHJsKCk7XG4gICAgICAgIHZhciBjZW50ZXJIZWFkZXJDb250YWluZXIgPSB0aGlzLmN0cmxzU2VydmljZS5nZXRIZWFkZXJSb3dDb250YWluZXJDdHJsKCk7XG4gICAgICAgIGNlbnRlckhlYWRlckNvbnRhaW5lci5zZXRIb3Jpem9udGFsU2Nyb2xsKG9mZnNldCk7XG4gICAgICAgIGJvdHRvbUNlbnRlckNvbnRhaW5lci5zZXRDb250YWluZXJUcmFuc2xhdGVYKG9mZnNldCk7XG4gICAgICAgIHRvcENlbnRlckNvbnRhaW5lci5zZXRDb250YWluZXJUcmFuc2xhdGVYKG9mZnNldCk7XG4gICAgICAgIHN0aWNreVRvcENlbnRlckNvbnRhaW5lci5zZXRDb250YWluZXJUcmFuc2xhdGVYKG9mZnNldCk7XG4gICAgICAgIHZhciBjZW50ZXJWaWV3cG9ydCA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRWaWV3cG9ydEVsZW1lbnQoKTtcbiAgICAgICAgdmFyIGlzQ2VudGVyVmlld3BvcnRMYXN0SG9yaXpvbnRhbCA9IHRoaXMubGFzdEhvcml6b250YWxTY3JvbGxFbGVtZW50ID09PSBjZW50ZXJWaWV3cG9ydDtcbiAgICAgICAgdmFyIHBhcnRuZXIgPSBpc0NlbnRlclZpZXdwb3J0TGFzdEhvcml6b250YWwgP1xuICAgICAgICAgICAgZmFrZUhTY3JvbGwuZ2V0Vmlld3BvcnQoKSA6XG4gICAgICAgICAgICB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Vmlld3BvcnRFbGVtZW50KCk7XG4gICAgICAgIHNldFNjcm9sbExlZnQocGFydG5lciwgTWF0aC5hYnMoc2Nyb2xsTGVmdCksIHRoaXMuZW5hYmxlUnRsKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuaXNDb250cm9sbGluZ1Njcm9sbCA9IGZ1bmN0aW9uIChlRGl2KSB7XG4gICAgICAgIGlmICghdGhpcy5sYXN0SG9yaXpvbnRhbFNjcm9sbEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMubGFzdEhvcml6b250YWxTY3JvbGxFbGVtZW50ID0gZURpdjtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlRGl2ID09PSB0aGlzLmxhc3RIb3Jpem9udGFsU2Nyb2xsRWxlbWVudDtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUub25GYWtlSG9yaXpvbnRhbFNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZha2VIU2Nyb2xsVmlld3BvcnQgPSB0aGlzLmN0cmxzU2VydmljZS5nZXRGYWtlSFNjcm9sbEN0cmwoKS5nZXRWaWV3cG9ydCgpO1xuICAgICAgICBpZiAoIXRoaXMuaXNDb250cm9sbGluZ1Njcm9sbChmYWtlSFNjcm9sbFZpZXdwb3J0KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub25Cb2R5SG9yaXpvbnRhbFNjcm9sbChmYWtlSFNjcm9sbFZpZXdwb3J0KTtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUub25DZW50ZXJWaWV3cG9ydFNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNlbnRlckNvbnRhaW5lclZpZXdwb3J0ID0gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldFZpZXdwb3J0RWxlbWVudCgpO1xuICAgICAgICBpZiAoIXRoaXMuaXNDb250cm9sbGluZ1Njcm9sbChjZW50ZXJDb250YWluZXJWaWV3cG9ydCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uQm9keUhvcml6b250YWxTY3JvbGwoY2VudGVyQ29udGFpbmVyVmlld3BvcnQpO1xuICAgIH07XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5vbkJvZHlIb3Jpem9udGFsU2Nyb2xsID0gZnVuY3Rpb24gKGVTb3VyY2UpIHtcbiAgICAgICAgdmFyIGNlbnRlckNvbnRhaW5lclZpZXdwb3J0ID0gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldFZpZXdwb3J0RWxlbWVudCgpO1xuICAgICAgICB2YXIgc2Nyb2xsTGVmdCA9IGNlbnRlckNvbnRhaW5lclZpZXdwb3J0LnNjcm9sbExlZnQ7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZEJsb2NrU2Nyb2xsVXBkYXRlKCdob3Jpem9udGFsJywgc2Nyb2xsTGVmdCwgdHJ1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBkbyBNYXRoLnJvdW5kKCkgcmF0aGVyIHRoYW4gTWF0aC5mbG9vcigpLCB0byBtaXJyb3IgaG93IHNjcm9sbCB2YWx1ZXMgYXJlIGFwcGxpZWQuXG4gICAgICAgIC8vIGVnIGlmIGEgc2NhbGUgaXMgYXBwbGllZCAoaWUgdXNlciBoYXMgem9vbWVkIHRoZSBicm93c2VyKSwgdGhlbiBhcHBseWluZyBzY3JvbGw9MjAwXG4gICAgICAgIC8vIGNvdWxkIHJlc3VsdCBpbiAxOTkuODgsIHdoaWNoIHRoZW4gZmxvb3IoMTk5Ljg4KSA9IDE5OSwgaG93ZXZlciByb3VuZCgxOTkuODgpID0gMjAwLlxuICAgICAgICAvLyBpbml0aWFsbHkgTWF0aC5mbG9vcigpIHdhcyB1c2VkLCBob3dldmVyIHRoaXMgY2F1c2VkIChhbG1vc3QpIGluZmluaXRlIGxvb3Agd2l0aCBhbGlnbmVkIGdyaWRzLFxuICAgICAgICAvLyBhcyB0aGUgc2Nyb2xsIHdvdWxkIG1vdmUgMXB4IGF0IGF0IHRpbWUgYm91bmNpbmcgZnJvbSBvbmUgZ3JpZCB0byB0aGUgbmV4dCAoZWcgb25lIGdyaWQgd291bGQgY2F1c2VcbiAgICAgICAgLy8gc2Nyb2xsIHRvIDIwMHB4LCB0aGUgbmV4dCB0byAxOTlweCwgdGhlbiB0aGUgZmlyc3QgYmFjayB0byAxOThweCBhbmQgc28gb24pLlxuICAgICAgICB0aGlzLmRvSG9yaXpvbnRhbFNjcm9sbChNYXRoLnJvdW5kKGdldFNjcm9sbExlZnQoZVNvdXJjZSwgdGhpcy5lbmFibGVSdGwpKSk7XG4gICAgICAgIHRoaXMucmVzZXRMYXN0SG9yaXpvbnRhbFNjcm9sbEVsZW1lbnREZWJvdW5jZWQoKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUub25WZXJ0aWNhbFNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNjcm9sbFRvcCA9IHRoaXMuZUJvZHlWaWV3cG9ydC5zY3JvbGxUb3A7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZEJsb2NrU2Nyb2xsVXBkYXRlKCd2ZXJ0aWNhbCcsIHNjcm9sbFRvcCwgdHJ1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lU2VydmljZS5zZXRTY3JvbGxUb3Aoc2Nyb2xsVG9wKTtcbiAgICAgICAgdGhpcy5uZXh0U2Nyb2xsVG9wID0gc2Nyb2xsVG9wO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0FuaW1hdGlvbkZyYW1lKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsVG9wID0gdGhpcy5uZXh0U2Nyb2xsVG9wO1xuICAgICAgICAgICAgdGhpcy5yZWRyYXdSb3dzQWZ0ZXJTY3JvbGwoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnNjaGVkdWxlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUucmVzZXRMYXN0SG9yaXpvbnRhbFNjcm9sbEVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMubGFzdEhvcml6b250YWxTY3JvbGxFbGVtZW50ID0gbnVsbDtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuZG9Ib3Jpem9udGFsU2Nyb2xsID0gZnVuY3Rpb24gKHNjcm9sbExlZnQpIHtcbiAgICAgICAgdmFyIGZha2VIU2Nyb2xsVmlld3BvcnQgPSB0aGlzLmN0cmxzU2VydmljZS5nZXRGYWtlSFNjcm9sbEN0cmwoKS5nZXRWaWV3cG9ydCgpO1xuICAgICAgICB2YXIgZmFrZVNjcm9sbExlZnQgPSBnZXRTY3JvbGxMZWZ0KGZha2VIU2Nyb2xsVmlld3BvcnQsIHRoaXMuZW5hYmxlUnRsKTtcbiAgICAgICAgaWYgKHRoaXMuc2Nyb2xsTGVmdCA9PT0gc2Nyb2xsTGVmdCAmJiBzY3JvbGxMZWZ0ID09PSBmYWtlU2Nyb2xsTGVmdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nyb2xsTGVmdCA9IHNjcm9sbExlZnQ7XG4gICAgICAgIHRoaXMuZmlyZVNjcm9sbEV2ZW50KCdob3Jpem9udGFsJyk7XG4gICAgICAgIHRoaXMuaG9yaXpvbnRhbGx5U2Nyb2xsSGVhZGVyQ2VudGVyQW5kRmxvYXRpbmdDZW50ZXIoc2Nyb2xsTGVmdCk7XG4gICAgICAgIHRoaXMub25Ib3Jpem9udGFsVmlld3BvcnRDaGFuZ2VkKCk7XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLmZpcmVTY3JvbGxFdmVudCA9IGZ1bmN0aW9uIChkaXJlY3Rpb24pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGJvZHlTY3JvbGxFdmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9CT0RZX1NDUk9MTCxcbiAgICAgICAgICAgIGRpcmVjdGlvbjogZGlyZWN0aW9uLFxuICAgICAgICAgICAgbGVmdDogdGhpcy5zY3JvbGxMZWZ0LFxuICAgICAgICAgICAgdG9wOiB0aGlzLnNjcm9sbFRvcFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGJvZHlTY3JvbGxFdmVudCk7XG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5zY3JvbGxUaW1lcik7XG4gICAgICAgIHRoaXMuc2Nyb2xsVGltZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuc2Nyb2xsVGltZXIgPSB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYm9keVNjcm9sbEVuZEV2ZW50ID0gT2JqZWN0LmFzc2lnbih7fSwgYm9keVNjcm9sbEV2ZW50LCB7XG4gICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0JPRFlfU0NST0xMX0VORFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBfdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChib2R5U2Nyb2xsRW5kRXZlbnQpO1xuICAgICAgICB9LCAxMDApO1xuICAgIH07XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5zaG91bGRCbG9ja1Njcm9sbFVwZGF0ZSA9IGZ1bmN0aW9uIChkaXJlY3Rpb24sIHNjcm9sbFRvLCB0b3VjaE9ubHkpIHtcbiAgICAgICAgLy8gdG91Y2ggZGV2aWNlcyBhbGxvdyBlbGFzdGljIHNjcm9sbCAtIHdoaWNoIHRlbXBvcmFsbHkgc2Nyb2xscyB0aGUgcGFuZWwgb3V0c2lkZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgICAgLy8gKGVnIHVzZXIgdXNlcyB0b3VjaCB0byBnbyB0byB0aGUgbGVmdCBvZiB0aGUgZ3JpZCwgYnV0IGRyYWdzIHBhc3QgdGhlIGxlZnQsIHRoZSByb3dzIHdpbGwgYWN0dWFsbHlcbiAgICAgICAgLy8gc2Nyb2xsIHBhc3QgdGhlIGxlZnQgdW50aWwgdGhlIHVzZXIgcmVsZWFzZXMgdGhlIG1vdXNlKS4gd2hlbiB0aGlzIGhhcHBlbnMsIHdlIHdhbnQgaWdub3JlIHRoZSBzY3JvbGwsXG4gICAgICAgIC8vIGFzIG90aGVyd2lzZSBpdCB3YXMgY2F1c2luZyB0aGUgcm93cyBhbmQgaGVhZGVyIHRvIGZsaWNrZXIuXG4gICAgICAgIGlmICh0b3VjaE9ubHkgPT09IHZvaWQgMCkgeyB0b3VjaE9ubHkgPSBmYWxzZTsgfVxuICAgICAgICAvLyBzb21ldGltZXMgd2hlbiBzY3JvbGxpbmcsIHdlIGdvdCB2YWx1ZXMgdGhhdCBleHRlbmRlZCB0aGUgbWF4aW11bSBzY3JvbGwgYWxsb3dlZC4gd2UgdXNlZCB0b1xuICAgICAgICAvLyBpZ25vcmUgdGhlc2Ugc2Nyb2xscy4gcHJvYmxlbSBpcyB0aGUgbWF4IHNjcm9sbCBwb3NpdGlvbiBjb3VsZCBiZSBza2lwcGVkIChlZyB0aGUgcHJldmlvdXMgc2Nyb2xsIGV2ZW50XG4gICAgICAgIC8vIGNvdWxkIGJlIDEwcHggYmVmb3JlIHRoZSBtYXggcG9zaXRpb24sIGFuZCB0aGVuIGN1cnJlbnQgc2Nyb2xsIGV2ZW50IGNvdWxkIGJlIDIwcHggYWZ0ZXIgdGhlIG1heCBwb3NpdGlvbikuXG4gICAgICAgIC8vIGlmIHdlIGp1c3QgaWdub3JlZCB0aGUgbGFzdCBldmVudCwgd2Ugd291bGQgYmUgc2V0dGluZyB0aGUgc2Nyb2xsIHRvIDEwcHggYmVmb3JlIHRoZSBtYXggcG9zaXRpb24sIHdoZW4gaW5cbiAgICAgICAgLy8gYWN0dWFsIGZhY3QgdGhlIHVzZXIgaGFzIGV4Y2VlZGVkIHRoZSBtYXggc2Nyb2xsIGFuZCB0aHVzIHNjcm9sbCBzaG91bGQgYmUgc2V0IHRvIHRoZSBtYXguXG4gICAgICAgIGlmICh0b3VjaE9ubHkgJiYgIWlzSU9TVXNlckFnZW50KCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGlyZWN0aW9uID09PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgICB2YXIgY2xpZW50SGVpZ2h0ID0gZ2V0SW5uZXJIZWlnaHQodGhpcy5lQm9keVZpZXdwb3J0KTtcbiAgICAgICAgICAgIHZhciBzY3JvbGxIZWlnaHQgPSB0aGlzLmVCb2R5Vmlld3BvcnQuc2Nyb2xsSGVpZ2h0O1xuICAgICAgICAgICAgaWYgKHNjcm9sbFRvIDwgMCB8fCAoc2Nyb2xsVG8gKyBjbGllbnRIZWlnaHQgPiBzY3JvbGxIZWlnaHQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICB2YXIgY2xpZW50V2lkdGggPSB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Q2VudGVyV2lkdGgoKTtcbiAgICAgICAgICAgIHZhciBzY3JvbGxXaWR0aCA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRWaWV3cG9ydEVsZW1lbnQoKS5zY3JvbGxXaWR0aDtcbiAgICAgICAgICAgIGlmICh0aGlzLmVuYWJsZVJ0bCAmJiBpc1J0bE5lZ2F0aXZlU2Nyb2xsKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2Nyb2xsVG8gPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHNjcm9sbFRvIDwgMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKE1hdGguYWJzKHNjcm9sbFRvKSArIGNsaWVudFdpZHRoID4gc2Nyb2xsV2lkdGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLnJlZHJhd1Jvd3NBZnRlclNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5maXJlU2Nyb2xsRXZlbnQoJ3ZlcnRpY2FsJyk7XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLm9uSG9yaXpvbnRhbFZpZXdwb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLm9uSG9yaXpvbnRhbFZpZXdwb3J0Q2hhbmdlZCgpO1xuICAgIH07XG4gICAgLy8gdGhpcyBpcyB0byBjYXRlciBmb3IgQUctMzI3NCwgd2hlcmUgZ3JpZCBpcyByZW1vdmVkIGZyb20gdGhlIGRvbSBhbmQgdGhlbiBpbnNlcnRlZCBiYWNrIGluIGFnYWluLlxuICAgIC8vICh3aGljaCBoYXBwZW5zIHdpdGggc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgdGFiYmluZykuIHRoaXMgY2FuIHJlc3VsdCBpbiBob3Jpem9udGFsIHNjcm9sbCBnZXR0aW5nXG4gICAgLy8gcmVzZXQgYmFjayB0byB0aGUgbGVmdCwgaG93ZXZlciBubyBzY3JvbGwgZXZlbnQgaXMgZmlyZWQuIHNvIHdlIG5lZWQgdG8gZ2V0IGhlYWRlciB0byBhbHNvIHNjcm9sbFxuICAgIC8vIGJhY2sgdG8gdGhlIGxlZnQgdG8gYmUga2VwdCBpbiBzeW5jLlxuICAgIC8vIGFkZGluZyBhbmQgcmVtb3ZpbmcgdGhlIGdyaWQgZnJvbSB0aGUgRE9NIGJvdGggcmVzZXRzIHRoZSBzY3JvbGwgcG9zaXRpb24gYW5kXG4gICAgLy8gdHJpZ2dlcnMgYSByZXNpemUgZXZlbnQsIHNvIG5vdGlmeSBsaXN0ZW5lcnMgaWYgdGhlIHNjcm9sbCBwb3NpdGlvbiBoYXMgY2hhbmdlZFxuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuY2hlY2tTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5zY3JvbGxMZWZ0ICE9PSB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Q2VudGVyVmlld3BvcnRTY3JvbGxMZWZ0KCkpIHtcbiAgICAgICAgICAgIHRoaXMub25Cb2R5SG9yaXpvbnRhbFNjcm9sbCh0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Vmlld3BvcnRFbGVtZW50KCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLmV4ZWN1dGVBbmltYXRpb25GcmFtZVNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZyYW1lTmVlZGVkID0gdGhpcy5zY3JvbGxUb3AgIT0gdGhpcy5uZXh0U2Nyb2xsVG9wO1xuICAgICAgICBpZiAoZnJhbWVOZWVkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2Nyb2xsVG9wID0gdGhpcy5uZXh0U2Nyb2xsVG9wO1xuICAgICAgICAgICAgdGhpcy5yZWRyYXdSb3dzQWZ0ZXJTY3JvbGwoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnJhbWVOZWVkZWQ7XG4gICAgfTtcbiAgICAvLyBjYWxsZWQgYnkgc2Nyb2xsSG9yaXpvbnRhbGx5IG1ldGhvZCBhbmQgYWxpZ25lZEdyaWRzU2VydmljZVxuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuc2V0SG9yaXpvbnRhbFNjcm9sbFBvc2l0aW9uID0gZnVuY3Rpb24gKGhTY3JvbGxQb3NpdGlvbikge1xuICAgICAgICB2YXIgbWluU2Nyb2xsTGVmdCA9IDA7XG4gICAgICAgIHZhciBtYXhTY3JvbGxMZWZ0ID0gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldFZpZXdwb3J0RWxlbWVudCgpLnNjcm9sbFdpZHRoIC0gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldENlbnRlcldpZHRoKCk7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZEJsb2NrU2Nyb2xsVXBkYXRlKCdob3Jpem9udGFsJywgaFNjcm9sbFBvc2l0aW9uKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZW5hYmxlUnRsICYmIGlzUnRsTmVnYXRpdmVTY3JvbGwoKSkge1xuICAgICAgICAgICAgICAgIGhTY3JvbGxQb3NpdGlvbiA9IGhTY3JvbGxQb3NpdGlvbiA+IDAgPyAwIDogbWF4U2Nyb2xsTGVmdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGhTY3JvbGxQb3NpdGlvbiA9IE1hdGgubWluKE1hdGgubWF4KGhTY3JvbGxQb3NpdGlvbiwgbWluU2Nyb2xsTGVmdCksIG1heFNjcm9sbExlZnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNldFNjcm9sbExlZnQodGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldFZpZXdwb3J0RWxlbWVudCgpLCBNYXRoLmFicyhoU2Nyb2xsUG9zaXRpb24pLCB0aGlzLmVuYWJsZVJ0bCk7XG4gICAgICAgIC8vIHdlIG5lZWQgdG8gbWFudWFsbHkgZG8gdGhlIGV2ZW50IGhhbmRsaW5nIChyYXRoZXIgdGhhbiB3YWl0IGZvciB0aGUgZXZlbnQpXG4gICAgICAgIC8vIGZvciB0aGUgYWxpZ25lZEdyaWRzU2VydmljZSwgYXMgaWYgd2UgZG9uJ3QsIHRoZSBhbGlnbmVkIGdyaWQgc2VydmljZSBnZXRzXG4gICAgICAgIC8vIG5vdGlmaWVkIGFzeW5jLCBhbmQgdGhlbiBpdCdzICdjb25zdW1pbmcnIGZsYWcgZG9lc24ndCBnZXQgdXNlZCByaWdodCwgYW5kXG4gICAgICAgIC8vIHdlIGNhbiBlbmQgdXAgd2l0aCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgIHRoaXMuZG9Ib3Jpem9udGFsU2Nyb2xsKGhTY3JvbGxQb3NpdGlvbik7XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLnNldFZlcnRpY2FsU2Nyb2xsUG9zaXRpb24gPSBmdW5jdGlvbiAodlNjcm9sbFBvc2l0aW9uKSB7XG4gICAgICAgIHRoaXMuZUJvZHlWaWV3cG9ydC5zY3JvbGxUb3AgPSB2U2Nyb2xsUG9zaXRpb247XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLmdldFZTY3JvbGxQb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgICAgIHRvcDogdGhpcy5lQm9keVZpZXdwb3J0LnNjcm9sbFRvcCxcbiAgICAgICAgICAgIGJvdHRvbTogdGhpcy5lQm9keVZpZXdwb3J0LnNjcm9sbFRvcCArIHRoaXMuZUJvZHlWaWV3cG9ydC5vZmZzZXRIZWlnaHRcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuZ2V0SFNjcm9sbFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmdldEhTY3JvbGxQb3NpdGlvbigpO1xuICAgIH07XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5pc0hvcml6b250YWxTY3JvbGxTaG93aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsLmlzSG9yaXpvbnRhbFNjcm9sbFNob3dpbmcoKTtcbiAgICB9O1xuICAgIC8vIGNhbGxlZCBieSB0aGUgaGVhZGVyUm9vdENvbXAgYW5kIG1vdmVDb2x1bW5Db250cm9sbGVyXG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5zY3JvbGxIb3Jpem9udGFsbHkgPSBmdW5jdGlvbiAocGl4ZWxzKSB7XG4gICAgICAgIHZhciBvbGRTY3JvbGxQb3NpdGlvbiA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRWaWV3cG9ydEVsZW1lbnQoKS5zY3JvbGxMZWZ0O1xuICAgICAgICB0aGlzLnNldEhvcml6b250YWxTY3JvbGxQb3NpdGlvbihvbGRTY3JvbGxQb3NpdGlvbiArIHBpeGVscyk7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Vmlld3BvcnRFbGVtZW50KCkuc2Nyb2xsTGVmdCAtIG9sZFNjcm9sbFBvc2l0aW9uO1xuICAgIH07XG4gICAgLy8gZ2V0cyBjYWxsZWQgYnkgcm93UmVuZGVyZXIgd2hlbiBuZXcgZGF0YSBsb2FkZWQsIGFzIGl0IHdpbGwgd2FudCB0byBzY3JvbGwgdG8gdGhlIHRvcFxuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuc2Nyb2xsVG9Ub3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZUJvZHlWaWV3cG9ydC5zY3JvbGxUb3AgPSAwO1xuICAgIH07XG4gICAgLy8gVmFsaWQgdmFsdWVzIGZvciBwb3NpdGlvbiBhcmUgYm90dG9tLCBtaWRkbGUgYW5kIHRvcFxuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuZW5zdXJlTm9kZVZpc2libGUgPSBmdW5jdGlvbiAoY29tcGFyYXRvciwgcG9zaXRpb24pIHtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSB2b2lkIDApIHsgcG9zaXRpb24gPSBudWxsOyB9XG4gICAgICAgIC8vIGxvb2sgZm9yIHRoZSBub2RlIGluZGV4IHdlIHdhbnQgdG8gZGlzcGxheVxuICAgICAgICB2YXIgcm93Q291bnQgPSB0aGlzLnJvd01vZGVsLmdldFJvd0NvdW50KCk7XG4gICAgICAgIHZhciBpbmRleFRvU2VsZWN0ID0gLTE7XG4gICAgICAgIC8vIGdvIHRocm91Z2ggYWxsIHRoZSBub2RlcywgZmluZCB0aGUgb25lIHdlIHdhbnQgdG8gc2hvd1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvd0NvdW50OyBpKyspIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gdGhpcy5yb3dNb2RlbC5nZXRSb3coaSk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNvbXBhcmF0b3IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAvLyBIYXZlIHRvIGFzc2VydCB0eXBlIGhlcmUsIGFzIHR5cGUgY291bGQgYmUgVERhdGEgJiBGdW5jdGlvblxuICAgICAgICAgICAgICAgIHZhciBwcmVkaWNhdGUgPSBjb21wYXJhdG9yO1xuICAgICAgICAgICAgICAgIGlmIChub2RlICYmIHByZWRpY2F0ZShub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpbmRleFRvU2VsZWN0ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY2hlY2sgb2JqZWN0IGVxdWFsaXR5IGFnYWluc3Qgbm9kZSBhbmQgZGF0YVxuICAgICAgICAgICAgICAgIGlmIChjb21wYXJhdG9yID09PSBub2RlIHx8IGNvbXBhcmF0b3IgPT09IG5vZGUuZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBpbmRleFRvU2VsZWN0ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChpbmRleFRvU2VsZWN0ID49IDApIHtcbiAgICAgICAgICAgIHRoaXMuZW5zdXJlSW5kZXhWaXNpYmxlKGluZGV4VG9TZWxlY3QsIHBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gVmFsaWQgdmFsdWVzIGZvciBwb3NpdGlvbiBhcmUgYm90dG9tLCBtaWRkbGUgYW5kIHRvcFxuICAgIC8vIHBvc2l0aW9uIHNob3VsZCBiZSB7J3RvcCcsJ21pZGRsZScsJ2JvdHRvbScsIG9yIHVuZGVmaW5lZC9udWxsfS5cbiAgICAvLyBpZiB1bmRlZmluZWQvbnVsbCwgdGhlbiB0aGUgZ3JpZCB3aWxsIHRvIHRoZSBtaW5pbWFsIGFtb3VudCBvZiBzY3JvbGxpbmcsXG4gICAgLy8gZWcgaWYgZ3JpZCBuZWVkcyB0byBzY3JvbGwgdXAsIGl0IHNjcm9sbHMgdW50aWwgcm93IGlzIG9uIHRvcCxcbiAgICAvLyAgICBpZiBncmlkIG5lZWRzIHRvIHNjcm9sbCBkb3duLCBpdCBzY3JvbGxzIHVudGlsIHJvdyBpcyBvbiBib3R0b20sXG4gICAgLy8gICAgaWYgcm93IGlzIGFscmVhZHkgaW4gdmlldywgZ3JpZCBkb2VzIG5vdCBzY3JvbGxcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLmVuc3VyZUluZGV4VmlzaWJsZSA9IGZ1bmN0aW9uIChpbmRleCwgcG9zaXRpb24pIHtcbiAgICAgICAgLy8gaWYgZm9yIHByaW50IG9yIGF1dG8gaGVpZ2h0LCBldmVyeXRoaW5nIGlzIGFsd2F5cyB2aXNpYmxlXG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21MYXlvdXQoKSA9PT0gQ29uc3RhbnRzLkRPTV9MQVlPVVRfUFJJTlQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93Q291bnQgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRSb3dDb3VudCgpO1xuICAgICAgICBpZiAodHlwZW9mIGluZGV4ICE9PSAnbnVtYmVyJyB8fCBpbmRleCA8IDAgfHwgaW5kZXggPj0gcm93Q291bnQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignaW52YWxpZCByb3cgaW5kZXggZm9yIGVuc3VyZUluZGV4VmlzaWJsZTogJyArIGluZGV4KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNQYWdpbmcgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1BhZ2luYXRpb24oKTtcbiAgICAgICAgdmFyIHBhZ2luYXRpb25QYW5lbEVuYWJsZWQgPSBpc1BhZ2luZyAmJiAhdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1BhZ2luYXRpb25QYW5lbCgpO1xuICAgICAgICBpZiAoIXBhZ2luYXRpb25QYW5lbEVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMucGFnaW5hdGlvblByb3h5LmdvVG9QYWdlV2l0aEluZGV4KGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZ3JpZEJvZHlDdHJsID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgIHZhciBzdGlja3lUb3BIZWlnaHQgPSBncmlkQm9keUN0cmwuZ2V0U3RpY2t5VG9wSGVpZ2h0KCk7XG4gICAgICAgIHZhciByb3dOb2RlID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93KGluZGV4KTtcbiAgICAgICAgdmFyIHJvd0dvdFNoaWZ0ZWREdXJpbmdPcGVyYXRpb247XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIHZhciBzdGFydGluZ1Jvd1RvcCA9IHJvd05vZGUucm93VG9wO1xuICAgICAgICAgICAgdmFyIHN0YXJ0aW5nUm93SGVpZ2h0ID0gcm93Tm9kZS5yb3dIZWlnaHQ7XG4gICAgICAgICAgICB2YXIgcGFnaW5hdGlvbk9mZnNldCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBpeGVsT2Zmc2V0KCk7XG4gICAgICAgICAgICB2YXIgcm93VG9wUGl4ZWwgPSByb3dOb2RlLnJvd1RvcCAtIHBhZ2luYXRpb25PZmZzZXQ7XG4gICAgICAgICAgICB2YXIgcm93Qm90dG9tUGl4ZWwgPSByb3dUb3BQaXhlbCArIHJvd05vZGUucm93SGVpZ2h0O1xuICAgICAgICAgICAgdmFyIHNjcm9sbFBvc2l0aW9uID0gdGhpcy5nZXRWU2Nyb2xsUG9zaXRpb24oKTtcbiAgICAgICAgICAgIHZhciBoZWlnaHRPZmZzZXQgPSB0aGlzLmhlaWdodFNjYWxlci5nZXREaXZTdHJldGNoT2Zmc2V0KCk7XG4gICAgICAgICAgICB2YXIgdlNjcm9sbFRvcCA9IHNjcm9sbFBvc2l0aW9uLnRvcCArIGhlaWdodE9mZnNldDtcbiAgICAgICAgICAgIHZhciB2U2Nyb2xsQm90dG9tID0gc2Nyb2xsUG9zaXRpb24uYm90dG9tICsgaGVpZ2h0T2Zmc2V0O1xuICAgICAgICAgICAgdmFyIHZpZXdwb3J0SGVpZ2h0ID0gdlNjcm9sbEJvdHRvbSAtIHZTY3JvbGxUb3A7XG4gICAgICAgICAgICAvLyB3b3JrIG91dCB0aGUgcGl4ZWxzIGZvciB0b3AsIG1pZGRsZSBhbmQgYm90dG9tIHVwIGZyb250LFxuICAgICAgICAgICAgLy8gbWFrZSB0aGUgaWYvZWxzZSBiZWxvdyBlYXNpZXIgdG8gcmVhZFxuICAgICAgICAgICAgdmFyIHB4VG9wID0gdGhpcy5oZWlnaHRTY2FsZXIuZ2V0U2Nyb2xsUG9zaXRpb25Gb3JQaXhlbChyb3dUb3BQaXhlbCk7XG4gICAgICAgICAgICB2YXIgcHhCb3R0b20gPSB0aGlzLmhlaWdodFNjYWxlci5nZXRTY3JvbGxQb3NpdGlvbkZvclBpeGVsKHJvd0JvdHRvbVBpeGVsIC0gdmlld3BvcnRIZWlnaHQpO1xuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIGlmIG1pZGRsZSwgdGhlIHJvdyBpcyBub3Qgb3V0c2lkZSB0aGUgdG9wIG9mIHRoZSBncmlkXG4gICAgICAgICAgICB2YXIgcHhNaWRkbGUgPSBNYXRoLm1pbigocHhUb3AgKyBweEJvdHRvbSkgLyAyLCByb3dUb3BQaXhlbCk7XG4gICAgICAgICAgICB2YXIgcm93QWJvdmVWaWV3cG9ydCA9ICh2U2Nyb2xsVG9wICsgc3RpY2t5VG9wSGVpZ2h0KSA+IHJvd1RvcFBpeGVsO1xuICAgICAgICAgICAgdmFyIHJvd0JlbG93Vmlld3BvcnQgPSB2U2Nyb2xsQm90dG9tIDwgcm93Qm90dG9tUGl4ZWw7XG4gICAgICAgICAgICB2YXIgbmV3U2Nyb2xsUG9zaXRpb24gPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIG5ld1Njcm9sbFBvc2l0aW9uID0gcHhUb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICAgICAgICBuZXdTY3JvbGxQb3NpdGlvbiA9IHB4Qm90dG9tO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocG9zaXRpb24gPT09ICdtaWRkbGUnKSB7XG4gICAgICAgICAgICAgICAgbmV3U2Nyb2xsUG9zaXRpb24gPSBweE1pZGRsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJvd0Fib3ZlVmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiByb3cgaXMgYmVmb3JlLCBzY3JvbGwgdXAgd2l0aCByb3cgYXQgdG9wXG4gICAgICAgICAgICAgICAgbmV3U2Nyb2xsUG9zaXRpb24gPSBweFRvcCAtIHN0aWNreVRvcEhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJvd0JlbG93Vmlld3BvcnQpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiByb3cgaXMgYWZ0ZXIsIHNjcm9sbCBkb3duIHdpdGggcm93IGF0IGJvdHRvbVxuICAgICAgICAgICAgICAgIG5ld1Njcm9sbFBvc2l0aW9uID0gcHhCb3R0b207XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobmV3U2Nyb2xsUG9zaXRpb24gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVCb2R5Vmlld3BvcnQuc2Nyb2xsVG9wID0gbmV3U2Nyb2xsUG9zaXRpb247XG4gICAgICAgICAgICAgICAgdGhpcy5yb3dSZW5kZXJlci5yZWRyYXdBZnRlclNjcm9sbCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdGhlIHJvdyBjYW4gZ2V0IHNoaWZ0ZWQgaWYgZHVyaW5nIHRoZSByZW5kZXJpbmcgKGR1cmluZyByb3dSZW5kZXJlci5yZWRyYXdBZnRlclNjcm9sbCgpKSxcbiAgICAgICAgICAgIC8vIHRoZSBoZWlnaHQgb2YgYSByb3cgY2hhbmdlcyBkdWUgdG8gbGF6eSBjYWxjdWxhdGlvbiBvZiByb3cgaGVpZ2h0cyB3aGVuIHVzaW5nXG4gICAgICAgICAgICAvLyBjb2xEZWYuYXV0b0hlaWdodCBvciBncmlkT3B0aW9ucy5nZXRSb3dIZWlnaHQuXG4gICAgICAgICAgICAvLyBpZiByb3cgd2FzIHNoaWZ0ZWQsIHRoZW4gdGhlIHBvc2l0aW9uIHdlIHNjcm9sbGVkIHRvIGlzIGluY29ycmVjdC5cbiAgICAgICAgICAgIHJvd0dvdFNoaWZ0ZWREdXJpbmdPcGVyYXRpb24gPSAoc3RhcnRpbmdSb3dUb3AgIT09IHJvd05vZGUucm93VG9wKVxuICAgICAgICAgICAgICAgIHx8IChzdGFydGluZ1Jvd0hlaWdodCAhPT0gcm93Tm9kZS5yb3dIZWlnaHQpO1xuICAgICAgICB9IHdoaWxlIChyb3dHb3RTaGlmdGVkRHVyaW5nT3BlcmF0aW9uKTtcbiAgICAgICAgLy8gc28gd2hlbiB3ZSByZXR1cm4gYmFjayB0byB1c2VyLCB0aGUgY2VsbHMgaGF2ZSByZW5kZXJlZFxuICAgICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lU2VydmljZS5mbHVzaEFsbEZyYW1lcygpO1xuICAgIH07XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5lbnN1cmVDb2x1bW5WaXNpYmxlID0gZnVuY3Rpb24gKGtleSwgcG9zaXRpb24pIHtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSB2b2lkIDApIHsgcG9zaXRpb24gPSAnYXV0byc7IH1cbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JpZENvbHVtbihrZXkpO1xuICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNhbGxpbmcgZW5zdXJlQ29sdW1uVmlzaWJsZSBvbiBhIHBpbm5lZCBjb2x1bW4gZG9lc24ndCBtYWtlIHNlbnNlXG4gICAgICAgIGlmIChjb2x1bW4uaXNQaW5uZWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGRlZmVuc2l2ZVxuICAgICAgICBpZiAoIXRoaXMuY29sdW1uTW9kZWwuaXNDb2x1bW5EaXNwbGF5ZWQoY29sdW1uKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXdIb3Jpem9udGFsU2Nyb2xsID0gdGhpcy5nZXRQb3NpdGlvbmVkSG9yaXpvbnRhbFNjcm9sbChjb2x1bW4sIHBvc2l0aW9uKTtcbiAgICAgICAgaWYgKG5ld0hvcml6b250YWxTY3JvbGwgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5zZXRDZW50ZXJWaWV3cG9ydFNjcm9sbExlZnQobmV3SG9yaXpvbnRhbFNjcm9sbCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhpcyB3aWxsIGhhcHBlbiBhbnl3YXksIGFzIHRoZSBtb3ZlIHdpbGwgY2F1c2UgYSAnc2Nyb2xsJyBldmVudCBvbiB0aGUgYm9keSwgaG93ZXZlclxuICAgICAgICAvLyBpdCBpcyBwb3NzaWJsZSB0aGF0IHRoZSBlbnN1cmVDb2x1bW5WaXNpYmxlIG1ldGhvZCBpcyBjYWxsZWQgZnJvbSB3aXRoaW4gQUcgR3JpZCBhbmRcbiAgICAgICAgLy8gdGhlIGNhbGxlciB3aWxsIG5lZWQgdG8gaGF2ZSB0aGUgY29sdW1ucyByZW5kZXJlZCB0byBjb250aW51ZSwgd2hpY2ggd2lsbCBiZSBiZWZvcmVcbiAgICAgICAgLy8gdGhlIGV2ZW50IGhhcyBiZWVuIHdvcmtlZCBvbiAod2hpY2ggaXMgdGhlIGNhc2UgZm9yIGNlbGwgbmF2aWdhdGlvbikuXG4gICAgICAgIHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5vbkhvcml6b250YWxWaWV3cG9ydENoYW5nZWQoKTtcbiAgICAgICAgLy8gc28gd2hlbiB3ZSByZXR1cm4gYmFjayB0byB1c2VyLCB0aGUgY2VsbHMgaGF2ZSByZW5kZXJlZFxuICAgICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lU2VydmljZS5mbHVzaEFsbEZyYW1lcygpO1xuICAgIH07XG4gICAgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZS5nZXRQb3NpdGlvbmVkSG9yaXpvbnRhbFNjcm9sbCA9IGZ1bmN0aW9uIChjb2x1bW4sIHBvc2l0aW9uKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuaXNDb2x1bW5PdXRzaWRlVmlld3BvcnQoY29sdW1uKSwgY29sdW1uQmVmb3JlU3RhcnQgPSBfYS5jb2x1bW5CZWZvcmVTdGFydCwgY29sdW1uQWZ0ZXJFbmQgPSBfYS5jb2x1bW5BZnRlckVuZDtcbiAgICAgICAgdmFyIHZpZXdwb3J0VG9vU21hbGxGb3JDb2x1bW4gPSB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Q2VudGVyV2lkdGgoKSA8IGNvbHVtbi5nZXRBY3R1YWxXaWR0aCgpO1xuICAgICAgICB2YXIgdmlld3BvcnRXaWR0aCA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRDZW50ZXJXaWR0aCgpO1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmVuYWJsZVJ0bDtcbiAgICAgICAgdmFyIGFsaWduQ29sVG9TdGFydCA9IChpc1J0bCA/IGNvbHVtbkJlZm9yZVN0YXJ0IDogY29sdW1uQWZ0ZXJFbmQpIHx8IHZpZXdwb3J0VG9vU21hbGxGb3JDb2x1bW47XG4gICAgICAgIHZhciBhbGlnbkNvbFRvRW5kID0gaXNSdGwgPyBjb2x1bW5BZnRlckVuZCA6IGNvbHVtbkJlZm9yZVN0YXJ0O1xuICAgICAgICBpZiAocG9zaXRpb24gIT09ICdhdXRvJykge1xuICAgICAgICAgICAgYWxpZ25Db2xUb1N0YXJ0ID0gcG9zaXRpb24gPT09ICdzdGFydCc7XG4gICAgICAgICAgICBhbGlnbkNvbFRvRW5kID0gcG9zaXRpb24gPT09ICdlbmQnO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpc01pZGRsZSA9IHBvc2l0aW9uID09PSAnbWlkZGxlJztcbiAgICAgICAgaWYgKGFsaWduQ29sVG9TdGFydCB8fCBhbGlnbkNvbFRvRW5kIHx8IGlzTWlkZGxlKSB7XG4gICAgICAgICAgICB2YXIgX2IgPSB0aGlzLmdldENvbHVtbkJvdW5kcyhjb2x1bW4pLCBjb2xMZWZ0ID0gX2IuY29sTGVmdCwgY29sTWlkZGxlID0gX2IuY29sTWlkZGxlLCBjb2xSaWdodCA9IF9iLmNvbFJpZ2h0O1xuICAgICAgICAgICAgaWYgKGlzTWlkZGxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbE1pZGRsZSAtIHZpZXdwb3J0V2lkdGggLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFsaWduQ29sVG9TdGFydCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1J0bCA/IGNvbFJpZ2h0IDogY29sTGVmdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc1J0bCA/IChjb2xMZWZ0IC0gdmlld3BvcnRXaWR0aCkgOiAoY29sUmlnaHQgLSB2aWV3cG9ydFdpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuaXNDb2x1bW5PdXRzaWRlVmlld3BvcnQgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuZ2V0Vmlld3BvcnRCb3VuZHMoKSwgdmlld3BvcnRTdGFydCA9IF9hLnN0YXJ0LCB2aWV3cG9ydEVuZCA9IF9hLmVuZDtcbiAgICAgICAgdmFyIF9iID0gdGhpcy5nZXRDb2x1bW5Cb3VuZHMoY29sdW1uKSwgY29sTGVmdCA9IF9iLmNvbExlZnQsIGNvbFJpZ2h0ID0gX2IuY29sUmlnaHQ7XG4gICAgICAgIHZhciBpc1J0bCA9IHRoaXMuZW5hYmxlUnRsO1xuICAgICAgICB2YXIgY29sdW1uQmVmb3JlU3RhcnQgPSBpc1J0bCA/ICh2aWV3cG9ydFN0YXJ0ID4gY29sUmlnaHQpIDogKHZpZXdwb3J0RW5kIDwgY29sUmlnaHQpO1xuICAgICAgICB2YXIgY29sdW1uQWZ0ZXJFbmQgPSBpc1J0bCA/ICh2aWV3cG9ydEVuZCA8IGNvbExlZnQpIDogKHZpZXdwb3J0U3RhcnQgPiBjb2xMZWZ0KTtcbiAgICAgICAgcmV0dXJuIHsgY29sdW1uQmVmb3JlU3RhcnQ6IGNvbHVtbkJlZm9yZVN0YXJ0LCBjb2x1bW5BZnRlckVuZDogY29sdW1uQWZ0ZXJFbmQgfTtcbiAgICB9O1xuICAgIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUuZ2V0Q29sdW1uQm91bmRzID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmVuYWJsZVJ0bDtcbiAgICAgICAgdmFyIGJvZHlXaWR0aCA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0Qm9keUNvbnRhaW5lcldpZHRoKCk7XG4gICAgICAgIHZhciBjb2xXaWR0aCA9IGNvbHVtbi5nZXRBY3R1YWxXaWR0aCgpO1xuICAgICAgICB2YXIgY29sTGVmdCA9IGNvbHVtbi5nZXRMZWZ0KCk7XG4gICAgICAgIHZhciBtdWx0aXBsaWVyID0gaXNSdGwgPyAtMSA6IDE7XG4gICAgICAgIHZhciBjb2xMZWZ0UGl4ZWwgPSBpc1J0bCA/IChib2R5V2lkdGggLSBjb2xMZWZ0KSA6IGNvbExlZnQ7XG4gICAgICAgIHZhciBjb2xSaWdodFBpeGVsID0gY29sTGVmdFBpeGVsICsgY29sV2lkdGggKiBtdWx0aXBsaWVyO1xuICAgICAgICB2YXIgY29sTWlkUGl4ZWwgPSBjb2xMZWZ0UGl4ZWwgKyBjb2xXaWR0aCAvIDIgKiBtdWx0aXBsaWVyO1xuICAgICAgICByZXR1cm4geyBjb2xMZWZ0OiBjb2xMZWZ0UGl4ZWwsIGNvbE1pZGRsZTogY29sTWlkUGl4ZWwsIGNvbFJpZ2h0OiBjb2xSaWdodFBpeGVsIH07XG4gICAgfTtcbiAgICBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLmdldFZpZXdwb3J0Qm91bmRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmlld3BvcnRXaWR0aCA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRDZW50ZXJXaWR0aCgpO1xuICAgICAgICB2YXIgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Q2VudGVyVmlld3BvcnRTY3JvbGxMZWZ0KCk7XG4gICAgICAgIHZhciB2aWV3cG9ydFN0YXJ0UGl4ZWwgPSBzY3JvbGxQb3NpdGlvbjtcbiAgICAgICAgdmFyIHZpZXdwb3J0RW5kUGl4ZWwgPSB2aWV3cG9ydFdpZHRoICsgc2Nyb2xsUG9zaXRpb247XG4gICAgICAgIHJldHVybiB7IHN0YXJ0OiB2aWV3cG9ydFN0YXJ0UGl4ZWwsIGVuZDogdmlld3BvcnRFbmRQaXhlbCwgd2lkdGg6IHZpZXdwb3J0V2lkdGggfTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMVIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFSKFtcbiAgICAgICAgQXV0b3dpcmVkKCdhbmltYXRpb25GcmFtZVNlcnZpY2UnKVxuICAgIF0sIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZS5wcm90b3R5cGUsIFwiYW5pbWF0aW9uRnJhbWVTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUihbXG4gICAgICAgIEF1dG93aXJlZCgncGFnaW5hdGlvblByb3h5JylcbiAgICBdLCBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLCBcInBhZ2luYXRpb25Qcm94eVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVIoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLCBcInJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUihbXG4gICAgICAgIEF1dG93aXJlZCgncm93Q29udGFpbmVySGVpZ2h0U2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZSwgXCJoZWlnaHRTY2FsZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFSKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dSZW5kZXJlcicpXG4gICAgXSwgR3JpZEJvZHlTY3JvbGxGZWF0dXJlLnByb3RvdHlwZSwgXCJyb3dSZW5kZXJlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBHcmlkQm9keVNjcm9sbEZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEdyaWRCb2R5U2Nyb2xsRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIEF1dG9TY3JvbGxTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEF1dG9TY3JvbGxTZXJ2aWNlKHBhcmFtcykge1xuICAgICAgICB0aGlzLnRpY2tpbmdJbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIHRoaXMub25TY3JvbGxDYWxsYmFjayA9IG51bGw7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udGFpbmVyID0gcGFyYW1zLnNjcm9sbENvbnRhaW5lcjtcbiAgICAgICAgdGhpcy5zY3JvbGxIb3Jpem9udGFsbHkgPSBwYXJhbXMuc2Nyb2xsQXhpcy5pbmRleE9mKCd4JykgIT09IC0xO1xuICAgICAgICB0aGlzLnNjcm9sbFZlcnRpY2FsbHkgPSBwYXJhbXMuc2Nyb2xsQXhpcy5pbmRleE9mKCd5JykgIT09IC0xO1xuICAgICAgICB0aGlzLnNjcm9sbEJ5VGljayA9IHBhcmFtcy5zY3JvbGxCeVRpY2sgIT0gbnVsbCA/IHBhcmFtcy5zY3JvbGxCeVRpY2sgOiAyMDtcbiAgICAgICAgaWYgKHBhcmFtcy5vblNjcm9sbENhbGxiYWNrKSB7XG4gICAgICAgICAgICB0aGlzLm9uU2Nyb2xsQ2FsbGJhY2sgPSBwYXJhbXMub25TY3JvbGxDYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zY3JvbGxWZXJ0aWNhbGx5KSB7XG4gICAgICAgICAgICB0aGlzLmdldFZlcnRpY2FsUG9zaXRpb24gPSBwYXJhbXMuZ2V0VmVydGljYWxQb3NpdGlvbjtcbiAgICAgICAgICAgIHRoaXMuc2V0VmVydGljYWxQb3NpdGlvbiA9IHBhcmFtcy5zZXRWZXJ0aWNhbFBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNjcm9sbEhvcml6b250YWxseSkge1xuICAgICAgICAgICAgdGhpcy5nZXRIb3Jpem9udGFsUG9zaXRpb24gPSBwYXJhbXMuZ2V0SG9yaXpvbnRhbFBvc2l0aW9uO1xuICAgICAgICAgICAgdGhpcy5zZXRIb3Jpem9udGFsUG9zaXRpb24gPSBwYXJhbXMuc2V0SG9yaXpvbnRhbFBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2hvdWxkU2tpcFZlcnRpY2FsU2Nyb2xsID0gcGFyYW1zLnNob3VsZFNraXBWZXJ0aWNhbFNjcm9sbCB8fCAoZnVuY3Rpb24gKCkgeyByZXR1cm4gZmFsc2U7IH0pO1xuICAgICAgICB0aGlzLnNob3VsZFNraXBIb3Jpem9udGFsU2Nyb2xsID0gcGFyYW1zLnNob3VsZFNraXBIb3Jpem9udGFsU2Nyb2xsIHx8IChmdW5jdGlvbiAoKSB7IHJldHVybiBmYWxzZTsgfSk7XG4gICAgfVxuICAgIEF1dG9TY3JvbGxTZXJ2aWNlLnByb3RvdHlwZS5jaGVjayA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50LCBmb3JjZVNraXBWZXJ0aWNhbFNjcm9sbCkge1xuICAgICAgICBpZiAoZm9yY2VTa2lwVmVydGljYWxTY3JvbGwgPT09IHZvaWQgMCkgeyBmb3JjZVNraXBWZXJ0aWNhbFNjcm9sbCA9IGZhbHNlOyB9XG4gICAgICAgIHZhciBza2lwVmVydGljYWxTY3JvbGwgPSBmb3JjZVNraXBWZXJ0aWNhbFNjcm9sbCB8fCB0aGlzLnNob3VsZFNraXBWZXJ0aWNhbFNjcm9sbCgpO1xuICAgICAgICBpZiAoc2tpcFZlcnRpY2FsU2Nyb2xsICYmIHRoaXMuc2hvdWxkU2tpcEhvcml6b250YWxTY3JvbGwoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZWN0ID0gdGhpcy5zY3JvbGxDb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBzY3JvbGxUaWNrID0gdGhpcy5zY3JvbGxCeVRpY2s7XG4gICAgICAgIHRoaXMudGlja0xlZnQgPSBtb3VzZUV2ZW50LmNsaWVudFggPCAocmVjdC5sZWZ0ICsgc2Nyb2xsVGljayk7XG4gICAgICAgIHRoaXMudGlja1JpZ2h0ID0gbW91c2VFdmVudC5jbGllbnRYID4gKHJlY3QucmlnaHQgLSBzY3JvbGxUaWNrKTtcbiAgICAgICAgdGhpcy50aWNrVXAgPSBtb3VzZUV2ZW50LmNsaWVudFkgPCAocmVjdC50b3AgKyBzY3JvbGxUaWNrKSAmJiAhc2tpcFZlcnRpY2FsU2Nyb2xsO1xuICAgICAgICB0aGlzLnRpY2tEb3duID0gbW91c2VFdmVudC5jbGllbnRZID4gKHJlY3QuYm90dG9tIC0gc2Nyb2xsVGljaykgJiYgIXNraXBWZXJ0aWNhbFNjcm9sbDtcbiAgICAgICAgaWYgKHRoaXMudGlja0xlZnQgfHwgdGhpcy50aWNrUmlnaHQgfHwgdGhpcy50aWNrVXAgfHwgdGhpcy50aWNrRG93bikge1xuICAgICAgICAgICAgdGhpcy5lbnN1cmVUaWNraW5nU3RhcnRlZCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5lbnN1cmVDbGVhcmVkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEF1dG9TY3JvbGxTZXJ2aWNlLnByb3RvdHlwZS5lbnN1cmVUaWNraW5nU3RhcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMudGlja2luZ0ludGVydmFsID09PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnRpY2tpbmdJbnRlcnZhbCA9IHdpbmRvdy5zZXRJbnRlcnZhbCh0aGlzLmRvVGljay5iaW5kKHRoaXMpLCAxMDApO1xuICAgICAgICAgICAgdGhpcy50aWNrQ291bnQgPSAwO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsU2VydmljZS5wcm90b3R5cGUuZG9UaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRpY2tDb3VudCsrO1xuICAgICAgICB2YXIgdGlja0Ftb3VudDtcbiAgICAgICAgdGlja0Ftb3VudCA9IHRoaXMudGlja0NvdW50ID4gMjAgPyAyMDAgOiAodGhpcy50aWNrQ291bnQgPiAxMCA/IDgwIDogNDApO1xuICAgICAgICBpZiAodGhpcy5zY3JvbGxWZXJ0aWNhbGx5KSB7XG4gICAgICAgICAgICB2YXIgdlNjcm9sbFBvc2l0aW9uID0gdGhpcy5nZXRWZXJ0aWNhbFBvc2l0aW9uKCk7XG4gICAgICAgICAgICBpZiAodGhpcy50aWNrVXApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFZlcnRpY2FsUG9zaXRpb24odlNjcm9sbFBvc2l0aW9uIC0gdGlja0Ftb3VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy50aWNrRG93bikge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VmVydGljYWxQb3NpdGlvbih2U2Nyb2xsUG9zaXRpb24gKyB0aWNrQW1vdW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5zY3JvbGxIb3Jpem9udGFsbHkpIHtcbiAgICAgICAgICAgIHZhciBoU2Nyb2xsUG9zaXRpb24gPSB0aGlzLmdldEhvcml6b250YWxQb3NpdGlvbigpO1xuICAgICAgICAgICAgaWYgKHRoaXMudGlja0xlZnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEhvcml6b250YWxQb3NpdGlvbihoU2Nyb2xsUG9zaXRpb24gLSB0aWNrQW1vdW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLnRpY2tSaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SG9yaXpvbnRhbFBvc2l0aW9uKGhTY3JvbGxQb3NpdGlvbiArIHRpY2tBbW91bnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm9uU2Nyb2xsQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMub25TY3JvbGxDYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBdXRvU2Nyb2xsU2VydmljZS5wcm90b3R5cGUuZW5zdXJlQ2xlYXJlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMudGlja2luZ0ludGVydmFsKSB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnRpY2tpbmdJbnRlcnZhbCk7XG4gICAgICAgICAgICB0aGlzLnRpY2tpbmdJbnRlcnZhbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBBdXRvU2Nyb2xsU2VydmljZTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMjEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiQ2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiQ2ID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiQ2LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fZGVjb3JhdGUkMVEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3JlYWQkaSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCRlID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJGkoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBSb3dEcmFnRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMjEoUm93RHJhZ0ZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUm93RHJhZ0ZlYXR1cmUoZUNvbnRhaW5lcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5pc011bHRpUm93RHJhZyA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc0dyaWRTb3J0ZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNHcmlkRmlsdGVyZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNSb3dHcm91cEFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5lQ29udGFpbmVyID0gZUNvbnRhaW5lcjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxEZWZhdWx0KCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsID0gdGhpcy5yb3dNb2RlbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVmcmVzaFN0YXR1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLm9uU29ydENoYW5nZWQoKTtcbiAgICAgICAgICAgIF90aGlzLm9uRmlsdGVyQ2hhbmdlZCgpO1xuICAgICAgICAgICAgX3RoaXMub25Sb3dHcm91cENoYW5nZWQoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9TT1JUX0NIQU5HRUQsIHRoaXMub25Tb3J0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9GSUxURVJfQ0hBTkdFRCwgdGhpcy5vbkZpbHRlckNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1JPV19HUk9VUF9DSEFOR0VELCB0aGlzLm9uUm93R3JvdXBDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX01PREVMX1VQREFURUQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJlZnJlc2hTdGF0dXMoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJlZnJlc2hTdGF0dXMoKTtcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBncmlkQm9keUNvbiA9IF90aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgICAgIF90aGlzLmF1dG9TY3JvbGxTZXJ2aWNlID0gbmV3IEF1dG9TY3JvbGxTZXJ2aWNlKHtcbiAgICAgICAgICAgICAgICBzY3JvbGxDb250YWluZXI6IGdyaWRCb2R5Q29uLmdldEJvZHlWaWV3cG9ydEVsZW1lbnQoKSxcbiAgICAgICAgICAgICAgICBzY3JvbGxBeGlzOiAneScsXG4gICAgICAgICAgICAgICAgZ2V0VmVydGljYWxQb3NpdGlvbjogZnVuY3Rpb24gKCkgeyByZXR1cm4gZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmdldFZTY3JvbGxQb3NpdGlvbigpLnRvcDsgfSxcbiAgICAgICAgICAgICAgICBzZXRWZXJ0aWNhbFBvc2l0aW9uOiBmdW5jdGlvbiAocG9zaXRpb24pIHsgcmV0dXJuIGdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKS5zZXRWZXJ0aWNhbFNjcm9sbFBvc2l0aW9uKHBvc2l0aW9uKTsgfSxcbiAgICAgICAgICAgICAgICBvblNjcm9sbENhbGxiYWNrOiBmdW5jdGlvbiAoKSB7IF90aGlzLm9uRHJhZ2dpbmcoX3RoaXMubGFzdERyYWdnaW5nRXZlbnQpOyB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUub25Tb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pc0dyaWRTb3J0ZWQgPSB0aGlzLnNvcnRDb250cm9sbGVyLmlzU29ydEFjdGl2ZSgpO1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLm9uRmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pc0dyaWRGaWx0ZXJlZCA9IHRoaXMuZmlsdGVyTWFuYWdlci5pc0FueUZpbHRlclByZXNlbnQoKTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5vblJvd0dyb3VwQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd0dyb3VwcyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0Um93R3JvdXBDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMuaXNSb3dHcm91cEFjdGl2ZSA9ICFtaXNzaW5nT3JFbXB0eShyb3dHcm91cHMpO1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLmdldENvbnRhaW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUNvbnRhaW5lcjtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5pc0ludGVyZXN0ZWRJbiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIHJldHVybiB0eXBlID09PSBEcmFnU291cmNlVHlwZS5Sb3dEcmFnO1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLmdldEljb25OYW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWFuYWdlZERyYWcgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd0RyYWdNYW5hZ2VkKCk7XG4gICAgICAgIGlmIChtYW5hZ2VkRHJhZyAmJiB0aGlzLnNob3VsZFByZXZlbnRSb3dNb3ZlKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9OT1RfQUxMT1dFRDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fTU9WRTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5zaG91bGRQcmV2ZW50Um93TW92ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNHcmlkU29ydGVkIHx8IHRoaXMuaXNHcmlkRmlsdGVyZWQgfHwgdGhpcy5pc1Jvd0dyb3VwQWN0aXZlO1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLmdldFJvd05vZGVzID0gZnVuY3Rpb24gKGRyYWdnaW5nRXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmlzRnJvbVRoaXNHcmlkKGRyYWdnaW5nRXZlbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZHJhZ2dpbmdFdmVudC5kcmFnSXRlbS5yb3dOb2RlcyB8fCBbXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNSb3dEcmFnTXVsdGlSb3cgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd0RyYWdNdWx0aVJvdygpO1xuICAgICAgICB2YXIgc2VsZWN0ZWROb2RlcyA9IF9fc3ByZWFkJGUodGhpcy5zZWxlY3Rpb25TZXJ2aWNlLmdldFNlbGVjdGVkTm9kZXMoKSkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgaWYgKGEucm93SW5kZXggPT0gbnVsbCB8fCBiLnJvd0luZGV4ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBfdGhpcy5nZXRSb3dJbmRleE51bWJlcihhKSAtIF90aGlzLmdldFJvd0luZGV4TnVtYmVyKGIpO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGN1cnJlbnROb2RlID0gZHJhZ2dpbmdFdmVudC5kcmFnSXRlbS5yb3dOb2RlO1xuICAgICAgICBpZiAoaXNSb3dEcmFnTXVsdGlSb3cgJiYgc2VsZWN0ZWROb2Rlcy5pbmRleE9mKGN1cnJlbnROb2RlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuaXNNdWx0aVJvd0RyYWcgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIHNlbGVjdGVkTm9kZXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc011bHRpUm93RHJhZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gW2N1cnJlbnROb2RlXTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5vbkRyYWdFbnRlciA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIC8vIGJ1aWxkcyBhIGxpdHMgb2YgYWxsIHJvd3MgYmVpbmcgZHJhZ2dlZCBiZWZvcmUgZmlyaW5nIGV2ZW50c1xuICAgICAgICBkcmFnZ2luZ0V2ZW50LmRyYWdJdGVtLnJvd05vZGVzID0gdGhpcy5nZXRSb3dOb2RlcyhkcmFnZ2luZ0V2ZW50KTtcbiAgICAgICAgLy8gd2hlbiBlbnRlcmluZywgd2UgZmlyZSB0aGUgZW50ZXIgZXZlbnQsIHRoZW4gaW4gb25FbnRlck9yRHJhZ2dpbmcsXG4gICAgICAgIC8vIHdlIGFsc28gZmlyZSB0aGUgbW92ZSBldmVudC4gc28gd2UgZ2V0IGJvdGggZXZlbnRzIHdoZW4gZW50ZXJpbmcuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hHcmlkRXZlbnQoRXZlbnRzLkVWRU5UX1JPV19EUkFHX0VOVEVSLCBkcmFnZ2luZ0V2ZW50KTtcbiAgICAgICAgdGhpcy5nZXRSb3dOb2RlcyhkcmFnZ2luZ0V2ZW50KS5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICByb3dOb2RlLnNldERyYWdnaW5nKHRydWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5vbkVudGVyT3JEcmFnZ2luZyhkcmFnZ2luZ0V2ZW50KTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5vbkRyYWdnaW5nID0gZnVuY3Rpb24gKGRyYWdnaW5nRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vbkVudGVyT3JEcmFnZ2luZyhkcmFnZ2luZ0V2ZW50KTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5pc0Zyb21UaGlzR3JpZCA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIHZhciBkcmFnU291cmNlRG9tRGF0YUtleSA9IGRyYWdnaW5nRXZlbnQuZHJhZ1NvdXJjZS5kcmFnU291cmNlRG9tRGF0YUtleTtcbiAgICAgICAgcmV0dXJuIGRyYWdTb3VyY2VEb21EYXRhS2V5ID09PSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21EYXRhS2V5KCk7XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUuaXNEcm9wWm9uZVdpdGhpblRoaXNHcmlkID0gZnVuY3Rpb24gKGRyYWdnaW5nRXZlbnQpIHtcbiAgICAgICAgdmFyIGdyaWRCb2R5Q29uID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgIHZhciBncmlkR3VpID0gZ3JpZEJvZHlDb24uZ2V0R3VpKCk7XG4gICAgICAgIHZhciBkcm9wWm9uZVRhcmdldCA9IGRyYWdnaW5nRXZlbnQuZHJvcFpvbmVUYXJnZXQ7XG4gICAgICAgIHJldHVybiAhZ3JpZEd1aS5jb250YWlucyhkcm9wWm9uZVRhcmdldCk7XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUub25FbnRlck9yRHJhZ2dpbmcgPSBmdW5jdGlvbiAoZHJhZ2dpbmdFdmVudCkge1xuICAgICAgICAvLyB0aGlzIGV2ZW50IGlzIGZpcmVkIGZvciBlbnRlciBhbmQgbW92ZVxuICAgICAgICB0aGlzLmRpc3BhdGNoR3JpZEV2ZW50KEV2ZW50cy5FVkVOVF9ST1dfRFJBR19NT1ZFLCBkcmFnZ2luZ0V2ZW50KTtcbiAgICAgICAgdGhpcy5sYXN0RHJhZ2dpbmdFdmVudCA9IGRyYWdnaW5nRXZlbnQ7XG4gICAgICAgIHZhciBwaXhlbCA9IHRoaXMubW91c2VFdmVudFNlcnZpY2UuZ2V0Tm9ybWFsaXNlZFBvc2l0aW9uKGRyYWdnaW5nRXZlbnQpLnk7XG4gICAgICAgIHZhciBtYW5hZ2VkRHJhZyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93RHJhZ01hbmFnZWQoKTtcbiAgICAgICAgaWYgKG1hbmFnZWREcmFnKSB7XG4gICAgICAgICAgICB0aGlzLmRvTWFuYWdlZERyYWcoZHJhZ2dpbmdFdmVudCwgcGl4ZWwpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYXV0b1Njcm9sbFNlcnZpY2UuY2hlY2soZHJhZ2dpbmdFdmVudC5ldmVudCk7XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUuZG9NYW5hZ2VkRHJhZyA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50LCBwaXhlbCkge1xuICAgICAgICB2YXIgaXNGcm9tVGhpc0dyaWQgPSB0aGlzLmlzRnJvbVRoaXNHcmlkKGRyYWdnaW5nRXZlbnQpO1xuICAgICAgICB2YXIgbWFuYWdlZERyYWcgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd0RyYWdNYW5hZ2VkKCk7XG4gICAgICAgIHZhciByb3dOb2RlcyA9IGRyYWdnaW5nRXZlbnQuZHJhZ0l0ZW0ucm93Tm9kZXM7XG4gICAgICAgIGlmIChtYW5hZ2VkRHJhZyAmJiB0aGlzLnNob3VsZFByZXZlbnRSb3dNb3ZlKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc01vdmVXaGVuUm93RHJhZ2dpbmcoKSB8fCAhaXNGcm9tVGhpc0dyaWQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0Ryb3Bab25lV2l0aGluVGhpc0dyaWQoZHJhZ2dpbmdFdmVudCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5oaWdobGlnaHRSb3dBdFBpeGVsKHJvd05vZGVzWzBdLCBwaXhlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm1vdmVSb3dzKHJvd05vZGVzLCBwaXhlbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5nZXRSb3dJbmRleE51bWJlciA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHJldHVybiBwYXJzZUludChsYXN0KHJvd05vZGUuZ2V0Um93SW5kZXhTdHJpbmcoKS5zcGxpdCgnLScpKSwgMTApO1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLm1vdmVSb3dBbmRDbGVhckhpZ2hsaWdodCA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBsYXN0SGlnaGxpZ2h0ZWRSb3dOb2RlID0gdGhpcy5jbGllbnRTaWRlUm93TW9kZWwuZ2V0TGFzdEhpZ2hsaWdodGVkUm93Tm9kZSgpO1xuICAgICAgICB2YXIgaXNCZWxvdyA9IGxhc3RIaWdobGlnaHRlZFJvd05vZGUgJiYgbGFzdEhpZ2hsaWdodGVkUm93Tm9kZS5oaWdobGlnaHRlZCA9PT0gUm93SGlnaGxpZ2h0UG9zaXRpb24uQmVsb3c7XG4gICAgICAgIHZhciBwaXhlbCA9IHRoaXMubW91c2VFdmVudFNlcnZpY2UuZ2V0Tm9ybWFsaXNlZFBvc2l0aW9uKGRyYWdnaW5nRXZlbnQpLnk7XG4gICAgICAgIHZhciByb3dOb2RlcyA9IGRyYWdnaW5nRXZlbnQuZHJhZ0l0ZW0ucm93Tm9kZXM7XG4gICAgICAgIHZhciBpbmNyZW1lbnQgPSBpc0JlbG93ID8gMSA6IDA7XG4gICAgICAgIGlmICh0aGlzLmlzRnJvbVRoaXNHcmlkKGRyYWdnaW5nRXZlbnQpKSB7XG4gICAgICAgICAgICByb3dOb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvd05vZGUucm93VG9wIDwgcGl4ZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5jcmVtZW50IC09IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm1vdmVSb3dzKHJvd05vZGVzLCBwaXhlbCwgaW5jcmVtZW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBnZXRSb3dJZEZ1bmNfMSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0lkRnVuYygpO1xuICAgICAgICAgICAgdmFyIGFkZEluZGV4ID0gdGhpcy5jbGllbnRTaWRlUm93TW9kZWwuZ2V0Um93SW5kZXhBdFBpeGVsKHBpeGVsKSArIDE7XG4gICAgICAgICAgICBpZiAodGhpcy5jbGllbnRTaWRlUm93TW9kZWwuZ2V0SGlnaGxpZ2h0UG9zaXRpb24ocGl4ZWwpID09PSBSb3dIaWdobGlnaHRQb3NpdGlvbi5BYm92ZSkge1xuICAgICAgICAgICAgICAgIGFkZEluZGV4LS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC51cGRhdGVSb3dEYXRhKHtcbiAgICAgICAgICAgICAgICBhZGQ6IHJvd05vZGVzXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKG5vZGUpIHsgcmV0dXJuIG5vZGUuZGF0YTsgfSlcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbiAoZGF0YSkgeyByZXR1cm4gIV90aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5nZXRSb3dOb2RlKGdldFJvd0lkRnVuY18xID8gZ2V0Um93SWRGdW5jXzEoeyBkYXRhOiBkYXRhLCBsZXZlbDogMCB9KSA6IGRhdGEuaWQpOyB9KSxcbiAgICAgICAgICAgICAgICBhZGRJbmRleDogYWRkSW5kZXhcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xlYXJSb3dIaWdobGlnaHQoKTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5jbGVhclJvd0hpZ2hsaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jbGllbnRTaWRlUm93TW9kZWwuaGlnaGxpZ2h0Um93QXRQaXhlbChudWxsKTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5tb3ZlUm93cyA9IGZ1bmN0aW9uIChyb3dOb2RlcywgcGl4ZWwsIGluY3JlbWVudCkge1xuICAgICAgICBpZiAoaW5jcmVtZW50ID09PSB2b2lkIDApIHsgaW5jcmVtZW50ID0gMDsgfVxuICAgICAgICB2YXIgcm93V2FzTW92ZWQgPSB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5lbnN1cmVSb3dzQXRQaXhlbChyb3dOb2RlcywgcGl4ZWwsIGluY3JlbWVudCk7XG4gICAgICAgIGlmIChyb3dXYXNNb3ZlZCkge1xuICAgICAgICAgICAgdGhpcy5mb2N1c1NlcnZpY2UuY2xlYXJGb2N1c2VkQ2VsbCgpO1xuICAgICAgICAgICAgaWYgKHRoaXMucmFuZ2VTZXJ2aWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yYW5nZVNlcnZpY2UucmVtb3ZlQWxsQ2VsbFJhbmdlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUuYWRkUm93RHJvcFpvbmUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghcGFyYW1zLmdldENvbnRhaW5lcigpKSB7XG4gICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBhZGRSb3dEcm9wWm9uZSAtIEEgY29udGFpbmVyIHRhcmdldCBuZWVkcyB0byBiZSBwcm92aWRlZCcpOyB9LCAnYWRkLWRyb3Atem9uZS1lbXB0eS10YXJnZXQnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5kcmFnQW5kRHJvcFNlcnZpY2UuZmluZEV4dGVybmFsWm9uZShwYXJhbXMpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGFkZFJvd0Ryb3Bab25lIC0gdGFyZ2V0IGFscmVhZHkgZXhpc3RzIGluIHRoZSBsaXN0IG9mIERyb3Bab25lcy4gVXNlIGByZW1vdmVSb3dEcm9wWm9uZWAgYmVmb3JlIGFkZGluZyBpdCBhZ2Fpbi4nKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJvY2Vzc2VkUGFyYW1zID0ge1xuICAgICAgICAgICAgZ2V0Q29udGFpbmVyOiBwYXJhbXMuZ2V0Q29udGFpbmVyXG4gICAgICAgIH07XG4gICAgICAgIGlmIChwYXJhbXMuZnJvbUdyaWQpIHtcbiAgICAgICAgICAgIHBhcmFtcy5mcm9tR3JpZCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHByb2Nlc3NlZFBhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChwYXJhbXMub25EcmFnRW50ZXIpIHtcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRQYXJhbXMub25EcmFnRW50ZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXMub25EcmFnRW50ZXIoX3RoaXMuZHJhZ2dpbmdUb1Jvd0RyYWdFdmVudChFdmVudHMuRVZFTlRfUk9XX0RSQUdfRU5URVIsIGUpKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5vbkRyYWdMZWF2ZSkge1xuICAgICAgICAgICAgICAgIHByb2Nlc3NlZFBhcmFtcy5vbkRyYWdMZWF2ZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtcy5vbkRyYWdMZWF2ZShfdGhpcy5kcmFnZ2luZ1RvUm93RHJhZ0V2ZW50KEV2ZW50cy5FVkVOVF9ST1dfRFJBR19MRUFWRSwgZSkpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFyYW1zLm9uRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgICAgICBwcm9jZXNzZWRQYXJhbXMub25EcmFnZ2luZyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtcy5vbkRyYWdnaW5nKF90aGlzLmRyYWdnaW5nVG9Sb3dEcmFnRXZlbnQoRXZlbnRzLkVWRU5UX1JPV19EUkFHX01PVkUsIGUpKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcmFtcy5vbkRyYWdTdG9wKSB7XG4gICAgICAgICAgICAgICAgcHJvY2Vzc2VkUGFyYW1zLm9uRHJhZ1N0b3AgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXMub25EcmFnU3RvcChfdGhpcy5kcmFnZ2luZ1RvUm93RHJhZ0V2ZW50KEV2ZW50cy5FVkVOVF9ST1dfRFJBR19FTkQsIGUpKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLmFkZERyb3BUYXJnZXQoX19hc3NpZ24kNih7IGlzSW50ZXJlc3RlZEluOiBmdW5jdGlvbiAodHlwZSkgeyByZXR1cm4gdHlwZSA9PT0gRHJhZ1NvdXJjZVR5cGUuUm93RHJhZzsgfSwgZ2V0SWNvbk5hbWU6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIERyYWdBbmREcm9wU2VydmljZS5JQ09OX01PVkU7IH0sIGV4dGVybmFsOiB0cnVlIH0sIHByb2Nlc3NlZFBhcmFtcykpO1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLmdldFJvd0Ryb3Bab25lID0gZnVuY3Rpb24gKGV2ZW50cykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZ2V0Q29udGFpbmVyID0gdGhpcy5nZXRDb250YWluZXIuYmluZCh0aGlzKTtcbiAgICAgICAgdmFyIG9uRHJhZ0VudGVyID0gdGhpcy5vbkRyYWdFbnRlci5iaW5kKHRoaXMpO1xuICAgICAgICB2YXIgb25EcmFnTGVhdmUgPSB0aGlzLm9uRHJhZ0xlYXZlLmJpbmQodGhpcyk7XG4gICAgICAgIHZhciBvbkRyYWdnaW5nID0gdGhpcy5vbkRyYWdnaW5nLmJpbmQodGhpcyk7XG4gICAgICAgIHZhciBvbkRyYWdTdG9wID0gdGhpcy5vbkRyYWdTdG9wLmJpbmQodGhpcyk7XG4gICAgICAgIGlmICghZXZlbnRzKSB7XG4gICAgICAgICAgICByZXR1cm4geyBnZXRDb250YWluZXI6IGdldENvbnRhaW5lciwgb25EcmFnRW50ZXI6IG9uRHJhZ0VudGVyLCBvbkRyYWdMZWF2ZTogb25EcmFnTGVhdmUsIG9uRHJhZ2dpbmc6IG9uRHJhZ2dpbmcsIG9uRHJhZ1N0b3A6IG9uRHJhZ1N0b3AsIC8qIEBwcml2YXRlICovIGZyb21HcmlkOiB0cnVlIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGdldENvbnRhaW5lcjogZ2V0Q29udGFpbmVyLFxuICAgICAgICAgICAgb25EcmFnRW50ZXI6IGV2ZW50cy5vbkRyYWdFbnRlclxuICAgICAgICAgICAgICAgID8gKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9uRHJhZ0VudGVyKGUpO1xuICAgICAgICAgICAgICAgICAgICBldmVudHMub25EcmFnRW50ZXIoX3RoaXMuZHJhZ2dpbmdUb1Jvd0RyYWdFdmVudChFdmVudHMuRVZFTlRfUk9XX0RSQUdfRU5URVIsIGUpKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIDogb25EcmFnRW50ZXIsXG4gICAgICAgICAgICBvbkRyYWdMZWF2ZTogZXZlbnRzLm9uRHJhZ0xlYXZlXG4gICAgICAgICAgICAgICAgPyAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb25EcmFnTGVhdmUoZSk7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50cy5vbkRyYWdMZWF2ZShfdGhpcy5kcmFnZ2luZ1RvUm93RHJhZ0V2ZW50KEV2ZW50cy5FVkVOVF9ST1dfRFJBR19MRUFWRSwgZSkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgOiBvbkRyYWdMZWF2ZSxcbiAgICAgICAgICAgIG9uRHJhZ2dpbmc6IGV2ZW50cy5vbkRyYWdnaW5nXG4gICAgICAgICAgICAgICAgPyAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb25EcmFnZ2luZyhlKTtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRzLm9uRHJhZ2dpbmcoX3RoaXMuZHJhZ2dpbmdUb1Jvd0RyYWdFdmVudChFdmVudHMuRVZFTlRfUk9XX0RSQUdfTU9WRSwgZSkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgOiBvbkRyYWdnaW5nLFxuICAgICAgICAgICAgb25EcmFnU3RvcDogZXZlbnRzLm9uRHJhZ1N0b3BcbiAgICAgICAgICAgICAgICA/IChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBvbkRyYWdTdG9wKGUpO1xuICAgICAgICAgICAgICAgICAgICBldmVudHMub25EcmFnU3RvcChfdGhpcy5kcmFnZ2luZ1RvUm93RHJhZ0V2ZW50KEV2ZW50cy5FVkVOVF9ST1dfRFJBR19FTkQsIGUpKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIDogb25EcmFnU3RvcCxcbiAgICAgICAgICAgIGZyb21HcmlkOiB0cnVlIC8qIEBwcml2YXRlICovXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUuZHJhZ2dpbmdUb1Jvd0RyYWdFdmVudCA9IGZ1bmN0aW9uICh0eXBlLCBkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIHZhciB5Tm9ybWFsaXNlZCA9IHRoaXMubW91c2VFdmVudFNlcnZpY2UuZ2V0Tm9ybWFsaXNlZFBvc2l0aW9uKGRyYWdnaW5nRXZlbnQpLnk7XG4gICAgICAgIHZhciBtb3VzZUlzUGFzdExhc3RSb3cgPSB5Tm9ybWFsaXNlZCA+IHRoaXMucGFnaW5hdGlvblByb3h5LmdldEN1cnJlbnRQYWdlSGVpZ2h0KCk7XG4gICAgICAgIHZhciBvdmVySW5kZXggPSAtMTtcbiAgICAgICAgdmFyIG92ZXJOb2RlO1xuICAgICAgICBpZiAoIW1vdXNlSXNQYXN0TGFzdFJvdykge1xuICAgICAgICAgICAgb3ZlckluZGV4ID0gdGhpcy5yb3dNb2RlbC5nZXRSb3dJbmRleEF0UGl4ZWwoeU5vcm1hbGlzZWQpO1xuICAgICAgICAgICAgb3Zlck5vZGUgPSB0aGlzLnJvd01vZGVsLmdldFJvdyhvdmVySW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2RGlyZWN0aW9uU3RyaW5nO1xuICAgICAgICBzd2l0Y2ggKGRyYWdnaW5nRXZlbnQudkRpcmVjdGlvbikge1xuICAgICAgICAgICAgY2FzZSBWZXJ0aWNhbERpcmVjdGlvbi5Eb3duOlxuICAgICAgICAgICAgICAgIHZEaXJlY3Rpb25TdHJpbmcgPSAnZG93bic7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFZlcnRpY2FsRGlyZWN0aW9uLlVwOlxuICAgICAgICAgICAgICAgIHZEaXJlY3Rpb25TdHJpbmcgPSAndXAnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB2RGlyZWN0aW9uU3RyaW5nID0gbnVsbDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgICAgICBldmVudDogZHJhZ2dpbmdFdmVudC5ldmVudCxcbiAgICAgICAgICAgIG5vZGU6IGRyYWdnaW5nRXZlbnQuZHJhZ0l0ZW0ucm93Tm9kZSxcbiAgICAgICAgICAgIG5vZGVzOiBkcmFnZ2luZ0V2ZW50LmRyYWdJdGVtLnJvd05vZGVzLFxuICAgICAgICAgICAgb3ZlckluZGV4OiBvdmVySW5kZXgsXG4gICAgICAgICAgICBvdmVyTm9kZTogb3Zlck5vZGUsXG4gICAgICAgICAgICB5OiB5Tm9ybWFsaXNlZCxcbiAgICAgICAgICAgIHZEaXJlY3Rpb246IHZEaXJlY3Rpb25TdHJpbmdcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIGV2ZW50O1xuICAgIH07XG4gICAgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLmRpc3BhdGNoR3JpZEV2ZW50ID0gZnVuY3Rpb24gKHR5cGUsIGRyYWdnaW5nRXZlbnQpIHtcbiAgICAgICAgdmFyIGV2ZW50ID0gdGhpcy5kcmFnZ2luZ1RvUm93RHJhZ0V2ZW50KHR5cGUsIGRyYWdnaW5nRXZlbnQpO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5vbkRyYWdMZWF2ZSA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hHcmlkRXZlbnQoRXZlbnRzLkVWRU5UX1JPV19EUkFHX0xFQVZFLCBkcmFnZ2luZ0V2ZW50KTtcbiAgICAgICAgdGhpcy5zdG9wRHJhZ2dpbmcoZHJhZ2dpbmdFdmVudCk7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd0RyYWdNYW5hZ2VkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJSb3dIaWdobGlnaHQoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5pc0Zyb21UaGlzR3JpZChkcmFnZ2luZ0V2ZW50KSkge1xuICAgICAgICAgICAgdGhpcy5pc011bHRpUm93RHJhZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUub25EcmFnU3RvcCA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hHcmlkRXZlbnQoRXZlbnRzLkVWRU5UX1JPV19EUkFHX0VORCwgZHJhZ2dpbmdFdmVudCk7XG4gICAgICAgIHRoaXMuc3RvcERyYWdnaW5nKGRyYWdnaW5nRXZlbnQpO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSb3dEcmFnTWFuYWdlZCgpICYmXG4gICAgICAgICAgICAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc01vdmVXaGVuUm93RHJhZ2dpbmcoKSB8fCAhdGhpcy5pc0Zyb21UaGlzR3JpZChkcmFnZ2luZ0V2ZW50KSkgJiZcbiAgICAgICAgICAgICF0aGlzLmlzRHJvcFpvbmVXaXRoaW5UaGlzR3JpZChkcmFnZ2luZ0V2ZW50KSkge1xuICAgICAgICAgICAgdGhpcy5tb3ZlUm93QW5kQ2xlYXJIaWdobGlnaHQoZHJhZ2dpbmdFdmVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZS5zdG9wRHJhZ2dpbmcgPSBmdW5jdGlvbiAoZHJhZ2dpbmdFdmVudCkge1xuICAgICAgICB0aGlzLmF1dG9TY3JvbGxTZXJ2aWNlLmVuc3VyZUNsZWFyZWQoKTtcbiAgICAgICAgdGhpcy5nZXRSb3dOb2RlcyhkcmFnZ2luZ0V2ZW50KS5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICByb3dOb2RlLnNldERyYWdnaW5nKGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFRKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnQW5kRHJvcFNlcnZpY2UnKVxuICAgIF0sIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZSwgXCJkcmFnQW5kRHJvcFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFRKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dNb2RlbCcpXG4gICAgXSwgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLCBcInJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUShbXG4gICAgICAgIEF1dG93aXJlZCgncGFnaW5hdGlvblByb3h5JylcbiAgICBdLCBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUsIFwicGFnaW5hdGlvblByb3h5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZvY3VzU2VydmljZScpXG4gICAgXSwgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVEoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NvcnRDb250cm9sbGVyJylcbiAgICBdLCBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUsIFwic29ydENvbnRyb2xsZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFRKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUsIFwiZmlsdGVyTWFuYWdlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVEoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NlbGVjdGlvblNlcnZpY2UnKVxuICAgIF0sIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZSwgXCJzZWxlY3Rpb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUShbXG4gICAgICAgIEF1dG93aXJlZCgnbW91c2VFdmVudFNlcnZpY2UnKVxuICAgIF0sIFJvd0RyYWdGZWF0dXJlLnByb3RvdHlwZSwgXCJtb3VzZUV2ZW50U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgUm93RHJhZ0ZlYXR1cmUucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVEoW1xuICAgICAgICBPcHRpb25hbCgncmFuZ2VTZXJ2aWNlJylcbiAgICBdLCBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUsIFwicmFuZ2VTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBSb3dEcmFnRmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gUm93RHJhZ0ZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMjAgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFQID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgUm93QW5pbWF0aW9uQ3NzQ2xhc3NlcztcbihmdW5jdGlvbiAoUm93QW5pbWF0aW9uQ3NzQ2xhc3Nlcykge1xuICAgIFJvd0FuaW1hdGlvbkNzc0NsYXNzZXNbXCJBTklNQVRJT05fT05cIl0gPSBcImFnLXJvdy1hbmltYXRpb25cIjtcbiAgICBSb3dBbmltYXRpb25Dc3NDbGFzc2VzW1wiQU5JTUFUSU9OX09GRlwiXSA9IFwiYWctcm93LW5vLWFuaW1hdGlvblwiO1xufSkoUm93QW5pbWF0aW9uQ3NzQ2xhc3NlcyB8fCAoUm93QW5pbWF0aW9uQ3NzQ2xhc3NlcyA9IHt9KSk7XG52YXIgQ1NTX0NMQVNTX0NFTExfU0VMRUNUQUJMRSA9ICdhZy1zZWxlY3RhYmxlJztcbnZhciBDU1NfQ0xBU1NfRk9SQ0VfVkVSVElDQUxfU0NST0xMID0gJ2FnLWZvcmNlLXZlcnRpY2FsLXNjcm9sbCc7XG52YXIgQ1NTX0NMQVNTX0NPTFVNTl9NT1ZJTkcgPSAnYWctY29sdW1uLW1vdmluZyc7XG52YXIgR3JpZEJvZHlDdHJsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQyMChHcmlkQm9keUN0cmwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gR3JpZEJvZHlDdHJsKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3RpY2t5VG9wSGVpZ2h0ID0gMDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLmdldFNjcm9sbEZlYXR1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvZHlTY3JvbGxGZWF0dXJlO1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5nZXRCb2R5Vmlld3BvcnRFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lQm9keVZpZXdwb3J0O1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGNvbXAsIGVHcmlkQm9keSwgZUJvZHlWaWV3cG9ydCwgZVRvcCwgZUJvdHRvbSwgZVN0aWNreVRvcCkge1xuICAgICAgICB0aGlzLmNvbXAgPSBjb21wO1xuICAgICAgICB0aGlzLmVHcmlkQm9keSA9IGVHcmlkQm9keTtcbiAgICAgICAgdGhpcy5lQm9keVZpZXdwb3J0ID0gZUJvZHlWaWV3cG9ydDtcbiAgICAgICAgdGhpcy5lVG9wID0gZVRvcDtcbiAgICAgICAgdGhpcy5lQm90dG9tID0gZUJvdHRvbTtcbiAgICAgICAgdGhpcy5lU3RpY2t5VG9wID0gZVN0aWNreVRvcDtcbiAgICAgICAgdGhpcy5zZXRDZWxsVGV4dFNlbGVjdGlvbih0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUNlbGxUZXh0U2VsZWN0KCkpO1xuICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBMYXlvdXRGZWF0dXJlKHRoaXMuY29tcCkpO1xuICAgICAgICB0aGlzLmJvZHlTY3JvbGxGZWF0dXJlID0gdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgR3JpZEJvZHlTY3JvbGxGZWF0dXJlKHRoaXMuZUJvZHlWaWV3cG9ydCkpO1xuICAgICAgICB0aGlzLmFkZFJvd0RyYWdMaXN0ZW5lcigpO1xuICAgICAgICB0aGlzLnNldHVwUm93QW5pbWF0aW9uQ3NzQ2xhc3MoKTtcbiAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVycygpO1xuICAgICAgICB0aGlzLmFkZEZvY3VzTGlzdGVuZXJzKFtlVG9wLCBlQm9keVZpZXdwb3J0LCBlQm90dG9tLCBlU3RpY2t5VG9wXSk7XG4gICAgICAgIHRoaXMub25HcmlkQ29sdW1uc0NoYW5nZWQoKTtcbiAgICAgICAgdGhpcy5hZGRCb2R5Vmlld3BvcnRMaXN0ZW5lcigpO1xuICAgICAgICB0aGlzLnNldEZsb2F0aW5nSGVpZ2h0cygpO1xuICAgICAgICB0aGlzLmRpc2FibGVCcm93c2VyRHJhZ2dpbmcoKTtcbiAgICAgICAgdGhpcy5hZGRTdG9wRWRpdGluZ1doZW5HcmlkTG9zZXNGb2N1cygpO1xuICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlckdyaWRCb2R5Q3RybCh0aGlzKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuZ2V0Q29tcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcDtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfR1JJRF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMub25HcmlkQ29sdW1uc0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfU0NST0xMX1ZJU0lCSUxJVFlfQ0hBTkdFRCwgdGhpcy5vblNjcm9sbFZpc2liaWxpdHlDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BJTk5FRF9ST1dfREFUQV9DSEFOR0VELCB0aGlzLm9uUGlubmVkUm93RGF0YUNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfSEVBREVSX0hFSUdIVF9DSEFOR0VELCB0aGlzLm9uSGVhZGVySGVpZ2h0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuYWRkRm9jdXNMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoZWxlbWVudHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGVsZW1lbnQsICdmb2N1c2luJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgICAgICAgICAgLy8gZWxlbWVudCBiZWluZyBmb2N1c2VkIGlzIG5lc3RlZD9cbiAgICAgICAgICAgICAgICB2YXIgaXNGb2N1c2VkRWxlbWVudE5lc3RlZCA9IGlzRWxlbWVudENoaWxkT2ZDbGFzcyh0YXJnZXQsICdhZy1yb290JywgZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKCdhZy1oYXMtZm9jdXMnLCAhaXNGb2N1c2VkRWxlbWVudE5lc3RlZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlbGVtZW50LCAnZm9jdXNvdXQnLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldCwgcmVsYXRlZFRhcmdldCA9IGUucmVsYXRlZFRhcmdldDtcbiAgICAgICAgICAgICAgICB2YXIgZ3JpZENvbnRhaW5SZWxhdGVkVGFyZ2V0ID0gZWxlbWVudC5jb250YWlucyhyZWxhdGVkVGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgaXNOZXN0ZWRSZWxhdGVkVGFyZ2V0ID0gaXNFbGVtZW50Q2hpbGRPZkNsYXNzKHJlbGF0ZWRUYXJnZXQsICdhZy1yb290JywgZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgdmFyIGlzTmVzdGVkVGFyZ2V0ID0gaXNFbGVtZW50Q2hpbGRPZkNsYXNzKHRhcmdldCwgJ2FnLXJvb3QnLCBlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAvLyBlbGVtZW50IGxvc2luZyBmb2N1cyBiZWxvbmdzIHRvIGEgbmVzdGVkIGdyaWQsXG4gICAgICAgICAgICAgICAgLy8gaXQgc2hvdWxkIG5vdCBiZSBoYW5kbGVkIGhlcmUuXG4gICAgICAgICAgICAgICAgaWYgKGlzTmVzdGVkVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gdGhlIGdyaWQgZG9lcyBub3QgY29udGFpbiwgb3IgdGhlIGZvY3VzIGVsZW1lbnQgaXMgd2l0aGluXG4gICAgICAgICAgICAgICAgLy8gYSBuZXN0ZWQgZ3JpZFxuICAgICAgICAgICAgICAgIGlmICghZ3JpZENvbnRhaW5SZWxhdGVkVGFyZ2V0IHx8IGlzTmVzdGVkUmVsYXRlZFRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ2FnLWhhcy1mb2N1cycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIHVzZWQgYnkgQ29sdW1uQW5pbWF0aW9uU2VydmljZVxuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuc2V0Q29sdW1uTW92aW5nQ3NzID0gZnVuY3Rpb24gKG1vdmluZykge1xuICAgICAgICB0aGlzLmNvbXAuc2V0Q29sdW1uTW92aW5nQ3NzKG1vdmluZyA/IENTU19DTEFTU19DT0xVTU5fTU9WSU5HIDogbnVsbCwgbW92aW5nKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuc2V0Q2VsbFRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoc2VsZWN0YWJsZSkge1xuICAgICAgICBpZiAoc2VsZWN0YWJsZSA9PT0gdm9pZCAwKSB7IHNlbGVjdGFibGUgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgY3NzQ2xhc3MgPSBzZWxlY3RhYmxlID8gQ1NTX0NMQVNTX0NFTExfU0VMRUNUQUJMRSA6IG51bGw7XG4gICAgICAgIHRoaXMuY29tcC5zZXRDZWxsU2VsZWN0YWJsZUNzcyhjc3NDbGFzcywgc2VsZWN0YWJsZSk7XG4gICAgfTtcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLm9uU2Nyb2xsVmlzaWJpbGl0eUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB2aXNpYmxlID0gdGhpcy5zY3JvbGxWaXNpYmxlU2VydmljZS5pc1ZlcnRpY2FsU2Nyb2xsU2hvd2luZygpO1xuICAgICAgICB0aGlzLnNldFZlcnRpY2FsU2Nyb2xsUGFkZGluZ1Zpc2libGUodmlzaWJsZSk7XG4gICAgICAgIHRoaXMuc2V0U3RpY2t5VG9wV2lkdGgodmlzaWJsZSk7XG4gICAgfTtcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLm9uR3JpZENvbHVtbnNDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sdW1ucyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsR3JpZENvbHVtbnMoKTtcbiAgICAgICAgdGhpcy5jb21wLnNldENvbHVtbkNvdW50KGNvbHVtbnMgPyBjb2x1bW5zLmxlbmd0aCA6IDApO1xuICAgIH07XG4gICAgLy8gaWYgd2UgZG8gbm90IGRvIHRoaXMsIHRoZW4gdGhlIHVzZXIgY2FuIHNlbGVjdCBhIHBpYyBpbiB0aGUgZ3JpZCAoZWcgYW4gaW1hZ2UgaW4gYSBjdXN0b20gY2VsbCByZW5kZXJlcilcbiAgICAvLyBhbmQgdGhlbiB0aGF0IHdpbGwgc3RhcnQgdGhlIGJyb3dzZXIgbmF0aXZlIGRyYWcgbicgZHJvcCwgd2hpY2ggbWVzc2VzIHVwIHdpdGggb3VyIG93biBkcmFnIGFuZCBkcm9wLlxuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuZGlzYWJsZUJyb3dzZXJEcmFnZ2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lR3JpZEJvZHksICdkcmFnc3RhcnQnLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC50YXJnZXQgaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5hZGRTdG9wRWRpdGluZ1doZW5HcmlkTG9zZXNGb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N0b3BFZGl0aW5nV2hlbkNlbGxzTG9zZUZvY3VzKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZm9jdXNPdXRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgZWxlbWVudCB0aGUgZm9jdXMgaXMgbW92aW5nIHRvXG4gICAgICAgICAgICB2YXIgZWxlbWVudFdpdGhGb2N1cyA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQ7XG4gICAgICAgICAgICBpZiAoZ2V0VGFiSW5kZXgoZWxlbWVudFdpdGhGb2N1cykgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5yb3dSZW5kZXJlci5zdG9wRWRpdGluZygpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjbGlja0luc2lkZUdyaWQgPSBcbiAgICAgICAgICAgIC8vIHNlZSBpZiBjbGljayBjYW1lIGZyb20gaW5zaWRlIHRoZSB2aWV3cG9ydHNcbiAgICAgICAgICAgIHZpZXdwb3J0cy5zb21lKGZ1bmN0aW9uICh2aWV3cG9ydCkgeyByZXR1cm4gdmlld3BvcnQuY29udGFpbnMoZWxlbWVudFdpdGhGb2N1cyk7IH0pXG4gICAgICAgICAgICAgICAgLy8gYW5kIGFsc28gdGhhdCBpdCdzIG5vdCBmcm9tIGEgZGV0YWlsIGdyaWRcbiAgICAgICAgICAgICAgICAmJiBfdGhpcy5tb3VzZUV2ZW50U2VydmljZS5pc0VsZW1lbnRJblRoaXNHcmlkKGVsZW1lbnRXaXRoRm9jdXMpO1xuICAgICAgICAgICAgaWYgKCFjbGlja0luc2lkZUdyaWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcG9wdXBTZXJ2aWNlID0gX3RoaXMucG9wdXBTZXJ2aWNlO1xuICAgICAgICAgICAgICAgIGNsaWNrSW5zaWRlR3JpZCA9XG4gICAgICAgICAgICAgICAgICAgIHBvcHVwU2VydmljZS5nZXRBY3RpdmVQb3B1cHMoKS5zb21lKGZ1bmN0aW9uIChwb3B1cCkgeyByZXR1cm4gcG9wdXAuY29udGFpbnMoZWxlbWVudFdpdGhGb2N1cyk7IH0pIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3B1cFNlcnZpY2UuaXNFbGVtZW50V2l0aGluQ3VzdG9tUG9wdXAoZWxlbWVudFdpdGhGb2N1cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNsaWNrSW5zaWRlR3JpZCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnJvd1JlbmRlcmVyLnN0b3BFZGl0aW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciB2aWV3cG9ydHMgPSBbdGhpcy5lQm9keVZpZXdwb3J0LCB0aGlzLmVCb3R0b20sIHRoaXMuZVRvcCwgdGhpcy5lU3RpY2t5VG9wXTtcbiAgICAgICAgdmlld3BvcnRzLmZvckVhY2goZnVuY3Rpb24gKHZpZXdwb3J0KSB7IHJldHVybiBfdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodmlld3BvcnQsICdmb2N1c291dCcsIGZvY3VzT3V0TGlzdGVuZXIpOyB9KTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUudXBkYXRlUm93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBoZWFkZXJDb3VudCA9IHRoaXMuaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UuZ2V0SGVhZGVyUm93Q291bnQoKTtcbiAgICAgICAgdmFyIHJvd0NvdW50ID0gdGhpcy5yb3dNb2RlbC5pc0xhc3RSb3dJbmRleEtub3duKCkgPyB0aGlzLnJvd01vZGVsLmdldFJvd0NvdW50KCkgOiAtMTtcbiAgICAgICAgdmFyIHRvdGFsID0gcm93Q291bnQgPT09IC0xID8gLTEgOiAoaGVhZGVyQ291bnQgKyByb3dDb3VudCk7XG4gICAgICAgIHRoaXMuY29tcC5zZXRSb3dDb3VudCh0b3RhbCk7XG4gICAgfTtcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLnJlZ2lzdGVyQm9keVZpZXdwb3J0UmVzaXplTGlzdGVuZXIgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5jb21wLnJlZ2lzdGVyQm9keVZpZXdwb3J0UmVzaXplTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5zZXRWZXJ0aWNhbFNjcm9sbFBhZGRpbmdWaXNpYmxlID0gZnVuY3Rpb24gKHZpc2libGUpIHtcbiAgICAgICAgdmFyIG92ZXJmbG93WSA9IHZpc2libGUgPyAnc2Nyb2xsJyA6ICdoaWRkZW4nO1xuICAgICAgICB0aGlzLmNvbXAuc2V0UGlubmVkVG9wQm90dG9tT3ZlcmZsb3dZKG92ZXJmbG93WSk7XG4gICAgfTtcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLmlzVmVydGljYWxTY3JvbGxTaG93aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2hvdyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQWx3YXlzU2hvd1ZlcnRpY2FsU2Nyb2xsKCk7XG4gICAgICAgIHZhciBjc3NDbGFzcyA9IHNob3cgPyBDU1NfQ0xBU1NfRk9SQ0VfVkVSVElDQUxfU0NST0xMIDogbnVsbDtcbiAgICAgICAgdmFyIGFsbG93VmVydGljYWxTY3JvbGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21MYXlvdXQoKSA9PT0gQ29uc3RhbnRzLkRPTV9MQVlPVVRfTk9STUFMO1xuICAgICAgICB0aGlzLmNvbXAuc2V0QWx3YXlzVmVydGljYWxTY3JvbGxDbGFzcyhjc3NDbGFzcywgc2hvdyk7XG4gICAgICAgIHJldHVybiBzaG93IHx8IChhbGxvd1ZlcnRpY2FsU2Nyb2xsICYmIGlzVmVydGljYWxTY3JvbGxTaG93aW5nKHRoaXMuZUJvZHlWaWV3cG9ydCkpO1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5zZXR1cFJvd0FuaW1hdGlvbkNzc0NsYXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyB3ZSBkb24ndCB3YW50IHRvIHVzZSByb3cgYW5pbWF0aW9uIGlmIHNjYWxpbmcsIGFzIHJvd3MganVtcCBzdHJhbmdlbHkgYXMgeW91IHNjcm9sbCxcbiAgICAgICAgICAgIC8vIHdoZW4gc2NhbGluZyBhbmQgZG9pbmcgcm93IGFuaW1hdGlvbi5cbiAgICAgICAgICAgIHZhciBhbmltYXRlUm93cyA9IF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0FuaW1hdGVSb3dzKCkgJiYgIV90aGlzLnJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UuaXNTdHJldGNoaW5nKCk7XG4gICAgICAgICAgICB2YXIgYW5pbWF0ZVJvd3NDc3NDbGFzcyA9IGFuaW1hdGVSb3dzID8gUm93QW5pbWF0aW9uQ3NzQ2xhc3Nlcy5BTklNQVRJT05fT04gOiBSb3dBbmltYXRpb25Dc3NDbGFzc2VzLkFOSU1BVElPTl9PRkY7XG4gICAgICAgICAgICBfdGhpcy5jb21wLnNldFJvd0FuaW1hdGlvbkNzc09uQm9keVZpZXdwb3J0KGFuaW1hdGVSb3dzQ3NzQ2xhc3MsIGFuaW1hdGVSb3dzKTtcbiAgICAgICAgfTtcbiAgICAgICAgbGlzdGVuZXIoKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9IRUlHSFRfU0NBTEVfQ0hBTkdFRCwgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5nZXRHcmlkQm9keUVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVHcmlkQm9keTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuYWRkQm9keVZpZXdwb3J0TGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gbGlzdGVuIGZvciBjbGlja3MgZGlyZWN0bHkgb24gdGhlIGVCb2R5Vmlld3BvcnQsIHNvIHRoZSB1c2VyIGhhcyBhIHdheSBvZiBzaG93aW5nXG4gICAgICAgIC8vIHRoZSBjb250ZXh0IG1lbnUgaWYgbm8gcm93cyBvciBjb2x1bW5zIGFyZSBkaXNwbGF5ZWQsIG9yIHVzZXIgc2ltcGx5IGNsaWNrcyBvdXRzaWRlIG9mIGEgY2VsbFxuICAgICAgICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbiAobW91c2VFdmVudCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1ByZXZlbnREZWZhdWx0T25Db250ZXh0TWVudSgpKSB7XG4gICAgICAgICAgICAgICAgbW91c2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHRhcmdldCA9IG1vdXNlRXZlbnQudGFyZ2V0O1xuICAgICAgICAgICAgaWYgKHRhcmdldCA9PT0gX3RoaXMuZUJvZHlWaWV3cG9ydCB8fCB0YXJnZXQgPT09IF90aGlzLmN0cmxzU2VydmljZS5nZXRDZW50ZXJSb3dDb250YWluZXJDdHJsKCkuZ2V0Vmlld3BvcnRFbGVtZW50KCkpIHtcbiAgICAgICAgICAgICAgICAvLyBzaG93IGl0XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbnRleHRNZW51RmFjdG9yeSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb250ZXh0TWVudUZhY3Rvcnkub25Db250ZXh0TWVudShtb3VzZUV2ZW50LCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBfdGhpcy5lR3JpZEJvZHkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lQm9keVZpZXdwb3J0LCAnY29udGV4dG1lbnUnLCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUJvZHlWaWV3cG9ydCwgJ3doZWVsJywgdGhpcy5vbkJvZHlWaWV3cG9ydFdoZWVsLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVTdGlja3lUb3AsICd3aGVlbCcsIHRoaXMub25TdGlja3lUb3BXaGVlbC5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUub25Cb2R5Vmlld3BvcnRXaGVlbCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1Njcm9sbFdoZW5Qb3B1cHNBcmVPcGVuKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wb3B1cFNlcnZpY2UuaGFzQW5jaG9yZWRQb3B1cCgpKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUub25TdGlja3lUb3BXaGVlbCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKGUub2Zmc2V0WSkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxWZXJ0aWNhbGx5KGUuZGVsdGFZKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5nZXRHdWkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVHcmlkQm9keTtcbiAgICB9O1xuICAgIC8vIGNhbGxlZCBieSByb3dEcmFnRmVhdHVyZVxuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuc2Nyb2xsVmVydGljYWxseSA9IGZ1bmN0aW9uIChwaXhlbHMpIHtcbiAgICAgICAgdmFyIG9sZFNjcm9sbFBvc2l0aW9uID0gdGhpcy5lQm9keVZpZXdwb3J0LnNjcm9sbFRvcDtcbiAgICAgICAgdGhpcy5ib2R5U2Nyb2xsRmVhdHVyZS5zZXRWZXJ0aWNhbFNjcm9sbFBvc2l0aW9uKG9sZFNjcm9sbFBvc2l0aW9uICsgcGl4ZWxzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUJvZHlWaWV3cG9ydC5zY3JvbGxUb3AgLSBvbGRTY3JvbGxQb3NpdGlvbjtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuYWRkUm93RHJhZ0xpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJvd0RyYWdGZWF0dXJlID0gdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgUm93RHJhZ0ZlYXR1cmUodGhpcy5lQm9keVZpZXdwb3J0KSk7XG4gICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLmFkZERyb3BUYXJnZXQodGhpcy5yb3dEcmFnRmVhdHVyZSk7XG4gICAgfTtcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLmdldFJvd0RyYWdGZWF0dXJlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dEcmFnRmVhdHVyZTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUub25QaW5uZWRSb3dEYXRhQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRGbG9hdGluZ0hlaWdodHMoKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuc2V0RmxvYXRpbmdIZWlnaHRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGlubmVkUm93TW9kZWwgPSB0aGlzLnBpbm5lZFJvd01vZGVsO1xuICAgICAgICB2YXIgZmxvYXRpbmdUb3BIZWlnaHQgPSBwaW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRUb3BUb3RhbEhlaWdodCgpO1xuICAgICAgICBpZiAoZmxvYXRpbmdUb3BIZWlnaHQpIHtcbiAgICAgICAgICAgIC8vIGFkZGluZyAxcHggZm9yIGNlbGwgYm90dG9tIGJvcmRlclxuICAgICAgICAgICAgZmxvYXRpbmdUb3BIZWlnaHQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmxvYXRpbmdCb3R0b21IZWlnaHQgPSBwaW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Ub3RhbEhlaWdodCgpO1xuICAgICAgICBpZiAoZmxvYXRpbmdCb3R0b21IZWlnaHQpIHtcbiAgICAgICAgICAgIC8vIGFkZGluZyAxcHggZm9yIGNlbGwgYm90dG9tIGJvcmRlclxuICAgICAgICAgICAgZmxvYXRpbmdCb3R0b21IZWlnaHQgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbXAuc2V0VG9wSGVpZ2h0KGZsb2F0aW5nVG9wSGVpZ2h0KTtcbiAgICAgICAgdGhpcy5jb21wLnNldEJvdHRvbUhlaWdodChmbG9hdGluZ0JvdHRvbUhlaWdodCk7XG4gICAgICAgIHRoaXMuY29tcC5zZXRUb3BEaXNwbGF5KGZsb2F0aW5nVG9wSGVpZ2h0ID8gJ2luaGVyaXQnIDogJ25vbmUnKTtcbiAgICAgICAgdGhpcy5jb21wLnNldEJvdHRvbURpc3BsYXkoZmxvYXRpbmdCb3R0b21IZWlnaHQgPyAnaW5oZXJpdCcgOiAnbm9uZScpO1xuICAgICAgICB0aGlzLnNldFN0aWNreVRvcE9mZnNldFRvcCgpO1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5zZXRTdGlja3lUb3BIZWlnaHQgPSBmdW5jdGlvbiAoaGVpZ2h0KSB7XG4gICAgICAgIGlmIChoZWlnaHQgPT09IHZvaWQgMCkgeyBoZWlnaHQgPSAwOyB9XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdzZXR0aW5nIHN0aWNreSB0b3AgaGVpZ2h0ICcgKyBoZWlnaHQpO1xuICAgICAgICB0aGlzLmNvbXAuc2V0U3RpY2t5VG9wSGVpZ2h0KGhlaWdodCArIFwicHhcIik7XG4gICAgICAgIHRoaXMuc3RpY2t5VG9wSGVpZ2h0ID0gaGVpZ2h0O1xuICAgIH07XG4gICAgR3JpZEJvZHlDdHJsLnByb3RvdHlwZS5nZXRTdGlja3lUb3BIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0aWNreVRvcEhlaWdodDtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuc2V0U3RpY2t5VG9wV2lkdGggPSBmdW5jdGlvbiAodlNjcm9sbFZpc2libGUpIHtcbiAgICAgICAgaWYgKCF2U2Nyb2xsVmlzaWJsZSkge1xuICAgICAgICAgICAgdGhpcy5jb21wLnNldFN0aWNreVRvcFdpZHRoKCcxMDAlJyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgc2Nyb2xsYmFyV2lkdGggPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRTY3JvbGxiYXJXaWR0aCgpO1xuICAgICAgICAgICAgdGhpcy5jb21wLnNldFN0aWNreVRvcFdpZHRoKFwiY2FsYygxMDAlIC0gXCIgKyBzY3JvbGxiYXJXaWR0aCArIFwicHgpXCIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLm9uSGVhZGVySGVpZ2h0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdGlja3lUb3BPZmZzZXRUb3AoKTtcbiAgICB9O1xuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuc2V0U3RpY2t5VG9wT2Zmc2V0VG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGVhZGVyQ3RybCA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRIZWFkZXJDdHJsKCk7XG4gICAgICAgIHZhciBoZWFkZXJIZWlnaHQgPSBoZWFkZXJDdHJsLmdldEhlYWRlckhlaWdodCgpO1xuICAgICAgICB2YXIgcGlubmVkVG9wSGVpZ2h0ID0gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRUb3BUb3RhbEhlaWdodCgpO1xuICAgICAgICB2YXIgaGVpZ2h0ID0gMDtcbiAgICAgICAgaWYgKGhlYWRlckhlaWdodCA+IDApIHtcbiAgICAgICAgICAgIGhlaWdodCArPSBoZWFkZXJIZWlnaHQgKyAxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwaW5uZWRUb3BIZWlnaHQgPiAwKSB7XG4gICAgICAgICAgICBoZWlnaHQgKz0gcGlubmVkVG9wSGVpZ2h0ICsgMTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbXAuc2V0U3RpY2t5VG9wVG9wKGhlaWdodCArIFwicHhcIik7XG4gICAgfTtcbiAgICAvLyBtZXRob2Qgd2lsbCBjYWxsIGl0c2VsZiBpZiBubyBhdmFpbGFibGUgd2lkdGguIHRoaXMgY292ZXJzIGlmIHRoZSBncmlkXG4gICAgLy8gaXNuJ3QgdmlzaWJsZSwgYnV0IGlzIGp1c3QgYWJvdXQgdG8gYmUgdmlzaWJsZS5cbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLnNpemVDb2x1bW5zVG9GaXQgPSBmdW5jdGlvbiAocGFyYW1zLCBuZXh0VGltZW91dCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVtb3ZlU2Nyb2xsV2lkdGggPSB0aGlzLmlzVmVydGljYWxTY3JvbGxTaG93aW5nKCk7XG4gICAgICAgIHZhciBzY3JvbGxXaWR0aFRvUmVtb3ZlID0gcmVtb3ZlU2Nyb2xsV2lkdGggPyB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRTY3JvbGxiYXJXaWR0aCgpIDogMDtcbiAgICAgICAgdmFyIGJvZHlWaWV3cG9ydFdpZHRoID0gZ2V0SW5uZXJXaWR0aCh0aGlzLmVCb2R5Vmlld3BvcnQpO1xuICAgICAgICB2YXIgYXZhaWxhYmxlV2lkdGggPSBib2R5Vmlld3BvcnRXaWR0aCAtIHNjcm9sbFdpZHRoVG9SZW1vdmU7XG4gICAgICAgIGlmIChhdmFpbGFibGVXaWR0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2l6ZUNvbHVtbnNUb0ZpdChhdmFpbGFibGVXaWR0aCwgXCJzaXplQ29sdW1uc1RvRml0XCIsIGZhbHNlLCBwYXJhbXMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0VGltZW91dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2l6ZUNvbHVtbnNUb0ZpdChwYXJhbXMsIDEwMCk7XG4gICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuZXh0VGltZW91dCA9PT0gMTAwKSB7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc2l6ZUNvbHVtbnNUb0ZpdChwYXJhbXMsIDUwMCk7XG4gICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5leHRUaW1lb3V0ID09PSA1MDApIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zaXplQ29sdW1uc1RvRml0KHBhcmFtcywgLTEpO1xuICAgICAgICAgICAgfSwgNTAwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogdHJpZWQgdG8gY2FsbCBzaXplQ29sdW1uc1RvRml0KCkgYnV0IHRoZSBncmlkIGlzIGNvbWluZyBiYWNrIHdpdGggJyArXG4gICAgICAgICAgICAgICAgJ3plcm8gd2lkdGgsIG1heWJlIHRoZSBncmlkIGlzIG5vdCB2aXNpYmxlIHlldCBvbiB0aGUgc2NyZWVuPycpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyArIHJhbmdlU2VydmljZVxuICAgIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUuYWRkU2Nyb2xsRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmVCb2R5Vmlld3BvcnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgLy8gKyBmb2N1c1NlcnZpY2VcbiAgICBHcmlkQm9keUN0cmwucHJvdG90eXBlLnJlbW92ZVNjcm9sbEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5lQm9keVZpZXdwb3J0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMVAoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UnKVxuICAgIF0sIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUsIFwicm93Q29udGFpbmVySGVpZ2h0U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVAoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlDdHJsLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFQKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgR3JpZEJvZHlDdHJsLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVAoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Njcm9sbFZpc2libGVTZXJ2aWNlJylcbiAgICBdLCBHcmlkQm9keUN0cmwucHJvdG90eXBlLCBcInNjcm9sbFZpc2libGVTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUChbXG4gICAgICAgIE9wdGlvbmFsKCdjb250ZXh0TWVudUZhY3RvcnknKVxuICAgIF0sIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUsIFwiY29udGV4dE1lbnVGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUChbXG4gICAgICAgIEF1dG93aXJlZCgnaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUsIFwiaGVhZGVyTmF2aWdhdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFQKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnQW5kRHJvcFNlcnZpY2UnKVxuICAgIF0sIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUsIFwiZHJhZ0FuZERyb3BTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxUChbXG4gICAgICAgIEF1dG93aXJlZCgncGlubmVkUm93TW9kZWwnKVxuICAgIF0sIEdyaWRCb2R5Q3RybC5wcm90b3R5cGUsIFwicGlubmVkUm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFQKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dSZW5kZXJlcicpXG4gICAgXSwgR3JpZEJvZHlDdHJsLnByb3RvdHlwZSwgXCJyb3dSZW5kZXJlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVAoW1xuICAgICAgICBBdXRvd2lyZWQoJ3BvcHVwU2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlDdHJsLnByb3RvdHlwZSwgXCJwb3B1cFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFQKFtcbiAgICAgICAgQXV0b3dpcmVkKCdtb3VzZUV2ZW50U2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlDdHJsLnByb3RvdHlwZSwgXCJtb3VzZUV2ZW50U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMVAoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBHcmlkQm9keUN0cmwucHJvdG90eXBlLCBcInJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIEdyaWRCb2R5Q3RybDtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIFNlbGVjdGlvbkhhbmRsZVR5cGU7XG4oZnVuY3Rpb24gKFNlbGVjdGlvbkhhbmRsZVR5cGUpIHtcbiAgICBTZWxlY3Rpb25IYW5kbGVUeXBlW1NlbGVjdGlvbkhhbmRsZVR5cGVbXCJGSUxMXCJdID0gMF0gPSBcIkZJTExcIjtcbiAgICBTZWxlY3Rpb25IYW5kbGVUeXBlW1NlbGVjdGlvbkhhbmRsZVR5cGVbXCJSQU5HRVwiXSA9IDFdID0gXCJSQU5HRVwiO1xufSkoU2VsZWN0aW9uSGFuZGxlVHlwZSB8fCAoU2VsZWN0aW9uSGFuZGxlVHlwZSA9IHt9KSk7XG52YXIgQ2VsbFJhbmdlVHlwZTtcbihmdW5jdGlvbiAoQ2VsbFJhbmdlVHlwZSkge1xuICAgIENlbGxSYW5nZVR5cGVbQ2VsbFJhbmdlVHlwZVtcIlZBTFVFXCJdID0gMF0gPSBcIlZBTFVFXCI7XG4gICAgQ2VsbFJhbmdlVHlwZVtDZWxsUmFuZ2VUeXBlW1wiRElNRU5TSU9OXCJdID0gMV0gPSBcIkRJTUVOU0lPTlwiO1xufSkoQ2VsbFJhbmdlVHlwZSB8fCAoQ2VsbFJhbmdlVHlwZSA9IHt9KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBDU1NfQ0VMTF9SQU5HRV9TRUxFQ1RFRCA9ICdhZy1jZWxsLXJhbmdlLXNlbGVjdGVkJztcbnZhciBDU1NfQ0VMTF9SQU5HRV9DSEFSVCA9ICdhZy1jZWxsLXJhbmdlLWNoYXJ0JztcbnZhciBDU1NfQ0VMTF9SQU5HRV9TSU5HTEVfQ0VMTCA9ICdhZy1jZWxsLXJhbmdlLXNpbmdsZS1jZWxsJztcbnZhciBDU1NfQ0VMTF9SQU5HRV9DSEFSVF9DQVRFR09SWSA9ICdhZy1jZWxsLXJhbmdlLWNoYXJ0LWNhdGVnb3J5JztcbnZhciBDU1NfQ0VMTF9SQU5HRV9IQU5ETEUgPSAnYWctY2VsbC1yYW5nZS1oYW5kbGUnO1xudmFyIENTU19DRUxMX1JBTkdFX1RPUCA9ICdhZy1jZWxsLXJhbmdlLXRvcCc7XG52YXIgQ1NTX0NFTExfUkFOR0VfUklHSFQgPSAnYWctY2VsbC1yYW5nZS1yaWdodCc7XG52YXIgQ1NTX0NFTExfUkFOR0VfQk9UVE9NID0gJ2FnLWNlbGwtcmFuZ2UtYm90dG9tJztcbnZhciBDU1NfQ0VMTF9SQU5HRV9MRUZUID0gJ2FnLWNlbGwtcmFuZ2UtbGVmdCc7XG52YXIgQ2VsbFJhbmdlRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDZWxsUmFuZ2VGZWF0dXJlKGJlYW5zLCBjdHJsKSB7XG4gICAgICAgIHRoaXMuYmVhbnMgPSBiZWFucztcbiAgICAgICAgdGhpcy5jZWxsQ3RybCA9IGN0cmw7XG4gICAgfVxuICAgIENlbGxSYW5nZUZlYXR1cmUucHJvdG90eXBlLnNldENvbXAgPSBmdW5jdGlvbiAoY2VsbENvbXAsIGVHdWkpIHtcbiAgICAgICAgdGhpcy5jZWxsQ29tcCA9IGNlbGxDb21wO1xuICAgICAgICB0aGlzLmVHdWkgPSBlR3VpO1xuICAgICAgICB0aGlzLm9uUmFuZ2VTZWxlY3Rpb25DaGFuZ2VkKCk7XG4gICAgfTtcbiAgICBDZWxsUmFuZ2VGZWF0dXJlLnByb3RvdHlwZS5vblJhbmdlU2VsZWN0aW9uQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2hlbiB1c2luZyByZWFjdFVpLCBnaXZlbiBVSSBpcyBhc3luYywgaXQncyBwb3NzaWJsZSB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYmVmb3JlIHRoZSBjb21wIGlzIHJlZ2lzdGVyZWRcbiAgICAgICAgaWYgKCF0aGlzLmNlbGxDb21wKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yYW5nZUNvdW50ID0gdGhpcy5iZWFucy5yYW5nZVNlcnZpY2UuZ2V0Q2VsbFJhbmdlQ291bnQodGhpcy5jZWxsQ3RybC5nZXRDZWxsUG9zaXRpb24oKSk7XG4gICAgICAgIHRoaXMuaGFzQ2hhcnRSYW5nZSA9IHRoaXMuZ2V0SGFzQ2hhcnRSYW5nZSgpO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NFTExfUkFOR0VfU0VMRUNURUQsIHRoaXMucmFuZ2VDb3VudCAhPT0gMCk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQ0VMTF9SQU5HRV9TRUxFQ1RFRCArIFwiLTFcIiwgdGhpcy5yYW5nZUNvdW50ID09PSAxKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX1JBTkdFX1NFTEVDVEVEICsgXCItMlwiLCB0aGlzLnJhbmdlQ291bnQgPT09IDIpO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NFTExfUkFOR0VfU0VMRUNURUQgKyBcIi0zXCIsIHRoaXMucmFuZ2VDb3VudCA9PT0gMyk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQ0VMTF9SQU5HRV9TRUxFQ1RFRCArIFwiLTRcIiwgdGhpcy5yYW5nZUNvdW50ID49IDQpO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NFTExfUkFOR0VfQ0hBUlQsIHRoaXMuaGFzQ2hhcnRSYW5nZSk7XG4gICAgICAgIHNldEFyaWFTZWxlY3RlZCh0aGlzLmVHdWksIHRoaXMucmFuZ2VDb3VudCA+IDAgPyB0cnVlIDogdW5kZWZpbmVkKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX1JBTkdFX1NJTkdMRV9DRUxMLCB0aGlzLmlzU2luZ2xlQ2VsbCgpKTtcbiAgICAgICAgdGhpcy51cGRhdGVSYW5nZUJvcmRlcnMoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoSGFuZGxlKCk7XG4gICAgfTtcbiAgICBDZWxsUmFuZ2VGZWF0dXJlLnByb3RvdHlwZS51cGRhdGVSYW5nZUJvcmRlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByYW5nZUJvcmRlcnMgPSB0aGlzLmdldFJhbmdlQm9yZGVycygpO1xuICAgICAgICB2YXIgaXNTaW5nbGVDZWxsID0gdGhpcy5pc1NpbmdsZUNlbGwoKTtcbiAgICAgICAgdmFyIGlzVG9wID0gIWlzU2luZ2xlQ2VsbCAmJiByYW5nZUJvcmRlcnMudG9wO1xuICAgICAgICB2YXIgaXNSaWdodCA9ICFpc1NpbmdsZUNlbGwgJiYgcmFuZ2VCb3JkZXJzLnJpZ2h0O1xuICAgICAgICB2YXIgaXNCb3R0b20gPSAhaXNTaW5nbGVDZWxsICYmIHJhbmdlQm9yZGVycy5ib3R0b207XG4gICAgICAgIHZhciBpc0xlZnQgPSAhaXNTaW5nbGVDZWxsICYmIHJhbmdlQm9yZGVycy5sZWZ0O1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NFTExfUkFOR0VfVE9QLCBpc1RvcCk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQ0VMTF9SQU5HRV9SSUdIVCwgaXNSaWdodCk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQ0VMTF9SQU5HRV9CT1RUT00sIGlzQm90dG9tKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX1JBTkdFX0xFRlQsIGlzTGVmdCk7XG4gICAgfTtcbiAgICBDZWxsUmFuZ2VGZWF0dXJlLnByb3RvdHlwZS5pc1NpbmdsZUNlbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByYW5nZVNlcnZpY2UgPSB0aGlzLmJlYW5zLnJhbmdlU2VydmljZTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmFuZ2VDb3VudCA9PT0gMSAmJiByYW5nZVNlcnZpY2UgJiYgIXJhbmdlU2VydmljZS5pc01vcmVUaGFuT25lQ2VsbCgpO1xuICAgIH07XG4gICAgQ2VsbFJhbmdlRmVhdHVyZS5wcm90b3R5cGUuZ2V0SGFzQ2hhcnRSYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJhbmdlU2VydmljZSA9IHRoaXMuYmVhbnMucmFuZ2VTZXJ2aWNlO1xuICAgICAgICBpZiAoIXRoaXMucmFuZ2VDb3VudCB8fCAhcmFuZ2VTZXJ2aWNlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNlbGxSYW5nZXMgPSByYW5nZVNlcnZpY2UuZ2V0Q2VsbFJhbmdlcygpO1xuICAgICAgICByZXR1cm4gY2VsbFJhbmdlcy5sZW5ndGggPiAwICYmIGNlbGxSYW5nZXMuZXZlcnkoZnVuY3Rpb24gKHJhbmdlKSB7IHJldHVybiBpbmNsdWRlcyhbQ2VsbFJhbmdlVHlwZS5ESU1FTlNJT04sIENlbGxSYW5nZVR5cGUuVkFMVUVdLCByYW5nZS50eXBlKTsgfSk7XG4gICAgfTtcbiAgICBDZWxsUmFuZ2VGZWF0dXJlLnByb3RvdHlwZS51cGRhdGVSYW5nZUJvcmRlcnNJZlJhbmdlQ291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHdlIG9ubHkgbmVlZCB0byB1cGRhdGUgcmFuZ2UgYm9yZGVycyBpZiB3ZSBhcmUgaW4gYSByYW5nZVxuICAgICAgICBpZiAodGhpcy5yYW5nZUNvdW50ID4gMCkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVSYW5nZUJvcmRlcnMoKTtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaEhhbmRsZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsUmFuZ2VGZWF0dXJlLnByb3RvdHlwZS5nZXRSYW5nZUJvcmRlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBpc1J0bCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCk7XG4gICAgICAgIHZhciB0b3AgPSBmYWxzZTtcbiAgICAgICAgdmFyIHJpZ2h0ID0gZmFsc2U7XG4gICAgICAgIHZhciBib3R0b20gPSBmYWxzZTtcbiAgICAgICAgdmFyIGxlZnQgPSBmYWxzZTtcbiAgICAgICAgdmFyIHRoaXNDb2wgPSB0aGlzLmNlbGxDdHJsLmdldENlbGxQb3NpdGlvbigpLmNvbHVtbjtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5iZWFucywgcmFuZ2VTZXJ2aWNlID0gX2EucmFuZ2VTZXJ2aWNlLCBjb2x1bW5Nb2RlbCA9IF9hLmNvbHVtbk1vZGVsO1xuICAgICAgICB2YXIgbGVmdENvbDtcbiAgICAgICAgdmFyIHJpZ2h0Q29sO1xuICAgICAgICBpZiAoaXNSdGwpIHtcbiAgICAgICAgICAgIGxlZnRDb2wgPSBjb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2xBZnRlcih0aGlzQ29sKTtcbiAgICAgICAgICAgIHJpZ2h0Q29sID0gY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkQ29sQmVmb3JlKHRoaXNDb2wpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbGVmdENvbCA9IGNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbEJlZm9yZSh0aGlzQ29sKTtcbiAgICAgICAgICAgIHJpZ2h0Q29sID0gY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkQ29sQWZ0ZXIodGhpc0NvbCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJhbmdlcyA9IHJhbmdlU2VydmljZS5nZXRDZWxsUmFuZ2VzKCkuZmlsdGVyKGZ1bmN0aW9uIChyYW5nZSkgeyByZXR1cm4gcmFuZ2VTZXJ2aWNlLmlzQ2VsbEluU3BlY2lmaWNSYW5nZShfdGhpcy5jZWxsQ3RybC5nZXRDZWxsUG9zaXRpb24oKSwgcmFuZ2UpOyB9KTtcbiAgICAgICAgLy8gdGhpcyBtZWFucyB3ZSBhcmUgdGhlIGZpcnN0IGNvbHVtbiBpbiB0aGUgZ3JpZFxuICAgICAgICBpZiAoIWxlZnRDb2wpIHtcbiAgICAgICAgICAgIGxlZnQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgbWVhbnMgd2UgYXJlIHRoZSBsYXN0IGNvbHVtbiBpbiB0aGUgZ3JpZFxuICAgICAgICBpZiAoIXJpZ2h0Q29sKSB7XG4gICAgICAgICAgICByaWdodCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0b3AgJiYgcmlnaHQgJiYgYm90dG9tICYmIGxlZnQpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciByYW5nZSA9IHJhbmdlc1tpXTtcbiAgICAgICAgICAgIHZhciBzdGFydFJvdyA9IHJhbmdlU2VydmljZS5nZXRSYW5nZVN0YXJ0Um93KHJhbmdlKTtcbiAgICAgICAgICAgIHZhciBlbmRSb3cgPSByYW5nZVNlcnZpY2UuZ2V0UmFuZ2VFbmRSb3cocmFuZ2UpO1xuICAgICAgICAgICAgaWYgKCF0b3AgJiYgdGhpcy5iZWFucy5yb3dQb3NpdGlvblV0aWxzLnNhbWVSb3coc3RhcnRSb3csIHRoaXMuY2VsbEN0cmwuZ2V0Q2VsbFBvc2l0aW9uKCkpKSB7XG4gICAgICAgICAgICAgICAgdG9wID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghYm90dG9tICYmIHRoaXMuYmVhbnMucm93UG9zaXRpb25VdGlscy5zYW1lUm93KGVuZFJvdywgdGhpcy5jZWxsQ3RybC5nZXRDZWxsUG9zaXRpb24oKSkpIHtcbiAgICAgICAgICAgICAgICBib3R0b20gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFsZWZ0ICYmIGxlZnRDb2wgJiYgcmFuZ2UuY29sdW1ucy5pbmRleE9mKGxlZnRDb2wpIDwgMCkge1xuICAgICAgICAgICAgICAgIGxlZnQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFyaWdodCAmJiByaWdodENvbCAmJiByYW5nZS5jb2x1bW5zLmluZGV4T2YocmlnaHRDb2wpIDwgMCkge1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB0b3A6IHRvcCwgcmlnaHQ6IHJpZ2h0LCBib3R0b206IGJvdHRvbSwgbGVmdDogbGVmdCB9O1xuICAgIH07XG4gICAgQ2VsbFJhbmdlRmVhdHVyZS5wcm90b3R5cGUucmVmcmVzaEhhbmRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmJlYW5zLnJhbmdlU2VydmljZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaG91bGRIYXZlU2VsZWN0aW9uSGFuZGxlID0gdGhpcy5zaG91bGRIYXZlU2VsZWN0aW9uSGFuZGxlKCk7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbkhhbmRsZSAmJiAhc2hvdWxkSGF2ZVNlbGVjdGlvbkhhbmRsZSkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25IYW5kbGUgPSB0aGlzLmJlYW5zLmNvbnRleHQuZGVzdHJveUJlYW4odGhpcy5zZWxlY3Rpb25IYW5kbGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzaG91bGRIYXZlU2VsZWN0aW9uSGFuZGxlKSB7XG4gICAgICAgICAgICB0aGlzLmFkZFNlbGVjdGlvbkhhbmRsZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQ0VMTF9SQU5HRV9IQU5ETEUsICEhdGhpcy5zZWxlY3Rpb25IYW5kbGUpO1xuICAgIH07XG4gICAgQ2VsbFJhbmdlRmVhdHVyZS5wcm90b3R5cGUuc2hvdWxkSGF2ZVNlbGVjdGlvbkhhbmRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5iZWFucywgZ3JpZE9wdGlvbnNXcmFwcGVyID0gX2EuZ3JpZE9wdGlvbnNXcmFwcGVyLCByYW5nZVNlcnZpY2UgPSBfYS5yYW5nZVNlcnZpY2U7XG4gICAgICAgIHZhciBjZWxsUmFuZ2VzID0gcmFuZ2VTZXJ2aWNlLmdldENlbGxSYW5nZXMoKTtcbiAgICAgICAgdmFyIHJhbmdlc0xlbiA9IGNlbGxSYW5nZXMubGVuZ3RoO1xuICAgICAgICBpZiAodGhpcy5yYW5nZUNvdW50IDwgMSB8fCByYW5nZXNMZW4gPCAxKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNlbGxSYW5nZSA9IGxhc3QoY2VsbFJhbmdlcyk7XG4gICAgICAgIHZhciBjZWxsUG9zaXRpb24gPSB0aGlzLmNlbGxDdHJsLmdldENlbGxQb3NpdGlvbigpO1xuICAgICAgICB2YXIgaXNGaWxsSGFuZGxlQXZhaWxhYmxlID0gZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlRmlsbEhhbmRsZSgpICYmICF0aGlzLmNlbGxDdHJsLmlzU3VwcHJlc3NGaWxsSGFuZGxlKCk7XG4gICAgICAgIHZhciBpc1JhbmdlSGFuZGxlQXZhaWxhYmxlID0gZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUmFuZ2VIYW5kbGUoKTtcbiAgICAgICAgdmFyIGhhbmRsZUlzQXZhaWxhYmxlID0gcmFuZ2VzTGVuID09PSAxICYmICF0aGlzLmNlbGxDdHJsLmlzRWRpdGluZygpICYmIChpc0ZpbGxIYW5kbGVBdmFpbGFibGUgfHwgaXNSYW5nZUhhbmRsZUF2YWlsYWJsZSk7XG4gICAgICAgIGlmICh0aGlzLmhhc0NoYXJ0UmFuZ2UpIHtcbiAgICAgICAgICAgIHZhciBoYXNDYXRlZ29yeVJhbmdlID0gY2VsbFJhbmdlc1swXS50eXBlID09PSBDZWxsUmFuZ2VUeXBlLkRJTUVOU0lPTjtcbiAgICAgICAgICAgIHZhciBpc0NhdGVnb3J5Q2VsbCA9IGhhc0NhdGVnb3J5UmFuZ2UgJiYgcmFuZ2VTZXJ2aWNlLmlzQ2VsbEluU3BlY2lmaWNSYW5nZShjZWxsUG9zaXRpb24sIGNlbGxSYW5nZXNbMF0pO1xuICAgICAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX1JBTkdFX0NIQVJUX0NBVEVHT1JZLCBpc0NhdGVnb3J5Q2VsbCk7XG4gICAgICAgICAgICBoYW5kbGVJc0F2YWlsYWJsZSA9IGNlbGxSYW5nZS50eXBlID09PSBDZWxsUmFuZ2VUeXBlLlZBTFVFO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoYW5kbGVJc0F2YWlsYWJsZSAmJlxuICAgICAgICAgICAgY2VsbFJhbmdlLmVuZFJvdyAhPSBudWxsICYmXG4gICAgICAgICAgICByYW5nZVNlcnZpY2UuaXNDb250aWd1b3VzUmFuZ2UoY2VsbFJhbmdlKSAmJlxuICAgICAgICAgICAgcmFuZ2VTZXJ2aWNlLmlzQm90dG9tUmlnaHRDZWxsKGNlbGxSYW5nZSwgY2VsbFBvc2l0aW9uKTtcbiAgICB9O1xuICAgIENlbGxSYW5nZUZlYXR1cmUucHJvdG90eXBlLmFkZFNlbGVjdGlvbkhhbmRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5iZWFucywgZ3JpZE9wdGlvbnNXcmFwcGVyID0gX2EuZ3JpZE9wdGlvbnNXcmFwcGVyLCByYW5nZVNlcnZpY2UgPSBfYS5yYW5nZVNlcnZpY2U7XG4gICAgICAgIHZhciBjZWxsUmFuZ2VUeXBlID0gbGFzdChyYW5nZVNlcnZpY2UuZ2V0Q2VsbFJhbmdlcygpKS50eXBlO1xuICAgICAgICB2YXIgc2VsZWN0aW9uSGFuZGxlRmlsbCA9IGdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUZpbGxIYW5kbGUoKSAmJiBtaXNzaW5nKGNlbGxSYW5nZVR5cGUpO1xuICAgICAgICB2YXIgdHlwZSA9IHNlbGVjdGlvbkhhbmRsZUZpbGwgPyBTZWxlY3Rpb25IYW5kbGVUeXBlLkZJTEwgOiBTZWxlY3Rpb25IYW5kbGVUeXBlLlJBTkdFO1xuICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb25IYW5kbGUgJiYgdGhpcy5zZWxlY3Rpb25IYW5kbGUuZ2V0VHlwZSgpICE9PSB0eXBlKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkhhbmRsZSA9IHRoaXMuYmVhbnMuY29udGV4dC5kZXN0cm95QmVhbih0aGlzLnNlbGVjdGlvbkhhbmRsZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnNlbGVjdGlvbkhhbmRsZSkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25IYW5kbGUgPSB0aGlzLmJlYW5zLnNlbGVjdGlvbkhhbmRsZUZhY3RvcnkuY3JlYXRlU2VsZWN0aW9uSGFuZGxlKHR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uSGFuZGxlLnJlZnJlc2godGhpcy5jZWxsQ3RybCk7XG4gICAgfTtcbiAgICBDZWxsUmFuZ2VGZWF0dXJlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmJlYW5zLmNvbnRleHQuZGVzdHJveUJlYW4odGhpcy5zZWxlY3Rpb25IYW5kbGUpO1xuICAgIH07XG4gICAgcmV0dXJuIENlbGxSYW5nZUZlYXR1cmU7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDEkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG4vKipcbiAqIFRha2VzIGNhcmUgb2Y6XG4gKiAgIykgQ2VsbCBXaWR0aCAoaW5jbHVkaW5nIHdoZW4gZG9pbmcgY2VsbCBzcGFubmluZywgd2hpY2ggbWFrZXMgd2lkdGggY292ZXIgbWFueSBjb2x1bW5zKVxuICogICMpIENlbGwgSGVpZ2h0ICh3aGVuIGRvaW5nIHJvdyBzcGFuLCBvdGhlcndpc2Ugd2UgZG9uJ3QgdG91Y2ggdGhlIGhlaWdodCBhcyBpdCdzIGp1c3Qgcm93IGhlaWdodClcbiAqICAjKSBDZWxsIExlZnQgKHRoZSBob3Jpem9udGFsIHBvc2l0aW9uaW5nIG9mIHRoZSBjZWxsLCB0aGUgdmVydGljYWwgcG9zaXRpb25pbmcgaXMgb24gdGhlIHJvdylcbiAqL1xudmFyIENlbGxQb3NpdGlvbkZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDEkKENlbGxQb3NpdGlvbkZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ2VsbFBvc2l0aW9uRmVhdHVyZShjdHJsLCBiZWFucykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5jZWxsQ3RybCA9IGN0cmw7XG4gICAgICAgIF90aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIF90aGlzLmNvbHVtbiA9IGN0cmwuZ2V0Q29sdW1uKCk7XG4gICAgICAgIF90aGlzLnJvd05vZGUgPSBjdHJsLmdldFJvd05vZGUoKTtcbiAgICAgICAgX3RoaXMuc2V0dXBDb2xTcGFuKCk7XG4gICAgICAgIF90aGlzLnNldHVwUm93U3BhbigpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENlbGxQb3NpdGlvbkZlYXR1cmUucHJvdG90eXBlLnNldHVwUm93U3BhbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yb3dTcGFuID0gdGhpcy5jb2x1bW4uZ2V0Um93U3Bhbih0aGlzLnJvd05vZGUpO1xuICAgIH07XG4gICAgQ2VsbFBvc2l0aW9uRmVhdHVyZS5wcm90b3R5cGUuc2V0Q29tcCA9IGZ1bmN0aW9uIChlR3VpKSB7XG4gICAgICAgIHRoaXMuZUd1aSA9IGVHdWk7XG4gICAgICAgIHRoaXMub25MZWZ0Q2hhbmdlZCgpO1xuICAgICAgICB0aGlzLm9uV2lkdGhDaGFuZ2VkKCk7XG4gICAgICAgIHRoaXMuYXBwbHlSb3dTcGFuKCk7XG4gICAgfTtcbiAgICBDZWxsUG9zaXRpb25GZWF0dXJlLnByb3RvdHlwZS5vbkRpc3BsYXlDb2x1bW5zQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbHNTcGFubmluZyA9IHRoaXMuZ2V0Q29sU3Bhbm5pbmdMaXN0KCk7XG4gICAgICAgIGlmICghYXJlRXF1YWwodGhpcy5jb2xzU3Bhbm5pbmcsIGNvbHNTcGFubmluZykpIHtcbiAgICAgICAgICAgIHRoaXMuY29sc1NwYW5uaW5nID0gY29sc1NwYW5uaW5nO1xuICAgICAgICAgICAgdGhpcy5vbldpZHRoQ2hhbmdlZCgpO1xuICAgICAgICAgICAgdGhpcy5vbkxlZnRDaGFuZ2VkKCk7IC8vIGxlZnQgY2hhbmdlcyB3aGVuIGRvaW5nIFJUTFxuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsUG9zaXRpb25GZWF0dXJlLnByb3RvdHlwZS5zZXR1cENvbFNwYW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGlmIG5vIGNvbCBzcGFuIGlzIGFjdGl2ZSwgdGhlbiB3ZSBkb24ndCBzZXQgaXQgdXAsIGFzIGl0IHdvdWxkIGJlIHdhc3RlZnVsIG9mIENQVVxuICAgICAgICBpZiAodGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCkuY29sU3BhbiA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb2xzU3Bhbm5pbmcgPSB0aGlzLmdldENvbFNwYW5uaW5nTGlzdCgpO1xuICAgICAgICAvLyBiZWNhdXNlIHdlIGFyZSBjb2wgc3Bhbm5pbmcsIGEgcmVvcmRlciBvZiB0aGUgY29scyBjYW4gY2hhbmdlIHdoYXQgY29scyB3ZSBhcmUgc3Bhbm5pbmcgb3ZlclxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmJlYW5zLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMub25EaXNwbGF5Q29sdW1uc0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIC8vIGJlY2F1c2Ugd2UgYXJlIHNwYW5uaW5nIG92ZXIgbXVsdGlwbGUgY29scywgd2UgY2hlY2sgZm9yIHdpZHRoIGFueSB0aW1lIGFueSBjb2xzIHdpZHRoIGNoYW5nZXMuXG4gICAgICAgIC8vIHRoaXMgaXMgZXhwZW5zaXZlIC0gcmVhbGx5IHdlIHNob3VsZCBiZSBleHBsaWNpdGx5IGNoZWNraW5nIG9ubHkgdGhlIGNvbHMgd2UgYXJlIHNwYW5uaW5nIG92ZXJcbiAgICAgICAgLy8gaW5zdGVhZCBvZiBldmVyeSBjb2wsIGhvd2V2ZXIgaXQgd291bGQgYmUgdHJpY2t5IGNvZGUgdG8gdHJhY2sgdGhlIGNvbHMgd2UgYXJlIHNwYW5uaW5nIG92ZXIsIHNvXG4gICAgICAgIC8vIGJlY2F1c2UgaGFyZGx5IGFueW9uZSB3aWxsIGJlIHVzaW5nIGNvbFNwYW4sIGFtIGZhdm91cmluZyB0aGlzIGVhc2llciB3YXkgZm9yIG1vcmUgbWFpbnRhaW5hYmxlIGNvZGUuXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuYmVhbnMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfV0lEVEhfQ0hBTkdFRCwgdGhpcy5vbldpZHRoQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIENlbGxQb3NpdGlvbkZlYXR1cmUucHJvdG90eXBlLm9uV2lkdGhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuZUd1aSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciB3aWR0aCA9IHRoaXMuZ2V0Q2VsbFdpZHRoKCk7XG4gICAgICAgIHRoaXMuZUd1aS5zdHlsZS53aWR0aCA9IHdpZHRoICsgXCJweFwiO1xuICAgIH07XG4gICAgQ2VsbFBvc2l0aW9uRmVhdHVyZS5wcm90b3R5cGUuZ2V0Q2VsbFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuY29sc1NwYW5uaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW4uZ2V0QWN0dWFsV2lkdGgoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5jb2xzU3Bhbm5pbmcucmVkdWNlKGZ1bmN0aW9uICh3aWR0aCwgY29sKSB7IHJldHVybiB3aWR0aCArIGNvbC5nZXRBY3R1YWxXaWR0aCgpOyB9LCAwKTtcbiAgICB9O1xuICAgIENlbGxQb3NpdGlvbkZlYXR1cmUucHJvdG90eXBlLmdldENvbFNwYW5uaW5nTGlzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbFNwYW4gPSB0aGlzLmNvbHVtbi5nZXRDb2xTcGFuKHRoaXMucm93Tm9kZSk7XG4gICAgICAgIHZhciBjb2xzU3Bhbm5pbmcgPSBbXTtcbiAgICAgICAgLy8gaWYganVzdCBvbmUgY29sLCB0aGUgY29sIHNwYW4gaXMganVzdCB0aGUgY29sdW1uIHdlIGFyZSBpblxuICAgICAgICBpZiAoY29sU3BhbiA9PT0gMSkge1xuICAgICAgICAgICAgY29sc1NwYW5uaW5nLnB1c2godGhpcy5jb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHBvaW50ZXIgPSB0aGlzLmNvbHVtbjtcbiAgICAgICAgICAgIHZhciBwaW5uZWQgPSB0aGlzLmNvbHVtbi5nZXRQaW5uZWQoKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBwb2ludGVyICYmIGkgPCBjb2xTcGFuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb2xzU3Bhbm5pbmcucHVzaChwb2ludGVyKTtcbiAgICAgICAgICAgICAgICBwb2ludGVyID0gdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2xBZnRlcihwb2ludGVyKTtcbiAgICAgICAgICAgICAgICBpZiAoIXBvaW50ZXIgfHwgbWlzc2luZyhwb2ludGVyKSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gd2UgZG8gbm90IGFsbG93IGNvbCBzcGFubmluZyB0byBzcGFuIG91dHNpZGUgb2YgcGlubmVkIGFyZWFzXG4gICAgICAgICAgICAgICAgaWYgKHBpbm5lZCAhPT0gcG9pbnRlci5nZXRQaW5uZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbHNTcGFubmluZztcbiAgICB9O1xuICAgIENlbGxQb3NpdGlvbkZlYXR1cmUucHJvdG90eXBlLm9uTGVmdENoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5lR3VpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxlZnQgPSB0aGlzLm1vZGlmeUxlZnRGb3JQcmludExheW91dCh0aGlzLmdldENlbGxMZWZ0KCkpO1xuICAgICAgICB0aGlzLmVHdWkuc3R5bGUubGVmdCA9IGxlZnQgKyAncHgnO1xuICAgIH07XG4gICAgQ2VsbFBvc2l0aW9uRmVhdHVyZS5wcm90b3R5cGUuZ2V0Q2VsbExlZnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtb3N0TGVmdENvbDtcbiAgICAgICAgaWYgKHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkgJiYgdGhpcy5jb2xzU3Bhbm5pbmcpIHtcbiAgICAgICAgICAgIG1vc3RMZWZ0Q29sID0gbGFzdCh0aGlzLmNvbHNTcGFubmluZyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtb3N0TGVmdENvbCA9IHRoaXMuY29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtb3N0TGVmdENvbC5nZXRMZWZ0KCk7XG4gICAgfTtcbiAgICBDZWxsUG9zaXRpb25GZWF0dXJlLnByb3RvdHlwZS5tb2RpZnlMZWZ0Rm9yUHJpbnRMYXlvdXQgPSBmdW5jdGlvbiAobGVmdFBvc2l0aW9uKSB7XG4gICAgICAgIGlmICghdGhpcy5jZWxsQ3RybC5pc1ByaW50TGF5b3V0KCkgfHwgdGhpcy5jb2x1bW4uZ2V0UGlubmVkKCkgPT09IENvbnN0YW50cy5QSU5ORURfTEVGVCkge1xuICAgICAgICAgICAgcmV0dXJuIGxlZnRQb3NpdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbGVmdFdpZHRoID0gdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2x1bW5zTGVmdFdpZHRoKCk7XG4gICAgICAgIGlmICh0aGlzLmNvbHVtbi5nZXRQaW5uZWQoKSA9PT0gQ29uc3RhbnRzLlBJTk5FRF9SSUdIVCkge1xuICAgICAgICAgICAgdmFyIGJvZHlXaWR0aCA9IHRoaXMuYmVhbnMuY29sdW1uTW9kZWwuZ2V0Qm9keUNvbnRhaW5lcldpZHRoKCk7XG4gICAgICAgICAgICByZXR1cm4gbGVmdFdpZHRoICsgYm9keVdpZHRoICsgKGxlZnRQb3NpdGlvbiB8fCAwKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpcyBpbiBib2R5XG4gICAgICAgIHJldHVybiBsZWZ0V2lkdGggKyAobGVmdFBvc2l0aW9uIHx8IDApO1xuICAgIH07XG4gICAgQ2VsbFBvc2l0aW9uRmVhdHVyZS5wcm90b3R5cGUuYXBwbHlSb3dTcGFuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yb3dTcGFuID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNpbmdsZVJvd0hlaWdodCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0hlaWdodEFzTnVtYmVyKCk7XG4gICAgICAgIHZhciB0b3RhbFJvd0hlaWdodCA9IHNpbmdsZVJvd0hlaWdodCAqIHRoaXMucm93U3BhbjtcbiAgICAgICAgdGhpcy5lR3VpLnN0eWxlLmhlaWdodCA9IHRvdGFsUm93SGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICB0aGlzLmVHdWkuc3R5bGUuekluZGV4ID0gJzEnO1xuICAgIH07XG4gICAgLy8gb3ZlcnJpZGluZyB0byBtYWtlIHB1YmxpYywgYXMgd2UgZG9uJ3QgZGlzcG9zZSB0aGlzIGJlYW4gdmlhIGNvbnRleHRcbiAgICBDZWxsUG9zaXRpb25GZWF0dXJlLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIHJldHVybiBDZWxsUG9zaXRpb25GZWF0dXJlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFfID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgQ2VsbEN1c3RvbVN0eWxlRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMV8oQ2VsbEN1c3RvbVN0eWxlRmVhdHVyZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDZWxsQ3VzdG9tU3R5bGVGZWF0dXJlKGN0cmwsIGJlYW5zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnN0YXRpY0NsYXNzZXMgPSBbXTtcbiAgICAgICAgX3RoaXMuY2VsbEN0cmwgPSBjdHJsO1xuICAgICAgICBfdGhpcy5iZWFucyA9IGJlYW5zO1xuICAgICAgICBfdGhpcy5jb2x1bW4gPSBjdHJsLmdldENvbHVtbigpO1xuICAgICAgICBfdGhpcy5yb3dOb2RlID0gY3RybC5nZXRSb3dOb2RlKCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQ2VsbEN1c3RvbVN0eWxlRmVhdHVyZS5wcm90b3R5cGUuc2V0Q29tcCA9IGZ1bmN0aW9uIChjb21wKSB7XG4gICAgICAgIHRoaXMuY2VsbENvbXAgPSBjb21wO1xuICAgICAgICB0aGlzLmFwcGx5VXNlclN0eWxlcygpO1xuICAgICAgICB0aGlzLmFwcGx5Q2VsbENsYXNzUnVsZXMoKTtcbiAgICAgICAgdGhpcy5hcHBseUNsYXNzZXNGcm9tQ29sRGVmKCk7XG4gICAgfTtcbiAgICBDZWxsQ3VzdG9tU3R5bGVGZWF0dXJlLnByb3RvdHlwZS5hcHBseUNlbGxDbGFzc1J1bGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIHZhciBjZWxsQ2xhc3NQYXJhbXMgPSB7XG4gICAgICAgICAgICB2YWx1ZTogdGhpcy5jZWxsQ3RybC5nZXRWYWx1ZSgpLFxuICAgICAgICAgICAgZGF0YTogdGhpcy5yb3dOb2RlLmRhdGEsXG4gICAgICAgICAgICBub2RlOiB0aGlzLnJvd05vZGUsXG4gICAgICAgICAgICBjb2xEZWY6IGNvbERlZixcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICByb3dJbmRleDogdGhpcy5yb3dOb2RlLnJvd0luZGV4LFxuICAgICAgICAgICAgYXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KClcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5iZWFucy5zdHlsaW5nU2VydmljZS5wcm9jZXNzQ2xhc3NSdWxlcyhjb2xEZWYuY2VsbENsYXNzUnVsZXMsIGNlbGxDbGFzc1BhcmFtcywgZnVuY3Rpb24gKGNsYXNzTmFtZSkgeyByZXR1cm4gX3RoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhjbGFzc05hbWUsIHRydWUpOyB9LCBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7IHJldHVybiBfdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKGNsYXNzTmFtZSwgZmFsc2UpOyB9KTtcbiAgICB9O1xuICAgIENlbGxDdXN0b21TdHlsZUZlYXR1cmUucHJvdG90eXBlLmFwcGx5VXNlclN0eWxlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICBpZiAoIWNvbERlZi5jZWxsU3R5bGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3R5bGVzO1xuICAgICAgICBpZiAodHlwZW9mIGNvbERlZi5jZWxsU3R5bGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhciBjZWxsU3R5bGVQYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgY29sdW1uOiB0aGlzLmNvbHVtbixcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5jZWxsQ3RybC5nZXRWYWx1ZSgpLFxuICAgICAgICAgICAgICAgIGNvbERlZjogY29sRGVmLFxuICAgICAgICAgICAgICAgIGRhdGE6IHRoaXMucm93Tm9kZS5kYXRhLFxuICAgICAgICAgICAgICAgIG5vZGU6IHRoaXMucm93Tm9kZSxcbiAgICAgICAgICAgICAgICByb3dJbmRleDogdGhpcy5yb3dOb2RlLnJvd0luZGV4LFxuICAgICAgICAgICAgICAgIGFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgICAgICBjb250ZXh0OiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGNlbGxTdHlsZUZ1bmMgPSBjb2xEZWYuY2VsbFN0eWxlO1xuICAgICAgICAgICAgc3R5bGVzID0gY2VsbFN0eWxlRnVuYyhjZWxsU3R5bGVQYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3R5bGVzID0gY29sRGVmLmNlbGxTdHlsZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNlbGxDb21wLnNldFVzZXJTdHlsZXMoc3R5bGVzKTtcbiAgICB9O1xuICAgIENlbGxDdXN0b21TdHlsZUZlYXR1cmUucHJvdG90eXBlLmFwcGx5Q2xhc3Nlc0Zyb21Db2xEZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb2xEZWYgPSB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgdmFyIGNlbGxDbGFzc1BhcmFtcyA9IHtcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLmNlbGxDdHJsLmdldFZhbHVlKCksXG4gICAgICAgICAgICBkYXRhOiB0aGlzLnJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgIG5vZGU6IHRoaXMucm93Tm9kZSxcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICBjb2xEZWY6IGNvbERlZixcbiAgICAgICAgICAgIHJvd0luZGV4OiB0aGlzLnJvd05vZGUucm93SW5kZXgsXG4gICAgICAgICAgICBhcGk6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5zdGF0aWNDbGFzc2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5zdGF0aWNDbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKGNsYXNzTmFtZSkgeyByZXR1cm4gX3RoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhjbGFzc05hbWUsIGZhbHNlKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0aWNDbGFzc2VzID0gdGhpcy5iZWFucy5zdHlsaW5nU2VydmljZS5nZXRTdGF0aWNDZWxsQ2xhc3Nlcyhjb2xEZWYsIGNlbGxDbGFzc1BhcmFtcyk7XG4gICAgICAgIGlmICh0aGlzLnN0YXRpY0NsYXNzZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXRpY0NsYXNzZXMuZm9yRWFjaChmdW5jdGlvbiAoY2xhc3NOYW1lKSB7IHJldHVybiBfdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKGNsYXNzTmFtZSwgdHJ1ZSk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBvdmVycmlkaW5nIHRvIG1ha2UgcHVibGljLCBhcyB3ZSBkb24ndCBkaXNwb3NlIHRoaXMgYmVhbiB2aWEgY29udGV4dFxuICAgIENlbGxDdXN0b21TdHlsZUZlYXR1cmUucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgcmV0dXJuIENlbGxDdXN0b21TdHlsZUZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMVogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBUb29sdGlwRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMVooVG9vbHRpcEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVG9vbHRpcEZlYXR1cmUoY3RybCwgYmVhbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY3RybCA9IGN0cmw7XG4gICAgICAgIF90aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLnNldENvbXAgPSBmdW5jdGlvbiAoY29tcCkge1xuICAgICAgICB0aGlzLmNvbXAgPSBjb21wO1xuICAgICAgICB0aGlzLnNldHVwVG9vbHRpcCgpO1xuICAgIH07XG4gICAgVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLnNldHVwVG9vbHRpcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5icm93c2VyVG9vbHRpcHMgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUJyb3dzZXJUb29sdGlwcygpO1xuICAgICAgICB0aGlzLnVwZGF0ZVRvb2x0aXBUZXh0KCk7XG4gICAgICAgIGlmICh0aGlzLmJyb3dzZXJUb29sdGlwcykge1xuICAgICAgICAgICAgdGhpcy5jb21wLnNldFRpdGxlKHRoaXMudG9vbHRpcCAhPSBudWxsID8gdGhpcy50b29sdGlwIDogdW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlVG9vbHRpcEZlYXR1cmVJZk5lZWRlZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUb29sdGlwRmVhdHVyZS5wcm90b3R5cGUudXBkYXRlVG9vbHRpcFRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9vbHRpcCA9IHRoaXMuY3RybC5nZXRUb29sdGlwVmFsdWUoKTtcbiAgICB9O1xuICAgIFRvb2x0aXBGZWF0dXJlLnByb3RvdHlwZS5jcmVhdGVUb29sdGlwRmVhdHVyZUlmTmVlZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5nZW5lcmljVG9vbHRpcEZlYXR1cmUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJlbnQgPSB7XG4gICAgICAgICAgICBnZXRUb29sdGlwUGFyYW1zOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5nZXRUb29sdGlwUGFyYW1zKCk7IH0sXG4gICAgICAgICAgICBnZXRHdWk6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmN0cmwuZ2V0R3VpKCk7IH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZW5lcmljVG9vbHRpcEZlYXR1cmUgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBDdXN0b21Ub29sdGlwRmVhdHVyZShwYXJlbnQpLCB0aGlzLmJlYW5zLmNvbnRleHQpO1xuICAgIH07XG4gICAgVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLnJlZnJlc2hUb29sVGlwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVwZGF0ZVRvb2x0aXBUZXh0KCk7XG4gICAgICAgIGlmICh0aGlzLmJyb3dzZXJUb29sdGlwcykge1xuICAgICAgICAgICAgdGhpcy5jb21wLnNldFRpdGxlKHRoaXMudG9vbHRpcCAhPSBudWxsID8gdGhpcy50b29sdGlwIDogdW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLmdldFRvb2x0aXBQYXJhbXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjdHJsID0gdGhpcy5jdHJsO1xuICAgICAgICB2YXIgY29sdW1uID0gY3RybC5nZXRDb2x1bW4gPyBjdHJsLmdldENvbHVtbigpIDogdW5kZWZpbmVkO1xuICAgICAgICB2YXIgY29sRGVmID0gY3RybC5nZXRDb2xEZWYgPyBjdHJsLmdldENvbERlZigpIDogdW5kZWZpbmVkO1xuICAgICAgICB2YXIgcm93Tm9kZSA9IGN0cmwuZ2V0Um93Tm9kZSA/IGN0cmwuZ2V0Um93Tm9kZSgpIDogdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbG9jYXRpb246IGN0cmwuZ2V0TG9jYXRpb24oKSxcbiAgICAgICAgICAgIGNvbERlZjogY29sRGVmLFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICByb3dJbmRleDogY3RybC5nZXRSb3dJbmRleCA/IGN0cmwuZ2V0Um93SW5kZXgoKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG5vZGU6IHJvd05vZGUsXG4gICAgICAgICAgICBkYXRhOiByb3dOb2RlID8gcm93Tm9kZS5kYXRhIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgdmFsdWU6IHRoaXMuZ2V0VG9vbHRpcFRleHQoKSxcbiAgICAgICAgICAgIHZhbHVlRm9ybWF0dGVkOiBjdHJsLmdldFZhbHVlRm9ybWF0dGVkID8gY3RybC5nZXRWYWx1ZUZvcm1hdHRlZCgpIDogdW5kZWZpbmVkLFxuICAgICAgICB9O1xuICAgIH07XG4gICAgVG9vbHRpcEZlYXR1cmUucHJvdG90eXBlLmdldFRvb2x0aXBUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b29sdGlwO1xuICAgIH07XG4gICAgLy8gb3ZlcnJpZGluZyB0byBtYWtlIHB1YmxpYywgYXMgd2UgZG9uJ3QgZGlzcG9zZSB0aGlzIGJlYW4gdmlhIGNvbnRleHRcbiAgICBUb29sdGlwRmVhdHVyZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICByZXR1cm4gVG9vbHRpcEZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2RlY29yYXRlJDFPID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG4vKiogVXNpbmcgdGhlIElvQyBoYXMgYSBzbGlnaHQgcGVyZm9ybWFuY2UgY29uc2lkZXJhdGlvbiwgd2hpY2ggaXMgbm8gcHJvYmxlbSBtb3N0IG9mIHRoZVxuICogdGltZSwgdW5sZXNzIHdlIGFyZSB0cmFzaGluZyBvYmplY3RzIC0gd2hpY2ggaXMgdGhlIGNhc2Ugd2hlbiBzY3JvbGxpbmcgYW5kIHJvd0NvbXBcbiAqIGFuZCBjZWxsQ29tcC4gU28gZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMsIFJvd0NvbXAgYW5kIENlbGxDb21wIGRvIG5vdCBnZXQgYXV0b3dpcmVkXG4gKiB3aXRoIHRoZSBJb0MuIEluc3RlYWQgdGhleSBnZXQgcGFzc2VkIHRoaXMgb2JqZWN0IHdoaWNoIGlzIGFsbCB0aGUgYmVhbnMgdGhlIFJvd0NvbXBcbiAqIGFuZCBDZWxsQ29tcCBuZWVkLiBOb3QgYXV0b3dpcmluZyBhbGwgdGhlIGNlbGxzIGdpdmVzIHBlcmZvcm1hbmNlIGltcHJvdmVtZW50LiAqL1xudmFyIEJlYW5zID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEJlYW5zKCkge1xuICAgIH1cbiAgICBCZWFucy5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kb2luZ01hc3RlckRldGFpbCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzTWFzdGVyRGV0YWlsKCk7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd01vZGVsRGVmYXVsdCgpKSB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbCA9IHRoaXMucm93TW9kZWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxTZXJ2ZXJTaWRlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyU2lkZVJvd01vZGVsID0gdGhpcy5yb3dNb2RlbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgncmVzaXplT2JzZXJ2ZXJTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwicmVzaXplT2JzZXJ2ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgncGFnaW5hdGlvblByb3h5JylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwicGFnaW5hdGlvblByb3h5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgnY29udGV4dCcpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImNvbnRleHRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5BcGknKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJjb2x1bW5BcGlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkQXBpJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiZ3JpZEFwaVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRPcHRpb25zV3JhcHBlcicpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImdyaWRPcHRpb25zV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2V4cHJlc3Npb25TZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiZXhwcmVzc2lvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dSZW5kZXJlcicpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgndGVtcGxhdGVTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwidGVtcGxhdGVTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgndmFsdWVTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwidmFsdWVTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgnZXZlbnRTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiZXZlbnRTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2hlYWRlck5hdmlnYXRpb25TZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiaGVhZGVyTmF2aWdhdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCduYXZpZ2F0aW9uU2VydmljZScpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcIm5hdmlnYXRpb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uQW5pbWF0aW9uU2VydmljZScpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImNvbHVtbkFuaW1hdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgT3B0aW9uYWwoJ3JhbmdlU2VydmljZScpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcInJhbmdlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZvY3VzU2VydmljZScpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBPcHRpb25hbCgnY29udGV4dE1lbnVGYWN0b3J5JylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiY29udGV4dE1lbnVGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwicG9wdXBTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgndmFsdWVGb3JtYXR0ZXJTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwidmFsdWVGb3JtYXR0ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgnc3R5bGluZ1NlcnZpY2UnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJzdHlsaW5nU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbkhvdmVyU2VydmljZScpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImNvbHVtbkhvdmVyU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3VzZXJDb21wb25lbnRGYWN0b3J5JylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwidXNlckNvbXBvbmVudEZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCd1c2VyQ29tcG9uZW50UmVnaXN0cnknKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJ1c2VyQ29tcG9uZW50UmVnaXN0cnlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdhbmltYXRpb25GcmFtZVNlcnZpY2UnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJhbmltYXRpb25GcmFtZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnQW5kRHJvcFNlcnZpY2UnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJkcmFnQW5kRHJvcFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdzb3J0Q29udHJvbGxlcicpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcInNvcnRDb250cm9sbGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgnZmlsdGVyTWFuYWdlcicpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImZpbHRlck1hbmFnZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwicm93Q29udGFpbmVySGVpZ2h0U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZyYW1ld29ya092ZXJyaWRlcycpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcImZyYW1ld29ya092ZXJyaWRlc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2NlbGxQb3NpdGlvblV0aWxzJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiY2VsbFBvc2l0aW9uVXRpbHNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dQb3NpdGlvblV0aWxzJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwicm93UG9zaXRpb25VdGlsc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3NlbGVjdGlvblNlcnZpY2UnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJzZWxlY3Rpb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIE9wdGlvbmFsKCdzZWxlY3Rpb25IYW5kbGVGYWN0b3J5JylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwic2VsZWN0aW9uSGFuZGxlRmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd0Nzc0NsYXNzQ2FsY3VsYXRvcicpXG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcInJvd0Nzc0NsYXNzQ2FsY3VsYXRvclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc0ZhY3RvcnknKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJjdHJsc0ZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdhZ1N0YWNrQ29tcG9uZW50c1JlZ2lzdHJ5JylcbiAgICBdLCBCZWFucy5wcm90b3R5cGUsIFwiYWdTdGFja0NvbXBvbmVudHNSZWdpc3RyeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlQ2FjaGUnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJ2YWx1ZUNhY2hlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTyhbXG4gICAgICAgIEF1dG93aXJlZCgncm93Tm9kZUV2ZW50VGhyb3R0bGUnKVxuICAgIF0sIEJlYW5zLnByb3RvdHlwZSwgXCJyb3dOb2RlRXZlbnRUaHJvdHRsZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU8oW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgQmVhbnMucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgQmVhbnMgPSBfX2RlY29yYXRlJDFPKFtcbiAgICAgICAgQmVhbignYmVhbnMnKVxuICAgIF0sIEJlYW5zKTtcbiAgICByZXR1cm4gQmVhbnM7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFZID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxWShDZWxsTW91c2VMaXN0ZW5lckZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlKGN0cmwsIGJlYW5zLCBjb2x1bW4pIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY2VsbEN0cmwgPSBjdHJsO1xuICAgICAgICBfdGhpcy5iZWFucyA9IGJlYW5zO1xuICAgICAgICBfdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vbk1vdXNlRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnROYW1lLCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmIChpc1N0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChtb3VzZUV2ZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICBjYXNlICdjbGljayc6XG4gICAgICAgICAgICAgICAgdGhpcy5vbkNlbGxDbGlja2VkKG1vdXNlRXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbW91c2Vkb3duJzpcbiAgICAgICAgICAgIGNhc2UgJ3RvdWNoc3RhcnQnOlxuICAgICAgICAgICAgICAgIHRoaXMub25Nb3VzZURvd24obW91c2VFdmVudCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkYmxjbGljayc6XG4gICAgICAgICAgICAgICAgdGhpcy5vbkNlbGxEb3VibGVDbGlja2VkKG1vdXNlRXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbW91c2VvdXQnOlxuICAgICAgICAgICAgICAgIHRoaXMub25Nb3VzZU91dChtb3VzZUV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ21vdXNlb3Zlcic6XG4gICAgICAgICAgICAgICAgdGhpcy5vbk1vdXNlT3Zlcihtb3VzZUV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vbkNlbGxDbGlja2VkID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQpIHtcbiAgICAgICAgLy8gaVBhZCBkb2Vzbid0IGhhdmUgZG91YmxlIGNsaWNrIC0gc28gd2UgbmVlZCB0byBtaW1pYyBpdCB0byBlbmFibGUgZWRpdGluZyBmb3IgaVBhZC5cbiAgICAgICAgaWYgKHRoaXMuaXNEb3VibGVDbGlja09uSVBhZCgpKSB7XG4gICAgICAgICAgICB0aGlzLm9uQ2VsbERvdWJsZUNsaWNrZWQobW91c2VFdmVudCk7XG4gICAgICAgICAgICBtb3VzZUV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIGlmIHdlIGRvbid0IGRvIHRoaXMsIHRoZW4gaVBhZCB6b29tcyBpblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBfYSA9IHRoaXMuYmVhbnMsIGV2ZW50U2VydmljZSA9IF9hLmV2ZW50U2VydmljZSwgcmFuZ2VTZXJ2aWNlID0gX2EucmFuZ2VTZXJ2aWNlLCBncmlkT3B0aW9uc1dyYXBwZXIgPSBfYS5ncmlkT3B0aW9uc1dyYXBwZXI7XG4gICAgICAgIHZhciBtdWx0aUtleVByZXNzZWQgPSBtb3VzZUV2ZW50LmN0cmxLZXkgfHwgbW91c2VFdmVudC5tZXRhS2V5O1xuICAgICAgICBpZiAocmFuZ2VTZXJ2aWNlICYmIG11bHRpS2V5UHJlc3NlZCkge1xuICAgICAgICAgICAgLy8gdGhlIG1vdXNlZG93biBldmVudCBoYXMgY3JlYXRlZCB0aGUgcmFuZ2UgYWxyZWFkeSwgc28gd2Ugb25seSBpbnRlcnNlY3QgaWYgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZVxuICAgICAgICAgICAgLy8gcmFuZ2Ugb24gdGhpcyBjZWxsXG4gICAgICAgICAgICBpZiAocmFuZ2VTZXJ2aWNlLmdldENlbGxSYW5nZUNvdW50KHRoaXMuY2VsbEN0cmwuZ2V0Q2VsbFBvc2l0aW9uKCkpID4gMSkge1xuICAgICAgICAgICAgICAgIHJhbmdlU2VydmljZS5pbnRlcnNlY3RMYXN0UmFuZ2UodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNlbGxDbGlja2VkRXZlbnQgPSB0aGlzLmNlbGxDdHJsLmNyZWF0ZUV2ZW50KG1vdXNlRXZlbnQsIEV2ZW50cy5FVkVOVF9DRUxMX0NMSUNLRUQpO1xuICAgICAgICBldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChjZWxsQ2xpY2tlZEV2ZW50KTtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICBpZiAoY29sRGVmLm9uQ2VsbENsaWNrZWQpIHtcbiAgICAgICAgICAgIC8vIHRvIG1ha2UgY2FsbGJhY2sgYXN5bmMsIGRvIGluIGEgdGltZW91dFxuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29sRGVmLm9uQ2VsbENsaWNrZWQoY2VsbENsaWNrZWRFdmVudCk7IH0sIDApO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlZGl0T25TaW5nbGVDbGljayA9IChncmlkT3B0aW9uc1dyYXBwZXIuaXNTaW5nbGVDbGlja0VkaXQoKSB8fCBjb2xEZWYuc2luZ2xlQ2xpY2tFZGl0KVxuICAgICAgICAgICAgJiYgIWdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ2xpY2tFZGl0KCk7XG4gICAgICAgIGlmIChlZGl0T25TaW5nbGVDbGljaykge1xuICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5zdGFydFJvd09yQ2VsbEVkaXQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gcmV0dXJucyB0cnVlIGlmIG9uIGlQYWQgYW5kIHRoaXMgaXMgc2Vjb25kICdjbGljaycgZXZlbnQgaW4gMjAwbXNcbiAgICBDZWxsTW91c2VMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLmlzRG91YmxlQ2xpY2tPbklQYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghaXNJT1NVc2VyQWdlbnQoKSB8fCBpc0V2ZW50U3VwcG9ydGVkKCdkYmxjbGljaycpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5vd01pbGxpcyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICB2YXIgcmVzID0gbm93TWlsbGlzIC0gdGhpcy5sYXN0SVBhZE1vdXNlQ2xpY2tFdmVudCA8IDIwMDtcbiAgICAgICAgdGhpcy5sYXN0SVBhZE1vdXNlQ2xpY2tFdmVudCA9IG5vd01pbGxpcztcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIENlbGxNb3VzZUxpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUub25DZWxsRG91YmxlQ2xpY2tlZCA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIHZhciBjb2xEZWYgPSB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgLy8gYWx3YXlzIGRpc3BhdGNoIGV2ZW50IHRvIGV2ZW50U2VydmljZVxuICAgICAgICB2YXIgY2VsbERvdWJsZUNsaWNrZWRFdmVudCA9IHRoaXMuY2VsbEN0cmwuY3JlYXRlRXZlbnQobW91c2VFdmVudCwgRXZlbnRzLkVWRU5UX0NFTExfRE9VQkxFX0NMSUNLRUQpO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGNlbGxEb3VibGVDbGlja2VkRXZlbnQpO1xuICAgICAgICAvLyBjaGVjayBpZiBjb2xEZWYgYWxzbyB3YW50cyB0byBoYW5kbGUgZXZlbnRcbiAgICAgICAgaWYgKHR5cGVvZiBjb2xEZWYub25DZWxsRG91YmxlQ2xpY2tlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgLy8gdG8gbWFrZSB0aGUgY2FsbGJhY2sgYXN5bmMsIGRvIGluIGEgdGltZW91dFxuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29sRGVmLm9uQ2VsbERvdWJsZUNsaWNrZWQoY2VsbERvdWJsZUNsaWNrZWRFdmVudCk7IH0sIDApO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlZGl0T25Eb3VibGVDbGljayA9ICF0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1NpbmdsZUNsaWNrRWRpdCgpXG4gICAgICAgICAgICAmJiAhdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0NsaWNrRWRpdCgpO1xuICAgICAgICBpZiAoZWRpdE9uRG91YmxlQ2xpY2spIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbEN0cmwuc3RhcnRSb3dPckNlbGxFZGl0KG51bGwsIG51bGwsIG1vdXNlRXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsTW91c2VMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLm9uTW91c2VEb3duID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQpIHtcbiAgICAgICAgdmFyIGN0cmxLZXkgPSBtb3VzZUV2ZW50LmN0cmxLZXksIG1ldGFLZXkgPSBtb3VzZUV2ZW50Lm1ldGFLZXksIHNoaWZ0S2V5ID0gbW91c2VFdmVudC5zaGlmdEtleTtcbiAgICAgICAgdmFyIHRhcmdldCA9IG1vdXNlRXZlbnQudGFyZ2V0O1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmJlYW5zLCBldmVudFNlcnZpY2UgPSBfYS5ldmVudFNlcnZpY2UsIHJhbmdlU2VydmljZSA9IF9hLnJhbmdlU2VydmljZTtcbiAgICAgICAgLy8gZG8gbm90IGNoYW5nZSB0aGUgcmFuZ2UgZm9yIHJpZ2h0LWNsaWNrcyBpbnNpZGUgYW4gZXhpc3RpbmcgcmFuZ2VcbiAgICAgICAgaWYgKHRoaXMuaXNSaWdodENsaWNrSW5FeGlzdGluZ1JhbmdlKG1vdXNlRXZlbnQpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJhbmdlcyA9IHJhbmdlU2VydmljZSAmJiByYW5nZVNlcnZpY2UuZ2V0Q2VsbFJhbmdlcygpLmxlbmd0aCAhPSAwO1xuICAgICAgICBpZiAoIXNoaWZ0S2V5IHx8ICFyYW5nZXMpIHtcbiAgICAgICAgICAgIC8vIFdlIG9ubHkgbmVlZCB0byBwYXNzIHRydWUgdG8gZm9jdXNDZWxsIHdoZW4gdGhlIGJyb3dzZXIgaXMgSUUvRWRnZSBhbmQgd2UgYXJlIHRyeWluZ1xuICAgICAgICAgICAgLy8gdG8gZm9jdXMgdGhlIGNlbGwgaXRzZWxmLiBUaGlzIHNob3VsZCBuZXZlciBiZSB0cnVlIGlmIHRoZSBtb3VzZWRvd24gd2FzIHRyaWdnZXJlZFxuICAgICAgICAgICAgLy8gZHVlIHRvIGEgY2xpY2sgb24gYSBjZWxsIGVkaXRvciBmb3IgZXhhbXBsZS5cbiAgICAgICAgICAgIHZhciBmb3JjZUJyb3dzZXJGb2N1cyA9IChpc0Jyb3dzZXJFZGdlKCkpICYmICF0aGlzLmNlbGxDdHJsLmlzRWRpdGluZygpICYmICFpc0ZvY3VzYWJsZUZvcm1GaWVsZCh0YXJnZXQpO1xuICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5mb2N1c0NlbGwoZm9yY2VCcm93c2VyRm9jdXMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHNoaWZ0IGNsaWNraW5nLCBhbmQgYSByYW5nZSBleGlzdHMsIHdlIGtlZXAgdGhlIGZvY3VzIG9uIHRoZSBjZWxsIHRoYXQgc3RhcnRlZCB0aGVcbiAgICAgICAgLy8gcmFuZ2UgYXMgdGhlIHVzZXIgdGhlbiBjaGFuZ2VzIHRoZSByYW5nZSBzZWxlY3Rpb24uXG4gICAgICAgIGlmIChzaGlmdEtleSAmJiByYW5nZXMpIHtcbiAgICAgICAgICAgIC8vIHRoaXMgc3RvcHMgdGhlIGNlbGwgZnJvbSBnZXR0aW5nIGZvY3VzZWRcbiAgICAgICAgICAgIG1vdXNlRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB3ZSBhcmUgY2xpY2tpbmcgb24gYSBjaGVja2JveCwgd2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIGNlbGwgd3JhcHBpbmcgdGhhdCBjaGVja2JveFxuICAgICAgICAvLyBpcyBmb2N1c2VkIGJ1dCB3ZSBkb24ndCB3YW50IHRvIGNoYW5nZSB0aGUgcmFuZ2Ugc2VsZWN0aW9uLCBzbyByZXR1cm4gaGVyZS5cbiAgICAgICAgaWYgKHRoaXMuY29udGFpbnNXaWRnZXQodGFyZ2V0KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyYW5nZVNlcnZpY2UpIHtcbiAgICAgICAgICAgIHZhciB0aGlzQ2VsbCA9IHRoaXMuY2VsbEN0cmwuZ2V0Q2VsbFBvc2l0aW9uKCk7XG4gICAgICAgICAgICBpZiAoc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICByYW5nZVNlcnZpY2UuZXh0ZW5kTGF0ZXN0UmFuZ2VUb0NlbGwodGhpc0NlbGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGN0cmxLZXlQcmVzc2VkID0gY3RybEtleSB8fCBtZXRhS2V5O1xuICAgICAgICAgICAgICAgIHJhbmdlU2VydmljZS5zZXRSYW5nZVRvQ2VsbCh0aGlzQ2VsbCwgY3RybEtleVByZXNzZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHRoaXMuY2VsbEN0cmwuY3JlYXRlRXZlbnQobW91c2VFdmVudCwgRXZlbnRzLkVWRU5UX0NFTExfTU9VU0VfRE9XTikpO1xuICAgIH07XG4gICAgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5pc1JpZ2h0Q2xpY2tJbkV4aXN0aW5nUmFuZ2UgPSBmdW5jdGlvbiAobW91c2VFdmVudCkge1xuICAgICAgICB2YXIgcmFuZ2VTZXJ2aWNlID0gdGhpcy5iZWFucy5yYW5nZVNlcnZpY2U7XG4gICAgICAgIGlmIChyYW5nZVNlcnZpY2UpIHtcbiAgICAgICAgICAgIHZhciBjZWxsSW5SYW5nZSA9IHJhbmdlU2VydmljZS5pc0NlbGxJbkFueVJhbmdlKHRoaXMuY2VsbEN0cmwuZ2V0Q2VsbFBvc2l0aW9uKCkpO1xuICAgICAgICAgICAgaWYgKGNlbGxJblJhbmdlICYmIG1vdXNlRXZlbnQuYnV0dG9uID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5jb250YWluc1dpZGdldCA9IGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICAgICAgcmV0dXJuIGlzRWxlbWVudENoaWxkT2ZDbGFzcyh0YXJnZXQsICdhZy1zZWxlY3Rpb24tY2hlY2tib3gnLCAzKTtcbiAgICB9O1xuICAgIENlbGxNb3VzZUxpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUub25Nb3VzZU91dCA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLm1vdXNlU3RheWluZ0luc2lkZUNlbGwobW91c2VFdmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbE1vdXNlT3V0RXZlbnQgPSB0aGlzLmNlbGxDdHJsLmNyZWF0ZUV2ZW50KG1vdXNlRXZlbnQsIEV2ZW50cy5FVkVOVF9DRUxMX01PVVNFX09VVCk7XG4gICAgICAgIHRoaXMuYmVhbnMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoY2VsbE1vdXNlT3V0RXZlbnQpO1xuICAgICAgICB0aGlzLmJlYW5zLmNvbHVtbkhvdmVyU2VydmljZS5jbGVhck1vdXNlT3ZlcigpO1xuICAgIH07XG4gICAgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vbk1vdXNlT3ZlciA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLm1vdXNlU3RheWluZ0luc2lkZUNlbGwobW91c2VFdmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbE1vdXNlT3ZlckV2ZW50ID0gdGhpcy5jZWxsQ3RybC5jcmVhdGVFdmVudChtb3VzZUV2ZW50LCBFdmVudHMuRVZFTlRfQ0VMTF9NT1VTRV9PVkVSKTtcbiAgICAgICAgdGhpcy5iZWFucy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChjZWxsTW91c2VPdmVyRXZlbnQpO1xuICAgICAgICB0aGlzLmJlYW5zLmNvbHVtbkhvdmVyU2VydmljZS5zZXRNb3VzZU92ZXIoW3RoaXMuY29sdW1uXSk7XG4gICAgfTtcbiAgICBDZWxsTW91c2VMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLm1vdXNlU3RheWluZ0luc2lkZUNlbGwgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoIWUudGFyZ2V0IHx8ICFlLnJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuY2VsbEN0cmwuZ2V0R3VpKCk7XG4gICAgICAgIHZhciBjZWxsQ29udGFpbnNUYXJnZXQgPSBlR3VpLmNvbnRhaW5zKGUudGFyZ2V0KTtcbiAgICAgICAgdmFyIGNlbGxDb250YWluc1JlbGF0ZWRUYXJnZXQgPSBlR3VpLmNvbnRhaW5zKGUucmVsYXRlZFRhcmdldCk7XG4gICAgICAgIHJldHVybiBjZWxsQ29udGFpbnNUYXJnZXQgJiYgY2VsbENvbnRhaW5zUmVsYXRlZFRhcmdldDtcbiAgICB9O1xuICAgIENlbGxNb3VzZUxpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIHJldHVybiBDZWxsTW91c2VMaXN0ZW5lckZlYXR1cmU7XG59KEJlYW5zKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMVggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBDZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFYKENlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUoY3RybCwgYmVhbnMsIGNvbHVtbiwgcm93Tm9kZSwgcm93Q3RybCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5jZWxsQ3RybCA9IGN0cmw7XG4gICAgICAgIF90aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIF90aGlzLnJvd05vZGUgPSByb3dOb2RlO1xuICAgICAgICBfdGhpcy5yb3dDdHJsID0gcm93Q3RybDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBDZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLnNldENvbXAgPSBmdW5jdGlvbiAoZUd1aSkge1xuICAgICAgICB0aGlzLmVHdWkgPSBlR3VpO1xuICAgIH07XG4gICAgQ2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vbktleURvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGtleSA9IGV2ZW50LmtleTtcbiAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5FTlRFUjpcbiAgICAgICAgICAgICAgICB0aGlzLm9uRW50ZXJLZXlEb3duKGV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5GMjpcbiAgICAgICAgICAgICAgICB0aGlzLm9uRjJLZXlEb3duKGV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5FU0NBUEU6XG4gICAgICAgICAgICAgICAgdGhpcy5vbkVzY2FwZUtleURvd24oZXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlRBQjpcbiAgICAgICAgICAgICAgICB0aGlzLm9uVGFiS2V5RG93bihldmVudCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuQkFDS1NQQUNFOlxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRFTEVURTpcbiAgICAgICAgICAgICAgICB0aGlzLm9uQmFja3NwYWNlT3JEZWxldGVLZXlQcmVzc2VkKGtleSwgZXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRPV046XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuVVA6XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuUklHSFQ6XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuTEVGVDpcbiAgICAgICAgICAgICAgICB0aGlzLm9uTmF2aWdhdGlvbktleVByZXNzZWQoZXZlbnQsIGtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUub25OYXZpZ2F0aW9uS2V5UHJlc3NlZCA9IGZ1bmN0aW9uIChldmVudCwga2V5KSB7XG4gICAgICAgIGlmICh0aGlzLmNlbGxDdHJsLmlzRWRpdGluZygpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5ICYmIHRoaXMuY2VsbEN0cmwuaXNSYW5nZVNlbGVjdGlvbkVuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5vblNoaWZ0UmFuZ2VTZWxlY3QoZXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5iZWFucy5uYXZpZ2F0aW9uU2VydmljZS5uYXZpZ2F0ZVRvTmV4dENlbGwoZXZlbnQsIGtleSwgdGhpcy5jZWxsQ3RybC5nZXRDZWxsUG9zaXRpb24oKSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgZG9uJ3QgcHJldmVudCBkZWZhdWx0LCB0aGUgZ3JpZCB3aWxsIHNjcm9sbCB3aXRoIHRoZSBuYXZpZ2F0aW9uIGtleXNcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9O1xuICAgIENlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUub25TaGlmdFJhbmdlU2VsZWN0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5iZWFucy5yYW5nZVNlcnZpY2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZW5kQ2VsbCA9IHRoaXMuYmVhbnMucmFuZ2VTZXJ2aWNlLmV4dGVuZExhdGVzdFJhbmdlSW5EaXJlY3Rpb24oZXZlbnQpO1xuICAgICAgICBpZiAoZW5kQ2VsbCkge1xuICAgICAgICAgICAgdGhpcy5iZWFucy5uYXZpZ2F0aW9uU2VydmljZS5lbnN1cmVDZWxsVmlzaWJsZShlbmRDZWxsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vblRhYktleURvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5iZWFucy5uYXZpZ2F0aW9uU2VydmljZS5vblRhYktleURvd24odGhpcy5jZWxsQ3RybCwgZXZlbnQpO1xuICAgIH07XG4gICAgQ2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vbkJhY2tzcGFjZU9yRGVsZXRlS2V5UHJlc3NlZCA9IGZ1bmN0aW9uIChrZXksIGV2ZW50KSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMsIGNlbGxDdHJsID0gX2EuY2VsbEN0cmwsIGJlYW5zID0gX2EuYmVhbnMsIHJvd05vZGUgPSBfYS5yb3dOb2RlO1xuICAgICAgICB2YXIgZ3JpZE9wdGlvbnNXcmFwcGVyID0gYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLCByYW5nZVNlcnZpY2UgPSBiZWFucy5yYW5nZVNlcnZpY2UsIGV2ZW50U2VydmljZSA9IGJlYW5zLmV2ZW50U2VydmljZTtcbiAgICAgICAgaWYgKGNlbGxDdHJsLmlzRWRpdGluZygpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBFdmVudHMuRVZFTlRfS0VZX1NIT1JUQ1VUX0NIQU5HRURfQ0VMTF9TVEFSVCB9KTtcbiAgICAgICAgaWYgKGlzRGVsZXRlS2V5KGtleSwgZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlQ2VsbEVkaXRpbmdPbkJhY2tzcGFjZSgpKSkge1xuICAgICAgICAgICAgaWYgKHJhbmdlU2VydmljZSAmJiBncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSYW5nZVNlbGVjdGlvbigpKSB7XG4gICAgICAgICAgICAgICAgcmFuZ2VTZXJ2aWNlLmNsZWFyQ2VsbFJhbmdlQ2VsbFZhbHVlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY2VsbEN0cmwuaXNDZWxsRWRpdGFibGUoKSkge1xuICAgICAgICAgICAgICAgIHJvd05vZGUuc2V0RGF0YVZhbHVlKGNlbGxDdHJsLmdldENvbHVtbigpLCBudWxsLCAnY2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjZWxsQ3RybC5zdGFydFJvd09yQ2VsbEVkaXQoa2V5LCB1bmRlZmluZWQsIGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICBldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh7IHR5cGU6IEV2ZW50cy5FVkVOVF9LRVlfU0hPUlRDVVRfQ0hBTkdFRF9DRUxMX0VORCB9KTtcbiAgICB9O1xuICAgIENlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUub25FbnRlcktleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5jZWxsQ3RybC5pc0VkaXRpbmcoKSB8fCB0aGlzLnJvd0N0cmwuaXNFZGl0aW5nKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbEN0cmwuc3RvcEVkaXRpbmdBbmRGb2N1cygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW50ZXJNb3Zlc0Rvd24oKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYmVhbnMubmF2aWdhdGlvblNlcnZpY2UubmF2aWdhdGVUb05leHRDZWxsKG51bGwsIEtleUNvZGUuRE9XTiwgdGhpcy5jZWxsQ3RybC5nZXRDZWxsUG9zaXRpb24oKSwgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5zdGFydFJvd09yQ2VsbEVkaXQoS2V5Q29kZS5FTlRFUiwgdW5kZWZpbmVkLCBlKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jZWxsQ3RybC5pc0VkaXRpbmcoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBzdGFydGVkIGVkaXRpbmcsIHRoZW4gd2UgbmVlZCB0byBwcmV2ZW50IGRlZmF1bHQsIG90aGVyd2lzZSB0aGUgRW50ZXIgYWN0aW9uIGNhbiBnZXRcbiAgICAgICAgICAgICAgICAgICAgLy8gYXBwbGllZCB0byB0aGUgY2VsbCBlZGl0b3IuIHRoaXMgaGFwcGVuZWQsIGZvciBleGFtcGxlLCB3aXRoIGxhcmdlVGV4dENlbGxFZGl0b3Igd2hlcmUgbm90XG4gICAgICAgICAgICAgICAgICAgIC8vIHByZXZlbnRpbmcgZGVmYXVsdCByZXN1bHRzIGluIGEgJ25ldyBsaW5lJyBjaGFyYWN0ZXIgZ2V0dGluZyBpbnNlcnRlZCBpbiB0aGUgdGV4dCBhcmVhXG4gICAgICAgICAgICAgICAgICAgIC8vIHdoZW4gdGhlIGVkaXRpbmcgd2FzIHN0YXJ0ZWRcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5vbkYyS2V5RG93biA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VsbEN0cmwuaXNFZGl0aW5nKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbEN0cmwuc3RhcnRSb3dPckNlbGxFZGl0KEtleUNvZGUuRjIsIHVuZGVmaW5lZCwgZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLm9uRXNjYXBlS2V5RG93biA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAodGhpcy5jZWxsQ3RybC5pc0VkaXRpbmcoKSkge1xuICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5zdG9wUm93T3JDZWxsRWRpdCh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuY2VsbEN0cmwuZm9jdXNDZWxsKHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLm9uS2V5UHJlc3MgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgLy8gY2hlY2sgdGhpcywgaW4gY2FzZSBmb2N1cyBpcyBvbiBhIChmb3IgZXhhbXBsZSkgYSB0ZXh0IGZpZWxkIGluc2lkZSB0aGUgY2VsbCxcbiAgICAgICAgLy8gaW4gd2hpY2ggY3NlIHdlIHNob3VsZCBub3QgYmUgbGlzdGVuaW5nIGZvciB0aGVzZSBrZXkgcHJlc3NlZFxuICAgICAgICB2YXIgZXZlbnRUYXJnZXQgPSBldmVudC50YXJnZXQ7XG4gICAgICAgIHZhciBldmVudE9uQ2hpbGRDb21wb25lbnQgPSBldmVudFRhcmdldCAhPT0gdGhpcy5lR3VpO1xuICAgICAgICBpZiAoZXZlbnRPbkNoaWxkQ29tcG9uZW50IHx8IHRoaXMuY2VsbEN0cmwuaXNFZGl0aW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJlc3NlZENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGV2ZW50LmNoYXJDb2RlKTtcbiAgICAgICAgaWYgKHByZXNzZWRDaGFyID09PSAnICcpIHtcbiAgICAgICAgICAgIHRoaXMub25TcGFjZUtleVByZXNzZWQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzRXZlbnRGcm9tUHJpbnRhYmxlQ2hhcmFjdGVyKGV2ZW50KSkge1xuICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5zdGFydFJvd09yQ2VsbEVkaXQobnVsbCwgcHJlc3NlZENoYXIsIGV2ZW50KTtcbiAgICAgICAgICAgIC8vIGlmIHdlIGRvbid0IHByZXZlbnQgZGVmYXVsdCwgdGhlbiB0aGUga2V5cHJlc3MgYWxzbyBnZXRzIGFwcGxpZWQgdG8gdGhlIHRleHQgZmllbGRcbiAgICAgICAgICAgIC8vIChhdCBsZWFzdCB3aGVuIGRvaW5nIHRoZSBkZWZhdWx0IGVkaXRvciksIGJ1dCB3ZSBuZWVkIHRvIGFsbG93IHRoZSBlZGl0b3IgdG8gZGVjaWRlXG4gICAgICAgICAgICAvLyB3aGF0IGl0IHdhbnRzIHRvIGRvLiB3ZSBvbmx5IGRvIHRoaXMgSUYgZWRpdGluZyB3YXMgc3RhcnRlZCAtIG90aGVyd2lzZSBpdCBtZXNzZXNcbiAgICAgICAgICAgIC8vIHVwIHdoZW4gdGhlIHVzZSBpcyBub3QgZG9pbmcgZWRpdGluZywgYnV0IHVzaW5nIHJlbmRlcmluZyB3aXRoIHRleHQgZmllbGRzIGluIGNlbGxSZW5kZXJlclxuICAgICAgICAgICAgLy8gKGFzIGl0IHdvdWxkIGJsb2NrIHRoZSB0aGUgdXNlciBmcm9tIHR5cGluZyBpbnRvIHRleHQgZmllbGRzKS5cbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUub25TcGFjZUtleVByZXNzZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGdyaWRPcHRpb25zV3JhcHBlciA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICBpZiAoIXRoaXMuY2VsbEN0cmwuaXNFZGl0aW5nKCkgJiYgZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93U2VsZWN0aW9uKCkpIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50U2VsZWN0aW9uID0gdGhpcy5yb3dOb2RlLmlzU2VsZWN0ZWQoKTtcbiAgICAgICAgICAgIHZhciBuZXdTZWxlY3Rpb24gPSAhY3VycmVudFNlbGVjdGlvbjtcbiAgICAgICAgICAgIGlmIChuZXdTZWxlY3Rpb24gfHwgIWdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzUm93RGVzZWxlY3Rpb24oKSkge1xuICAgICAgICAgICAgICAgIHZhciBncm91cFNlbGVjdHNGaWx0ZXJlZCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBTZWxlY3RzRmlsdGVyZWQoKTtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRlZENvdW50ID0gdGhpcy5yb3dOb2RlLnNldFNlbGVjdGVkUGFyYW1zKHtcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IG5ld1NlbGVjdGlvbixcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VTZWxlY3Q6IGV2ZW50LnNoaWZ0S2V5LFxuICAgICAgICAgICAgICAgICAgICBncm91cFNlbGVjdHNGaWx0ZXJlZDogZ3JvdXBTZWxlY3RzRmlsdGVyZWRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudFNlbGVjdGlvbiA9PT0gdW5kZWZpbmVkICYmIHVwZGF0ZWRDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VTZWxlY3Q6IGV2ZW50LnNoaWZ0S2V5LFxuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBTZWxlY3RzRmlsdGVyZWQ6IGdyb3VwU2VsZWN0c0ZpbHRlcmVkXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBwcmV2ZW50IGRlZmF1bHQgYXMgc3BhY2Uga2V5LCBieSBkZWZhdWx0LCBtb3ZlcyBicm93c2VyIHNjcm9sbCBkb3duXG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfTtcbiAgICBDZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgcmV0dXJuIENlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxVyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMU4gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBEbmRTb3VyY2VDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxVyhEbmRTb3VyY2VDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERuZFNvdXJjZUNvbXAocm93Tm9kZSwgY29sdW1uLCBiZWFucywgZUNlbGwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgXCI8ZGl2IGNsYXNzPVxcXCJhZy1kcmFnLWhhbmRsZSBhZy1yb3ctZHJhZ1xcXCIgZHJhZ2dhYmxlPVxcXCJ0cnVlXFxcIj48L2Rpdj5cIikgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucm93Tm9kZSA9IHJvd05vZGU7XG4gICAgICAgIF90aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICAgICAgX3RoaXMuYmVhbnMgPSBiZWFucztcbiAgICAgICAgX3RoaXMuZUNlbGwgPSBlQ2VsbDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEbmRTb3VyY2VDb21wLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIGVHdWkuYXBwZW5kQ2hpbGQoY3JlYXRlSWNvbk5vU3Bhbigncm93RHJhZycsIHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKSk7XG4gICAgICAgIC8vIHdlIG5lZWQgdG8gc3RvcCB0aGUgZXZlbnQgcHJvcGFnYXRpb24gaGVyZSB0byBhdm9pZCBzdGFydGluZyBhIHJhbmdlIHNlbGVjdGlvbiB3aGlsZSBkcmFnZ2luZ1xuICAgICAgICB0aGlzLmFkZEd1aUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGREcmFnU291cmNlKCk7XG4gICAgICAgIHRoaXMuY2hlY2tWaXNpYmlsaXR5KCk7XG4gICAgfTtcbiAgICBEbmRTb3VyY2VDb21wLnByb3RvdHlwZS5hZGREcmFnU291cmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZEd1aUV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIHRoaXMub25EcmFnU3RhcnQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBEbmRTb3VyY2VDb21wLnByb3RvdHlwZS5vbkRyYWdTdGFydCA9IGZ1bmN0aW9uIChkcmFnRXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHByb3ZpZGVkT25Sb3dEcmFnID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCkuZG5kU291cmNlT25Sb3dEcmFnO1xuICAgICAgICBkcmFnRXZlbnQuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZSh0aGlzLmVDZWxsLCAwLCAwKTtcbiAgICAgICAgLy8gZGVmYXVsdCBiZWhhdmlvdXIgaXMgdG8gY29udmVydCBkYXRhIHRvIGpzb24gYW5kIHNldCBpbnRvIGRyYWcgY29tcG9uZW50XG4gICAgICAgIHZhciBkZWZhdWx0T25Sb3dEcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIganNvbkRhdGEgPSBKU09OLnN0cmluZ2lmeShfdGhpcy5yb3dOb2RlLmRhdGEpO1xuICAgICAgICAgICAgICAgIGRyYWdFdmVudC5kYXRhVHJhbnNmZXIuc2V0RGF0YSgnYXBwbGljYXRpb24vanNvbicsIGpzb25EYXRhKTtcbiAgICAgICAgICAgICAgICBkcmFnRXZlbnQuZGF0YVRyYW5zZmVyLnNldERhdGEoJ3RleHQvcGxhaW4nLCBqc29uRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHdlIGNhbm5vdCBjb252ZXJ0IHRoZSBkYXRhIHRvIGpzb24sIHRoZW4gd2UgZG8gbm90IHNldCB0aGUgdHlwZVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAocHJvdmlkZWRPblJvd0RyYWcpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZTogdGhpcy5yb3dOb2RlLCBkcmFnRXZlbnQ6IGRyYWdFdmVudCxcbiAgICAgICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICAgICAgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcHJvdmlkZWRPblJvd0RyYWcocGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlZmF1bHRPblJvd0RyYWcoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRG5kU291cmNlQ29tcC5wcm90b3R5cGUuY2hlY2tWaXNpYmlsaXR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmlzaWJsZSA9IHRoaXMuY29sdW1uLmlzRG5kU291cmNlKHRoaXMucm93Tm9kZSk7XG4gICAgICAgIHRoaXMuc2V0RGlzcGxheWVkKHZpc2libGUpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxTihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBEbmRTb3VyY2VDb21wLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBEbmRTb3VyY2VDb21wO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxViA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXNzaWduJDUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2Fzc2lnbikgfHwgZnVuY3Rpb24gKCkge1xuICAgIF9fYXNzaWduJDUgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduJDUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgQ1NTX0NFTEwgPSAnYWctY2VsbCc7XG52YXIgQ1NTX0FVVE9fSEVJR0hUID0gJ2FnLWNlbGwtYXV0by1oZWlnaHQnO1xudmFyIENTU19OT1JNQUxfSEVJR0hUID0gJ2FnLWNlbGwtbm9ybWFsLWhlaWdodCc7XG52YXIgQ1NTX0NFTExfRk9DVVMgPSAnYWctY2VsbC1mb2N1cyc7XG52YXIgQ1NTX0NFTExfRklSU1RfUklHSFRfUElOTkVEID0gJ2FnLWNlbGwtZmlyc3QtcmlnaHQtcGlubmVkJztcbnZhciBDU1NfQ0VMTF9MQVNUX0xFRlRfUElOTkVEID0gJ2FnLWNlbGwtbGFzdC1sZWZ0LXBpbm5lZCc7XG52YXIgQ1NTX0NFTExfTk9UX0lOTElORV9FRElUSU5HID0gJ2FnLWNlbGwtbm90LWlubGluZS1lZGl0aW5nJztcbnZhciBDU1NfQ0VMTF9JTkxJTkVfRURJVElORyA9ICdhZy1jZWxsLWlubGluZS1lZGl0aW5nJztcbnZhciBDU1NfQ0VMTF9QT1BVUF9FRElUSU5HID0gJ2FnLWNlbGwtcG9wdXAtZWRpdGluZyc7XG52YXIgQ1NTX0NPTFVNTl9IT1ZFUiA9ICdhZy1jb2x1bW4taG92ZXInO1xudmFyIENTU19DRUxMX1dSQVBfVEVYVCA9ICdhZy1jZWxsLXdyYXAtdGV4dCc7XG52YXIgaW5zdGFuY2VJZFNlcXVlbmNlJDMgPSAwO1xudmFyIENlbGxDdHJsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxVihDZWxsQ3RybCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDZWxsQ3RybChjb2x1bW4sIHJvd05vZGUsIGJlYW5zLCByb3dDdHJsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnN1cHByZXNzUmVmcmVzaENlbGwgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMub25DZWxsQ29tcEF0dGFjaGVkRnVuY3MgPSBbXTtcbiAgICAgICAgX3RoaXMucmVtb3ZlQXV0b0hlaWdodExpc3RlbmVycyA9IG51bGw7XG4gICAgICAgIF90aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICAgICAgX3RoaXMucm93Tm9kZSA9IHJvd05vZGU7XG4gICAgICAgIF90aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIF90aGlzLnJvd0N0cmwgPSByb3dDdHJsO1xuICAgICAgICAvLyB1bmlxdWUgaWQgdG8gdGhpcyBpbnN0YW5jZSwgaW5jbHVkaW5nIHRoZSBjb2x1bW4gSUQgdG8gaGVscCB3aXRoIGRlYnVnZ2luZyBpbiBSZWFjdCBhcyBpdCdzIHVzZWQgaW4gJ2tleSdcbiAgICAgICAgX3RoaXMuaW5zdGFuY2VJZCA9IGNvbHVtbi5nZXRJZCgpICsgJy0nICsgaW5zdGFuY2VJZFNlcXVlbmNlJDMrKztcbiAgICAgICAgX3RoaXMuY3JlYXRlQ2VsbFBvc2l0aW9uKCk7XG4gICAgICAgIF90aGlzLmFkZEZlYXR1cmVzKCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNlbGxQb3NpdGlvbkZlYXR1cmUgPSBuZXcgQ2VsbFBvc2l0aW9uRmVhdHVyZSh0aGlzLCB0aGlzLmJlYW5zKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jZWxsUG9zaXRpb25GZWF0dXJlLmRlc3Ryb3koKTsgfSk7XG4gICAgICAgIHRoaXMuY2VsbEN1c3RvbVN0eWxlRmVhdHVyZSA9IG5ldyBDZWxsQ3VzdG9tU3R5bGVGZWF0dXJlKHRoaXMsIHRoaXMuYmVhbnMpO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNlbGxDdXN0b21TdHlsZUZlYXR1cmUuZGVzdHJveSgpOyB9KTtcbiAgICAgICAgdGhpcy5jZWxsTW91c2VMaXN0ZW5lckZlYXR1cmUgPSBuZXcgQ2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlKHRoaXMsIHRoaXMuYmVhbnMsIHRoaXMuY29sdW1uKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jZWxsTW91c2VMaXN0ZW5lckZlYXR1cmUuZGVzdHJveSgpOyB9KTtcbiAgICAgICAgdGhpcy5jZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUgPSBuZXcgQ2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlKHRoaXMsIHRoaXMuYmVhbnMsIHRoaXMuY29sdW1uLCB0aGlzLnJvd05vZGUsIHRoaXMucm93Q3RybCk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlLmRlc3Ryb3koKTsgfSk7XG4gICAgICAgIHZhciByYW5nZVNlbGVjdGlvbkVuYWJsZWQgPSB0aGlzLmJlYW5zLnJhbmdlU2VydmljZSAmJiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJhbmdlU2VsZWN0aW9uKCk7XG4gICAgICAgIGlmIChyYW5nZVNlbGVjdGlvbkVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbFJhbmdlRmVhdHVyZSA9IG5ldyBDZWxsUmFuZ2VGZWF0dXJlKHRoaXMuYmVhbnMsIHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jZWxsUmFuZ2VGZWF0dXJlLmRlc3Ryb3koKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZGRUb29sdGlwRmVhdHVyZSgpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmFkZFRvb2x0aXBGZWF0dXJlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZ2V0VG9vbHRpcFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNvbERlZiA9IF90aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgICAgIHZhciBkYXRhID0gX3RoaXMucm93Tm9kZS5kYXRhO1xuICAgICAgICAgICAgaWYgKGNvbERlZi50b29sdGlwRmllbGQgJiYgZXhpc3RzKGRhdGEpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldFZhbHVlVXNpbmdGaWVsZChkYXRhLCBjb2xEZWYudG9vbHRpcEZpZWxkLCBfdGhpcy5jb2x1bW4uaXNUb29sdGlwRmllbGRDb250YWluc0RvdHMoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdmFsdWVHZXR0ZXIgPSBjb2xEZWYudG9vbHRpcFZhbHVlR2V0dGVyO1xuICAgICAgICAgICAgaWYgKHZhbHVlR2V0dGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlR2V0dGVyKHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYXRpb246ICdjZWxsJyxcbiAgICAgICAgICAgICAgICAgICAgYXBpOiBfdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkFwaTogX3RoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiBfdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICAgICAgICAgICAgICBjb2xEZWY6IF90aGlzLmNvbHVtbi5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uOiBfdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICAgICAgICAgIHJvd0luZGV4OiBfdGhpcy5jZWxsUG9zaXRpb24ucm93SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIG5vZGU6IF90aGlzLnJvd05vZGUsXG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IF90aGlzLnJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IF90aGlzLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZUZvcm1hdHRlZDogX3RoaXMudmFsdWVGb3JtYXR0ZWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHRvb2x0aXBDdHJsID0ge1xuICAgICAgICAgICAgZ2V0Q29sdW1uOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb2x1bW47IH0sXG4gICAgICAgICAgICBnZXRDb2xEZWY6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTsgfSxcbiAgICAgICAgICAgIGdldFJvd0luZGV4OiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jZWxsUG9zaXRpb24ucm93SW5kZXg7IH0sXG4gICAgICAgICAgICBnZXRSb3dOb2RlOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5yb3dOb2RlOyB9LFxuICAgICAgICAgICAgZ2V0R3VpOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5nZXRHdWkoKTsgfSxcbiAgICAgICAgICAgIGdldExvY2F0aW9uOiBmdW5jdGlvbiAoKSB7IHJldHVybiAnY2VsbCc7IH0sXG4gICAgICAgICAgICBnZXRUb29sdGlwVmFsdWU6IGdldFRvb2x0aXBWYWx1ZSxcbiAgICAgICAgICAgIC8vIHRoaXMgbWFrZXMgbm8gc2Vuc2UsIHdoeSBpcyB0aGUgY2VsbCBmb3JtYXR0ZWQgdmFsdWUgcGFzc2VkIHRvIHRoZSB0b29sdGlwPz8/XG4gICAgICAgICAgICBnZXRWYWx1ZUZvcm1hdHRlZDogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudmFsdWVGb3JtYXR0ZWQ7IH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy50b29sdGlwRmVhdHVyZSA9IG5ldyBUb29sdGlwRmVhdHVyZSh0b29sdGlwQ3RybCwgdGhpcy5iZWFucyk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudG9vbHRpcEZlYXR1cmUuZGVzdHJveSgpOyB9KTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGNvbXAsIGVHdWksIGVDZWxsV3JhcHBlciwgcHJpbnRMYXlvdXQsIHN0YXJ0RWRpdGluZykge1xuICAgICAgICB0aGlzLmNlbGxDb21wID0gY29tcDtcbiAgICAgICAgdGhpcy5nb3cgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlcjtcbiAgICAgICAgdGhpcy5lR3VpID0gZUd1aTtcbiAgICAgICAgdGhpcy5wcmludExheW91dCA9IHByaW50TGF5b3V0O1xuICAgICAgICAvLyB3ZSBmb3JjZSB0byBtYWtlIHN1cmUgZm9ybWF0dGVyIGdldHMgY2FsbGVkIGF0IGxlYXN0IG9uY2UsXG4gICAgICAgIC8vIGV2ZW4gaWYgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkIChpcyBpcyB1bmRlZmluZWQpXG4gICAgICAgIHRoaXMudXBkYXRlQW5kRm9ybWF0VmFsdWUodHJ1ZSk7XG4gICAgICAgIHRoaXMuYWRkRG9tRGF0YSgpO1xuICAgICAgICB0aGlzLm9uQ2VsbEZvY3VzZWQoKTtcbiAgICAgICAgdGhpcy5hcHBseVN0YXRpY0Nzc0NsYXNzZXMoKTtcbiAgICAgICAgdGhpcy5zZXRXcmFwVGV4dCgpO1xuICAgICAgICB0aGlzLm9uRmlyc3RSaWdodFBpbm5lZENoYW5nZWQoKTtcbiAgICAgICAgdGhpcy5vbkxhc3RMZWZ0UGlubmVkQ2hhbmdlZCgpO1xuICAgICAgICB0aGlzLm9uQ29sdW1uSG92ZXIoKTtcbiAgICAgICAgdGhpcy5zZXR1cENvbnRyb2xDb21wcygpO1xuICAgICAgICBpZiAoZUNlbGxXcmFwcGVyKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hBdXRvSGVpZ2h0KGVDZWxsV3JhcHBlcik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRBcmlhQ29sSW5kZXgoKTtcbiAgICAgICAgaWYgKCF0aGlzLmdvdy5pc1N1cHByZXNzQ2VsbEZvY3VzKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbENvbXAuc2V0VGFiSW5kZXgoLTEpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2xJZFNhbml0aXNlZCA9IGVzY2FwZVN0cmluZyh0aGlzLmNvbHVtbi5nZXRJZCgpKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5zZXRDb2xJZChjb2xJZFNhbml0aXNlZCk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuc2V0Um9sZSgnZ3JpZGNlbGwnKTtcbiAgICAgICAgdGhpcy5jZWxsUG9zaXRpb25GZWF0dXJlLnNldENvbXAoZUd1aSk7XG4gICAgICAgIHRoaXMuY2VsbEN1c3RvbVN0eWxlRmVhdHVyZS5zZXRDb21wKGNvbXApO1xuICAgICAgICB0aGlzLnRvb2x0aXBGZWF0dXJlLnNldENvbXAoY29tcCk7XG4gICAgICAgIHRoaXMuY2VsbEtleWJvYXJkTGlzdGVuZXJGZWF0dXJlLnNldENvbXAodGhpcy5lR3VpKTtcbiAgICAgICAgaWYgKHRoaXMuY2VsbFJhbmdlRmVhdHVyZSkge1xuICAgICAgICAgICAgdGhpcy5jZWxsUmFuZ2VGZWF0dXJlLnNldENvbXAoY29tcCwgZUd1aSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXJ0RWRpdGluZyAmJiB0aGlzLmlzQ2VsbEVkaXRhYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRFZGl0aW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNob3dWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm9uQ2VsbENvbXBBdHRhY2hlZEZ1bmNzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5vbkNlbGxDb21wQXR0YWNoZWRGdW5jcy5mb3JFYWNoKGZ1bmN0aW9uIChmdW5jKSB7IHJldHVybiBmdW5jKCk7IH0pO1xuICAgICAgICAgICAgdGhpcy5vbkNlbGxDb21wQXR0YWNoZWRGdW5jcyA9IFtdO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUucmVmcmVzaEF1dG9IZWlnaHQgPSBmdW5jdGlvbiAoZUNlbGxXcmFwcGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5jb2x1bW4uaXNBdXRvSGVpZ2h0KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZVBhcmVudENlbGwgPSBlQ2VsbFdyYXBwZXIucGFyZW50RWxlbWVudDtcbiAgICAgICAgLy8gdGFraW5nIG1pblJvd0hlaWdodCBmcm9tIGdldFJvd0hlaWdodEZvck5vZGUgbWVhbnMgdGhlIGdldFJvd0hlaWdodCgpIGNhbGxiYWNrIGlzIHVzZWQsXG4gICAgICAgIC8vIHRodXMgYWxsb3dpbmcgZGlmZmVyZW50IG1pbiBoZWlnaHRzIGZvciBkaWZmZXJlbnQgcm93cy5cbiAgICAgICAgdmFyIG1pblJvd0hlaWdodCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0hlaWdodEZvck5vZGUodGhpcy5yb3dOb2RlKS5oZWlnaHQ7XG4gICAgICAgIHZhciBtZWFzdXJlSGVpZ2h0ID0gZnVuY3Rpb24gKHRpbWVzQ2FsbGVkKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuZWRpdGluZykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGJlY2F1c2Ugb2YgdGhlIHJldHJ5J3MgYmVsb3csIGl0J3MgcG9zc2libGUgdGhlIHJldHJ5J3MgZ28gYmV5b25kXG4gICAgICAgICAgICAvLyB0aGUgcm93cyBsaWZlLlxuICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgX2EgPSBnZXRFbGVtZW50U2l6ZShlUGFyZW50Q2VsbCksIHBhZGRpbmdUb3AgPSBfYS5wYWRkaW5nVG9wLCBwYWRkaW5nQm90dG9tID0gX2EucGFkZGluZ0JvdHRvbTtcbiAgICAgICAgICAgIHZhciB3cmFwcGVySGVpZ2h0ID0gZUNlbGxXcmFwcGVyLm9mZnNldEhlaWdodDtcbiAgICAgICAgICAgIHZhciBhdXRvSGVpZ2h0ID0gd3JhcHBlckhlaWdodCArIHBhZGRpbmdUb3AgKyBwYWRkaW5nQm90dG9tO1xuICAgICAgICAgICAgaWYgKHRpbWVzQ2FsbGVkIDwgNSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vdCBpbiBkb2MgeWV0LCBtZWFucyBmcmFtZXdvcmsgbm90IHlldCBpbnNlcnRlZCwgc28gd2FpdCBmb3IgbmV4dCBWTSB0dXJuLFxuICAgICAgICAgICAgICAgIC8vIG1heWJlIGl0IHdpbGwgYmUgcmVhZHkgbmV4dCBWTSB0dXJuXG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IF90aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICAgICAgICAgIHZhciBub3RZZXRJbkRvbSA9ICFkb2MgfHwgIWRvYy5jb250YWlucyhlQ2VsbFdyYXBwZXIpO1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgaGFwcGVucyBpbiBSZWFjdCwgd2hlcmUgUmVhY3QgaGFzbid0IHB1dCBhbnkgY29udGVudCBpbi4gd2Ugc2F5ICdwb3NzaWJseSdcbiAgICAgICAgICAgICAgICAvLyBhcyBhKSBtYXkgbm90IGJlIFJlYWN0IGFuZCBiKSB0aGUgY2VsbCBjb3VsZCBiZSBlbXB0eSBhbnl3YXlcbiAgICAgICAgICAgICAgICB2YXIgcG9zc2libHlOb0NvbnRlbnRZZXQgPSBhdXRvSGVpZ2h0ID09IDA7XG4gICAgICAgICAgICAgICAgaWYgKG5vdFlldEluRG9tIHx8IHBvc3NpYmx5Tm9Db250ZW50WWV0KSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmJlYW5zLmZyYW1ld29ya092ZXJyaWRlcy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIG1lYXN1cmVIZWlnaHQodGltZXNDYWxsZWQgKyAxKTsgfSwgMCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gTWF0aC5tYXgoYXV0b0hlaWdodCwgbWluUm93SGVpZ2h0KTtcbiAgICAgICAgICAgIF90aGlzLnJvd05vZGUuc2V0Um93QXV0b0hlaWdodChuZXdIZWlnaHQsIF90aGlzLmNvbHVtbik7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIG1lYXN1cmVIZWlnaHQoMCk7IH07XG4gICAgICAgIC8vIGRvIG9uY2UgdG8gc2V0IHNpemUgaW4gY2FzZSBzaXplIGRvZXNuJ3QgY2hhbmdlLCBjb21tb24gd2hlbiBjZWxsIGlzIGJsYW5rXG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgICAgIHZhciBkZXN0cm95UmVzaXplT2JzZXJ2ZXIgPSB0aGlzLmJlYW5zLnJlc2l6ZU9ic2VydmVyU2VydmljZS5vYnNlcnZlUmVzaXplKGVDZWxsV3JhcHBlciwgbGlzdGVuZXIpO1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVBdXRvSGVpZ2h0TGlzdGVuZXJzKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUF1dG9IZWlnaHRMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlQXV0b0hlaWdodExpc3RlbmVycyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW1vdmVBdXRvSGVpZ2h0TGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZGVzdHJveVJlc2l6ZU9ic2VydmVyKCk7XG4gICAgICAgICAgICBfdGhpcy5yb3dOb2RlLnNldFJvd0F1dG9IZWlnaHQodW5kZWZpbmVkLCBfdGhpcy5jb2x1bW4pO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmdldEluc3RhbmNlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmluc3RhbmNlSWQ7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc2hvd1ZhbHVlID0gZnVuY3Rpb24gKGZvcmNlTmV3Q2VsbFJlbmRlcmVySW5zdGFuY2UpIHtcbiAgICAgICAgaWYgKGZvcmNlTmV3Q2VsbFJlbmRlcmVySW5zdGFuY2UgPT09IHZvaWQgMCkgeyBmb3JjZU5ld0NlbGxSZW5kZXJlckluc3RhbmNlID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIHZhbHVlVG9EaXNwbGF5ID0gdGhpcy52YWx1ZUZvcm1hdHRlZCAhPSBudWxsID8gdGhpcy52YWx1ZUZvcm1hdHRlZCA6IHRoaXMudmFsdWU7XG4gICAgICAgIHZhciBwYXJhbXMgPSB0aGlzLmNyZWF0ZUNlbGxSZW5kZXJlclBhcmFtcygpO1xuICAgICAgICB2YXIgY29tcERldGFpbHMgPSB0aGlzLmJlYW5zLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldENlbGxSZW5kZXJlckRldGFpbHModGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCksIHBhcmFtcyk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuc2V0UmVuZGVyRGV0YWlscyhjb21wRGV0YWlscywgdmFsdWVUb0Rpc3BsYXksIGZvcmNlTmV3Q2VsbFJlbmRlcmVySW5zdGFuY2UpO1xuICAgICAgICB0aGlzLnJlZnJlc2hIYW5kbGUoKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5zZXR1cENvbnRyb2xDb21wcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB0aGlzLmluY2x1ZGVTZWxlY3Rpb24gPSB0aGlzLmlzSW5jbHVkZUNvbnRyb2woY29sRGVmLmNoZWNrYm94U2VsZWN0aW9uKTtcbiAgICAgICAgdGhpcy5pbmNsdWRlUm93RHJhZyA9IHRoaXMuaXNJbmNsdWRlQ29udHJvbChjb2xEZWYucm93RHJhZyk7XG4gICAgICAgIHRoaXMuaW5jbHVkZURuZFNvdXJjZSA9IHRoaXMuaXNJbmNsdWRlQ29udHJvbChjb2xEZWYuZG5kU291cmNlKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5zZXRJbmNsdWRlU2VsZWN0aW9uKHRoaXMuaW5jbHVkZVNlbGVjdGlvbik7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuc2V0SW5jbHVkZURuZFNvdXJjZSh0aGlzLmluY2x1ZGVEbmRTb3VyY2UpO1xuICAgICAgICB0aGlzLmNlbGxDb21wLnNldEluY2x1ZGVSb3dEcmFnKHRoaXMuaW5jbHVkZVJvd0RyYWcpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmlzRm9yY2VXcmFwcGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB0ZXh0IHNlbGVjdGlvbiByZXF1aXJlcyB0aGUgdmFsdWUgdG8gYmUgd3JhcHBlZCBpbiBhbm90aGVyIGVsZW1lbnRcbiAgICAgICAgdmFyIGZvcmNlV3JhcHBlciA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlQ2VsbFRleHRTZWxlY3Rpb24oKSB8fCB0aGlzLmNvbHVtbi5pc0F1dG9IZWlnaHQoKTtcbiAgICAgICAgcmV0dXJuIGZvcmNlV3JhcHBlcjtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5pc0luY2x1ZGVDb250cm9sID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciByb3dOb2RlUGlubmVkID0gdGhpcy5yb3dOb2RlLnJvd1Bpbm5lZCAhPSBudWxsO1xuICAgICAgICB2YXIgaXNGdW5jID0gdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nO1xuICAgICAgICB2YXIgcmVzID0gcm93Tm9kZVBpbm5lZCA/IGZhbHNlIDogaXNGdW5jIHx8IHZhbHVlID09PSB0cnVlO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLnJlZnJlc2hTaG91bGREZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIHZhciBzZWxlY3Rpb25DaGFuZ2VkID0gdGhpcy5pbmNsdWRlU2VsZWN0aW9uICE9IHRoaXMuaXNJbmNsdWRlQ29udHJvbChjb2xEZWYuY2hlY2tib3hTZWxlY3Rpb24pO1xuICAgICAgICB2YXIgcm93RHJhZ0NoYW5nZWQgPSB0aGlzLmluY2x1ZGVSb3dEcmFnICE9IHRoaXMuaXNJbmNsdWRlQ29udHJvbChjb2xEZWYucm93RHJhZyk7XG4gICAgICAgIHZhciBkbmRTb3VyY2VDaGFuZ2VkID0gdGhpcy5pbmNsdWRlRG5kU291cmNlICE9IHRoaXMuaXNJbmNsdWRlQ29udHJvbChjb2xEZWYuZG5kU291cmNlKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdGlvbkNoYW5nZWQgfHwgcm93RHJhZ0NoYW5nZWQgfHwgZG5kU291cmNlQ2hhbmdlZDtcbiAgICB9O1xuICAgIC8vIGVpdGhlciBjYWxsZWQgaW50ZXJuYWxseSBpZiBzaW5nbGUgY2VsbCBlZGl0aW5nLCBvciBjYWxsZWQgYnkgcm93UmVuZGVyZXIgaWYgcm93IGVkaXRpbmdcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc3RhcnRFZGl0aW5nID0gZnVuY3Rpb24gKGtleSwgY2hhclByZXNzLCBjZWxsU3RhcnRlZEVkaXQsIGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChrZXkgPT09IHZvaWQgMCkgeyBrZXkgPSBudWxsOyB9XG4gICAgICAgIGlmIChjaGFyUHJlc3MgPT09IHZvaWQgMCkgeyBjaGFyUHJlc3MgPSBudWxsOyB9XG4gICAgICAgIGlmIChjZWxsU3RhcnRlZEVkaXQgPT09IHZvaWQgMCkgeyBjZWxsU3RhcnRlZEVkaXQgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoZXZlbnQgPT09IHZvaWQgMCkgeyBldmVudCA9IG51bGw7IH1cbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgaWYgKCF0aGlzLmlzQ2VsbEVkaXRhYmxlKCkgfHwgdGhpcy5lZGl0aW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gYmVjYXVzZSBvZiBhc3luYyBpbiBSZWFjdCwgdGhlIGNlbGxDb21wIG1heSBub3QgYmUgc2V0IHlldCwgaWYgbm8gY2VsbENvbXAgdGhlbiB3ZSBhcmVcbiAgICAgICAgLy8geWV0IHRvIGluaXRpYWxpc2UgdGhlIGNlbGwsIHNvIHdlIHJlLXNjaGVkdWxlIHRoaXMgb3BlcmF0aW9uIGZvciB3aGVuIGNlbExDb21wIGlzIGF0dGFjaGVkXG4gICAgICAgIGlmICghdGhpcy5jZWxsQ29tcCkge1xuICAgICAgICAgICAgdGhpcy5vbkNlbGxDb21wQXR0YWNoZWRGdW5jcy5wdXNoKGZ1bmN0aW9uICgpIHsgX3RoaXMuc3RhcnRFZGl0aW5nKGtleSwgY2hhclByZXNzLCBjZWxsU3RhcnRlZEVkaXQsIGV2ZW50KTsgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVkaXRvclBhcmFtcyA9IHRoaXMuY3JlYXRlQ2VsbEVkaXRvclBhcmFtcyhrZXksIGNoYXJQcmVzcywgY2VsbFN0YXJ0ZWRFZGl0KTtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB2YXIgY29tcERldGFpbHMgPSB0aGlzLmJlYW5zLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldENlbGxFZGl0b3JEZXRhaWxzKGNvbERlZiwgZWRpdG9yUGFyYW1zKTtcbiAgICAgICAgLy8gaWYgY2VsbEVkaXRvclNlbGVjdG9yIHdhcyB1c2VkLCB3ZSBnaXZlIHByZWZlcmVuY2UgdG8gcG9wdXAgYW5kIHBvcHVwUG9zaXRpb24gZnJvbSB0aGUgc2VsZWN0b3JcbiAgICAgICAgdmFyIHBvcHVwID0gKChfYSA9IGNvbXBEZXRhaWxzKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EucG9wdXBGcm9tU2VsZWN0b3IpICE9IG51bGwgPyBjb21wRGV0YWlscy5wb3B1cEZyb21TZWxlY3RvciA6ICEhY29sRGVmLmNlbGxFZGl0b3JQb3B1cDtcbiAgICAgICAgdmFyIHBvc2l0aW9uID0gKChfYiA9IGNvbXBEZXRhaWxzKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IucG9wdXBQb3NpdGlvbkZyb21TZWxlY3RvcikgIT0gbnVsbCA/IGNvbXBEZXRhaWxzLnBvcHVwUG9zaXRpb25Gcm9tU2VsZWN0b3IgOiBjb2xEZWYuY2VsbEVkaXRvclBvcHVwUG9zaXRpb247XG4gICAgICAgIHRoaXMuc2V0RWRpdGluZyh0cnVlLCBwb3B1cCk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuc2V0RWRpdERldGFpbHMoY29tcERldGFpbHMsIHBvcHVwLCBwb3NpdGlvbik7XG4gICAgICAgIHZhciBlID0gdGhpcy5jcmVhdGVFdmVudChldmVudCwgRXZlbnRzLkVWRU5UX0NFTExfRURJVElOR19TVEFSVEVEKTtcbiAgICAgICAgdGhpcy5iZWFucy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChlKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5zZXRFZGl0aW5nID0gZnVuY3Rpb24gKGVkaXRpbmcsIGluUG9wdXApIHtcbiAgICAgICAgaWYgKGluUG9wdXAgPT09IHZvaWQgMCkgeyBpblBvcHVwID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKHRoaXMuZWRpdGluZyA9PT0gZWRpdGluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWRpdGluZyA9IGVkaXRpbmc7XG4gICAgICAgIHRoaXMuZWRpdGluZ0luUG9wdXAgPSBpblBvcHVwO1xuICAgICAgICB0aGlzLnNldElubGluZUVkaXRpbmdDbGFzcygpO1xuICAgICAgICB0aGlzLnJlZnJlc2hIYW5kbGUoKTtcbiAgICB9O1xuICAgIC8vIHBhc3MgaW4gJ3RydWUnIHRvIGNhbmNlbCB0aGUgZWRpdGluZy5cbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc3RvcFJvd09yQ2VsbEVkaXQgPSBmdW5jdGlvbiAoY2FuY2VsKSB7XG4gICAgICAgIGlmIChjYW5jZWwgPT09IHZvaWQgMCkgeyBjYW5jZWwgPSBmYWxzZTsgfVxuICAgICAgICBpZiAodGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNGdWxsUm93RWRpdCgpKSB7XG4gICAgICAgICAgICB0aGlzLnJvd0N0cmwuc3RvcFJvd0VkaXRpbmcoY2FuY2VsKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcEVkaXRpbmcoY2FuY2VsKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLm9uUG9wdXBFZGl0b3JDbG9zZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pc0VkaXRpbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5vdGU6IHRoaXMgaGFwcGVucyBiZWNhdXNlIG9mIGEgY2xpY2sgb3V0c2lkZSBvZiB0aGUgZ3JpZCBvciBpZiB0aGUgcG9wdXBFZGl0b3JcbiAgICAgICAgLy8gaXMgY2xvc2VkIHdpdGggYEVzY2FwZWAga2V5LiBpZiBhbm90aGVyIGNlbGwgd2FzIGNsaWNrZWQsIHRoZW4gdGhlIGVkaXRpbmcgd2lsbFxuICAgICAgICAvLyBoYXZlIGFscmVhZHkgc3RvcHBlZCBhbmQgcmV0dXJuZWQgb24gdGhlIGNvbmRpdGlvbmFsIGFib3ZlLlxuICAgICAgICB0aGlzLnN0b3BFZGl0aW5nQW5kRm9jdXMoKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS50YWtlVmFsdWVGcm9tQ2VsbEVkaXRvciA9IGZ1bmN0aW9uIChjYW5jZWwpIHtcbiAgICAgICAgdmFyIG5vVmFsdWVSZXN1bHQgPSB7IG5ld1ZhbHVlRXhpc3RzOiBmYWxzZSB9O1xuICAgICAgICBpZiAoY2FuY2VsKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9WYWx1ZVJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbEVkaXRvciA9IHRoaXMuY2VsbENvbXAuZ2V0Q2VsbEVkaXRvcigpO1xuICAgICAgICBpZiAoIWNlbGxFZGl0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBub1ZhbHVlUmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIHZhciB1c2VyV2FudHNUb0NhbmNlbCA9IGNlbGxFZGl0b3IuaXNDYW5jZWxBZnRlckVuZCAmJiBjZWxsRWRpdG9yLmlzQ2FuY2VsQWZ0ZXJFbmQoKTtcbiAgICAgICAgaWYgKHVzZXJXYW50c1RvQ2FuY2VsKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9WYWx1ZVJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV3VmFsdWUgPSBjZWxsRWRpdG9yLmdldFZhbHVlKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICBuZXdWYWx1ZUV4aXN0czogdHJ1ZVxuICAgICAgICB9O1xuICAgIH07XG4gICAgLyoqXG4gICAgICogQHJldHVybnMgYFRydWVgIGlmIHRoZSB2YWx1ZSBjaGFuZ2VzLCBvdGhlcndpc2UgYEZhbHNlYC5cbiAgICAgKi9cbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc2F2ZU5ld1ZhbHVlID0gZnVuY3Rpb24gKG9sZFZhbHVlLCBuZXdWYWx1ZSkge1xuICAgICAgICBpZiAobmV3VmFsdWUgPT09IG9sZFZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUmVhZE9ubHlFZGl0KCkpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudEZvclNhdmVWYWx1ZVJlYWRPbmx5KG9sZFZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2Ugc3VwcHJlc3NSZWZyZXNoQ2VsbCBiZWNhdXNlIHRoZSBjYWxsIHRvIHJvd05vZGUuc2V0RGF0YVZhbHVlKCkgcmVzdWx0cyBpbiBjaGFuZ2UgZGV0ZWN0aW9uXG4gICAgICAgIC8vIGdldHRpbmcgdHJpZ2dlcmVkLCB3aGljaCByZXN1bHRzIGluIGFsbCBjZWxscyBnZXR0aW5nIHJlZnJlc2hlZC4gd2UgZG8gbm90IHdhbnQgdGhpcyByZWZyZXNoXG4gICAgICAgIC8vIHRvIGhhcHBlbiBvbiB0aGlzIGNhbGwgYXMgd2Ugd2FudCB0byBjYWxsIGl0IGV4cGxpY2l0bHkgYmVsb3cuIG90aGVyd2lzZSByZWZyZXNoIGdldHMgY2FsbGVkIHR3aWNlLlxuICAgICAgICAvLyBpZiB3ZSBvbmx5IGRpZCB0aGlzIHJlZnJlc2ggKGFuZCBub3QgdGhlIG9uZSBiZWxvdykgdGhlbiB0aGUgY2VsbCB3b3VsZCBmbGFzaCBhbmQgbm90IGJlIGZvcmNlZC5cbiAgICAgICAgdGhpcy5zdXBwcmVzc1JlZnJlc2hDZWxsID0gdHJ1ZTtcbiAgICAgICAgdmFyIHZhbHVlQ2hhbmdlZCA9IHRoaXMucm93Tm9kZS5zZXREYXRhVmFsdWUodGhpcy5jb2x1bW4sIG5ld1ZhbHVlKTtcbiAgICAgICAgdGhpcy5zdXBwcmVzc1JlZnJlc2hDZWxsID0gZmFsc2U7XG4gICAgICAgIHJldHVybiB2YWx1ZUNoYW5nZWQ7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudEZvclNhdmVWYWx1ZVJlYWRPbmx5ID0gZnVuY3Rpb24gKG9sZFZhbHVlLCBuZXdWYWx1ZSkge1xuICAgICAgICB2YXIgcm93Tm9kZSA9IHRoaXMucm93Tm9kZTtcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0NFTExfRURJVF9SRVFVRVNULFxuICAgICAgICAgICAgZXZlbnQ6IG51bGwsXG4gICAgICAgICAgICByb3dJbmRleDogcm93Tm9kZS5yb3dJbmRleCxcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogcm93Tm9kZS5yb3dQaW5uZWQsXG4gICAgICAgICAgICBjb2x1bW46IHRoaXMuY29sdW1uLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmJlYW5zLmdyaWRBcGksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuYmVhbnMuY29sdW1uQXBpLFxuICAgICAgICAgICAgY29sRGVmOiB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKSxcbiAgICAgICAgICAgIGRhdGE6IHJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgIG5vZGU6IHJvd05vZGUsXG4gICAgICAgICAgICBvbGRWYWx1ZTogb2xkVmFsdWUsXG4gICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICB2YWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICBzb3VyY2U6IHVuZGVmaW5lZFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEVuZHMgdGhlIENlbGwgRWRpdGluZ1xuICAgICAqIEBwYXJhbSBjYW5jZWwgYFRydWVgIGlmIHRoZSBlZGl0IHByb2Nlc3MgaXMgYmVpbmcgY2FuY2VsZWQuXG4gICAgICogQHJldHVybnMgYFRydWVgIGlmIHRoZSB2YWx1ZSBvZiB0aGUgYEdyaWRDZWxsYCBoYXMgYmVlbiB1cGRhdGVkLCBvdGhlcndpc2UgYEZhbHNlYC5cbiAgICAgKi9cbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc3RvcEVkaXRpbmcgPSBmdW5jdGlvbiAoY2FuY2VsKSB7XG4gICAgICAgIGlmIChjYW5jZWwgPT09IHZvaWQgMCkgeyBjYW5jZWwgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoIXRoaXMuZWRpdGluZykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBfYSA9IHRoaXMudGFrZVZhbHVlRnJvbUNlbGxFZGl0b3IoY2FuY2VsKSwgbmV3VmFsdWUgPSBfYS5uZXdWYWx1ZSwgbmV3VmFsdWVFeGlzdHMgPSBfYS5uZXdWYWx1ZUV4aXN0cztcbiAgICAgICAgdmFyIG9sZFZhbHVlID0gdGhpcy5nZXRWYWx1ZUZyb21WYWx1ZVNlcnZpY2UoKTtcbiAgICAgICAgdmFyIHZhbHVlQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICBpZiAobmV3VmFsdWVFeGlzdHMpIHtcbiAgICAgICAgICAgIHZhbHVlQ2hhbmdlZCA9IHRoaXMuc2F2ZU5ld1ZhbHVlKG9sZFZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRFZGl0aW5nKGZhbHNlKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5zZXRFZGl0RGV0YWlscygpOyAvLyBwYXNzaW5nIG5vdGhpbmcgc3RvcHMgZWRpdGluZ1xuICAgICAgICB0aGlzLnVwZGF0ZUFuZEZvcm1hdFZhbHVlKCk7XG4gICAgICAgIHRoaXMucmVmcmVzaENlbGwoeyBmb3JjZVJlZnJlc2g6IHRydWUsIHN1cHByZXNzRmxhc2g6IHRydWUgfSk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFZGl0aW5nU3RvcHBlZEV2ZW50KG9sZFZhbHVlLCBuZXdWYWx1ZSwgIWNhbmNlbCAmJiAhIXZhbHVlQ2hhbmdlZCk7XG4gICAgICAgIHJldHVybiB2YWx1ZUNoYW5nZWQ7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZGlzcGF0Y2hFZGl0aW5nU3RvcHBlZEV2ZW50ID0gZnVuY3Rpb24gKG9sZFZhbHVlLCBuZXdWYWx1ZSwgdmFsdWVDaGFuZ2VkKSB7XG4gICAgICAgIHZhciBlZGl0aW5nU3RvcHBlZEV2ZW50ID0gX19hc3NpZ24kNShfX2Fzc2lnbiQ1KHt9LCB0aGlzLmNyZWF0ZUV2ZW50KG51bGwsIEV2ZW50cy5FVkVOVF9DRUxMX0VESVRJTkdfU1RPUFBFRCkpLCB7IG9sZFZhbHVlOiBvbGRWYWx1ZSxcbiAgICAgICAgICAgIG5ld1ZhbHVlOiBuZXdWYWx1ZSxcbiAgICAgICAgICAgIHZhbHVlQ2hhbmdlZDogdmFsdWVDaGFuZ2VkIH0pO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGVkaXRpbmdTdG9wcGVkRXZlbnQpO1xuICAgIH07XG4gICAgLy8gaWYgd2UgYXJlIGVkaXRpbmcgaW5saW5lLCB0aGVuIHdlIGRvbid0IGhhdmUgdGhlIHBhZGRpbmcgaW4gdGhlIGNlbGwgKHNldCBpbiB0aGUgdGhlbWVzKVxuICAgIC8vIHRvIGFsbG93IHRoZSB0ZXh0IGVkaXRvciBmdWxsIGFjY2VzcyB0byB0aGUgZW50aXJlIGNlbGxcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc2V0SW5saW5lRWRpdGluZ0NsYXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuaXNBbGl2ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gYmVjYXVzZSBvZiBhc3luYyBpbiBSZWFjdCwgdGhlIGNlbGxDb21wIG1heSBub3QgYmUgc2V0IHlldCwgaWYgbm8gY2VsbENvbXAgdGhlbiB3ZSBhcmVcbiAgICAgICAgLy8geWV0IHRvIGluaXRpYWxpc2UgdGhlIGNlbGwsIHNvIHdlIHJlLXNjaGVkdWxlIHRoaXMgb3BlcmF0aW9uIGZvciB3aGVuIGNlbExDb21wIGlzIGF0dGFjaGVkXG4gICAgICAgIGlmICghdGhpcy5jZWxsQ29tcCkge1xuICAgICAgICAgICAgdGhpcy5vbkNlbGxDb21wQXR0YWNoZWRGdW5jcy5wdXNoKGZ1bmN0aW9uICgpIHsgX3RoaXMuc2V0SW5saW5lRWRpdGluZ0NsYXNzKCk7IH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFnLWNlbGwtaW5saW5lLWVkaXRpbmcgLSBhcHBlYXJzIHdoZW4gdXNlciBpcyBpbmxpbmUgZWRpdGluZ1xuICAgICAgICAvLyBhZy1jZWxsLW5vdC1pbmxpbmUtZWRpdGluZyAtIGFwcGVhcnMgd2hlbiB1c2VyIGlzIG5vIGlubGluZSBlZGl0aW5nXG4gICAgICAgIC8vIGFnLWNlbGwtcG9wdXAtZWRpdGluZyAtIGFwcGVhcnMgd2hlbiB1c2VyIGlzIGVkaXRpbmcgY2VsbCBpbiBwb3B1cCAoYXBwZWFycyBvbiB0aGUgY2VsbCwgbm90IG9uIHRoZSBwb3B1cClcbiAgICAgICAgLy8gbm90ZTogb25lIG9mIHthZy1jZWxsLWlubGluZS1lZGl0aW5nLCBhZy1jZWxsLW5vdC1pbmxpbmUtZWRpdGluZ30gaXMgYWx3YXlzIHByZXNlbnQsIHRoZXkgdG9nZ2xlLlxuICAgICAgICAvLyAgICAgICBob3dldmVyIHthZy1jZWxsLXBvcHVwLWVkaXRpbmd9IHNob3dzIHdoZW4gcG9wdXAsIHNvIHlvdSBoYXZlIGJvdGgge2FnLWNlbGwtcG9wdXAtZWRpdGluZ31cbiAgICAgICAgLy8gICAgICAgYW5kIHthZy1jZWxsLW5vdC1pbmxpbmUtZWRpdGluZ30gc2hvd2luZyBhdCB0aGUgc2FtZSB0aW1lLlxuICAgICAgICB2YXIgZWRpdGluZ0lubGluZSA9IHRoaXMuZWRpdGluZyAmJiAhdGhpcy5lZGl0aW5nSW5Qb3B1cDtcbiAgICAgICAgdmFyIHBvcHVwRWRpdG9yU2hvd2luZyA9IHRoaXMuZWRpdGluZyAmJiB0aGlzLmVkaXRpbmdJblBvcHVwO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NFTExfSU5MSU5FX0VESVRJTkcsIGVkaXRpbmdJbmxpbmUpO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NFTExfTk9UX0lOTElORV9FRElUSU5HLCAhZWRpdGluZ0lubGluZSk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQ0VMTF9QT1BVUF9FRElUSU5HLCBwb3B1cEVkaXRvclNob3dpbmcpO1xuICAgICAgICB0aGlzLnJvd0N0cmwuc2V0SW5saW5lRWRpdGluZ0Nzcyh0aGlzLmVkaXRpbmcpO1xuICAgIH07XG4gICAgLy8gdGhpcyBpcyBuZWVkZWQgYXMgdGhlIEpTIENlbGxDb21wIHN0aWxsIGFsbG93cyBpc1BvcHVwKCkgb24gdGhlIENlbGxFZGl0b3IgY2xhc3MsIHNvXG4gICAgLy8gaXQncyBwb3NzaWJsZSB0aGUgZWRpdG9yIGlzIGluIGEgcG9wdXAgZXZlbiB0aG91Z2ggaXQncyBub3QgY29uZmlndXJlZCB2aWEgdGhlIGNvbERlZiBhcyBzb1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5oYWNrU2F5RWRpdGluZ0luUG9wdXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmVkaXRpbmdJblBvcHVwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lZGl0aW5nSW5Qb3B1cCA9IHRydWU7XG4gICAgICAgIHRoaXMuc2V0SW5saW5lRWRpdGluZ0NsYXNzKCk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuY3JlYXRlQ2VsbEVkaXRvclBhcmFtcyA9IGZ1bmN0aW9uIChrZXksIGNoYXJQcmVzcywgY2VsbFN0YXJ0ZWRFZGl0KSB7XG4gICAgICAgIHZhciByZXMgPSB7XG4gICAgICAgICAgICB2YWx1ZTogdGhpcy5nZXRWYWx1ZUZyb21WYWx1ZVNlcnZpY2UoKSxcbiAgICAgICAgICAgIGtleToga2V5LFxuICAgICAgICAgICAgZXZlbnRLZXk6IGtleSxcbiAgICAgICAgICAgIGNoYXJQcmVzczogY2hhclByZXNzLFxuICAgICAgICAgICAgY29sdW1uOiB0aGlzLmNvbHVtbixcbiAgICAgICAgICAgIGNvbERlZjogdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCksXG4gICAgICAgICAgICByb3dJbmRleDogdGhpcy5nZXRDZWxsUG9zaXRpb24oKS5yb3dJbmRleCxcbiAgICAgICAgICAgIG5vZGU6IHRoaXMucm93Tm9kZSxcbiAgICAgICAgICAgIGRhdGE6IHRoaXMucm93Tm9kZS5kYXRhLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNlbGxTdGFydGVkRWRpdDogY2VsbFN0YXJ0ZWRFZGl0LFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKSxcbiAgICAgICAgICAgIG9uS2V5RG93bjogdGhpcy5vbktleURvd24uYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHN0b3BFZGl0aW5nOiB0aGlzLnN0b3BFZGl0aW5nQW5kRm9jdXMuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIGVHcmlkQ2VsbDogdGhpcy5nZXRHdWkoKSxcbiAgICAgICAgICAgIHBhcnNlVmFsdWU6IHRoaXMucGFyc2VWYWx1ZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgZm9ybWF0VmFsdWU6IHRoaXMuZm9ybWF0VmFsdWUuYmluZCh0aGlzKVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmNyZWF0ZUNlbGxSZW5kZXJlclBhcmFtcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGFkZFJvd0NvbXBMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIEFHIEdyaWQgdjI2LCBwYXJhbXMuYWRkUm93Q29tcExpc3RlbmVyKCkgaXMgZGVwcmVjYXRlZC4gSWYgeW91IG5lZWQgdGhpcyBmdW5jdGlvbmFsaXR5LCBwbGVhc2UgY29udGFjdCBBRyBHcmlkIHN1cHBvcnQgYW5kIGFkdmlzZSB3aHkgc28gdGhhdCB3ZSBjYW4gcmV2ZXJ0IHdpdGggYW4gYXBwcm9wcmlhdGUgd29ya2Fyb3VuZCwgYXMgd2UgZG9udCBoYXZlIGFueSB2YWxpZCB1c2UgY2FzZXMgZm9yIGl0LiBUaGlzIG1ldGhvZCB3YXMgb3JpZ2luYWxseSBwcm92aWRlZCBhcyBhIHdvcmsgYXJvdW5kIHRvIGtub3cgd2hlbiBjZWxscyB3ZXJlIGRlc3Ryb3llZCBpbiBBRyBHcmlkIGJlZm9yZSBjdXN0b20gQ2VsbCBSZW5kZXJlcnMgY291bGQgYmUgcHJvdmlkZWQuJyk7XG4gICAgICAgICAgICBfdGhpcy5yb3dDdHJsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH07XG4gICAgICAgIHZhciByZXMgPSB7XG4gICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZSxcbiAgICAgICAgICAgIHZhbHVlRm9ybWF0dGVkOiB0aGlzLnZhbHVlRm9ybWF0dGVkLFxuICAgICAgICAgICAgZ2V0VmFsdWU6IHRoaXMuZ2V0VmFsdWVGcm9tVmFsdWVTZXJ2aWNlLmJpbmQodGhpcyksXG4gICAgICAgICAgICBzZXRWYWx1ZTogZnVuY3Rpb24gKHZhbHVlKSB7IHJldHVybiBfdGhpcy5iZWFucy52YWx1ZVNlcnZpY2Uuc2V0VmFsdWUoX3RoaXMucm93Tm9kZSwgX3RoaXMuY29sdW1uLCB2YWx1ZSk7IH0sXG4gICAgICAgICAgICBmb3JtYXRWYWx1ZTogdGhpcy5mb3JtYXRWYWx1ZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgZGF0YTogdGhpcy5yb3dOb2RlLmRhdGEsXG4gICAgICAgICAgICBub2RlOiB0aGlzLnJvd05vZGUsXG4gICAgICAgICAgICBwaW5uZWQ6IHRoaXMuY29sdW1uLmdldFBpbm5lZCgpLFxuICAgICAgICAgICAgY29sRGVmOiB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICByb3dJbmRleDogdGhpcy5nZXRDZWxsUG9zaXRpb24oKS5yb3dJbmRleCxcbiAgICAgICAgICAgIGFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICAgICAgcmVmcmVzaENlbGw6IHRoaXMucmVmcmVzaENlbGwuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIGVHcmlkQ2VsbDogdGhpcy5nZXRHdWkoKSxcbiAgICAgICAgICAgIGVQYXJlbnRPZlZhbHVlOiB0aGlzLmNlbGxDb21wLmdldFBhcmVudE9mVmFsdWUoKSxcbiAgICAgICAgICAgIHJlZ2lzdGVyUm93RHJhZ2dlcjogZnVuY3Rpb24gKHJvd0RyYWdnZXJFbGVtZW50LCBkcmFnU3RhcnRQaXhlbHMsIHZhbHVlLCBzdXBwcmVzc1Zpc2liaWxpdHlDaGFuZ2UpIHsgcmV0dXJuIF90aGlzLnJlZ2lzdGVyUm93RHJhZ2dlcihyb3dEcmFnZ2VyRWxlbWVudCwgZHJhZ1N0YXJ0UGl4ZWxzLCBzdXBwcmVzc1Zpc2liaWxpdHlDaGFuZ2UpOyB9LFxuICAgICAgICAgICAgLy8gdGhpcyBmdW5jdGlvbiBpcyBub3QgZG9jdW1lbnRlZCBhbnl3aGVyZSwgc28gd2UgY291bGQgZHJvcCBpdFxuICAgICAgICAgICAgLy8gaXQgd2FzIGluIHRoZSBvbGRlbiBkYXlzIHRvIGFsbG93IHVzZXIgdG8gcmVnaXN0ZXIgZm9yIHdoZW4gcmVuZGVyZWRcbiAgICAgICAgICAgIC8vIHJvdyB3YXMgcmVtb3ZlZCAodGhlIHJvdyBjb21wIHdhcyByZW1vdmVkKSwgaG93ZXZlciBub3cgdGhhdCB0aGUgdXNlclxuICAgICAgICAgICAgLy8gY2FuIHByb3ZpZGUgY29tcG9uZW50cyBmb3IgY2VsbHMsIHRoZSBkZXN0cm95IG1ldGhvZCBnZXRzIGNhbGwgd2hlbiB0aGlzXG4gICAgICAgICAgICAvLyBoYXBwZW5zIHNvIG5vIGxvbmdlciBuZWVkIHRvIGZpcmUgZXZlbnQuXG4gICAgICAgICAgICBhZGRSb3dDb21wTGlzdGVuZXI6IGFkZFJvd0NvbXBMaXN0ZW5lclxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLnBhcnNlVmFsdWUgPSBmdW5jdGlvbiAobmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgbm9kZTogdGhpcy5yb3dOb2RlLFxuICAgICAgICAgICAgZGF0YTogdGhpcy5yb3dOb2RlLmRhdGEsXG4gICAgICAgICAgICBvbGRWYWx1ZTogdGhpcy5nZXRWYWx1ZSgpLFxuICAgICAgICAgICAgbmV3VmFsdWU6IG5ld1ZhbHVlLFxuICAgICAgICAgICAgY29sRGVmOiBjb2xEZWYsXG4gICAgICAgICAgICBjb2x1bW46IHRoaXMuY29sdW1uLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KClcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHZhbHVlUGFyc2VyID0gY29sRGVmLnZhbHVlUGFyc2VyO1xuICAgICAgICByZXR1cm4gZXhpc3RzKHZhbHVlUGFyc2VyKSA/IHRoaXMuYmVhbnMuZXhwcmVzc2lvblNlcnZpY2UuZXZhbHVhdGUodmFsdWVQYXJzZXIsIHBhcmFtcykgOiBuZXdWYWx1ZTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5zZXRGb2N1c091dE9uRWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuZWRpdGluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjZWxsRWRpdG9yID0gdGhpcy5jZWxsQ29tcC5nZXRDZWxsRWRpdG9yKCk7XG4gICAgICAgIGlmIChjZWxsRWRpdG9yICYmIGNlbGxFZGl0b3IuZm9jdXNPdXQpIHtcbiAgICAgICAgICAgIGNlbGxFZGl0b3IuZm9jdXNPdXQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLnNldEZvY3VzSW5PbkVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmVkaXRpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbEVkaXRvciA9IHRoaXMuY2VsbENvbXAuZ2V0Q2VsbEVkaXRvcigpO1xuICAgICAgICBpZiAoY2VsbEVkaXRvciAmJiBjZWxsRWRpdG9yLmZvY3VzSW4pIHtcbiAgICAgICAgICAgIC8vIGlmIHRoZSBlZGl0b3IgaXMgcHJlc2VudCwgdGhlbiB3ZSBqdXN0IGZvY3VzIGl0XG4gICAgICAgICAgICBjZWxsRWRpdG9yLmZvY3VzSW4oKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIHRoZSBlZGl0b3IgaXMgbm90IHByZXNlbnQsIGl0IG1lYW5zIGFzeW5jIGNlbGwgZWRpdG9yIChlZyBSZWFjdCBmaWJyZSlcbiAgICAgICAgICAgIC8vIGFuZCB3ZSBhcmUgdHJ5aW5nIHRvIHNldCBmb2N1cyBiZWZvcmUgdGhlIGNlbGwgZWRpdG9yIGlzIHByZXNlbnQsIHNvIHdlXG4gICAgICAgICAgICAvLyBmb2N1cyB0aGUgY2VsbCBpbnN0ZWFkXG4gICAgICAgICAgICB0aGlzLmZvY3VzQ2VsbCh0cnVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLm9uQ2VsbENoYW5nZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgLy8gYmVjYXVzZSBvZiBhc3luYyBpbiBSZWFjdCwgdGhlIGNlbGxDb21wIG1heSBub3QgYmUgc2V0IHlldCwgaWYgbm8gY2VsbENvbXAgdGhlbiB3ZSBhcmVcbiAgICAgICAgLy8geWV0IHRvIGluaXRpYWxpc2UgdGhlIGNlbGwsIHNvIG5vIG5lZWQgdG8gcmVmcmVzaC5cbiAgICAgICAgaWYgKCF0aGlzLmNlbGxDb21wKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50SW1wYWN0c1RoaXNDZWxsID0gZXZlbnQuY29sdW1uID09PSB0aGlzLmNvbHVtbjtcbiAgICAgICAgaWYgKGV2ZW50SW1wYWN0c1RoaXNDZWxsKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hDZWxsKHt9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gKyBzdG9wIGVkaXRpbmcge2ZvcmNlUmVmcmVzaDogdHJ1ZSwgc3VwcHJlc3NGbGFzaDogdHJ1ZX1cbiAgICAvLyArIGV2ZW50IGNlbGxDaGFuZ2VkIHt9XG4gICAgLy8gKyBjZWxsUmVuZGVyZXIucGFyYW1zLnJlZnJlc2goKSB7fSAtPiBtZXRob2QgcGFzc2VzICdhcyBpcycgdG8gdGhlIGNlbGxSZW5kZXJlciwgc28gcGFyYW1zIGNvdWxkIGJlIGFueXRoaW5nXG4gICAgLy8gKyByb3dDdHJsOiBldmVudCBkYXRhQ2hhbmdlZCB7c3VwcHJlc3NGbGFzaDogIXVwZGF0ZSwgbmV3RGF0YTogIXVwZGF0ZX1cbiAgICAvLyArIHJvd0N0cmw6IGFwaSByZWZyZXNoQ2VsbHMoKSB7YW5pbWF0ZTogdHJ1ZS9mYWxzZX1cbiAgICAvLyArIHJvd1JlbmRlcmVyOiBhcGkgc29mdFJlZnJlc2hWaWV3KCkge31cbiAgICBDZWxsQ3RybC5wcm90b3R5cGUucmVmcmVzaENlbGwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIC8vIGlmIHdlIGFyZSBpbiB0aGUgbWlkZGxlIG9mICdzdG9wRWRpdGluZycsIHRoZW4gd2UgZG9uJ3QgcmVmcmVzaCBoZXJlLCBhcyByZWZyZXNoIGdldHMgY2FsbGVkIGV4cGxpY2l0bHlcbiAgICAgICAgaWYgKHRoaXMuc3VwcHJlc3NSZWZyZXNoQ2VsbCB8fCB0aGlzLmVkaXRpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBJbiBSZWFjdCwgZHVlIHRvIGFzeW5jLCBpdCdzIHBvc3NpYmxlIGEgcmVmcmVzaCB3YXMgYXNrZWQgZm9yIGJlZm9yZSB0aGUgQ2VsbENvbXBcbiAgICAgICAgLy8gaGFzIGJlZW4gc2V0LiBJZiB0aGlzIGhhcHBlbnMsIHdlIHNraXAgdGhlIHJlZnJlc2gsIGFzIHRoZSBjZWxsIGlzIGdvaW5nIHRvIGJlXG4gICAgICAgIC8vIGluaXRpYWxpc2VkIGFueXdheSBvbmNlIHRoZSBDZWxsQ29tcCBpcyBzZXQuXG4gICAgICAgIGlmICghdGhpcy5jZWxsQ29tcCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2xEZWYgPSB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgdmFyIG5ld0RhdGEgPSBwYXJhbXMgIT0gbnVsbCAmJiAhIXBhcmFtcy5uZXdEYXRhO1xuICAgICAgICB2YXIgc3VwcHJlc3NGbGFzaCA9IChwYXJhbXMgIT0gbnVsbCAmJiAhIXBhcmFtcy5zdXBwcmVzc0ZsYXNoKSB8fCAhIWNvbERlZi5zdXBwcmVzc0NlbGxGbGFzaDtcbiAgICAgICAgLy8gd2UgYWx3YXlzIHJlZnJlc2ggaWYgY2VsbCBoYXMgbm8gdmFsdWUgLSB0aGlzIGNhbiBoYXBwZW4gd2hlbiB1c2VyIHByb3ZpZGVzIENlbGwgUmVuZGVyZXIgYW5kIHRoZVxuICAgICAgICAvLyBjZWxsIHJlbmRlcmVyIGRvZXNuJ3QgcmVseSBvbiBhIHZhbHVlLCBpbnN0ZWFkIGl0IGNvdWxkIGJlIGxvb2tpbmcgZGlyZWN0bHkgYXQgdGhlIGRhdGEsIG9yIG1heWJlXG4gICAgICAgIC8vIHByaW50aW5nIHRoZSBjdXJyZW50IHRpbWUgKHdoaWNoIHdvdWxkIGJlIHNpbGx5KT8/Py4gR2VuZXJhbGx5IHNwZWFraW5nXG4gICAgICAgIC8vIG5vbiBvZiB7ZmllbGQsIHZhbHVlR2V0dGVyLCBzaG93Um93R3JvdXB9IGlzIGJhZCBpbiB0aGUgdXNlcnMgYXBwbGljYXRpb24sIGhvd2V2ZXIgZm9yIHRoaXMgZWRnZSBjYXNlLCBpdCdzXG4gICAgICAgIC8vIGJlc3QgYWx3YXlzIHJlZnJlc2ggYW5kIHRha2UgdGhlIHBlcmZvcm1hbmNlIGhpdCByYXRoZXIgdGhhbiBuZXZlciByZWZyZXNoIGFuZCB1c2VycyBjb21wbGFpbmluZyBpbiBzdXBwb3J0XG4gICAgICAgIC8vIHRoYXQgY2VsbHMgYXJlIG5vdCB1cGRhdGluZy5cbiAgICAgICAgdmFyIG5vVmFsdWVQcm92aWRlZCA9IGNvbERlZi5maWVsZCA9PSBudWxsICYmIGNvbERlZi52YWx1ZUdldHRlciA9PSBudWxsICYmIGNvbERlZi5zaG93Um93R3JvdXAgPT0gbnVsbDtcbiAgICAgICAgdmFyIGZvcmNlUmVmcmVzaCA9IChwYXJhbXMgJiYgcGFyYW1zLmZvcmNlUmVmcmVzaCkgfHwgbm9WYWx1ZVByb3ZpZGVkIHx8IG5ld0RhdGE7XG4gICAgICAgIHZhciB2YWx1ZXNEaWZmZXJlbnQgPSB0aGlzLnVwZGF0ZUFuZEZvcm1hdFZhbHVlKCk7XG4gICAgICAgIHZhciBkYXRhTmVlZHNVcGRhdGluZyA9IGZvcmNlUmVmcmVzaCB8fCB2YWx1ZXNEaWZmZXJlbnQ7XG4gICAgICAgIGlmIChkYXRhTmVlZHNVcGRhdGluZykge1xuICAgICAgICAgICAgLy8gaWYgaXQncyAnbmV3IGRhdGEnLCB0aGVuIHdlIGRvbid0IHJlZnJlc2ggdGhlIGNlbGxSZW5kZXJlciwgZXZlbiBpZiByZWZyZXNoIG1ldGhvZCBpcyBhdmFpbGFibGUuXG4gICAgICAgICAgICAvLyB0aGlzIGlzIGJlY2F1c2UgaWYgdGhlIHdob2xlIGRhdGEgaXMgbmV3IChpZSB3ZSBhcmUgc2hvd2luZyBzdG9jayBwcmljZSAnQkJBJyBub3cgYW5kIG5vdCAnU1NEJylcbiAgICAgICAgICAgIC8vIHRoZW4gd2UgYXJlIG5vdCBzaG93aW5nIGEgbW92ZW1lbnQgaW4gdGhlIHN0b2NrIHByaWNlLCByYXRoZXIgd2UgYXJlIHNob3dpbmcgZGlmZmVyZW50IHN0b2NrLlxuICAgICAgICAgICAgdGhpcy5zaG93VmFsdWUobmV3RGF0YSk7XG4gICAgICAgICAgICAvLyB3ZSBkb24ndCB3YW50IHRvIGZsYXNoIHRoZSBjZWxscyB3aGVuIHByb2Nlc3NpbmcgYSBmaWx0ZXIgY2hhbmdlLCBhcyBvdGhlcndpc2UgdGhlIFVJIHdvdWxkXG4gICAgICAgICAgICAvLyBiZSB0byBidXN5LiBzZWUgY29tbWVudCBpbiBGaWx0ZXJNYW5hZ2VyIHdpdGggcmVnYXJkcyBwcm9jZXNzaW5nRmlsdGVyQ2hhbmdlXG4gICAgICAgICAgICB2YXIgcHJvY2Vzc2luZ0ZpbHRlckNoYW5nZSA9IHRoaXMuYmVhbnMuZmlsdGVyTWFuYWdlci5pc1N1cHByZXNzRmxhc2hpbmdDZWxsc0JlY2F1c2VGaWx0ZXJpbmcoKTtcbiAgICAgICAgICAgIHZhciBmbGFzaENlbGwgPSAhc3VwcHJlc3NGbGFzaCAmJiAhcHJvY2Vzc2luZ0ZpbHRlckNoYW5nZSAmJlxuICAgICAgICAgICAgICAgICh0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUNlbGxDaGFuZ2VGbGFzaCgpIHx8IGNvbERlZi5lbmFibGVDZWxsQ2hhbmdlRmxhc2gpO1xuICAgICAgICAgICAgaWYgKGZsYXNoQ2VsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmxhc2hDZWxsKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNlbGxDdXN0b21TdHlsZUZlYXR1cmUuYXBwbHlVc2VyU3R5bGVzKCk7XG4gICAgICAgICAgICB0aGlzLmNlbGxDdXN0b21TdHlsZUZlYXR1cmUuYXBwbHlDbGFzc2VzRnJvbUNvbERlZigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVmcmVzaFRvb2xUaXAoKTtcbiAgICAgICAgLy8gd2UgZG8gY2VsbENsYXNzUnVsZXMgZXZlbiBpZiB0aGUgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkLCBzbyB0aGF0IHVzZXJzIHdobyBoYXZlIHJ1bGVzIHRoYXRcbiAgICAgICAgLy8gbG9vayBhdCBvdGhlciBwYXJ0cyBvZiB0aGUgcm93ICh3aGVyZSB0aGUgb3RoZXIgcGFydCBvZiB0aGUgcm93IG1pZ2h0IG9mIGNoYW5nZWQpIHdpbGwgd29yay5cbiAgICAgICAgdGhpcy5jZWxsQ3VzdG9tU3R5bGVGZWF0dXJlLmFwcGx5Q2VsbENsYXNzUnVsZXMoKTtcbiAgICB9O1xuICAgIC8vIGNlbGwgZWRpdG9ycyBjYWxsIHRoaXMsIHdoZW4gdGhleSB3YW50IHRvIHN0b3AgZm9yIHJlYXNvbnMgb3RoZXJcbiAgICAvLyB0aGFuIHdoYXQgd2UgcGljayB1cCBvbi4gZWcgc2VsZWN0aW5nIGZyb20gYSBkcm9wZG93biBlbmRzIGVkaXRpbmcuXG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLnN0b3BFZGl0aW5nQW5kRm9jdXMgPSBmdW5jdGlvbiAoc3VwcHJlc3NOYXZpZ2F0ZUFmdGVyRWRpdCkge1xuICAgICAgICBpZiAoc3VwcHJlc3NOYXZpZ2F0ZUFmdGVyRWRpdCA9PT0gdm9pZCAwKSB7IHN1cHByZXNzTmF2aWdhdGVBZnRlckVkaXQgPSBmYWxzZTsgfVxuICAgICAgICB0aGlzLnN0b3BSb3dPckNlbGxFZGl0KCk7XG4gICAgICAgIHRoaXMuZm9jdXNDZWxsKHRydWUpO1xuICAgICAgICBpZiAoIXN1cHByZXNzTmF2aWdhdGVBZnRlckVkaXQpIHtcbiAgICAgICAgICAgIHRoaXMubmF2aWdhdGVBZnRlckVkaXQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLm5hdmlnYXRlQWZ0ZXJFZGl0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZnVsbFJvd0VkaXQgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0Z1bGxSb3dFZGl0KCk7XG4gICAgICAgIGlmIChmdWxsUm93RWRpdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlbnRlck1vdmVzRG93bkFmdGVyRWRpdCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW50ZXJNb3Zlc0Rvd25BZnRlckVkaXQoKTtcbiAgICAgICAgaWYgKGVudGVyTW92ZXNEb3duQWZ0ZXJFZGl0KSB7XG4gICAgICAgICAgICB0aGlzLmJlYW5zLm5hdmlnYXRpb25TZXJ2aWNlLm5hdmlnYXRlVG9OZXh0Q2VsbChudWxsLCBLZXlDb2RlLkRPV04sIHRoaXMuZ2V0Q2VsbFBvc2l0aW9uKCksIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gdXNlciBjYW4gYWxzbyBjYWxsIHRoaXMgdmlhIEFQSVxuICAgIENlbGxDdHJsLnByb3RvdHlwZS5mbGFzaENlbGwgPSBmdW5jdGlvbiAoZGVsYXlzKSB7XG4gICAgICAgIHZhciBmbGFzaERlbGF5ID0gZGVsYXlzICYmIGRlbGF5cy5mbGFzaERlbGF5O1xuICAgICAgICB2YXIgZmFkZURlbGF5ID0gZGVsYXlzICYmIGRlbGF5cy5mYWRlRGVsYXk7XG4gICAgICAgIHRoaXMuYW5pbWF0ZUNlbGwoJ2RhdGEtY2hhbmdlZCcsIGZsYXNoRGVsYXksIGZhZGVEZWxheSk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuYW5pbWF0ZUNlbGwgPSBmdW5jdGlvbiAoY3NzTmFtZSwgZmxhc2hEZWxheSwgZmFkZURlbGF5KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBmdWxsTmFtZSA9IFwiYWctY2VsbC1cIiArIGNzc05hbWU7XG4gICAgICAgIHZhciBhbmltYXRpb25GdWxsTmFtZSA9IFwiYWctY2VsbC1cIiArIGNzc05hbWUgKyBcIi1hbmltYXRpb25cIjtcbiAgICAgICAgdmFyIGdyaWRPcHRpb25zV3JhcHBlciA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICBpZiAoIWZsYXNoRGVsYXkpIHtcbiAgICAgICAgICAgIGZsYXNoRGVsYXkgPSBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q2VsbEZsYXNoRGVsYXkoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWV4aXN0cyhmYWRlRGVsYXkpKSB7XG4gICAgICAgICAgICBmYWRlRGVsYXkgPSBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q2VsbEZhZGVEZWxheSgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gaGlnaGxpZ2h0IHRoZSBjZWxscywgd2l0aG91dCBhbnkgYW5pbWF0aW9uXG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhmdWxsTmFtZSwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhhbmltYXRpb25GdWxsTmFtZSwgZmFsc2UpO1xuICAgICAgICAvLyB0aGVuIG9uY2UgdGhhdCBpcyBhcHBsaWVkLCB3ZSByZW1vdmUgdGhlIGhpZ2hsaWdodCB3aXRoIGFuaW1hdGlvblxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmlzQWxpdmUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoZnVsbE5hbWUsIGZhbHNlKTtcbiAgICAgICAgICAgIF90aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoYW5pbWF0aW9uRnVsbE5hbWUsIHRydWUpO1xuICAgICAgICAgICAgX3RoaXMuZUd1aS5zdHlsZS50cmFuc2l0aW9uID0gXCJiYWNrZ3JvdW5kLWNvbG9yIFwiICsgZmFkZURlbGF5ICsgXCJtc1wiO1xuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICghX3RoaXMuaXNBbGl2ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gYW5kIHRoZW4gdG8gbGVhdmUgdGhpbmdzIGFzIHdlIGdvdCB0aGVtLCB3ZSByZW1vdmUgdGhlIGFuaW1hdGlvblxuICAgICAgICAgICAgICAgIF90aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoYW5pbWF0aW9uRnVsbE5hbWUsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lR3VpLnN0eWxlLnRyYW5zaXRpb24gPSAnJztcbiAgICAgICAgICAgIH0sIGZhZGVEZWxheSk7XG4gICAgICAgIH0sIGZsYXNoRGVsYXkpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLm9uRmxhc2hDZWxscyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VsbENvbXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbElkID0gdGhpcy5iZWFucy5jZWxsUG9zaXRpb25VdGlscy5jcmVhdGVJZCh0aGlzLmdldENlbGxQb3NpdGlvbigpKTtcbiAgICAgICAgdmFyIHNob3VsZEZsYXNoID0gZXZlbnQuY2VsbHNbY2VsbElkXTtcbiAgICAgICAgaWYgKHNob3VsZEZsYXNoKSB7XG4gICAgICAgICAgICB0aGlzLmFuaW1hdGVDZWxsKCdoaWdobGlnaHQnKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmlzQ2VsbEVkaXRhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW4uaXNDZWxsRWRpdGFibGUodGhpcy5yb3dOb2RlKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5pc1N1cHByZXNzRmlsbEhhbmRsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uLmlzU3VwcHJlc3NGaWxsSGFuZGxlKCk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZm9ybWF0VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdmFyIHJlcyA9IHRoaXMuY2FsbFZhbHVlRm9ybWF0dGVyKHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIHJlcyAhPSBudWxsID8gcmVzIDogdmFsdWU7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuY2FsbFZhbHVlRm9ybWF0dGVyID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJlYW5zLnZhbHVlRm9ybWF0dGVyU2VydmljZS5mb3JtYXRWYWx1ZSh0aGlzLmNvbHVtbiwgdGhpcy5yb3dOb2RlLCB2YWx1ZSk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUudXBkYXRlQW5kRm9ybWF0VmFsdWUgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICAgICAgaWYgKGZvcmNlID09PSB2b2lkIDApIHsgZm9yY2UgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLnZhbHVlO1xuICAgICAgICB2YXIgb2xkVmFsdWVGb3JtYXR0ZWQgPSB0aGlzLnZhbHVlRm9ybWF0dGVkO1xuICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy5nZXRWYWx1ZUZyb21WYWx1ZVNlcnZpY2UoKTtcbiAgICAgICAgdGhpcy52YWx1ZUZvcm1hdHRlZCA9IHRoaXMuY2FsbFZhbHVlRm9ybWF0dGVyKHRoaXMudmFsdWUpO1xuICAgICAgICB2YXIgdmFsdWVzRGlmZmVyZW50ID0gZm9yY2UgPyB0cnVlIDpcbiAgICAgICAgICAgICF0aGlzLnZhbHVlc0FyZUVxdWFsKG9sZFZhbHVlLCB0aGlzLnZhbHVlKSB8fCB0aGlzLnZhbHVlRm9ybWF0dGVkICE9IG9sZFZhbHVlRm9ybWF0dGVkO1xuICAgICAgICByZXR1cm4gdmFsdWVzRGlmZmVyZW50O1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLnZhbHVlc0FyZUVxdWFsID0gZnVuY3Rpb24gKHZhbDEsIHZhbDIpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgLy8gaWYgdGhlIHVzZXIgcHJvdmlkZWQgYW4gZXF1YWxzIG1ldGhvZCwgdXNlIHRoYXQsIG90aGVyd2lzZSBkbyBzaW1wbGUgY29tcGFyaXNvblxuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIHJldHVybiBjb2xEZWYuZXF1YWxzID8gY29sRGVmLmVxdWFscyh2YWwxLCB2YWwyKSA6IHR5cGVvZiB2YWwxID09PSB0eXBlb2YgdmFsMiAmJiAoKF9hID0gdmFsMSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnRvU3RyaW5nKCkpID09PSAoKF9iID0gdmFsMikgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLnRvU3RyaW5nKCkpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmdldENvbXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbGxDb21wO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmdldFZhbHVlRnJvbVZhbHVlU2VydmljZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gaWYgd2UgZG9uJ3QgY2hlY2sgdGhpcywgdGhlbiB0aGUgZ3JpZCB3aWxsIHJlbmRlciBsZWFmIGdyb3VwcyBhcyBvcGVuIGV2ZW4gaWYgd2UgYXJlIG5vdFxuICAgICAgICAvLyBhbGxvd2luZyB0aGUgdXNlciB0byBvcGVuIGxlYWYgZ3JvdXBzLiBjb25mdXNlZD8gcmVtZW1iZXIgZm9yIHBpdm90IG1vZGUgd2UgZG9uJ3QgYWxsb3dcbiAgICAgICAgLy8gb3BlbmluZyBsZWFmIGdyb3Vwcywgc28gd2UgaGF2ZSB0byBmb3JjZSBsZWFmR3JvdXBzIHRvIGJlIGNsb3NlZCBpbiBjYXNlIHRoZSB1c2VyIGV4cGFuZGVkXG4gICAgICAgIC8vIHRoZW0gdmlhIHRoZSBBUEksIG9yIHVzZXIgdXNlciBleHBhbmRlZCB0aGVtIGluIHRoZSBVSSBiZWZvcmUgdHVybmluZyBvbiBwaXZvdCBtb2RlXG4gICAgICAgIHZhciBsb2NrZWRDbG9zZWRHcm91cCA9IHRoaXMucm93Tm9kZS5sZWFmR3JvdXAgJiYgdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5pc1Bpdm90TW9kZSgpO1xuICAgICAgICB2YXIgaXNPcGVuR3JvdXAgPSB0aGlzLnJvd05vZGUuZ3JvdXAgJiYgdGhpcy5yb3dOb2RlLmV4cGFuZGVkICYmICF0aGlzLnJvd05vZGUuZm9vdGVyICYmICFsb2NrZWRDbG9zZWRHcm91cDtcbiAgICAgICAgLy8gYXJlIHdlIHNob3dpbmcgZ3JvdXAgZm9vdGVyc1xuICAgICAgICB2YXIgZ3JvdXBGb290ZXJzRW5hYmxlZCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBJbmNsdWRlRm9vdGVyKCk7XG4gICAgICAgIC8vIGlmIGRvaW5nIGZvb3RlcnMsIHdlIG5vcm1hbGx5IGRvbid0IHNob3cgYWdnIGRhdGEgYXQgZ3JvdXAgbGV2ZWwgd2hlbiBncm91cCBpcyBvcGVuXG4gICAgICAgIHZhciBncm91cEFsd2F5c1Nob3dBZ2dEYXRhID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFN1cHByZXNzQmxhbmtIZWFkZXIoKTtcbiAgICAgICAgLy8gaWYgZG9pbmcgZ3JvdXBpbmcgYW5kIGZvb3RlcnMsIHdlIGRvbid0IHdhbnQgdG8gaW5jbHVkZSB0aGUgYWdnIHZhbHVlXG4gICAgICAgIC8vIGluIHRoZSBoZWFkZXIgd2hlbiB0aGUgZ3JvdXAgaXMgb3BlblxuICAgICAgICB2YXIgaWdub3JlQWdnRGF0YSA9IChpc09wZW5Hcm91cCAmJiBncm91cEZvb3RlcnNFbmFibGVkKSAmJiAhZ3JvdXBBbHdheXNTaG93QWdnRGF0YTtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5iZWFucy52YWx1ZVNlcnZpY2UuZ2V0VmFsdWUodGhpcy5jb2x1bW4sIHRoaXMucm93Tm9kZSwgZmFsc2UsIGlnbm9yZUFnZ0RhdGEpO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmdldFZhbHVlRm9ybWF0dGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZUZvcm1hdHRlZDtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5hZGREb21EYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldERvbURhdGEoZWxlbWVudCwgQ2VsbEN0cmwuRE9NX0RBVEFfS0VZX0NFTExfQ1RSTCwgdGhpcyk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldERvbURhdGEoZWxlbWVudCwgQ2VsbEN0cmwuRE9NX0RBVEFfS0VZX0NFTExfQ1RSTCwgbnVsbCk7IH0pO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmNyZWF0ZUV2ZW50ID0gZnVuY3Rpb24gKGRvbUV2ZW50LCBldmVudFR5cGUpIHtcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogZXZlbnRUeXBlLFxuICAgICAgICAgICAgbm9kZTogdGhpcy5yb3dOb2RlLFxuICAgICAgICAgICAgZGF0YTogdGhpcy5yb3dOb2RlLmRhdGEsXG4gICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZSxcbiAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICBjb2xEZWY6IHRoaXMuY29sdW1uLmdldENvbERlZigpLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmJlYW5zLmdyaWRBcGksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuYmVhbnMuY29sdW1uQXBpLFxuICAgICAgICAgICAgcm93UGlubmVkOiB0aGlzLnJvd05vZGUucm93UGlubmVkLFxuICAgICAgICAgICAgZXZlbnQ6IGRvbUV2ZW50LFxuICAgICAgICAgICAgcm93SW5kZXg6IHRoaXMucm93Tm9kZS5yb3dJbmRleFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gZXZlbnQ7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUub25LZXlQcmVzcyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB0aGlzLmNlbGxLZXlib2FyZExpc3RlbmVyRmVhdHVyZS5vbktleVByZXNzKGV2ZW50KTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vbktleURvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5jZWxsS2V5Ym9hcmRMaXN0ZW5lckZlYXR1cmUub25LZXlEb3duKGV2ZW50KTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vbk1vdXNlRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnROYW1lLCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIHRoaXMuY2VsbE1vdXNlTGlzdGVuZXJGZWF0dXJlLm9uTW91c2VFdmVudChldmVudE5hbWUsIG1vdXNlRXZlbnQpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmdldEd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUd1aTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5yZWZyZXNoVG9vbFRpcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b29sdGlwRmVhdHVyZS5yZWZyZXNoVG9vbFRpcCgpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmdldENvbFNwYW5uaW5nTGlzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbFBvc2l0aW9uRmVhdHVyZS5nZXRDb2xTcGFubmluZ0xpc3QoKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vbkxlZnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VsbENvbXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNlbGxQb3NpdGlvbkZlYXR1cmUub25MZWZ0Q2hhbmdlZCgpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLm9uRGlzcGxheWVkQ29sdW1uc0NoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5lR3VpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRBcmlhQ29sSW5kZXgoKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5zZXRBcmlhQ29sSW5kZXggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb2xJZHggPSB0aGlzLmJlYW5zLmNvbHVtbk1vZGVsLmdldEFyaWFDb2x1bW5JbmRleCh0aGlzLmNvbHVtbik7XG4gICAgICAgIHNldEFyaWFDb2xJbmRleCh0aGlzLmdldEd1aSgpLCBjb2xJZHgpOyAvLyBmb3IgcmVhY3QsIHdlIGRvbid0IHVzZSBKU1gsIGFzIGl0IHNsb3dlZCBkb3duIGNvbHVtbiBtb3ZpbmdcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5pc1N1cHByZXNzTmF2aWdhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW4uaXNTdXBwcmVzc05hdmlnYWJsZSh0aGlzLnJvd05vZGUpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLm9uV2lkdGhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZWxsUG9zaXRpb25GZWF0dXJlLm9uV2lkdGhDaGFuZ2VkKCk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZ2V0Q29sdW1uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW47XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZ2V0Um93Tm9kZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93Tm9kZTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5nZXRCZWFucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmVhbnM7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuaXNQcmludExheW91dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJpbnRMYXlvdXQ7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuYXBwZW5kQ2hpbGQgPSBmdW5jdGlvbiAoaHRtbEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5lR3VpLmFwcGVuZENoaWxkKGh0bWxFbGVtZW50KTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5yZWZyZXNoSGFuZGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5jZWxsUmFuZ2VGZWF0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLmNlbGxSYW5nZUZlYXR1cmUucmVmcmVzaEhhbmRsZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZ2V0Q2VsbFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZWxsUG9zaXRpb247XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuaXNFZGl0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lZGl0aW5nO1xuICAgIH07XG4gICAgLy8gY2FsbGVkIGJ5IHJvd1JlbmRlcmVyIHdoZW4gdXNlciBuYXZpZ2F0ZXMgdmlhIHRhYiBrZXlcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuc3RhcnRSb3dPckNlbGxFZGl0ID0gZnVuY3Rpb24gKGtleSwgY2hhclByZXNzLCBldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQgPT09IHZvaWQgMCkgeyBldmVudCA9IG51bGw7IH1cbiAgICAgICAgaWYgKCF0aGlzLmNlbGxDb21wKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRnVsbFJvd0VkaXQoKSkge1xuICAgICAgICAgICAgdGhpcy5yb3dDdHJsLnN0YXJ0Um93RWRpdGluZyhrZXksIGNoYXJQcmVzcywgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0RWRpdGluZyhrZXksIGNoYXJQcmVzcywgdHJ1ZSwgZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZ2V0Um93Q3RybCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93Q3RybDtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5nZXRSb3dQb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvd0luZGV4OiB0aGlzLmNlbGxQb3NpdGlvbi5yb3dJbmRleCxcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogdGhpcy5jZWxsUG9zaXRpb24ucm93UGlubmVkXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUudXBkYXRlUmFuZ2VCb3JkZXJzSWZSYW5nZUNvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VsbENvbXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5jZWxsUmFuZ2VGZWF0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLmNlbGxSYW5nZUZlYXR1cmUudXBkYXRlUmFuZ2VCb3JkZXJzSWZSYW5nZUNvdW50KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vblJhbmdlU2VsZWN0aW9uQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNlbGxDb21wKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY2VsbFJhbmdlRmVhdHVyZSkge1xuICAgICAgICAgICAgdGhpcy5jZWxsUmFuZ2VGZWF0dXJlLm9uUmFuZ2VTZWxlY3Rpb25DaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5pc1JhbmdlU2VsZWN0aW9uRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbFJhbmdlRmVhdHVyZSAhPSBudWxsO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmZvY3VzQ2VsbCA9IGZ1bmN0aW9uIChmb3JjZUJyb3dzZXJGb2N1cykge1xuICAgICAgICBpZiAoZm9yY2VCcm93c2VyRm9jdXMgPT09IHZvaWQgMCkgeyBmb3JjZUJyb3dzZXJGb2N1cyA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMuYmVhbnMuZm9jdXNTZXJ2aWNlLnNldEZvY3VzZWRDZWxsKHtcbiAgICAgICAgICAgIHJvd0luZGV4OiB0aGlzLmdldENlbGxQb3NpdGlvbigpLnJvd0luZGV4LFxuICAgICAgICAgICAgY29sdW1uOiB0aGlzLmNvbHVtbixcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogdGhpcy5yb3dOb2RlLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIGZvcmNlQnJvd3NlckZvY3VzOiBmb3JjZUJyb3dzZXJGb2N1c1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vblJvd0luZGV4Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2hlbiBpbmRleCBjaGFuZ2VzLCB0aGlzIGluZmx1ZW5jZXMgaXRlbXMgdGhhdCBuZWVkIHRoZSBpbmRleCwgc28gd2UgdXBkYXRlIHRoZVxuICAgICAgICAvLyBncmlkIGNlbGwgc28gdGhleSBhcmUgd29ya2luZyBvZmYgdGhlIG5ldyBpbmRleC5cbiAgICAgICAgdGhpcy5jcmVhdGVDZWxsUG9zaXRpb24oKTtcbiAgICAgICAgLy8gd2hlbiB0aGUgaW5kZXggb2YgdGhlIHJvdyBjaGFuZ2VzLCBpZSBtZWFucyB0aGUgY2VsbCBtYXkgaGF2ZSBsb3N0IG9yIGdhaW5lZCBmb2N1c1xuICAgICAgICB0aGlzLm9uQ2VsbEZvY3VzZWQoKTtcbiAgICAgICAgLy8gY2hlY2sgcmFuZ2Ugc2VsZWN0aW9uXG4gICAgICAgIGlmICh0aGlzLmNlbGxSYW5nZUZlYXR1cmUpIHtcbiAgICAgICAgICAgIHRoaXMuY2VsbFJhbmdlRmVhdHVyZS5vblJhbmdlU2VsZWN0aW9uQ2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUub25GaXJzdFJpZ2h0UGlubmVkQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNlbGxDb21wKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZpcnN0UmlnaHRQaW5uZWQgPSB0aGlzLmNvbHVtbi5pc0ZpcnN0UmlnaHRQaW5uZWQoKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX0ZJUlNUX1JJR0hUX1BJTk5FRCwgZmlyc3RSaWdodFBpbm5lZCk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUub25MYXN0TGVmdFBpbm5lZENoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jZWxsQ29tcCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsYXN0TGVmdFBpbm5lZCA9IHRoaXMuY29sdW1uLmlzTGFzdExlZnRQaW5uZWQoKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX0xBU1RfTEVGVF9QSU5ORUQsIGxhc3RMZWZ0UGlubmVkKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vbkNlbGxGb2N1c2VkID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5jZWxsQ29tcCB8fCB0aGlzLmdvdy5pc1N1cHByZXNzQ2VsbEZvY3VzKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbEZvY3VzZWQgPSB0aGlzLmJlYW5zLmZvY3VzU2VydmljZS5pc0NlbGxGb2N1c2VkKHRoaXMuY2VsbFBvc2l0aW9uKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX0ZPQ1VTLCBjZWxsRm9jdXNlZCk7XG4gICAgICAgIC8vIHNlZSBpZiB3ZSBuZWVkIHRvIGZvcmNlIGJyb3dzZXIgZm9jdXMgLSB0aGlzIGNhbiBoYXBwZW4gaWYgZm9jdXMgaXMgcHJvZ3JhbW1hdGljYWxseSBzZXRcbiAgICAgICAgaWYgKGNlbGxGb2N1c2VkICYmIGV2ZW50ICYmIGV2ZW50LmZvcmNlQnJvd3NlckZvY3VzKSB7XG4gICAgICAgICAgICB2YXIgZm9jdXNFbCA9IHRoaXMuY2VsbENvbXAuZ2V0Rm9jdXNhYmxlRWxlbWVudCgpO1xuICAgICAgICAgICAgZm9jdXNFbC5mb2N1cyh7IHByZXZlbnRTY3JvbGw6ICEhZXZlbnQucHJldmVudFNjcm9sbE9uQnJvd3NlckZvY3VzIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGFub3RoZXIgY2VsbCB3YXMgZm9jdXNlZCwgYW5kIHdlIGFyZSBlZGl0aW5nLCB0aGVuIHN0b3AgZWRpdGluZ1xuICAgICAgICB2YXIgZnVsbFJvd0VkaXQgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0Z1bGxSb3dFZGl0KCk7XG4gICAgICAgIGlmICghY2VsbEZvY3VzZWQgJiYgIWZ1bGxSb3dFZGl0ICYmIHRoaXMuZWRpdGluZykge1xuICAgICAgICAgICAgdGhpcy5zdG9wUm93T3JDZWxsRWRpdCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuY3JlYXRlQ2VsbFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNlbGxQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgIHJvd0luZGV4OiB0aGlzLnJvd05vZGUucm93SW5kZXgsXG4gICAgICAgICAgICByb3dQaW5uZWQ6IG1ha2VOdWxsKHRoaXMucm93Tm9kZS5yb3dQaW5uZWQpLFxuICAgICAgICAgICAgY29sdW1uOiB0aGlzLmNvbHVtblxuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gQ1NTIENsYXNzZXMgdGhhdCBvbmx5IGdldCBhcHBsaWVkIG9uY2UsIHRoZXkgbmV2ZXIgY2hhbmdlXG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmFwcGx5U3RhdGljQ3NzQ2xhc3NlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMLCB0cnVlKTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX05PVF9JTkxJTkVfRURJVElORywgdHJ1ZSk7XG4gICAgICAgIC8vIG5vcm1hbCBjZWxscyBmaWxsIHRoZSBoZWlnaHQgb2YgdGhlIHJvdy4gYXV0b0hlaWdodCBjZWxscyBoYXZlIG5vIGhlaWdodCB0byBsZXQgdGhlbVxuICAgICAgICAvLyBmaXQgdGhlIGhlaWdodCBvZiBjb250ZW50LlxuICAgICAgICB2YXIgYXV0b0hlaWdodCA9IHRoaXMuY29sdW1uLmlzQXV0b0hlaWdodCgpID09IHRydWU7XG4gICAgICAgIHRoaXMuY2VsbENvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhDU1NfQVVUT19IRUlHSFQsIGF1dG9IZWlnaHQpO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX05PUk1BTF9IRUlHSFQsICFhdXRvSGVpZ2h0KTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vbkNvbHVtbkhvdmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2VsbENvbXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQ29sdW1uSG92ZXJIaWdobGlnaHQoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpc0hvdmVyZWQgPSB0aGlzLmJlYW5zLmNvbHVtbkhvdmVyU2VydmljZS5pc0hvdmVyZWQodGhpcy5jb2x1bW4pO1xuICAgICAgICB0aGlzLmNlbGxDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoQ1NTX0NPTFVNTl9IT1ZFUiwgaXNIb3ZlcmVkKTtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5vbkNvbERlZkNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jZWxsQ29tcCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0V3JhcFRleHQoKTtcbiAgICAgICAgaWYgKCF0aGlzLmVkaXRpbmcpIHtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaENlbGwoeyBmb3JjZVJlZnJlc2g6IHRydWUsIHN1cHByZXNzRmxhc2g6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5zZXRXcmFwVGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCkud3JhcFRleHQgPT0gdHJ1ZTtcbiAgICAgICAgdGhpcy5jZWxsQ29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DRUxMX1dSQVBfVEVYVCwgdmFsdWUpO1xuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmRpc3BhdGNoQ2VsbENvbnRleHRNZW51RXZlbnQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB2YXIgY2VsbENvbnRleHRNZW51RXZlbnQgPSB0aGlzLmNyZWF0ZUV2ZW50KGV2ZW50LCBFdmVudHMuRVZFTlRfQ0VMTF9DT05URVhUX01FTlUpO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGNlbGxDb250ZXh0TWVudUV2ZW50KTtcbiAgICAgICAgaWYgKGNvbERlZi5vbkNlbGxDb250ZXh0TWVudSkge1xuICAgICAgICAgICAgLy8gdG8gbWFrZSB0aGUgY2FsbGJhY2sgYXN5bmMsIGRvIGluIGEgdGltZW91dFxuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29sRGVmLm9uQ2VsbENvbnRleHRNZW51KGNlbGxDb250ZXh0TWVudUV2ZW50KTsgfSwgMCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5nZXRDZWxsUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbGxDb21wID8gdGhpcy5jZWxsQ29tcC5nZXRDZWxsUmVuZGVyZXIoKSA6IG51bGw7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZ2V0Q2VsbEVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbENvbXAgPyB0aGlzLmNlbGxDb21wLmdldENlbGxFZGl0b3IoKSA6IG51bGw7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vbkNlbGxDb21wQXR0YWNoZWRGdW5jcyA9IFtdO1xuICAgICAgICBpZiAodGhpcy5yZW1vdmVBdXRvSGVpZ2h0TGlzdGVuZXJzKSB7XG4gICAgICAgICAgICB0aGlzLnJlbW92ZUF1dG9IZWlnaHRMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlQXV0b0hlaWdodExpc3RlbmVycyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuY3JlYXRlU2VsZWN0aW9uQ2hlY2tib3ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjYlNlbGVjdGlvbkNvbXBvbmVudCA9IG5ldyBDaGVja2JveFNlbGVjdGlvbkNvbXBvbmVudCgpO1xuICAgICAgICB0aGlzLmJlYW5zLmNvbnRleHQuY3JlYXRlQmVhbihjYlNlbGVjdGlvbkNvbXBvbmVudCk7XG4gICAgICAgIGNiU2VsZWN0aW9uQ29tcG9uZW50LmluaXQoeyByb3dOb2RlOiB0aGlzLnJvd05vZGUsIGNvbHVtbjogdGhpcy5jb2x1bW4gfSk7XG4gICAgICAgIC8vIHB1dCB0aGUgY2hlY2tib3ggaW4gYmVmb3JlIHRoZSB2YWx1ZVxuICAgICAgICByZXR1cm4gY2JTZWxlY3Rpb25Db21wb25lbnQ7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5wcm90b3R5cGUuY3JlYXRlRG5kU291cmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZG5kU291cmNlQ29tcCA9IG5ldyBEbmRTb3VyY2VDb21wKHRoaXMucm93Tm9kZSwgdGhpcy5jb2x1bW4sIHRoaXMuYmVhbnMsIHRoaXMuZUd1aSk7XG4gICAgICAgIHRoaXMuYmVhbnMuY29udGV4dC5jcmVhdGVCZWFuKGRuZFNvdXJjZUNvbXApO1xuICAgICAgICByZXR1cm4gZG5kU291cmNlQ29tcDtcbiAgICB9O1xuICAgIENlbGxDdHJsLnByb3RvdHlwZS5yZWdpc3RlclJvd0RyYWdnZXIgPSBmdW5jdGlvbiAoY3VzdG9tRWxlbWVudCwgZHJhZ1N0YXJ0UGl4ZWxzLCBzdXBwcmVzc1Zpc2liaWxpdHlDaGFuZ2UpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gaWYgcHJldmlvdXNseSBleGlzdGVkLCB0aGVuIHdlIGFyZSBvbmx5IHVwZGF0aW5nXG4gICAgICAgIGlmICh0aGlzLmN1c3RvbVJvd0RyYWdDb21wKSB7XG4gICAgICAgICAgICB0aGlzLmN1c3RvbVJvd0RyYWdDb21wLnNldERyYWdFbGVtZW50KGN1c3RvbUVsZW1lbnQsIGRyYWdTdGFydFBpeGVscyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5ld0NvbXAgPSB0aGlzLmNyZWF0ZVJvd0RyYWdDb21wKGN1c3RvbUVsZW1lbnQsIGRyYWdTdGFydFBpeGVscywgc3VwcHJlc3NWaXNpYmlsaXR5Q2hhbmdlKTtcbiAgICAgICAgaWYgKG5ld0NvbXApIHtcbiAgICAgICAgICAgIHRoaXMuY3VzdG9tUm93RHJhZ0NvbXAgPSBuZXdDb21wO1xuICAgICAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5iZWFucy5jb250ZXh0LmRlc3Ryb3lCZWFuKG5ld0NvbXApOyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbEN0cmwucHJvdG90eXBlLmNyZWF0ZVJvd0RyYWdDb21wID0gZnVuY3Rpb24gKGN1c3RvbUVsZW1lbnQsIGRyYWdTdGFydFBpeGVscywgc3VwcHJlc3NWaXNpYmlsaXR5Q2hhbmdlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwYWdpbmF0aW9uID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNQYWdpbmF0aW9uKCk7XG4gICAgICAgIHZhciByb3dEcmFnTWFuYWdlZCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93RHJhZ01hbmFnZWQoKTtcbiAgICAgICAgdmFyIGNsaWVudFNpZGVSb3dNb2RlbEFjdGl2ZSA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxEZWZhdWx0KCk7XG4gICAgICAgIGlmIChyb3dEcmFnTWFuYWdlZCkge1xuICAgICAgICAgICAgLy8gcm93IGRyYWdnaW5nIG9ubHkgYXZhaWxhYmxlIGluIGRlZmF1bHQgcm93IG1vZGVsXG4gICAgICAgICAgICBpZiAoIWNsaWVudFNpZGVSb3dNb2RlbEFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IG1hbmFnZWQgcm93IGRyYWdnaW5nIGlzIG9ubHkgYWxsb3dlZCBpbiB0aGUgQ2xpZW50IFNpZGUgUm93IE1vZGVsJyk7IH0sICdDZWxsQ29tcC5hZGRSb3dEcmFnZ2luZycpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwYWdpbmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogbWFuYWdlZCByb3cgZHJhZ2dpbmcgaXMgbm90IHBvc3NpYmxlIHdoZW4gZG9pbmcgcGFnaW5hdGlvbicpOyB9LCAnQ2VsbENvbXAuYWRkUm93RHJhZ2dpbmcnKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gb3RoZXJ3aXNlIChub3JtYWwgY2FzZSkgd2UgYXJlIGNyZWF0aW5nIGEgUm93RHJhZ2dpbmdDb21wIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICB2YXIgcm93RHJhZ0NvbXAgPSBuZXcgUm93RHJhZ0NvbXAoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudmFsdWU7IH0sIHRoaXMucm93Tm9kZSwgdGhpcy5jb2x1bW4sIGN1c3RvbUVsZW1lbnQsIGRyYWdTdGFydFBpeGVscywgc3VwcHJlc3NWaXNpYmlsaXR5Q2hhbmdlKTtcbiAgICAgICAgdGhpcy5iZWFucy5jb250ZXh0LmNyZWF0ZUJlYW4ocm93RHJhZ0NvbXApO1xuICAgICAgICByZXR1cm4gcm93RHJhZ0NvbXA7XG4gICAgfTtcbiAgICBDZWxsQ3RybC5ET01fREFUQV9LRVlfQ0VMTF9DVFJMID0gJ2NlbGxDdHJsJztcbiAgICByZXR1cm4gQ2VsbEN0cmw7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMVUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX3ZhbHVlcyQyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX192YWx1ZXMpIHx8IGZ1bmN0aW9uKG8pIHtcbiAgICB2YXIgcyA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wuaXRlcmF0b3IsIG0gPSBzICYmIG9bc10sIGkgPSAwO1xuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xufTtcbnZhciBfX3JlYWQkaCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCRkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJGgoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBSb3dUeXBlJDE7XG4oZnVuY3Rpb24gKFJvd1R5cGUpIHtcbiAgICBSb3dUeXBlW1wiTm9ybWFsXCJdID0gXCJOb3JtYWxcIjtcbiAgICBSb3dUeXBlW1wiRnVsbFdpZHRoXCJdID0gXCJGdWxsV2lkdGhcIjtcbiAgICBSb3dUeXBlW1wiRnVsbFdpZHRoTG9hZGluZ1wiXSA9IFwiRnVsbFdpZHRoTG9hZGluZ1wiO1xuICAgIFJvd1R5cGVbXCJGdWxsV2lkdGhHcm91cFwiXSA9IFwiRnVsbFdpZHRoR3JvdXBcIjtcbiAgICBSb3dUeXBlW1wiRnVsbFdpZHRoRGV0YWlsXCJdID0gXCJGdWxsV2lkdGhEZXRhaWxcIjtcbn0pKFJvd1R5cGUkMSB8fCAoUm93VHlwZSQxID0ge30pKTtcbnZhciBpbnN0YW5jZUlkU2VxdWVuY2UkMiA9IDA7XG52YXIgUm93Q3RybCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMVUoUm93Q3RybCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSb3dDdHJsKHJvd05vZGUsIGJlYW5zLCBhbmltYXRlSW4sIHVzZUFuaW1hdGlvbkZyYW1lRm9yQ3JlYXRlLCBwcmludExheW91dCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5hbGxSb3dHdWlzID0gW107XG4gICAgICAgIF90aGlzLmFjdGl2ZSA9IHRydWU7XG4gICAgICAgIF90aGlzLmNlbnRlckNlbGxDdHJscyA9IHsgbGlzdDogW10sIG1hcDoge30gfTtcbiAgICAgICAgX3RoaXMubGVmdENlbGxDdHJscyA9IHsgbGlzdDogW10sIG1hcDoge30gfTtcbiAgICAgICAgX3RoaXMucmlnaHRDZWxsQ3RybHMgPSB7IGxpc3Q6IFtdLCBtYXA6IHt9IH07XG4gICAgICAgIF90aGlzLmxhc3RNb3VzZURvd25PbkRyYWdnZXIgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMudXBkYXRlQ29sdW1uTGlzdHNQZW5kaW5nID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIF90aGlzLnJvd05vZGUgPSByb3dOb2RlO1xuICAgICAgICBfdGhpcy5wYWdpbmF0aW9uUGFnZSA9IF90aGlzLmJlYW5zLnBhZ2luYXRpb25Qcm94eS5nZXRDdXJyZW50UGFnZSgpO1xuICAgICAgICBfdGhpcy51c2VBbmltYXRpb25GcmFtZUZvckNyZWF0ZSA9IHVzZUFuaW1hdGlvbkZyYW1lRm9yQ3JlYXRlO1xuICAgICAgICBfdGhpcy5wcmludExheW91dCA9IHByaW50TGF5b3V0O1xuICAgICAgICBfdGhpcy5pbnN0YW5jZUlkID0gcm93Tm9kZS5pZCArICctJyArIGluc3RhbmNlSWRTZXF1ZW5jZSQyKys7XG4gICAgICAgIF90aGlzLnNldEFuaW1hdGVGbGFncyhhbmltYXRlSW4pO1xuICAgICAgICBfdGhpcy5yb3dGb2N1c2VkID0gX3RoaXMuYmVhbnMuZm9jdXNTZXJ2aWNlLmlzUm93Rm9jdXNlZChfdGhpcy5yb3dOb2RlLnJvd0luZGV4LCBfdGhpcy5yb3dOb2RlLnJvd1Bpbm5lZCk7XG4gICAgICAgIF90aGlzLnJvd0xldmVsID0gX3RoaXMuYmVhbnMucm93Q3NzQ2xhc3NDYWxjdWxhdG9yLmNhbGN1bGF0ZVJvd0xldmVsKF90aGlzLnJvd05vZGUpO1xuICAgICAgICBfdGhpcy5zZXRSb3dUeXBlKCk7XG4gICAgICAgIF90aGlzLmFkZExpc3RlbmVycygpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFJvd0N0cmwucHJvdG90eXBlLmlzU3RpY2t5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dOb2RlLnN0aWNreTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldEJlYW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5iZWFucztcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldEluc3RhbmNlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmluc3RhbmNlSWQ7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKHJvd0NvbXAsIGVsZW1lbnQsIGNvbnRhaW5lclR5cGUpIHtcbiAgICAgICAgdmFyIGd1aSA9IHsgcm93Q29tcDogcm93Q29tcCwgZWxlbWVudDogZWxlbWVudCwgY29udGFpbmVyVHlwZTogY29udGFpbmVyVHlwZSB9O1xuICAgICAgICB0aGlzLmFsbFJvd0d1aXMucHVzaChndWkpO1xuICAgICAgICBpZiAoY29udGFpbmVyVHlwZSA9PT0gUm93Q29udGFpbmVyVHlwZS5MRUZUKSB7XG4gICAgICAgICAgICB0aGlzLmxlZnRHdWkgPSBndWk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29udGFpbmVyVHlwZSA9PT0gUm93Q29udGFpbmVyVHlwZS5SSUdIVCkge1xuICAgICAgICAgICAgdGhpcy5yaWdodEd1aSA9IGd1aTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb250YWluZXJUeXBlID09PSBSb3dDb250YWluZXJUeXBlLkZVTExfV0lEVEgpIHtcbiAgICAgICAgICAgIHRoaXMuZnVsbFdpZHRoR3VpID0gZ3VpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXJHdWkgPSBndWk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFsbE5vcm1hbFByZXNlbnQgPSB0aGlzLmxlZnRHdWkgIT0gbnVsbCAmJiB0aGlzLnJpZ2h0R3VpICE9IG51bGwgJiYgdGhpcy5jZW50ZXJHdWkgIT0gbnVsbDtcbiAgICAgICAgdmFyIGZ1bGxXaWR0aFByZXNlbnQgPSB0aGlzLmZ1bGxXaWR0aEd1aSAhPSBudWxsO1xuICAgICAgICBpZiAoYWxsTm9ybWFsUHJlc2VudCB8fCBmdWxsV2lkdGhQcmVzZW50KSB7XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpc2VSb3dDb21wcygpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnJvd1R5cGUgIT09ICdGdWxsV2lkdGhMb2FkaW5nJykge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyBmaXJlZCB3aXRoaW4gc2V0Q29tcCBhcyB3ZSBrbm93IHRoYXQgdGhlIGNvbXBvbmVudCByZW5kZXJlciBpcyBub3cgdHJ5aW5nIHRvIHJlbmRlci5cbiAgICAgICAgICAgIC8vIGxpbmtlZCB3aXRoIHRoZSBmYWN0IHRoZSBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbiBxdWV1ZXMgYmVoaW5kIHJlcXVlc3RBbmltYXRpb25GcmFtZSBzaG91bGQgYWxsb3dcbiAgICAgICAgICAgIC8vIHVzIHRvIGJlIGNlcnRhaW4gdGhhdCBhbGwgcmVuZGVyaW5nIGlzIGRvbmUgYnkgdGhlIHRpbWUgdGhlIGV2ZW50IGZpcmVzLlxuICAgICAgICAgICAgdGhpcy5iZWFucy5yb3dSZW5kZXJlci5kaXNwYXRjaEZpcnN0RGF0YVJlbmRlcmVkRXZlbnQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuaXNDYWNoZWFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd1R5cGUgPT09IFJvd1R5cGUkMS5GdWxsV2lkdGhEZXRhaWxcbiAgICAgICAgICAgICYmIHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzS2VlcERldGFpbFJvd3MoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnNldENhY2hlZCA9IGZ1bmN0aW9uIChjYWNoZWQpIHtcbiAgICAgICAgdmFyIGRpc3BsYXlWYWx1ZSA9IGNhY2hlZCA/ICdub25lJyA6ICcnO1xuICAgICAgICB0aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAocmcpIHsgcmV0dXJuIHJnLmVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IGRpc3BsYXlWYWx1ZTsgfSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5pbml0aWFsaXNlUm93Q29tcHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBnb3cgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlcjtcbiAgICAgICAgdGhpcy5vblJvd0hlaWdodENoYW5nZWQoKTtcbiAgICAgICAgdGhpcy51cGRhdGVSb3dJbmRleGVzKCk7XG4gICAgICAgIHRoaXMuc2V0Rm9jdXNlZENsYXNzZXMoKTtcbiAgICAgICAgdGhpcy5zZXRTdHlsZXNGcm9tR3JpZE9wdGlvbnMoKTtcbiAgICAgICAgaWYgKGdvdy5pc1Jvd1NlbGVjdGlvbigpICYmIHRoaXMucm93Tm9kZS5zZWxlY3RhYmxlKSB7XG4gICAgICAgICAgICB0aGlzLm9uUm93U2VsZWN0ZWQoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZUNvbHVtbkxpc3RzKCF0aGlzLnVzZUFuaW1hdGlvbkZyYW1lRm9yQ3JlYXRlKTtcbiAgICAgICAgaWYgKHRoaXMuc2xpZGVSb3dJbikge1xuICAgICAgICAgICAgZXhlY3V0ZU5leHRWTVR1cm4odGhpcy5vblRvcENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZmFkZVJvd0luKSB7XG4gICAgICAgICAgICBleGVjdXRlTmV4dFZNVHVybihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuYWxsUm93R3Vpcy5mb3JFYWNoKGZ1bmN0aW9uIChndWkpIHsgcmV0dXJuIGd1aS5yb3dDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLW9wYWNpdHktemVybycsIGZhbHNlKTsgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYnVzaW5lc3NLZXkgPSB0aGlzLmdldFJvd0J1c2luZXNzS2V5KCk7XG4gICAgICAgIHZhciByb3dJZFNhbml0aXNlZCA9IGVzY2FwZVN0cmluZyh0aGlzLnJvd05vZGUuaWQpO1xuICAgICAgICB2YXIgYnVzaW5lc3NLZXlTYW5pdGlzZWQgPSBlc2NhcGVTdHJpbmcoYnVzaW5lc3NLZXkpO1xuICAgICAgICB0aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAoZ3VpKSB7XG4gICAgICAgICAgICB2YXIgY29tcCA9IGd1aS5yb3dDb21wO1xuICAgICAgICAgICAgY29tcC5zZXRSb2xlKCdyb3cnKTtcbiAgICAgICAgICAgIHZhciBpbml0aWFsUm93Q2xhc3NlcyA9IF90aGlzLmdldEluaXRpYWxSb3dDbGFzc2VzKGd1aS5jb250YWluZXJUeXBlKTtcbiAgICAgICAgICAgIGluaXRpYWxSb3dDbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHsgcmV0dXJuIGNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhuYW1lLCB0cnVlKTsgfSk7XG4gICAgICAgICAgICBpZiAoX3RoaXMucm93Tm9kZS5ncm91cCkge1xuICAgICAgICAgICAgICAgIHNldEFyaWFFeHBhbmRlZChndWkuZWxlbWVudCwgX3RoaXMucm93Tm9kZS5leHBhbmRlZCA9PSB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyb3dJZFNhbml0aXNlZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29tcC5zZXRSb3dJZChyb3dJZFNhbml0aXNlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYnVzaW5lc3NLZXlTYW5pdGlzZWQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbXAuc2V0Um93QnVzaW5lc3NLZXkoYnVzaW5lc3NLZXlTYW5pdGlzZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmlzRnVsbFdpZHRoKCkgJiYgIV90aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ2VsbEZvY3VzKCkpIHtcbiAgICAgICAgICAgICAgICBjb21wLnNldFRhYkluZGV4KC0xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERPTSBEQVRBXG4gICAgICAgICAgICBnb3cuc2V0RG9tRGF0YShndWkuZWxlbWVudCwgUm93Q3RybC5ET01fREFUQV9LRVlfUk9XX0NUUkwsIF90aGlzKTtcbiAgICAgICAgICAgIF90aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGdvdy5zZXREb21EYXRhKGd1aS5lbGVtZW50LCBSb3dDdHJsLkRPTV9EQVRBX0tFWV9ST1dfQ1RSTCwgbnVsbCk7IH0pO1xuICAgICAgICAgICAgLy8gYWRkaW5nIGhvdmVyIGZ1bmN0aW9uYWxpdHkgYWRkcyBsaXN0ZW5lciB0byB0aGlzIHJvdywgc28gd2VcbiAgICAgICAgICAgIC8vIGRvIGl0IGxhemlseSBpbiBhbiBhbmltYXRpb24gZnJhbWVcbiAgICAgICAgICAgIGlmIChfdGhpcy51c2VBbmltYXRpb25GcmFtZUZvckNyZWF0ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmJlYW5zLmFuaW1hdGlvbkZyYW1lU2VydmljZS5jcmVhdGVUYXNrKF90aGlzLmFkZEhvdmVyRnVuY3Rpb25hbGl0eS5iaW5kKF90aGlzLCBndWkuZWxlbWVudCksIF90aGlzLnJvd05vZGUucm93SW5kZXgsICdjcmVhdGVUYXNrc1AyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5hZGRIb3ZlckZ1bmN0aW9uYWxpdHkoZ3VpLmVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLmlzRnVsbFdpZHRoKCkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXR1cEZ1bGxXaWR0aChndWkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdvdy5pc1Jvd0RyYWdFbnRpcmVSb3coKSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmFkZFJvd0RyYWdnZXJUb1JvdyhndWkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF90aGlzLnVzZUFuaW1hdGlvbkZyYW1lRm9yQ3JlYXRlKSB7XG4gICAgICAgICAgICAgICAgLy8gdGhlIGhlaWdodCBhbmltYXRpb24gd2Ugb25seSB3YW50IGFjdGl2ZSBhZnRlciB0aGUgcm93IGlzIGFsaXZlIGZvciAxIHNlY29uZC5cbiAgICAgICAgICAgICAgICAvLyB0aGlzIHN0b3BzIHRoZSByb3cgYW5pbWF0aW9uIHdvcmtpbmcgd2hlbiByb3dzIGFyZSBpbml0aWFsbHkgY3JhdGVkLiBvdGhlcndpc2VcbiAgICAgICAgICAgICAgICAvLyBhdXRvLWhlaWdodCByb3dzIGdldCBpbnNlcnRlZCBpbnRvIHRoZSBkb20gYW5kIHJlc2l6ZWQgaW1tZWRpYXRlbHksIHdoaWNoIGdpdmVzXG4gICAgICAgICAgICAgICAgLy8gdmVyeSBiYWQgVVggKGVnIDEwIHJvd3MgZ2V0IGluc2VydGVkLCB0aGVuIGFsbCAxMCBleHBhbmQsIGxvb2sgcGFydGljdWxhcmx5IGJhZFxuICAgICAgICAgICAgICAgIC8vIHdoZW4gc2Nyb2xsaW5nKS4gc28gdGhpcyBtYWtlcyBzdXJlIHdoZW4gcm93cyBhcmUgc2hvd24gZm9yIHRoZSBmaXJzdCB0aW1lLCB0aGV5XG4gICAgICAgICAgICAgICAgLy8gYXJlIHJlc2l6ZWQgaW1tZWRpYXRlbHkgd2l0aG91dCBhbmltYXRpb24uXG4gICAgICAgICAgICAgICAgX3RoaXMuYmVhbnMuYW5pbWF0aW9uRnJhbWVTZXJ2aWNlLmFkZERlc3Ryb3lUYXNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1hZnRlci1jcmVhdGVkJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmV4ZWN1dGVQcm9jZXNzUm93UG9zdENyZWF0ZUZ1bmMoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmFkZFJvd0RyYWdnZXJUb1JvdyA9IGZ1bmN0aW9uIChndWkpIHtcbiAgICAgICAgdmFyIGdvdyA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICBpZiAoZ293LmlzRW5hYmxlUmFuZ2VTZWxlY3Rpb24oKSkge1xuICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFNldHRpbmcgYHJvd0RyYWdFbnRpcmVSb3c6IHRydWVgIGluIHRoZSBncmlkT3B0aW9ucyBkb2VzblxcJ3Qgd29yayB3aXRoIGBlbmFibGVSYW5nZVNlbGVjdGlvbjogdHJ1ZWAnKTtcbiAgICAgICAgICAgIH0sICdyb3dEcmFnQW5kUmFuZ2VTZWxlY3Rpb25FbmFibGVkJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IGdvdy5nZXRMb2NhbGVUZXh0RnVuYygpO1xuICAgICAgICB2YXIgcm93RHJhZ0NvbXAgPSBuZXcgUm93RHJhZ0NvbXAoZnVuY3Rpb24gKCkgeyByZXR1cm4gXCIxIFwiICsgdHJhbnNsYXRlKCdyb3dEcmFnUm93JywgJ3JvdycpOyB9LCB0aGlzLnJvd05vZGUsIHVuZGVmaW5lZCwgZ3VpLmVsZW1lbnQsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4ocm93RHJhZ0NvbXAsIHRoaXMuYmVhbnMuY29udGV4dCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXR1cEZ1bGxXaWR0aCA9IGZ1bmN0aW9uIChndWkpIHtcbiAgICAgICAgdmFyIHBpbm5lZCA9IHRoaXMuZ2V0UGlubmVkRm9yQ29udGFpbmVyKGd1aS5jb250YWluZXJUeXBlKTtcbiAgICAgICAgdmFyIHBhcmFtcyA9IHRoaXMuY3JlYXRlRnVsbFdpZHRoUGFyYW1zKGd1aS5lbGVtZW50LCBwaW5uZWQpO1xuICAgICAgICB2YXIgbWFzdGVyRGV0YWlsTW9kdWxlTG9hZGVkID0gTW9kdWxlUmVnaXN0cnkuaXNSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLk1hc3RlckRldGFpbE1vZHVsZSk7XG4gICAgICAgIGlmICh0aGlzLnJvd1R5cGUgPT0gUm93VHlwZSQxLkZ1bGxXaWR0aERldGFpbCAmJiAhbWFzdGVyRGV0YWlsTW9kdWxlTG9hZGVkKSB7XG4gICAgICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuaXNQYWNrYWdlQmFzZWQoKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGNlbGwgcmVuZGVyZXIgJ2FnRGV0YWlsQ2VsbFJlbmRlcmVyJyAoZm9yIG1hc3RlciBkZXRhaWwpIG5vdCBmb3VuZC4gQ2FuIG9ubHkgYmUgdXNlZCB3aXRoIGFnLWdyaWQtZW50ZXJwcmlzZSBwYWNrYWdlLlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGNlbGwgcmVuZGVyZXIgJ2FnRGV0YWlsQ2VsbFJlbmRlcmVyJyAoZm9yIG1hc3RlciBkZXRhaWwpIG5vdCBmb3VuZC4gQ2FuIG9ubHkgYmUgdXNlZCB3aXRoIEFHIEdyaWQgRW50ZXJwcmlzZSBNb2R1bGUgXCIgKyBNb2R1bGVOYW1lcy5NYXN0ZXJEZXRhaWxNb2R1bGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb21wRGV0YWlscztcbiAgICAgICAgc3dpdGNoICh0aGlzLnJvd1R5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgUm93VHlwZSQxLkZ1bGxXaWR0aERldGFpbDpcbiAgICAgICAgICAgICAgICBjb21wRGV0YWlscyA9IHRoaXMuYmVhbnMudXNlckNvbXBvbmVudEZhY3RvcnkuZ2V0RnVsbFdpZHRoRGV0YWlsQ2VsbFJlbmRlcmVyRGV0YWlscyhwYXJhbXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dUeXBlJDEuRnVsbFdpZHRoR3JvdXA6XG4gICAgICAgICAgICAgICAgY29tcERldGFpbHMgPSB0aGlzLmJlYW5zLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldEZ1bGxXaWR0aEdyb3VwQ2VsbFJlbmRlcmVyRGV0YWlscyhwYXJhbXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dUeXBlJDEuRnVsbFdpZHRoTG9hZGluZzpcbiAgICAgICAgICAgICAgICBjb21wRGV0YWlscyA9IHRoaXMuYmVhbnMudXNlckNvbXBvbmVudEZhY3RvcnkuZ2V0RnVsbFdpZHRoTG9hZGluZ0NlbGxSZW5kZXJlckRldGFpbHMocGFyYW1zKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgY29tcERldGFpbHMgPSB0aGlzLmJlYW5zLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldEZ1bGxXaWR0aENlbGxSZW5kZXJlckRldGFpbHMocGFyYW1zKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBndWkucm93Q29tcC5zaG93RnVsbFdpZHRoKGNvbXBEZXRhaWxzKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmlzUHJpbnRMYXlvdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW50TGF5b3V0O1xuICAgIH07XG4gICAgLy8gdXNlIGJ5IGF1dG9XaWR0aENhbGN1bGF0b3IsIGFzIGl0IGNsb25lcyB0aGUgZWxlbWVudHNcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRDZWxsRWxlbWVudCA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgdmFyIGNlbGxDdHJsID0gdGhpcy5nZXRDZWxsQ3RybChjb2x1bW4pO1xuICAgICAgICByZXR1cm4gY2VsbEN0cmwgPyBjZWxsQ3RybC5nZXRHdWkoKSA6IG51bGw7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5leGVjdXRlUHJvY2Vzc1Jvd1Bvc3RDcmVhdGVGdW5jID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZnVuYyA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFByb2Nlc3NSb3dQb3N0Q3JlYXRlRnVuYygpO1xuICAgICAgICBpZiAoIWZ1bmMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZVJvdzogdGhpcy5jZW50ZXJHdWkgPyB0aGlzLmNlbnRlckd1aS5lbGVtZW50IDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZVBpbm5lZExlZnRSb3c6IHRoaXMubGVmdEd1aSA/IHRoaXMubGVmdEd1aS5lbGVtZW50IDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZVBpbm5lZFJpZ2h0Um93OiB0aGlzLnJpZ2h0R3VpID8gdGhpcy5yaWdodEd1aS5lbGVtZW50IDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgbm9kZTogdGhpcy5yb3dOb2RlLFxuICAgICAgICAgICAgcm93SW5kZXg6IHRoaXMucm93Tm9kZS5yb3dJbmRleCxcbiAgICAgICAgICAgIGFkZFJlbmRlcmVkUm93TGlzdGVuZXI6IHRoaXMuYWRkRXZlbnRMaXN0ZW5lci5iaW5kKHRoaXMpLFxuICAgICAgICB9O1xuICAgICAgICBmdW5jKHBhcmFtcyk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRSb3dUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNTdHViID0gdGhpcy5yb3dOb2RlLnN0dWI7XG4gICAgICAgIHZhciBpc0Z1bGxXaWR0aENlbGwgPSB0aGlzLnJvd05vZGUuaXNGdWxsV2lkdGhDZWxsKCk7XG4gICAgICAgIHZhciBpc0RldGFpbENlbGwgPSB0aGlzLmJlYW5zLmRvaW5nTWFzdGVyRGV0YWlsICYmIHRoaXMucm93Tm9kZS5kZXRhaWw7XG4gICAgICAgIHZhciBwaXZvdE1vZGUgPSB0aGlzLmJlYW5zLmNvbHVtbk1vZGVsLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIC8vIHdlIG9ubHkgdXNlIGZ1bGwgd2lkdGggZm9yIGdyb3Vwcywgbm90IGZvb3RlcnMuIGl0IHdvdWxkbid0IG1ha2Ugc2Vuc2UgdG8gaW5jbHVkZSBmb290ZXJzIGlmIG5vdCBsb29raW5nXG4gICAgICAgIC8vIGZvciB0b3RhbHMuIGlmIHVzZXJzIGNvbXBsYWluIGFib3V0IHRoaXMsIHRoZW4gd2Ugc2hvdWxkIGludHJvZHVjZSBhIG5ldyBwcm9wZXJ0eSAnZm9vdGVyVXNlRW50aXJlUm93J1xuICAgICAgICAvLyBzbyBlYWNoIGNhbiBiZSBzZXQgaW5kZXBlbmRlbnRseSAoYXMgYSBjdXN0b21lciBjb21wbGFpbmVkIGFib3V0IGZvb3RlcnMgZ2V0dGluZyBmdWxsIHdpZHRoLCBoZW5jZVxuICAgICAgICAvLyBpbnRyb2R1Y2luZyB0aGlzIGxvZ2ljKVxuICAgICAgICB2YXIgaXNHcm91cFJvdyA9ICEhdGhpcy5yb3dOb2RlLmdyb3VwICYmICF0aGlzLnJvd05vZGUuZm9vdGVyO1xuICAgICAgICB2YXIgaXNGdWxsV2lkdGhHcm91cCA9IGlzR3JvdXBSb3cgJiYgdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFVzZUVudGlyZVJvdyhwaXZvdE1vZGUpO1xuICAgICAgICBpZiAoaXNTdHViKSB7XG4gICAgICAgICAgICB0aGlzLnJvd1R5cGUgPSBSb3dUeXBlJDEuRnVsbFdpZHRoTG9hZGluZztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc0RldGFpbENlbGwpIHtcbiAgICAgICAgICAgIHRoaXMucm93VHlwZSA9IFJvd1R5cGUkMS5GdWxsV2lkdGhEZXRhaWw7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNGdWxsV2lkdGhDZWxsKSB7XG4gICAgICAgICAgICB0aGlzLnJvd1R5cGUgPSBSb3dUeXBlJDEuRnVsbFdpZHRoO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzRnVsbFdpZHRoR3JvdXApIHtcbiAgICAgICAgICAgIHRoaXMucm93VHlwZSA9IFJvd1R5cGUkMS5GdWxsV2lkdGhHcm91cDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucm93VHlwZSA9IFJvd1R5cGUkMS5Ob3JtYWw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnVwZGF0ZUNvbHVtbkxpc3RzID0gZnVuY3Rpb24gKHN1cHByZXNzQW5pbWF0aW9uRnJhbWUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHN1cHByZXNzQW5pbWF0aW9uRnJhbWUgPT09IHZvaWQgMCkgeyBzdXBwcmVzc0FuaW1hdGlvbkZyYW1lID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKHRoaXMuaXNGdWxsV2lkdGgoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub0FuaW1hdGlvbiA9IHN1cHByZXNzQW5pbWF0aW9uRnJhbWVcbiAgICAgICAgICAgIHx8IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NBbmltYXRpb25GcmFtZSgpXG4gICAgICAgICAgICB8fCB0aGlzLnByaW50TGF5b3V0O1xuICAgICAgICBpZiAobm9BbmltYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQ29sdW1uTGlzdHNJbXBsKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudXBkYXRlQ29sdW1uTGlzdHNQZW5kaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5iZWFucy5hbmltYXRpb25GcmFtZVNlcnZpY2UuY3JlYXRlVGFzayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZUNvbHVtbkxpc3RzSW1wbCgpO1xuICAgICAgICB9LCB0aGlzLnJvd05vZGUucm93SW5kZXgsICdjcmVhdGVUYXNrc1AxJyk7XG4gICAgICAgIHRoaXMudXBkYXRlQ29sdW1uTGlzdHNQZW5kaW5nID0gdHJ1ZTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmNyZWF0ZUNlbGxDdHJscyA9IGZ1bmN0aW9uIChwcmV2LCBjb2xzLCBwaW5uZWQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHBpbm5lZCA9PT0gdm9pZCAwKSB7IHBpbm5lZCA9IG51bGw7IH1cbiAgICAgICAgdmFyIHJlcyA9IHtcbiAgICAgICAgICAgIGxpc3Q6IFtdLFxuICAgICAgICAgICAgbWFwOiB7fVxuICAgICAgICB9O1xuICAgICAgICB2YXIgYWRkQ2VsbCA9IGZ1bmN0aW9uIChjb2xJbnN0YW5jZUlkLCBjZWxsQ3RybCkge1xuICAgICAgICAgICAgcmVzLmxpc3QucHVzaChjZWxsQ3RybCk7XG4gICAgICAgICAgICByZXMubWFwW2NvbEluc3RhbmNlSWRdID0gY2VsbEN0cmw7XG4gICAgICAgIH07XG4gICAgICAgIGNvbHMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICAvLyB3ZSB1c2UgaW5zdGFuY2VJZCdzIHJhdGhlciB0aGFuIGNvbElkIGFzIGl0J3MgcG9zc2libGUgdGhlcmUgaXMgYSBDb2x1bW4gd2l0aCBzYW1lIElkLFxuICAgICAgICAgICAgLy8gYnV0IGl0J3MgcmVmZXJyaW5nIHRvIGEgZGlmZmVyZW50IGNvbHVtbiBpbnN0YW5jZS4gSGFwcGVucyBhIGxvdCB3aXRoIHBpdm90LCBhcyBwaXZvdCBjb2wgaWQncyBhcmVcbiAgICAgICAgICAgIC8vIHJldXNlZCBlZyBwaXZvdF8wLCBwaXZvdF8xIGV0Y1xuICAgICAgICAgICAgdmFyIGNvbEluc3RhbmNlSWQgPSBjb2wuZ2V0SW5zdGFuY2VJZCgpO1xuICAgICAgICAgICAgdmFyIGNlbGxDdHJsID0gcHJldi5tYXBbY29sSW5zdGFuY2VJZF07XG4gICAgICAgICAgICBpZiAoIWNlbGxDdHJsKSB7XG4gICAgICAgICAgICAgICAgY2VsbEN0cmwgPSBuZXcgQ2VsbEN0cmwoY29sLCBfdGhpcy5yb3dOb2RlLCBfdGhpcy5iZWFucywgX3RoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYWRkQ2VsbChjb2xJbnN0YW5jZUlkLCBjZWxsQ3RybCk7XG4gICAgICAgIH0pO1xuICAgICAgICBwcmV2Lmxpc3QuZm9yRWFjaChmdW5jdGlvbiAocHJldkNlbGxDdHJsKSB7XG4gICAgICAgICAgICB2YXIgY2VsbEluUmVzdWx0ID0gcmVzLm1hcFtwcmV2Q2VsbEN0cmwuZ2V0Q29sdW1uKCkuZ2V0SW5zdGFuY2VJZCgpXSAhPSBudWxsO1xuICAgICAgICAgICAgaWYgKGNlbGxJblJlc3VsdCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBrZWVwQ2VsbCA9ICFfdGhpcy5pc0NlbGxFbGlnaWJsZVRvQmVSZW1vdmVkKHByZXZDZWxsQ3RybCwgcGlubmVkKTtcbiAgICAgICAgICAgIGlmIChrZWVwQ2VsbCkge1xuICAgICAgICAgICAgICAgIGFkZENlbGwocHJldkNlbGxDdHJsLmdldENvbHVtbigpLmdldEluc3RhbmNlSWQoKSwgcHJldkNlbGxDdHJsKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2Q2VsbEN0cmwuZGVzdHJveSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnVwZGF0ZUNvbHVtbkxpc3RzSW1wbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy51cGRhdGVDb2x1bW5MaXN0c1BlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgdmFyIGNvbHVtbk1vZGVsID0gdGhpcy5iZWFucy5jb2x1bW5Nb2RlbDtcbiAgICAgICAgaWYgKHRoaXMucHJpbnRMYXlvdXQpIHtcbiAgICAgICAgICAgIHRoaXMuY2VudGVyQ2VsbEN0cmxzID0gdGhpcy5jcmVhdGVDZWxsQ3RybHModGhpcy5jZW50ZXJDZWxsQ3RybHMsIGNvbHVtbk1vZGVsLmdldEFsbERpc3BsYXllZENvbHVtbnMoKSk7XG4gICAgICAgICAgICB0aGlzLmxlZnRDZWxsQ3RybHMgPSB7IGxpc3Q6IFtdLCBtYXA6IHt9IH07XG4gICAgICAgICAgICB0aGlzLnJpZ2h0Q2VsbEN0cmxzID0geyBsaXN0OiBbXSwgbWFwOiB7fSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGNlbnRlckNvbHMgPSBjb2x1bW5Nb2RlbC5nZXRWaWV3cG9ydENlbnRlckNvbHVtbnNGb3JSb3codGhpcy5yb3dOb2RlKTtcbiAgICAgICAgICAgIHRoaXMuY2VudGVyQ2VsbEN0cmxzID0gdGhpcy5jcmVhdGVDZWxsQ3RybHModGhpcy5jZW50ZXJDZWxsQ3RybHMsIGNlbnRlckNvbHMpO1xuICAgICAgICAgICAgdmFyIGxlZnRDb2xzID0gY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkTGVmdENvbHVtbnNGb3JSb3codGhpcy5yb3dOb2RlKTtcbiAgICAgICAgICAgIHRoaXMubGVmdENlbGxDdHJscyA9IHRoaXMuY3JlYXRlQ2VsbEN0cmxzKHRoaXMubGVmdENlbGxDdHJscywgbGVmdENvbHMsIENvbnN0YW50cy5QSU5ORURfTEVGVCk7XG4gICAgICAgICAgICB2YXIgcmlnaHRDb2xzID0gY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkUmlnaHRDb2x1bW5zRm9yUm93KHRoaXMucm93Tm9kZSk7XG4gICAgICAgICAgICB0aGlzLnJpZ2h0Q2VsbEN0cmxzID0gdGhpcy5jcmVhdGVDZWxsQ3RybHModGhpcy5yaWdodENlbGxDdHJscywgcmlnaHRDb2xzLCBDb25zdGFudHMuUElOTkVEX1JJR0hUKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgdmFyIGNlbGxDb250cm9scyA9IGl0ZW0uY29udGFpbmVyVHlwZSA9PT0gUm93Q29udGFpbmVyVHlwZS5MRUZUID8gX3RoaXMubGVmdENlbGxDdHJscyA6XG4gICAgICAgICAgICAgICAgaXRlbS5jb250YWluZXJUeXBlID09PSBSb3dDb250YWluZXJUeXBlLlJJR0hUID8gX3RoaXMucmlnaHRDZWxsQ3RybHMgOiBfdGhpcy5jZW50ZXJDZWxsQ3RybHM7XG4gICAgICAgICAgICBpdGVtLnJvd0NvbXAuc2V0Q2VsbEN0cmxzKGNlbGxDb250cm9scy5saXN0KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5pc0NlbGxFbGlnaWJsZVRvQmVSZW1vdmVkID0gZnVuY3Rpb24gKGNlbGxDdHJsLCBuZXh0Q29udGFpbmVyUGlubmVkKSB7XG4gICAgICAgIHZhciBSRU1PVkVfQ0VMTCA9IHRydWU7XG4gICAgICAgIHZhciBLRUVQX0NFTEwgPSBmYWxzZTtcbiAgICAgICAgLy8gYWx3YXlzIHJlbW92ZSB0aGUgY2VsbCBpZiBpdCdzIG5vdCByZW5kZXJlZCBvciBpZiBpdCdzIGluIHRoZSB3cm9uZyBwaW5uZWQgbG9jYXRpb25cbiAgICAgICAgdmFyIGNvbHVtbiA9IGNlbGxDdHJsLmdldENvbHVtbigpO1xuICAgICAgICBpZiAoY29sdW1uLmdldFBpbm5lZCgpICE9IG5leHRDb250YWluZXJQaW5uZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBSRU1PVkVfQ0VMTDtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSB3YW50IHRvIHRyeSBhbmQga2VlcCBlZGl0aW5nIGFuZCBmb2N1c2VkIGNlbGxzXG4gICAgICAgIHZhciBlZGl0aW5nID0gY2VsbEN0cmwuaXNFZGl0aW5nKCk7XG4gICAgICAgIHZhciBmb2N1c2VkID0gdGhpcy5iZWFucy5mb2N1c1NlcnZpY2UuaXNDZWxsRm9jdXNlZChjZWxsQ3RybC5nZXRDZWxsUG9zaXRpb24oKSk7XG4gICAgICAgIHZhciBtaWdodFdhbnRUb0tlZXBDZWxsID0gZWRpdGluZyB8fCBmb2N1c2VkO1xuICAgICAgICBpZiAobWlnaHRXYW50VG9LZWVwQ2VsbCkge1xuICAgICAgICAgICAgdmFyIGNvbHVtbl8xID0gY2VsbEN0cmwuZ2V0Q29sdW1uKCk7XG4gICAgICAgICAgICB2YXIgZGlzcGxheWVkQ29sdW1ucyA9IHRoaXMuYmVhbnMuY29sdW1uTW9kZWwuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucygpO1xuICAgICAgICAgICAgdmFyIGNlbGxTdGlsbERpc3BsYXllZCA9IGRpc3BsYXllZENvbHVtbnMuaW5kZXhPZihjb2x1bW5fMSkgPj0gMDtcbiAgICAgICAgICAgIHJldHVybiBjZWxsU3RpbGxEaXNwbGF5ZWQgPyBLRUVQX0NFTEwgOiBSRU1PVkVfQ0VMTDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUkVNT1ZFX0NFTEw7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRBbmltYXRlRmxhZ3MgPSBmdW5jdGlvbiAoYW5pbWF0ZUluKSB7XG4gICAgICAgIGlmICghdGhpcy5pc1N0aWNreSgpICYmIGFuaW1hdGVJbikge1xuICAgICAgICAgICAgdmFyIG9sZFJvd1RvcEV4aXN0cyA9IGV4aXN0cyh0aGlzLnJvd05vZGUub2xkUm93VG9wKTtcbiAgICAgICAgICAgIC8vIGlmIHRoZSByb3cgaGFkIGEgcHJldmlvdXMgcG9zaXRpb24sIHdlIHNsaWRlIGl0IGluIChhbmltYXRlIHJvdyB0b3ApXG4gICAgICAgICAgICB0aGlzLnNsaWRlUm93SW4gPSBvbGRSb3dUb3BFeGlzdHM7XG4gICAgICAgICAgICAvLyBpZiB0aGUgcm93IGhhZCBubyBwcmV2aW91cyBwb3NpdGlvbiwgd2UgZmFkZSBpdCBpbiAoYW5pbWF0ZVxuICAgICAgICAgICAgdGhpcy5mYWRlUm93SW4gPSAhb2xkUm93VG9wRXhpc3RzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zbGlkZVJvd0luID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmZhZGVSb3dJbiA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5pc0VkaXRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVkaXRpbmdSb3c7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zdG9wUm93RWRpdGluZyA9IGZ1bmN0aW9uIChjYW5jZWwpIHtcbiAgICAgICAgdGhpcy5zdG9wRWRpdGluZyhjYW5jZWwpO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuaXNGdWxsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd1R5cGUgIT09IFJvd1R5cGUkMS5Ob3JtYWw7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRSb3dUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dUeXBlO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUucmVmcmVzaEZ1bGxXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gcmV0dXJucyAndHJ1ZScgaWYgcmVmcmVzaCBzdWNjZWVkZWRcbiAgICAgICAgdmFyIHRyeVJlZnJlc2ggPSBmdW5jdGlvbiAoZ3VpLCBwaW5uZWQpIHtcbiAgICAgICAgICAgIGlmICghZ3VpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9IC8vIG5vIHJlZnJlc2ggbmVlZGVkXG4gICAgICAgICAgICB2YXIgY2VsbFJlbmRlcmVyID0gZ3VpLnJvd0NvbXAuZ2V0RnVsbFdpZHRoQ2VsbFJlbmRlcmVyKCk7XG4gICAgICAgICAgICAvLyBubyBjZWxsIHJlbmRlcmVyLCBlaXRoZXIgbWVhbnMgY29tcCBub3QgeWV0IHJlYWR5LCBvciBjb21wIHJlYWR5IGJ1dCBub3cgcmVmZXJlbmNlXG4gICAgICAgICAgICAvLyB0byBpdCAoaGFwcGVucyBpbiByZWFjdCB3aGVuIGNvbXAgaXMgc3RhdGVsZXNzKS4gaWYgY29tcCBub3QgcmVhZHksIHdlIGRvbid0IG5lZWQgdG9cbiAgICAgICAgICAgIC8vIHJlZnJlc2gsIGhvd2V2ZXIgd2UgZG9uJ3Qga25vdyB3aGljaCBvbmUsIHNvIHdlIHJlZnJlc2ggdG8gY292ZXIgdGhlIGNhc2Ugd2hlcmUgaXQnc1xuICAgICAgICAgICAgLy8gcmVhY3QgY29tcCB3aXRob3V0IHJlZmVyZW5jZSBzbyBuZWVkIHRvIGZvcmNlIGEgcmVmcmVzaFxuICAgICAgICAgICAgaWYgKCFjZWxsUmVuZGVyZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBubyByZWZyZXNoIG1ldGhvZCBwcmVzZW50LCBzbyBjYW4ndCByZWZyZXNoLCBoYXJkIHJlZnJlc2ggbmVlZGVkXG4gICAgICAgICAgICBpZiAoIWNlbGxSZW5kZXJlci5yZWZyZXNoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IF90aGlzLmNyZWF0ZUZ1bGxXaWR0aFBhcmFtcyhndWkuZWxlbWVudCwgcGlubmVkKTtcbiAgICAgICAgICAgIHZhciByZWZyZXNoU3VjY2VlZGVkID0gY2VsbFJlbmRlcmVyLnJlZnJlc2gocGFyYW1zKTtcbiAgICAgICAgICAgIHJldHVybiByZWZyZXNoU3VjY2VlZGVkO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgZnVsbFdpZHRoU3VjY2VzcyA9IHRyeVJlZnJlc2godGhpcy5mdWxsV2lkdGhHdWksIG51bGwpO1xuICAgICAgICB2YXIgY2VudGVyU3VjY2VzcyA9IHRyeVJlZnJlc2godGhpcy5jZW50ZXJHdWksIG51bGwpO1xuICAgICAgICB2YXIgbGVmdFN1Y2Nlc3MgPSB0cnlSZWZyZXNoKHRoaXMubGVmdEd1aSwgQ29uc3RhbnRzLlBJTk5FRF9MRUZUKTtcbiAgICAgICAgdmFyIHJpZ2h0U3VjY2VzcyA9IHRyeVJlZnJlc2godGhpcy5yaWdodEd1aSwgQ29uc3RhbnRzLlBJTk5FRF9SSUdIVCk7XG4gICAgICAgIHZhciBhbGxGdWxsV2lkdGhSb3dzUmVmcmVzaGVkID0gZnVsbFdpZHRoU3VjY2VzcyAmJiBjZW50ZXJTdWNjZXNzICYmIGxlZnRTdWNjZXNzICYmIHJpZ2h0U3VjY2VzcztcbiAgICAgICAgcmV0dXJuIGFsbEZ1bGxXaWR0aFJvd3NSZWZyZXNoZWQ7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5hZGRMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9IRUlHSFRfQ0hBTkdFRCwgdGhpcy5vblJvd0hlaWdodENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9ST1dfU0VMRUNURUQsIHRoaXMub25Sb3dTZWxlY3RlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX1JPV19JTkRFWF9DSEFOR0VELCB0aGlzLm9uUm93SW5kZXhDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfVE9QX0NIQU5HRUQsIHRoaXMub25Ub3BDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfRVhQQU5ERURfQ0hBTkdFRCwgdGhpcy51cGRhdGVFeHBhbmRlZENzcy5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX0hBU19DSElMRFJFTl9DSEFOR0VELCB0aGlzLnVwZGF0ZUV4cGFuZGVkQ3NzLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfREFUQV9DSEFOR0VELCB0aGlzLm9uUm93Tm9kZURhdGFDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfQ0VMTF9DSEFOR0VELCB0aGlzLm9uUm93Tm9kZUNlbGxDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfSElHSExJR0hUX0NIQU5HRUQsIHRoaXMub25Sb3dOb2RlSGlnaGxpZ2h0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX0RSQUdHSU5HX0NIQU5HRUQsIHRoaXMub25Sb3dOb2RlRHJhZ2dpbmdDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfVUlfTEVWRUxfQ0hBTkdFRCwgdGhpcy5vblVpTGV2ZWxDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB2YXIgZXZlbnRTZXJ2aWNlID0gdGhpcy5iZWFucy5ldmVudFNlcnZpY2U7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BBR0lOQVRJT05fUElYRUxfT0ZGU0VUX0NIQU5HRUQsIHRoaXMub25QYWdpbmF0aW9uUGl4ZWxPZmZzZXRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9IRUlHSFRfU0NBTEVfQ0hBTkdFRCwgdGhpcy5vblRvcENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfVklSVFVBTF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMub25WaXJ0dWFsQ29sdW1uc0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NFTExfRk9DVVNFRCwgdGhpcy5vbkNlbGxGb2N1c0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BBR0lOQVRJT05fQ0hBTkdFRCwgdGhpcy5vblBhZ2luYXRpb25DaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9NT0RFTF9VUERBVEVELCB0aGlzLm9uTW9kZWxVcGRhdGVkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQsIHRoaXMub25Db2x1bW5Nb3ZlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRMaXN0ZW5lcnNGb3JDZWxsQ29tcHMoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLm9uQ29sdW1uTW92ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlQ29sdW1uTGlzdHMoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmFkZExpc3RlbmVyc0ZvckNlbGxDb21wcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX1JPV19JTkRFWF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwub25Sb3dJbmRleENoYW5nZWQoKTsgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJvd05vZGUsIFJvd05vZGUuRVZFTlRfQ0VMTF9DSEFOR0VELCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIF90aGlzLmdldEFsbENlbGxDdHJscygpLmZvckVhY2goZnVuY3Rpb24gKGNlbGxDdHJsKSB7IHJldHVybiBjZWxsQ3RybC5vbkNlbGxDaGFuZ2VkKGV2ZW50KTsgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25Sb3dOb2RlRGF0YUNoYW5nZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgLy8gaWYgdGhpcyBpcyBhbiB1cGRhdGUsIHdlIHdhbnQgdG8gcmVmcmVzaCwgYXMgdGhpcyB3aWxsIGFsbG93IHRoZSB1c2VyIHRvIHB1dCBpbiBhIHRyYW5zaXRpb25cbiAgICAgICAgLy8gaW50byB0aGUgY2VsbFJlbmRlcmVyIHJlZnJlc2ggbWV0aG9kLiBvdGhlcndpc2UgdGhpcyBtaWdodCBiZSBjb21wbGV0ZWx5IG5ldyBkYXRhLCBpbiB3aGljaCBjYXNlXG4gICAgICAgIC8vIHdlIHdpbGwgd2FudCB0byBjb21wbGV0ZWx5IHJlcGxhY2UgdGhlIGNlbGxzXG4gICAgICAgIHRoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgICAgIHJldHVybiBjZWxsQ3RybC5yZWZyZXNoQ2VsbCh7XG4gICAgICAgICAgICAgICAgc3VwcHJlc3NGbGFzaDogIWV2ZW50LnVwZGF0ZSxcbiAgICAgICAgICAgICAgICBuZXdEYXRhOiAhZXZlbnQudXBkYXRlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGNoZWNrIGZvciBzZWxlY3RlZCBhbHNvLCBhcyB0aGlzIGNvdWxkIGJlIGFmdGVyIGxhenkgbG9hZGluZyBvZiB0aGUgcm93IGRhdGEsIGluIHdoaWNoIGNhc2VcbiAgICAgICAgLy8gdGhlIGlkIG1pZ2h0IG9mIGp1c3QgZ290dGVuIHNldCBpbnNpZGUgdGhlIHJvdyBhbmQgdGhlIHJvdyBzZWxlY3RlZCBzdGF0ZSBtYXkgb2YgY2hhbmdlZFxuICAgICAgICAvLyBhcyBhIHJlc3VsdC4gdGhpcyBpcyB3aGF0IGhhcHBlbnMgd2hlbiBzZWxlY3RlZCByb3dzIGFyZSBsb2FkZWQgaW4gdmlydHVhbCBwYWdpbmF0aW9uLlxuICAgICAgICAvLyAtIG5pYWxsIG5vdGUgLSBzaW5jZSBtb3ZpbmcgdG8gdGhlIHN0dWIgY29tcG9uZW50LCB0aGlzIG1heSBubyBsb25nZXIgYmUgdHJ1ZSwgYXMgcmVwbGFjaW5nXG4gICAgICAgIC8vIHRoZSBzdHViIGNvbXBvbmVudCBub3cgcmVwbGFjZXMgdGhlIGVudGlyZSByb3dcbiAgICAgICAgdGhpcy5vblJvd1NlbGVjdGVkKCk7XG4gICAgICAgIC8vIGFzIGRhdGEgaGFzIGNoYW5nZWQsIHRoZW4gdGhlIHN0eWxlIGFuZCBjbGFzcyBuZWVkcyB0byBiZSByZWNvbXB1dGVkXG4gICAgICAgIHRoaXMucG9zdFByb2Nlc3NDc3MoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLm9uUm93Tm9kZUNlbGxDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBhcyBkYXRhIGhhcyBjaGFuZ2VkLCB0aGVuIHRoZSBzdHlsZSBhbmQgY2xhc3MgbmVlZHMgdG8gYmUgcmVjb21wdXRlZFxuICAgICAgICB0aGlzLnBvc3RQcm9jZXNzQ3NzKCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5wb3N0UHJvY2Vzc0NzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdHlsZXNGcm9tR3JpZE9wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5wb3N0UHJvY2Vzc0NsYXNzZXNGcm9tR3JpZE9wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5wb3N0UHJvY2Vzc1Jvd0NsYXNzUnVsZXMoKTtcbiAgICAgICAgdGhpcy5wb3N0UHJvY2Vzc1Jvd0RyYWdnaW5nKCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vblJvd05vZGVIaWdobGlnaHRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGlnaGxpZ2h0ZWQgPSB0aGlzLnJvd05vZGUuaGlnaGxpZ2h0ZWQ7XG4gICAgICAgIHRoaXMuYWxsUm93R3Vpcy5mb3JFYWNoKGZ1bmN0aW9uIChndWkpIHtcbiAgICAgICAgICAgIHZhciBhYm92ZU9uID0gaGlnaGxpZ2h0ZWQgPT09IFJvd0hpZ2hsaWdodFBvc2l0aW9uLkFib3ZlO1xuICAgICAgICAgICAgdmFyIGJlbG93T24gPSBoaWdobGlnaHRlZCA9PT0gUm93SGlnaGxpZ2h0UG9zaXRpb24uQmVsb3c7XG4gICAgICAgICAgICBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctaGlnaGxpZ2h0LWFib3ZlJywgYWJvdmVPbik7XG4gICAgICAgICAgICBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctaGlnaGxpZ2h0LWJlbG93JywgYmVsb3dPbik7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25Sb3dOb2RlRHJhZ2dpbmdDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBvc3RQcm9jZXNzUm93RHJhZ2dpbmcoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnBvc3RQcm9jZXNzUm93RHJhZ2dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkcmFnZ2luZyA9IHRoaXMucm93Tm9kZS5kcmFnZ2luZztcbiAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkgeyByZXR1cm4gZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LWRyYWdnaW5nJywgZHJhZ2dpbmcpOyB9KTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnVwZGF0ZUV4cGFuZGVkQ3NzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZXhwYW5kYWJsZSA9IHRoaXMucm93Tm9kZS5pc0V4cGFuZGFibGUoKTtcbiAgICAgICAgdmFyIGV4cGFuZGVkID0gdGhpcy5yb3dOb2RlLmV4cGFuZGVkID09IHRydWU7XG4gICAgICAgIHRoaXMuYWxsUm93R3Vpcy5mb3JFYWNoKGZ1bmN0aW9uIChndWkpIHtcbiAgICAgICAgICAgIGd1aS5yb3dDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLXJvdy1ncm91cCcsIGV4cGFuZGFibGUpO1xuICAgICAgICAgICAgZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LWdyb3VwLWV4cGFuZGVkJywgZXhwYW5kYWJsZSAmJiBleHBhbmRlZCk7XG4gICAgICAgICAgICBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctZ3JvdXAtY29udHJhY3RlZCcsIGV4cGFuZGFibGUgJiYgIWV4cGFuZGVkKTtcbiAgICAgICAgICAgIHNldEFyaWFFeHBhbmRlZChndWkuZWxlbWVudCwgZXhwYW5kYWJsZSAmJiBleHBhbmRlZCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2Ugc2tpcCBhbmltYXRpb25zIGZvciBvbkRpc3BsYXllZENvbHVtbkNoYW5nZWQsIGFzIG90aGVyd2lzZSB0aGUgY2xpZW50IGNvdWxkIHJlbW92ZSBjb2x1bW5zIGFuZFxuICAgICAgICAvLyB0aGVuIHNldCBkYXRhLCBhbmQgYW55IG9sZCB2YWx1ZUdldHRlcidzIChpZSBmcm9tIGNvbHMgdGhhdCB3ZXJlIHJlbW92ZWQpIHdvdWxkIHN0aWxsIGdldCBjYWxsZWQuXG4gICAgICAgIHRoaXMudXBkYXRlQ29sdW1uTGlzdHModHJ1ZSk7XG4gICAgICAgIGlmICh0aGlzLmJlYW5zLmNvbHVtbk1vZGVsLndhc0F1dG9Sb3dIZWlnaHRFdmVyQWN0aXZlKCkpIHtcbiAgICAgICAgICAgIHRoaXMucm93Tm9kZS5jaGVja0F1dG9IZWlnaHRzKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLm9uVmlydHVhbENvbHVtbnNDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUNvbHVtbkxpc3RzKCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRSb3dQb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogbWFrZU51bGwodGhpcy5yb3dOb2RlLnJvd1Bpbm5lZCksXG4gICAgICAgICAgICByb3dJbmRleDogdGhpcy5yb3dOb2RlLnJvd0luZGV4XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vbktleWJvYXJkTmF2aWdhdGUgPSBmdW5jdGlvbiAoa2V5Ym9hcmRFdmVudCkge1xuICAgICAgICB2YXIgY3VycmVudEZ1bGxXaWR0aENvbXAgPSB0aGlzLmFsbFJvd0d1aXMuZmluZChmdW5jdGlvbiAoYykgeyByZXR1cm4gYy5lbGVtZW50LmNvbnRhaW5zKGtleWJvYXJkRXZlbnQudGFyZ2V0KTsgfSk7XG4gICAgICAgIHZhciBjdXJyZW50RnVsbFdpZHRoQ29udGFpbmVyID0gY3VycmVudEZ1bGxXaWR0aENvbXAgPyBjdXJyZW50RnVsbFdpZHRoQ29tcC5lbGVtZW50IDogbnVsbDtcbiAgICAgICAgdmFyIGlzRnVsbFdpZHRoQ29udGFpbmVyRm9jdXNlZCA9IGN1cnJlbnRGdWxsV2lkdGhDb250YWluZXIgPT09IGtleWJvYXJkRXZlbnQudGFyZ2V0O1xuICAgICAgICBpZiAoIWlzRnVsbFdpZHRoQ29udGFpbmVyRm9jdXNlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5yb3dOb2RlO1xuICAgICAgICB2YXIgbGFzdEZvY3VzZWRDZWxsID0gdGhpcy5iZWFucy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNlZENlbGwoKTtcbiAgICAgICAgdmFyIGNlbGxQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgIHJvd0luZGV4OiBub2RlLnJvd0luZGV4LFxuICAgICAgICAgICAgcm93UGlubmVkOiBub2RlLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIGNvbHVtbjogKGxhc3RGb2N1c2VkQ2VsbCAmJiBsYXN0Rm9jdXNlZENlbGwuY29sdW1uKVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmJlYW5zLm5hdmlnYXRpb25TZXJ2aWNlLm5hdmlnYXRlVG9OZXh0Q2VsbChrZXlib2FyZEV2ZW50LCBrZXlib2FyZEV2ZW50LmtleSwgY2VsbFBvc2l0aW9uLCB0cnVlKTtcbiAgICAgICAga2V5Ym9hcmRFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25UYWJLZXlEb3duID0gZnVuY3Rpb24gKGtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgaWYgKGtleWJvYXJkRXZlbnQuZGVmYXVsdFByZXZlbnRlZCB8fCBpc1N0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChrZXlib2FyZEV2ZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjdXJyZW50RnVsbFdpZHRoQ29tcCA9IHRoaXMuYWxsUm93R3Vpcy5maW5kKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjLmVsZW1lbnQuY29udGFpbnMoa2V5Ym9hcmRFdmVudC50YXJnZXQpOyB9KTtcbiAgICAgICAgdmFyIGN1cnJlbnRGdWxsV2lkdGhDb250YWluZXIgPSBjdXJyZW50RnVsbFdpZHRoQ29tcCA/IGN1cnJlbnRGdWxsV2lkdGhDb21wLmVsZW1lbnQgOiBudWxsO1xuICAgICAgICB2YXIgaXNGdWxsV2lkdGhDb250YWluZXJGb2N1c2VkID0gY3VycmVudEZ1bGxXaWR0aENvbnRhaW5lciA9PT0ga2V5Ym9hcmRFdmVudC50YXJnZXQ7XG4gICAgICAgIHZhciBuZXh0RWwgPSBudWxsO1xuICAgICAgICBpZiAoIWlzRnVsbFdpZHRoQ29udGFpbmVyRm9jdXNlZCkge1xuICAgICAgICAgICAgbmV4dEVsID0gdGhpcy5iZWFucy5mb2N1c1NlcnZpY2UuZmluZE5leHRGb2N1c2FibGVFbGVtZW50KGN1cnJlbnRGdWxsV2lkdGhDb250YWluZXIsIGZhbHNlLCBrZXlib2FyZEV2ZW50LnNoaWZ0S2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKHRoaXMuaXNGdWxsV2lkdGgoKSAmJiBpc0Z1bGxXaWR0aENvbnRhaW5lckZvY3VzZWQpIHx8ICFuZXh0RWwpIHtcbiAgICAgICAgICAgIHRoaXMuYmVhbnMubmF2aWdhdGlvblNlcnZpY2Uub25UYWJLZXlEb3duKHRoaXMsIGtleWJvYXJkRXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vbkZ1bGxXaWR0aFJvd0ZvY3VzZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgbm9kZSA9IHRoaXMucm93Tm9kZTtcbiAgICAgICAgdmFyIGlzRm9jdXNlZCA9IHRoaXMuaXNGdWxsV2lkdGgoKSAmJiBldmVudC5yb3dJbmRleCA9PT0gbm9kZS5yb3dJbmRleCAmJiBldmVudC5yb3dQaW5uZWQgPT0gbm9kZS5yb3dQaW5uZWQ7XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5mdWxsV2lkdGhHdWkgPyB0aGlzLmZ1bGxXaWR0aEd1aS5lbGVtZW50IDogKF9hID0gdGhpcy5jZW50ZXJHdWkpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5lbGVtZW50O1xuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSAvLyBjYW4gaGFwcGVuIHdpdGggcmVhY3QgdWksIGNvbXAgbm90IHlldCByZWFkeVxuICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoJ2FnLWZ1bGwtd2lkdGgtZm9jdXMnLCBpc0ZvY3VzZWQpO1xuICAgICAgICBpZiAoaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICAvLyB3ZSBkb24ndCBzY3JvbGwgbm9ybWFsIHJvd3MgaW50byB2aWV3IHdoZW4gd2UgZm9jdXMgdGhlbSwgc28gd2UgZG9uJ3Qgd2FudFxuICAgICAgICAgICAgLy8gdG8gc2Nyb2xsIEZ1bGwgV2lkdGggcm93cyBlaXRoZXIuXG4gICAgICAgICAgICBlbGVtZW50LmZvY3VzKHsgcHJldmVudFNjcm9sbDogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUucmVmcmVzaENlbGwgPSBmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgdGhpcy5jZW50ZXJDZWxsQ3RybHMgPSB0aGlzLnJlbW92ZUNlbGxDdHJsKHRoaXMuY2VudGVyQ2VsbEN0cmxzLCBjZWxsQ3RybCk7XG4gICAgICAgIHRoaXMubGVmdENlbGxDdHJscyA9IHRoaXMucmVtb3ZlQ2VsbEN0cmwodGhpcy5sZWZ0Q2VsbEN0cmxzLCBjZWxsQ3RybCk7XG4gICAgICAgIHRoaXMucmlnaHRDZWxsQ3RybHMgPSB0aGlzLnJlbW92ZUNlbGxDdHJsKHRoaXMucmlnaHRDZWxsQ3RybHMsIGNlbGxDdHJsKTtcbiAgICAgICAgdGhpcy51cGRhdGVDb2x1bW5MaXN0cygpO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUucmVtb3ZlQ2VsbEN0cmwgPSBmdW5jdGlvbiAocHJldiwgY2VsbEN0cmxUb1JlbW92ZSkge1xuICAgICAgICB2YXIgcmVzID0ge1xuICAgICAgICAgICAgbGlzdDogW10sXG4gICAgICAgICAgICBtYXA6IHt9XG4gICAgICAgIH07XG4gICAgICAgIHByZXYubGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkge1xuICAgICAgICAgICAgaWYgKGNlbGxDdHJsID09PSBjZWxsQ3RybFRvUmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzLmxpc3QucHVzaChjZWxsQ3RybCk7XG4gICAgICAgICAgICByZXMubWFwW2NlbGxDdHJsLmdldEluc3RhbmNlSWQoKV0gPSBjZWxsQ3RybDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vbk1vdXNlRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnROYW1lLCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIHN3aXRjaCAoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICBjYXNlICdkYmxjbGljayc6XG4gICAgICAgICAgICAgICAgdGhpcy5vblJvd0RibENsaWNrKG1vdXNlRXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnY2xpY2snOlxuICAgICAgICAgICAgICAgIHRoaXMub25Sb3dDbGljayhtb3VzZUV2ZW50KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3RvdWNoc3RhcnQnOlxuICAgICAgICAgICAgY2FzZSAnbW91c2Vkb3duJzpcbiAgICAgICAgICAgICAgICB0aGlzLm9uUm93TW91c2VEb3duKG1vdXNlRXZlbnQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5jcmVhdGVSb3dFdmVudCA9IGZ1bmN0aW9uICh0eXBlLCBkb21FdmVudCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdHlwZTogdHlwZSxcbiAgICAgICAgICAgIG5vZGU6IHRoaXMucm93Tm9kZSxcbiAgICAgICAgICAgIGRhdGE6IHRoaXMucm93Tm9kZS5kYXRhLFxuICAgICAgICAgICAgcm93SW5kZXg6IHRoaXMucm93Tm9kZS5yb3dJbmRleCxcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogdGhpcy5yb3dOb2RlLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKSxcbiAgICAgICAgICAgIGFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgZXZlbnQ6IGRvbUV2ZW50XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5jcmVhdGVSb3dFdmVudFdpdGhTb3VyY2UgPSBmdW5jdGlvbiAodHlwZSwgZG9tRXZlbnQpIHtcbiAgICAgICAgdmFyIGV2ZW50ID0gdGhpcy5jcmVhdGVSb3dFdmVudCh0eXBlLCBkb21FdmVudCk7XG4gICAgICAgIC8vIHdoZW4gZmlyc3QgZGV2ZWxvcGluZyB0aGlzLCB3ZSBpbmNsdWRlZCB0aGUgcm93Q29tcCBpbiB0aGUgZXZlbnQuXG4gICAgICAgIC8vIHRoaXMgc2VlbXMgdmVyeSB3ZWlyZC4gc28gd2hlbiBpbnRyb2R1Y2luZyB0aGUgZXZlbnQgdHlwZXMsIGkgbGVmdCB0aGUgJ3NvdXJjZSdcbiAgICAgICAgLy8gb3V0IG9mIHRoZSB0eXBlLCBhbmQganVzdCBpbmNsdWRlIHRoZSBzb3VyY2UgaW4gdGhlIHR3byBwbGFjZXMgd2hlcmUgdGhpcyBldmVudFxuICAgICAgICAvLyB3YXMgZmlyZWQgKHJvd0NsaWNrZWQgYW5kIHJvd0RvdWJsZUNsaWNrZWQpLiBpdCBkb2Vzbid0IG1ha2Ugc2Vuc2UgZm9yIGFueVxuICAgICAgICAvLyB1c2VycyB0byBiZSB1c2luZyB0aGlzLCBhcyB0aGUgcm93Q29tcCBpc24ndCBhbiBvYmplY3Qgd2UgZXhwb3NlLCBzbyB3b3VsZCBiZVxuICAgICAgICAvLyB2ZXJ5IHN1cnByaXNpbmcgaWYgYSB1c2VyIHdhcyB1c2luZyBpdC5cbiAgICAgICAgZXZlbnQuc291cmNlID0gdGhpcztcbiAgICAgICAgcmV0dXJuIGV2ZW50O1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25Sb3dEYmxDbGljayA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmIChpc1N0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChtb3VzZUV2ZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhZ0V2ZW50ID0gdGhpcy5jcmVhdGVSb3dFdmVudFdpdGhTb3VyY2UoRXZlbnRzLkVWRU5UX1JPV19ET1VCTEVfQ0xJQ0tFRCwgbW91c2VFdmVudCk7XG4gICAgICAgIHRoaXMuYmVhbnMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoYWdFdmVudCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vblJvd01vdXNlRG93biA9IGZ1bmN0aW9uIChtb3VzZUV2ZW50KSB7XG4gICAgICAgIHRoaXMubGFzdE1vdXNlRG93bk9uRHJhZ2dlciA9IGlzRWxlbWVudENoaWxkT2ZDbGFzcyhtb3VzZUV2ZW50LnRhcmdldCwgJ2FnLXJvdy1kcmFnJywgMyk7XG4gICAgICAgIGlmICghdGhpcy5pc0Z1bGxXaWR0aCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLnJvd05vZGU7XG4gICAgICAgIHZhciBjb2x1bW5Nb2RlbCA9IHRoaXMuYmVhbnMuY29sdW1uTW9kZWw7XG4gICAgICAgIGlmICh0aGlzLmJlYW5zLnJhbmdlU2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5iZWFucy5yYW5nZVNlcnZpY2UucmVtb3ZlQWxsQ2VsbFJhbmdlcygpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYmVhbnMuZm9jdXNTZXJ2aWNlLnNldEZvY3VzZWRDZWxsKHtcbiAgICAgICAgICAgIHJvd0luZGV4OiBub2RlLnJvd0luZGV4LFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKClbMF0sXG4gICAgICAgICAgICByb3dQaW5uZWQ6IG5vZGUucm93UGlubmVkLFxuICAgICAgICAgICAgZm9yY2VCcm93c2VyRm9jdXM6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vblJvd0NsaWNrID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQpIHtcbiAgICAgICAgdmFyIHN0b3AgPSBpc1N0b3BQcm9wYWdhdGlvbkZvckFnR3JpZChtb3VzZUV2ZW50KSB8fCB0aGlzLmxhc3RNb3VzZURvd25PbkRyYWdnZXI7XG4gICAgICAgIGlmIChzdG9wKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFnRXZlbnQgPSB0aGlzLmNyZWF0ZVJvd0V2ZW50V2l0aFNvdXJjZShFdmVudHMuRVZFTlRfUk9XX0NMSUNLRUQsIG1vdXNlRXZlbnQpO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGFnRXZlbnQpO1xuICAgICAgICAvLyBjdHJsS2V5IGZvciB3aW5kb3dzLCBtZXRhS2V5IGZvciBBcHBsZVxuICAgICAgICB2YXIgbXVsdGlTZWxlY3RLZXlQcmVzc2VkID0gbW91c2VFdmVudC5jdHJsS2V5IHx8IG1vdXNlRXZlbnQubWV0YUtleTtcbiAgICAgICAgdmFyIHNoaWZ0S2V5UHJlc3NlZCA9IG1vdXNlRXZlbnQuc2hpZnRLZXk7XG4gICAgICAgIC8vIHdlIGRvIG5vdCBhbGxvdyBzZWxlY3RpbmcgdGhlIGdyb3VwIGJ5IGNsaWNraW5nLCB3aGVuIGdyb3VwU2VsZWN0Q2hpbGRyZW4sIGFzIHRoZSBsb2dpYyB0b1xuICAgICAgICAvLyBoYW5kbGUgdGhpcyBpcyBicm9rZW4uIHRvIG9ic2VydmUsIGNoYW5nZSB0aGUgbG9naWMgYmVsb3cgYW5kIGFsbG93IGdyb3VwcyB0byBiZSBzZWxlY3RlZC5cbiAgICAgICAgLy8geW91IHdpbGwgc2VlIHRoZSBncm91cCBnZXRzIHNlbGVjdGVkLCB0aGVuIGFsbCBjaGlsZHJlbiBnZXQgc2VsZWN0ZWQsIHRoZW4gdGhlIGdyaWQgdW5zZWxlY3RzXG4gICAgICAgIC8vIHRoZSBjaGlsZHJlbiAoYXMgdGhlIGRlZmF1bHQgYmVoYXZpb3VyIHdoZW4gY2xpY2tpbmcgaXMgdG8gdW5zZWxlY3Qgb3RoZXIgcm93cykgd2hpY2ggcmVzdWx0c1xuICAgICAgICAvLyBpbiB0aGUgZ3JvdXAgZ2V0dGluZyB1bnNlbGVjdGVkIChhcyBhbGwgY2hpbGRyZW4gYXJlIHVuc2VsZWN0ZWQpLiB0aGUgY29ycmVjdCB0aGluZyB3b3VsZCBiZVxuICAgICAgICAvLyB0byBjaGFuZ2UgdGhpcywgc28gdGhhdCBjaGlsZHJlbiBvZiB0aGUgc2VsZWN0ZWQgZ3JvdXAgYXJlIG5vdCB0aGVuIHN1YnNlcXVlbmx5IHVuLXNlbGVjdGVkLlxuICAgICAgICB2YXIgZ3JvdXBTZWxlY3RzQ2hpbGRyZW4gPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU2VsZWN0c0NoaWxkcmVuKCk7XG4gICAgICAgIGlmIChcbiAgICAgICAgLy8gd2UgZG8gbm90IGFsbG93IHNlbGVjdGluZyBncm91cHMgYnkgY2xpY2tpbmcgKGFzIHRoZSBjbGljayBoZXJlIGV4cGFuZHMgdGhlIGdyb3VwKSwgb3IgaWYgaXQncyBhIGRldGFpbCByb3csXG4gICAgICAgIC8vIHNvIHJldHVybiBpZiBpdCdzIGEgZ3JvdXAgcm93XG4gICAgICAgIChncm91cFNlbGVjdHNDaGlsZHJlbiAmJiB0aGlzLnJvd05vZGUuZ3JvdXApIHx8XG4gICAgICAgICAgICAvLyB0aGlzIGlzIG5lZWRlZCBzbyB3ZSBkb24ndCB1bnNlbGVjdCBvdGhlciByb3dzIHdoZW4gd2UgY2xpY2sgdGhpcyByb3csIGVnIGlmIHRoaXMgcm93IGlzIG5vdCBzZWxlY3RhYmxlLFxuICAgICAgICAgICAgLy8gYW5kIHdlIGNsaWNrIGl0LCB0aGUgc2VsZWN0aW9uIHNob3VsZCBub3QgY2hhbmdlIChpZSBhbnkgY3VycmVudGx5IHNlbGVjdGVkIHJvdyBzaG91bGQgc3RheSBzZWxlY3RlZClcbiAgICAgICAgICAgICF0aGlzLnJvd05vZGUuc2VsZWN0YWJsZSB8fFxuICAgICAgICAgICAgLy8gd2UgYWxzbyBkb24ndCBhbGxvdyBzZWxlY3Rpb24gb2YgcGlubmVkIHJvd3NcbiAgICAgICAgICAgIHRoaXMucm93Tm9kZS5yb3dQaW5uZWQgfHxcbiAgICAgICAgICAgIC8vIGlmIG5vIHNlbGVjdGlvbiBtZXRob2QgZW5hYmxlZCwgZG8gbm90aGluZ1xuICAgICAgICAgICAgIXRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93U2VsZWN0aW9uKCkgfHxcbiAgICAgICAgICAgIC8vIGlmIGNsaWNrIHNlbGVjdGlvbiBzdXBwcmVzc2VkLCBkbyBub3RoaW5nXG4gICAgICAgICAgICB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzUm93Q2xpY2tTZWxlY3Rpb24oKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtdWx0aVNlbGVjdE9uQ2xpY2sgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd011bHRpU2VsZWN0V2l0aENsaWNrKCk7XG4gICAgICAgIHZhciByb3dEZXNlbGVjdGlvbldpdGhDdHJsID0gIXRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NSb3dEZXNlbGVjdGlvbigpO1xuICAgICAgICBpZiAodGhpcy5yb3dOb2RlLmlzU2VsZWN0ZWQoKSkge1xuICAgICAgICAgICAgaWYgKG11bHRpU2VsZWN0T25DbGljaykge1xuICAgICAgICAgICAgICAgIHRoaXMucm93Tm9kZS5zZXRTZWxlY3RlZFBhcmFtcyh7IG5ld1ZhbHVlOiBmYWxzZSwgZXZlbnQ6IG1vdXNlRXZlbnQgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChtdWx0aVNlbGVjdEtleVByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAocm93RGVzZWxlY3Rpb25XaXRoQ3RybCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoeyBuZXdWYWx1ZTogZmFsc2UsIGV2ZW50OiBtb3VzZUV2ZW50IH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHNlbGVjdGVkIHdpdGggbm8gbXVsdGkga2V5LCBtdXN0IG1ha2Ugc3VyZSBhbnl0aGluZyBlbHNlIGlzIHVuc2VsZWN0ZWRcbiAgICAgICAgICAgICAgICB0aGlzLnJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoeyBuZXdWYWx1ZTogdHJ1ZSwgY2xlYXJTZWxlY3Rpb246ICFzaGlmdEtleVByZXNzZWQsIHJhbmdlU2VsZWN0OiBzaGlmdEtleVByZXNzZWQsIGV2ZW50OiBtb3VzZUV2ZW50IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGNsZWFyU2VsZWN0aW9uID0gbXVsdGlTZWxlY3RPbkNsaWNrID8gZmFsc2UgOiAhbXVsdGlTZWxlY3RLZXlQcmVzc2VkO1xuICAgICAgICAgICAgdGhpcy5yb3dOb2RlLnNldFNlbGVjdGVkUGFyYW1zKHsgbmV3VmFsdWU6IHRydWUsIGNsZWFyU2VsZWN0aW9uOiBjbGVhclNlbGVjdGlvbiwgcmFuZ2VTZWxlY3Q6IHNoaWZ0S2V5UHJlc3NlZCwgZXZlbnQ6IG1vdXNlRXZlbnQgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnNldHVwRGV0YWlsUm93QXV0b0hlaWdodCA9IGZ1bmN0aW9uIChlRGV0YWlsR3VpKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLnJvd1R5cGUgIT09IFJvd1R5cGUkMS5GdWxsV2lkdGhEZXRhaWwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRGV0YWlsUm93QXV0b0hlaWdodCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNoZWNrUm93U2l6ZUZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgY2xpZW50SGVpZ2h0ID0gZURldGFpbEd1aS5jbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICAvLyBpZiB0aGUgVUkgaXMgbm90IHJlYWR5LCB0aGUgaGVpZ2h0IGNhbiBiZSAwLCB3aGljaCB3ZSBpZ25vcmUsIGFzIG90aGVyd2lzZSBhIGZsaWNrZXIgd2lsbCBvY2N1clxuICAgICAgICAgICAgLy8gYXMgVUkgZ29lcyBmcm9tIHRoZSBkZWZhdWx0IGhlaWdodCwgdG8gMCwgdGhlbiB0byB0aGUgcmVhbCBoZWlnaHQgYXMgVUkgYmVjb21lcyByZWFkeS4gdGhpcyBtZWFuc1xuICAgICAgICAgICAgLy8gaXQncyBub3QgcG9zc2libGUgZm9yIGhhdmUgMCBhcyBhdXRvLWhlaWdodCwgaG93ZXZlciB0aGlzIGlzIGFuIGltcHJvYmFibGUgdXNlIGNhc2UsIGFzIGV2ZW4gYW5cbiAgICAgICAgICAgIC8vIGVtcHR5IGRldGFpbCBncmlkIHdvdWxkIHN0aWxsIGhhdmUgc29tZSBzdHlsaW5nIGFyb3VuZCBpdCBnaXZpbmcgYXQgbGVhc3QgYSBmZXcgcGl4ZWxzLlxuICAgICAgICAgICAgaWYgKGNsaWVudEhlaWdodCAhPSBudWxsICYmIGNsaWVudEhlaWdodCA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSBkbyB0aGUgdXBkYXRlIGluIGEgdGltZW91dCwgdG8gbWFrZSBzdXJlIHdlIGFyZSBub3QgY2FsbGluZyBmcm9tIGluc2lkZSB0aGUgZ3JpZFxuICAgICAgICAgICAgICAgIC8vIGRvaW5nIGFub3RoZXIgdXBkYXRlXG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0ZVJvd0hlaWdodEZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnJvd05vZGUuc2V0Um93SGVpZ2h0KGNsaWVudEhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5iZWFucy5jbGllbnRTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmJlYW5zLmNsaWVudFNpZGVSb3dNb2RlbC5vblJvd0hlaWdodENoYW5nZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfdGhpcy5iZWFucy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmJlYW5zLnNlcnZlclNpZGVSb3dNb2RlbC5vblJvd0hlaWdodENoYW5nZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgX3RoaXMuYmVhbnMuZnJhbWV3b3JrT3ZlcnJpZGVzLnNldFRpbWVvdXQodXBkYXRlUm93SGVpZ2h0RnVuYywgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciByZXNpemVPYnNlcnZlckRlc3Ryb3lGdW5jID0gdGhpcy5iZWFucy5yZXNpemVPYnNlcnZlclNlcnZpY2Uub2JzZXJ2ZVJlc2l6ZShlRGV0YWlsR3VpLCBjaGVja1Jvd1NpemVGdW5jKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhyZXNpemVPYnNlcnZlckRlc3Ryb3lGdW5jKTtcbiAgICAgICAgY2hlY2tSb3dTaXplRnVuYygpO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuY3JlYXRlRnVsbFdpZHRoUGFyYW1zID0gZnVuY3Rpb24gKGVSb3csIHBpbm5lZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgZnVsbFdpZHRoOiB0cnVlLFxuICAgICAgICAgICAgZGF0YTogdGhpcy5yb3dOb2RlLmRhdGEsXG4gICAgICAgICAgICBub2RlOiB0aGlzLnJvd05vZGUsXG4gICAgICAgICAgICB2YWx1ZTogdGhpcy5yb3dOb2RlLmtleSxcbiAgICAgICAgICAgIHZhbHVlRm9ybWF0dGVkOiB0aGlzLnJvd05vZGUua2V5LFxuICAgICAgICAgICAgcm93SW5kZXg6IHRoaXMucm93Tm9kZS5yb3dJbmRleCxcbiAgICAgICAgICAgIGFwaTogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICAgICAgLy8gdGhlc2UgbmVlZCB0byBiZSB0YWtlbiBvdXQsIGFzIHBhcnQgb2YgJ2FmdGVyQXR0YWNoZWQnIG5vd1xuICAgICAgICAgICAgZUdyaWRDZWxsOiBlUm93LFxuICAgICAgICAgICAgZVBhcmVudE9mVmFsdWU6IGVSb3csXG4gICAgICAgICAgICBwaW5uZWQ6IHBpbm5lZCxcbiAgICAgICAgICAgIGFkZFJlbmRlcmVkUm93TGlzdGVuZXI6IHRoaXMuYWRkRXZlbnRMaXN0ZW5lci5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgcmVnaXN0ZXJSb3dEcmFnZ2VyOiBmdW5jdGlvbiAocm93RHJhZ2dlckVsZW1lbnQsIGRyYWdTdGFydFBpeGVscywgdmFsdWUsIHN1cHByZXNzVmlzaWJpbGl0eUNoYW5nZSkgeyByZXR1cm4gX3RoaXMuYWRkRnVsbFdpZHRoUm93RHJhZ2dpbmcocm93RHJhZ2dlckVsZW1lbnQsIGRyYWdTdGFydFBpeGVscywgdmFsdWUsIHN1cHByZXNzVmlzaWJpbGl0eUNoYW5nZSk7IH1cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmFkZEZ1bGxXaWR0aFJvd0RyYWdnaW5nID0gZnVuY3Rpb24gKHJvd0RyYWdnZXJFbGVtZW50LCBkcmFnU3RhcnRQaXhlbHMsIHZhbHVlLCBzdXBwcmVzc1Zpc2liaWxpdHlDaGFuZ2UpIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSB2b2lkIDApIHsgdmFsdWUgPSAnJzsgfVxuICAgICAgICBpZiAoIXRoaXMuaXNGdWxsV2lkdGgoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dEcmFnQ29tcCA9IG5ldyBSb3dEcmFnQ29tcChmdW5jdGlvbiAoKSB7IHJldHVybiB2YWx1ZTsgfSwgdGhpcy5yb3dOb2RlLCB1bmRlZmluZWQsIHJvd0RyYWdnZXJFbGVtZW50LCBkcmFnU3RhcnRQaXhlbHMsIHN1cHByZXNzVmlzaWJpbGl0eUNoYW5nZSk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4ocm93RHJhZ0NvbXAsIHRoaXMuYmVhbnMuY29udGV4dCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vblVpTGV2ZWxDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbmV3TGV2ZWwgPSB0aGlzLmJlYW5zLnJvd0Nzc0NsYXNzQ2FsY3VsYXRvci5jYWxjdWxhdGVSb3dMZXZlbCh0aGlzLnJvd05vZGUpO1xuICAgICAgICBpZiAodGhpcy5yb3dMZXZlbCAhPSBuZXdMZXZlbCkge1xuICAgICAgICAgICAgdmFyIGNsYXNzVG9BZGRfMSA9ICdhZy1yb3ctbGV2ZWwtJyArIG5ld0xldmVsO1xuICAgICAgICAgICAgdmFyIGNsYXNzVG9SZW1vdmVfMSA9ICdhZy1yb3ctbGV2ZWwtJyArIHRoaXMucm93TGV2ZWw7XG4gICAgICAgICAgICB0aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAoZ3VpKSB7XG4gICAgICAgICAgICAgICAgZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhjbGFzc1RvQWRkXzEsIHRydWUpO1xuICAgICAgICAgICAgICAgIGd1aS5yb3dDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoY2xhc3NUb1JlbW92ZV8xLCBmYWxzZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd0xldmVsID0gbmV3TGV2ZWw7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5pc0ZpcnN0Um93T25QYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dOb2RlLnJvd0luZGV4ID09PSB0aGlzLmJlYW5zLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlRmlyc3RSb3coKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmlzTGFzdFJvd09uUGFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93Tm9kZS5yb3dJbmRleCA9PT0gdGhpcy5iZWFucy5wYWdpbmF0aW9uUHJveHkuZ2V0UGFnZUxhc3RSb3coKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLm9uTW9kZWxVcGRhdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlZnJlc2hGaXJzdEFuZExhc3RSb3dTdHlsZXMoKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnJlZnJlc2hGaXJzdEFuZExhc3RSb3dTdHlsZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBuZXdGaXJzdCA9IHRoaXMuaXNGaXJzdFJvd09uUGFnZSgpO1xuICAgICAgICB2YXIgbmV3TGFzdCA9IHRoaXMuaXNMYXN0Um93T25QYWdlKCk7XG4gICAgICAgIGlmICh0aGlzLmZpcnN0Um93T25QYWdlICE9PSBuZXdGaXJzdCkge1xuICAgICAgICAgICAgdGhpcy5maXJzdFJvd09uUGFnZSA9IG5ld0ZpcnN0O1xuICAgICAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkgeyByZXR1cm4gZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LWZpcnN0JywgbmV3Rmlyc3QpOyB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5sYXN0Um93T25QYWdlICE9PSBuZXdMYXN0KSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RSb3dPblBhZ2UgPSBuZXdMYXN0O1xuICAgICAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkgeyByZXR1cm4gZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LWxhc3QnLCBuZXdMYXN0KTsgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnN0b3BFZGl0aW5nID0gZnVuY3Rpb24gKGNhbmNlbCkge1xuICAgICAgICB2YXIgZV8xLCBfYTtcbiAgICAgICAgaWYgKGNhbmNlbCA9PT0gdm9pZCAwKSB7IGNhbmNlbCA9IGZhbHNlOyB9XG4gICAgICAgIC8vIGlmIHdlIGFyZSBhbHJlYWR5IHN0b3BwaW5nIHJvdyBlZGl0LCB0aGVyZSBpc1xuICAgICAgICAvLyBubyBuZWVkIHRvIHN0YXJ0IHRoaXMgcHJvY2VzcyBhZ2Fpbi5cbiAgICAgICAgaWYgKHRoaXMuc3RvcHBpbmdSb3dFZGl0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNlbGxDb250cm9scyA9IHRoaXMuZ2V0QWxsQ2VsbEN0cmxzKCk7XG4gICAgICAgIHZhciBpc1Jvd0VkaXQgPSB0aGlzLmVkaXRpbmdSb3c7XG4gICAgICAgIHRoaXMuc3RvcHBpbmdSb3dFZGl0ID0gdHJ1ZTtcbiAgICAgICAgdmFyIGZpcmVSb3dFZGl0RXZlbnQgPSBmYWxzZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZvciAodmFyIGNlbGxDb250cm9sc18xID0gX192YWx1ZXMkMihjZWxsQ29udHJvbHMpLCBjZWxsQ29udHJvbHNfMV8xID0gY2VsbENvbnRyb2xzXzEubmV4dCgpOyAhY2VsbENvbnRyb2xzXzFfMS5kb25lOyBjZWxsQ29udHJvbHNfMV8xID0gY2VsbENvbnRyb2xzXzEubmV4dCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGN0cmwgPSBjZWxsQ29udHJvbHNfMV8xLnZhbHVlO1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZUNoYW5nZWQgPSBjdHJsLnN0b3BFZGl0aW5nKGNhbmNlbCk7XG4gICAgICAgICAgICAgICAgaWYgKGlzUm93RWRpdCAmJiAhY2FuY2VsICYmICFmaXJlUm93RWRpdEV2ZW50ICYmIHZhbHVlQ2hhbmdlZCkge1xuICAgICAgICAgICAgICAgICAgICBmaXJlUm93RWRpdEV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVfMV8xKSB7IGVfMSA9IHsgZXJyb3I6IGVfMV8xIH07IH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChjZWxsQ29udHJvbHNfMV8xICYmICFjZWxsQ29udHJvbHNfMV8xLmRvbmUgJiYgKF9hID0gY2VsbENvbnRyb2xzXzEucmV0dXJuKSkgX2EuY2FsbChjZWxsQ29udHJvbHNfMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHsgaWYgKGVfMSkgdGhyb3cgZV8xLmVycm9yOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZpcmVSb3dFZGl0RXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBldmVudF8xID0gdGhpcy5jcmVhdGVSb3dFdmVudChFdmVudHMuRVZFTlRfUk9XX1ZBTFVFX0NIQU5HRUQpO1xuICAgICAgICAgICAgdGhpcy5iZWFucy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNSb3dFZGl0KSB7XG4gICAgICAgICAgICB0aGlzLnNldEVkaXRpbmdSb3coZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RvcHBpbmdSb3dFZGl0ID0gZmFsc2U7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRJbmxpbmVFZGl0aW5nQ3NzID0gZnVuY3Rpb24gKGVkaXRpbmcpIHtcbiAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkge1xuICAgICAgICAgICAgZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhcImFnLXJvdy1pbmxpbmUtZWRpdGluZ1wiLCBlZGl0aW5nKTtcbiAgICAgICAgICAgIGd1aS5yb3dDb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoXCJhZy1yb3ctbm90LWlubGluZS1lZGl0aW5nXCIsICFlZGl0aW5nKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRFZGl0aW5nUm93ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuZWRpdGluZ1JvdyA9IHZhbHVlO1xuICAgICAgICB0aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAoZ3VpKSB7IHJldHVybiBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctZWRpdGluZycsIHZhbHVlKTsgfSk7XG4gICAgICAgIHZhciBldmVudCA9IHZhbHVlID9cbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUm93RXZlbnQoRXZlbnRzLkVWRU5UX1JPV19FRElUSU5HX1NUQVJURUQpXG4gICAgICAgICAgICA6IHRoaXMuY3JlYXRlUm93RXZlbnQoRXZlbnRzLkVWRU5UX1JPV19FRElUSU5HX1NUT1BQRUQpO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnN0YXJ0Um93RWRpdGluZyA9IGZ1bmN0aW9uIChrZXksIGNoYXJQcmVzcywgc291cmNlUmVuZGVyZWRDZWxsLCBldmVudCkge1xuICAgICAgICBpZiAoa2V5ID09PSB2b2lkIDApIHsga2V5ID0gbnVsbDsgfVxuICAgICAgICBpZiAoY2hhclByZXNzID09PSB2b2lkIDApIHsgY2hhclByZXNzID0gbnVsbDsgfVxuICAgICAgICBpZiAoc291cmNlUmVuZGVyZWRDZWxsID09PSB2b2lkIDApIHsgc291cmNlUmVuZGVyZWRDZWxsID0gbnVsbDsgfVxuICAgICAgICBpZiAoZXZlbnQgPT09IHZvaWQgMCkgeyBldmVudCA9IG51bGw7IH1cbiAgICAgICAgLy8gZG9uJ3QgZG8gaXQgaWYgYWxyZWFkeSBlZGl0aW5nXG4gICAgICAgIGlmICh0aGlzLmVkaXRpbmdSb3cpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYXRMZWFzdE9uZUVkaXRpbmcgPSB0aGlzLmdldEFsbENlbGxDdHJscygpLnJlZHVjZShmdW5jdGlvbiAocHJldiwgY2VsbEN0cmwpIHtcbiAgICAgICAgICAgIHZhciBjZWxsU3RhcnRlZEVkaXQgPSBjZWxsQ3RybCA9PT0gc291cmNlUmVuZGVyZWRDZWxsO1xuICAgICAgICAgICAgaWYgKGNlbGxTdGFydGVkRWRpdCkge1xuICAgICAgICAgICAgICAgIGNlbGxDdHJsLnN0YXJ0RWRpdGluZyhrZXksIGNoYXJQcmVzcywgY2VsbFN0YXJ0ZWRFZGl0LCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjZWxsQ3RybC5zdGFydEVkaXRpbmcobnVsbCwgbnVsbCwgY2VsbFN0YXJ0ZWRFZGl0LCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJldikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNlbGxDdHJsLmlzRWRpdGluZygpO1xuICAgICAgICB9LCBmYWxzZSk7XG4gICAgICAgIGlmIChhdExlYXN0T25lRWRpdGluZykge1xuICAgICAgICAgICAgdGhpcy5zZXRFZGl0aW5nUm93KHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRBbGxDZWxsQ3RybHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXMgPSBfX3NwcmVhZCRkKHRoaXMuY2VudGVyQ2VsbEN0cmxzLmxpc3QsIHRoaXMubGVmdENlbGxDdHJscy5saXN0LCB0aGlzLnJpZ2h0Q2VsbEN0cmxzLmxpc3QpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUucG9zdFByb2Nlc3NDbGFzc2VzRnJvbUdyaWRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY3NzQ2xhc3NlcyA9IHRoaXMuYmVhbnMucm93Q3NzQ2xhc3NDYWxjdWxhdG9yLnByb2Nlc3NDbGFzc2VzRnJvbUdyaWRPcHRpb25zKHRoaXMucm93Tm9kZSk7XG4gICAgICAgIGlmICghY3NzQ2xhc3NlcyB8fCAhY3NzQ2xhc3Nlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjc3NDbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKGNsYXNzU3RyKSB7XG4gICAgICAgICAgICBfdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGMucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKGNsYXNzU3RyLCB0cnVlKTsgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUucG9zdFByb2Nlc3NSb3dDbGFzc1J1bGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmJlYW5zLnJvd0Nzc0NsYXNzQ2FsY3VsYXRvci5wcm9jZXNzUm93Q2xhc3NSdWxlcyh0aGlzLnJvd05vZGUsIGZ1bmN0aW9uIChjbGFzc05hbWUpIHtcbiAgICAgICAgICAgIF90aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAoZ3VpKSB7IHJldHVybiBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKGNsYXNzTmFtZSwgdHJ1ZSk7IH0pO1xuICAgICAgICB9LCBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICBfdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkgeyByZXR1cm4gZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhjbGFzc05hbWUsIGZhbHNlKTsgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuc2V0U3R5bGVzRnJvbUdyaWRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93U3R5bGVzID0gdGhpcy5wcm9jZXNzU3R5bGVzRnJvbUdyaWRPcHRpb25zKCk7XG4gICAgICAgIHRoaXMuYWxsUm93R3Vpcy5mb3JFYWNoKGZ1bmN0aW9uIChndWkpIHsgcmV0dXJuIGd1aS5yb3dDb21wLnNldFVzZXJTdHlsZXMocm93U3R5bGVzKTsgfSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRSb3dCdXNpbmVzc0tleSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGJ1c2luZXNzS2V5Rm9yTm9kZUZ1bmMgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRCdXNpbmVzc0tleUZvck5vZGVGdW5jKCk7XG4gICAgICAgIGlmICh0eXBlb2YgYnVzaW5lc3NLZXlGb3JOb2RlRnVuYyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBidXNpbmVzc0tleUZvck5vZGVGdW5jKHRoaXMucm93Tm9kZSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRQaW5uZWRGb3JDb250YWluZXIgPSBmdW5jdGlvbiAocm93Q29udGFpbmVyVHlwZSkge1xuICAgICAgICB2YXIgcGlubmVkID0gcm93Q29udGFpbmVyVHlwZSA9PT0gUm93Q29udGFpbmVyVHlwZS5MRUZUXG4gICAgICAgICAgICA/IENvbnN0YW50cy5QSU5ORURfTEVGVFxuICAgICAgICAgICAgOiByb3dDb250YWluZXJUeXBlID09PSBSb3dDb250YWluZXJUeXBlLlJJR0hUXG4gICAgICAgICAgICAgICAgPyBDb25zdGFudHMuUElOTkVEX1JJR0hUXG4gICAgICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICByZXR1cm4gcGlubmVkO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuZ2V0SW5pdGlhbFJvd0NsYXNzZXMgPSBmdW5jdGlvbiAocm93Q29udGFpbmVyVHlwZSkge1xuICAgICAgICB2YXIgcGlubmVkID0gdGhpcy5nZXRQaW5uZWRGb3JDb250YWluZXIocm93Q29udGFpbmVyVHlwZSk7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICByb3dOb2RlOiB0aGlzLnJvd05vZGUsXG4gICAgICAgICAgICByb3dGb2N1c2VkOiB0aGlzLnJvd0ZvY3VzZWQsXG4gICAgICAgICAgICBmYWRlUm93SW46IHRoaXMuZmFkZVJvd0luLFxuICAgICAgICAgICAgcm93SXNFdmVuOiB0aGlzLnJvd05vZGUucm93SW5kZXggJSAyID09PSAwLFxuICAgICAgICAgICAgcm93TGV2ZWw6IHRoaXMucm93TGV2ZWwsXG4gICAgICAgICAgICBmdWxsV2lkdGhSb3c6IHRoaXMuaXNGdWxsV2lkdGgoKSxcbiAgICAgICAgICAgIGZpcnN0Um93T25QYWdlOiB0aGlzLmlzRmlyc3RSb3dPblBhZ2UoKSxcbiAgICAgICAgICAgIGxhc3RSb3dPblBhZ2U6IHRoaXMuaXNMYXN0Um93T25QYWdlKCksXG4gICAgICAgICAgICBwcmludExheW91dDogdGhpcy5wcmludExheW91dCxcbiAgICAgICAgICAgIGV4cGFuZGFibGU6IHRoaXMucm93Tm9kZS5pc0V4cGFuZGFibGUoKSxcbiAgICAgICAgICAgIHBpbm5lZDogcGlubmVkXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzLmJlYW5zLnJvd0Nzc0NsYXNzQ2FsY3VsYXRvci5nZXRJbml0aWFsUm93Q2xhc3NlcyhwYXJhbXMpO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUucHJvY2Vzc1N0eWxlc0Zyb21HcmlkT3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcGFydCAxIC0gcm93U3R5bGVcbiAgICAgICAgdmFyIHJvd1N0eWxlID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93U3R5bGUoKTtcbiAgICAgICAgaWYgKHJvd1N0eWxlICYmIHR5cGVvZiByb3dTdHlsZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiByb3dTdHlsZSBzaG91bGQgYmUgYW4gb2JqZWN0IG9mIGtleS92YWx1ZSBzdHlsZXMsIG5vdCBiZSBhIGZ1bmN0aW9uLCB1c2UgZ2V0Um93U3R5bGUoKSBpbnN0ZWFkJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcGFydCAxIC0gcm93U3R5bGVGdW5jXG4gICAgICAgIHZhciByb3dTdHlsZUZ1bmMgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dTdHlsZUZ1bmMoKTtcbiAgICAgICAgdmFyIHJvd1N0eWxlRnVuY1Jlc3VsdDtcbiAgICAgICAgaWYgKHJvd1N0eWxlRnVuYykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICBkYXRhOiB0aGlzLnJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgICAgICBub2RlOiB0aGlzLnJvd05vZGUsXG4gICAgICAgICAgICAgICAgcm93SW5kZXg6IHRoaXMucm93Tm9kZS5yb3dJbmRleFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJvd1N0eWxlRnVuY1Jlc3VsdCA9IHJvd1N0eWxlRnVuYyhwYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCByb3dTdHlsZSwgcm93U3R5bGVGdW5jUmVzdWx0KTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLm9uUm93U2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIFRyZWF0IHVuZGVmaW5lZCBhcyBmYWxzZSwgaWYgd2UgcGFzcyB1bmRlZmluZWQgZG93biBpdCBnZXRzIHRyZWF0ZWQgYXMgdG9nZ2xlIGNsYXNzLCByYXRoZXIgdGhhbiBleHBsaWNpdGx5XG4gICAgICAgIC8vIHNldHRpbmcgdGhlIHJlcXVpcmVkIHZhbHVlXG4gICAgICAgIHZhciBzZWxlY3RlZCA9ICEhdGhpcy5yb3dOb2RlLmlzU2VsZWN0ZWQoKTtcbiAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkge1xuICAgICAgICAgICAgZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LXNlbGVjdGVkJywgc2VsZWN0ZWQpO1xuICAgICAgICAgICAgc2V0QXJpYVNlbGVjdGVkKGd1aS5lbGVtZW50LCBzZWxlY3RlZCA/IHRydWUgOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgdmFyIGFyaWFMYWJlbCA9IF90aGlzLmNyZWF0ZUFyaWFMYWJlbCgpO1xuICAgICAgICAgICAgc2V0QXJpYUxhYmVsKGd1aS5lbGVtZW50LCBhcmlhTGFiZWwgPT0gbnVsbCA/ICcnIDogYXJpYUxhYmVsKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5jcmVhdGVBcmlhTGFiZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9IHRoaXMucm93Tm9kZS5pc1NlbGVjdGVkKCk7XG4gICAgICAgIGlmIChzZWxlY3RlZCAmJiB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzUm93RGVzZWxlY3Rpb24oKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIGxhYmVsID0gdHJhbnNsYXRlKHNlbGVjdGVkID8gJ2FyaWFSb3dEZXNlbGVjdCcgOiAnYXJpYVJvd1NlbGVjdCcsIFwiUHJlc3MgU1BBQ0UgdG8gXCIgKyAoc2VsZWN0ZWQgPyAnZGVzZWxlY3QnIDogJ3NlbGVjdCcpICsgXCIgdGhpcyByb3cuXCIpO1xuICAgICAgICByZXR1cm4gbGFiZWw7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5pc1VzZUFuaW1hdGlvbkZyYW1lRm9yQ3JlYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy51c2VBbmltYXRpb25GcmFtZUZvckNyZWF0ZTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmFkZEhvdmVyRnVuY3Rpb25hbGl0eSA9IGZ1bmN0aW9uIChlUm93KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIGJlY2F1c2Ugd2UgdXNlIGFuaW1hdGlvbiBmcmFtZXMgdG8gZG8gdGhpcywgaXQncyBwb3NzaWJsZSB0aGUgcm93IG5vIGxvbmdlciBleGlzdHNcbiAgICAgICAgLy8gYnkgdGhlIHRpbWUgd2UgZ2V0IHRvIGFkZCBpdFxuICAgICAgICBpZiAoIXRoaXMuYWN0aXZlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gYmVjYXVzZSBtb3VzZWVudGVyIGFuZCBtb3VzZWxlYXZlIGRvIG5vdCBwcm9wYWdhdGUsIHdlIGNhbm5vdCBsaXN0ZW4gb24gdGhlIGdyaWRQYW5lbFxuICAgICAgICAvLyBsaWtlIHdlIGRvIGZvciBhbGwgdGhlIG90aGVyIG1vdXNlIGV2ZW50cy5cbiAgICAgICAgLy8gYmVjYXVzZSBvZiB0aGUgcGlubmluZywgd2UgY2Fubm90IHNpbXBseSBhZGQgLyByZW1vdmUgdGhlIGNsYXNzIGJhc2VkIG9uIHRoZSBlUm93LiB3ZVxuICAgICAgICAvLyBoYXZlIHRvIGNoZWNrIGFsbCBlUm93J3MgKGJvZHkgJiBwaW5uZWQpLiBzbyB0aGUgdHJpY2sgaXMgaWYgYW55IG9mIHRoZSByb3dzIGdldHMgYVxuICAgICAgICAvLyBtb3VzZSBob3ZlciwgaXQgc2V0cyBzdWNoIGluIHRoZSByb3dOb2RlLCBhbmQgdGhlbiBhbGwgdGhyZWUgcmVmbGVjdCB0aGUgY2hhbmdlIGFzXG4gICAgICAgIC8vIGFsbCBhcmUgbGlzdGVuaW5nIGZvciBldmVudCBvbiB0aGUgcm93IG5vZGUuXG4gICAgICAgIC8vIHN0ZXAgMSAtIGFkZCBsaXN0ZW5lciwgdG8gc2V0IGZsYWcgb24gcm93IG5vZGVcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZVJvdywgJ21vdXNlZW50ZXInLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5yb3dOb2RlLm9uTW91c2VFbnRlcigpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoZVJvdywgJ21vdXNlbGVhdmUnLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5yb3dOb2RlLm9uTW91c2VMZWF2ZSgpOyB9KTtcbiAgICAgICAgLy8gc3RlcCAyIC0gbGlzdGVuIGZvciBjaGFuZ2VzIG9uIHJvdyBub2RlICh3aGljaCBhbnkgZVJvdyBjYW4gdHJpZ2dlcilcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5yb3dOb2RlLCBSb3dOb2RlLkVWRU5UX01PVVNFX0VOVEVSLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBpZiBob3ZlciB0dXJuZWQgb2ZmLCB3ZSBkb24ndCBhZGQgdGhlIGNsYXNzLiB3ZSBkbyB0aGlzIGhlcmUgc28gdGhhdCBpZiB0aGUgYXBwbGljYXRpb25cbiAgICAgICAgICAgIC8vIHRvZ2dsZXMgdGhpcyBwcm9wZXJ0eSBtaWQgd2F5LCB3ZSByZW1vdmUgdGhlIGhvdmVyIGZvcm0gdGhlIGxhc3Qgcm93LCBidXQgd2Ugc3RvcFxuICAgICAgICAgICAgLy8gYWRkaW5nIGhvdmVycyBmcm9tIHRoYXQgcG9pbnQgb253YXJkcy5cbiAgICAgICAgICAgIGlmICghX3RoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NSb3dIb3ZlckhpZ2hsaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgZVJvdy5jbGFzc0xpc3QuYWRkKCdhZy1yb3ctaG92ZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMucm93Tm9kZSwgUm93Tm9kZS5FVkVOVF9NT1VTRV9MRUFWRSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZVJvdy5jbGFzc0xpc3QucmVtb3ZlKCdhZy1yb3ctaG92ZXInKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBmb3IgYW5pbWF0aW9uLCB3ZSBkb24ndCB3YW50IHRvIGFuaW1hdGUgZW50cnkgb3IgZXhpdCB0byBhIHZlcnkgZmFyIGF3YXkgcGl4ZWwsXG4gICAgLy8gb3RoZXJ3aXNlIHRoZSByb3cgd291bGQgbW92ZSBzbyBmYXN0LCBpdCB3b3VsZCBhcHBlYXIgdG8gZGlzYXBwZWFyLiBzbyB0aGlzIG1ldGhvZFxuICAgIC8vIG1vdmVzIHRoZSByb3cgY2xvc2VyIHRvIHRoZSB2aWV3cG9ydCBpZiBpdCBpcyBmYXIgYXdheSwgc28gdGhlIHJvdyBzbGlkZSBpbiAvIG91dFxuICAgIC8vIGF0IGEgc3BlZWQgdGhlIHVzZXIgY2FuIHNlZS5cbiAgICBSb3dDdHJsLnByb3RvdHlwZS5yb3VuZFJvd1RvcFRvQm91bmRzID0gZnVuY3Rpb24gKHJvd1RvcCkge1xuICAgICAgICB2YXIgZ3JpZEJvZHlDb24gPSB0aGlzLmJlYW5zLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgdmFyIHJhbmdlID0gZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmdldFZTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICB2YXIgbWluUGl4ZWwgPSB0aGlzLmFwcGx5UGFnaW5hdGlvbk9mZnNldChyYW5nZS50b3AsIHRydWUpIC0gMTAwO1xuICAgICAgICB2YXIgbWF4UGl4ZWwgPSB0aGlzLmFwcGx5UGFnaW5hdGlvbk9mZnNldChyYW5nZS5ib3R0b20sIHRydWUpICsgMTAwO1xuICAgICAgICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgobWluUGl4ZWwsIHJvd1RvcCksIG1heFBpeGVsKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldEZyYW1ld29ya092ZXJyaWRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmVhbnMuZnJhbWV3b3JrT3ZlcnJpZGVzO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25Sb3dIZWlnaHRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBjaGVjayBmb3IgZXhpc3RzIGZpcnN0IC0gaWYgdGhlIHVzZXIgaXMgcmVzZXR0aW5nIHRoZSByb3cgaGVpZ2h0LCB0aGVuXG4gICAgICAgIC8vIGl0IHdpbGwgYmUgbnVsbCAob3IgdW5kZWZpbmVkKSBtb21lbnRhcmlseSB1bnRpbCB0aGUgbmV4dCB0aW1lIHRoZSBmbGF0dGVuXG4gICAgICAgIC8vIHN0YWdlIGlzIGNhbGxlZCB3aGVyZSB0aGUgcm93IHdpbGwgdGhlbiB1cGRhdGUgYWdhaW4gd2l0aCBhIG5ldyBoZWlnaHRcbiAgICAgICAgaWYgKHRoaXMucm93Tm9kZS5yb3dIZWlnaHQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dIZWlnaHQgPSB0aGlzLnJvd05vZGUucm93SGVpZ2h0O1xuICAgICAgICB2YXIgZGVmYXVsdFJvd0hlaWdodCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERlZmF1bHRSb3dIZWlnaHQoKTtcbiAgICAgICAgdmFyIGlzSGVpZ2h0RnJvbUZ1bmMgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0dldFJvd0hlaWdodEZ1bmN0aW9uKCk7XG4gICAgICAgIHZhciBoZWlnaHRGcm9tRnVuYyA9IGlzSGVpZ2h0RnJvbUZ1bmMgPyB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dIZWlnaHRGb3JOb2RlKHRoaXMucm93Tm9kZSkuaGVpZ2h0IDogdW5kZWZpbmVkO1xuICAgICAgICB2YXIgbGluZUhlaWdodCA9IGhlaWdodEZyb21GdW5jID8gTWF0aC5taW4oZGVmYXVsdFJvd0hlaWdodCwgaGVpZ2h0RnJvbUZ1bmMpIC0gMiArIFwicHhcIiA6IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkge1xuICAgICAgICAgICAgZ3VpLmVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gcm93SGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICAgICAgLy8gSWYgdGhlIHJvdyBoZWlnaHQgaXMgY29taW5nIGZyb20gYSBmdW5jdGlvbiwgdGhpcyBtZWFucyBzb21lIHJvd3MgY2FuXG4gICAgICAgICAgICAvLyBiZSBzbWFsbGVyIHRoYW4gdGhlIHRoZW1lIGhhZCBpbnRlbmRlZC4gc28gd2Ugc2V0IC0tYWctbGluZS1oZWlnaHQgb25cbiAgICAgICAgICAgIC8vIHRoZSByb3csIHdoaWNoIGlzIHBpY2tlZCB1cCBieSB0aGUgdGhlbWUgQ1NTIGFuZCBpcyB1c2VkIGluIGEgY2FsY1xuICAgICAgICAgICAgLy8gZm9yIHRoZSBDU1MgbGluZS1oZWlnaHQgcHJvcGVydHksIHdoaWNoIG1ha2VzIHN1cmUgdGhlIGxpbmUtaGVpZ2h0IGlzXG4gICAgICAgICAgICAvLyBub3QgYmlnZ2VyIHRoYW4gdGhlIHJvdyBoZWlnaHQsIG90aGVyd2lzZSB0aGUgcm93IHRleHQgd291bGQgbm90IGZpdC5cbiAgICAgICAgICAgIC8vIFdlIGRvIG5vdCB1c2Ugcm93Tm9kZS5yb3dIZWlnaHQgaGVyZSwgYXMgdGhpcyBjb3VsZCBiZSB0aGUgcmVzdWx0IG9mIGF1dG9IZWlnaHQsXG4gICAgICAgICAgICAvLyBhbmQgd2UgZm91bmQgdXNpbmcgdGhlIGF1dG9IZWlnaHQgcmVzdWx0IGNhdXNlcyBhIGxvb3AsIHdoZXJlIGNoYW5naW5nIHRoZVxuICAgICAgICAgICAgLy8gbGluZS1oZWlnaHQgdGhlbSBpbXBhY3RzIHRoZSBjZWxsIGhlaWdodCwgcmVzdWx0aW5nIGluIGEgbmV3IGF1dG9IZWlnaHQsXG4gICAgICAgICAgICAvLyByZXN1bHRpbmcgaW4gYSBuZXcgbGluZS1oZWlnaHQgYW5kIHNvIG9uIGxvb3AuXG4gICAgICAgICAgICAvLyBjb25zdCBoZWlnaHRGcm9tRnVuYyA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0hlaWdodEZvck5vZGUodGhpcy5yb3dOb2RlKS5oZWlnaHQ7XG4gICAgICAgICAgICBpZiAobGluZUhlaWdodCkge1xuICAgICAgICAgICAgICAgIGd1aS5lbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCctLWFnLWxpbmUtaGVpZ2h0JywgbGluZUhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChldmVudFR5cGUgPT09ICdyZW5kZXJlZFJvd1JlbW92ZWQnIHx8IGV2ZW50VHlwZSA9PT0gJ3Jvd1JlbW92ZWQnKSB7XG4gICAgICAgICAgICBldmVudFR5cGUgPSBFdmVudHMuRVZFTlRfVklSVFVBTF9ST1dfUkVNT1ZFRDtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogU2luY2UgdmVyc2lvbiAxMSwgZXZlbnQgcmVuZGVyZWRSb3dSZW1vdmVkIGlzIG5vdyBjYWxsZWQgJyArIEV2ZW50cy5FVkVOVF9WSVJUVUFMX1JPV19SRU1PVkVEKTtcbiAgICAgICAgfVxuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIuY2FsbCh0aGlzLCBldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoZXZlbnRUeXBlID09PSAncmVuZGVyZWRSb3dSZW1vdmVkJyB8fCBldmVudFR5cGUgPT09ICdyb3dSZW1vdmVkJykge1xuICAgICAgICAgICAgZXZlbnRUeXBlID0gRXZlbnRzLkVWRU5UX1ZJUlRVQUxfUk9XX1JFTU9WRUQ7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFNpbmNlIHZlcnNpb24gMTEsIGV2ZW50IHJlbmRlcmVkUm93UmVtb3ZlZCBhbmQgcm93UmVtb3ZlZCBpcyBub3cgY2FsbGVkICcgKyBFdmVudHMuRVZFTlRfVklSVFVBTF9ST1dfUkVNT1ZFRCk7XG4gICAgICAgIH1cbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyLmNhbGwodGhpcywgZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICAvLyBub3RlIC0gdGhpcyBpcyBOT1QgY2FsbGVkIGJ5IGNvbnRleHQsIGFzIHdlIGRvbid0IHdpcmUgLyB1bndpcmUgdGhlIENlbGxDb21wIGZvciBwZXJmb3JtYW5jZSByZWFzb25zLlxuICAgIFJvd0N0cmwucHJvdG90eXBlLmRlc3Ryb3lGaXJzdFBhc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlID0gZmFsc2U7XG4gICAgICAgIC8vIHdoeSBkbyB3ZSBoYXZlIHRoaXMgbWV0aG9kPyBzaG91bGRuJ3QgZXZlcnl0aGluZyBiZWxvdyBiZSBhZGRlZCBhcyBhIGRlc3Ryb3kgZnVuYyBiZXNpZGVcbiAgICAgICAgLy8gdGhlIGNvcnJlc3BvbmRpbmcgY3JlYXRlIGxvZ2ljP1xuICAgICAgICB0aGlzLnNldHVwUmVtb3ZlQW5pbWF0aW9uKCk7XG4gICAgICAgIHZhciBldmVudCA9IHRoaXMuY3JlYXRlUm93RXZlbnQoRXZlbnRzLkVWRU5UX1ZJUlRVQUxfUk9XX1JFTU9WRUQpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICB0aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXR1cFJlbW92ZUFuaW1hdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2UgZG9uJ3QgYW5pbWF0ZSBzdGlja3kgcm93c1xuICAgICAgICBpZiAodGhpcy5pc1N0aWNreSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd1N0aWxsVmlzaWJsZUp1c3ROb3RJblZpZXdwb3J0ID0gdGhpcy5yb3dOb2RlLnJvd1RvcCAhPSBudWxsO1xuICAgICAgICBpZiAocm93U3RpbGxWaXNpYmxlSnVzdE5vdEluVmlld3BvcnQpIHtcbiAgICAgICAgICAgIC8vIGlmIHRoZSByb3cgaXMgbm90IHJlbmRlcmVkLCBidXQgaW4gdmlld3BvcnQsIGl0IG1lYW5zIGl0IGhhcyBtb3ZlZCxcbiAgICAgICAgICAgIC8vIHNvIHdlIGFuaW1hdGUgdGhlIHJvdyBvdXQuIGlmIHRoZSBuZXcgbG9jYXRpb24gaXMgdmVyeSBmYXIgYXdheSxcbiAgICAgICAgICAgIC8vIHRoZSBhbmltYXRpb24gd2lsbCBiZSBzbyBmYXN0IHRoZSByb3cgd2lsbCBsb29rIGxpa2UgaXQncyBqdXN0IGRpc2FwcGVhcmVkLFxuICAgICAgICAgICAgLy8gc28gaW5zdGVhZCB3ZSBhbmltYXRlIHRvIGEgcG9zaXRpb24ganVzdCBvdXRzaWRlIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgICAgIHZhciByb3dUb3AgPSB0aGlzLnJvdW5kUm93VG9wVG9Cb3VuZHModGhpcy5yb3dOb2RlLnJvd1RvcCk7XG4gICAgICAgICAgICB0aGlzLnNldFJvd1RvcChyb3dUb3ApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkgeyByZXR1cm4gZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctb3BhY2l0eS16ZXJvJywgdHJ1ZSk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5kZXN0cm95U2Vjb25kUGFzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmxlbmd0aCA9IDA7XG4gICAgICAgIHZhciBkZXN0cm95Q2VsbEN0cmxzID0gZnVuY3Rpb24gKGN0cmxzKSB7XG4gICAgICAgICAgICBjdHJscy5saXN0LmZvckVhY2goZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGMuZGVzdHJveSgpOyB9KTtcbiAgICAgICAgICAgIHJldHVybiB7IGxpc3Q6IFtdLCBtYXA6IHt9IH07XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2VudGVyQ2VsbEN0cmxzID0gZGVzdHJveUNlbGxDdHJscyh0aGlzLmNlbnRlckNlbGxDdHJscyk7XG4gICAgICAgIHRoaXMubGVmdENlbGxDdHJscyA9IGRlc3Ryb3lDZWxsQ3RybHModGhpcy5sZWZ0Q2VsbEN0cmxzKTtcbiAgICAgICAgdGhpcy5yaWdodENlbGxDdHJscyA9IGRlc3Ryb3lDZWxsQ3RybHModGhpcy5yaWdodENlbGxDdHJscyk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRGb2N1c2VkQ2xhc3NlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hbGxSb3dHdWlzLmZvckVhY2goZnVuY3Rpb24gKGd1aSkge1xuICAgICAgICAgICAgZ3VpLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LWZvY3VzJywgX3RoaXMucm93Rm9jdXNlZCk7XG4gICAgICAgICAgICBndWkucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctbm8tZm9jdXMnLCAhX3RoaXMucm93Rm9jdXNlZCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25DZWxsRm9jdXNDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93Rm9jdXNlZCA9IHRoaXMuYmVhbnMuZm9jdXNTZXJ2aWNlLmlzUm93Rm9jdXNlZCh0aGlzLnJvd05vZGUucm93SW5kZXgsIHRoaXMucm93Tm9kZS5yb3dQaW5uZWQpO1xuICAgICAgICBpZiAocm93Rm9jdXNlZCAhPT0gdGhpcy5yb3dGb2N1c2VkKSB7XG4gICAgICAgICAgICB0aGlzLnJvd0ZvY3VzZWQgPSByb3dGb2N1c2VkO1xuICAgICAgICAgICAgdGhpcy5zZXRGb2N1c2VkQ2xhc3NlcygpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlIGFyZSBlZGl0aW5nLCB0aGVuIG1vdmluZyB0aGUgZm9jdXMgb3V0IG9mIGEgcm93IHdpbGwgc3RvcCBlZGl0aW5nXG4gICAgICAgIGlmICghcm93Rm9jdXNlZCAmJiB0aGlzLmVkaXRpbmdSb3cpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcEVkaXRpbmcoZmFsc2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vblBhZ2luYXRpb25DaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY3VycmVudFBhZ2UgPSB0aGlzLmJlYW5zLnBhZ2luYXRpb25Qcm94eS5nZXRDdXJyZW50UGFnZSgpO1xuICAgICAgICAvLyBpdCBpcyBwb3NzaWJsZSB0aGlzIHJvdyBpcyBpbiB0aGUgbmV3IHBhZ2UsIGJ1dCB0aGUgcGFnZSBudW1iZXIgaGFzIGNoYW5nZWQsIHdoaWNoIG1lYW5zXG4gICAgICAgIC8vIGl0IG5lZWRzIHRvIHJlcG9zaXRpb24gaXRzZWxmIHJlbGF0aXZlIHRvIHRoZSBuZXcgcGFnZVxuICAgICAgICBpZiAodGhpcy5wYWdpbmF0aW9uUGFnZSAhPT0gY3VycmVudFBhZ2UpIHtcbiAgICAgICAgICAgIHRoaXMucGFnaW5hdGlvblBhZ2UgPSBjdXJyZW50UGFnZTtcbiAgICAgICAgICAgIHRoaXMub25Ub3BDaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWZyZXNoRmlyc3RBbmRMYXN0Um93U3R5bGVzKCk7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5vblRvcENoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0Um93VG9wKHRoaXMucm93Tm9kZS5yb3dUb3ApO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUub25QYWdpbmF0aW9uUGl4ZWxPZmZzZXRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB0aGUgcGl4ZWwgb2Zmc2V0IGlzIHVzZWQgd2hlbiBjYWxjdWxhdGluZyByb3dUb3AgdG8gc2V0IG9uIHRoZSByb3cgRElWXG4gICAgICAgIHRoaXMub25Ub3BDaGFuZ2VkKCk7XG4gICAgfTtcbiAgICAvLyBhcHBsaWVzIHBhZ2luYXRpb24gb2Zmc2V0LCBlZyBpZiBvbiBzZWNvbmQgcGFnZSwgYW5kIHBhZ2UgaGVpZ2h0IGlzIDUwMHB4LCB0aGVuIHJlbW92ZXNcbiAgICAvLyA1MDBweCBmcm9tIHRoZSB0b3AgcG9zaXRpb24sIHNvIGEgcm93IHdpdGggcm93VG9wIDYwMHB4IGlzIGRpc3BsYXllZCBhdCBsb2NhdGlvbiAxMDBweC5cbiAgICAvLyByZXZlcnNlIHdpbGwgdGFrZSB0aGUgb2Zmc2V0IGF3YXkgcmF0aGVyIHRoYW4gYWRkLlxuICAgIFJvd0N0cmwucHJvdG90eXBlLmFwcGx5UGFnaW5hdGlvbk9mZnNldCA9IGZ1bmN0aW9uICh0b3BQeCwgcmV2ZXJzZSkge1xuICAgICAgICBpZiAocmV2ZXJzZSA9PT0gdm9pZCAwKSB7IHJldmVyc2UgPSBmYWxzZTsgfVxuICAgICAgICBpZiAodGhpcy5yb3dOb2RlLmlzUm93UGlubmVkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0b3BQeDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGl4ZWxPZmZzZXQgPSB0aGlzLmJlYW5zLnBhZ2luYXRpb25Qcm94eS5nZXRQaXhlbE9mZnNldCgpO1xuICAgICAgICB2YXIgbXVsdGlwbGllciA9IHJldmVyc2UgPyAxIDogLTE7XG4gICAgICAgIHJldHVybiB0b3BQeCArIChwaXhlbE9mZnNldCAqIG11bHRpcGxpZXIpO1xuICAgIH07XG4gICAgUm93Q3RybC5wcm90b3R5cGUuc2V0Um93VG9wID0gZnVuY3Rpb24gKHBpeGVscykge1xuICAgICAgICAvLyBwcmludCBsYXlvdXQgdXNlcyBub3JtYWwgZmxvdyBsYXlvdXQgZm9yIHJvdyBwb3NpdGlvbmluZ1xuICAgICAgICBpZiAodGhpcy5wcmludExheW91dCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5lZWQgdG8gbWFrZSBzdXJlIHJvd1RvcCBpcyBub3QgbnVsbCwgYXMgdGhpcyBjYW4gaGFwcGVuIGlmIHRoZSBub2RlIHdhcyBvbmNlXG4gICAgICAgIC8vIHZpc2libGUgKGllIHBhcmVudCBncm91cCB3YXMgZXhwYW5kZWQpIGJ1dCBpcyBub3cgbm90IHZpc2libGVcbiAgICAgICAgaWYgKGV4aXN0cyhwaXhlbHMpKSB7XG4gICAgICAgICAgICB2YXIgYWZ0ZXJQYWdpbmF0aW9uUGl4ZWxzID0gdGhpcy5hcHBseVBhZ2luYXRpb25PZmZzZXQocGl4ZWxzKTtcbiAgICAgICAgICAgIHZhciBhZnRlclNjYWxpbmdQaXhlbHMgPSB0aGlzLnJvd05vZGUuaXNSb3dQaW5uZWQoKSA/IGFmdGVyUGFnaW5hdGlvblBpeGVscyA6IHRoaXMuYmVhbnMucm93Q29udGFpbmVySGVpZ2h0U2VydmljZS5nZXRSZWFsUGl4ZWxQb3NpdGlvbihhZnRlclBhZ2luYXRpb25QaXhlbHMpO1xuICAgICAgICAgICAgdmFyIHRvcFB4ID0gYWZ0ZXJTY2FsaW5nUGl4ZWxzICsgXCJweFwiO1xuICAgICAgICAgICAgdGhpcy5zZXRSb3dUb3BTdHlsZSh0b3BQeCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHRoZSB0b3AgbmVlZHMgdG8gYmUgc2V0IGludG8gdGhlIERPTSBlbGVtZW50IHdoZW4gdGhlIGVsZW1lbnQgaXMgY3JlYXRlZCwgbm90IHVwZGF0ZWQgYWZ0ZXJ3YXJkcy5cbiAgICAvLyBvdGhlcndpc2UgdGhlIHRyYW5zaXRpb24gd291bGQgbm90IHdvcmssIGFzIGl0IHdvdWxkIGJlIHRyYW5zaXRpb25pbmcgZnJvbSB6ZXJvICh0aGUgdW5zZXQgdmFsdWUpLlxuICAgIC8vIGZvciBleGFtcGxlLCBzdXBwb3NlIGEgcm93IHRoYXQgaXMgb3V0c2lkZSB0aGUgdmlld3BvcnQsIHRoZW4gdXNlciBkb2VzIGEgZmlsdGVyIHRvIHJlbW92ZSBvdGhlciByb3dzXG4gICAgLy8gYW5kIHRoaXMgcm93IG5vdyBhcHBlYXJzIGluIHRoZSB2aWV3cG9ydCwgYW5kIHRoZSByb3cgbW92ZXMgdXAgKGllIGl0IHdhcyB1bmRlciB0aGUgdmlld3BvcnQgYW5kIG5vdCByZW5kZXJlZCxcbiAgICAvLyBidXQgbm93IGlzIGluIHRoZSB2aWV3cG9ydCkgdGhlbiBhIG5ldyBSb3dDb21wIGlzIGNyZWF0ZWQsIGhvd2V2ZXIgaXQgc2hvdWxkIGhhdmUgaXQncyBwb3NpdGlvbiBpbml0aWFsaXNlZFxuICAgIC8vIHRvIGJlbG93IHRoZSB2aWV3cG9ydCwgc28gdGhlIHJvdyB3aWxsIGFwcGVhciB0byBhbmltYXRlIHVwLiBpZiB3ZSBkaWRuJ3Qgc2V0IHRoZSBpbml0aWFsIHBvc2l0aW9uIGF0IGNyZWF0aW9uXG4gICAgLy8gdGltZSwgdGhlIHJvdyB3b3VsZCBhbmltYXRlIGRvd24gKGllIGZyb20gcG9zaXRpb24gemVybykuXG4gICAgUm93Q3RybC5wcm90b3R5cGUuZ2V0SW5pdGlhbFJvd1RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHN1cHByZXNzUm93VHJhbnNmb3JtID0gdGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1Jvd1RyYW5zZm9ybSgpO1xuICAgICAgICByZXR1cm4gc3VwcHJlc3NSb3dUcmFuc2Zvcm0gPyB0aGlzLmdldEluaXRpYWxSb3dUb3BTaGFyZWQoKSA6IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldEluaXRpYWxUcmFuc2Zvcm0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzdXBwcmVzc1Jvd1RyYW5zZm9ybSA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NSb3dUcmFuc2Zvcm0oKTtcbiAgICAgICAgcmV0dXJuIHN1cHByZXNzUm93VHJhbnNmb3JtID8gdW5kZWZpbmVkIDogXCJ0cmFuc2xhdGVZKFwiICsgdGhpcy5nZXRJbml0aWFsUm93VG9wU2hhcmVkKCkgKyBcIilcIjtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldEluaXRpYWxSb3dUb3BTaGFyZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHByaW50IGxheW91dCB1c2VzIG5vcm1hbCBmbG93IGxheW91dCBmb3Igcm93IHBvc2l0aW9uaW5nXG4gICAgICAgIGlmICh0aGlzLnByaW50TGF5b3V0KSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd1RvcDtcbiAgICAgICAgaWYgKHRoaXMuaXNTdGlja3koKSkge1xuICAgICAgICAgICAgcm93VG9wID0gdGhpcy5yb3dOb2RlLnN0aWNreVJvd1RvcDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIHNsaWRpbmcgaW4sIHdlIHRha2UgdGhlIG9sZCByb3cgdG9wLiBvdGhlcndpc2Ugd2UganVzdCBzZXQgdGhlIGN1cnJlbnQgcm93IHRvcC5cbiAgICAgICAgICAgIHZhciBwaXhlbHMgPSB0aGlzLnNsaWRlUm93SW4gPyB0aGlzLnJvdW5kUm93VG9wVG9Cb3VuZHModGhpcy5yb3dOb2RlLm9sZFJvd1RvcCkgOiB0aGlzLnJvd05vZGUucm93VG9wO1xuICAgICAgICAgICAgdmFyIGFmdGVyUGFnaW5hdGlvblBpeGVscyA9IHRoaXMuYXBwbHlQYWdpbmF0aW9uT2Zmc2V0KHBpeGVscyk7XG4gICAgICAgICAgICAvLyB3ZSBkb24ndCBhcHBseSBzY2FsaW5nIGlmIHJvdyBpcyBwaW5uZWRcbiAgICAgICAgICAgIHJvd1RvcCA9IHRoaXMucm93Tm9kZS5pc1Jvd1Bpbm5lZCgpID8gYWZ0ZXJQYWdpbmF0aW9uUGl4ZWxzIDogdGhpcy5iZWFucy5yb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLmdldFJlYWxQaXhlbFBvc2l0aW9uKGFmdGVyUGFnaW5hdGlvblBpeGVscyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd1RvcCArICdweCc7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5zZXRSb3dUb3BTdHlsZSA9IGZ1bmN0aW9uICh0b3BQeCkge1xuICAgICAgICB2YXIgc3VwcHJlc3NSb3dUcmFuc2Zvcm0gPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzUm93VHJhbnNmb3JtKCk7XG4gICAgICAgIHRoaXMuYWxsUm93R3Vpcy5mb3JFYWNoKGZ1bmN0aW9uIChndWkpIHsgcmV0dXJuIHN1cHByZXNzUm93VHJhbnNmb3JtID9cbiAgICAgICAgICAgIGd1aS5yb3dDb21wLnNldFRvcCh0b3BQeCkgOlxuICAgICAgICAgICAgZ3VpLnJvd0NvbXAuc2V0VHJhbnNmb3JtKFwidHJhbnNsYXRlWShcIiArIHRvcFB4ICsgXCIpXCIpOyB9KTtcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd05vZGU7XG4gICAgfTtcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRDZWxsQ3RybCA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgLy8gZmlyc3QgdXAsIGNoZWNrIGZvciBjZWxsIGRpcmVjdGx5IGxpbmtlZCB0byB0aGlzIGNvbHVtblxuICAgICAgICB2YXIgcmVzID0gbnVsbDtcbiAgICAgICAgdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkge1xuICAgICAgICAgICAgaWYgKGNlbGxDdHJsLmdldENvbHVtbigpID09IGNvbHVtbikge1xuICAgICAgICAgICAgICAgIHJlcyA9IGNlbGxDdHJsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHJlcyAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgICAgIC8vIHNlY29uZCB1cCwgaWYgbm90IGZvdW5kLCB0aGVuIGNoZWNrIGZvciBzcGFubmVkIGNvbHMuXG4gICAgICAgIC8vIHdlIGRvIHRoaXMgc2Vjb25kIChhbmQgbm90IGF0IHRoZSBzYW1lIHRpbWUpIGFzIHRoaXMgaXNcbiAgICAgICAgLy8gbW9yZSBleHBlbnNpdmUsIGFzIHNwYW5uaW5nIGNvbHMgaXMgYVxuICAgICAgICAvLyBpbmZyZXF1ZW50bHkgdXNlZCBmZWF0dXJlIHNvIHdlIGRvbid0IG5lZWQgdG8gZG8gdGhpcyBtb3N0XG4gICAgICAgIC8vIG9mIHRoZSB0aW1lXG4gICAgICAgIHRoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgICAgIGlmIChjZWxsQ3RybC5nZXRDb2xTcGFubmluZ0xpc3QoKS5pbmRleE9mKGNvbHVtbikgPj0gMCkge1xuICAgICAgICAgICAgICAgIHJlcyA9IGNlbGxDdHJsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLm9uUm93SW5kZXhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB3ZSBvbmx5IGJvdGhlciB1cGRhdGluZyBpZiB0aGUgcm93SW5kZXggaXMgcHJlc2VudC4gaWYgaXQgaXMgbm90IHByZXNlbnQsIGl0IG1lYW5zIHRoaXMgcm93XG4gICAgICAgIC8vIGlzIGNoaWxkIG9mIGEgZ3JvdXAgbm9kZSwgYW5kIHRoZSBncm91cCBub2RlIHdhcyBjbG9zZWQsIGl0J3MgdGhlIG9ubHkgd2F5IHRvIGhhdmUgbm8gcm93IGluZGV4LlxuICAgICAgICAvLyB3aGVuIHRoaXMgaGFwcGVucywgcm93IGlzIGFib3V0IHRvIGJlIGRlLXJlbmRlcmVkLCBzbyB3ZSBkb24ndCBjYXJlLCByb3dDb21wIGlzIGFib3V0IHRvIGRpZSFcbiAgICAgICAgaWYgKHRoaXMucm93Tm9kZS5yb3dJbmRleCAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLm9uQ2VsbEZvY3VzQ2hhbmdlZCgpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVSb3dJbmRleGVzKCk7XG4gICAgICAgICAgICB0aGlzLnBvc3RQcm9jZXNzQ3NzKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0N0cmwucHJvdG90eXBlLnVwZGF0ZVJvd0luZGV4ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dJbmRleFN0ciA9IHRoaXMucm93Tm9kZS5nZXRSb3dJbmRleFN0cmluZygpO1xuICAgICAgICB2YXIgaGVhZGVyUm93Q291bnQgPSB0aGlzLmJlYW5zLmhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLmdldEhlYWRlclJvd0NvdW50KCk7XG4gICAgICAgIHZhciByb3dJc0V2ZW4gPSB0aGlzLnJvd05vZGUucm93SW5kZXggJSAyID09PSAwO1xuICAgICAgICB2YXIgYXJpYVJvd0luZGV4ID0gaGVhZGVyUm93Q291bnQgKyB0aGlzLnJvd05vZGUucm93SW5kZXggKyAxO1xuICAgICAgICB0aGlzLmFsbFJvd0d1aXMuZm9yRWFjaChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgYy5yb3dDb21wLnNldFJvd0luZGV4KHJvd0luZGV4U3RyKTtcbiAgICAgICAgICAgIGMucm93Q29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1yb3ctZXZlbicsIHJvd0lzRXZlbik7XG4gICAgICAgICAgICBjLnJvd0NvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctcm93LW9kZCcsICFyb3dJc0V2ZW4pO1xuICAgICAgICAgICAgc2V0QXJpYVJvd0luZGV4KGMuZWxlbWVudCwgYXJpYVJvd0luZGV4KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyByZXR1cm5zIHRoZSBwaW5uZWQgbGVmdCBjb250YWluZXIsIGVpdGhlciB0aGUgbm9ybWFsIG9uZSwgb3IgdGhlIGVtYmVkZGVkIGZ1bGwgd2l0aCBvbmUgaWYgZXhpc3RzXG4gICAgUm93Q3RybC5wcm90b3R5cGUuZ2V0UGlubmVkTGVmdFJvd0VsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxlZnRHdWkgPyB0aGlzLmxlZnRHdWkuZWxlbWVudCA6IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIC8vIHJldHVybnMgdGhlIHBpbm5lZCByaWdodCBjb250YWluZXIsIGVpdGhlciB0aGUgbm9ybWFsIG9uZSwgb3IgdGhlIGVtYmVkZGVkIGZ1bGwgd2l0aCBvbmUgaWYgZXhpc3RzXG4gICAgUm93Q3RybC5wcm90b3R5cGUuZ2V0UGlubmVkUmlnaHRSb3dFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yaWdodEd1aSA/IHRoaXMucmlnaHRHdWkuZWxlbWVudCA6IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIC8vIHJldHVybnMgdGhlIGJvZHkgY29udGFpbmVyLCBlaXRoZXIgdGhlIG5vcm1hbCBvbmUsIG9yIHRoZSBlbWJlZGRlZCBmdWxsIHdpdGggb25lIGlmIGV4aXN0c1xuICAgIFJvd0N0cmwucHJvdG90eXBlLmdldEJvZHlSb3dFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZW50ZXJHdWkgPyB0aGlzLmNlbnRlckd1aS5lbGVtZW50IDogdW5kZWZpbmVkO1xuICAgIH07XG4gICAgLy8gcmV0dXJucyB0aGUgZnVsbCB3aWR0aCBjb250YWluZXJcbiAgICBSb3dDdHJsLnByb3RvdHlwZS5nZXRGdWxsV2lkdGhSb3dFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mdWxsV2lkdGhHdWkgPyB0aGlzLmZ1bGxXaWR0aEd1aS5lbGVtZW50IDogdW5kZWZpbmVkO1xuICAgIH07XG4gICAgUm93Q3RybC5ET01fREFUQV9LRVlfUk9XX0NUUkwgPSAncmVuZGVyZWRSb3cnO1xuICAgIHJldHVybiBSb3dDdHJsO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFUID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxTSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcmVhZCRnID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFUKFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZShlbGVtZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTW91c2VMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5tb2NrQ29udGV4dE1lbnVGb3JJUGFkKCk7XG4gICAgICAgIHRoaXMuYWRkS2V5Ym9hcmRFdmVudHMoKTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLmFkZEtleWJvYXJkRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZXZlbnROYW1lcyA9IFsna2V5ZG93bicsICdrZXlwcmVzcyddO1xuICAgICAgICBldmVudE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgdmFyIGxpc3RlbmVyID0gX3RoaXMucHJvY2Vzc0tleWJvYXJkRXZlbnQuYmluZChfdGhpcywgZXZlbnROYW1lKTtcbiAgICAgICAgICAgIF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihfdGhpcy5lbGVtZW50LCBldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZS5hZGRNb3VzZUxpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG1vdXNlRG93bkV2ZW50ID0gaXNFdmVudFN1cHBvcnRlZCgndG91Y2hzdGFydCcpID8gJ3RvdWNoc3RhcnQnIDogJ21vdXNlZG93bic7XG4gICAgICAgIHZhciBldmVudE5hbWVzID0gWydkYmxjbGljaycsICdjb250ZXh0bWVudScsICdtb3VzZW92ZXInLCAnbW91c2VvdXQnLCAnY2xpY2snLCBtb3VzZURvd25FdmVudF07XG4gICAgICAgIGV2ZW50TmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICB2YXIgbGlzdGVuZXIgPSBfdGhpcy5wcm9jZXNzTW91c2VFdmVudC5iaW5kKF90aGlzLCBldmVudE5hbWUpO1xuICAgICAgICAgICAgX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKF90aGlzLmVsZW1lbnQsIGV2ZW50TmFtZSwgbGlzdGVuZXIpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLnByb2Nlc3NNb3VzZUV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50TmFtZSwgbW91c2VFdmVudCkge1xuICAgICAgICBpZiAoIXRoaXMubW91c2VFdmVudFNlcnZpY2UuaXNFdmVudEZyb21UaGlzR3JpZChtb3VzZUV2ZW50KSB8fFxuICAgICAgICAgICAgaXNTdG9wUHJvcGFnYXRpb25Gb3JBZ0dyaWQobW91c2VFdmVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93Q29tcCA9IHRoaXMuZ2V0Um93Rm9yRXZlbnQobW91c2VFdmVudCk7XG4gICAgICAgIHZhciBjZWxsQ3RybCA9IHRoaXMubW91c2VFdmVudFNlcnZpY2UuZ2V0UmVuZGVyZWRDZWxsRm9yRXZlbnQobW91c2VFdmVudCk7XG4gICAgICAgIGlmIChldmVudE5hbWUgPT09IFwiY29udGV4dG1lbnVcIikge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVDb250ZXh0TWVudU1vdXNlRXZlbnQobW91c2VFdmVudCwgbnVsbCwgcm93Q29tcCwgY2VsbEN0cmwpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNlbGxDdHJsKSB7XG4gICAgICAgICAgICAgICAgY2VsbEN0cmwub25Nb3VzZUV2ZW50KGV2ZW50TmFtZSwgbW91c2VFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocm93Q29tcCkge1xuICAgICAgICAgICAgICAgIHJvd0NvbXAub25Nb3VzZUV2ZW50KGV2ZW50TmFtZSwgbW91c2VFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLm1vY2tDb250ZXh0TWVudUZvcklQYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIHdlIGRvIE5PVCB3YW50IHRoaXMgd2hlbiBub3QgaW4gaVBhZCwgb3RoZXJ3aXNlIHdlIHdpbGwgYmUgZG9pbmdcbiAgICAgICAgaWYgKCFpc0lPU1VzZXJBZ2VudCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRvdWNoTGlzdGVuZXIgPSBuZXcgVG91Y2hMaXN0ZW5lcih0aGlzLmVsZW1lbnQpO1xuICAgICAgICB2YXIgbG9uZ1RhcExpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgcm93Q29tcCA9IF90aGlzLmdldFJvd0ZvckV2ZW50KGV2ZW50LnRvdWNoRXZlbnQpO1xuICAgICAgICAgICAgdmFyIGNlbGxDb21wID0gX3RoaXMubW91c2VFdmVudFNlcnZpY2UuZ2V0UmVuZGVyZWRDZWxsRm9yRXZlbnQoZXZlbnQudG91Y2hFdmVudCk7XG4gICAgICAgICAgICBfdGhpcy5oYW5kbGVDb250ZXh0TWVudU1vdXNlRXZlbnQobnVsbCwgZXZlbnQudG91Y2hFdmVudCwgcm93Q29tcCwgY2VsbENvbXApO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0b3VjaExpc3RlbmVyLCBUb3VjaExpc3RlbmVyLkVWRU5UX0xPTkdfVEFQLCBsb25nVGFwTGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRvdWNoTGlzdGVuZXIuZGVzdHJveSgpOyB9KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLmdldFJvd0ZvckV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBzb3VyY2VFbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgICAgICB3aGlsZSAoc291cmNlRWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIHJvd0NvbiA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvbURhdGEoc291cmNlRWxlbWVudCwgUm93Q3RybC5ET01fREFUQV9LRVlfUk9XX0NUUkwpO1xuICAgICAgICAgICAgaWYgKHJvd0Nvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiByb3dDb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzb3VyY2VFbGVtZW50ID0gc291cmNlRWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUuaGFuZGxlQ29udGV4dE1lbnVNb3VzZUV2ZW50ID0gZnVuY3Rpb24gKG1vdXNlRXZlbnQsIHRvdWNoRXZlbnQsIHJvd0NvbXAsIGNlbGxDdHJsKSB7XG4gICAgICAgIHZhciByb3dOb2RlID0gcm93Q29tcCA/IHJvd0NvbXAuZ2V0Um93Tm9kZSgpIDogbnVsbDtcbiAgICAgICAgdmFyIGNvbHVtbiA9IGNlbGxDdHJsID8gY2VsbEN0cmwuZ2V0Q29sdW1uKCkgOiBudWxsO1xuICAgICAgICB2YXIgdmFsdWUgPSBudWxsO1xuICAgICAgICBpZiAoY29sdW1uKSB7XG4gICAgICAgICAgICB2YXIgZXZlbnRfMSA9IG1vdXNlRXZlbnQgPyBtb3VzZUV2ZW50IDogdG91Y2hFdmVudDtcbiAgICAgICAgICAgIGNlbGxDdHJsLmRpc3BhdGNoQ2VsbENvbnRleHRNZW51RXZlbnQoZXZlbnRfMSk7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMudmFsdWVTZXJ2aWNlLmdldFZhbHVlKGNvbHVtbiwgcm93Tm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgdXNlciBjbGlja2VkIG9uIGEgY2VsbCwgYW5jaG9yIHRvIHRoYXQgY2VsbCwgb3RoZXJ3aXNlIGFuY2hvciB0byB0aGUgZ3JpZCBwYW5lbFxuICAgICAgICB2YXIgZ3JpZEJvZHlDb24gPSB0aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgdmFyIGFuY2hvclRvRWxlbWVudCA9IGNlbGxDdHJsID8gY2VsbEN0cmwuZ2V0R3VpKCkgOiBncmlkQm9keUNvbi5nZXRHcmlkQm9keUVsZW1lbnQoKTtcbiAgICAgICAgaWYgKHRoaXMuY29udGV4dE1lbnVGYWN0b3J5KSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRleHRNZW51RmFjdG9yeS5vbkNvbnRleHRNZW51KG1vdXNlRXZlbnQsIHRvdWNoRXZlbnQsIHJvd05vZGUsIGNvbHVtbiwgdmFsdWUsIGFuY2hvclRvRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLnByb2Nlc3NLZXlib2FyZEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50TmFtZSwga2V5Ym9hcmRFdmVudCkge1xuICAgICAgICB2YXIgY2VsbENvbXAgPSBnZXRDdHJsRm9yRXZlbnQodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIGtleWJvYXJkRXZlbnQsIENlbGxDdHJsLkRPTV9EQVRBX0tFWV9DRUxMX0NUUkwpO1xuICAgICAgICB2YXIgcm93Q29tcCA9IGdldEN0cmxGb3JFdmVudCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwga2V5Ym9hcmRFdmVudCwgUm93Q3RybC5ET01fREFUQV9LRVlfUk9XX0NUUkwpO1xuICAgICAgICBpZiAoa2V5Ym9hcmRFdmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNlbGxDb21wKSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NDZWxsS2V5Ym9hcmRFdmVudChjZWxsQ29tcCwgZXZlbnROYW1lLCBrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyb3dDb21wICYmIHJvd0NvbXAuaXNGdWxsV2lkdGgoKSkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzRnVsbFdpZHRoUm93S2V5Ym9hcmRFdmVudChyb3dDb21wLCBldmVudE5hbWUsIGtleWJvYXJkRXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZS5wcm9jZXNzQ2VsbEtleWJvYXJkRXZlbnQgPSBmdW5jdGlvbiAoY2VsbEN0cmwsIGV2ZW50TmFtZSwga2V5Ym9hcmRFdmVudCkge1xuICAgICAgICB2YXIgcm93Tm9kZSA9IGNlbGxDdHJsLmdldFJvd05vZGUoKTtcbiAgICAgICAgdmFyIGNvbHVtbiA9IGNlbGxDdHJsLmdldENvbHVtbigpO1xuICAgICAgICB2YXIgZWRpdGluZyA9IGNlbGxDdHJsLmlzRWRpdGluZygpO1xuICAgICAgICB2YXIgZ3JpZFByb2Nlc3NpbmdBbGxvd2VkID0gIWlzVXNlclN1cHByZXNzaW5nS2V5Ym9hcmRFdmVudCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwga2V5Ym9hcmRFdmVudCwgcm93Tm9kZSwgY29sdW1uLCBlZGl0aW5nKTtcbiAgICAgICAgaWYgKGdyaWRQcm9jZXNzaW5nQWxsb3dlZCkge1xuICAgICAgICAgICAgc3dpdGNoIChldmVudE5hbWUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdrZXlkb3duJzpcbiAgICAgICAgICAgICAgICAgICAgLy8gZmlyc3Qgc2VlIGlmIGl0J3MgYSBzY3JvbGwga2V5LCBwYWdlIHVwIC8gZG93biwgaG9tZSAvIGVuZCBldGNcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhc1Njcm9sbEtleSA9ICFlZGl0aW5nICYmIHRoaXMubmF2aWdhdGlvblNlcnZpY2UuaGFuZGxlUGFnZVNjcm9sbGluZ0tleShrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgbm90IGEgc2Nyb2xsIGtleSwgdGhlbiB3ZSBwYXNzIG9udG8gY2VsbFxuICAgICAgICAgICAgICAgICAgICBpZiAoIXdhc1Njcm9sbEtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2VsbEN0cmwub25LZXlEb3duKGtleWJvYXJkRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIHBlcmZvcm0gY2xpcGJvYXJkIGFuZCB1bmRvIC8gcmVkbyBvcGVyYXRpb25zXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG9HcmlkT3BlcmF0aW9ucyhrZXlib2FyZEV2ZW50LCBjZWxsQ3RybC5pc0VkaXRpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2tleXByZXNzJzpcbiAgICAgICAgICAgICAgICAgICAgY2VsbEN0cmwub25LZXlQcmVzcyhrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50TmFtZSA9PT0gJ2tleWRvd24nKSB7XG4gICAgICAgICAgICB2YXIgY2VsbEtleURvd25FdmVudCA9IGNlbGxDdHJsLmNyZWF0ZUV2ZW50KGtleWJvYXJkRXZlbnQsIEV2ZW50cy5FVkVOVF9DRUxMX0tFWV9ET1dOKTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoY2VsbEtleURvd25FdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50TmFtZSA9PT0gJ2tleXByZXNzJykge1xuICAgICAgICAgICAgdmFyIGNlbGxLZXlQcmVzc0V2ZW50ID0gY2VsbEN0cmwuY3JlYXRlRXZlbnQoa2V5Ym9hcmRFdmVudCwgRXZlbnRzLkVWRU5UX0NFTExfS0VZX1BSRVNTKTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoY2VsbEtleVByZXNzRXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZS5wcm9jZXNzRnVsbFdpZHRoUm93S2V5Ym9hcmRFdmVudCA9IGZ1bmN0aW9uIChyb3dDb21wLCBldmVudE5hbWUsIGtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgdmFyIHJvd05vZGUgPSByb3dDb21wLmdldFJvd05vZGUoKTtcbiAgICAgICAgdmFyIGZvY3VzZWRDZWxsID0gdGhpcy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNlZENlbGwoKTtcbiAgICAgICAgdmFyIGNvbHVtbiA9IChmb2N1c2VkQ2VsbCAmJiBmb2N1c2VkQ2VsbC5jb2x1bW4pO1xuICAgICAgICB2YXIgZ3JpZFByb2Nlc3NpbmdBbGxvd2VkID0gIWlzVXNlclN1cHByZXNzaW5nS2V5Ym9hcmRFdmVudCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwga2V5Ym9hcmRFdmVudCwgcm93Tm9kZSwgY29sdW1uLCBmYWxzZSk7XG4gICAgICAgIGlmIChncmlkUHJvY2Vzc2luZ0FsbG93ZWQpIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSBrZXlib2FyZEV2ZW50LmtleTtcbiAgICAgICAgICAgIGlmIChldmVudE5hbWUgPT09ICdrZXlkb3duJykge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5VUDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRPV046XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dDb21wLm9uS2V5Ym9hcmROYXZpZ2F0ZShrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuVEFCOlxuICAgICAgICAgICAgICAgICAgICAgICAgcm93Q29tcC5vblRhYktleURvd24oa2V5Ym9hcmRFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudE5hbWUgPT09ICdrZXlkb3duJykge1xuICAgICAgICAgICAgdmFyIGNlbGxLZXlEb3duRXZlbnQgPSByb3dDb21wLmNyZWF0ZVJvd0V2ZW50KEV2ZW50cy5FVkVOVF9DRUxMX0tFWV9ET1dOLCBrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoY2VsbEtleURvd25FdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2ZW50TmFtZSA9PT0gJ2tleXByZXNzJykge1xuICAgICAgICAgICAgdmFyIGNlbGxLZXlQcmVzc0V2ZW50ID0gcm93Q29tcC5jcmVhdGVSb3dFdmVudChFdmVudHMuRVZFTlRfQ0VMTF9LRVlfUFJFU1MsIGtleWJvYXJkRXZlbnQpO1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChjZWxsS2V5UHJlc3NFdmVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLmRvR3JpZE9wZXJhdGlvbnMgPSBmdW5jdGlvbiAoa2V5Ym9hcmRFdmVudCwgZWRpdGluZykge1xuICAgICAgICAvLyBjaGVjayBpZiBjdHJsIG9yIG1ldGEga2V5IHByZXNzZWRcbiAgICAgICAgaWYgKCFrZXlib2FyZEV2ZW50LmN0cmxLZXkgJiYgIWtleWJvYXJkRXZlbnQubWV0YUtleSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHRoZSBjZWxsIHRoZSBldmVudCBjYW1lIGZyb20gaXMgZWRpdGluZywgdGhlbiB3ZSBkbyBub3RcbiAgICAgICAgLy8gd2FudCB0byBkbyB0aGUgZGVmYXVsdCBzaG9ydGN1dCBrZXlzLCBvdGhlcndpc2UgdGhlIGVkaXRvclxuICAgICAgICAvLyAoZWcgYSB0ZXh0IGZpZWxkKSB3b3VsZCBub3QgYmUgYWJsZSB0byBkbyB0aGUgbm9ybWFsIGN1dC9jb3B5L3Bhc3RlXG4gICAgICAgIGlmIChlZGl0aW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gZm9yIGNvcHkgLyBwYXN0ZSwgd2UgZG9uJ3Qgd2FudCB0byBleGVjdXRlIHdoZW4gdGhlIGV2ZW50XG4gICAgICAgIC8vIHdhcyBmcm9tIGEgY2hpbGQgZ3JpZCAoaGFwcGVucyBpbiBtYXN0ZXIgZGV0YWlsKVxuICAgICAgICBpZiAoIXRoaXMubW91c2VFdmVudFNlcnZpY2UuaXNFdmVudEZyb21UaGlzR3JpZChrZXlib2FyZEV2ZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBrZXlDb2RlID0gbm9ybWFsaXNlUXdlcnR5QXplcnR5KGtleWJvYXJkRXZlbnQpO1xuICAgICAgICBpZiAoa2V5Q29kZSA9PT0gS2V5Q29kZS5BKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vbkN0cmxBbmRBKGtleWJvYXJkRXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXlDb2RlID09PSBLZXlDb2RlLkMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9uQ3RybEFuZEMoa2V5Ym9hcmRFdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGtleUNvZGUgPT09IEtleUNvZGUuVikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub25DdHJsQW5kVigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXlDb2RlID09PSBLZXlDb2RlLkQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9uQ3RybEFuZEQoa2V5Ym9hcmRFdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGtleUNvZGUgPT09IEtleUNvZGUuWikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMub25DdHJsQW5kWihrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoa2V5Q29kZSA9PT0gS2V5Q29kZS5ZKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vbkN0cmxBbmRZKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLm9uQ3RybEFuZEEgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIF9hID0gdGhpcywgcGlubmVkUm93TW9kZWwgPSBfYS5waW5uZWRSb3dNb2RlbCwgcGFnaW5hdGlvblByb3h5ID0gX2EucGFnaW5hdGlvblByb3h5LCByYW5nZVNlcnZpY2UgPSBfYS5yYW5nZVNlcnZpY2U7XG4gICAgICAgIHZhciBQSU5ORURfQk9UVE9NID0gQ29uc3RhbnRzLlBJTk5FRF9CT1RUT00sIFBJTk5FRF9UT1AgPSBDb25zdGFudHMuUElOTkVEX1RPUDtcbiAgICAgICAgaWYgKHJhbmdlU2VydmljZSAmJiBwYWdpbmF0aW9uUHJveHkuaXNSb3dzVG9SZW5kZXIoKSkge1xuICAgICAgICAgICAgdmFyIF9iID0gX19yZWFkJGcoW1xuICAgICAgICAgICAgICAgIHBpbm5lZFJvd01vZGVsLmlzRW1wdHkoUElOTkVEX1RPUCksXG4gICAgICAgICAgICAgICAgcGlubmVkUm93TW9kZWwuaXNFbXB0eShQSU5ORURfQk9UVE9NKVxuICAgICAgICAgICAgXSwgMiksIGlzRW1wdHlQaW5uZWRUb3AgPSBfYlswXSwgaXNFbXB0eVBpbm5lZEJvdHRvbSA9IF9iWzFdO1xuICAgICAgICAgICAgdmFyIGZsb2F0aW5nU3RhcnQgPSBpc0VtcHR5UGlubmVkVG9wID8gbnVsbCA6IFBJTk5FRF9UT1A7XG4gICAgICAgICAgICB2YXIgZmxvYXRpbmdFbmQgPSB2b2lkIDA7XG4gICAgICAgICAgICB2YXIgcm93RW5kID0gdm9pZCAwO1xuICAgICAgICAgICAgaWYgKGlzRW1wdHlQaW5uZWRCb3R0b20pIHtcbiAgICAgICAgICAgICAgICBmbG9hdGluZ0VuZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgcm93RW5kID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93Q291bnQoKSAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmbG9hdGluZ0VuZCA9IFBJTk5FRF9CT1RUT007XG4gICAgICAgICAgICAgICAgcm93RW5kID0gcGlubmVkUm93TW9kZWwuZ2V0UGlubmVkQm90dG9tUm93RGF0YSgpLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYWxsRGlzcGxheWVkQ29sdW1ucyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucygpO1xuICAgICAgICAgICAgaWYgKG1pc3NpbmdPckVtcHR5KGFsbERpc3BsYXllZENvbHVtbnMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmFuZ2VTZXJ2aWNlLnNldENlbGxSYW5nZSh7XG4gICAgICAgICAgICAgICAgcm93U3RhcnRJbmRleDogMCxcbiAgICAgICAgICAgICAgICByb3dTdGFydFBpbm5lZDogZmxvYXRpbmdTdGFydCxcbiAgICAgICAgICAgICAgICByb3dFbmRJbmRleDogcm93RW5kLFxuICAgICAgICAgICAgICAgIHJvd0VuZFBpbm5lZDogZmxvYXRpbmdFbmQsXG4gICAgICAgICAgICAgICAgY29sdW1uU3RhcnQ6IGFsbERpc3BsYXllZENvbHVtbnNbMF0sXG4gICAgICAgICAgICAgICAgY29sdW1uRW5kOiBsYXN0KGFsbERpc3BsYXllZENvbHVtbnMpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUub25DdHJsQW5kQyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoIXRoaXMuY2xpcGJvYXJkU2VydmljZSB8fCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUNlbGxUZXh0U2VsZWN0aW9uKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNsaXBib2FyZFNlcnZpY2UuY29weVRvQ2xpcGJvYXJkKCk7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZS5vbkN0cmxBbmRWID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuaXNSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkNsaXBib2FyZE1vZHVsZSkgJiYgIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NDbGlwYm9hcmRQYXN0ZSgpKSB7XG4gICAgICAgICAgICB0aGlzLmNsaXBib2FyZFNlcnZpY2UucGFzdGVGcm9tQ2xpcGJvYXJkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLm9uQ3RybEFuZEQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5DbGlwYm9hcmRNb2R1bGUpICYmICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ2xpcGJvYXJkUGFzdGUoKSkge1xuICAgICAgICAgICAgdGhpcy5jbGlwYm9hcmRTZXJ2aWNlLmNvcHlSYW5nZURvd24oKTtcbiAgICAgICAgfVxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUub25DdHJsQW5kWiA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVW5kb1JlZG9DZWxsRWRpdGluZygpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICB0aGlzLnVuZG9SZWRvU2VydmljZS5yZWRvKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnVuZG9SZWRvU2VydmljZS51bmRvKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLm9uQ3RybEFuZFkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudW5kb1JlZG9TZXJ2aWNlLnJlZG8oKTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBBdXRvd2lyZWQoJ21vdXNlRXZlbnRTZXJ2aWNlJylcbiAgICBdLCBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZSwgXCJtb3VzZUV2ZW50U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlU2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUsIFwidmFsdWVTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTShbXG4gICAgICAgIE9wdGlvbmFsKCdjb250ZXh0TWVudUZhY3RvcnknKVxuICAgIF0sIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLCBcImNvbnRleHRNZW51RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTShbXG4gICAgICAgIEF1dG93aXJlZCgnbmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLCBcIm5hdmlnYXRpb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTShbXG4gICAgICAgIEF1dG93aXJlZCgnZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFNKFtcbiAgICAgICAgQXV0b3dpcmVkKCd1bmRvUmVkb1NlcnZpY2UnKVxuICAgIF0sIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLCBcInVuZG9SZWRvU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBBdXRvd2lyZWQoJ3BhZ2luYXRpb25Qcm94eScpXG4gICAgXSwgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUsIFwicGFnaW5hdGlvblByb3h5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTShbXG4gICAgICAgIEF1dG93aXJlZCgncGlubmVkUm93TW9kZWwnKVxuICAgIF0sIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLCBcInBpbm5lZFJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxTShbXG4gICAgICAgIE9wdGlvbmFsKCdyYW5nZVNlcnZpY2UnKVxuICAgIF0sIFJvd0NvbnRhaW5lckV2ZW50c0ZlYXR1cmUucHJvdG90eXBlLCBcInJhbmdlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBPcHRpb25hbCgnY2xpcGJvYXJkU2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUsIFwiY2xpcGJvYXJkU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMU0oW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gUm93Q29udGFpbmVyRXZlbnRzRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxUyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMUwgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbi8vIGxpc3RlbnMgdG8gY2hhbmdlcyBpbiB0aGUgY2VudGVyIHZpZXdwb3J0IHNpemUsIGZvciBjb2x1bW4gYW5kIHJvdyB2aXJ0dWFsaXNhdGlvbixcbi8vIGFuZCBhZGp1c3RzIGdyaWQgYXMgbmVjZXNzYXJ5LiB0aGVyZSBhcmUgdHdvIHZpZXdwb3J0cywgb25lIGZvciBob3Jpem9udGFsIGFuZCBvbmUgZm9yXG4vLyB2ZXJ0aWNhbCBzY3JvbGxpbmcuXG52YXIgVmlld3BvcnRTaXplRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMVMoVmlld3BvcnRTaXplRmVhdHVyZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBWaWV3cG9ydFNpemVGZWF0dXJlKGNlbnRlckNvbnRhaW5lckN0cmwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY2VudGVyQ29udGFpbmVyQ3RybCA9IGNlbnRlckNvbnRhaW5lckN0cmw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVmlld3BvcnRTaXplRmVhdHVyZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmdyaWRCb2R5Q3RybCA9IF90aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgICAgIF90aGlzLmxpc3RlbkZvclJlc2l6ZSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9TQ1JPTExCQVJfV0lEVEhfQ0hBTkdFRCwgdGhpcy5vblNjcm9sbGJhcldpZHRoQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIFZpZXdwb3J0U2l6ZUZlYXR1cmUucHJvdG90eXBlLmxpc3RlbkZvclJlc2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25DZW50ZXJWaWV3cG9ydFJlc2l6ZWQoKTsgfTtcbiAgICAgICAgLy8gY2VudGVyQ29udGFpbmVyIGdldHMgaG9yaXpvbnRhbCByZXNpemVzXG4gICAgICAgIHRoaXMuY2VudGVyQ29udGFpbmVyQ3RybC5yZWdpc3RlclZpZXdwb3J0UmVzaXplTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgICAgICAvLyBlQm9keVZpZXdwb3J0IGdldHMgdmVydGljYWwgcmVzaXplc1xuICAgICAgICB0aGlzLmdyaWRCb2R5Q3RybC5yZWdpc3RlckJvZHlWaWV3cG9ydFJlc2l6ZUxpc3RlbmVyKGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIFZpZXdwb3J0U2l6ZUZlYXR1cmUucHJvdG90eXBlLm9uU2Nyb2xsYmFyV2lkdGhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNoZWNrVmlld3BvcnRBbmRTY3JvbGxzKCk7XG4gICAgfTtcbiAgICBWaWV3cG9ydFNpemVGZWF0dXJlLnByb3RvdHlwZS5vbkNlbnRlclZpZXdwb3J0UmVzaXplZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2VudGVyQ29udGFpbmVyQ3RybC5pc1ZpZXdwb3J0VmlzaWJsZSgpKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrVmlld3BvcnRBbmRTY3JvbGxzKCk7XG4gICAgICAgICAgICB2YXIgbmV3V2lkdGggPSB0aGlzLmNlbnRlckNvbnRhaW5lckN0cmwuZ2V0Q2VudGVyV2lkdGgoKTtcbiAgICAgICAgICAgIGlmIChuZXdXaWR0aCAhPT0gdGhpcy5jZW50ZXJXaWR0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2VudGVyV2lkdGggPSBuZXdXaWR0aDtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLnJlZnJlc2hGbGV4ZWRDb2x1bW5zKHsgdmlld3BvcnRXaWR0aDogdGhpcy5jZW50ZXJXaWR0aCwgdXBkYXRlQm9keVdpZHRoczogdHJ1ZSwgZmlyZVJlc2l6ZWRFdmVudDogdHJ1ZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYm9keUhlaWdodCA9IDA7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIGdldHMgY2FsbGVkIGV2ZXJ5IHRpbWUgdGhlIHZpZXdwb3J0IHNpemUgY2hhbmdlcy4gd2UgdXNlIHRoaXMgdG8gY2hlY2sgdmlzaWJpbGl0eSBvZiBzY3JvbGxiYXJzXG4gICAgLy8gaW4gdGhlIGdyaWQgcGFuZWwsIGFuZCBhbHNvIHRvIGNoZWNrIHNpemUgYW5kIHBvc2l0aW9uIG9mIHZpZXdwb3J0IGZvciByb3cgYW5kIGNvbHVtbiB2aXJ0dWFsaXNhdGlvbi5cbiAgICBWaWV3cG9ydFNpemVGZWF0dXJlLnByb3RvdHlwZS5jaGVja1ZpZXdwb3J0QW5kU2Nyb2xscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gcmVzdWx0cyBpbiB1cGRhdGluZyBhbnl0aGluZyB0aGF0IGRlcGVuZHMgb24gc2Nyb2xsIHNob3dpbmdcbiAgICAgICAgdGhpcy51cGRhdGVTY3JvbGxWaXNpYmxlU2VydmljZSgpO1xuICAgICAgICAvLyBmaXJlcyBldmVudCBpZiBoZWlnaHQgY2hhbmdlcywgdXNlZCBieSBQYWdpbmF0aW9uU2VydmljZSwgSGVpZ2h0U2NhbGVyU2VydmljZSwgUm93UmVuZGVyZXJcbiAgICAgICAgdGhpcy5jaGVja0JvZHlIZWlnaHQoKTtcbiAgICAgICAgLy8gY2hlY2sgZm9yIHZpcnR1YWwgY29sdW1ucyBmb3IgQ29sdW1uQ29udHJvbGxlclxuICAgICAgICB0aGlzLm9uSG9yaXpvbnRhbFZpZXdwb3J0Q2hhbmdlZCgpO1xuICAgICAgICB0aGlzLmdyaWRCb2R5Q3RybC5nZXRTY3JvbGxGZWF0dXJlKCkuY2hlY2tTY3JvbGxMZWZ0KCk7XG4gICAgfTtcbiAgICBWaWV3cG9ydFNpemVGZWF0dXJlLnByb3RvdHlwZS5nZXRCb2R5SGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ib2R5SGVpZ2h0O1xuICAgIH07XG4gICAgVmlld3BvcnRTaXplRmVhdHVyZS5wcm90b3R5cGUuY2hlY2tCb2R5SGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZUJvZHlWaWV3cG9ydCA9IHRoaXMuZ3JpZEJvZHlDdHJsLmdldEJvZHlWaWV3cG9ydEVsZW1lbnQoKTtcbiAgICAgICAgdmFyIGJvZHlIZWlnaHQgPSBnZXRJbm5lckhlaWdodChlQm9keVZpZXdwb3J0KTtcbiAgICAgICAgaWYgKHRoaXMuYm9keUhlaWdodCAhPT0gYm9keUhlaWdodCkge1xuICAgICAgICAgICAgdGhpcy5ib2R5SGVpZ2h0ID0gYm9keUhlaWdodDtcbiAgICAgICAgICAgIHZhciBldmVudF8xID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9CT0RZX0hFSUdIVF9DSEFOR0VEXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlld3BvcnRTaXplRmVhdHVyZS5wcm90b3R5cGUudXBkYXRlU2Nyb2xsVmlzaWJsZVNlcnZpY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGJlY2F1c2Ugb2YgY29sdW1uIGFuaW1hdGlvbiAod2hpY2ggdGFrZXMgMjAwbXMpLCB3ZSBoYXZlIHRvIGRvIHRoaXMgdHdpY2UuXG4gICAgICAgIC8vIGVnIGlmIHVzZXIgcmVtb3ZlcyBjb2xzIGFueXdoZXJlIGV4Y2VwdCBhdCB0aGUgUkhTLCB0aGVuIHRoZSBjb2xzIG9uIHRoZSBSSFNcbiAgICAgICAgLy8gd2lsbCBhbmltYXRlIHRvIHRoZSBsZWZ0IHRvIGZpbGwgdGhlIGdhcC4gdGhpcyBhbmltYXRpb24gbWVhbnMganVzdCBhZnRlclxuICAgICAgICAvLyB0aGUgY29scyBhcmUgcmVtb3ZlZCwgdGhlIHJlbWFpbmluZyBjb2xzIGFyZSBzdGlsbCBpbiB0aGUgb3JpZ2luYWwgbG9jYXRpb25cbiAgICAgICAgLy8gYXQgdGhlIHN0YXJ0IG9mIHRoZSBhbmltYXRpb24sIHNvIHByZSBhbmltYXRpb24gdGhlIEggc2Nyb2xsYmFyIGlzIHN0aWxsIG5lZWRlZCxcbiAgICAgICAgLy8gYnV0IHBvc3QgYW5pbWF0aW9uIGl0IGlzIG5vdC5cbiAgICAgICAgdGhpcy51cGRhdGVTY3JvbGxWaXNpYmxlU2VydmljZUltcGwoKTtcbiAgICAgICAgc2V0VGltZW91dCh0aGlzLnVwZGF0ZVNjcm9sbFZpc2libGVTZXJ2aWNlSW1wbC5iaW5kKHRoaXMpLCA1MDApO1xuICAgIH07XG4gICAgVmlld3BvcnRTaXplRmVhdHVyZS5wcm90b3R5cGUudXBkYXRlU2Nyb2xsVmlzaWJsZVNlcnZpY2VJbXBsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgaG9yaXpvbnRhbFNjcm9sbFNob3dpbmc6IHRoaXMuaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZygpLFxuICAgICAgICAgICAgdmVydGljYWxTY3JvbGxTaG93aW5nOiB0aGlzLmdyaWRCb2R5Q3RybC5pc1ZlcnRpY2FsU2Nyb2xsU2hvd2luZygpXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2Nyb2xsVmlzaWJsZVNlcnZpY2Uuc2V0U2Nyb2xsc1Zpc2libGUocGFyYW1zKTtcbiAgICAgICAgLy8gZml4IC0gZ3JpZENvbXAgc2hvdWxkIGp1c3QgbGlzdGVuIHRvIGV2ZW50IGZyb20gYWJvdmVcbiAgICAgICAgdGhpcy5ncmlkQm9keUN0cmwuc2V0VmVydGljYWxTY3JvbGxQYWRkaW5nVmlzaWJsZShwYXJhbXMudmVydGljYWxTY3JvbGxTaG93aW5nKTtcbiAgICB9O1xuICAgIFZpZXdwb3J0U2l6ZUZlYXR1cmUucHJvdG90eXBlLmlzSG9yaXpvbnRhbFNjcm9sbFNob3dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc0Fsd2F5c1Nob3dIb3Jpem9udGFsU2Nyb2xsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNBbHdheXNTaG93SG9yaXpvbnRhbFNjcm9sbCgpO1xuICAgICAgICByZXR1cm4gaXNBbHdheXNTaG93SG9yaXpvbnRhbFNjcm9sbCB8fCB0aGlzLmNlbnRlckNvbnRhaW5lckN0cmwuaXNWaWV3cG9ydEhTY3JvbGxTaG93aW5nKCk7XG4gICAgfTtcbiAgICAvLyB0aGlzIGdldHMgY2FsbGVkIHdoZW5ldmVyIGEgY2hhbmdlIGluIHRoZSB2aWV3cG9ydCwgc28gd2UgY2FuIGluZm9ybSBjb2x1bW4gY29udHJvbGxlciBpdCBoYXMgdG8gd29ya1xuICAgIC8vIG91dCB0aGUgdmlydHVhbCBjb2x1bW5zIGFnYWluLiBnZXRzIGNhbGxlZCBmcm9tIGZvbGxvd2luZyBsb2NhdGlvbnM6XG4gICAgLy8gKyBlbnN1cmVDb2xWaXNpYmxlLCBzY3JvbGwsIGluaXQsIGxheW91dENoYW5nZWQsIGRpc3BsYXllZENvbHVtbnNDaGFuZ2VkLCBBUEkgKGRvTGF5b3V0KVxuICAgIFZpZXdwb3J0U2l6ZUZlYXR1cmUucHJvdG90eXBlLm9uSG9yaXpvbnRhbFZpZXdwb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNjcm9sbFdpZHRoID0gdGhpcy5jZW50ZXJDb250YWluZXJDdHJsLmdldENlbnRlcldpZHRoKCk7XG4gICAgICAgIHZhciBzY3JvbGxQb3NpdGlvbiA9IHRoaXMuY2VudGVyQ29udGFpbmVyQ3RybC5nZXRWaWV3cG9ydFNjcm9sbExlZnQoKTtcbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zZXRWaWV3cG9ydFBvc2l0aW9uKHNjcm9sbFdpZHRoLCBzY3JvbGxQb3NpdGlvbik7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFMKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIFZpZXdwb3J0U2l6ZUZlYXR1cmUucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUwoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBWaWV3cG9ydFNpemVGZWF0dXJlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUwoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Njcm9sbFZpc2libGVTZXJ2aWNlJylcbiAgICBdLCBWaWV3cG9ydFNpemVGZWF0dXJlLnByb3RvdHlwZSwgXCJzY3JvbGxWaXNpYmxlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUwoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgVmlld3BvcnRTaXplRmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gVmlld3BvcnRTaXplRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxUiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMUsgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBTZXRQaW5uZWRMZWZ0V2lkdGhGZWF0dXJlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxUihTZXRQaW5uZWRMZWZ0V2lkdGhGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNldFBpbm5lZExlZnRXaWR0aEZlYXR1cmUoZWxlbWVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTZXRQaW5uZWRMZWZ0V2lkdGhGZWF0dXJlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0xFRlRfUElOTkVEX1dJRFRIX0NIQU5HRUQsIHRoaXMub25QaW5uZWRMZWZ0V2lkdGhDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgU2V0UGlubmVkTGVmdFdpZHRoRmVhdHVyZS5wcm90b3R5cGUub25QaW5uZWRMZWZ0V2lkdGhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGVmdFdpZHRoID0gdGhpcy5waW5uZWRXaWR0aFNlcnZpY2UuZ2V0UGlubmVkTGVmdFdpZHRoKCk7XG4gICAgICAgIHZhciBkaXNwbGF5ZWQgPSBsZWZ0V2lkdGggPiAwO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lbGVtZW50LCBkaXNwbGF5ZWQpO1xuICAgICAgICBpZiAoZGlzcGxheWVkKSB7XG4gICAgICAgICAgICBzZXRGaXhlZFdpZHRoKHRoaXMuZWxlbWVudCwgbGVmdFdpZHRoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxSyhbXG4gICAgICAgIEF1dG93aXJlZCgncGlubmVkV2lkdGhTZXJ2aWNlJylcbiAgICBdLCBTZXRQaW5uZWRMZWZ0V2lkdGhGZWF0dXJlLnByb3RvdHlwZSwgXCJwaW5uZWRXaWR0aFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFLKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFNldFBpbm5lZExlZnRXaWR0aEZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFNldFBpbm5lZExlZnRXaWR0aEZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMVEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFKID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgU2V0UGlubmVkUmlnaHRXaWR0aEZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFRKFNldFBpbm5lZFJpZ2h0V2lkdGhGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNldFBpbm5lZFJpZ2h0V2lkdGhGZWF0dXJlKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU2V0UGlubmVkUmlnaHRXaWR0aEZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfUklHSFRfUElOTkVEX1dJRFRIX0NIQU5HRUQsIHRoaXMub25QaW5uZWRSaWdodFdpZHRoQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIFNldFBpbm5lZFJpZ2h0V2lkdGhGZWF0dXJlLnByb3RvdHlwZS5vblBpbm5lZFJpZ2h0V2lkdGhDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmlnaHRXaWR0aCA9IHRoaXMucGlubmVkV2lkdGhTZXJ2aWNlLmdldFBpbm5lZFJpZ2h0V2lkdGgoKTtcbiAgICAgICAgdmFyIGRpc3BsYXllZCA9IHJpZ2h0V2lkdGggPiAwO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lbGVtZW50LCBkaXNwbGF5ZWQpO1xuICAgICAgICBpZiAoZGlzcGxheWVkKSB7XG4gICAgICAgICAgICBzZXRGaXhlZFdpZHRoKHRoaXMuZWxlbWVudCwgcmlnaHRXaWR0aCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMUooW1xuICAgICAgICBBdXRvd2lyZWQoJ3Bpbm5lZFdpZHRoU2VydmljZScpXG4gICAgXSwgU2V0UGlubmVkUmlnaHRXaWR0aEZlYXR1cmUucHJvdG90eXBlLCBcInBpbm5lZFdpZHRoU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUooW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgU2V0UGlubmVkUmlnaHRXaWR0aEZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFNldFBpbm5lZFJpZ2h0V2lkdGhGZWF0dXJlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFQID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxSSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFNldEhlaWdodEZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFQKFNldEhlaWdodEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2V0SGVpZ2h0RmVhdHVyZShlQ29udGFpbmVyLCBlV3JhcHBlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lQ29udGFpbmVyID0gZUNvbnRhaW5lcjtcbiAgICAgICAgX3RoaXMuZVdyYXBwZXIgPSBlV3JhcHBlcjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTZXRIZWlnaHRGZWF0dXJlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1JPV19DT05UQUlORVJfSEVJR0hUX0NIQU5HRUQsIHRoaXMub25IZWlnaHRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgU2V0SGVpZ2h0RmVhdHVyZS5wcm90b3R5cGUub25IZWlnaHRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGVpZ2h0ID0gdGhpcy5tYXhEaXZIZWlnaHRTY2FsZXIuZ2V0VWlDb250YWluZXJIZWlnaHQoKTtcbiAgICAgICAgdmFyIGhlaWdodFN0cmluZyA9IGhlaWdodCAhPSBudWxsID8gaGVpZ2h0ICsgXCJweFwiIDogXCJcIjtcbiAgICAgICAgdGhpcy5lQ29udGFpbmVyLnN0eWxlLmhlaWdodCA9IGhlaWdodFN0cmluZztcbiAgICAgICAgaWYgKHRoaXMuZVdyYXBwZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZVdyYXBwZXIuc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0U3RyaW5nO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFJKFtcbiAgICAgICAgQXV0b3dpcmVkKFwicm93Q29udGFpbmVySGVpZ2h0U2VydmljZVwiKVxuICAgIF0sIFNldEhlaWdodEZlYXR1cmUucHJvdG90eXBlLCBcIm1heERpdkhlaWdodFNjYWxlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUkoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgU2V0SGVpZ2h0RmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gU2V0SGVpZ2h0RmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxTyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMUggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBEcmFnTGlzdGVuZXJGZWF0dXJlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxTyhEcmFnTGlzdGVuZXJGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIERyYWdMaXN0ZW5lckZlYXR1cmUoZUNvbnRhaW5lcikge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lQ29udGFpbmVyID0gZUNvbnRhaW5lcjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBEcmFnTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUmFuZ2VTZWxlY3Rpb24oKSB8fCAvLyBubyByYW5nZSBzZWxlY3Rpb24gaWYgbm8gcHJvcGVydHlcbiAgICAgICAgICAgIG1pc3NpbmcodGhpcy5yYW5nZVNlcnZpY2UpIC8vIG5vIHJhbmdlIHNlbGVjdGlvbiBpZiBub3QgZW50ZXJwcmlzZSB2ZXJzaW9uXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBlRWxlbWVudDogdGhpcy5lQ29udGFpbmVyLFxuICAgICAgICAgICAgb25EcmFnU3RhcnQ6IHRoaXMucmFuZ2VTZXJ2aWNlLm9uRHJhZ1N0YXJ0LmJpbmQodGhpcy5yYW5nZVNlcnZpY2UpLFxuICAgICAgICAgICAgb25EcmFnU3RvcDogdGhpcy5yYW5nZVNlcnZpY2Uub25EcmFnU3RvcC5iaW5kKHRoaXMucmFuZ2VTZXJ2aWNlKSxcbiAgICAgICAgICAgIG9uRHJhZ2dpbmc6IHRoaXMucmFuZ2VTZXJ2aWNlLm9uRHJhZ2dpbmcuYmluZCh0aGlzLnJhbmdlU2VydmljZSlcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kcmFnU2VydmljZS5hZGREcmFnU291cmNlKHBhcmFtcyk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZHJhZ1NlcnZpY2UucmVtb3ZlRHJhZ1NvdXJjZShwYXJhbXMpOyB9KTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMUgoW1xuICAgICAgICBPcHRpb25hbCgncmFuZ2VTZXJ2aWNlJylcbiAgICBdLCBEcmFnTGlzdGVuZXJGZWF0dXJlLnByb3RvdHlwZSwgXCJyYW5nZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFIKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnU2VydmljZScpXG4gICAgXSwgRHJhZ0xpc3RlbmVyRmVhdHVyZS5wcm90b3R5cGUsIFwiZHJhZ1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFIKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIERyYWdMaXN0ZW5lckZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIERyYWdMaXN0ZW5lckZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMU4gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFHID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ2VudGVyV2lkdGhGZWF0dXJlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxTihDZW50ZXJXaWR0aEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ2VudGVyV2lkdGhGZWF0dXJlKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQ2VudGVyV2lkdGhGZWF0dXJlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGlzdGVuZXIgPSB0aGlzLnNldFdpZHRoLmJpbmQodGhpcyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET01fTEFZT1VULCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfQ0hBTkdFRCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX1dJRFRIX0NIQU5HRUQsIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5zZXRXaWR0aCgpO1xuICAgIH07XG4gICAgQ2VudGVyV2lkdGhGZWF0dXJlLnByb3RvdHlwZS5zZXRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbHVtbk1vZGVsID0gdGhpcy5jb2x1bW5Nb2RlbDtcbiAgICAgICAgdmFyIHByaW50TGF5b3V0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tTGF5b3V0KCkgPT09IENvbnN0YW50cy5ET01fTEFZT1VUX1BSSU5UO1xuICAgICAgICB2YXIgY2VudGVyV2lkdGggPSBjb2x1bW5Nb2RlbC5nZXRCb2R5Q29udGFpbmVyV2lkdGgoKTtcbiAgICAgICAgdmFyIGxlZnRXaWR0aCA9IGNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbHVtbnNMZWZ0V2lkdGgoKTtcbiAgICAgICAgdmFyIHJpZ2h0V2lkdGggPSBjb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2x1bW5zUmlnaHRXaWR0aCgpO1xuICAgICAgICB2YXIgdG90YWxXaWR0aCA9IHByaW50TGF5b3V0ID8gY2VudGVyV2lkdGggKyBsZWZ0V2lkdGggKyByaWdodFdpZHRoIDogY2VudGVyV2lkdGg7XG4gICAgICAgIHRoaXMuY2FsbGJhY2sodG90YWxXaWR0aCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFHKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgQ2VudGVyV2lkdGhGZWF0dXJlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUcoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgQ2VudGVyV2lkdGhGZWF0dXJlLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBDZW50ZXJXaWR0aEZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMU0gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFGID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX19yZWFkJGYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgX19zcHJlYWQkYyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCRmKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG52YXIgUm93Q29udGFpbmVyTmFtZTtcbihmdW5jdGlvbiAoUm93Q29udGFpbmVyTmFtZSkge1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJMRUZUXCJdID0gXCJsZWZ0XCI7XG4gICAgUm93Q29udGFpbmVyTmFtZVtcIlJJR0hUXCJdID0gXCJyaWdodFwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJDRU5URVJcIl0gPSBcImNlbnRlclwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJGVUxMX1dJRFRIXCJdID0gXCJmdWxsV2lkdGhcIjtcbiAgICBSb3dDb250YWluZXJOYW1lW1wiVE9QX0xFRlRcIl0gPSBcInRvcExlZnRcIjtcbiAgICBSb3dDb250YWluZXJOYW1lW1wiVE9QX1JJR0hUXCJdID0gXCJ0b3BSaWdodFwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJUT1BfQ0VOVEVSXCJdID0gXCJ0b3BDZW50ZXJcIjtcbiAgICBSb3dDb250YWluZXJOYW1lW1wiVE9QX0ZVTExfV0lEVEhcIl0gPSBcInRvcEZ1bGxXaWR0aFwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJTVElDS1lfVE9QX0xFRlRcIl0gPSBcInN0aWNreVRvcExlZnRcIjtcbiAgICBSb3dDb250YWluZXJOYW1lW1wiU1RJQ0tZX1RPUF9SSUdIVFwiXSA9IFwic3RpY2t5VG9wUmlnaHRcIjtcbiAgICBSb3dDb250YWluZXJOYW1lW1wiU1RJQ0tZX1RPUF9DRU5URVJcIl0gPSBcInN0aWNreVRvcENlbnRlclwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJTVElDS1lfVE9QX0ZVTExfV0lEVEhcIl0gPSBcInN0aWNreVRvcEZ1bGxXaWR0aFwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJCT1RUT01fTEVGVFwiXSA9IFwiYm90dG9tTGVmdFwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJCT1RUT01fUklHSFRcIl0gPSBcImJvdHRvbVJpZ2h0XCI7XG4gICAgUm93Q29udGFpbmVyTmFtZVtcIkJPVFRPTV9DRU5URVJcIl0gPSBcImJvdHRvbUNlbnRlclwiO1xuICAgIFJvd0NvbnRhaW5lck5hbWVbXCJCT1RUT01fRlVMTF9XSURUSFwiXSA9IFwiYm90dG9tRnVsbFdpZHRoXCI7XG59KShSb3dDb250YWluZXJOYW1lIHx8IChSb3dDb250YWluZXJOYW1lID0ge30pKTtcbnZhciBSb3dDb250YWluZXJUeXBlO1xuKGZ1bmN0aW9uIChSb3dDb250YWluZXJUeXBlKSB7XG4gICAgUm93Q29udGFpbmVyVHlwZVtcIkxFRlRcIl0gPSBcImxlZnRcIjtcbiAgICBSb3dDb250YWluZXJUeXBlW1wiUklHSFRcIl0gPSBcInJpZ2h0XCI7XG4gICAgUm93Q29udGFpbmVyVHlwZVtcIkNFTlRFUlwiXSA9IFwiY2VudGVyXCI7XG4gICAgUm93Q29udGFpbmVyVHlwZVtcIkZVTExfV0lEVEhcIl0gPSBcImZ1bGxXaWR0aFwiO1xufSkoUm93Q29udGFpbmVyVHlwZSB8fCAoUm93Q29udGFpbmVyVHlwZSA9IHt9KSk7XG5mdW5jdGlvbiBnZXRSb3dDb250YWluZXJUeXBlRm9yTmFtZShuYW1lKSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5DRU5URVI6XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfQ0VOVEVSOlxuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9DRU5URVI6XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fQ0VOVEVSOlxuICAgICAgICAgICAgcmV0dXJuIFJvd0NvbnRhaW5lclR5cGUuQ0VOVEVSO1xuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuTEVGVDpcbiAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLlRPUF9MRUZUOlxuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9MRUZUOlxuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX0xFRlQ6XG4gICAgICAgICAgICByZXR1cm4gUm93Q29udGFpbmVyVHlwZS5MRUZUO1xuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuUklHSFQ6XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfUklHSFQ6XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX1JJR0hUOlxuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX1JJR0hUOlxuICAgICAgICAgICAgcmV0dXJuIFJvd0NvbnRhaW5lclR5cGUuUklHSFQ7XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5GVUxMX1dJRFRIOlxuICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuVE9QX0ZVTExfV0lEVEg6XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0ZVTExfV0lEVEg6XG4gICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fRlVMTF9XSURUSDpcbiAgICAgICAgICAgIHJldHVybiBSb3dDb250YWluZXJUeXBlLkZVTExfV0lEVEg7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBFcnJvcignSW52YWxpZCBSb3cgQ29udGFpbmVyIFR5cGUnKTtcbiAgICB9XG59XG52YXIgQ29udGFpbmVyQ3NzQ2xhc3NlcyA9IGNvbnZlcnRUb01hcChbXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuQ0VOVEVSLCAnYWctY2VudGVyLWNvbHMtY29udGFpbmVyJ10sXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuTEVGVCwgJ2FnLXBpbm5lZC1sZWZ0LWNvbHMtY29udGFpbmVyJ10sXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuUklHSFQsICdhZy1waW5uZWQtcmlnaHQtY29scy1jb250YWluZXInXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5GVUxMX1dJRFRILCAnYWctZnVsbC13aWR0aC1jb250YWluZXInXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5UT1BfQ0VOVEVSLCAnYWctZmxvYXRpbmctdG9wLWNvbnRhaW5lciddLFxuICAgIFtSb3dDb250YWluZXJOYW1lLlRPUF9MRUZULCAnYWctcGlubmVkLWxlZnQtZmxvYXRpbmctdG9wJ10sXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuVE9QX1JJR0hULCAnYWctcGlubmVkLXJpZ2h0LWZsb2F0aW5nLXRvcCddLFxuICAgIFtSb3dDb250YWluZXJOYW1lLlRPUF9GVUxMX1dJRFRILCAnYWctZmxvYXRpbmctdG9wLWZ1bGwtd2lkdGgtY29udGFpbmVyJ10sXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9DRU5URVIsICdhZy1zdGlja3ktdG9wLWNvbnRhaW5lciddLFxuICAgIFtSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfTEVGVCwgJ2FnLXBpbm5lZC1sZWZ0LXN0aWNreS10b3AnXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX1JJR0hULCAnYWctcGlubmVkLXJpZ2h0LXN0aWNreS10b3AnXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0ZVTExfV0lEVEgsICdhZy1zdGlja3ktdG9wLWZ1bGwtd2lkdGgtY29udGFpbmVyJ10sXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuQk9UVE9NX0NFTlRFUiwgJ2FnLWZsb2F0aW5nLWJvdHRvbS1jb250YWluZXInXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5CT1RUT01fTEVGVCwgJ2FnLXBpbm5lZC1sZWZ0LWZsb2F0aW5nLWJvdHRvbSddLFxuICAgIFtSb3dDb250YWluZXJOYW1lLkJPVFRPTV9SSUdIVCwgJ2FnLXBpbm5lZC1yaWdodC1mbG9hdGluZy1ib3R0b20nXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5CT1RUT01fRlVMTF9XSURUSCwgJ2FnLWZsb2F0aW5nLWJvdHRvbS1mdWxsLXdpZHRoLWNvbnRhaW5lciddLFxuXSk7XG52YXIgVmlld3BvcnRDc3NDbGFzc2VzID0gY29udmVydFRvTWFwKFtcbiAgICBbUm93Q29udGFpbmVyTmFtZS5DRU5URVIsICdhZy1jZW50ZXItY29scy12aWV3cG9ydCddLFxuICAgIFtSb3dDb250YWluZXJOYW1lLlRPUF9DRU5URVIsICdhZy1mbG9hdGluZy10b3Atdmlld3BvcnQnXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0NFTlRFUiwgJ2FnLXN0aWNreS10b3Atdmlld3BvcnQnXSxcbiAgICBbUm93Q29udGFpbmVyTmFtZS5CT1RUT01fQ0VOVEVSLCAnYWctZmxvYXRpbmctYm90dG9tLXZpZXdwb3J0J10sXG5dKTtcbnZhciBXcmFwcGVyQ3NzQ2xhc3NlcyA9IGNvbnZlcnRUb01hcChbXG4gICAgW1Jvd0NvbnRhaW5lck5hbWUuQ0VOVEVSLCAnYWctY2VudGVyLWNvbHMtY2xpcHBlciddLFxuXSk7XG52YXIgUm93Q29udGFpbmVyQ3RybCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMU0oUm93Q29udGFpbmVyQ3RybCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSb3dDb250YWluZXJDdHJsKG5hbWUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUm93Q29udGFpbmVyQ3RybC5nZXRSb3dDb250YWluZXJDc3NDbGFzc2VzID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lckNsYXNzID0gQ29udGFpbmVyQ3NzQ2xhc3Nlcy5nZXQobmFtZSk7XG4gICAgICAgIHZhciB2aWV3cG9ydENsYXNzID0gVmlld3BvcnRDc3NDbGFzc2VzLmdldChuYW1lKTtcbiAgICAgICAgdmFyIHdyYXBwZXJDbGFzcyA9IFdyYXBwZXJDc3NDbGFzc2VzLmdldChuYW1lKTtcbiAgICAgICAgcmV0dXJuIHsgY29udGFpbmVyOiBjb250YWluZXJDbGFzcywgdmlld3BvcnQ6IHZpZXdwb3J0Q2xhc3MsIHdyYXBwZXI6IHdyYXBwZXJDbGFzcyB9O1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5nZXRQaW5uZWQgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fTEVGVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfTEVGVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0xFRlQ6XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuTEVGVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gQ29uc3RhbnRzLlBJTk5FRF9MRUZUO1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9SSUdIVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfUklHSFQ6XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9SSUdIVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5SSUdIVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZW5hYmxlUnRsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKTtcbiAgICAgICAgdGhpcy5lbWJlZEZ1bGxXaWR0aFJvd3MgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VtYmVkRnVsbFdpZHRoUm93cygpO1xuICAgICAgICB0aGlzLmZvckNvbnRhaW5lcnMoW1Jvd0NvbnRhaW5lck5hbWUuQ0VOVEVSXSwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudmlld3BvcnRTaXplRmVhdHVyZSA9IF90aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBWaWV3cG9ydFNpemVGZWF0dXJlKF90aGlzKSk7IH0pO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUucmVnaXN0ZXJXaXRoQ3RybHNTZXJ2aWNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBzd2l0Y2ggKHRoaXMubmFtZSkge1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLkNFTlRFUjpcbiAgICAgICAgICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlckNlbnRlclJvd0NvbnRhaW5lckN0cmwodGhpcyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuTEVGVDpcbiAgICAgICAgICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlckxlZnRSb3dDb250YWluZXJDdHJsKHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLlJJR0hUOlxuICAgICAgICAgICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLnJlZ2lzdGVyUmlnaHRSb3dDb250YWluZXJDdHJsKHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLlRPUF9DRU5URVI6XG4gICAgICAgICAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2UucmVnaXN0ZXJUb3BDZW50ZXJSb3dDb250YWluZXJDdHJsKHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLlRPUF9MRUZUOlxuICAgICAgICAgICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLnJlZ2lzdGVyVG9wTGVmdFJvd0NvbnRhaW5lckNvbih0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfUklHSFQ6XG4gICAgICAgICAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2UucmVnaXN0ZXJUb3BSaWdodFJvd0NvbnRhaW5lckN0cmwodGhpcyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9DRU5URVI6XG4gICAgICAgICAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2UucmVnaXN0ZXJTdGlja3lUb3BDZW50ZXJSb3dDb250YWluZXJDdHJsKHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfTEVGVDpcbiAgICAgICAgICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlclN0aWNreVRvcExlZnRSb3dDb250YWluZXJDb24odGhpcyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9SSUdIVDpcbiAgICAgICAgICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlclN0aWNreVRvcFJpZ2h0Um93Q29udGFpbmVyQ3RybCh0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fQ0VOVEVSOlxuICAgICAgICAgICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLnJlZ2lzdGVyQm90dG9tQ2VudGVyUm93Q29udGFpbmVyQ3RybCh0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fTEVGVDpcbiAgICAgICAgICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlckJvdHRvbUxlZnRSb3dDb250YWluZXJDdHJsKHRoaXMpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9SSUdIVDpcbiAgICAgICAgICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlckJvdHRvbVJpZ2h0Um93Q29udGFpbmVyQ3RybCh0aGlzKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuZm9yQ29udGFpbmVycyA9IGZ1bmN0aW9uIChuYW1lcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG5hbWVzLmluZGV4T2YodGhpcy5uYW1lKSA+PSAwKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5nZXRDb250YWluZXJFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lQ29udGFpbmVyO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuZ2V0Vmlld3BvcnRTaXplRmVhdHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlld3BvcnRTaXplRmVhdHVyZTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLnNldENvbXAgPSBmdW5jdGlvbiAodmlldywgZUNvbnRhaW5lciwgZVZpZXdwb3J0LCBlV3JhcHBlcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNvbXAgPSB2aWV3O1xuICAgICAgICB0aGlzLmVDb250YWluZXIgPSBlQ29udGFpbmVyO1xuICAgICAgICB0aGlzLmVWaWV3cG9ydCA9IGVWaWV3cG9ydDtcbiAgICAgICAgdGhpcy5lV3JhcHBlciA9IGVXcmFwcGVyO1xuICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBSb3dDb250YWluZXJFdmVudHNGZWF0dXJlKHRoaXMuZUNvbnRhaW5lcikpO1xuICAgICAgICB0aGlzLmFkZFByZXZlbnRTY3JvbGxXaGlsZURyYWdnaW5nKCk7XG4gICAgICAgIHRoaXMubGlzdGVuT25Eb21PcmRlcigpO1xuICAgICAgICB0aGlzLnN0b3BIU2Nyb2xsT25QaW5uZWRSb3dzKCk7XG4gICAgICAgIHZhciBhbGxUb3BOb0ZXID0gW1Jvd0NvbnRhaW5lck5hbWUuVE9QX0NFTlRFUiwgUm93Q29udGFpbmVyTmFtZS5UT1BfTEVGVCwgUm93Q29udGFpbmVyTmFtZS5UT1BfUklHSFRdO1xuICAgICAgICB2YXIgYWxsU3RpY2t5VG9wTm9GVyA9IFtSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfTEVGVCwgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX1JJR0hUXTtcbiAgICAgICAgdmFyIGFsbEJvdHRvbU5vRlcgPSBbUm93Q29udGFpbmVyTmFtZS5CT1RUT01fQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9MRUZULCBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9SSUdIVF07XG4gICAgICAgIHZhciBhbGxNaWRkbGVOb0ZXID0gW1Jvd0NvbnRhaW5lck5hbWUuQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLkxFRlQsIFJvd0NvbnRhaW5lck5hbWUuUklHSFRdO1xuICAgICAgICB2YXIgYWxsTm9GVyA9IF9fc3ByZWFkJGMoYWxsVG9wTm9GVywgYWxsQm90dG9tTm9GVywgYWxsTWlkZGxlTm9GVywgYWxsU3RpY2t5VG9wTm9GVyk7XG4gICAgICAgIHZhciBhbGxNaWRkbGUgPSBbUm93Q29udGFpbmVyTmFtZS5DRU5URVIsIFJvd0NvbnRhaW5lck5hbWUuTEVGVCwgUm93Q29udGFpbmVyTmFtZS5SSUdIVCwgUm93Q29udGFpbmVyTmFtZS5GVUxMX1dJRFRIXTtcbiAgICAgICAgdmFyIGFsbENlbnRlciA9IFtSb3dDb250YWluZXJOYW1lLkNFTlRFUiwgUm93Q29udGFpbmVyTmFtZS5UT1BfQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9DRU5URVJdO1xuICAgICAgICB2YXIgYWxsTGVmdCA9IFtSb3dDb250YWluZXJOYW1lLkxFRlQsIFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX0xFRlQsIFJvd0NvbnRhaW5lck5hbWUuVE9QX0xFRlQsIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9MRUZUXTtcbiAgICAgICAgdmFyIGFsbFJpZ2h0ID0gW1Jvd0NvbnRhaW5lck5hbWUuUklHSFQsIFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX1JJR0hULCBSb3dDb250YWluZXJOYW1lLlRPUF9SSUdIVCwgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX1JJR0hUXTtcbiAgICAgICAgdGhpcy5mb3JDb250YWluZXJzKGFsbExlZnQsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBTZXRQaW5uZWRMZWZ0V2lkdGhGZWF0dXJlKF90aGlzLmVDb250YWluZXIpKTsgfSk7XG4gICAgICAgIHRoaXMuZm9yQ29udGFpbmVycyhhbGxSaWdodCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IFNldFBpbm5lZFJpZ2h0V2lkdGhGZWF0dXJlKF90aGlzLmVDb250YWluZXIpKTsgfSk7XG4gICAgICAgIHRoaXMuZm9yQ29udGFpbmVycyhhbGxNaWRkbGUsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBTZXRIZWlnaHRGZWF0dXJlKF90aGlzLmVDb250YWluZXIsIF90aGlzLmVXcmFwcGVyKSk7IH0pO1xuICAgICAgICB0aGlzLmZvckNvbnRhaW5lcnMoYWxsTm9GVywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IERyYWdMaXN0ZW5lckZlYXR1cmUoX3RoaXMuZUNvbnRhaW5lcikpOyB9KTtcbiAgICAgICAgdGhpcy5mb3JDb250YWluZXJzKGFsbENlbnRlciwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IENlbnRlcldpZHRoRmVhdHVyZShmdW5jdGlvbiAod2lkdGgpIHsgcmV0dXJuIF90aGlzLmNvbXAuc2V0Q29udGFpbmVyV2lkdGgod2lkdGggKyBcInB4XCIpOyB9KSk7IH0pO1xuICAgICAgICB0aGlzLmFkZExpc3RlbmVycygpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyV2l0aEN0cmxzU2VydmljZSgpO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1NDUk9MTF9WSVNJQklMSVRZX0NIQU5HRUQsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uU2Nyb2xsVmlzaWJpbGl0eUNoYW5nZWQoKTsgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfQ0hBTkdFRCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCgpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19XSURUSF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5vbkRpc3BsYXllZENvbHVtbnNXaWR0aENoYW5nZWQoKTsgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX1JPV1NfQ0hBTkdFRCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25EaXNwbGF5ZWRSb3dzQ2hhbmdlZCgpOyB9KTtcbiAgICAgICAgdGhpcy5vblNjcm9sbFZpc2liaWxpdHlDaGFuZ2VkKCk7XG4gICAgICAgIHRoaXMub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCgpO1xuICAgICAgICB0aGlzLm9uRGlzcGxheWVkQ29sdW1uc1dpZHRoQ2hhbmdlZCgpO1xuICAgICAgICB0aGlzLm9uRGlzcGxheWVkUm93c0NoYW5nZWQoKTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmxpc3Rlbk9uRG9tT3JkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIHN0aWNreSBzZWN0aW9uIG11c3Qgc2hvdyByb3dzIGluIHNldCBvcmRlclxuICAgICAgICB2YXIgYWxsU3RpY2t5Q29udGFpbmVycyA9IFtSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfTEVGVCwgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX1JJR0hULCBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfRlVMTF9XSURUSF07XG4gICAgICAgIHZhciBpc1N0aWNrQ29udGFpbmVyID0gYWxsU3RpY2t5Q29udGFpbmVycy5pbmRleE9mKHRoaXMubmFtZSkgPj0gMDtcbiAgICAgICAgaWYgKGlzU3RpY2tDb250YWluZXIpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXREb21PcmRlcih0cnVlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb21wLnNldERvbU9yZGVyKF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0Vuc3VyZURvbU9yZGVyKCkpOyB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfRE9NX0xBWU9VVCwgbGlzdGVuZXIpO1xuICAgICAgICBsaXN0ZW5lcigpO1xuICAgIH07XG4gICAgLy8gd2hlbiBlZGl0aW5nIGEgcGlubmVkIHJvdywgaWYgdGhlIGNlbGwgaXMgaGFsZiBvdXRzaWRlIHRoZSBzY3JvbGxhYmxlIGFyZWEsIHRoZSBicm93c2VyIGNhblxuICAgIC8vIHNjcm9sbCB0aGUgY29sdW1uIGludG8gdmlldy4gd2UgZG8gbm90IHdhbnQgdGhpcywgdGhlIHBpbm5lZCBzZWN0aW9ucyBzaG91bGQgbmV2ZXIgc2Nyb2xsLlxuICAgIC8vIHNvIHdlIGxpc3RlbiB0byBzY3JvbGxzIG9uIHRoZXNlIGNvbnRhaW5lcnMgYW5kIHJlc2V0IHRoZSBzY3JvbGwgaWYgd2UgZmluZCBvbmUuXG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuc3RvcEhTY3JvbGxPblBpbm5lZFJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZm9yQ29udGFpbmVycyhbUm93Q29udGFpbmVyTmFtZS5UT1BfQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfQ0VOVEVSLCBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9DRU5URVJdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcmVzZXRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZVZpZXdwb3J0LnNjcm9sbExlZnQgPSAwOyB9O1xuICAgICAgICAgICAgX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKF90aGlzLmVWaWV3cG9ydCwgJ3Njcm9sbCcsIHJlc2V0U2Nyb2xsTGVmdCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5mb3JDb250YWluZXJzKFtSb3dDb250YWluZXJOYW1lLkNFTlRFUl0sIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uSG9yaXpvbnRhbFZpZXdwb3J0Q2hhbmdlZCgpOyB9KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLm9uRGlzcGxheWVkQ29sdW1uc1dpZHRoQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5mb3JDb250YWluZXJzKFtSb3dDb250YWluZXJOYW1lLkNFTlRFUl0sIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm9uSG9yaXpvbnRhbFZpZXdwb3J0Q2hhbmdlZCgpOyB9KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLm9uU2Nyb2xsVmlzaWJpbGl0eUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm5hbWUgIT09IFJvd0NvbnRhaW5lck5hbWUuQ0VOVEVSKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHZpc2libGUgPSB0aGlzLnNjcm9sbFZpc2libGVTZXJ2aWNlLmlzSG9yaXpvbnRhbFNjcm9sbFNob3dpbmcoKTtcbiAgICAgICAgdmFyIHNjcm9sbGJhcldpZHRoID0gdmlzaWJsZSA/ICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRTY3JvbGxiYXJXaWR0aCgpIHx8IDApIDogMDtcbiAgICAgICAgdmFyIGhlaWdodCA9IHNjcm9sbGJhcldpZHRoID09IDAgPyAnMTAwJScgOiBcImNhbGMoMTAwJSArIFwiICsgc2Nyb2xsYmFyV2lkdGggKyBcInB4KVwiO1xuICAgICAgICB0aGlzLmNvbXAuc2V0Vmlld3BvcnRIZWlnaHQoaGVpZ2h0KTtcbiAgICB9O1xuICAgIC8vIHRoaXMgbWV0aG9kcyBwcmV2ZW50cyB0aGUgZ3JpZCB2aWV3cyBmcm9tIGJlaW5nIHNjcm9sbGVkIHdoaWxlIHRoZSBkcmFnU2VydmljZSBpcyBiZWluZyB1c2VkXG4gICAgLy8gZWcuIHRoZSB2aWV3IHNob3VsZCBub3Qgc2Nyb2xsIHVwIGFuZCBkb3duIHdoaWxlIGRyYWdnaW5nIHJvd3MgdXNpbmcgdGhlIHJvd0RyYWdDb21wLlxuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmFkZFByZXZlbnRTY3JvbGxXaGlsZURyYWdnaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcHJldmVudFNjcm9sbCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuZHJhZ1NlcnZpY2UuaXNEcmFnZ2luZygpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUuY2FuY2VsYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmVDb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgcHJldmVudFNjcm9sbCwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5lQ29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHByZXZlbnRTY3JvbGwpOyB9KTtcbiAgICB9O1xuICAgIC8vIHRoaXMgZ2V0cyBjYWxsZWQgd2hlbmV2ZXIgYSBjaGFuZ2UgaW4gdGhlIHZpZXdwb3J0LCBzbyB3ZSBjYW4gaW5mb3JtIGNvbHVtbiBjb250cm9sbGVyIGl0IGhhcyB0byB3b3JrXG4gICAgLy8gb3V0IHRoZSB2aXJ0dWFsIGNvbHVtbnMgYWdhaW4uIGdldHMgY2FsbGVkIGZyb20gZm9sbG93aW5nIGxvY2F0aW9uczpcbiAgICAvLyArIGVuc3VyZUNvbFZpc2libGUsIHNjcm9sbCwgaW5pdCwgbGF5b3V0Q2hhbmdlZCwgZGlzcGxheWVkQ29sdW1uc0NoYW5nZWQsIEFQSSAoZG9MYXlvdXQpXG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUub25Ib3Jpem9udGFsVmlld3BvcnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2Nyb2xsV2lkdGggPSB0aGlzLmdldENlbnRlcldpZHRoKCk7XG4gICAgICAgIHZhciBzY3JvbGxQb3NpdGlvbiA9IHRoaXMuZ2V0Q2VudGVyVmlld3BvcnRTY3JvbGxMZWZ0KCk7XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2V0Vmlld3BvcnRQb3NpdGlvbihzY3JvbGxXaWR0aCwgc2Nyb2xsUG9zaXRpb24pO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuZ2V0Q2VudGVyV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBnZXRJbm5lcldpZHRoKHRoaXMuZVZpZXdwb3J0KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmdldENlbnRlclZpZXdwb3J0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2UgZGVmZXIgdG8gYSB1dGlsLCBhcyBob3cgeW91IGNhbGN1bGF0ZWQgc2Nyb2xsTGVmdCB3aGVuIGRvaW5nIFJUTCBkZXBlbmRzIG9uIHRoZSBicm93c2VyXG4gICAgICAgIHJldHVybiBnZXRTY3JvbGxMZWZ0KHRoaXMuZVZpZXdwb3J0LCB0aGlzLmVuYWJsZVJ0bCk7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5yZWdpc3RlclZpZXdwb3J0UmVzaXplTGlzdGVuZXIgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIHVuc3Vic2NyaWJlRnJvbVJlc2l6ZSA9IHRoaXMucmVzaXplT2JzZXJ2ZXJTZXJ2aWNlLm9ic2VydmVSZXNpemUodGhpcy5lVmlld3BvcnQsIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiB1bnN1YnNjcmliZUZyb21SZXNpemUoKTsgfSk7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5pc1ZpZXdwb3J0VmlzaWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGlzVmlzaWJsZSh0aGlzLmVWaWV3cG9ydCk7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5pc1ZpZXdwb3J0SFNjcm9sbFNob3dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpc0hvcml6b250YWxTY3JvbGxTaG93aW5nKHRoaXMuZVZpZXdwb3J0KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmdldFZpZXdwb3J0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGdldFNjcm9sbExlZnQodGhpcy5lVmlld3BvcnQsIHRoaXMuZW5hYmxlUnRsKTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmlzSG9yaXpvbnRhbFNjcm9sbFNob3dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc0Fsd2F5c1Nob3dIb3Jpem9udGFsU2Nyb2xsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNBbHdheXNTaG93SG9yaXpvbnRhbFNjcm9sbCgpO1xuICAgICAgICByZXR1cm4gaXNBbHdheXNTaG93SG9yaXpvbnRhbFNjcm9sbCB8fCBpc0hvcml6b250YWxTY3JvbGxTaG93aW5nKHRoaXMuZVZpZXdwb3J0KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmdldFZpZXdwb3J0RWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZVZpZXdwb3J0O1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuc2V0Q29udGFpbmVyVHJhbnNsYXRlWCA9IGZ1bmN0aW9uIChhbW91bnQpIHtcbiAgICAgICAgdGhpcy5lQ29udGFpbmVyLnN0eWxlLnRyYW5zZm9ybSA9IFwidHJhbnNsYXRlWChcIiArIGFtb3VudCArIFwicHgpXCI7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5nZXRIU2Nyb2xsUG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXMgPSB7XG4gICAgICAgICAgICBsZWZ0OiB0aGlzLmVWaWV3cG9ydC5zY3JvbGxMZWZ0LFxuICAgICAgICAgICAgcmlnaHQ6IHRoaXMuZVZpZXdwb3J0LnNjcm9sbExlZnQgKyB0aGlzLmVWaWV3cG9ydC5vZmZzZXRXaWR0aFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuc2V0Q2VudGVyVmlld3BvcnRTY3JvbGxMZWZ0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIC8vIHdlIGRlZmVyIHRvIGEgdXRpbCwgYXMgaG93IHlvdSBjYWxjdWxhdGVkIHNjcm9sbExlZnQgd2hlbiBkb2luZyBSVEwgZGVwZW5kcyBvbiB0aGUgYnJvd3NlclxuICAgICAgICBzZXRTY3JvbGxMZWZ0KHRoaXMuZVZpZXdwb3J0LCB2YWx1ZSwgdGhpcy5lbmFibGVSdGwpO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUub25EaXNwbGF5ZWRSb3dzQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGZ1bGxXaXRoQ29udGFpbmVyID0gdGhpcy5uYW1lID09PSBSb3dDb250YWluZXJOYW1lLlRPUF9GVUxMX1dJRFRIXG4gICAgICAgICAgICB8fCB0aGlzLm5hbWUgPT09IFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9GVUxMX1dJRFRIXG4gICAgICAgICAgICB8fCB0aGlzLm5hbWUgPT09IFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX0ZVTExfV0lEVEhcbiAgICAgICAgICAgIHx8IHRoaXMubmFtZSA9PT0gUm93Q29udGFpbmVyTmFtZS5GVUxMX1dJRFRIO1xuICAgICAgICB2YXIgZG9lc1Jvd01hdGNoID0gZnVuY3Rpb24gKHJvd0N0cmwpIHtcbiAgICAgICAgICAgIHZhciBmdWxsV2lkdGhSb3cgPSByb3dDdHJsLmlzRnVsbFdpZHRoKCk7XG4gICAgICAgICAgICB2YXIgcHJpbnRMYXlvdXQgPSBfdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tTGF5b3V0KCkgPT09IENvbnN0YW50cy5ET01fTEFZT1VUX1BSSU5UO1xuICAgICAgICAgICAgdmFyIGVtYmVkRlcgPSBfdGhpcy5lbWJlZEZ1bGxXaWR0aFJvd3MgfHwgcHJpbnRMYXlvdXQ7XG4gICAgICAgICAgICB2YXIgbWF0Y2ggPSBmdWxsV2l0aENvbnRhaW5lciA/XG4gICAgICAgICAgICAgICAgIWVtYmVkRlcgJiYgZnVsbFdpZHRoUm93XG4gICAgICAgICAgICAgICAgOiBlbWJlZEZXIHx8ICFmdWxsV2lkdGhSb3c7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgIH07XG4gICAgICAgIC8vIHRoaXMgbGlzdCBjb250YWlucyBlaXRoZXIgYWxsIHBpbm5lZCB0b3AsIGNlbnRlciBvciBwaW5uZWQgYm90dG9tIHJvd3NcbiAgICAgICAgdmFyIGFsbFJvd3NSZWdhcmRsZXNzT2ZGdWxsV2lkdGggPSB0aGlzLmdldFJvd0N0cmxzKCk7XG4gICAgICAgIC8vIHRoaXMgZmlsdGVycyBvdXQgcm93cyBub3QgZm9yIHRoaXMgY29udGFpbmVyLCBlZyBpZiBpdCdzIGEgZnVsbCB3aXRoIHJvdywgYnV0IHdlIGFyZSBub3QgZnVsbCB3aXRoIGNvbnRhaW5lclxuICAgICAgICB2YXIgcm93c1RoaXNDb250YWluZXIgPSBhbGxSb3dzUmVnYXJkbGVzc09mRnVsbFdpZHRoLmZpbHRlcihkb2VzUm93TWF0Y2gpO1xuICAgICAgICB0aGlzLmNvbXAuc2V0Um93Q3RybHMocm93c1RoaXNDb250YWluZXIpO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuZ2V0Um93Q3RybHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5uYW1lKSB7XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuVE9QX0NFTlRFUjpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfTEVGVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5UT1BfUklHSFQ6XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuVE9QX0ZVTExfV0lEVEg6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93UmVuZGVyZXIuZ2V0VG9wUm93Q3RybHMoKTtcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0NFTlRFUjpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0xFRlQ6XG4gICAgICAgICAgICBjYXNlIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9SSUdIVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0ZVTExfV0lEVEg6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93UmVuZGVyZXIuZ2V0U3RpY2t5VG9wUm93Q3RybHMoKTtcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fQ0VOVEVSOlxuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9MRUZUOlxuICAgICAgICAgICAgY2FzZSBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9SSUdIVDpcbiAgICAgICAgICAgIGNhc2UgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fRlVMTF9XSURUSDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dSZW5kZXJlci5nZXRCb3R0b21Sb3dDdHJscygpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dSZW5kZXJlci5nZXRSb3dDdHJscygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFGKFtcbiAgICAgICAgQXV0b3dpcmVkKCdzY3JvbGxWaXNpYmxlU2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUsIFwic2Nyb2xsVmlzaWJsZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFGKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnU2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUsIFwiZHJhZ1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFGKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUYoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUYoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jlc2l6ZU9ic2VydmVyU2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUsIFwicmVzaXplT2JzZXJ2ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxRihbXG4gICAgICAgIEF1dG93aXJlZCgncm93UmVuZGVyZXInKVxuICAgIF0sIFJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxRihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBSb3dDb250YWluZXJDdHJsO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFMID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxRSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEdSSURfQk9EWV9URU1QTEFURSA9IC8qIGh0bWwgKi8gXCI8ZGl2IGNsYXNzPVxcXCJhZy1yb290IGFnLXVuc2VsZWN0YWJsZVxcXCIgcm9sZT1cXFwiZ3JpZFxcXCI+XFxuICAgICAgICA8YWctaGVhZGVyLXJvb3QgcmVmPVxcXCJncmlkSGVhZGVyXFxcIj48L2FnLWhlYWRlci1yb290PlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZmxvYXRpbmctdG9wXFxcIiByZWY9XFxcImVUb3BcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJ0b3BMZWZ0Q29udGFpbmVyXFxcIiBuYW1lPVxcXCJcIiArIFJvd0NvbnRhaW5lck5hbWUuVE9QX0xFRlQgKyBcIlxcXCI+PC9hZy1yb3ctY29udGFpbmVyPlxcbiAgICAgICAgICAgIDxhZy1yb3ctY29udGFpbmVyIHJlZj1cXFwidG9wQ2VudGVyQ29udGFpbmVyXFxcIiBuYW1lPVxcXCJcIiArIFJvd0NvbnRhaW5lck5hbWUuVE9QX0NFTlRFUiArIFwiXFxcIj48L2FnLXJvdy1jb250YWluZXI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJ0b3BSaWdodENvbnRhaW5lclxcXCIgbmFtZT1cXFwiXCIgKyBSb3dDb250YWluZXJOYW1lLlRPUF9SSUdIVCArIFwiXFxcIj48L2FnLXJvdy1jb250YWluZXI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJ0b3BGdWxsV2lkdGhDb250YWluZXJcXFwiIG5hbWU9XFxcIlwiICsgUm93Q29udGFpbmVyTmFtZS5UT1BfRlVMTF9XSURUSCArIFwiXFxcIj48L2FnLXJvdy1jb250YWluZXI+XFxuICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLWJvZHktdmlld3BvcnRcXFwiIHJlZj1cXFwiZUJvZHlWaWV3cG9ydFxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcImxlZnRDb250YWluZXJcXFwiIG5hbWU9XFxcIlwiICsgUm93Q29udGFpbmVyTmFtZS5MRUZUICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcImNlbnRlckNvbnRhaW5lclxcXCIgbmFtZT1cXFwiXCIgKyBSb3dDb250YWluZXJOYW1lLkNFTlRFUiArIFwiXFxcIj48L2FnLXJvdy1jb250YWluZXI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJyaWdodENvbnRhaW5lclxcXCIgbmFtZT1cXFwiXCIgKyBSb3dDb250YWluZXJOYW1lLlJJR0hUICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcImZ1bGxXaWR0aENvbnRhaW5lclxcXCIgbmFtZT1cXFwiXCIgKyBSb3dDb250YWluZXJOYW1lLkZVTExfV0lEVEggKyBcIlxcXCI+PC9hZy1yb3ctY29udGFpbmVyPlxcbiAgICAgICAgPC9kaXY+XFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1zdGlja3ktdG9wXFxcIiByZWY9XFxcImVTdGlja3lUb3BcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJzdGlja3lUb3BMZWZ0Q29udGFpbmVyXFxcIiBuYW1lPVxcXCJcIiArIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9MRUZUICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcInN0aWNreVRvcENlbnRlckNvbnRhaW5lclxcXCIgbmFtZT1cXFwiXCIgKyBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfQ0VOVEVSICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcInN0aWNreVRvcFJpZ2h0Q29udGFpbmVyXFxcIiBuYW1lPVxcXCJcIiArIFJvd0NvbnRhaW5lck5hbWUuU1RJQ0tZX1RPUF9SSUdIVCArIFwiXFxcIj48L2FnLXJvdy1jb250YWluZXI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJzdGlja3lUb3BGdWxsV2lkdGhDb250YWluZXJcXFwiIG5hbWU9XFxcIlwiICsgUm93Q29udGFpbmVyTmFtZS5TVElDS1lfVE9QX0ZVTExfV0lEVEggKyBcIlxcXCI+PC9hZy1yb3ctY29udGFpbmVyPlxcbiAgICAgICAgPC9kaXY+XFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1mbG9hdGluZy1ib3R0b21cXFwiIHJlZj1cXFwiZUJvdHRvbVxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcImJvdHRvbUxlZnRDb250YWluZXJcXFwiIG5hbWU9XFxcIlwiICsgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fTEVGVCArIFwiXFxcIj48L2FnLXJvdy1jb250YWluZXI+XFxuICAgICAgICAgICAgPGFnLXJvdy1jb250YWluZXIgcmVmPVxcXCJib3R0b21DZW50ZXJDb250YWluZXJcXFwiIG5hbWU9XFxcIlwiICsgUm93Q29udGFpbmVyTmFtZS5CT1RUT01fQ0VOVEVSICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcImJvdHRvbVJpZ2h0Q29udGFpbmVyXFxcIiBuYW1lPVxcXCJcIiArIFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX1JJR0hUICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgICAgICA8YWctcm93LWNvbnRhaW5lciByZWY9XFxcImJvdHRvbUZ1bGxXaWR0aENvbnRhaW5lclxcXCIgbmFtZT1cXFwiXCIgKyBSb3dDb250YWluZXJOYW1lLkJPVFRPTV9GVUxMX1dJRFRIICsgXCJcXFwiPjwvYWctcm93LWNvbnRhaW5lcj5cXG4gICAgICAgIDwvZGl2PlxcbiAgICAgICAgPGFnLWZha2UtaG9yaXpvbnRhbC1zY3JvbGw+PC9hZy1mYWtlLWhvcml6b250YWwtc2Nyb2xsPlxcbiAgICAgICAgPGFnLW92ZXJsYXktd3JhcHBlcj48L2FnLW92ZXJsYXktd3JhcHBlcj5cXG4gICAgPC9kaXY+XCI7XG52YXIgR3JpZEJvZHlDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxTChHcmlkQm9keUNvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gR3JpZEJvZHlDb21wKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgR1JJRF9CT0RZX1RFTVBMQVRFKSB8fCB0aGlzO1xuICAgIH1cbiAgICBHcmlkQm9keUNvbXAucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBzZXRIZWlnaHQgPSBmdW5jdGlvbiAoaGVpZ2h0LCBlbGVtZW50KSB7XG4gICAgICAgICAgICB2YXIgaGVpZ2h0U3RyaW5nID0gaGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZS5taW5IZWlnaHQgPSBoZWlnaHRTdHJpbmc7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlLmhlaWdodCA9IGhlaWdodFN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBQcm94eSA9IHtcbiAgICAgICAgICAgIHNldFJvd0FuaW1hdGlvbkNzc09uQm9keVZpZXdwb3J0OiBmdW5jdGlvbiAoY3NzQ2xhc3MsIGFuaW1hdGUpIHsgcmV0dXJuIF90aGlzLnNldFJvd0FuaW1hdGlvbkNzc09uQm9keVZpZXdwb3J0KGNzc0NsYXNzLCBhbmltYXRlKTsgfSxcbiAgICAgICAgICAgIHNldENvbHVtbkNvdW50OiBmdW5jdGlvbiAoY291bnQpIHsgcmV0dXJuIHNldEFyaWFDb2xDb3VudChfdGhpcy5nZXRHdWkoKSwgY291bnQpOyB9LFxuICAgICAgICAgICAgc2V0Um93Q291bnQ6IGZ1bmN0aW9uIChjb3VudCkgeyByZXR1cm4gc2V0QXJpYVJvd0NvdW50KF90aGlzLmdldEd1aSgpLCBjb3VudCk7IH0sXG4gICAgICAgICAgICBzZXRUb3BIZWlnaHQ6IGZ1bmN0aW9uIChoZWlnaHQpIHsgcmV0dXJuIHNldEhlaWdodChoZWlnaHQsIF90aGlzLmVUb3ApOyB9LFxuICAgICAgICAgICAgc2V0Qm90dG9tSGVpZ2h0OiBmdW5jdGlvbiAoaGVpZ2h0KSB7IHJldHVybiBzZXRIZWlnaHQoaGVpZ2h0LCBfdGhpcy5lQm90dG9tKTsgfSxcbiAgICAgICAgICAgIHNldFRvcERpc3BsYXk6IGZ1bmN0aW9uIChkaXNwbGF5KSB7IHJldHVybiBfdGhpcy5lVG9wLnN0eWxlLmRpc3BsYXkgPSBkaXNwbGF5OyB9LFxuICAgICAgICAgICAgc2V0Qm90dG9tRGlzcGxheTogZnVuY3Rpb24gKGRpc3BsYXkpIHsgcmV0dXJuIF90aGlzLmVCb3R0b20uc3R5bGUuZGlzcGxheSA9IGRpc3BsYXk7IH0sXG4gICAgICAgICAgICBzZXRTdGlja3lUb3BIZWlnaHQ6IGZ1bmN0aW9uIChoZWlnaHQpIHsgcmV0dXJuIF90aGlzLmVTdGlja3lUb3Auc3R5bGUuaGVpZ2h0ID0gaGVpZ2h0OyB9LFxuICAgICAgICAgICAgc2V0U3RpY2t5VG9wVG9wOiBmdW5jdGlvbiAodG9wKSB7IHJldHVybiBfdGhpcy5lU3RpY2t5VG9wLnN0eWxlLnRvcCA9IHRvcDsgfSxcbiAgICAgICAgICAgIHNldFN0aWNreVRvcFdpZHRoOiBmdW5jdGlvbiAod2lkdGgpIHsgcmV0dXJuIF90aGlzLmVTdGlja3lUb3Auc3R5bGUud2lkdGggPSB3aWR0aDsgfSxcbiAgICAgICAgICAgIHNldENvbHVtbk1vdmluZ0NzczogZnVuY3Rpb24gKGNzc0NsYXNzLCBmbGFnKSB7IHJldHVybiBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKENTU19DTEFTU19DT0xVTU5fTU9WSU5HLCBmbGFnKTsgfSxcbiAgICAgICAgICAgIHVwZGF0ZUxheW91dENsYXNzZXM6IGZ1bmN0aW9uIChjc3NDbGFzcywgcGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJvZHlWaWV3cG9ydENsYXNzTGlzdCA9IF90aGlzLmVCb2R5Vmlld3BvcnQuY2xhc3NMaXN0O1xuICAgICAgICAgICAgICAgIGJvZHlWaWV3cG9ydENsYXNzTGlzdC50b2dnbGUoTGF5b3V0Q3NzQ2xhc3Nlcy5BVVRPX0hFSUdIVCwgcGFyYW1zLmF1dG9IZWlnaHQpO1xuICAgICAgICAgICAgICAgIGJvZHlWaWV3cG9ydENsYXNzTGlzdC50b2dnbGUoTGF5b3V0Q3NzQ2xhc3Nlcy5OT1JNQUwsIHBhcmFtcy5ub3JtYWwpO1xuICAgICAgICAgICAgICAgIGJvZHlWaWV3cG9ydENsYXNzTGlzdC50b2dnbGUoTGF5b3V0Q3NzQ2xhc3Nlcy5QUklOVCwgcGFyYW1zLnByaW50KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKExheW91dENzc0NsYXNzZXMuQVVUT19IRUlHSFQsIHBhcmFtcy5hdXRvSGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKExheW91dENzc0NsYXNzZXMuTk9STUFMLCBwYXJhbXMubm9ybWFsKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKExheW91dENzc0NsYXNzZXMuUFJJTlQsIHBhcmFtcy5wcmludCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0QWx3YXlzVmVydGljYWxTY3JvbGxDbGFzczogZnVuY3Rpb24gKGNzc0NsYXNzLCBvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5lQm9keVZpZXdwb3J0LmNsYXNzTGlzdC50b2dnbGUoQ1NTX0NMQVNTX0ZPUkNFX1ZFUlRJQ0FMX1NDUk9MTCwgb24pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlZ2lzdGVyQm9keVZpZXdwb3J0UmVzaXplTGlzdGVuZXI6IGZ1bmN0aW9uIChsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHZhciB1bnN1YnNjcmliZUZyb21SZXNpemUgPSBfdGhpcy5yZXNpemVPYnNlcnZlclNlcnZpY2Uub2JzZXJ2ZVJlc2l6ZShfdGhpcy5lQm9keVZpZXdwb3J0LCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgX3RoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gdW5zdWJzY3JpYmVGcm9tUmVzaXplKCk7IH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldFBpbm5lZFRvcEJvdHRvbU92ZXJmbG93WTogZnVuY3Rpb24gKG92ZXJmbG93KSB7IHJldHVybiBfdGhpcy5lVG9wLnN0eWxlLm92ZXJmbG93WSA9IF90aGlzLmVCb3R0b20uc3R5bGUub3ZlcmZsb3dZID0gb3ZlcmZsb3c7IH0sXG4gICAgICAgICAgICBzZXRDZWxsU2VsZWN0YWJsZUNzczogZnVuY3Rpb24gKGNzc0NsYXNzLCBzZWxlY3RhYmxlKSB7XG4gICAgICAgICAgICAgICAgW190aGlzLmVUb3AsIF90aGlzLmVCb2R5Vmlld3BvcnQsIF90aGlzLmVCb3R0b21dXG4gICAgICAgICAgICAgICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uIChjdCkgeyByZXR1cm4gY3QuY2xhc3NMaXN0LnRvZ2dsZShDU1NfQ0xBU1NfQ0VMTF9TRUxFQ1RBQkxFLCBzZWxlY3RhYmxlKTsgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmN0cmwgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBHcmlkQm9keUN0cmwoKSk7XG4gICAgICAgIHRoaXMuY3RybC5zZXRDb21wKGNvbXBQcm94eSwgdGhpcy5nZXRHdWkoKSwgdGhpcy5lQm9keVZpZXdwb3J0LCB0aGlzLmVUb3AsIHRoaXMuZUJvdHRvbSwgdGhpcy5lU3RpY2t5VG9wKTtcbiAgICAgICAgaWYgKHRoaXMucmFuZ2VTZXJ2aWNlIHx8IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93U2VsZWN0aW9uTXVsdGkoKSkge1xuICAgICAgICAgICAgc2V0QXJpYU11bHRpU2VsZWN0YWJsZSh0aGlzLmdldEd1aSgpLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JpZEJvZHlDb21wLnByb3RvdHlwZS5zZXRSb3dBbmltYXRpb25Dc3NPbkJvZHlWaWV3cG9ydCA9IGZ1bmN0aW9uIChjc3NDbGFzcywgYW5pbWF0ZVJvd3MpIHtcbiAgICAgICAgdmFyIGJvZHlWaWV3cG9ydENsYXNzTGlzdCA9IHRoaXMuZUJvZHlWaWV3cG9ydC5jbGFzc0xpc3Q7XG4gICAgICAgIGJvZHlWaWV3cG9ydENsYXNzTGlzdC50b2dnbGUoUm93QW5pbWF0aW9uQ3NzQ2xhc3Nlcy5BTklNQVRJT05fT04sIGFuaW1hdGVSb3dzKTtcbiAgICAgICAgYm9keVZpZXdwb3J0Q2xhc3NMaXN0LnRvZ2dsZShSb3dBbmltYXRpb25Dc3NDbGFzc2VzLkFOSU1BVElPTl9PRkYsICFhbmltYXRlUm93cyk7XG4gICAgfTtcbiAgICBHcmlkQm9keUNvbXAucHJvdG90eXBlLmdldEZsb2F0aW5nVG9wQm90dG9tID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gW3RoaXMuZVRvcCwgdGhpcy5lQm90dG9tXTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMUUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jlc2l6ZU9ic2VydmVyU2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlDb21wLnByb3RvdHlwZSwgXCJyZXNpemVPYnNlcnZlclNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFFKFtcbiAgICAgICAgT3B0aW9uYWwoJ3JhbmdlU2VydmljZScpXG4gICAgXSwgR3JpZEJvZHlDb21wLnByb3RvdHlwZSwgXCJyYW5nZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFFKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VCb2R5Vmlld3BvcnQnKVxuICAgIF0sIEdyaWRCb2R5Q29tcC5wcm90b3R5cGUsIFwiZUJvZHlWaWV3cG9ydFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVN0aWNreVRvcCcpXG4gICAgXSwgR3JpZEJvZHlDb21wLnByb3RvdHlwZSwgXCJlU3RpY2t5VG9wXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxRShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVG9wJylcbiAgICBdLCBHcmlkQm9keUNvbXAucHJvdG90eXBlLCBcImVUb3BcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFFKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VCb3R0b20nKVxuICAgIF0sIEdyaWRCb2R5Q29tcC5wcm90b3R5cGUsIFwiZUJvdHRvbVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZ3JpZEhlYWRlcicpXG4gICAgXSwgR3JpZEJvZHlDb21wLnByb3RvdHlwZSwgXCJoZWFkZXJSb290Q29tcFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUUoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgR3JpZEJvZHlDb21wLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIHJldHVybiBHcmlkQm9keUNvbXA7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFLID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxRCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFNjcm9sbFZpc2libGVTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxSyhTY3JvbGxWaXNpYmxlU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTY3JvbGxWaXNpYmxlU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBTY3JvbGxWaXNpYmxlU2VydmljZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19DSEFOR0VELCB0aGlzLm9uRGlzcGxheWVkQ29sdW1uc0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfV0lEVEhfQ0hBTkdFRCwgdGhpcy5vbkRpc3BsYXllZENvbHVtbnNXaWR0aENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBTY3JvbGxWaXNpYmxlU2VydmljZS5wcm90b3R5cGUub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICB9O1xuICAgIFNjcm9sbFZpc2libGVTZXJ2aWNlLnByb3RvdHlwZS5vbkRpc3BsYXllZENvbHVtbnNXaWR0aENoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgfTtcbiAgICBTY3JvbGxWaXNpYmxlU2VydmljZS5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBiZWNhdXNlIG9mIGNvbHVtbiBhbmltYXRpb24gKHdoaWNoIHRha2VzIDIwMG1zKSwgd2UgaGF2ZSB0byBkbyB0aGlzIHR3aWNlLlxuICAgICAgICAvLyBlZyBpZiB1c2VyIHJlbW92ZXMgY29scyBhbnl3aGVyZSBleGNlcHQgYXQgdGhlIFJIUywgdGhlbiB0aGUgY29scyBvbiB0aGUgUkhTXG4gICAgICAgIC8vIHdpbGwgYW5pbWF0ZSB0byB0aGUgbGVmdCB0byBmaWxsIHRoZSBnYXAuIHRoaXMgYW5pbWF0aW9uIG1lYW5zIGp1c3QgYWZ0ZXJcbiAgICAgICAgLy8gdGhlIGNvbHMgYXJlIHJlbW92ZWQsIHRoZSByZW1haW5pbmcgY29scyBhcmUgc3RpbGwgaW4gdGhlIG9yaWdpbmFsIGxvY2F0aW9uXG4gICAgICAgIC8vIGF0IHRoZSBzdGFydCBvZiB0aGUgYW5pbWF0aW9uLCBzbyBwcmUgYW5pbWF0aW9uIHRoZSBIIHNjcm9sbGJhciBpcyBzdGlsbCBuZWVkZWQsXG4gICAgICAgIC8vIGJ1dCBwb3N0IGFuaW1hdGlvbiBpdCBpcyBub3QuXG4gICAgICAgIHRoaXMudXBkYXRlSW1wbCgpO1xuICAgICAgICBzZXRUaW1lb3V0KHRoaXMudXBkYXRlSW1wbC5iaW5kKHRoaXMpLCA1MDApO1xuICAgIH07XG4gICAgU2Nyb2xsVmlzaWJsZVNlcnZpY2UucHJvdG90eXBlLnVwZGF0ZUltcGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjZW50ZXJSb3dDdHJsID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0Q2VudGVyUm93Q29udGFpbmVyQ3RybCgpO1xuICAgICAgICBpZiAoIWNlbnRlclJvd0N0cmwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgaG9yaXpvbnRhbFNjcm9sbFNob3dpbmc6IGNlbnRlclJvd0N0cmwuaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZygpLFxuICAgICAgICAgICAgdmVydGljYWxTY3JvbGxTaG93aW5nOiB0aGlzLmlzVmVydGljYWxTY3JvbGxTaG93aW5nKClcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZXRTY3JvbGxzVmlzaWJsZShwYXJhbXMpO1xuICAgIH07XG4gICAgU2Nyb2xsVmlzaWJsZVNlcnZpY2UucHJvdG90eXBlLnNldFNjcm9sbHNWaXNpYmxlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgYXRMZWFzdE9uZURpZmZlcmVudCA9IHRoaXMuaG9yaXpvbnRhbFNjcm9sbFNob3dpbmcgIT09IHBhcmFtcy5ob3Jpem9udGFsU2Nyb2xsU2hvd2luZyB8fFxuICAgICAgICAgICAgdGhpcy52ZXJ0aWNhbFNjcm9sbFNob3dpbmcgIT09IHBhcmFtcy52ZXJ0aWNhbFNjcm9sbFNob3dpbmc7XG4gICAgICAgIGlmIChhdExlYXN0T25lRGlmZmVyZW50KSB7XG4gICAgICAgICAgICB0aGlzLmhvcml6b250YWxTY3JvbGxTaG93aW5nID0gcGFyYW1zLmhvcml6b250YWxTY3JvbGxTaG93aW5nO1xuICAgICAgICAgICAgdGhpcy52ZXJ0aWNhbFNjcm9sbFNob3dpbmcgPSBwYXJhbXMudmVydGljYWxTY3JvbGxTaG93aW5nO1xuICAgICAgICAgICAgdmFyIGV2ZW50XzEgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX1NDUk9MTF9WSVNJQklMSVRZX0NIQU5HRURcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50XzEpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyB1c2VkIGJ5IHBhZ2luYXRpb24gc2VydmljZSAtIHRvIGtub3cgcGFnZSBoZWlnaHRcbiAgICBTY3JvbGxWaXNpYmxlU2VydmljZS5wcm90b3R5cGUuaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaG9yaXpvbnRhbFNjcm9sbFNob3dpbmc7XG4gICAgfTtcbiAgICAvLyB1c2VkIGJ5IGhlYWRlciBjb250YWluZXJcbiAgICBTY3JvbGxWaXNpYmxlU2VydmljZS5wcm90b3R5cGUuaXNWZXJ0aWNhbFNjcm9sbFNob3dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZlcnRpY2FsU2Nyb2xsU2hvd2luZztcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMUQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgU2Nyb2xsVmlzaWJsZVNlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUQoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgU2Nyb2xsVmlzaWJsZVNlcnZpY2UucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgU2Nyb2xsVmlzaWJsZVNlcnZpY2UgPSBfX2RlY29yYXRlJDFEKFtcbiAgICAgICAgQmVhbignc2Nyb2xsVmlzaWJsZVNlcnZpY2UnKVxuICAgIF0sIFNjcm9sbFZpc2libGVTZXJ2aWNlKTtcbiAgICByZXR1cm4gU2Nyb2xsVmlzaWJsZVNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMUogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFDID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgTW91c2VFdmVudFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFKKE1vdXNlRXZlbnRTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIE1vdXNlRXZlbnRTZXJ2aWNlKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZ3JpZEluc3RhbmNlSWQgPSBNb3VzZUV2ZW50U2VydmljZV8xLmdyaWRJbnN0YW5jZVNlcXVlbmNlLm5leHQoKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBNb3VzZUV2ZW50U2VydmljZV8xID0gTW91c2VFdmVudFNlcnZpY2U7XG4gICAgLy8gd2UgcHV0IHRoZSBpbnN0YW5jZSBpZCBvbnRvIHRoZSBtYWluIERPTSBlbGVtZW50LiB0aGlzIGlzIHVzZWQgZm9yIGV2ZW50cywgd2hlbiBncmlkcyBhcmUgaW5zaWRlIGdyaWRzLFxuICAgIC8vIHNvIHRoZSBncmlkIGNhbiB3b3JrIG91dCBpZiB0aGUgZXZlbiBjYW1lIGZyb20gdGhpcyBncmlkIG9yIGEgZ3JpZCBpbnNpZGUgdGhpcyBvbmUuIHNlZSB0aGUgY3RybCt2IGxvZ2ljXG4gICAgLy8gZm9yIHdoZXJlIHRoaXMgaXMgdXNlZC5cbiAgICBNb3VzZUV2ZW50U2VydmljZS5wcm90b3R5cGUuc3RhbXBUb3BMZXZlbEdyaWRDb21wV2l0aEdyaWRJbnN0YW5jZSA9IGZ1bmN0aW9uIChlR3JpZERpdikge1xuICAgICAgICBlR3JpZERpdltNb3VzZUV2ZW50U2VydmljZV8xLkdSSURfRE9NX0tFWV0gPSB0aGlzLmdyaWRJbnN0YW5jZUlkO1xuICAgIH07XG4gICAgTW91c2VFdmVudFNlcnZpY2UucHJvdG90eXBlLmdldFJlbmRlcmVkQ2VsbEZvckV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHJldHVybiBnZXRDdHJsRm9yRXZlbnQodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIGV2ZW50LCBDZWxsQ3RybC5ET01fREFUQV9LRVlfQ0VMTF9DVFJMKTtcbiAgICB9O1xuICAgIC8vIHdhbGtzIHRoZSBwYXRoIG9mIHRoZSBldmVudCwgYW5kIHJldHVybnMgdHJ1ZSBpZiB0aGlzIGdyaWQgaXMgdGhlIGZpcnN0IG9uZSB0aGF0IGl0IGZpbmRzLiBpZiBkb2luZ1xuICAgIC8vIG1hc3RlciAvIGRldGFpbCBncmlkcywgYW5kIGEgY2hpbGQgZ3JpZCBpcyBmb3VuZCwgdGhlbiBpdCByZXR1cm5zIGZhbHNlLiB0aGlzIHN0b3BzIHRoaW5ncyBsaWtlIGNvcHkvcGFzdGVcbiAgICAvLyBnZXR0aW5nIGV4ZWN1dGVkIG9uIG1hbnkgZ3JpZHMgYXQgdGhlIHNhbWUgdGltZS5cbiAgICBNb3VzZUV2ZW50U2VydmljZS5wcm90b3R5cGUuaXNFdmVudEZyb21UaGlzR3JpZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgcmVzID0gdGhpcy5pc0VsZW1lbnRJblRoaXNHcmlkKGV2ZW50LnRhcmdldCk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBNb3VzZUV2ZW50U2VydmljZS5wcm90b3R5cGUuaXNFbGVtZW50SW5UaGlzR3JpZCA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIHZhciBwb2ludGVyID0gZWxlbWVudDtcbiAgICAgICAgd2hpbGUgKHBvaW50ZXIpIHtcbiAgICAgICAgICAgIHZhciBpbnN0YW5jZUlkID0gcG9pbnRlcltNb3VzZUV2ZW50U2VydmljZV8xLkdSSURfRE9NX0tFWV07XG4gICAgICAgICAgICBpZiAoZXhpc3RzKGluc3RhbmNlSWQpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50RnJvbVRoaXNHcmlkID0gaW5zdGFuY2VJZCA9PT0gdGhpcy5ncmlkSW5zdGFuY2VJZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnRGcm9tVGhpc0dyaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIE1vdXNlRXZlbnRTZXJ2aWNlLnByb3RvdHlwZS5nZXRDZWxsUG9zaXRpb25Gb3JFdmVudCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgY2VsbENvbXAgPSB0aGlzLmdldFJlbmRlcmVkQ2VsbEZvckV2ZW50KGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIGNlbGxDb21wID8gY2VsbENvbXAuZ2V0Q2VsbFBvc2l0aW9uKCkgOiBudWxsO1xuICAgIH07XG4gICAgTW91c2VFdmVudFNlcnZpY2UucHJvdG90eXBlLmdldE5vcm1hbGlzZWRQb3NpdGlvbiA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgZ3JpZFBhbmVsSGFzU2Nyb2xscyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvbUxheW91dCgpID09PSBDb25zdGFudHMuRE9NX0xBWU9VVF9OT1JNQUw7XG4gICAgICAgIHZhciBlID0gZXZlbnQ7XG4gICAgICAgIHZhciB4O1xuICAgICAgICB2YXIgeTtcbiAgICAgICAgaWYgKGUuY2xpZW50WCAhPSBudWxsIHx8IGUuY2xpZW50WSAhPSBudWxsKSB7XG4gICAgICAgICAgICB4ID0gZS5jbGllbnRYO1xuICAgICAgICAgICAgeSA9IGUuY2xpZW50WTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHggPSBlLng7XG4gICAgICAgICAgICB5ID0gZS55O1xuICAgICAgICB9XG4gICAgICAgIGlmIChncmlkUGFuZWxIYXNTY3JvbGxzKSB7XG4gICAgICAgICAgICB2YXIgZ3JpZEJvZHlDb24gPSB0aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgICAgIHZhciB2UmFuZ2UgPSBncmlkQm9keUNvbi5nZXRTY3JvbGxGZWF0dXJlKCkuZ2V0VlNjcm9sbFBvc2l0aW9uKCk7XG4gICAgICAgICAgICB2YXIgaFJhbmdlID0gZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmdldEhTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICAgICAgeCArPSBoUmFuZ2UubGVmdDtcbiAgICAgICAgICAgIHkgKz0gdlJhbmdlLnRvcDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB4OiB4LCB5OiB5IH07XG4gICAgfTtcbiAgICB2YXIgTW91c2VFdmVudFNlcnZpY2VfMTtcbiAgICBNb3VzZUV2ZW50U2VydmljZS5ncmlkSW5zdGFuY2VTZXF1ZW5jZSA9IG5ldyBOdW1iZXJTZXF1ZW5jZSgpO1xuICAgIE1vdXNlRXZlbnRTZXJ2aWNlLkdSSURfRE9NX0tFWSA9ICdfX2FnX2dyaWRfaW5zdGFuY2UnO1xuICAgIF9fZGVjb3JhdGUkMUMoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgTW91c2VFdmVudFNlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIE1vdXNlRXZlbnRTZXJ2aWNlID0gTW91c2VFdmVudFNlcnZpY2VfMSA9IF9fZGVjb3JhdGUkMUMoW1xuICAgICAgICBCZWFuKCdtb3VzZUV2ZW50U2VydmljZScpXG4gICAgXSwgTW91c2VFdmVudFNlcnZpY2UpO1xuICAgIHJldHVybiBNb3VzZUV2ZW50U2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxSSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXNzaWduJDQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2Fzc2lnbikgfHwgZnVuY3Rpb24gKCkge1xuICAgIF9fYXNzaWduJDQgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduJDQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgX19kZWNvcmF0ZSQxQiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIE5hdmlnYXRpb25TZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxSShOYXZpZ2F0aW9uU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBOYXZpZ2F0aW9uU2VydmljZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMub25QYWdlRG93biA9IHRocm90dGxlKF90aGlzLm9uUGFnZURvd24sIDEwMCk7XG4gICAgICAgIF90aGlzLm9uUGFnZVVwID0gdGhyb3R0bGUoX3RoaXMub25QYWdlVXAsIDEwMCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLndoZW5SZWFkeShmdW5jdGlvbiAocCkge1xuICAgICAgICAgICAgX3RoaXMuZ3JpZEJvZHlDb24gPSBwLmdyaWRCb2R5Q3RybDtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuaGFuZGxlUGFnZVNjcm9sbGluZ0tleSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIga2V5ID0gZXZlbnQua2V5O1xuICAgICAgICB2YXIgYWx0ID0gZXZlbnQuYWx0S2V5O1xuICAgICAgICB2YXIgY3RybCA9IGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleTtcbiAgICAgICAgdmFyIHJhbmdlU2VydmljZVNob3VsZEhhbmRsZVNoaWZ0ID0gISF0aGlzLnJhbmdlU2VydmljZSAmJiBldmVudC5zaGlmdEtleTtcbiAgICAgICAgdmFyIGN1cnJlbnRDZWxsID0gdGhpcy5tb3VzZUV2ZW50U2VydmljZS5nZXRDZWxsUG9zaXRpb25Gb3JFdmVudChldmVudCk7XG4gICAgICAgIGlmICghY3VycmVudENlbGwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJvY2Vzc2VkID0gZmFsc2U7XG4gICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuUEFHRV9IT01FOlxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlBBR0VfRU5EOlxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSBob21lIGFuZCBlbmQgd2hlbiBjdHJsICYgYWx0IGFyZSBOT1QgcHJlc3NlZFxuICAgICAgICAgICAgICAgIGlmICghY3RybCAmJiAhYWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25Ib21lT3JFbmRLZXkoa2V5KTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuTEVGVDpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5SSUdIVDpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5VUDpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSB3aGVuIGN0cmwgaXMgcHJlc3NlZCBvbmx5LCBpZiBzaGlmdCBpcyBwcmVzc2VkXG4gICAgICAgICAgICAgICAgLy8gaXQgd2lsbCBiZSBoYW5kbGVkIGJ5IHRoZSByYW5nZVNlcnZpY2VcbiAgICAgICAgICAgICAgICBpZiAoY3RybCAmJiAhYWx0ICYmICFyYW5nZVNlcnZpY2VTaG91bGRIYW5kbGVTaGlmdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uQ3RybFVwRG93bkxlZnRSaWdodChrZXksIGN1cnJlbnRDZWxsKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuUEFHRV9ET1dOOlxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSBwYWdlIHVwIGFuZCBwYWdlIGRvd24gd2hlbiBjdHJsICYgYWx0IGFyZSBOT1QgcHJlc3NlZFxuICAgICAgICAgICAgICAgIGlmICghY3RybCAmJiAhYWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25QYWdlRG93bihjdXJyZW50Q2VsbCk7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlBBR0VfVVA6XG4gICAgICAgICAgICAgICAgLy8gaGFuZGxlIHBhZ2UgdXAgYW5kIHBhZ2UgZG93biB3aGVuIGN0cmwgJiBhbHQgYXJlIE5PVCBwcmVzc2VkXG4gICAgICAgICAgICAgICAgaWYgKCFjdHJsICYmICFhbHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblBhZ2VVcChjdXJyZW50Q2VsbCk7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9jZXNzZWQpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZDtcbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5uYXZpZ2F0ZVRvID0gZnVuY3Rpb24gKG5hdmlnYXRlUGFyYW1zKSB7XG4gICAgICAgIHZhciBzY3JvbGxJbmRleCA9IG5hdmlnYXRlUGFyYW1zLnNjcm9sbEluZGV4LCBzY3JvbGxUeXBlID0gbmF2aWdhdGVQYXJhbXMuc2Nyb2xsVHlwZSwgc2Nyb2xsQ29sdW1uID0gbmF2aWdhdGVQYXJhbXMuc2Nyb2xsQ29sdW1uLCBmb2N1c0luZGV4ID0gbmF2aWdhdGVQYXJhbXMuZm9jdXNJbmRleCwgZm9jdXNDb2x1bW4gPSBuYXZpZ2F0ZVBhcmFtcy5mb2N1c0NvbHVtbjtcbiAgICAgICAgaWYgKGV4aXN0cyhzY3JvbGxDb2x1bW4pICYmICFzY3JvbGxDb2x1bW4uaXNQaW5uZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5ncmlkQm9keUNvbi5nZXRTY3JvbGxGZWF0dXJlKCkuZW5zdXJlQ29sdW1uVmlzaWJsZShzY3JvbGxDb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChleGlzdHMoc2Nyb2xsSW5kZXgpKSB7XG4gICAgICAgICAgICB0aGlzLmdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKS5lbnN1cmVJbmRleFZpc2libGUoc2Nyb2xsSW5kZXgsIHNjcm9sbFR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHNldEZvY3VzZWRDZWxsIHJlbGllcyBvbiB0aGUgYnJvd3NlciBkZWZhdWx0IGZvY3VzIGJlaGF2aW9yIHRvIHNjcm9sbCB0aGUgZm9jdXNlZCBjZWxsIGludG8gdmlldyxcbiAgICAgICAgLy8gaG93ZXZlciwgdGhpcyBiZWhhdmlvciB3aWxsIGNhdXNlIHRoZSBjZWxsIGJvcmRlciB0byBiZSBjdXQgb2ZmLCBvciBpZiB3ZSBoYXZlIHN0aWNreSByb3dzLCB0aGVcbiAgICAgICAgLy8gY2VsbCB3aWxsIGJlIGNvbXBsZXRlbHkgaGlkZGVuLCBzbyB3ZSBjYWxsIGVuc3VyZUluZGV4VmlzaWJsZSB3aXRob3V0IGEgcG9zaXRpb24gdG8gZ3VhcmFudGVlXG4gICAgICAgIC8vIG1pbmltYWwgc2Nyb2xsIHRvIGdldCB0aGUgcm93IGludG8gdmlldy5cbiAgICAgICAgaWYgKCFuYXZpZ2F0ZVBhcmFtcy5pc0FzeW5jKSB7XG4gICAgICAgICAgICB0aGlzLmdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKS5lbnN1cmVJbmRleFZpc2libGUoZm9jdXNJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgZG9uJ3QgZG8gdGhpcywgdGhlIHJhbmdlIHdpbGwgYmUgbGVmdCBvbiB0aGUgbGFzdCBjZWxsLCB3aGljaCB3aWxsIGxlYXZlIHRoZSBsYXN0IGZvY3VzZWQgY2VsbFxuICAgICAgICAvLyBoaWdobGlnaHRlZC5cbiAgICAgICAgdGhpcy5mb2N1c1NlcnZpY2Uuc2V0Rm9jdXNlZENlbGwoeyByb3dJbmRleDogZm9jdXNJbmRleCwgY29sdW1uOiBmb2N1c0NvbHVtbiwgcm93UGlubmVkOiBudWxsLCBmb3JjZUJyb3dzZXJGb2N1czogdHJ1ZSB9KTtcbiAgICAgICAgaWYgKHRoaXMucmFuZ2VTZXJ2aWNlKSB7XG4gICAgICAgICAgICB2YXIgY2VsbFBvc2l0aW9uID0geyByb3dJbmRleDogZm9jdXNJbmRleCwgcm93UGlubmVkOiBudWxsLCBjb2x1bW46IGZvY3VzQ29sdW1uIH07XG4gICAgICAgICAgICB0aGlzLnJhbmdlU2VydmljZS5zZXRSYW5nZVRvQ2VsbChjZWxsUG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUub25QYWdlRG93biA9IGZ1bmN0aW9uIChncmlkQ2VsbCkge1xuICAgICAgICB2YXIgZ3JpZEJvZHlDb24gPSB0aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgdmFyIHNjcm9sbFBvc2l0aW9uID0gZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmdldFZTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgICB2YXIgcGl4ZWxzSW5PbmVQYWdlID0gdGhpcy5nZXRWaWV3cG9ydEhlaWdodCgpO1xuICAgICAgICB2YXIgcGFnaW5nUGl4ZWxPZmZzZXQgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQaXhlbE9mZnNldCgpO1xuICAgICAgICB2YXIgY3VycmVudFBhZ2VCb3R0b21QaXhlbCA9IHNjcm9sbFBvc2l0aW9uLnRvcCArIHBpeGVsc0luT25lUGFnZTtcbiAgICAgICAgdmFyIGN1cnJlbnRQYWdlQm90dG9tUm93ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93SW5kZXhBdFBpeGVsKGN1cnJlbnRQYWdlQm90dG9tUGl4ZWwgKyBwYWdpbmdQaXhlbE9mZnNldCk7XG4gICAgICAgIGlmICh0aGlzLmNvbHVtbk1vZGVsLmlzQXV0b1Jvd0hlaWdodEFjdGl2ZSgpKSB7XG4gICAgICAgICAgICB0aGlzLm5hdmlnYXRlVG9OZXh0UGFnZVdpdGhBdXRvSGVpZ2h0KGdyaWRDZWxsLCBjdXJyZW50UGFnZUJvdHRvbVJvdyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm5hdmlnYXRlVG9OZXh0UGFnZShncmlkQ2VsbCwgY3VycmVudFBhZ2VCb3R0b21Sb3cpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUub25QYWdlVXAgPSBmdW5jdGlvbiAoZ3JpZENlbGwpIHtcbiAgICAgICAgdmFyIGdyaWRCb2R5Q29uID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgIHZhciBzY3JvbGxQb3NpdGlvbiA9IGdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKS5nZXRWU2Nyb2xsUG9zaXRpb24oKTtcbiAgICAgICAgdmFyIHBhZ2luZ1BpeGVsT2Zmc2V0ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGl4ZWxPZmZzZXQoKTtcbiAgICAgICAgdmFyIGN1cnJlbnRQYWdlVG9wUGl4ZWwgPSBzY3JvbGxQb3NpdGlvbi50b3A7XG4gICAgICAgIHZhciBjdXJyZW50UGFnZVRvcFJvdyA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFJvd0luZGV4QXRQaXhlbChjdXJyZW50UGFnZVRvcFBpeGVsICsgcGFnaW5nUGl4ZWxPZmZzZXQpO1xuICAgICAgICBpZiAodGhpcy5jb2x1bW5Nb2RlbC5pc0F1dG9Sb3dIZWlnaHRBY3RpdmUoKSkge1xuICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVRvTmV4dFBhZ2VXaXRoQXV0b0hlaWdodChncmlkQ2VsbCwgY3VycmVudFBhZ2VUb3BSb3csIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVRvTmV4dFBhZ2UoZ3JpZENlbGwsIGN1cnJlbnRQYWdlVG9wUm93LCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLm5hdmlnYXRlVG9OZXh0UGFnZSA9IGZ1bmN0aW9uIChncmlkQ2VsbCwgc2Nyb2xsSW5kZXgsIHVwKSB7XG4gICAgICAgIGlmICh1cCA9PT0gdm9pZCAwKSB7IHVwID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgdmFyIHBpeGVsc0luT25lUGFnZSA9IHRoaXMuZ2V0Vmlld3BvcnRIZWlnaHQoKTtcbiAgICAgICAgdmFyIGZpcnN0Um93ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGFnZUZpcnN0Um93KCk7XG4gICAgICAgIHZhciBsYXN0Um93ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGFnZUxhc3RSb3coKTtcbiAgICAgICAgdmFyIHBhZ2luZ1BpeGVsT2Zmc2V0ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGl4ZWxPZmZzZXQoKTtcbiAgICAgICAgdmFyIGN1cnJlbnRSb3dOb2RlID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93KGdyaWRDZWxsLnJvd0luZGV4KTtcbiAgICAgICAgdmFyIHJvd1BpeGVsRGlmZiA9IHVwXG4gICAgICAgICAgICA/ICgoKF9hID0gY3VycmVudFJvd05vZGUpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5yb3dIZWlnaHQpIC0gcGl4ZWxzSW5PbmVQYWdlIC0gcGFnaW5nUGl4ZWxPZmZzZXQpXG4gICAgICAgICAgICA6IChwaXhlbHNJbk9uZVBhZ2UgLSBwYWdpbmdQaXhlbE9mZnNldCk7XG4gICAgICAgIHZhciBuZXh0Q2VsbFBpeGVsID0gKChfYiA9IGN1cnJlbnRSb3dOb2RlKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Iucm93VG9wKSArIHJvd1BpeGVsRGlmZjtcbiAgICAgICAgdmFyIGZvY3VzSW5kZXggPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRSb3dJbmRleEF0UGl4ZWwobmV4dENlbGxQaXhlbCArIHBhZ2luZ1BpeGVsT2Zmc2V0KTtcbiAgICAgICAgaWYgKGZvY3VzSW5kZXggPT09IGdyaWRDZWxsLnJvd0luZGV4KSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHVwID8gLTEgOiAxO1xuICAgICAgICAgICAgc2Nyb2xsSW5kZXggPSBmb2N1c0luZGV4ID0gZ3JpZENlbGwucm93SW5kZXggKyBkaWZmO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzY3JvbGxUeXBlO1xuICAgICAgICBpZiAodXApIHtcbiAgICAgICAgICAgIHNjcm9sbFR5cGUgPSAnYm90dG9tJztcbiAgICAgICAgICAgIGlmIChmb2N1c0luZGV4IDwgZmlyc3RSb3cpIHtcbiAgICAgICAgICAgICAgICBmb2N1c0luZGV4ID0gZmlyc3RSb3c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2Nyb2xsSW5kZXggPCBmaXJzdFJvdykge1xuICAgICAgICAgICAgICAgIHNjcm9sbEluZGV4ID0gZmlyc3RSb3c7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzY3JvbGxUeXBlID0gJ3RvcCc7XG4gICAgICAgICAgICBpZiAoZm9jdXNJbmRleCA+IGxhc3RSb3cpIHtcbiAgICAgICAgICAgICAgICBmb2N1c0luZGV4ID0gbGFzdFJvdztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzY3JvbGxJbmRleCA+IGxhc3RSb3cpIHtcbiAgICAgICAgICAgICAgICBzY3JvbGxJbmRleCA9IGxhc3RSb3c7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaXNSb3dUYWxsZXJUaGFuVmlldyhmb2N1c0luZGV4KSkge1xuICAgICAgICAgICAgc2Nyb2xsSW5kZXggPSBmb2N1c0luZGV4O1xuICAgICAgICAgICAgc2Nyb2xsVHlwZSA9ICd0b3AnO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubmF2aWdhdGVUbyh7XG4gICAgICAgICAgICBzY3JvbGxJbmRleDogc2Nyb2xsSW5kZXgsXG4gICAgICAgICAgICBzY3JvbGxUeXBlOiBzY3JvbGxUeXBlLFxuICAgICAgICAgICAgc2Nyb2xsQ29sdW1uOiBudWxsLFxuICAgICAgICAgICAgZm9jdXNJbmRleDogZm9jdXNJbmRleCxcbiAgICAgICAgICAgIGZvY3VzQ29sdW1uOiBncmlkQ2VsbC5jb2x1bW5cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUubmF2aWdhdGVUb05leHRQYWdlV2l0aEF1dG9IZWlnaHQgPSBmdW5jdGlvbiAoZ3JpZENlbGwsIHNjcm9sbEluZGV4LCB1cCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodXAgPT09IHZvaWQgMCkgeyB1cCA9IGZhbHNlOyB9XG4gICAgICAgIC8vIGJlY2F1c2UgYXV0b0hlaWdodCB3aWxsIGNhbGN1bGF0ZSB0aGUgaGVpZ2h0IG9mIHJvd3MgYWZ0ZXIgc2Nyb2xsXG4gICAgICAgIC8vIGZpcnN0IHdlIHNjcm9sbCB0b3dhcmRzIHRoZSByZXF1aXJlZCBwb2ludCwgdGhlbiB3ZSBhZGQgYSBzbWFsbFxuICAgICAgICAvLyBkZWxheSB0byBhbGxvdyB0aGUgaGVpZ2h0IHRvIGJlIHJlY2FsY3VsYXRlZCwgY2hlY2sgd2hpY2ggaW5kZXhcbiAgICAgICAgLy8gc2hvdWxkIGJlIGZvY3VzZWQgYW5kIHRoZW4gZmluYWxseSBuYXZpZ2F0ZSB0byB0aGF0IGluZGV4LlxuICAgICAgICAvLyBUT0RPOiB3ZSBzaG91bGQgcHJvYmFibHkgaGF2ZSBhbiBldmVudCBmaXJlZCBvbmNlIHRvIHNjcm9sbGJhciBoYXNcbiAgICAgICAgLy8gc2V0dGxlZCBhbmQgYWxsIHJvd0hlaWdodHMgaGF2ZSBiZWVuIGNhbGN1bGF0ZWQgaW5zdGVhZCBvZiByZWx5aW5nXG4gICAgICAgIC8vIG9uIGEgc2V0VGltZW91dCBvZiA1MG1zLlxuICAgICAgICB0aGlzLm5hdmlnYXRlVG8oe1xuICAgICAgICAgICAgc2Nyb2xsSW5kZXg6IHNjcm9sbEluZGV4LFxuICAgICAgICAgICAgc2Nyb2xsVHlwZTogdXAgPyAnYm90dG9tJyA6ICd0b3AnLFxuICAgICAgICAgICAgc2Nyb2xsQ29sdW1uOiBudWxsLFxuICAgICAgICAgICAgZm9jdXNJbmRleDogc2Nyb2xsSW5kZXgsXG4gICAgICAgICAgICBmb2N1c0NvbHVtbjogZ3JpZENlbGwuY29sdW1uXG4gICAgICAgIH0pO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBmb2N1c0luZGV4ID0gX3RoaXMuZ2V0TmV4dEZvY3VzSW5kZXhGb3JBdXRvSGVpZ2h0KGdyaWRDZWxsLCB1cCk7XG4gICAgICAgICAgICBfdGhpcy5uYXZpZ2F0ZVRvKHtcbiAgICAgICAgICAgICAgICBzY3JvbGxJbmRleDogc2Nyb2xsSW5kZXgsXG4gICAgICAgICAgICAgICAgc2Nyb2xsVHlwZTogdXAgPyAnYm90dG9tJyA6ICd0b3AnLFxuICAgICAgICAgICAgICAgIHNjcm9sbENvbHVtbjogbnVsbCxcbiAgICAgICAgICAgICAgICBmb2N1c0luZGV4OiBmb2N1c0luZGV4LFxuICAgICAgICAgICAgICAgIGZvY3VzQ29sdW1uOiBncmlkQ2VsbC5jb2x1bW4sXG4gICAgICAgICAgICAgICAgaXNBc3luYzogdHJ1ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIDUwKTtcbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROZXh0Rm9jdXNJbmRleEZvckF1dG9IZWlnaHQgPSBmdW5jdGlvbiAoZ3JpZENlbGwsIHVwKSB7XG4gICAgICAgIGlmICh1cCA9PT0gdm9pZCAwKSB7IHVwID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgc3RlcCA9IHVwID8gLTEgOiAxO1xuICAgICAgICB2YXIgcGl4ZWxzSW5PbmVQYWdlID0gdGhpcy5nZXRWaWV3cG9ydEhlaWdodCgpO1xuICAgICAgICB2YXIgbGFzdFJvd0luZGV4ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGFnZUxhc3RSb3coKTtcbiAgICAgICAgdmFyIHBpeGVsU3VtID0gMDtcbiAgICAgICAgdmFyIGN1cnJlbnRJbmRleCA9IGdyaWRDZWxsLnJvd0luZGV4O1xuICAgICAgICB3aGlsZSAoY3VycmVudEluZGV4ID49IDAgJiYgY3VycmVudEluZGV4IDw9IGxhc3RSb3dJbmRleCkge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRDZWxsID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93KGN1cnJlbnRJbmRleCk7XG4gICAgICAgICAgICBpZiAoY3VycmVudENlbGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudENlbGxIZWlnaHQgPSAoX2EgPSBjdXJyZW50Q2VsbC5yb3dIZWlnaHQsIChfYSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiAwKSk7XG4gICAgICAgICAgICAgICAgaWYgKHBpeGVsU3VtICsgY3VycmVudENlbGxIZWlnaHQgPiBwaXhlbHNJbk9uZVBhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBpeGVsU3VtICs9IGN1cnJlbnRDZWxsSGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudEluZGV4ICs9IHN0ZXA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KDAsIE1hdGgubWluKGN1cnJlbnRJbmRleCwgbGFzdFJvd0luZGV4KSk7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0Vmlld3BvcnRIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBncmlkQm9keUNvbiA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRCb2R5Q3RybCgpO1xuICAgICAgICB2YXIgc2Nyb2xsUG9zaXRpb24gPSBncmlkQm9keUNvbi5nZXRTY3JvbGxGZWF0dXJlKCkuZ2V0VlNjcm9sbFBvc2l0aW9uKCk7XG4gICAgICAgIHZhciBzY3JvbGxiYXJXaWR0aCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFNjcm9sbGJhcldpZHRoKCk7XG4gICAgICAgIHZhciBwaXhlbHNJbk9uZVBhZ2UgPSBzY3JvbGxQb3NpdGlvbi5ib3R0b20gLSBzY3JvbGxQb3NpdGlvbi50b3A7XG4gICAgICAgIGlmICh0aGlzLmN0cmxzU2VydmljZS5nZXRDZW50ZXJSb3dDb250YWluZXJDdHJsKCkuaXNIb3Jpem9udGFsU2Nyb2xsU2hvd2luZygpKSB7XG4gICAgICAgICAgICBwaXhlbHNJbk9uZVBhZ2UgLT0gc2Nyb2xsYmFyV2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBpeGVsc0luT25lUGFnZTtcbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5pc1Jvd1RhbGxlclRoYW5WaWV3ID0gZnVuY3Rpb24gKHJvd0luZGV4KSB7XG4gICAgICAgIHZhciByb3dOb2RlID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93KHJvd0luZGV4KTtcbiAgICAgICAgaWYgKCFyb3dOb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd0hlaWdodCA9IHJvd05vZGUucm93SGVpZ2h0O1xuICAgICAgICBpZiAodHlwZW9mIHJvd0hlaWdodCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcm93SGVpZ2h0ID4gdGhpcy5nZXRWaWV3cG9ydEhlaWdodCgpO1xuICAgIH07XG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLm9uQ3RybFVwRG93bkxlZnRSaWdodCA9IGZ1bmN0aW9uIChrZXksIGdyaWRDZWxsKSB7XG4gICAgICAgIHZhciBjZWxsVG9Gb2N1cyA9IHRoaXMuY2VsbE5hdmlnYXRpb25TZXJ2aWNlLmdldE5leHRDZWxsVG9Gb2N1cyhrZXksIGdyaWRDZWxsLCB0cnVlKTtcbiAgICAgICAgdmFyIHJvd0luZGV4ID0gY2VsbFRvRm9jdXMucm93SW5kZXgsIGNvbHVtbiA9IGNlbGxUb0ZvY3VzLmNvbHVtbjtcbiAgICAgICAgdGhpcy5uYXZpZ2F0ZVRvKHtcbiAgICAgICAgICAgIHNjcm9sbEluZGV4OiByb3dJbmRleCxcbiAgICAgICAgICAgIHNjcm9sbFR5cGU6IG51bGwsXG4gICAgICAgICAgICBzY3JvbGxDb2x1bW46IGNvbHVtbixcbiAgICAgICAgICAgIGZvY3VzSW5kZXg6IHJvd0luZGV4LFxuICAgICAgICAgICAgZm9jdXNDb2x1bW46IGNvbHVtblxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIGhvbWUgYnJpbmdzIGZvY3VzIHRvIHRvcCBsZWZ0IGNlbGwsIGVuZCBicmluZ3MgZm9jdXMgdG8gYm90dG9tIHJpZ2h0LCBncmlkIHNjcm9sbGVkIHRvIGJyaW5nXG4gICAgLy8gc2FtZSBjZWxsIGludG8gdmlldyAod2hpY2ggbWVhbnMgZWl0aGVyIHNjcm9sbCBhbGwgdGhlIHdheSB1cCwgb3IgYWxsIHRoZSB3YXkgZG93bikuXG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLm9uSG9tZU9yRW5kS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgaG9tZUtleSA9IGtleSA9PT0gS2V5Q29kZS5QQUdFX0hPTUU7XG4gICAgICAgIHZhciBhbGxDb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7XG4gICAgICAgIHZhciBjb2x1bW5Ub1NlbGVjdCA9IGhvbWVLZXkgPyBhbGxDb2x1bW5zWzBdIDogbGFzdChhbGxDb2x1bW5zKTtcbiAgICAgICAgdmFyIHNjcm9sbEluZGV4ID0gaG9tZUtleSA/IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VGaXJzdFJvdygpIDogdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGFnZUxhc3RSb3coKTtcbiAgICAgICAgdGhpcy5uYXZpZ2F0ZVRvKHtcbiAgICAgICAgICAgIHNjcm9sbEluZGV4OiBzY3JvbGxJbmRleCxcbiAgICAgICAgICAgIHNjcm9sbFR5cGU6IG51bGwsXG4gICAgICAgICAgICBzY3JvbGxDb2x1bW46IGNvbHVtblRvU2VsZWN0LFxuICAgICAgICAgICAgZm9jdXNJbmRleDogc2Nyb2xsSW5kZXgsXG4gICAgICAgICAgICBmb2N1c0NvbHVtbjogY29sdW1uVG9TZWxlY3RcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyByZXN1bHQgb2Yga2V5Ym9hcmQgZXZlbnRcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUub25UYWJLZXlEb3duID0gZnVuY3Rpb24gKHByZXZpb3VzLCBrZXlib2FyZEV2ZW50KSB7XG4gICAgICAgIHZhciBiYWNrd2FyZHMgPSBrZXlib2FyZEV2ZW50LnNoaWZ0S2V5O1xuICAgICAgICB2YXIgbW92ZWRUb05leHRDZWxsID0gdGhpcy50YWJUb05leHRDZWxsQ29tbW9uKHByZXZpb3VzLCBiYWNrd2FyZHMsIGtleWJvYXJkRXZlbnQpO1xuICAgICAgICBpZiAobW92ZWRUb05leHRDZWxsKSB7XG4gICAgICAgICAgICAvLyBvbmx5IHByZXZlbnQgZGVmYXVsdCBpZiB3ZSBmb3VuZCBhIGNlbGwuIHNvIGlmIHVzZXIgaXMgb24gbGFzdCBjZWxsIGFuZCBoaXRzIHRhYiwgdGhlbiB3ZSBkZWZhdWx0XG4gICAgICAgICAgICAvLyB0byB0aGUgbm9ybWFsIHRhYmJpbmcgc28gdXNlciBjYW4gZXhpdCB0aGUgZ3JpZC5cbiAgICAgICAgICAgIGtleWJvYXJkRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB3ZSBkaWRuJ3QgbW92ZSB0byBuZXh0IGNlbGwsIHRoZW4gbmVlZCB0byB0YWIgb3V0IG9mIHRoZSBjZWxscywgaWUgdG8gdGhlIGhlYWRlciAoaWYgZ29pbmdcbiAgICAgICAgLy8gYmFja3dhcmRzKVxuICAgICAgICBpZiAoYmFja3dhcmRzKSB7XG4gICAgICAgICAgICB2YXIgX2EgPSBwcmV2aW91cy5nZXRSb3dQb3NpdGlvbigpLCByb3dJbmRleCA9IF9hLnJvd0luZGV4LCByb3dQaW5uZWQgPSBfYS5yb3dQaW5uZWQ7XG4gICAgICAgICAgICB2YXIgZmlyc3RSb3cgPSByb3dQaW5uZWQgPyByb3dJbmRleCA9PT0gMCA6IHJvd0luZGV4ID09PSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlRmlyc3RSb3coKTtcbiAgICAgICAgICAgIGlmIChmaXJzdFJvdykge1xuICAgICAgICAgICAgICAgIGtleWJvYXJkRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5mb2N1c0xhc3RIZWFkZXIoa2V5Ym9hcmRFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBpZiB0aGUgY2FzZSBpdCdzIGEgcG9wdXAgZWRpdG9yLCB0aGUgZm9jdXMgaXMgb24gdGhlIGVkaXRvciBhbmQgbm90IHRoZSBwcmV2aW91cyBjZWxsLlxuICAgICAgICAgICAgLy8gaW4gb3JkZXIgZm9yIHRoZSB0YWIgbmF2aWdhdGlvbiB0byB3b3JrLCB3ZSBuZWVkIHRvIGZvY3VzIHRoZSBicm93c2VyIGJhY2sgb250byB0aGVcbiAgICAgICAgICAgIC8vIHByZXZpb3VzIGNlbGwuXG4gICAgICAgICAgICBpZiAocHJldmlvdXMgaW5zdGFuY2VvZiBDZWxsQ3RybCkge1xuICAgICAgICAgICAgICAgIHByZXZpb3VzLmZvY3VzQ2VsbCh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmZvY3VzU2VydmljZS5mb2N1c05leHRHcmlkQ29yZUNvbnRhaW5lcihiYWNrd2FyZHMpKSB7XG4gICAgICAgICAgICAgICAga2V5Ym9hcmRFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBjb21lcyBmcm9tIEFQSVxuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS50YWJUb05leHRDZWxsID0gZnVuY3Rpb24gKGJhY2t3YXJkcywgZXZlbnQpIHtcbiAgICAgICAgdmFyIGZvY3VzZWRDZWxsID0gdGhpcy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNlZENlbGwoKTtcbiAgICAgICAgLy8gaWYgbm8gZm9jdXMsIHRoZW4gY2Fubm90IG5hdmlnYXRlXG4gICAgICAgIGlmICghZm9jdXNlZENlbGwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbE9yUm93ID0gdGhpcy5nZXRDZWxsQnlQb3NpdGlvbihmb2N1c2VkQ2VsbCk7XG4gICAgICAgIC8vIGlmIGNlbGwgaXMgbm90IHJlbmRlcmVkLCBtZWFucyB1c2VyIGhhcyBzY3JvbGxlZCBhd2F5IGZyb20gdGhlIGNlbGxcbiAgICAgICAgLy8gb3IgdGhhdCB0aGUgZm9jdXNlZENlbGwgaXMgYSBGdWxsIFdpZHRoIFJvd1xuICAgICAgICBpZiAoIWNlbGxPclJvdykge1xuICAgICAgICAgICAgY2VsbE9yUm93ID0gdGhpcy5yb3dSZW5kZXJlci5nZXRSb3dCeVBvc2l0aW9uKGZvY3VzZWRDZWxsKTtcbiAgICAgICAgICAgIGlmICghY2VsbE9yUm93IHx8ICFjZWxsT3JSb3cuaXNGdWxsV2lkdGgoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy50YWJUb05leHRDZWxsQ29tbW9uKGNlbGxPclJvdywgYmFja3dhcmRzLCBldmVudCk7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUudGFiVG9OZXh0Q2VsbENvbW1vbiA9IGZ1bmN0aW9uIChwcmV2aW91cywgYmFja3dhcmRzLCBldmVudCkge1xuICAgICAgICB2YXIgZWRpdGluZyA9IHByZXZpb3VzLmlzRWRpdGluZygpO1xuICAgICAgICAvLyBpZiBjZWxsIGlzIG5vdCBlZGl0aW5nLCB0aGVyZSBpcyBzdGlsbCBjaGFuY2Ugcm93IGlzIGVkaXRpbmcgaWYgaXQncyBGdWxsIFJvdyBFZGl0aW5nXG4gICAgICAgIGlmICghZWRpdGluZyAmJiBwcmV2aW91cyBpbnN0YW5jZW9mIENlbGxDdHJsKSB7XG4gICAgICAgICAgICB2YXIgY2VsbCA9IHByZXZpb3VzO1xuICAgICAgICAgICAgdmFyIHJvdyA9IGNlbGwuZ2V0Um93Q3RybCgpO1xuICAgICAgICAgICAgaWYgKHJvdykge1xuICAgICAgICAgICAgICAgIGVkaXRpbmcgPSByb3cuaXNFZGl0aW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlcztcbiAgICAgICAgaWYgKGVkaXRpbmcpIHtcbiAgICAgICAgICAgIC8vIGlmIHdlIGFyZSBlZGl0aW5nLCB3ZSBrbm93IGl0J3Mgbm90IGEgRnVsbCBXaWR0aCBSb3cgKFJvd0NvbXApXG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNGdWxsUm93RWRpdCgpKSB7XG4gICAgICAgICAgICAgICAgcmVzID0gdGhpcy5tb3ZlVG9OZXh0RWRpdGluZ1JvdyhwcmV2aW91cywgYmFja3dhcmRzLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXMgPSB0aGlzLm1vdmVUb05leHRFZGl0aW5nQ2VsbChwcmV2aW91cywgYmFja3dhcmRzLCBldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXMgPSB0aGlzLm1vdmVUb05leHRDZWxsTm90RWRpdGluZyhwcmV2aW91cywgYmFja3dhcmRzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBhIGNlbGwgd2Fzbid0IGZvdW5kLCBpdCdzIHBvc3NpYmxlIHRoYXQgZm9jdXMgd2FzIG1vdmVkIHRvIHRoZSBoZWFkZXJcbiAgICAgICAgcmV0dXJuIHJlcyB8fCAhIXRoaXMuZm9jdXNTZXJ2aWNlLmdldEZvY3VzZWRIZWFkZXIoKTtcbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5tb3ZlVG9OZXh0RWRpdGluZ0NlbGwgPSBmdW5jdGlvbiAocHJldmlvdXNDZWxsLCBiYWNrd2FyZHMsIGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudCA9PT0gdm9pZCAwKSB7IGV2ZW50ID0gbnVsbDsgfVxuICAgICAgICB2YXIgcHJldmlvdXNQb3MgPSBwcmV2aW91c0NlbGwuZ2V0Q2VsbFBvc2l0aW9uKCk7XG4gICAgICAgIC8vIGJlZm9yZSB3ZSBzdG9wIGVkaXRpbmcsIHdlIG5lZWQgdG8gZm9jdXMgdGhlIGNlbGwgZWxlbWVudFxuICAgICAgICAvLyBzbyB0aGUgZ3JpZCBkb2Vzbid0IGRldGVjdCB0aGF0IGZvY3VzIGhhcyBsZWZ0IHRoZSBncmlkXG4gICAgICAgIHByZXZpb3VzQ2VsbC5nZXRHdWkoKS5mb2N1cygpO1xuICAgICAgICAvLyBuZWVkIHRvIGRvIHRoaXMgYmVmb3JlIGdldHRpbmcgbmV4dCBjZWxsIHRvIGVkaXQsIGluIGNhc2UgdGhlIG5leHQgY2VsbFxuICAgICAgICAvLyBoYXMgZWRpdGFibGUgZnVuY3Rpb24gKGVnIGNvbERlZi5lZGl0YWJsZT1mdW5jKCkgKSBhbmQgaXQgZGVwZW5kcyBvbiB0aGVcbiAgICAgICAgLy8gcmVzdWx0IG9mIHRoaXMgY2VsbCwgc28gbmVlZCB0byBzYXZlIHVwZGF0ZXMgZnJvbSB0aGUgZmlyc3QgZWRpdCwgaW4gY2FzZVxuICAgICAgICAvLyB0aGUgdmFsdWUgaXMgcmVmZXJlbmNlZCBpbiB0aGUgZnVuY3Rpb24uXG4gICAgICAgIHByZXZpb3VzQ2VsbC5zdG9wRWRpdGluZygpO1xuICAgICAgICAvLyBmaW5kIHRoZSBuZXh0IGNlbGwgdG8gc3RhcnQgZWRpdGluZ1xuICAgICAgICB2YXIgbmV4dENlbGwgPSB0aGlzLmZpbmROZXh0Q2VsbFRvRm9jdXNPbihwcmV2aW91c1BvcywgYmFja3dhcmRzLCB0cnVlKTtcbiAgICAgICAgaWYgKG5leHRDZWxsID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvbmx5IHByZXZlbnQgZGVmYXVsdCBpZiB3ZSBmb3VuZCBhIGNlbGwuIHNvIGlmIHVzZXIgaXMgb24gbGFzdCBjZWxsIGFuZCBoaXRzIHRhYiwgdGhlbiB3ZSBkZWZhdWx0XG4gICAgICAgIC8vIHRvIHRoZSBub3JtYWwgdGFiYmluZyBzbyB1c2VyIGNhbiBleGl0IHRoZSBncmlkLlxuICAgICAgICBuZXh0Q2VsbC5zdGFydEVkaXRpbmcobnVsbCwgbnVsbCwgdHJ1ZSwgZXZlbnQpO1xuICAgICAgICBuZXh0Q2VsbC5mb2N1c0NlbGwoZmFsc2UpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5tb3ZlVG9OZXh0RWRpdGluZ1JvdyA9IGZ1bmN0aW9uIChwcmV2aW91c0NlbGwsIGJhY2t3YXJkcywgZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50ID09PSB2b2lkIDApIHsgZXZlbnQgPSBudWxsOyB9XG4gICAgICAgIHZhciBwcmV2aW91c1BvcyA9IHByZXZpb3VzQ2VsbC5nZXRDZWxsUG9zaXRpb24oKTtcbiAgICAgICAgLy8gZmluZCB0aGUgbmV4dCBjZWxsIHRvIHN0YXJ0IGVkaXRpbmdcbiAgICAgICAgdmFyIG5leHRDZWxsID0gdGhpcy5maW5kTmV4dENlbGxUb0ZvY3VzT24ocHJldmlvdXNQb3MsIGJhY2t3YXJkcywgdHJ1ZSk7XG4gICAgICAgIGlmIChuZXh0Q2VsbCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5leHRQb3MgPSBuZXh0Q2VsbC5nZXRDZWxsUG9zaXRpb24oKTtcbiAgICAgICAgdmFyIHByZXZpb3VzRWRpdGFibGUgPSB0aGlzLmlzQ2VsbEVkaXRhYmxlKHByZXZpb3VzUG9zKTtcbiAgICAgICAgdmFyIG5leHRFZGl0YWJsZSA9IHRoaXMuaXNDZWxsRWRpdGFibGUobmV4dFBvcyk7XG4gICAgICAgIHZhciByb3dzTWF0Y2ggPSBuZXh0UG9zICYmIHByZXZpb3VzUG9zLnJvd0luZGV4ID09PSBuZXh0UG9zLnJvd0luZGV4ICYmIHByZXZpb3VzUG9zLnJvd1Bpbm5lZCA9PT0gbmV4dFBvcy5yb3dQaW5uZWQ7XG4gICAgICAgIGlmIChwcmV2aW91c0VkaXRhYmxlKSB7XG4gICAgICAgICAgICBwcmV2aW91c0NlbGwuc2V0Rm9jdXNPdXRPbkVkaXRvcigpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcm93c01hdGNoKSB7XG4gICAgICAgICAgICB2YXIgcFJvdyA9IHByZXZpb3VzQ2VsbC5nZXRSb3dDdHJsKCk7XG4gICAgICAgICAgICBwUm93LnN0b3BFZGl0aW5nKCk7XG4gICAgICAgICAgICB2YXIgblJvdyA9IG5leHRDZWxsLmdldFJvd0N0cmwoKTtcbiAgICAgICAgICAgIG5Sb3cuc3RhcnRSb3dFZGl0aW5nKHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV4dEVkaXRhYmxlKSB7XG4gICAgICAgICAgICBuZXh0Q2VsbC5zZXRGb2N1c0luT25FZGl0b3IoKTtcbiAgICAgICAgICAgIG5leHRDZWxsLmZvY3VzQ2VsbCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbmV4dENlbGwuZm9jdXNDZWxsKHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLm1vdmVUb05leHRDZWxsTm90RWRpdGluZyA9IGZ1bmN0aW9uIChwcmV2aW91c0NlbGwsIGJhY2t3YXJkcykge1xuICAgICAgICB2YXIgZGlzcGxheWVkQ29sdW1ucyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucygpO1xuICAgICAgICB2YXIgY2VsbFBvcztcbiAgICAgICAgaWYgKHByZXZpb3VzQ2VsbCBpbnN0YW5jZW9mIFJvd0N0cmwpIHtcbiAgICAgICAgICAgIGNlbGxQb3MgPSBfX2Fzc2lnbiQ0KF9fYXNzaWduJDQoe30sIHByZXZpb3VzQ2VsbC5nZXRSb3dQb3NpdGlvbigpKSwgeyBjb2x1bW46IGJhY2t3YXJkcyA/IGRpc3BsYXllZENvbHVtbnNbMF0gOiBsYXN0KGRpc3BsYXllZENvbHVtbnMpIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2VsbFBvcyA9IHByZXZpb3VzQ2VsbC5nZXRDZWxsUG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIHRoZSBuZXh0IGNlbGwgdG8gc3RhcnQgZWRpdGluZ1xuICAgICAgICB2YXIgbmV4dENlbGwgPSB0aGlzLmZpbmROZXh0Q2VsbFRvRm9jdXNPbihjZWxsUG9zLCBiYWNrd2FyZHMsIGZhbHNlKTtcbiAgICAgICAgLy8gb25seSBwcmV2ZW50IGRlZmF1bHQgaWYgd2UgZm91bmQgYSBjZWxsLiBzbyBpZiB1c2VyIGlzIG9uIGxhc3QgY2VsbCBhbmQgaGl0cyB0YWIsIHRoZW4gd2UgZGVmYXVsdFxuICAgICAgICAvLyB0byB0aGUgbm9ybWFsIHRhYmJpbmcgc28gdXNlciBjYW4gZXhpdCB0aGUgZ3JpZC5cbiAgICAgICAgaWYgKG5leHRDZWxsIGluc3RhbmNlb2YgQ2VsbEN0cmwpIHtcbiAgICAgICAgICAgIG5leHRDZWxsLmZvY3VzQ2VsbCh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuZXh0Q2VsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudHJ5VG9Gb2N1c0Z1bGxXaWR0aFJvdyhuZXh0Q2VsbC5nZXRSb3dQb3NpdGlvbigpLCBiYWNrd2FyZHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBleGlzdHMobmV4dENlbGwpO1xuICAgIH07XG4gICAgLy8gY2FsbGVkIGJ5IHRoZSBjZWxsLCB3aGVuIHRhYiBpcyBwcmVzc2VkIHdoaWxlIGVkaXRpbmcuXG4gICAgLy8gQHJldHVybjogUmVuZGVyZWRDZWxsIHdoZW4gbmF2aWdhdGlvbiBzdWNjZXNzZnVsLCBvdGhlcndpc2UgbnVsbFxuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5maW5kTmV4dENlbGxUb0ZvY3VzT24gPSBmdW5jdGlvbiAocHJldmlvdXNQb3NpdGlvbiwgYmFja3dhcmRzLCBzdGFydEVkaXRpbmcpIHtcbiAgICAgICAgdmFyIG5leHRQb3NpdGlvbiA9IHByZXZpb3VzUG9zaXRpb247XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBpZiAocHJldmlvdXNQb3NpdGlvbiAhPT0gbmV4dFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgcHJldmlvdXNQb3NpdGlvbiA9IG5leHRQb3NpdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghYmFja3dhcmRzKSB7XG4gICAgICAgICAgICAgICAgbmV4dFBvc2l0aW9uID0gdGhpcy5nZXRMYXN0Q2VsbE9mQ29sU3BhbihuZXh0UG9zaXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmV4dFBvc2l0aW9uID0gdGhpcy5jZWxsTmF2aWdhdGlvblNlcnZpY2UuZ2V0TmV4dFRhYmJlZENlbGwobmV4dFBvc2l0aW9uLCBiYWNrd2FyZHMpO1xuICAgICAgICAgICAgLy8gYWxsb3cgdXNlciB0byBvdmVycmlkZSB3aGF0IGNlbGwgdG8gZ28gdG8gbmV4dFxuICAgICAgICAgICAgdmFyIHVzZXJGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0VGFiVG9OZXh0Q2VsbEZ1bmMoKTtcbiAgICAgICAgICAgIGlmIChleGlzdHModXNlckZ1bmMpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgYmFja3dhcmRzOiBiYWNrd2FyZHMsXG4gICAgICAgICAgICAgICAgICAgIGVkaXRpbmc6IHN0YXJ0RWRpdGluZyxcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNDZWxsUG9zaXRpb246IHByZXZpb3VzUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgIG5leHRDZWxsUG9zaXRpb246IG5leHRQb3NpdGlvbiA/IG5leHRQb3NpdGlvbiA6IG51bGxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHZhciB1c2VyQ2VsbCA9IHVzZXJGdW5jKHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgaWYgKGV4aXN0cyh1c2VyQ2VsbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJDZWxsLmZsb2F0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiB0YWJUb05leHRDZWxsRnVuYyByZXR1cm4gdHlwZSBzaG91bGQgaGF2ZSBhdHRyaWJ1dGVzOiByb3dJbmRleCwgcm93UGlubmVkLCBjb2x1bW4uIEhvd2V2ZXIgeW91IGhhZCAnZmxvYXRpbmcnLCBtYXliZSB5b3UgbWVhbnQgJ3Jvd1Bpbm5lZCc/XCIpOyB9LCAnbm8gZmxvYXRpbmcgaW4gdXNlckNlbGwnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJDZWxsLnJvd1Bpbm5lZCA9IHVzZXJDZWxsLmZsb2F0aW5nO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG5leHRQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvd0luZGV4OiB1c2VyQ2VsbC5yb3dJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbjogdXNlckNlbGwuY29sdW1uLFxuICAgICAgICAgICAgICAgICAgICAgICAgcm93UGlubmVkOiB1c2VyQ2VsbC5yb3dQaW5uZWRcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRQb3NpdGlvbiA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgbm8gJ25leHQgY2VsbCcsIG1lYW5zIHdlIGhhdmUgZ290IHRvIGxhc3QgY2VsbCBvZiBncmlkLCBzbyBub3RoaW5nIHRvIG1vdmUgdG8sXG4gICAgICAgICAgICAvLyBzbyBib3R0b20gcmlnaHQgY2VsbCBnb2luZyBmb3J3YXJkcywgb3IgdG9wIGxlZnQgZ29pbmcgYmFja3dhcmRzXG4gICAgICAgICAgICBpZiAoIW5leHRQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5leHRQb3NpdGlvbi5yb3dJbmRleCA8IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgaGVhZGVyTGVuID0gdGhpcy5oZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5nZXRIZWFkZXJSb3dDb3VudCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzSGVhZGVyUG9zaXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXJQb3NpdGlvbjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyUm93SW5kZXg6IGhlYWRlckxlbiArIChuZXh0UG9zaXRpb24ucm93SW5kZXgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uOiBuZXh0UG9zaXRpb24uY29sdW1uXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIGVkaXRpbmcsIGJ1dCBjZWxsIG5vdCBlZGl0YWJsZSwgc2tpcCBjZWxsLiB3ZSBkbyB0aGlzIGJlZm9yZSB3ZSBkbyBhbGwgb2ZcbiAgICAgICAgICAgIC8vIHRoZSAnZW5zdXJlIGluZGV4IHZpc2libGUnIGFuZCAnZmx1c2ggYWxsIGZyYW1lcycsIG90aGVyd2lzZSBpZiB3ZSBhcmUgc2tpcHBpbmdcbiAgICAgICAgICAgIC8vIGEgYnVuY2ggb2YgY2VsbHMgKGVnIDEwIHJvd3MpIHRoZW4gYWxsIHRoZSB3b3JrIG9uIGVuc3VyaW5nIGNlbGwgdmlzaWJsZSBpcyB1c2VsZXNzXG4gICAgICAgICAgICAvLyAoZXhjZXB0IGZvciB0aGUgbGFzdCBvbmUpIHdoaWNoIGNhdXNlcyBncmlkIHRvIHN0YWxsIGZvciBhIHdoaWxlLlxuICAgICAgICAgICAgLy8gbm90ZSAtIGZvciBmdWxsIHJvdyBlZGl0LCB3ZSBkbyBmb2N1cyBub24tZWRpdGFibGUgY2VsbHMsIGFzIHRoZSByb3cgc3RheXMgaW4gZWRpdCBtb2RlLlxuICAgICAgICAgICAgdmFyIGZ1bGxSb3dFZGl0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNGdWxsUm93RWRpdCgpO1xuICAgICAgICAgICAgaWYgKHN0YXJ0RWRpdGluZyAmJiAhZnVsbFJvd0VkaXQpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2VsbElzRWRpdGFibGUgPSB0aGlzLmlzQ2VsbEVkaXRhYmxlKG5leHRQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgaWYgKCFjZWxsSXNFZGl0YWJsZSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVuc3VyZUNlbGxWaXNpYmxlKG5leHRQb3NpdGlvbik7XG4gICAgICAgICAgICAvLyB3ZSBoYXZlIHRvIGNhbGwgdGhpcyBhZnRlciBlbnN1cmVDb2x1bW5WaXNpYmxlIC0gb3RoZXJ3aXNlIGl0IGNvdWxkIGJlIGEgdmlydHVhbCBjb2x1bW5cbiAgICAgICAgICAgIC8vIG9yIHJvdyB0aGF0IGlzIG5vdCBjdXJyZW50bHkgaW4gdmlldywgaGVuY2UgdGhlIHJlbmRlcmVkQ2VsbCB3b3VsZCBub3QgZXhpc3RcbiAgICAgICAgICAgIHZhciBuZXh0Q2VsbCA9IHRoaXMuZ2V0Q2VsbEJ5UG9zaXRpb24obmV4dFBvc2l0aW9uKTtcbiAgICAgICAgICAgIC8vIGlmIG5leHQgY2VsbCBpcyBmdWxsV2lkdGggcm93LCB0aGVuIG5vIHJlbmRlcmVkIGNlbGwsXG4gICAgICAgICAgICAvLyBhcyBmdWxsV2lkdGggcm93cyBoYXZlIG5vIGNlbGxzLCBzbyB3ZSBza2lwIGl0XG4gICAgICAgICAgICBpZiAoIW5leHRDZWxsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvdyA9IHRoaXMucm93UmVuZGVyZXIuZ2V0Um93QnlQb3NpdGlvbihuZXh0UG9zaXRpb24pO1xuICAgICAgICAgICAgICAgIGlmICghcm93IHx8ICFyb3cuaXNGdWxsV2lkdGgoKSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb3c7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5leHRDZWxsLmlzU3VwcHJlc3NOYXZpZ2FibGUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYnkgZGVmYXVsdCwgd2hlbiB3ZSBjbGljayBhIGNlbGwsIGl0IGdldHMgc2VsZWN0ZWQgaW50byBhIHJhbmdlLCBzbyB0byBrZWVwIGtleWJvYXJkIG5hdmlnYXRpb25cbiAgICAgICAgICAgIC8vIGNvbnNpc3RlbnQsIHdlIHNldCBpbnRvIHJhbmdlIGhlcmUgYWxzby5cbiAgICAgICAgICAgIGlmICh0aGlzLnJhbmdlU2VydmljZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmFuZ2VTZXJ2aWNlLnNldFJhbmdlVG9DZWxsKG5leHRQb3NpdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB3ZSBzdWNjZXNzZnVsbHkgdGFiYmVkIG9udG8gYSBncmlkIGNlbGwsIHNvIHJldHVybiB0cnVlXG4gICAgICAgICAgICByZXR1cm4gbmV4dENlbGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5pc0NlbGxFZGl0YWJsZSA9IGZ1bmN0aW9uIChjZWxsKSB7XG4gICAgICAgIHZhciByb3dOb2RlID0gdGhpcy5sb29rdXBSb3dOb2RlRm9yQ2VsbChjZWxsKTtcbiAgICAgICAgaWYgKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHJldHVybiBjZWxsLmNvbHVtbi5pc0NlbGxFZGl0YWJsZShyb3dOb2RlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0Q2VsbEJ5UG9zaXRpb24gPSBmdW5jdGlvbiAoY2VsbFBvc2l0aW9uKSB7XG4gICAgICAgIHZhciByb3dDdHJsID0gdGhpcy5yb3dSZW5kZXJlci5nZXRSb3dCeVBvc2l0aW9uKGNlbGxQb3NpdGlvbik7XG4gICAgICAgIGlmICghcm93Q3RybCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd0N0cmwuZ2V0Q2VsbEN0cmwoY2VsbFBvc2l0aW9uLmNvbHVtbik7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUubG9va3VwUm93Tm9kZUZvckNlbGwgPSBmdW5jdGlvbiAoY2VsbCkge1xuICAgICAgICBpZiAoY2VsbC5yb3dQaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfVE9QKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRUb3BSb3coY2VsbC5yb3dJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNlbGwucm93UGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX0JPVFRPTSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkQm90dG9tUm93KGNlbGwucm93SW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRSb3coY2VsbC5yb3dJbmRleCk7XG4gICAgfTtcbiAgICAvLyB3ZSB1c2UgaW5kZXggZm9yIHJvd3MsIGJ1dCBjb2x1bW4gb2JqZWN0IGZvciBjb2x1bW5zLCBhcyB0aGUgbmV4dCBjb2x1bW4gKGJ5IGluZGV4KSBtaWdodCBub3RcbiAgICAvLyBiZSB2aXNpYmxlIChoZWFkZXIgZ3JvdXBpbmcpIHNvIGl0J3Mgbm90IHJlbGlhYmxlLCBzbyB1c2luZyB0aGUgY29sdW1uIG9iamVjdCBpbnN0ZWFkLlxuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5uYXZpZ2F0ZVRvTmV4dENlbGwgPSBmdW5jdGlvbiAoZXZlbnQsIGtleSwgY3VycmVudENlbGwsIGFsbG93VXNlck92ZXJyaWRlKSB7XG4gICAgICAgIC8vIHdlIGtlZXAgc2VhcmNoaW5nIGZvciBhIG5leHQgY2VsbCB1bnRpbCB3ZSBmaW5kIG9uZS4gdGhpcyBpcyBob3cgdGhlIGdyb3VwIHJvd3MgZ2V0IHNraXBwZWRcbiAgICAgICAgdmFyIG5leHRDZWxsID0gY3VycmVudENlbGw7XG4gICAgICAgIHZhciBoaXRFZGdlT2ZHcmlkID0gZmFsc2U7XG4gICAgICAgIHdoaWxlIChuZXh0Q2VsbCAmJiAobmV4dENlbGwgPT09IGN1cnJlbnRDZWxsIHx8ICF0aGlzLmlzVmFsaWROYXZpZ2F0ZUNlbGwobmV4dENlbGwpKSkge1xuICAgICAgICAgICAgLy8gaWYgdGhlIGN1cnJlbnQgY2VsbCBpcyBzcGFubmluZyBhY3Jvc3MgbXVsdGlwbGUgY29sdW1ucywgd2UgbmVlZCB0byBtb3ZlXG4gICAgICAgICAgICAvLyBvdXIgY3VycmVudCBwb3NpdGlvbiB0byBiZSB0aGUgbGFzdCBjZWxsIG9uIHRoZSByaWdodCBiZWZvcmUgZmluZGluZyB0aGVcbiAgICAgICAgICAgIC8vIHRoZSBuZXh0IHRhcmdldC5cbiAgICAgICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gS2V5Q29kZS5MRUZUKSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRDZWxsID0gdGhpcy5nZXRMYXN0Q2VsbE9mQ29sU3BhbihuZXh0Q2VsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoa2V5ID09PSBLZXlDb2RlLlJJR0hUKSB7XG4gICAgICAgICAgICAgICAgbmV4dENlbGwgPSB0aGlzLmdldExhc3RDZWxsT2ZDb2xTcGFuKG5leHRDZWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5leHRDZWxsID0gdGhpcy5jZWxsTmF2aWdhdGlvblNlcnZpY2UuZ2V0TmV4dENlbGxUb0ZvY3VzKGtleSwgbmV4dENlbGwpO1xuICAgICAgICAgICAgLy8gZWcgaWYgZ29pbmcgZG93biwgYW5kIG5leHRDZWxsPXVuZGVmaW5lZCwgbWVhbnMgd2UgYXJlIGdvbmUgcGFzdCB0aGUgbGFzdCByb3dcbiAgICAgICAgICAgIGhpdEVkZ2VPZkdyaWQgPSBtaXNzaW5nKG5leHRDZWxsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGl0RWRnZU9mR3JpZCAmJiBldmVudCAmJiBldmVudC5rZXkgPT09IEtleUNvZGUuVVApIHtcbiAgICAgICAgICAgIG5leHRDZWxsID0ge1xuICAgICAgICAgICAgICAgIHJvd0luZGV4OiAtMSxcbiAgICAgICAgICAgICAgICByb3dQaW5uZWQ6IG51bGwsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBjdXJyZW50Q2VsbC5jb2x1bW5cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWxsb3cgdXNlciB0byBvdmVycmlkZSB3aGF0IGNlbGwgdG8gZ28gdG8gbmV4dC4gd2hlbiBkb2luZyBub3JtYWwgY2VsbCBuYXZpZ2F0aW9uICh3aXRoIGtleXMpXG4gICAgICAgIC8vIHdlIGFsbG93IHRoaXMsIGhvd2V2ZXIgaWYgcHJvY2Vzc2luZyAnZW50ZXIgYWZ0ZXIgZWRpdCcgd2UgZG9uJ3QgYWxsb3cgb3ZlcnJpZGVcbiAgICAgICAgaWYgKGFsbG93VXNlck92ZXJyaWRlKSB7XG4gICAgICAgICAgICB2YXIgdXNlckZ1bmMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXROYXZpZ2F0ZVRvTmV4dENlbGxGdW5jKCk7XG4gICAgICAgICAgICBpZiAoZXhpc3RzKHVzZXJGdW5jKSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5LFxuICAgICAgICAgICAgICAgICAgICBwcmV2aW91c0NlbGxQb3NpdGlvbjogY3VycmVudENlbGwsXG4gICAgICAgICAgICAgICAgICAgIG5leHRDZWxsUG9zaXRpb246IG5leHRDZWxsID8gbmV4dENlbGwgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnRcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHZhciB1c2VyQ2VsbCA9IHVzZXJGdW5jKHBhcmFtcyk7XG4gICAgICAgICAgICAgICAgaWYgKGV4aXN0cyh1c2VyQ2VsbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJDZWxsLmZsb2F0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiB0YWJUb05leHRDZWxsRnVuYyByZXR1cm4gdHlwZSBzaG91bGQgaGF2ZSBhdHRyaWJ1dGVzOiByb3dJbmRleCwgcm93UGlubmVkLCBjb2x1bW4uIEhvd2V2ZXIgeW91IGhhZCAnZmxvYXRpbmcnLCBtYXliZSB5b3UgbWVhbnQgJ3Jvd1Bpbm5lZCc/XCIpOyB9LCAnbm8gZmxvYXRpbmcgaW4gdXNlckNlbGwnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJDZWxsLnJvd1Bpbm5lZCA9IHVzZXJDZWxsLmZsb2F0aW5nO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG5leHRDZWxsID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93UGlubmVkOiB1c2VyQ2VsbC5yb3dQaW5uZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICByb3dJbmRleDogdXNlckNlbGwucm93SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW46IHVzZXJDZWxsLmNvbHVtblxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dENlbGwgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBubyBuZXh0IGNlbGwgbWVhbnMgd2UgaGF2ZSByZWFjaGVkIGEgZ3JpZCBib3VuZGFyeSwgZWcgbGVmdCwgcmlnaHQsIHRvcCBvciBib3R0b20gb2YgZ3JpZFxuICAgICAgICBpZiAoIW5leHRDZWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5leHRDZWxsLnJvd0luZGV4IDwgMCkge1xuICAgICAgICAgICAgdmFyIGhlYWRlckxlbiA9IHRoaXMuaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UuZ2V0SGVhZGVyUm93Q291bnQoKTtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzSGVhZGVyUG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIGhlYWRlclBvc2l0aW9uOiB7IGhlYWRlclJvd0luZGV4OiBoZWFkZXJMZW4gKyAobmV4dENlbGwucm93SW5kZXgpLCBjb2x1bW46IGN1cnJlbnRDZWxsLmNvbHVtbiB9LFxuICAgICAgICAgICAgICAgIGV2ZW50OiBldmVudCB8fCB1bmRlZmluZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGluIGNhc2Ugd2UgaGF2ZSBjb2wgc3Bhbm5pbmcgd2UgZ2V0IHRoZSBjZWxsQ29tcCBhbmQgdXNlIGl0IHRvIGdldCB0aGVcbiAgICAgICAgLy8gcG9zaXRpb24uIFRoaXMgd2FzIHdlIGFsd2F5cyBmb2N1cyB0aGUgZmlyc3QgY2VsbCBpbnNpZGUgdGhlIHNwYW5uaW5nLlxuICAgICAgICB2YXIgbm9ybWFsaXNlZFBvc2l0aW9uID0gdGhpcy5nZXROb3JtYWxpc2VkUG9zaXRpb24obmV4dENlbGwpO1xuICAgICAgICBpZiAobm9ybWFsaXNlZFBvc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmZvY3VzUG9zaXRpb24obm9ybWFsaXNlZFBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudHJ5VG9Gb2N1c0Z1bGxXaWR0aFJvdyhuZXh0Q2VsbCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROb3JtYWxpc2VkUG9zaXRpb24gPSBmdW5jdGlvbiAoY2VsbFBvc2l0aW9uKSB7XG4gICAgICAgIC8vIGVuc3VyZUNlbGxWaXNpYmxlIGZpcnN0LCB0byBtYWtlIHN1cmUgY2VsbCBhdCBwb3NpdGlvbiBpcyByZW5kZXJlZC5cbiAgICAgICAgdGhpcy5lbnN1cmVDZWxsVmlzaWJsZShjZWxsUG9zaXRpb24pO1xuICAgICAgICB2YXIgY2VsbEN0cmwgPSB0aGlzLmdldENlbGxCeVBvc2l0aW9uKGNlbGxQb3NpdGlvbik7XG4gICAgICAgIC8vIG5vdCBndWFyYW50ZWVkIHRvIGhhdmUgYSBjZWxsQ29tcCB3aGVuIHVzaW5nIHRoZSBTU1JNIGFzIGJsb2NrcyBhcmUgbG9hZGluZy5cbiAgICAgICAgaWYgKCFjZWxsQ3RybCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY2VsbFBvc2l0aW9uID0gY2VsbEN0cmwuZ2V0Q2VsbFBvc2l0aW9uKCk7XG4gICAgICAgIC8vIHdlIGNhbGwgdGhpcyBhZ2FpbiwgYXMgbmV4dENlbGwgY2FuIGJlIGRpZmZlcmVudCB0byBpdCdzIHByZXZpb3VzIHZhbHVlIGR1ZSB0byBDb2x1bW4gU3Bhbm5pbmdcbiAgICAgICAgLy8gKGllIGlmIGN1cnNvciBtb3ZpbmcgZnJvbSByaWdodCB0byBsZWZ0LCBhbmQgY2VsbCBpcyBzcGFubmluZyBjb2x1bW5zLCB0aGVuIG5leHRDZWxsIHdhcyB0aGVcbiAgICAgICAgLy8gbGFzdCBjb2x1bW4gaW4gdGhlIGdyb3VwLCBob3dldmVyIG5vdyBpdCdzIHRoZSBmaXJzdCBjb2x1bW4gaW4gdGhlIGdyb3VwKS4gaWYgd2UgZGlkbid0IGRvXG4gICAgICAgIC8vIGVuc3VyZUNlbGxWaXNpYmxlIGFnYWluLCB0aGVuIHdlIGNvdWxkIG9ubHkgYmUgc2hvd2luZyB0aGUgbGFzdCBwb3J0aW9uIChsYXN0IGNvbHVtbikgb2YgdGhlXG4gICAgICAgIC8vIG1lcmdlZCBjZWxscy5cbiAgICAgICAgdGhpcy5lbnN1cmVDZWxsVmlzaWJsZShjZWxsUG9zaXRpb24pO1xuICAgICAgICByZXR1cm4gY2VsbFBvc2l0aW9uO1xuICAgIH07XG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLnRyeVRvRm9jdXNGdWxsV2lkdGhSb3cgPSBmdW5jdGlvbiAocG9zaXRpb24sIGJhY2t3YXJkcykge1xuICAgICAgICBpZiAoYmFja3dhcmRzID09PSB2b2lkIDApIHsgYmFja3dhcmRzID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIGRpc3BsYXllZENvbHVtbnMgPSB0aGlzLmNvbHVtbk1vZGVsLmdldEFsbERpc3BsYXllZENvbHVtbnMoKTtcbiAgICAgICAgdmFyIHJvd0NvbXAgPSB0aGlzLnJvd1JlbmRlcmVyLmdldFJvd0J5UG9zaXRpb24ocG9zaXRpb24pO1xuICAgICAgICBpZiAoIXJvd0NvbXAgfHwgIXJvd0NvbXAuaXNGdWxsV2lkdGgoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjdXJyZW50Q2VsbEZvY3VzZWQgPSB0aGlzLmZvY3VzU2VydmljZS5nZXRGb2N1c2VkQ2VsbCgpO1xuICAgICAgICB2YXIgY2VsbFBvc2l0aW9uID0ge1xuICAgICAgICAgICAgcm93SW5kZXg6IHBvc2l0aW9uLnJvd0luZGV4LFxuICAgICAgICAgICAgcm93UGlubmVkOiBwb3NpdGlvbi5yb3dQaW5uZWQsXG4gICAgICAgICAgICBjb2x1bW46IHBvc2l0aW9uLmNvbHVtbiB8fCAoYmFja3dhcmRzID8gbGFzdChkaXNwbGF5ZWRDb2x1bW5zKSA6IGRpc3BsYXllZENvbHVtbnNbMF0pXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZm9jdXNQb3NpdGlvbihjZWxsUG9zaXRpb24pO1xuICAgICAgICB2YXIgZnJvbUJlbG93ID0gY3VycmVudENlbGxGb2N1c2VkICE9IG51bGwgPyB0aGlzLnJvd1Bvc2l0aW9uVXRpbHMuYmVmb3JlKGNlbGxQb3NpdGlvbiwgY3VycmVudENlbGxGb2N1c2VkKSA6IGZhbHNlO1xuICAgICAgICB2YXIgZm9jdXNFdmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9GVUxMX1dJRFRIX1JPV19GT0NVU0VELFxuICAgICAgICAgICAgcm93SW5kZXg6IGNlbGxQb3NpdGlvbi5yb3dJbmRleCxcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogY2VsbFBvc2l0aW9uLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIGNvbHVtbjogY2VsbFBvc2l0aW9uLmNvbHVtbixcbiAgICAgICAgICAgIGlzRnVsbFdpZHRoQ2VsbDogdHJ1ZSxcbiAgICAgICAgICAgIGZsb2F0aW5nOiBjZWxsUG9zaXRpb24ucm93UGlubmVkLFxuICAgICAgICAgICAgZnJvbUJlbG93OiBmcm9tQmVsb3dcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChmb2N1c0V2ZW50KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZm9jdXNQb3NpdGlvbiA9IGZ1bmN0aW9uIChjZWxsUG9zaXRpb24pIHtcbiAgICAgICAgdGhpcy5mb2N1c1NlcnZpY2Uuc2V0Rm9jdXNlZENlbGwoe1xuICAgICAgICAgICAgcm93SW5kZXg6IGNlbGxQb3NpdGlvbi5yb3dJbmRleCxcbiAgICAgICAgICAgIGNvbHVtbjogY2VsbFBvc2l0aW9uLmNvbHVtbixcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogY2VsbFBvc2l0aW9uLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIGZvcmNlQnJvd3NlckZvY3VzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy5yYW5nZVNlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMucmFuZ2VTZXJ2aWNlLnNldFJhbmdlVG9DZWxsKGNlbGxQb3NpdGlvbik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5pc1ZhbGlkTmF2aWdhdGVDZWxsID0gZnVuY3Rpb24gKGNlbGwpIHtcbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLnJvd1Bvc2l0aW9uVXRpbHMuZ2V0Um93Tm9kZShjZWxsKTtcbiAgICAgICAgLy8gd2UgZG8gbm90IGFsbG93IGZvY3VzaW5nIG9uIGRldGFpbCByb3dzIGFuZCBmdWxsIHdpZHRoIHJvd3NcbiAgICAgICAgcmV0dXJuICEhcm93Tm9kZTtcbiAgICB9O1xuICAgIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRMYXN0Q2VsbE9mQ29sU3BhbiA9IGZ1bmN0aW9uIChjZWxsKSB7XG4gICAgICAgIHZhciBjZWxsQ3RybCA9IHRoaXMuZ2V0Q2VsbEJ5UG9zaXRpb24oY2VsbCk7XG4gICAgICAgIGlmICghY2VsbEN0cmwpIHtcbiAgICAgICAgICAgIHJldHVybiBjZWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2xTcGFubmluZ0xpc3QgPSBjZWxsQ3RybC5nZXRDb2xTcGFubmluZ0xpc3QoKTtcbiAgICAgICAgaWYgKGNvbFNwYW5uaW5nTGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBjZWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByb3dJbmRleDogY2VsbC5yb3dJbmRleCxcbiAgICAgICAgICAgIGNvbHVtbjogbGFzdChjb2xTcGFubmluZ0xpc3QpLFxuICAgICAgICAgICAgcm93UGlubmVkOiBjZWxsLnJvd1Bpbm5lZFxuICAgICAgICB9O1xuICAgIH07XG4gICAgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmVuc3VyZUNlbGxWaXNpYmxlID0gZnVuY3Rpb24gKGdyaWRDZWxsKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdmFyIGlzR3JvdXBTdGlja3lFbmFibGVkID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFJvd3NTdGlja3koKTtcbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLnJvd01vZGVsLmdldFJvdyhncmlkQ2VsbC5yb3dJbmRleCk7XG4gICAgICAgIC8vIHN0aWNreSByb3dzIGFyZSBhbHdheXMgdmlzaWJsZSwgc28gdGhlIGdyaWQgc2hvdWxkbid0IHNjcm9sbCB0byBmb2N1cyB0aGVtLlxuICAgICAgICB2YXIgc2tpcFNjcm9sbFRvUm93ID0gaXNHcm91cFN0aWNreUVuYWJsZWQgJiYgKChfYSA9IHJvd05vZGUpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zdGlja3kpO1xuICAgICAgICAvLyB0aGlzIHNjcm9sbHMgdGhlIHJvdyBpbnRvIHZpZXdcbiAgICAgICAgaWYgKCFza2lwU2Nyb2xsVG9Sb3cgJiYgbWlzc2luZyhncmlkQ2VsbC5yb3dQaW5uZWQpKSB7XG4gICAgICAgICAgICB0aGlzLmdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKS5lbnN1cmVJbmRleFZpc2libGUoZ3JpZENlbGwucm93SW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZ3JpZENlbGwuY29sdW1uLmlzUGlubmVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmVuc3VyZUNvbHVtblZpc2libGUoZ3JpZENlbGwuY29sdW1uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxQihbXG4gICAgICAgIEF1dG93aXJlZCgnbW91c2VFdmVudFNlcnZpY2UnKVxuICAgIF0sIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJtb3VzZUV2ZW50U2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBBdXRvd2lyZWQoJ3BhZ2luYXRpb25Qcm94eScpXG4gICAgXSwgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInBhZ2luYXRpb25Qcm94eVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZvY3VzU2VydmljZScpXG4gICAgXSwgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBPcHRpb25hbCgncmFuZ2VTZXJ2aWNlJylcbiAgICBdLCBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUsIFwicmFuZ2VTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxQihbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFCKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFCKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dSZW5kZXJlcicpXG4gICAgXSwgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxQihbXG4gICAgICAgIEF1dG93aXJlZCgnaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJoZWFkZXJOYXZpZ2F0aW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBBdXRvd2lyZWQoXCJyb3dQb3NpdGlvblV0aWxzXCIpXG4gICAgXSwgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInJvd1Bvc2l0aW9uVXRpbHNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFCKFtcbiAgICAgICAgQXV0b3dpcmVkKFwiY2VsbE5hdmlnYXRpb25TZXJ2aWNlXCIpXG4gICAgXSwgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcImNlbGxOYXZpZ2F0aW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBBdXRvd2lyZWQoXCJwaW5uZWRSb3dNb2RlbFwiKVxuICAgIF0sIE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJwaW5uZWRSb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMUIoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgTmF2aWdhdGlvblNlcnZpY2UgPSBfX2RlY29yYXRlJDFCKFtcbiAgICAgICAgQmVhbignbmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIE5hdmlnYXRpb25TZXJ2aWNlKTtcbiAgICByZXR1cm4gTmF2aWdhdGlvblNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMUggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFBID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgUG9wdXBFZGl0b3JXcmFwcGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxSChQb3B1cEVkaXRvcldyYXBwZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUG9wdXBFZGl0b3JXcmFwcGVyKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCAvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiYWctcG9wdXAtZWRpdG9yXFxcIiB0YWJpbmRleD1cXFwiLTFcXFwiLz5cIikgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFBvcHVwRWRpdG9yV3JhcHBlci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0RG9tRGF0YSh0aGlzLmdldEd1aSgpLCBQb3B1cEVkaXRvcldyYXBwZXIuRE9NX0tFWV9QT1BVUF9FRElUT1JfV1JBUFBFUiwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuYWRkS2V5RG93bkxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBQb3B1cEVkaXRvcldyYXBwZXIucHJvdG90eXBlLmFkZEtleURvd25MaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICB2YXIgcGFyYW1zID0gdGhpcy5wYXJhbXM7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKCFpc1VzZXJTdXBwcmVzc2luZ0tleWJvYXJkRXZlbnQoX3RoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBldmVudCwgcGFyYW1zLm5vZGUsIHBhcmFtcy5jb2x1bW4sIHRydWUpKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zLm9uS2V5RG93bihldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGVHdWksICdrZXlkb3duJywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgUG9wdXBFZGl0b3JXcmFwcGVyLkRPTV9LRVlfUE9QVVBfRURJVE9SX1dSQVBQRVIgPSAncG9wdXBFZGl0b3JXcmFwcGVyJztcbiAgICBfX2RlY29yYXRlJDFBKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFBvcHVwRWRpdG9yV3JhcHBlci5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gUG9wdXBFZGl0b3JXcmFwcGVyO1xufShQb3B1cENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFHID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgQ2VsbENvbXAgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFHKENlbGxDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENlbGxDb21wKGJlYW5zLCBjZWxsQ3RybCwgcHJpbnRMYXlvdXQsIGVSb3csIGVkaXRpbmdSb3cpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgLy8gZXZlcnkgdGltZSB3ZSBnbyBpbnRvIGVkaXQgbW9kZSwgb3IgYmFjayBhZ2FpbiwgdGhpcyBnZXRzIGluY3JlbWVudGVkLlxuICAgICAgICAvLyBpdCdzIHRoZSBjb21wb25lbnRzIHdheSBvZiBkZWFsaW5nIHdpdGggdGhlIGFzeW5jIG5hdHVyZSBvZiBmcmFtZXdvcmsgY29tcG9uZW50cyxcbiAgICAgICAgLy8gc28gaWYgYSBmcmFtZXdvcmsgY29tcG9uZW50IHRha2VzIGEgd2hpbGUgdG8gYmUgY3JlYXRlZCwgd2Uga25vdyBpZiB0aGUgb2JqZWN0XG4gICAgICAgIC8vIGlzIHN0aWxsIHJlbGV2YW50IHdoZW4gY3JlYXRpbmcgaXMgZmluaXNoZWQuIGVnIHdlIGNvdWxkIGNsaWNrIGVkaXQgLyB1bi1lZGl0IDIwXG4gICAgICAgIC8vIHRpbWVzIGJlZm9yZSB0aGUgZmlyc3QgUmVhY3QgZWRpdCBjb21wb25lbnQgY29tZXMgYmFjayAtIHdlIHNob3VsZCBkaXNjYXJkXG4gICAgICAgIC8vIHRoZSBmaXJzdCAxOS5cbiAgICAgICAgX3RoaXMucmVuZGVyZXJWZXJzaW9uID0gMDtcbiAgICAgICAgX3RoaXMuZWRpdG9yVmVyc2lvbiA9IDA7XG4gICAgICAgIF90aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIF90aGlzLmNvbHVtbiA9IGNlbGxDdHJsLmdldENvbHVtbigpO1xuICAgICAgICBfdGhpcy5yb3dOb2RlID0gY2VsbEN0cmwuZ2V0Um93Tm9kZSgpO1xuICAgICAgICBfdGhpcy5yb3dDdHJsID0gY2VsbEN0cmwuZ2V0Um93Q3RybCgpO1xuICAgICAgICBfdGhpcy5lUm93ID0gZVJvdztcbiAgICAgICAgX3RoaXMuc2V0VGVtcGxhdGUoLyogaHRtbCAqLyBcIjxkaXYgY29tcC1pZD1cXFwiXCIgKyBfdGhpcy5nZXRDb21wSWQoKSArIFwiXFxcIi8+XCIpO1xuICAgICAgICB2YXIgZUd1aSA9IF90aGlzLmdldEd1aSgpO1xuICAgICAgICBfdGhpcy5mb3JjZVdyYXBwZXIgPSBjZWxsQ3RybC5pc0ZvcmNlV3JhcHBlcigpO1xuICAgICAgICBfdGhpcy5yZWZyZXNoV3JhcHBlcihmYWxzZSk7XG4gICAgICAgIHZhciBzZXRBdHRyaWJ1dGUgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUsIGVsZW1lbnQpIHtcbiAgICAgICAgICAgIHZhciBhY3R1YWxFbGVtZW50ID0gZWxlbWVudCA/IGVsZW1lbnQgOiBlR3VpO1xuICAgICAgICAgICAgaWYgKHZhbHVlICE9IG51bGwgJiYgdmFsdWUgIT0gJycpIHtcbiAgICAgICAgICAgICAgICBhY3R1YWxFbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhY3R1YWxFbGVtZW50LnJlbW92ZUF0dHJpYnV0ZShuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNvbXBQcm94eSA9IHtcbiAgICAgICAgICAgIGFkZE9yUmVtb3ZlQ3NzQ2xhc3M6IGZ1bmN0aW9uIChjc3NDbGFzc05hbWUsIG9uKSB7IHJldHVybiBfdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKGNzc0NsYXNzTmFtZSwgb24pOyB9LFxuICAgICAgICAgICAgc2V0VXNlclN0eWxlczogZnVuY3Rpb24gKHN0eWxlcykgeyByZXR1cm4gYWRkU3R5bGVzVG9FbGVtZW50KGVHdWksIHN0eWxlcyk7IH0sXG4gICAgICAgICAgICBnZXRGb2N1c2FibGVFbGVtZW50OiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5nZXRGb2N1c2FibGVFbGVtZW50KCk7IH0sXG4gICAgICAgICAgICBzZXRUYWJJbmRleDogZnVuY3Rpb24gKHRhYkluZGV4KSB7IHJldHVybiBzZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgdGFiSW5kZXgudG9TdHJpbmcoKSk7IH0sXG4gICAgICAgICAgICBzZXRSb2xlOiBmdW5jdGlvbiAocm9sZSkgeyByZXR1cm4gc2V0QXJpYVJvbGUoZUd1aSwgcm9sZSk7IH0sXG4gICAgICAgICAgICBzZXRDb2xJZDogZnVuY3Rpb24gKGNvbElkKSB7IHJldHVybiBzZXRBdHRyaWJ1dGUoJ2NvbC1pZCcsIGNvbElkKTsgfSxcbiAgICAgICAgICAgIHNldFRpdGxlOiBmdW5jdGlvbiAodGl0bGUpIHsgcmV0dXJuIHNldEF0dHJpYnV0ZSgndGl0bGUnLCB0aXRsZSk7IH0sXG4gICAgICAgICAgICBzZXRJbmNsdWRlU2VsZWN0aW9uOiBmdW5jdGlvbiAoaW5jbHVkZSkgeyByZXR1cm4gX3RoaXMuaW5jbHVkZVNlbGVjdGlvbiA9IGluY2x1ZGU7IH0sXG4gICAgICAgICAgICBzZXRJbmNsdWRlUm93RHJhZzogZnVuY3Rpb24gKGluY2x1ZGUpIHsgcmV0dXJuIF90aGlzLmluY2x1ZGVSb3dEcmFnID0gaW5jbHVkZTsgfSxcbiAgICAgICAgICAgIHNldEluY2x1ZGVEbmRTb3VyY2U6IGZ1bmN0aW9uIChpbmNsdWRlKSB7IHJldHVybiBfdGhpcy5pbmNsdWRlRG5kU291cmNlID0gaW5jbHVkZTsgfSxcbiAgICAgICAgICAgIHNldFJlbmRlckRldGFpbHM6IGZ1bmN0aW9uIChjb21wRGV0YWlscywgdmFsdWVUb0Rpc3BsYXksIGZvcmNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLnNldFJlbmRlckRldGFpbHMoY29tcERldGFpbHMsIHZhbHVlVG9EaXNwbGF5LCBmb3JjZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0RWRpdERldGFpbHM6IGZ1bmN0aW9uIChjb21wRGV0YWlscywgcG9wdXAsIHBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLnNldEVkaXREZXRhaWxzKGNvbXBEZXRhaWxzLCBwb3B1cCwgcG9zaXRpb24pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldENlbGxFZGl0b3I6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNlbGxFZGl0b3IgfHwgbnVsbDsgfSxcbiAgICAgICAgICAgIGdldENlbGxSZW5kZXJlcjogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY2VsbFJlbmRlcmVyIHx8IG51bGw7IH0sXG4gICAgICAgICAgICBnZXRQYXJlbnRPZlZhbHVlOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5nZXRQYXJlbnRPZlZhbHVlKCk7IH1cbiAgICAgICAgfTtcbiAgICAgICAgX3RoaXMuY2VsbEN0cmwgPSBjZWxsQ3RybDtcbiAgICAgICAgY2VsbEN0cmwuc2V0Q29tcChjb21wUHJveHksIF90aGlzLmdldEd1aSgpLCBfdGhpcy5lQ2VsbFdyYXBwZXIsIHByaW50TGF5b3V0LCBlZGl0aW5nUm93KTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBDZWxsQ29tcC5wcm90b3R5cGUuZ2V0UGFyZW50T2ZWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZUNlbGxWYWx1ZSkge1xuICAgICAgICAgICAgLy8gaWYgbm90IGVkaXRpbmcsIGFuZCB1c2luZyB3cmFwcGVyLCB0aGVuIHZhbHVlIGdvZXMgaW4gZUNlbGxWYWx1ZVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZUNlbGxWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5lQ2VsbFdyYXBwZXIpIHtcbiAgICAgICAgICAgIC8vIGlmIGVkaXRpbmcsIGFuZCB1c2luZyB3cmFwcGVyLCB2YWx1ZSAoY2VsbCBlZGl0b3IpIGdvZXMgaW4gZUNlbGxXcmFwcGVyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lQ2VsbFdyYXBwZXI7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgZWRpdGluZyBvciByZW5kZXJpbmcsIGFuZCBub3QgdXNpbmcgd3JhcHBlciwgdmFsdWUgKG9yIGNvbXApIGlzIGRpcmVjdGx5IGluc2lkZSBjZWxsXG4gICAgICAgIHJldHVybiB0aGlzLmdldEd1aSgpO1xuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLnNldFJlbmRlckRldGFpbHMgPSBmdW5jdGlvbiAoY29tcERldGFpbHMsIHZhbHVlVG9EaXNwbGF5LCBmb3JjZU5ld0NlbGxSZW5kZXJlckluc3RhbmNlKSB7XG4gICAgICAgIC8vIHRoaXMgY2FuIGhhcHBlbiBpZiB0aGUgdXNlcnMgYXNrcyBmb3IgdGhlIGNlbGwgdG8gcmVmcmVzaCwgYnV0IHdlIGFyZSBub3Qgc2hvd2luZyB0aGUgdmFsZSBhcyB3ZSBhcmUgZWRpdGluZ1xuICAgICAgICB2YXIgaXNJbmxpbmVFZGl0aW5nID0gdGhpcy5jZWxsRWRpdG9yICYmICF0aGlzLmNlbGxFZGl0b3JQb3B1cFdyYXBwZXI7XG4gICAgICAgIGlmIChpc0lubGluZUVkaXRpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGlzIG1lYW5zIGZpcnN0UmVuZGVyIHdpbGwgYmUgdHJ1ZSBmb3Igb25lIHBhc3Mgb25seSwgYXMgaXQncyBpbml0aWFsaXNlZCB0byB1bmRlZmluZWRcbiAgICAgICAgdGhpcy5maXJzdFJlbmRlciA9IHRoaXMuZmlyc3RSZW5kZXIgPT0gbnVsbDtcbiAgICAgICAgLy8gaWYgZGlzcGxheSB0ZW1wbGF0ZSBoYXMgY2hhbmdlZCwgbWVhbnMgYW55IHByZXZpb3VzIENlbGwgUmVuZGVyZXIgaXMgaW4gdGhlIHdyb25nIGxvY2F0aW9uXG4gICAgICAgIHZhciBjb250cm9sV3JhcHBlckNoYW5nZWQgPSB0aGlzLnJlZnJlc2hXcmFwcGVyKGZhbHNlKTtcbiAgICAgICAgLy8gYWxsIG9mIHRoZXNlIGhhdmUgZGVwZW5kZW5jaWVzIG9uIHRoZSBlR3VpLCBzbyBvbmx5IGRvIHRoZW0gYWZ0ZXIgZUd1aSBpcyBzZXRcbiAgICAgICAgaWYgKGNvbXBEZXRhaWxzKSB7XG4gICAgICAgICAgICB2YXIgbmV2ZXJSZWZyZXNoID0gZm9yY2VOZXdDZWxsUmVuZGVyZXJJbnN0YW5jZSB8fCBjb250cm9sV3JhcHBlckNoYW5nZWQ7XG4gICAgICAgICAgICB2YXIgY2VsbFJlbmRlcmVyUmVmcmVzaFN1Y2Nlc3NmdWwgPSBuZXZlclJlZnJlc2ggPyBmYWxzZSA6IHRoaXMucmVmcmVzaENlbGxSZW5kZXJlcihjb21wRGV0YWlscyk7XG4gICAgICAgICAgICBpZiAoIWNlbGxSZW5kZXJlclJlZnJlc2hTdWNjZXNzZnVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXN0cm95UmVuZGVyZXIoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNyZWF0ZUNlbGxSZW5kZXJlckluc3RhbmNlKGNvbXBEZXRhaWxzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGVzdHJveVJlbmRlcmVyKCk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFZhbHVlV2l0aG91dENlbGxSZW5kZXJlcih2YWx1ZVRvRGlzcGxheSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5zZXRFZGl0RGV0YWlscyA9IGZ1bmN0aW9uIChjb21wRGV0YWlscywgcG9wdXAsIHBvc2l0aW9uKSB7XG4gICAgICAgIGlmIChjb21wRGV0YWlscykge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVDZWxsRWRpdG9ySW5zdGFuY2UoY29tcERldGFpbHMsIHBvcHVwLCBwb3NpdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3lFZGl0b3IoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLnJlbW92ZUNvbnRyb2xzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNoZWNrYm94U2VsZWN0aW9uQ29tcCA9IHRoaXMuYmVhbnMuY29udGV4dC5kZXN0cm95QmVhbih0aGlzLmNoZWNrYm94U2VsZWN0aW9uQ29tcCk7XG4gICAgICAgIHRoaXMuZG5kU291cmNlQ29tcCA9IHRoaXMuYmVhbnMuY29udGV4dC5kZXN0cm95QmVhbih0aGlzLmRuZFNvdXJjZUNvbXApO1xuICAgICAgICB0aGlzLnJvd0RyYWdnaW5nQ29tcCA9IHRoaXMuYmVhbnMuY29udGV4dC5kZXN0cm95QmVhbih0aGlzLnJvd0RyYWdnaW5nQ29tcCk7XG4gICAgfTtcbiAgICAvLyByZXR1cm5zIHRydWUgaWYgd3JhcHBlciB3YXMgY2hhbmdlZFxuICAgIENlbGxDb21wLnByb3RvdHlwZS5yZWZyZXNoV3JhcHBlciA9IGZ1bmN0aW9uIChlZGl0aW5nKSB7XG4gICAgICAgIHZhciBwcm92aWRpbmdDb250cm9scyA9IHRoaXMuaW5jbHVkZVJvd0RyYWcgfHwgdGhpcy5pbmNsdWRlRG5kU291cmNlIHx8IHRoaXMuaW5jbHVkZVNlbGVjdGlvbjtcbiAgICAgICAgdmFyIHVzaW5nV3JhcHBlciA9IHByb3ZpZGluZ0NvbnRyb2xzIHx8IHRoaXMuZm9yY2VXcmFwcGVyO1xuICAgICAgICB2YXIgcHV0V3JhcHBlckluID0gdXNpbmdXcmFwcGVyICYmIHRoaXMuZUNlbGxXcmFwcGVyID09IG51bGw7XG4gICAgICAgIGlmIChwdXRXcmFwcGVySW4pIHtcbiAgICAgICAgICAgIHRoaXMuZUNlbGxXcmFwcGVyID0gbG9hZFRlbXBsYXRlKFwiPGRpdiBjbGFzcz1cXFwiYWctY2VsbC13cmFwcGVyXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPjwvZGl2PlwiKTtcbiAgICAgICAgICAgIHRoaXMuZ2V0R3VpKCkuYXBwZW5kQ2hpbGQodGhpcy5lQ2VsbFdyYXBwZXIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0YWtlV3JhcHBlck91dCA9ICF1c2luZ1dyYXBwZXIgJiYgdGhpcy5lQ2VsbFdyYXBwZXIgIT0gbnVsbDtcbiAgICAgICAgaWYgKHRha2VXcmFwcGVyT3V0KSB7XG4gICAgICAgICAgICByZW1vdmVGcm9tUGFyZW50KHRoaXMuZUNlbGxXcmFwcGVyKTtcbiAgICAgICAgICAgIHRoaXMuZUNlbGxXcmFwcGVyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctY2VsbC12YWx1ZScsICF1c2luZ1dyYXBwZXIpO1xuICAgICAgICB2YXIgdXNpbmdDZWxsVmFsdWUgPSAhZWRpdGluZyAmJiB1c2luZ1dyYXBwZXI7XG4gICAgICAgIHZhciBwdXRDZWxsVmFsdWVJbiA9IHVzaW5nQ2VsbFZhbHVlICYmIHRoaXMuZUNlbGxWYWx1ZSA9PSBudWxsO1xuICAgICAgICBpZiAocHV0Q2VsbFZhbHVlSW4pIHtcbiAgICAgICAgICAgIHRoaXMuZUNlbGxWYWx1ZSA9IGxvYWRUZW1wbGF0ZShcIjxzcGFuIGNsYXNzPVxcXCJhZy1jZWxsLXZhbHVlXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPjwvc3Bhbj5cIik7XG4gICAgICAgICAgICB0aGlzLmVDZWxsV3JhcHBlci5hcHBlbmRDaGlsZCh0aGlzLmVDZWxsVmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0YWtlQ2VsbFZhbHVlT3V0ID0gIXVzaW5nQ2VsbFZhbHVlICYmIHRoaXMuZUNlbGxWYWx1ZSAhPSBudWxsO1xuICAgICAgICBpZiAodGFrZUNlbGxWYWx1ZU91dCkge1xuICAgICAgICAgICAgcmVtb3ZlRnJvbVBhcmVudCh0aGlzLmVDZWxsVmFsdWUpO1xuICAgICAgICAgICAgdGhpcy5lQ2VsbFZhbHVlID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0ZW1wbGF0ZUNoYW5nZWQgPSBwdXRXcmFwcGVySW4gfHwgdGFrZVdyYXBwZXJPdXQgfHwgcHV0Q2VsbFZhbHVlSW4gfHwgdGFrZUNlbGxWYWx1ZU91dDtcbiAgICAgICAgaWYgKHRlbXBsYXRlQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVDb250cm9scygpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZWRpdGluZyAmJiBwcm92aWRpbmdDb250cm9scykge1xuICAgICAgICAgICAgdGhpcy5hZGRDb250cm9scygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0ZW1wbGF0ZUNoYW5nZWQ7XG4gICAgfTtcbiAgICBDZWxsQ29tcC5wcm90b3R5cGUuYWRkQ29udHJvbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpZCA9IHRoaXMuZUNlbGxWYWx1ZS5pZCA9IFwiY2VsbC1cIiArIHRoaXMuZ2V0Q29tcElkKCk7XG4gICAgICAgIHZhciBkZXNjcmliZWRCeUlkcyA9IFtdO1xuICAgICAgICBpZiAodGhpcy5pbmNsdWRlUm93RHJhZykge1xuICAgICAgICAgICAgaWYgKHRoaXMucm93RHJhZ2dpbmdDb21wID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvd0RyYWdnaW5nQ29tcCA9IHRoaXMuY2VsbEN0cmwuY3JlYXRlUm93RHJhZ0NvbXAoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yb3dEcmFnZ2luZ0NvbXApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcHV0IHRoZSBjaGVja2JveCBpbiBiZWZvcmUgdGhlIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZUNlbGxXcmFwcGVyLmluc2VydEJlZm9yZSh0aGlzLnJvd0RyYWdnaW5nQ29tcC5nZXRHdWkoKSwgdGhpcy5lQ2VsbFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaW5jbHVkZURuZFNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZG5kU291cmNlQ29tcCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kbmRTb3VyY2VDb21wID0gdGhpcy5jZWxsQ3RybC5jcmVhdGVEbmRTb3VyY2UoKTtcbiAgICAgICAgICAgICAgICAvLyBwdXQgdGhlIGNoZWNrYm94IGluIGJlZm9yZSB0aGUgdmFsdWVcbiAgICAgICAgICAgICAgICB0aGlzLmVDZWxsV3JhcHBlci5pbnNlcnRCZWZvcmUodGhpcy5kbmRTb3VyY2VDb21wLmdldEd1aSgpLCB0aGlzLmVDZWxsVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmluY2x1ZGVTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNoZWNrYm94U2VsZWN0aW9uQ29tcCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGVja2JveFNlbGVjdGlvbkNvbXAgPSB0aGlzLmNlbGxDdHJsLmNyZWF0ZVNlbGVjdGlvbkNoZWNrYm94KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5lQ2VsbFdyYXBwZXIuaW5zZXJ0QmVmb3JlKHRoaXMuY2hlY2tib3hTZWxlY3Rpb25Db21wLmdldEd1aSgpLCB0aGlzLmVDZWxsVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVzY3JpYmVkQnlJZHMucHVzaCh0aGlzLmNoZWNrYm94U2VsZWN0aW9uQ29tcC5nZXRDaGVja2JveElkKCkpO1xuICAgICAgICB9XG4gICAgICAgIGRlc2NyaWJlZEJ5SWRzLnB1c2goaWQpO1xuICAgICAgICBzZXRBcmlhRGVzY3JpYmVkQnkodGhpcy5nZXRHdWkoKSwgZGVzY3JpYmVkQnlJZHMuam9pbignICcpKTtcbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5jcmVhdGVDZWxsRWRpdG9ySW5zdGFuY2UgPSBmdW5jdGlvbiAoY29tcERldGFpbHMsIHBvcHVwLCBwb3NpdGlvbikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdmVyc2lvbkNvcHkgPSB0aGlzLmVkaXRvclZlcnNpb247XG4gICAgICAgIHZhciBjZWxsRWRpdG9yUHJvbWlzZSA9IGNvbXBEZXRhaWxzLm5ld0FnU3RhY2tJbnN0YW5jZSgpO1xuICAgICAgICBpZiAoIWNlbGxFZGl0b3JQcm9taXNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gLy8gaWYgZW1wdHksIHVzZXJDb21wb25lbnRGYWN0b3J5IGFscmVhZHkgZGlkIGEgY29uc29sZSBtZXNzYWdlXG4gICAgICAgIHZhciBwYXJhbXMgPSBjb21wRGV0YWlscy5wYXJhbXM7XG4gICAgICAgIGNlbGxFZGl0b3JQcm9taXNlLnRoZW4oZnVuY3Rpb24gKGMpIHsgcmV0dXJuIF90aGlzLmFmdGVyQ2VsbEVkaXRvckNyZWF0ZWQodmVyc2lvbkNvcHksIGMsIHBhcmFtcywgcG9wdXAsIHBvc2l0aW9uKTsgfSk7XG4gICAgICAgIC8vIGlmIHdlIGRvbid0IGRvIHRoaXMsIGFuZCBlZGl0b3IgY29tcG9uZW50IGlzIGFzeW5jLCB0aGVuIHRoZXJlIHdpbGwgYmUgYSBwZXJpb2RcbiAgICAgICAgLy8gd2hlbiB0aGUgY29tcG9uZW50IGlzbid0IHByZXNlbnQgYW5kIGtleWJvYXJkIG5hdmlnYXRpb24gd29uJ3Qgd29yayAtIHNvIGV4YW1wbGVcbiAgICAgICAgLy8gb2YgdXNlciBoaXR0aW5nIHRhYiBxdWlja2x5IChtb3JlIHF1aWNrbHkgdGhhbiByZW5kZXJlcnMgZ2V0dGluZyBjcmVhdGVkKSB3b24ndCB3b3JrXG4gICAgICAgIHZhciBjZWxsRWRpdG9yQXN5bmMgPSBtaXNzaW5nKHRoaXMuY2VsbEVkaXRvcik7XG4gICAgICAgIGlmIChjZWxsRWRpdG9yQXN5bmMgJiYgcGFyYW1zLmNlbGxTdGFydGVkRWRpdCkge1xuICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5mb2N1c0NlbGwodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5pbnNlcnRWYWx1ZVdpdGhvdXRDZWxsUmVuZGVyZXIgPSBmdW5jdGlvbiAodmFsdWVUb0Rpc3BsYXkpIHtcbiAgICAgICAgdmFyIGVQYXJlbnQgPSB0aGlzLmdldFBhcmVudE9mVmFsdWUoKTtcbiAgICAgICAgY2xlYXJFbGVtZW50KGVQYXJlbnQpO1xuICAgICAgICB2YXIgZXNjYXBlZFZhbHVlID0gdmFsdWVUb0Rpc3BsYXkgIT0gbnVsbCA/IGVzY2FwZVN0cmluZyh2YWx1ZVRvRGlzcGxheSkgOiBudWxsO1xuICAgICAgICBpZiAoZXNjYXBlZFZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgIGVQYXJlbnQuaW5uZXJIVE1MID0gZXNjYXBlZFZhbHVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ29tcC5wcm90b3R5cGUuZGVzdHJveUVkaXRvckFuZFJlbmRlcmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3lSZW5kZXJlcigpO1xuICAgICAgICB0aGlzLmRlc3Ryb3lFZGl0b3IoKTtcbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5kZXN0cm95UmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb250ZXh0ID0gdGhpcy5iZWFucy5jb250ZXh0O1xuICAgICAgICB0aGlzLmNlbGxSZW5kZXJlciA9IGNvbnRleHQuZGVzdHJveUJlYW4odGhpcy5jZWxsUmVuZGVyZXIpO1xuICAgICAgICByZW1vdmVGcm9tUGFyZW50KHRoaXMuY2VsbFJlbmRlcmVyR3VpKTtcbiAgICAgICAgdGhpcy5jZWxsUmVuZGVyZXJHdWkgPSBudWxsO1xuICAgICAgICB0aGlzLnJlbmRlcmVyVmVyc2lvbisrO1xuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLmRlc3Ryb3lFZGl0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb250ZXh0ID0gdGhpcy5iZWFucy5jb250ZXh0O1xuICAgICAgICBpZiAodGhpcy5oaWRlRWRpdG9yUG9wdXApIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZUVkaXRvclBvcHVwKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5oaWRlRWRpdG9yUG9wdXAgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuY2VsbEVkaXRvciA9IGNvbnRleHQuZGVzdHJveUJlYW4odGhpcy5jZWxsRWRpdG9yKTtcbiAgICAgICAgdGhpcy5jZWxsRWRpdG9yUG9wdXBXcmFwcGVyID0gY29udGV4dC5kZXN0cm95QmVhbih0aGlzLmNlbGxFZGl0b3JQb3B1cFdyYXBwZXIpO1xuICAgICAgICByZW1vdmVGcm9tUGFyZW50KHRoaXMuY2VsbEVkaXRvckd1aSk7XG4gICAgICAgIHRoaXMuY2VsbEVkaXRvckd1aSA9IG51bGw7XG4gICAgICAgIHRoaXMuZWRpdG9yVmVyc2lvbisrO1xuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLnJlZnJlc2hDZWxsUmVuZGVyZXIgPSBmdW5jdGlvbiAoY29tcENsYXNzQW5kUGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmNlbGxSZW5kZXJlciA9PSBudWxsIHx8IHRoaXMuY2VsbFJlbmRlcmVyLnJlZnJlc2ggPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGRpZmZlcmVudCBDZWxsIFJlbmRlcmVyIGNvbmZpZ3VyZWQgdGhpcyB0aW1lIChlZyB1c2VyIGlzIHVzaW5nIHNlbGVjdG9yLCBhbmRcbiAgICAgICAgLy8gcmV0dXJucyBkaWZmZXJlbnQgY29tcG9uZW50KSB0aGVuIGRvbid0IHJlZnJlc2gsIGZvcmNlIHJlY3JlYXRlIG9mIENlbGwgUmVuZGVyZXJcbiAgICAgICAgaWYgKHRoaXMuY2VsbFJlbmRlcmVyQ2xhc3MgIT09IGNvbXBDbGFzc0FuZFBhcmFtcy5jb21wb25lbnRDbGFzcykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRha2UgYW55IGN1c3RvbSBwYXJhbXMgb2ZmIG9mIHRoZSB1c2VyXG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmNlbGxSZW5kZXJlci5yZWZyZXNoKGNvbXBDbGFzc0FuZFBhcmFtcy5wYXJhbXMpO1xuICAgICAgICAvLyBOT1RFIG9uIHVuZGVmaW5lZDogcHJldmlvdXMgdmVyc2lvbiBvZiB0aGUgY2VsbFJlbmRlcmVyLnJlZnJlc2goKSBpbnRlcmZhY2VcbiAgICAgICAgLy8gcmV0dXJuZWQgbm90aGluZywgaWYgdGhlIG1ldGhvZCBleGlzdGVkLCB3ZSBhc3N1bWVkIGl0IHJlZnJlc2hlZC4gc28gZm9yXG4gICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LCB3ZSBhc3N1bWUgaWYgbWV0aG9kIGV4aXN0cyBhbmQgcmV0dXJucyBub3RoaW5nLFxuICAgICAgICAvLyB0aGF0IGl0IHdhcyBzdWNjZXNzZnVsLlxuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSB0cnVlIHx8IHJlc3VsdCA9PT0gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLmNyZWF0ZUNlbGxSZW5kZXJlckluc3RhbmNlID0gZnVuY3Rpb24gKGNvbXBEZXRhaWxzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIG5ldmVyIHVzZSB0YXNrIHNlcnZpY2UgaWYgYW5ndWxhckNvbXBpbGVSb3dzPXRydWUsIGFzIHRoYXQgYXNzdW1lIHRoZSBjZWxsIHJlbmRlcmVyc1xuICAgICAgICAvLyBhcmUgZmluaXNoZWQgd2hlbiB0aGUgcm93IGlzIGNyZWF0ZWQuIGFsc28gd2UgbmV2ZXIgdXNlIGl0IGlmIGFuaW1hdGlvbiBmcmFtZSBzZXJ2aWNlXG4gICAgICAgIC8vIGlzIHR1cm5lZCBvZmYuXG4gICAgICAgIC8vIGFuZCBsYXN0bHkgd2UgbmV2ZXIgdXNlIGl0IGlmIGRvaW5nIGF1dG8taGVpZ2h0LCBhcyB0aGUgYXV0by1oZWlnaHQgc2VydmljZSBjaGVja3MgdGhlXG4gICAgICAgIC8vIHJvdyBoZWlnaHQgZGlyZWN0bHkgYWZ0ZXIgdGhlIGNlbGwgaXMgY3JlYXRlZCwgaXQgZG9lc24ndCB3YWl0IGFyb3VuZCBmb3IgdGhlIHRhc2tzIHRvIGNvbXBsZXRlXG4gICAgICAgIHZhciBhbmd1bGFyQ29tcGlsZVJvd3MgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5pc0FuZ3VsYXJDb21waWxlUm93cygpO1xuICAgICAgICB2YXIgc3VwcHJlc3NBbmltYXRpb25GcmFtZSA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NBbmltYXRpb25GcmFtZSgpO1xuICAgICAgICB2YXIgdXNlVGFza1NlcnZpY2UgPSAhYW5ndWxhckNvbXBpbGVSb3dzICYmICFzdXBwcmVzc0FuaW1hdGlvbkZyYW1lO1xuICAgICAgICB2YXIgZGlzcGxheUNvbXBvbmVudFZlcnNpb25Db3B5ID0gdGhpcy5yZW5kZXJlclZlcnNpb247XG4gICAgICAgIHZhciBjb21wb25lbnRDbGFzcyA9IGNvbXBEZXRhaWxzLmNvbXBvbmVudENsYXNzO1xuICAgICAgICB2YXIgY3JlYXRlQ2VsbFJlbmRlcmVyRnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFsZVRhc2sgPSBfdGhpcy5yZW5kZXJlclZlcnNpb24gIT09IGRpc3BsYXlDb21wb25lbnRWZXJzaW9uQ29weSB8fCAhX3RoaXMuaXNBbGl2ZSgpO1xuICAgICAgICAgICAgaWYgKHN0YWxlVGFzaykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRoaXMgY2FuIHJldHVybiBudWxsIGluIHRoZSBldmVudCB0aGF0IHRoZSB1c2VyIGhhcyBzd2l0Y2hlZCBmcm9tIGEgcmVuZGVyZXIgY29tcG9uZW50IHRvIG5vdGhpbmcsIGZvciBleGFtcGxlXG4gICAgICAgICAgICAvLyB3aGVuIHVzaW5nIGEgY2VsbFJlbmRlcmVyU2VsZWN0IHRvIHJldHVybiBhIGNvbXBvbmVudCBvciBudWxsIGRlcGVuZGluZyBvbiByb3cgZGF0YSBldGNcbiAgICAgICAgICAgIHZhciBjb21wb25lbnRQcm9taXNlID0gY29tcERldGFpbHMubmV3QWdTdGFja0luc3RhbmNlKCk7XG4gICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSBfdGhpcy5hZnRlckNlbGxSZW5kZXJlckNyZWF0ZWQuYmluZChfdGhpcywgZGlzcGxheUNvbXBvbmVudFZlcnNpb25Db3B5LCBjb21wb25lbnRDbGFzcyk7XG4gICAgICAgICAgICBpZiAoY29tcG9uZW50UHJvbWlzZSkge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudFByb21pc2UudGhlbihjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIHdlIG9ubHkgdXNlIHRhc2sgc2VydmljZSB3aGVuIHJlbmRlcmluZyBmb3IgZmlyc3QgdGltZSwgd2hpY2ggbWVhbnMgaXQgaXMgbm90IHVzZWQgd2hlbiBkb2luZyBlZGl0cy5cbiAgICAgICAgLy8gaWYgd2UgY2hhbmdlZCB0aGlzIChhbHdheXMgdXNlIHRhc2sgc2VydmljZSkgd291bGQgbWFrZSBzZW5zZSwgaG93ZXZlciBpdCB3b3VsZCBicmVhayB0ZXN0cywgcG9zc2libHlcbiAgICAgICAgLy8gdGVzdCBvZiB1c2Vycy5cbiAgICAgICAgaWYgKHVzZVRhc2tTZXJ2aWNlICYmIHRoaXMuZmlyc3RSZW5kZXIpIHtcbiAgICAgICAgICAgIHRoaXMuYmVhbnMuYW5pbWF0aW9uRnJhbWVTZXJ2aWNlLmNyZWF0ZVRhc2soY3JlYXRlQ2VsbFJlbmRlcmVyRnVuYywgdGhpcy5yb3dOb2RlLnJvd0luZGV4LCAnY3JlYXRlVGFza3NQMicpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY3JlYXRlQ2VsbFJlbmRlcmVyRnVuYygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDZWxsQ29tcC5wcm90b3R5cGUuZ2V0Q3RybCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VsbEN0cmw7XG4gICAgfTtcbiAgICBDZWxsQ29tcC5wcm90b3R5cGUuZ2V0Um93Q3RybCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93Q3RybDtcbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5nZXRDZWxsUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNlbGxSZW5kZXJlcjtcbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5nZXRDZWxsRWRpdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZWxsRWRpdG9yO1xuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLmFmdGVyQ2VsbFJlbmRlcmVyQ3JlYXRlZCA9IGZ1bmN0aW9uIChjZWxsUmVuZGVyZXJWZXJzaW9uLCBjZWxsUmVuZGVyZXJDbGFzcywgY2VsbFJlbmRlcmVyKSB7XG4gICAgICAgIHZhciBzdGFsZVRhc2sgPSAhdGhpcy5pc0FsaXZlKCkgfHwgY2VsbFJlbmRlcmVyVmVyc2lvbiAhPT0gdGhpcy5yZW5kZXJlclZlcnNpb247XG4gICAgICAgIGlmIChzdGFsZVRhc2spIHtcbiAgICAgICAgICAgIHRoaXMuYmVhbnMuY29udGV4dC5kZXN0cm95QmVhbihjZWxsUmVuZGVyZXIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2VsbFJlbmRlcmVyID0gY2VsbFJlbmRlcmVyO1xuICAgICAgICB0aGlzLmNlbGxSZW5kZXJlckNsYXNzID0gY2VsbFJlbmRlcmVyQ2xhc3M7XG4gICAgICAgIHRoaXMuY2VsbFJlbmRlcmVyR3VpID0gdGhpcy5jZWxsUmVuZGVyZXIuZ2V0R3VpKCk7XG4gICAgICAgIGlmICh0aGlzLmNlbGxSZW5kZXJlckd1aSAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgZVBhcmVudCA9IHRoaXMuZ2V0UGFyZW50T2ZWYWx1ZSgpO1xuICAgICAgICAgICAgY2xlYXJFbGVtZW50KGVQYXJlbnQpO1xuICAgICAgICAgICAgZVBhcmVudC5hcHBlbmRDaGlsZCh0aGlzLmNlbGxSZW5kZXJlckd1aSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5hZnRlckNlbGxFZGl0b3JDcmVhdGVkID0gZnVuY3Rpb24gKHJlcXVlc3RWZXJzaW9uLCBjZWxsRWRpdG9yLCBwYXJhbXMsIHBvcHVwLCBwb3NpdGlvbikge1xuICAgICAgICAvLyBpZiBlZGl0aW5nQ2VsbD1mYWxzZSwgbWVhbnMgdXNlciBjYW5jZWxsZWQgdGhlIGVkaXRvciBiZWZvcmUgY29tcG9uZW50IHdhcyByZWFkeS5cbiAgICAgICAgLy8gaWYgdmVyc2lvbk1pc21hdGNoLCB0aGVuIHVzZXIgY2FuY2VsbGVkIHRoZSBlZGl0LCB0aGVuIHN0YXJ0ZWQgdGhlIGVkaXQgYWdhaW4sIGFuZCB0aGlzXG4gICAgICAgIC8vICAgaXMgdGhlIGZpcnN0IGVkaXRvciB3aGljaCBpcyBub3cgc3RhbGUuXG4gICAgICAgIHZhciBzdGFsZUNvbXAgPSByZXF1ZXN0VmVyc2lvbiAhPT0gdGhpcy5lZGl0b3JWZXJzaW9uO1xuICAgICAgICBpZiAoc3RhbGVDb21wKSB7XG4gICAgICAgICAgICB0aGlzLmJlYW5zLmNvbnRleHQuZGVzdHJveUJlYW4oY2VsbEVkaXRvcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVkaXRpbmdDYW5jZWxsZWRCeVVzZXJDb21wID0gY2VsbEVkaXRvci5pc0NhbmNlbEJlZm9yZVN0YXJ0ICYmIGNlbGxFZGl0b3IuaXNDYW5jZWxCZWZvcmVTdGFydCgpO1xuICAgICAgICBpZiAoZWRpdGluZ0NhbmNlbGxlZEJ5VXNlckNvbXApIHtcbiAgICAgICAgICAgIHRoaXMuYmVhbnMuY29udGV4dC5kZXN0cm95QmVhbihjZWxsRWRpdG9yKTtcbiAgICAgICAgICAgIHRoaXMuY2VsbEN0cmwuc3RvcEVkaXRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNlbGxFZGl0b3IuZ2V0R3VpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBjZWxsRWRpdG9yIGZvciBjb2x1bW4gXCIgKyB0aGlzLmNvbHVtbi5nZXRJZCgpICsgXCIgaXMgbWlzc2luZyBnZXRHdWkoKSBtZXRob2RcIik7XG4gICAgICAgICAgICB0aGlzLmJlYW5zLmNvbnRleHQuZGVzdHJveUJlYW4oY2VsbEVkaXRvcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jZWxsRWRpdG9yID0gY2VsbEVkaXRvcjtcbiAgICAgICAgdGhpcy5jZWxsRWRpdG9yR3VpID0gY2VsbEVkaXRvci5nZXRHdWkoKTtcbiAgICAgICAgdmFyIGNlbGxFZGl0b3JJblBvcHVwID0gcG9wdXAgfHwgKGNlbGxFZGl0b3IuaXNQb3B1cCAhPT0gdW5kZWZpbmVkICYmIGNlbGxFZGl0b3IuaXNQb3B1cCgpKTtcbiAgICAgICAgaWYgKGNlbGxFZGl0b3JJblBvcHVwKSB7XG4gICAgICAgICAgICBpZiAoIXBvcHVwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jZWxsQ3RybC5oYWNrU2F5RWRpdGluZ0luUG9wdXAoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYWRkUG9wdXBDZWxsRWRpdG9yKHBhcmFtcywgcG9zaXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZGRJbkNlbGxFZGl0b3IoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2VsbEVkaXRvci5hZnRlckd1aUF0dGFjaGVkKSB7XG4gICAgICAgICAgICBjZWxsRWRpdG9yLmFmdGVyR3VpQXR0YWNoZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbENvbXAucHJvdG90eXBlLmFkZEluQ2VsbEVkaXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICAvLyBpZiBmb2N1cyBpcyBpbnNpZGUgdGhlIGNlbGwsIHdlIG1vdmUgZm9jdXMgdG8gdGhlIGNlbGwgaXRzZWxmXG4gICAgICAgIC8vIGJlZm9yZSByZW1vdmluZyBpdCdzIGNvbnRlbnRzLCBvdGhlcndpc2UgZXJyb3JzIGNvdWxkIGJlIHRocm93bi5cbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIGlmIChlR3VpLmNvbnRhaW5zKGVEb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgICAgZUd1aS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVzdHJveVJlbmRlcmVyKCk7XG4gICAgICAgIHRoaXMucmVmcmVzaFdyYXBwZXIodHJ1ZSk7XG4gICAgICAgIHRoaXMuY2xlYXJQYXJlbnRPZlZhbHVlKCk7XG4gICAgICAgIGlmICh0aGlzLmNlbGxFZGl0b3JHdWkpIHtcbiAgICAgICAgICAgIHZhciBlUGFyZW50ID0gdGhpcy5nZXRQYXJlbnRPZlZhbHVlKCk7XG4gICAgICAgICAgICBlUGFyZW50LmFwcGVuZENoaWxkKHRoaXMuY2VsbEVkaXRvckd1aSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5hZGRQb3B1cENlbGxFZGl0b3IgPSBmdW5jdGlvbiAocGFyYW1zLCBwb3NpdGlvbikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5iZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNGdWxsUm93RWRpdCgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHBvcHVwIGNlbGxFZGl0b3IgZG9lcyBub3Qgd29yayB3aXRoIGZ1bGxSb3dFZGl0IC0geW91IGNhbm5vdCB1c2UgdGhlbSBib3RoICcgK1xuICAgICAgICAgICAgICAgICctIGVpdGhlciB0dXJuIG9mZiBmdWxsUm93RWRpdCwgb3Igc3RvcCB1c2luZyBwb3B1cCBlZGl0b3JzLicpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjZWxsRWRpdG9yID0gdGhpcy5jZWxsRWRpdG9yO1xuICAgICAgICAvLyBpZiBhIHBvcHVwLCB0aGVuIHdlIHdyYXAgaW4gYSBwb3B1cCBlZGl0b3IgYW5kIHJldHVybiB0aGUgcG9wdXBcbiAgICAgICAgdGhpcy5jZWxsRWRpdG9yUG9wdXBXcmFwcGVyID0gdGhpcy5iZWFucy5jb250ZXh0LmNyZWF0ZUJlYW4obmV3IFBvcHVwRWRpdG9yV3JhcHBlcihwYXJhbXMpKTtcbiAgICAgICAgdmFyIGVQb3B1cEd1aSA9IHRoaXMuY2VsbEVkaXRvclBvcHVwV3JhcHBlci5nZXRHdWkoKTtcbiAgICAgICAgaWYgKHRoaXMuY2VsbEVkaXRvckd1aSkge1xuICAgICAgICAgICAgZVBvcHVwR3VpLmFwcGVuZENoaWxkKHRoaXMuY2VsbEVkaXRvckd1aSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBvcHVwU2VydmljZSA9IHRoaXMuYmVhbnMucG9wdXBTZXJ2aWNlO1xuICAgICAgICB2YXIgdXNlTW9kZWxQb3B1cCA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3RvcEVkaXRpbmdXaGVuQ2VsbHNMb3NlRm9jdXMoKTtcbiAgICAgICAgLy8gc2VlIGlmIHBvc2l0aW9uIHByb3ZpZGVkIGJ5IGNvbERlZiwgaWYgbm90IHRoZW4gY2hlY2sgb2xkIHdheSBvZiBtZXRob2Qgb24gY2VsbENvbXBcbiAgICAgICAgdmFyIHBvc2l0aW9uVG9Vc2UgPSBwb3NpdGlvbiAhPSBudWxsID8gcG9zaXRpb24gOiBjZWxsRWRpdG9yLmdldFBvcHVwUG9zaXRpb24gPyBjZWxsRWRpdG9yLmdldFBvcHVwUG9zaXRpb24oKSA6ICdvdmVyJztcbiAgICAgICAgdmFyIHBvc2l0aW9uUGFyYW1zID0ge1xuICAgICAgICAgICAgY29sdW1uOiB0aGlzLmNvbHVtbixcbiAgICAgICAgICAgIHJvd05vZGU6IHRoaXMucm93Tm9kZSxcbiAgICAgICAgICAgIHR5cGU6ICdwb3B1cENlbGxFZGl0b3InLFxuICAgICAgICAgICAgZXZlbnRTb3VyY2U6IHRoaXMuZ2V0R3VpKCksXG4gICAgICAgICAgICBlUG9wdXA6IGVQb3B1cEd1aSxcbiAgICAgICAgICAgIGtlZXBXaXRoaW5Cb3VuZHM6IHRydWVcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHBvc2l0aW9uQ2FsbGJhY2sgPSBwb3NpdGlvblRvVXNlID09PSAndW5kZXInID9cbiAgICAgICAgICAgIHBvcHVwU2VydmljZS5wb3NpdGlvblBvcHVwVW5kZXJDb21wb25lbnQuYmluZChwb3B1cFNlcnZpY2UsIHBvc2l0aW9uUGFyYW1zKVxuICAgICAgICAgICAgOiBwb3B1cFNlcnZpY2UucG9zaXRpb25Qb3B1cE92ZXJDb21wb25lbnQuYmluZChwb3B1cFNlcnZpY2UsIHBvc2l0aW9uUGFyYW1zKTtcbiAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBhZGRQb3B1cFJlcyA9IHBvcHVwU2VydmljZS5hZGRQb3B1cCh7XG4gICAgICAgICAgICBtb2RhbDogdXNlTW9kZWxQb3B1cCxcbiAgICAgICAgICAgIGVDaGlsZDogZVBvcHVwR3VpLFxuICAgICAgICAgICAgY2xvc2VPbkVzYzogdHJ1ZSxcbiAgICAgICAgICAgIGNsb3NlZENhbGxiYWNrOiBmdW5jdGlvbiAoKSB7IF90aGlzLmNlbGxDdHJsLm9uUG9wdXBFZGl0b3JDbG9zZWQoKTsgfSxcbiAgICAgICAgICAgIGFuY2hvclRvRWxlbWVudDogdGhpcy5nZXRHdWkoKSxcbiAgICAgICAgICAgIHBvc2l0aW9uQ2FsbGJhY2s6IHBvc2l0aW9uQ2FsbGJhY2ssXG4gICAgICAgICAgICBhcmlhTGFiZWw6IHRyYW5zbGF0ZSgnYXJpYUxhYmVsQ2VsbEVkaXRvcicsICdDZWxsIEVkaXRvcicpXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWRkUG9wdXBSZXMpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZUVkaXRvclBvcHVwID0gYWRkUG9wdXBSZXMuaGlkZUZ1bmM7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5kZXRhY2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZVJvdy5yZW1vdmVDaGlsZCh0aGlzLmdldEd1aSgpKTtcbiAgICB9O1xuICAgIC8vIGlmIHRoZSByb3cgaXMgYWxzbyBnZXR0aW5nIGRlc3Ryb3llZCwgdGhlbiB3ZSBkb24ndCBuZWVkIHRvIHJlbW92ZSBmcm9tIGRvbSxcbiAgICAvLyBhcyB0aGUgcm93IHdpbGwgYWxzbyBnZXQgcmVtb3ZlZCwgc28gbm8gbmVlZCB0byB0YWtlIG91dCB0aGUgY2VsbHMgZnJvbSB0aGUgcm93XG4gICAgLy8gaWYgdGhlIHJvdyBpcyBnb2luZyAocmVtb3ZpbmcgaXMgYW4gZXhwZW5zaXZlIG9wZXJhdGlvbiwgc28gb25seSBuZWVkIHRvIHJlbW92ZVxuICAgIC8vIHRoZSB0b3AgcGFydClcbiAgICAvL1xuICAgIC8vIG5vdGUgLSB0aGlzIGlzIE5PVCBjYWxsZWQgYnkgY29udGV4dCwgYXMgd2UgZG9uJ3Qgd2lyZSAvIHVud2lyZSB0aGUgQ2VsbENvbXAgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMuXG4gICAgQ2VsbENvbXAucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY2VsbEN0cmwuc3RvcEVkaXRpbmcoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95RWRpdG9yQW5kUmVuZGVyZXIoKTtcbiAgICAgICAgdGhpcy5yZW1vdmVDb250cm9scygpO1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIENlbGxDb21wLnByb3RvdHlwZS5jbGVhclBhcmVudE9mVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgLy8gaWYgZm9jdXMgaXMgaW5zaWRlIHRoZSBjZWxsLCB3ZSBtb3ZlIGZvY3VzIHRvIHRoZSBjZWxsIGl0c2VsZlxuICAgICAgICAvLyBiZWZvcmUgcmVtb3ZpbmcgaXQncyBjb250ZW50cywgb3RoZXJ3aXNlIGVycm9ycyBjb3VsZCBiZSB0aHJvd24uXG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICBpZiAoZUd1aS5jb250YWlucyhlRG9jdW1lbnQuYWN0aXZlRWxlbWVudCkgJiYgYnJvd3NlclN1cHBvcnRzUHJldmVudFNjcm9sbCgpKSB7XG4gICAgICAgICAgICBlR3VpLmZvY3VzKHsgcHJldmVudFNjcm9sbDogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgICBjbGVhckVsZW1lbnQodGhpcy5nZXRQYXJlbnRPZlZhbHVlKCkpO1xuICAgIH07XG4gICAgcmV0dXJuIENlbGxDb21wO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxRiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIFJvd0NvbXAgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFGKFJvd0NvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUm93Q29tcChjdHJsLCBiZWFucywgY29udGFpbmVyVHlwZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5jZWxsQ29tcHMgPSB7fTtcbiAgICAgICAgX3RoaXMuYmVhbnMgPSBiZWFucztcbiAgICAgICAgX3RoaXMucm93Q3RybCA9IGN0cmw7XG4gICAgICAgIF90aGlzLnNldFRlbXBsYXRlKC8qIGh0bWwgKi8gXCI8ZGl2IGNvbXAtaWQ9XFxcIlwiICsgX3RoaXMuZ2V0Q29tcElkKCkgKyBcIlxcXCIgc3R5bGU9XFxcIlwiICsgX3RoaXMuZ2V0SW5pdGlhbFN0eWxlKCkgKyBcIlxcXCIvPlwiKTtcbiAgICAgICAgdmFyIGVHdWkgPSBfdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgdmFyIHN0eWxlID0gZUd1aS5zdHlsZTtcbiAgICAgICAgdmFyIGNvbXBQcm94eSA9IHtcbiAgICAgICAgICAgIHNldERvbU9yZGVyOiBmdW5jdGlvbiAoZG9tT3JkZXIpIHsgcmV0dXJuIF90aGlzLmRvbU9yZGVyID0gZG9tT3JkZXI7IH0sXG4gICAgICAgICAgICBzZXRDZWxsQ3RybHM6IGZ1bmN0aW9uIChjZWxsQ3RybHMpIHsgcmV0dXJuIF90aGlzLnNldENlbGxDdHJscyhjZWxsQ3RybHMpOyB9LFxuICAgICAgICAgICAgc2hvd0Z1bGxXaWR0aDogZnVuY3Rpb24gKGNvbXBEZXRhaWxzKSB7IHJldHVybiBfdGhpcy5zaG93RnVsbFdpZHRoKGNvbXBEZXRhaWxzKTsgfSxcbiAgICAgICAgICAgIGdldEZ1bGxXaWR0aENlbGxSZW5kZXJlcjogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZ2V0RnVsbFdpZHRoQ2VsbFJlbmRlcmVyKCk7IH0sXG4gICAgICAgICAgICBhZGRPclJlbW92ZUNzc0NsYXNzOiBmdW5jdGlvbiAobmFtZSwgb24pIHsgcmV0dXJuIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MobmFtZSwgb24pOyB9LFxuICAgICAgICAgICAgc2V0VXNlclN0eWxlczogZnVuY3Rpb24gKHN0eWxlcykgeyByZXR1cm4gYWRkU3R5bGVzVG9FbGVtZW50KGVHdWksIHN0eWxlcyk7IH0sXG4gICAgICAgICAgICBzZXRUb3A6IGZ1bmN0aW9uICh0b3ApIHsgcmV0dXJuIHN0eWxlLnRvcCA9IHRvcDsgfSxcbiAgICAgICAgICAgIHNldFRyYW5zZm9ybTogZnVuY3Rpb24gKHRyYW5zZm9ybSkgeyByZXR1cm4gc3R5bGUudHJhbnNmb3JtID0gdHJhbnNmb3JtOyB9LFxuICAgICAgICAgICAgc2V0Um93SW5kZXg6IGZ1bmN0aW9uIChyb3dJbmRleCkgeyByZXR1cm4gZUd1aS5zZXRBdHRyaWJ1dGUoJ3Jvdy1pbmRleCcsIHJvd0luZGV4KTsgfSxcbiAgICAgICAgICAgIHNldFJvbGU6IGZ1bmN0aW9uIChyb2xlKSB7IHJldHVybiBzZXRBcmlhUm9sZShlR3VpLCByb2xlKTsgfSxcbiAgICAgICAgICAgIHNldFJvd0lkOiBmdW5jdGlvbiAocm93SWQpIHsgcmV0dXJuIGVHdWkuc2V0QXR0cmlidXRlKCdyb3ctaWQnLCByb3dJZCk7IH0sXG4gICAgICAgICAgICBzZXRSb3dCdXNpbmVzc0tleTogZnVuY3Rpb24gKGJ1c2luZXNzS2V5KSB7IHJldHVybiBlR3VpLnNldEF0dHJpYnV0ZSgncm93LWJ1c2luZXNzLWtleScsIGJ1c2luZXNzS2V5KTsgfSxcbiAgICAgICAgICAgIHNldFRhYkluZGV4OiBmdW5jdGlvbiAodGFiSW5kZXgpIHsgcmV0dXJuIGVHdWkuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIHRhYkluZGV4LnRvU3RyaW5nKCkpOyB9XG4gICAgICAgIH07XG4gICAgICAgIGN0cmwuc2V0Q29tcChjb21wUHJveHksIF90aGlzLmdldEd1aSgpLCBjb250YWluZXJUeXBlKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSb3dDb21wLnByb3RvdHlwZS5nZXRJbml0aWFsU3R5bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSB0aGlzLnJvd0N0cmwuZ2V0SW5pdGlhbFRyYW5zZm9ybSgpO1xuICAgICAgICB2YXIgdG9wID0gdGhpcy5yb3dDdHJsLmdldEluaXRpYWxSb3dUb3AoKTtcbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybSA/IFwidHJhbnNmb3JtOiBcIiArIHRyYW5zZm9ybSA6IFwidG9wOiBcIiArIHRvcDtcbiAgICB9O1xuICAgIFJvd0NvbXAucHJvdG90eXBlLnNob3dGdWxsV2lkdGggPSBmdW5jdGlvbiAoY29tcERldGFpbHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gZnVuY3Rpb24gKGNlbGxSZW5kZXJlcikge1xuICAgICAgICAgICAgaWYgKF90aGlzLmlzQWxpdmUoKSkge1xuICAgICAgICAgICAgICAgIHZhciBlR3VpID0gY2VsbFJlbmRlcmVyLmdldEd1aSgpO1xuICAgICAgICAgICAgICAgIF90aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKGVHdWkpO1xuICAgICAgICAgICAgICAgIF90aGlzLnJvd0N0cmwuc2V0dXBEZXRhaWxSb3dBdXRvSGVpZ2h0KGVHdWkpO1xuICAgICAgICAgICAgICAgIF90aGlzLnNldEZ1bGxXaWR0aFJvd0NvbXAoY2VsbFJlbmRlcmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIF90aGlzLmJlYW5zLmNvbnRleHQuZGVzdHJveUJlYW4oY2VsbFJlbmRlcmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLy8gaWYgbm90IGluIGNhY2hlLCBjcmVhdGUgbmV3IG9uZVxuICAgICAgICB2YXIgcmVzID0gY29tcERldGFpbHMubmV3QWdTdGFja0luc3RhbmNlKCk7XG4gICAgICAgIGlmICghcmVzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmVzLnRoZW4oY2FsbGJhY2spO1xuICAgIH07XG4gICAgUm93Q29tcC5wcm90b3R5cGUuc2V0Q2VsbEN0cmxzID0gZnVuY3Rpb24gKGNlbGxDdHJscykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY2VsbHNUb1JlbW92ZSA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuY2VsbENvbXBzKTtcbiAgICAgICAgY2VsbEN0cmxzLmZvckVhY2goZnVuY3Rpb24gKGNlbGxDdHJsKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0gY2VsbEN0cmwuZ2V0SW5zdGFuY2VJZCgpO1xuICAgICAgICAgICAgdmFyIGV4aXN0aW5nQ2VsbENvbXAgPSBfdGhpcy5jZWxsQ29tcHNba2V5XTtcbiAgICAgICAgICAgIGlmIChleGlzdGluZ0NlbGxDb21wID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5uZXdDZWxsQ29tcChjZWxsQ3RybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjZWxsc1RvUmVtb3ZlW2tleV0gPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGNlbGxDb21wc1RvUmVtb3ZlID0gZ2V0QWxsVmFsdWVzSW5PYmplY3QoY2VsbHNUb1JlbW92ZSlcbiAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKGNlbGxDb21wKSB7IHJldHVybiBjZWxsQ29tcCAhPSBudWxsOyB9KTtcbiAgICAgICAgdGhpcy5kZXN0cm95Q2VsbHMoY2VsbENvbXBzVG9SZW1vdmUpO1xuICAgICAgICB0aGlzLmVuc3VyZURvbU9yZGVyKGNlbGxDdHJscyk7XG4gICAgfTtcbiAgICBSb3dDb21wLnByb3RvdHlwZS5lbnN1cmVEb21PcmRlciA9IGZ1bmN0aW9uIChjZWxsQ3RybHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmRvbU9yZGVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVsZW1lbnRzSW5PcmRlciA9IFtdO1xuICAgICAgICBjZWxsQ3RybHMuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgICAgIHZhciBjZWxsQ29tcCA9IF90aGlzLmNlbGxDb21wc1tjZWxsQ3RybC5nZXRJbnN0YW5jZUlkKCldO1xuICAgICAgICAgICAgaWYgKGNlbGxDb21wKSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudHNJbk9yZGVyLnB1c2goY2VsbENvbXAuZ2V0R3VpKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgc2V0RG9tQ2hpbGRPcmRlcih0aGlzLmdldEd1aSgpLCBlbGVtZW50c0luT3JkZXIpO1xuICAgIH07XG4gICAgUm93Q29tcC5wcm90b3R5cGUubmV3Q2VsbENvbXAgPSBmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgdmFyIGNlbGxDb21wID0gbmV3IENlbGxDb21wKHRoaXMuYmVhbnMsIGNlbGxDdHJsLCB0aGlzLnJvd0N0cmwuaXNQcmludExheW91dCgpLCB0aGlzLmdldEd1aSgpLCB0aGlzLnJvd0N0cmwuaXNFZGl0aW5nKCkpO1xuICAgICAgICB0aGlzLmNlbGxDb21wc1tjZWxsQ3RybC5nZXRJbnN0YW5jZUlkKCldID0gY2VsbENvbXA7XG4gICAgICAgIHRoaXMuZ2V0R3VpKCkuYXBwZW5kQ2hpbGQoY2VsbENvbXAuZ2V0R3VpKCkpO1xuICAgIH07XG4gICAgUm93Q29tcC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuZGVzdHJveUFsbENlbGxzKCk7XG4gICAgfTtcbiAgICBSb3dDb21wLnByb3RvdHlwZS5kZXN0cm95QWxsQ2VsbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjZWxsc1RvRGVzdHJveSA9IGdldEFsbFZhbHVlc0luT2JqZWN0KHRoaXMuY2VsbENvbXBzKS5maWx0ZXIoZnVuY3Rpb24gKGNwKSB7IHJldHVybiBjcCAhPSBudWxsOyB9KTtcbiAgICAgICAgdGhpcy5kZXN0cm95Q2VsbHMoY2VsbHNUb0Rlc3Ryb3kpO1xuICAgIH07XG4gICAgUm93Q29tcC5wcm90b3R5cGUuc2V0RnVsbFdpZHRoUm93Q29tcCA9IGZ1bmN0aW9uIChmdWxsV2lkdGhSb3dDb21wb25lbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuZnVsbFdpZHRoQ2VsbFJlbmRlcmVyKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkIC0gc2hvdWxkIG5vdCBiZSBzZXR0aW5nIGZ1bGxXaWR0aFJvd0NvbXBvbmVudCB0d2ljZScpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZnVsbFdpZHRoQ2VsbFJlbmRlcmVyID0gZnVsbFdpZHRoUm93Q29tcG9uZW50O1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmZ1bGxXaWR0aENlbGxSZW5kZXJlciA9IF90aGlzLmJlYW5zLmNvbnRleHQuZGVzdHJveUJlYW4oX3RoaXMuZnVsbFdpZHRoQ2VsbFJlbmRlcmVyKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dDb21wLnByb3RvdHlwZS5nZXRGdWxsV2lkdGhDZWxsUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZ1bGxXaWR0aENlbGxSZW5kZXJlcjtcbiAgICB9O1xuICAgIFJvd0NvbXAucHJvdG90eXBlLmRlc3Ryb3lDZWxscyA9IGZ1bmN0aW9uIChjZWxsQ29tcHMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgY2VsbENvbXBzLmZvckVhY2goZnVuY3Rpb24gKGNlbGxDb21wKSB7XG4gICAgICAgICAgICAvLyBjb3VsZCBiZSBvbGQgcmVmZXJlbmNlLCBpZSByZW1vdmVkIGNlbGxcbiAgICAgICAgICAgIGlmICghY2VsbENvbXApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBjaGVjayBjZWxsQ29tcCBiZWxvbmdzIGluIHRoaXMgY29udGFpbmVyXG4gICAgICAgICAgICB2YXIgaW5zdGFuY2VJZCA9IGNlbGxDb21wLmdldEN0cmwoKS5nZXRJbnN0YW5jZUlkKCk7XG4gICAgICAgICAgICBpZiAoX3RoaXMuY2VsbENvbXBzW2luc3RhbmNlSWRdICE9PSBjZWxsQ29tcCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNlbGxDb21wLmRldGFjaCgpO1xuICAgICAgICAgICAgY2VsbENvbXAuZGVzdHJveSgpO1xuICAgICAgICAgICAgX3RoaXMuY2VsbENvbXBzW2luc3RhbmNlSWRdID0gbnVsbDtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gUm93Q29tcDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMUUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiQzID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiQzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiQzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fZGVjb3JhdGUkMXogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbmZ1bmN0aW9uIHRlbXBsYXRlRmFjdG9yeSgpIHtcbiAgICB2YXIgbmFtZSA9IENvbXBvbmVudC5lbGVtZW50R2V0dGluZ0NyZWF0ZWQuZ2V0QXR0cmlidXRlKCduYW1lJyk7XG4gICAgdmFyIGNzc0NsYXNzZXMgPSBSb3dDb250YWluZXJDdHJsLmdldFJvd0NvbnRhaW5lckNzc0NsYXNzZXMobmFtZSk7XG4gICAgdmFyIHJlcztcbiAgICB2YXIgdGVtcGxhdGUxID0gbmFtZSA9PT0gUm93Q29udGFpbmVyTmFtZS5DRU5URVI7XG4gICAgdmFyIHRlbXBsYXRlMiA9IG5hbWUgPT09IFJvd0NvbnRhaW5lck5hbWUuVE9QX0NFTlRFUlxuICAgICAgICB8fCBuYW1lID09PSBSb3dDb250YWluZXJOYW1lLlNUSUNLWV9UT1BfQ0VOVEVSXG4gICAgICAgIHx8IG5hbWUgPT09IFJvd0NvbnRhaW5lck5hbWUuQk9UVE9NX0NFTlRFUjtcbiAgICBpZiAodGVtcGxhdGUxKSB7XG4gICAgICAgIHJlcyA9IC8qIGh0bWwgKi9cbiAgICAgICAgICAgIFwiPGRpdiBjbGFzcz1cXFwiXCIgKyBjc3NDbGFzc2VzLndyYXBwZXIgKyBcIlxcXCIgcmVmPVxcXCJlV3JhcHBlclxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiXCIgKyBjc3NDbGFzc2VzLnZpZXdwb3J0ICsgXCJcXFwiIHJlZj1cXFwiZVZpZXdwb3J0XFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiXCIgKyBjc3NDbGFzc2VzLmNvbnRhaW5lciArIFwiXFxcIiByZWY9XFxcImVDb250YWluZXJcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgICAgICA8L2Rpdj5cIjtcbiAgICB9XG4gICAgZWxzZSBpZiAodGVtcGxhdGUyKSB7XG4gICAgICAgIHJlcyA9IC8qIGh0bWwgKi9cbiAgICAgICAgICAgIFwiPGRpdiBjbGFzcz1cXFwiXCIgKyBjc3NDbGFzc2VzLnZpZXdwb3J0ICsgXCJcXFwiIHJlZj1cXFwiZVZpZXdwb3J0XFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJcIiArIGNzc0NsYXNzZXMuY29udGFpbmVyICsgXCJcXFwiIHJlZj1cXFwiZUNvbnRhaW5lclxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XCI7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXMgPSAvKiBodG1sICovXG4gICAgICAgICAgICBcIjxkaXYgY2xhc3M9XFxcIlwiICsgY3NzQ2xhc3Nlcy5jb250YWluZXIgKyBcIlxcXCIgcmVmPVxcXCJlQ29udGFpbmVyXFxcIj48L2Rpdj5cIjtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbnZhciBSb3dDb250YWluZXJDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxRShSb3dDb250YWluZXJDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJvd0NvbnRhaW5lckNvbXAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHRlbXBsYXRlRmFjdG9yeSgpKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yb3dDb21wcyA9IHt9O1xuICAgICAgICBfdGhpcy5uYW1lID0gQ29tcG9uZW50LmVsZW1lbnRHZXR0aW5nQ3JlYXRlZC5nZXRBdHRyaWJ1dGUoJ25hbWUnKTtcbiAgICAgICAgX3RoaXMudHlwZSA9IGdldFJvd0NvbnRhaW5lclR5cGVGb3JOYW1lKF90aGlzLm5hbWUpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFJvd0NvbnRhaW5lckNvbXAucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb21wUHJveHkgPSB7XG4gICAgICAgICAgICBzZXRWaWV3cG9ydEhlaWdodDogZnVuY3Rpb24gKGhlaWdodCkgeyByZXR1cm4gX3RoaXMuZVZpZXdwb3J0LnN0eWxlLmhlaWdodCA9IGhlaWdodDsgfSxcbiAgICAgICAgICAgIHNldFJvd0N0cmxzOiBmdW5jdGlvbiAocm93Q3RybHMpIHsgcmV0dXJuIF90aGlzLnNldFJvd0N0cmxzKHJvd0N0cmxzKTsgfSxcbiAgICAgICAgICAgIHNldERvbU9yZGVyOiBmdW5jdGlvbiAoZG9tT3JkZXIpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kb21PcmRlciA9IGRvbU9yZGVyO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldENvbnRhaW5lcldpZHRoOiBmdW5jdGlvbiAod2lkdGgpIHsgcmV0dXJuIF90aGlzLmVDb250YWluZXIuc3R5bGUud2lkdGggPSB3aWR0aDsgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY3RybCA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IFJvd0NvbnRhaW5lckN0cmwodGhpcy5uYW1lKSk7XG4gICAgICAgIGN0cmwuc2V0Q29tcChjb21wUHJveHksIHRoaXMuZUNvbnRhaW5lciwgdGhpcy5lVmlld3BvcnQsIHRoaXMuZVdyYXBwZXIpO1xuICAgIH07XG4gICAgUm93Q29udGFpbmVyQ29tcC5wcm90b3R5cGUucHJlRGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gZGVzdHJveXMgYWxsIHJvdyBjb21wc1xuICAgICAgICB0aGlzLnNldFJvd0N0cmxzKFtdKTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckNvbXAucHJvdG90eXBlLnNldFJvd0N0cmxzID0gZnVuY3Rpb24gKHJvd0N0cmxzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvbGRSb3dzID0gX19hc3NpZ24kMyh7fSwgdGhpcy5yb3dDb21wcyk7XG4gICAgICAgIHRoaXMucm93Q29tcHMgPSB7fTtcbiAgICAgICAgdGhpcy5sYXN0UGxhY2VkRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHZhciBwcm9jZXNzUm93ID0gZnVuY3Rpb24gKHJvd0Nvbikge1xuICAgICAgICAgICAgdmFyIGluc3RhbmNlSWQgPSByb3dDb24uZ2V0SW5zdGFuY2VJZCgpO1xuICAgICAgICAgICAgdmFyIGV4aXN0aW5nUm93Q29tcCA9IG9sZFJvd3NbaW5zdGFuY2VJZF07XG4gICAgICAgICAgICBpZiAoZXhpc3RpbmdSb3dDb21wKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMucm93Q29tcHNbaW5zdGFuY2VJZF0gPSBleGlzdGluZ1Jvd0NvbXA7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG9sZFJvd3NbaW5zdGFuY2VJZF07XG4gICAgICAgICAgICAgICAgX3RoaXMuZW5zdXJlRG9tT3JkZXIoZXhpc3RpbmdSb3dDb21wLmdldEd1aSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciByb3dDb21wID0gX3RoaXMubmV3Um93Q29tcChyb3dDb24pO1xuICAgICAgICAgICAgICAgIF90aGlzLnJvd0NvbXBzW2luc3RhbmNlSWRdID0gcm93Q29tcDtcbiAgICAgICAgICAgICAgICBfdGhpcy5hcHBlbmRSb3cocm93Q29tcC5nZXRHdWkoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHJvd0N0cmxzLmZvckVhY2gocHJvY2Vzc1Jvdyk7XG4gICAgICAgIGdldEFsbFZhbHVlc0luT2JqZWN0KG9sZFJvd3MpLmZvckVhY2goZnVuY3Rpb24gKG9sZFJvd0NvbXApIHtcbiAgICAgICAgICAgIF90aGlzLmVDb250YWluZXIucmVtb3ZlQ2hpbGQob2xkUm93Q29tcC5nZXRHdWkoKSk7XG4gICAgICAgICAgICBvbGRSb3dDb21wLmRlc3Ryb3koKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNldEFyaWFSb2xlKHRoaXMuZUNvbnRhaW5lciwgcm93Q3RybHMubGVuZ3RoID8gXCJyb3dncm91cFwiIDogXCJwcmVzZW50YXRpb25cIik7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDb21wLnByb3RvdHlwZS5hcHBlbmRSb3cgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICBpZiAodGhpcy5kb21PcmRlcikge1xuICAgICAgICAgICAgaW5zZXJ0V2l0aERvbU9yZGVyKHRoaXMuZUNvbnRhaW5lciwgZWxlbWVudCwgdGhpcy5sYXN0UGxhY2VkRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVDb250YWluZXIuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sYXN0UGxhY2VkRWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJDb21wLnByb3RvdHlwZS5lbnN1cmVEb21PcmRlciA9IGZ1bmN0aW9uIChlUm93KSB7XG4gICAgICAgIGlmICh0aGlzLmRvbU9yZGVyKSB7XG4gICAgICAgICAgICBlbnN1cmVEb21PcmRlcih0aGlzLmVDb250YWluZXIsIGVSb3csIHRoaXMubGFzdFBsYWNlZEVsZW1lbnQpO1xuICAgICAgICAgICAgdGhpcy5sYXN0UGxhY2VkRWxlbWVudCA9IGVSb3c7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckNvbXAucHJvdG90eXBlLm5ld1Jvd0NvbXAgPSBmdW5jdGlvbiAocm93Q3RybCkge1xuICAgICAgICBSb3dDb250YWluZXJDdHJsLmdldFBpbm5lZCh0aGlzLm5hbWUpO1xuICAgICAgICB2YXIgcmVzID0gbmV3IFJvd0NvbXAocm93Q3RybCwgdGhpcy5iZWFucywgdGhpcy50eXBlKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMXooW1xuICAgICAgICBBdXRvd2lyZWQoJ2JlYW5zJylcbiAgICBdLCBSb3dDb250YWluZXJDb21wLnByb3RvdHlwZSwgXCJiZWFuc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXooW1xuICAgICAgICBSZWZTZWxlY3RvcignZVZpZXdwb3J0JylcbiAgICBdLCBSb3dDb250YWluZXJDb21wLnByb3RvdHlwZSwgXCJlVmlld3BvcnRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDF6KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VDb250YWluZXInKVxuICAgIF0sIFJvd0NvbnRhaW5lckNvbXAucHJvdG90eXBlLCBcImVDb250YWluZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDF6KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VXcmFwcGVyJylcbiAgICBdLCBSb3dDb250YWluZXJDb21wLnByb3RvdHlwZSwgXCJlV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXooW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93Q29udGFpbmVyQ29tcC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJDF6KFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIFJvd0NvbnRhaW5lckNvbXAucHJvdG90eXBlLCBcInByZURlc3Ryb3lcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFJvd0NvbnRhaW5lckNvbXA7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19kZWNvcmF0ZSQxeSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEJvZHlEcm9wUGl2b3RUYXJnZXQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQm9keURyb3BQaXZvdFRhcmdldChwaW5uZWQpIHtcbiAgICAgICAgdGhpcy5jb2x1bW5zVG9BZ2dyZWdhdGUgPSBbXTtcbiAgICAgICAgdGhpcy5jb2x1bW5zVG9Hcm91cCA9IFtdO1xuICAgICAgICB0aGlzLmNvbHVtbnNUb1Bpdm90ID0gW107XG4gICAgICAgIHRoaXMucGlubmVkID0gcGlubmVkO1xuICAgIH1cbiAgICAvKiogQ2FsbGJhY2sgZm9yIHdoZW4gZHJhZyBlbnRlcnMgKi9cbiAgICBCb2R5RHJvcFBpdm90VGFyZ2V0LnByb3RvdHlwZS5vbkRyYWdFbnRlciA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY2xlYXJDb2x1bW5zTGlzdCgpO1xuICAgICAgICAvLyBpbiBwaXZvdCBtb2RlLCB3ZSBkb24ndCBhY2NlcHQgYW55IGRyb3BzIGlmIGZ1bmN0aW9ucyBhcmUgcmVhZCBvbmx5XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0Z1bmN0aW9uc1JlYWRPbmx5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZHJhZ0NvbHVtbnMgPSBkcmFnZ2luZ0V2ZW50LmRyYWdJdGVtLmNvbHVtbnM7XG4gICAgICAgIGlmICghZHJhZ0NvbHVtbnMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkcmFnQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIC8vIHdlIGRvbid0IGFsbG93IGFkZGluZyBzZWNvbmRhcnkgY29sdW1uc1xuICAgICAgICAgICAgaWYgKCFjb2x1bW4uaXNQcmltYXJ5KCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY29sdW1uLmlzQW55RnVuY3Rpb25BY3RpdmUoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb2x1bW4uaXNBbGxvd1ZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jb2x1bW5zVG9BZ2dyZWdhdGUucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY29sdW1uLmlzQWxsb3dSb3dHcm91cCgpKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY29sdW1uc1RvR3JvdXAucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY29sdW1uLmlzQWxsb3dQaXZvdCgpKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY29sdW1uc1RvUGl2b3QucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEJvZHlEcm9wUGl2b3RUYXJnZXQucHJvdG90eXBlLmdldEljb25OYW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdG90YWxDb2x1bW5zID0gdGhpcy5jb2x1bW5zVG9BZ2dyZWdhdGUubGVuZ3RoICsgdGhpcy5jb2x1bW5zVG9Hcm91cC5sZW5ndGggKyB0aGlzLmNvbHVtbnNUb1Bpdm90Lmxlbmd0aDtcbiAgICAgICAgaWYgKHRvdGFsQ29sdW1ucyA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBpbm5lZCA/IERyYWdBbmREcm9wU2VydmljZS5JQ09OX1BJTk5FRCA6IERyYWdBbmREcm9wU2VydmljZS5JQ09OX01PVkU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvKiogQ2FsbGJhY2sgZm9yIHdoZW4gZHJhZyBsZWF2ZXMgKi9cbiAgICBCb2R5RHJvcFBpdm90VGFyZ2V0LnByb3RvdHlwZS5vbkRyYWdMZWF2ZSA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIC8vIGlmIHdlIGFyZSB0YWtpbmcgY29sdW1ucyBvdXQgb2YgdGhlIGNlbnRlciwgdGhlbiB3ZSByZW1vdmUgdGhlbSBmcm9tIHRoZSByZXBvcnRcbiAgICAgICAgdGhpcy5jbGVhckNvbHVtbnNMaXN0KCk7XG4gICAgfTtcbiAgICBCb2R5RHJvcFBpdm90VGFyZ2V0LnByb3RvdHlwZS5jbGVhckNvbHVtbnNMaXN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNvbHVtbnNUb0FnZ3JlZ2F0ZS5sZW5ndGggPSAwO1xuICAgICAgICB0aGlzLmNvbHVtbnNUb0dyb3VwLmxlbmd0aCA9IDA7XG4gICAgICAgIHRoaXMuY29sdW1uc1RvUGl2b3QubGVuZ3RoID0gMDtcbiAgICB9O1xuICAgIC8qKiBDYWxsYmFjayBmb3Igd2hlbiBkcmFnZ2luZyAqL1xuICAgIEJvZHlEcm9wUGl2b3RUYXJnZXQucHJvdG90eXBlLm9uRHJhZ2dpbmcgPSBmdW5jdGlvbiAoZHJhZ2dpbmdFdmVudCkge1xuICAgIH07XG4gICAgLyoqIENhbGxiYWNrIGZvciB3aGVuIGRyYWcgc3RvcHMgKi9cbiAgICBCb2R5RHJvcFBpdm90VGFyZ2V0LnByb3RvdHlwZS5vbkRyYWdTdG9wID0gZnVuY3Rpb24gKGRyYWdnaW5nRXZlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMuY29sdW1uc1RvQWdncmVnYXRlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwuYWRkVmFsdWVDb2x1bW5zKHRoaXMuY29sdW1uc1RvQWdncmVnYXRlLCBcInRvb2xQYW5lbERyYWdBbmREcm9wXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmNvbHVtbnNUb0dyb3VwLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwuYWRkUm93R3JvdXBDb2x1bW5zKHRoaXMuY29sdW1uc1RvR3JvdXAsIFwidG9vbFBhbmVsRHJhZ0FuZERyb3BcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY29sdW1uc1RvUGl2b3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5hZGRQaXZvdENvbHVtbnModGhpcy5jb2x1bW5zVG9QaXZvdCwgXCJ0b29sUGFuZWxEcmFnQW5kRHJvcFwiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxeShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEJvZHlEcm9wUGl2b3RUYXJnZXQucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxeShbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZE9wdGlvbnNXcmFwcGVyJylcbiAgICBdLCBCb2R5RHJvcFBpdm90VGFyZ2V0LnByb3RvdHlwZSwgXCJncmlkT3B0aW9uc1dyYXBwZXJcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gQm9keURyb3BQaXZvdFRhcmdldDtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2RlY29yYXRlJDF4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX19yZWFkJGUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgTW92ZUNvbHVtbkZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTW92ZUNvbHVtbkZlYXR1cmUocGlubmVkLCBlQ29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMubmVlZFRvTW92ZUxlZnQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5uZWVkVG9Nb3ZlUmlnaHQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5waW5uZWQgPSBwaW5uZWQ7XG4gICAgICAgIHRoaXMuZUNvbnRhaW5lciA9IGVDb250YWluZXI7XG4gICAgICAgIHRoaXMuY2VudGVyQ29udGFpbmVyID0gIWV4aXN0cyhwaW5uZWQpO1xuICAgIH1cbiAgICBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmdyaWRCb2R5Q29uID0gX3RoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRCb2R5Q3RybCgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5nZXRJY29uTmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkID8gRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fUElOTkVEIDogRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fTU9WRTtcbiAgICB9O1xuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5vbkRyYWdFbnRlciA9IGZ1bmN0aW9uIChkcmFnZ2luZ0V2ZW50KSB7XG4gICAgICAgIC8vIHdlIGRvIGR1bW15IGRyYWcsIHNvIG1ha2Ugc3VyZSBjb2x1bW4gYXBwZWFycyBpbiB0aGUgcmlnaHQgbG9jYXRpb24gd2hlbiBmaXJzdCBwbGFjZWRcbiAgICAgICAgdmFyIGNvbHVtbnMgPSBkcmFnZ2luZ0V2ZW50LmRyYWdJdGVtLmNvbHVtbnM7XG4gICAgICAgIHZhciBkcmFnQ2FtZUZyb21Ub29sUGFuZWwgPSBkcmFnZ2luZ0V2ZW50LmRyYWdTb3VyY2UudHlwZSA9PT0gRHJhZ1NvdXJjZVR5cGUuVG9vbFBhbmVsO1xuICAgICAgICBpZiAoZHJhZ0NhbWVGcm9tVG9vbFBhbmVsKSB7XG4gICAgICAgICAgICAvLyB0aGUgaWYgc3RhdGVtZW50IGRvZXNuJ3Qgd29yayBpZiBkcmFnIGxlYXZlcyBncmlkLCB0aGVuIGVudGVycyBhZ2FpblxuICAgICAgICAgICAgdGhpcy5zZXRDb2x1bW5zVmlzaWJsZShjb2x1bW5zLCB0cnVlLCBcInVpQ29sdW1uRHJhZ2dlZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHJlc3RvcmUgcHJldmlvdXMgc3RhdGUgb2YgdmlzaWJsZSBjb2x1bW5zIHVwb24gcmUtZW50ZXJpbmcuIHRoaXMgbWVhbnMgaWYgdGhlIHVzZXIgZHJhZ3NcbiAgICAgICAgICAgIC8vIGEgZ3JvdXAgb3V0LCBhbmQgdGhlbiBkcmFncyB0aGUgZ3JvdXAgYmFjayBpbiwgb25seSBjb2x1bW5zIHRoYXQgd2VyZSBvcmlnaW5hbGx5IHZpc2libGVcbiAgICAgICAgICAgIC8vIHdpbGwgYmUgdmlzaWJsZSBhZ2Fpbi4gb3RoZXJ3aXNlIGEgZ3JvdXAgd2l0aCB0aHJlZSBjb2x1bW5zIChidXQgb25seSB0d28gdmlzaWJsZSkgY291bGRcbiAgICAgICAgICAgIC8vIGJlIGRyYWdnZWQgb3V0LCB0aGVuIHdoZW4gaXQncyBkcmFnZ2VkIGluIGFnYWluLCBhbGwgdGhyZWUgYXJlIHZpc2libGUuIHRoaXMgc3RvcHMgdGhhdC5cbiAgICAgICAgICAgIHZhciB2aXNpYmxlU3RhdGVfMSA9IGRyYWdnaW5nRXZlbnQuZHJhZ0l0ZW0udmlzaWJsZVN0YXRlO1xuICAgICAgICAgICAgdmFyIHZpc2libGVDb2x1bW5zID0gKGNvbHVtbnMgfHwgW10pLmZpbHRlcihmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiB2aXNpYmxlU3RhdGVfMVtjb2x1bW4uZ2V0SWQoKV07IH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRDb2x1bW5zVmlzaWJsZSh2aXNpYmxlQ29sdW1ucywgdHJ1ZSwgXCJ1aUNvbHVtbkRyYWdnZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRDb2x1bW5zUGlubmVkKGNvbHVtbnMsIHRoaXMucGlubmVkLCBcInVpQ29sdW1uRHJhZ2dlZFwiKTtcbiAgICAgICAgdGhpcy5vbkRyYWdnaW5nKGRyYWdnaW5nRXZlbnQsIHRydWUsIHRydWUpO1xuICAgIH07XG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLm9uRHJhZ0xlYXZlID0gZnVuY3Rpb24gKGRyYWdnaW5nRXZlbnQpIHtcbiAgICAgICAgdGhpcy5lbnN1cmVJbnRlcnZhbENsZWFyZWQoKTtcbiAgICB9O1xuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5zZXRDb2x1bW5zVmlzaWJsZSA9IGZ1bmN0aW9uIChjb2x1bW5zLCB2aXNpYmxlLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gdm9pZCAwKSB7IHNvdXJjZSA9IFwiYXBpXCI7IH1cbiAgICAgICAgaWYgKGNvbHVtbnMpIHtcbiAgICAgICAgICAgIHZhciBhbGxvd2VkQ29scyA9IGNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjKSB7IHJldHVybiAhYy5nZXRDb2xEZWYoKS5sb2NrVmlzaWJsZTsgfSk7XG4gICAgICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbnNWaXNpYmxlKGFsbG93ZWRDb2xzLCB2aXNpYmxlLCBzb3VyY2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUuc2V0Q29sdW1uc1Bpbm5lZCA9IGZ1bmN0aW9uIChjb2x1bW5zLCBwaW5uZWQsIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlID09PSB2b2lkIDApIHsgc291cmNlID0gXCJhcGlcIjsgfVxuICAgICAgICBpZiAoY29sdW1ucykge1xuICAgICAgICAgICAgdmFyIGFsbG93ZWRDb2xzID0gY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKGMpIHsgcmV0dXJuICFjLmdldENvbERlZigpLmxvY2tQaW5uZWQ7IH0pO1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5zUGlubmVkKGFsbG93ZWRDb2xzLCBwaW5uZWQsIHNvdXJjZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5vbkRyYWdTdG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmVuc3VyZUludGVydmFsQ2xlYXJlZCgpO1xuICAgIH07XG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLm5vcm1hbGlzZVggPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICAvLyBmbGlwIHRoZSBjb29yZGluYXRlIGlmIGRvaW5nIFJUTFxuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKSkge1xuICAgICAgICAgICAgdmFyIGNsaWVudFdpZHRoID0gdGhpcy5lQ29udGFpbmVyLmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgeCA9IGNsaWVudFdpZHRoIC0geDtcbiAgICAgICAgfVxuICAgICAgICAvLyBhZGp1c3QgZm9yIHNjcm9sbCBvbmx5IGlmIGNlbnRyZSBjb250YWluZXIgKHRoZSBwaW5uZWQgY29udGFpbmVycyBkb24ndCBzY3JvbGwpXG4gICAgICAgIGlmICh0aGlzLmNlbnRlckNvbnRhaW5lcikge1xuICAgICAgICAgICAgeCArPSB0aGlzLmN0cmxzU2VydmljZS5nZXRDZW50ZXJSb3dDb250YWluZXJDdHJsKCkuZ2V0Q2VudGVyVmlld3BvcnRTY3JvbGxMZWZ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfTtcbiAgICBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUuY2hlY2tDZW50ZXJGb3JTY3JvbGxpbmcgPSBmdW5jdGlvbiAoeEFkanVzdGVkRm9yU2Nyb2xsKSB7XG4gICAgICAgIGlmICh0aGlzLmNlbnRlckNvbnRhaW5lcikge1xuICAgICAgICAgICAgLy8gc2Nyb2xsIGlmIHRoZSBtb3VzZSBoYXMgZ29uZSBvdXRzaWRlIHRoZSBncmlkIChvciBqdXN0IG91dHNpZGUgdGhlIHNjcm9sbGFibGUgcGFydCBpZiBwaW5uaW5nKVxuICAgICAgICAgICAgLy8gcHV0dGluZyBpbiA1MCBidWZmZXIsIHNvIGV2ZW4gaWYgdXNlciBnZXRzIHRvIGVkZ2Ugb2YgZ3JpZCwgYSBzY3JvbGwgd2lsbCBoYXBwZW5cbiAgICAgICAgICAgIHZhciBmaXJzdFZpc2libGVQaXhlbCA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldENlbnRlclJvd0NvbnRhaW5lckN0cmwoKS5nZXRDZW50ZXJWaWV3cG9ydFNjcm9sbExlZnQoKTtcbiAgICAgICAgICAgIHZhciBsYXN0VmlzaWJsZVBpeGVsID0gZmlyc3RWaXNpYmxlUGl4ZWwgKyB0aGlzLmN0cmxzU2VydmljZS5nZXRDZW50ZXJSb3dDb250YWluZXJDdHJsKCkuZ2V0Q2VudGVyV2lkdGgoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZWVkVG9Nb3ZlUmlnaHQgPSB4QWRqdXN0ZWRGb3JTY3JvbGwgPCAoZmlyc3RWaXNpYmxlUGl4ZWwgKyA1MCk7XG4gICAgICAgICAgICAgICAgdGhpcy5uZWVkVG9Nb3ZlTGVmdCA9IHhBZGp1c3RlZEZvclNjcm9sbCA+IChsYXN0VmlzaWJsZVBpeGVsIC0gNTApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZWVkVG9Nb3ZlTGVmdCA9IHhBZGp1c3RlZEZvclNjcm9sbCA8IChmaXJzdFZpc2libGVQaXhlbCArIDUwKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5lZWRUb01vdmVSaWdodCA9IHhBZGp1c3RlZEZvclNjcm9sbCA+IChsYXN0VmlzaWJsZVBpeGVsIC0gNTApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubmVlZFRvTW92ZUxlZnQgfHwgdGhpcy5uZWVkVG9Nb3ZlUmlnaHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuc3VyZUludGVydmFsU3RhcnRlZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbnN1cmVJbnRlcnZhbENsZWFyZWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLm9uRHJhZ2dpbmcgPSBmdW5jdGlvbiAoZHJhZ2dpbmdFdmVudCwgZnJvbUVudGVyLCBmYWtlRXZlbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKGZyb21FbnRlciA9PT0gdm9pZCAwKSB7IGZyb21FbnRlciA9IGZhbHNlOyB9XG4gICAgICAgIGlmIChmYWtlRXZlbnQgPT09IHZvaWQgMCkgeyBmYWtlRXZlbnQgPSBmYWxzZTsgfVxuICAgICAgICB0aGlzLmxhc3REcmFnZ2luZ0V2ZW50ID0gZHJhZ2dpbmdFdmVudDtcbiAgICAgICAgLy8gaWYgbW92aW5nIHVwIG9yIGRvd24gKGllIG5vdCBsZWZ0IG9yIHJpZ2h0KSB0aGVuIGRvIG5vdGhpbmdcbiAgICAgICAgaWYgKG1pc3NpbmcoZHJhZ2dpbmdFdmVudC5oRGlyZWN0aW9uKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtb3VzZVhOb3JtYWxpc2VkID0gdGhpcy5ub3JtYWxpc2VYKGRyYWdnaW5nRXZlbnQueCk7XG4gICAgICAgIC8vIGlmIHRoZSB1c2VyIGlzIGRyYWdnaW5nIGludG8gdGhlIHBhbmVsLCBpZSBjb21pbmcgZnJvbSB0aGUgc2lkZSBwYW5lbCBpbnRvIHRoZSBtYWluIGdyaWQsXG4gICAgICAgIC8vIHdlIGRvbid0IHdhbnQgdG8gc2Nyb2xsIHRoZSBncmlkIHRoaXMgdGltZSwgaXQgd291bGQgYXBwZWFyIGxpa2UgdGhlIHRhYmxlIGlzIGp1bXBpbmdcbiAgICAgICAgLy8gZWFjaCB0aW1lIGEgY29sdW1uIGlzIGRyYWdnZWQgaW4uXG4gICAgICAgIGlmICghZnJvbUVudGVyKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrQ2VudGVyRm9yU2Nyb2xsaW5nKG1vdXNlWE5vcm1hbGlzZWQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoRGlyZWN0aW9uTm9ybWFsaXNlZCA9IHRoaXMubm9ybWFsaXNlRGlyZWN0aW9uKGRyYWdnaW5nRXZlbnQuaERpcmVjdGlvbik7XG4gICAgICAgIHZhciBkcmFnU291cmNlVHlwZSA9IGRyYWdnaW5nRXZlbnQuZHJhZ1NvdXJjZS50eXBlO1xuICAgICAgICB2YXIgY29sdW1uc1RvTW92ZSA9IGRyYWdnaW5nRXZlbnQuZHJhZ1NvdXJjZS5nZXREcmFnSXRlbSgpLmNvbHVtbnM7XG4gICAgICAgIGNvbHVtbnNUb01vdmUgPSBjb2x1bW5zVG9Nb3ZlLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICBpZiAoY29sLmdldENvbERlZigpLmxvY2tQaW5uZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiBsb2NrZWQgcmV0dXJuIHRydWUgb25seSBpZiBib3RoIGNvbCBhbmQgY29udGFpbmVyIGFyZSBzYW1lIHBpbiB0eXBlLlxuICAgICAgICAgICAgICAgIC8vIGRvdWJsZSBlcXVhbHMgKD09KSBoZXJlIG9uIHB1cnBvc2Ugc28gdGhhdCBudWxsPT11bmRlZmluZWQgaXMgdHJ1ZSAoZm9yIG5vdCBwaW5uZWQgb3B0aW9ucylcbiAgICAgICAgICAgICAgICByZXR1cm4gY29sLmdldFBpbm5lZCgpID09IF90aGlzLnBpbm5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIG5vdCBwaW4gbG9ja2VkLCB0aGVuIGFsd2F5cyBhbGxvd2VkIHRvIGJlIGluIHRoaXMgY29udGFpbmVyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYXR0ZW1wdE1vdmVDb2x1bW5zKGRyYWdTb3VyY2VUeXBlLCBjb2x1bW5zVG9Nb3ZlLCBoRGlyZWN0aW9uTm9ybWFsaXNlZCwgbW91c2VYTm9ybWFsaXNlZCwgZnJvbUVudGVyLCBmYWtlRXZlbnQpO1xuICAgIH07XG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLm5vcm1hbGlzZURpcmVjdGlvbiA9IGZ1bmN0aW9uIChoRGlyZWN0aW9uKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGhEaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBjYXNlIEhvcml6b250YWxEaXJlY3Rpb24uTGVmdDogcmV0dXJuIEhvcml6b250YWxEaXJlY3Rpb24uUmlnaHQ7XG4gICAgICAgICAgICAgICAgY2FzZSBIb3Jpem9udGFsRGlyZWN0aW9uLlJpZ2h0OiByZXR1cm4gSG9yaXpvbnRhbERpcmVjdGlvbi5MZWZ0O1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBVbmtub3duIGRpcmVjdGlvbiBcIiArIGhEaXJlY3Rpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGhEaXJlY3Rpb247XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBjb2x1bW4gaW4gdGhlIGxpc3QgT05MWSBpZiB0aGUgY29scyBhcmUgYWxsIGJlc2lkZVxuICAgIC8vIGVhY2ggb3RoZXIuIGlmIHRoZSBjb2xzIGFyZSBub3QgYmVzaWRlIGVhY2ggb3RoZXIsIHRoZW4gcmV0dXJucyBudWxsXG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLmNhbGN1bGF0ZU9sZEluZGV4ID0gZnVuY3Rpb24gKG1vdmluZ0NvbHMpIHtcbiAgICAgICAgdmFyIGdyaWRDb2xzID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxHcmlkQ29sdW1ucygpO1xuICAgICAgICB2YXIgaW5kZXhlcyA9IHNvcnROdW1lcmljYWxseShtb3ZpbmdDb2xzLm1hcChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBncmlkQ29scy5pbmRleE9mKGNvbCk7IH0pKTtcbiAgICAgICAgdmFyIGZpcnN0SW5kZXggPSBpbmRleGVzWzBdO1xuICAgICAgICB2YXIgbGFzdEluZGV4ID0gbGFzdChpbmRleGVzKTtcbiAgICAgICAgdmFyIHNwcmVhZCA9IGxhc3RJbmRleCAtIGZpcnN0SW5kZXg7XG4gICAgICAgIHZhciBnYXBzRXhpc3QgPSBzcHJlYWQgIT09IGluZGV4ZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgcmV0dXJuIGdhcHNFeGlzdCA/IG51bGwgOiBmaXJzdEluZGV4O1xuICAgIH07XG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLmF0dGVtcHRNb3ZlQ29sdW1ucyA9IGZ1bmN0aW9uIChkcmFnU291cmNlVHlwZSwgYWxsTW92aW5nQ29sdW1ucywgaERpcmVjdGlvbiwgbW91c2VYLCBmcm9tRW50ZXIsIGZha2VFdmVudCkge1xuICAgICAgICB2YXIgZHJhZ2dpbmdMZWZ0ID0gaERpcmVjdGlvbiA9PT0gSG9yaXpvbnRhbERpcmVjdGlvbi5MZWZ0O1xuICAgICAgICB2YXIgZHJhZ2dpbmdSaWdodCA9IGhEaXJlY3Rpb24gPT09IEhvcml6b250YWxEaXJlY3Rpb24uUmlnaHQ7XG4gICAgICAgIGlmIChkcmFnU291cmNlVHlwZSA9PT0gRHJhZ1NvdXJjZVR5cGUuSGVhZGVyQ2VsbCkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIGNvbHVtbnMgd2UncmUgZHJhZ2dpbmcgYXJlIHRoZSBvbmx5IHZpc2libGUgY29sdW1ucyBvZiB0aGVpciBncm91cCwgbW92ZSB0aGUgaGlkZGVuIG9uZXMgdG9vXG4gICAgICAgICAgICB2YXIgbmV3Q29sc18xID0gW107XG4gICAgICAgICAgICBhbGxNb3ZpbmdDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgIHZhciBtb3ZpbmdHcm91cCA9IG51bGw7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudCA9IGNvbC5nZXRQYXJlbnQoKTtcbiAgICAgICAgICAgICAgICB3aGlsZSAocGFyZW50ICE9IG51bGwgJiYgcGFyZW50LmdldERpc3BsYXllZExlYWZDb2x1bW5zKCkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vdmluZ0dyb3VwID0gcGFyZW50O1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQuZ2V0UGFyZW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtb3ZpbmdHcm91cCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vdmluZ0dyb3VwLmdldExlYWZDb2x1bW5zKCkuZm9yRWFjaChmdW5jdGlvbiAobmV3Q29sKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5ld0NvbHNfMS5pbmNsdWRlcyhuZXdDb2wpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q29sc18xLnB1c2gobmV3Q29sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFuZXdDb2xzXzEuaW5jbHVkZXMoY29sKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXdDb2xzXzEucHVzaChjb2wpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYWxsTW92aW5nQ29sdW1ucyA9IG5ld0NvbHNfMTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpdCBpcyBpbXBvcnRhbnQgdG8gc29ydCB0aGUgbW92aW5nIGNvbHVtbnMgYXMgdGhleSBhcmUgaW4gZ3JpZCBjb2x1bW5zLCBhcyB0aGUgbGlzdCBvZiBtb3ZpbmcgY29sdW1uc1xuICAgICAgICAvLyBjb3VsZCB0aGVtc2VsdmVzIGJlIHBhcnQgb2YgJ21hcnJpZWQgY2hpbGRyZW4nIGdyb3Vwcywgd2hpY2ggbWVhbnMgd2UgbmVlZCB0byBtYWludGFpbiB0aGUgb3JkZXIgd2l0aGluXG4gICAgICAgIC8vIHRoZSBtb3ZpbmcgbGlzdC5cbiAgICAgICAgdmFyIGFsbE1vdmluZ0NvbHVtbnNPcmRlcmVkID0gYWxsTW92aW5nQ29sdW1ucy5zbGljZSgpO1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLnNvcnRDb2x1bW5zTGlrZUdyaWRDb2x1bW5zKGFsbE1vdmluZ0NvbHVtbnNPcmRlcmVkKTtcbiAgICAgICAgdmFyIHZhbGlkTW92ZXMgPSB0aGlzLmNhbGN1bGF0ZVZhbGlkTW92ZXMoYWxsTW92aW5nQ29sdW1uc09yZGVyZWQsIGRyYWdnaW5nUmlnaHQsIG1vdXNlWCk7XG4gICAgICAgIC8vIGlmIGNvbHMgYXJlIG5vdCBhZGphY2VudCwgdGhlbiB0aGlzIHJldHVybnMgbnVsbC4gd2hlbiBtb3ZpbmcsIHdlIGNvbnN0cmFpbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBtb3ZlXG4gICAgICAgIC8vIChpZSBsZWZ0IG9yIHJpZ2h0KSB0byB0aGUgbW91c2UgZGlyZWN0aW9uLiBob3dldmVyXG4gICAgICAgIHZhciBvbGRJbmRleCA9IHRoaXMuY2FsY3VsYXRlT2xkSW5kZXgoYWxsTW92aW5nQ29sdW1uc09yZGVyZWQpO1xuICAgICAgICBpZiAodmFsaWRNb3Zlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmlyc3RWYWxpZE1vdmUgPSB2YWxpZE1vdmVzWzBdO1xuICAgICAgICAvLyB0aGUgdHdvIGNoZWNrIGJlbG93IHN0b3AgYW4gZXJyb3Igd2hlbiB0aGUgdXNlciBncmFicyBhIGdyb3VwIG15IGEgbWlkZGxlIGNvbHVtbiwgdGhlblxuICAgICAgICAvLyBpdCBpcyBwb3NzaWJsZSB0aGUgbW91c2UgcG9pbnRlciBpcyB0byB0aGUgcmlnaHQgb2YgYSBjb2x1bW4gd2hpbGUgYmVlbiBkcmFnZ2VkIGxlZnQuXG4gICAgICAgIC8vIHNvIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIG1vdXNlIHBvaW50ZXIgaXMgYWN0dWFsbHkgbGVmdCBvZiB0aGUgbGVmdCBtb3N0IGNvbHVtblxuICAgICAgICAvLyBpZiBtb3ZpbmcgbGVmdCwgYW5kIHJpZ2h0IG9mIHRoZSByaWdodCBtb3N0IGNvbHVtbiBpZiBtb3ZpbmcgcmlnaHRcbiAgICAgICAgLy8gd2UgY2hlY2sgJ2Zyb21FbnRlcicgYmVsb3cgc28gd2UgbW92ZSB0aGUgY29sdW1uIHRvIHRoZSBuZXcgc3BvdCBpZiB0aGUgbW91c2UgaXMgY29taW5nIGZyb21cbiAgICAgICAgLy8gb3V0c2lkZSB0aGUgZ3JpZCwgZWcgaWYgdGhlIGNvbHVtbiBpcyBtb3ZpbmcgZnJvbSBzaWRlIHBhbmVsLCBtb3VzZSBpcyBtb3ZpbmcgbGVmdCwgdGhlbiB3ZSBzaG91bGRcbiAgICAgICAgLy8gcGxhY2UgdGhlIGNvbHVtbiB0byB0aGUgUkhTIGV2ZW4gaWYgdGhlIG1vdXNlIGlzIG1vdmluZyBsZWZ0IGFuZCB0aGUgY29sdW1uIGlzIGFscmVhZHkgb25cbiAgICAgICAgLy8gdGhlIExIUy4gb3RoZXJ3aXNlIHdlIHN0aWNrIHRvIHRoZSBydWxlIGRlc2NyaWJlZCBhYm92ZS5cbiAgICAgICAgdmFyIGNvbnN0cmFpbkRpcmVjdGlvbiA9IG9sZEluZGV4ICE9PSBudWxsICYmICFmcm9tRW50ZXI7XG4gICAgICAgIC8vIGRvbid0IGNvbnNpZGVyICdmcm9tRW50ZXInIHdoZW4gZHJhZ2dpbmcgaGVhZGVyIGNlbGxzLCBvdGhlcndpc2UgZ3JvdXAgY2FuIGp1bXAgdG8gb3Bwb3NpdGUgZGlyZWN0aW9uIG9mIGRyYWdcbiAgICAgICAgaWYgKGRyYWdTb3VyY2VUeXBlID09IERyYWdTb3VyY2VUeXBlLkhlYWRlckNlbGwpIHtcbiAgICAgICAgICAgIGNvbnN0cmFpbkRpcmVjdGlvbiA9IG9sZEluZGV4ICE9PSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHRoZSBldmVudCB3YXMgZmFrZWQgYnkgYSBjaGFuZ2UgaW4gY29sdW1uIHBpbiBzdGF0ZSwgdGhlbiB0aGUgb3JpZ2luYWwgbG9jYXRpb24gb2YgdGhlIGNvbHVtblxuICAgICAgICAvLyBpcyBub3QgcmVsaWFibGUgZm9yIGRpY3RhdGluZyB3aGVyZSB0aGUgY29sdW1uIG1heSBub3cgYmUgcGxhY2VkLlxuICAgICAgICBpZiAoY29uc3RyYWluRGlyZWN0aW9uICYmICFmYWtlRXZlbnQpIHtcbiAgICAgICAgICAgIC8vIG9ubHkgYWxsb3cgbGVmdCBkcmFnIGlmIHRoaXMgY29sdW1uIGlzIG1vdmluZyBsZWZ0XG4gICAgICAgICAgICBpZiAoZHJhZ2dpbmdMZWZ0ICYmIGZpcnN0VmFsaWRNb3ZlID49IG9sZEluZGV4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gb25seSBhbGxvdyByaWdodCBkcmFnIGlmIHRoaXMgY29sdW1uIGlzIG1vdmluZyByaWdodFxuICAgICAgICAgICAgaWYgKGRyYWdnaW5nUmlnaHQgJiYgZmlyc3RWYWxpZE1vdmUgPD0gb2xkSW5kZXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gRnJvbSB3aGVuIHdlIGZpbmQgYSBtb3ZlIHRoYXQgcGFzc2VzIGFsbCB0aGUgcnVsZXNcbiAgICAgICAgLy8gUmVtZW1iZXIgd2hhdCB0aGF0IG1vdmUgd291bGQgbG9vayBsaWtlIGluIHRlcm1zIG9mIGRpc3BsYXllZCBjb2xzXG4gICAgICAgIC8vIGtlZXAgZ29pbmcgd2l0aCBmdXJ0aGVyIG1vdmVzIHVudGlsIHdlIGZpbmQgYSBkaWZmZXJlbnQgcmVzdWx0IGluIGRpc3BsYXllZCBvdXRwdXRcbiAgICAgICAgLy8gSW4gdGhpcyB3YXkgcG90ZW50aWFsTW92ZXMgY29udGFpbnMgYWxsIHBvdGVudGlhbCBtb3ZlcyBvdmVyICdoaWRkZW4nIGNvbHVtbnNcbiAgICAgICAgdmFyIGRpc3BsYXllZENvbHMgPSB0aGlzLmNvbHVtbk1vZGVsLmdldEFsbERpc3BsYXllZENvbHVtbnMoKTtcbiAgICAgICAgdmFyIHBvdGVudGlhbE1vdmVzID0gW107XG4gICAgICAgIHZhciB0YXJnZXRPcmRlciA9IG51bGw7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsaWRNb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIG1vdmUgPSB2YWxpZE1vdmVzW2ldO1xuICAgICAgICAgICAgdmFyIG9yZGVyID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcm9wb3NlZENvbHVtbk9yZGVyKGFsbE1vdmluZ0NvbHVtbnNPcmRlcmVkLCBtb3ZlKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5jb2x1bW5Nb2RlbC5kb2VzT3JkZXJQYXNzUnVsZXMob3JkZXIpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGlzcGxheWVkT3JkZXIgPSBvcmRlci5maWx0ZXIoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gZGlzcGxheWVkQ29scy5pbmNsdWRlcyhjb2wpOyB9KTtcbiAgICAgICAgICAgIGlmICh0YXJnZXRPcmRlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRhcmdldE9yZGVyID0gZGlzcGxheWVkT3JkZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghXy5hcmVFcXVhbChkaXNwbGF5ZWRPcmRlciwgdGFyZ2V0T3JkZXIpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7IC8vIFN0b3AgbG9va2luZyBmb3IgcG90ZW50aWFsIG1vdmVzIGlmIHRoZSBkaXNwbGF5ZWQgcmVzdWx0IGNoYW5nZXMgZnJvbSB0aGUgdGFyZ2V0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZnJhZ0NvdW50ID0gdGhpcy5ncm91cEZyYWdDb3VudChvcmRlcik7XG4gICAgICAgICAgICBwb3RlbnRpYWxNb3Zlcy5wdXNoKHsgbW92ZTogbW92ZSwgZnJhZ0NvdW50OiBmcmFnQ291bnQgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBvdGVudGlhbE1vdmVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBiZXN0IG1vdmUgaXMgdGhlIG1vdmUgd2l0aCBsZWFzdCBncm91cCBmcmFnbWVudGF0aW9uXG4gICAgICAgIHBvdGVudGlhbE1vdmVzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEuZnJhZ0NvdW50IC0gYi5mcmFnQ291bnQ7IH0pO1xuICAgICAgICB2YXIgYmVzdE1vdmUgPSBwb3RlbnRpYWxNb3Zlc1swXS5tb3ZlO1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLm1vdmVDb2x1bW5zKGFsbE1vdmluZ0NvbHVtbnNPcmRlcmVkLCBiZXN0TW92ZSwgXCJ1aUNvbHVtbkRyYWdnZWRcIik7XG4gICAgfTtcbiAgICAvLyBBIG1lYXN1cmUgb2YgaG93IGZyYWdtZW50ZWQgaW4gdGVybXMgb2YgZ3JvdXBzIGFuIG9yZGVyIG9mIGNvbHVtbnMgaXNcbiAgICBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUuZ3JvdXBGcmFnQ291bnQgPSBmdW5jdGlvbiAoY29sdW1ucykge1xuICAgICAgICBmdW5jdGlvbiBwYXJlbnRzKGNvbCkge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgdmFyIHBhcmVudCA9IGNvbC5nZXRPcmlnaW5hbFBhcmVudCgpO1xuICAgICAgICAgICAgd2hpbGUgKHBhcmVudCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gocGFyZW50KTtcbiAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQuZ2V0T3JpZ2luYWxQYXJlbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvdW50ID0gMDtcbiAgICAgICAgdmFyIF9sb29wXzEgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgdmFyIGEgPSBwYXJlbnRzKGNvbHVtbnNbaV0pO1xuICAgICAgICAgICAgdmFyIGIgPSBwYXJlbnRzKGNvbHVtbnNbaSArIDFdKTtcbiAgICAgICAgICAgIC8vIGl0ZXJhdGUgb3ZlciB0aGUgbG9uZ2VzdCBvbmVcbiAgICAgICAgICAgIF9hID0gX19yZWFkJGUoYS5sZW5ndGggPiBiLmxlbmd0aCA/IFthLCBiXSA6IFtiLCBhXSwgMiksIGEgPSBfYVswXSwgYiA9IF9hWzFdO1xuICAgICAgICAgICAgYS5mb3JFYWNoKGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoYi5pbmRleE9mKHBhcmVudCkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvdW50Kys7IC8vIE1vcmUgZnJhZ21lbnRlZCBpZiBvdGhlciBjb2x1bW4gZG9lc24ndCBzaGFyZSB0aGUgcGFyZW50XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29sdW1ucy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIF9sb29wXzEoaSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvdW50O1xuICAgIH07XG4gICAgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLmNhbGN1bGF0ZVZhbGlkTW92ZXMgPSBmdW5jdGlvbiAobW92aW5nQ29scywgZHJhZ2dpbmdSaWdodCwgbW91c2VYKSB7XG4gICAgICAgIHZhciBpc01vdmVCbG9ja2VkID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc01vdmFibGVDb2x1bW5zKCkgfHwgbW92aW5nQ29scy5zb21lKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5nZXRDb2xEZWYoKS5zdXBwcmVzc01vdmFibGU7IH0pO1xuICAgICAgICBpZiAoaXNNb3ZlQmxvY2tlZCkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGxpc3Qgb2YgY29scyBvbiB0aGUgc2NyZWVuLCBzbyBpdCdzIHRoZXNlIHdlIHVzZSB3aGVuIGNvbXBhcmluZyB0aGUgeCBtb3VzZSBwb3NpdGlvblxuICAgICAgICB2YXIgYWxsRGlzcGxheWVkQ29scyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkQ29sdW1ucyh0aGlzLnBpbm5lZCk7XG4gICAgICAgIC8vIGJ1dCB0aGlzIGxpc3QgaXMgdGhlIGxpc3Qgb2YgYWxsIGNvbHMsIHdoZW4gd2UgbW92ZSBhIGNvbCBpdCdzIHRoZSBpbmRleCB3aXRoaW4gdGhpcyBsaXN0IHRoYXQgZ2V0cyB1c2VkLFxuICAgICAgICAvLyBzbyB0aGUgcmVzdWx0IHdlIHJldHVybiBoYXMgdG8gYmUgYW5kIGluZGV4IGxvY2F0aW9uIGZvciB0aGlzIGxpc3RcbiAgICAgICAgdmFyIGFsbEdyaWRDb2xzID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxHcmlkQ29sdW1ucygpO1xuICAgICAgICB2YXIgbW92aW5nRGlzcGxheWVkQ29scyA9IGFsbERpc3BsYXllZENvbHMuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGluY2x1ZGVzKG1vdmluZ0NvbHMsIGNvbCk7IH0pO1xuICAgICAgICB2YXIgb3RoZXJEaXNwbGF5ZWRDb2xzID0gYWxsRGlzcGxheWVkQ29scy5maWx0ZXIoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gIWluY2x1ZGVzKG1vdmluZ0NvbHMsIGNvbCk7IH0pO1xuICAgICAgICB2YXIgb3RoZXJHcmlkQ29scyA9IGFsbEdyaWRDb2xzLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiAhaW5jbHVkZXMobW92aW5nQ29scywgY29sKTsgfSk7XG4gICAgICAgIC8vIHdvcmsgb3V0IGhvdyBtYW55IERJU1BMQVlFRCBjb2x1bW5zIGZpdCBiZWZvcmUgdGhlICd4JyBwb3NpdGlvbi4gdGhpcyBnaXZlcyB1cyB0aGUgZGlzcGxheUluZGV4LlxuICAgICAgICAvLyBmb3IgZXhhbXBsZSwgaWYgY29scyBhcmUgYSxiLGMsZCBhbmQgd2UgZmluZCBhLGIgZml0IGJlZm9yZSAneCcsIHRoZW4gd2Ugd2FudCB0byBwbGFjZSB0aGUgbW92aW5nXG4gICAgICAgIC8vIGNvbCBiZXR3ZWVuIGIgYW5kIGMgKHNvIHRoYXQgaXQgaXMgdW5kZXIgdGhlIG1vdXNlIHBvc2l0aW9uKS5cbiAgICAgICAgdmFyIGRpc3BsYXlJbmRleCA9IDA7XG4gICAgICAgIHZhciBhdmFpbGFibGVXaWR0aCA9IG1vdXNlWDtcbiAgICAgICAgLy8gaWYgd2UgYXJlIGRyYWdnaW5nIHJpZ2h0LCB0aGVuIHRoZSBjb2x1bW5zIHdpbGwgYmUgdG8gdGhlIGxlZnQgb2YgdGhlIG1vdXNlLCBzbyB3ZSBhbHNvIHdhbnQgdG9cbiAgICAgICAgLy8gaW5jbHVkZSB0aGUgd2lkdGggb2YgdGhlIG1vdmluZyBjb2x1bW5zXG4gICAgICAgIGlmIChkcmFnZ2luZ1JpZ2h0KSB7XG4gICAgICAgICAgICB2YXIgd2lkdGhPZk1vdmluZ0Rpc3BsYXllZENvbHNfMSA9IDA7XG4gICAgICAgICAgICBtb3ZpbmdEaXNwbGF5ZWRDb2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gd2lkdGhPZk1vdmluZ0Rpc3BsYXllZENvbHNfMSArPSBjb2wuZ2V0QWN0dWFsV2lkdGgoKTsgfSk7XG4gICAgICAgICAgICBhdmFpbGFibGVXaWR0aCAtPSB3aWR0aE9mTW92aW5nRGlzcGxheWVkQ29sc18xO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhdmFpbGFibGVXaWR0aCA+IDApIHtcbiAgICAgICAgICAgIC8vIG5vdyBjb3VudCBob3cgbWFueSBvZiB0aGUgZGlzcGxheWVkIGNvbHVtbnMgd2lsbCBmaXQgdG8gdGhlIGxlZnRcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3RoZXJEaXNwbGF5ZWRDb2xzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbCA9IG90aGVyRGlzcGxheWVkQ29sc1tpXTtcbiAgICAgICAgICAgICAgICBhdmFpbGFibGVXaWR0aCAtPSBjb2wuZ2V0QWN0dWFsV2lkdGgoKTtcbiAgICAgICAgICAgICAgICBpZiAoYXZhaWxhYmxlV2lkdGggPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkaXNwbGF5SW5kZXgrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRyaWFsIGFuZCBlcnJvciwgaWYgZ29pbmcgcmlnaHQsIHdlIGFkanVzdCBieSBvbmUsIGkgZGlkbid0IG1hbmFnZSB0byBxdWFudGlmeSB3aHksIGJ1dCBpdCB3b3Jrc1xuICAgICAgICAgICAgaWYgKGRyYWdnaW5nUmlnaHQpIHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5SW5kZXgrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyB0aGUgZGlzcGxheSBpbmRleCBpcyB3aXRoIHJlc3BlY3QgdG8gYWxsIHRoZSBzaG93aW5nIGNvbHVtbnMsIGhvd2V2ZXIgd2hlbiB3ZSBtb3ZlLCBpdCdzIHdpdGhcbiAgICAgICAgLy8gcmVzcGVjdCB0byBhbGwgZ3JpZCBjb2x1bW5zLCBzbyB3ZSBuZWVkIHRvIHRyYW5zbGF0ZSBmcm9tIGRpc3BsYXkgaW5kZXggdG8gZ3JpZCBpbmRleFxuICAgICAgICB2YXIgZmlyc3RWYWxpZE1vdmU7XG4gICAgICAgIGlmIChkaXNwbGF5SW5kZXggPiAwKSB7XG4gICAgICAgICAgICB2YXIgbGVmdENvbHVtbiA9IG90aGVyRGlzcGxheWVkQ29sc1tkaXNwbGF5SW5kZXggLSAxXTtcbiAgICAgICAgICAgIGZpcnN0VmFsaWRNb3ZlID0gb3RoZXJHcmlkQ29scy5pbmRleE9mKGxlZnRDb2x1bW4pICsgMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZpcnN0VmFsaWRNb3ZlID0gb3RoZXJHcmlkQ29scy5pbmRleE9mKG90aGVyRGlzcGxheWVkQ29sc1swXSk7XG4gICAgICAgICAgICBpZiAoZmlyc3RWYWxpZE1vdmUgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgZmlyc3RWYWxpZE1vdmUgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciB2YWxpZE1vdmVzID0gW2ZpcnN0VmFsaWRNb3ZlXTtcbiAgICAgICAgdmFyIG51bWJlckNvbXBhcmF0b3IgPSBmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYSAtIGI7IH07XG4gICAgICAgIC8vIGFkZCBpbiBvdGhlciB2YWxpZCBtb3ZlcyBkdWUgdG8gaGlkZGVuIGNvbHVtbnMgYW5kIG1hcnJpZWQgY2hpbGRyZW4uIGZvciBleGFtcGxlLCBhIHBhcnRpY3VsYXJcbiAgICAgICAgLy8gbW92ZSBtaWdodCBicmVhayBhIGdyb3VwIHRoYXQgaGFzIG1hcnJpZWQgY2hpbGRyZW4gKHNvIG1vdmUgaXNuJ3QgdmFsaWQpLCBob3dldmVyIHRoZXJlIGNvdWxkXG4gICAgICAgIC8vIGJlIGhpZGRlbiBjb2x1bW5zIChub3QgZGlzcGxheWVkKSB0aGF0IHdlIGNvdWxkIGp1bXAgb3ZlciB0byBtYWtlIHRoZSBtb3ZlIHZhbGlkLiBiZWNhdXNlXG4gICAgICAgIC8vIHRoZXkgYXJlIGhpZGRlbiwgdXNlciBkb2Vzbid0IHNlZSBhbnkgZGlmZmVyZW50LCBob3dldmVyIGl0IGFsbG93cyBtb3ZlcyB0aGF0IHdvdWxkIG90aGVyd2lzZVxuICAgICAgICAvLyBub3Qgd29yay4gZm9yIGV4YW1wbGUgaW1hZ2luZSBhIGdyb3VwIHdpdGggOSBjb2x1bW5zIGFuZCBhbGwgY29sdW1ucyBhcmUgaGlkZGVuIGV4Y2VwdCB0aGVcbiAgICAgICAgLy8gbWlkZGxlIG9uZSAoc28gNCBoaWRkZW4gdG8gbGVmdCwgNCBoaWRkZW4gdG8gcmlnaHQpLCB0aGVuIHdoZW4gbW92aW5nICdmaXJzdFZhbGlkTW92ZScgd2lsbFxuICAgICAgICAvLyBiZSByZWxhdGl2ZSB0byB0aGUgbm90LXNob3duIGNvbHVtbiwgaG93ZXZlciB3ZSBuZWVkIHRvIGNvbnNpZGVyIHRoZSBtb3ZlIGp1bXBpbmcgb3ZlciBhbGwgdGhlXG4gICAgICAgIC8vIGhpZGRlbiBjaGlsZHJlbi4gaWYgd2UgZGlkbid0IGRvIHRoaXMsIHRoZW4gaWYgdGhlIGdyb3VwIGp1c3QgZGVzY3JpYmVkIHdhcyBhdCB0aGUgZW5kIChSSFMpIG9mIHRoZVxuICAgICAgICAvLyBncmlkLCB0aGVyZSB3b3VsZCBiZSBubyB3YXkgdG8gcHV0IGEgY29sdW1uIGFmdGVyIGl0IChhcyB0aGUgZ3JpZCB3b3VsZCBvbmx5IGNvbnNpZGVyIGJlc2lkZSB0aGVcbiAgICAgICAgLy8gdmlzaWJsZSBjb2x1bW4sIHdoaWNoIHdvdWxkIGZhaWwgdmFsaWQgbW92ZSBydWxlcykuXG4gICAgICAgIGlmIChkcmFnZ2luZ1JpZ2h0KSB7XG4gICAgICAgICAgICAvLyBpZiBkcmFnZ2luZyByaWdodCwgdGhlbiB3ZSBhZGQgYWxsIHRoZSBhZGRpdGlvbmFsIG1vdmVzIHRvIHRoZSByaWdodC4gc28gaW4gb3RoZXIgd29yZHNcbiAgICAgICAgICAgIC8vIGlmIHRoZSBuZXh0IG1vdmUgaXMgbm90IHZhbGlkLCBmaW5kIHRoZSBuZXh0IG1vdmUgdG8gdGhlIHJpZ2h0IHRoYXQgaXMgdmFsaWQuXG4gICAgICAgICAgICB2YXIgcG9pbnRlciA9IGZpcnN0VmFsaWRNb3ZlICsgMTtcbiAgICAgICAgICAgIHZhciBsYXN0SW5kZXggPSBhbGxHcmlkQ29scy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUgKHBvaW50ZXIgPD0gbGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFsaWRNb3Zlcy5wdXNoKHBvaW50ZXIpO1xuICAgICAgICAgICAgICAgIHBvaW50ZXIrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGFkZGluZyBjb2x1bW5zIGhlcmUgbWVhbnMgdGhlIG9yZGVyIGlzIG5vdyBtZXNzZWQgdXBcbiAgICAgICAgICAgIHZhbGlkTW92ZXMuc29ydChudW1iZXJDb21wYXJhdG9yKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIGRyYWdnaW5nIGxlZnQgd2UgZG8gdGhlIHJldmVyc2Ugb2YgZHJhZ2dpbmcgcmlnaHQsIHdlIGFkZCBpbiBhbGwgdGhlIHZhbGlkIG1vdmVzIHRvIHRoZVxuICAgICAgICAgICAgLy8gbGVmdC4gaG93ZXZlciB3ZSBhbHNvIGhhdmUgdG8gY29uc2lkZXIgbW92ZXMgdG8gdGhlIHJpZ2h0IGZvciBhbGwgaGlkZGVuIGNvbHVtbnMgZmlyc3QuXG4gICAgICAgICAgICAvLyAodGhpcyBsb2dpYyBpcyBoYXJkIHRvIHJlYXNvbiB3aXRoLCBpdCB3YXMgd29ya2VkIG91dCB3aXRoIHRyaWFsIGFuZCBlcnJvcixcbiAgICAgICAgICAgIC8vIG1vcmUgb2JzZXJ2YXRpb24gcmF0aGVyIHRoYW4gc2NpZW5jZSkuXG4gICAgICAgICAgICAvLyBhZGQgbW92ZXMgdG8gdGhlIHJpZ2h0XG4gICAgICAgICAgICB2YXIgcG9pbnRlciA9IGZpcnN0VmFsaWRNb3ZlO1xuICAgICAgICAgICAgdmFyIGxhc3RJbmRleCA9IGFsbEdyaWRDb2xzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB2YXIgZGlzcGxhY2VkQ29sID0gYWxsR3JpZENvbHNbcG9pbnRlcl07XG4gICAgICAgICAgICB3aGlsZSAocG9pbnRlciA8PSBsYXN0SW5kZXggJiYgdGhpcy5pc0NvbHVtbkhpZGRlbihhbGxEaXNwbGF5ZWRDb2xzLCBkaXNwbGFjZWRDb2wpKSB7XG4gICAgICAgICAgICAgICAgcG9pbnRlcisrO1xuICAgICAgICAgICAgICAgIHZhbGlkTW92ZXMucHVzaChwb2ludGVyKTtcbiAgICAgICAgICAgICAgICBkaXNwbGFjZWRDb2wgPSBhbGxHcmlkQ29sc1twb2ludGVyXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGFkZCBtb3ZlcyB0byB0aGUgbGVmdFxuICAgICAgICAgICAgcG9pbnRlciA9IGZpcnN0VmFsaWRNb3ZlIC0gMTtcbiAgICAgICAgICAgIHZhciBmaXJzdERpc3BsYXlJbmRleCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAocG9pbnRlciA+PSBmaXJzdERpc3BsYXlJbmRleCkge1xuICAgICAgICAgICAgICAgIHZhbGlkTW92ZXMucHVzaChwb2ludGVyKTtcbiAgICAgICAgICAgICAgICBwb2ludGVyLS07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhZGRpbmcgY29sdW1ucyBoZXJlIG1lYW5zIHRoZSBvcmRlciBpcyBub3cgbWVzc2VkIHVwXG4gICAgICAgICAgICB2YWxpZE1vdmVzLnNvcnQobnVtYmVyQ29tcGFyYXRvcikucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWxpZE1vdmVzO1xuICAgIH07XG4gICAgLy8gaXNIaWRkZW4gdGFrZXMgaW50byBhY2NvdW50IHZpc2libGU9ZmFsc2UgYW5kIGdyb3VwPWNsb3NlZCwgaWUgaXQgaXMgbm90IGRpc3BsYXllZFxuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5pc0NvbHVtbkhpZGRlbiA9IGZ1bmN0aW9uIChkaXNwbGF5ZWRDb2x1bW5zLCBjb2wpIHtcbiAgICAgICAgcmV0dXJuIGRpc3BsYXllZENvbHVtbnMuaW5kZXhPZihjb2wpIDwgMDtcbiAgICB9O1xuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5lbnN1cmVJbnRlcnZhbFN0YXJ0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5tb3ZpbmdJbnRlcnZhbElkKSB7XG4gICAgICAgICAgICB0aGlzLmludGVydmFsQ291bnQgPSAwO1xuICAgICAgICAgICAgdGhpcy5mYWlsZWRNb3ZlQXR0ZW1wdHMgPSAwO1xuICAgICAgICAgICAgdGhpcy5tb3ZpbmdJbnRlcnZhbElkID0gd2luZG93LnNldEludGVydmFsKHRoaXMubW92ZUludGVydmFsLmJpbmQodGhpcyksIDEwMCk7XG4gICAgICAgICAgICBpZiAodGhpcy5uZWVkVG9Nb3ZlTGVmdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLnNldEdob3N0SWNvbihEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9MRUZULCB0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLnNldEdob3N0SWNvbihEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9SSUdIVCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIE1vdmVDb2x1bW5GZWF0dXJlLnByb3RvdHlwZS5lbnN1cmVJbnRlcnZhbENsZWFyZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm1vdmluZ0ludGVydmFsSWQpIHtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKHRoaXMubW92aW5nSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICB0aGlzLm1vdmluZ0ludGVydmFsSWQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5kcmFnQW5kRHJvcFNlcnZpY2Uuc2V0R2hvc3RJY29uKERyYWdBbmREcm9wU2VydmljZS5JQ09OX01PVkUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUubW92ZUludGVydmFsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB0aGUgYW1vdW50cyB3ZSBtb3ZlIGdldCBiaWdnZXIgYXQgZWFjaCBpbnRlcnZhbCwgc28gdGhlIHNwZWVkIGFjY2VsZXJhdGVzLCBzdGFydGluZyBhIGJpdCBzbG93XG4gICAgICAgIC8vIGFuZCBnZXR0aW5nIGZhc3Rlci4gdGhpcyBpcyB0byBnaXZlIHNtb290aGVyIHVzZXIgZXhwZXJpZW5jZS4gd2UgbWF4IGF0IDEwMHB4IHRvIGxpbWl0IHRoZSBzcGVlZC5cbiAgICAgICAgdmFyIHBpeGVsc1RvTW92ZTtcbiAgICAgICAgdGhpcy5pbnRlcnZhbENvdW50Kys7XG4gICAgICAgIHBpeGVsc1RvTW92ZSA9IDEwICsgKHRoaXMuaW50ZXJ2YWxDb3VudCAqIDUpO1xuICAgICAgICBpZiAocGl4ZWxzVG9Nb3ZlID4gMTAwKSB7XG4gICAgICAgICAgICBwaXhlbHNUb01vdmUgPSAxMDA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBpeGVsc01vdmVkID0gbnVsbDtcbiAgICAgICAgdmFyIHNjcm9sbEZlYXR1cmUgPSB0aGlzLmdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKTtcbiAgICAgICAgaWYgKHRoaXMubmVlZFRvTW92ZUxlZnQpIHtcbiAgICAgICAgICAgIHBpeGVsc01vdmVkID0gc2Nyb2xsRmVhdHVyZS5zY3JvbGxIb3Jpem9udGFsbHkoLXBpeGVsc1RvTW92ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5uZWVkVG9Nb3ZlUmlnaHQpIHtcbiAgICAgICAgICAgIHBpeGVsc01vdmVkID0gc2Nyb2xsRmVhdHVyZS5zY3JvbGxIb3Jpem9udGFsbHkocGl4ZWxzVG9Nb3ZlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGl4ZWxzTW92ZWQgIT09IDApIHtcbiAgICAgICAgICAgIHRoaXMub25EcmFnZ2luZyh0aGlzLmxhc3REcmFnZ2luZ0V2ZW50KTtcbiAgICAgICAgICAgIHRoaXMuZmFpbGVkTW92ZUF0dGVtcHRzID0gMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHdlIGNvdW50IHRoZSBmYWlsZWQgbW92ZSBhdHRlbXB0cy4gaWYgd2UgZmFpbCB0byBtb3ZlIDcgdGltZXMsIHRoZW4gd2UgcGluIHRoZSBjb2x1bW4uXG4gICAgICAgICAgICAvLyB0aGlzIGlzIGhvdyB3ZSBhY2hpZXZlIHBpbmluZyBieSBkcmFnZ2luZyB0aGUgY29sdW1uIHRvIHRoZSBlZGdlIG9mIHRoZSBncmlkLlxuICAgICAgICAgICAgdGhpcy5mYWlsZWRNb3ZlQXR0ZW1wdHMrKztcbiAgICAgICAgICAgIHZhciBjb2x1bW5zID0gdGhpcy5sYXN0RHJhZ2dpbmdFdmVudC5kcmFnSXRlbS5jb2x1bW5zO1xuICAgICAgICAgICAgdmFyIGNvbHVtbnNUaGF0Q2FuUGluID0gY29sdW1ucy5maWx0ZXIoZnVuY3Rpb24gKGMpIHsgcmV0dXJuICFjLmdldENvbERlZigpLmxvY2tQaW5uZWQ7IH0pO1xuICAgICAgICAgICAgaWYgKGNvbHVtbnNUaGF0Q2FuUGluLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWdBbmREcm9wU2VydmljZS5zZXRHaG9zdEljb24oRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fUElOTkVEKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5mYWlsZWRNb3ZlQXR0ZW1wdHMgPiA3KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwaW5UeXBlID0gdGhpcy5uZWVkVG9Nb3ZlTGVmdCA/IENvbnN0YW50cy5QSU5ORURfTEVGVCA6IENvbnN0YW50cy5QSU5ORURfUklHSFQ7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Q29sdW1uc1Bpbm5lZChjb2x1bW5zVGhhdENhblBpbiwgcGluVHlwZSwgXCJ1aUNvbHVtbkRyYWdnZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLm51ZGdlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDF4KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgTW92ZUNvbHVtbkZlYXR1cmUucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxeChbXG4gICAgICAgIEF1dG93aXJlZCgnZHJhZ0FuZERyb3BTZXJ2aWNlJylcbiAgICBdLCBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUsIFwiZHJhZ0FuZERyb3BTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxeChbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZE9wdGlvbnNXcmFwcGVyJylcbiAgICBdLCBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUsIFwiZ3JpZE9wdGlvbnNXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxeChbXG4gICAgICAgIEF1dG93aXJlZCgnY3RybHNTZXJ2aWNlJylcbiAgICBdLCBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxeChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBNb3ZlQ29sdW1uRmVhdHVyZS5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICByZXR1cm4gTW92ZUNvbHVtbkZlYXR1cmU7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFEID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxdyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEJvZHlEcm9wVGFyZ2V0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxRChCb2R5RHJvcFRhcmdldCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBCb2R5RHJvcFRhcmdldChwaW5uZWQsIGVDb250YWluZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucGlubmVkID0gcGlubmVkO1xuICAgICAgICBfdGhpcy5lQ29udGFpbmVyID0gZUNvbnRhaW5lcjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKF90aGlzLnBpbm5lZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9MRUZUOlxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5lU2Vjb25kYXJ5Q29udGFpbmVycyA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwLmdyaWRCb2R5Q3RybC5nZXRCb2R5Vmlld3BvcnRFbGVtZW50KCksIHAubGVmdFJvd0NvbnRhaW5lckN0cmwuZ2V0Q29udGFpbmVyRWxlbWVudCgpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwLmJvdHRvbUxlZnRSb3dDb250YWluZXJDdHJsLmdldENvbnRhaW5lckVsZW1lbnQoKV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbcC50b3BMZWZ0Um93Q29udGFpbmVyQ3RybC5nZXRDb250YWluZXJFbGVtZW50KCldXG4gICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDpcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZVNlY29uZGFyeUNvbnRhaW5lcnMgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICBbcC5ncmlkQm9keUN0cmwuZ2V0Qm9keVZpZXdwb3J0RWxlbWVudCgpLCBwLnJpZ2h0Um93Q29udGFpbmVyQ3RybC5nZXRDb250YWluZXJFbGVtZW50KCldLFxuICAgICAgICAgICAgICAgICAgICAgICAgW3AuYm90dG9tUmlnaHRSb3dDb250YWluZXJDdHJsLmdldENvbnRhaW5lckVsZW1lbnQoKV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbcC50b3BSaWdodFJvd0NvbnRhaW5lckN0cmwuZ2V0Q29udGFpbmVyRWxlbWVudCgpXVxuICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5lU2Vjb25kYXJ5Q29udGFpbmVycyA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwLmdyaWRCb2R5Q3RybC5nZXRCb2R5Vmlld3BvcnRFbGVtZW50KCksIHAuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRWaWV3cG9ydEVsZW1lbnQoKV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbcC5ib3R0b21DZW50ZXJSb3dDb250YWluZXJDdHJsLmdldFZpZXdwb3J0RWxlbWVudCgpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtwLnRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwuZ2V0Vmlld3BvcnRFbGVtZW50KCldXG4gICAgICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEJvZHlEcm9wVGFyZ2V0LnByb3RvdHlwZS5pc0ludGVyZXN0ZWRJbiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIHJldHVybiB0eXBlID09PSBEcmFnU291cmNlVHlwZS5IZWFkZXJDZWxsIHx8XG4gICAgICAgICAgICAodHlwZSA9PT0gRHJhZ1NvdXJjZVR5cGUuVG9vbFBhbmVsICYmIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQWxsb3dEcmFnRnJvbUNvbHVtbnNUb29sUGFuZWwoKSk7XG4gICAgfTtcbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUuZ2V0U2Vjb25kYXJ5Q29udGFpbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZVNlY29uZGFyeUNvbnRhaW5lcnM7XG4gICAgfTtcbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUuZ2V0Q29udGFpbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lQ29udGFpbmVyO1xuICAgIH07XG4gICAgQm9keURyb3BUYXJnZXQucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMubW92ZUNvbHVtbkZlYXR1cmUgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBNb3ZlQ29sdW1uRmVhdHVyZSh0aGlzLnBpbm5lZCwgdGhpcy5lQ29udGFpbmVyKSk7XG4gICAgICAgIHRoaXMuYm9keURyb3BQaXZvdFRhcmdldCA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEJvZHlEcm9wUGl2b3RUYXJnZXQodGhpcy5waW5uZWQpKTtcbiAgICAgICAgdGhpcy5kcmFnQW5kRHJvcFNlcnZpY2UuYWRkRHJvcFRhcmdldCh0aGlzKTtcbiAgICB9O1xuICAgIEJvZHlEcm9wVGFyZ2V0LnByb3RvdHlwZS5nZXRJY29uTmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudERyb3BMaXN0ZW5lci5nZXRJY29uTmFtZSgpO1xuICAgIH07XG4gICAgLy8gd2Ugd2FudCB0byB1c2UgdGhlIGJvZHlQaXZvdFRhcmdldCBpZiB0aGUgdXNlciBpcyBkcmFnZ2luZyBjb2x1bW5zIGluIGZyb20gdGhlIHRvb2xQYW5lbFxuICAgIC8vIGFuZCB3ZSBhcmUgaW4gcGl2b3QgbW9kZSwgYXMgaXQgaGFzIHRvIGxvZ2ljIHRvIHNldCBwaXZvdC92YWx1ZS9ncm91cCBvbiB0aGUgY29sdW1ucyB3aGVuXG4gICAgLy8gZHJvcHBlZCBpbnRvIHRoZSBncmlkJ3MgYm9keS5cbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUuaXNEcm9wQ29sdW1uSW5QaXZvdE1vZGUgPSBmdW5jdGlvbiAoZHJhZ2dpbmdFdmVudCkge1xuICAgICAgICAvLyBpbiBwaXZvdCBtb2RlLCB0aGVuIGlmIG1vdmluZyBhIGNvbHVtbiAoaWUgZGlkbid0IGNvbWUgZnJvbSB0b29scGFuZWwpIHRoZW4gaXQnc1xuICAgICAgICAvLyBhIHN0YW5kYXJkIGNvbHVtbiBtb3ZlLCBob3dldmVyIGlmIGl0IGNhbWUgZnJvbSB0aGUgdG9vbHBhbmVsLCB0aGVuIHdlIGFyZSBpbnRyb2R1Y2luZ1xuICAgICAgICAvLyBkaW1lbnNpb25zIG9yIHZhbHVlcyB0byB0aGUgZ3JpZFxuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90TW9kZSgpICYmIGRyYWdnaW5nRXZlbnQuZHJhZ1NvdXJjZS50eXBlID09PSBEcmFnU291cmNlVHlwZS5Ub29sUGFuZWw7XG4gICAgfTtcbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUub25EcmFnRW50ZXIgPSBmdW5jdGlvbiAoZHJhZ2dpbmdFdmVudCkge1xuICAgICAgICAvLyB3ZSBwaWNrIHRoZSBkcm9wIGxpc3RlbmVyIGRlcGVuZGluZyBvbiB3aGV0aGVyIHdlIGFyZSBpbiBwaXZvdCBtb2RlIGFyZSBub3QuIGlmIHdlIGFyZVxuICAgICAgICAvLyBpbiBwaXZvdCBtb2RlLCB0aGVuIGRyb3BwaW5nIGNvbHMgY2hhbmdlcyB0aGUgcm93IGdyb3VwLCBwaXZvdCwgdmFsdWUgc3RhdHMuIG90aGVyd2lzZVxuICAgICAgICAvLyB3ZSBjaGFuZ2UgdmlzaWJpbGl0eSBzdGF0ZSBhbmQgcG9zaXRpb24uXG4gICAgICAgIHRoaXMuY3VycmVudERyb3BMaXN0ZW5lciA9IHRoaXMuaXNEcm9wQ29sdW1uSW5QaXZvdE1vZGUoZHJhZ2dpbmdFdmVudCkgPyB0aGlzLmJvZHlEcm9wUGl2b3RUYXJnZXQgOiB0aGlzLm1vdmVDb2x1bW5GZWF0dXJlO1xuICAgICAgICB0aGlzLmN1cnJlbnREcm9wTGlzdGVuZXIub25EcmFnRW50ZXIoZHJhZ2dpbmdFdmVudCk7XG4gICAgfTtcbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUub25EcmFnTGVhdmUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMuY3VycmVudERyb3BMaXN0ZW5lci5vbkRyYWdMZWF2ZShwYXJhbXMpO1xuICAgIH07XG4gICAgQm9keURyb3BUYXJnZXQucHJvdG90eXBlLm9uRHJhZ2dpbmcgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMuY3VycmVudERyb3BMaXN0ZW5lci5vbkRyYWdnaW5nKHBhcmFtcyk7XG4gICAgfTtcbiAgICBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUub25EcmFnU3RvcCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50RHJvcExpc3RlbmVyLm9uRHJhZ1N0b3AocGFyYW1zKTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMXcoW1xuICAgICAgICBBdXRvd2lyZWQoJ2RyYWdBbmREcm9wU2VydmljZScpXG4gICAgXSwgQm9keURyb3BUYXJnZXQucHJvdG90eXBlLCBcImRyYWdBbmREcm9wU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXcoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBCb2R5RHJvcFRhcmdldC5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDF3KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEJvZHlEcm9wVGFyZ2V0LnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDF3KFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIEJvZHlEcm9wVGFyZ2V0LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMXcoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgQm9keURyb3BUYXJnZXQucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEJvZHlEcm9wVGFyZ2V0O1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19yZWFkJGQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgX19zcHJlYWQkYiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCRkKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG52YXIgQ3NzQ2xhc3NBcHBsaWVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENzc0NsYXNzQXBwbGllcigpIHtcbiAgICB9XG4gICAgQ3NzQ2xhc3NBcHBsaWVyLmdldEhlYWRlckNsYXNzZXNGcm9tQ29sRGVmID0gZnVuY3Rpb24gKGFic3RyYWN0Q29sRGVmLCBncmlkT3B0aW9uc1dyYXBwZXIsIGNvbHVtbiwgY29sdW1uR3JvdXApIHtcbiAgICAgICAgaWYgKG1pc3NpbmcoYWJzdHJhY3RDb2xEZWYpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uQ2xhc3Nlc0Zyb21Db2xsRGVmKGFic3RyYWN0Q29sRGVmLmhlYWRlckNsYXNzLCBhYnN0cmFjdENvbERlZiwgZ3JpZE9wdGlvbnNXcmFwcGVyLCBjb2x1bW4sIGNvbHVtbkdyb3VwKTtcbiAgICB9O1xuICAgIENzc0NsYXNzQXBwbGllci5nZXRUb29sUGFuZWxDbGFzc2VzRnJvbUNvbERlZiA9IGZ1bmN0aW9uIChhYnN0cmFjdENvbERlZiwgZ3JpZE9wdGlvbnNXcmFwcGVyLCBjb2x1bW4sIGNvbHVtbkdyb3VwKSB7XG4gICAgICAgIGlmIChtaXNzaW5nKGFic3RyYWN0Q29sRGVmKSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbHVtbkNsYXNzZXNGcm9tQ29sbERlZihhYnN0cmFjdENvbERlZi50b29sUGFuZWxDbGFzcywgYWJzdHJhY3RDb2xEZWYsIGdyaWRPcHRpb25zV3JhcHBlciwgY29sdW1uLCBjb2x1bW5Hcm91cCk7XG4gICAgfTtcbiAgICBDc3NDbGFzc0FwcGxpZXIuZ2V0Q2xhc3NQYXJhbXMgPSBmdW5jdGlvbiAoYWJzdHJhY3RDb2xEZWYsIGdyaWRPcHRpb25zV3JhcHBlciwgY29sdW1uLCBjb2x1bW5Hcm91cCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLy8gYmFkIG5hbWluZywgYXMgY29sRGVmIGhlcmUgY2FuIGJlIGEgZ3JvdXAgb3IgYSBjb2x1bW4sXG4gICAgICAgICAgICAvLyBob3dldmVyIG1vc3QgcGVvcGxlIHdvbid0IGFwcHJlY2lhdGUgdGhlIGRpZmZlcmVuY2UsXG4gICAgICAgICAgICAvLyBzbyBrZWVwaW5nIGl0IGFzIGNvbERlZiB0byBhdm9pZCBjb25mdXNpb24uXG4gICAgICAgICAgICBjb2xEZWY6IGFic3RyYWN0Q29sRGVmLFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICBjb2x1bW5Hcm91cDogY29sdW1uR3JvdXAsXG4gICAgICAgICAgICBhcGk6IGdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgY29udGV4dDogZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICB9O1xuICAgIH07XG4gICAgQ3NzQ2xhc3NBcHBsaWVyLmdldENvbHVtbkNsYXNzZXNGcm9tQ29sbERlZiA9IGZ1bmN0aW9uIChjbGFzc2VzT3JGdW5jLCBhYnN0cmFjdENvbERlZiwgZ3JpZE9wdGlvbnNXcmFwcGVyLCBjb2x1bW4sIGNvbHVtbkdyb3VwKSB7XG4gICAgICAgIGlmIChtaXNzaW5nKGNsYXNzZXNPckZ1bmMpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNsYXNzVG9Vc2U7XG4gICAgICAgIGlmICh0eXBlb2YgY2xhc3Nlc09yRnVuYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHRoaXMuZ2V0Q2xhc3NQYXJhbXMoYWJzdHJhY3RDb2xEZWYsIGdyaWRPcHRpb25zV3JhcHBlciwgY29sdW1uLCBjb2x1bW5Hcm91cCk7XG4gICAgICAgICAgICBjbGFzc1RvVXNlID0gY2xhc3Nlc09yRnVuYyhwYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NUb1VzZSA9IGNsYXNzZXNPckZ1bmM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBjbGFzc1RvVXNlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIFtjbGFzc1RvVXNlXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjbGFzc1RvVXNlKSkge1xuICAgICAgICAgICAgcmV0dXJuIF9fc3ByZWFkJGIoY2xhc3NUb1VzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH07XG4gICAgcmV0dXJuIENzc0NsYXNzQXBwbGllcjtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMUMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDF2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgSGVhZGVyQ2VsbENvbXAgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFDKEhlYWRlckNlbGxDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlckNlbGxDb21wKGN0cmwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgSGVhZGVyQ2VsbENvbXAuVEVNUExBVEUsIGN0cmwpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmhlYWRlckNvbXBWZXJzaW9uID0gMDtcbiAgICAgICAgX3RoaXMuY29sdW1uID0gY3RybC5nZXRDb2x1bW5Hcm91cENoaWxkKCk7XG4gICAgICAgIF90aGlzLnBpbm5lZCA9IGN0cmwuZ2V0UGlubmVkKCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgSGVhZGVyQ2VsbENvbXAucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgdmFyIHNldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIChuYW1lLCB2YWx1ZSwgZWxlbWVudCkge1xuICAgICAgICAgICAgdmFyIGFjdHVhbEVsZW1lbnQgPSBlbGVtZW50ID8gZWxlbWVudCA6IGVHdWk7XG4gICAgICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCAmJiB2YWx1ZSAhPSAnJykge1xuICAgICAgICAgICAgICAgIGFjdHVhbEVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGFjdHVhbEVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcFByb3h5ID0ge1xuICAgICAgICAgICAgc2V0V2lkdGg6IGZ1bmN0aW9uICh3aWR0aCkgeyByZXR1cm4gZUd1aS5zdHlsZS53aWR0aCA9IHdpZHRoOyB9LFxuICAgICAgICAgICAgYWRkT3JSZW1vdmVDc3NDbGFzczogZnVuY3Rpb24gKGNzc0NsYXNzTmFtZSwgb24pIHsgcmV0dXJuIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoY3NzQ2xhc3NOYW1lLCBvbik7IH0sXG4gICAgICAgICAgICBzZXRDb2xJZDogZnVuY3Rpb24gKGlkKSB7IHJldHVybiBzZXRBdHRyaWJ1dGUoJ2NvbC1pZCcsIGlkKTsgfSxcbiAgICAgICAgICAgIHNldFRpdGxlOiBmdW5jdGlvbiAodGl0bGUpIHsgcmV0dXJuIHNldEF0dHJpYnV0ZSgndGl0bGUnLCB0aXRsZSk7IH0sXG4gICAgICAgICAgICBzZXRBcmlhRGVzY3JpcHRpb246IGZ1bmN0aW9uIChsYWJlbCkgeyByZXR1cm4gc2V0QXJpYURlc2NyaXB0aW9uKGVHdWksIGxhYmVsKTsgfSxcbiAgICAgICAgICAgIHNldEFyaWFTb3J0OiBmdW5jdGlvbiAoc29ydCkgeyByZXR1cm4gc29ydCA/IHNldEFyaWFTb3J0KGVHdWksIHNvcnQpIDogcmVtb3ZlQXJpYVNvcnQoZUd1aSk7IH0sXG4gICAgICAgICAgICBzZXRVc2VyQ29tcERldGFpbHM6IGZ1bmN0aW9uIChjb21wRGV0YWlscykgeyByZXR1cm4gX3RoaXMuc2V0VXNlckNvbXBEZXRhaWxzKGNvbXBEZXRhaWxzKTsgfSxcbiAgICAgICAgICAgIGdldFVzZXJDb21wSW5zdGFuY2U6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmhlYWRlckNvbXA7IH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jdHJsLnNldENvbXAoY29tcFByb3h5LCB0aGlzLmdldEd1aSgpLCB0aGlzLmVSZXNpemUsIHRoaXMuZUhlYWRlckNvbXBXcmFwcGVyKTtcbiAgICAgICAgdmFyIHNlbGVjdEFsbEd1aSA9IHRoaXMuY3RybC5nZXRTZWxlY3RBbGxHdWkoKTtcbiAgICAgICAgdGhpcy5lUmVzaXplLmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJlbmQnLCBzZWxlY3RBbGxHdWkpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbENvbXAucHJvdG90eXBlLmRlc3Ryb3lIZWFkZXJDb21wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5oZWFkZXJDb21wKSB7XG4gICAgICAgICAgICB0aGlzLmVIZWFkZXJDb21wV3JhcHBlci5yZW1vdmVDaGlsZCh0aGlzLmhlYWRlckNvbXBHdWkpO1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJDb21wID0gdGhpcy5kZXN0cm95QmVhbih0aGlzLmhlYWRlckNvbXApO1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJDb21wR3VpID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ29tcC5wcm90b3R5cGUuc2V0VXNlckNvbXBEZXRhaWxzID0gZnVuY3Rpb24gKGNvbXBEZXRhaWxzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuaGVhZGVyQ29tcFZlcnNpb24rKztcbiAgICAgICAgdmFyIHZlcnNpb25Db3B5ID0gdGhpcy5oZWFkZXJDb21wVmVyc2lvbjtcbiAgICAgICAgY29tcERldGFpbHMubmV3QWdTdGFja0luc3RhbmNlKCkudGhlbihmdW5jdGlvbiAoY29tcCkgeyByZXR1cm4gX3RoaXMuYWZ0ZXJDb21wQ3JlYXRlZCh2ZXJzaW9uQ29weSwgY29tcCk7IH0pO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbENvbXAucHJvdG90eXBlLmFmdGVyQ29tcENyZWF0ZWQgPSBmdW5jdGlvbiAodmVyc2lvbiwgaGVhZGVyQ29tcCkge1xuICAgICAgICBpZiAodmVyc2lvbiAhPSB0aGlzLmhlYWRlckNvbXBWZXJzaW9uIHx8ICF0aGlzLmlzQWxpdmUoKSkge1xuICAgICAgICAgICAgdGhpcy5kZXN0cm95QmVhbihoZWFkZXJDb21wKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlc3Ryb3lIZWFkZXJDb21wKCk7XG4gICAgICAgIHRoaXMuaGVhZGVyQ29tcCA9IGhlYWRlckNvbXA7XG4gICAgICAgIHRoaXMuaGVhZGVyQ29tcEd1aSA9IGhlYWRlckNvbXAuZ2V0R3VpKCk7XG4gICAgICAgIHRoaXMuZUhlYWRlckNvbXBXcmFwcGVyLmFwcGVuZENoaWxkKHRoaXMuaGVhZGVyQ29tcEd1aSk7XG4gICAgICAgIHRoaXMuY3RybC5zZXREcmFnU291cmNlKHRoaXMuZ2V0R3VpKCkpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbENvbXAuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWhlYWRlci1jZWxsXFxcIiByb2xlPVxcXCJjb2x1bW5oZWFkZXJcXFwiIHRhYmluZGV4PVxcXCItMVxcXCI+XFxuICAgICAgICAgICAgPGRpdiByZWY9XFxcImVSZXNpemVcXFwiIGNsYXNzPVxcXCJhZy1oZWFkZXItY2VsbC1yZXNpemVcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPGRpdiByZWY9XFxcImVIZWFkZXJDb21wV3JhcHBlclxcXCIgY2xhc3M9XFxcImFnLWhlYWRlci1jZWxsLWNvbXAtd3JhcHBlclxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj48L2Rpdj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkMXYoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVJlc2l6ZScpXG4gICAgXSwgSGVhZGVyQ2VsbENvbXAucHJvdG90eXBlLCBcImVSZXNpemVcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDF2KFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VIZWFkZXJDb21wV3JhcHBlcicpXG4gICAgXSwgSGVhZGVyQ2VsbENvbXAucHJvdG90eXBlLCBcImVIZWFkZXJDb21wV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXYoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgSGVhZGVyQ2VsbENvbXAucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgX19kZWNvcmF0ZSQxdihbXG4gICAgICAgIFByZURlc3Ryb3lcbiAgICBdLCBIZWFkZXJDZWxsQ29tcC5wcm90b3R5cGUsIFwiZGVzdHJveUhlYWRlckNvbXBcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEhlYWRlckNlbGxDb21wO1xufShBYnN0cmFjdEhlYWRlckNlbGxDb21wKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMUIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDF1ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgSGVhZGVyR3JvdXBDZWxsQ29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMUIoSGVhZGVyR3JvdXBDZWxsQ29tcCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBIZWFkZXJHcm91cENlbGxDb21wKGN0cmwpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIEhlYWRlckdyb3VwQ2VsbENvbXAuVEVNUExBVEUsIGN0cmwpIHx8IHRoaXM7XG4gICAgfVxuICAgIEhlYWRlckdyb3VwQ2VsbENvbXAucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgdmFyIHNldEF0dHJpYnV0ZSA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgIT0gdW5kZWZpbmVkID8gZUd1aS5zZXRBdHRyaWJ1dGUoa2V5LCB2YWx1ZSkgOiBlR3VpLnJlbW92ZUF0dHJpYnV0ZShrZXkpO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgY29tcFByb3h5ID0ge1xuICAgICAgICAgICAgYWRkT3JSZW1vdmVDc3NDbGFzczogZnVuY3Rpb24gKGNzc0NsYXNzTmFtZSwgb24pIHsgcmV0dXJuIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoY3NzQ2xhc3NOYW1lLCBvbik7IH0sXG4gICAgICAgICAgICBhZGRPclJlbW92ZVJlc2l6YWJsZUNzc0NsYXNzOiBmdW5jdGlvbiAoY3NzQ2xhc3NOYW1lLCBvbikgeyByZXR1cm4gX3RoaXMuZVJlc2l6ZS5jbGFzc0xpc3QudG9nZ2xlKGNzc0NsYXNzTmFtZSwgb24pOyB9LFxuICAgICAgICAgICAgc2V0V2lkdGg6IGZ1bmN0aW9uICh3aWR0aCkgeyByZXR1cm4gZUd1aS5zdHlsZS53aWR0aCA9IHdpZHRoOyB9LFxuICAgICAgICAgICAgc2V0Q29sSWQ6IGZ1bmN0aW9uIChpZCkgeyByZXR1cm4gZUd1aS5zZXRBdHRyaWJ1dGUoXCJjb2wtaWRcIiwgaWQpOyB9LFxuICAgICAgICAgICAgc2V0QXJpYUV4cGFuZGVkOiBmdW5jdGlvbiAoZXhwYW5kZWQpIHsgcmV0dXJuIHNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsIGV4cGFuZGVkKTsgfSxcbiAgICAgICAgICAgIHNldFRpdGxlOiBmdW5jdGlvbiAodGl0bGUpIHsgcmV0dXJuIHNldEF0dHJpYnV0ZShcInRpdGxlXCIsIHRpdGxlKTsgfSxcbiAgICAgICAgICAgIHNldFVzZXJDb21wRGV0YWlsczogZnVuY3Rpb24gKGRldGFpbHMpIHsgcmV0dXJuIF90aGlzLnNldFVzZXJDb21wRGV0YWlscyhkZXRhaWxzKTsgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmN0cmwuc2V0Q29tcChjb21wUHJveHksIGVHdWksIHRoaXMuZVJlc2l6ZSk7XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENlbGxDb21wLnByb3RvdHlwZS5zZXRVc2VyQ29tcERldGFpbHMgPSBmdW5jdGlvbiAoZGV0YWlscykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBkZXRhaWxzLm5ld0FnU3RhY2tJbnN0YW5jZSgpLnRoZW4oZnVuY3Rpb24gKGNvbXApIHsgcmV0dXJuIF90aGlzLmFmdGVySGVhZGVyQ29tcENyZWF0ZWQoY29tcCk7IH0pO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDZWxsQ29tcC5wcm90b3R5cGUuYWZ0ZXJIZWFkZXJDb21wQ3JlYXRlZCA9IGZ1bmN0aW9uIChoZWFkZXJHcm91cENvbXApIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGRlc3Ryb3lGdW5jID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZGVzdHJveUJlYW4oaGVhZGVyR3JvdXBDb21wKTsgfTtcbiAgICAgICAgaWYgKCF0aGlzLmlzQWxpdmUoKSkge1xuICAgICAgICAgICAgZGVzdHJveUZ1bmMoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKGhlYWRlckdyb3VwQ29tcC5nZXRHdWkoKSk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZGVzdHJveUZ1bmMpO1xuICAgICAgICB0aGlzLmN0cmwuc2V0RHJhZ1NvdXJjZShoZWFkZXJHcm91cENvbXAuZ2V0R3VpKCkpO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDZWxsQ29tcC5URU1QTEFURSA9IFwiPGRpdiBjbGFzcz1cXFwiYWctaGVhZGVyLWdyb3VwLWNlbGxcXFwiIHJvbGU9XFxcImNvbHVtbmhlYWRlclxcXCIgdGFiaW5kZXg9XFxcIi0xXFxcIj5cXG4gICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZVJlc2l6ZVxcXCIgY2xhc3M9XFxcImFnLWhlYWRlci1jZWxsLXJlc2l6ZVxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj48L2Rpdj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkMXUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3VzZXJDb21wb25lbnRGYWN0b3J5JylcbiAgICBdLCBIZWFkZXJHcm91cENlbGxDb21wLnByb3RvdHlwZSwgXCJ1c2VyQ29tcG9uZW50RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVJlc2l6ZScpXG4gICAgXSwgSGVhZGVyR3JvdXBDZWxsQ29tcC5wcm90b3R5cGUsIFwiZVJlc2l6ZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXUoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgSGVhZGVyR3JvdXBDZWxsQ29tcC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gSGVhZGVyR3JvdXBDZWxsQ29tcDtcbn0oQWJzdHJhY3RIZWFkZXJDZWxsQ29tcCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFBID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxdCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEhlYWRlclJvd1R5cGU7XG4oZnVuY3Rpb24gKEhlYWRlclJvd1R5cGUpIHtcbiAgICBIZWFkZXJSb3dUeXBlW1wiQ09MVU1OX0dST1VQXCJdID0gXCJncm91cFwiO1xuICAgIEhlYWRlclJvd1R5cGVbXCJDT0xVTU5cIl0gPSBcImNvbHVtblwiO1xuICAgIEhlYWRlclJvd1R5cGVbXCJGTE9BVElOR19GSUxURVJcIl0gPSBcImZpbHRlclwiO1xufSkoSGVhZGVyUm93VHlwZSB8fCAoSGVhZGVyUm93VHlwZSA9IHt9KSk7XG52YXIgSGVhZGVyUm93Q29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMUEoSGVhZGVyUm93Q29tcCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBIZWFkZXJSb3dDb21wKGN0cmwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuaGVhZGVyQ29tcHMgPSB7fTtcbiAgICAgICAgdmFyIGV4dHJhQ2xhc3MgPSBjdHJsLmdldFR5cGUoKSA9PSBIZWFkZXJSb3dUeXBlLkNPTFVNTl9HUk9VUCA/IFwiYWctaGVhZGVyLXJvdy1jb2x1bW4tZ3JvdXBcIiA6XG4gICAgICAgICAgICBjdHJsLmdldFR5cGUoKSA9PSBIZWFkZXJSb3dUeXBlLkZMT0FUSU5HX0ZJTFRFUiA/IFwiYWctaGVhZGVyLXJvdy1jb2x1bW4tZmlsdGVyXCIgOiBcImFnLWhlYWRlci1yb3ctY29sdW1uXCI7XG4gICAgICAgIF90aGlzLnNldFRlbXBsYXRlKC8qIGh0bWwgKi8gXCI8ZGl2IGNsYXNzPVxcXCJhZy1oZWFkZXItcm93IFwiICsgZXh0cmFDbGFzcyArIFwiXFxcIiByb2xlPVxcXCJyb3dcXFwiPjwvZGl2PlwiKTtcbiAgICAgICAgX3RoaXMuY3RybCA9IGN0cmw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgLy9ub2luc3BlY3Rpb24gSlNVbnVzZWRMb2NhbFN5bWJvbHNcbiAgICBIZWFkZXJSb3dDb21wLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29tcFByb3h5ID0ge1xuICAgICAgICAgICAgc2V0VHJhbnNmb3JtOiBmdW5jdGlvbiAodHJhbnNmb3JtKSB7IHJldHVybiBfdGhpcy5nZXRHdWkoKS5zdHlsZS50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07IH0sXG4gICAgICAgICAgICBzZXRIZWlnaHQ6IGZ1bmN0aW9uIChoZWlnaHQpIHsgcmV0dXJuIF90aGlzLmdldEd1aSgpLnN0eWxlLmhlaWdodCA9IGhlaWdodDsgfSxcbiAgICAgICAgICAgIHNldFRvcDogZnVuY3Rpb24gKHRvcCkgeyByZXR1cm4gX3RoaXMuZ2V0R3VpKCkuc3R5bGUudG9wID0gdG9wOyB9LFxuICAgICAgICAgICAgc2V0SGVhZGVyQ3RybHM6IGZ1bmN0aW9uIChjdHJscykgeyByZXR1cm4gX3RoaXMuc2V0SGVhZGVyQ3RybHMoY3RybHMpOyB9LFxuICAgICAgICAgICAgc2V0V2lkdGg6IGZ1bmN0aW9uICh3aWR0aCkgeyByZXR1cm4gX3RoaXMuZ2V0R3VpKCkuc3R5bGUud2lkdGggPSB3aWR0aDsgfSxcbiAgICAgICAgICAgIHNldEFyaWFSb3dJbmRleDogZnVuY3Rpb24gKHJvd0luZGV4KSB7IHJldHVybiBzZXRBcmlhUm93SW5kZXgoX3RoaXMuZ2V0R3VpKCksIHJvd0luZGV4KTsgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmN0cmwuc2V0Q29tcChjb21wUHJveHkpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29tcC5wcm90b3R5cGUuZGVzdHJveUhlYWRlckN0cmxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldEhlYWRlckN0cmxzKFtdKTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0NvbXAucHJvdG90eXBlLnNldEhlYWRlckN0cmxzID0gZnVuY3Rpb24gKGN0cmxzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb2xkQ29tcHMgPSB0aGlzLmhlYWRlckNvbXBzO1xuICAgICAgICB0aGlzLmhlYWRlckNvbXBzID0ge307XG4gICAgICAgIGN0cmxzLmZvckVhY2goZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgICAgIHZhciBpZCA9IGN0cmwuZ2V0SW5zdGFuY2VJZCgpO1xuICAgICAgICAgICAgdmFyIGNvbXAgPSBvbGRDb21wc1tpZF07XG4gICAgICAgICAgICBkZWxldGUgb2xkQ29tcHNbaWRdO1xuICAgICAgICAgICAgaWYgKGNvbXAgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbXAgPSBfdGhpcy5jcmVhdGVIZWFkZXJDb21wKGN0cmwpO1xuICAgICAgICAgICAgICAgIF90aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKGNvbXAuZ2V0R3VpKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuaGVhZGVyQ29tcHNbaWRdID0gY29tcDtcbiAgICAgICAgfSk7XG4gICAgICAgIGl0ZXJhdGVPYmplY3Qob2xkQ29tcHMsIGZ1bmN0aW9uIChpZCwgY29tcCkge1xuICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkucmVtb3ZlQ2hpbGQoY29tcC5nZXRHdWkoKSk7XG4gICAgICAgICAgICBfdGhpcy5kZXN0cm95QmVhbihjb21wKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBlbnN1cmVEb21PcmRlciA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5zdXJlRG9tT3JkZXIoKTtcbiAgICAgICAgaWYgKGVuc3VyZURvbU9yZGVyKSB7XG4gICAgICAgICAgICB2YXIgY29tcHMgPSBnZXRBbGxWYWx1ZXNJbk9iamVjdCh0aGlzLmhlYWRlckNvbXBzKTtcbiAgICAgICAgICAgIC8vIG9yZGVyaW5nIHRoZSBjb2x1bW5zIGJ5IGxlZnQgcG9zaXRpb24gb3JkZXJzIHRoZW0gaW4gdGhlIG9yZGVyIHRoZXkgYXBwZWFyIG9uIHRoZSBzY3JlZW5cbiAgICAgICAgICAgIGNvbXBzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGVmdEEgPSBhLmdldEN0cmwoKS5nZXRDb2x1bW5Hcm91cENoaWxkKCkuZ2V0TGVmdCgpO1xuICAgICAgICAgICAgICAgIHZhciBsZWZ0QiA9IGIuZ2V0Q3RybCgpLmdldENvbHVtbkdyb3VwQ2hpbGQoKS5nZXRMZWZ0KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRBIC0gbGVmdEI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBlbGVtZW50c0luT3JkZXIgPSBjb21wcy5tYXAoZnVuY3Rpb24gKGMpIHsgcmV0dXJuIGMuZ2V0R3VpKCk7IH0pO1xuICAgICAgICAgICAgc2V0RG9tQ2hpbGRPcmRlcih0aGlzLmdldEd1aSgpLCBlbGVtZW50c0luT3JkZXIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb21wLnByb3RvdHlwZS5jcmVhdGVIZWFkZXJDb21wID0gZnVuY3Rpb24gKGhlYWRlckN0cmwpIHtcbiAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgc3dpdGNoICh0aGlzLmN0cmwuZ2V0VHlwZSgpKSB7XG4gICAgICAgICAgICBjYXNlIEhlYWRlclJvd1R5cGUuQ09MVU1OX0dST1VQOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBIZWFkZXJHcm91cENlbGxDb21wKGhlYWRlckN0cmwpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIZWFkZXJSb3dUeXBlLkZMT0FUSU5HX0ZJTFRFUjpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgSGVhZGVyRmlsdGVyQ2VsbENvbXAoaGVhZGVyQ3RybCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBIZWFkZXJDZWxsQ29tcChoZWFkZXJDdHJsKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNyZWF0ZUJlYW4ocmVzdWx0KTtcbiAgICAgICAgcmVzdWx0LnNldFBhcmVudENvbXBvbmVudCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMXQoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgSGVhZGVyUm93Q29tcC5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJDF0KFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIEhlYWRlclJvd0NvbXAucHJvdG90eXBlLCBcImRlc3Ryb3lIZWFkZXJDdHJsc1wiLCBudWxsKTtcbiAgICByZXR1cm4gSGVhZGVyUm93Q29tcDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMXogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFzID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgaW5zdGFuY2VJZFNlcXVlbmNlJDEgPSAwO1xudmFyIEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDF6KEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWJzdHJhY3RIZWFkZXJDZWxsQ3RybChjb2x1bW5Hcm91cENoaWxkLCBwYXJlbnRSb3dDdHJsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmxhc3RGb2N1c0V2ZW50ID0gbnVsbDtcbiAgICAgICAgX3RoaXMuY29sdW1uR3JvdXBDaGlsZCA9IGNvbHVtbkdyb3VwQ2hpbGQ7XG4gICAgICAgIF90aGlzLnBhcmVudFJvd0N0cmwgPSBwYXJlbnRSb3dDdHJsO1xuICAgICAgICAvLyB1bmlxdWUgaWQgdG8gdGhpcyBpbnN0YW5jZSwgaW5jbHVkaW5nIHRoZSBjb2x1bW4gSUQgdG8gaGVscCB3aXRoIGRlYnVnZ2luZyBpbiBSZWFjdCBhcyBpdCdzIHVzZWQgaW4gJ2tleSdcbiAgICAgICAgX3RoaXMuaW5zdGFuY2VJZCA9IGNvbHVtbkdyb3VwQ2hpbGQuZ2V0VW5pcXVlSWQoKSArICctJyArIGluc3RhbmNlSWRTZXF1ZW5jZSQxKys7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWJzdHJhY3RIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2hvdWxkU3RvcEV2ZW50UHJvcGFnYXRpb24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmZvY3VzU2VydmljZS5nZXRGb2N1c2VkSGVhZGVyKCksIGhlYWRlclJvd0luZGV4ID0gX2EuaGVhZGVyUm93SW5kZXgsIGNvbHVtbiA9IF9hLmNvbHVtbjtcbiAgICAgICAgcmV0dXJuIGlzVXNlclN1cHByZXNzaW5nSGVhZGVyS2V5Ym9hcmRFdmVudCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgZSwgaGVhZGVyUm93SW5kZXgsIGNvbHVtbik7XG4gICAgfTtcbiAgICBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5nZXRXcmFwcGVySGFzRm9jdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgYWN0aXZlRWwgPSBlRG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIGFjdGl2ZUVsID09PSB0aGlzLmVHdWk7XG4gICAgfTtcbiAgICBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5zZXRHdWkgPSBmdW5jdGlvbiAoZUd1aSkge1xuICAgICAgICB0aGlzLmVHdWkgPSBlR3VpO1xuICAgICAgICB0aGlzLmFkZERvbURhdGEoKTtcbiAgICB9O1xuICAgIEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgd3JhcHBlckhhc0ZvY3VzID0gdGhpcy5nZXRXcmFwcGVySGFzRm9jdXMoKTtcbiAgICAgICAgc3dpdGNoIChlLmtleSkge1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlBBR0VfRE9XTjpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5QQUdFX1VQOlxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlBBR0VfSE9NRTpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5QQUdFX0VORDpcbiAgICAgICAgICAgICAgICBpZiAod3JhcHBlckhhc0ZvY3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmFkZERvbURhdGEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBrZXkgPSBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLkRPTV9EQVRBX0tFWV9IRUFERVJfQ1RSTDtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0RG9tRGF0YSh0aGlzLmVHdWksIGtleSwgdGhpcyk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldERvbURhdGEoX3RoaXMuZUd1aSwga2V5LCBudWxsKTsgfSk7XG4gICAgfTtcbiAgICBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5nZXRHdWkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVHdWk7XG4gICAgfTtcbiAgICBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5mb2N1cyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoIXRoaXMuZUd1aSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFzdEZvY3VzRXZlbnQgPSBldmVudCB8fCBudWxsO1xuICAgICAgICB0aGlzLmVHdWkuZm9jdXMoKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5nZXRSb3dJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50Um93Q3RybC5nZXRSb3dJbmRleCgpO1xuICAgIH07XG4gICAgQWJzdHJhY3RIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuZ2V0UGFyZW50Um93Q3RybCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50Um93Q3RybDtcbiAgICB9O1xuICAgIEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmdldFBpbm5lZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50Um93Q3RybC5nZXRQaW5uZWQoKTtcbiAgICB9O1xuICAgIEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmdldEluc3RhbmNlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmluc3RhbmNlSWQ7XG4gICAgfTtcbiAgICBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5nZXRDb2x1bW5Hcm91cENoaWxkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Hcm91cENoaWxkO1xuICAgIH07XG4gICAgQWJzdHJhY3RIZWFkZXJDZWxsQ3RybC5ET01fREFUQV9LRVlfSEVBREVSX0NUUkwgPSAnaGVhZGVyQ3RybCc7XG4gICAgX19kZWNvcmF0ZSQxcyhbXG4gICAgICAgIEF1dG93aXJlZCgnZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBBYnN0cmFjdEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFzKFtcbiAgICAgICAgQXV0b3dpcmVkKCdiZWFucycpXG4gICAgXSwgQWJzdHJhY3RIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwiYmVhbnNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFzKFtcbiAgICAgICAgQXV0b3dpcmVkKCd1c2VyQ29tcG9uZW50RmFjdG9yeScpXG4gICAgXSwgQWJzdHJhY3RIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwidXNlckNvbXBvbmVudEZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gQWJzdHJhY3RIZWFkZXJDZWxsQ3RybDtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzO1xuKGZ1bmN0aW9uIChDbGllbnRTaWRlUm93TW9kZWxTdGVwcykge1xuICAgIENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzW1wiRVZFUllUSElOR1wiXSA9IFwiZ3JvdXBcIjtcbiAgICBDbGllbnRTaWRlUm93TW9kZWxTdGVwc1tcIkZJTFRFUlwiXSA9IFwiZmlsdGVyXCI7XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsU3RlcHNbXCJTT1JUXCJdID0gXCJzb3J0XCI7XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsU3RlcHNbXCJNQVBcIl0gPSBcIm1hcFwiO1xuICAgIENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzW1wiQUdHUkVHQVRFXCJdID0gXCJhZ2dyZWdhdGVcIjtcbiAgICBDbGllbnRTaWRlUm93TW9kZWxTdGVwc1tcIkZJTFRFUl9BR0dSRUdBVEVTXCJdID0gXCJmaWx0ZXJfYWdncmVnYXRlc1wiO1xuICAgIENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzW1wiUElWT1RcIl0gPSBcInBpdm90XCI7XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsU3RlcHNbXCJOT1RISU5HXCJdID0gXCJub3RoaW5nXCI7XG59KShDbGllbnRTaWRlUm93TW9kZWxTdGVwcyB8fCAoQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMgPSB7fSkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19kZWNvcmF0ZSQxciA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xuZnVuY3Rpb24gdW53cmFwVXNlckNvbXAoY29tcCkge1xuICAgIHZhciBjb21wQXNBbnkgPSBjb21wO1xuICAgIHZhciBpc1Byb3h5ID0gY29tcEFzQW55ICE9IG51bGwgJiYgY29tcEFzQW55LmdldEZyYW1ld29ya0NvbXBvbmVudEluc3RhbmNlICE9IG51bGw7XG4gICAgcmV0dXJuIGlzUHJveHkgPyBjb21wQXNBbnkuZ2V0RnJhbWV3b3JrQ29tcG9uZW50SW5zdGFuY2UoKSA6IGNvbXA7XG59XG52YXIgR3JpZEFwaSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBHcmlkQXBpKCkge1xuICAgICAgICB0aGlzLmRldGFpbEdyaWRJbmZvTWFwID0ge307XG4gICAgICAgIHRoaXMuZGVzdHJveUNhbGxlZCA9IGZhbHNlO1xuICAgIH1cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZWdpc3Rlck92ZXJsYXlXcmFwcGVyQ29tcCA9IGZ1bmN0aW9uIChvdmVybGF5V3JhcHBlckNvbXApIHtcbiAgICAgICAgdGhpcy5vdmVybGF5V3JhcHBlckNvbXAgPSBvdmVybGF5V3JhcHBlckNvbXA7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZWdpc3RlclNpZGVCYXJDb21wID0gZnVuY3Rpb24gKHNpZGVCYXJDb21wKSB7XG4gICAgICAgIHRoaXMuc2lkZUJhckNvbXAgPSBzaWRlQmFyQ29tcDtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHN3aXRjaCAodGhpcy5yb3dNb2RlbC5nZXRUeXBlKCkpIHtcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0NMSUVOVF9TSURFOlxuICAgICAgICAgICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsID0gdGhpcy5yb3dNb2RlbDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0lORklOSVRFOlxuICAgICAgICAgICAgICAgIHRoaXMuaW5maW5pdGVSb3dNb2RlbCA9IHRoaXMucm93TW9kZWw7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9TRVJWRVJfU0lERTpcbiAgICAgICAgICAgICAgICB0aGlzLnNlcnZlclNpZGVSb3dNb2RlbCA9IHRoaXMucm93TW9kZWw7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmdyaWRCb2R5Q3RybCA9IF90aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvKiogVXNlZCBpbnRlcm5hbGx5IGJ5IGdyaWQuIE5vdCBpbnRlbmRlZCB0byBiZSB1c2VkIGJ5IHRoZSBjbGllbnQuIEludGVyZmFjZSBtYXkgY2hhbmdlIGJldHdlZW4gcmVsZWFzZXMuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuX19nZXRBbGlnbmVkR3JpZFNlcnZpY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFsaWduZWRHcmlkc1NlcnZpY2U7XG4gICAgfTtcbiAgICAvKiogVXNlZCBpbnRlcm5hbGx5IGJ5IGdyaWQuIE5vdCBpbnRlbmRlZCB0byBiZSB1c2VkIGJ5IHRoZSBjbGllbnQuIEludGVyZmFjZSBtYXkgY2hhbmdlIGJldHdlZW4gcmVsZWFzZXMuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuX19nZXRDb250ZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250ZXh0O1xuICAgIH07XG4gICAgLyoqIFJlZ2lzdGVyIGEgZGV0YWlsIGdyaWQgd2l0aCB0aGUgbWFzdGVyIGdyaWQgd2hlbiBpdCBpcyBjcmVhdGVkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmFkZERldGFpbEdyaWRJbmZvID0gZnVuY3Rpb24gKGlkLCBncmlkSW5mbykge1xuICAgICAgICB0aGlzLmRldGFpbEdyaWRJbmZvTWFwW2lkXSA9IGdyaWRJbmZvO1xuICAgIH07XG4gICAgLyoqIFVucmVnaXN0ZXIgYSBkZXRhaWwgZ3JpZCBmcm9tIHRoZSBtYXN0ZXIgZ3JpZCB3aGVuIGl0IGlzIGRlc3Ryb3llZC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZW1vdmVEZXRhaWxHcmlkSW5mbyA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICB0aGlzLmRldGFpbEdyaWRJbmZvTWFwW2lkXSA9IHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBgRGV0YWlsR3JpZEluZm9gIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHN1cHBsaWVkIGBkZXRhaWxHcmlkSWRgLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldERldGFpbEdyaWRJbmZvID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRldGFpbEdyaWRJbmZvTWFwW2lkXTtcbiAgICB9O1xuICAgIC8qKiBJdGVyYXRlcyB0aHJvdWdoIGVhY2ggYERldGFpbEdyaWRJbmZvYCBpbiB0aGUgZ3JpZCBhbmQgY2FsbHMgdGhlIHN1cHBsaWVkIGNhbGxiYWNrIG9uIGVhY2guICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZm9yRWFjaERldGFpbEdyaWRJbmZvID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBpbmRleCA9IDA7XG4gICAgICAgIGl0ZXJhdGVPYmplY3QodGhpcy5kZXRhaWxHcmlkSW5mb01hcCwgZnVuY3Rpb24gKGlkLCBncmlkSW5mbykge1xuICAgICAgICAgICAgLy8gY2hlY2sgZm9yIHVuZGVmaW5lZCwgYXMgb2xkIHJlZmVyZW5jZXMgd2lsbCBzdGlsbCBiZSBseWluZyBhcm91bmRcbiAgICAgICAgICAgIGlmIChleGlzdHMoZ3JpZEluZm8pKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZ3JpZEluZm8sIGluZGV4KTtcbiAgICAgICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8qKiBTaW1pbGFyIHRvIGBleHBvcnREYXRhQXNDc3ZgLCBleGNlcHQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGEgc3RyaW5nIHJhdGhlciB0aGFuIGRvd25sb2FkIGl0LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldERhdGFBc0NzdiA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuQ3N2RXhwb3J0TW9kdWxlLCAnYXBpLmdldERhdGFBc0NzdicpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jc3ZDcmVhdG9yLmdldERhdGFBc0NzdihwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogRG93bmxvYWRzIGEgQ1NWIGV4cG9ydCBvZiB0aGUgZ3JpZCdzIGRhdGEuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZXhwb3J0RGF0YUFzQ3N2ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5Dc3ZFeHBvcnRNb2R1bGUsICdhcGkuZXhwb3J0RGF0YUFzQ1N2JykpIHtcbiAgICAgICAgICAgIHRoaXMuY3N2Q3JlYXRvci5leHBvcnREYXRhQXNDc3YocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0RXhjZWxFeHBvcnRNb2RlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgYmFzZVBhcmFtcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERlZmF1bHRFeHBvcnRQYXJhbXMoJ2V4Y2VsJyk7XG4gICAgICAgIHZhciBtZXJnZWRQYXJhbXMgPSBPYmplY3QuYXNzaWduKHsgZXhwb3J0TW9kZTogJ3hsc3gnIH0sIGJhc2VQYXJhbXMsIHBhcmFtcyk7XG4gICAgICAgIHJldHVybiBtZXJnZWRQYXJhbXMuZXhwb3J0TW9kZTtcbiAgICB9O1xuICAgIC8qKiBTaW1pbGFyIHRvIGBleHBvcnREYXRhQXNFeGNlbGAsIGV4Y2VwdCBpbnN0ZWFkIG9mIGRvd25sb2FkaW5nIGEgZmlsZSwgaXQgd2lsbCByZXR1cm4gYSBbQmxvYl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0Jsb2IpIHRvIGJlIHByb2Nlc3NlZCBieSB0aGUgdXNlci4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXREYXRhQXNFeGNlbCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCFNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkV4Y2VsRXhwb3J0TW9kdWxlLCAnYXBpLmdldERhdGFBc0V4Y2VsJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwb3J0TW9kZSA9IHRoaXMuZ2V0RXhjZWxFeHBvcnRNb2RlKHBhcmFtcyk7XG4gICAgICAgIGlmICh0aGlzLmV4Y2VsQ3JlYXRvci5nZXRGYWN0b3J5TW9kZShleHBvcnRNb2RlKSA9PT0gRXhjZWxGYWN0b3J5TW9kZS5NVUxUSV9TSEVFVCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBUaGUgRXhjZWwgRXhwb3J0ZXIgaXMgY3VycmVudGx5IG9uIE11bHRpIFNoZWV0IG1vZGUuIEVuZCB0aGF0IG9wZXJhdGlvbiBieSBjYWxsaW5nIGBhcGkuZ2V0TXVsdGlwbGVTaGVldEFzRXhjZWwoKWAgb3IgYGFwaS5leHBvcnRNdWx0aXBsZVNoZWV0c0FzRXhjZWwoKWAnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5leGNlbENyZWF0b3IuZ2V0RGF0YUFzRXhjZWwocGFyYW1zKTtcbiAgICB9O1xuICAgIC8qKiBEb3dubG9hZHMgYW4gRXhjZWwgZXhwb3J0IG9mIHRoZSBncmlkJ3MgZGF0YS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5leHBvcnREYXRhQXNFeGNlbCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCFNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkV4Y2VsRXhwb3J0TW9kdWxlLCAnYXBpLmV4cG9ydERhdGFBc0V4Y2VsJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwb3J0TW9kZSA9IHRoaXMuZ2V0RXhjZWxFeHBvcnRNb2RlKHBhcmFtcyk7XG4gICAgICAgIGlmICh0aGlzLmV4Y2VsQ3JlYXRvci5nZXRGYWN0b3J5TW9kZShleHBvcnRNb2RlKSA9PT0gRXhjZWxGYWN0b3J5TW9kZS5NVUxUSV9TSEVFVCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBUaGUgRXhjZWwgRXhwb3J0ZXIgaXMgY3VycmVudGx5IG9uIE11bHRpIFNoZWV0IG1vZGUuIEVuZCB0aGF0IG9wZXJhdGlvbiBieSBjYWxsaW5nIGBhcGkuZ2V0TXVsdGlwbGVTaGVldEFzRXhjZWwoKWAgb3IgYGFwaS5leHBvcnRNdWx0aXBsZVNoZWV0c0FzRXhjZWwoKWAnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmV4Y2VsQ3JlYXRvci5leHBvcnREYXRhQXNFeGNlbChwYXJhbXMpO1xuICAgIH07XG4gICAgLyoqIFRoaXMgaXMgbWV0aG9kIHRvIGJlIHVzZWQgdG8gZ2V0IHRoZSBncmlkJ3MgZGF0YSBhcyBhIHNoZWV0LCB0aGF0IHdpbGwgbGF0ZXIgYmUgZXhwb3J0ZWQgZWl0aGVyIGJ5IGBnZXRNdWx0aXBsZVNoZWV0c0FzRXhjZWwoKWAgb3IgYGV4cG9ydE11bHRpcGxlU2hlZXRzQXNFeGNlbCgpYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRTaGVldERhdGFGb3JFeGNlbCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCFNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkV4Y2VsRXhwb3J0TW9kdWxlLCAnYXBpLmdldFNoZWV0RGF0YUZvckV4Y2VsJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwb3J0TW9kZSA9IHRoaXMuZ2V0RXhjZWxFeHBvcnRNb2RlKHBhcmFtcyk7XG4gICAgICAgIHRoaXMuZXhjZWxDcmVhdG9yLnNldEZhY3RvcnlNb2RlKEV4Y2VsRmFjdG9yeU1vZGUuTVVMVElfU0hFRVQsIGV4cG9ydE1vZGUpO1xuICAgICAgICByZXR1cm4gdGhpcy5leGNlbENyZWF0b3IuZ2V0U2hlZXREYXRhRm9yRXhjZWwocGFyYW1zKTtcbiAgICB9O1xuICAgIC8qKiBTaW1pbGFyIHRvIGBleHBvcnRNdWx0aXBsZVNoZWV0c0FzRXhjZWxgLCBleGNlcHQgaW5zdGVhZCBvZiBkb3dubG9hZGluZyBhIGZpbGUsIGl0IHdpbGwgcmV0dXJuIGEgW0Jsb2JdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9CbG9iKSB0byBiZSBwcm9jZXNzZWQgYnkgdGhlIHVzZXIuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0TXVsdGlwbGVTaGVldHNBc0V4Y2VsID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5FeGNlbEV4cG9ydE1vZHVsZSwgJ2FwaS5nZXRNdWx0aXBsZVNoZWV0c0FzRXhjZWwnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhjZWxDcmVhdG9yLmdldE11bHRpcGxlU2hlZXRzQXNFeGNlbChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogRG93bmxvYWRzIGFuIEV4Y2VsIGV4cG9ydCBvZiBtdWx0aXBsZSBzaGVldHMgaW4gb25lIGZpbGUuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZXhwb3J0TXVsdGlwbGVTaGVldHNBc0V4Y2VsID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5FeGNlbEV4cG9ydE1vZHVsZSwgJ2FwaS5leHBvcnRNdWx0aXBsZVNoZWV0c0FzRXhjZWwnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhjZWxDcmVhdG9yLmV4cG9ydE11bHRpcGxlU2hlZXRzQXNFeGNlbChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogc2luY2UgdmVyc2lvbiAxOC54LCBhcGkuc2V0RW50ZXJwcmlzZURhdGFzb3VyY2UoKSBzaG91bGQgYmUgcmVwbGFjZWQgd2l0aCBhcGkuc2V0U2VydmVyU2lkZURhdGFzb3VyY2UoKSAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEVudGVycHJpc2VEYXRhc291cmNlID0gZnVuY3Rpb24gKGRhdGFzb3VyY2UpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2luY2UgdmVyc2lvbiAxOC54LCBhcGkuc2V0RW50ZXJwcmlzZURhdGFzb3VyY2UoKSBzaG91bGQgYmUgcmVwbGFjZWQgd2l0aCBhcGkuc2V0U2VydmVyU2lkZURhdGFzb3VyY2UoKVwiKTtcbiAgICAgICAgdGhpcy5zZXRTZXJ2ZXJTaWRlRGF0YXNvdXJjZShkYXRhc291cmNlKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFNldHMgYW4gQVJJQSBwcm9wZXJ0eSBpbiB0aGUgZ3JpZCBwYW5lbCAoZWxlbWVudCB3aXRoIGByb2xlPVxcXCJncmlkXFxcImApLCBhbmQgcmVtb3ZlcyBhbiBBUklBIHByb3BlcnR5IHdoZW4gdGhlIHZhbHVlIGlzIG51bGwuXG4gICAgICpcbiAgICAgKiBFeGFtcGxlOiBgYXBpLnNldEdyaWRBcmlhUHJvcGVydHkoJ2xhYmVsJywgJ215IGdyaWQnKWAgd2lsbCBzZXQgYGFyaWEtbGFiZWw9XFxcIm15IGdyaWRcXFwiYC5cbiAgICAgKlxuICAgICAqIGBhcGkuc2V0R3JpZEFyaWFQcm9wZXJ0eSgnbGFiZWwnLCBudWxsKWAgd2lsbCByZW1vdmUgdGhlIGBhcmlhLWxhYmVsYCBhdHRyaWJ1dGUgZnJvbSB0aGUgZ3JpZCBlbGVtZW50LlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEdyaWRBcmlhUHJvcGVydHkgPSBmdW5jdGlvbiAocHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgIGlmICghcHJvcGVydHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZUdyaWQgPSB0aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKS5nZXRHdWkoKTtcbiAgICAgICAgdmFyIGFyaWFQcm9wZXJ0eSA9IFwiYXJpYS1cIiArIHByb3BlcnR5O1xuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGVHcmlkLnJlbW92ZUF0dHJpYnV0ZShhcmlhUHJvcGVydHkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZUdyaWQuc2V0QXR0cmlidXRlKGFyaWFQcm9wZXJ0eSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogU2V0IG5ldyBkYXRhc291cmNlIGZvciBTZXJ2ZXItU2lkZSBSb3cgTW9kZWwuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0U2VydmVyU2lkZURhdGFzb3VyY2UgPSBmdW5jdGlvbiAoZGF0YXNvdXJjZSkge1xuICAgICAgICBpZiAodGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIC8vIHNob3VsZCByZWFsbHkgaGF2ZSBhbiBJRW50ZXJwcmlzZVJvd01vZGVsIGludGVyZmFjZSwgc28gd2UgYXJlIG5vdCBjYXN0aW5nIHRvIGFueVxuICAgICAgICAgICAgdGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwuc2V0RGF0YXNvdXJjZShkYXRhc291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHlvdSBjYW4gb25seSB1c2UgYW4gZW50ZXJwcmlzZSBkYXRhc291cmNlIHdoZW4gZ3JpZE9wdGlvbnMucm93TW9kZWxUeXBlIGlzICdcIiArIENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9TRVJWRVJfU0lERSArIFwiJ1wiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgYGNhY2hlQmxvY2tTaXplYCB1c2VkIGJ5IGBzZXJ2ZXJTaWRlSW5maW5pdGVTY3JvbGxgIHdoZW4gcmVxdWVzdGluZyBkYXRhIGZyb20gdGhlIHNlcnZlci5cbiAgICAgKlxuICAgICAqIE5vdGUgdGhpcyBwdXJnZXMgYWxsIHRoZSBjYWNoZWQgZGF0YSBhbmQgcmVsb2FkcyBhbGwgdGhlIHJvd3Mgb2YgdGhlIGdyaWQuXG4gICAgICogKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRDYWNoZUJsb2NrU2l6ZSA9IGZ1bmN0aW9uIChibG9ja1NpemUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNlcnZlclNpZGVSb3dNb2RlbCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogeW91IGNhbiBvbmx5IHNldCBjYWNoZUJsb2NrU2l6ZSB3aXRoIGdyaWRPcHRpb25zLnJvd01vZGVsVHlwZSAnXCIgKyBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfU0VSVkVSX1NJREUgKyBcIidcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoJ2NhY2hlQmxvY2tTaXplJywgYmxvY2tTaXplKTtcbiAgICAgICAgdGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwucmVzZXRSb290U3RvcmUoKTtcbiAgICB9O1xuICAgIC8qKiBTZXQgbmV3IGRhdGFzb3VyY2UgZm9yIEluZmluaXRlIFJvdyBNb2RlbC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXREYXRhc291cmNlID0gZnVuY3Rpb24gKGRhdGFzb3VyY2UpIHtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxJbmZpbml0ZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnJvd01vZGVsLnNldERhdGFzb3VyY2UoZGF0YXNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiB5b3UgY2FuIG9ubHkgdXNlIGEgZGF0YXNvdXJjZSB3aGVuIGdyaWRPcHRpb25zLnJvd01vZGVsVHlwZSBpcyAnXCIgKyBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfSU5GSU5JVEUgKyBcIidcIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBTZXQgbmV3IGRhdGFzb3VyY2UgZm9yIFZpZXdwb3J0IFJvdyBNb2RlbC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRWaWV3cG9ydERhdGFzb3VyY2UgPSBmdW5jdGlvbiAodmlld3BvcnREYXRhc291cmNlKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1Jvd01vZGVsVmlld3BvcnQoKSkge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyBiYWQgY29kaW5nLCBiZWNhdXNlIGl0J3MgdXNpbmcgYW4gaW50ZXJmYWNlIHRoYXQncyBleHBvc2VkIGluIHRoZSBlbnRlcnByaXNlLlxuICAgICAgICAgICAgLy8gcmVhbGx5IHdlIHNob3VsZCBjcmVhdGUgYW4gaW50ZXJmYWNlIGluIHRoZSBjb3JlIGZvciB2aWV3cG9ydERhdGFzb3VyY2UgYW5kIGxldFxuICAgICAgICAgICAgLy8gdGhlIGVudGVycHJpc2UgaW1wbGVtZW50IGl0LCByYXRoZXIgdGhhbiBjYXN0aW5nIHRvICdhbnknIGhlcmVcbiAgICAgICAgICAgIHRoaXMucm93TW9kZWwuc2V0Vmlld3BvcnREYXRhc291cmNlKHZpZXdwb3J0RGF0YXNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiB5b3UgY2FuIG9ubHkgdXNlIGEgdmlld3BvcnQgZGF0YXNvdXJjZSB3aGVuIGdyaWRPcHRpb25zLnJvd01vZGVsVHlwZSBpcyAnXCIgKyBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfVklFV1BPUlQgKyBcIidcIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBTZXQgdGhlIHJvdyBkYXRhLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFJvd0RhdGEgPSBmdW5jdGlvbiAocm93RGF0YSkge1xuICAgICAgICAvLyBpbW11dGFibGUgc2VydmljZSBpcyBwYXJ0IG9mIHRoZSBDU1JNIG1vZHVsZSwgaWYgbWlzc2luZywgbm8gQ1NSTVxuICAgICAgICB2YXIgbWlzc2luZ0ltbXV0YWJsZVNlcnZpY2UgPSB0aGlzLmltbXV0YWJsZVNlcnZpY2UgPT0gbnVsbDtcbiAgICAgICAgaWYgKG1pc3NpbmdJbW11dGFibGVTZXJ2aWNlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHlvdSBjYW4gb25seSBzZXQgcm93RGF0YSB3aGVuIHVzaW5nIHRoZSBDbGllbnQgU2lkZSBSb3cgTW9kZWwnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBubyBrZXlzIHByb3ZpZGVkIHByb3ZpZGVkIGZvciByb3dzLCB0aGVuIHdlIGNhbiB0cmVhZCB0aGUgb3BlcmF0aW9uIGFzIEltbXV0YWJsZVxuICAgICAgICBpZiAodGhpcy5pbW11dGFibGVTZXJ2aWNlLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuaW1tdXRhYmxlU2VydmljZS5zZXRSb3dEYXRhKHJvd0RhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLnJlc2V0KCk7XG4gICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5zZXRSb3dEYXRhKHJvd0RhdGEpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogc2luY2UgdjEyLCBhcGkuc2V0RmxvYXRpbmdUb3BSb3dEYXRhKCkgaXMgbm93IGFwaS5zZXRQaW5uZWRUb3BSb3dEYXRhKCkgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRGbG9hdGluZ1RvcFJvd0RhdGEgPSBmdW5jdGlvbiAocm93cykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYxMiwgYXBpLnNldEZsb2F0aW5nVG9wUm93RGF0YSgpIGlzIG5vdyBhcGkuc2V0UGlubmVkVG9wUm93RGF0YSgpJyk7XG4gICAgICAgIHRoaXMuc2V0UGlubmVkVG9wUm93RGF0YShyb3dzKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBzaW5jZSB2MTIsIGFwaS5zZXRGbG9hdGluZ0JvdHRvbVJvd0RhdGEoKSBpcyBub3cgYXBpLnNldFBpbm5lZEJvdHRvbVJvd0RhdGEoKSAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEZsb2F0aW5nQm90dG9tUm93RGF0YSA9IGZ1bmN0aW9uIChyb3dzKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdjEyLCBhcGkuc2V0RmxvYXRpbmdCb3R0b21Sb3dEYXRhKCkgaXMgbm93IGFwaS5zZXRQaW5uZWRCb3R0b21Sb3dEYXRhKCknKTtcbiAgICAgICAgdGhpcy5zZXRQaW5uZWRCb3R0b21Sb3dEYXRhKHJvd3MpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IHNpbmNlIHYxMiwgYXBpLmdldEZsb2F0aW5nVG9wUm93Q291bnQoKSBpcyBub3cgYXBpLmdldFBpbm5lZFRvcFJvd0NvdW50KCkgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRGbG9hdGluZ1RvcFJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYxMiwgYXBpLmdldEZsb2F0aW5nVG9wUm93Q291bnQoKSBpcyBub3cgYXBpLmdldFBpbm5lZFRvcFJvd0NvdW50KCknKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGlubmVkVG9wUm93Q291bnQoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBzaW5jZSB2MTIsIGFwaS5nZXRGbG9hdGluZ0JvdHRvbVJvd0NvdW50KCkgaXMgbm93IGFwaS5nZXRQaW5uZWRCb3R0b21Sb3dDb3VudCgpICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0RmxvYXRpbmdCb3R0b21Sb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MTIsIGFwaS5nZXRGbG9hdGluZ0JvdHRvbVJvd0NvdW50KCkgaXMgbm93IGFwaS5nZXRQaW5uZWRCb3R0b21Sb3dDb3VudCgpJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBpbm5lZEJvdHRvbVJvd0NvdW50KCk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogc2luY2UgdjEyLCBhcGkuZ2V0RmxvYXRpbmdUb3BSb3coKSBpcyBub3cgYXBpLmdldFBpbm5lZFRvcFJvdygpICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0RmxvYXRpbmdUb3BSb3cgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2MTIsIGFwaS5nZXRGbG9hdGluZ1RvcFJvdygpIGlzIG5vdyBhcGkuZ2V0UGlubmVkVG9wUm93KCknKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGlubmVkVG9wUm93KGluZGV4KTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBzaW5jZSB2MTIsIGFwaS5nZXRGbG9hdGluZ0JvdHRvbVJvdygpIGlzIG5vdyBhcGkuZ2V0UGlubmVkQm90dG9tUm93KCkgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRGbG9hdGluZ0JvdHRvbVJvdyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHYxMiwgYXBpLmdldEZsb2F0aW5nQm90dG9tUm93KCkgaXMgbm93IGFwaS5nZXRQaW5uZWRCb3R0b21Sb3coKScpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQaW5uZWRCb3R0b21Sb3coaW5kZXgpO1xuICAgIH07XG4gICAgLyoqIFNldCB0aGUgdG9wIHBpbm5lZCByb3dzLiBDYWxsIHdpdGggbm8gcm93cyAvIHVuZGVmaW5lZCB0byBjbGVhciB0b3AgcGlubmVkIHJvd3MuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0UGlubmVkVG9wUm93RGF0YSA9IGZ1bmN0aW9uIChyb3dzKSB7XG4gICAgICAgIHRoaXMucGlubmVkUm93TW9kZWwuc2V0UGlubmVkVG9wUm93RGF0YShyb3dzKTtcbiAgICB9O1xuICAgIC8qKiBTZXQgdGhlIGJvdHRvbSBwaW5uZWQgcm93cy4gQ2FsbCB3aXRoIG5vIHJvd3MgLyB1bmRlZmluZWQgdG8gY2xlYXIgYm90dG9tIHBpbm5lZCByb3dzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFBpbm5lZEJvdHRvbVJvd0RhdGEgPSBmdW5jdGlvbiAocm93cykge1xuICAgICAgICB0aGlzLnBpbm5lZFJvd01vZGVsLnNldFBpbm5lZEJvdHRvbVJvd0RhdGEocm93cyk7XG4gICAgfTtcbiAgICAvKiogR2V0cyB0aGUgbnVtYmVyIG9mIHRvcCBwaW5uZWQgcm93cy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRQaW5uZWRUb3BSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkVG9wUm93Q291bnQoKTtcbiAgICB9O1xuICAgIC8qKiBHZXRzIHRoZSBudW1iZXIgb2YgYm90dG9tIHBpbm5lZCByb3dzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFBpbm5lZEJvdHRvbVJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Sb3dDb3VudCgpO1xuICAgIH07XG4gICAgLyoqIEdldHMgdGhlIHRvcCBwaW5uZWQgcm93IHdpdGggdGhlIHNwZWNpZmllZCBpbmRleC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRQaW5uZWRUb3BSb3cgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkVG9wUm93KGluZGV4KTtcbiAgICB9O1xuICAgIC8qKiBHZXRzIHRoZSB0b3AgcGlubmVkIHJvdyB3aXRoIHRoZSBzcGVjaWZpZWQgaW5kZXguICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0UGlubmVkQm90dG9tUm93ID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbm5lZFJvd01vZGVsLmdldFBpbm5lZEJvdHRvbVJvdyhpbmRleCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBDYWxsIHRvIHNldCBuZXcgY29sdW1uIGRlZmluaXRpb25zLiBUaGUgZ3JpZCB3aWxsIHJlZHJhdyBhbGwgdGhlIGNvbHVtbiBoZWFkZXJzLCBhbmQgdGhlbiByZWRyYXcgYWxsIG9mIHRoZSByb3dzLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldENvbHVtbkRlZnMgPSBmdW5jdGlvbiAoY29sRGVmcywgc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IHZvaWQgMCkgeyBzb3VyY2UgPSBcImFwaVwiOyB9XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uRGVmcyhjb2xEZWZzLCBzb3VyY2UpO1xuICAgIH07XG4gICAgLyoqIENhbGwgdG8gc2V0IG5ldyBhdXRvIGdyb3VwIGNvbHVtbiBkZWZpbml0aW9uLiBUaGUgZ3JpZCB3aWxsIHJlY3JlYXRlIGFueSBhdXRvLWdyb3VwIGNvbHVtbnMgaWYgcHJlc2VudC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRBdXRvR3JvdXBDb2x1bW5EZWYgPSBmdW5jdGlvbiAoY29sRGVmLCBzb3VyY2UpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfQVVUT19HUk9VUF9DT0xVTU5fREVGLCBjb2xEZWYsIHRydWUpO1xuICAgIH07XG4gICAgLyoqIENhbGwgdG8gc2V0IG5ldyBEZWZhdWx0IENvbHVtbiBEZWZpbml0aW9uLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldERlZmF1bHRDb2xEZWYgPSBmdW5jdGlvbiAoY29sRGVmLCBzb3VyY2UpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfREVGQVVMVF9DT0xfREVGLCBjb2xEZWYsIHRydWUpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZXhwaXJlVmFsdWVDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy52YWx1ZUNhY2hlLmV4cGlyZSgpO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBvYmplY3Qgd2l0aCB0d28gcHJvcGVydGllczpcbiAgICAgKiAgLSBgdG9wYDogVGhlIHRvcCBwaXhlbCBwb3NpdGlvbiBvZiB0aGUgY3VycmVudCBzY3JvbGwgaW4gdGhlIGdyaWRcbiAgICAgKiAgLSBgYm90dG9tYDogVGhlIGJvdHRvbSBwaXhlbCBwb3NpdGlvbiBvZiB0aGUgY3VycmVudCBzY3JvbGwgaW4gdGhlIGdyaWRcbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRWZXJ0aWNhbFBpeGVsUmFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRCb2R5Q3RybC5nZXRTY3JvbGxGZWF0dXJlKCkuZ2V0VlNjcm9sbFBvc2l0aW9uKCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIHR3byBwcm9wZXJ0aWVzOlxuICAgICAqIC0gYGxlZnRgOiBUaGUgbGVmdCBwaXhlbCBwb3NpdGlvbiBvZiB0aGUgY3VycmVudCBzY3JvbGwgaW4gdGhlIGdyaWRcbiAgICAgKiAtIGByaWdodGA6IFRoZSByaWdodCBwaXhlbCBwb3NpdGlvbiBvZiB0aGUgY3VycmVudCBzY3JvbGwgaW4gdGhlIGdyaWRcbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRIb3Jpem9udGFsUGl4ZWxSYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZEJvZHlDdHJsLmdldFNjcm9sbEZlYXR1cmUoKS5nZXRIU2Nyb2xsUG9zaXRpb24oKTtcbiAgICB9O1xuICAgIC8qKiBJZiBgdHJ1ZWAsIHRoZSBob3Jpem9udGFsIHNjcm9sbGJhciB3aWxsIGFsd2F5cyBiZSBwcmVzZW50LCBldmVuIGlmIG5vdCByZXF1aXJlZC4gT3RoZXJ3aXNlLCBpdCB3aWxsIG9ubHkgYmUgZGlzcGxheWVkIHdoZW4gbmVjZXNzYXJ5LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEFsd2F5c1Nob3dIb3Jpem9udGFsU2Nyb2xsID0gZnVuY3Rpb24gKHNob3cpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoJ2Fsd2F5c1Nob3dIb3Jpem9udGFsU2Nyb2xsJywgc2hvdyk7XG4gICAgfTtcbiAgICAvKiogSWYgYHRydWVgLCB0aGUgdmVydGljYWwgc2Nyb2xsYmFyIHdpbGwgYWx3YXlzIGJlIHByZXNlbnQsIGV2ZW4gaWYgbm90IHJlcXVpcmVkLiBPdGhlcndpc2UgaXQgd2lsbCBvbmx5IGJlIGRpc3BsYXllZCB3aGVuIG5lY2Vzc2FyeS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRBbHdheXNTaG93VmVydGljYWxTY3JvbGwgPSBmdW5jdGlvbiAoc2hvdykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eSgnYWx3YXlzU2hvd1ZlcnRpY2FsU2Nyb2xsJywgc2hvdyk7XG4gICAgfTtcbiAgICAvKiogRm9yY2UgcmVmcmVzaCBhbGwgdG9vbCBwYW5lbHMgYnkgY2FsbGluZyB0aGVpciBgcmVmcmVzaGAgbWV0aG9kLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnJlZnJlc2hUb29sUGFuZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zaWRlQmFyQ29tcCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2lkZUJhckNvbXAucmVmcmVzaCgpO1xuICAgIH07XG4gICAgLyoqIFBlcmZvcm1zIGNoYW5nZSBkZXRlY3Rpb24gb24gYWxsIGNlbGxzLCByZWZyZXNoaW5nIGNlbGxzIHdoZXJlIHJlcXVpcmVkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnJlZnJlc2hDZWxscyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PT0gdm9pZCAwKSB7IHBhcmFtcyA9IHt9OyB9XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmFtcykpIHtcbiAgICAgICAgICAgIC8vIHRoZSBvbGQgdmVyc2lvbiBvZiByZWZyZXNoQ2VsbHMoKSB0b29rIGFuIGFycmF5IG9mIHJvd05vZGVzIGZvciB0aGUgZmlyc3QgYXJndW1lbnRcbiAgICAgICAgICAgIGNvbnNvbGUud2Fybignc2luY2UgQUcgR3JpZCB2MTEuMSwgcmVmcmVzaENlbGxzKCkgbm93IHRha2VzIHBhcmFtZXRlcnMsIHBsZWFzZSBzZWUgdGhlIGRvY3VtZW50YXRpb24uJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yb3dSZW5kZXJlci5yZWZyZXNoQ2VsbHMocGFyYW1zKTtcbiAgICB9O1xuICAgIC8qKiBGbGFzaCByb3dzLCBjb2x1bW5zIG9yIGluZGl2aWR1YWwgY2VsbHMuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZmxhc2hDZWxscyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PT0gdm9pZCAwKSB7IHBhcmFtcyA9IHt9OyB9XG4gICAgICAgIHRoaXMucm93UmVuZGVyZXIuZmxhc2hDZWxscyhwYXJhbXMpO1xuICAgIH07XG4gICAgLyoqIFJlbW92ZSByb3cocykgZnJvbSB0aGUgRE9NIGFuZCByZWNyZWF0ZSB0aGVtIGFnYWluIGZyb20gc2NyYXRjaC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZWRyYXdSb3dzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zID09PSB2b2lkIDApIHsgcGFyYW1zID0ge307IH1cbiAgICAgICAgdmFyIHJvd05vZGVzID0gcGFyYW1zID8gcGFyYW1zLnJvd05vZGVzIDogdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnJvd1JlbmRlcmVyLnJlZHJhd1Jvd3Mocm93Tm9kZXMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0RnVuY3Rpb25zUmVhZE9ubHkgPSBmdW5jdGlvbiAocmVhZE9ubHkpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoJ2Z1bmN0aW9uc1JlYWRPbmx5JywgcmVhZE9ubHkpO1xuICAgIH07XG4gICAgLyoqIFJlZHJhd3MgdGhlIGhlYWRlci4gVXNlZnVsIGlmIGEgY29sdW1uIG5hbWUgY2hhbmdlcywgb3Igc29tZXRoaW5nIGVsc2UgdGhhdCBjaGFuZ2VzIGhvdyB0aGUgY29sdW1uIGhlYWRlciBpcyBkaXNwbGF5ZWQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVmcmVzaEhlYWRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2UuZ2V0SGVhZGVyUm93Q29udGFpbmVyQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjLnJlZnJlc2goKTsgfSk7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBgdHJ1ZWAgaWYgYW55IGZpbHRlciBpcyBzZXQuIFRoaXMgaW5jbHVkZXMgcXVpY2sgZmlsdGVyLCBhZHZhbmNlZCBmaWx0ZXIgb3IgZXh0ZXJuYWwgZmlsdGVyLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzQW55RmlsdGVyUHJlc2VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyTWFuYWdlci5pc0FueUZpbHRlclByZXNlbnQoKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgY29sdW1uIGZpbHRlciBpcyBzZXQsIG90aGVyd2lzZSBgZmFsc2VgLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzQ29sdW1uRmlsdGVyUHJlc2VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyTWFuYWdlci5pc0NvbHVtbkZpbHRlclByZXNlbnQoKSB8fCB0aGlzLmZpbHRlck1hbmFnZXIuaXNBZ2dyZWdhdGVGaWx0ZXJQcmVzZW50KCk7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHF1aWNrIGZpbHRlciBpcyBzZXQsIG90aGVyd2lzZSBgZmFsc2VgLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzUXVpY2tGaWx0ZXJQcmVzZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5maWx0ZXJNYW5hZ2VyLmlzUXVpY2tGaWx0ZXJQcmVzZW50KCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByb3cgbW9kZWwgaW5zaWRlIHRoZSB0YWJsZS5cbiAgICAgKiBGcm9tIGhlcmUgeW91IGNhbiBzZWUgdGhlIG9yaWdpbmFsIHJvd3MsIHJvd3MgYWZ0ZXIgZmlsdGVyIGhhcyBiZWVuIGFwcGxpZWQsXG4gICAgICogcm93cyBhZnRlciBhZ2dyZWdhdGlvbiBoYXMgYmVlbiBhcHBsaWVkLCBhbmQgdGhlIGZpbmFsIHNldCBvZiAndG8gYmUgZGlzcGxheWVkJyByb3dzLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldE1vZGVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbDtcbiAgICB9O1xuICAgIC8qKiBFeHBhbmQgb3IgY29sbGFwc2UgYSBzcGVjaWZpYyByb3cgbm9kZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRSb3dOb2RlRXhwYW5kZWQgPSBmdW5jdGlvbiAocm93Tm9kZSwgZXhwYW5kZWQpIHtcbiAgICAgICAgaWYgKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHJvd05vZGUuc2V0RXhwYW5kZWQoZXhwYW5kZWQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiAgSWYgYWZ0ZXIgZ2V0dGluZyB0aGUgbW9kZWwsIHlvdSBleHBhbmQgb3IgY29sbGFwc2UgYSBncm91cCwgY2FsbCB0aGlzIG1ldGhvZCB0byBpbmZvcm0gdGhlIGdyaWQuXG4gICAgICogIEl0IHdpbGwgd29yayBvdXQgdGhlIGZpbmFsIHNldCBvZiAndG8gYmUgZGlzcGxheWVkJyByb3dzIGFnYWluIChpLmUuIGV4cGFuZCBvciBjb2xsYXBzZSB0aGUgZ3JvdXAgdmlzdWFsbHkpLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLm9uR3JvdXBFeHBhbmRlZE9yQ29sbGFwc2VkID0gZnVuY3Rpb24gKGRlcHJlY2F0ZWRfcmVmcmVzaEZyb21JbmRleCkge1xuICAgICAgICBpZiAobWlzc2luZyh0aGlzLmNsaWVudFNpZGVSb3dNb2RlbCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY2Fubm90IGNhbGwgb25Hcm91cEV4cGFuZGVkT3JDb2xsYXBzZWQgdW5sZXNzIHVzaW5nIG5vcm1hbCByb3cgbW9kZWwnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXhpc3RzKGRlcHJlY2F0ZWRfcmVmcmVzaEZyb21JbmRleCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogYXBpLm9uR3JvdXBFeHBhbmRlZE9yQ29sbGFwc2VkIC0gcmVmcmVzaEZyb21JbmRleCBwYXJhbWV0ZXIgaXMgbm8gbG9uZ2VyIHVzZWQsIHRoZSBncmlkIHdpbGwgcmVmcmVzaCBhbGwgcm93cycpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIGRvbid0IHJlYWxseSB3YW50IHRoZSB1c2VyIGNhbGxpbmcgdGhpcyBpZiBvbmx5IG9uZSByb3dOb2RlIHdhcyBleHBhbmRlZCwgaW5zdGVhZCB0aGV5IHNob3VsZCBiZVxuICAgICAgICAvLyBjYWxsaW5nIHJvd05vZGUuc2V0RXhwYW5kZWQoYm9vbGVhbikgLSB0aGlzIHdheSB3ZSBkbyBhICdrZWVwUmVuZGVyZWRSb3dzPWZhbHNlJyBzbyB0aGF0IHRoZSB3aG9sZVxuICAgICAgICAvLyBncmlkIGdldHMgcmVmcmVzaGVkIGFnYWluIC0gb3RoZXJ3aXNlIHRoZSByb3cgd2l0aCB0aGUgcm93Tm9kZXMgdGhhdCB3ZXJlIGNoYW5nZWQgd29uJ3QgZ2V0IHVwZGF0ZWQsXG4gICAgICAgIC8vIGFuZCB0aHVzIHRoZSBleHBhbmQgaWNvbiBpbiB0aGUgZ3JvdXAgY2VsbCB3b24ndCBnZXQgJ29wZW5lZCcgb3IgJ2Nsb3NlZCcuXG4gICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLnJlZnJlc2hNb2RlbCh7IHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLk1BUCB9KTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBzaW5jZSB2ZXJzaW9uIDE4LngsIGFwaS5yZWZyZXNoSW5NZW1vcnlSb3dNb2RlbCgpIHNob3VsZCBiZSByZXBsYWNlZCB3aXRoIGFwaS5yZWZyZXNoQ2xpZW50U2lkZVJvd01vZGVsKCkgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZWZyZXNoSW5NZW1vcnlSb3dNb2RlbCA9IGZ1bmN0aW9uIChzdGVwKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IHNpbmNlIHZlcnNpb24gMTgueCwgYXBpLnJlZnJlc2hJbk1lbW9yeVJvd01vZGVsKCkgc2hvdWxkIGJlIHJlcGxhY2VkIHdpdGggYXBpLnJlZnJlc2hDbGllbnRTaWRlUm93TW9kZWwoKVwiKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoQ2xpZW50U2lkZVJvd01vZGVsKHN0ZXApO1xuICAgIH07XG4gICAgLyoqIEdldHMgdGhlIENsaWVudC1TaWRlIFJvdyBNb2RlbCB0byByZWZyZXNoLCBleGVjdXRpbmcgdGhlIGdyb3VwaW5nLCBmaWx0ZXJpbmcgYW5kIHNvcnRpbmcgYWdhaW4uICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVmcmVzaENsaWVudFNpZGVSb3dNb2RlbCA9IGZ1bmN0aW9uIChzdGVwKSB7XG4gICAgICAgIGlmIChtaXNzaW5nKHRoaXMuY2xpZW50U2lkZVJvd01vZGVsKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdjYW5ub3QgY2FsbCByZWZyZXNoQ2xpZW50U2lkZVJvd01vZGVsIHVubGVzcyB1c2luZyBub3JtYWwgcm93IG1vZGVsJyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtc1N0ZXAgPSBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5FVkVSWVRISU5HO1xuICAgICAgICB2YXIgc3RlcHNNYXBwZWQgPSB7XG4gICAgICAgICAgICBncm91cDogQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuRVZFUllUSElORyxcbiAgICAgICAgICAgIGZpbHRlcjogQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuRklMVEVSLFxuICAgICAgICAgICAgbWFwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5NQVAsXG4gICAgICAgICAgICBhZ2dyZWdhdGU6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLkFHR1JFR0FURSxcbiAgICAgICAgICAgIHNvcnQ6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLlNPUlQsXG4gICAgICAgICAgICBwaXZvdDogQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuUElWT1RcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGV4aXN0cyhzdGVwKSkge1xuICAgICAgICAgICAgcGFyYW1zU3RlcCA9IHN0ZXBzTWFwcGVkW3N0ZXBdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtaXNzaW5nKHBhcmFtc1N0ZXApKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQUcgR3JpZDogaW52YWxpZCBzdGVwIFwiICsgc3RlcCArIFwiLCBhdmFpbGFibGUgc3RlcHMgYXJlIFwiICsgT2JqZWN0LmtleXMoc3RlcHNNYXBwZWQpLmpvaW4oJywgJykpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhbmltYXRlID0gIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NBbmltYXRpb25GcmFtZSgpO1xuICAgICAgICB2YXIgbW9kZWxQYXJhbXMgPSB7XG4gICAgICAgICAgICBzdGVwOiBwYXJhbXNTdGVwLFxuICAgICAgICAgICAga2VlcFJlbmRlcmVkUm93czogdHJ1ZSxcbiAgICAgICAgICAgIGtlZXBFZGl0aW5nUm93czogdHJ1ZSxcbiAgICAgICAgICAgIGFuaW1hdGU6IGFuaW1hdGVcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jbGllbnRTaWRlUm93TW9kZWwucmVmcmVzaE1vZGVsKG1vZGVsUGFyYW1zKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCB3aGVuIHRoZXJlIGFyZSBubyBtb3JlIGFuaW1hdGlvbiBmcmFtZXMgbGVmdCB0byBwcm9jZXNzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzQW5pbWF0aW9uRnJhbWVRdWV1ZUVtcHR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hbmltYXRpb25GcmFtZVNlcnZpY2UuaXNRdWV1ZUVtcHR5KCk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5mbHVzaEFsbEFuaW1hdGlvbkZyYW1lcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hbmltYXRpb25GcmFtZVNlcnZpY2UuZmx1c2hBbGxGcmFtZXMoKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHJvdyBub2RlIHdpdGggdGhlIGdpdmVuIElELlxuICAgICAqIFRoZSByb3cgbm9kZSBJRCBpcyB0aGUgb25lIHlvdSBwcm92aWRlIGZyb20gdGhlIGNhbGxiYWNrIGBnZXRSb3dJZChwYXJhbXMpYCxcbiAgICAgKiBvdGhlcndpc2UgdGhlIElEIGlzIGEgbnVtYmVyIChjYXN0IGFzIHN0cmluZykgYXV0by1nZW5lcmF0ZWQgYnkgdGhlIGdyaWQgd2hlblxuICAgICAqIHRoZSByb3cgZGF0YSBpcyBzZXQuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0Um93Tm9kZSA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXRSb3dOb2RlKGlkKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHNpemVzIHRoYXQgdmFyaW91cyBVSSBlbGVtZW50cyB3aWxsIGJlIHJlbmRlcmVkIGF0IHdpdGggdGhlIGN1cnJlbnQgdGhlbWUuXG4gICAgICogSWYgeW91IG92ZXJyaWRlIHRoZSByb3cgb3IgaGVhZGVyIGhlaWdodCB1c2luZyBgZ3JpZE9wdGlvbnNgLCB0aGUgb3ZlcnJpZGUgdmFsdWUgeW91IHByb3ZpZGVkIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0U2l6ZXNGb3JDdXJyZW50VGhlbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByb3dIZWlnaHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0hlaWdodEFzTnVtYmVyKCksXG4gICAgICAgICAgICBoZWFkZXJIZWlnaHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEhlYWRlckhlaWdodCgpXG4gICAgICAgIH07XG4gICAgfTtcbiAgICAvKiogRXhwYW5kIGFsbCBncm91cHMuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZXhwYW5kQWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5jbGllbnRTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmV4cGFuZE9yQ29sbGFwc2VBbGwodHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyU2lkZVJvd01vZGVsLmV4cGFuZEFsbCh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZXhwYW5kQWxsIG9ubHkgd29ya3Mgd2l0aCBDbGllbnQgU2lkZSBSb3cgTW9kZWwgYW5kIFNlcnZlciBTaWRlIFJvdyBNb2RlbCcpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQ29sbGFwc2UgYWxsIGdyb3Vwcy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jb2xsYXBzZUFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2xpZW50U2lkZVJvd01vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5leHBhbmRPckNvbGxhcHNlQWxsKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnNlcnZlclNpZGVSb3dNb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwuZXhwYW5kQWxsKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY29sbGFwc2VBbGwgb25seSB3b3JrcyB3aXRoIENsaWVudCBTaWRlIFJvdyBNb2RlbCBhbmQgU2VydmVyIFNpZGUgUm93IE1vZGVsJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBHZXRzIHRoZSB0b29sIHBhbmVsIGluc3RhbmNlIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHN1cHBsaWVkIGBpZGAuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0VG9vbFBhbmVsSW5zdGFuY2UgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNpZGVCYXJDb21wKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHRvb2xQYW5lbCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBBRyBHcmlkIEVudGVycHJpc2UnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tcCA9IHRoaXMuc2lkZUJhckNvbXAuZ2V0VG9vbFBhbmVsSW5zdGFuY2UoaWQpO1xuICAgICAgICByZXR1cm4gdW53cmFwVXNlckNvbXAoY29tcCk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5hZGRWaXJ0dWFsUm93TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnROYW1lLCByb3dJbmRleCwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHR5cGVvZiBldmVudE5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGFkZFZpcnR1YWxSb3dMaXN0ZW5lciBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGFkZFJlbmRlcmVkUm93TGlzdGVuZXIuJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZGRSZW5kZXJlZFJvd0xpc3RlbmVyKGV2ZW50TmFtZSwgcm93SW5kZXgsIGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIHRvIGEgdmlydHVhbCByb3cuXG4gICAgICogQSB2aXJ0dWFsIHJvdyBpcyBhIHJvdyB0aGF0IGlzIHZpc3VhbGx5IHJlbmRlcmVkIG9uIHRoZSBzY3JlZW4gKHJvd3MgdGhhdCBhcmUgbm90IHZpc2libGUgYmVjYXVzZSBvZiB0aGUgc2Nyb2xsIHBvc2l0aW9uIGFyZSBub3QgcmVuZGVyZWQpLlxuICAgICAqIFVubGlrZSBub3JtYWwgZXZlbnRzLCB5b3UgZG8gbm90IG5lZWQgdG8gdW5yZWdpc3RlciByZW5kZXJlZCByb3cgbGlzdGVuZXJzLlxuICAgICAqIFdoZW4gdGhlIHJlbmRlcmVkIHJvdyBpcyByZW1vdmVkIGZyb20gdGhlIGdyaWQsIGFsbCBhc3NvY2lhdGVkIHJlbmRlcmVkIHJvdyBsaXN0ZW5lcnMgd2lsbCBhbHNvIGJlIHJlbW92ZWQuXG4gICAgICogbGlzdGVuIGZvciB0aGlzIGV2ZW50IGlmIHlvdXIgYGNlbGxSZW5kZXJlcmAgbmVlZHMgdG8gZG8gY2xlYW51cCB3aGVuIHRoZSByb3cgbm8gbG9uZ2VyIGV4aXN0cy5cbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5hZGRSZW5kZXJlZFJvd0xpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50TmFtZSwgcm93SW5kZXgsIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmIChldmVudE5hbWUgPT09ICd2aXJ0dWFsUm93U2VsZWN0ZWQnKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBldmVudCB2aXJ0dWFsUm93U2VsZWN0ZWQgaXMgZGVwcmVjYXRlZCwgdG8gcmVnaXN0ZXIgZm9yIGluZGl2aWR1YWwgcm93XFxuICAgICAgICAgICAgICAgIHNlbGVjdGlvbiBldmVudHMsIGFkZCBhIGxpc3RlbmVyIGRpcmVjdGx5IHRvIHRoZSByb3cgbm9kZS5cIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yb3dSZW5kZXJlci5hZGRSZW5kZXJlZFJvd0xpc3RlbmVyKGV2ZW50TmFtZSwgcm93SW5kZXgsIGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKiBQYXNzIGEgcXVpY2sgZmlsdGVyIHRleHQgaW50byB0aGUgZ3JpZCBmb3IgZmlsdGVyaW5nLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFF1aWNrRmlsdGVyID0gZnVuY3Rpb24gKG5ld0ZpbHRlcikge1xuICAgICAgICB0aGlzLmZpbHRlck1hbmFnZXIuc2V0UXVpY2tGaWx0ZXIobmV3RmlsdGVyKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBkbyBub3QgdXNlIGFwaSBmb3Igc2VsZWN0aW9uLCBjYWxsIHJvd05vZGUuc2V0U2VsZWN0ZWQodmFsdWUpIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZWxlY3RJbmRleCA9IGZ1bmN0aW9uIChpbmRleCwgdHJ5TXVsdGksIHN1cHByZXNzRXZlbnRzKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZG8gbm90IHVzZSBhcGkgZm9yIHNlbGVjdGlvbiwgY2FsbCByb3dOb2RlLnNldFNlbGVjdGVkKHZhbHVlKSBpbnN0ZWFkJyk7XG4gICAgICAgIGlmIChzdXBwcmVzc0V2ZW50cykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzdXBwcmVzc0V2ZW50cyBpcyBubyBsb25nZXIgc3VwcG9ydGVkLCBzdG9wIGxpc3RlbmluZyBmb3IgdGhlIGV2ZW50IGlmIHlvdSBubyBsb25nZXIgd2FudCBpdCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS5zZWxlY3RJbmRleChpbmRleCwgdHJ5TXVsdGkpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IGRvIG5vdCB1c2UgYXBpIGZvciBzZWxlY3Rpb24sIGNhbGwgcm93Tm9kZS5zZXRTZWxlY3RlZCh2YWx1ZSkgaW5zdGVhZC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5kZXNlbGVjdEluZGV4ID0gZnVuY3Rpb24gKGluZGV4LCBzdXBwcmVzc0V2ZW50cykge1xuICAgICAgICBpZiAoc3VwcHJlc3NFdmVudHMgPT09IHZvaWQgMCkgeyBzdXBwcmVzc0V2ZW50cyA9IGZhbHNlOyB9XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZG8gbm90IHVzZSBhcGkgZm9yIHNlbGVjdGlvbiwgY2FsbCByb3dOb2RlLnNldFNlbGVjdGVkKHZhbHVlKSBpbnN0ZWFkJyk7XG4gICAgICAgIGlmIChzdXBwcmVzc0V2ZW50cykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzdXBwcmVzc0V2ZW50cyBpcyBubyBsb25nZXIgc3VwcG9ydGVkLCBzdG9wIGxpc3RlbmluZyBmb3IgdGhlIGV2ZW50IGlmIHlvdSBubyBsb25nZXIgd2FudCBpdCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS5kZXNlbGVjdEluZGV4KGluZGV4KTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBBUEkgZm9yIHNlbGVjdGlvbiBpcyBkZXByZWNhdGVkLCBjYWxsIHJvd05vZGUuc2V0U2VsZWN0ZWQodmFsdWUpIGluc3RlYWQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2VsZWN0Tm9kZSA9IGZ1bmN0aW9uIChub2RlLCB0cnlNdWx0aSwgc3VwcHJlc3NFdmVudHMpIHtcbiAgICAgICAgaWYgKHRyeU11bHRpID09PSB2b2lkIDApIHsgdHJ5TXVsdGkgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoc3VwcHJlc3NFdmVudHMgPT09IHZvaWQgMCkgeyBzdXBwcmVzc0V2ZW50cyA9IGZhbHNlOyB9XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogQVBJIGZvciBzZWxlY3Rpb24gaXMgZGVwcmVjYXRlZCwgY2FsbCByb3dOb2RlLnNldFNlbGVjdGVkKHZhbHVlKSBpbnN0ZWFkJyk7XG4gICAgICAgIGlmIChzdXBwcmVzc0V2ZW50cykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzdXBwcmVzc0V2ZW50cyBpcyBubyBsb25nZXIgc3VwcG9ydGVkLCBzdG9wIGxpc3RlbmluZyBmb3IgdGhlIGV2ZW50IGlmIHlvdSBubyBsb25nZXIgd2FudCBpdCcpO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoeyBuZXdWYWx1ZTogdHJ1ZSwgY2xlYXJTZWxlY3Rpb246ICF0cnlNdWx0aSB9KTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBBUEkgZm9yIHNlbGVjdGlvbiBpcyBkZXByZWNhdGVkLCBjYWxsIHJvd05vZGUuc2V0U2VsZWN0ZWQodmFsdWUpIGluc3RlYWQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZGVzZWxlY3ROb2RlID0gZnVuY3Rpb24gKG5vZGUsIHN1cHByZXNzRXZlbnRzKSB7XG4gICAgICAgIGlmIChzdXBwcmVzc0V2ZW50cyA9PT0gdm9pZCAwKSB7IHN1cHByZXNzRXZlbnRzID0gZmFsc2U7IH1cbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBBUEkgZm9yIHNlbGVjdGlvbiBpcyBkZXByZWNhdGVkLCBjYWxsIHJvd05vZGUuc2V0U2VsZWN0ZWQodmFsdWUpIGluc3RlYWQnKTtcbiAgICAgICAgaWYgKHN1cHByZXNzRXZlbnRzKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHN1cHByZXNzRXZlbnRzIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQsIHN0b3AgbGlzdGVuaW5nIGZvciB0aGUgZXZlbnQgaWYgeW91IG5vIGxvbmdlciB3YW50IGl0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5zZXRTZWxlY3RlZFBhcmFtcyh7IG5ld1ZhbHVlOiBmYWxzZSB9KTtcbiAgICB9O1xuICAgIC8qKiBTZWxlY3QgYWxsIHJvd3MsIHJlZ2FyZGxlc3Mgb2YgZmlsdGVyaW5nIGFuZCByb3dzIHRoYXQgYXJlIG5vdCB2aXNpYmxlIGR1ZSB0byBncm91cGluZyBiZWluZyBlbmFibGVkIGFuZCB0aGVpciBncm91cHMgbm90IGV4cGFuZGVkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNlbGVjdEFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLnNlbGVjdEFsbFJvd05vZGVzKCk7XG4gICAgfTtcbiAgICAvKiogQ2xlYXIgYWxsIHJvdyBzZWxlY3Rpb25zLCByZWdhcmRsZXNzIG9mIGZpbHRlcmluZy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5kZXNlbGVjdEFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLmRlc2VsZWN0QWxsUm93Tm9kZXMoKTtcbiAgICB9O1xuICAgIC8qKiBTZWxlY3QgYWxsIGZpbHRlcmVkIHJvd3MuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2VsZWN0QWxsRmlsdGVyZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS5zZWxlY3RBbGxSb3dOb2Rlcyh0cnVlKTtcbiAgICB9O1xuICAgIC8qKiBDbGVhciBhbGwgZmlsdGVyZWQgc2VsZWN0aW9ucy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5kZXNlbGVjdEFsbEZpbHRlcmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNlbGVjdGlvblNlcnZpY2UuZGVzZWxlY3RBbGxSb3dOb2Rlcyh0cnVlKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCByZWNvbXB1dGVBZ2dyZWdhdGVzIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSBjYWxsIGFwaS5yZWZyZXNoQ2xpZW50U2lkZVJvd01vZGVsKCdhZ2dyZWdhdGUnKSBpbnN0ZWFkICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVjb21wdXRlQWdncmVnYXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy5jbGllbnRTaWRlUm93TW9kZWwpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ2Nhbm5vdCBjYWxsIHJlY29tcHV0ZUFnZ3JlZ2F0ZXMgdW5sZXNzIHVzaW5nIG5vcm1hbCByb3cgbW9kZWwnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLndhcm4oXCJyZWNvbXB1dGVBZ2dyZWdhdGVzIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSBjYWxsIGFwaS5yZWZyZXNoQ2xpZW50U2lkZVJvd01vZGVsKCdhZ2dyZWdhdGUnKSBpbnN0ZWFkXCIpO1xuICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5yZWZyZXNoTW9kZWwoeyBzdGVwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5BR0dSRUdBVEUgfSk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBTZXRzIGNvbHVtbnMgdG8gYWRqdXN0IGluIHNpemUgdG8gZml0IHRoZSBncmlkIGhvcml6b250YWxseS5cbiAgICAgKiovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2l6ZUNvbHVtbnNUb0ZpdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5ncmlkQm9keUN0cmwuc2l6ZUNvbHVtbnNUb0ZpdChwYXJhbXMpO1xuICAgIH07XG4gICAgLyoqIFNob3cgdGhlICdsb2FkaW5nJyBvdmVybGF5LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNob3dMb2FkaW5nT3ZlcmxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vdmVybGF5V3JhcHBlckNvbXAuc2hvd0xvYWRpbmdPdmVybGF5KCk7XG4gICAgfTtcbiAgICAvKiogU2hvdyB0aGUgJ25vIHJvd3MnIG92ZXJsYXkuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2hvd05vUm93c092ZXJsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub3ZlcmxheVdyYXBwZXJDb21wLnNob3dOb1Jvd3NPdmVybGF5KCk7XG4gICAgfTtcbiAgICAvKiogSGlkZXMgdGhlIG92ZXJsYXkgaWYgc2hvd2luZy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5oaWRlT3ZlcmxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vdmVybGF5V3JhcHBlckNvbXAuaGlkZU92ZXJsYXkoKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzTm9kZVNlbGVjdGVkID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBubyBuZWVkIHRvIGNhbGwgYXBpLmlzTm9kZVNlbGVjdGVkKCksIGp1c3QgY2FsbCBub2RlLmlzU2VsZWN0ZWQoKSBpbnN0ZWFkJyk7XG4gICAgICAgIHJldHVybiBub2RlLmlzU2VsZWN0ZWQoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBVc2UgZ2V0U2VsZWN0ZWROb2Rlc0J5SWQgbm8gbG9uZ2VyIGV4aXN0cywgdXNlIGdldFNlbGVjdGVkTm9kZXMoKS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRTZWxlY3RlZE5vZGVzQnlJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogc2luY2UgdmVyc2lvbiAzLjQsIGdldFNlbGVjdGVkTm9kZXNCeUlkIG5vIGxvbmdlciBleGlzdHMsIHVzZSBnZXRTZWxlY3RlZE5vZGVzKCkgaW5zdGVhZCcpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gdW5zb3J0ZWQgbGlzdCBvZiBzZWxlY3RlZCBub2Rlcy5cbiAgICAgKiBHZXR0aW5nIHRoZSB1bmRlcmx5aW5nIG5vZGUgKHJhdGhlciB0aGFuIHRoZSBkYXRhKSBpcyB1c2VmdWwgd2hlbiB3b3JraW5nIHdpdGggdHJlZSAvIGFnZ3JlZ2F0ZWQgZGF0YSxcbiAgICAgKiBhcyB0aGUgbm9kZSBjYW4gYmUgdHJhdmVyc2VkLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFNlbGVjdGVkTm9kZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGlvblNlcnZpY2UuZ2V0U2VsZWN0ZWROb2RlcygpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgYW4gdW5zb3J0ZWQgbGlzdCBvZiBzZWxlY3RlZCByb3dzIChpLmUuIHJvdyBkYXRhIHRoYXQgeW91IHByb3ZpZGVkKS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRTZWxlY3RlZFJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGlvblNlcnZpY2UuZ2V0U2VsZWN0ZWRSb3dzKCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgbGlzdCBvZiBhbGwgc2VsZWN0ZWQgbm9kZXMgYXQgJ2Jlc3QgY29zdCcsIGEgZmVhdHVyZSB0byBiZSB1c2VkIHdpdGggZ3JvdXBzIC8gdHJlZXMuXG4gICAgICogSWYgYSBncm91cCBoYXMgYWxsIGl0cyBjaGlsZHJlbiBzZWxlY3RlZCwgdGhlbiB0aGUgZ3JvdXAgYXBwZWFycyBpbiB0aGUgcmVzdWx0LCBidXQgbm90IHRoZSBjaGlsZHJlbi5cbiAgICAgKiBEZXNpZ25lZCBmb3IgdXNlIHdpdGggYCdjaGlsZHJlbidgIGFzIHRoZSBncm91cCBzZWxlY3Rpb24gdHlwZSwgd2hlcmUgZ3JvdXBzIGRvbid0IGFjdHVhbGx5IGFwcGVhciBpbiB0aGUgc2VsZWN0aW9uIG5vcm1hbGx5LlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldEJlc3RDb3N0Tm9kZVNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uU2VydmljZS5nZXRCZXN0Q29zdE5vZGVTZWxlY3Rpb24oKTtcbiAgICB9O1xuICAgIC8qKiBSZXRyaWV2ZSByZW5kZXJlZCBub2Rlcy4gRHVlIHRvIHZpcnR1YWxpc2F0aW9uIHRoaXMgd2lsbCBjb250YWluIG9ubHkgdGhlIGN1cnJlbnQgdmlzaWJsZSByb3dzIGFuZCB0aG9zZSBpbiB0aGUgYnVmZmVyLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFJlbmRlcmVkTm9kZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd1JlbmRlcmVyLmdldFJlbmRlcmVkTm9kZXMoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBlbnN1cmVDb2xJbmRleFZpc2libGUoaW5kZXgpIG5vIGxvbmdlciBzdXBwb3J0ZWQsIHVzZSBlbnN1cmVDb2x1bW5WaXNpYmxlKGNvbEtleSkgaW5zdGVhZC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5lbnN1cmVDb2xJbmRleFZpc2libGUgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBlbnN1cmVDb2xJbmRleFZpc2libGUoaW5kZXgpIG5vIGxvbmdlciBzdXBwb3J0ZWQsIHVzZSBlbnN1cmVDb2x1bW5WaXNpYmxlKGNvbEtleSkgaW5zdGVhZC4nKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBFbnN1cmVzIHRoZSBjb2x1bW4gaXMgdmlzaWJsZSBieSBzY3JvbGxpbmcgdGhlIHRhYmxlIGlmIG5lZWRlZC5cbiAgICAgKlxuICAgICAqIFRoaXMgd2lsbCBoYXZlIG5vIGVmZmVjdCBiZWZvcmUgdGhlIGZpcnN0RGF0YVJlbmRlcmVkIGV2ZW50IGhhcyBmaXJlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBrZXkgLSBUaGUgY29sdW1uIHRvIGVuc3VyZSB2aXNpYmxlXG4gICAgICogQHBhcmFtIHBvc2l0aW9uIC0gV2hlcmUgdGhlIGNvbHVtbiB3aWxsIGJlIHBvc2l0aW9uZWQuXG4gICAgICogLSBgYXV0b2AgLSBTY3JvbGxzIHRoZSBtaW5pbXVtIGFtb3VudCB0byBtYWtlIHN1cmUgdGhlIGNvbHVtbiBpcyB2aXNpYmxlLlxuICAgICAqIC0gYHN0YXJ0YCAtIFNjcm9sbHMgdGhlIGNvbHVtbiB0byB0aGUgc3RhcnQgb2YgdGhlIHZpZXdwb3J0LlxuICAgICAqIC0gYG1pZGRsZWAgLSBTY3JvbGxzIHRoZSBjb2x1bW4gdG8gdGhlIG1pZGRsZSBvZiB0aGUgdmlld3BvcnQuXG4gICAgICogLSBgZW5kYCAtIFNjcm9sbHMgdGhlIGNvbHVtbiB0byB0aGUgZW5kIG9mIHRoZSB2aWV3cG9ydC5cbiAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmVuc3VyZUNvbHVtblZpc2libGUgPSBmdW5jdGlvbiAoa2V5LCBwb3NpdGlvbikge1xuICAgICAgICBpZiAocG9zaXRpb24gPT09IHZvaWQgMCkgeyBwb3NpdGlvbiA9ICdhdXRvJzsgfVxuICAgICAgICB0aGlzLmdyaWRCb2R5Q3RybC5nZXRTY3JvbGxGZWF0dXJlKCkuZW5zdXJlQ29sdW1uVmlzaWJsZShrZXksIHBvc2l0aW9uKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFZlcnRpY2FsbHkgc2Nyb2xscyB0aGUgZ3JpZCB1bnRpbCB0aGUgcHJvdmlkZWQgcm93IGluZGV4IGlzIGluc2lkZSB0aGUgdmlzaWJsZSB2aWV3cG9ydC5cbiAgICAgKiBJZiBhIHBvc2l0aW9uIGlzIHByb3ZpZGVkLCB0aGUgZ3JpZCB3aWxsIGF0dGVtcHQgdG8gc2Nyb2xsIHVudGlsIHRoZSByb3cgaXMgYXQgdGhlIGdpdmVuIHBvc2l0aW9uIHdpdGhpbiB0aGUgdmlld3BvcnQuXG4gICAgICogVGhpcyB3aWxsIGhhdmUgbm8gZWZmZWN0IGJlZm9yZSB0aGUgZmlyc3REYXRhUmVuZGVyZWQgZXZlbnQgaGFzIGZpcmVkLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmVuc3VyZUluZGV4VmlzaWJsZSA9IGZ1bmN0aW9uIChpbmRleCwgcG9zaXRpb24pIHtcbiAgICAgICAgdGhpcy5ncmlkQm9keUN0cmwuZ2V0U2Nyb2xsRmVhdHVyZSgpLmVuc3VyZUluZGV4VmlzaWJsZShpbmRleCwgcG9zaXRpb24pO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogVmVydGljYWxseSBzY3JvbGxzIHRoZSBncmlkIHVudGlsIHRoZSBwcm92aWRlZCByb3cgKG9yIGEgcm93IG1hdGNoaW5nIHRoZSBwcm92aWRlZCBjb21wYXJhdG9yKSBpcyBpbnNpZGUgdGhlIHZpc2libGUgdmlld3BvcnQuXG4gICAgICogSWYgYSBwb3NpdGlvbiBpcyBwcm92aWRlZCwgdGhlIGdyaWQgd2lsbCBhdHRlbXB0IHRvIHNjcm9sbCB1bnRpbCB0aGUgcm93IGlzIGF0IHRoZSBnaXZlbiBwb3NpdGlvbiB3aXRoaW4gdGhlIHZpZXdwb3J0LlxuICAgICAqIFRoaXMgd2lsbCBoYXZlIG5vIGVmZmVjdCBiZWZvcmUgdGhlIGZpcnN0RGF0YVJlbmRlcmVkIGV2ZW50IGhhcyBmaXJlZC5cbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5lbnN1cmVOb2RlVmlzaWJsZSA9IGZ1bmN0aW9uIChub2RlU2VsZWN0b3IsIHBvc2l0aW9uKSB7XG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gdm9pZCAwKSB7IHBvc2l0aW9uID0gbnVsbDsgfVxuICAgICAgICB0aGlzLmdyaWRCb2R5Q3RybC5nZXRTY3JvbGxGZWF0dXJlKCkuZW5zdXJlTm9kZVZpc2libGUobm9kZVNlbGVjdG9yLCBwb3NpdGlvbik7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBTaW1pbGFyIHRvIGBmb3JFYWNoTm9kZWAsIGV4Y2VwdCBsaXN0cyBhbGwgdGhlIGxlYWYgbm9kZXMuXG4gICAgICogVGhpcyBlZmZlY3RpdmVseSBnb2VzIHRocm91Z2ggYWxsIHRoZSBkYXRhIHRoYXQgeW91IHByb3ZpZGVkIHRvIHRoZSBncmlkIGJlZm9yZSB0aGUgZ3JpZCBwZXJmb3JtZWQgYW55IGdyb3VwaW5nLlxuICAgICAqIElmIHVzaW5nIHRyZWUgZGF0YSwgZ29lcyB0aHJvdWdoIGFsbCB0aGUgbm9kZXMgZm9yIHRoZSBkYXRhIHlvdSBwcm92aWRlZCwgaW5jbHVkaW5nIG5vZGVzIHRoYXQgaGF2ZSBjaGlsZHJlbixcbiAgICAgKiBidXQgZXhjbHVkaW5nIGdyb3VwcyB0aGUgZ3JpZCBjcmVhdGVkIHdoZXJlIGdhcHMgd2VyZSBtaXNzaW5nIGluIHRoZSBoaWVyYXJjaHkuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZm9yRWFjaExlYWZOb2RlID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIGlmIChtaXNzaW5nKHRoaXMuY2xpZW50U2lkZVJvd01vZGVsKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdjYW5ub3QgY2FsbCBmb3JFYWNoTm9kZSB1bmxlc3MgdXNpbmcgbm9ybWFsIHJvdyBtb2RlbCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmZvckVhY2hMZWFmTm9kZShjYWxsYmFjayk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyB0aHJvdWdoIGVhY2ggbm9kZSAocm93KSBpbiB0aGUgZ3JpZCBhbmQgY2FsbHMgdGhlIGNhbGxiYWNrIGZvciBlYWNoIG5vZGUuXG4gICAgICogVGhpcyB3b3JrcyBzaW1pbGFyIHRvIHRoZSBgZm9yRWFjaGAgbWV0aG9kIG9uIGEgSmF2YVNjcmlwdCBhcnJheS5cbiAgICAgKiBUaGlzIGlzIGNhbGxlZCBmb3IgZXZlcnkgbm9kZSwgaWdub3JpbmcgYW55IGZpbHRlcmluZyBvciBzb3J0aW5nIGFwcGxpZWQgd2l0aGluIHRoZSBncmlkLlxuICAgICAqIElmIHVzaW5nIHRoZSBJbmZpbml0ZSBSb3cgTW9kZWwsIHRoZW4gdGhpcyBnZXRzIGNhbGxlZCBmb3IgZWFjaCBwYWdlIGxvYWRlZCBpbiB0aGUgcGFnZSBjYWNoZS5cbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5mb3JFYWNoTm9kZSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICB0aGlzLnJvd01vZGVsLmZvckVhY2hOb2RlKGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKiBTaW1pbGFyIHRvIGBmb3JFYWNoTm9kZWAsIGV4Y2VwdCBza2lwcyBhbnkgZmlsdGVyZWQgb3V0IGRhdGEuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZm9yRWFjaE5vZGVBZnRlckZpbHRlciA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICBpZiAobWlzc2luZyh0aGlzLmNsaWVudFNpZGVSb3dNb2RlbCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignY2Fubm90IGNhbGwgZm9yRWFjaE5vZGVBZnRlckZpbHRlciB1bmxlc3MgdXNpbmcgbm9ybWFsIHJvdyBtb2RlbCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmZvckVhY2hOb2RlQWZ0ZXJGaWx0ZXIoY2FsbGJhY2spO1xuICAgIH07XG4gICAgLyoqIFNpbWlsYXIgdG8gYGZvckVhY2hOb2RlQWZ0ZXJGaWx0ZXJgLCBleGNlcHQgdGhlIGNhbGxiYWNrcyBhcmUgY2FsbGVkIGluIHRoZSBvcmRlciB0aGUgcm93cyBhcmUgZGlzcGxheWVkIGluIHRoZSBncmlkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmZvckVhY2hOb2RlQWZ0ZXJGaWx0ZXJBbmRTb3J0ID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIGlmIChtaXNzaW5nKHRoaXMuY2xpZW50U2lkZVJvd01vZGVsKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdjYW5ub3QgY2FsbCBmb3JFYWNoTm9kZUFmdGVyRmlsdGVyQW5kU29ydCB1bmxlc3MgdXNpbmcgbm9ybWFsIHJvdyBtb2RlbCcpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmZvckVhY2hOb2RlQWZ0ZXJGaWx0ZXJBbmRTb3J0KGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGZpbHRlciBjb21wb25lbnQgaW5zdGFuY2UgZm9yIGEgY29sdW1uLlxuICAgICAqIGBrZXlgIGNhbiBiZSBhIHN0cmluZyBmaWVsZCBuYW1lIG9yIGEgQ29sRGVmIG9iamVjdCAobWF0Y2hlcyBvbiBvYmplY3QgcmVmZXJlbmNlLCB1c2VmdWwgaWYgZmllbGQgbmFtZXMgYXJlIG5vdCB1bmlxdWUpLlxuICAgICAqIElmIHlvdXIgZmlsdGVyIGlzIGNyZWF0ZWQgYXN5bmNocm9ub3VzbHksIGBnZXRGaWx0ZXJJbnN0YW5jZWAgd2lsbCByZXR1cm4gYG51bGxgIHNvIHlvdSB3aWxsIG5lZWQgdG8gdXNlIHRoZSBgY2FsbGJhY2tgIHRvIGFjY2VzcyB0aGUgZmlsdGVyIGluc3RhbmNlIGluc3RlYWQuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0RmlsdGVySW5zdGFuY2UgPSBmdW5jdGlvbiAoa2V5LCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgcmVzID0gdGhpcy5nZXRGaWx0ZXJJbnN0YW5jZUltcGwoa2V5LCBmdW5jdGlvbiAoaW5zdGFuY2UpIHtcbiAgICAgICAgICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgdW53cmFwcGVkID0gdW53cmFwVXNlckNvbXAoaW5zdGFuY2UpO1xuICAgICAgICAgICAgY2FsbGJhY2sodW53cmFwcGVkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciB1bndyYXBwZWQgPSB1bndyYXBVc2VyQ29tcChyZXMpO1xuICAgICAgICByZXR1cm4gdW53cmFwcGVkO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0RmlsdGVySW5zdGFuY2VJbXBsID0gZnVuY3Rpb24gKGtleSwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0UHJpbWFyeUNvbHVtbihrZXkpO1xuICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmlsdGVyUHJvbWlzZSA9IHRoaXMuZmlsdGVyTWFuYWdlci5nZXRGaWx0ZXJDb21wb25lbnQoY29sdW1uLCAnTk9fVUknKTtcbiAgICAgICAgdmFyIGN1cnJlbnRWYWx1ZSA9IGZpbHRlclByb21pc2UgJiYgZmlsdGVyUHJvbWlzZS5yZXNvbHZlTm93KG51bGwsIGZ1bmN0aW9uIChmaWx0ZXJDb21wKSB7IHJldHVybiBmaWx0ZXJDb21wOyB9KTtcbiAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgICAgc2V0VGltZW91dChjYWxsYmFjaywgMCwgY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChmaWx0ZXJQcm9taXNlKSB7XG4gICAgICAgICAgICBmaWx0ZXJQcm9taXNlLnRoZW4oZnVuY3Rpb24gKGNvbXApIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhjb21wKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjdXJyZW50VmFsdWU7XG4gICAgfTtcbiAgICAvKiogRGVzdHJveXMgYSBmaWx0ZXIuIFVzZWZ1bCB0byBmb3JjZSBhIHBhcnRpY3VsYXIgZmlsdGVyIHRvIGJlIGNyZWF0ZWQgZnJvbSBzY3JhdGNoIGFnYWluLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmRlc3Ryb3lGaWx0ZXIgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldFByaW1hcnlDb2x1bW4oa2V5KTtcbiAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyTWFuYWdlci5kZXN0cm95RmlsdGVyKGNvbHVtbiwgXCJmaWx0ZXJEZXN0cm95ZWRcIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBHZXRzIHRoZSBzdGF0dXMgcGFuZWwgaW5zdGFuY2UgY29ycmVzcG9uZGluZyB0byB0aGUgc3VwcGxpZWQgYGlkYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRTdGF0dXNQYW5lbCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXR1c0JhclNlcnZpY2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tcCA9IHRoaXMuc3RhdHVzQmFyU2VydmljZS5nZXRTdGF0dXNQYW5lbChrZXkpO1xuICAgICAgICByZXR1cm4gdW53cmFwVXNlckNvbXAoY29tcCk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRDb2x1bW5EZWYgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldFByaW1hcnlDb2x1bW4oa2V5KTtcbiAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgY29sdW1uIGRlZmluaXRpb25zLlxuICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0Q29sdW1uRGVmcyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0Q29sdW1uRGVmcygpOyB9O1xuICAgIC8qKiBJbmZvcm1zIHRoZSBncmlkIHRoYXQgYSBmaWx0ZXIgaGFzIGNoYW5nZWQuIFRoaXMgaXMgdHlwaWNhbGx5IGNhbGxlZCBhZnRlciBhIGZpbHRlciBjaGFuZ2UgdGhyb3VnaCBvbmUgb2YgdGhlIGZpbHRlciBBUElzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLm9uRmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5maWx0ZXJNYW5hZ2VyLm9uRmlsdGVyQ2hhbmdlZCgpO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZ3JpZCB0byBhY3QgYXMgaWYgdGhlIHNvcnQgd2FzIGNoYW5nZWQuXG4gICAgICogVXNlZnVsIGlmIHlvdSB1cGRhdGUgc29tZSB2YWx1ZXMgYW5kIHdhbnQgdG8gZ2V0IHRoZSBncmlkIHRvIHJlb3JkZXIgdGhlbSBhY2NvcmRpbmcgdG8gdGhlIG5ldyB2YWx1ZXMuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUub25Tb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zb3J0Q29udHJvbGxlci5vblNvcnRDaGFuZ2VkKCdhcGknKTtcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBzdGF0ZSBvZiBhbGwgdGhlIGFkdmFuY2VkIGZpbHRlcnMuIFByb3ZpZGUgaXQgd2l0aCB3aGF0IHlvdSBnZXQgZnJvbSBgZ2V0RmlsdGVyTW9kZWwoKWAgdG8gcmVzdG9yZSBmaWx0ZXIgc3RhdGUuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0RmlsdGVyTW9kZWwgPSBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgdGhpcy5maWx0ZXJNYW5hZ2VyLnNldEZpbHRlck1vZGVsKG1vZGVsKTtcbiAgICB9O1xuICAgIC8qKiBHZXRzIHRoZSBjdXJyZW50IHN0YXRlIG9mIGFsbCB0aGUgYWR2YW5jZWQgZmlsdGVycy4gVXNlZCBmb3Igc2F2aW5nIGZpbHRlciBzdGF0ZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRGaWx0ZXJNb2RlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyTWFuYWdlci5nZXRGaWx0ZXJNb2RlbCgpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIGZvY3VzZWQgY2VsbCAob3IgdGhlIGxhc3QgZm9jdXNlZCBjZWxsIGlmIHRoZSBncmlkIGxvc3QgZm9jdXMpLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldEZvY3VzZWRDZWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNlZENlbGwoKTtcbiAgICB9O1xuICAgIC8qKiBDbGVhcnMgdGhlIGZvY3VzZWQgY2VsbC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jbGVhckZvY3VzZWRDZWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c1NlcnZpY2UuY2xlYXJGb2N1c2VkQ2VsbCgpO1xuICAgIH07XG4gICAgLyoqIFNldHMgdGhlIGZvY3VzIHRvIHRoZSBzcGVjaWZpZWQgY2VsbC4gYHJvd1Bpbm5lZGAgY2FuIGJlIGVpdGhlciAndG9wJywgJ2JvdHRvbScgb3IgbnVsbCAoZm9yIG5vdCBwaW5uZWQpLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEZvY3VzZWRDZWxsID0gZnVuY3Rpb24gKHJvd0luZGV4LCBjb2xLZXksIHJvd1Bpbm5lZCkge1xuICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5zZXRGb2N1c2VkQ2VsbCh7IHJvd0luZGV4OiByb3dJbmRleCwgY29sdW1uOiBjb2xLZXksIHJvd1Bpbm5lZDogcm93UGlubmVkLCBmb3JjZUJyb3dzZXJGb2N1czogdHJ1ZSB9KTtcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBgc3VwcHJlc3NSb3dEcmFnYCBwcm9wZXJ0eS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRTdXBwcmVzc1Jvd0RyYWcgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfU1VQUFJFU1NfUk9XX0RSQUcsIHZhbHVlKTtcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBgc3VwcHJlc3NNb3ZlV2hlblJvd0RyYWdnaW5nYCBwcm9wZXJ0eS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRTdXBwcmVzc01vdmVXaGVuUm93RHJhZ2dpbmcgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfU1VQUFJFU1NfTU9WRV9XSEVOX1JPV19EUkFHLCB2YWx1ZSk7XG4gICAgfTtcbiAgICAvKiogU2V0cyB0aGUgYHN1cHByZXNzUm93Q2xpY2tTZWxlY3Rpb25gIHByb3BlcnR5LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFN1cHByZXNzUm93Q2xpY2tTZWxlY3Rpb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfU1VQUFJFU1NfUk9XX0NMSUNLX1NFTEVDVElPTiwgdmFsdWUpO1xuICAgIH07XG4gICAgLyoqIEFkZHMgYSBkcm9wIHpvbmUgb3V0c2lkZSBvZiB0aGUgZ3JpZCB3aGVyZSByb3dzIGNhbiBiZSBkcm9wcGVkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmFkZFJvd0Ryb3Bab25lID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB0aGlzLmdyaWRCb2R5Q3RybC5nZXRSb3dEcmFnRmVhdHVyZSgpLmFkZFJvd0Ryb3Bab25lKHBhcmFtcyk7XG4gICAgfTtcbiAgICAvKiogUmVtb3ZlcyBhbiBleHRlcm5hbCBkcm9wIHpvbmUgYWRkZWQgYnkgYGFkZFJvd0Ryb3Bab25lYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZW1vdmVSb3dEcm9wWm9uZSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIGFjdGl2ZURyb3BUYXJnZXQgPSB0aGlzLmRyYWdBbmREcm9wU2VydmljZS5maW5kRXh0ZXJuYWxab25lKHBhcmFtcyk7XG4gICAgICAgIGlmIChhY3RpdmVEcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICB0aGlzLmRyYWdBbmREcm9wU2VydmljZS5yZW1vdmVEcm9wVGFyZ2V0KGFjdGl2ZURyb3BUYXJnZXQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyB0aGUgYFJvd0Ryb3Bab25lUGFyYW1zYCB0byBiZSB1c2VkIGJ5IGFub3RoZXIgZ3JpZCdzIGBhZGRSb3dEcm9wWm9uZWAgbWV0aG9kLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFJvd0Ryb3Bab25lUGFyYW1zID0gZnVuY3Rpb24gKGV2ZW50cykge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkQm9keUN0cmwuZ2V0Um93RHJhZ0ZlYXR1cmUoKS5nZXRSb3dEcm9wWm9uZShldmVudHMpO1xuICAgIH07XG4gICAgLyoqIFNldHMgdGhlIGhlaWdodCBpbiBwaXhlbHMgZm9yIHRoZSByb3cgY29udGFpbmluZyB0aGUgY29sdW1uIGxhYmVsIGhlYWRlci4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRIZWFkZXJIZWlnaHQgPSBmdW5jdGlvbiAoaGVhZGVySGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0hFQURFUl9IRUlHSFQsIGhlYWRlckhlaWdodCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBTd2l0Y2ggYmV0d2VlbiBsYXlvdXQgb3B0aW9uczogYG5vcm1hbGAsIGBhdXRvSGVpZ2h0YCwgYHByaW50YC5cbiAgICAgKiBEZWZhdWx0cyB0byBgbm9ybWFsYCBpZiBubyBkb21MYXlvdXQgcHJvdmlkZWQuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0RG9tTGF5b3V0ID0gZnVuY3Rpb24gKGRvbUxheW91dCkge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET01fTEFZT1VULCBkb21MYXlvdXQpO1xuICAgIH07XG4gICAgLyoqIFNldHMgdGhlIGBlbmFibGVDZWxsVGV4dFNlbGVjdGlvbmAgcHJvcGVydHkuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0RW5hYmxlQ2VsbFRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoc2VsZWN0YWJsZSkge1xuICAgICAgICB0aGlzLmdyaWRCb2R5Q3RybC5zZXRDZWxsVGV4dFNlbGVjdGlvbihzZWxlY3RhYmxlKTtcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBwcmVmZXJyZWQgZGlyZWN0aW9uIGZvciB0aGUgc2VsZWN0aW9uIGZpbGwgaGFuZGxlLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEZpbGxIYW5kbGVEaXJlY3Rpb24gPSBmdW5jdGlvbiAoZGlyZWN0aW9uKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0ZJTExfSEFORExFX0RJUkVDVElPTiwgZGlyZWN0aW9uKTtcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBoZWlnaHQgaW4gcGl4ZWxzIGZvciB0aGUgcm93cyBjb250YWluaW5nIGhlYWRlciBjb2x1bW4gZ3JvdXBzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEdyb3VwSGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKGhlYWRlckhlaWdodCkge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9IRUFERVJfSEVJR0hULCBoZWFkZXJIZWlnaHQpO1xuICAgIH07XG4gICAgLyoqIFNldHMgdGhlIGhlaWdodCBpbiBwaXhlbHMgZm9yIHRoZSByb3cgY29udGFpbmluZyB0aGUgZmxvYXRpbmcgZmlsdGVycy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRGbG9hdGluZ0ZpbHRlcnNIZWlnaHQgPSBmdW5jdGlvbiAoaGVhZGVySGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0ZMT0FUSU5HX0ZJTFRFUlNfSEVJR0hULCBoZWFkZXJIZWlnaHQpO1xuICAgIH07XG4gICAgLyoqIFNldHMgdGhlIGhlaWdodCBpbiBwaXhlbHMgZm9yIHRoZSByb3cgY29udGFpbmluZyB0aGUgY29sdW1ucyB3aGVuIGluIHBpdm90IG1vZGUuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0UGl2b3RIZWFkZXJIZWlnaHQgPSBmdW5jdGlvbiAoaGVhZGVySGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1BJVk9UX0hFQURFUl9IRUlHSFQsIGhlYWRlckhlaWdodCk7XG4gICAgfTtcbiAgICAvKiogU2V0cyB0aGUgaGVpZ2h0IGluIHBpeGVscyBmb3IgdGhlIHJvdyBjb250YWluaW5nIGhlYWRlciBjb2x1bW4gZ3JvdXBzIHdoZW4gaW4gcGl2b3QgbW9kZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRQaXZvdEdyb3VwSGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKGhlYWRlckhlaWdodCkge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QSVZPVF9HUk9VUF9IRUFERVJfSEVJR0hULCBoZWFkZXJIZWlnaHQpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0SXNFeHRlcm5hbEZpbHRlclByZXNlbnQgPSBmdW5jdGlvbiAoaXNFeHRlcm5hbEZpbHRlclByZXNlbnRGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0lTX0VYVEVSTkFMX0ZJTFRFUl9QUkVTRU5ULCBpc0V4dGVybmFsRmlsdGVyUHJlc2VudEZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0RG9lc0V4dGVybmFsRmlsdGVyUGFzcyA9IGZ1bmN0aW9uIChkb2VzRXh0ZXJuYWxGaWx0ZXJQYXNzRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET0VTX0VYVEVSTkFMX0ZJTFRFUl9QQVNTLCBkb2VzRXh0ZXJuYWxGaWx0ZXJQYXNzRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXROYXZpZ2F0ZVRvTmV4dENlbGwgPSBmdW5jdGlvbiAobmF2aWdhdGVUb05leHRDZWxsRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9OQVZJR0FURV9UT19ORVhUX0NFTEwsIG5hdmlnYXRlVG9OZXh0Q2VsbEZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0VGFiVG9OZXh0Q2VsbCA9IGZ1bmN0aW9uICh0YWJUb05leHRDZWxsRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9UQUJfVE9fTkVYVF9DRUxMLCB0YWJUb05leHRDZWxsRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRUYWJUb05leHRIZWFkZXIgPSBmdW5jdGlvbiAodGFiVG9OZXh0SGVhZGVyRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9UQUJfVE9fTkVYVF9IRUFERVIsIHRhYlRvTmV4dEhlYWRlckZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0TmF2aWdhdGVUb05leHRIZWFkZXIgPSBmdW5jdGlvbiAobmF2aWdhdGVUb05leHRIZWFkZXJGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX05BVklHQVRFX1RPX05FWFRfSEVBREVSLCBuYXZpZ2F0ZVRvTmV4dEhlYWRlckZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0R3JvdXBSb3dBZ2dOb2RlcyA9IGZ1bmN0aW9uIChncm91cFJvd0FnZ05vZGVzRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9ST1dfQUdHX05PREVTLCBncm91cFJvd0FnZ05vZGVzRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRHcm91cFJvd0FnZyA9IGZ1bmN0aW9uIChnZXRHcm91cFJvd0FnZ0Z1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX0dST1VQX1JPV19BR0csIGdldEdyb3VwUm93QWdnRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRCdXNpbmVzc0tleUZvck5vZGUgPSBmdW5jdGlvbiAoZ2V0QnVzaW5lc3NLZXlGb3JOb2RlRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HRVRfQlVTSU5FU1NfS0VZX0ZPUl9OT0RFLCBnZXRCdXNpbmVzc0tleUZvck5vZGVGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEdldENoaWxkQ291bnQgPSBmdW5jdGlvbiAoZ2V0Q2hpbGRDb3VudEZ1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX0NISUxEX0NPVU5ULCBnZXRDaGlsZENvdW50RnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRQcm9jZXNzUm93UG9zdENyZWF0ZSA9IGZ1bmN0aW9uIChwcm9jZXNzUm93UG9zdENyZWF0ZUZ1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUFJPQ0VTU19ST1dfUE9TVF9DUkVBVEUsIHByb2Nlc3NSb3dQb3N0Q3JlYXRlRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRSb3dOb2RlSWQgPSBmdW5jdGlvbiAoZ2V0Um93Tm9kZUlkRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HRVRfUk9XX05PREVfSUQsIGdldFJvd05vZGVJZEZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0R2V0Um93SWQgPSBmdW5jdGlvbiAoZ2V0Um93SWRGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9ST1dfSUQsIGdldFJvd0lkRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRSb3dDbGFzcyA9IGZ1bmN0aW9uIChyb3dDbGFzc0Z1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1JPV19DTEFTUywgcm93Q2xhc3NGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldElzRnVsbFdpZHRoQ2VsbCA9IGZ1bmN0aW9uIChpc0Z1bGxXaWR0aENlbGxGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0lTX0ZVTExfV0lEVEhfQ0VMTCwgaXNGdWxsV2lkdGhDZWxsRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRJc0Z1bGxXaWR0aFJvdyA9IGZ1bmN0aW9uIChpc0Z1bGxXaWR0aFJvd0Z1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfSVNfRlVMTF9XSURUSF9ST1csIGlzRnVsbFdpZHRoUm93RnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRJc1Jvd1NlbGVjdGFibGUgPSBmdW5jdGlvbiAoaXNSb3dTZWxlY3RhYmxlRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19ST1dfU0VMRUNUQUJMRSwgaXNSb3dTZWxlY3RhYmxlRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRJc1Jvd01hc3RlciA9IGZ1bmN0aW9uIChpc1Jvd01hc3RlckZ1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfSVNfUk9XX01BU1RFUiwgaXNSb3dNYXN0ZXJGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFBvc3RTb3J0ID0gZnVuY3Rpb24gKHBvc3RTb3J0RnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QT1NUX1NPUlQsIHBvc3RTb3J0RnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRQb3N0U29ydFJvd3MgPSBmdW5jdGlvbiAocG9zdFNvcnRSb3dzRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QT1NUX1NPUlRfUk9XUywgcG9zdFNvcnRSb3dzRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXREb2N1bWVudCA9IGZ1bmN0aW9uIChnZXREb2N1bWVudEZ1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX0RPQ1VNRU5ULCBnZXREb2N1bWVudEZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0R2V0Q29udGV4dE1lbnVJdGVtcyA9IGZ1bmN0aW9uIChnZXRDb250ZXh0TWVudUl0ZW1zRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HRVRfQ09OVEVYVF9NRU5VX0lURU1TLCBnZXRDb250ZXh0TWVudUl0ZW1zRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRNYWluTWVudUl0ZW1zID0gZnVuY3Rpb24gKGdldE1haW5NZW51SXRlbXNGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9NQUlOX01FTlVfSVRFTVMsIGdldE1haW5NZW51SXRlbXNGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFByb2Nlc3NDZWxsRm9yQ2xpcGJvYXJkID0gZnVuY3Rpb24gKHByb2Nlc3NDZWxsRm9yQ2xpcGJvYXJkRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QUk9DRVNTX0NFTExfRk9SX0NMSVBCT0FSRCwgcHJvY2Vzc0NlbGxGb3JDbGlwYm9hcmRGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFNlbmRUb0NsaXBib2FyZCA9IGZ1bmN0aW9uIChzZW5kVG9DbGlwYm9hcmRGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1NFTkRfVE9fQ0xJUEJPQVJELCBzZW5kVG9DbGlwYm9hcmRGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFByb2Nlc3NDZWxsRnJvbUNsaXBib2FyZCA9IGZ1bmN0aW9uIChwcm9jZXNzQ2VsbEZyb21DbGlwYm9hcmRGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1BST0NFU1NfQ0VMTF9GUk9NX0NMSVBCT0FSRCwgcHJvY2Vzc0NlbGxGcm9tQ2xpcGJvYXJkRnVuYyk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgdXNlIGBzZXRQcm9jZXNzUGl2b3RSZXN1bHRDb2xEZWZgIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRQcm9jZXNzU2Vjb25kYXJ5Q29sRGVmID0gZnVuY3Rpb24gKHByb2Nlc3NTZWNvbmRhcnlDb2xEZWZGdW5jKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdmVyc2lvbiAyOC4wLnggc2V0UHJvY2Vzc1NlY29uZGFyeUNvbERlZiBoYXMgYmVlbiByZW5hbWVkLCBwbGVhc2UgdXNlIHNldFByb2Nlc3NQaXZvdFJlc3VsdENvbERlZiBpbnN0ZWFkJyk7XG4gICAgICAgIHRoaXMuc2V0UHJvY2Vzc1Bpdm90UmVzdWx0Q29sRGVmKHByb2Nlc3NTZWNvbmRhcnlDb2xEZWZGdW5jKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCB1c2UgYHNldFByb2Nlc3NQaXZvdFJlc3VsdENvbEdyb3VwRGVmYCBpbnN0ZWFkICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0UHJvY2Vzc1NlY29uZGFyeUNvbEdyb3VwRGVmID0gZnVuY3Rpb24gKHByb2Nlc3NTZWNvbmRhcnlDb2xHcm91cERlZkZ1bmMpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2ZXJzaW9uIDI4LjAueCBzZXRQcm9jZXNzU2Vjb25kYXJ5Q29sR3JvdXBEZWYgaGFzIGJlZW4gcmVuYW1lZCwgcGxlYXNlIHVzZSBzZXRQcm9jZXNzUGl2b3RSZXN1bHRDb2xHcm91cERlZiBpbnN0ZWFkJyk7XG4gICAgICAgIHRoaXMuc2V0UHJvY2Vzc1Bpdm90UmVzdWx0Q29sR3JvdXBEZWYocHJvY2Vzc1NlY29uZGFyeUNvbEdyb3VwRGVmRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRQcm9jZXNzUGl2b3RSZXN1bHRDb2xEZWYgPSBmdW5jdGlvbiAocHJvY2Vzc1Bpdm90UmVzdWx0Q29sRGVmRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QUk9DRVNTX1BJVk9UX1JFU1VMVF9DT0xfREVGLCBwcm9jZXNzUGl2b3RSZXN1bHRDb2xEZWZGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldFByb2Nlc3NQaXZvdFJlc3VsdENvbEdyb3VwRGVmID0gZnVuY3Rpb24gKHByb2Nlc3NQaXZvdFJlc3VsdENvbEdyb3VwRGVmRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QUk9DRVNTX1BJVk9UX1JFU1VMVF9DT0xfR1JPVVBfREVGLCBwcm9jZXNzUGl2b3RSZXN1bHRDb2xHcm91cERlZkZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0UG9zdFByb2Nlc3NQb3B1cCA9IGZ1bmN0aW9uIChwb3N0UHJvY2Vzc1BvcHVwRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QT1NUX1BST0NFU1NfUE9QVVAsIHBvc3RQcm9jZXNzUG9wdXBGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldERlZmF1bHRHcm91cE9yZGVyQ29tcGFyYXRvciA9IGZ1bmN0aW9uIChkZWZhdWx0R3JvdXBPcmRlckNvbXBhcmF0b3JGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0RFRkFVTFRfR1JPVVBfT1JERVJfQ09NUEFSQVRPUiwgZGVmYXVsdEdyb3VwT3JkZXJDb21wYXJhdG9yRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRJbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3IgPSBmdW5jdGlvbiAoaW5pdGlhbEdyb3VwT3JkZXJDb21wYXJhdG9yRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JTklUSUFMX0dST1VQX09SREVSX0NPTVBBUkFUT1IsIGluaXRpYWxHcm91cE9yZGVyQ29tcGFyYXRvckZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0R2V0Q2hhcnRUb29sYmFySXRlbXMgPSBmdW5jdGlvbiAoZ2V0Q2hhcnRUb29sYmFySXRlbXNGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9DSEFSVF9UT09MQkFSX0lURU1TLCBnZXRDaGFydFRvb2xiYXJJdGVtc0Z1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0UGFnaW5hdGlvbk51bWJlckZvcm1hdHRlciA9IGZ1bmN0aW9uIChwYWdpbmF0aW9uTnVtYmVyRm9ybWF0dGVyRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QQUdJTkFUSU9OX05VTUJFUl9GT1JNQVRURVIsIHBhZ2luYXRpb25OdW1iZXJGb3JtYXR0ZXJGdW5jKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCB1c2Ugc2V0R2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxQYXJhbXMgaW5zdGVhZCAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEdldFNlcnZlclNpZGVTdG9yZVBhcmFtcyA9IGZ1bmN0aW9uIChnZXRTZXJ2ZXJTaWRlU3RvcmVQYXJhbXNGdW5jKSB7XG4gICAgICAgIHRoaXMuc2V0R2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxQYXJhbXMoZ2V0U2VydmVyU2lkZVN0b3JlUGFyYW1zRnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFBhcmFtcyA9IGZ1bmN0aW9uIChnZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFBhcmFtc0Z1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1NFUlZFUl9TSURFX0dST1VQX1BBUkFNUywgZ2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxQYXJhbXNGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldElzU2VydmVyU2lkZUdyb3VwT3BlbkJ5RGVmYXVsdCA9IGZ1bmN0aW9uIChpc1NlcnZlclNpZGVHcm91cE9wZW5CeURlZmF1bHRGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0lTX1NFUlZFUl9TSURFX0dST1VQU19PUEVOX0JZX0RFRkFVTFQsIGlzU2VydmVyU2lkZUdyb3VwT3BlbkJ5RGVmYXVsdEZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0SXNBcHBseVNlcnZlclNpZGVUcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIChpc0FwcGx5U2VydmVyU2lkZVRyYW5zYWN0aW9uRnVuYykge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9JU19BUFBMWV9TRVJWRVJfU0lERV9UUkFOU0FDVElPTiwgaXNBcHBseVNlcnZlclNpZGVUcmFuc2FjdGlvbkZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0SXNTZXJ2ZXJTaWRlR3JvdXAgPSBmdW5jdGlvbiAoaXNTZXJ2ZXJTaWRlR3JvdXBGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0lTX1NFUlZFUl9TSURFX0dST1VQLCBpc1NlcnZlclNpZGVHcm91cEZ1bmMpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0R2V0U2VydmVyU2lkZUdyb3VwS2V5ID0gZnVuY3Rpb24gKGdldFNlcnZlclNpZGVHcm91cEtleUZ1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1NFUlZFUl9TSURFX0dST1VQX0tFWSwgZ2V0U2VydmVyU2lkZUdyb3VwS2V5RnVuYyk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHZXRSb3dTdHlsZSA9IGZ1bmN0aW9uIChyb3dTdHlsZUZ1bmMpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR0VUX1JPV19TVFlMRSwgcm93U3R5bGVGdW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldEdldFJvd0hlaWdodCA9IGZ1bmN0aW9uIChyb3dIZWlnaHRGdW5jKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dFVF9ST1dfSEVJR0hULCByb3dIZWlnaHRGdW5jKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgc2lkZSBiYXIgaXMgdmlzaWJsZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5pc1NpZGVCYXJWaXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zaWRlQmFyQ29tcCA/IHRoaXMuc2lkZUJhckNvbXAuaXNEaXNwbGF5ZWQoKSA6IGZhbHNlO1xuICAgIH07XG4gICAgLyoqIFNob3cvaGlkZSB0aGUgZW50aXJlIHNpZGUgYmFyLCBpbmNsdWRpbmcgYW55IHZpc2libGUgcGFuZWwgYW5kIHRoZSB0YWIgYnV0dG9ucy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRTaWRlQmFyVmlzaWJsZSA9IGZ1bmN0aW9uIChzaG93KSB7XG4gICAgICAgIGlmICghdGhpcy5zaWRlQmFyQ29tcCkge1xuICAgICAgICAgICAgaWYgKHNob3cpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpZGVCYXIgaXMgbm90IGxvYWRlZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2lkZUJhckNvbXAuc2V0RGlzcGxheWVkKHNob3cpO1xuICAgIH07XG4gICAgLyoqIFNldHMgdGhlIHNpZGUgYmFyIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBncmlkLiBQb3NzaWJsZSB2YWx1ZXMgYXJlIGAnbGVmdCdgIG9yIGAncmlnaHQnYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRTaWRlQmFyUG9zaXRpb24gPSBmdW5jdGlvbiAocG9zaXRpb24pIHtcbiAgICAgICAgaWYgKCF0aGlzLnNpZGVCYXJDb21wKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpZGVCYXIgaXMgbm90IGxvYWRlZCcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2lkZUJhckNvbXAuc2V0U2lkZUJhclBvc2l0aW9uKHBvc2l0aW9uKTtcbiAgICB9O1xuICAgIC8qKiBPcGVucyBhIHBhcnRpY3VsYXIgdG9vbCBwYW5lbC4gUHJvdmlkZSB0aGUgSUQgb2YgdGhlIHRvb2wgcGFuZWwgdG8gb3Blbi4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5vcGVuVG9vbFBhbmVsID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoIXRoaXMuc2lkZUJhckNvbXApIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogdG9vbFBhbmVsIGlzIG9ubHkgYXZhaWxhYmxlIGluIEFHIEdyaWQgRW50ZXJwcmlzZScpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2lkZUJhckNvbXAub3BlblRvb2xQYW5lbChrZXkpO1xuICAgIH07XG4gICAgLyoqIENsb3NlcyB0aGUgY3VycmVudGx5IG9wZW4gdG9vbCBwYW5lbCAoaWYgYW55KS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jbG9zZVRvb2xQYW5lbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNpZGVCYXJDb21wKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHRvb2xQYW5lbCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBBRyBHcmlkIEVudGVycHJpc2UnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNpZGVCYXJDb21wLmNsb3NlKCk7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyB0aGUgSUQgb2YgdGhlIGN1cnJlbnRseSBzaG93biB0b29sIHBhbmVsIGlmIGFueSwgb3RoZXJ3aXNlIGBudWxsYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRPcGVuZWRUb29sUGFuZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpZGVCYXJDb21wID8gdGhpcy5zaWRlQmFyQ29tcC5vcGVuZWRJdGVtKCkgOiBudWxsO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIGN1cnJlbnQgc2lkZSBiYXIgY29uZmlndXJhdGlvbi4gSWYgYSBzaG9ydGN1dCB3YXMgdXNlZCwgcmV0dXJucyB0aGUgZGV0YWlsZWQgbG9uZyBmb3JtLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFNpZGVCYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRTaWRlQmFyKCk7XG4gICAgfTtcbiAgICAvKiogUmVzZXRzIHRoZSBzaWRlIGJhciB0byB0aGUgcHJvdmlkZWQgY29uZmlndXJhdGlvbi4gVGhlIHBhcmFtZXRlciBpcyB0aGUgc2FtZSBhcyB0aGUgc2lkZUJhciBncmlkIHByb3BlcnR5LiBUaGUgc2lkZSBiYXIgaXMgcmUtY3JlYXRlZCBmcm9tIHNjcmF0Y2ggd2l0aCB0aGUgbmV3IGNvbmZpZy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRTaWRlQmFyID0gZnVuY3Rpb24gKGRlZikge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eSgnc2lkZUJhcicsIFNpZGVCYXJEZWZQYXJzZXIucGFyc2UoZGVmKSk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRTdXBwcmVzc0NsaXBib2FyZFBhc3RlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1NVUFBSRVNTX0NMSVBCT0FSRF9QQVNURSwgdmFsdWUpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgYHRydWVgIGlmIHRoZSB0b29sIHBhbmVsIGlzIHNob3dpbmcsIG90aGVyd2lzZSBgZmFsc2VgLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzVG9vbFBhbmVsU2hvd2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2lkZUJhckNvbXAuaXNUb29sUGFuZWxTaG93aW5nKCk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZCAtIHNpbmNlIHZlcnNpb24gMjUuMSwgZG9MYXlvdXQgd2FzIHRha2VuIG91dCwgYXMgaXQncyBub3QgbmVlZGVkLiBUaGUgZ3JpZCByZXNwb25kcyB0byBncmlkIHNpemUgY2hhbmdlcyBhdXRvbWF0aWNhbGx5LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmRvTGF5b3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWVzc2FnZSA9IFwiQUcgR3JpZCAtIHNpbmNlIHZlcnNpb24gMjUuMSwgZG9MYXlvdXQgd2FzIHRha2VuIG91dCwgYXMgaXQncyBub3QgbmVlZGVkLiBUaGUgZ3JpZCByZXNwb25kcyB0byBncmlkIHNpemUgY2hhbmdlcyBhdXRvbWF0aWNhbGx5XCI7XG4gICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4obWVzc2FnZSk7IH0sICdkb0xheW91dERlcHJlY2F0ZWQnKTtcbiAgICB9O1xuICAgIC8qKiBUZWxscyB0aGUgZ3JpZCB0byByZWNhbGN1bGF0ZSB0aGUgcm93IGhlaWdodHMuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVzZXRSb3dIZWlnaHRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoZXhpc3RzKHRoaXMuY2xpZW50U2lkZVJvd01vZGVsKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29sdW1uTW9kZWwuaXNBdXRvUm93SGVpZ2h0QWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGNhbGxpbmcgZ3JpZEFwaS5yZXNldFJvd0hlaWdodHMoKSBtYWtlcyBubyBzZW5zZSB3aGVuIHVzaW5nIEF1dG8gUm93IEhlaWdodC4nKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5yZXNldFJvd0hlaWdodHMoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0R3JvdXBSZW1vdmVTaW5nbGVDaGlsZHJlbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5zZXRQcm9wZXJ0eShHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9SRU1PVkVfU0lOR0xFX0NISUxEUkVOLCB2YWx1ZSk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHcm91cFJlbW92ZUxvd2VzdFNpbmdsZUNoaWxkcmVuID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dST1VQX1JFTU9WRV9MT1dFU1RfU0lOR0xFX0NISUxEUkVOLCB2YWx1ZSk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRHcm91cERpc3BsYXlUeXBlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dST1VQX0RJU1BMQVlfVFlQRSwgdmFsdWUpO1xuICAgIH07XG4gICAgLyoqIFRlbGxzIHRoZSBncmlkIGEgcm93IGhlaWdodCBoYXMgY2hhbmdlZC4gVG8gYmUgdXNlZCBhZnRlciBjYWxsaW5nIGByb3dOb2RlLnNldFJvd0hlaWdodChuZXdIZWlnaHQpYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5vblJvd0hlaWdodENoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmNsaWVudFNpZGVSb3dNb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5jbGllbnRTaWRlUm93TW9kZWwub25Sb3dIZWlnaHRDaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuc2VydmVyU2lkZVJvd01vZGVsLm9uUm93SGVpZ2h0Q2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB2YWx1ZSBmb3IgYSBjb2x1bW4gZm9yIGEgcGFydGljdWxhciBgcm93Tm9kZWAgKHJvdykuXG4gICAgICogVGhpcyBpcyB1c2VmdWwgaWYgeW91IHdhbnQgdGhlIHJhdyB2YWx1ZSBvZiBhIGNlbGwgZS5nLiBpZiBpbXBsZW1lbnRpbmcgeW91ciBvd24gQ1NWIGV4cG9ydC5cbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uIChjb2xLZXksIHJvd05vZGUpIHtcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0UHJpbWFyeUNvbHVtbihjb2xLZXkpO1xuICAgICAgICBpZiAobWlzc2luZyhjb2x1bW4pKSB7XG4gICAgICAgICAgICBjb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldEdyaWRDb2x1bW4oY29sS2V5KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWlzc2luZyhjb2x1bW4pKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZVNlcnZpY2UuZ2V0VmFsdWUoY29sdW1uLCByb3dOb2RlKTtcbiAgICB9O1xuICAgIC8qKiBBZGQgYW4gZXZlbnQgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgYGV2ZW50VHlwZWAuIFdvcmtzIHNpbWlsYXIgdG8gYGFkZEV2ZW50TGlzdGVuZXJgIGZvciBhIGJyb3dzZXIgRE9NIGVsZW1lbnQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBhc3luYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnVzZUFzeW5jRXZlbnRzKCk7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lciwgYXN5bmMpO1xuICAgIH07XG4gICAgLyoqIEFkZCBhbiBldmVudCBsaXN0ZW5lciBmb3IgYWxsIGV2ZW50IHR5cGVzIGNvbWluZyBmcm9tIHRoZSBncmlkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmFkZEdsb2JhbExpc3RlbmVyID0gZnVuY3Rpb24gKGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBhc3luYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnVzZUFzeW5jRXZlbnRzKCk7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmFkZEdsb2JhbExpc3RlbmVyKGxpc3RlbmVyLCBhc3luYyk7XG4gICAgfTtcbiAgICAvKiogUmVtb3ZlIGFuIGV2ZW50IGxpc3RlbmVyLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgYXN5bmMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci51c2VBc3luY0V2ZW50cygpO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIsIGFzeW5jKTtcbiAgICB9O1xuICAgIC8qKiBSZW1vdmUgYSBnbG9iYWwgZXZlbnQgbGlzdGVuZXIuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVtb3ZlR2xvYmFsTGlzdGVuZXIgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGFzeW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIudXNlQXN5bmNFdmVudHMoKTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UucmVtb3ZlR2xvYmFsTGlzdGVuZXIobGlzdGVuZXIsIGFzeW5jKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmRpc3BhdGNoRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICAvKiogV2lsbCBkZXN0cm95IHRoZSBncmlkIGFuZCByZWxlYXNlIHJlc291cmNlcy4gSWYgeW91IGFyZSB1c2luZyBhIGZyYW1ld29yayB5b3UgZG8gbm90IG5lZWQgdG8gY2FsbCB0aGlzLCBhcyB0aGUgZ3JpZCBsaW5rcyBpbiB3aXRoIHRoZSBmcmFtZXdvcmsgbGlmZWN5Y2xlLiBIb3dldmVyIGlmIHlvdSBhcmUgdXNpbmcgV2ViIENvbXBvbmVudHMgb3IgbmF0aXZlIEphdmFTY3JpcHQsIHlvdSBkbyBuZWVkIHRvIGNhbGwgdGhpcywgdG8gYXZvaWQgYSBtZW1vcnkgbGVhayBpbiB5b3VyIGFwcGxpY2F0aW9uLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHRoaXMgaXMgbmVlZGVkIGFzIEdyaWRBUEkgaXMgYSBiZWFuLCBhbmQgR3JpZEFQSS5kZXN0cm95KCkgaXMgY2FsbGVkIGFzIHBhcnRcbiAgICAgICAgLy8gb2YgY29udGV4dC5kZXN0cm95KCkuIHNvIHdlIG5lZWQgdG8gc3RvcCB0aGUgaW5maW5pdGUgbG9vcC5cbiAgICAgICAgaWYgKHRoaXMuZGVzdHJveUNhbGxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVzdHJveUNhbGxlZCA9IHRydWU7XG4gICAgICAgIC8vIGRlc3Ryb3kgdGhlIFVJIGZpcnN0IChhcyB0aGV5IHVzZSB0aGUgc2VydmljZXMpXG4gICAgICAgIHZhciBncmlkQ3RybCA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRDdHJsKCk7XG4gICAgICAgIGlmIChncmlkQ3RybCkge1xuICAgICAgICAgICAgZ3JpZEN0cmwuZGVzdHJveUdyaWRVaSgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGRlc3Ryb3kgdGhlIHNlcnZpY2VzXG4gICAgICAgIHRoaXMuY29udGV4dC5kZXN0cm95KCk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jbGVhbkRvd25SZWZlcmVuY2VzVG9Bdm9pZE1lbW9yeUxlYWtJbkNhc2VBcHBsaWNhdGlvbklzS2VlcGluZ1JlZmVyZW5jZVRvRGVzdHJveWVkR3JpZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gc29tZSB1c2VycyB3ZXJlIHJhaXNpbmcgc3VwcG9ydCBpc3N1ZXMgd2l0aCByZWdhcmRzIG1lbW9yeSBsZWFrcy4gdGhlIHByb2JsZW0gd2FzIHRoZSBjdXN0b21lcnMgYXBwbGljYXRpb25zXG4gICAgICAgIC8vIHdlcmUga2VlcGluZyByZWZlcmVuY2VzIHRvIHRoZSBBUEkuIHRyeWluZyB0byBlZHVjYXRlIHRoZW0gYWxsIHdvdWxkIGJlIGRpZmZpY3VsdCwgZWFzaWVyIHRvIGp1c3QgcmVtb3ZlXG4gICAgICAgIC8vIGFsbCByZWZlcmVuY2VzIGluIHRoZSBBUEkgc28gYXQgbGVhc3QgdGhlIGNvcmUgZ3JpZCBjYW4gYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIHdhaXQgYWJvdXQgMTAwbXMgYmVmb3JlIGNsZWFyaW5nIGRvd24gdGhlIHJlZmVyZW5jZXMsIGluIGNhc2UgdXNlciBoYXMgc29tZSBjbGVhbnVwIHRvIGRvLFxuICAgICAgICAvLyBhbmQgbmVlZHMgdG8gZGVmZXJlbmNlIHRoZSBBUEkgZmlyc3RcbiAgICAgICAgc2V0VGltZW91dChyZW1vdmVBbGxSZWZlcmVuY2VzLmJpbmQod2luZG93LCB0aGlzLCAnR3JpZCBBUEknKSwgMTAwKTtcbiAgICB9O1xuICAgIEdyaWRBcGkucHJvdG90eXBlLndhcm5JZkRlc3Ryb3llZCA9IGZ1bmN0aW9uIChtZXRob2ROYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLmRlc3Ryb3lDYWxsZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IEdyaWQgQVBJIG1ldGhvZCBcIiArIG1ldGhvZE5hbWUgKyBcIiB3YXMgY2FsbGVkIG9uIGEgZ3JpZCB0aGF0IHdhcyBkZXN0cm95ZWQuXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmRlc3Ryb3lDYWxsZWQ7XG4gICAgfTtcbiAgICAvKiogUmVzZXQgdGhlIHF1aWNrIGZpbHRlciBjYWNoZSB0ZXh0IG9uIGV2ZXJ5IHJvd05vZGUuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVzZXRRdWlja0ZpbHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMud2FybklmRGVzdHJveWVkKCdyZXNldFF1aWNrRmlsdGVyJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd01vZGVsLmZvckVhY2hOb2RlKGZ1bmN0aW9uIChub2RlKSB7IHJldHVybiBub2RlLnF1aWNrRmlsdGVyQWdncmVnYXRlVGV4dCA9IG51bGw7IH0pO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IGluIHYyMC4xLngsIGFwaS5nZXRSYW5nZVNlbGVjdGlvbnMoKSBpcyBnb25lLCBwbGVhc2UgdXNlIGdldENlbGxSYW5nZXMoKSBpbnN0ZWFkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFJhbmdlU2VsZWN0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogaW4gdjIwLjEueCwgYXBpLmdldFJhbmdlU2VsZWN0aW9ucygpIGlzIGdvbmUsIHBsZWFzZSB1c2UgZ2V0Q2VsbFJhbmdlcygpIGluc3RlYWQuXFxuICAgICAgICBXZSBoYWQgdG8gY2hhbmdlIGhvdyBjZWxsIHNlbGVjdGlvbnMgd29ya3MgYSBzbWFsbCBiaXQgdG8gYWxsb3cgY2hhcnRpbmcgdG8gaW50ZWdyYXRlLiBUaGUgcmV0dXJuIHR5cGUgb2ZcXG4gICAgICAgIGdldENlbGxSYW5nZXMoKSBpcyBhIGJpdCBkaWZmZXJlbnQsIHBsZWFzZSBjaGVjayB0aGUgQUcgR3JpZCBkb2N1bWVudGF0aW9uLlwiKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyB0aGUgbGlzdCBvZiBzZWxlY3RlZCBjZWxsIHJhbmdlcy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRDZWxsUmFuZ2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yYW5nZVNlcnZpY2UpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJhbmdlU2VydmljZS5nZXRDZWxsUmFuZ2VzKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjZWxsIHJhbmdlIHNlbGVjdGlvbiBpcyBvbmx5IGF2YWlsYWJsZSBpbiBBRyBHcmlkIEVudGVycHJpc2UnKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jYW1lbENhc2VUb0h1bWFuUmVhZGFibGUgPSBmdW5jdGlvbiAoY2FtZWxDYXNlKSB7XG4gICAgICAgIHJldHVybiBjYW1lbENhc2VUb0h1bWFuVGV4dChjYW1lbENhc2UpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IEFzIG9mIHZlcnNpb24gMjEueCwgcmFuZ2Ugc2VsZWN0aW9uIGNoYW5nZWQgc2xpZ2h0bHkgdG8gYWxsb3cgY2hhcnRpbmcgaW50ZWdyYXRpb24uIFBsZWFzZSBjYWxsIGFwaS5hZGRDZWxsUmFuZ2UoKSBpbnN0ZWFkIG9mIGFwaS5hZGRSYW5nZVNlbGVjdGlvbigpICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuYWRkUmFuZ2VTZWxlY3Rpb24gPSBmdW5jdGlvbiAoZGVwcmVjYXRlZE5vTG9uZ2VyVXNlZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IEFzIG9mIHZlcnNpb24gMjEueCwgcmFuZ2Ugc2VsZWN0aW9uIGNoYW5nZWQgc2xpZ2h0bHkgdG8gYWxsb3cgY2hhcnRpbmcgaW50ZWdyYXRpb24uIFBsZWFzZSBjYWxsIGFwaS5hZGRDZWxsUmFuZ2UoKSBpbnN0ZWFkIG9mIGFwaS5hZGRSYW5nZVNlbGVjdGlvbigpJyk7XG4gICAgfTtcbiAgICAvKiogQWRkcyB0aGUgcHJvdmlkZWQgY2VsbCByYW5nZSB0byB0aGUgc2VsZWN0ZWQgcmFuZ2VzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmFkZENlbGxSYW5nZSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJhbmdlU2VydmljZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjZWxsIHJhbmdlIHNlbGVjdGlvbiBpcyBvbmx5IGF2YWlsYWJsZSBpbiBBRyBHcmlkIEVudGVycHJpc2UnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJhbmdlU2VydmljZS5hZGRDZWxsUmFuZ2UocGFyYW1zKTtcbiAgICB9O1xuICAgIC8qKiBDbGVhcnMgdGhlIHNlbGVjdGVkIHJhbmdlcy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jbGVhclJhbmdlU2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMucmFuZ2VTZXJ2aWNlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGNlbGwgcmFuZ2Ugc2VsZWN0aW9uIGlzIG9ubHkgYXZhaWxhYmxlIGluIEFHIEdyaWQgRW50ZXJwcmlzZScpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmFuZ2VTZXJ2aWNlLnJlbW92ZUFsbENlbGxSYW5nZXMoKTtcbiAgICB9O1xuICAgIC8qKiBSZXZlcnRzIHRoZSBsYXN0IGNlbGwgZWRpdC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS51bmRvQ2VsbEVkaXRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudW5kb1JlZG9TZXJ2aWNlLnVuZG8oKTtcbiAgICB9O1xuICAgIC8qKiBSZS1hcHBsaWVzIHRoZSBtb3N0IHJlY2VudGx5IHVuZG9uZSBjZWxsIGVkaXQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVkb0NlbGxFZGl0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnVuZG9SZWRvU2VydmljZS5yZWRvKCk7XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBjdXJyZW50IG51bWJlciBvZiBhdmFpbGFibGUgY2VsbCBlZGl0IHVuZG8gb3BlcmF0aW9ucy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRDdXJyZW50VW5kb1NpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVuZG9SZWRvU2VydmljZS5nZXRDdXJyZW50VW5kb1N0YWNrU2l6ZSgpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgY3VycmVudCBudW1iZXIgb2YgYXZhaWxhYmxlIGNlbGwgZWRpdCByZWRvIG9wZXJhdGlvbnMuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0Q3VycmVudFJlZG9TaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy51bmRvUmVkb1NlcnZpY2UuZ2V0Q3VycmVudFJlZG9TdGFja1NpemUoKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGEgbGlzdCBvZiBtb2RlbHMgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY2hhcnRzIHRoYXQgYXJlIGN1cnJlbnRseSByZW5kZXJlZCBmcm9tIHRoZSBncmlkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldENoYXJ0TW9kZWxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5SYW5nZVNlbGVjdGlvbk1vZHVsZSwgJ2FwaS5nZXRDaGFydE1vZGVscycpICYmXG4gICAgICAgICAgICBNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkuZ2V0Q2hhcnRNb2RlbHMnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnRTZXJ2aWNlLmdldENoYXJ0TW9kZWxzKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBgQ2hhcnRSZWZgIHVzaW5nIHRoZSBzdXBwbGllZCBgY2hhcnRJZGAuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0Q2hhcnRSZWYgPSBmdW5jdGlvbiAoY2hhcnRJZCkge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5SYW5nZVNlbGVjdGlvbk1vZHVsZSwgJ2FwaS5nZXRDaGFydFJlZicpICYmXG4gICAgICAgICAgICBNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkuZ2V0Q2hhcnRSZWYnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnRTZXJ2aWNlLmdldENoYXJ0UmVmKGNoYXJ0SWQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogUmV0dXJucyBhIHN0cmluZyBjb250YWluaW5nIHRoZSByZXF1ZXN0ZWQgZGF0YSBVUkwgd2hpY2ggY29udGFpbnMgYSByZXByZXNlbnRhdGlvbiBvZiB0aGUgY2hhcnQgaW1hZ2UuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0Q2hhcnRJbWFnZURhdGFVUkwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkuZ2V0Q2hhcnRJbWFnZURhdGFVUkwnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnRTZXJ2aWNlLmdldENoYXJ0SW1hZ2VEYXRhVVJMKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBEb3dubG9hZHMgdGhlIGNoYXJ0IGltYWdlIGluIHRoZSBicm93c2VyLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmRvd25sb2FkQ2hhcnQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkuZG93bmxvYWRDaGFydCcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGFydFNlcnZpY2UuZG93bmxvYWRDaGFydChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogT3BlbiB0aGUgQ2hhcnQgVG9vbCBQYW5lbC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5vcGVuQ2hhcnRUb29sUGFuZWwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkub3BlbkNoYXJ0VG9vbFBhbmVsJykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoYXJ0U2VydmljZS5vcGVuQ2hhcnRUb29sUGFuZWwocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqIENsb3NlIHRoZSBDaGFydCBUb29sIFBhbmVsLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmNsb3NlQ2hhcnRUb29sUGFuZWwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkuY2xvc2VDaGFydFRvb2xQYW5lbCcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGFydFNlcnZpY2UuY2xvc2VDaGFydFRvb2xQYW5lbChwYXJhbXMuY2hhcnRJZCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBVc2VkIHRvIHByb2dyYW1tYXRpY2FsbHkgY3JlYXRlIGNoYXJ0cyBmcm9tIGEgcmFuZ2UuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuY3JlYXRlUmFuZ2VDaGFydCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuUmFuZ2VTZWxlY3Rpb25Nb2R1bGUsICdhcGkuY3JlYXRlUmFuZ2VDaGFydCcpICYmXG4gICAgICAgICAgICBNb2R1bGVSZWdpc3RyeS5hc3NlcnRSZWdpc3RlcmVkKE1vZHVsZU5hbWVzLkdyaWRDaGFydHNNb2R1bGUsICdhcGkuY3JlYXRlUmFuZ2VDaGFydCcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGFydFNlcnZpY2UuY3JlYXRlUmFuZ2VDaGFydChwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogVXNlZCB0byBwcm9ncmFtbWF0aWNhbGx5IGNyZWF0ZSBjcm9zcyBmaWx0ZXIgY2hhcnRzIGZyb20gYSByYW5nZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jcmVhdGVDcm9zc0ZpbHRlckNoYXJ0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5SYW5nZVNlbGVjdGlvbk1vZHVsZSwgJ2FwaS5jcmVhdGVDcm9zc0ZpbHRlckNoYXJ0JykgJiZcbiAgICAgICAgICAgIE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuR3JpZENoYXJ0c01vZHVsZSwgJ2FwaS5jcmVhdGVDcm9zc0ZpbHRlckNoYXJ0JykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoYXJ0U2VydmljZS5jcmVhdGVDcm9zc0ZpbHRlckNoYXJ0KHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBSZXN0b3JlcyBhIGNoYXJ0IHVzaW5nIHRoZSBgQ2hhcnRNb2RlbGAgdGhhdCB3YXMgcHJldmlvdXNseSBvYnRhaW5lZCBmcm9tIGBnZXRDaGFydE1vZGVscygpYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZXN0b3JlQ2hhcnQgPSBmdW5jdGlvbiAoY2hhcnRNb2RlbCwgY2hhcnRDb250YWluZXIpIHtcbiAgICAgICAgaWYgKE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuUmFuZ2VTZWxlY3Rpb25Nb2R1bGUsICdhcGkucmVzdG9yZUNoYXJ0JykgJiZcbiAgICAgICAgICAgIE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuR3JpZENoYXJ0c01vZHVsZSwgJ2FwaS5yZXN0b3JlQ2hhcnQnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhcnRTZXJ2aWNlLnJlc3RvcmVDaGFydChjaGFydE1vZGVsLCBjaGFydENvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBVc2VkIHRvIHByb2dyYW1tYXRpY2FsbHkgY3JlYXRlIHBpdm90IGNoYXJ0cyBmcm9tIGEgZ3JpZC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jcmVhdGVQaXZvdENoYXJ0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoTW9kdWxlUmVnaXN0cnkuYXNzZXJ0UmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5SYW5nZVNlbGVjdGlvbk1vZHVsZSwgJ2FwaS5jcmVhdGVQaXZvdENoYXJ0JykgJiZcbiAgICAgICAgICAgIE1vZHVsZVJlZ2lzdHJ5LmFzc2VydFJlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuR3JpZENoYXJ0c01vZHVsZSwgJ2FwaS5jcmVhdGVQaXZvdENoYXJ0JykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoYXJ0U2VydmljZS5jcmVhdGVQaXZvdENoYXJ0KHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBDb3BpZXMgZGF0YSB0byBjbGlwYm9hcmQgYnkgZm9sbG93aW5nIHRoZSBzYW1lIHJ1bGVzIGFzIHByZXNzaW5nIEN0cmwrQy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jb3B5VG9DbGlwYm9hcmQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmICghdGhpcy5jbGlwYm9hcmRTZXJ2aWNlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGNsaXBib2FyZCBpcyBvbmx5IGF2YWlsYWJsZSBpbiBBRyBHcmlkIEVudGVycHJpc2UnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNsaXBib2FyZFNlcnZpY2UuY29weVRvQ2xpcGJvYXJkKHBhcmFtcyk7XG4gICAgfTtcbiAgICAvKiogQ29waWVzIHRoZSBzZWxlY3RlZCByb3dzIHRvIHRoZSBjbGlwYm9hcmQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuY29weVNlbGVjdGVkUm93c1RvQ2xpcGJvYXJkID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAoIXRoaXMuY2xpcGJvYXJkU2VydmljZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjbGlwYm9hcmQgaXMgb25seSBhdmFpbGFibGUgaW4gQUcgR3JpZCBFbnRlcnByaXNlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGlwYm9hcmRTZXJ2aWNlLmNvcHlTZWxlY3RlZFJvd3NUb0NsaXBib2FyZChwYXJhbXMpO1xuICAgIH07XG4gICAgLyoqIENvcGllcyB0aGUgc2VsZWN0ZWQgcmFuZ2VzIHRvIHRoZSBjbGlwYm9hcmQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuY29weVNlbGVjdGVkUmFuZ2VUb0NsaXBib2FyZCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNsaXBib2FyZFNlcnZpY2UpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogY2xpcGJvYXJkIGlzIG9ubHkgYXZhaWxhYmxlIGluIEFHIEdyaWQgRW50ZXJwcmlzZScpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpcGJvYXJkU2VydmljZS5jb3B5U2VsZWN0ZWRSYW5nZVRvQ2xpcGJvYXJkKHBhcmFtcyk7XG4gICAgfTtcbiAgICAvKiogQ29waWVzIHRoZSBzZWxlY3RlZCByYW5nZSBkb3duLCBzaW1pbGFyIHRvIGBDdHJsICsgRGAgaW4gRXhjZWwuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuY29weVNlbGVjdGVkUmFuZ2VEb3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2xpcGJvYXJkU2VydmljZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBjbGlwYm9hcmQgaXMgb25seSBhdmFpbGFibGUgaW4gQUcgR3JpZCBFbnRlcnByaXNlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGlwYm9hcmRTZXJ2aWNlLmNvcHlSYW5nZURvd24oKTtcbiAgICB9O1xuICAgIC8qKiBTaG93cyB0aGUgY29sdW1uIG1lbnUgYWZ0ZXIgYW5kIHBvc2l0aW9ucyBpdCByZWxhdGl2ZSB0byB0aGUgcHJvdmlkZWQgYnV0dG9uIGVsZW1lbnQuIFVzZSBpbiBjb25qdW5jdGlvbiB3aXRoIHlvdXIgb3duIGhlYWRlciB0ZW1wbGF0ZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zaG93Q29sdW1uTWVudUFmdGVyQnV0dG9uQ2xpY2sgPSBmdW5jdGlvbiAoY29sS2V5LCBidXR0b25FbGVtZW50KSB7XG4gICAgICAgIC8vIHVzZSBncmlkIGNvbHVtbiBzbyB3b3JrcyB3aXRoIHBpdm90IG1vZGVcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JpZENvbHVtbihjb2xLZXkpO1xuICAgICAgICB0aGlzLm1lbnVGYWN0b3J5LnNob3dNZW51QWZ0ZXJCdXR0b25DbGljayhjb2x1bW4sIGJ1dHRvbkVsZW1lbnQsICdjb2x1bW5NZW51Jyk7XG4gICAgfTtcbiAgICAvKiogU2hvd3MgdGhlIGNvbHVtbiBtZW51IGFmdGVyIGFuZCBwb3NpdGlvbnMgaXQgcmVsYXRpdmUgdG8gdGhlIG1vdXNlIGV2ZW50LiBVc2UgaW4gY29uanVuY3Rpb24gd2l0aCB5b3VyIG93biBoZWFkZXIgdGVtcGxhdGUuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2hvd0NvbHVtbk1lbnVBZnRlck1vdXNlQ2xpY2sgPSBmdW5jdGlvbiAoY29sS2V5LCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIC8vIHVzZSBncmlkIGNvbHVtbiBzbyB3b3JrcyB3aXRoIHBpdm90IG1vZGVcbiAgICAgICAgdmFyIGNvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JpZENvbHVtbihjb2xLZXkpO1xuICAgICAgICBpZiAoIWNvbHVtbikge1xuICAgICAgICAgICAgY29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5Q29sdW1uKGNvbEtleSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBjb2x1bW4gJ1wiICsgY29sS2V5ICsgXCInIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1lbnVGYWN0b3J5LnNob3dNZW51QWZ0ZXJNb3VzZUV2ZW50KGNvbHVtbiwgbW91c2VFdmVudCk7XG4gICAgfTtcbiAgICAvKiogSGlkZXMgYW55IHZpc2libGUgY29udGV4dCBtZW51IG9yIGNvbHVtbiBtZW51LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmhpZGVQb3B1cE1lbnUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGhpZGUgdGhlIGNvbnRleHQgbWVudSBpZiBpbiBlbnRlcnByaXNlXG4gICAgICAgIGlmICh0aGlzLmNvbnRleHRNZW51RmFjdG9yeSkge1xuICAgICAgICAgICAgdGhpcy5jb250ZXh0TWVudUZhY3RvcnkuaGlkZUFjdGl2ZU1lbnUoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBhbmQgaGlkZSB0aGUgY29sdW1uIG1lbnUgYWx3YXlzXG4gICAgICAgIHRoaXMubWVudUZhY3RvcnkuaGlkZUFjdGl2ZU1lbnUoKTtcbiAgICB9O1xuICAgIC8qKiBET00gZWxlbWVudCB0byB1c2UgYXMgdGhlIHBvcHVwIHBhcmVudCBmb3IgZ3JpZCBwb3B1cHMgKGNvbnRleHQgbWVudSwgY29sdW1uIG1lbnUgZXRjKS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRQb3B1cFBhcmVudCA9IGZ1bmN0aW9uIChlUG9wdXBQYXJlbnQpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUE9QVVBfUEFSRU5ULCBlUG9wdXBQYXJlbnQpO1xuICAgIH07XG4gICAgLyoqIE5hdmlnYXRlcyB0aGUgZ3JpZCBmb2N1cyB0byB0aGUgbmV4dCBjZWxsLCBhcyBpZiB0YWJiaW5nLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnRhYlRvTmV4dENlbGwgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvblNlcnZpY2UudGFiVG9OZXh0Q2VsbChmYWxzZSwgZXZlbnQpO1xuICAgIH07XG4gICAgLyoqIE5hdmlnYXRlcyB0aGUgZ3JpZCBmb2N1cyB0byB0aGUgcHJldmlvdXMgY2VsbCwgYXMgaWYgc2hpZnQtdGFiYmluZy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS50YWJUb1ByZXZpb3VzQ2VsbCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uU2VydmljZS50YWJUb05leHRDZWxsKHRydWUsIGV2ZW50KTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBsaXN0IG9mIGFjdGl2ZSBjZWxsIHJlbmRlcmVyIGluc3RhbmNlcy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRDZWxsUmVuZGVyZXJJbnN0YW5jZXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChwYXJhbXMgPT09IHZvaWQgMCkgeyBwYXJhbXMgPSB7fTsgfVxuICAgICAgICB2YXIgcmVzID0gdGhpcy5yb3dSZW5kZXJlci5nZXRDZWxsUmVuZGVyZXJJbnN0YW5jZXMocGFyYW1zKTtcbiAgICAgICAgdmFyIHVud3JhcHBlZCA9IHJlcy5tYXAodW53cmFwVXNlckNvbXApO1xuICAgICAgICByZXR1cm4gdW53cmFwcGVkO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIGxpc3Qgb2YgYWN0aXZlIGNlbGwgZWRpdG9yIGluc3RhbmNlcy4gT3B0aW9uYWxseSBwcm92aWRlIHBhcmFtZXRlcnMgdG8gcmVzdHJpY3QgdG8gY2VydGFpbiBjb2x1bW5zIC8gcm93IG5vZGVzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldENlbGxFZGl0b3JJbnN0YW5jZXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChwYXJhbXMgPT09IHZvaWQgMCkgeyBwYXJhbXMgPSB7fTsgfVxuICAgICAgICB2YXIgcmVzID0gdGhpcy5yb3dSZW5kZXJlci5nZXRDZWxsRWRpdG9ySW5zdGFuY2VzKHBhcmFtcyk7XG4gICAgICAgIHZhciB1bndyYXBwZWQgPSByZXMubWFwKHVud3JhcFVzZXJDb21wKTtcbiAgICAgICAgcmV0dXJuIHVud3JhcHBlZDtcbiAgICB9O1xuICAgIC8qKiBJZiB0aGUgZ3JpZCBpcyBlZGl0aW5nLCByZXR1cm5zIGJhY2sgZGV0YWlscyBvZiB0aGUgZWRpdGluZyBjZWxsKHMpLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldEVkaXRpbmdDZWxscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93UmVuZGVyZXIuZ2V0RWRpdGluZ0NlbGxzKCk7XG4gICAgfTtcbiAgICAvKiogSWYgYSBjZWxsIGlzIGVkaXRpbmcsIGl0IHN0b3BzIHRoZSBlZGl0aW5nLiBQYXNzIGB0cnVlYCBpZiB5b3Ugd2FudCB0byBjYW5jZWwgdGhlIGVkaXRpbmcgKGkuZS4gZG9uJ3QgYWNjZXB0IGNoYW5nZXMpLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnN0b3BFZGl0aW5nID0gZnVuY3Rpb24gKGNhbmNlbCkge1xuICAgICAgICBpZiAoY2FuY2VsID09PSB2b2lkIDApIHsgY2FuY2VsID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy5yb3dSZW5kZXJlci5zdG9wRWRpdGluZyhjYW5jZWwpO1xuICAgIH07XG4gICAgLyoqIFN0YXJ0IGVkaXRpbmcgdGhlIHByb3ZpZGVkIGNlbGwuIElmIGFub3RoZXIgY2VsbCBpcyBlZGl0aW5nLCB0aGUgZWRpdGluZyB3aWxsIGJlIHN0b3BwZWQgaW4gdGhhdCBvdGhlciBjZWxsLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnN0YXJ0RWRpdGluZ0NlbGwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldEdyaWRDb2x1bW4ocGFyYW1zLmNvbEtleSk7XG4gICAgICAgIGlmICghY29sdW1uKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBubyBjb2x1bW4gZm91bmQgZm9yIFwiICsgcGFyYW1zLmNvbEtleSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNlbGxQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgIHJvd0luZGV4OiBwYXJhbXMucm93SW5kZXgsXG4gICAgICAgICAgICByb3dQaW5uZWQ6IHBhcmFtcy5yb3dQaW5uZWQgfHwgbnVsbCxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uXG4gICAgICAgIH07XG4gICAgICAgIHZhciBub3RQaW5uZWQgPSBwYXJhbXMucm93UGlubmVkID09IG51bGw7XG4gICAgICAgIGlmIChub3RQaW5uZWQpIHtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEJvZHlDdHJsLmdldFNjcm9sbEZlYXR1cmUoKS5lbnN1cmVJbmRleFZpc2libGUocGFyYW1zLnJvd0luZGV4KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2VsbCA9IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0Q2VsbEJ5UG9zaXRpb24oY2VsbFBvc2l0aW9uKTtcbiAgICAgICAgaWYgKCFjZWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY2VsbC5zdGFydFJvd09yQ2VsbEVkaXQocGFyYW1zLmtleSwgcGFyYW1zLmNoYXJQcmVzcyk7XG4gICAgfTtcbiAgICAvKiogQWRkIGFuIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuYWRkQWdnRnVuYyA9IGZ1bmN0aW9uIChrZXksIGFnZ0Z1bmMpIHtcbiAgICAgICAgaWYgKHRoaXMuYWdnRnVuY1NlcnZpY2UpIHtcbiAgICAgICAgICAgIHRoaXMuYWdnRnVuY1NlcnZpY2UuYWRkQWdnRnVuYyhrZXksIGFnZ0Z1bmMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQWRkIGFnZ3JlZ2F0aW9ucyBmdW5jdGlvbiB3aXRoIHRoZSBzcGVjaWZpZWQga2V5cy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5hZGRBZ2dGdW5jcyA9IGZ1bmN0aW9uIChhZ2dGdW5jcykge1xuICAgICAgICBpZiAodGhpcy5hZ2dGdW5jU2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5hZ2dGdW5jU2VydmljZS5hZGRBZ2dGdW5jcyhhZ2dGdW5jcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBDbGVhcnMgYWxsIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9ucyAoaW5jbHVkaW5nIHRob3NlIHByb3ZpZGVkIGJ5IHRoZSBncmlkKS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5jbGVhckFnZ0Z1bmNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5hZ2dGdW5jU2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5hZ2dGdW5jU2VydmljZS5jbGVhcigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQXBwbHkgdHJhbnNhY3Rpb25zIHRvIHRoZSBzZXJ2ZXIgc2lkZSByb3cgbW9kZWwuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuYXBwbHlTZXJ2ZXJTaWRlVHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAodHJhbnNhY3Rpb24pIHtcbiAgICAgICAgaWYgKCF0aGlzLnNlcnZlclNpZGVUcmFuc2FjdGlvbk1hbmFnZXIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogQ2Fubm90IGFwcGx5IFNlcnZlciBTaWRlIFRyYW5zYWN0aW9uIGlmIG5vdCB1c2luZyB0aGUgU2VydmVyIFNpZGUgUm93IE1vZGVsLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNlcnZlclNpZGVUcmFuc2FjdGlvbk1hbmFnZXIuYXBwbHlUcmFuc2FjdGlvbih0cmFuc2FjdGlvbik7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5hcHBseVNlcnZlclNpZGVUcmFuc2FjdGlvbkFzeW5jID0gZnVuY3Rpb24gKHRyYW5zYWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAoIXRoaXMuc2VydmVyU2lkZVRyYW5zYWN0aW9uTWFuYWdlcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBDYW5ub3QgYXBwbHkgU2VydmVyIFNpZGUgVHJhbnNhY3Rpb24gaWYgbm90IHVzaW5nIHRoZSBTZXJ2ZXIgU2lkZSBSb3cgTW9kZWwuJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyU2lkZVRyYW5zYWN0aW9uTWFuYWdlci5hcHBseVRyYW5zYWN0aW9uQXN5bmModHJhbnNhY3Rpb24sIGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKiBHZXRzIGFsbCBmYWlsZWQgc2VydmVyIHNpZGUgbG9hZHMgdG8gcmV0cnkuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmV0cnlTZXJ2ZXJTaWRlTG9hZHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogQVBJIHJldHJ5U2VydmVyU2lkZUxvYWRzKCkgY2FuIG9ubHkgYmUgdXNlZCB3aGVuIHVzaW5nIFNlcnZlci1TaWRlIFJvdyBNb2RlbC4nKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlcnZlclNpZGVSb3dNb2RlbC5yZXRyeUxvYWRzKCk7XG4gICAgfTtcbiAgICBHcmlkQXBpLnByb3RvdHlwZS5mbHVzaFNlcnZlclNpZGVBc3luY1RyYW5zYWN0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNlcnZlclNpZGVUcmFuc2FjdGlvbk1hbmFnZXIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogQ2Fubm90IGZsdXNoIFNlcnZlciBTaWRlIFRyYW5zYWN0aW9uIGlmIG5vdCB1c2luZyB0aGUgU2VydmVyIFNpZGUgUm93IE1vZGVsLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNlcnZlclNpZGVUcmFuc2FjdGlvbk1hbmFnZXIuZmx1c2hBc3luY1RyYW5zYWN0aW9ucygpO1xuICAgIH07XG4gICAgLyoqIFVwZGF0ZSByb3cgZGF0YS4gUGFzcyBhIHRyYW5zYWN0aW9uIG9iamVjdCB3aXRoIGxpc3RzIGZvciBgYWRkYCwgYHJlbW92ZWAgYW5kIGB1cGRhdGVgLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmFwcGx5VHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAocm93RGF0YVRyYW5zYWN0aW9uKSB7XG4gICAgICAgIGlmICghdGhpcy5jbGllbnRTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHVwZGF0ZVJvd0RhdGEoKSBvbmx5IHdvcmtzIHdpdGggQ2xpZW50U2lkZVJvd01vZGVsLiBXb3JraW5nIHdpdGggSW5maW5pdGVSb3dNb2RlbCB3YXMgZGVwcmVjYXRlZCBpbiB2MjMuMSBhbmQgcmVtb3ZlZCBpbiB2MjQuMScpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXMgPSB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC51cGRhdGVSb3dEYXRhKHJvd0RhdGFUcmFuc2FjdGlvbik7XG4gICAgICAgIC8vIHJlZnJlc2ggYWxsIHRoZSBmdWxsIHdpZHRoIHJvd3NcbiAgICAgICAgdGhpcy5yb3dSZW5kZXJlci5yZWZyZXNoRnVsbFdpZHRoUm93cyhyZXMudXBkYXRlKTtcbiAgICAgICAgLy8gZG8gY2hhbmdlIGRldGVjdGlvbiBmb3IgYWxsIHByZXNlbnQgY2VsbHNcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ2hhbmdlRGV0ZWN0aW9uKCkpIHtcbiAgICAgICAgICAgIHRoaXMucm93UmVuZGVyZXIucmVmcmVzaENlbGxzKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBgZGVsdGFTb3J0YCBwcm9wZXJ0eSAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnNldERlbHRhU29ydCA9IGZ1bmN0aW9uIChlbmFibGUpIHtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuc2V0UHJvcGVydHkoJ2RlbHRhU29ydCcsIGVuYWJsZSk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogYXMgb2YgdjIzLjEsIGdyaWQgQVBJIHVwZGF0ZVJvd0RhdGEodHJhbnNhY3Rpb24pIGlzIG5vdyBjYWxsZWQgYXBwbHlUcmFuc2FjdGlvbih0cmFuc2FjdGlvbikuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUudXBkYXRlUm93RGF0YSA9IGZ1bmN0aW9uIChyb3dEYXRhVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgdmFyIG1lc3NhZ2UgPSAnQUcgR3JpZDogYXMgb2YgdjIzLjEsIGdyaWQgQVBJIHVwZGF0ZVJvd0RhdGEodHJhbnNhY3Rpb24pIGlzIG5vdyBjYWxsZWQgYXBwbHlUcmFuc2FjdGlvbih0cmFuc2FjdGlvbikuIHVwZGF0ZVJvd0RhdGEgaXMgZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGEgZnV0dXJlIG1ham9yIHJlbGVhc2UuJztcbiAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybihtZXNzYWdlKTsgfSwgJ3VwZGF0ZVJvd0RhdGEgZGVwcmVjYXRlZCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5hcHBseVRyYW5zYWN0aW9uKHJvd0RhdGFUcmFuc2FjdGlvbik7XG4gICAgfTtcbiAgICAvKiogU2FtZSBhcyBgYXBwbHlUcmFuc2FjdGlvbmAgZXhjZXB0IGV4ZWN1dGVzIGFzeW5jaHJvbm91c2x5IGZvciBlZmZpY2llbmN5LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmFwcGx5VHJhbnNhY3Rpb25Bc3luYyA9IGZ1bmN0aW9uIChyb3dEYXRhVHJhbnNhY3Rpb24sIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICghdGhpcy5jbGllbnRTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGFwaS5hcHBseVRyYW5zYWN0aW9uQXN5bmMoKSBvbmx5IHdvcmtzIHdpdGggQ2xpZW50U2lkZVJvd01vZGVsLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmJhdGNoVXBkYXRlUm93RGF0YShyb3dEYXRhVHJhbnNhY3Rpb24sIGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKiBFeGVjdXRlcyBhbnkgcmVtYWluaW5nIGFzeW5jaHJvbm91cyBncmlkIHRyYW5zYWN0aW9ucywgaWYgYW55IGFyZSB3YWl0aW5nIHRvIGJlIGV4ZWN1dGVkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmZsdXNoQXN5bmNUcmFuc2FjdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jbGllbnRTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGFwaS5hcHBseVRyYW5zYWN0aW9uQXN5bmMoKSBvbmx5IHdvcmtzIHdpdGggQ2xpZW50U2lkZVJvd01vZGVsLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmZsdXNoQXN5bmNUcmFuc2FjdGlvbnMoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBhcyBvZiB2MjMuMSwgZ3JpZCBBUEkgYmF0Y2hVcGRhdGVSb3dEYXRhKHRyYW5zYWN0aW9uLCBjYWxsYmFjaykgaXMgbm93IGNhbGxlZCBhcHBseVRyYW5zYWN0aW9uQXN5bmModHJhbnNhY3Rpb24sIGNhbGxiYWNrKS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5iYXRjaFVwZGF0ZVJvd0RhdGEgPSBmdW5jdGlvbiAocm93RGF0YVRyYW5zYWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgbWVzc2FnZSA9ICdBRyBHcmlkOiBhcyBvZiB2MjMuMSwgZ3JpZCBBUEkgYmF0Y2hVcGRhdGVSb3dEYXRhKHRyYW5zYWN0aW9uLCBjYWxsYmFjaykgaXMgbm93IGNhbGxlZCBhcHBseVRyYW5zYWN0aW9uQXN5bmModHJhbnNhY3Rpb24sIGNhbGxiYWNrKS4gYmF0Y2hVcGRhdGVSb3dEYXRhIGlzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSBtYWpvciByZWxlYXNlLic7XG4gICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4obWVzc2FnZSk7IH0sICdiYXRjaFVwZGF0ZVJvd0RhdGEgZGVwcmVjYXRlZCcpO1xuICAgICAgICB0aGlzLmFwcGx5VHJhbnNhY3Rpb25Bc3luYyhyb3dEYXRhVHJhbnNhY3Rpb24sIGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBpbnNlcnRJdGVtc0F0SW5kZXgoKSBpcyBkZXByZWNhdGVkLCB1c2UgdXBkYXRlUm93RGF0YSh0cmFuc2FjdGlvbikgaW5zdGVhZC4qL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmluc2VydEl0ZW1zQXRJbmRleCA9IGZ1bmN0aW9uIChpbmRleCwgaXRlbXMsIHNraXBSZWZyZXNoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogaW5zZXJ0SXRlbXNBdEluZGV4KCkgaXMgZGVwcmVjYXRlZCwgdXNlIHVwZGF0ZVJvd0RhdGEodHJhbnNhY3Rpb24pIGluc3RlYWQuJyk7XG4gICAgICAgIHRoaXMudXBkYXRlUm93RGF0YSh7IGFkZDogaXRlbXMsIGFkZEluZGV4OiBpbmRleCwgdXBkYXRlOiBudWxsLCByZW1vdmU6IG51bGwgfSk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogcmVtb3ZlSXRlbXMoKSBpcyBkZXByZWNhdGVkLCB1c2UgdXBkYXRlUm93RGF0YSh0cmFuc2FjdGlvbikgaW5zdGVhZC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZW1vdmVJdGVtcyA9IGZ1bmN0aW9uIChyb3dOb2Rlcywgc2tpcFJlZnJlc2gpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiByZW1vdmVJdGVtcygpIGlzIGRlcHJlY2F0ZWQsIHVzZSB1cGRhdGVSb3dEYXRhKHRyYW5zYWN0aW9uKSBpbnN0ZWFkLicpO1xuICAgICAgICB2YXIgZGF0YVRvUmVtb3ZlID0gcm93Tm9kZXMubWFwKGZ1bmN0aW9uIChyb3dOb2RlKSB7IHJldHVybiByb3dOb2RlLmRhdGE7IH0pO1xuICAgICAgICB0aGlzLnVwZGF0ZVJvd0RhdGEoeyBhZGQ6IG51bGwsIGFkZEluZGV4OiBudWxsLCB1cGRhdGU6IG51bGwsIHJlbW92ZTogZGF0YVRvUmVtb3ZlIH0pO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IGFkZEl0ZW1zKCkgaXMgZGVwcmVjYXRlZCwgdXNlIHVwZGF0ZVJvd0RhdGEodHJhbnNhY3Rpb24pIGluc3RlYWQuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuYWRkSXRlbXMgPSBmdW5jdGlvbiAoaXRlbXMsIHNraXBSZWZyZXNoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogYWRkSXRlbXMoKSBpcyBkZXByZWNhdGVkLCB1c2UgdXBkYXRlUm93RGF0YSh0cmFuc2FjdGlvbikgaW5zdGVhZC4nKTtcbiAgICAgICAgdGhpcy51cGRhdGVSb3dEYXRhKHsgYWRkOiBpdGVtcywgYWRkSW5kZXg6IG51bGwsIHVwZGF0ZTogbnVsbCwgcmVtb3ZlOiBudWxsIH0pO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IHJlZnJlc2hWaXJ0dWFsUGFnZUNhY2hlKCkgaXMgbm93IGNhbGxlZCByZWZyZXNoSW5maW5pdGVDYWNoZSgpLCBwbGVhc2UgY2FsbCByZWZyZXNoSW5maW5pdGVDYWNoZSgpIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZWZyZXNoVmlydHVhbFBhZ2VDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiByZWZyZXNoVmlydHVhbFBhZ2VDYWNoZSgpIGlzIG5vdyBjYWxsZWQgcmVmcmVzaEluZmluaXRlQ2FjaGUoKSwgcGxlYXNlIGNhbGwgcmVmcmVzaEluZmluaXRlQ2FjaGUoKSBpbnN0ZWFkJyk7XG4gICAgICAgIHRoaXMucmVmcmVzaEluZmluaXRlQ2FjaGUoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiByZWZyZXNoSW5maW5pdGVQYWdlQ2FjaGUoKSBpcyBub3cgY2FsbGVkIHJlZnJlc2hJbmZpbml0ZUNhY2hlKCksIHBsZWFzZSBjYWxsIHJlZnJlc2hJbmZpbml0ZUNhY2hlKCkgaW5zdGVhZCAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnJlZnJlc2hJbmZpbml0ZVBhZ2VDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiByZWZyZXNoSW5maW5pdGVQYWdlQ2FjaGUoKSBpcyBub3cgY2FsbGVkIHJlZnJlc2hJbmZpbml0ZUNhY2hlKCksIHBsZWFzZSBjYWxsIHJlZnJlc2hJbmZpbml0ZUNhY2hlKCkgaW5zdGVhZCcpO1xuICAgICAgICB0aGlzLnJlZnJlc2hJbmZpbml0ZUNhY2hlKCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBNYXJrcyBhbGwgdGhlIGN1cnJlbnRseSBsb2FkZWQgYmxvY2tzIGluIHRoZSBjYWNoZSBmb3IgcmVsb2FkLlxuICAgICAqIElmIHlvdSBoYXZlIDEwIGJsb2NrcyBpbiB0aGUgY2FjaGUsIGFsbCAxMCB3aWxsIGJlIG1hcmtlZCBmb3IgcmVsb2FkLlxuICAgICAqIFRoZSBvbGQgZGF0YSB3aWxsIGNvbnRpbnVlIHRvIGJlIGRpc3BsYXllZCB1bnRpbCB0aGUgbmV3IGRhdGEgaXMgbG9hZGVkLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnJlZnJlc2hJbmZpbml0ZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pbmZpbml0ZVJvd01vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLmluZmluaXRlUm93TW9kZWwucmVmcmVzaENhY2hlKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBhcGkucmVmcmVzaEluZmluaXRlQ2FjaGUgaXMgb25seSBhdmFpbGFibGUgd2hlbiByb3dNb2RlbFR5cGU9J2luZmluaXRlJy5cIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBwdXJnZVZpcnR1YWxQYWdlQ2FjaGUoKSBpcyBub3cgY2FsbGVkIHB1cmdlSW5maW5pdGVDYWNoZSgpLCBwbGVhc2UgY2FsbCBwdXJnZUluZmluaXRlQ2FjaGUoKSBpbnN0ZWFkICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucHVyZ2VWaXJ0dWFsUGFnZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHB1cmdlVmlydHVhbFBhZ2VDYWNoZSgpIGlzIG5vdyBjYWxsZWQgcHVyZ2VJbmZpbml0ZUNhY2hlKCksIHBsZWFzZSBjYWxsIHB1cmdlSW5maW5pdGVDYWNoZSgpIGluc3RlYWQnKTtcbiAgICAgICAgdGhpcy5wdXJnZUluZmluaXRlUGFnZUNhY2hlKCk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogcHVyZ2VJbmZpbml0ZVBhZ2VDYWNoZSgpIGlzIG5vdyBjYWxsZWQgcHVyZ2VJbmZpbml0ZUNhY2hlKCksIHBsZWFzZSBjYWxsIHB1cmdlSW5maW5pdGVDYWNoZSgpIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wdXJnZUluZmluaXRlUGFnZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHB1cmdlSW5maW5pdGVQYWdlQ2FjaGUoKSBpcyBub3cgY2FsbGVkIHB1cmdlSW5maW5pdGVDYWNoZSgpLCBwbGVhc2UgY2FsbCBwdXJnZUluZmluaXRlQ2FjaGUoKSBpbnN0ZWFkJyk7XG4gICAgICAgIHRoaXMucHVyZ2VJbmZpbml0ZUNhY2hlKCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBQdXJnZXMgdGhlIGNhY2hlLlxuICAgICAqIFRoZSBncmlkIGlzIHRoZW4gdG9sZCB0byByZWZyZXNoLiBPbmx5IHRoZSBibG9ja3MgcmVxdWlyZWQgdG8gZGlzcGxheSB0aGUgY3VycmVudCBkYXRhIG9uIHNjcmVlbiBhcmUgZmV0Y2hlZCAodHlwaWNhbGx5IG5vIG1vcmUgdGhhbiAyKS5cbiAgICAgKiBUaGUgZ3JpZCB3aWxsIGRpc3BsYXkgbm90aGluZyB3aGlsZSB0aGUgbmV3IGJsb2NrcyBhcmUgbG9hZGVkLlxuICAgICAqIFVzZSB0aGlzIHRvIGltbWVkaWF0ZWx5IHJlbW92ZSB0aGUgb2xkIGRhdGEgZnJvbSB0aGUgdXNlci5cbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wdXJnZUluZmluaXRlQ2FjaGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmluZmluaXRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuaW5maW5pdGVSb3dNb2RlbC5wdXJnZUNhY2hlKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBhcGkucHVyZ2VJbmZpbml0ZUNhY2hlIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gcm93TW9kZWxUeXBlPSdpbmZpbml0ZScuXCIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogc2luY2UgdmVyc2lvbiAxOC54LCBhcGkucHVyZ2VFbnRlcnByaXNlQ2FjaGUoKSBzaG91bGQgYmUgcmVwbGFjZWQgd2l0aCBhcGkucmVmcmVzaFNlcnZlclNpZGUoe3B1cmdlOiB0cnVlfSkgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wdXJnZUVudGVycHJpc2VDYWNoZSA9IGZ1bmN0aW9uIChyb3V0ZSkge1xuICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBzaW5jZSB2ZXJzaW9uIDE4LngsIGFwaS5wdXJnZUVudGVycHJpc2VDYWNoZSgpIHNob3VsZCBiZSByZXBsYWNlZCB3aXRoIGFwaS5yZWZyZXNoU2VydmVyU2lkZSh7cHVyZ2U6IHRydWV9KVwiKTtcbiAgICAgICAgdGhpcy5wdXJnZVNlcnZlclNpZGVDYWNoZShyb3V0ZSk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgQUcgR3JpZDogc2luY2UgdjI1LjAsIGFwaS5wdXJnZVNlcnZlclNpZGVDYWNoZSBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIGFwaS5yZWZyZXNoU2VydmVyU2lkZSh7cHVyZ2U6IHRydWV9KSBpbnN0ZWFkLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnB1cmdlU2VydmVyU2lkZUNhY2hlID0gZnVuY3Rpb24gKHJvdXRlKSB7XG4gICAgICAgIGlmIChyb3V0ZSA9PT0gdm9pZCAwKSB7IHJvdXRlID0gW107IH1cbiAgICAgICAgaWYgKHRoaXMuc2VydmVyU2lkZVJvd01vZGVsKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBzaW5jZSB2MjUuMCwgYXBpLnB1cmdlU2VydmVyU2lkZUNhY2hlIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgYXBpLnJlZnJlc2hTZXJ2ZXJTaWRlKHtwdXJnZTogdHJ1ZX0pIGluc3RlYWQuXCIpO1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoU2VydmVyU2lkZSh7XG4gICAgICAgICAgICAgICAgcm91dGU6IHJvdXRlLFxuICAgICAgICAgICAgICAgIHB1cmdlOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGFwaS5wdXJnZVNlcnZlclNpZGVDYWNoZSBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIHJvd01vZGVsVHlwZT0nc2VydmVyU2lkZScuXCIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBSZWZyZXNoIGEgc2VydmVyLXNpZGUgbGV2ZWwuXG4gICAgICogSWYgeW91IHBhc3Mgbm8gcGFyYW1ldGVycywgdGhlbiB0aGUgdG9wIGxldmVsIHN0b3JlIGlzIHB1cmdlZC5cbiAgICAgKiBUbyBwdXJnZSBhIGNoaWxkIGxldmVsLCBwYXNzIGluIHRoZSBzdHJpbmcgb2Yga2V5cyB0byBnZXQgdG8gdGhlIGRlc2lyZWQgbGV2ZWwuXG4gICAgICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucmVmcmVzaFNlcnZlclNpZGUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmICghdGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGFwaS5yZWZyZXNoU2VydmVyU2lkZSBpcyBvbmx5IGF2YWlsYWJsZSB3aGVuIHJvd01vZGVsVHlwZT0nc2VydmVyU2lkZScuXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VydmVyU2lkZVJvd01vZGVsLnJlZnJlc2hTdG9yZShwYXJhbXMpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIHVzZSBgcmVmcmVzaFNlcnZlclNpZGVgIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5yZWZyZXNoU2VydmVyU2lkZVN0b3JlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgbWVzc2FnZSA9IFwiQUcgR3JpZDogR3JpZCBBUEkgcmVmcmVzaFNlcnZlclNpZGVTdG9yZSgpIHdhcyByZW5hbWVkIHRvIHJlZnJlc2hTZXJ2ZXJTaWRlKCkgaW4gdjI4LjBcIjtcbiAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybihtZXNzYWdlKTsgfSwgJ3JlZnJlc2hTZXJ2ZXJTaWRlU3RvcmUtcmVuYW1lZCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoU2VydmVyU2lkZShwYXJhbXMpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIHVzZSBgZ2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxTdGF0ZWAgaW5zdGVhZCAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFNlcnZlclNpZGVTdG9yZVN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWVzc2FnZSA9IFwiQUcgR3JpZDogR3JpZCBBUEkgZ2V0U2VydmVyU2lkZVN0b3JlU3RhdGUoKSB3YXMgcmVuYW1lZCB0byBnZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFN0YXRlKCkgaW4gdjI4LjBcIjtcbiAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybihtZXNzYWdlKTsgfSwgJ2dldFNlcnZlclNpZGVTdG9yZVN0YXRlLXJlbmFtZWQnKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2VydmVyU2lkZUdyb3VwTGV2ZWxTdGF0ZSgpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgaW5mbyBvbiBhbGwgc2VydmVyIHNpZGUgZ3JvdXAgbGV2ZWxzLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFNlcnZlclNpZGVHcm91cExldmVsU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zZXJ2ZXJTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGFwaS5nZXRTZXJ2ZXJTaWRlR3JvdXBMZXZlbFN0YXRlIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gcm93TW9kZWxUeXBlPSdzZXJ2ZXJTaWRlJy5cIik7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2VydmVyU2lkZVJvd01vZGVsLmdldFN0b3JlU3RhdGUoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBnZXRWaXJ0dWFsUm93Q291bnQoKSBpcyBub3cgY2FsbGVkIGdldEluZmluaXRlUm93Q291bnQoKSwgcGxlYXNlIGNhbGwgZ2V0SW5maW5pdGVSb3dDb3VudCgpIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRWaXJ0dWFsUm93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZ2V0VmlydHVhbFJvd0NvdW50KCkgaXMgbm93IGNhbGxlZCBnZXRJbmZpbml0ZVJvd0NvdW50KCksIHBsZWFzZSBjYWxsIGdldEluZmluaXRlUm93Q291bnQoKSBpbnN0ZWFkJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEluZmluaXRlUm93Q291bnQoKTtcbiAgICB9O1xuICAgIC8qKiBUaGUgcm93IGNvdW50IGRlZmluZXMgaG93IG1hbnkgcm93cyB0aGUgZ3JpZCBhbGxvd3Mgc2Nyb2xsaW5nIHRvLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldEluZmluaXRlUm93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmluZmluaXRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmluZmluaXRlUm93TW9kZWwuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGFwaS5nZXRWaXJ0dWFsUm93Q291bnQgaXMgb25seSBhdmFpbGFibGUgd2hlbiByb3dNb2RlbFR5cGU9J3ZpcnR1YWwnLlwiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIEFHIEdyaWQ6IGFwaS5pc01heFJvd0ZvdW5kIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgYXBpLmlzTGFzdFJvd0luZGV4S25vd24oKSAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmlzTWF4Um93Rm91bmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGFwaS5pc01heFJvd0ZvdW5kIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgYXBpLmlzTGFzdFJvd0luZGV4S25vd24oKVwiKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNMYXN0Um93SW5kZXhLbm93bigpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgYHRydWVgIGlmIGdyaWQgYWxsb3dzIGZvciBzY3JvbGxpbmcgcGFzdCB0aGUgbGFzdCByb3cgdG8gbG9hZCBtb3JlIHJvd3MsIHRodXMgcHJvdmlkaW5nIGluZmluaXRlIHNjcm9sbC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5pc0xhc3RSb3dJbmRleEtub3duID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pbmZpbml0ZVJvd01vZGVsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pbmZpbml0ZVJvd01vZGVsLmlzTGFzdFJvd0luZGV4S25vd24oKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IGFwaS5pc01heFJvd0ZvdW5kIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gcm93TW9kZWxUeXBlPSd2aXJ0dWFsJy5cIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBzZXRWaXJ0dWFsUm93Q291bnQoKSBpcyBub3cgY2FsbGVkIHNldEluZmluaXRlUm93Q291bnQoKSwgcGxlYXNlIGNhbGwgc2V0SW5maW5pdGVSb3dDb3VudCgpIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRWaXJ0dWFsUm93Q291bnQgPSBmdW5jdGlvbiAocm93Q291bnQsIG1heFJvd0ZvdW5kKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2V0VmlydHVhbFJvd0NvdW50KCkgaXMgbm93IGNhbGxlZCBzZXRJbmZpbml0ZVJvd0NvdW50KCksIHBsZWFzZSBjYWxsIHNldEluZmluaXRlUm93Q291bnQoKSBpbnN0ZWFkJyk7XG4gICAgICAgIHRoaXMuc2V0Um93Q291bnQocm93Q291bnQsIG1heFJvd0ZvdW5kKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBzZXRJbmZpbml0ZVJvd0NvdW50KCkgaXMgbm93IGNhbGxlZCBzZXRSb3dDb3VudCgpLCBwbGVhc2UgY2FsbCBzZXRSb3dDb3VudCgpIGluc3RlYWQgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRJbmZpbml0ZVJvd0NvdW50ID0gZnVuY3Rpb24gKHJvd0NvdW50LCBtYXhSb3dGb3VuZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNldEluZmluaXRlUm93Q291bnQoKSBpcyBub3cgY2FsbGVkIHNldFJvd0NvdW50KCksIHBsZWFzZSBjYWxsIHNldFJvd0NvdW50KCkgaW5zdGVhZCcpO1xuICAgICAgICB0aGlzLnNldFJvd0NvdW50KHJvd0NvdW50LCBtYXhSb3dGb3VuZCk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBgcm93Q291bnRgIGFuZCBgbGFzdFJvd0luZGV4S25vd25gIHByb3BlcnRpZXMuXG4gICAgICogVGhlIHNlY29uZCBwYXJhbWV0ZXIsIGBsYXN0Um93SW5kZXhLbm93bmAsIGlzIG9wdGlvbmFsIGFuZCBpZiBsZWZ0IG91dCwgb25seSBgcm93Q291bnRgIGlzIHNldC5cbiAgICAgKiBTZXQgYHJvd0NvdW50YCB0byBhZGp1c3QgdGhlIGhlaWdodCBvZiB0aGUgdmVydGljYWwgc2Nyb2xsLlxuICAgICAqIFNldCBgbGFzdFJvd0luZGV4S25vd25gIHRvIGVuYWJsZSAvIGRpc2FibGUgc2VhcmNoaW5nIGZvciBtb3JlIHJvd3MuXG4gICAgICogVXNlIHRoaXMgbWV0aG9kIGlmIHlvdSBhZGQgb3IgcmVtb3ZlIHJvd3MgaW50byB0aGUgZGF0YXNldCBhbmQgbmVlZCB0byByZXNldCB0aGUgbnVtYmVyIG9mIHJvd3Mgb3IgcHV0IHRoZSBkYXRhIGJhY2sgaW50byAnbG9vayBmb3IgZGF0YScgbW9kZS5cbiAgICAgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5zZXRSb3dDb3VudCA9IGZ1bmN0aW9uIChyb3dDb3VudCwgbWF4Um93Rm91bmQpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5maW5pdGVSb3dNb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5pbmZpbml0ZVJvd01vZGVsLnNldFJvd0NvdW50KHJvd0NvdW50LCBtYXhSb3dGb3VuZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBhcGkuc2V0Um93Q291bnQgaXMgb25seSBhdmFpbGFibGUgZm9yIEluZmluaXRlIFJvdyBNb2RlbC5cIik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBBRyBHcmlkOiBnZXRWaXJ0dWFsUGFnZVN0YXRlKCkgaXMgbm93IGNhbGxlZCBnZXRDYWNoZUJsb2NrU3RhdGUoKSwgcGxlYXNlIGNhbGwgZ2V0Q2FjaGVCbG9ja1N0YXRlKCkgaW5zdGVhZCAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldFZpcnR1YWxQYWdlU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZ2V0VmlydHVhbFBhZ2VTdGF0ZSgpIGlzIG5vdyBjYWxsZWQgZ2V0Q2FjaGVCbG9ja1N0YXRlKCksIHBsZWFzZSBjYWxsIGdldENhY2hlQmxvY2tTdGF0ZSgpIGluc3RlYWQnKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FjaGVCbG9ja1N0YXRlKCk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgZ2V0SW5maW5pdGVQYWdlU3RhdGUoKSBpcyBub3cgY2FsbGVkIGdldENhY2hlQmxvY2tTdGF0ZSgpLCBwbGVhc2UgY2FsbCBnZXRDYWNoZUJsb2NrU3RhdGUoKSBpbnN0ZWFkICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0SW5maW5pdGVQYWdlU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogZ2V0SW5maW5pdGVQYWdlU3RhdGUoKSBpcyBub3cgY2FsbGVkIGdldENhY2hlQmxvY2tTdGF0ZSgpLCBwbGVhc2UgY2FsbCBnZXRDYWNoZUJsb2NrU3RhdGUoKSBpbnN0ZWFkJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENhY2hlQmxvY2tTdGF0ZSgpO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBzdGF0ZSBvZiB0aGUgY2FjaGUuIFRoaXMgaXMgdXNlZnVsIGZvciBkZWJ1Z2dpbmcgYW5kIHVuZGVyc3RhbmRpbmcgaG93IHRoZSBjYWNoZSBpcyB3b3JraW5nLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldENhY2hlQmxvY2tTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93Tm9kZUJsb2NrTG9hZGVyLmdldEJsb2NrU3RhdGUoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCAgSW4gQUcgR3JpZCB2MjUuMi4wLCBjaGVja0dyaWRTaXplKCkgd2FzIHJlbW92ZWQsIGFzIGl0IHdhcyBsZWdhY3kgYW5kIGRpZG4ndCBkbyBhbnl0aGluZyB1c2VmdWwuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuY2hlY2tHcmlkU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFwiSW4gQUcgR3JpZCB2MjUuMi4wLCBjaGVja0dyaWRTaXplKCkgd2FzIHJlbW92ZWQsIGFzIGl0IHdhcyBsZWdhY3kgYW5kIGRpZG4ndCBkbyBhbnl0aGluZyB1c2VmdWwuXCIpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkICBJbiBBRyBHcmlkIHYxMiwgZ2V0Rmlyc3RSZW5kZXJlZFJvdygpIHdhcyByZW5hbWVkIHRvIGdldEZpcnN0RGlzcGxheWVkUm93KCkgKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXRGaXJzdFJlbmRlcmVkUm93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0luIEFHIEdyaWQgdjEyLCBnZXRGaXJzdFJlbmRlcmVkUm93KCkgd2FzIHJlbmFtZWQgdG8gZ2V0Rmlyc3REaXNwbGF5ZWRSb3coKScpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdERpc3BsYXllZFJvdygpO1xuICAgIH07XG4gICAgLyoqIEdldCB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGRpc3BsYXllZCByb3cgZHVlIHRvIHNjcm9sbGluZyAoaW5jbHVkZXMgaW52aXNpYmxlIHJlbmRlcmVkIHJvd3MgaW4gdGhlIGJ1ZmZlcikuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0Rmlyc3REaXNwbGF5ZWRSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd1JlbmRlcmVyLmdldEZpcnN0VmlydHVhbFJlbmRlcmVkUm93KCk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgSW4gQUcgR3JpZCB2MTIsIGdldExhc3RSZW5kZXJlZFJvdygpIHdhcyByZW5hbWVkIHRvIGdldExhc3REaXNwbGF5ZWRSb3coKSAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLmdldExhc3RSZW5kZXJlZFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdpbiBBRyBHcmlkIHYxMiwgZ2V0TGFzdFJlbmRlcmVkUm93KCkgd2FzIHJlbmFtZWQgdG8gZ2V0TGFzdERpc3BsYXllZFJvdygpJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldExhc3REaXNwbGF5ZWRSb3coKTtcbiAgICB9O1xuICAgIC8qKiBHZXQgdGhlIGluZGV4IG9mIHRoZSBsYXN0IGRpc3BsYXllZCByb3cgZHVlIHRvIHNjcm9sbGluZyAoaW5jbHVkZXMgaW52aXNpYmxlIHJlbmRlcmVkIHJvd3MgaW4gdGhlIGJ1ZmZlcikuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0TGFzdERpc3BsYXllZFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93UmVuZGVyZXIuZ2V0TGFzdFZpcnR1YWxSZW5kZXJlZFJvdygpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIGRpc3BsYXllZCBgUm93Tm9kZWAgYXQgdGhlIGdpdmVuIGBpbmRleGAuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUuZ2V0RGlzcGxheWVkUm93QXRJbmRleCA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXRSb3coaW5kZXgpO1xuICAgIH07XG4gICAgLyoqIFJldHVybnMgdGhlIHRvdGFsIG51bWJlciBvZiBkaXNwbGF5ZWQgcm93cy4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93TW9kZWwuZ2V0Um93Q291bnQoKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgYHRydWVgIHdoZW4gdGhlIGxhc3QgcGFnZSBpcyBrbm93bi5cbiAgICAgKiBUaGlzIHdpbGwgYWx3YXlzIGJlIGB0cnVlYCBpZiB5b3UgYXJlIHVzaW5nIHRoZSBDbGllbnQtU2lkZSBSb3cgTW9kZWwgZm9yIHBhZ2luYXRpb24uXG4gICAgICogUmV0dXJucyBgZmFsc2VgIHdoZW4gdGhlIGxhc3QgcGFnZSBpcyBub3Qga25vd247IHRoaXMgb25seSBoYXBwZW5zIHdoZW4gdXNpbmcgSW5maW5pdGUgUm93IE1vZGVsLlxuICAgICAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnBhZ2luYXRpb25Jc0xhc3RQYWdlRm91bmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhZ2luYXRpb25Qcm94eS5pc0xhc3RQYWdlRm91bmQoKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIGhvdyBtYW55IHJvd3MgYXJlIGJlaW5nIHNob3duIHBlciBwYWdlLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnBhZ2luYXRpb25HZXRQYWdlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VTaXplKCk7XG4gICAgfTtcbiAgICAvKiogU2V0cyB0aGUgYHBhZ2luYXRpb25QYWdlU2l6ZWAsIHRoZW4gcmUtcGFnaW5hdGVzIHRoZSBncmlkIHNvIHRoZSBjaGFuZ2VzIGFyZSBhcHBsaWVkIGltbWVkaWF0ZWx5LiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnBhZ2luYXRpb25TZXRQYWdlU2l6ZSA9IGZ1bmN0aW9uIChzaXplKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KCdwYWdpbmF0aW9uUGFnZVNpemUnLCBzaXplKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSAwLWJhc2VkIGluZGV4IG9mIHRoZSBwYWdlIHdoaWNoIGlzIHNob3dpbmcuICovXG4gICAgR3JpZEFwaS5wcm90b3R5cGUucGFnaW5hdGlvbkdldEN1cnJlbnRQYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Q3VycmVudFBhZ2UoKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXMuIFJldHVybnMgYG51bGxgIGlmIGBwYWdpbmF0aW9uSXNMYXN0UGFnZUZvdW5kKCkgPT09IGZhbHNlYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wYWdpbmF0aW9uR2V0VG90YWxQYWdlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvblByb3h5LmdldFRvdGFsUGFnZXMoKTtcbiAgICB9O1xuICAgIC8qKiBUaGUgdG90YWwgbnVtYmVyIG9mIHJvd3MuIFJldHVybnMgYG51bGxgIGlmIGBwYWdpbmF0aW9uSXNMYXN0UGFnZUZvdW5kKCkgPT09IGZhbHNlYC4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wYWdpbmF0aW9uR2V0Um93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRNYXN0ZXJSb3dDb3VudCgpO1xuICAgIH07XG4gICAgLyoqIE5hdmlnYXRlcyB0byB0aGUgbmV4dCBwYWdlLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnBhZ2luYXRpb25Hb1RvTmV4dFBhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucGFnaW5hdGlvblByb3h5LmdvVG9OZXh0UGFnZSgpO1xuICAgIH07XG4gICAgLyoqIE5hdmlnYXRlcyB0byB0aGUgcHJldmlvdXMgcGFnZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wYWdpbmF0aW9uR29Ub1ByZXZpb3VzUGFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uUHJveHkuZ29Ub1ByZXZpb3VzUGFnZSgpO1xuICAgIH07XG4gICAgLyoqIE5hdmlnYXRlcyB0byB0aGUgZmlyc3QgcGFnZS4gKi9cbiAgICBHcmlkQXBpLnByb3RvdHlwZS5wYWdpbmF0aW9uR29Ub0ZpcnN0UGFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uUHJveHkuZ29Ub0ZpcnN0UGFnZSgpO1xuICAgIH07XG4gICAgLyoqIE5hdmlnYXRlcyB0byB0aGUgbGFzdCBwYWdlLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnBhZ2luYXRpb25Hb1RvTGFzdFBhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucGFnaW5hdGlvblByb3h5LmdvVG9MYXN0UGFnZSgpO1xuICAgIH07XG4gICAgLyoqIEdvZXMgdG8gdGhlIHNwZWNpZmllZCBwYWdlLiBJZiB0aGUgcGFnZSByZXF1ZXN0ZWQgZG9lc24ndCBleGlzdCwgaXQgd2lsbCBnbyB0byB0aGUgbGFzdCBwYWdlLiAqL1xuICAgIEdyaWRBcGkucHJvdG90eXBlLnBhZ2luYXRpb25Hb1RvUGFnZSA9IGZ1bmN0aW9uIChwYWdlKSB7XG4gICAgICAgIHRoaXMucGFnaW5hdGlvblByb3h5LmdvVG9QYWdlKHBhZ2UpO1xuICAgIH07XG4gICAgR3JpZEFwaS5wcm90b3R5cGUuc2V0Um93Q2xhc3MgPSBmdW5jdGlvbiAoY2xhc3NOYW1lKSB7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1JPV19DTEFTUywgY2xhc3NOYW1lKTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnaW1tdXRhYmxlU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiaW1tdXRhYmxlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnY3N2Q3JlYXRvcicpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiY3N2Q3JlYXRvclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnZXhjZWxDcmVhdG9yJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJleGNlbENyZWF0b3JcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dSZW5kZXJlcicpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwicm93UmVuZGVyZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCduYXZpZ2F0aW9uU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwibmF2aWdhdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJmaWx0ZXJNYW5hZ2VyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgnc2VsZWN0aW9uU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwic2VsZWN0aW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRPcHRpb25zV3JhcHBlcicpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiZ3JpZE9wdGlvbnNXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgndmFsdWVTZXJ2aWNlJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJ2YWx1ZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdhbGlnbmVkR3JpZHNTZXJ2aWNlJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJhbGlnbmVkR3JpZHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgnZXZlbnRTZXJ2aWNlJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJldmVudFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdwaW5uZWRSb3dNb2RlbCcpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwicGlubmVkUm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb250ZXh0JylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJjb250ZXh0XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgncm93TW9kZWwnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcInJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgnc29ydENvbnRyb2xsZXInKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcInNvcnRDb250cm9sbGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgncGFnaW5hdGlvblByb3h5JylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJwYWdpbmF0aW9uUHJveHlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2RyYWdBbmREcm9wU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiZHJhZ0FuZERyb3BTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIE9wdGlvbmFsKCdyYW5nZVNlcnZpY2UnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcInJhbmdlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnY2xpcGJvYXJkU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiY2xpcGJvYXJkU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnYWdnRnVuY1NlcnZpY2UnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcImFnZ0Z1bmNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIEF1dG93aXJlZCgnbWVudUZhY3RvcnknKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcIm1lbnVGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIE9wdGlvbmFsKCdjb250ZXh0TWVudUZhY3RvcnknKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcImNvbnRleHRNZW51RmFjdG9yeVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlQ2FjaGUnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcInZhbHVlQ2FjaGVcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdhbmltYXRpb25GcmFtZVNlcnZpY2UnKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcImFuaW1hdGlvbkZyYW1lU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnc3RhdHVzQmFyU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwic3RhdHVzQmFyU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnY2hhcnRTZXJ2aWNlJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJjaGFydFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFyKFtcbiAgICAgICAgT3B0aW9uYWwoJ3VuZG9SZWRvU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwidW5kb1JlZG9TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIE9wdGlvbmFsKCdyb3dOb2RlQmxvY2tMb2FkZXInKVxuICAgIF0sIEdyaWRBcGkucHJvdG90eXBlLCBcInJvd05vZGVCbG9ja0xvYWRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBPcHRpb25hbCgnc3NybVRyYW5zYWN0aW9uTWFuYWdlcicpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwic2VydmVyU2lkZVRyYW5zYWN0aW9uTWFuYWdlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIE9wdGlvbmFsKCdmcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyJylcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJmcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBHcmlkQXBpLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBQcmVEZXN0cm95XG4gICAgXSwgR3JpZEFwaS5wcm90b3R5cGUsIFwiY2xlYW5Eb3duUmVmZXJlbmNlc1RvQXZvaWRNZW1vcnlMZWFrSW5DYXNlQXBwbGljYXRpb25Jc0tlZXBpbmdSZWZlcmVuY2VUb0Rlc3Ryb3llZEdyaWRcIiwgbnVsbCk7XG4gICAgR3JpZEFwaSA9IF9fZGVjb3JhdGUkMXIoW1xuICAgICAgICBCZWFuKCdncmlkQXBpJylcbiAgICBdLCBHcmlkQXBpKTtcbiAgICByZXR1cm4gR3JpZEFwaTtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMXkgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFxID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgU2V0TGVmdEZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDF5KFNldExlZnRGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNldExlZnRGZWF0dXJlKGNvbHVtbk9yR3JvdXAsIGVDZWxsLCBiZWFucywgY29sc1NwYW5uaW5nKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmNvbHVtbk9yR3JvdXAgPSBjb2x1bW5Pckdyb3VwO1xuICAgICAgICBfdGhpcy5lQ2VsbCA9IGVDZWxsO1xuICAgICAgICBfdGhpcy5hcmlhRWwgPSBfdGhpcy5lQ2VsbC5xdWVyeVNlbGVjdG9yKCdbcm9sZT1jb2x1bW5oZWFkZXJdJykgfHwgX3RoaXMuZUNlbGw7XG4gICAgICAgIF90aGlzLmNvbHNTcGFubmluZyA9IGNvbHNTcGFubmluZztcbiAgICAgICAgX3RoaXMuYmVhbnMgPSBiZWFucztcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBTZXRMZWZ0RmVhdHVyZS5wcm90b3R5cGUuc2V0Q29sc1NwYW5uaW5nID0gZnVuY3Rpb24gKGNvbHNTcGFubmluZykge1xuICAgICAgICB0aGlzLmNvbHNTcGFubmluZyA9IGNvbHNTcGFubmluZztcbiAgICAgICAgdGhpcy5vbkxlZnRDaGFuZ2VkKCk7XG4gICAgfTtcbiAgICBTZXRMZWZ0RmVhdHVyZS5wcm90b3R5cGUuZ2V0Q29sdW1uT3JHcm91cCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkgJiYgdGhpcy5jb2xzU3Bhbm5pbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBsYXN0KHRoaXMuY29sc1NwYW5uaW5nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Pckdyb3VwO1xuICAgIH07XG4gICAgU2V0TGVmdEZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuY29sdW1uT3JHcm91cCwgQ29sdW1uLkVWRU5UX0xFRlRfQ0hBTkdFRCwgdGhpcy5vbkxlZnRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLnNldExlZnRGaXJzdFRpbWUoKTtcbiAgICAgICAgLy8gd2hlbiBpbiBwcmludCBsYXlvdXQsIHRoZSBsZWZ0IHBvc2l0aW9uIGlzIGFsc28gZGVwZW5kZW50IG9uIHRoZSB3aWR0aCBvZiB0aGUgcGlubmVkIHNlY3Rpb25zLlxuICAgICAgICAvLyBzbyBhZGRpdGlvbmFsbHkgdXBkYXRlIGxlZnQgaWYgYW55IGNvbHVtbiB3aWR0aCBjaGFuZ2VzLlxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX1dJRFRIX0NIQU5HRUQsIHRoaXMub25MZWZ0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgLy8gc2V0dGluZyBsZWZ0IGhhcyBhIGRlcGVuZGVuY3kgb24gcHJpbnQgbGF5b3V0XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET01fTEFZT1VULCB0aGlzLm9uTGVmdENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBTZXRMZWZ0RmVhdHVyZS5wcm90b3R5cGUuc2V0TGVmdEZpcnN0VGltZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHN1cHByZXNzTW92ZUFuaW1hdGlvbiA9IHRoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NDb2x1bW5Nb3ZlQW5pbWF0aW9uKCk7XG4gICAgICAgIHZhciBvbGRMZWZ0RXhpc3RzID0gZXhpc3RzKHRoaXMuY29sdW1uT3JHcm91cC5nZXRPbGRMZWZ0KCkpO1xuICAgICAgICB2YXIgYW5pbWF0ZUNvbHVtbk1vdmUgPSB0aGlzLmJlYW5zLmNvbHVtbkFuaW1hdGlvblNlcnZpY2UuaXNBY3RpdmUoKSAmJiBvbGRMZWZ0RXhpc3RzICYmICFzdXBwcmVzc01vdmVBbmltYXRpb247XG4gICAgICAgIGlmIChhbmltYXRlQ29sdW1uTW92ZSkge1xuICAgICAgICAgICAgdGhpcy5hbmltYXRlSW5MZWZ0KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm9uTGVmdENoYW5nZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2V0TGVmdEZlYXR1cmUucHJvdG90eXBlLmFuaW1hdGVJbkxlZnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb2xPckdyb3VwID0gdGhpcy5nZXRDb2x1bW5Pckdyb3VwKCk7XG4gICAgICAgIHZhciBsZWZ0ID0gY29sT3JHcm91cC5nZXRMZWZ0KCk7XG4gICAgICAgIHZhciBvbGRMZWZ0ID0gY29sT3JHcm91cC5nZXRPbGRMZWZ0KCk7XG4gICAgICAgIHZhciBvbGRBY3R1YWxMZWZ0ID0gdGhpcy5tb2RpZnlMZWZ0Rm9yUHJpbnRMYXlvdXQoY29sT3JHcm91cCwgb2xkTGVmdCk7XG4gICAgICAgIHZhciBhY3R1YWxMZWZ0ID0gdGhpcy5tb2RpZnlMZWZ0Rm9yUHJpbnRMYXlvdXQoY29sT3JHcm91cCwgbGVmdCk7XG4gICAgICAgIHRoaXMuc2V0TGVmdChvbGRBY3R1YWxMZWZ0KTtcbiAgICAgICAgLy8gd2UgbXVzdCBrZWVwIHRyYWNrIG9mIHRoZSBsZWZ0IHdlIHdhbnQgdG8gc2V0IHRvLCBhcyB0aGlzIHdvdWxkIG90aGVyd2lzZSBsZWFkIHRvIGEgcmFjZVxuICAgICAgICAvLyBjb25kaXRpb24sIGlmIHRoZSB1c2VyIGNoYW5nZWQgdGhlIGxlZnQgdmFsdWUgbWFueSB0aW1lcyBpbiBvbmUgVk0gdHVybiwgdGhlbiB3ZSB3YW50IHRvIG1ha2VcbiAgICAgICAgLy8gbWFrZSBzdXJlIHRoZSBhY3R1YWxMZWZ0IHdlIHNldCBpbiB0aGUgdGltZW91dCBiZWxvdyAoaW4gdGhlIG5leHQgVk0gdHVybikgaXMgdGhlIGNvcnJlY3QgbGVmdFxuICAgICAgICAvLyBwb3NpdGlvbi4gZWcgaWYgdXNlciBjaGFuZ2VzIGNvbHVtbiBwb3NpdGlvbiB0d2ljZSwgdGhlbiBzZXRMZWZ0KCkgYmVsb3cgZXhlY3V0ZXMgdHdpY2UgaW4gbmV4dFxuICAgICAgICAvLyBWTSB0dXJuLCBidXQgb25seSBvbmUgKHRoZSBjb3JyZWN0IG9uZSkgc2hvdWxkIGdldCBhcHBsaWVkLlxuICAgICAgICB0aGlzLmFjdHVhbExlZnQgPSBhY3R1YWxMZWZ0O1xuICAgICAgICB0aGlzLmJlYW5zLmNvbHVtbkFuaW1hdGlvblNlcnZpY2UuZXhlY3V0ZU5leHRWTVR1cm4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gdGVzdCB0aGlzIGxlZnQgdmFsdWUgaXMgdGhlIGxhdGVzdCBvbmUgdG8gYmUgYXBwbGllZCwgYW5kIGlmIG5vdCwgZG8gbm90aGluZ1xuICAgICAgICAgICAgaWYgKF90aGlzLmFjdHVhbExlZnQgPT09IGFjdHVhbExlZnQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5zZXRMZWZ0KGFjdHVhbExlZnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFNldExlZnRGZWF0dXJlLnByb3RvdHlwZS5vbkxlZnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sT3JHcm91cCA9IHRoaXMuZ2V0Q29sdW1uT3JHcm91cCgpO1xuICAgICAgICB2YXIgbGVmdCA9IGNvbE9yR3JvdXAuZ2V0TGVmdCgpO1xuICAgICAgICB0aGlzLmFjdHVhbExlZnQgPSB0aGlzLm1vZGlmeUxlZnRGb3JQcmludExheW91dChjb2xPckdyb3VwLCBsZWZ0KTtcbiAgICAgICAgdGhpcy5zZXRMZWZ0KHRoaXMuYWN0dWFsTGVmdCk7XG4gICAgfTtcbiAgICBTZXRMZWZ0RmVhdHVyZS5wcm90b3R5cGUubW9kaWZ5TGVmdEZvclByaW50TGF5b3V0ID0gZnVuY3Rpb24gKGNvbE9yR3JvdXAsIGxlZnRQb3NpdGlvbikge1xuICAgICAgICB2YXIgcHJpbnRMYXlvdXQgPSB0aGlzLmJlYW5zLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21MYXlvdXQoKSA9PT0gQ29uc3RhbnRzLkRPTV9MQVlPVVRfUFJJTlQ7XG4gICAgICAgIGlmICghcHJpbnRMYXlvdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBsZWZ0UG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbE9yR3JvdXAuZ2V0UGlubmVkKCkgPT09IENvbnN0YW50cy5QSU5ORURfTEVGVCkge1xuICAgICAgICAgICAgcmV0dXJuIGxlZnRQb3NpdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbGVmdFdpZHRoID0gdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2x1bW5zTGVmdFdpZHRoKCk7XG4gICAgICAgIGlmIChjb2xPckdyb3VwLmdldFBpbm5lZCgpID09PSBDb25zdGFudHMuUElOTkVEX1JJR0hUKSB7XG4gICAgICAgICAgICB2YXIgYm9keVdpZHRoID0gdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5nZXRCb2R5Q29udGFpbmVyV2lkdGgoKTtcbiAgICAgICAgICAgIHJldHVybiBsZWZ0V2lkdGggKyBib2R5V2lkdGggKyBsZWZ0UG9zaXRpb247XG4gICAgICAgIH1cbiAgICAgICAgLy8gaXMgaW4gYm9keVxuICAgICAgICByZXR1cm4gbGVmdFdpZHRoICsgbGVmdFBvc2l0aW9uO1xuICAgIH07XG4gICAgU2V0TGVmdEZlYXR1cmUucHJvdG90eXBlLnNldExlZnQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgLy8gaWYgdGhlIHZhbHVlIGlzIG51bGwsIHRoZW4gdGhhdCBtZWFucyB0aGUgY29sdW1uIGlzIG5vIGxvbmdlclxuICAgICAgICAvLyBkaXNwbGF5ZWQuIHRoZXJlIGlzIGxvZ2ljIGluIHRoZSByZW5kZXJpbmcgdG8gZmFkZSB0aGVzZSBjb2x1bW5zXG4gICAgICAgIC8vIG91dCwgc28gd2UgZG9uJ3QgdHJ5IGFuZCBjaGFuZ2UgdGhlaXIgbGVmdCBwb3NpdGlvbnMuXG4gICAgICAgIGlmIChleGlzdHModmFsdWUpKSB7XG4gICAgICAgICAgICB0aGlzLmVDZWxsLnN0eWxlLmxlZnQgPSB2YWx1ZSArIFwicHhcIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaW5kZXhDb2x1bW47XG4gICAgICAgIGlmICh0aGlzLmNvbHVtbk9yR3JvdXAgaW5zdGFuY2VvZiBDb2x1bW4pIHtcbiAgICAgICAgICAgIGluZGV4Q29sdW1uID0gdGhpcy5jb2x1bW5Pckdyb3VwO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGNvbHVtbkdyb3VwID0gdGhpcy5jb2x1bW5Pckdyb3VwO1xuICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gY29sdW1uR3JvdXAuZ2V0TGVhZkNvbHVtbnMoKTtcbiAgICAgICAgICAgIGlmICghY2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICBzZXRBcmlhQ29sU3Bhbih0aGlzLmFyaWFFbCwgY2hpbGRyZW4ubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGluZGV4Q29sdW1uID0gY2hpbGRyZW5bMF07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5iZWFucy5jb2x1bW5Nb2RlbC5nZXRBcmlhQ29sdW1uSW5kZXgoaW5kZXhDb2x1bW4pO1xuICAgICAgICBzZXRBcmlhQ29sSW5kZXgodGhpcy5hcmlhRWwsIGluZGV4KTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMXEoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgU2V0TGVmdEZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFNldExlZnRGZWF0dXJlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDF4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxcCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEhvdmVyRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMXgoSG92ZXJGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhvdmVyRmVhdHVyZShjb2x1bW5zLCBlbGVtZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmNvbHVtbnMgPSBjb2x1bW5zO1xuICAgICAgICBfdGhpcy5lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBIb3ZlckZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0NvbHVtbkhvdmVySGlnaGxpZ2h0KCkpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkTW91c2VIb3Zlckxpc3RlbmVycygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIb3ZlckZlYXR1cmUucHJvdG90eXBlLmFkZE1vdXNlSG92ZXJMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZWxlbWVudCwgJ21vdXNlb3V0JywgdGhpcy5vbk1vdXNlT3V0LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVsZW1lbnQsICdtb3VzZW92ZXInLCB0aGlzLm9uTW91c2VPdmVyLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgSG92ZXJGZWF0dXJlLnByb3RvdHlwZS5vbk1vdXNlT3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNvbHVtbkhvdmVyU2VydmljZS5jbGVhck1vdXNlT3ZlcigpO1xuICAgIH07XG4gICAgSG92ZXJGZWF0dXJlLnByb3RvdHlwZS5vbk1vdXNlT3ZlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb2x1bW5Ib3ZlclNlcnZpY2Uuc2V0TW91c2VPdmVyKHRoaXMuY29sdW1ucyk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFwKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Ib3ZlclNlcnZpY2UnKVxuICAgIF0sIEhvdmVyRmVhdHVyZS5wcm90b3R5cGUsIFwiY29sdW1uSG92ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxcChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBIb3ZlckZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEhvdmVyRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxdyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMW8gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBIZWFkZXJGaWx0ZXJDZWxsQ3RybCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMXcoSGVhZGVyRmlsdGVyQ2VsbEN0cmwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gSGVhZGVyRmlsdGVyQ2VsbEN0cmwoY29sdW1uLCBwYXJlbnRSb3dDdHJsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNvbHVtbiwgcGFyZW50Um93Q3RybCkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY29sdW1uID0gY29sdW1uO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEhlYWRlckZpbHRlckNlbGxDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGNvbXAsIGVHdWksIGVCdXR0b25TaG93TWFpbkZpbHRlciwgZUZsb2F0aW5nRmlsdGVyQm9keSkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnNldEd1aS5jYWxsKHRoaXMsIGVHdWkpO1xuICAgICAgICB0aGlzLmNvbXAgPSBjb21wO1xuICAgICAgICB0aGlzLmVCdXR0b25TaG93TWFpbkZpbHRlciA9IGVCdXR0b25TaG93TWFpbkZpbHRlcjtcbiAgICAgICAgdGhpcy5lRmxvYXRpbmdGaWx0ZXJCb2R5ID0gZUZsb2F0aW5nRmlsdGVyQm9keTtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB2YXIgZmlsdGVyRXhpc3RzID0gISFjb2xEZWYuZmlsdGVyIHx8ICEhY29sRGVmLmZpbHRlckZyYW1ld29yaztcbiAgICAgICAgdmFyIGZsb2F0aW5nRmlsdGVyRXhpc3RzID0gISFjb2xEZWYuZmxvYXRpbmdGaWx0ZXI7XG4gICAgICAgIHRoaXMuYWN0aXZlID0gZmlsdGVyRXhpc3RzICYmIGZsb2F0aW5nRmlsdGVyRXhpc3RzO1xuICAgICAgICB0aGlzLnNldHVwV2lkdGgoKTtcbiAgICAgICAgdGhpcy5zZXR1cExlZnQoKTtcbiAgICAgICAgdGhpcy5zZXR1cEhvdmVyKCk7XG4gICAgICAgIHRoaXMuc2V0dXBGb2N1cygpO1xuICAgICAgICB0aGlzLnNldHVwVXNlckNvbXAoKTtcbiAgICAgICAgdGhpcy5zZXR1cFN5bmNXaXRoRmlsdGVyKCk7XG4gICAgICAgIHRoaXMuc2V0dXBVaSgpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVCdXR0b25TaG93TWFpbkZpbHRlciwgJ2NsaWNrJywgdGhpcy5zaG93UGFyZW50RmlsdGVyLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwVWkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUJ1dHRvbldyYXBwZXJDc3NDbGFzcygnYWctaGlkZGVuJywgIXRoaXMuYWN0aXZlIHx8IHRoaXMuc3VwcHJlc3NGaWx0ZXJCdXR0b24pO1xuICAgICAgICBpZiAoIXRoaXMuYWN0aXZlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb21wLmFkZE9yUmVtb3ZlQm9keUNzc0NsYXNzKCdhZy1mbG9hdGluZy1maWx0ZXItZnVsbC1ib2R5JywgdGhpcy5zdXBwcmVzc0ZpbHRlckJ1dHRvbik7XG4gICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUJvZHlDc3NDbGFzcygnYWctZmxvYXRpbmctZmlsdGVyLWJvZHknLCAhdGhpcy5zdXBwcmVzc0ZpbHRlckJ1dHRvbik7XG4gICAgICAgIHZhciBlTWVudUljb24gPSBjcmVhdGVJY29uTm9TcGFuKCdmaWx0ZXInLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgdGhpcy5jb2x1bW4pO1xuICAgICAgICBpZiAoZU1lbnVJY29uKSB7XG4gICAgICAgICAgICB0aGlzLmVCdXR0b25TaG93TWFpbkZpbHRlci5hcHBlbmRDaGlsZChlTWVudUljb24pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBGb2N1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgTWFuYWdlZEZvY3VzRmVhdHVyZSh0aGlzLmVHdWksIHtcbiAgICAgICAgICAgIHNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uOiB0aGlzLnNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uLmJpbmQodGhpcyksXG4gICAgICAgICAgICBvblRhYktleURvd246IHRoaXMub25UYWJLZXlEb3duLmJpbmQodGhpcyksXG4gICAgICAgICAgICBoYW5kbGVLZXlEb3duOiB0aGlzLmhhbmRsZUtleURvd24uYmluZCh0aGlzKSxcbiAgICAgICAgICAgIG9uRm9jdXNJbjogdGhpcy5vbkZvY3VzSW4uYmluZCh0aGlzKVxuICAgICAgICB9KSk7XG4gICAgfTtcbiAgICBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUub25UYWJLZXlEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIHZhciBhY3RpdmVFbCA9IGVEb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuICAgICAgICB2YXIgd3JhcHBlckhhc0ZvY3VzID0gYWN0aXZlRWwgPT09IHRoaXMuZUd1aTtcbiAgICAgICAgaWYgKHdyYXBwZXJIYXNGb2N1cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXh0Rm9jdXNhYmxlRWwgPSB0aGlzLmZvY3VzU2VydmljZS5maW5kTmV4dEZvY3VzYWJsZUVsZW1lbnQodGhpcy5lR3VpLCBudWxsLCBlLnNoaWZ0S2V5KTtcbiAgICAgICAgaWYgKG5leHRGb2N1c2FibGVFbCkge1xuICAgICAgICAgICAgdGhpcy5iZWFucy5oZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5zY3JvbGxUb0NvbHVtbih0aGlzLmNvbHVtbik7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBuZXh0Rm9jdXNhYmxlRWwuZm9jdXMoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV4dEZvY3VzYWJsZUNvbHVtbiA9IHRoaXMuZmluZE5leHRDb2x1bW5XaXRoRmxvYXRpbmdGaWx0ZXIoZS5zaGlmdEtleSk7XG4gICAgICAgIGlmICghbmV4dEZvY3VzYWJsZUNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmZvY3VzU2VydmljZS5mb2N1c0hlYWRlclBvc2l0aW9uKHtcbiAgICAgICAgICAgIGhlYWRlclBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgaGVhZGVyUm93SW5kZXg6IHRoaXMuZ2V0UGFyZW50Um93Q3RybCgpLmdldFJvd0luZGV4KCksXG4gICAgICAgICAgICAgICAgY29sdW1uOiBuZXh0Rm9jdXNhYmxlQ29sdW1uXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXZlbnQ6IGVcbiAgICAgICAgfSkpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLmZpbmROZXh0Q29sdW1uV2l0aEZsb2F0aW5nRmlsdGVyID0gZnVuY3Rpb24gKGJhY2t3YXJkcykge1xuICAgICAgICB2YXIgY29sdW1Nb2RlbCA9IHRoaXMuYmVhbnMuY29sdW1uTW9kZWw7XG4gICAgICAgIHZhciBuZXh0Q29sID0gdGhpcy5jb2x1bW47XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIG5leHRDb2wgPSBiYWNrd2FyZHNcbiAgICAgICAgICAgICAgICA/IGNvbHVtTW9kZWwuZ2V0RGlzcGxheWVkQ29sQmVmb3JlKG5leHRDb2wpXG4gICAgICAgICAgICAgICAgOiBjb2x1bU1vZGVsLmdldERpc3BsYXllZENvbEFmdGVyKG5leHRDb2wpO1xuICAgICAgICAgICAgaWYgKCFuZXh0Q29sKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gd2hpbGUgKCFuZXh0Q29sLmdldENvbERlZigpLmZpbHRlciB8fCAhbmV4dENvbC5nZXRDb2xEZWYoKS5mbG9hdGluZ0ZpbHRlcik7XG4gICAgICAgIHJldHVybiBuZXh0Q29sO1xuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmhhbmRsZUtleURvd24uY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgdmFyIHdyYXBwZXJIYXNGb2N1cyA9IHRoaXMuZ2V0V3JhcHBlckhhc0ZvY3VzKCk7XG4gICAgICAgIHN3aXRjaCAoZS5rZXkpIHtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5VUDpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgICAgIGlmICghd3JhcHBlckhhc0ZvY3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuTEVGVDpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5SSUdIVDpcbiAgICAgICAgICAgICAgICBpZiAod3JhcHBlckhhc0ZvY3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5FTlRFUjpcbiAgICAgICAgICAgICAgICBpZiAod3JhcHBlckhhc0ZvY3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmZvY3VzU2VydmljZS5mb2N1c0ludG8odGhpcy5lR3VpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkVTQ0FQRTpcbiAgICAgICAgICAgICAgICBpZiAoIXdyYXBwZXJIYXNGb2N1cykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVHdWkuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlckZpbHRlckNlbGxDdHJsLnByb3RvdHlwZS5vbkZvY3VzSW4gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgaXNSZWxhdGVkV2l0aGluID0gdGhpcy5lR3VpLmNvbnRhaW5zKGUucmVsYXRlZFRhcmdldCk7XG4gICAgICAgIC8vIHdoZW4gdGhlIGZvY3VzIGlzIGFscmVhZHkgd2l0aGluIHRoZSBjb21wb25lbnQsXG4gICAgICAgIC8vIHdlIGRlZmF1bHQgdG8gdGhlIGJyb3dzZXIncyBiZWhhdmlvclxuICAgICAgICBpZiAoaXNSZWxhdGVkV2l0aGluKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5vdEZyb21IZWFkZXJXcmFwcGVyID0gISFlLnJlbGF0ZWRUYXJnZXQgJiYgIWUucmVsYXRlZFRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoJ2FnLWZsb2F0aW5nLWZpbHRlcicpO1xuICAgICAgICB2YXIgZnJvbVdpdGhpbkhlYWRlciA9ICEhZS5yZWxhdGVkVGFyZ2V0ICYmIGlzRWxlbWVudENoaWxkT2ZDbGFzcyhlLnJlbGF0ZWRUYXJnZXQsICdhZy1mbG9hdGluZy1maWx0ZXInKTtcbiAgICAgICAgaWYgKG5vdEZyb21IZWFkZXJXcmFwcGVyICYmIGZyb21XaXRoaW5IZWFkZXIgJiYgZS50YXJnZXQgPT09IHRoaXMuZUd1aSkge1xuICAgICAgICAgICAgdmFyIGxhc3RGb2N1c0V2ZW50ID0gdGhpcy5sYXN0Rm9jdXNFdmVudDtcbiAgICAgICAgICAgIHZhciBmcm9tVGFiID0gISEobGFzdEZvY3VzRXZlbnQgJiYgbGFzdEZvY3VzRXZlbnQua2V5ID09PSBLZXlDb2RlLlRBQik7XG4gICAgICAgICAgICBpZiAobGFzdEZvY3VzRXZlbnQgJiYgZnJvbVRhYikge1xuICAgICAgICAgICAgICAgIHZhciBzaG91bGRGb2N1c0xhc3QgPSBsYXN0Rm9jdXNFdmVudC5zaGlmdEtleTtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5mb2N1c0ludG8odGhpcy5lR3VpLCBzaG91bGRGb2N1c0xhc3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciByb3dJbmRleCA9IHRoaXMuZ2V0Um93SW5kZXgoKTtcbiAgICAgICAgdGhpcy5iZWFucy5mb2N1c1NlcnZpY2Uuc2V0Rm9jdXNlZEhlYWRlcihyb3dJbmRleCwgdGhpcy5jb2x1bW4pO1xuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwSG92ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEhvdmVyRmVhdHVyZShbdGhpcy5jb2x1bW5dLCB0aGlzLmVHdWkpKTtcbiAgICAgICAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNDb2x1bW5Ib3ZlckhpZ2hsaWdodCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGhvdmVyZWQgPSBfdGhpcy5jb2x1bW5Ib3ZlclNlcnZpY2UuaXNIb3ZlcmVkKF90aGlzLmNvbHVtbik7XG4gICAgICAgICAgICBfdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWNvbHVtbi1ob3ZlcicsIGhvdmVyZWQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9IT1ZFUl9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBMZWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2V0TGVmdEZlYXR1cmUgPSBuZXcgU2V0TGVmdEZlYXR1cmUodGhpcy5jb2x1bW4sIHRoaXMuZUd1aSwgdGhpcy5iZWFucyk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4oc2V0TGVmdEZlYXR1cmUpO1xuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwVXNlckNvbXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIHZhciBmaWx0ZXJQYXJhbXMgPSB0aGlzLmZpbHRlck1hbmFnZXIuY3JlYXRlRmlsdGVyUGFyYW1zKHRoaXMuY29sdW1uLCBjb2xEZWYpO1xuICAgICAgICB2YXIgZmluYWxGaWx0ZXJQYXJhbXMgPSB0aGlzLnVzZXJDb21wb25lbnRGYWN0b3J5Lm1lcmdlUGFyYW1zV2l0aEFwcGxpY2F0aW9uUHJvdmlkZWRQYXJhbXMoY29sRGVmLCBGaWx0ZXJDb21wb25lbnQsIGZpbHRlclBhcmFtcyk7XG4gICAgICAgIHZhciBkZWZhdWx0RmxvYXRpbmdGaWx0ZXJUeXBlID0gdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeS5nZXREZWZhdWx0RmxvYXRpbmdGaWx0ZXJUeXBlKGNvbERlZik7XG4gICAgICAgIGlmIChkZWZhdWx0RmxvYXRpbmdGaWx0ZXJUeXBlID09IG51bGwpIHtcbiAgICAgICAgICAgIGRlZmF1bHRGbG9hdGluZ0ZpbHRlclR5cGUgPSAnYWdSZWFkT25seUZsb2F0aW5nRmlsdGVyJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgY29sdW1uOiB0aGlzLmNvbHVtbixcbiAgICAgICAgICAgIGZpbHRlclBhcmFtczogZmluYWxGaWx0ZXJQYXJhbXMsXG4gICAgICAgICAgICBjdXJyZW50UGFyZW50TW9kZWw6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmN1cnJlbnRQYXJlbnRNb2RlbCgpOyB9LFxuICAgICAgICAgICAgcGFyZW50RmlsdGVySW5zdGFuY2U6IGZ1bmN0aW9uIChjYikgeyByZXR1cm4gX3RoaXMucGFyZW50RmlsdGVySW5zdGFuY2UoY2IpOyB9LFxuICAgICAgICAgICAgc2hvd1BhcmVudEZpbHRlcjogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuc2hvd1BhcmVudEZpbHRlcigpOyB9LFxuICAgICAgICAgICAgc3VwcHJlc3NGaWx0ZXJCdXR0b246IGZhbHNlIC8vIFRoaXMgb25lIG1pZ2h0IGJlIG92ZXJyaWRkZW4gZnJvbSB0aGUgY29sRGVmXG4gICAgICAgIH07XG4gICAgICAgIC8vIHRoaXMgaXMgdW51c3VhbCAtIHdlIG5lZWQgYSBwYXJhbXMgdmFsdWUgT1VUU0lERSB0aGUgY29tcG9uZW50IHRoZSBwYXJhbXMgYXJlIGZvci5cbiAgICAgICAgLy8gdGhlIHBhcmFtcyBhcmUgZm9yIHRoZSBmbG9hdGluZyBmaWx0ZXIgY29tcG9uZW50LCBidXQgdGhpcyBwcm9wZXJ0eSBpcyBhY3R1YWxseSBmb3IgdGhlIHdyYXBwZXIuXG4gICAgICAgIHRoaXMuc3VwcHJlc3NGaWx0ZXJCdXR0b24gPSBjb2xEZWYuZmxvYXRpbmdGaWx0ZXJDb21wb25lbnRQYXJhbXMgPyAhIWNvbERlZi5mbG9hdGluZ0ZpbHRlckNvbXBvbmVudFBhcmFtcy5zdXBwcmVzc0ZpbHRlckJ1dHRvbiA6IGZhbHNlO1xuICAgICAgICB2YXIgY29tcERldGFpbHMgPSB0aGlzLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldEZsb2F0aW5nRmlsdGVyQ29tcERldGFpbHMoY29sRGVmLCBwYXJhbXMsIGRlZmF1bHRGbG9hdGluZ0ZpbHRlclR5cGUpO1xuICAgICAgICBpZiAoY29tcERldGFpbHMpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXRDb21wRGV0YWlscyhjb21wRGV0YWlscyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlckZpbHRlckNlbGxDdHJsLnByb3RvdHlwZS5jdXJyZW50UGFyZW50TW9kZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmaWx0ZXJDb21wb25lbnQgPSB0aGlzLmdldEZpbHRlckNvbXBvbmVudChmYWxzZSk7XG4gICAgICAgIHJldHVybiBmaWx0ZXJDb21wb25lbnQgPyBmaWx0ZXJDb21wb25lbnQucmVzb2x2ZU5vdyhudWxsLCBmdW5jdGlvbiAoZmlsdGVyKSB7IHJldHVybiBmaWx0ZXIgJiYgZmlsdGVyLmdldE1vZGVsKCk7IH0pIDogbnVsbDtcbiAgICB9O1xuICAgIEhlYWRlckZpbHRlckNlbGxDdHJsLnByb3RvdHlwZS5nZXRGaWx0ZXJDb21wb25lbnQgPSBmdW5jdGlvbiAoY3JlYXRlSWZEb2VzTm90RXhpc3QpIHtcbiAgICAgICAgaWYgKGNyZWF0ZUlmRG9lc05vdEV4aXN0ID09PSB2b2lkIDApIHsgY3JlYXRlSWZEb2VzTm90RXhpc3QgPSB0cnVlOyB9XG4gICAgICAgIHJldHVybiB0aGlzLmZpbHRlck1hbmFnZXIuZ2V0RmlsdGVyQ29tcG9uZW50KHRoaXMuY29sdW1uLCAnTk9fVUknLCBjcmVhdGVJZkRvZXNOb3RFeGlzdCk7XG4gICAgfTtcbiAgICBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUucGFyZW50RmlsdGVySW5zdGFuY2UgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGZpbHRlckNvbXBvbmVudCA9IHRoaXMuZ2V0RmlsdGVyQ29tcG9uZW50KCk7XG4gICAgICAgIGlmIChmaWx0ZXJDb21wb25lbnQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZpbHRlckNvbXBvbmVudC50aGVuKGZ1bmN0aW9uIChpbnN0YW5jZSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodW53cmFwVXNlckNvbXAoaW5zdGFuY2UpKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUuc2hvd1BhcmVudEZpbHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGV2ZW50U291cmNlID0gdGhpcy5zdXBwcmVzc0ZpbHRlckJ1dHRvbiA/IHRoaXMuZUZsb2F0aW5nRmlsdGVyQm9keSA6IHRoaXMuZUJ1dHRvblNob3dNYWluRmlsdGVyO1xuICAgICAgICB0aGlzLm1lbnVGYWN0b3J5LnNob3dNZW51QWZ0ZXJCdXR0b25DbGljayh0aGlzLmNvbHVtbiwgZXZlbnRTb3VyY2UsICdmbG9hdGluZ0ZpbHRlcicsICdmaWx0ZXJNZW51VGFiJywgWydmaWx0ZXJNZW51VGFiJ10pO1xuICAgIH07XG4gICAgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwU3luY1dpdGhGaWx0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3luY1dpdGhGaWx0ZXIgPSBmdW5jdGlvbiAoZmlsdGVyQ2hhbmdlZEV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgY29tcFByb21pc2UgPSBfdGhpcy5jb21wLmdldEZsb2F0aW5nRmlsdGVyQ29tcCgpO1xuICAgICAgICAgICAgaWYgKCFjb21wUHJvbWlzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwYXJlbnRNb2RlbCA9IF90aGlzLmN1cnJlbnRQYXJlbnRNb2RlbCgpO1xuICAgICAgICAgICAgY29tcFByb21pc2UudGhlbihmdW5jdGlvbiAoY29tcCkge1xuICAgICAgICAgICAgICAgIGlmIChjb21wKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXAub25QYXJlbnRNb2RlbENoYW5nZWQocGFyZW50TW9kZWwsIGZpbHRlckNoYW5nZWRFdmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuY29sdW1uLCBDb2x1bW4uRVZFTlRfRklMVEVSX0NIQU5HRUQsIHN5bmNXaXRoRmlsdGVyKTtcbiAgICAgICAgaWYgKHRoaXMuZmlsdGVyTWFuYWdlci5pc0ZpbHRlckFjdGl2ZSh0aGlzLmNvbHVtbikpIHtcbiAgICAgICAgICAgIHN5bmNXaXRoRmlsdGVyKG51bGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHdpZHRoID0gX3RoaXMuY29sdW1uLmdldEFjdHVhbFdpZHRoKCkgKyBcInB4XCI7XG4gICAgICAgICAgICBfdGhpcy5jb21wLnNldFdpZHRoKHdpZHRoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5jb2x1bW4sIENvbHVtbi5FVkVOVF9XSURUSF9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFvKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwiZmlsdGVyTWFuYWdlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMW8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbkhvdmVyU2VydmljZScpXG4gICAgXSwgSGVhZGVyRmlsdGVyQ2VsbEN0cmwucHJvdG90eXBlLCBcImNvbHVtbkhvdmVyU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMW8oW1xuICAgICAgICBBdXRvd2lyZWQoJ21lbnVGYWN0b3J5JylcbiAgICBdLCBIZWFkZXJGaWx0ZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwibWVudUZhY3RvcnlcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gSGVhZGVyRmlsdGVyQ2VsbEN0cmw7XG59KEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxdiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMW4gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBSZXNpemVGZWF0dXJlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxdihSZXNpemVGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJlc2l6ZUZlYXR1cmUocGlubmVkLCBjb2x1bW4sIGVSZXNpemUsIGNvbXAsIGN0cmwpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucGlubmVkID0gcGlubmVkO1xuICAgICAgICBfdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIF90aGlzLmVSZXNpemUgPSBlUmVzaXplO1xuICAgICAgICBfdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgX3RoaXMuY3RybCA9IGN0cmw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUmVzaXplRmVhdHVyZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICB2YXIgZGVzdHJveVJlc2l6ZUZ1bmNzID0gW107XG4gICAgICAgIHZhciBjYW5SZXNpemU7XG4gICAgICAgIHZhciBjYW5BdXRvc2l6ZTtcbiAgICAgICAgdmFyIGFkZFJlc2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNldERpc3BsYXllZChfdGhpcy5lUmVzaXplLCBjYW5SZXNpemUpO1xuICAgICAgICAgICAgaWYgKCFjYW5SZXNpemUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZmluaXNoZWRXaXRoUmVzaXplRnVuYyA9IF90aGlzLmhvcml6b250YWxSZXNpemVTZXJ2aWNlLmFkZFJlc2l6ZUJhcih7XG4gICAgICAgICAgICAgICAgZVJlc2l6ZUJhcjogX3RoaXMuZVJlc2l6ZSxcbiAgICAgICAgICAgICAgICBvblJlc2l6ZVN0YXJ0OiBfdGhpcy5vblJlc2l6ZVN0YXJ0LmJpbmQoX3RoaXMpLFxuICAgICAgICAgICAgICAgIG9uUmVzaXppbmc6IF90aGlzLm9uUmVzaXppbmcuYmluZChfdGhpcywgZmFsc2UpLFxuICAgICAgICAgICAgICAgIG9uUmVzaXplRW5kOiBfdGhpcy5vblJlc2l6aW5nLmJpbmQoX3RoaXMsIHRydWUpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlc3Ryb3lSZXNpemVGdW5jcy5wdXNoKGZpbmlzaGVkV2l0aFJlc2l6ZUZ1bmMpO1xuICAgICAgICAgICAgaWYgKGNhbkF1dG9zaXplKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNraXBIZWFkZXJPbkF1dG9TaXplXzEgPSBfdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTa2lwSGVhZGVyT25BdXRvU2l6ZSgpO1xuICAgICAgICAgICAgICAgIHZhciBhdXRvU2l6ZUNvbExpc3RlbmVyXzEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbHVtbk1vZGVsLmF1dG9TaXplQ29sdW1uKF90aGlzLmNvbHVtbiwgc2tpcEhlYWRlck9uQXV0b1NpemVfMSwgXCJ1aUNvbHVtblJlc2l6ZWRcIik7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBfdGhpcy5lUmVzaXplLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgYXV0b1NpemVDb2xMaXN0ZW5lcl8xKTtcbiAgICAgICAgICAgICAgICB2YXIgdG91Y2hMaXN0ZW5lcl8xID0gbmV3IFRvdWNoTGlzdGVuZXIoX3RoaXMuZVJlc2l6ZSk7XG4gICAgICAgICAgICAgICAgdG91Y2hMaXN0ZW5lcl8xLmFkZEV2ZW50TGlzdGVuZXIoVG91Y2hMaXN0ZW5lci5FVkVOVF9ET1VCTEVfVEFQLCBhdXRvU2l6ZUNvbExpc3RlbmVyXzEpO1xuICAgICAgICAgICAgICAgIF90aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZVJlc2l6ZS5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGF1dG9TaXplQ29sTGlzdGVuZXJfMSk7XG4gICAgICAgICAgICAgICAgICAgIHRvdWNoTGlzdGVuZXJfMS5yZW1vdmVFdmVudExpc3RlbmVyKFRvdWNoTGlzdGVuZXIuRVZFTlRfRE9VQkxFX1RBUCwgYXV0b1NpemVDb2xMaXN0ZW5lcl8xKTtcbiAgICAgICAgICAgICAgICAgICAgdG91Y2hMaXN0ZW5lcl8xLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHJlbW92ZVJlc2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGRlc3Ryb3lSZXNpemVGdW5jcy5mb3JFYWNoKGZ1bmN0aW9uIChmKSB7IHJldHVybiBmKCk7IH0pO1xuICAgICAgICAgICAgZGVzdHJveVJlc2l6ZUZ1bmNzLmxlbmd0aCA9IDA7XG4gICAgICAgIH07XG4gICAgICAgIHZhciByZWZyZXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHJlc2l6ZSA9IF90aGlzLmNvbHVtbi5pc1Jlc2l6YWJsZSgpO1xuICAgICAgICAgICAgdmFyIGF1dG9TaXplID0gIV90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQXV0b1NpemUoKSAmJiAhY29sRGVmLnN1cHByZXNzQXV0b1NpemU7XG4gICAgICAgICAgICB2YXIgcHJvcGVydHlDaGFuZ2UgPSByZXNpemUgIT09IGNhblJlc2l6ZSB8fCBhdXRvU2l6ZSAhPT0gY2FuQXV0b3NpemU7XG4gICAgICAgICAgICBpZiAocHJvcGVydHlDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICBjYW5SZXNpemUgPSByZXNpemU7XG4gICAgICAgICAgICAgICAgY2FuQXV0b3NpemUgPSBhdXRvU2l6ZTtcbiAgICAgICAgICAgICAgICByZW1vdmVSZXNpemUoKTtcbiAgICAgICAgICAgICAgICBhZGRSZXNpemUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcmVmcmVzaCgpO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKHJlbW92ZVJlc2l6ZSk7XG4gICAgICAgIHRoaXMuY3RybC5hZGRSZWZyZXNoRnVuY3Rpb24ocmVmcmVzaCk7XG4gICAgfTtcbiAgICBSZXNpemVGZWF0dXJlLnByb3RvdHlwZS5vblJlc2l6aW5nID0gZnVuY3Rpb24gKGZpbmlzaGVkLCByZXNpemVBbW91bnQpIHtcbiAgICAgICAgdmFyIHJlc2l6ZUFtb3VudE5vcm1hbGlzZWQgPSB0aGlzLm5vcm1hbGlzZVJlc2l6ZUFtb3VudChyZXNpemVBbW91bnQpO1xuICAgICAgICB2YXIgY29sdW1uV2lkdGhzID0gW3sga2V5OiB0aGlzLmNvbHVtbiwgbmV3V2lkdGg6IHRoaXMucmVzaXplU3RhcnRXaWR0aCArIHJlc2l6ZUFtb3VudE5vcm1hbGlzZWQgfV07XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uV2lkdGhzKGNvbHVtbldpZHRocywgdGhpcy5yZXNpemVXaXRoU2hpZnRLZXksIGZpbmlzaGVkLCBcInVpQ29sdW1uRHJhZ2dlZFwiKTtcbiAgICAgICAgaWYgKGZpbmlzaGVkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctY29sdW1uLXJlc2l6aW5nJywgZmFsc2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZXNpemVGZWF0dXJlLnByb3RvdHlwZS5vblJlc2l6ZVN0YXJ0ID0gZnVuY3Rpb24gKHNoaWZ0S2V5KSB7XG4gICAgICAgIHRoaXMucmVzaXplU3RhcnRXaWR0aCA9IHRoaXMuY29sdW1uLmdldEFjdHVhbFdpZHRoKCk7XG4gICAgICAgIHRoaXMucmVzaXplV2l0aFNoaWZ0S2V5ID0gc2hpZnRLZXk7XG4gICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1jb2x1bW4tcmVzaXppbmcnLCB0cnVlKTtcbiAgICB9O1xuICAgIC8vIG9wdGlvbmFsbHkgaW52ZXJ0cyB0aGUgZHJhZywgZGVwZW5kaW5nIG9uIHBpbm5lZCBhbmQgUlRMXG4gICAgLy8gbm90ZSAtIHRoaXMgbWV0aG9kIGlzIGR1cGxpY2F0ZWQgaW4gUmVuZGVyZWRIZWFkZXJHcm91cENlbGwgLSBzaG91bGQgcmVmYWN0b3Igb3V0P1xuICAgIFJlc2l6ZUZlYXR1cmUucHJvdG90eXBlLm5vcm1hbGlzZVJlc2l6ZUFtb3VudCA9IGZ1bmN0aW9uIChkcmFnQ2hhbmdlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBkcmFnQ2hhbmdlO1xuICAgICAgICB2YXIgbm90UGlubmluZ0xlZnQgPSB0aGlzLnBpbm5lZCAhPT0gQ29uc3RhbnRzLlBJTk5FRF9MRUZUO1xuICAgICAgICB2YXIgcGlubmluZ1JpZ2h0ID0gdGhpcy5waW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfUklHSFQ7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICAvLyBmb3IgUlRMLCBkcmFnZ2luZyBsZWZ0IG1ha2VzIHRoZSBjb2wgYmlnZ2VyLCBleGNlcHQgd2hlbiBwaW5uaW5nIGxlZnRcbiAgICAgICAgICAgIGlmIChub3RQaW5uaW5nTGVmdCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCAqPSAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZvciBMVFIgKGllIG5vcm1hbCksIGRyYWdnaW5nIGxlZnQgbWFrZXMgdGhlIGNvbCBzbWFsbGVyLCBleGNlcHQgd2hlbiBwaW5uaW5nIHJpZ2h0XG4gICAgICAgICAgICBpZiAocGlubmluZ1JpZ2h0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICo9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFuKFtcbiAgICAgICAgQXV0b3dpcmVkKCdob3Jpem9udGFsUmVzaXplU2VydmljZScpXG4gICAgXSwgUmVzaXplRmVhdHVyZS5wcm90b3R5cGUsIFwiaG9yaXpvbnRhbFJlc2l6ZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFuKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgUmVzaXplRmVhdHVyZS5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFuKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFJlc2l6ZUZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFJlc2l6ZUZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMXUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBBZ0NoZWNrYm94ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxdShBZ0NoZWNrYm94LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnQ2hlY2tib3goY29uZmlnLCBjbGFzc05hbWUsIGlucHV0VHlwZSkge1xuICAgICAgICBpZiAoY2xhc3NOYW1lID09PSB2b2lkIDApIHsgY2xhc3NOYW1lID0gJ2FnLWNoZWNrYm94JzsgfVxuICAgICAgICBpZiAoaW5wdXRUeXBlID09PSB2b2lkIDApIHsgaW5wdXRUeXBlID0gJ2NoZWNrYm94JzsgfVxuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjb25maWcsIGNsYXNzTmFtZSwgaW5wdXRUeXBlKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5sYWJlbEFsaWdubWVudCA9ICdyaWdodCc7XG4gICAgICAgIF90aGlzLnNlbGVjdGVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnJlYWRPbmx5ID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnBhc3NpdmUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS5hZGRJbnB1dExpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lSW5wdXQsICdjbGljaycsIHRoaXMub25DaGVja2JveENsaWNrLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVMYWJlbCwgJ2NsaWNrJywgdGhpcy50b2dnbGUuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS5nZXROZXh0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkID09PSB1bmRlZmluZWQgPyB0cnVlIDogIXRoaXMuc2VsZWN0ZWQ7XG4gICAgfTtcbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS5zZXRQYXNzaXZlID0gZnVuY3Rpb24gKHBhc3NpdmUpIHtcbiAgICAgICAgdGhpcy5wYXNzaXZlID0gcGFzc2l2ZTtcbiAgICB9O1xuICAgIEFnQ2hlY2tib3gucHJvdG90eXBlLmlzUmVhZE9ubHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlYWRPbmx5O1xuICAgIH07XG4gICAgQWdDaGVja2JveC5wcm90b3R5cGUuc2V0UmVhZE9ubHkgPSBmdW5jdGlvbiAocmVhZE9ubHkpIHtcbiAgICAgICAgdGhpcy5lV3JhcHBlci5jbGFzc0xpc3QudG9nZ2xlKCdhZy1kaXNhYmxlZCcsIHJlYWRPbmx5KTtcbiAgICAgICAgdGhpcy5lSW5wdXQuZGlzYWJsZWQgPSByZWFkT25seTtcbiAgICAgICAgdGhpcy5yZWFkT25seSA9IHJlYWRPbmx5O1xuICAgIH07XG4gICAgQWdDaGVja2JveC5wcm90b3R5cGUuc2V0RGlzYWJsZWQgPSBmdW5jdGlvbiAoZGlzYWJsZWQpIHtcbiAgICAgICAgdGhpcy5lV3JhcHBlci5jbGFzc0xpc3QudG9nZ2xlKCdhZy1kaXNhYmxlZCcsIGRpc2FibGVkKTtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5wcm90b3R5cGUuc2V0RGlzYWJsZWQuY2FsbCh0aGlzLCBkaXNhYmxlZCk7XG4gICAgfTtcbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS50b2dnbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmVJbnB1dC5kaXNhYmxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gdGhpcy5pc1NlbGVjdGVkKCk7XG4gICAgICAgIHZhciBuZXh0VmFsdWUgPSB0aGlzLmdldE5leHRWYWx1ZSgpO1xuICAgICAgICBpZiAodGhpcy5wYXNzaXZlKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoQ2hhbmdlKG5leHRWYWx1ZSwgcHJldmlvdXNWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKG5leHRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQ2hlY2tib3gucHJvdG90eXBlLmdldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1NlbGVjdGVkKCk7XG4gICAgfTtcbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSwgc2lsZW50KSB7XG4gICAgICAgIHRoaXMucmVmcmVzaFNlbGVjdGVkQ2xhc3ModmFsdWUpO1xuICAgICAgICB0aGlzLnNldFNlbGVjdGVkKHZhbHVlLCBzaWxlbnQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQ2hlY2tib3gucHJvdG90eXBlLnNldE5hbWUgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmdldElucHV0RWxlbWVudCgpO1xuICAgICAgICBpbnB1dC5uYW1lID0gbmFtZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS5pc1NlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RlZDtcbiAgICB9O1xuICAgIEFnQ2hlY2tib3gucHJvdG90eXBlLnNldFNlbGVjdGVkID0gZnVuY3Rpb24gKHNlbGVjdGVkLCBzaWxlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTZWxlY3RlZCgpID09PSBzZWxlY3RlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJldmlvdXNWYWx1ZSA9IHRoaXMuaXNTZWxlY3RlZCgpO1xuICAgICAgICBzZWxlY3RlZCA9IHRoaXMuc2VsZWN0ZWQgPSB0eXBlb2Ygc2VsZWN0ZWQgPT09ICdib29sZWFuJyA/IHNlbGVjdGVkIDogdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmVJbnB1dC5jaGVja2VkID0gc2VsZWN0ZWQ7XG4gICAgICAgIHRoaXMuZUlucHV0LmluZGV0ZXJtaW5hdGUgPSBzZWxlY3RlZCA9PT0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIXNpbGVudCkge1xuICAgICAgICAgICAgdGhpcy5kaXNwYXRjaENoYW5nZSh0aGlzLnNlbGVjdGVkLCB0aGlzLnByZXZpb3VzVmFsdWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ0NoZWNrYm94LnByb3RvdHlwZS5kaXNwYXRjaENoYW5nZSA9IGZ1bmN0aW9uIChzZWxlY3RlZCwgcHJldmlvdXNWYWx1ZSwgZXZlbnQpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHsgdHlwZTogQWdDaGVja2JveC5FVkVOVF9DSEFOR0VELCBzZWxlY3RlZDogc2VsZWN0ZWQsIHByZXZpb3VzVmFsdWU6IHByZXZpb3VzVmFsdWUsIGV2ZW50OiBldmVudCB9KTtcbiAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5nZXRJbnB1dEVsZW1lbnQoKTtcbiAgICAgICAgdmFyIGNoZWNrYm94Q2hhbmdlZEV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0NIRUNLQk9YX0NIQU5HRUQsXG4gICAgICAgICAgICBpZDogaW5wdXQuaWQsXG4gICAgICAgICAgICBuYW1lOiBpbnB1dC5uYW1lLFxuICAgICAgICAgICAgc2VsZWN0ZWQ6IHNlbGVjdGVkLFxuICAgICAgICAgICAgcHJldmlvdXNWYWx1ZTogcHJldmlvdXNWYWx1ZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGNoZWNrYm94Q2hhbmdlZEV2ZW50KTtcbiAgICB9O1xuICAgIEFnQ2hlY2tib3gucHJvdG90eXBlLm9uQ2hlY2tib3hDbGljayA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICh0aGlzLnBhc3NpdmUgfHwgdGhpcy5lSW5wdXQuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHRoaXMuaXNTZWxlY3RlZCgpO1xuICAgICAgICB2YXIgc2VsZWN0ZWQgPSB0aGlzLnNlbGVjdGVkID0gZS50YXJnZXQuY2hlY2tlZDtcbiAgICAgICAgdGhpcy5yZWZyZXNoU2VsZWN0ZWRDbGFzcyhzZWxlY3RlZCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hDaGFuZ2Uoc2VsZWN0ZWQsIHByZXZpb3VzVmFsdWUsIGUpO1xuICAgIH07XG4gICAgQWdDaGVja2JveC5wcm90b3R5cGUucmVmcmVzaFNlbGVjdGVkQ2xhc3MgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdGhpcy5lV3JhcHBlci5jbGFzc0xpc3QudG9nZ2xlKCdhZy1jaGVja2VkJywgdmFsdWUgPT09IHRydWUpO1xuICAgICAgICB0aGlzLmVXcmFwcGVyLmNsYXNzTGlzdC50b2dnbGUoJ2FnLWluZGV0ZXJtaW5hdGUnLCB2YWx1ZSA9PSBudWxsKTtcbiAgICB9O1xuICAgIHJldHVybiBBZ0NoZWNrYm94O1xufShBZ0Fic3RyYWN0SW5wdXRGaWVsZCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDF0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxbSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFNlbGVjdEFsbEZlYXR1cmUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDF0KFNlbGVjdEFsbEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU2VsZWN0QWxsRmVhdHVyZShjb2x1bW4pIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY2JTZWxlY3RBbGxWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnByb2Nlc3NpbmdFdmVudEZyb21DaGVja2JveCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5jb2x1bW4gPSBjb2x1bW47XG4gICAgICAgIHZhciBjb2xEZWYgPSBjb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIF90aGlzLmZpbHRlcmVkT25seSA9IGNvbERlZiA/ICEhY29sRGVmLmhlYWRlckNoZWNrYm94U2VsZWN0aW9uRmlsdGVyZWRPbmx5IDogZmFsc2U7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgU2VsZWN0QWxsRmVhdHVyZS5wcm90b3R5cGUub25TcGFjZUtleVByZXNzZWQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgY2hlY2tib3ggPSB0aGlzLmNiU2VsZWN0QWxsO1xuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgaWYgKGNoZWNrYm94LmlzRGlzcGxheWVkKCkgJiYgIWNoZWNrYm94LmdldEd1aSgpLmNvbnRhaW5zKGVEb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgY2hlY2tib3guc2V0VmFsdWUoIWNoZWNrYm94LmdldFZhbHVlKCkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZS5nZXRDaGVja2JveEd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2JTZWxlY3RBbGwuZ2V0R3VpKCk7XG4gICAgfTtcbiAgICBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy5oZWFkZXJDZWxsQ3RybCA9IGN0cmw7XG4gICAgICAgIHRoaXMuY2JTZWxlY3RBbGwgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBBZ0NoZWNrYm94KCkpO1xuICAgICAgICB0aGlzLmNiU2VsZWN0QWxsLmFkZENzc0NsYXNzKCdhZy1oZWFkZXItc2VsZWN0LWFsbCcpO1xuICAgICAgICBzZXRBcmlhUm9sZSh0aGlzLmNiU2VsZWN0QWxsLmdldEd1aSgpLCAncHJlc2VudGF0aW9uJyk7XG4gICAgICAgIHRoaXMuc2hvd09ySGlkZVNlbGVjdEFsbCgpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX05FV19DT0xVTU5TX0xPQURFRCwgdGhpcy5zaG93T3JIaWRlU2VsZWN0QWxsLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMuc2hvd09ySGlkZVNlbGVjdEFsbC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9TRUxFQ1RJT05fQ0hBTkdFRCwgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTU9ERUxfVVBEQVRFRCwgdGhpcy5vbk1vZGVsQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5jYlNlbGVjdEFsbCwgQWdDaGVja2JveC5FVkVOVF9DSEFOR0VELCB0aGlzLm9uQ2JTZWxlY3RBbGwuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuY2JTZWxlY3RBbGwuZ2V0SW5wdXRFbGVtZW50KCkuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICctMScpO1xuICAgICAgICB0aGlzLnJlZnJlc2hTZWxlY3RBbGxMYWJlbCgpO1xuICAgIH07XG4gICAgU2VsZWN0QWxsRmVhdHVyZS5wcm90b3R5cGUuc2hvd09ySGlkZVNlbGVjdEFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYlNlbGVjdEFsbFZpc2libGUgPSB0aGlzLmlzQ2hlY2tib3hTZWxlY3Rpb24oKTtcbiAgICAgICAgdGhpcy5jYlNlbGVjdEFsbC5zZXREaXNwbGF5ZWQodGhpcy5jYlNlbGVjdEFsbFZpc2libGUpO1xuICAgICAgICBpZiAodGhpcy5jYlNlbGVjdEFsbFZpc2libGUpIHtcbiAgICAgICAgICAgIC8vIGluIGNhc2UgdXNlciBpcyB0cnlpbmcgdGhpcyBmZWF0dXJlIHdpdGggdGhlIHdyb25nIG1vZGVsIHR5cGVcbiAgICAgICAgICAgIHRoaXMuY2hlY2tSaWdodFJvd01vZGVsVHlwZSgpO1xuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIGNoZWNrYm94IGlzIHNob3dpbmcgdGhlIHJpZ2h0IHN0YXRlXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlT2ZDaGVja2JveCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVmcmVzaFNlbGVjdEFsbExhYmVsKCk7XG4gICAgfTtcbiAgICBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZS5vbk1vZGVsQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNiU2VsZWN0QWxsVmlzaWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlU3RhdGVPZkNoZWNrYm94KCk7XG4gICAgfTtcbiAgICBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZS5vblNlbGVjdGlvbkNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jYlNlbGVjdEFsbFZpc2libGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlT2ZDaGVja2JveCgpO1xuICAgIH07XG4gICAgU2VsZWN0QWxsRmVhdHVyZS5wcm90b3R5cGUuZ2V0TmV4dENoZWNrYm94U3RhdGUgPSBmdW5jdGlvbiAoc2VsZWN0aW9uQ291bnQpIHtcbiAgICAgICAgLy8gaWYgbm8gcm93cywgYWx3YXlzIGhhdmUgaXQgdW5zZWxlY3RlZFxuICAgICAgICBpZiAoc2VsZWN0aW9uQ291bnQuc2VsZWN0ZWQgPT09IDAgJiYgc2VsZWN0aW9uQ291bnQubm90U2VsZWN0ZWQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBtaXggb2Ygc2VsZWN0ZWQgYW5kIHVuc2VsZWN0ZWQsIHRoaXMgaXMgdGhlIHRyaS1zdGF0ZVxuICAgICAgICBpZiAoc2VsZWN0aW9uQ291bnQuc2VsZWN0ZWQgPiAwICYmIHNlbGVjdGlvbkNvdW50Lm5vdFNlbGVjdGVkID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgLy8gb25seSBzZWxlY3RlZFxuICAgICAgICBpZiAoc2VsZWN0aW9uQ291bnQuc2VsZWN0ZWQgPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBub3RoaW5nIHNlbGVjdGVkXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFNlbGVjdEFsbEZlYXR1cmUucHJvdG90eXBlLnVwZGF0ZVN0YXRlT2ZDaGVja2JveCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJvY2Vzc2luZ0V2ZW50RnJvbUNoZWNrYm94KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wcm9jZXNzaW5nRXZlbnRGcm9tQ2hlY2tib3ggPSB0cnVlO1xuICAgICAgICB2YXIgc2VsZWN0aW9uQ291bnQgPSB0aGlzLmdldFNlbGVjdGlvbkNvdW50KCk7XG4gICAgICAgIHZhciBhbGxTZWxlY3RlZCA9IHRoaXMuZ2V0TmV4dENoZWNrYm94U3RhdGUoc2VsZWN0aW9uQ291bnQpO1xuICAgICAgICB0aGlzLmNiU2VsZWN0QWxsLnNldFZhbHVlKGFsbFNlbGVjdGVkKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoU2VsZWN0QWxsTGFiZWwoKTtcbiAgICAgICAgdGhpcy5wcm9jZXNzaW5nRXZlbnRGcm9tQ2hlY2tib3ggPSBmYWxzZTtcbiAgICB9O1xuICAgIFNlbGVjdEFsbEZlYXR1cmUucHJvdG90eXBlLnJlZnJlc2hTZWxlY3RBbGxMYWJlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNiU2VsZWN0QWxsVmlzaWJsZSkge1xuICAgICAgICAgICAgdGhpcy5oZWFkZXJDZWxsQ3RybC5zZXRBcmlhRGVzY3JpcHRpb25Qcm9wZXJ0eSgnc2VsZWN0QWxsJywgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgICAgIHZhciBjaGVja2VkID0gdGhpcy5jYlNlbGVjdEFsbC5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgdmFyIGFyaWFTdGF0dXMgPSBjaGVja2VkID8gdHJhbnNsYXRlKCdhcmlhQ2hlY2tlZCcsICdjaGVja2VkJykgOiB0cmFuc2xhdGUoJ2FyaWFVbmNoZWNrZWQnLCAndW5jaGVja2VkJyk7XG4gICAgICAgICAgICB2YXIgYXJpYUxhYmVsID0gdHJhbnNsYXRlKCdhcmlhUm93U2VsZWN0QWxsJywgJ1ByZXNzIFNwYWNlIHRvIHRvZ2dsZSBhbGwgcm93cyBzZWxlY3Rpb24nKTtcbiAgICAgICAgICAgIHRoaXMuaGVhZGVyQ2VsbEN0cmwuc2V0QXJpYURlc2NyaXB0aW9uUHJvcGVydHkoJ3NlbGVjdEFsbCcsIGFyaWFMYWJlbCArIFwiIChcIiArIGFyaWFTdGF0dXMgKyBcIilcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5oZWFkZXJDZWxsQ3RybC5yZWZyZXNoQXJpYURlc2NyaXB0aW9uKCk7XG4gICAgfTtcbiAgICBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZS5nZXRTZWxlY3Rpb25Db3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHNlbGVjdGVkQ291bnQgPSAwO1xuICAgICAgICB2YXIgbm90U2VsZWN0ZWRDb3VudCA9IDA7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBTZWxlY3RzQ2hpbGRyZW4oKSAmJiBub2RlLmdyb3VwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGUuaXNTZWxlY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRDb3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoIW5vZGUuc2VsZWN0YWJsZSkgO1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbm90U2VsZWN0ZWRDb3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5maWx0ZXJlZE9ubHkpIHtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEFwaS5mb3JFYWNoTm9kZUFmdGVyRmlsdGVyKGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEFwaS5mb3JFYWNoTm9kZShjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5vdFNlbGVjdGVkOiBub3RTZWxlY3RlZENvdW50LFxuICAgICAgICAgICAgc2VsZWN0ZWQ6IHNlbGVjdGVkQ291bnRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFNlbGVjdEFsbEZlYXR1cmUucHJvdG90eXBlLmNoZWNrUmlnaHRSb3dNb2RlbFR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dNb2RlbFR5cGUgPSB0aGlzLnJvd01vZGVsLmdldFR5cGUoKTtcbiAgICAgICAgdmFyIHJvd01vZGVsTWF0Y2hlcyA9IHJvd01vZGVsVHlwZSA9PT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0NMSUVOVF9TSURFO1xuICAgICAgICBpZiAoIXJvd01vZGVsTWF0Y2hlcykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc2VsZWN0QWxsQ2hlY2tib3ggaXMgb25seSBhdmFpbGFibGUgaWYgdXNpbmcgbm9ybWFsIHJvdyBtb2RlbCwgeW91IGFyZSB1c2luZyBcIiArIHJvd01vZGVsVHlwZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFNlbGVjdEFsbEZlYXR1cmUucHJvdG90eXBlLm9uQ2JTZWxlY3RBbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnByb2Nlc3NpbmdFdmVudEZyb21DaGVja2JveCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5jYlNlbGVjdEFsbFZpc2libGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLmNiU2VsZWN0QWxsLmdldFZhbHVlKCk7XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLnNlbGVjdEFsbFJvd05vZGVzKHRoaXMuZmlsdGVyZWRPbmx5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS5kZXNlbGVjdEFsbFJvd05vZGVzKHRoaXMuZmlsdGVyZWRPbmx5KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2VsZWN0QWxsRmVhdHVyZS5wcm90b3R5cGUuaXNDaGVja2JveFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuY29sdW1uLmdldENvbERlZigpLmhlYWRlckNoZWNrYm94U2VsZWN0aW9uO1xuICAgICAgICBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdmFyIGZ1bmMgPSByZXN1bHQ7XG4gICAgICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgIGNvbHVtbjogdGhpcy5jb2x1bW4sXG4gICAgICAgICAgICAgICAgY29sRGVmOiB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuY29sdW1uQXBpLFxuICAgICAgICAgICAgICAgIGFwaTogdGhpcy5ncmlkQXBpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMocGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSb3dNb2RlbFNlcnZlclNpZGUoKSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogaGVhZGVyQ2hlY2tib3hTZWxlY3Rpb24gaXMgbm90IHN1cHBvcnRlZCBmb3IgU2VydmVyIFNpZGUgUm93IE1vZGVsJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxJbmZpbml0ZSgpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBoZWFkZXJDaGVja2JveFNlbGVjdGlvbiBpcyBub3Qgc3VwcG9ydGVkIGZvciBJbmZpbml0ZSBSb3cgTW9kZWwnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSb3dNb2RlbFZpZXdwb3J0KCkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGhlYWRlckNoZWNrYm94U2VsZWN0aW9uIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIFZpZXdwb3J0IFJvdyBNb2RlbCcpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSB0aGUgcm93IG1vZGVsIGlzIGNvbXBhdGlibGUsIHNvIHJldHVybiB0cnVlXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFtKFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkQXBpJylcbiAgICBdLCBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZSwgXCJncmlkQXBpXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxbShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uQXBpJylcbiAgICBdLCBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZSwgXCJjb2x1bW5BcGlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFtKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dNb2RlbCcpXG4gICAgXSwgU2VsZWN0QWxsRmVhdHVyZS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFtKFtcbiAgICAgICAgQXV0b3dpcmVkKCdzZWxlY3Rpb25TZXJ2aWNlJylcbiAgICBdLCBTZWxlY3RBbGxGZWF0dXJlLnByb3RvdHlwZSwgXCJzZWxlY3Rpb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIFNlbGVjdEFsbEZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMXMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFsID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgSGVhZGVyQ2VsbEN0cmwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFzKEhlYWRlckNlbGxDdHJsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlckNlbGxDdHJsKGNvbHVtbiwgcGFyZW50Um93Q3RybCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjb2x1bW4sIHBhcmVudFJvd0N0cmwpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnJlZnJlc2hGdW5jdGlvbnMgPSBbXTtcbiAgICAgICAgX3RoaXMudXNlckhlYWRlckNsYXNzZXMgPSBuZXcgU2V0KCk7XG4gICAgICAgIF90aGlzLmFyaWFEZXNjcmlwdGlvblByb3BlcnRpZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIF90aGlzLmNvbHVtbiA9IGNvbHVtbjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0Q29tcCA9IGZ1bmN0aW9uIChjb21wLCBlR3VpLCBlUmVzaXplLCBlSGVhZGVyQ29tcFdyYXBwZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5zZXRHdWkuY2FsbCh0aGlzLCBlR3VpKTtcbiAgICAgICAgdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgdGhpcy51cGRhdGVTdGF0ZSgpO1xuICAgICAgICB0aGlzLnNldHVwV2lkdGgoKTtcbiAgICAgICAgdGhpcy5zZXR1cE1vdmluZ0NzcygpO1xuICAgICAgICB0aGlzLnNldHVwTWVudUNsYXNzKCk7XG4gICAgICAgIHRoaXMuc2V0dXBTb3J0YWJsZUNsYXNzKCk7XG4gICAgICAgIHRoaXMuc2V0dXBXcmFwVGV4dENsYXNzKCk7XG4gICAgICAgIHRoaXMuc2V0dXBBdXRvSGVpZ2h0KGVIZWFkZXJDb21wV3JhcHBlcik7XG4gICAgICAgIHRoaXMuYWRkQ29sdW1uSG92ZXJMaXN0ZW5lcigpO1xuICAgICAgICB0aGlzLnNldHVwRmlsdGVyQ3NzKCk7XG4gICAgICAgIHRoaXMuc2V0dXBDb2xJZCgpO1xuICAgICAgICB0aGlzLnNldHVwQ2xhc3Nlc0Zyb21Db2xEZWYoKTtcbiAgICAgICAgdGhpcy5zZXR1cFRvb2x0aXAoKTtcbiAgICAgICAgdGhpcy5hZGRBY3RpdmVIZWFkZXJNb3VzZUxpc3RlbmVycygpO1xuICAgICAgICB0aGlzLnNldHVwU2VsZWN0QWxsKCk7XG4gICAgICAgIHRoaXMuc2V0dXBVc2VyQ29tcCgpO1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhKCk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IFJlc2l6ZUZlYXR1cmUodGhpcy5nZXRQaW5uZWQoKSwgdGhpcy5jb2x1bW4sIGVSZXNpemUsIGNvbXAsIHRoaXMpKTtcbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgSG92ZXJGZWF0dXJlKFt0aGlzLmNvbHVtbl0sIGVHdWkpKTtcbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgU2V0TGVmdEZlYXR1cmUodGhpcy5jb2x1bW4sIGVHdWksIHRoaXMuYmVhbnMpKTtcbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgTWFuYWdlZEZvY3VzRmVhdHVyZShlR3VpLCB7XG4gICAgICAgICAgICBzaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvbjogZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLnNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uKGUpOyB9LFxuICAgICAgICAgICAgb25UYWJLZXlEb3duOiBmdW5jdGlvbiAoKSB7IHJldHVybiBudWxsOyB9LFxuICAgICAgICAgICAgaGFuZGxlS2V5RG93bjogdGhpcy5oYW5kbGVLZXlEb3duLmJpbmQodGhpcyksXG4gICAgICAgICAgICBvbkZvY3VzSW46IHRoaXMub25Gb2N1c0luLmJpbmQodGhpcyksXG4gICAgICAgICAgICBvbkZvY3VzT3V0OiB0aGlzLm9uRm9jdXNPdXQuYmluZCh0aGlzKVxuICAgICAgICB9KSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuY29sdW1uLCBDb2x1bW4uRVZFTlRfQ09MX0RFRl9DSEFOR0VELCB0aGlzLm9uQ29sRGVmQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fVkFMVUVfQ0hBTkdFRCwgdGhpcy5vbkNvbHVtblZhbHVlQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIHRoaXMub25Db2x1bW5Sb3dHcm91cENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1BJVk9UX0NIQU5HRUQsIHRoaXMub25Db2x1bW5QaXZvdENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBVc2VyQ29tcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbXBEZXRhaWxzID0gdGhpcy5sb29rdXBVc2VyQ29tcERldGFpbHMoKTtcbiAgICAgICAgdGhpcy5zZXRDb21wRGV0YWlscyhjb21wRGV0YWlscyk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0Q29tcERldGFpbHMgPSBmdW5jdGlvbiAoY29tcERldGFpbHMpIHtcbiAgICAgICAgdGhpcy51c2VyQ29tcERldGFpbHMgPSBjb21wRGV0YWlscztcbiAgICAgICAgdGhpcy5jb21wLnNldFVzZXJDb21wRGV0YWlscyhjb21wRGV0YWlscyk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUubG9va3VwVXNlckNvbXBEZXRhaWxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyYW1zID0gdGhpcy5jcmVhdGVQYXJhbXMoKTtcbiAgICAgICAgdmFyIGNvbERlZiA9IHRoaXMuY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICByZXR1cm4gdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeS5nZXRIZWFkZXJDb21wRGV0YWlscyhjb2xEZWYsIHBhcmFtcyk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuY3JlYXRlUGFyYW1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBjb2x1bW46IHRoaXMuY29sdW1uLFxuICAgICAgICAgICAgZGlzcGxheU5hbWU6IHRoaXMuZGlzcGxheU5hbWUsXG4gICAgICAgICAgICBlbmFibGVTb3J0aW5nOiBjb2xEZWYuc29ydGFibGUsXG4gICAgICAgICAgICBlbmFibGVNZW51OiB0aGlzLm1lbnVFbmFibGVkLFxuICAgICAgICAgICAgc2hvd0NvbHVtbk1lbnU6IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5ncmlkQXBpLnNob3dDb2x1bW5NZW51QWZ0ZXJCdXR0b25DbGljayhfdGhpcy5jb2x1bW4sIHNvdXJjZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJvZ3Jlc3NTb3J0OiBmdW5jdGlvbiAobXVsdGlTb3J0KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuc29ydENvbnRyb2xsZXIucHJvZ3Jlc3NTb3J0KF90aGlzLmNvbHVtbiwgISFtdWx0aVNvcnQsIFwidWlDb2x1bW5Tb3J0ZWRcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0U29ydDogZnVuY3Rpb24gKHNvcnQsIG11bHRpU29ydCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNvcnRDb250cm9sbGVyLnNldFNvcnRGb3JDb2x1bW4oX3RoaXMuY29sdW1uLCBzb3J0LCAhIW11bHRpU29ydCwgXCJ1aUNvbHVtblNvcnRlZFwiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZEFwaSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5jb2x1bW5BcGksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCksXG4gICAgICAgICAgICBlR3JpZEhlYWRlcjogdGhpcy5nZXRHdWkoKVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwU2VsZWN0QWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNlbGVjdEFsbEZlYXR1cmUgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBTZWxlY3RBbGxGZWF0dXJlKHRoaXMuY29sdW1uKSk7XG4gICAgICAgIHRoaXMuc2VsZWN0QWxsRmVhdHVyZS5zZXRDb21wKHRoaXMpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmdldFNlbGVjdEFsbEd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0QWxsRmVhdHVyZS5nZXRDaGVja2JveEd1aSgpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmhhbmRsZUtleURvd24uY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgaWYgKGUua2V5ID09PSBLZXlDb2RlLlNQQUNFKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdEFsbEZlYXR1cmUub25TcGFjZUtleVByZXNzZWQoZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUua2V5ID09PSBLZXlDb2RlLkVOVEVSKSB7XG4gICAgICAgICAgICB0aGlzLm9uRW50ZXJLZXlQcmVzc2VkKGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUub25FbnRlcktleVByZXNzZWQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAvLy8gVEhJUyBJUyBCQUQgLSB3ZSBhcmUgYXNzdW1pbmcgdGhlIGhlYWRlciBpcyBub3QgYSB1c2VyIHByb3ZpZGVkIGNvbXBcbiAgICAgICAgdmFyIGhlYWRlckNvbXAgPSB0aGlzLmNvbXAuZ2V0VXNlckNvbXBJbnN0YW5jZSgpO1xuICAgICAgICBpZiAoIWhlYWRlckNvbXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkge1xuICAgICAgICAgICAgaWYgKHRoaXMubWVudUVuYWJsZWQgJiYgaGVhZGVyQ29tcC5zaG93TWVudSkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBoZWFkZXJDb21wLnNob3dNZW51KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5zb3J0YWJsZSkge1xuICAgICAgICAgICAgdmFyIG11bHRpU29ydCA9IGUuc2hpZnRLZXk7XG4gICAgICAgICAgICB0aGlzLnNvcnRDb250cm9sbGVyLnByb2dyZXNzU29ydCh0aGlzLmNvbHVtbiwgbXVsdGlTb3J0LCBcInVpQ29sdW1uU29ydGVkXCIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuaXNNZW51RW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVudUVuYWJsZWQ7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUub25Gb2N1c0luID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdldEd1aSgpLmNvbnRhaW5zKGUucmVsYXRlZFRhcmdldCkpIHtcbiAgICAgICAgICAgIHZhciByb3dJbmRleCA9IHRoaXMuZ2V0Um93SW5kZXgoKTtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNTZXJ2aWNlLnNldEZvY3VzZWRIZWFkZXIocm93SW5kZXgsIHRoaXMuY29sdW1uKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldEFjdGl2ZUhlYWRlcih0cnVlKTtcbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5vbkZvY3VzT3V0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKHRoaXMuZ2V0R3VpKCkuY29udGFpbnMoZS5yZWxhdGVkVGFyZ2V0KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0QWN0aXZlSGVhZGVyKGZhbHNlKTtcbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5zZXR1cFRvb2x0aXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB0b29sdGlwQ3RybCA9IHtcbiAgICAgICAgICAgIGdldENvbHVtbjogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY29sdW1uOyB9LFxuICAgICAgICAgICAgZ2V0Q29sRGVmOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7IH0sXG4gICAgICAgICAgICBnZXRHdWk6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmVHdWk7IH0sXG4gICAgICAgICAgICBnZXRMb2NhdGlvbjogZnVuY3Rpb24gKCkgeyByZXR1cm4gJ2hlYWRlcic7IH0sXG4gICAgICAgICAgICBnZXRUb29sdGlwVmFsdWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzID0gX3RoaXMuY29sdW1uLmdldENvbERlZigpLmhlYWRlclRvb2x0aXA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHZhciB0b29sdGlwRmVhdHVyZSA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IFRvb2x0aXBGZWF0dXJlKHRvb2x0aXBDdHJsLCB0aGlzLmJlYW5zKSk7XG4gICAgICAgIHRvb2x0aXBGZWF0dXJlLnNldENvbXAodGhpcy5jb21wKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoRnVuY3Rpb25zLnB1c2goZnVuY3Rpb24gKCkgeyByZXR1cm4gdG9vbHRpcEZlYXR1cmUucmVmcmVzaFRvb2xUaXAoKTsgfSk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBDbGFzc2VzRnJvbUNvbERlZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlZnJlc2hIZWFkZXJDbGFzc2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNvbERlZiA9IF90aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgICAgIHZhciBnb2EgPSBfdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXI7XG4gICAgICAgICAgICB2YXIgY2xhc3NlcyA9IENzc0NsYXNzQXBwbGllci5nZXRIZWFkZXJDbGFzc2VzRnJvbUNvbERlZihjb2xEZWYsIGdvYSwgX3RoaXMuY29sdW1uLCBudWxsKTtcbiAgICAgICAgICAgIHZhciBvbGRDbGFzc2VzID0gX3RoaXMudXNlckhlYWRlckNsYXNzZXM7XG4gICAgICAgICAgICBfdGhpcy51c2VySGVhZGVyQ2xhc3NlcyA9IG5ldyBTZXQoY2xhc3Nlcyk7XG4gICAgICAgICAgICBjbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkQ2xhc3Nlcy5oYXMoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xhc3MgYWxyZWFkeSBhZGRlZCwgbm8gbmVlZCB0byBhcHBseSBpdCwgYnV0IHJlbW92ZSBmcm9tIG9sZCBzZXRcbiAgICAgICAgICAgICAgICAgICAgb2xkQ2xhc3Nlcy5kZWxldGUoYyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBjbGFzcyBuZXcgc2luY2UgbGFzdCB0aW1lLCBzbyBhcHBseSBpdFxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoYywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBub3cgb2xkIHNldCBvbmx5IGhhcyBjbGFzc2VzIHRoYXQgd2VyZSBhcHBsaWVkIGxhc3QgdGltZSwgYnV0IG5vdCB0aGlzIHRpbWUsIHNvIHJlbW92ZSB0aGVtXG4gICAgICAgICAgICBvbGRDbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKGMpIHsgcmV0dXJuIF90aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcyhjLCBmYWxzZSk7IH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJlZnJlc2hGdW5jdGlvbnMucHVzaChyZWZyZXNoSGVhZGVyQ2xhc3Nlcyk7XG4gICAgICAgIHJlZnJlc2hIZWFkZXJDbGFzc2VzKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0RHJhZ1NvdXJjZSA9IGZ1bmN0aW9uIChlU291cmNlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZHJhZ1NvdXJjZUVsZW1lbnQgPSBlU291cmNlO1xuICAgICAgICB0aGlzLnJlbW92ZURyYWdTb3VyY2UoKTtcbiAgICAgICAgaWYgKCFlU291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmRyYWdnYWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoaWRlQ29sdW1uT25FeGl0ID0gIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NEcmFnTGVhdmVIaWRlc0NvbHVtbnMoKTtcbiAgICAgICAgdGhpcy5tb3ZlRHJhZ1NvdXJjZSA9IHtcbiAgICAgICAgICAgIHR5cGU6IERyYWdTb3VyY2VUeXBlLkhlYWRlckNlbGwsXG4gICAgICAgICAgICBlRWxlbWVudDogZVNvdXJjZSxcbiAgICAgICAgICAgIGRlZmF1bHRJY29uTmFtZTogaGlkZUNvbHVtbk9uRXhpdCA/IERyYWdBbmREcm9wU2VydmljZS5JQ09OX0hJREUgOiBEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9OT1RfQUxMT1dFRCxcbiAgICAgICAgICAgIGdldERyYWdJdGVtOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jcmVhdGVEcmFnSXRlbSgpOyB9LFxuICAgICAgICAgICAgZHJhZ0l0ZW1OYW1lOiB0aGlzLmRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgb25EcmFnU3RhcnRlZDogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY29sdW1uLnNldE1vdmluZyh0cnVlLCBcInVpQ29sdW1uTW92ZWRcIik7IH0sXG4gICAgICAgICAgICBvbkRyYWdTdG9wcGVkOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb2x1bW4uc2V0TW92aW5nKGZhbHNlLCBcInVpQ29sdW1uTW92ZWRcIik7IH0sXG4gICAgICAgICAgICBvbkdyaWRFbnRlcjogZnVuY3Rpb24gKGRyYWdJdGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgICAgICAgICBpZiAoaGlkZUNvbHVtbk9uRXhpdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdW5sb2NrZWRDb2x1bW5zID0gKChfYiA9IChfYSA9IGRyYWdJdGVtKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY29sdW1ucykgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiAhY29sLmdldENvbERlZigpLmxvY2tWaXNpYmxlOyB9KSkgfHwgW107XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbnNWaXNpYmxlKHVubG9ja2VkQ29sdW1ucywgdHJ1ZSwgXCJ1aUNvbHVtbk1vdmVkXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkdyaWRFeGl0OiBmdW5jdGlvbiAoZHJhZ0l0ZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICAgICAgICAgIGlmIChoaWRlQ29sdW1uT25FeGl0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB1bmxvY2tlZENvbHVtbnMgPSAoKF9iID0gKF9hID0gZHJhZ0l0ZW0pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jb2x1bW5zKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuICFjb2wuZ2V0Q29sRGVmKCkubG9ja1Zpc2libGU7IH0pKSB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uc1Zpc2libGUodW5sb2NrZWRDb2x1bW5zLCBmYWxzZSwgXCJ1aUNvbHVtbk1vdmVkXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLmFkZERyYWdTb3VyY2UodGhpcy5tb3ZlRHJhZ1NvdXJjZSwgdHJ1ZSk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuY3JlYXRlRHJhZ0l0ZW0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB2aXNpYmxlU3RhdGUgPSB7fTtcbiAgICAgICAgdmlzaWJsZVN0YXRlW3RoaXMuY29sdW1uLmdldElkKCldID0gdGhpcy5jb2x1bW4uaXNWaXNpYmxlKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb2x1bW5zOiBbdGhpcy5jb2x1bW5dLFxuICAgICAgICAgICAgdmlzaWJsZVN0YXRlOiB2aXNpYmxlU3RhdGVcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5yZW1vdmVEcmFnU291cmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5tb3ZlRHJhZ1NvdXJjZSkge1xuICAgICAgICAgICAgdGhpcy5kcmFnQW5kRHJvcFNlcnZpY2UucmVtb3ZlRHJhZ1NvdXJjZSh0aGlzLm1vdmVEcmFnU291cmNlKTtcbiAgICAgICAgICAgIHRoaXMubW92ZURyYWdTb3VyY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5vbkNvbERlZkNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnVwZGF0ZVN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sRGVmID0gdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIHRoaXMubWVudUVuYWJsZWQgPSB0aGlzLm1lbnVGYWN0b3J5LmlzTWVudUVuYWJsZWQodGhpcy5jb2x1bW4pICYmICFjb2xEZWYuc3VwcHJlc3NNZW51O1xuICAgICAgICB0aGlzLnNvcnRhYmxlID0gY29sRGVmLnNvcnRhYmxlO1xuICAgICAgICB0aGlzLmRpc3BsYXlOYW1lID0gdGhpcy5jYWxjdWxhdGVEaXNwbGF5TmFtZSgpO1xuICAgICAgICB0aGlzLmRyYWdnYWJsZSA9IHRoaXMud29ya091dERyYWdnYWJsZSgpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmFkZFJlZnJlc2hGdW5jdGlvbiA9IGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgIHRoaXMucmVmcmVzaEZ1bmN0aW9ucy5wdXNoKGZ1bmMpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlU3RhdGUoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoSGVhZGVyQ29tcCgpO1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhKCk7XG4gICAgICAgIHRoaXMucmVmcmVzaEZ1bmN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uIChmKSB7IHJldHVybiBmKCk7IH0pO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnJlZnJlc2hIZWFkZXJDb21wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbmV3Q29tcERldGFpbHMgPSB0aGlzLmxvb2t1cFVzZXJDb21wRGV0YWlscygpO1xuICAgICAgICB2YXIgY29tcEluc3RhbmNlID0gdGhpcy5jb21wLmdldFVzZXJDb21wSW5zdGFuY2UoKTtcbiAgICAgICAgLy8gb25seSB0cnkgcmVmcmVzaCBpZiBvbGQgY29tcCBleGlzdHMgYWRuIGl0IGlzIHRoZSBjb3JyZWN0IHR5cGVcbiAgICAgICAgdmFyIGF0dGVtcHRSZWZyZXNoID0gY29tcEluc3RhbmNlICE9IG51bGwgJiYgdGhpcy51c2VyQ29tcERldGFpbHMuY29tcG9uZW50Q2xhc3MgPT0gbmV3Q29tcERldGFpbHMuY29tcG9uZW50Q2xhc3M7XG4gICAgICAgIHZhciBoZWFkZXJDb21wUmVmcmVzaGVkID0gYXR0ZW1wdFJlZnJlc2ggPyB0aGlzLmF0dGVtcHRIZWFkZXJDb21wUmVmcmVzaChuZXdDb21wRGV0YWlscy5wYXJhbXMpIDogZmFsc2U7XG4gICAgICAgIGlmIChoZWFkZXJDb21wUmVmcmVzaGVkKSB7XG4gICAgICAgICAgICAvLyB3ZSBkbyB0aGlzIGFzIGEgcmVmcmVzaCBoYXBwZW5zIGFmdGVyIGNvbERlZnMgY2hhbmdlLCBhbmQgaXQncyBwb3NzaWJsZSB0aGUgY29sdW1uIGhhcyBoYWQgaXQnc1xuICAgICAgICAgICAgLy8gZHJhZ2dhYmxlIHByb3BlcnR5IHRvZ2dsZWQuIG5vIG5lZWQgdG8gY2FsbCB0aGlzIGlmIG5vdCByZWZyZXNoaW5nLCBhcyBzZXREcmFnU291cmNlIGlzIGRvbmVcbiAgICAgICAgICAgIC8vIGFzIHBhcnQgb2YgYXBwZW5kSGVhZGVyQ29tcFxuICAgICAgICAgICAgdGhpcy5zZXREcmFnU291cmNlKHRoaXMuZHJhZ1NvdXJjZUVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRDb21wRGV0YWlscyhuZXdDb21wRGV0YWlscyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5hdHRlbXB0SGVhZGVyQ29tcFJlZnJlc2ggPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBoZWFkZXJDb21wID0gdGhpcy5jb21wLmdldFVzZXJDb21wSW5zdGFuY2UoKTtcbiAgICAgICAgaWYgKCFoZWFkZXJDb21wKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgbm8gcmVmcmVzaCBtZXRob2QsIHRoZW4gd2Ugd2FudCB0byByZXBsYWNlIHRoZSBoZWFkZXJDb21wXG4gICAgICAgIGlmICghaGVhZGVyQ29tcC5yZWZyZXNoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlcyA9IGhlYWRlckNvbXAucmVmcmVzaChwYXJhbXMpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmNhbGN1bGF0ZURpc3BsYXlOYW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5TmFtZUZvckNvbHVtbih0aGlzLmNvbHVtbiwgJ2hlYWRlcicsIHRydWUpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmNoZWNrRGlzcGxheU5hbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGRpc3BsYXkgbmFtZSBjYW4gY2hhbmdlIGlmIGFnZ0Z1bmMgZGlmZmVyZW50LCBlZyBzdW0oR29sZCkgaXMgbm93IG1heChHb2xkKVxuICAgICAgICBpZiAodGhpcy5kaXNwbGF5TmFtZSAhPT0gdGhpcy5jYWxjdWxhdGVEaXNwbGF5TmFtZSgpKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLndvcmtPdXREcmFnZ2FibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb2xEZWYgPSB0aGlzLmNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgdmFyIGlzU3VwcHJlc3NNb3ZhYmxlQ29sdW1ucyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NNb3ZhYmxlQ29sdW1ucygpO1xuICAgICAgICB2YXIgY29sQ2FuTW92ZSA9ICFpc1N1cHByZXNzTW92YWJsZUNvbHVtbnMgJiYgIWNvbERlZi5zdXBwcmVzc01vdmFibGUgJiYgIWNvbERlZi5sb2NrUG9zaXRpb247XG4gICAgICAgIC8vIHdlIHNob3VsZCBzdGlsbCBiZSBhbGxvd2VkIGRyYWcgdGhlIGNvbHVtbiwgZXZlbiBpZiBpdCBjYW4ndCBiZSBtb3ZlZCwgaWYgdGhlIGNvbHVtblxuICAgICAgICAvLyBjYW4gYmUgZHJhZ2dlZCB0byBhIHJvd0dyb3VwIG9yIHBpdm90IGRyb3Agem9uZVxuICAgICAgICByZXR1cm4gISFjb2xDYW5Nb3ZlIHx8ICEhY29sRGVmLmVuYWJsZVJvd0dyb3VwIHx8ICEhY29sRGVmLmVuYWJsZVBpdm90O1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLm9uQ29sdW1uUm93R3JvdXBDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNoZWNrRGlzcGxheU5hbWUoKTtcbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5vbkNvbHVtblBpdm90Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jaGVja0Rpc3BsYXlOYW1lKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUub25Db2x1bW5WYWx1ZUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY2hlY2tEaXNwbGF5TmFtZSgpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmNvbXAuc2V0V2lkdGgoX3RoaXMuY29sdW1uLmdldEFjdHVhbFdpZHRoKCkgKyAncHgnKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5jb2x1bW4sIENvbHVtbi5FVkVOVF9XSURUSF9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBNb3ZpbmdDc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgd2hhdCBtYWtlcyB0aGUgaGVhZGVyIGdvIGRhcmsgd2hlbiBpdCBpcyBiZWVuIG1vdmVkIChnaXZlcyBpbXByZXNzaW9uIHRvXG4gICAgICAgICAgICAvLyB1c2VyIHRoYXQgdGhlIGNvbHVtbiB3YXMgcGlja2VkIHVwKS5cbiAgICAgICAgICAgIF90aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctaGVhZGVyLWNlbGwtbW92aW5nJywgX3RoaXMuY29sdW1uLmlzTW92aW5nKCkpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmNvbHVtbiwgQ29sdW1uLkVWRU5UX01PVklOR19DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBNZW51Q2xhc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctY29sdW1uLW1lbnUtdmlzaWJsZScsIF90aGlzLmNvbHVtbi5pc01lbnVWaXNpYmxlKCkpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmNvbHVtbiwgQ29sdW1uLkVWRU5UX01FTlVfVklTSUJMRV9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBTb3J0YWJsZUNsYXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdXBkYXRlU29ydGFibGVDc3NDbGFzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctaGVhZGVyLWNlbGwtc29ydGFibGUnLCAhIV90aGlzLnNvcnRhYmxlKTtcbiAgICAgICAgfTtcbiAgICAgICAgdXBkYXRlU29ydGFibGVDc3NDbGFzcygpO1xuICAgICAgICB0aGlzLmFkZFJlZnJlc2hGdW5jdGlvbih1cGRhdGVTb3J0YWJsZUNzc0NsYXNzKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5jb2x1bW4sIENvbHVtbi5FVkVOVF9TT1JUX0NIQU5HRUQsIHRoaXMucmVmcmVzaEFyaWFTb3J0LmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwV3JhcFRleHRDbGFzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHdyYXBUZXh0ID0gISFfdGhpcy5jb2x1bW4uZ2V0Q29sRGVmKCkud3JhcEhlYWRlclRleHQ7XG4gICAgICAgICAgICBfdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWhlYWRlci1jZWxsLXdyYXAtdGV4dCcsIHdyYXBUZXh0KTtcbiAgICAgICAgfTtcbiAgICAgICAgbGlzdGVuZXIoKTtcbiAgICAgICAgdGhpcy5hZGRSZWZyZXNoRnVuY3Rpb24obGlzdGVuZXIpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwQXV0b0hlaWdodCA9IGZ1bmN0aW9uICh3cmFwcGVyRWxlbWVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbWVhc3VyZUhlaWdodCA9IGZ1bmN0aW9uICh0aW1lc0NhbGxlZCkge1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgX2EgPSBnZXRFbGVtZW50U2l6ZShfdGhpcy5nZXRHdWkoKSksIHBhZGRpbmdUb3AgPSBfYS5wYWRkaW5nVG9wLCBwYWRkaW5nQm90dG9tID0gX2EucGFkZGluZ0JvdHRvbTtcbiAgICAgICAgICAgIHZhciB3cmFwcGVySGVpZ2h0ID0gd3JhcHBlckVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICAgICAgdmFyIGF1dG9IZWlnaHQgPSB3cmFwcGVySGVpZ2h0ICsgcGFkZGluZ1RvcCArIHBhZGRpbmdCb3R0b207XG4gICAgICAgICAgICBpZiAodGltZXNDYWxsZWQgPCA1KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgbm90IGluIGRvYyB5ZXQsIG1lYW5zIGZyYW1ld29yayBub3QgeWV0IGluc2VydGVkLCBzbyB3YWl0IGZvciBuZXh0IFZNIHR1cm4sXG4gICAgICAgICAgICAgICAgLy8gbWF5YmUgaXQgd2lsbCBiZSByZWFkeSBuZXh0IFZNIHR1cm5cbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gX3RoaXMuYmVhbnMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgICAgICAgICAgdmFyIG5vdFlldEluRG9tID0gIWRvYyB8fCAhZG9jLmNvbnRhaW5zKHdyYXBwZXJFbGVtZW50KTtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGhhcHBlbnMgaW4gUmVhY3QsIHdoZXJlIFJlYWN0IGhhc24ndCBwdXQgYW55IGNvbnRlbnQgaW4uIHdlIHNheSAncG9zc2libHknXG4gICAgICAgICAgICAgICAgLy8gYXMgYSkgbWF5IG5vdCBiZSBSZWFjdCBhbmQgYikgdGhlIGNlbGwgY291bGQgYmUgZW1wdHkgYW55d2F5XG4gICAgICAgICAgICAgICAgdmFyIHBvc3NpYmx5Tm9Db250ZW50WWV0ID0gYXV0b0hlaWdodCA9PSAwO1xuICAgICAgICAgICAgICAgIGlmIChub3RZZXRJbkRvbSB8fCBwb3NzaWJseU5vQ29udGVudFlldCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5iZWFucy5mcmFtZXdvcmtPdmVycmlkZXMuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBtZWFzdXJlSGVpZ2h0KHRpbWVzQ2FsbGVkICsgMSk7IH0sIDApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uSGVhZGVySGVpZ2h0KF90aGlzLmNvbHVtbiwgYXV0b0hlaWdodCk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBpc01lYXN1cmluZyA9IGZhbHNlO1xuICAgICAgICB2YXIgc3RvcFJlc2l6ZU9ic2VydmVyO1xuICAgICAgICB2YXIgY2hlY2tNZWFzdXJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbmV3VmFsdWUgPSBfdGhpcy5jb2x1bW4uaXNBdXRvSGVhZGVySGVpZ2h0KCk7XG4gICAgICAgICAgICBpZiAobmV3VmFsdWUgJiYgIWlzTWVhc3VyaW5nKSB7XG4gICAgICAgICAgICAgICAgc3RhcnRNZWFzdXJpbmcoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghbmV3VmFsdWUgJiYgaXNNZWFzdXJpbmcpIHtcbiAgICAgICAgICAgICAgICBzdG9wTWVhc3VyaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBzdGFydE1lYXN1cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlzTWVhc3VyaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIG1lYXN1cmVIZWlnaHQoMCk7XG4gICAgICAgICAgICBzdG9wUmVzaXplT2JzZXJ2ZXIgPSBfdGhpcy5yZXNpemVPYnNlcnZlclNlcnZpY2Uub2JzZXJ2ZVJlc2l6ZSh3cmFwcGVyRWxlbWVudCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gbWVhc3VyZUhlaWdodCgwKTsgfSk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBzdG9wTWVhc3VyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaXNNZWFzdXJpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChzdG9wUmVzaXplT2JzZXJ2ZXIpIHtcbiAgICAgICAgICAgICAgICBzdG9wUmVzaXplT2JzZXJ2ZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0b3BSZXNpemVPYnNlcnZlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfTtcbiAgICAgICAgY2hlY2tNZWFzdXJpbmcoKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBzdG9wTWVhc3VyaW5nKCk7IH0pO1xuICAgICAgICAvLyBJbiB0aGVvcnkgd2UgY291bGQgcmVseSBvbiB0aGUgcmVzaXplIG9ic2VydmVyIGZvciBldmVyeXRoaW5nIC0gYnV0IHNpbmNlIGl0J3MgZGVib3VuY2VkXG4gICAgICAgIC8vIGl0IGNhbiBiZSBhIGxpdHRsZSBqYW5reSBmb3Igc21vb3RoIG1vdmVtZW50LiBpbiB0aGlzIGNhc2UgaXRzIGJldHRlciB0byByZWFjdCB0byBvdXIgb3duIGV2ZW50c1xuICAgICAgICAvLyBBbmQgdW5mb3J0dW5hdGVseSB3ZSBjYW50IF9qdXN0XyByZWx5IG9uIG91ciBvd24gZXZlbnRzLCBzaW5jZSBjdXN0b20gY29tcG9uZW50cyBjYW4gY2hhbmdlIHdoZW5ldmVyXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuY29sdW1uLCBDb2x1bW4uRVZFTlRfV0lEVEhfQ0hBTkdFRCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gaXNNZWFzdXJpbmcgJiYgbWVhc3VyZUhlaWdodCgwKTsgfSk7XG4gICAgICAgIC8vIERpc3BsYXlpbmcgdGhlIHNvcnQgaWNvbiBjaGFuZ2VzIHRoZSBhdmFpbGFibGUgYXJlYSBmb3IgdGV4dCwgc28gc29ydCBjaGFuZ2VzIGNhbiBhZmZlY3QgaGVpZ2h0XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuY29sdW1uLCBDb2x1bW4uRVZFTlRfU09SVF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBSZW5kZXJpbmcgY2hhbmdlcyBmb3Igc29ydCwgaGFwcGVuIGFmdGVyIHRoZSBldmVudC4uLiBub3QgaWRlYWxcbiAgICAgICAgICAgIGlmIChpc01lYXN1cmluZykge1xuICAgICAgICAgICAgICAgIF90aGlzLmJlYW5zLmZyYW1ld29ya092ZXJyaWRlcy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIG1lYXN1cmVIZWlnaHQoMCk7IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRSZWZyZXNoRnVuY3Rpb24oY2hlY2tNZWFzdXJpbmcpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnJlZnJlc2hBcmlhU29ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuc29ydGFibGUpIHtcbiAgICAgICAgICAgIHZhciB0cmFuc2xhdGUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMb2NhbGVUZXh0RnVuYygpO1xuICAgICAgICAgICAgdGhpcy5jb21wLnNldEFyaWFTb3J0KGdldEFyaWFTb3J0U3RhdGUodGhpcy5jb2x1bW4pKTtcbiAgICAgICAgICAgIHRoaXMuc2V0QXJpYURlc2NyaXB0aW9uUHJvcGVydHkoJ3NvcnQnLCB0cmFuc2xhdGUoJ2FyaWFTb3J0YWJsZUNvbHVtbicsICdQcmVzcyBFTlRFUiB0byBzb3J0LicpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXRBcmlhU29ydCgpO1xuICAgICAgICAgICAgdGhpcy5zZXRBcmlhRGVzY3JpcHRpb25Qcm9wZXJ0eSgnc29ydCcsIG51bGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUucmVmcmVzaEFyaWFNZW51ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5tZW51RW5hYmxlZCkge1xuICAgICAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgICAgICB0aGlzLnNldEFyaWFEZXNjcmlwdGlvblByb3BlcnR5KCdtZW51JywgdHJhbnNsYXRlKCdhcmlhTWVudUNvbHVtbicsICdQcmVzcyBDVFJMIEVOVEVSIHRvIG9wZW4gY29sdW1uIG1lbnUuJykpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXRBcmlhRGVzY3JpcHRpb25Qcm9wZXJ0eSgnbWVudScsIG51bGwpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0QXJpYURlc2NyaXB0aW9uUHJvcGVydHkgPSBmdW5jdGlvbiAocHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmFyaWFEZXNjcmlwdGlvblByb3BlcnRpZXMuc2V0KHByb3BlcnR5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmFyaWFEZXNjcmlwdGlvblByb3BlcnRpZXMuZGVsZXRlKHByb3BlcnR5KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnJlZnJlc2hBcmlhRGVzY3JpcHRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkZXNjcmlwdGlvbkFycmF5ID0gQXJyYXkuZnJvbSh0aGlzLmFyaWFEZXNjcmlwdGlvblByb3BlcnRpZXMudmFsdWVzKCkpO1xuICAgICAgICB0aGlzLmNvbXAuc2V0QXJpYURlc2NyaXB0aW9uKGRlc2NyaXB0aW9uQXJyYXkubGVuZ3RoID8gZGVzY3JpcHRpb25BcnJheS5qb2luKCcgJykgOiB1bmRlZmluZWQpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnJlZnJlc2hBcmlhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhU29ydCgpO1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhTWVudSgpO1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhRGVzY3JpcHRpb24oKTtcbiAgICB9O1xuICAgIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZS5hZGRDb2x1bW5Ib3Zlckxpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0NvbHVtbkhvdmVySGlnaGxpZ2h0KCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaXNIb3ZlcmVkID0gX3RoaXMuY29sdW1uSG92ZXJTZXJ2aWNlLmlzSG92ZXJlZChfdGhpcy5jb2x1bW4pO1xuICAgICAgICAgICAgX3RoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1jb2x1bW4taG92ZXInLCBpc0hvdmVyZWQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9IT1ZFUl9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBGaWx0ZXJDc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctaGVhZGVyLWNlbGwtZmlsdGVyZWQnLCBfdGhpcy5jb2x1bW4uaXNGaWx0ZXJBY3RpdmUoKSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuY29sdW1uLCBDb2x1bW4uRVZFTlRfRklMVEVSX0FDVElWRV9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBDb2xJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb21wLnNldENvbElkKHRoaXMuY29sdW1uLmdldENvbElkKCkpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLmFkZEFjdGl2ZUhlYWRlck1vdXNlTGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbGlzdGVuZXIgPSBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMuc2V0QWN0aXZlSGVhZGVyKGUudHlwZSA9PT0gJ21vdXNlZW50ZXInKTsgfTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5nZXRHdWkoKSwgJ21vdXNlZW50ZXInLCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ2V0R3VpKCksICdtb3VzZWxlYXZlJywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLnNldEFjdGl2ZUhlYWRlciA9IGZ1bmN0aW9uIChhY3RpdmUpIHtcbiAgICAgICAgdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWhlYWRlci1hY3RpdmUnLCBhY3RpdmUpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxbChbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWwoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbkhvdmVyU2VydmljZScpXG4gICAgXSwgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLCBcImNvbHVtbkhvdmVyU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWwoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NvcnRDb250cm9sbGVyJylcbiAgICBdLCBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwic29ydENvbnRyb2xsZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFsKFtcbiAgICAgICAgQXV0b3dpcmVkKCdtZW51RmFjdG9yeScpXG4gICAgXSwgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLCBcIm1lbnVGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxbChbXG4gICAgICAgIEF1dG93aXJlZCgnZHJhZ0FuZERyb3BTZXJ2aWNlJylcbiAgICBdLCBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwiZHJhZ0FuZERyb3BTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxbChbXG4gICAgICAgIEF1dG93aXJlZCgncmVzaXplT2JzZXJ2ZXJTZXJ2aWNlJylcbiAgICBdLCBIZWFkZXJDZWxsQ3RybC5wcm90b3R5cGUsIFwicmVzaXplT2JzZXJ2ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxbChbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZEFwaScpXG4gICAgXSwgSGVhZGVyQ2VsbEN0cmwucHJvdG90eXBlLCBcImdyaWRBcGlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFsKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5BcGknKVxuICAgIF0sIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZSwgXCJjb2x1bW5BcGlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFsKFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIEhlYWRlckNlbGxDdHJsLnByb3RvdHlwZSwgXCJyZW1vdmVEcmFnU291cmNlXCIsIG51bGwpO1xuICAgIHJldHVybiBIZWFkZXJDZWxsQ3RybDtcbn0oQWJzdHJhY3RIZWFkZXJDZWxsQ3RybCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxayA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEdyb3VwUmVzaXplRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMXIoR3JvdXBSZXNpemVGZWF0dXJlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdyb3VwUmVzaXplRmVhdHVyZShjb21wLCBlUmVzaXplLCBwaW5uZWQsIGNvbHVtbkdyb3VwKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmVSZXNpemUgPSBlUmVzaXplO1xuICAgICAgICBfdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgX3RoaXMucGlubmVkID0gcGlubmVkO1xuICAgICAgICBfdGhpcy5jb2x1bW5Hcm91cCA9IGNvbHVtbkdyb3VwO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEdyb3VwUmVzaXplRmVhdHVyZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmNvbHVtbkdyb3VwLmlzUmVzaXphYmxlKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZVJlc2l6YWJsZUNzc0NsYXNzKCdhZy1oaWRkZW4nLCB0cnVlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmluaXNoZWRXaXRoUmVzaXplRnVuYyA9IHRoaXMuaG9yaXpvbnRhbFJlc2l6ZVNlcnZpY2UuYWRkUmVzaXplQmFyKHtcbiAgICAgICAgICAgIGVSZXNpemVCYXI6IHRoaXMuZVJlc2l6ZSxcbiAgICAgICAgICAgIG9uUmVzaXplU3RhcnQ6IHRoaXMub25SZXNpemVTdGFydC5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgb25SZXNpemluZzogdGhpcy5vblJlc2l6aW5nLmJpbmQodGhpcywgZmFsc2UpLFxuICAgICAgICAgICAgb25SZXNpemVFbmQ6IHRoaXMub25SZXNpemluZy5iaW5kKHRoaXMsIHRydWUpXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZpbmlzaGVkV2l0aFJlc2l6ZUZ1bmMpO1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NBdXRvU2l6ZSgpKSB7XG4gICAgICAgICAgICB2YXIgc2tpcEhlYWRlck9uQXV0b1NpemVfMSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU2tpcEhlYWRlck9uQXV0b1NpemUoKTtcbiAgICAgICAgICAgIHRoaXMuZVJlc2l6ZS5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyBnZXQgbGlzdCBvZiBhbGwgdGhlIGNvbHVtbiBrZXlzIHdlIGFyZSByZXNwb25zaWJsZSBmb3JcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZWFmQ29scyA9IF90aGlzLmNvbHVtbkdyb3VwLmdldERpc3BsYXllZExlYWZDb2x1bW5zKCk7XG4gICAgICAgICAgICAgICAgbGVhZkNvbHMuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG5vdCBhbGwgY29scyBpbiB0aGUgZ3JvdXAgbWF5IGJlIHBhcnRpY2lwYXRpbmcgd2l0aCBhdXRvLXJlc2l6ZVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbHVtbi5nZXRDb2xEZWYoKS5zdXBwcmVzc0F1dG9TaXplKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzLnB1c2goY29sdW1uLmdldENvbElkKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5jb2x1bW5Nb2RlbC5hdXRvU2l6ZUNvbHVtbnMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uczoga2V5cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNraXBIZWFkZXI6IHNraXBIZWFkZXJPbkF1dG9TaXplXzEsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdG9wQXRHcm91cDogX3RoaXMuY29sdW1uR3JvdXAsXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6ICd1aUNvbHVtblJlc2l6ZWQnXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfdGhpcy5yZXNpemVMZWFmQ29sdW1uc1RvRml0KCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgR3JvdXBSZXNpemVGZWF0dXJlLnByb3RvdHlwZS5vblJlc2l6ZVN0YXJ0ID0gZnVuY3Rpb24gKHNoaWZ0S2V5KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlSW5pdGlhbFZhbHVlcygpO1xuICAgICAgICB2YXIgdGFrZUZyb21Hcm91cCA9IG51bGw7XG4gICAgICAgIGlmIChzaGlmdEtleSkge1xuICAgICAgICAgICAgdGFrZUZyb21Hcm91cCA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkR3JvdXBBZnRlcih0aGlzLmNvbHVtbkdyb3VwKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFrZUZyb21Hcm91cCkge1xuICAgICAgICAgICAgdmFyIHRha2VGcm9tTGVhZkNvbHMgPSB0YWtlRnJvbUdyb3VwLmdldERpc3BsYXllZExlYWZDb2x1bW5zKCk7XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVRha2VGcm9tQ29scyA9IHRha2VGcm9tTGVhZkNvbHMuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5pc1Jlc2l6YWJsZSgpOyB9KTtcbiAgICAgICAgICAgIHRoaXMucmVzaXplVGFrZUZyb21TdGFydFdpZHRoID0gMDtcbiAgICAgICAgICAgIHRoaXMucmVzaXplVGFrZUZyb21Db2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gX3RoaXMucmVzaXplVGFrZUZyb21TdGFydFdpZHRoICs9IGNvbC5nZXRBY3R1YWxXaWR0aCgpOyB9KTtcbiAgICAgICAgICAgIHRoaXMucmVzaXplVGFrZUZyb21SYXRpb3MgPSBbXTtcbiAgICAgICAgICAgIHRoaXMucmVzaXplVGFrZUZyb21Db2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gX3RoaXMucmVzaXplVGFrZUZyb21SYXRpb3MucHVzaChjb2wuZ2V0QWN0dWFsV2lkdGgoKSAvIF90aGlzLnJlc2l6ZVRha2VGcm9tU3RhcnRXaWR0aCk7IH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZXNpemVUYWtlRnJvbUNvbHMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5yZXNpemVUYWtlRnJvbVN0YXJ0V2lkdGggPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5yZXNpemVUYWtlRnJvbVJhdGlvcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWNvbHVtbi1yZXNpemluZycsIHRydWUpO1xuICAgIH07XG4gICAgR3JvdXBSZXNpemVGZWF0dXJlLnByb3RvdHlwZS5vblJlc2l6aW5nID0gZnVuY3Rpb24gKGZpbmlzaGVkLCByZXNpemVBbW91bnQpIHtcbiAgICAgICAgdmFyIHJlc2l6ZUFtb3VudE5vcm1hbGlzZWQgPSB0aGlzLm5vcm1hbGlzZURyYWdDaGFuZ2UocmVzaXplQW1vdW50KTtcbiAgICAgICAgdmFyIHdpZHRoID0gdGhpcy5yZXNpemVTdGFydFdpZHRoICsgcmVzaXplQW1vdW50Tm9ybWFsaXNlZDtcbiAgICAgICAgdGhpcy5yZXNpemVDb2x1bW5zKHdpZHRoLCBmaW5pc2hlZCk7XG4gICAgfTtcbiAgICBHcm91cFJlc2l6ZUZlYXR1cmUucHJvdG90eXBlLnJlc2l6ZUxlYWZDb2x1bW5zVG9GaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwcmVmZXJyZWRTaXplID0gdGhpcy5hdXRvV2lkdGhDYWxjdWxhdG9yLmdldFByZWZlcnJlZFdpZHRoRm9yQ29sdW1uR3JvdXAodGhpcy5jb2x1bW5Hcm91cCk7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlSW5pdGlhbFZhbHVlcygpO1xuICAgICAgICBpZiAocHJlZmVycmVkU2l6ZSA+IHRoaXMucmVzaXplU3RhcnRXaWR0aCkge1xuICAgICAgICAgICAgdGhpcy5yZXNpemVDb2x1bW5zKHByZWZlcnJlZFNpemUsIHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcm91cFJlc2l6ZUZlYXR1cmUucHJvdG90eXBlLnJlc2l6ZUNvbHVtbnMgPSBmdW5jdGlvbiAodG90YWxXaWR0aCwgZmluaXNoZWQpIHtcbiAgICAgICAgaWYgKGZpbmlzaGVkID09PSB2b2lkIDApIHsgZmluaXNoZWQgPSB0cnVlOyB9XG4gICAgICAgIHZhciByZXNpemVTZXRzID0gW107XG4gICAgICAgIHJlc2l6ZVNldHMucHVzaCh7XG4gICAgICAgICAgICBjb2x1bW5zOiB0aGlzLnJlc2l6ZUNvbHMsXG4gICAgICAgICAgICByYXRpb3M6IHRoaXMucmVzaXplUmF0aW9zLFxuICAgICAgICAgICAgd2lkdGg6IHRvdGFsV2lkdGhcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLnJlc2l6ZVRha2VGcm9tQ29scykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSB0b3RhbFdpZHRoIC0gdGhpcy5yZXNpemVTdGFydFdpZHRoO1xuICAgICAgICAgICAgcmVzaXplU2V0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBjb2x1bW5zOiB0aGlzLnJlc2l6ZVRha2VGcm9tQ29scyxcbiAgICAgICAgICAgICAgICByYXRpb3M6IHRoaXMucmVzaXplVGFrZUZyb21SYXRpb3MsXG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMucmVzaXplVGFrZUZyb21TdGFydFdpZHRoIC0gZGlmZlxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5yZXNpemVDb2x1bW5TZXRzKHtcbiAgICAgICAgICAgIHJlc2l6ZVNldHM6IHJlc2l6ZVNldHMsXG4gICAgICAgICAgICBmaW5pc2hlZDogZmluaXNoZWQsXG4gICAgICAgICAgICBzb3VyY2U6ICd1aUNvbHVtbkRyYWdnZWQnXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZmluaXNoZWQpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1jb2x1bW4tcmVzaXppbmcnLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyb3VwUmVzaXplRmVhdHVyZS5wcm90b3R5cGUuY2FsY3VsYXRlSW5pdGlhbFZhbHVlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGxlYWZDb2xzID0gdGhpcy5jb2x1bW5Hcm91cC5nZXREaXNwbGF5ZWRMZWFmQ29sdW1ucygpO1xuICAgICAgICB0aGlzLnJlc2l6ZUNvbHMgPSBsZWFmQ29scy5maWx0ZXIoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gY29sLmlzUmVzaXphYmxlKCk7IH0pO1xuICAgICAgICB0aGlzLnJlc2l6ZVN0YXJ0V2lkdGggPSAwO1xuICAgICAgICB0aGlzLnJlc2l6ZUNvbHMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBfdGhpcy5yZXNpemVTdGFydFdpZHRoICs9IGNvbC5nZXRBY3R1YWxXaWR0aCgpOyB9KTtcbiAgICAgICAgdGhpcy5yZXNpemVSYXRpb3MgPSBbXTtcbiAgICAgICAgdGhpcy5yZXNpemVDb2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gX3RoaXMucmVzaXplUmF0aW9zLnB1c2goY29sLmdldEFjdHVhbFdpZHRoKCkgLyBfdGhpcy5yZXNpemVTdGFydFdpZHRoKTsgfSk7XG4gICAgfTtcbiAgICAvLyBvcHRpb25hbGx5IGludmVydHMgdGhlIGRyYWcsIGRlcGVuZGluZyBvbiBwaW5uZWQgYW5kIFJUTFxuICAgIC8vIG5vdGUgLSB0aGlzIG1ldGhvZCBpcyBkdXBsaWNhdGVkIGluIFJlbmRlcmVkSGVhZGVyQ2VsbCAtIHNob3VsZCByZWZhY3RvciBvdXQ/XG4gICAgR3JvdXBSZXNpemVGZWF0dXJlLnByb3RvdHlwZS5ub3JtYWxpc2VEcmFnQ2hhbmdlID0gZnVuY3Rpb24gKGRyYWdDaGFuZ2UpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGRyYWdDaGFuZ2U7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICAvLyBmb3IgUlRMLCBkcmFnZ2luZyBsZWZ0IG1ha2VzIHRoZSBjb2wgYmlnZ2VyLCBleGNlcHQgd2hlbiBwaW5uaW5nIGxlZnRcbiAgICAgICAgICAgIGlmICh0aGlzLnBpbm5lZCAhPT0gQ29uc3RhbnRzLlBJTk5FRF9MRUZUKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICo9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMucGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX1JJR0hUKSB7XG4gICAgICAgICAgICAvLyBmb3IgTFRSIChpZSBub3JtYWwpLCBkcmFnZ2luZyBsZWZ0IG1ha2VzIHRoZSBjb2wgc21hbGxlciwgZXhjZXB0IHdoZW4gcGlubmluZyByaWdodFxuICAgICAgICAgICAgcmVzdWx0ICo9IC0xO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFrKFtcbiAgICAgICAgQXV0b3dpcmVkKCdob3Jpem9udGFsUmVzaXplU2VydmljZScpXG4gICAgXSwgR3JvdXBSZXNpemVGZWF0dXJlLnByb3RvdHlwZSwgXCJob3Jpem9udGFsUmVzaXplU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWsoW1xuICAgICAgICBBdXRvd2lyZWQoJ2F1dG9XaWR0aENhbGN1bGF0b3InKVxuICAgIF0sIEdyb3VwUmVzaXplRmVhdHVyZS5wcm90b3R5cGUsIFwiYXV0b1dpZHRoQ2FsY3VsYXRvclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWsoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBHcm91cFJlc2l6ZUZlYXR1cmUucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxayhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBHcm91cFJlc2l6ZUZlYXR1cmUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEdyb3VwUmVzaXplRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxcSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMWogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBHcm91cFdpZHRoRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMXEoR3JvdXBXaWR0aEZlYXR1cmUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gR3JvdXBXaWR0aEZlYXR1cmUoY29tcCwgY29sdW1uR3JvdXApIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgLy8gdGhlIGNoaWxkcmVuIGNhbiBjaGFuZ2UsIHdlIGtlZXAgZGVzdHJveSBmdW5jdGlvbnMgcmVsYXRlZCB0byBsaXN0ZW5pbmcgdG8gdGhlIGNoaWxkcmVuIGhlcmVcbiAgICAgICAgX3RoaXMucmVtb3ZlQ2hpbGRMaXN0ZW5lcnNGdW5jcyA9IFtdO1xuICAgICAgICBfdGhpcy5jb2x1bW5Hcm91cCA9IGNvbHVtbkdyb3VwO1xuICAgICAgICBfdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBHcm91cFdpZHRoRmVhdHVyZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2UgbmVlZCB0byBsaXN0ZW4gdG8gY2hhbmdlcyBpbiBjaGlsZCBjb2x1bW5zLCBhcyB0aGV5IGltcGFjdCBvdXIgd2lkdGhcbiAgICAgICAgdGhpcy5hZGRMaXN0ZW5lcnNUb0NoaWxkcmVuQ29sdW1ucygpO1xuICAgICAgICAvLyB0aGUgY2hpbGRyZW4gYmVsb25naW5nIHRvIHRoaXMgZ3JvdXAgY2FuIGNoYW5nZSwgc28gd2UgbmVlZCB0byBhZGQgYW5kIHJlbW92ZSBsaXN0ZW5lcnMgYXMgdGhleSBjaGFuZ2VcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5jb2x1bW5Hcm91cCwgQ29sdW1uR3JvdXAuRVZFTlRfRElTUExBWUVEX0NISUxEUkVOX0NIQU5HRUQsIHRoaXMub25EaXNwbGF5ZWRDaGlsZHJlbkNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMub25XaWR0aENoYW5nZWQoKTtcbiAgICAgICAgLy8gdGhlIGNoaWxkIGxpc3RlbmVycyBhcmUgbm90IHRpZWQgdG8gdGhpcyBjb21wb25lbnRzIGxpZmUtY3ljbGUsIGFzIGNoaWxkcmVuIGNhbiBnZXQgYWRkZWQgYW5kIHJlbW92ZWRcbiAgICAgICAgLy8gdG8gdGhlIGdyb3VwIC0gaGVuY2UgdGhleSBhcmUgb24gYSBkaWZmZXJlbnQgbGlmZS1jeWNsZS4gc28gd2UgbXVzdCBtYWtlIHN1cmUgdGhlIGV4aXN0aW5nIGNoaWxkcmVuXG4gICAgICAgIC8vIGxpc3RlbmVycyBhcmUgcmVtb3ZlZCB3aGVuIHdlIGZpbmFsbHkgZ2V0IGRlc3Ryb3llZFxuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKHRoaXMucmVtb3ZlTGlzdGVuZXJzT25DaGlsZHJlbkNvbHVtbnMuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBHcm91cFdpZHRoRmVhdHVyZS5wcm90b3R5cGUuYWRkTGlzdGVuZXJzVG9DaGlsZHJlbkNvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIGZpcnN0IGRlc3Ryb3kgYW55IG9sZCBsaXN0ZW5lcnNcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcnNPbkNoaWxkcmVuQ29sdW1ucygpO1xuICAgICAgICAvLyBub3cgYWRkIG5ldyBsaXN0ZW5lcnMgdG8gdGhlIG5ldyBzZXQgb2YgY2hpbGRyZW5cbiAgICAgICAgdmFyIHdpZHRoQ2hhbmdlZExpc3RlbmVyID0gdGhpcy5vbldpZHRoQ2hhbmdlZC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmNvbHVtbkdyb3VwLmdldExlYWZDb2x1bW5zKCkuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgICBjb2x1bW4uYWRkRXZlbnRMaXN0ZW5lcihDb2x1bW4uRVZFTlRfV0lEVEhfQ0hBTkdFRCwgd2lkdGhDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICAgICAgY29sdW1uLmFkZEV2ZW50TGlzdGVuZXIoQ29sdW1uLkVWRU5UX1ZJU0lCTEVfQ0hBTkdFRCwgd2lkdGhDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICAgICAgX3RoaXMucmVtb3ZlQ2hpbGRMaXN0ZW5lcnNGdW5jcy5wdXNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW4ucmVtb3ZlRXZlbnRMaXN0ZW5lcihDb2x1bW4uRVZFTlRfV0lEVEhfQ0hBTkdFRCwgd2lkdGhDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIGNvbHVtbi5yZW1vdmVFdmVudExpc3RlbmVyKENvbHVtbi5FVkVOVF9WSVNJQkxFX0NIQU5HRUQsIHdpZHRoQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEdyb3VwV2lkdGhGZWF0dXJlLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lcnNPbkNoaWxkcmVuQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVDaGlsZExpc3RlbmVyc0Z1bmNzLmZvckVhY2goZnVuY3Rpb24gKGZ1bmMpIHsgcmV0dXJuIGZ1bmMoKTsgfSk7XG4gICAgICAgIHRoaXMucmVtb3ZlQ2hpbGRMaXN0ZW5lcnNGdW5jcyA9IFtdO1xuICAgIH07XG4gICAgR3JvdXBXaWR0aEZlYXR1cmUucHJvdG90eXBlLm9uRGlzcGxheWVkQ2hpbGRyZW5DaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZExpc3RlbmVyc1RvQ2hpbGRyZW5Db2x1bW5zKCk7XG4gICAgICAgIHRoaXMub25XaWR0aENoYW5nZWQoKTtcbiAgICB9O1xuICAgIEdyb3VwV2lkdGhGZWF0dXJlLnByb3RvdHlwZS5vbldpZHRoQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb21wLnNldFdpZHRoKHRoaXMuY29sdW1uR3JvdXAuZ2V0QWN0dWFsV2lkdGgoKSArICdweCcpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxaihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBHcm91cFdpZHRoRmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gR3JvdXBXaWR0aEZlYXR1cmU7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMXAgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFpID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgSGVhZGVyR3JvdXBDZWxsQ3RybCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMXAoSGVhZGVyR3JvdXBDZWxsQ3RybCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBIZWFkZXJHcm91cENlbGxDdHJsKGNvbHVtbkdyb3VwLCBwYXJlbnRSb3dDdHJsKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNvbHVtbkdyb3VwLCBwYXJlbnRSb3dDdHJsKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5jb2x1bW5Hcm91cCA9IGNvbHVtbkdyb3VwO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLnNldENvbXAgPSBmdW5jdGlvbiAoY29tcCwgZUd1aSwgZVJlc2l6ZSkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnNldEd1aS5jYWxsKHRoaXMsIGVHdWkpO1xuICAgICAgICB0aGlzLmNvbXAgPSBjb21wO1xuICAgICAgICB0aGlzLmRpc3BsYXlOYW1lID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5TmFtZUZvckNvbHVtbkdyb3VwKHRoaXMuY29sdW1uR3JvdXAsICdoZWFkZXInKTtcbiAgICAgICAgdGhpcy5hZGRDbGFzc2VzKCk7XG4gICAgICAgIHRoaXMuYWRkQXR0cmlidXRlcygpO1xuICAgICAgICB0aGlzLnNldHVwTW92aW5nQ3NzKCk7XG4gICAgICAgIHRoaXMuc2V0dXBFeHBhbmRhYmxlKCk7XG4gICAgICAgIHRoaXMuc2V0dXBUb29sdGlwKCk7XG4gICAgICAgIHRoaXMuc2V0dXBVc2VyQ29tcCgpO1xuICAgICAgICB2YXIgcGlubmVkID0gdGhpcy5nZXRQYXJlbnRSb3dDdHJsKCkuZ2V0UGlubmVkKCk7XG4gICAgICAgIHZhciBsZWFmQ29scyA9IHRoaXMuY29sdW1uR3JvdXAuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCgpLmdldExlYWZDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEhvdmVyRmVhdHVyZShsZWFmQ29scywgZUd1aSkpO1xuICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBTZXRMZWZ0RmVhdHVyZSh0aGlzLmNvbHVtbkdyb3VwLCBlR3VpLCB0aGlzLmJlYW5zKSk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEdyb3VwV2lkdGhGZWF0dXJlKGNvbXAsIHRoaXMuY29sdW1uR3JvdXApKTtcbiAgICAgICAgdGhpcy5ncm91cFJlc2l6ZUZlYXR1cmUgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBHcm91cFJlc2l6ZUZlYXR1cmUoY29tcCwgZVJlc2l6ZSwgcGlubmVkLCB0aGlzLmNvbHVtbkdyb3VwKSk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IE1hbmFnZWRGb2N1c0ZlYXR1cmUoZUd1aSwge1xuICAgICAgICAgICAgc2hvdWxkU3RvcEV2ZW50UHJvcGFnYXRpb246IHRoaXMuc2hvdWxkU3RvcEV2ZW50UHJvcGFnYXRpb24uYmluZCh0aGlzKSxcbiAgICAgICAgICAgIG9uVGFiS2V5RG93bjogZnVuY3Rpb24gKCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9LFxuICAgICAgICAgICAgaGFuZGxlS2V5RG93bjogdGhpcy5oYW5kbGVLZXlEb3duLmJpbmQodGhpcyksXG4gICAgICAgICAgICBvbkZvY3VzSW46IHRoaXMub25Gb2N1c0luLmJpbmQodGhpcylcbiAgICAgICAgfSkpO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDZWxsQ3RybC5wcm90b3R5cGUucmVzaXplTGVhZkNvbHVtbnNUb0ZpdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5ncm91cFJlc2l6ZUZlYXR1cmUub25SZXNpemVTdGFydChmYWxzZSk7XG4gICAgICAgIHRoaXMuZ3JvdXBSZXNpemVGZWF0dXJlLnJlc2l6ZUxlYWZDb2x1bW5zVG9GaXQoKTtcbiAgICB9O1xuICAgIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwVXNlckNvbXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBkaXNwbGF5TmFtZSA9IHRoaXMuZGlzcGxheU5hbWU7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogdGhpcy5kaXNwbGF5TmFtZSxcbiAgICAgICAgICAgIGNvbHVtbkdyb3VwOiB0aGlzLmNvbHVtbkdyb3VwLFxuICAgICAgICAgICAgc2V0RXhwYW5kZWQ6IGZ1bmN0aW9uIChleHBhbmRlZCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbkdyb3VwT3BlbmVkKF90aGlzLmNvbHVtbkdyb3VwLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoKSwgZXhwYW5kZWQsIFwiZ3JpZEluaXRpYWxpemluZ1wiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZEFwaSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5jb2x1bW5BcGksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KClcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKCFkaXNwbGF5TmFtZSkge1xuICAgICAgICAgICAgdmFyIGNvbHVtbkdyb3VwID0gdGhpcy5jb2x1bW5Hcm91cDtcbiAgICAgICAgICAgIHZhciBsZWFmQ29scyA9IGNvbHVtbkdyb3VwLmdldExlYWZDb2x1bW5zKCk7XG4gICAgICAgICAgICAvLyBmaW5kIHRoZSB0b3AgbW9zdCBjb2x1bW4gZ3JvdXAgdGhhdCByZXByZXNlbnRzIHRoZSBzYW1lIGNvbHVtbnMuIHNvIGlmIHdlIGFyZSBkcmFnZ2luZyBhIGdyb3VwLCB3ZSBhbHNvXG4gICAgICAgICAgICAvLyB3YW50IHRvIHZpc3VhbGx5IHNob3cgdGhlIHBhcmVudCBncm91cHMgZHJhZ2dpbmcgZm9yIHRoZSBzYW1lIGNvbHVtbiBzZXQuIGZvciBleGFtcGxlIGltYWdpbmcgNSBsZXZlbHNcbiAgICAgICAgICAgIC8vIG9mIGdyb3VwaW5nLCB3aXRoIGVhY2ggZ3JvdXAgb25seSBjb250YWluaW5nIHRoZSBuZXh0IGdyb3VwLCBhbmQgdGhlIGxhc3QgZ3JvdXAgY29udGFpbmluZyB0aHJlZSBjb2x1bW5zLFxuICAgICAgICAgICAgLy8gdGhlbiB3aGVuIHlvdSBtb3ZlIGFueSBncm91cCAoZXZlbiB0aGUgbG93ZXN0IGxldmVsIGdyb3VwKSB5b3UgYXJlIGluLWZhY3QgbW92aW5nIGFsbCB0aGUgZ3JvdXBzLCBhcyBhbGxcbiAgICAgICAgICAgIC8vIHRoZSBncm91cHMgcmVwcmVzZW50IHRoZSBzYW1lIGNvbHVtbiBzZXQuXG4gICAgICAgICAgICB3aGlsZSAoY29sdW1uR3JvdXAuZ2V0UGFyZW50KCkgJiYgY29sdW1uR3JvdXAuZ2V0UGFyZW50KCkuZ2V0TGVhZkNvbHVtbnMoKS5sZW5ndGggPT09IGxlYWZDb2xzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNvbHVtbkdyb3VwID0gY29sdW1uR3JvdXAuZ2V0UGFyZW50KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY29sR3JvdXBEZWYgPSBjb2x1bW5Hcm91cC5nZXRDb2xHcm91cERlZigpO1xuICAgICAgICAgICAgaWYgKGNvbEdyb3VwRGVmKSB7XG4gICAgICAgICAgICAgICAgZGlzcGxheU5hbWUgPSBjb2xHcm91cERlZi5oZWFkZXJOYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFkaXNwbGF5TmFtZSkge1xuICAgICAgICAgICAgICAgIGRpc3BsYXlOYW1lID0gbGVhZkNvbHMgPyB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXlOYW1lRm9yQ29sdW1uKGxlYWZDb2xzWzBdLCAnaGVhZGVyJywgdHJ1ZSkgOiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tcERldGFpbHMgPSB0aGlzLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldEhlYWRlckdyb3VwQ29tcERldGFpbHMocGFyYW1zKTtcbiAgICAgICAgdGhpcy5jb21wLnNldFVzZXJDb21wRGV0YWlscyhjb21wRGV0YWlscyk7XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENlbGxDdHJsLnByb3RvdHlwZS5zZXR1cFRvb2x0aXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb2xHcm91cERlZiA9IHRoaXMuY29sdW1uR3JvdXAuZ2V0Q29sR3JvdXBEZWYoKTtcbiAgICAgICAgdmFyIHRvb2x0aXBDdHJsID0ge1xuICAgICAgICAgICAgZ2V0Q29sdW1uOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jb2x1bW5Hcm91cDsgfSxcbiAgICAgICAgICAgIGdldEd1aTogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZUd1aTsgfSxcbiAgICAgICAgICAgIGdldExvY2F0aW9uOiBmdW5jdGlvbiAoKSB7IHJldHVybiAnaGVhZGVyR3JvdXAnOyB9LFxuICAgICAgICAgICAgZ2V0VG9vbHRpcFZhbHVlOiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb2xHcm91cERlZiAmJiBjb2xHcm91cERlZi5oZWFkZXJUb29sdGlwOyB9XG4gICAgICAgIH07XG4gICAgICAgIGlmIChjb2xHcm91cERlZikge1xuICAgICAgICAgICAgdG9vbHRpcEN0cmwuZ2V0Q29sRGVmID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gY29sR3JvdXBEZWY7IH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRvb2x0aXBGZWF0dXJlID0gdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgVG9vbHRpcEZlYXR1cmUodG9vbHRpcEN0cmwsIHRoaXMuYmVhbnMpKTtcbiAgICAgICAgdG9vbHRpcEZlYXR1cmUuc2V0Q29tcCh0aGlzLmNvbXApO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDZWxsQ3RybC5wcm90b3R5cGUuc2V0dXBFeHBhbmRhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcHJvdmlkZWRDb2xHcm91cCA9IHRoaXMuY29sdW1uR3JvdXAuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCgpO1xuICAgICAgICB0aGlzLnJlZnJlc2hFeHBhbmRlZCgpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihwcm92aWRlZENvbEdyb3VwLCBQcm92aWRlZENvbHVtbkdyb3VwLkVWRU5UX0VYUEFOREFCTEVfQ0hBTkdFRCwgdGhpcy5yZWZyZXNoRXhwYW5kZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHByb3ZpZGVkQ29sR3JvdXAsIFByb3ZpZGVkQ29sdW1uR3JvdXAuRVZFTlRfRVhQQU5ERURfQ0hBTkdFRCwgdGhpcy5yZWZyZXNoRXhwYW5kZWQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENlbGxDdHJsLnByb3RvdHlwZS5yZWZyZXNoRXhwYW5kZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbkdyb3VwO1xuICAgICAgICB0aGlzLmV4cGFuZGFibGUgPSBjb2x1bW4uaXNFeHBhbmRhYmxlKCk7XG4gICAgICAgIHZhciBleHBhbmRlZCA9IGNvbHVtbi5pc0V4cGFuZGVkKCk7XG4gICAgICAgIGlmICh0aGlzLmV4cGFuZGFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXRBcmlhRXhwYW5kZWQoZXhwYW5kZWQgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29tcC5zZXRBcmlhRXhwYW5kZWQodW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDZWxsQ3RybC5wcm90b3R5cGUuYWRkQXR0cmlidXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb21wLnNldENvbElkKHRoaXMuY29sdW1uR3JvdXAuZ2V0VW5pcXVlSWQoKSk7XG4gICAgfTtcbiAgICBIZWFkZXJHcm91cENlbGxDdHJsLnByb3RvdHlwZS5hZGRDbGFzc2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29sR3JvdXBEZWYgPSB0aGlzLmNvbHVtbkdyb3VwLmdldENvbEdyb3VwRGVmKCk7XG4gICAgICAgIHZhciBjbGFzc2VzID0gQ3NzQ2xhc3NBcHBsaWVyLmdldEhlYWRlckNsYXNzZXNGcm9tQ29sRGVmKGNvbEdyb3VwRGVmLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCwgdGhpcy5jb2x1bW5Hcm91cCk7XG4gICAgICAgIC8vIGhhdmluZyBkaWZmZXJlbnQgY2xhc3NlcyBiZWxvdyBhbGxvd3MgdGhlIHN0eWxlIHRvIG5vdCBoYXZlIGEgYm90dG9tIGJvcmRlclxuICAgICAgICAvLyBvbiB0aGUgZ3JvdXAgaGVhZGVyLCBpZiBubyBncm91cCBpcyBzcGVjaWZpZWRcbiAgICAgICAgY2xhc3Nlcy5wdXNoKHRoaXMuY29sdW1uR3JvdXAuaXNQYWRkaW5nKCkgPyBcImFnLWhlYWRlci1ncm91cC1jZWxsLW5vLWdyb3VwXCIgOiBcImFnLWhlYWRlci1ncm91cC1jZWxsLXdpdGgtZ3JvdXBcIik7XG4gICAgICAgIGNsYXNzZXMuZm9yRWFjaChmdW5jdGlvbiAoYykgeyByZXR1cm4gX3RoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKGMsIHRydWUpOyB9KTtcbiAgICB9O1xuICAgIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLnNldHVwTW92aW5nQ3NzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcHJvdmlkZWRDb2x1bW5Hcm91cCA9IHRoaXMuY29sdW1uR3JvdXAuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCgpO1xuICAgICAgICB2YXIgbGVhZkNvbHVtbnMgPSBwcm92aWRlZENvbHVtbkdyb3VwLmdldExlYWZDb2x1bW5zKCk7XG4gICAgICAgIC8vIHRoaXMgZnVuY3Rpb24gYWRkcyBvciByZW1vdmVzIHRoZSBtb3ZpbmcgY3NzLCBiYXNlZCBvbiBpZiB0aGUgY29sIGlzIG1vdmluZy5cbiAgICAgICAgLy8gdGhpcyBpcyB3aGF0IG1ha2VzIHRoZSBoZWFkZXIgZ28gZGFyayB3aGVuIGl0IGlzIGJlZW4gbW92ZWQgKGdpdmVzIGltcHJlc3Npb24gdG9cbiAgICAgICAgLy8gdXNlciB0aGF0IHRoZSBjb2x1bW4gd2FzIHBpY2tlZCB1cCkuXG4gICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmNvbXAuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctaGVhZGVyLWNlbGwtbW92aW5nJywgX3RoaXMuY29sdW1uR3JvdXAuaXNNb3ZpbmcoKSk7IH07XG4gICAgICAgIGxlYWZDb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGNvbCwgQ29sdW1uLkVWRU5UX01PVklOR19DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICBsaXN0ZW5lcigpO1xuICAgIH07XG4gICAgSGVhZGVyR3JvdXBDZWxsQ3RybC5wcm90b3R5cGUub25Gb2N1c0luID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmVHdWkuY29udGFpbnMoZS5yZWxhdGVkVGFyZ2V0KSkge1xuICAgICAgICAgICAgdmFyIHJvd0luZGV4ID0gdGhpcy5nZXRSb3dJbmRleCgpO1xuICAgICAgICAgICAgdGhpcy5iZWFucy5mb2N1c1NlcnZpY2Uuc2V0Rm9jdXNlZEhlYWRlcihyb3dJbmRleCwgdGhpcy5jb2x1bW5Hcm91cCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmhhbmRsZUtleURvd24uY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgdmFyIHdyYXBwZXJIYXNGb2N1cyA9IHRoaXMuZ2V0V3JhcHBlckhhc0ZvY3VzKCk7XG4gICAgICAgIGlmICghdGhpcy5leHBhbmRhYmxlIHx8ICF3cmFwcGVySGFzRm9jdXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZS5rZXkgPT09IEtleUNvZGUuRU5URVIpIHtcbiAgICAgICAgICAgIHZhciBjb2x1bW4gPSB0aGlzLmNvbHVtbkdyb3VwO1xuICAgICAgICAgICAgdmFyIG5ld0V4cGFuZGVkVmFsdWUgPSAhY29sdW1uLmlzRXhwYW5kZWQoKTtcbiAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uR3JvdXBPcGVuZWQoY29sdW1uLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoKSwgbmV3RXhwYW5kZWRWYWx1ZSwgXCJ1aUNvbHVtbkV4cGFuZGVkXCIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyB1bmxpa2UgY29sdW1ucywgdGhpcyB3aWxsIG9ubHkgZ2V0IGNhbGxlZCBvbmNlLCBhcyB3ZSBkb24ndCByZWFjdCBvbiBwcm9wcyBvbiBjb2x1bW4gZ3JvdXBzXG4gICAgLy8gKHdlIHdpbGwgYWx3YXlzIGRlc3Ryb3kgYW5kIHJlY3JlYXRlIHRoaXMgY29tcCBpZiBzb21ldGhpbmcgY2hhbmdlcylcbiAgICBIZWFkZXJHcm91cENlbGxDdHJsLnByb3RvdHlwZS5zZXREcmFnU291cmNlID0gZnVuY3Rpb24gKGVIZWFkZXJHcm91cCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5pc1N1cHByZXNzTW92aW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYWxsTGVhZkNvbHVtbnMgPSB0aGlzLmNvbHVtbkdyb3VwLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoKS5nZXRMZWFmQ29sdW1ucygpO1xuICAgICAgICB2YXIgaGlkZUNvbHVtbk9uRXhpdCA9ICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzRHJhZ0xlYXZlSGlkZXNDb2x1bW5zKCk7XG4gICAgICAgIHZhciBkcmFnU291cmNlID0ge1xuICAgICAgICAgICAgdHlwZTogRHJhZ1NvdXJjZVR5cGUuSGVhZGVyQ2VsbCxcbiAgICAgICAgICAgIGVFbGVtZW50OiBlSGVhZGVyR3JvdXAsXG4gICAgICAgICAgICBkZWZhdWx0SWNvbk5hbWU6IGhpZGVDb2x1bW5PbkV4aXQgPyBEcmFnQW5kRHJvcFNlcnZpY2UuSUNPTl9ISURFIDogRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fTk9UX0FMTE9XRUQsXG4gICAgICAgICAgICBkcmFnSXRlbU5hbWU6IHRoaXMuZGlzcGxheU5hbWUsXG4gICAgICAgICAgICAvLyB3ZSBhZGQgaW4gdGhlIG9yaWdpbmFsIGdyb3VwIGxlYWYgY29sdW1ucywgc28gd2UgbW92ZSBib3RoIHZpc2libGUgYW5kIG5vbi12aXNpYmxlIGl0ZW1zXG4gICAgICAgICAgICBnZXREcmFnSXRlbTogdGhpcy5nZXREcmFnSXRlbUZvckdyb3VwLmJpbmQodGhpcyksXG4gICAgICAgICAgICBvbkRyYWdTdGFydGVkOiBmdW5jdGlvbiAoKSB7IHJldHVybiBhbGxMZWFmQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5zZXRNb3ZpbmcodHJ1ZSwgXCJ1aUNvbHVtbkRyYWdnZWRcIik7IH0pOyB9LFxuICAgICAgICAgICAgb25EcmFnU3RvcHBlZDogZnVuY3Rpb24gKCkgeyByZXR1cm4gYWxsTGVhZkNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuc2V0TW92aW5nKGZhbHNlLCBcInVpQ29sdW1uRHJhZ2dlZFwiKTsgfSk7IH0sXG4gICAgICAgICAgICBvbkdyaWRFbnRlcjogZnVuY3Rpb24gKGRyYWdJdGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgICAgICAgICBpZiAoaGlkZUNvbHVtbk9uRXhpdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdW5sb2NrZWRDb2x1bW5zID0gKChfYiA9IChfYSA9IGRyYWdJdGVtKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY29sdW1ucykgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiAhY29sLmdldENvbERlZigpLmxvY2tWaXNpYmxlOyB9KSkgfHwgW107XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbnNWaXNpYmxlKHVubG9ja2VkQ29sdW1ucywgdHJ1ZSwgXCJ1aUNvbHVtbk1vdmVkXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkdyaWRFeGl0OiBmdW5jdGlvbiAoZHJhZ0l0ZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgX2EsIF9iO1xuICAgICAgICAgICAgICAgIGlmIChoaWRlQ29sdW1uT25FeGl0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB1bmxvY2tlZENvbHVtbnMgPSAoKF9iID0gKF9hID0gZHJhZ0l0ZW0pID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jb2x1bW5zKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuICFjb2wuZ2V0Q29sRGVmKCkubG9ja1Zpc2libGU7IH0pKSB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uc1Zpc2libGUodW5sb2NrZWRDb2x1bW5zLCBmYWxzZSwgXCJ1aUNvbHVtbk1vdmVkXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLmFkZERyYWdTb3VyY2UoZHJhZ1NvdXJjZSwgdHJ1ZSk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZHJhZ0FuZERyb3BTZXJ2aWNlLnJlbW92ZURyYWdTb3VyY2UoZHJhZ1NvdXJjZSk7IH0pO1xuICAgIH07XG4gICAgLy8gd2hlbiBtb3ZpbmcgdGhlIGNvbHVtbnMsIHdlIHdhbnQgdG8gbW92ZSBhbGwgdGhlIGNvbHVtbnMgKGNvbnRhaW5lZCB3aXRoaW4gdGhlIERyYWdJdGVtKSBpbiB0aGlzIGdyb3VwIGluIG9uZSBnbyxcbiAgICAvLyBhbmQgaW4gdGhlIG9yZGVyIHRoZXkgYXJlIGN1cnJlbnRseSBpbiB0aGUgc2NyZWVuLlxuICAgIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLmdldERyYWdJdGVtRm9yR3JvdXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhbGxDb2x1bW5zT3JpZ2luYWxPcmRlciA9IHRoaXMuY29sdW1uR3JvdXAuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCgpLmdldExlYWZDb2x1bW5zKCk7XG4gICAgICAgIC8vIGNhcHR1cmUgdmlzaWJsZSBzdGF0ZSwgdXNlZCB3aGVuIHJlLWVudGVyaW5nIGdyaWQgdG8gZGljdGF0ZSB3aGljaCBjb2x1bW5zIHNob3VsZCBiZSB2aXNpYmxlXG4gICAgICAgIHZhciB2aXNpYmxlU3RhdGUgPSB7fTtcbiAgICAgICAgYWxsQ29sdW1uc09yaWdpbmFsT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiB2aXNpYmxlU3RhdGVbY29sdW1uLmdldElkKCldID0gY29sdW1uLmlzVmlzaWJsZSgpOyB9KTtcbiAgICAgICAgdmFyIGFsbENvbHVtbnNDdXJyZW50T3JkZXIgPSBbXTtcbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCkuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgICBpZiAoYWxsQ29sdW1uc09yaWdpbmFsT3JkZXIuaW5kZXhPZihjb2x1bW4pID49IDApIHtcbiAgICAgICAgICAgICAgICBhbGxDb2x1bW5zQ3VycmVudE9yZGVyLnB1c2goY29sdW1uKTtcbiAgICAgICAgICAgICAgICByZW1vdmVGcm9tQXJyYXkoYWxsQ29sdW1uc09yaWdpbmFsT3JkZXIsIGNvbHVtbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyB3ZSBhcmUgbGVmdCB3aXRoIG5vbi12aXNpYmxlIGNvbHVtbnMsIHN0aWNrIHRoZXNlIGluIGF0IHRoZSBlbmRcbiAgICAgICAgYWxsQ29sdW1uc09yaWdpbmFsT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiBhbGxDb2x1bW5zQ3VycmVudE9yZGVyLnB1c2goY29sdW1uKTsgfSk7XG4gICAgICAgIC8vIGNyZWF0ZSBhbmQgcmV0dXJuIGRyYWdJdGVtXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjb2x1bW5zOiBhbGxDb2x1bW5zQ3VycmVudE9yZGVyLFxuICAgICAgICAgICAgdmlzaWJsZVN0YXRlOiB2aXNpYmxlU3RhdGVcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLmlzU3VwcHJlc3NNb3ZpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGlmIGFueSBjaGlsZCBpcyBmaXhlZCwgdGhlbiBkb24ndCBhbGxvdyBtb3ZpbmdcbiAgICAgICAgdmFyIGNoaWxkU3VwcHJlc3Nlc01vdmluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmNvbHVtbkdyb3VwLmdldExlYWZDb2x1bW5zKCkuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgICAgICBpZiAoY29sdW1uLmdldENvbERlZigpLnN1cHByZXNzTW92YWJsZSB8fCBjb2x1bW4uZ2V0Q29sRGVmKCkubG9ja1Bvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgY2hpbGRTdXBwcmVzc2VzTW92aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciByZXN1bHQgPSBjaGlsZFN1cHByZXNzZXNNb3ZpbmcgfHwgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc01vdmFibGVDb2x1bW5zKCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFpKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgSGVhZGVyR3JvdXBDZWxsQ3RybC5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFpKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnQW5kRHJvcFNlcnZpY2UnKVxuICAgIF0sIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLCBcImRyYWdBbmREcm9wU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWkoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRBcGknKVxuICAgIF0sIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLCBcImdyaWRBcGlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFpKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5BcGknKVxuICAgIF0sIEhlYWRlckdyb3VwQ2VsbEN0cmwucHJvdG90eXBlLCBcImNvbHVtbkFwaVwiLCB2b2lkIDApO1xuICAgIHJldHVybiBIZWFkZXJHcm91cENlbGxDdHJsO1xufShBYnN0cmFjdEhlYWRlckNlbGxDdHJsKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMW8gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFoID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgaW5zdGFuY2VJZFNlcXVlbmNlID0gMDtcbnZhciBIZWFkZXJSb3dDdHJsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxbyhIZWFkZXJSb3dDdHJsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlclJvd0N0cmwocm93SW5kZXgsIHBpbm5lZCwgdHlwZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5pbnN0YW5jZUlkID0gaW5zdGFuY2VJZFNlcXVlbmNlKys7XG4gICAgICAgIF90aGlzLmhlYWRlckNlbGxDdHJscyA9IHt9O1xuICAgICAgICBfdGhpcy5yb3dJbmRleCA9IHJvd0luZGV4O1xuICAgICAgICBfdGhpcy5waW5uZWQgPSBwaW5uZWQ7XG4gICAgICAgIF90aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLmdldEluc3RhbmNlSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmluc3RhbmNlSWQ7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGNvbXApIHtcbiAgICAgICAgdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgdGhpcy5vblJvd0hlaWdodENoYW5nZWQoKTtcbiAgICAgICAgdGhpcy5vblZpcnR1YWxDb2x1bW5zQ2hhbmdlZCgpO1xuICAgICAgICB0aGlzLnNldFdpZHRoKCk7XG4gICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgaWYgKGlzQnJvd3NlclNhZmFyaSgpKSB7XG4gICAgICAgICAgICAvLyBmaXggZm9yIGEgU2FmYXJpIHJlbmRlcmluZyBidWcgdGhhdCBjYXVzZWQgdGhlIGhlYWRlciB0byBmbGlja2VyIGFib3ZlIGNoYXJ0IHBhbmVsc1xuICAgICAgICAgICAgLy8gYXMgeW91IG1vdmUgdGhlIG1vdXNlIG92ZXIgdGhlIGhlYWRlclxuICAgICAgICAgICAgdGhpcy5jb21wLnNldFRyYW5zZm9ybSgndHJhbnNsYXRlWigwKScpO1xuICAgICAgICB9XG4gICAgICAgIGNvbXAuc2V0QXJpYVJvd0luZGV4KHRoaXMucm93SW5kZXggKyAxKTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9SRVNJWkVELCB0aGlzLm9uQ29sdW1uUmVzaXplZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgLy8gd2hlbiBwcmludCBsYXlvdXQgY2hhbmdlcywgaXQgY2hhbmdlcyB3aGF0IGNvbHVtbnMgYXJlIGluIHdoYXQgc2VjdGlvblxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfRE9NX0xBWU9VVCwgdGhpcy5vbkRpc3BsYXllZENvbHVtbnNDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9WSVJUVUFMX0NPTFVNTlNfQ0hBTkdFRCwgdGhpcy5vblZpcnR1YWxDb2x1bW5zQ2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fSEVBREVSX0hFSUdIVF9DSEFOR0VELCB0aGlzLm9uUm93SGVpZ2h0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0hFQURFUl9IRUlHSFQsIHRoaXMub25Sb3dIZWlnaHRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfUElWT1RfSEVBREVSX0hFSUdIVCwgdGhpcy5vblJvd0hlaWdodENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9IRUFERVJfSEVJR0hULCB0aGlzLm9uUm93SGVpZ2h0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1BJVk9UX0dST1VQX0hFQURFUl9IRUlHSFQsIHRoaXMub25Sb3dIZWlnaHRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfRkxPQVRJTkdfRklMVEVSU19IRUlHSFQsIHRoaXMub25Sb3dIZWlnaHRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q3RybC5wcm90b3R5cGUuZ2V0SGVhZGVyQ2VsbEN0cmwgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZXModGhpcy5oZWFkZXJDZWxsQ3RybHMpLmZpbmQoZnVuY3Rpb24gKGNlbGxDdHJsKSB7IHJldHVybiBjZWxsQ3RybC5nZXRDb2x1bW5Hcm91cENoaWxkKCkgPT09IGNvbHVtbjsgfSk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5vbkRpc3BsYXllZENvbHVtbnNDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9uVmlydHVhbENvbHVtbnNDaGFuZ2VkKCk7XG4gICAgICAgIHRoaXMuc2V0V2lkdGgoKTtcbiAgICAgICAgdGhpcy5vblJvd0hlaWdodENoYW5nZWQoKTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnR5cGU7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5vbkNvbHVtblJlc2l6ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0V2lkdGgoKTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLnNldFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgd2lkdGggPSB0aGlzLmdldFdpZHRoRm9yUm93KCk7XG4gICAgICAgIHRoaXMuY29tcC5zZXRXaWR0aCh3aWR0aCArIFwicHhcIik7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5nZXRXaWR0aEZvclJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByaW50TGF5b3V0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tTGF5b3V0KCkgPT09IENvbnN0YW50cy5ET01fTEFZT1VUX1BSSU5UO1xuICAgICAgICBpZiAocHJpbnRMYXlvdXQpIHtcbiAgICAgICAgICAgIHZhciBwaW5uZWQgPSB0aGlzLnBpbm5lZCAhPSBudWxsO1xuICAgICAgICAgICAgaWYgKHBpbm5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0Q29udGFpbmVyV2lkdGgoQ29uc3RhbnRzLlBJTk5FRF9SSUdIVClcbiAgICAgICAgICAgICAgICArIHRoaXMuY29sdW1uTW9kZWwuZ2V0Q29udGFpbmVyV2lkdGgoQ29uc3RhbnRzLlBJTk5FRF9MRUZUKVxuICAgICAgICAgICAgICAgICsgdGhpcy5jb2x1bW5Nb2RlbC5nZXRDb250YWluZXJXaWR0aChudWxsKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBub3QgcHJpbnRpbmcsIGp1c3QgcmV0dXJuIHRoZSB3aWR0aCBhcyBub3JtYWxcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0Q29udGFpbmVyV2lkdGgodGhpcy5waW5uZWQpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q3RybC5wcm90b3R5cGUub25Sb3dIZWlnaHRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGVhZGVyUm93Q291bnQgPSB0aGlzLmNvbHVtbk1vZGVsLmdldEhlYWRlclJvd0NvdW50KCk7XG4gICAgICAgIHZhciBzaXplcyA9IFtdO1xuICAgICAgICB2YXIgbnVtYmVyT2ZGbG9hdGluZyA9IDA7XG4gICAgICAgIGlmICh0aGlzLmNvbHVtbk1vZGVsLmhhc0Zsb2F0aW5nRmlsdGVycygpKSB7XG4gICAgICAgICAgICBoZWFkZXJSb3dDb3VudCsrO1xuICAgICAgICAgICAgbnVtYmVyT2ZGbG9hdGluZyA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGdyb3VwSGVpZ2h0ID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRDb2x1bW5Hcm91cEhlYWRlclJvd0hlaWdodCgpO1xuICAgICAgICB2YXIgaGVhZGVySGVpZ2h0ID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRDb2x1bW5IZWFkZXJSb3dIZWlnaHQoKTtcbiAgICAgICAgdmFyIG51bWJlck9mTm9uR3JvdXBzID0gMSArIG51bWJlck9mRmxvYXRpbmc7XG4gICAgICAgIHZhciBudW1iZXJPZkdyb3VwcyA9IGhlYWRlclJvd0NvdW50IC0gbnVtYmVyT2ZOb25Hcm91cHM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtYmVyT2ZHcm91cHM7IGkrKykge1xuICAgICAgICAgICAgc2l6ZXMucHVzaChncm91cEhlaWdodCk7XG4gICAgICAgIH1cbiAgICAgICAgc2l6ZXMucHVzaChoZWFkZXJIZWlnaHQpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bWJlck9mRmxvYXRpbmc7IGkrKykge1xuICAgICAgICAgICAgc2l6ZXMucHVzaCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRGbG9hdGluZ0ZpbHRlcnNIZWlnaHQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRvcE9mZnNldCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5yb3dJbmRleDsgaSsrKSB7XG4gICAgICAgICAgICB0b3BPZmZzZXQgKz0gc2l6ZXNbaV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRoaXNSb3dIZWlnaHQgPSBzaXplc1t0aGlzLnJvd0luZGV4XSArICdweCc7XG4gICAgICAgIHRoaXMuY29tcC5zZXRUb3AodG9wT2Zmc2V0ICsgJ3B4Jyk7XG4gICAgICAgIHRoaXMuY29tcC5zZXRIZWlnaHQodGhpc1Jvd0hlaWdodCk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5nZXRQaW5uZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbm5lZDtcbiAgICB9O1xuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLmdldFJvd0luZGV4ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dJbmRleDtcbiAgICB9O1xuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLm9uVmlydHVhbENvbHVtbnNDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgb2xkQ3RybHMgPSB0aGlzLmhlYWRlckNlbGxDdHJscztcbiAgICAgICAgdGhpcy5oZWFkZXJDZWxsQ3RybHMgPSB7fTtcbiAgICAgICAgdmFyIGNvbHVtbnMgPSB0aGlzLmdldENvbHVtbnNJblZpZXdwb3J0KCk7XG4gICAgICAgIGNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgIC8vIHNraXAgZ3JvdXBzIHRoYXQgaGF2ZSBubyBkaXNwbGF5ZWQgY2hpbGRyZW4uIHRoaXMgY2FuIGhhcHBlbiB3aGVuIHRoZSBncm91cCBpcyBicm9rZW4sXG4gICAgICAgICAgICAvLyBhbmQgdGhpcyBzZWN0aW9uIGhhcHBlbnMgdG8gaGF2ZSBub3RoaW5nIHRvIGRpc3BsYXkgZm9yIHRoZSBvcGVuIC8gY2xvc2VkIHN0YXRlLlxuICAgICAgICAgICAgLy8gKGEgYnJva2VuIGdyb3VwIGlzIG9uZSB0aGF0IGlzIHNwbGl0LCBpZSBjb2x1bW5zIGluIHRoZSBncm91cCBoYXZlIGEgbm9uLWdyb3VwIGNvbHVtblxuICAgICAgICAgICAgLy8gaW4gYmV0d2VlbiB0aGVtKVxuICAgICAgICAgICAgaWYgKGNoaWxkLmlzRW1wdHlHcm91cCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGlkT2ZDaGlsZCA9IGNoaWxkLmdldFVuaXF1ZUlkKCk7XG4gICAgICAgICAgICAvLyBpZiB3ZSBhbHJlYWR5IGhhdmUgdGhpcyBjZWxsIHJlbmRlcmVkLCBkbyBub3RoaW5nXG4gICAgICAgICAgICB2YXIgaGVhZGVyQ3RybCA9IG9sZEN0cmxzW2lkT2ZDaGlsZF07XG4gICAgICAgICAgICBkZWxldGUgb2xkQ3RybHNbaWRPZkNoaWxkXTtcbiAgICAgICAgICAgIC8vIGl0J3MgcG9zc2libGUgdGhlcmUgaXMgYSBuZXcgQ29sdW1uIHdpdGggdGhlIHNhbWUgSUQsIGJ1dCBpdCdzIGZvciBhIGRpZmZlcmVudCBDb2x1bW4uXG4gICAgICAgICAgICAvLyB0aGlzIGlzIGNvbW1vbiB3aXRoIHBpdm90aW5nLCB3aGVyZSB0aGUgcGl2b3QgY29scyBjaGFuZ2UsIGJ1dCB0aGUgaWQncyBhcmUgc3RpbGwgcGl2b3RfMCxcbiAgICAgICAgICAgIC8vIHBpdm90XzEgZXRjLiBzbyBpZiBuZXcgY29sIGJ1dCBzYW1lIElELCBuZWVkIHRvIHJlbW92ZSB0aGUgb2xkIGNvbCBoZXJlIGZpcnN0IGFzIHdlIGFyZVxuICAgICAgICAgICAgLy8gYWJvdXQgdG8gcmVwbGFjZSBpdCBpbiB0aGUgdGhpcy5oZWFkZXJDb21wcyBtYXAuXG4gICAgICAgICAgICB2YXIgZm9yT2xkQ29sdW1uID0gaGVhZGVyQ3RybCAmJiBoZWFkZXJDdHJsLmdldENvbHVtbkdyb3VwQ2hpbGQoKSAhPSBjaGlsZDtcbiAgICAgICAgICAgIGlmIChmb3JPbGRDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kZXN0cm95QmVhbihoZWFkZXJDdHJsKTtcbiAgICAgICAgICAgICAgICBoZWFkZXJDdHJsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGhlYWRlckN0cmwgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX3RoaXMudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEhlYWRlclJvd1R5cGUuRkxPQVRJTkdfRklMVEVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyQ3RybCA9IF90aGlzLmNyZWF0ZUJlYW4obmV3IEhlYWRlckZpbHRlckNlbGxDdHJsKGNoaWxkLCBfdGhpcykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgSGVhZGVyUm93VHlwZS5DT0xVTU5fR1JPVVA6XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJDdHJsID0gX3RoaXMuY3JlYXRlQmVhbihuZXcgSGVhZGVyR3JvdXBDZWxsQ3RybChjaGlsZCwgX3RoaXMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyQ3RybCA9IF90aGlzLmNyZWF0ZUJlYW4obmV3IEhlYWRlckNlbGxDdHJsKGNoaWxkLCBfdGhpcykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuaGVhZGVyQ2VsbEN0cmxzW2lkT2ZDaGlsZF0gPSBoZWFkZXJDdHJsO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gd2Ugd2FudCB0byBrZWVwIGNvbHVtbnMgdGhhdCBhcmUgZm9jdXNlZCwgb3RoZXJ3aXNlIGtleWJvYXJkIG5hdmlnYXRpb24gYnJlYWtzXG4gICAgICAgIHZhciBpc0ZvY3VzZWRBbmREaXNwbGF5ZWQgPSBmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICAgICAgdmFyIGlzRm9jdXNlZCA9IF90aGlzLmZvY3VzU2VydmljZS5pc0hlYWRlcldyYXBwZXJGb2N1c2VkKGN0cmwpO1xuICAgICAgICAgICAgaWYgKCFpc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaXNEaXNwbGF5ZWQgPSBfdGhpcy5jb2x1bW5Nb2RlbC5pc0Rpc3BsYXllZChjdHJsLmdldENvbHVtbkdyb3VwQ2hpbGQoKSk7XG4gICAgICAgICAgICByZXR1cm4gaXNEaXNwbGF5ZWQ7XG4gICAgICAgIH07XG4gICAgICAgIGl0ZXJhdGVPYmplY3Qob2xkQ3RybHMsIGZ1bmN0aW9uIChpZCwgb2xkQ3RybCkge1xuICAgICAgICAgICAgdmFyIGtlZXBDdHJsID0gaXNGb2N1c2VkQW5kRGlzcGxheWVkKG9sZEN0cmwpO1xuICAgICAgICAgICAgaWYgKGtlZXBDdHJsKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuaGVhZGVyQ2VsbEN0cmxzW2lkXSA9IG9sZEN0cmw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kZXN0cm95QmVhbihvbGRDdHJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBjdHJsc1RvRGlzcGxheSA9IGdldEFsbFZhbHVlc0luT2JqZWN0KHRoaXMuaGVhZGVyQ2VsbEN0cmxzKTtcbiAgICAgICAgdGhpcy5jb21wLnNldEhlYWRlckN0cmxzKGN0cmxzVG9EaXNwbGF5KTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLmRlc3Ryb3lDdHJscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaXRlcmF0ZU9iamVjdCh0aGlzLmhlYWRlckNlbGxDdHJscywgZnVuY3Rpb24gKGtleSwgY3RybCkge1xuICAgICAgICAgICAgX3RoaXMuZGVzdHJveUJlYW4oY3RybCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmhlYWRlckNlbGxDdHJscyA9IHt9O1xuICAgIH07XG4gICAgSGVhZGVyUm93Q3RybC5wcm90b3R5cGUuZ2V0Q29sdW1uc0luVmlld3BvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwcmludExheW91dCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvbUxheW91dCgpID09PSBDb25zdGFudHMuRE9NX0xBWU9VVF9QUklOVDtcbiAgICAgICAgcmV0dXJuIHByaW50TGF5b3V0ID8gdGhpcy5nZXRDb2x1bW5zSW5WaWV3cG9ydFByaW50TGF5b3V0KCkgOiB0aGlzLmdldENvbHVtbnNJblZpZXdwb3J0Tm9ybWFsTGF5b3V0KCk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5nZXRDb2x1bW5zSW5WaWV3cG9ydFByaW50TGF5b3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBmb3IgcHJpbnQgbGF5b3V0LCB3ZSBhZGQgYWxsIGNvbHVtbnMgaW50byB0aGUgY2VudGVyXG4gICAgICAgIGlmICh0aGlzLnBpbm5lZCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHZpZXdwb3J0Q29sdW1ucyA9IFtdO1xuICAgICAgICB2YXIgYWN0dWFsRGVwdGggPSB0aGlzLmdldEFjdHVhbERlcHRoKCk7XG4gICAgICAgIFtDb25zdGFudHMuUElOTkVEX0xFRlQsIG51bGwsIENvbnN0YW50cy5QSU5ORURfUklHSFRdLmZvckVhY2goZnVuY3Rpb24gKHBpbm5lZCkge1xuICAgICAgICAgICAgdmFyIGl0ZW1zID0gX3RoaXMuY29sdW1uTW9kZWwuZ2V0VmlydHVhbEhlYWRlckdyb3VwUm93KHBpbm5lZCwgYWN0dWFsRGVwdGgpO1xuICAgICAgICAgICAgdmlld3BvcnRDb2x1bW5zID0gdmlld3BvcnRDb2x1bW5zLmNvbmNhdChpdGVtcyk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdmlld3BvcnRDb2x1bW5zO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q3RybC5wcm90b3R5cGUuZ2V0QWN0dWFsRGVwdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnR5cGUgPT0gSGVhZGVyUm93VHlwZS5GTE9BVElOR19GSUxURVIgPyB0aGlzLnJvd0luZGV4IC0gMSA6IHRoaXMucm93SW5kZXg7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZS5nZXRDb2x1bW5zSW5WaWV3cG9ydE5vcm1hbExheW91dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd2hlbiBpbiBub3JtYWwgbGF5b3V0LCB3ZSBhZGQgdGhlIGNvbHVtbnMgZm9yIHRoYXQgY29udGFpbmVyIG9ubHlcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0VmlydHVhbEhlYWRlckdyb3VwUm93KHRoaXMucGlubmVkLCB0aGlzLmdldEFjdHVhbERlcHRoKCkpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q3RybC5wcm90b3R5cGUuZm9jdXNIZWFkZXIgPSBmdW5jdGlvbiAoY29sdW1uLCBldmVudCkge1xuICAgICAgICB2YXIgYWxsQ3RybHMgPSBnZXRBbGxWYWx1ZXNJbk9iamVjdCh0aGlzLmhlYWRlckNlbGxDdHJscyk7XG4gICAgICAgIHZhciBjdHJsID0gYWxsQ3RybHMuZmluZChmdW5jdGlvbiAoY3RybCkgeyByZXR1cm4gY3RybC5nZXRDb2x1bW5Hcm91cENoaWxkKCkgPT0gY29sdW1uOyB9KTtcbiAgICAgICAgaWYgKCFjdHJsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY3RybC5mb2N1cyhldmVudCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxaChbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxaChbXG4gICAgICAgIEF1dG93aXJlZCgnZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBIZWFkZXJSb3dDdHJsLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFoKFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIEhlYWRlclJvd0N0cmwucHJvdG90eXBlLCBcImRlc3Ryb3lDdHJsc1wiLCBudWxsKTtcbiAgICByZXR1cm4gSGVhZGVyUm93Q3RybDtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxbiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMWcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3JlYWQkYyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCRhID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJGMoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBIZWFkZXJSb3dDb250YWluZXJDdHJsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxbihIZWFkZXJSb3dDb250YWluZXJDdHJsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlclJvd0NvbnRhaW5lckN0cmwocGlubmVkKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmdyb3Vwc1Jvd0N0cmxzID0gW107XG4gICAgICAgIF90aGlzLnBpbm5lZCA9IHBpbm5lZDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGNvbXAsIGVHdWkpIHtcbiAgICAgICAgdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgdGhpcy5lVmlld3BvcnQgPSBlR3VpO1xuICAgICAgICB0aGlzLnNldHVwQ2VudGVyV2lkdGgoKTtcbiAgICAgICAgdGhpcy5zZXR1cFBpbm5lZFdpZHRoKCk7XG4gICAgICAgIHRoaXMuc2V0dXBEcmFnQW5kRHJvcCh0aGlzLmVWaWV3cG9ydCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfR1JJRF9DT0xVTU5TX0NIQU5HRUQsIHRoaXMub25HcmlkQ29sdW1uc0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZVZpZXdwb3J0LCAnc2Nyb2xsJywgdGhpcy5yZXNldFNjcm9sbExlZnQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLnJlZ2lzdGVySGVhZGVyQ29udGFpbmVyKHRoaXMsIHRoaXMucGlubmVkKTtcbiAgICAgICAgaWYgKHRoaXMuY29sdW1uTW9kZWwuaXNSZWFkeSgpKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2goKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuc2V0dXBEcmFnQW5kRHJvcCA9IGZ1bmN0aW9uIChkcm9wQ29udGFpbmVyKSB7XG4gICAgICAgIHZhciBib2R5RHJvcFRhcmdldCA9IG5ldyBCb2R5RHJvcFRhcmdldCh0aGlzLnBpbm5lZCwgZHJvcENvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4oYm9keURyb3BUYXJnZXQpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUucmVmcmVzaCA9IGZ1bmN0aW9uIChrZWVwQ29sdW1ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoa2VlcENvbHVtbnMgPT09IHZvaWQgMCkgeyBrZWVwQ29sdW1ucyA9IGZhbHNlOyB9XG4gICAgICAgIHZhciBzZXF1ZW5jZSA9IG5ldyBOdW1iZXJTZXF1ZW5jZSgpO1xuICAgICAgICB2YXIgZm9jdXNlZEhlYWRlclBvc2l0aW9uID0gdGhpcy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNIZWFkZXJUb1VzZUFmdGVyUmVmcmVzaCgpO1xuICAgICAgICB2YXIgcmVmcmVzaENvbHVtbkdyb3VwcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBncm91cFJvd0NvdW50ID0gX3RoaXMuY29sdW1uTW9kZWwuZ2V0SGVhZGVyUm93Q291bnQoKSAtIDE7XG4gICAgICAgICAgICBfdGhpcy5ncm91cHNSb3dDdHJscyA9IF90aGlzLmRlc3Ryb3lCZWFucyhfdGhpcy5ncm91cHNSb3dDdHJscyk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyb3VwUm93Q291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBjdHJsID0gX3RoaXMuY3JlYXRlQmVhbihuZXcgSGVhZGVyUm93Q3RybChzZXF1ZW5jZS5uZXh0KCksIF90aGlzLnBpbm5lZCwgSGVhZGVyUm93VHlwZS5DT0xVTU5fR1JPVVApKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5ncm91cHNSb3dDdHJscy5wdXNoKGN0cmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgcmVmcmVzaENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcm93SW5kZXggPSBzZXF1ZW5jZS5uZXh0KCk7XG4gICAgICAgICAgICB2YXIgbmVlZE5ld0luc3RhbmNlID0gX3RoaXMuY29sdW1uc1Jvd0N0cmwgPT0gbnVsbCB8fCAha2VlcENvbHVtbnMgfHwgX3RoaXMuY29sdW1uc1Jvd0N0cmwuZ2V0Um93SW5kZXgoKSAhPT0gcm93SW5kZXg7XG4gICAgICAgICAgICBpZiAobmVlZE5ld0luc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZGVzdHJveUJlYW4oX3RoaXMuY29sdW1uc1Jvd0N0cmwpO1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbHVtbnNSb3dDdHJsID0gX3RoaXMuY3JlYXRlQmVhbihuZXcgSGVhZGVyUm93Q3RybChyb3dJbmRleCwgX3RoaXMucGlubmVkLCBIZWFkZXJSb3dUeXBlLkNPTFVNTikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgcmVmcmVzaEZpbHRlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgaW5jbHVkZUZsb2F0aW5nRmlsdGVyID0gX3RoaXMuY29sdW1uTW9kZWwuaGFzRmxvYXRpbmdGaWx0ZXJzKCk7XG4gICAgICAgICAgICB2YXIgZGVzdHJveVByZXZpb3VzQ29tcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5maWx0ZXJzUm93Q3RybCA9IF90aGlzLmRlc3Ryb3lCZWFuKF90aGlzLmZpbHRlcnNSb3dDdHJsKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoIWluY2x1ZGVGbG9hdGluZ0ZpbHRlcikge1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lQcmV2aW91c0NvbXAoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcm93SW5kZXggPSBzZXF1ZW5jZS5uZXh0KCk7XG4gICAgICAgICAgICBpZiAoX3RoaXMuZmlsdGVyc1Jvd0N0cmwpIHtcbiAgICAgICAgICAgICAgICB2YXIgcm93SW5kZXhNaXNtYXRjaCA9IF90aGlzLmZpbHRlcnNSb3dDdHJsLmdldFJvd0luZGV4KCkgIT09IHJvd0luZGV4O1xuICAgICAgICAgICAgICAgIGlmICgha2VlcENvbHVtbnMgfHwgcm93SW5kZXhNaXNtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95UHJldmlvdXNDb21wKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFfdGhpcy5maWx0ZXJzUm93Q3RybCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmZpbHRlcnNSb3dDdHJsID0gX3RoaXMuY3JlYXRlQmVhbihuZXcgSGVhZGVyUm93Q3RybChyb3dJbmRleCwgX3RoaXMucGlubmVkLCBIZWFkZXJSb3dUeXBlLkZMT0FUSU5HX0ZJTFRFUikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZWZyZXNoQ29sdW1uR3JvdXBzKCk7XG4gICAgICAgIHJlZnJlc2hDb2x1bW5zKCk7XG4gICAgICAgIHJlZnJlc2hGaWx0ZXJzKCk7XG4gICAgICAgIHZhciBhbGxDdHJscyA9IHRoaXMuZ2V0QWxsQ3RybHMoKTtcbiAgICAgICAgdGhpcy5jb21wLnNldEN0cmxzKGFsbEN0cmxzKTtcbiAgICAgICAgdGhpcy5yZXN0b3JlRm9jdXNPbkhlYWRlcihmb2N1c2VkSGVhZGVyUG9zaXRpb24pO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUucmVzdG9yZUZvY3VzT25IZWFkZXIgPSBmdW5jdGlvbiAocG9zaXRpb24pIHtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09IG51bGwgfHwgcG9zaXRpb24uY29sdW1uLmdldFBpbm5lZCgpICE9IHRoaXMucGlubmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5mb2N1c1NlcnZpY2UuZm9jdXNIZWFkZXJQb3NpdGlvbih7IGhlYWRlclBvc2l0aW9uOiBwb3NpdGlvbiB9KTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLmdldEFsbEN0cmxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzID0gX19zcHJlYWQkYSh0aGlzLmdyb3Vwc1Jvd0N0cmxzLCBbdGhpcy5jb2x1bW5zUm93Q3RybF0pO1xuICAgICAgICBpZiAodGhpcy5maWx0ZXJzUm93Q3RybCkge1xuICAgICAgICAgICAgcmVzLnB1c2godGhpcy5maWx0ZXJzUm93Q3RybCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIC8vIGdyaWQgY29scyBoYXZlIGNoYW5nZWQgLSB0aGlzIGFsc28gbWVhbnMgdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSBoZWFkZXIgY2FuIGhhdmVcbiAgICAvLyBjaGFuZ2VkLiBzbyB3ZSByZW1vdmUgYWxsIHRoZSBvbGQgcm93cyBhbmQgaW5zZXJ0IG5ldyBvbmVzIGZvciBhIGNvbXBsZXRlIHJlZnJlc2hcbiAgICBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5vbkdyaWRDb2x1bW5zQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoKHRydWUpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuc2V0dXBDZW50ZXJXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMucGlubmVkICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBDZW50ZXJXaWR0aEZlYXR1cmUoZnVuY3Rpb24gKHdpZHRoKSB7IHJldHVybiBfdGhpcy5jb21wLnNldENlbnRlcldpZHRoKHdpZHRoICsgXCJweFwiKTsgfSkpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuc2V0SG9yaXpvbnRhbFNjcm9sbCA9IGZ1bmN0aW9uIChvZmZzZXQpIHtcbiAgICAgICAgdGhpcy5jb21wLnNldENvbnRhaW5lclRyYW5zZm9ybShcInRyYW5zbGF0ZVgoXCIgKyBvZmZzZXQgKyBcInB4KVwiKTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLnJlc2V0U2Nyb2xsTGVmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5lVmlld3BvcnQuc2Nyb2xsTGVmdCA9IDA7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5zZXR1cFBpbm5lZFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5waW5uZWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwaW5uaW5nTGVmdCA9IHRoaXMucGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX0xFRlQ7XG4gICAgICAgIHZhciBwaW5uaW5nUmlnaHQgPSB0aGlzLnBpbm5lZCA9PT0gQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDtcbiAgICAgICAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHdpZHRoID0gcGlubmluZ0xlZnQgPyBfdGhpcy5waW5uZWRXaWR0aFNlcnZpY2UuZ2V0UGlubmVkTGVmdFdpZHRoKCkgOiBfdGhpcy5waW5uZWRXaWR0aFNlcnZpY2UuZ2V0UGlubmVkUmlnaHRXaWR0aCgpO1xuICAgICAgICAgICAgaWYgKHdpZHRoID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IC8vIGNhbiBoYXBwZW4gYXQgaW5pdGlhbGlzYXRpb24sIHdpZHRoIG5vdCB5ZXQgc2V0XG4gICAgICAgICAgICB2YXIgaGlkZGVuID0gd2lkdGggPT0gMDtcbiAgICAgICAgICAgIHZhciBpc1J0bCA9IF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICAgICAgdmFyIHNjcm9sbGJhcldpZHRoID0gX3RoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFNjcm9sbGJhcldpZHRoKCk7XG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBpcyBhIHNjcm9sbCBzaG93aW5nIChhbmQgdGFraW5nIHVwIHNwYWNlLCBzbyBXaW5kb3dzLCBhbmQgbm90IGlPUylcbiAgICAgICAgICAgIC8vIGluIHRoZSBib2R5LCB0aGVuIHdlIGFkZCBleHRyYSBzcGFjZSB0byBrZWVwIGhlYWRlciBhbGlnbmVkIHdpdGggdGhlIGJvZHksXG4gICAgICAgICAgICAvLyBhcyBib2R5IHdpZHRoIGZpdHMgdGhlIGNvbHMgYW5kIHRoZSBzY3JvbGxiYXJcbiAgICAgICAgICAgIHZhciBhZGRQYWRkaW5nRm9yU2Nyb2xsYmFyID0gX3RoaXMuc2Nyb2xsVmlzaWJsZVNlcnZpY2UuaXNWZXJ0aWNhbFNjcm9sbFNob3dpbmcoKSAmJiAoKGlzUnRsICYmIHBpbm5pbmdMZWZ0KSB8fCAoIWlzUnRsICYmIHBpbm5pbmdSaWdodCkpO1xuICAgICAgICAgICAgdmFyIHdpZHRoV2l0aFBhZGRpbmcgPSBhZGRQYWRkaW5nRm9yU2Nyb2xsYmFyID8gd2lkdGggKyBzY3JvbGxiYXJXaWR0aCA6IHdpZHRoO1xuICAgICAgICAgICAgX3RoaXMuY29tcC5zZXRQaW5uZWRDb250YWluZXJXaWR0aCh3aWR0aFdpdGhQYWRkaW5nICsgJ3B4Jyk7XG4gICAgICAgICAgICBfdGhpcy5jb21wLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWhpZGRlbicsIGhpZGRlbik7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTEVGVF9QSU5ORURfV0lEVEhfQ0hBTkdFRCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1JJR0hUX1BJTk5FRF9XSURUSF9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfU0NST0xMX1ZJU0lCSUxJVFlfQ0hBTkdFRCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1NDUk9MTEJBUl9XSURUSF9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5nZXRIZWFkZXJDdHJsRm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICBpZiAoY29sdW1uIGluc3RhbmNlb2YgQ29sdW1uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29sdW1uc1Jvd0N0cmwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5zUm93Q3RybC5nZXRIZWFkZXJDZWxsQ3RybChjb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmdyb3Vwc1Jvd0N0cmxzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5ncm91cHNSb3dDdHJscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGN0cmwgPSB0aGlzLmdyb3Vwc1Jvd0N0cmxzW2ldLmdldEhlYWRlckNlbGxDdHJsKGNvbHVtbik7XG4gICAgICAgICAgICBpZiAoY3RybCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjdHJsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5nZXRIdG1sRWxlbWVudEZvckNvbHVtbkhlYWRlciA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgLyogdHNsaW50OmVuYWJsZSAqL1xuICAgICAgICB2YXIgY2VsbEN0cmwgPSB0aGlzLmdldEhlYWRlckN0cmxGb3JDb2x1bW4oY29sdW1uKTtcbiAgICAgICAgaWYgKCFjZWxsQ3RybCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNlbGxDdHJsLmdldEd1aSgpO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuZ2V0Um93VHlwZSA9IGZ1bmN0aW9uIChyb3dJbmRleCkge1xuICAgICAgICB2YXIgYWxsQ3RybHMgPSB0aGlzLmdldEFsbEN0cmxzKCk7XG4gICAgICAgIHZhciBjdHJsID0gYWxsQ3RybHNbcm93SW5kZXhdO1xuICAgICAgICByZXR1cm4gY3RybCA/IGN0cmwuZ2V0VHlwZSgpIDogdW5kZWZpbmVkO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUuZm9jdXNIZWFkZXIgPSBmdW5jdGlvbiAocm93SW5kZXgsIGNvbHVtbiwgZXZlbnQpIHtcbiAgICAgICAgdmFyIGFsbEN0cmxzID0gdGhpcy5nZXRBbGxDdHJscygpO1xuICAgICAgICB2YXIgY3RybCA9IGFsbEN0cmxzW3Jvd0luZGV4XTtcbiAgICAgICAgaWYgKCFjdHJsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGN0cmwuZm9jdXNIZWFkZXIoY29sdW1uLCBldmVudCk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZS5nZXRSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QWxsQ3RybHMoKS5sZW5ndGg7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFnKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEhlYWRlclJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWcoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Njcm9sbFZpc2libGVTZXJ2aWNlJylcbiAgICBdLCBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZSwgXCJzY3JvbGxWaXNpYmxlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWcoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Bpbm5lZFdpZHRoU2VydmljZScpXG4gICAgXSwgSGVhZGVyUm93Q29udGFpbmVyQ3RybC5wcm90b3R5cGUsIFwicGlubmVkV2lkdGhTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxZyhbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEhlYWRlclJvd0NvbnRhaW5lckN0cmwucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxZyhbXG4gICAgICAgIEF1dG93aXJlZCgnZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBIZWFkZXJSb3dDb250YWluZXJDdHJsLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gSGVhZGVyUm93Q29udGFpbmVyQ3RybDtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxbSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMWYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBIZWFkZXJSb3dDb250YWluZXJDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxbShIZWFkZXJSb3dDb250YWluZXJDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlclJvd0NvbnRhaW5lckNvbXAocGlubmVkKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmhlYWRlclJvd0NvbXBzID0ge307XG4gICAgICAgIF90aGlzLnJvd0NvbXBzTGlzdCA9IFtdO1xuICAgICAgICBfdGhpcy5waW5uZWQgPSBwaW5uZWQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ29tcC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5zZWxlY3RBbmRTZXRUZW1wbGF0ZSgpO1xuICAgICAgICB2YXIgY29tcFByb3h5ID0ge1xuICAgICAgICAgICAgYWRkT3JSZW1vdmVDc3NDbGFzczogZnVuY3Rpb24gKGNzc0NsYXNzTmFtZSwgb24pIHsgcmV0dXJuIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoY3NzQ2xhc3NOYW1lLCBvbik7IH0sXG4gICAgICAgICAgICBzZXRDdHJsczogZnVuY3Rpb24gKGN0cmxzKSB7IHJldHVybiBfdGhpcy5zZXRDdHJscyhjdHJscyk7IH0sXG4gICAgICAgICAgICAvLyBvbmx5IGdldHMgY2FsbGVkIGZvciBjZW50ZXIgc2VjdGlvblxuICAgICAgICAgICAgc2V0Q2VudGVyV2lkdGg6IGZ1bmN0aW9uICh3aWR0aCkgeyByZXR1cm4gX3RoaXMuZUNlbnRlckNvbnRhaW5lci5zdHlsZS53aWR0aCA9IHdpZHRoOyB9LFxuICAgICAgICAgICAgc2V0Q29udGFpbmVyVHJhbnNmb3JtOiBmdW5jdGlvbiAodHJhbnNmb3JtKSB7IHJldHVybiBfdGhpcy5lQ2VudGVyQ29udGFpbmVyLnN0eWxlLnRyYW5zZm9ybSA9IHRyYW5zZm9ybTsgfSxcbiAgICAgICAgICAgIC8vIG9ubHkgZ2V0cyBjYWxsZWQgZm9yIHBpbm5lZCBzZWN0aW9uc1xuICAgICAgICAgICAgc2V0UGlubmVkQ29udGFpbmVyV2lkdGg6IGZ1bmN0aW9uICh3aWR0aCkge1xuICAgICAgICAgICAgICAgIHZhciBlR3VpID0gX3RoaXMuZ2V0R3VpKCk7XG4gICAgICAgICAgICAgICAgZUd1aS5zdHlsZS53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgIGVHdWkuc3R5bGUubWF4V2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgICAgICBlR3VpLnN0eWxlLm1pbldpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjdHJsID0gdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgSGVhZGVyUm93Q29udGFpbmVyQ3RybCh0aGlzLnBpbm5lZCkpO1xuICAgICAgICBjdHJsLnNldENvbXAoY29tcFByb3h5LCB0aGlzLmdldEd1aSgpKTtcbiAgICB9O1xuICAgIEhlYWRlclJvd0NvbnRhaW5lckNvbXAucHJvdG90eXBlLnNlbGVjdEFuZFNldFRlbXBsYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGlubmVkTGVmdCA9IHRoaXMucGlubmVkID09IENvbnN0YW50cy5QSU5ORURfTEVGVDtcbiAgICAgICAgdmFyIHBpbm5lZFJpZ2h0ID0gdGhpcy5waW5uZWQgPT0gQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDtcbiAgICAgICAgdmFyIHRlbXBsYXRlID0gcGlubmVkTGVmdCA/IEhlYWRlclJvd0NvbnRhaW5lckNvbXAuUElOTkVEX0xFRlRfVEVNUExBVEUgOlxuICAgICAgICAgICAgcGlubmVkUmlnaHQgPyBIZWFkZXJSb3dDb250YWluZXJDb21wLlBJTk5FRF9SSUdIVF9URU1QTEFURSA6IEhlYWRlclJvd0NvbnRhaW5lckNvbXAuQ0VOVEVSX1RFTVBMQVRFO1xuICAgICAgICB0aGlzLnNldFRlbXBsYXRlKHRlbXBsYXRlKTtcbiAgICAgICAgLy8gZm9yIGxlZnQgYW5kIHJpZ2h0LCB3ZSBhZGQgcm93cyBkaXJlY3RseSB0byB0aGUgcm9vdCBlbGVtZW50LFxuICAgICAgICAvLyBidXQgZm9yIGNlbnRlciBjb250YWluZXIgd2UgYWRkIGVsZW1lbnRzIHRvIHRoZSBjaGlsZCBjb250YWluZXIuXG4gICAgICAgIHRoaXMuZVJvd0NvbnRhaW5lciA9IHRoaXMuZUNlbnRlckNvbnRhaW5lciA/IHRoaXMuZUNlbnRlckNvbnRhaW5lciA6IHRoaXMuZ2V0R3VpKCk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDb21wLnByb3RvdHlwZS5kZXN0cm95Um93Q29tcHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0Q3RybHMoW10pO1xuICAgIH07XG4gICAgSGVhZGVyUm93Q29udGFpbmVyQ29tcC5wcm90b3R5cGUuZGVzdHJveVJvd0NvbXAgPSBmdW5jdGlvbiAocm93Q29tcCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3lCZWFuKHJvd0NvbXApO1xuICAgICAgICB0aGlzLmVSb3dDb250YWluZXIucmVtb3ZlQ2hpbGQocm93Q29tcC5nZXRHdWkoKSk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDb21wLnByb3RvdHlwZS5zZXRDdHJscyA9IGZ1bmN0aW9uIChjdHJscykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgb2xkUm93Q29tcHMgPSB0aGlzLmhlYWRlclJvd0NvbXBzO1xuICAgICAgICB0aGlzLmhlYWRlclJvd0NvbXBzID0ge307XG4gICAgICAgIHRoaXMucm93Q29tcHNMaXN0ID0gW107XG4gICAgICAgIHZhciBwcmV2R3VpO1xuICAgICAgICB2YXIgYXBwZW5kRW5zdXJpbmdEb21PcmRlciA9IGZ1bmN0aW9uIChyb3dDb21wKSB7XG4gICAgICAgICAgICB2YXIgZUd1aSA9IHJvd0NvbXAuZ2V0R3VpKCk7XG4gICAgICAgICAgICB2YXIgbm90QWxyZWFkeUluID0gZUd1aS5wYXJlbnRFbGVtZW50ICE9IF90aGlzLmVSb3dDb250YWluZXI7XG4gICAgICAgICAgICBpZiAobm90QWxyZWFkeUluKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZVJvd0NvbnRhaW5lci5hcHBlbmRDaGlsZChlR3VpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwcmV2R3VpKSB7XG4gICAgICAgICAgICAgICAgZW5zdXJlRG9tT3JkZXIoX3RoaXMuZVJvd0NvbnRhaW5lciwgZUd1aSwgcHJldkd1aSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcmV2R3VpID0gZUd1aTtcbiAgICAgICAgfTtcbiAgICAgICAgY3RybHMuZm9yRWFjaChmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICAgICAgdmFyIGN0cmxJZCA9IGN0cmwuZ2V0SW5zdGFuY2VJZCgpO1xuICAgICAgICAgICAgdmFyIGV4aXN0aW5nQ29tcCA9IG9sZFJvd0NvbXBzW2N0cmxJZF07XG4gICAgICAgICAgICBkZWxldGUgb2xkUm93Q29tcHNbY3RybElkXTtcbiAgICAgICAgICAgIHZhciByb3dDb21wID0gZXhpc3RpbmdDb21wID8gZXhpc3RpbmdDb21wIDogX3RoaXMuY3JlYXRlQmVhbihuZXcgSGVhZGVyUm93Q29tcChjdHJsKSk7XG4gICAgICAgICAgICBfdGhpcy5oZWFkZXJSb3dDb21wc1tjdHJsSWRdID0gcm93Q29tcDtcbiAgICAgICAgICAgIF90aGlzLnJvd0NvbXBzTGlzdC5wdXNoKHJvd0NvbXApO1xuICAgICAgICAgICAgYXBwZW5kRW5zdXJpbmdEb21PcmRlcihyb3dDb21wKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGdldEFsbFZhbHVlc0luT2JqZWN0KG9sZFJvd0NvbXBzKS5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7IHJldHVybiBfdGhpcy5kZXN0cm95Um93Q29tcChjKTsgfSk7XG4gICAgfTtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDb21wLlBJTk5FRF9MRUZUX1RFTVBMQVRFID0gXCI8ZGl2IGNsYXNzPVxcXCJhZy1waW5uZWQtbGVmdC1oZWFkZXJcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCIvPlwiO1xuICAgIEhlYWRlclJvd0NvbnRhaW5lckNvbXAuUElOTkVEX1JJR0hUX1RFTVBMQVRFID0gXCI8ZGl2IGNsYXNzPVxcXCJhZy1waW5uZWQtcmlnaHQtaGVhZGVyXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiLz5cIjtcbiAgICBIZWFkZXJSb3dDb250YWluZXJDb21wLkNFTlRFUl9URU1QTEFURSA9IFwiPGRpdiBjbGFzcz1cXFwiYWctaGVhZGVyLXZpZXdwb3J0XFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLWhlYWRlci1jb250YWluZXJcXFwiIHJlZj1cXFwiZUNlbnRlckNvbnRhaW5lclxcXCIgcm9sZT1cXFwicm93Z3JvdXBcXFwiPjwvZGl2PlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgX19kZWNvcmF0ZSQxZihbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ2VudGVyQ29udGFpbmVyJylcbiAgICBdLCBIZWFkZXJSb3dDb250YWluZXJDb21wLnByb3RvdHlwZSwgXCJlQ2VudGVyQ29udGFpbmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxZihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBIZWFkZXJSb3dDb250YWluZXJDb21wLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMWYoW1xuICAgICAgICBQcmVEZXN0cm95XG4gICAgXSwgSGVhZGVyUm93Q29udGFpbmVyQ29tcC5wcm90b3R5cGUsIFwiZGVzdHJveVJvd0NvbXBzXCIsIG51bGwpO1xuICAgIHJldHVybiBIZWFkZXJSb3dDb250YWluZXJDb21wO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxbCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMWUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBIZWFkZXJOYXZpZ2F0aW9uRGlyZWN0aW9uO1xuKGZ1bmN0aW9uIChIZWFkZXJOYXZpZ2F0aW9uRGlyZWN0aW9uKSB7XG4gICAgSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbltIZWFkZXJOYXZpZ2F0aW9uRGlyZWN0aW9uW1wiVVBcIl0gPSAwXSA9IFwiVVBcIjtcbiAgICBIZWFkZXJOYXZpZ2F0aW9uRGlyZWN0aW9uW0hlYWRlck5hdmlnYXRpb25EaXJlY3Rpb25bXCJET1dOXCJdID0gMV0gPSBcIkRPV05cIjtcbiAgICBIZWFkZXJOYXZpZ2F0aW9uRGlyZWN0aW9uW0hlYWRlck5hdmlnYXRpb25EaXJlY3Rpb25bXCJMRUZUXCJdID0gMl0gPSBcIkxFRlRcIjtcbiAgICBIZWFkZXJOYXZpZ2F0aW9uRGlyZWN0aW9uW0hlYWRlck5hdmlnYXRpb25EaXJlY3Rpb25bXCJSSUdIVFwiXSA9IDNdID0gXCJSSUdIVFwiO1xufSkoSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbiB8fCAoSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbiA9IHt9KSk7XG52YXIgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFsKEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmN0cmxzU2VydmljZS53aGVuUmVhZHkoZnVuY3Rpb24gKHApIHtcbiAgICAgICAgICAgIF90aGlzLmdyaWRCb2R5Q29uID0gcC5ncmlkQm9keUN0cmw7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmdldEhlYWRlclJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2VudGVySGVhZGVyQ29udGFpbmVyID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0SGVhZGVyUm93Q29udGFpbmVyQ3RybCgpO1xuICAgICAgICByZXR1cm4gY2VudGVySGVhZGVyQ29udGFpbmVyID8gY2VudGVySGVhZGVyQ29udGFpbmVyLmdldFJvd0NvdW50KCkgOiAwO1xuICAgIH07XG4gICAgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmdldEhlYWRlclJvd1R5cGUgPSBmdW5jdGlvbiAocm93SW5kZXgpIHtcbiAgICAgICAgdmFyIGNlbnRlckhlYWRlckNvbnRhaW5lciA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEhlYWRlclJvd0NvbnRhaW5lckN0cmwoKTtcbiAgICAgICAgaWYgKGNlbnRlckhlYWRlckNvbnRhaW5lcikge1xuICAgICAgICAgICAgcmV0dXJuIGNlbnRlckhlYWRlckNvbnRhaW5lci5nZXRSb3dUeXBlKHJvd0luZGV4KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLypcbiAgICAgKiBUaGlzIG1ldGhvZCBuYXZpZ2F0ZXMgZ3JpZCBoZWFkZXIgdmVydGljYWxseVxuICAgICAqIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgdG8gcHJldmVudERlZmF1bHQgb24gdGhlIGV2ZW50IHRoYXQgY2F1c2VkIHRoaXMgbmF2aWdhdGlvbi5cbiAgICAgKi9cbiAgICBIZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUubmF2aWdhdGVWZXJ0aWNhbGx5ID0gZnVuY3Rpb24gKGRpcmVjdGlvbiwgZnJvbUhlYWRlciwgZXZlbnQpIHtcbiAgICAgICAgaWYgKCFmcm9tSGVhZGVyKSB7XG4gICAgICAgICAgICBmcm9tSGVhZGVyID0gdGhpcy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNlZEhlYWRlcigpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZnJvbUhlYWRlcikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoZWFkZXJSb3dJbmRleCA9IGZyb21IZWFkZXIuaGVhZGVyUm93SW5kZXgsIGNvbHVtbiA9IGZyb21IZWFkZXIuY29sdW1uO1xuICAgICAgICB2YXIgcm93TGVuID0gdGhpcy5nZXRIZWFkZXJSb3dDb3VudCgpO1xuICAgICAgICB2YXIgaXNVcCA9IGRpcmVjdGlvbiA9PT0gSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbi5VUDtcbiAgICAgICAgdmFyIG5leHRSb3cgPSBpc1VwID8gaGVhZGVyUm93SW5kZXggLSAxIDogaGVhZGVyUm93SW5kZXggKyAxO1xuICAgICAgICB2YXIgbmV4dEZvY3VzQ29sdW1uID0gbnVsbDtcbiAgICAgICAgdmFyIHNraXBDb2x1bW4gPSBmYWxzZTtcbiAgICAgICAgaWYgKG5leHRSb3cgPCAwKSB7XG4gICAgICAgICAgICBuZXh0Um93ID0gMDtcbiAgICAgICAgICAgIG5leHRGb2N1c0NvbHVtbiA9IGNvbHVtbjtcbiAgICAgICAgICAgIHNraXBDb2x1bW4gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0Um93ID49IHJvd0xlbikge1xuICAgICAgICAgICAgbmV4dFJvdyA9IC0xOyAvLyAtMSBpbmRpY2F0ZXMgdGhlIGZvY3VzIHNob3VsZCBtb3ZlIHRvIGdyaWQgcm93cy5cbiAgICAgICAgfVxuICAgICAgICB2YXIgY3VycmVudFJvd1R5cGUgPSB0aGlzLmdldEhlYWRlclJvd1R5cGUoaGVhZGVyUm93SW5kZXgpO1xuICAgICAgICBpZiAoIXNraXBDb2x1bW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50Um93VHlwZSA9PT0gSGVhZGVyUm93VHlwZS5DT0xVTU5fR1JPVVApIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudENvbHVtbiA9IGNvbHVtbjtcbiAgICAgICAgICAgICAgICBuZXh0Rm9jdXNDb2x1bW4gPSBpc1VwID8gY29sdW1uLmdldFBhcmVudCgpIDogY3VycmVudENvbHVtbi5nZXREaXNwbGF5ZWRDaGlsZHJlbigpWzBdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoY3VycmVudFJvd1R5cGUgPT09IEhlYWRlclJvd1R5cGUuRkxPQVRJTkdfRklMVEVSKSB7XG4gICAgICAgICAgICAgICAgbmV4dEZvY3VzQ29sdW1uID0gY29sdW1uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRDb2x1bW4gPSBjb2x1bW47XG4gICAgICAgICAgICAgICAgbmV4dEZvY3VzQ29sdW1uID0gaXNVcCA/IGN1cnJlbnRDb2x1bW4uZ2V0UGFyZW50KCkgOiBjdXJyZW50Q29sdW1uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFuZXh0Rm9jdXNDb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzSGVhZGVyUG9zaXRpb24oe1xuICAgICAgICAgICAgaGVhZGVyUG9zaXRpb246IHsgaGVhZGVyUm93SW5kZXg6IG5leHRSb3csIGNvbHVtbjogbmV4dEZvY3VzQ29sdW1uIH0sXG4gICAgICAgICAgICBhbGxvd1VzZXJPdmVycmlkZTogdHJ1ZSxcbiAgICAgICAgICAgIGV2ZW50OiBldmVudFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8qXG4gICAgICogVGhpcyBtZXRob2QgbmF2aWdhdGVzIGdyaWQgaGVhZGVyIGhvcml6b250YWxseVxuICAgICAqIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgdG8gcHJldmVudERlZmF1bHQgb24gdGhlIGV2ZW50IHRoYXQgY2F1c2VkIHRoaXMgbmF2aWdhdGlvbi5cbiAgICAgKi9cbiAgICBIZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUubmF2aWdhdGVIb3Jpem9udGFsbHkgPSBmdW5jdGlvbiAoZGlyZWN0aW9uLCBmcm9tVGFiLCBldmVudCkge1xuICAgICAgICBpZiAoZnJvbVRhYiA9PT0gdm9pZCAwKSB7IGZyb21UYWIgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgZm9jdXNlZEhlYWRlciA9IHRoaXMuZm9jdXNTZXJ2aWNlLmdldEZvY3VzZWRIZWFkZXIoKTtcbiAgICAgICAgdmFyIGlzTGVmdCA9IGRpcmVjdGlvbiA9PT0gSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbi5MRUZUO1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICB2YXIgbmV4dEhlYWRlcjtcbiAgICAgICAgdmFyIG5vcm1hbGlzZWREaXJlY3Rpb247XG4gICAgICAgIC8vIGVpdGhlciBuYXZpZ2F0aW5nIHRvIHRoZSBsZWZ0IG9yIGlzUnRsIChjYW5ub3QgYmUgYm90aClcbiAgICAgICAgaWYgKGlzTGVmdCAhPT0gaXNSdGwpIHtcbiAgICAgICAgICAgIG5vcm1hbGlzZWREaXJlY3Rpb24gPSAnQmVmb3JlJztcbiAgICAgICAgICAgIG5leHRIZWFkZXIgPSB0aGlzLmhlYWRlclBvc2l0aW9uVXRpbHMuZmluZEhlYWRlcihmb2N1c2VkSGVhZGVyLCBub3JtYWxpc2VkRGlyZWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5vcm1hbGlzZWREaXJlY3Rpb24gPSAnQWZ0ZXInO1xuICAgICAgICAgICAgbmV4dEhlYWRlciA9IHRoaXMuaGVhZGVyUG9zaXRpb25VdGlscy5maW5kSGVhZGVyKGZvY3VzZWRIZWFkZXIsIG5vcm1hbGlzZWREaXJlY3Rpb24pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0SGVhZGVyIHx8ICFmcm9tVGFiKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mb2N1c1NlcnZpY2UuZm9jdXNIZWFkZXJQb3NpdGlvbih7XG4gICAgICAgICAgICAgICAgaGVhZGVyUG9zaXRpb246IG5leHRIZWFkZXIsXG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uOiBub3JtYWxpc2VkRGlyZWN0aW9uLFxuICAgICAgICAgICAgICAgIGZyb21UYWI6IGZyb21UYWIsXG4gICAgICAgICAgICAgICAgYWxsb3dVc2VyT3ZlcnJpZGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZXZlbnQ6IGV2ZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c05leHRIZWFkZXJSb3coZm9jdXNlZEhlYWRlciwgbm9ybWFsaXNlZERpcmVjdGlvbiwgZXZlbnQpO1xuICAgIH07XG4gICAgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmZvY3VzTmV4dEhlYWRlclJvdyA9IGZ1bmN0aW9uIChmb2N1c2VkSGVhZGVyLCBkaXJlY3Rpb24sIGV2ZW50KSB7XG4gICAgICAgIHZhciBjdXJyZW50SW5kZXggPSBmb2N1c2VkSGVhZGVyLmhlYWRlclJvd0luZGV4O1xuICAgICAgICB2YXIgbmV4dFBvc2l0aW9uID0gbnVsbDtcbiAgICAgICAgdmFyIG5leHRSb3dJbmRleDtcbiAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gJ0JlZm9yZScpIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50SW5kZXggPiAwKSB7XG4gICAgICAgICAgICAgICAgbmV4dFJvd0luZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICBuZXh0UG9zaXRpb24gPSB0aGlzLmhlYWRlclBvc2l0aW9uVXRpbHMuZmluZENvbEF0RWRnZUZvckhlYWRlclJvdyhuZXh0Um93SW5kZXgsICdlbmQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5leHRSb3dJbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICBuZXh0UG9zaXRpb24gPSB0aGlzLmhlYWRlclBvc2l0aW9uVXRpbHMuZmluZENvbEF0RWRnZUZvckhlYWRlclJvdyhuZXh0Um93SW5kZXgsICdzdGFydCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmZvY3VzU2VydmljZS5mb2N1c0hlYWRlclBvc2l0aW9uKHtcbiAgICAgICAgICAgIGhlYWRlclBvc2l0aW9uOiBuZXh0UG9zaXRpb24sXG4gICAgICAgICAgICBkaXJlY3Rpb246IGRpcmVjdGlvbixcbiAgICAgICAgICAgIGZyb21UYWI6IHRydWUsXG4gICAgICAgICAgICBhbGxvd1VzZXJPdmVycmlkZTogdHJ1ZSxcbiAgICAgICAgICAgIGV2ZW50OiBldmVudFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5zY3JvbGxUb0NvbHVtbiA9IGZ1bmN0aW9uIChjb2x1bW4sIGRpcmVjdGlvbikge1xuICAgICAgICBpZiAoZGlyZWN0aW9uID09PSB2b2lkIDApIHsgZGlyZWN0aW9uID0gJ0FmdGVyJzsgfVxuICAgICAgICBpZiAoY29sdW1uLmdldFBpbm5lZCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbHVtblRvU2Nyb2xsVG87XG4gICAgICAgIGlmIChjb2x1bW4gaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgdmFyIGNvbHVtbnMgPSBjb2x1bW4uZ2V0RGlzcGxheWVkTGVhZkNvbHVtbnMoKTtcbiAgICAgICAgICAgIGNvbHVtblRvU2Nyb2xsVG8gPSBkaXJlY3Rpb24gPT09ICdCZWZvcmUnID8gbGFzdChjb2x1bW5zKSA6IGNvbHVtbnNbMF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb2x1bW5Ub1Njcm9sbFRvID0gY29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmVuc3VyZUNvbHVtblZpc2libGUoY29sdW1uVG9TY3JvbGxUbyk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFlKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFlKFtcbiAgICAgICAgQXV0b3dpcmVkKCdoZWFkZXJQb3NpdGlvblV0aWxzJylcbiAgICBdLCBIZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUsIFwiaGVhZGVyUG9zaXRpb25VdGlsc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWUoW1xuICAgICAgICBBdXRvd2lyZWQoJ2FuaW1hdGlvbkZyYW1lU2VydmljZScpXG4gICAgXSwgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcImFuaW1hdGlvbkZyYW1lU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWUoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWUoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UgPSBfX2RlY29yYXRlJDFlKFtcbiAgICAgICAgQmVhbignaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlKTtcbiAgICByZXR1cm4gSGVhZGVyTmF2aWdhdGlvblNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMWsgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgR3JpZEhlYWRlckN0cmwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFrKEdyaWRIZWFkZXJDdHJsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdyaWRIZWFkZXJDdHJsKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZS5zZXRDb21wID0gZnVuY3Rpb24gKGNvbXAsIGVHdWksIGVGb2N1c2FibGVFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuY29tcCA9IGNvbXA7XG4gICAgICAgIHRoaXMuZUd1aSA9IGVHdWk7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IE1hbmFnZWRGb2N1c0ZlYXR1cmUoZUZvY3VzYWJsZUVsZW1lbnQsIHtcbiAgICAgICAgICAgIG9uVGFiS2V5RG93bjogdGhpcy5vblRhYktleURvd24uYmluZCh0aGlzKSxcbiAgICAgICAgICAgIGhhbmRsZUtleURvd246IHRoaXMuaGFuZGxlS2V5RG93bi5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgb25Gb2N1c091dDogdGhpcy5vbkZvY3VzT3V0LmJpbmQodGhpcylcbiAgICAgICAgfSkpO1xuICAgICAgICAvLyBmb3Igc2V0dGluZyBhZy1waXZvdC1vbiAvIGFnLXBpdm90LW9mZiBDU1MgY2xhc3Nlc1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9NT0RFX0NIQU5HRUQsIHRoaXMub25QaXZvdE1vZGVDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm9uUGl2b3RNb2RlQ2hhbmdlZCgpO1xuICAgICAgICB0aGlzLnNldHVwSGVhZGVySGVpZ2h0KCk7XG4gICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLnJlZ2lzdGVyR3JpZEhlYWRlckN0cmwodGhpcyk7XG4gICAgfTtcbiAgICBHcmlkSGVhZGVyQ3RybC5wcm90b3R5cGUuc2V0dXBIZWFkZXJIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IHRoaXMuc2V0SGVhZGVySGVpZ2h0LmJpbmQodGhpcyk7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9IRUFERVJfSEVJR0hULCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QSVZPVF9IRUFERVJfSEVJR0hULCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9HUk9VUF9IRUFERVJfSEVJR0hULCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9QSVZPVF9HUk9VUF9IRUFERVJfSEVJR0hULCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9GTE9BVElOR19GSUxURVJTX0hFSUdIVCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX0NIQU5HRUQsIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fSEVBREVSX0hFSUdIVF9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBHcmlkSGVhZGVyQ3RybC5wcm90b3R5cGUuZ2V0SGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5oZWFkZXJIZWlnaHQ7XG4gICAgfTtcbiAgICBHcmlkSGVhZGVyQ3RybC5wcm90b3R5cGUuc2V0SGVhZGVySGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLCBjb2x1bW5Nb2RlbCA9IF9hLmNvbHVtbk1vZGVsLCBncmlkT3B0aW9uc1dyYXBwZXIgPSBfYS5ncmlkT3B0aW9uc1dyYXBwZXI7XG4gICAgICAgIHZhciBudW1iZXJPZkZsb2F0aW5nID0gMDtcbiAgICAgICAgdmFyIGhlYWRlclJvd0NvdW50ID0gY29sdW1uTW9kZWwuZ2V0SGVhZGVyUm93Q291bnQoKTtcbiAgICAgICAgdmFyIHRvdGFsSGVhZGVySGVpZ2h0O1xuICAgICAgICB2YXIgaGFzRmxvYXRpbmdGaWx0ZXJzID0gY29sdW1uTW9kZWwuaGFzRmxvYXRpbmdGaWx0ZXJzKCk7XG4gICAgICAgIGlmIChoYXNGbG9hdGluZ0ZpbHRlcnMpIHtcbiAgICAgICAgICAgIGhlYWRlclJvd0NvdW50Kys7XG4gICAgICAgICAgICBudW1iZXJPZkZsb2F0aW5nID0gMTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZ3JvdXBIZWlnaHQgPSB0aGlzLmNvbHVtbk1vZGVsLmdldENvbHVtbkdyb3VwSGVhZGVyUm93SGVpZ2h0KCk7XG4gICAgICAgIHZhciBoZWFkZXJIZWlnaHQgPSB0aGlzLmNvbHVtbk1vZGVsLmdldENvbHVtbkhlYWRlclJvd0hlaWdodCgpO1xuICAgICAgICB2YXIgbnVtYmVyT2ZOb25Hcm91cHMgPSAxICsgbnVtYmVyT2ZGbG9hdGluZztcbiAgICAgICAgdmFyIG51bWJlck9mR3JvdXBzID0gaGVhZGVyUm93Q291bnQgLSBudW1iZXJPZk5vbkdyb3VwcztcbiAgICAgICAgdG90YWxIZWFkZXJIZWlnaHQgPSBudW1iZXJPZkZsb2F0aW5nICogZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEZsb2F0aW5nRmlsdGVyc0hlaWdodCgpO1xuICAgICAgICB0b3RhbEhlYWRlckhlaWdodCArPSBudW1iZXJPZkdyb3VwcyAqIGdyb3VwSGVpZ2h0O1xuICAgICAgICB0b3RhbEhlYWRlckhlaWdodCArPSBoZWFkZXJIZWlnaHQ7XG4gICAgICAgIGlmICh0aGlzLmhlYWRlckhlaWdodCA9PT0gdG90YWxIZWFkZXJIZWlnaHQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmhlYWRlckhlaWdodCA9IHRvdGFsSGVhZGVySGVpZ2h0O1xuICAgICAgICAvLyBvbmUgZXh0cmEgcGl4ZWwgaXMgbmVlZGVkIGhlcmUgdG8gYWNjb3VudCBmb3IgdGhlXG4gICAgICAgIC8vIGhlaWdodCBvZiB0aGUgYm9yZGVyXG4gICAgICAgIHZhciBweCA9IHRvdGFsSGVhZGVySGVpZ2h0ICsgMSArIFwicHhcIjtcbiAgICAgICAgdGhpcy5jb21wLnNldEhlaWdodEFuZE1pbkhlaWdodChweCk7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoe1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0hFQURFUl9IRUlHSFRfQ0hBTkdFRFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZS5vblBpdm90TW9kZUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwaXZvdE1vZGUgPSB0aGlzLmNvbHVtbk1vZGVsLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1waXZvdC1vbicsIHBpdm90TW9kZSk7XG4gICAgICAgIHRoaXMuY29tcC5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1waXZvdC1vZmYnLCAhcGl2b3RNb2RlKTtcbiAgICB9O1xuICAgIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZS5vblRhYktleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICB2YXIgZGlyZWN0aW9uID0gZS5zaGlmdEtleSAhPT0gaXNSdGxcbiAgICAgICAgICAgID8gSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbi5MRUZUXG4gICAgICAgICAgICA6IEhlYWRlck5hdmlnYXRpb25EaXJlY3Rpb24uUklHSFQ7XG4gICAgICAgIGlmICh0aGlzLmhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLm5hdmlnYXRlSG9yaXpvbnRhbGx5KGRpcmVjdGlvbiwgdHJ1ZSwgZSkgfHxcbiAgICAgICAgICAgIHRoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzTmV4dEdyaWRDb3JlQ29udGFpbmVyKGUuc2hpZnRLZXkpKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZS5oYW5kbGVLZXlEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGRpcmVjdGlvbiA9IG51bGw7XG4gICAgICAgIHN3aXRjaCAoZS5rZXkpIHtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5MRUZUOlxuICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IEhlYWRlck5hdmlnYXRpb25EaXJlY3Rpb24uTEVGVDtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5SSUdIVDpcbiAgICAgICAgICAgICAgICBpZiAoIWV4aXN0cyhkaXJlY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IEhlYWRlck5hdmlnYXRpb25EaXJlY3Rpb24uUklHSFQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UubmF2aWdhdGVIb3Jpem9udGFsbHkoZGlyZWN0aW9uLCBmYWxzZSwgZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuVVA6XG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbi5VUDtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgICAgIGlmICghZXhpc3RzKGRpcmVjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gSGVhZGVyTmF2aWdhdGlvbkRpcmVjdGlvbi5ET1dOO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5uYXZpZ2F0ZVZlcnRpY2FsbHkoZGlyZWN0aW9uLCBudWxsLCBlKSkge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZS5vbkZvY3VzT3V0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIHZhciByZWxhdGVkVGFyZ2V0ID0gZS5yZWxhdGVkVGFyZ2V0O1xuICAgICAgICBpZiAoIXJlbGF0ZWRUYXJnZXQgJiYgdGhpcy5lR3VpLmNvbnRhaW5zKGVEb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5lR3VpLmNvbnRhaW5zKHJlbGF0ZWRUYXJnZXQpKSB7XG4gICAgICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5jbGVhckZvY3VzZWRIZWFkZXIoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxZChbXG4gICAgICAgIEF1dG93aXJlZCgnaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZSwgXCJoZWFkZXJOYXZpZ2F0aW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZvY3VzU2VydmljZScpXG4gICAgXSwgR3JpZEhlYWRlckN0cmwucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBHcmlkSGVhZGVyQ3RybC5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFkKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEdyaWRIZWFkZXJDdHJsLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gR3JpZEhlYWRlckN0cmw7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMWogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDFjID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgR3JpZEhlYWRlckNvbXAgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDFqKEdyaWRIZWFkZXJDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdyaWRIZWFkZXJDb21wKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgR3JpZEhlYWRlckNvbXAuVEVNUExBVEUpIHx8IHRoaXM7XG4gICAgfVxuICAgIEdyaWRIZWFkZXJDb21wLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgY29tcFByb3h5ID0ge1xuICAgICAgICAgICAgYWRkT3JSZW1vdmVDc3NDbGFzczogZnVuY3Rpb24gKGNzc0NsYXNzTmFtZSwgb24pIHsgcmV0dXJuIF90aGlzLmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoY3NzQ2xhc3NOYW1lLCBvbik7IH0sXG4gICAgICAgICAgICBzZXRIZWlnaHRBbmRNaW5IZWlnaHQ6IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5nZXRHdWkoKS5zdHlsZS5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkuc3R5bGUubWluSGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgY3RybCA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEdyaWRIZWFkZXJDdHJsKCkpO1xuICAgICAgICBjdHJsLnNldENvbXAoY29tcFByb3h5LCB0aGlzLmdldEd1aSgpLCB0aGlzLmdldEZvY3VzYWJsZUVsZW1lbnQoKSk7XG4gICAgICAgIHZhciBhZGRDb250YWluZXIgPSBmdW5jdGlvbiAoY29udGFpbmVyKSB7XG4gICAgICAgICAgICBfdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihjb250YWluZXIpO1xuICAgICAgICAgICAgX3RoaXMuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICAgICAgfTtcbiAgICAgICAgYWRkQ29udGFpbmVyKG5ldyBIZWFkZXJSb3dDb250YWluZXJDb21wKENvbnN0YW50cy5QSU5ORURfTEVGVCkpO1xuICAgICAgICBhZGRDb250YWluZXIobmV3IEhlYWRlclJvd0NvbnRhaW5lckNvbXAobnVsbCkpO1xuICAgICAgICBhZGRDb250YWluZXIobmV3IEhlYWRlclJvd0NvbnRhaW5lckNvbXAoQ29uc3RhbnRzLlBJTk5FRF9SSUdIVCkpO1xuICAgIH07XG4gICAgR3JpZEhlYWRlckNvbXAuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWhlYWRlclxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIi8+XCI7XG4gICAgX19kZWNvcmF0ZSQxYyhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBHcmlkSGVhZGVyQ29tcC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gR3JpZEhlYWRlckNvbXA7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFpID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxYiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEhvcml6b250YWxSZXNpemVTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxaShIb3Jpem9udGFsUmVzaXplU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBIb3Jpem9udGFsUmVzaXplU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBIb3Jpem9udGFsUmVzaXplU2VydmljZS5wcm90b3R5cGUuYWRkUmVzaXplQmFyID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZHJhZ1NvdXJjZSA9IHtcbiAgICAgICAgICAgIGRyYWdTdGFydFBpeGVsczogcGFyYW1zLmRyYWdTdGFydFBpeGVscyB8fCAwLFxuICAgICAgICAgICAgZUVsZW1lbnQ6IHBhcmFtcy5lUmVzaXplQmFyLFxuICAgICAgICAgICAgb25EcmFnU3RhcnQ6IHRoaXMub25EcmFnU3RhcnQuYmluZCh0aGlzLCBwYXJhbXMpLFxuICAgICAgICAgICAgb25EcmFnU3RvcDogdGhpcy5vbkRyYWdTdG9wLmJpbmQodGhpcywgcGFyYW1zKSxcbiAgICAgICAgICAgIG9uRHJhZ2dpbmc6IHRoaXMub25EcmFnZ2luZy5iaW5kKHRoaXMsIHBhcmFtcylcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kcmFnU2VydmljZS5hZGREcmFnU291cmNlKGRyYWdTb3VyY2UsIHRydWUpO1xuICAgICAgICAvLyB3ZSBwYXNzIHJlbW92ZSBmdW5jIGJhY2sgdG8gdGhlIGNhbGxlciwgc28gY2FsbCBjYW4gdGVsbCB1cyB3aGVuIHRoZXlcbiAgICAgICAgLy8gYXJlIGZpbmlzaGVkLCBhbmQgdGhlbiB3ZSByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gdGhlIGRyYWcgc291cmNlXG4gICAgICAgIHZhciBmaW5pc2hlZFdpdGhSZXNpemVGdW5jID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZHJhZ1NlcnZpY2UucmVtb3ZlRHJhZ1NvdXJjZShkcmFnU291cmNlKTsgfTtcbiAgICAgICAgcmV0dXJuIGZpbmlzaGVkV2l0aFJlc2l6ZUZ1bmM7XG4gICAgfTtcbiAgICBIb3Jpem9udGFsUmVzaXplU2VydmljZS5wcm90b3R5cGUub25EcmFnU3RhcnQgPSBmdW5jdGlvbiAocGFyYW1zLCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIHRoaXMuZHJhZ1N0YXJ0WCA9IG1vdXNlRXZlbnQuY2xpZW50WDtcbiAgICAgICAgdGhpcy5zZXRSZXNpemVJY29ucygpO1xuICAgICAgICB2YXIgc2hpZnRLZXkgPSBtb3VzZUV2ZW50IGluc3RhbmNlb2YgTW91c2VFdmVudCAmJiBtb3VzZUV2ZW50LnNoaWZ0S2V5ID09PSB0cnVlO1xuICAgICAgICBwYXJhbXMub25SZXNpemVTdGFydChzaGlmdEtleSk7XG4gICAgfTtcbiAgICBIb3Jpem9udGFsUmVzaXplU2VydmljZS5wcm90b3R5cGUuc2V0UmVzaXplSWNvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjdHJsID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEN0cmwoKTtcbiAgICAgICAgLy8gY2hhbmdlIHRoZSBib2R5IGN1cnNvciwgc28gd2hlbiBkcmFnIG1vdmVzIG91dCBvZiB0aGUgZHJhZyBiYXIsIHRoZSBjdXJzb3IgaXMgc3RpbGwgJ3Jlc2l6ZScgKG9yICdtb3ZlJ1xuICAgICAgICBjdHJsLnNldFJlc2l6ZUN1cnNvcih0cnVlKTtcbiAgICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0ZXh0IHNlbGVjdGlvbiBvdXRzaWRlIHRoZSBncmlkIChvdGhlcndpc2UgaXQgbG9va3Mgd2VpcmQgYXMgdGV4dCBoaWdobGlnaHRzIHdoZW4gd2UgbW92ZSlcbiAgICAgICAgY3RybC5kaXNhYmxlVXNlclNlbGVjdCh0cnVlKTtcbiAgICB9O1xuICAgIEhvcml6b250YWxSZXNpemVTZXJ2aWNlLnByb3RvdHlwZS5vbkRyYWdTdG9wID0gZnVuY3Rpb24gKHBhcmFtcywgbW91c2VFdmVudCkge1xuICAgICAgICBwYXJhbXMub25SZXNpemVFbmQodGhpcy5yZXNpemVBbW91bnQpO1xuICAgICAgICB0aGlzLnJlc2V0SWNvbnMoKTtcbiAgICB9O1xuICAgIEhvcml6b250YWxSZXNpemVTZXJ2aWNlLnByb3RvdHlwZS5yZXNldEljb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY3RybCA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRDdHJsKCk7XG4gICAgICAgIGN0cmwuc2V0UmVzaXplQ3Vyc29yKGZhbHNlKTtcbiAgICAgICAgY3RybC5kaXNhYmxlVXNlclNlbGVjdChmYWxzZSk7XG4gICAgfTtcbiAgICBIb3Jpem9udGFsUmVzaXplU2VydmljZS5wcm90b3R5cGUub25EcmFnZ2luZyA9IGZ1bmN0aW9uIChwYXJhbXMsIG1vdXNlRXZlbnQpIHtcbiAgICAgICAgdGhpcy5yZXNpemVBbW91bnQgPSBtb3VzZUV2ZW50LmNsaWVudFggLSB0aGlzLmRyYWdTdGFydFg7XG4gICAgICAgIHBhcmFtcy5vblJlc2l6aW5nKHRoaXMucmVzaXplQW1vdW50KTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMWIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2RyYWdTZXJ2aWNlJylcbiAgICBdLCBIb3Jpem9udGFsUmVzaXplU2VydmljZS5wcm90b3R5cGUsIFwiZHJhZ1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFiKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEhvcml6b250YWxSZXNpemVTZXJ2aWNlLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBIb3Jpem9udGFsUmVzaXplU2VydmljZSA9IF9fZGVjb3JhdGUkMWIoW1xuICAgICAgICBCZWFuKCdob3Jpem9udGFsUmVzaXplU2VydmljZScpXG4gICAgXSwgSG9yaXpvbnRhbFJlc2l6ZVNlcnZpY2UpO1xuICAgIHJldHVybiBIb3Jpem9udGFsUmVzaXplU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxaCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMWEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBTdGFuZGFyZE1lbnVGYWN0b3J5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxaChTdGFuZGFyZE1lbnVGYWN0b3J5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN0YW5kYXJkTWVudUZhY3RvcnkoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgU3RhbmRhcmRNZW51RmFjdG9yeS5wcm90b3R5cGUuaGlkZUFjdGl2ZU1lbnUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmhpZGVQb3B1cCkge1xuICAgICAgICAgICAgdGhpcy5oaWRlUG9wdXAoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU3RhbmRhcmRNZW51RmFjdG9yeS5wcm90b3R5cGUuc2hvd01lbnVBZnRlck1vdXNlRXZlbnQgPSBmdW5jdGlvbiAoY29sdW1uLCBtb3VzZUV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc2hvd1BvcHVwKGNvbHVtbiwgZnVuY3Rpb24gKGVNZW51KSB7XG4gICAgICAgICAgICBfdGhpcy5wb3B1cFNlcnZpY2UucG9zaXRpb25Qb3B1cFVuZGVyTW91c2VFdmVudCh7XG4gICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICAgICAgdHlwZTogJ2NvbHVtbk1lbnUnLFxuICAgICAgICAgICAgICAgIG1vdXNlRXZlbnQ6IG1vdXNlRXZlbnQsXG4gICAgICAgICAgICAgICAgZVBvcHVwOiBlTWVudVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIG1vdXNlRXZlbnQudGFyZ2V0KTtcbiAgICB9O1xuICAgIFN0YW5kYXJkTWVudUZhY3RvcnkucHJvdG90eXBlLnNob3dNZW51QWZ0ZXJCdXR0b25DbGljayA9IGZ1bmN0aW9uIChjb2x1bW4sIGV2ZW50U291cmNlLCBjb250YWluZXJUeXBlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc2hvd1BvcHVwKGNvbHVtbiwgZnVuY3Rpb24gKGVNZW51KSB7XG4gICAgICAgICAgICBfdGhpcy5wb3B1cFNlcnZpY2UucG9zaXRpb25Qb3B1cFVuZGVyQ29tcG9uZW50KHtcbiAgICAgICAgICAgICAgICB0eXBlOiBjb250YWluZXJUeXBlLFxuICAgICAgICAgICAgICAgIGV2ZW50U291cmNlOiBldmVudFNvdXJjZSxcbiAgICAgICAgICAgICAgICBlUG9wdXA6IGVNZW51LFxuICAgICAgICAgICAgICAgIGtlZXBXaXRoaW5Cb3VuZHM6IHRydWUsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBldmVudFNvdXJjZSk7XG4gICAgfTtcbiAgICBTdGFuZGFyZE1lbnVGYWN0b3J5LnByb3RvdHlwZS5zaG93UG9wdXAgPSBmdW5jdGlvbiAoY29sdW1uLCBwb3NpdGlvbkNhbGxiYWNrLCBldmVudFNvdXJjZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZmlsdGVyV3JhcHBlciA9IHRoaXMuZmlsdGVyTWFuYWdlci5nZXRPckNyZWF0ZUZpbHRlcldyYXBwZXIoY29sdW1uLCAnQ09MVU1OX01FTlUnKTtcbiAgICAgICAgaWYgKCFmaWx0ZXJXcmFwcGVyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FHIEdyaWQgLSB1bmFibGUgdG8gc2hvdyBwb3B1cCBmaWx0ZXIsIGZpbHRlciBpbnN0YW50aWF0aW9uIGZhaWxlZCcpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlTWVudSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBzZXRBcmlhUm9sZShlTWVudSwgJ3ByZXNlbnRhdGlvbicpO1xuICAgICAgICBlTWVudS5jbGFzc0xpc3QuYWRkKCdhZy1tZW51Jyk7XG4gICAgICAgIHRoaXMudGFiTGlzdGVuZXIgPSB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlTWVudSwgJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMudHJhcEZvY3VzV2l0aGluKGUsIGVNZW51KTsgfSk7XG4gICAgICAgIGZpbHRlcldyYXBwZXIuZ3VpUHJvbWlzZS50aGVuKGZ1bmN0aW9uIChndWkpIHsgcmV0dXJuIGVNZW51LmFwcGVuZENoaWxkKGd1aSk7IH0pO1xuICAgICAgICB2YXIgaGlkZVBvcHVwO1xuICAgICAgICB2YXIgYW5jaG9yVG9FbGVtZW50ID0gZXZlbnRTb3VyY2UgfHwgdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCkuZ2V0R3VpKCk7XG4gICAgICAgIHZhciBjbG9zZWRDYWxsYmFjayA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBjb2x1bW4uc2V0TWVudVZpc2libGUoZmFsc2UsICdjb250ZXh0TWVudScpO1xuICAgICAgICAgICAgdmFyIGlzS2V5Ym9hcmRFdmVudCA9IGUgaW5zdGFuY2VvZiBLZXlib2FyZEV2ZW50O1xuICAgICAgICAgICAgaWYgKF90aGlzLnRhYkxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMudGFiTGlzdGVuZXIgPSBfdGhpcy50YWJMaXN0ZW5lcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzS2V5Ym9hcmRFdmVudCAmJiBldmVudFNvdXJjZSAmJiBpc1Zpc2libGUoZXZlbnRTb3VyY2UpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZvY3VzYWJsZUVsID0gX3RoaXMuZm9jdXNTZXJ2aWNlLmZpbmRUYWJiYWJsZVBhcmVudChldmVudFNvdXJjZSk7XG4gICAgICAgICAgICAgICAgaWYgKGZvY3VzYWJsZUVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvY3VzYWJsZUVsLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIGFkZFBvcHVwUmVzID0gdGhpcy5wb3B1cFNlcnZpY2UuYWRkUG9wdXAoe1xuICAgICAgICAgICAgbW9kYWw6IHRydWUsXG4gICAgICAgICAgICBlQ2hpbGQ6IGVNZW51LFxuICAgICAgICAgICAgY2xvc2VPbkVzYzogdHJ1ZSxcbiAgICAgICAgICAgIGNsb3NlZENhbGxiYWNrOiBjbG9zZWRDYWxsYmFjayxcbiAgICAgICAgICAgIHBvc2l0aW9uQ2FsbGJhY2s6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHBvc2l0aW9uQ2FsbGJhY2soZU1lbnUpOyB9LFxuICAgICAgICAgICAgYW5jaG9yVG9FbGVtZW50OiBhbmNob3JUb0VsZW1lbnQsXG4gICAgICAgICAgICBhcmlhTGFiZWw6IHRyYW5zbGF0ZSgnYXJpYUxhYmVsQ29sdW1uTWVudScsICdDb2x1bW4gTWVudScpXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWRkUG9wdXBSZXMpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZVBvcHVwID0gaGlkZVBvcHVwID0gYWRkUG9wdXBSZXMuaGlkZUZ1bmM7XG4gICAgICAgIH1cbiAgICAgICAgZmlsdGVyV3JhcHBlci5maWx0ZXJQcm9taXNlLnRoZW4oZnVuY3Rpb24gKGZpbHRlcikge1xuICAgICAgICAgICAgLy8gbmVlZCB0byBtYWtlIHN1cmUgdGhlIGZpbHRlciBpcyBwcmVzZW50IGJlZm9yZSBwb3NpdGlvbmluZywgYXMgb25seVxuICAgICAgICAgICAgLy8gYWZ0ZXIgZmlsdGVyIGl0IGlzIHZpc2libGUgY2FuIHdlIGZpbmQgb3V0IHdoYXQgdGhlIHdpZHRoIG9mIGl0IGlzXG4gICAgICAgICAgICBwb3NpdGlvbkNhbGxiYWNrKGVNZW51KTtcbiAgICAgICAgICAgIGlmIChmaWx0ZXIuYWZ0ZXJHdWlBdHRhY2hlZCkge1xuICAgICAgICAgICAgICAgIGZpbHRlci5hZnRlckd1aUF0dGFjaGVkKHsgY29udGFpbmVyOiAnY29sdW1uTWVudScsIGhpZGVQb3B1cDogaGlkZVBvcHVwIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgY29sdW1uLnNldE1lbnVWaXNpYmxlKHRydWUsICdjb250ZXh0TWVudScpO1xuICAgIH07XG4gICAgU3RhbmRhcmRNZW51RmFjdG9yeS5wcm90b3R5cGUudHJhcEZvY3VzV2l0aGluID0gZnVuY3Rpb24gKGUsIG1lbnUpIHtcbiAgICAgICAgaWYgKGUua2V5ICE9PSBLZXlDb2RlLlRBQiB8fFxuICAgICAgICAgICAgZS5kZWZhdWx0UHJldmVudGVkIHx8XG4gICAgICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5maW5kTmV4dEZvY3VzYWJsZUVsZW1lbnQobWVudSwgZmFsc2UsIGUuc2hpZnRLZXkpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5mb2N1c0ludG8obWVudSwgZS5zaGlmdEtleSk7XG4gICAgfTtcbiAgICBTdGFuZGFyZE1lbnVGYWN0b3J5LnByb3RvdHlwZS5pc01lbnVFbmFibGVkID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAvLyBmb3Igc3RhbmRhcmQsIHdlIHNob3cgbWVudSBpZiBmaWx0ZXIgaXMgZW5hYmxlZCwgYW5kIHRoZSBtZW51IGlzIG5vdCBzdXBwcmVzc2VkXG4gICAgICAgIHJldHVybiBjb2x1bW4uaXNGaWx0ZXJBbGxvd2VkKCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDFhKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmaWx0ZXJNYW5hZ2VyJylcbiAgICBdLCBTdGFuZGFyZE1lbnVGYWN0b3J5LnByb3RvdHlwZSwgXCJmaWx0ZXJNYW5hZ2VyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxYShbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBTdGFuZGFyZE1lbnVGYWN0b3J5LnByb3RvdHlwZSwgXCJwb3B1cFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDFhKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIFN0YW5kYXJkTWVudUZhY3RvcnkucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMWEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgU3RhbmRhcmRNZW51RmFjdG9yeS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgU3RhbmRhcmRNZW51RmFjdG9yeSA9IF9fZGVjb3JhdGUkMWEoW1xuICAgICAgICBCZWFuKCdtZW51RmFjdG9yeScpXG4gICAgXSwgU3RhbmRhcmRNZW51RmFjdG9yeSk7XG4gICAgcmV0dXJuIFN0YW5kYXJkTWVudUZhY3Rvcnk7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMWcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDE5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgVGFiYmVkTGF5b3V0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxZyhUYWJiZWRMYXlvdXQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVGFiYmVkTGF5b3V0KHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBUYWJiZWRMYXlvdXQuZ2V0VGVtcGxhdGUocGFyYW1zLmNzc0NsYXNzKSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuaXRlbXMgPSBbXTtcbiAgICAgICAgX3RoaXMudGFiYmVkSXRlbVNjcm9sbE1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgX3RoaXMucGFyYW1zID0gcGFyYW1zO1xuICAgICAgICBpZiAocGFyYW1zLml0ZW1zKSB7XG4gICAgICAgICAgICBwYXJhbXMuaXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gX3RoaXMuYWRkSXRlbShpdGVtKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBUYWJiZWRMYXlvdXQucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IE1hbmFnZWRGb2N1c0ZlYXR1cmUodGhpcy5nZXRGb2N1c2FibGVFbGVtZW50KCksIHtcbiAgICAgICAgICAgIG9uVGFiS2V5RG93bjogdGhpcy5vblRhYktleURvd24uYmluZCh0aGlzKSxcbiAgICAgICAgICAgIGhhbmRsZUtleURvd246IHRoaXMuaGFuZGxlS2V5RG93bi5iaW5kKHRoaXMpXG4gICAgICAgIH0pKTtcbiAgICB9O1xuICAgIFRhYmJlZExheW91dC5nZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uIChjc3NDbGFzcykge1xuICAgICAgICByZXR1cm4gLyogaHRtbCAqLyBcIjxkaXYgY2xhc3M9XFxcImFnLXRhYnMgXCIgKyBjc3NDbGFzcyArIFwiXFxcIj5cXG4gICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZUhlYWRlclxcXCIgcm9sZT1cXFwidGFibGlzdFxcXCIgY2xhc3M9XFxcImFnLXRhYnMtaGVhZGVyIFwiICsgKGNzc0NsYXNzID8gY3NzQ2xhc3MgKyBcIi1oZWFkZXJcIiA6ICcnKSArIFwiXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZUJvZHlcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCIgY2xhc3M9XFxcImFnLXRhYnMtYm9keSBcIiArIChjc3NDbGFzcyA/IGNzc0NsYXNzICsgXCItYm9keVwiIDogJycpICsgXCJcXFwiPjwvZGl2PlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgfTtcbiAgICBUYWJiZWRMYXlvdXQucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgc3dpdGNoIChlLmtleSkge1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlJJR0hUOlxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkxFRlQ6XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVIZWFkZXIuY29udGFpbnMoZURvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGlzUmlnaHRLZXkgPSBlLmtleSA9PT0gS2V5Q29kZS5SSUdIVDtcbiAgICAgICAgICAgICAgICB2YXIgaXNSdGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50UG9zaXRpb24gPSB0aGlzLml0ZW1zLmluZGV4T2YodGhpcy5hY3RpdmVJdGVtKTtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dFBvc2l0aW9uID0gaXNSaWdodEtleSAhPT0gaXNSdGwgPyBNYXRoLm1pbihjdXJyZW50UG9zaXRpb24gKyAxLCB0aGlzLml0ZW1zLmxlbmd0aCAtIDEpIDogTWF0aC5tYXgoY3VycmVudFBvc2l0aW9uIC0gMSwgMCk7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRQb3NpdGlvbiA9PT0gbmV4dFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIHZhciBuZXh0SXRlbSA9IHRoaXMuaXRlbXNbbmV4dFBvc2l0aW9uXTtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dJdGVtV3JhcHBlcihuZXh0SXRlbSk7XG4gICAgICAgICAgICAgICAgbmV4dEl0ZW0uZUhlYWRlckJ1dHRvbi5mb2N1cygpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlVQOlxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRPV046XG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgVGFiYmVkTGF5b3V0LnByb3RvdHlwZS5vblRhYktleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIF9hID0gdGhpcywgZm9jdXNTZXJ2aWNlID0gX2EuZm9jdXNTZXJ2aWNlLCBlSGVhZGVyID0gX2EuZUhlYWRlciwgZUJvZHkgPSBfYS5lQm9keSwgYWN0aXZlSXRlbSA9IF9hLmFjdGl2ZUl0ZW07XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgYWN0aXZlRWxlbWVudCA9IGVEb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmIChlSGVhZGVyLmNvbnRhaW5zKGFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAvLyBmb2N1cyBpcyBpbiBoZWFkZXIsIG1vdmUgaW50byBib2R5IG9mIHBvcHVwXG4gICAgICAgICAgICBmb2N1c1NlcnZpY2UuZm9jdXNJbnRvKGVCb2R5LCBlLnNoaWZ0S2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZvY3VzIGlzIGluIGJvZHksIGVzdGFibGlzaCBpZiBpdCBzaG91bGQgcmV0dXJuIHRvIGhlYWRlclxuICAgICAgICAgICAgaWYgKGZvY3VzU2VydmljZS5pc0ZvY3VzVW5kZXJNYW5hZ2VkQ29tcG9uZW50KGVCb2R5KSkge1xuICAgICAgICAgICAgICAgIC8vIGZvY3VzIHdhcyBpbiBhIG1hbmFnZWQgZm9jdXMgY29tcG9uZW50IGFuZCBoYXMgbm93IGxlZnQsIHNvIHdlIGNhbiByZXR1cm4gdG8gdGhlIGhlYWRlclxuICAgICAgICAgICAgICAgIGFjdGl2ZUl0ZW0uZUhlYWRlckJ1dHRvbi5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIG5leHRFbCA9IGZvY3VzU2VydmljZS5maW5kTmV4dEZvY3VzYWJsZUVsZW1lbnQoZUJvZHksIGZhbHNlLCBlLnNoaWZ0S2V5KTtcbiAgICAgICAgICAgICAgICBpZiAobmV4dEVsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIGFub3RoZXIgZWxlbWVudCBleGlzdHMgaW4gdGhlIGJvZHkgdGhhdCBjYW4gYmUgZm9jdXNzZWQsIGdvIHRvIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgbmV4dEVsLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgcmV0dXJuIHRvIHRoZSBoZWFkZXJcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlSXRlbS5lSGVhZGVyQnV0dG9uLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBUYWJiZWRMYXlvdXQucHJvdG90eXBlLnNldEFmdGVyQXR0YWNoZWRQYXJhbXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHRoaXMuYWZ0ZXJBdHRhY2hlZFBhcmFtcyA9IHBhcmFtcztcbiAgICB9O1xuICAgIFRhYmJlZExheW91dC5wcm90b3R5cGUuc2hvd0ZpcnN0SXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5zaG93SXRlbVdyYXBwZXIodGhpcy5pdGVtc1swXSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFRhYmJlZExheW91dC5wcm90b3R5cGUuYWRkSXRlbSA9IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIHZhciBlSGVhZGVyQnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgICAgICBzZXRBcmlhUm9sZShlSGVhZGVyQnV0dG9uLCAndGFiJyk7XG4gICAgICAgIGVIZWFkZXJCdXR0b24uc2V0QXR0cmlidXRlKCd0YWJJbmRleCcsICctMScpO1xuICAgICAgICBlSGVhZGVyQnV0dG9uLmFwcGVuZENoaWxkKGl0ZW0udGl0bGUpO1xuICAgICAgICBlSGVhZGVyQnV0dG9uLmNsYXNzTGlzdC5hZGQoJ2FnLXRhYicpO1xuICAgICAgICB0aGlzLmVIZWFkZXIuYXBwZW5kQ2hpbGQoZUhlYWRlckJ1dHRvbik7XG4gICAgICAgIHNldEFyaWFMYWJlbChlSGVhZGVyQnV0dG9uLCBpdGVtLnRpdGxlTGFiZWwpO1xuICAgICAgICB2YXIgd3JhcHBlciA9IHtcbiAgICAgICAgICAgIHRhYmJlZEl0ZW06IGl0ZW0sXG4gICAgICAgICAgICBlSGVhZGVyQnV0dG9uOiBlSGVhZGVyQnV0dG9uXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaXRlbXMucHVzaCh3cmFwcGVyKTtcbiAgICAgICAgZUhlYWRlckJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuc2hvd0l0ZW1XcmFwcGVyLmJpbmQodGhpcywgd3JhcHBlcikpO1xuICAgIH07XG4gICAgVGFiYmVkTGF5b3V0LnByb3RvdHlwZS5zaG93SXRlbSA9IGZ1bmN0aW9uICh0YWJiZWRJdGVtKSB7XG4gICAgICAgIHZhciBpdGVtV3JhcHBlciA9IHRoaXMuaXRlbXMuZmluZChmdW5jdGlvbiAod3JhcHBlcikgeyByZXR1cm4gd3JhcHBlci50YWJiZWRJdGVtID09PSB0YWJiZWRJdGVtOyB9KTtcbiAgICAgICAgaWYgKGl0ZW1XcmFwcGVyKSB7XG4gICAgICAgICAgICB0aGlzLnNob3dJdGVtV3JhcHBlcihpdGVtV3JhcHBlcik7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFRhYmJlZExheW91dC5wcm90b3R5cGUuc2hvd0l0ZW1XcmFwcGVyID0gZnVuY3Rpb24gKHdyYXBwZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHRhYmJlZEl0ZW0gPSB3cmFwcGVyLnRhYmJlZEl0ZW0sIGVIZWFkZXJCdXR0b24gPSB3cmFwcGVyLmVIZWFkZXJCdXR0b247XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5vbkl0ZW1DbGlja2VkKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmFtcy5vbkl0ZW1DbGlja2VkKHsgaXRlbTogdGFiYmVkSXRlbSB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5hY3RpdmVJdGVtID09PSB3cmFwcGVyKSB7XG4gICAgICAgICAgICBjYWxsSWZQcmVzZW50KHRoaXMucGFyYW1zLm9uQWN0aXZlSXRlbUNsaWNrZWQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmxhc3RTY3JvbGxMaXN0ZW5lcikge1xuICAgICAgICAgICAgdGhpcy5sYXN0U2Nyb2xsTGlzdGVuZXIgPSB0aGlzLmxhc3RTY3JvbGxMaXN0ZW5lcigpO1xuICAgICAgICB9XG4gICAgICAgIGNsZWFyRWxlbWVudCh0aGlzLmVCb2R5KTtcbiAgICAgICAgdGFiYmVkSXRlbS5ib2R5UHJvbWlzZS50aGVuKGZ1bmN0aW9uIChib2R5KSB7XG4gICAgICAgICAgICBfdGhpcy5lQm9keS5hcHBlbmRDaGlsZChib2R5KTtcbiAgICAgICAgICAgIHZhciBvbmx5VW5tYW5hZ2VkID0gIV90aGlzLmZvY3VzU2VydmljZS5pc0tleWJvYXJkTW9kZSgpO1xuICAgICAgICAgICAgX3RoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzSW50byhfdGhpcy5lQm9keSwgZmFsc2UsIG9ubHlVbm1hbmFnZWQpO1xuICAgICAgICAgICAgaWYgKHRhYmJlZEl0ZW0uYWZ0ZXJBdHRhY2hlZENhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgdGFiYmVkSXRlbS5hZnRlckF0dGFjaGVkQ2FsbGJhY2soX3RoaXMuYWZ0ZXJBdHRhY2hlZFBhcmFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3RoaXMucGFyYW1zLmtlZXBTY3JvbGxQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBzY3JvbGxhYmxlQ29udGFpbmVyXzEgPSAodGFiYmVkSXRlbS5nZXRTY3JvbGxhYmxlQ29udGFpbmVyICYmIHRhYmJlZEl0ZW0uZ2V0U2Nyb2xsYWJsZUNvbnRhaW5lcigpKSB8fCBib2R5O1xuICAgICAgICAgICAgICAgIF90aGlzLmxhc3RTY3JvbGxMaXN0ZW5lciA9IF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihzY3JvbGxhYmxlQ29udGFpbmVyXzEsICdzY3JvbGwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRhYmJlZEl0ZW1TY3JvbGxNYXAuc2V0KHRhYmJlZEl0ZW0ubmFtZSwgc2Nyb2xsYWJsZUNvbnRhaW5lcl8xLnNjcm9sbFRvcCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdmFyIHNjcm9sbFBvc2l0aW9uXzEgPSBfdGhpcy50YWJiZWRJdGVtU2Nyb2xsTWFwLmdldCh0YWJiZWRJdGVtLm5hbWUpO1xuICAgICAgICAgICAgICAgIGlmIChzY3JvbGxQb3NpdGlvbl8xICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2FmYXJpIG5lZWRzIGEgc21hbGwgdGltZW91dCBvciBpdCB3aWxsIGZpcmUgYSBzY3JvbGwgZXZlbnQgdG8gcG9zaXRpb24gMFxuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbGFibGVDb250YWluZXJfMS5zY3JvbGxUb3AgPSBzY3JvbGxQb3NpdGlvbl8xO1xuICAgICAgICAgICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy5hY3RpdmVJdGVtKSB7XG4gICAgICAgICAgICB0aGlzLmFjdGl2ZUl0ZW0uZUhlYWRlckJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKCdhZy10YWItc2VsZWN0ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBlSGVhZGVyQnV0dG9uLmNsYXNzTGlzdC5hZGQoJ2FnLXRhYi1zZWxlY3RlZCcpO1xuICAgICAgICB0aGlzLmFjdGl2ZUl0ZW0gPSB3cmFwcGVyO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxOShbXG4gICAgICAgIEF1dG93aXJlZCgnZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBUYWJiZWRMYXlvdXQucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTkoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUhlYWRlcicpXG4gICAgXSwgVGFiYmVkTGF5b3V0LnByb3RvdHlwZSwgXCJlSGVhZGVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxOShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQm9keScpXG4gICAgXSwgVGFiYmVkTGF5b3V0LnByb3RvdHlwZSwgXCJlQm9keVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTkoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgVGFiYmVkTGF5b3V0LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBUYWJiZWRMYXlvdXQ7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG4vKipcbiAqIEBkZXByZWNhdGVkXG4gKi9cbmZ1bmN0aW9uIHNpbXBsZUh0dHBSZXF1ZXN0KHBhcmFtcykge1xuICAgIHJldHVybiBuZXcgQWdQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgIHZhciBodHRwUmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICBodHRwUmVxdWVzdC5vcGVuKCdHRVQnLCBwYXJhbXMudXJsKTtcbiAgICAgICAgaHR0cFJlcXVlc3Quc2VuZCgpO1xuICAgICAgICBodHRwUmVxdWVzdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoaHR0cFJlcXVlc3QucmVhZHlTdGF0ZSA9PT0gNCAmJiBodHRwUmVxdWVzdC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoSlNPTi5wYXJzZShodHRwUmVxdWVzdC5yZXNwb25zZVRleHQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxZiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMTggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBERUJPVU5DRV9ERUxBWSA9IDUwO1xudmFyIFJlc2l6ZU9ic2VydmVyU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMWYoUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJlc2l6ZU9ic2VydmVyU2VydmljZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnBvbHlmaWxsRnVuY3Rpb25zID0gW107XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlLnByb3RvdHlwZS5vYnNlcnZlUmVzaXplID0gZnVuY3Rpb24gKGVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgd2luID0gKGVEb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3cpO1xuICAgICAgICAvLyB0aGlzIGdldHMgZmlyZWQgdG9vIG9mdGVuIGFuZCBtaWdodCBjYXVzZSBzb21lIHJlbGF5b3V0IGlzc3Vlc1xuICAgICAgICAvLyBzbyB3ZSBhZGQgYSBkZWJvdW5jZSB0byB0aGUgY2FsbGJhY2sgaGVyZSB0byBhdm9pZCB0aGUgZmxhc2hpbmcgZWZmZWN0LlxuICAgICAgICB2YXIgZGVib3VuY2VkQ2FsbGJhY2sgPSBkZWJvdW5jZShjYWxsYmFjaywgREVCT1VOQ0VfREVMQVkpO1xuICAgICAgICB2YXIgdXNlQnJvd3NlclJlc2l6ZU9ic2VydmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHJlc2l6ZU9ic2VydmVyID0gbmV3IHdpbi5SZXNpemVPYnNlcnZlcihkZWJvdW5jZWRDYWxsYmFjayk7XG4gICAgICAgICAgICByZXNpemVPYnNlcnZlci5vYnNlcnZlKGVsZW1lbnQpO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHJlc2l6ZU9ic2VydmVyLmRpc2Nvbm5lY3QoKTsgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHVzZVBvbHlmaWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gaW5pdGlhbGlzZSB0byB0aGUgY3VycmVudCB3aWR0aCBhbmQgaGVpZ2h0LCBzbyBmaXJzdCBjYWxsIHdpbGwgaGF2ZSBubyBjaGFuZ2VzXG4gICAgICAgICAgICB2YXIgd2lkdGhMYXN0VGltZSA9IG9mZnNldFdpZHRoKGVsZW1lbnQpO1xuICAgICAgICAgICAgdmFyIGhlaWdodExhc3RUaW1lID0gb2Zmc2V0SGVpZ2h0KGVsZW1lbnQpO1xuICAgICAgICAgICAgLy8gd2hlbiBmaW5pc2hlZCwgdGhpcyBnZXRzIHR1cm5lZCB0byBmYWxzZS5cbiAgICAgICAgICAgIHZhciBydW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHZhciBwZXJpb2RpY2FsbHlDaGVja1dpZHRoQW5kSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChydW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdXaWR0aCA9IG9mZnNldFdpZHRoKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SGVpZ2h0ID0gb2Zmc2V0SGVpZ2h0KGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hhbmdlZCA9IG5ld1dpZHRoICE9PSB3aWR0aExhc3RUaW1lIHx8IG5ld0hlaWdodCAhPT0gaGVpZ2h0TGFzdFRpbWU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aWR0aExhc3RUaW1lID0gbmV3V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHRMYXN0VGltZSA9IG5ld0hlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZG9OZXh0UG9seWZpbGxUdXJuKHBlcmlvZGljYWxseUNoZWNrV2lkdGhBbmRIZWlnaHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBwZXJpb2RpY2FsbHlDaGVja1dpZHRoQW5kSGVpZ2h0KCk7XG4gICAgICAgICAgICAvLyB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gd2UgcmV0dXJuIHNldHMgcnVubmluZyB0byBmYWxzZVxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHJ1bm5pbmcgPSBmYWxzZTsgfTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHN1cHByZXNzUmVzaXplID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0Jyb3dzZXJSZXNpemVPYnNlcnZlcigpO1xuICAgICAgICB2YXIgcmVzaXplT2JzZXJ2ZXJFeGlzdHMgPSAhIXdpbi5SZXNpemVPYnNlcnZlcjtcbiAgICAgICAgaWYgKHJlc2l6ZU9ic2VydmVyRXhpc3RzICYmICFzdXBwcmVzc1Jlc2l6ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHVzZUJyb3dzZXJSZXNpemVPYnNlcnZlcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1c2VQb2x5ZmlsbCgpO1xuICAgIH07XG4gICAgUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlLnByb3RvdHlwZS5kb05leHRQb2x5ZmlsbFR1cm4gPSBmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICB0aGlzLnBvbHlmaWxsRnVuY3Rpb25zLnB1c2goZnVuYyk7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVQb2x5ZmlsbCgpO1xuICAgIH07XG4gICAgUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlLnByb3RvdHlwZS5zY2hlZHVsZVBvbHlmaWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5wb2x5ZmlsbFNjaGVkdWxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBleGVjdXRlQWxsRnVuY3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZnVuY3MgPSBfdGhpcy5wb2x5ZmlsbEZ1bmN0aW9ucztcbiAgICAgICAgICAgIC8vIG1ha2Ugc3VyZSBzZXQgc2NoZWR1bGVkIHRvIGZhbHNlIGFuZCBjbGVhciBjbGVhciBhcnJheVxuICAgICAgICAgICAgLy8gYmVmb3JlIGV4ZWN1dGluZyB0aGUgZnVuY3MsIGFzIHRoZSBmdW5jcyBjb3VsZCBhZGQgbW9yZSBmdW5jc1xuICAgICAgICAgICAgX3RoaXMucG9seWZpbGxTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIF90aGlzLnBvbHlmaWxsRnVuY3Rpb25zID0gW107XG4gICAgICAgICAgICBmdW5jcy5mb3JFYWNoKGZ1bmN0aW9uIChmKSB7IHJldHVybiBmKCk7IH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnBvbHlmaWxsU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5nZXRGcmFtZXdvcmtPdmVycmlkZXMoKS5zZXRUaW1lb3V0KGV4ZWN1dGVBbGxGdW5jcywgREVCT1VOQ0VfREVMQVkpO1xuICAgIH07XG4gICAgUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlID0gX19kZWNvcmF0ZSQxOChbXG4gICAgICAgIEJlYW4oJ3Jlc2l6ZU9ic2VydmVyU2VydmljZScpXG4gICAgXSwgUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlKTtcbiAgICByZXR1cm4gUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFlID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxNyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEFuaW1hdGlvbkZyYW1lU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMWUoQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFuaW1hdGlvbkZyYW1lU2VydmljZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIC8vIHAxIGFuZCBwMiBhcmUgY3JlYXRlIHRhc2tzIGFyZSB0byBkbyB3aXRoIHJvdyBhbmQgY2VsbCBjcmVhdGlvbi5cbiAgICAgICAgLy8gZm9yIHRoZW0gd2Ugd2FudCB0byBleGVjdXRlIGFjY29yZGluZyB0byByb3cgb3JkZXIsIHNvIHdlIHVzZVxuICAgICAgICAvLyBUYXNrSXRlbSBzbyB3ZSBrbm93IHdoYXQgaW5kZXggdGhlIGl0ZW0gaXMgZm9yLlxuICAgICAgICBfdGhpcy5jcmVhdGVUYXNrc1AxID0geyBsaXN0OiBbXSwgc29ydGVkOiBmYWxzZSB9OyAvLyBlZyBkcmF3aW5nIGJhY2stZ3JvdW5kIG9mIHJvd3NcbiAgICAgICAgX3RoaXMuY3JlYXRlVGFza3NQMiA9IHsgbGlzdDogW10sIHNvcnRlZDogZmFsc2UgfTsgLy8gZWcgY2VsbCByZW5kZXJlcnMsIGFkZGluZyBob3ZlciBmdW5jdGlvbmFsaXR5XG4gICAgICAgIC8vIGRlc3Ryb3kgdGFza3MgYXJlIHRvIGRvIHdpdGggcm93IHJlbW92YWwuIHRoZXkgYXJlIGRvbmUgYWZ0ZXIgcm93IGNyZWF0aW9uIGFzIHRoZSB1c2VyIHdpbGwgbmVlZCB0byBzZWUgbmV3XG4gICAgICAgIC8vIHJvd3MgZmlyc3QgKGFzIGJsYW5rIGlzIHNjcm9sbGVkIGludG8gdmlldyksIHdoZW4gd2UgcmVtb3ZlIHRoZSBvbGQgcm93cyAobm8gbG9uZ2VyIGluIHZpZXcpIGlzIG5vdCBhc1xuICAgICAgICAvLyBpbXBvcnRhbnQuXG4gICAgICAgIF90aGlzLmRlc3Ryb3lUYXNrcyA9IFtdO1xuICAgICAgICBfdGhpcy50aWNraW5nID0gZmFsc2U7XG4gICAgICAgIC8vIHdlIG5lZWQgdG8ga25vdyBkaXJlY3Rpb24gb2Ygc2Nyb2xsLCB0byBidWlsZCB1cCByb3dzIGluIHRoZSBkaXJlY3Rpb24gb2ZcbiAgICAgICAgLy8gdGhlIHNjcm9sbC4gZWcgaWYgdXNlciBzY3JvbGxzIGRvd24sIHdlIGV4dGVuZCB0aGUgcm93cyBieSBidWlsZGluZyBkb3duLlxuICAgICAgICBfdGhpcy5zY3JvbGxHb2luZ0Rvd24gPSB0cnVlO1xuICAgICAgICBfdGhpcy5sYXN0U2Nyb2xsVG9wID0gMDtcbiAgICAgICAgX3RoaXMudGFza0NvdW50ID0gMDtcbiAgICAgICAgX3RoaXMuY2FuY2VsbGVkVGFza3MgPSBuZXcgU2V0KCk7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnByb3RvdHlwZS5zZXRTY3JvbGxUb3AgPSBmdW5jdGlvbiAoc2Nyb2xsVG9wKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsR29pbmdEb3duID0gc2Nyb2xsVG9wID4gdGhpcy5sYXN0U2Nyb2xsVG9wO1xuICAgICAgICB0aGlzLmxhc3RTY3JvbGxUb3AgPSBzY3JvbGxUb3A7XG4gICAgfTtcbiAgICBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudXNlQW5pbWF0aW9uRnJhbWUgPSAhdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0FuaW1hdGlvbkZyYW1lKCk7XG4gICAgfTtcbiAgICBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLmlzT24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVzZUFuaW1hdGlvbkZyYW1lO1xuICAgIH07XG4gICAgLy8gdGhpcyBtZXRob2QgaXMgZm9yIG91ciBBRyBHcmlkIHNhbml0eSBvbmx5IC0gaWYgYW5pbWF0aW9uIGZyYW1lcyBhcmUgdHVybmVkIG9mZixcbiAgICAvLyB0aGVuIG5vIHBsYWNlIGluIHRoZSBjb2RlIHNob3VsZCBiZSBsb29raW5nIHRvIGFkZCBhbnkgd29yayB0byBiZSBkb25lIGluIGFuaW1hdGlvblxuICAgIC8vIGZyYW1lcy4gdGhpcyBzdG9wcyBidWdzIC0gd2hlcmUgc29tZSBjb2RlIGlzIGFza2luZyBmb3IgYSBmcmFtZSB0byBiZSBleGVjdXRlZFxuICAgIC8vIHdoZW4gaXQgc2hvdWxkIG5vdC5cbiAgICBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLnZlcmlmeUFuaW1hdGlvbkZyYW1lT24gPSBmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xuICAgICAgICBpZiAodGhpcy51c2VBbmltYXRpb25GcmFtZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IEFuaW1hdGlvbkZyYW1lU2VydmljZS5cIiArIG1ldGhvZE5hbWUgKyBcIiBjYWxsZWQgYnV0IGFuaW1hdGlvbiBmcmFtZXMgYXJlIG9mZlwiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnByb3RvdHlwZS5jcmVhdGVUYXNrID0gZnVuY3Rpb24gKHRhc2ssIGluZGV4LCBsaXN0KSB7XG4gICAgICAgIHRoaXMudmVyaWZ5QW5pbWF0aW9uRnJhbWVPbihsaXN0KTtcbiAgICAgICAgdmFyIHRhc2tJdGVtID0geyB0YXNrOiB0YXNrLCBpbmRleDogaW5kZXgsIGNyZWF0ZU9yZGVyOiArK3RoaXMudGFza0NvdW50IH07XG4gICAgICAgIHRoaXMuYWRkVGFza1RvTGlzdCh0aGlzW2xpc3RdLCB0YXNrSXRlbSk7XG4gICAgICAgIHRoaXMuc2NoZWR1bGUoKTtcbiAgICB9O1xuICAgIEFuaW1hdGlvbkZyYW1lU2VydmljZS5wcm90b3R5cGUuY2FuY2VsVGFzayA9IGZ1bmN0aW9uICh0YXNrKSB7XG4gICAgICAgIHRoaXMuY2FuY2VsbGVkVGFza3MuYWRkKHRhc2spO1xuICAgIH07XG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnByb3RvdHlwZS5hZGRUYXNrVG9MaXN0ID0gZnVuY3Rpb24gKHRhc2tMaXN0LCB0YXNrKSB7XG4gICAgICAgIHRhc2tMaXN0Lmxpc3QucHVzaCh0YXNrKTtcbiAgICAgICAgdGFza0xpc3Quc29ydGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLnNvcnRUYXNrTGlzdCA9IGZ1bmN0aW9uICh0YXNrTGlzdCkge1xuICAgICAgICBpZiAodGFza0xpc3Quc29ydGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNvcnREaXJlY3Rpb24gPSB0aGlzLnNjcm9sbEdvaW5nRG93biA/IDEgOiAtMTtcbiAgICAgICAgLy8gc29ydCBmaXJzdCBieSByb3cgaW5kZXggKHRha2luZyBpbnRvIGFjY291bnQgc2Nyb2xsIGRpcmVjdGlvbiksIHRoZW4gYnlcbiAgICAgICAgLy8gb3JkZXIgb2YgdGFzayBjcmVhdGlvbiAoYWx3YXlzIGFzY2VuZGluZywgc28gY2VsbHMgd2lsbCByZW5kZXIgbGVmdC10by1yaWdodClcbiAgICAgICAgdGFza0xpc3QubGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLmluZGV4ICE9PSBiLmluZGV4ID8gc29ydERpcmVjdGlvbiAqIChiLmluZGV4IC0gYS5pbmRleCkgOiBiLmNyZWF0ZU9yZGVyIC0gYS5jcmVhdGVPcmRlcjsgfSk7XG4gICAgICAgIHRhc2tMaXN0LnNvcnRlZCA9IHRydWU7XG4gICAgfTtcbiAgICBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLmFkZERlc3Ryb3lUYXNrID0gZnVuY3Rpb24gKHRhc2spIHtcbiAgICAgICAgdGhpcy52ZXJpZnlBbmltYXRpb25GcmFtZU9uKCdjcmVhdGVUYXNrc1AzJyk7XG4gICAgICAgIHRoaXMuZGVzdHJveVRhc2tzLnB1c2godGFzayk7XG4gICAgICAgIHRoaXMuc2NoZWR1bGUoKTtcbiAgICB9O1xuICAgIEFuaW1hdGlvbkZyYW1lU2VydmljZS5wcm90b3R5cGUuZXhlY3V0ZUZyYW1lID0gZnVuY3Rpb24gKG1pbGxpcykge1xuICAgICAgICB0aGlzLnZlcmlmeUFuaW1hdGlvbkZyYW1lT24oJ2V4ZWN1dGVGcmFtZScpO1xuICAgICAgICB2YXIgcDFUYXNrTGlzdCA9IHRoaXMuY3JlYXRlVGFza3NQMTtcbiAgICAgICAgdmFyIHAxVGFza3MgPSBwMVRhc2tMaXN0Lmxpc3Q7XG4gICAgICAgIHZhciBwMlRhc2tMaXN0ID0gdGhpcy5jcmVhdGVUYXNrc1AyO1xuICAgICAgICB2YXIgcDJUYXNrcyA9IHAyVGFza0xpc3QubGlzdDtcbiAgICAgICAgdmFyIGRlc3Ryb3lUYXNrcyA9IHRoaXMuZGVzdHJveVRhc2tzO1xuICAgICAgICB2YXIgZnJhbWVTdGFydCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICB2YXIgZHVyYXRpb24gPSAobmV3IERhdGUoKS5nZXRUaW1lKCkpIC0gZnJhbWVTdGFydDtcbiAgICAgICAgLy8gMTZtcyBpcyA2MCBmcHNcbiAgICAgICAgdmFyIG5vTWF4TWlsbGlzID0gbWlsbGlzIDw9IDA7XG4gICAgICAgIHZhciBncmlkQm9keUNvbiA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRCb2R5Q3RybCgpO1xuICAgICAgICB3aGlsZSAobm9NYXhNaWxsaXMgfHwgZHVyYXRpb24gPCBtaWxsaXMpIHtcbiAgICAgICAgICAgIHZhciBncmlkQm9keURpZFNvbWV0aGluZyA9IGdyaWRCb2R5Q29uLmdldFNjcm9sbEZlYXR1cmUoKS5leGVjdXRlQW5pbWF0aW9uRnJhbWVTY3JvbGwoKTtcbiAgICAgICAgICAgIGlmICghZ3JpZEJvZHlEaWRTb21ldGhpbmcpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFzayA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICBpZiAocDFUYXNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zb3J0VGFza0xpc3QocDFUYXNrTGlzdCk7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sgPSBwMVRhc2tzLnBvcCgpLnRhc2s7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHAyVGFza3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc29ydFRhc2tMaXN0KHAyVGFza0xpc3QpO1xuICAgICAgICAgICAgICAgICAgICB0YXNrID0gcDJUYXNrcy5wb3AoKS50YXNrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkZXN0cm95VGFza3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2sgPSBkZXN0cm95VGFza3MucG9wKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbmNlbGxlZFRhc2tzLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FuY2VsbGVkVGFza3MuaGFzKHRhc2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkdXJhdGlvbiA9IChuZXcgRGF0ZSgpLmdldFRpbWUoKSkgLSBmcmFtZVN0YXJ0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChwMVRhc2tzLmxlbmd0aCB8fCBwMlRhc2tzLmxlbmd0aCB8fCBkZXN0cm95VGFza3MubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLnJlcXVlc3RGcmFtZSgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdG9wVGlja2luZygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLnN0b3BUaWNraW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRpY2tpbmcgPSBmYWxzZTtcbiAgICB9O1xuICAgIEFuaW1hdGlvbkZyYW1lU2VydmljZS5wcm90b3R5cGUuZmx1c2hBbGxGcmFtZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy51c2VBbmltYXRpb25GcmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXhlY3V0ZUZyYW1lKC0xKTtcbiAgICB9O1xuICAgIEFuaW1hdGlvbkZyYW1lU2VydmljZS5wcm90b3R5cGUuc2NoZWR1bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy51c2VBbmltYXRpb25GcmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy50aWNraW5nKSB7XG4gICAgICAgICAgICB0aGlzLnRpY2tpbmcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0RnJhbWUoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnByb3RvdHlwZS5yZXF1ZXN0RnJhbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGNoZWNrIGZvciB0aGUgZXhpc3RlbmNlIG9mIHJlcXVlc3RBbmltYXRpb25GcmFtZSwgYW5kIGlmXG4gICAgICAgIC8vIGl0J3MgbWlzc2luZywgdGhlbiB3ZSBwb2x5ZmlsbCBpdCB3aXRoIHNldFRpbWVvdXQoKVxuICAgICAgICB2YXIgY2FsbGJhY2sgPSB0aGlzLmV4ZWN1dGVGcmFtZS5iaW5kKHRoaXMsIDYwKTtcbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIHZhciB3aW4gPSAoZURvY3VtZW50LmRlZmF1bHRWaWV3IHx8IHdpbmRvdyk7XG4gICAgICAgIGlmICh3aW4ucmVxdWVzdEFuaW1hdGlvbkZyYW1lKSB7XG4gICAgICAgICAgICB3aW4ucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh3aW4ud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lKSB7XG4gICAgICAgICAgICB3aW4ud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lKGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHdpbi5zZXRUaW1lb3V0KGNhbGxiYWNrLCAwKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnByb3RvdHlwZS5pc1F1ZXVlRW1wdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAhdGhpcy50aWNraW5nO1xuICAgIH07XG4gICAgLy8gYSBkZWJvdW5jZSB1dGlsaXR5IHVzZWQgZm9yIHBhcnRzIG9mIHRoZSBhcHAgaW52b2x2ZWQgd2l0aCByZW5kZXJpbmcuXG4gICAgLy8gdGhlIGFkdmFudGFnZSBvdmVyIG5vcm1hbCBkZWJvdW5jZSBpcyB0aGUgY2xpZW50IGNhbiBjYWxsIGZsdXNoQWxsRnJhbWVzKClcbiAgICAvLyB0byBtYWtlIHN1cmUgYWxsIHJlbmRlcmluZyBpcyBjb21wbGV0ZS4gd2UgZG9uJ3Qgd2FpdCBhbnkgbWlsbGlzZWNvbmRzLFxuICAgIC8vIGFzIHRoaXMgaXMgaW50ZW5kZWQgdG8gYmF0Y2ggY2FsbHMgaW4gb25lIFZNIHR1cm4uXG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlLnByb3RvdHlwZS5kZWJvdW5jZSA9IGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwZW5kaW5nID0gZmFsc2U7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmlzT24oKSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmdldEZyYW1ld29ya092ZXJyaWRlcygpLnNldFRpbWVvdXQoZnVuYywgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwZW5kaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIF90aGlzLmFkZERlc3Ryb3lUYXNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBwZW5kaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZnVuYygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDE3KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEFuaW1hdGlvbkZyYW1lU2VydmljZS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxNyhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBbmltYXRpb25GcmFtZVNlcnZpY2UucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlID0gX19kZWNvcmF0ZSQxNyhbXG4gICAgICAgIEJlYW4oJ2FuaW1hdGlvbkZyYW1lU2VydmljZScpXG4gICAgXSwgQW5pbWF0aW9uRnJhbWVTZXJ2aWNlKTtcbiAgICByZXR1cm4gQW5pbWF0aW9uRnJhbWVTZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDFkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxNiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFJFU0laRV9DT05UQUlORVJfU1RZTEUgPSAnYWctcmVzaXplci13cmFwcGVyJztcbnZhciBSRVNJWkVfVEVNUExBVEUgPSAvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiXCIgKyBSRVNJWkVfQ09OVEFJTkVSX1NUWUxFICsgXCJcXFwiPlxcbiAgICAgICAgPGRpdiByZWY9XFxcImVUb3BMZWZ0UmVzaXplclxcXCIgY2xhc3M9XFxcImFnLXJlc2l6ZXIgYWctcmVzaXplci10b3BMZWZ0XFxcIj48L2Rpdj5cXG4gICAgICAgIDxkaXYgcmVmPVxcXCJlVG9wUmVzaXplclxcXCIgY2xhc3M9XFxcImFnLXJlc2l6ZXIgYWctcmVzaXplci10b3BcXFwiPjwvZGl2PlxcbiAgICAgICAgPGRpdiByZWY9XFxcImVUb3BSaWdodFJlc2l6ZXJcXFwiIGNsYXNzPVxcXCJhZy1yZXNpemVyIGFnLXJlc2l6ZXItdG9wUmlnaHRcXFwiPjwvZGl2PlxcbiAgICAgICAgPGRpdiByZWY9XFxcImVSaWdodFJlc2l6ZXJcXFwiIGNsYXNzPVxcXCJhZy1yZXNpemVyIGFnLXJlc2l6ZXItcmlnaHRcXFwiPjwvZGl2PlxcbiAgICAgICAgPGRpdiByZWY9XFxcImVCb3R0b21SaWdodFJlc2l6ZXJcXFwiIGNsYXNzPVxcXCJhZy1yZXNpemVyIGFnLXJlc2l6ZXItYm90dG9tUmlnaHRcXFwiPjwvZGl2PlxcbiAgICAgICAgPGRpdiByZWY9XFxcImVCb3R0b21SZXNpemVyXFxcIiBjbGFzcz1cXFwiYWctcmVzaXplciBhZy1yZXNpemVyLWJvdHRvbVxcXCI+PC9kaXY+XFxuICAgICAgICA8ZGl2IHJlZj1cXFwiZUJvdHRvbUxlZnRSZXNpemVyXFxcIiBjbGFzcz1cXFwiYWctcmVzaXplciBhZy1yZXNpemVyLWJvdHRvbUxlZnRcXFwiPjwvZGl2PlxcbiAgICAgICAgPGRpdiByZWY9XFxcImVMZWZ0UmVzaXplclxcXCIgY2xhc3M9XFxcImFnLXJlc2l6ZXIgYWctcmVzaXplci1sZWZ0XFxcIj48L2Rpdj5cXG4gICAgPC9kaXY+XCI7XG52YXIgUG9zaXRpb25hYmxlRmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMWQoUG9zaXRpb25hYmxlRmVhdHVyZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBQb3NpdGlvbmFibGVGZWF0dXJlKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgX3RoaXMuZHJhZ1N0YXJ0UG9zaXRpb24gPSB7XG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMFxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5wb3NpdGlvbiA9IHtcbiAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICB5OiAwXG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmxhc3RTaXplID0ge1xuICAgICAgICAgICAgd2lkdGg6IC0xLFxuICAgICAgICAgICAgaGVpZ2h0OiAtMVxuICAgICAgICB9O1xuICAgICAgICBfdGhpcy5wb3NpdGlvbmVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnJlc2l6ZXJzQWRkZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMucmVzaXplTGlzdGVuZXJzID0gW107XG4gICAgICAgIF90aGlzLmJvdW5kYXJ5RWwgPSBudWxsO1xuICAgICAgICBfdGhpcy5pc1Jlc2l6aW5nID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmlzTW92aW5nID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnJlc2l6YWJsZSA9IHt9O1xuICAgICAgICBfdGhpcy5tb3ZhYmxlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmN1cnJlbnRSZXNpemVyID0gbnVsbDtcbiAgICAgICAgX3RoaXMuY29uZmlnID0gT2JqZWN0LmFzc2lnbih7fSwgeyBwb3B1cDogZmFsc2UgfSwgY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5jZW50ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMub2Zmc2V0UGFyZW50LCBjbGllbnRIZWlnaHQgPSBfYS5jbGllbnRIZWlnaHQsIGNsaWVudFdpZHRoID0gX2EuY2xpZW50V2lkdGg7XG4gICAgICAgIHZhciB4ID0gKGNsaWVudFdpZHRoIC8gMikgLSAodGhpcy5nZXRXaWR0aCgpIC8gMik7XG4gICAgICAgIHZhciB5ID0gKGNsaWVudEhlaWdodCAvIDIpIC0gKHRoaXMuZ2V0SGVpZ2h0KCkgLyAyKTtcbiAgICAgICAgdGhpcy5vZmZzZXRFbGVtZW50KHgsIHkpO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuaW5pdGlhbGlzZVBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbmZpZywgY2VudGVyZWQgPSBfYS5jZW50ZXJlZCwgZm9yY2VQb3B1cFBhcmVudEFzT2Zmc2V0UGFyZW50ID0gX2EuZm9yY2VQb3B1cFBhcmVudEFzT2Zmc2V0UGFyZW50LCBtaW5XaWR0aCA9IF9hLm1pbldpZHRoLCB3aWR0aCA9IF9hLndpZHRoLCBtaW5IZWlnaHQgPSBfYS5taW5IZWlnaHQsIGhlaWdodCA9IF9hLmhlaWdodCwgeCA9IF9hLngsIHkgPSBfYS55O1xuICAgICAgICBpZiAoIXRoaXMub2Zmc2V0UGFyZW50KSB7XG4gICAgICAgICAgICB0aGlzLnNldE9mZnNldFBhcmVudCgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb21wdXRlZE1pbkhlaWdodCA9IDA7XG4gICAgICAgIHZhciBjb21wdXRlZE1pbldpZHRoID0gMDtcbiAgICAgICAgLy8gaGVyZSB3ZSBkb24ndCB1c2UgdGhlIG1haW4gb2Zmc2V0IHBhcmVudCBidXQgdGhlIGVsZW1lbnQncyBvZmZzZXRQYXJlbnRcbiAgICAgICAgLy8gaW4gb3JkZXIgdG8gY2FsY3VsYXRlZCB0aGUgbWluV2lkdGggYW5kIG1pbkhlaWdodCBjb3JyZWN0bHlcbiAgICAgICAgdmFyIGlzVmlzaWJsZSA9ICEhdGhpcy5lbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgICAgICAgaWYgKGlzVmlzaWJsZSkge1xuICAgICAgICAgICAgdmFyIGJvdW5kYXJ5RWwgPSB0aGlzLmZpbmRCb3VuZGFyeUVsZW1lbnQoKTtcbiAgICAgICAgICAgIHZhciBvZmZzZXRQYXJlbnRDb21wdXRlZFN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGJvdW5kYXJ5RWwpO1xuICAgICAgICAgICAgaWYgKG9mZnNldFBhcmVudENvbXB1dGVkU3R5bGVzLm1pbldpZHRoICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFkZGluZ1dpZHRoID0gYm91bmRhcnlFbC5vZmZzZXRXaWR0aCAtIHRoaXMuZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgICAgICBjb21wdXRlZE1pbldpZHRoID0gcGFyc2VJbnQob2Zmc2V0UGFyZW50Q29tcHV0ZWRTdHlsZXMubWluV2lkdGgsIDEwKSAtIHBhZGRpbmdXaWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvZmZzZXRQYXJlbnRDb21wdXRlZFN0eWxlcy5taW5IZWlnaHQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHZhciBwYWRkaW5nSGVpZ2h0ID0gYm91bmRhcnlFbC5vZmZzZXRIZWlnaHQgLSB0aGlzLmVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICAgICAgICAgIGNvbXB1dGVkTWluSGVpZ2h0ID0gcGFyc2VJbnQob2Zmc2V0UGFyZW50Q29tcHV0ZWRTdHlsZXMubWluSGVpZ2h0LCAxMCkgLSBwYWRkaW5nSGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubWluSGVpZ2h0ID0gbWluSGVpZ2h0IHx8IGNvbXB1dGVkTWluSGVpZ2h0O1xuICAgICAgICB0aGlzLm1pbldpZHRoID0gbWluV2lkdGggfHwgY29tcHV0ZWRNaW5XaWR0aDtcbiAgICAgICAgaWYgKHdpZHRoKSB7XG4gICAgICAgICAgICB0aGlzLnNldFdpZHRoKHdpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLnNldEhlaWdodChoZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghd2lkdGggfHwgIWhlaWdodCkge1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoU2l6ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjZW50ZXJlZCkge1xuICAgICAgICAgICAgdGhpcy5jZW50ZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh4IHx8IHkpIHtcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0RWxlbWVudCh4LCB5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc1Zpc2libGUgJiYgZm9yY2VQb3B1cFBhcmVudEFzT2Zmc2V0UGFyZW50ICYmIHRoaXMuYm91bmRhcnlFbCkge1xuICAgICAgICAgICAgdmFyIHRvcF8xID0gcGFyc2VGbG9hdCh0aGlzLmJvdW5kYXJ5RWwuc3R5bGUudG9wKTtcbiAgICAgICAgICAgIHZhciBsZWZ0ID0gcGFyc2VGbG9hdCh0aGlzLmJvdW5kYXJ5RWwuc3R5bGUubGVmdCk7XG4gICAgICAgICAgICB0aGlzLm9mZnNldEVsZW1lbnQoaXNOYU4obGVmdCkgPyAwIDogbGVmdCwgaXNOYU4odG9wXzEpID8gMCA6IHRvcF8xKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBvc2l0aW9uZWQgPSAhIXRoaXMub2Zmc2V0UGFyZW50O1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuaXNQb3NpdGlvbmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbmVkO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuZ2V0UG9zaXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuc2V0TW92YWJsZSA9IGZ1bmN0aW9uIChtb3ZhYmxlLCBtb3ZlRWxlbWVudCkge1xuICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnBvcHVwIHx8IG1vdmFibGUgPT09IHRoaXMubW92YWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubW92YWJsZSA9IG1vdmFibGU7XG4gICAgICAgIHZhciBwYXJhbXMgPSB0aGlzLm1vdmVFbGVtZW50RHJhZ0xpc3RlbmVyIHx8IHtcbiAgICAgICAgICAgIGVFbGVtZW50OiBtb3ZlRWxlbWVudCxcbiAgICAgICAgICAgIG9uRHJhZ1N0YXJ0OiB0aGlzLm9uTW92ZVN0YXJ0LmJpbmQodGhpcyksXG4gICAgICAgICAgICBvbkRyYWdnaW5nOiB0aGlzLm9uTW92ZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgb25EcmFnU3RvcDogdGhpcy5vbk1vdmVFbmQuYmluZCh0aGlzKVxuICAgICAgICB9O1xuICAgICAgICBpZiAobW92YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5kcmFnU2VydmljZS5hZGREcmFnU291cmNlKHBhcmFtcyk7XG4gICAgICAgICAgICB0aGlzLm1vdmVFbGVtZW50RHJhZ0xpc3RlbmVyID0gcGFyYW1zO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kcmFnU2VydmljZS5yZW1vdmVEcmFnU291cmNlKHBhcmFtcyk7XG4gICAgICAgICAgICB0aGlzLm1vdmVFbGVtZW50RHJhZ0xpc3RlbmVyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5zZXRSZXNpemFibGUgPSBmdW5jdGlvbiAocmVzaXphYmxlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY2xlYXJSZXNpemVMaXN0ZW5lcnMoKTtcbiAgICAgICAgaWYgKHJlc2l6YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5hZGRSZXNpemVycygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVSZXNpemVycygpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcmVzaXphYmxlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIGlmIChyZXNpemFibGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzaXphYmxlID0ge1xuICAgICAgICAgICAgICAgIHRvcExlZnQ6IHJlc2l6YWJsZSxcbiAgICAgICAgICAgICAgICB0b3A6IHJlc2l6YWJsZSxcbiAgICAgICAgICAgICAgICB0b3BSaWdodDogcmVzaXphYmxlLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiByZXNpemFibGUsXG4gICAgICAgICAgICAgICAgYm90dG9tUmlnaHQ6IHJlc2l6YWJsZSxcbiAgICAgICAgICAgICAgICBib3R0b206IHJlc2l6YWJsZSxcbiAgICAgICAgICAgICAgICBib3R0b21MZWZ0OiByZXNpemFibGUsXG4gICAgICAgICAgICAgICAgbGVmdDogcmVzaXphYmxlXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIE9iamVjdC5rZXlzKHJlc2l6YWJsZSkuZm9yRWFjaChmdW5jdGlvbiAoc2lkZSkge1xuICAgICAgICAgICAgdmFyIHJlc2l6YWJsZVN0cnVjdHVyZSA9IHJlc2l6YWJsZTtcbiAgICAgICAgICAgIHZhciB2YWwgPSAhIXJlc2l6YWJsZVN0cnVjdHVyZVtzaWRlXTtcbiAgICAgICAgICAgIHZhciByZXNpemVyRWwgPSBfdGhpcy5nZXRSZXNpemVyRWxlbWVudChzaWRlKTtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgZHJhZ1N0YXJ0UGl4ZWxzOiAwLFxuICAgICAgICAgICAgICAgIGVFbGVtZW50OiByZXNpemVyRWwsXG4gICAgICAgICAgICAgICAgb25EcmFnU3RhcnQ6IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblJlc2l6ZVN0YXJ0KGUsIHNpZGUpOyB9LFxuICAgICAgICAgICAgICAgIG9uRHJhZ2dpbmc6IF90aGlzLm9uUmVzaXplLmJpbmQoX3RoaXMpLFxuICAgICAgICAgICAgICAgIG9uRHJhZ1N0b3A6IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblJlc2l6ZUVuZChlLCBzaWRlKTsgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoISFfdGhpcy5yZXNpemFibGVbc2lkZV0gIT09IHZhbCB8fCAoIV90aGlzLmlzQWxpdmUoKSAmJiAhdmFsKSkge1xuICAgICAgICAgICAgICAgIGlmICh2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZHJhZ1NlcnZpY2UuYWRkRHJhZ1NvdXJjZShwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5yZXNpemVMaXN0ZW5lcnMucHVzaChwYXJhbXMpO1xuICAgICAgICAgICAgICAgICAgICByZXNpemVyRWwuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdhbGwnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzaXplckVsLnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFBvc2l0aW9uYWJsZUZlYXR1cmUucHJvdG90eXBlLnJlbW92ZVNpemVGcm9tRWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnaGVpZ2h0Jyk7XG4gICAgICAgIHRoaXMuZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnd2lkdGgnKTtcbiAgICAgICAgdGhpcy5lbGVtZW50LnN0eWxlLnJlbW92ZVByb3BlcnR5KCdmbGV4Jyk7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5yZXN0b3JlTGFzdFNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudC5zdHlsZS5mbGV4ID0gJzAgMCBhdXRvJztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5sYXN0U2l6ZSwgaGVpZ2h0ID0gX2EuaGVpZ2h0LCB3aWR0aCA9IF9hLndpZHRoO1xuICAgICAgICBpZiAod2lkdGggIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLmVsZW1lbnQuc3R5bGUud2lkdGggPSB3aWR0aCArIFwicHhcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGVpZ2h0ICE9PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50LnN0eWxlLmhlaWdodCA9IGhlaWdodCArIFwicHhcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuZ2V0SGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICB9O1xuICAgIFBvc2l0aW9uYWJsZUZlYXR1cmUucHJvdG90eXBlLnNldEhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgdmFyIHBvcHVwID0gdGhpcy5jb25maWcucG9wdXA7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5lbGVtZW50O1xuICAgICAgICB2YXIgaXNQZXJjZW50ID0gZmFsc2U7XG4gICAgICAgIGlmICh0eXBlb2YgaGVpZ2h0ID09PSAnc3RyaW5nJyAmJiBoZWlnaHQuaW5kZXhPZignJScpICE9PSAtMSkge1xuICAgICAgICAgICAgc2V0Rml4ZWRIZWlnaHQoZUd1aSwgaGVpZ2h0KTtcbiAgICAgICAgICAgIGhlaWdodCA9IGdldEFic29sdXRlSGVpZ2h0KGVHdWkpO1xuICAgICAgICAgICAgaXNQZXJjZW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnBvc2l0aW9uZWQpIHtcbiAgICAgICAgICAgIHZhciBlbFJlY3QgPSB0aGlzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB2YXIgcGFyZW50UmVjdCA9IHRoaXMub2Zmc2V0UGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgaGVpZ2h0ID0gTWF0aC5tYXgodGhpcy5taW5IZWlnaHQsIGhlaWdodCk7XG4gICAgICAgICAgICB2YXIgY2xpZW50SGVpZ2h0ID0gdGhpcy5vZmZzZXRQYXJlbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICAgICAgdmFyIHlQb3NpdGlvbiA9IHBvcHVwID8gdGhpcy5wb3NpdGlvbi55IDogZWxSZWN0LnRvcDtcbiAgICAgICAgICAgIHZhciBwYXJlbnRUb3AgPSBwb3B1cCA/IDAgOiBwYXJlbnRSZWN0LnRvcDtcbiAgICAgICAgICAgIGlmIChjbGllbnRIZWlnaHQgJiYgKGhlaWdodCArIHlQb3NpdGlvbiA+IGNsaWVudEhlaWdodCArIHBhcmVudFRvcCkpIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSBjbGllbnRIZWlnaHQgLSB5UG9zaXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZ2V0SGVpZ2h0KCkgPT09IGhlaWdodCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNQZXJjZW50KSB7XG4gICAgICAgICAgICBpZiAocG9wdXApIHtcbiAgICAgICAgICAgICAgICBzZXRGaXhlZEhlaWdodChlR3VpLCBoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZUd1aS5zdHlsZS5oZWlnaHQgPSBoZWlnaHQgKyBcInB4XCI7XG4gICAgICAgICAgICAgICAgZUd1aS5zdHlsZS5mbGV4ID0gJzAgMCBhdXRvJztcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RTaXplLmhlaWdodCA9IHR5cGVvZiBoZWlnaHQgPT09ICdudW1iZXInID8gaGVpZ2h0IDogcGFyc2VGbG9hdChoZWlnaHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZUd1aS5zdHlsZS5tYXhIZWlnaHQgPSAndW5zZXQnO1xuICAgICAgICAgICAgZUd1aS5zdHlsZS5taW5IZWlnaHQgPSAndW5zZXQnO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5nZXRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICB9O1xuICAgIFBvc2l0aW9uYWJsZUZlYXR1cmUucHJvdG90eXBlLnNldFdpZHRoID0gZnVuY3Rpb24gKHdpZHRoKSB7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5lbGVtZW50O1xuICAgICAgICB2YXIgcG9wdXAgPSB0aGlzLmNvbmZpZy5wb3B1cDtcbiAgICAgICAgdmFyIGlzUGVyY2VudCA9IGZhbHNlO1xuICAgICAgICBpZiAodHlwZW9mIHdpZHRoID09PSAnc3RyaW5nJyAmJiB3aWR0aC5pbmRleE9mKCclJykgIT09IC0xKSB7XG4gICAgICAgICAgICBzZXRGaXhlZFdpZHRoKGVHdWksIHdpZHRoKTtcbiAgICAgICAgICAgIHdpZHRoID0gZ2V0QWJzb2x1dGVXaWR0aChlR3VpKTtcbiAgICAgICAgICAgIGlzUGVyY2VudCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5wb3NpdGlvbmVkKSB7XG4gICAgICAgICAgICB3aWR0aCA9IE1hdGgubWF4KHRoaXMubWluV2lkdGgsIHdpZHRoKTtcbiAgICAgICAgICAgIHZhciBjbGllbnRXaWR0aCA9IHRoaXMub2Zmc2V0UGFyZW50LmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgdmFyIHhQb3NpdGlvbiA9IHBvcHVwID8gdGhpcy5wb3NpdGlvbi54IDogdGhpcy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQ7XG4gICAgICAgICAgICBpZiAoY2xpZW50V2lkdGggJiYgKHdpZHRoICsgeFBvc2l0aW9uID4gY2xpZW50V2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgd2lkdGggPSBjbGllbnRXaWR0aCAtIHhQb3NpdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5nZXRXaWR0aCgpID09PSB3aWR0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNQZXJjZW50KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWcucG9wdXApIHtcbiAgICAgICAgICAgICAgICBzZXRGaXhlZFdpZHRoKGVHdWksIHdpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGVHdWkuc3R5bGUud2lkdGggPSB3aWR0aCArIFwicHhcIjtcbiAgICAgICAgICAgICAgICBlR3VpLnN0eWxlLmZsZXggPSAnIHVuc2V0JztcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RTaXplLndpZHRoID0gdHlwZW9mIHdpZHRoID09PSAnbnVtYmVyJyA/IHdpZHRoIDogcGFyc2VGbG9hdCh3aWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlR3VpLnN0eWxlLm1heFdpZHRoID0gJ3Vuc2V0JztcbiAgICAgICAgICAgIGVHdWkuc3R5bGUubWluV2lkdGggPSAndW5zZXQnO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5vZmZzZXRFbGVtZW50ID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgaWYgKHggPT09IHZvaWQgMCkgeyB4ID0gMDsgfVxuICAgICAgICBpZiAoeSA9PT0gdm9pZCAwKSB7IHkgPSAwOyB9XG4gICAgICAgIHZhciBlUG9wdXAgPSB0aGlzLmNvbmZpZy5mb3JjZVBvcHVwUGFyZW50QXNPZmZzZXRQYXJlbnQgPyB0aGlzLmJvdW5kYXJ5RWwgOiB0aGlzLmVsZW1lbnQ7XG4gICAgICAgIHRoaXMucG9wdXBTZXJ2aWNlLnBvc2l0aW9uUG9wdXAoe1xuICAgICAgICAgICAgZVBvcHVwOiBlUG9wdXAsXG4gICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgeTogeSxcbiAgICAgICAgICAgIGtlZXBXaXRoaW5Cb3VuZHM6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc2V0UG9zaXRpb24ocGFyc2VGbG9hdChlUG9wdXAuc3R5bGUubGVmdCksIHBhcnNlRmxvYXQoZVBvcHVwLnN0eWxlLnRvcCkpO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuc2V0UG9zaXRpb24gPSBmdW5jdGlvbiAoeCwgeSkge1xuICAgICAgICB0aGlzLnBvc2l0aW9uLnggPSB4O1xuICAgICAgICB0aGlzLnBvc2l0aW9uLnkgPSB5O1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUudXBkYXRlRHJhZ1N0YXJ0UG9zaXRpb24gPSBmdW5jdGlvbiAoeCwgeSkge1xuICAgICAgICB0aGlzLmRyYWdTdGFydFBvc2l0aW9uID0geyB4OiB4LCB5OiB5IH07XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5jYWxjdWxhdGVNb3VzZU1vdmVtZW50ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgZSA9IHBhcmFtcy5lLCBpc0xlZnQgPSBwYXJhbXMuaXNMZWZ0LCBpc1RvcCA9IHBhcmFtcy5pc1RvcCwgYW55d2hlcmVXaXRoaW4gPSBwYXJhbXMuYW55d2hlcmVXaXRoaW4sIHRvcEJ1ZmZlciA9IHBhcmFtcy50b3BCdWZmZXI7XG4gICAgICAgIHZhciB4RGlmZiA9IGUuY2xpZW50WCAtIHRoaXMuZHJhZ1N0YXJ0UG9zaXRpb24ueDtcbiAgICAgICAgdmFyIHlEaWZmID0gZS5jbGllbnRZIC0gdGhpcy5kcmFnU3RhcnRQb3NpdGlvbi55O1xuICAgICAgICB2YXIgbW92ZW1lbnRYID0gdGhpcy5zaG91bGRTa2lwWChlLCAhIWlzTGVmdCwgISFhbnl3aGVyZVdpdGhpbiwgeERpZmYpID8gMCA6IHhEaWZmO1xuICAgICAgICB2YXIgbW92ZW1lbnRZID0gdGhpcy5zaG91bGRTa2lwWShlLCAhIWlzVG9wLCB0b3BCdWZmZXIsIHlEaWZmKSA/IDAgOiB5RGlmZjtcbiAgICAgICAgcmV0dXJuIHsgbW92ZW1lbnRYOiBtb3ZlbWVudFgsIG1vdmVtZW50WTogbW92ZW1lbnRZIH07XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5zaG91bGRTa2lwWCA9IGZ1bmN0aW9uIChlLCBpc0xlZnQsIGFueXdoZXJlV2l0aGluLCBkaWZmKSB7XG4gICAgICAgIHZhciBlbFJlY3QgPSB0aGlzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBwYXJlbnRSZWN0ID0gdGhpcy5vZmZzZXRQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBib3VuZGFyeUVsUmVjdCA9IHRoaXMuYm91bmRhcnlFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIHhQb3NpdGlvbiA9IHRoaXMuY29uZmlnLnBvcHVwID8gdGhpcy5wb3NpdGlvbi54IDogZWxSZWN0LmxlZnQ7XG4gICAgICAgIC8vIHNraXAgaWYgY3Vyc29yIGlzIG91dHNpZGUgb2YgcG9wdXBQYXJlbnQgaG9yaXpvbnRhbGx5XG4gICAgICAgIHZhciBza2lwWCA9ICgoeFBvc2l0aW9uIDw9IDAgJiYgcGFyZW50UmVjdC5sZWZ0ID49IGUuY2xpZW50WCkgfHxcbiAgICAgICAgICAgIChwYXJlbnRSZWN0LnJpZ2h0IDw9IGUuY2xpZW50WCAmJiBwYXJlbnRSZWN0LnJpZ2h0IDw9IGJvdW5kYXJ5RWxSZWN0LnJpZ2h0KSk7XG4gICAgICAgIGlmIChza2lwWCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTGVmdCkge1xuICAgICAgICAgICAgc2tpcFggPSAoXG4gICAgICAgICAgICAvLyBza2lwIGlmIHdlIGFyZSBtb3ZpbmcgdG8gdGhlIGxlZnQgYW5kIHRoZSBjdXJzb3JcbiAgICAgICAgICAgIC8vIGlzIHBvc2l0aW9uZWQgdG8gdGhlIHJpZ2h0IG9mIHRoZSBsZWZ0IHNpZGUgYW5jaG9yXG4gICAgICAgICAgICAoZGlmZiA8IDAgJiYgZS5jbGllbnRYID4geFBvc2l0aW9uICsgcGFyZW50UmVjdC5sZWZ0KSB8fFxuICAgICAgICAgICAgICAgIC8vIHNraXAgaWYgd2UgYXJlIG1vdmluZyB0byB0aGUgcmlnaHQgYW5kIHRoZSBjdXJzb3JcbiAgICAgICAgICAgICAgICAvLyBpcyBwb3NpdGlvbmVkIHRvIHRoZSBsZWZ0IG9mIHRoZSBkaWFsb2dcbiAgICAgICAgICAgICAgICAoZGlmZiA+IDAgJiYgZS5jbGllbnRYIDwgeFBvc2l0aW9uICsgcGFyZW50UmVjdC5sZWZ0KSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoYW55d2hlcmVXaXRoaW4pIHtcbiAgICAgICAgICAgICAgICAvLyBpZiBhbnl3aGVyZVdpdGhpbiBpcyB0cnVlLCB3ZSBhbGxvdyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgLy8gYXMgbG9uZyBhcyB0aGUgY3Vyc29yIGlzIHdpdGhpbiB0aGUgZGlhbG9nXG4gICAgICAgICAgICAgICAgc2tpcFggPSAoKGRpZmYgPCAwICYmIGUuY2xpZW50WCA+IGJvdW5kYXJ5RWxSZWN0LnJpZ2h0KSB8fFxuICAgICAgICAgICAgICAgICAgICAoZGlmZiA+IDAgJiYgZS5jbGllbnRYIDwgeFBvc2l0aW9uICsgcGFyZW50UmVjdC5sZWZ0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBza2lwWCA9IChcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgbW92ZW1lbnQgaXMgYm91bmQgdG8gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIGRpYWxvZ1xuICAgICAgICAgICAgICAgIC8vIHdlIHNraXAgaWYgd2UgYXJlIG1vdmluZyB0byB0aGUgbGVmdCBhbmQgdGhlIGN1cnNvclxuICAgICAgICAgICAgICAgIC8vIGlzIHRvIHRoZSByaWdodCBvZiB0aGUgZGlhbG9nXG4gICAgICAgICAgICAgICAgKGRpZmYgPCAwICYmIGUuY2xpZW50WCA+IGJvdW5kYXJ5RWxSZWN0LnJpZ2h0KSB8fFxuICAgICAgICAgICAgICAgICAgICAvLyBvciBza2lwIGlmIHdlIGFyZSBtb3ZpbmcgdG8gdGhlIHJpZ2h0IGFuZCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgICAgIC8vIGlzIHRvIHRoZSBsZWZ0IG9mIHRoZSByaWdodCBzaWRlIGFuY2hvclxuICAgICAgICAgICAgICAgICAgICAoZGlmZiA+IDAgJiYgZS5jbGllbnRYIDwgYm91bmRhcnlFbFJlY3QucmlnaHQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2tpcFg7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5zaG91bGRTa2lwWSA9IGZ1bmN0aW9uIChlLCBpc1RvcCwgdG9wQnVmZmVyLCBkaWZmKSB7XG4gICAgICAgIGlmICh0b3BCdWZmZXIgPT09IHZvaWQgMCkgeyB0b3BCdWZmZXIgPSAwOyB9XG4gICAgICAgIHZhciBlbFJlY3QgPSB0aGlzLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBwYXJlbnRSZWN0ID0gdGhpcy5vZmZzZXRQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBib3VuZGFyeUVsUmVjdCA9IHRoaXMuYm91bmRhcnlFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIHlQb3NpdGlvbiA9IHRoaXMuY29uZmlnLnBvcHVwID8gdGhpcy5wb3NpdGlvbi55IDogZWxSZWN0LnRvcDtcbiAgICAgICAgLy8gc2tpcCBpZiBjdXJzb3IgaXMgb3V0c2lkZSBvZiBwb3B1cFBhcmVudCB2ZXJ0aWNhbGx5XG4gICAgICAgIHZhciBza2lwWSA9ICgoeVBvc2l0aW9uIDw9IDAgJiYgcGFyZW50UmVjdC50b3AgPj0gZS5jbGllbnRZKSB8fFxuICAgICAgICAgICAgKHBhcmVudFJlY3QuYm90dG9tIDw9IGUuY2xpZW50WSAmJiBwYXJlbnRSZWN0LmJvdHRvbSA8PSBib3VuZGFyeUVsUmVjdC5ib3R0b20pKTtcbiAgICAgICAgaWYgKHNraXBZKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNUb3ApIHtcbiAgICAgICAgICAgIHNraXBZID0gKFxuICAgICAgICAgICAgLy8gc2tpcCBpZiB3ZSBhcmUgbW92aW5nIHRvIHRvd2FyZHMgdG9wIGFuZCB0aGUgY3Vyc29yIGlzXG4gICAgICAgICAgICAvLyBiZWxvdyB0aGUgdG9wIGFuY2hvciArIHRvcEJ1ZmZlclxuICAgICAgICAgICAgLy8gbm90ZTogdG9wQnVmZmVyIGlzIHVzZWQgd2hlbiBtb3ZpbmcgdGhlIGRpYWxvZyB1c2luZyB0aGUgdGl0bGUgYmFyXG4gICAgICAgICAgICAoZGlmZiA8IDAgJiYgZS5jbGllbnRZID4geVBvc2l0aW9uICsgcGFyZW50UmVjdC50b3AgKyB0b3BCdWZmZXIpIHx8XG4gICAgICAgICAgICAgICAgLy8gc2tpcCBpZiB3ZSBhcmUgbW92aW5nIHRvIHRoZSBib3R0b20gYW5kIHRoZSBjdXJzb3IgaXNcbiAgICAgICAgICAgICAgICAvLyBhYm92ZSB0aGUgdG9wIGFuY2hvclxuICAgICAgICAgICAgICAgIChkaWZmID4gMCAmJiBlLmNsaWVudFkgPCB5UG9zaXRpb24gKyBwYXJlbnRSZWN0LnRvcCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2tpcFkgPSAoXG4gICAgICAgICAgICAvLyBza2lwIGlmIHdlIGFyZSBtb3ZpbmcgdG93YXJkcyB0aGUgdG9wIGFuZCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAvLyBpcyBiZWxvdyB0aGUgYm90dG9tIGFuY2hvclxuICAgICAgICAgICAgKGRpZmYgPCAwICYmIGUuY2xpZW50WSA+IGJvdW5kYXJ5RWxSZWN0LmJvdHRvbSkgfHxcbiAgICAgICAgICAgICAgICAvLyBza2lwIGlmIHdlIGFyZSBtb3ZpbmcgdG93YXJkcyB0aGUgYm90dG9tIGFuZCB0aGUgY3Vyc29yXG4gICAgICAgICAgICAgICAgLy8gaXMgYWJvdmUgdGhlIGJvdHRvbSBhbmNob3JcbiAgICAgICAgICAgICAgICAoZGlmZiA+IDAgJiYgZS5jbGllbnRZIDwgYm91bmRhcnlFbFJlY3QuYm90dG9tKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNraXBZO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuY3JlYXRlUmVzaXplTWFwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZWxlbWVudDtcbiAgICAgICAgdGhpcy5yZXNpemVyTWFwID0ge1xuICAgICAgICAgICAgdG9wTGVmdDogeyBlbGVtZW50OiBlR3VpLnF1ZXJ5U2VsZWN0b3IoJ1tyZWY9ZVRvcExlZnRSZXNpemVyXScpIH0sXG4gICAgICAgICAgICB0b3A6IHsgZWxlbWVudDogZUd1aS5xdWVyeVNlbGVjdG9yKCdbcmVmPWVUb3BSZXNpemVyXScpIH0sXG4gICAgICAgICAgICB0b3BSaWdodDogeyBlbGVtZW50OiBlR3VpLnF1ZXJ5U2VsZWN0b3IoJ1tyZWY9ZVRvcFJpZ2h0UmVzaXplcl0nKSB9LFxuICAgICAgICAgICAgcmlnaHQ6IHsgZWxlbWVudDogZUd1aS5xdWVyeVNlbGVjdG9yKCdbcmVmPWVSaWdodFJlc2l6ZXJdJykgfSxcbiAgICAgICAgICAgIGJvdHRvbVJpZ2h0OiB7IGVsZW1lbnQ6IGVHdWkucXVlcnlTZWxlY3RvcignW3JlZj1lQm90dG9tUmlnaHRSZXNpemVyXScpIH0sXG4gICAgICAgICAgICBib3R0b206IHsgZWxlbWVudDogZUd1aS5xdWVyeVNlbGVjdG9yKCdbcmVmPWVCb3R0b21SZXNpemVyXScpIH0sXG4gICAgICAgICAgICBib3R0b21MZWZ0OiB7IGVsZW1lbnQ6IGVHdWkucXVlcnlTZWxlY3RvcignW3JlZj1lQm90dG9tTGVmdFJlc2l6ZXJdJykgfSxcbiAgICAgICAgICAgIGxlZnQ6IHsgZWxlbWVudDogZUd1aS5xdWVyeVNlbGVjdG9yKCdbcmVmPWVMZWZ0UmVzaXplcl0nKSB9XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5hZGRSZXNpemVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVzaXplcnNBZGRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5lbGVtZW50O1xuICAgICAgICBpZiAoIWVHdWkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyc2VyID0gbmV3IERPTVBhcnNlcigpO1xuICAgICAgICB2YXIgcmVzaXplcnMgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKFJFU0laRV9URU1QTEFURSwgJ3RleHQvaHRtbCcpLmJvZHk7XG4gICAgICAgIGVHdWkuYXBwZW5kQ2hpbGQocmVzaXplcnMuZmlyc3RDaGlsZCk7XG4gICAgICAgIHRoaXMuY3JlYXRlUmVzaXplTWFwKCk7XG4gICAgICAgIHRoaXMucmVzaXplcnNBZGRlZCA9IHRydWU7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5yZW1vdmVSZXNpemVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yZXNpemVyTWFwID0gdW5kZWZpbmVkO1xuICAgICAgICB2YXIgcmVzaXplckVsID0gdGhpcy5lbGVtZW50LnF1ZXJ5U2VsZWN0b3IoXCIuXCIgKyBSRVNJWkVfQ09OVEFJTkVSX1NUWUxFKTtcbiAgICAgICAgaWYgKHJlc2l6ZXJFbCkge1xuICAgICAgICAgICAgdGhpcy5lbGVtZW50LnJlbW92ZUNoaWxkKHJlc2l6ZXJFbCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXNpemVyc0FkZGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5nZXRSZXNpemVyRWxlbWVudCA9IGZ1bmN0aW9uIChzaWRlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlc2l6ZXJNYXBbc2lkZV0uZWxlbWVudDtcbiAgICB9O1xuICAgIFBvc2l0aW9uYWJsZUZlYXR1cmUucHJvdG90eXBlLm9uUmVzaXplU3RhcnQgPSBmdW5jdGlvbiAoZSwgc2lkZSkge1xuICAgICAgICB0aGlzLmJvdW5kYXJ5RWwgPSB0aGlzLmZpbmRCb3VuZGFyeUVsZW1lbnQoKTtcbiAgICAgICAgaWYgKCF0aGlzLnBvc2l0aW9uZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGlzZVBvc2l0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdXJyZW50UmVzaXplciA9IHtcbiAgICAgICAgICAgIGlzVG9wOiAhIXNpZGUubWF0Y2goL3RvcC9pKSxcbiAgICAgICAgICAgIGlzUmlnaHQ6ICEhc2lkZS5tYXRjaCgvcmlnaHQvaSksXG4gICAgICAgICAgICBpc0JvdHRvbTogISFzaWRlLm1hdGNoKC9ib3R0b20vaSksXG4gICAgICAgICAgICBpc0xlZnQ6ICEhc2lkZS5tYXRjaCgvbGVmdC9pKSxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5lbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2FnLXJlc2l6aW5nJyk7XG4gICAgICAgIHRoaXMucmVzaXplck1hcFtzaWRlXS5lbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2FnLWFjdGl2ZScpO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbmZpZywgcG9wdXAgPSBfYS5wb3B1cCwgZm9yY2VQb3B1cFBhcmVudEFzT2Zmc2V0UGFyZW50ID0gX2EuZm9yY2VQb3B1cFBhcmVudEFzT2Zmc2V0UGFyZW50O1xuICAgICAgICBpZiAoIXBvcHVwICYmICFmb3JjZVBvcHVwUGFyZW50QXNPZmZzZXRQYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuYXBwbHlTaXplVG9TaWJsaW5ncyh0aGlzLmN1cnJlbnRSZXNpemVyLmlzQm90dG9tIHx8IHRoaXMuY3VycmVudFJlc2l6ZXIuaXNUb3ApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXNSZXNpemluZyA9IHRydWU7XG4gICAgICAgIHRoaXMudXBkYXRlRHJhZ1N0YXJ0UG9zaXRpb24oZS5jbGllbnRYLCBlLmNsaWVudFkpO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuZ2V0U2libGluZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5lbGVtZW50O1xuICAgICAgICB2YXIgcGFyZW50ID0gZWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHBhcmVudC5jaGlsZHJlbikuZmlsdGVyKGZ1bmN0aW9uIChlbCkgeyByZXR1cm4gIWVsLmNsYXNzTGlzdC5jb250YWlucygnYWctaGlkZGVuJyk7IH0pO1xuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuZ2V0TWluU2l6ZU9mU2libGluZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzaWJsaW5ncyA9IHRoaXMuZ2V0U2libGluZ3MoKSB8fCBbXTtcbiAgICAgICAgdmFyIGhlaWdodCA9IDA7XG4gICAgICAgIHZhciB3aWR0aCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2libGluZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50RWwgPSBzaWJsaW5nc1tpXTtcbiAgICAgICAgICAgIHZhciBpc0ZsZXggPSAhIWN1cnJlbnRFbC5zdHlsZS5mbGV4ICYmIGN1cnJlbnRFbC5zdHlsZS5mbGV4ICE9PSAnMCAwIGF1dG8nO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRFbCA9PT0gdGhpcy5lbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbmV4dEhlaWdodCA9IHRoaXMubWluSGVpZ2h0IHx8IDA7XG4gICAgICAgICAgICB2YXIgbmV4dFdpZHRoID0gdGhpcy5taW5XaWR0aCB8fCAwO1xuICAgICAgICAgICAgaWYgKGlzRmxleCkge1xuICAgICAgICAgICAgICAgIHZhciBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoY3VycmVudEVsKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcHV0ZWRTdHlsZS5taW5IZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dEhlaWdodCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUubWluSGVpZ2h0LCAxMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjb21wdXRlZFN0eWxlLm1pbldpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRXaWR0aCA9IHBhcnNlSW50KGNvbXB1dGVkU3R5bGUubWluV2lkdGgsIDEwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBuZXh0SGVpZ2h0ID0gY3VycmVudEVsLm9mZnNldEhlaWdodDtcbiAgICAgICAgICAgICAgICBuZXh0V2lkdGggPSBjdXJyZW50RWwub2Zmc2V0V2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoZWlnaHQgKz0gbmV4dEhlaWdodDtcbiAgICAgICAgICAgIHdpZHRoICs9IG5leHRXaWR0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBoZWlnaHQ6IGhlaWdodCwgd2lkdGg6IHdpZHRoIH07XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5hcHBseVNpemVUb1NpYmxpbmdzID0gZnVuY3Rpb24gKHZlcnRpY2FsKSB7XG4gICAgICAgIHZhciBjb250YWluZXJUb0ZsZXggPSBudWxsO1xuICAgICAgICB2YXIgc2libGluZ3MgPSB0aGlzLmdldFNpYmxpbmdzKCk7XG4gICAgICAgIGlmICghc2libGluZ3MpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpYmxpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZWwgPSBzaWJsaW5nc1tpXTtcbiAgICAgICAgICAgIGlmIChlbCA9PT0gY29udGFpbmVyVG9GbGV4KSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmVydGljYWwpIHtcbiAgICAgICAgICAgICAgICBlbC5zdHlsZS5oZWlnaHQgPSBlbC5vZmZzZXRIZWlnaHQgKyBcInB4XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbC5zdHlsZS53aWR0aCA9IGVsLm9mZnNldFdpZHRoICsgXCJweFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWwuc3R5bGUuZmxleCA9ICcwIDAgYXV0byc7XG4gICAgICAgICAgICBpZiAoZWwgPT09IHRoaXMuZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lclRvRmxleCA9IHNpYmxpbmdzW2kgKyAxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoY29udGFpbmVyVG9GbGV4KSB7XG4gICAgICAgICAgICBjb250YWluZXJUb0ZsZXguc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2hlaWdodCcpO1xuICAgICAgICAgICAgY29udGFpbmVyVG9GbGV4LnN0eWxlLnJlbW92ZVByb3BlcnR5KCdtaW4taGVpZ2h0Jyk7XG4gICAgICAgICAgICBjb250YWluZXJUb0ZsZXguc3R5bGUucmVtb3ZlUHJvcGVydHkoJ21heC1oZWlnaHQnKTtcbiAgICAgICAgICAgIGNvbnRhaW5lclRvRmxleC5zdHlsZS5mbGV4ID0gJzEgMSBhdXRvJztcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUub25SZXNpemUgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNSZXNpemluZyB8fCAhdGhpcy5jdXJyZW50UmVzaXplcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29uZmlnLCBwb3B1cCA9IF9hLnBvcHVwLCBmb3JjZVBvcHVwUGFyZW50QXNPZmZzZXRQYXJlbnQgPSBfYS5mb3JjZVBvcHVwUGFyZW50QXNPZmZzZXRQYXJlbnQ7XG4gICAgICAgIHZhciBfYiA9IHRoaXMuY3VycmVudFJlc2l6ZXIsIGlzVG9wID0gX2IuaXNUb3AsIGlzUmlnaHQgPSBfYi5pc1JpZ2h0LCBpc0JvdHRvbSA9IF9iLmlzQm90dG9tLCBpc0xlZnQgPSBfYi5pc0xlZnQ7XG4gICAgICAgIHZhciBpc0hvcml6b250YWwgPSBpc1JpZ2h0IHx8IGlzTGVmdDtcbiAgICAgICAgdmFyIGlzVmVydGljYWwgPSBpc0JvdHRvbSB8fCBpc1RvcDtcbiAgICAgICAgdmFyIF9jID0gdGhpcy5jYWxjdWxhdGVNb3VzZU1vdmVtZW50KHsgZTogZSwgaXNMZWZ0OiBpc0xlZnQsIGlzVG9wOiBpc1RvcCB9KSwgbW92ZW1lbnRYID0gX2MubW92ZW1lbnRYLCBtb3ZlbWVudFkgPSBfYy5tb3ZlbWVudFk7XG4gICAgICAgIHZhciB4UG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uLng7XG4gICAgICAgIHZhciB5UG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uLnk7XG4gICAgICAgIHZhciBvZmZzZXRMZWZ0ID0gMDtcbiAgICAgICAgdmFyIG9mZnNldFRvcCA9IDA7XG4gICAgICAgIGlmIChpc0hvcml6b250YWwgJiYgbW92ZW1lbnRYKSB7XG4gICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gaXNMZWZ0ID8gLTEgOiAxO1xuICAgICAgICAgICAgdmFyIG9sZFdpZHRoID0gdGhpcy5nZXRXaWR0aCgpO1xuICAgICAgICAgICAgdmFyIG5ld1dpZHRoID0gb2xkV2lkdGggKyAobW92ZW1lbnRYICogZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIHZhciBza2lwV2lkdGggPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChpc0xlZnQpIHtcbiAgICAgICAgICAgICAgICBvZmZzZXRMZWZ0ID0gb2xkV2lkdGggLSBuZXdXaWR0aDtcbiAgICAgICAgICAgICAgICBpZiAoeFBvc2l0aW9uICsgb2Zmc2V0TGVmdCA8PSAwIHx8IG5ld1dpZHRoIDw9IHRoaXMubWluV2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2tpcFdpZHRoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0TGVmdCA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFza2lwV2lkdGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFdpZHRoKG5ld1dpZHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNWZXJ0aWNhbCAmJiBtb3ZlbWVudFkpIHtcbiAgICAgICAgICAgIHZhciBkaXJlY3Rpb24gPSBpc1RvcCA/IC0xIDogMTtcbiAgICAgICAgICAgIHZhciBvbGRIZWlnaHQgPSB0aGlzLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgdmFyIG5ld0hlaWdodCA9IG9sZEhlaWdodCArIChtb3ZlbWVudFkgKiBkaXJlY3Rpb24pO1xuICAgICAgICAgICAgdmFyIHNraXBIZWlnaHQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChpc1RvcCkge1xuICAgICAgICAgICAgICAgIG9mZnNldFRvcCA9IG9sZEhlaWdodCAtIG5ld0hlaWdodDtcbiAgICAgICAgICAgICAgICBpZiAoeVBvc2l0aW9uICsgb2Zmc2V0VG9wIDw9IDAgfHwgbmV3SGVpZ2h0IDw9IHRoaXMubWluSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHNraXBIZWlnaHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXRUb3AgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGRvIG5vdCBsZXQgdGhlIHNpemUgb2YgYWxsIHNpYmxpbmdzIGJlIGhpZ2hlciB0aGFuIHRoZSBwYXJlbnQgY29udGFpbmVyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5wb3B1cCAmJlxuICAgICAgICAgICAgICAgICAgICAhdGhpcy5jb25maWcuZm9yY2VQb3B1cFBhcmVudEFzT2Zmc2V0UGFyZW50ICYmXG4gICAgICAgICAgICAgICAgICAgIG9sZEhlaWdodCA8IG5ld0hlaWdodCAmJlxuICAgICAgICAgICAgICAgICAgICAodGhpcy5nZXRNaW5TaXplT2ZTaWJsaW5ncygpLmhlaWdodCArIG5ld0hlaWdodCkgPiB0aGlzLmVsZW1lbnQucGFyZW50RWxlbWVudC5vZmZzZXRIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgc2tpcEhlaWdodCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFza2lwSGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRIZWlnaHQobmV3SGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZURyYWdTdGFydFBvc2l0aW9uKGUuY2xpZW50WCwgZS5jbGllbnRZKTtcbiAgICAgICAgaWYgKChwb3B1cCB8fCBmb3JjZVBvcHVwUGFyZW50QXNPZmZzZXRQYXJlbnQpICYmIG9mZnNldExlZnQgfHwgb2Zmc2V0VG9wKSB7XG4gICAgICAgICAgICB0aGlzLm9mZnNldEVsZW1lbnQoeFBvc2l0aW9uICsgb2Zmc2V0TGVmdCwgeVBvc2l0aW9uICsgb2Zmc2V0VG9wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUub25SZXNpemVFbmQgPSBmdW5jdGlvbiAoZSwgc2lkZSkge1xuICAgICAgICB0aGlzLmlzUmVzaXppbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jdXJyZW50UmVzaXplciA9IG51bGw7XG4gICAgICAgIHRoaXMuYm91bmRhcnlFbCA9IG51bGw7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0eXBlOiAncmVzaXplJyxcbiAgICAgICAgICAgIGFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdhZy1yZXNpemluZycpO1xuICAgICAgICB0aGlzLnJlc2l6ZXJNYXBbc2lkZV0uZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCdhZy1hY3RpdmUnKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHBhcmFtcyk7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5yZWZyZXNoU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmVsZW1lbnQ7XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5wb3B1cCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy53aWR0aCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0V2lkdGgoZUd1aS5vZmZzZXRXaWR0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGVpZ2h0KGVHdWkub2Zmc2V0SGVpZ2h0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUub25Nb3ZlU3RhcnQgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB0aGlzLmJvdW5kYXJ5RWwgPSB0aGlzLmZpbmRCb3VuZGFyeUVsZW1lbnQoKTtcbiAgICAgICAgaWYgKCF0aGlzLnBvc2l0aW9uZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGlzZVBvc2l0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc01vdmluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QuYWRkKCdhZy1tb3ZpbmcnKTtcbiAgICAgICAgdGhpcy51cGRhdGVEcmFnU3RhcnRQb3NpdGlvbihlLmNsaWVudFgsIGUuY2xpZW50WSk7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5vbk1vdmUgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNNb3ZpbmcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgX2EgPSB0aGlzLnBvc2l0aW9uLCB4ID0gX2EueCwgeSA9IF9hLnk7XG4gICAgICAgIHZhciB0b3BCdWZmZXI7XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5jYWxjdWxhdGVUb3BCdWZmZXIpIHtcbiAgICAgICAgICAgIHRvcEJ1ZmZlciA9IHRoaXMuY29uZmlnLmNhbGN1bGF0ZVRvcEJ1ZmZlcigpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBfYiA9IHRoaXMuY2FsY3VsYXRlTW91c2VNb3ZlbWVudCh7XG4gICAgICAgICAgICBlOiBlLFxuICAgICAgICAgICAgaXNUb3A6IHRydWUsXG4gICAgICAgICAgICBhbnl3aGVyZVdpdGhpbjogdHJ1ZSxcbiAgICAgICAgICAgIHRvcEJ1ZmZlcjogdG9wQnVmZmVyXG4gICAgICAgIH0pLCBtb3ZlbWVudFggPSBfYi5tb3ZlbWVudFgsIG1vdmVtZW50WSA9IF9iLm1vdmVtZW50WTtcbiAgICAgICAgdGhpcy5vZmZzZXRFbGVtZW50KHggKyBtb3ZlbWVudFgsIHkgKyBtb3ZlbWVudFkpO1xuICAgICAgICB0aGlzLnVwZGF0ZURyYWdTdGFydFBvc2l0aW9uKGUuY2xpZW50WCwgZS5jbGllbnRZKTtcbiAgICB9O1xuICAgIFBvc2l0aW9uYWJsZUZlYXR1cmUucHJvdG90eXBlLm9uTW92ZUVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5pc01vdmluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmJvdW5kYXJ5RWwgPSBudWxsO1xuICAgICAgICB0aGlzLmVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnYWctbW92aW5nJyk7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5zZXRPZmZzZXRQYXJlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5mb3JjZVBvcHVwUGFyZW50QXNPZmZzZXRQYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0UGFyZW50ID0gdGhpcy5wb3B1cFNlcnZpY2UuZ2V0UG9wdXBQYXJlbnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0UGFyZW50ID0gdGhpcy5lbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUuZmluZEJvdW5kYXJ5RWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVsID0gdGhpcy5lbGVtZW50O1xuICAgICAgICB3aGlsZSAoZWwpIHtcbiAgICAgICAgICAgIGlmICh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCkucG9zaXRpb24gIT09ICdzdGF0aWMnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWwgPSBlbC5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnQ7XG4gICAgfTtcbiAgICBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZS5jbGVhclJlc2l6ZUxpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgd2hpbGUgKHRoaXMucmVzaXplTGlzdGVuZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHRoaXMucmVzaXplTGlzdGVuZXJzLnBvcCgpO1xuICAgICAgICAgICAgdGhpcy5kcmFnU2VydmljZS5yZW1vdmVEcmFnU291cmNlKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBvc2l0aW9uYWJsZUZlYXR1cmUucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5tb3ZlRWxlbWVudERyYWdMaXN0ZW5lcikge1xuICAgICAgICAgICAgdGhpcy5kcmFnU2VydmljZS5yZW1vdmVEcmFnU291cmNlKHRoaXMubW92ZUVsZW1lbnREcmFnTGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xlYXJSZXNpemVMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5yZW1vdmVSZXNpemVycygpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxNihbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBQb3NpdGlvbmFibGVGZWF0dXJlLnByb3RvdHlwZSwgXCJwb3B1cFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDE2KFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnU2VydmljZScpXG4gICAgXSwgUG9zaXRpb25hYmxlRmVhdHVyZS5wcm90b3R5cGUsIFwiZHJhZ1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gUG9zaXRpb25hYmxlRmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxYyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMTUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBBdXRvV2lkdGhDYWxjdWxhdG9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxYyhBdXRvV2lkdGhDYWxjdWxhdG9yLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEF1dG9XaWR0aENhbGN1bGF0b3IoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQXV0b1dpZHRoQ2FsY3VsYXRvci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICBfdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsID0gcC5jZW50ZXJSb3dDb250YWluZXJDdHJsO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIHRoaXMgaXMgdGhlIHRyaWNrOiB3ZSBjcmVhdGUgYSBkdW1teSBjb250YWluZXIgYW5kIGNsb25lIGFsbCB0aGUgY2VsbHNcbiAgICAvLyBpbnRvIHRoZSBkdW1teSwgdGhlbiBjaGVjayB0aGUgZHVtbXkncyB3aWR0aC4gdGhlbiBkZXN0cm95IHRoZSBkdW1teVxuICAgIC8vIGFzIHdlIGRvbid0IG5lZWQgaXQgYW55IG1vcmUuXG4gICAgLy8gZHJhd2JhY2s6IG9ubHkgdGhlIGNlbGxzIHZpc2libGUgb24gdGhlIHNjcmVlbiBhcmUgY29uc2lkZXJlZFxuICAgIEF1dG9XaWR0aENhbGN1bGF0b3IucHJvdG90eXBlLmdldFByZWZlcnJlZFdpZHRoRm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbiwgc2tpcEhlYWRlcikge1xuICAgICAgICB2YXIgZUhlYWRlckNlbGwgPSB0aGlzLmdldEhlYWRlckNlbGxGb3JDb2x1bW4oY29sdW1uKTtcbiAgICAgICAgLy8gY2VsbCBpc24ndCB2aXNpYmxlXG4gICAgICAgIGlmICghZUhlYWRlckNlbGwpIHtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZWxlbWVudHMgPSB0aGlzLnJvd1JlbmRlcmVyLmdldEFsbENlbGxzRm9yQ29sdW1uKGNvbHVtbik7XG4gICAgICAgIGlmICghc2tpcEhlYWRlcikge1xuICAgICAgICAgICAgLy8gd2Ugb25seSBjb25zaWRlciB0aGUgbG93ZXN0IGxldmVsIGNlbGwsIG5vdCB0aGUgZ3JvdXAgY2VsbC4gaW4gOTklIG9mIHRoZSB0aW1lLCB0aGlzXG4gICAgICAgICAgICAvLyB3aWxsIGJlIGVub3VnaC4gaWYgd2UgY29uc2lkZXIgZ3JvdXBzLCB0aGVuIGl0IGdldHMgdG9vIGNvbXBsaWNhdGVkIGZvciB3aGF0IGl0J3Mgd29ydGgsXG4gICAgICAgICAgICAvLyBhcyB0aGUgZ3JvdXBzIGNhbiBzcGFuIGNvbHVtbnMgYW5kIHRoaXMgY2xhc3Mgb25seSBjb25zaWRlcnMgb25lIGNvbHVtbiBhdCBhIHRpbWUuXG4gICAgICAgICAgICBlbGVtZW50cy5wdXNoKGVIZWFkZXJDZWxsKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5hZGRFbGVtZW50c1RvQ29udGFpbmVyQW5kR2V0V2lkdGgoZWxlbWVudHMpO1xuICAgIH07XG4gICAgQXV0b1dpZHRoQ2FsY3VsYXRvci5wcm90b3R5cGUuZ2V0UHJlZmVycmVkV2lkdGhGb3JDb2x1bW5Hcm91cCA9IGZ1bmN0aW9uIChjb2x1bW5Hcm91cCkge1xuICAgICAgICB2YXIgZUhlYWRlckNlbGwgPSB0aGlzLmdldEhlYWRlckNlbGxGb3JDb2x1bW4oY29sdW1uR3JvdXApO1xuICAgICAgICBpZiAoIWVIZWFkZXJDZWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkRWxlbWVudHNUb0NvbnRhaW5lckFuZEdldFdpZHRoKFtlSGVhZGVyQ2VsbF0pO1xuICAgIH07XG4gICAgQXV0b1dpZHRoQ2FsY3VsYXRvci5wcm90b3R5cGUuYWRkRWxlbWVudHNUb0NvbnRhaW5lckFuZEdldFdpZHRoID0gZnVuY3Rpb24gKGVsZW1lbnRzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlRHVtbXlDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICAgIC8vIHBvc2l0aW9uIGZpeGVkLCBzbyBpdCBpc24ndCByZXN0cmljdGVkIHRvIHRoZSBib3VuZGFyaWVzIG9mIHRoZSBwYXJlbnRcbiAgICAgICAgZUR1bW15Q29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ2ZpeGVkJztcbiAgICAgICAgLy8gd2UgcHV0IHRoZSBkdW1teSBpbnRvIHRoZSBib2R5IGNvbnRhaW5lciwgc28gaXQgd2lsbCBpbmhlcml0IGFsbCB0aGVcbiAgICAgICAgLy8gY3NzIHN0eWxlcyB0aGF0IHRoZSByZWFsIGNlbGxzIGFyZSBpbmhlcml0aW5nXG4gICAgICAgIHZhciBlQm9keUNvbnRhaW5lciA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybC5nZXRDb250YWluZXJFbGVtZW50KCk7XG4gICAgICAgIGVCb2R5Q29udGFpbmVyLmFwcGVuZENoaWxkKGVEdW1teUNvbnRhaW5lcik7XG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7IHJldHVybiBfdGhpcy5jbG9uZUl0ZW1JbnRvRHVtbXkoZWwsIGVEdW1teUNvbnRhaW5lcik7IH0pO1xuICAgICAgICAvLyBhdCB0aGlzIHBvaW50LCBhbGwgdGhlIGNsb25lcyBhcmUgbGluZWQgdXAgdmVydGljYWxseSB3aXRoIG5hdHVyYWwgd2lkdGhzLiB0aGUgZHVtbXlcbiAgICAgICAgLy8gY29udGFpbmVyIHdpbGwgaGF2ZSBhIHdpZHRoIHdpZGUgZW5vdWdoIGp1c3QgdG8gZml0IHRoZSBsYXJnZXN0LlxuICAgICAgICB2YXIgZHVtbXlDb250YWluZXJXaWR0aCA9IGVEdW1teUNvbnRhaW5lci5vZmZzZXRXaWR0aDtcbiAgICAgICAgLy8gd2UgYXJlIGZpbmlzaGVkIHdpdGggdGhlIGR1bW15IGNvbnRhaW5lciwgc28gZ2V0IHJpZCBvZiBpdFxuICAgICAgICBlQm9keUNvbnRhaW5lci5yZW1vdmVDaGlsZChlRHVtbXlDb250YWluZXIpO1xuICAgICAgICAvLyB3ZSBhZGQgcGFkZGluZyBhcyBJIGZvdW5kIHNvbWV0aW1lcyB0aGUgZ3VpIHN0aWxsIHB1dCAnLi4uJyBhZnRlciBzb21lIG9mIHRoZSB0ZXh0cy4gc28gdGhlXG4gICAgICAgIC8vIHVzZXIgY2FuIGNvbmZpZ3VyZSB0aGUgZ3JpZCB0byBhZGQgYSBmZXcgbW9yZSBwaXhlbHMgYWZ0ZXIgdGhlIGNhbGN1bGF0ZWQgd2lkdGhcbiAgICAgICAgdmFyIGF1dG9TaXplUGFkZGluZyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEF1dG9TaXplUGFkZGluZygpO1xuICAgICAgICByZXR1cm4gZHVtbXlDb250YWluZXJXaWR0aCArIGF1dG9TaXplUGFkZGluZztcbiAgICB9O1xuICAgIEF1dG9XaWR0aENhbGN1bGF0b3IucHJvdG90eXBlLmdldEhlYWRlckNlbGxGb3JDb2x1bW4gPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIC8qIHRzbGludDplbmFibGUgKi9cbiAgICAgICAgdmFyIGVsZW1lbnQgPSBudWxsO1xuICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5nZXRIZWFkZXJSb3dDb250YWluZXJDdHJscygpLmZvckVhY2goZnVuY3Rpb24gKGNvbnRhaW5lcikge1xuICAgICAgICAgICAgdmFyIHJlcyA9IGNvbnRhaW5lci5nZXRIdG1sRWxlbWVudEZvckNvbHVtbkhlYWRlcihjb2x1bW4pO1xuICAgICAgICAgICAgaWYgKHJlcyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudCA9IHJlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH07XG4gICAgQXV0b1dpZHRoQ2FsY3VsYXRvci5wcm90b3R5cGUuY2xvbmVJdGVtSW50b0R1bW15ID0gZnVuY3Rpb24gKGVDZWxsLCBlRHVtbXlDb250YWluZXIpIHtcbiAgICAgICAgLy8gbWFrZSBhIGRlZXAgY2xvbmUgb2YgdGhlIGNlbGxcbiAgICAgICAgdmFyIGVDZWxsQ2xvbmUgPSBlQ2VsbC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICAgIC8vIHRoZSBvcmlnaW5hbCBoYXMgYSBmaXhlZCB3aWR0aCwgd2UgcmVtb3ZlIHRoaXMgdG8gYWxsb3cgdGhlIG5hdHVyYWwgd2lkdGggYmFzZWQgb24gY29udGVudFxuICAgICAgICBlQ2VsbENsb25lLnN0eWxlLndpZHRoID0gJyc7XG4gICAgICAgIC8vIHRoZSBvcmlnaW5hbCBoYXMgcG9zaXRpb24gPSBhYnNvbHV0ZSwgd2UgbmVlZCB0byByZW1vdmUgdGhpcyBzbyBpdCdzIHBvc2l0aW9uZWQgbm9ybWFsbHlcbiAgICAgICAgZUNlbGxDbG9uZS5zdHlsZS5wb3NpdGlvbiA9ICdzdGF0aWMnO1xuICAgICAgICBlQ2VsbENsb25lLnN0eWxlLmxlZnQgPSAnJztcbiAgICAgICAgLy8gd2UgcHV0IHRoZSBjZWxsIGludG8gYSBjb250YWluaW5nIGRpdiwgYXMgb3RoZXJ3aXNlIHRoZSBjZWxscyB3b3VsZCBqdXN0IGxpbmUgdXBcbiAgICAgICAgLy8gb24gdGhlIHNhbWUgbGluZSwgc3RhbmRhcmQgZmxvdyBsYXlvdXQsIGJ5IHB1dHRpbmcgdGhlbSBpbnRvIGRpdnMsIHRoZXkgYXJlIGxhaWRcbiAgICAgICAgLy8gb3V0IG9uZSBwZXIgbGluZVxuICAgICAgICB2YXIgZUNsb25lUGFyZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHZhciBlQ2xvbmVQYXJlbnRDbGFzc0xpc3QgPSBlQ2xvbmVQYXJlbnQuY2xhc3NMaXN0O1xuICAgICAgICB2YXIgaXNIZWFkZXIgPSBbJ2FnLWhlYWRlci1jZWxsJywgJ2FnLWhlYWRlci1ncm91cC1jZWxsJ10uc29tZShmdW5jdGlvbiAoY2xzKSB7IHJldHVybiBlQ2VsbENsb25lLmNsYXNzTGlzdC5jb250YWlucyhjbHMpOyB9KTtcbiAgICAgICAgaWYgKGlzSGVhZGVyKSB7XG4gICAgICAgICAgICBlQ2xvbmVQYXJlbnRDbGFzc0xpc3QuYWRkKCdhZy1oZWFkZXInLCAnYWctaGVhZGVyLXJvdycpO1xuICAgICAgICAgICAgZUNsb25lUGFyZW50LnN0eWxlLnBvc2l0aW9uID0gJ3N0YXRpYyc7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlQ2xvbmVQYXJlbnRDbGFzc0xpc3QuYWRkKCdhZy1yb3cnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIHBhcmVudCB1c2luZyBjbGFzc2VzIChoZWFkZXJzIGhhdmUgYWctaGVhZGVyLWNlbGwsIHJvd3MgaGF2ZSBhZy1yb3cpLCBhbmQgY29weSBjbGFzc2VzIGZyb20gaXQuXG4gICAgICAgIC8vIGlmIHdlIGRpZG4ndCBkbyB0aGlzLCB0aGluZ3MgbGlrZSBhZy1yb3ctbGV2ZWwtMiB3b3VsZCBiZSBtaXNzaW5nIGlmIHByZXNlbnQsIHdoaWNoIHNldHMgaW5kZW50c1xuICAgICAgICAvLyBvbnRvIGdyb3VwIGl0ZW1zLlxuICAgICAgICB2YXIgcG9pbnRlciA9IGVDZWxsLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIHdoaWxlIChwb2ludGVyKSB7XG4gICAgICAgICAgICB2YXIgaXNSb3cgPSBbJ2FnLWhlYWRlci1yb3cnLCAnYWctcm93J10uc29tZShmdW5jdGlvbiAoY2xzKSB7IHJldHVybiBwb2ludGVyLmNsYXNzTGlzdC5jb250YWlucyhjbHMpOyB9KTtcbiAgICAgICAgICAgIGlmIChpc1Jvdykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRlci5jbGFzc0xpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW0gPSBwb2ludGVyLmNsYXNzTGlzdFtpXTtcbiAgICAgICAgICAgICAgICAgICAgLy8gd2Ugc2tpcCBhZy1yb3ctcG9zaXRpb24tYWJzb2x1dGUsIGFzIHRoaXMgaGFzIHN0cnVjdHVyYWwgQ1NTIGFwcGxpZWQgdGhhdCBzdG9wcyB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gZWxlbWVudCBmcm9tIGZpdHRpbmcgaW50byBpdCdzIHBhcmVudCwgYW5kIHdlIG5lZWQgdGhlIGVsZW1lbnQgdG8gc3RyZXRjaCB0aGUgcGFyZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIGFzIHdlIGFyZSBtZWFzdXJpbmcgdGhlIHBhcmVudHMgd2lkdGhcbiAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0gIT0gJ2FnLXJvdy1wb3NpdGlvbi1hYnNvbHV0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVDbG9uZVBhcmVudENsYXNzTGlzdC5hZGQoaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoZSB0d2lnIG9uIHRoZSBicmFuY2gsIHRoZSBicmFuY2ggb24gdGhlIHRyZWUsIHRoZSB0cmVlIGluIHRoZSBob2xlLFxuICAgICAgICAvLyB0aGUgaG9sZSBpbiB0aGUgYm9nLCB0aGUgYm9nIGluIHRoZSBjbG9uZSwgdGhlIGNsb25lIGluIHRoZSBwYXJlbnQsXG4gICAgICAgIC8vIHRoZSBwYXJlbnQgaW4gdGhlIGR1bW15LCBhbmQgdGhlIGR1bW15IGRvd24gaW4gdGhlIHZhbGwtZS1vb28sIE9PT09PT09PTyEgT2ggcm93IHRoZSByYXR0bGluZyBib2cuLi4uXG4gICAgICAgIGVDbG9uZVBhcmVudC5hcHBlbmRDaGlsZChlQ2VsbENsb25lKTtcbiAgICAgICAgZUR1bW15Q29udGFpbmVyLmFwcGVuZENoaWxkKGVDbG9uZVBhcmVudCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDE1KFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dSZW5kZXJlcicpXG4gICAgXSwgQXV0b1dpZHRoQ2FsY3VsYXRvci5wcm90b3R5cGUsIFwicm93UmVuZGVyZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDE1KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEF1dG9XaWR0aENhbGN1bGF0b3IucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd0Nzc0NsYXNzQ2FsY3VsYXRvcicpXG4gICAgXSwgQXV0b1dpZHRoQ2FsY3VsYXRvci5wcm90b3R5cGUsIFwicm93Q3NzQ2xhc3NDYWxjdWxhdG9yXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxNShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBdXRvV2lkdGhDYWxjdWxhdG9yLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIEF1dG9XaWR0aENhbGN1bGF0b3IgPSBfX2RlY29yYXRlJDE1KFtcbiAgICAgICAgQmVhbignYXV0b1dpZHRoQ2FsY3VsYXRvcicpXG4gICAgXSwgQXV0b1dpZHRoQ2FsY3VsYXRvcik7XG4gICAgcmV0dXJuIEF1dG9XaWR0aENhbGN1bGF0b3I7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMWIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDE0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX192YWx1ZXMkMSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fdmFsdWVzKSB8fCBmdW5jdGlvbihvKSB7XG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcbiAgICBpZiAobyAmJiB0eXBlb2Ygby5sZW5ndGggPT09IFwibnVtYmVyXCIpIHJldHVybiB7XG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IocyA/IFwiT2JqZWN0IGlzIG5vdCBpdGVyYWJsZS5cIiA6IFwiU3ltYm9sLml0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcbn07XG52YXIgX19yZWFkJGIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgX19zcHJlYWQkOSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCRiKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG52YXIgU3RpY2t5Um93RmVhdHVyZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMWIoU3RpY2t5Um93RmVhdHVyZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTdGlja3lSb3dGZWF0dXJlKGNyZWF0ZVJvd0NvbiwgZGVzdHJveVJvd0N0cmxzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmNyZWF0ZVJvd0NvbiA9IGNyZWF0ZVJvd0NvbjtcbiAgICAgICAgX3RoaXMuZGVzdHJveVJvd0N0cmxzID0gZGVzdHJveVJvd0N0cmxzO1xuICAgICAgICBfdGhpcy5zdGlja3lSb3dDdHJscyA9IFtdO1xuICAgICAgICBfdGhpcy5jb250YWluZXJIZWlnaHQgPSAwO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFN0aWNreVJvd0ZlYXR1cmUucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLndoZW5SZWFkeShmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgICAgICBfdGhpcy5ncmlkQm9keUN0cmwgPSBwYXJhbXMuZ3JpZEJvZHlDdHJsO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFN0aWNreVJvd0ZlYXR1cmUucHJvdG90eXBlLmdldFN0aWNreVJvd0N0cmxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGlja3lSb3dDdHJscztcbiAgICB9O1xuICAgIFN0aWNreVJvd0ZlYXR1cmUucHJvdG90eXBlLmNoZWNrU3RpY2t5Um93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGhlaWdodCA9IDA7XG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFJvd3NTdGlja3koKSkge1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoTm9kZXNBbmRDb250YWluZXJIZWlnaHQoW10sIGhlaWdodCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN0aWNreVJvd3MgPSBbXTtcbiAgICAgICAgdmFyIGZpcnN0UGl4ZWwgPSB0aGlzLnJvd1JlbmRlcmVyLmdldEZpcnN0VmlzaWJsZVZlcnRpY2FsUGl4ZWwoKTtcbiAgICAgICAgdmFyIGFkZFN0aWNreVJvdyA9IGZ1bmN0aW9uIChzdGlja3lSb3cpIHtcbiAgICAgICAgICAgIHN0aWNreVJvd3MucHVzaChzdGlja3lSb3cpO1xuICAgICAgICAgICAgdmFyIGxhc3RBbmNlc3RlciA9IHN0aWNreVJvdztcbiAgICAgICAgICAgIHdoaWxlIChsYXN0QW5jZXN0ZXIuZXhwYW5kZWQpIHtcbiAgICAgICAgICAgICAgICBsYXN0QW5jZXN0ZXIgPSBsYXN0KGxhc3RBbmNlc3Rlci5jaGlsZHJlbkFmdGVyU29ydCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbGFzdENoaWxkQm90dG9tID0gbGFzdEFuY2VzdGVyLnJvd1RvcCArIGxhc3RBbmNlc3Rlci5yb3dIZWlnaHQ7XG4gICAgICAgICAgICB2YXIgc3RpY2tSb3dCb3R0b20gPSBmaXJzdFBpeGVsICsgaGVpZ2h0ICsgc3RpY2t5Um93LnJvd0hlaWdodDtcbiAgICAgICAgICAgIGlmIChsYXN0Q2hpbGRCb3R0b20gPCBzdGlja1Jvd0JvdHRvbSkge1xuICAgICAgICAgICAgICAgIHN0aWNreVJvdy5zdGlja3lSb3dUb3AgPSBoZWlnaHQgKyAobGFzdENoaWxkQm90dG9tIC0gc3RpY2tSb3dCb3R0b20pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RpY2t5Um93LnN0aWNreVJvd1RvcCA9IGhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhlaWdodCA9IDA7XG4gICAgICAgICAgICBzdGlja3lSb3dzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhpc1Jvd0xhc3RQeCA9IHJvd05vZGUuc3RpY2t5Um93VG9wICsgcm93Tm9kZS5yb3dIZWlnaHQ7XG4gICAgICAgICAgICAgICAgaWYgKGhlaWdodCA8IHRoaXNSb3dMYXN0UHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpc1Jvd0xhc3RQeDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgIHZhciBmaXJzdFBpeGVsQWZ0ZXJTdGlja3lSb3dzID0gZmlyc3RQaXhlbCArIGhlaWdodDtcbiAgICAgICAgICAgIHZhciBmaXJzdEluZGV4ID0gdGhpcy5yb3dNb2RlbC5nZXRSb3dJbmRleEF0UGl4ZWwoZmlyc3RQaXhlbEFmdGVyU3RpY2t5Um93cyk7XG4gICAgICAgICAgICB2YXIgZmlyc3RSb3cgPSB0aGlzLnJvd01vZGVsLmdldFJvdyhmaXJzdEluZGV4KTtcbiAgICAgICAgICAgIGlmIChmaXJzdFJvdyA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBvbmx5IGhhcHBlbnMgd2hlbiBwaXZvdGluZywgYW5kIHdlIGFyZSBzaG93aW5nIHJvb3Qgbm9kZVxuICAgICAgICAgICAgaWYgKGZpcnN0Um93LmxldmVsIDwgMCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHBhcmVudHMgPSBbXTtcbiAgICAgICAgICAgIHZhciBwID0gZmlyc3RSb3cucGFyZW50O1xuICAgICAgICAgICAgd2hpbGUgKHAubGV2ZWwgPj0gMCkge1xuICAgICAgICAgICAgICAgIHBhcmVudHMucHVzaChwKTtcbiAgICAgICAgICAgICAgICBwID0gcC5wYXJlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZmlyc3RNaXNzaW5nUGFyZW50ID0gcGFyZW50cy5yZXZlcnNlKCkuZmluZChmdW5jdGlvbiAocGFyZW50KSB7IHJldHVybiBzdGlja3lSb3dzLmluZGV4T2YocGFyZW50KSA8IDAgJiYgcGFyZW50LmRpc3BsYXllZDsgfSk7XG4gICAgICAgICAgICBpZiAoZmlyc3RNaXNzaW5nUGFyZW50KSB7XG4gICAgICAgICAgICAgICAgYWRkU3RpY2t5Um93KGZpcnN0TWlzc2luZ1BhcmVudCk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiBmaXJzdCByb3cgaXMgYW4gb3BlbiBncm91cCwgYW5kIHByYWN0aWNhbGx5IHNob3duLCBpdCBuZWVkc1xuICAgICAgICAgICAgLy8gdG8gYmUgc3R1Y2tcbiAgICAgICAgICAgIGlmIChmaXJzdFJvdy5ncm91cCAmJiBmaXJzdFJvdy5leHBhbmRlZCAmJiAhZmlyc3RSb3cuZm9vdGVyICYmIGZpcnN0Um93LnJvd1RvcCA8IGZpcnN0UGl4ZWxBZnRlclN0aWNreVJvd3MpIHtcbiAgICAgICAgICAgICAgICBhZGRTdGlja3lSb3coZmlyc3RSb3cpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWZyZXNoTm9kZXNBbmRDb250YWluZXJIZWlnaHQoc3RpY2t5Um93cywgaGVpZ2h0KTtcbiAgICB9O1xuICAgIFN0aWNreVJvd0ZlYXR1cmUucHJvdG90eXBlLnJlZnJlc2hOb2Rlc0FuZENvbnRhaW5lckhlaWdodCA9IGZ1bmN0aW9uIChhbGxTdGlja3lOb2RlcywgaGVpZ2h0KSB7XG4gICAgICAgIHZhciBlXzEsIF9hLCBfYjtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlbW92ZWRDdHJscyA9IHRoaXMuc3RpY2t5Um93Q3RybHMuZmlsdGVyKGZ1bmN0aW9uIChjdHJsKSB7IHJldHVybiBhbGxTdGlja3lOb2Rlcy5pbmRleE9mKGN0cmwuZ2V0Um93Tm9kZSgpKSA9PT0gLTE7IH0pO1xuICAgICAgICB2YXIgYWRkZWROb2RlcyA9IGFsbFN0aWNreU5vZGVzLmZpbHRlcihmdW5jdGlvbiAocm93Tm9kZSkgeyByZXR1cm4gX3RoaXMuc3RpY2t5Um93Q3RybHMuZmluZEluZGV4KGZ1bmN0aW9uIChjdHJsKSB7IHJldHVybiBjdHJsLmdldFJvd05vZGUoKSA9PT0gcm93Tm9kZTsgfSkgPT09IC0xOyB9KTtcbiAgICAgICAgdmFyIGN0cmxzVG9EZXN0cm95ID0ge307XG4gICAgICAgIHJlbW92ZWRDdHJscy5mb3JFYWNoKGZ1bmN0aW9uIChyZW1vdmVkQ3RybCkge1xuICAgICAgICAgICAgY3RybHNUb0Rlc3Ryb3lbcmVtb3ZlZEN0cmwuZ2V0Um93Tm9kZSgpLmlkXSA9IHJlbW92ZWRDdHJsO1xuICAgICAgICAgICAgX3RoaXMuc3RpY2t5Um93Q3RybHMgPSBfdGhpcy5zdGlja3lSb3dDdHJscy5maWx0ZXIoZnVuY3Rpb24gKGN0cmwpIHsgcmV0dXJuIGN0cmwgIT09IHJlbW92ZWRDdHJsOyB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3IgKHZhciBfYyA9IF9fdmFsdWVzJDEoT2JqZWN0LnZhbHVlcyhjdHJsc1RvRGVzdHJveSkpLCBfZCA9IF9jLm5leHQoKTsgIV9kLmRvbmU7IF9kID0gX2MubmV4dCgpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGN0cmwgPSBfZC52YWx1ZTtcbiAgICAgICAgICAgICAgICBjdHJsLmdldFJvd05vZGUoKS5zdGlja3kgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZV8xXzEpIHsgZV8xID0geyBlcnJvcjogZV8xXzEgfTsgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKF9kICYmICFfZC5kb25lICYmIChfYSA9IF9jLnJldHVybikpIF9hLmNhbGwoX2MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7IGlmIChlXzEpIHRocm93IGVfMS5lcnJvcjsgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVzdHJveVJvd0N0cmxzKGN0cmxzVG9EZXN0cm95LCBmYWxzZSk7XG4gICAgICAgIHZhciBuZXdDdHJscyA9IGFkZGVkTm9kZXMubWFwKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICByb3dOb2RlLnN0aWNreSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gX3RoaXMuY3JlYXRlUm93Q29uKHJvd05vZGUsIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICAoX2IgPSB0aGlzLnN0aWNreVJvd0N0cmxzKS5wdXNoLmFwcGx5KF9iLCBfX3NwcmVhZCQ5KG5ld0N0cmxzKSk7XG4gICAgICAgIHRoaXMuc3RpY2t5Um93Q3RybHMuZm9yRWFjaChmdW5jdGlvbiAoY3RybCkgeyByZXR1cm4gY3RybC5zZXRSb3dUb3AoY3RybC5nZXRSb3dOb2RlKCkuc3RpY2t5Um93VG9wKTsgfSk7XG4gICAgICAgIHRoaXMuc3RpY2t5Um93Q3RybHMuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYi5nZXRSb3dOb2RlKCkucm93SW5kZXggLSBhLmdldFJvd05vZGUoKS5yb3dJbmRleDsgfSk7XG4gICAgICAgIGlmICh0aGlzLmNvbnRhaW5lckhlaWdodCAhPT0gaGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRhaW5lckhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEJvZHlDdHJsLnNldFN0aWNreVRvcEhlaWdodChoZWlnaHQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDE0KFtcbiAgICAgICAgQXV0b3dpcmVkKFwicm93TW9kZWxcIilcbiAgICBdLCBTdGlja3lSb3dGZWF0dXJlLnByb3RvdHlwZSwgXCJyb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTQoW1xuICAgICAgICBBdXRvd2lyZWQoXCJyb3dSZW5kZXJlclwiKVxuICAgIF0sIFN0aWNreVJvd0ZlYXR1cmUucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxNChbXG4gICAgICAgIEF1dG93aXJlZChcImN0cmxzU2VydmljZVwiKVxuICAgIF0sIFN0aWNreVJvd0ZlYXR1cmUucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTQoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgU3RpY2t5Um93RmVhdHVyZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gU3RpY2t5Um93RmVhdHVyZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxYSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMTMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3JlYWQkYSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCQ4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJGEoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBSb3dSZW5kZXJlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMWEoUm93UmVuZGVyZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUm93UmVuZGVyZXIoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5kZXN0cm95RnVuY3NGb3JDb2x1bW5MaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgLy8gbWFwIG9mIHJvdyBpZHMgdG8gcm93IG9iamVjdHMuIGtlZXBzIHRyYWNrIG9mIHdoaWNoIGVsZW1lbnRzXG4gICAgICAgIC8vIGFyZSByZW5kZXJlZCBmb3Igd2hpY2ggcm93cyBpbiB0aGUgZG9tLlxuICAgICAgICBfdGhpcy5yb3dDdHJsc0J5Um93SW5kZXggPSB7fTtcbiAgICAgICAgX3RoaXMuem9tYmllUm93Q3RybHMgPSB7fTtcbiAgICAgICAgX3RoaXMuYWxsUm93Q3RybHMgPSBbXTtcbiAgICAgICAgX3RoaXMudG9wUm93Q3RybHMgPSBbXTtcbiAgICAgICAgX3RoaXMuYm90dG9tUm93Q3RybHMgPSBbXTtcbiAgICAgICAgLy8gd2Ugb25seSBhbGxvdyBvbmUgcmVmcmVzaCBhdCBhIHRpbWUsIG90aGVyd2lzZSB0aGUgaW50ZXJuYWwgbWVtb3J5IHN0cnVjdHVyZSBoZXJlXG4gICAgICAgIC8vIHdpbGwgZ2V0IG1lc3NlZCB1cC4gdGhpcyBjYW4gaGFwcGVuIGlmIHRoZSB1c2VyIGhhcyBhIGNlbGxSZW5kZXJlciwgYW5kIGluc2lkZSB0aGVcbiAgICAgICAgLy8gcmVuZGVyZXIgdGhleSBjYWxsIGFuIEFQSSBtZXRob2QgdGhhdCByZXN1bHRzIGluIGFub3RoZXIgcGFzcyBvZiB0aGUgcmVmcmVzaCxcbiAgICAgICAgLy8gdGhlbiBpdCB3aWxsIGJlIHRyeWluZyB0byBkcmF3IHJvd3MgaW4gdGhlIG1pZGRsZSBvZiBhIHJlZnJlc2guXG4gICAgICAgIF90aGlzLnJlZnJlc2hJblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmRhdGFGaXJzdFJlbmRlcmVkRmlyZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmdyaWRCb2R5Q3RybCA9IF90aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgICAgIF90aGlzLmluaXRpYWxpc2UoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuaW5pdGlhbGlzZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9QQUdJTkFUSU9OX0NIQU5HRUQsIHRoaXMub25QYWdlTG9hZGVkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BJTk5FRF9ST1dfREFUQV9DSEFOR0VELCB0aGlzLm9uUGlubmVkUm93RGF0YUNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfQ0hBTkdFRCwgdGhpcy5vbkRpc3BsYXllZENvbHVtbnNDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0JPRFlfU0NST0xMLCB0aGlzLnJlZHJhd0FmdGVyU2Nyb2xsLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0JPRFlfSEVJR0hUX0NIQU5HRUQsIHRoaXMucmVkcmF3QWZ0ZXJTY3JvbGwuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET01fTEFZT1VULCB0aGlzLm9uRG9tTGF5b3V0Q2hhbmdlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX1JPV19DTEFTUywgdGhpcy5yZWRyYXdSb3dzLmJpbmQodGhpcykpO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFJvd3NTdGlja3koKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucm93TW9kZWwuZ2V0VHlwZSgpICE9IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERSkge1xuICAgICAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZSBmZWF0dXJlIFN0aWNreSBSb3cgR3JvdXBzIG9ubHkgd29ya3Mgd2l0aCB0aGUgQ2xpZW50IFNpZGUgUm93IE1vZGVsJyk7IH0sICdyb3dSZW5kZXJlci5zdGlja3lXb3Jrc1dpdGhDc3JtT25seScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNUcmVlRGF0YSgpKSB7XG4gICAgICAgICAgICAgICAgZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogVGhlIGZlYXR1cmUgU3RpY2t5IFJvdyBHcm91cHMgZG9lcyBub3Qgd29yayB3aXRoIFRyZWUgRGF0YS4nKTsgfSwgJ3Jvd1JlbmRlcmVyLnN0aWNreURvZXNOb3RXb3JrV2l0aFRyZWVEYXRhJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0aWNreVJvd0ZlYXR1cmUgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBTdGlja3lSb3dGZWF0dXJlKHRoaXMuY3JlYXRlUm93Q29uLmJpbmQodGhpcyksIHRoaXMuZGVzdHJveVJvd0N0cmxzLmJpbmQodGhpcykpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlZ2lzdGVyQ2VsbEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGlzZUNhY2hlKCk7XG4gICAgICAgIHRoaXMucHJpbnRMYXlvdXQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21MYXlvdXQoKSA9PT0gQ29uc3RhbnRzLkRPTV9MQVlPVVRfUFJJTlQ7XG4gICAgICAgIHRoaXMuZW1iZWRGdWxsV2lkdGhSb3dzID0gdGhpcy5wcmludExheW91dCB8fCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VtYmVkRnVsbFdpZHRoUm93cygpO1xuICAgICAgICB0aGlzLnJlZHJhd0FmdGVyTW9kZWxVcGRhdGUoKTtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5pbml0aWFsaXNlQ2FjaGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0tlZXBEZXRhaWxSb3dzKCkpIHtcbiAgICAgICAgICAgIHZhciBjb3VudFByb3AgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRLZWVwRGV0YWlsUm93c0NvdW50KCk7XG4gICAgICAgICAgICB2YXIgY291bnQgPSBjb3VudFByb3AgIT0gbnVsbCA/IGNvdW50UHJvcCA6IDM7XG4gICAgICAgICAgICB0aGlzLmNhY2hlZFJvd0N0cmxzID0gbmV3IFJvd0N0cmxDYWNoZShjb3VudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRSb3dDdHJscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWxsUm93Q3RybHM7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZ2V0U3RpY2t5VG9wUm93Q3RybHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zdGlja3lSb3dGZWF0dXJlKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RpY2t5Um93RmVhdHVyZS5nZXRTdGlja3lSb3dDdHJscygpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnVwZGF0ZUFsbFJvd0N0cmxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGl2ZUxpc3QgPSBnZXRBbGxWYWx1ZXNJbk9iamVjdCh0aGlzLnJvd0N0cmxzQnlSb3dJbmRleCk7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0Vuc3VyZURvbU9yZGVyKCkpIHtcbiAgICAgICAgICAgIGxpdmVMaXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEuZ2V0Um93Tm9kZSgpLnJvd0luZGV4IC0gYi5nZXRSb3dOb2RlLnJvd0luZGV4OyB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgem9tYmllTGlzdCA9IGdldEFsbFZhbHVlc0luT2JqZWN0KHRoaXMuem9tYmllUm93Q3RybHMpO1xuICAgICAgICB2YXIgY2FjaGVkTGlzdCA9IHRoaXMuY2FjaGVkUm93Q3RybHMgPyB0aGlzLmNhY2hlZFJvd0N0cmxzLmdldEVudHJpZXMoKSA6IFtdO1xuICAgICAgICB0aGlzLmFsbFJvd0N0cmxzID0gX19zcHJlYWQkOChsaXZlTGlzdCwgem9tYmllTGlzdCwgY2FjaGVkTGlzdCk7XG4gICAgfTtcbiAgICAvLyBpbiBhIGNsZWFuIGRlc2lnbiwgZWFjaCBjZWxsIHdvdWxkIHJlZ2lzdGVyIGZvciBlYWNoIG9mIHRoZXNlIGV2ZW50cy4gaG93ZXZlciB3aGVuIHNjcm9sbGluZywgYWxsIHRoZSBjZWxsc1xuICAgIC8vIHJlZ2lzdGVyaW5nIGFuZCBkZS1yZWdpc3RlcmluZyBmb3IgZXZlbnRzIGlzIGEgcGVyZm9ybWFuY2UgYm90dGxlbmVjay4gc28gd2UgcmVnaXN0ZXIgaGVyZSBvbmNlIGFuZCBpbmZvcm1cbiAgICAvLyBhbGwgYWN0aXZlIGNlbGxzLlxuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5yZWdpc3RlckNlbGxFdmVudExpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DRUxMX0ZPQ1VTRUQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgX3RoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHsgcmV0dXJuIGNlbGxDdHJsLm9uQ2VsbEZvY3VzZWQoZXZlbnQpOyB9KTtcbiAgICAgICAgICAgIF90aGlzLmdldEZ1bGxXaWR0aFJvd0N0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAocm93Q3RybCkge1xuICAgICAgICAgICAgICAgIHJvd0N0cmwub25GdWxsV2lkdGhSb3dGb2N1c2VkKGV2ZW50KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9GTEFTSF9DRUxMUywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBfdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwub25GbGFzaENlbGxzKGV2ZW50KTsgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9IT1ZFUl9DSEFOR0VELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwub25Db2x1bW5Ib3ZlcigpOyB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfQ0hBTkdFRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHsgcmV0dXJuIGNlbGxDdHJsLm9uRGlzcGxheWVkQ29sdW1uc0NoYW5nZWQoKTsgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBvbmx5IGZvciBwcmludExheW91dCAtIGJlY2F1c2Ugd2UgYXJlIHJlbmRlcmluZyBhbGwgdGhlIGNlbGxzIGluIHRoZSBzYW1lIHJvdywgcmVnYXJkbGVzcyBvZiBwaW5uZWQgc3RhdGUsXG4gICAgICAgIC8vIHRoZW4gY2hhbmdpbmcgdGhlIHdpZHRoIG9mIHRoZSBjb250YWluZXJzIHdpbGwgaW1wYWN0IGxlZnQgcG9zaXRpb24uIGVnIHRoZSBjZW50ZXIgY29scyBhbGwgaGF2ZSB0aGVpclxuICAgICAgICAvLyBsZWZ0IHBvc2l0aW9uIGFkanVzdGVkIGJ5IHRoZSB3aWR0aCBvZiB0aGUgbGVmdCBwaW5uZWQgY29sdW1uLCBzbyBpZiB0aGUgcGlubmVkIGxlZnQgY29sdW1uIHdpZHRoIGNoYW5nZXMsXG4gICAgICAgIC8vIGFsbCB0aGUgY2VudGVyIGNvbHMgbmVlZCB0byBiZSBzaGlmdGVkIHRvIGFjY29tbW9kYXRlIHRoaXMuIHdoZW4gaW4gbm9ybWFsIGxheW91dCwgdGhlIHBpbm5lZCBjb2xzIGFyZVxuICAgICAgICAvLyBpbiBkaWZmZXJlbnQgY29udGFpbmVycyBzbyBkb2Vzbid0IGltcGFjdC5cbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19XSURUSF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoX3RoaXMucHJpbnRMYXlvdXQpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwub25MZWZ0Q2hhbmdlZCgpOyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHZhciByYW5nZVNlbGVjdGlvbkVuYWJsZWQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJhbmdlU2VsZWN0aW9uKCk7XG4gICAgICAgIGlmIChyYW5nZVNlbGVjdGlvbkVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfUkFOR0VfU0VMRUNUSU9OX0NIQU5HRUQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwub25SYW5nZVNlbGVjdGlvbkNoYW5nZWQoKTsgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX01PVkVELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHsgcmV0dXJuIGNlbGxDdHJsLnVwZGF0ZVJhbmdlQm9yZGVyc0lmUmFuZ2VDb3VudCgpOyB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUElOTkVELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHsgcmV0dXJuIGNlbGxDdHJsLnVwZGF0ZVJhbmdlQm9yZGVyc0lmUmFuZ2VDb3VudCgpOyB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fVklTSUJMRSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmdldEFsbENlbGxDdHJscygpLmZvckVhY2goZnVuY3Rpb24gKGNlbGxDdHJsKSB7IHJldHVybiBjZWxsQ3RybC51cGRhdGVSYW5nZUJvcmRlcnNJZlJhbmdlQ291bnQoKTsgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBhZGQgbGlzdGVuZXJzIHRvIHRoZSBncmlkIGNvbHVtbnNcbiAgICAgICAgdGhpcy5yZWZyZXNoTGlzdGVuZXJzVG9Db2x1bW5zRm9yQ2VsbENvbXBzKCk7XG4gICAgICAgIC8vIGlmIHRoZSBncmlkIGNvbHVtbnMgY2hhbmdlLCB0aGVuIHJlZnJlc2ggdGhlIGxpc3RlbmVycyBhZ2FpblxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0dSSURfQ09MVU1OU19DSEFOR0VELCB0aGlzLnJlZnJlc2hMaXN0ZW5lcnNUb0NvbHVtbnNGb3JDZWxsQ29tcHMuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkRGVzdHJveUZ1bmModGhpcy5yZW1vdmVHcmlkQ29sdW1uTGlzdGVuZXJzLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgLy8gZXhlY3V0ZXMgYWxsIGZ1bmN0aW9ucyBpbiBkZXN0cm95RnVuY3NGb3JDb2x1bW5MaXN0ZW5lcnMgYW5kIHRoZW4gY2xlYXJzIHRoZSBsaXN0XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlbW92ZUdyaWRDb2x1bW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveUZ1bmNzRm9yQ29sdW1uTGlzdGVuZXJzLmZvckVhY2goZnVuY3Rpb24gKGZ1bmMpIHsgcmV0dXJuIGZ1bmMoKTsgfSk7XG4gICAgICAgIHRoaXMuZGVzdHJveUZ1bmNzRm9yQ29sdW1uTGlzdGVuZXJzLmxlbmd0aCA9IDA7XG4gICAgfTtcbiAgICAvLyB0aGlzIGZ1bmN0aW9uIGFkZHMgbGlzdGVuZXJzIG9udG8gYWxsIHRoZSBncmlkIGNvbHVtbnMsIHdoaWNoIGFyZSB0aGUgY29sdW1uIHRoYXQgd2UgY291bGQgaGF2ZSBjZWxsQ29tcHMgZm9yLlxuICAgIC8vIHdoZW4gdGhlIGdyaWQgY29sdW1ucyBjaGFuZ2UsIHdlIGFkZCBsaXN0ZW5lcnMgYWdhaW4uIGluIGFuIGlkZWFsIGRlc2lnbiwgZWFjaCBDZWxsQ29tcCB3b3VsZCBqdXN0IHJlZ2lzdGVyIHRvXG4gICAgLy8gdGhlIGNvbHVtbiBpdCBiZWxvbmdzIHRvIG9uIGNyZWF0aW9uLCBob3dldmVyIHRoaXMgd2FzIGEgYm90dGxlbmVjayB3aXRoIHRoZSBudW1iZXIgb2YgY2VsbHMsIHNvIGRvIGl0IGhlcmVcbiAgICAvLyBvbmNlIGluc3RlYWQuXG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlZnJlc2hMaXN0ZW5lcnNUb0NvbHVtbnNGb3JDZWxsQ29tcHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMucmVtb3ZlR3JpZENvbHVtbkxpc3RlbmVycygpO1xuICAgICAgICB2YXIgY29scyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsR3JpZENvbHVtbnMoKTtcbiAgICAgICAgaWYgKCFjb2xzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29scy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHtcbiAgICAgICAgICAgIHZhciBmb3JFYWNoQ2VsbFdpdGhUaGlzQ29sID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNlbGxDdHJsLmdldENvbHVtbigpID09PSBjb2wpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGNlbGxDdHJsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBsZWZ0Q2hhbmdlZExpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZvckVhY2hDZWxsV2l0aFRoaXNDb2woZnVuY3Rpb24gKGNlbGxDdHJsKSB7IHJldHVybiBjZWxsQ3RybC5vbkxlZnRDaGFuZ2VkKCk7IH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciB3aWR0aENoYW5nZWRMaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBmb3JFYWNoQ2VsbFdpdGhUaGlzQ29sKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwub25XaWR0aENoYW5nZWQoKTsgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGZpcnN0UmlnaHRQaW5uZWRDaGFuZ2VkTGlzdGVuZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZm9yRWFjaENlbGxXaXRoVGhpc0NvbChmdW5jdGlvbiAoY2VsbEN0cmwpIHsgcmV0dXJuIGNlbGxDdHJsLm9uRmlyc3RSaWdodFBpbm5lZENoYW5nZWQoKTsgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGxhc3RMZWZ0UGlubmVkQ2hhbmdlZExpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZvckVhY2hDZWxsV2l0aFRoaXNDb2woZnVuY3Rpb24gKGNlbGxDdHJsKSB7IHJldHVybiBjZWxsQ3RybC5vbkxhc3RMZWZ0UGlubmVkQ2hhbmdlZCgpOyB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgY29sRGVmQ2hhbmdlZExpc3RlbmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZvckVhY2hDZWxsV2l0aFRoaXNDb2woZnVuY3Rpb24gKGNlbGxDdHJsKSB7IHJldHVybiBjZWxsQ3RybC5vbkNvbERlZkNoYW5nZWQoKTsgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29sLmFkZEV2ZW50TGlzdGVuZXIoQ29sdW1uLkVWRU5UX0xFRlRfQ0hBTkdFRCwgbGVmdENoYW5nZWRMaXN0ZW5lcik7XG4gICAgICAgICAgICBjb2wuYWRkRXZlbnRMaXN0ZW5lcihDb2x1bW4uRVZFTlRfV0lEVEhfQ0hBTkdFRCwgd2lkdGhDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICAgICAgY29sLmFkZEV2ZW50TGlzdGVuZXIoQ29sdW1uLkVWRU5UX0ZJUlNUX1JJR0hUX1BJTk5FRF9DSEFOR0VELCBmaXJzdFJpZ2h0UGlubmVkQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgICAgIGNvbC5hZGRFdmVudExpc3RlbmVyKENvbHVtbi5FVkVOVF9MQVNUX0xFRlRfUElOTkVEX0NIQU5HRUQsIGxhc3RMZWZ0UGlubmVkQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgICAgIGNvbC5hZGRFdmVudExpc3RlbmVyKENvbHVtbi5FVkVOVF9DT0xfREVGX0NIQU5HRUQsIGNvbERlZkNoYW5nZWRMaXN0ZW5lcik7XG4gICAgICAgICAgICBfdGhpcy5kZXN0cm95RnVuY3NGb3JDb2x1bW5MaXN0ZW5lcnMucHVzaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgY29sLnJlbW92ZUV2ZW50TGlzdGVuZXIoQ29sdW1uLkVWRU5UX0xFRlRfQ0hBTkdFRCwgbGVmdENoYW5nZWRMaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgY29sLnJlbW92ZUV2ZW50TGlzdGVuZXIoQ29sdW1uLkVWRU5UX1dJRFRIX0NIQU5HRUQsIHdpZHRoQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICBjb2wucmVtb3ZlRXZlbnRMaXN0ZW5lcihDb2x1bW4uRVZFTlRfRklSU1RfUklHSFRfUElOTkVEX0NIQU5HRUQsIGZpcnN0UmlnaHRQaW5uZWRDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIGNvbC5yZW1vdmVFdmVudExpc3RlbmVyKENvbHVtbi5FVkVOVF9MQVNUX0xFRlRfUElOTkVEX0NIQU5HRUQsIGxhc3RMZWZ0UGlubmVkQ2hhbmdlZExpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICBjb2wucmVtb3ZlRXZlbnRMaXN0ZW5lcihDb2x1bW4uRVZFTlRfQ09MX0RFRl9DSEFOR0VELCBjb2xEZWZDaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLm9uRG9tTGF5b3V0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByaW50TGF5b3V0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tTGF5b3V0KCkgPT09IENvbnN0YW50cy5ET01fTEFZT1VUX1BSSU5UO1xuICAgICAgICB2YXIgZW1iZWRGdWxsV2lkdGhSb3dzID0gcHJpbnRMYXlvdXQgfHwgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbWJlZEZ1bGxXaWR0aFJvd3MoKTtcbiAgICAgICAgLy8gaWYgbW92aW5nIHRvd2FyZHMgb3IgYXdheSBmcm9tIHByaW50IGxheW91dCwgbWVhbnMgd2UgbmVlZCB0byBkZXN0cm95IGFsbCByb3dzLCBhcyByb3dzIGFyZSBub3QgbGFpZFxuICAgICAgICAvLyBvdXQgdXNpbmcgYWJzb2x1dGUgcG9zaXRpb25pbmcgd2hlbiBkb2luZyBwcmludCBsYXlvdXRcbiAgICAgICAgdmFyIGRlc3Ryb3lSb3dzID0gZW1iZWRGdWxsV2lkdGhSb3dzICE9PSB0aGlzLmVtYmVkRnVsbFdpZHRoUm93cyB8fCB0aGlzLnByaW50TGF5b3V0ICE9PSBwcmludExheW91dDtcbiAgICAgICAgdGhpcy5wcmludExheW91dCA9IHByaW50TGF5b3V0O1xuICAgICAgICB0aGlzLmVtYmVkRnVsbFdpZHRoUm93cyA9IGVtYmVkRnVsbFdpZHRoUm93cztcbiAgICAgICAgaWYgKGRlc3Ryb3lSb3dzKSB7XG4gICAgICAgICAgICB0aGlzLnJlZHJhd0FmdGVyTW9kZWxVcGRhdGUoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gZm9yIHJvdyBtb2RlbHMgdGhhdCBoYXZlIGRhdGFzb3VyY2VzLCB3aGVuIHdlIHVwZGF0ZSB0aGUgZGF0YXNvdXJjZSwgd2UgbmVlZCB0byBmb3JjZSB0aGUgcm93UmVuZGVyZXJcbiAgICAvLyB0byByZWRyYXcgYWxsIHJvd3MuIG90aGVyd2lzZSB0aGUgb2xkIHJvd3MgZnJvbSB0aGUgb2xkIGRhdGFzb3VyY2Ugd2lsbCBzdGF5IGRpc3BsYXllZC5cbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZGF0YXNvdXJjZUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmlyc3RSZW5kZXJlZFJvdyA9IDA7XG4gICAgICAgIHRoaXMubGFzdFJlbmRlcmVkUm93ID0gLTE7XG4gICAgICAgIHZhciByb3dJbmRleGVzVG9SZW1vdmUgPSBPYmplY3Qua2V5cyh0aGlzLnJvd0N0cmxzQnlSb3dJbmRleCk7XG4gICAgICAgIHRoaXMucmVtb3ZlUm93Q3RybHMocm93SW5kZXhlc1RvUmVtb3ZlKTtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5vblBhZ2VMb2FkZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHJlY3ljbGVSb3dzOiBldmVudC5rZWVwUmVuZGVyZWRSb3dzLFxuICAgICAgICAgICAgYW5pbWF0ZTogZXZlbnQuYW5pbWF0ZSxcbiAgICAgICAgICAgIG5ld0RhdGE6IGV2ZW50Lm5ld0RhdGEsXG4gICAgICAgICAgICBuZXdQYWdlOiBldmVudC5uZXdQYWdlLFxuICAgICAgICAgICAgLy8gYmVjYXVzZSB0aGlzIGlzIGEgbW9kZWwgdXBkYXRlZCBldmVudCAobm90IHBpbm5lZCByb3dzKSwgd2VcbiAgICAgICAgICAgIC8vIGNhbiBza2lwIHVwZGF0aW5nIHRoZSBwaW5uZWQgcm93cy4gdGhpcyBpcyBuZWVkZWQgc28gdGhhdCBpZiB1c2VyXG4gICAgICAgICAgICAvLyBpcyBkb2luZyB0cmFuc2FjdGlvbiB1cGRhdGVzLCB0aGUgcGlubmVkIHJvd3MgYXJlIG5vdCBnZXR0aW5nIGNvbnN0YW50bHlcbiAgICAgICAgICAgIC8vIHRyYXNoZWQgLSBvciBlZGl0aW5nIGNlbGxzIGluIHBpbm5lZCByb3dzIGFyZSBub3QgcmVmcmVzaGVkIGFuZCBwdXQgaW50byByZWFkIG1vZGVcbiAgICAgICAgICAgIG9ubHlCb2R5OiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucmVkcmF3QWZ0ZXJNb2RlbFVwZGF0ZShwYXJhbXMpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldEFsbENlbGxzRm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICB2YXIgcmVzID0gW107XG4gICAgICAgIHRoaXMuZ2V0QWxsUm93Q3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChyb3dDdHJsKSB7XG4gICAgICAgICAgICB2YXIgZUNlbGwgPSByb3dDdHJsLmdldENlbGxFbGVtZW50KGNvbHVtbik7XG4gICAgICAgICAgICBpZiAoZUNlbGwpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChlQ2VsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlZnJlc2hGbG9hdGluZ1Jvd0NvbXBzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlZnJlc2hGbG9hdGluZ1Jvd3ModGhpcy50b3BSb3dDdHJscywgdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRUb3BSb3dEYXRhKCkpO1xuICAgICAgICB0aGlzLnJlZnJlc2hGbG9hdGluZ1Jvd3ModGhpcy5ib3R0b21Sb3dDdHJscywgdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Sb3dEYXRhKCkpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldFRvcFJvd0N0cmxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b3BSb3dDdHJscztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRCb3R0b21Sb3dDdHJscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYm90dG9tUm93Q3RybHM7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUucmVmcmVzaEZsb2F0aW5nUm93cyA9IGZ1bmN0aW9uIChyb3dDb21wcywgcm93Tm9kZXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcm93Q29tcHMuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgICAgICByb3cuZGVzdHJveUZpcnN0UGFzcygpO1xuICAgICAgICAgICAgcm93LmRlc3Ryb3lTZWNvbmRQYXNzKCk7XG4gICAgICAgIH0pO1xuICAgICAgICByb3dDb21wcy5sZW5ndGggPSAwO1xuICAgICAgICBpZiAoIXJvd05vZGVzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcm93Tm9kZXMuZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICAgICAgdmFyIHJvd0N0cmwgPSBuZXcgUm93Q3RybChyb3dOb2RlLCBfdGhpcy5iZWFucywgZmFsc2UsIGZhbHNlLCBfdGhpcy5wcmludExheW91dCk7XG4gICAgICAgICAgICByb3dDb21wcy5wdXNoKHJvd0N0cmwpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5vblBpbm5lZFJvd0RhdGFDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyByZWN5Y2xpbmcgcm93cyBpbiBvcmRlciB0byBlbnN1cmUgY2VsbCBlZGl0aW5nIGlzIG5vdCBjYW5jZWxsZWRcbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHJlY3ljbGVSb3dzOiB0cnVlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucmVkcmF3QWZ0ZXJNb2RlbFVwZGF0ZShwYXJhbXMpO1xuICAgIH07XG4gICAgLy8gaWYgdGhlIHJvdyBub2RlcyBhcmUgbm90IHJlbmRlcmVkLCBubyBpbmRleCBpcyByZXR1cm5lZFxuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRSZW5kZXJlZEluZGV4ZXNGb3JSb3dOb2RlcyA9IGZ1bmN0aW9uIChyb3dOb2Rlcykge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIGlmIChtaXNzaW5nKHJvd05vZGVzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMucm93Q3RybHNCeVJvd0luZGV4LCBmdW5jdGlvbiAoaW5kZXgsIHJlbmRlcmVkUm93KSB7XG4gICAgICAgICAgICB2YXIgcm93Tm9kZSA9IHJlbmRlcmVkUm93LmdldFJvd05vZGUoKTtcbiAgICAgICAgICAgIGlmIChyb3dOb2Rlcy5pbmRleE9mKHJvd05vZGUpID49IDApIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChpbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlZHJhd1Jvd3MgPSBmdW5jdGlvbiAocm93Tm9kZXMpIHtcbiAgICAgICAgLy8gaWYgbm8gcm93IG5vZGVzIHByb3ZpZGVkLCB0aGVuIHJlZnJlc2ggZXZlcnl0aGluZ1xuICAgICAgICB2YXIgcGFydGlhbFJlZnJlc2ggPSByb3dOb2RlcyAhPSBudWxsICYmIHJvd05vZGVzLmxlbmd0aCA+IDA7XG4gICAgICAgIGlmIChwYXJ0aWFsUmVmcmVzaCkge1xuICAgICAgICAgICAgdmFyIGluZGV4ZXNUb1JlbW92ZSA9IHRoaXMuZ2V0UmVuZGVyZWRJbmRleGVzRm9yUm93Tm9kZXMocm93Tm9kZXMpO1xuICAgICAgICAgICAgLy8gcmVtb3ZlIHRoZSByb3dzXG4gICAgICAgICAgICB0aGlzLnJlbW92ZVJvd0N0cmxzKGluZGV4ZXNUb1JlbW92ZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWRkIGRyYXcgdGhlbSBhZ2FpblxuICAgICAgICB0aGlzLnJlZHJhd0FmdGVyTW9kZWxVcGRhdGUoe1xuICAgICAgICAgICAgcmVjeWNsZVJvd3M6IHBhcnRpYWxSZWZyZXNoXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldENlbGxUb1Jlc3RvcmVGb2N1c1RvQWZ0ZXJSZWZyZXNoID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHZhciBmb2N1c2VkQ2VsbCA9ICgoX2EgPSBwYXJhbXMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5zdXBwcmVzc0tlZXBGb2N1cykgPyBudWxsIDogdGhpcy5mb2N1c1NlcnZpY2UuZ2V0Rm9jdXNDZWxsVG9Vc2VBZnRlclJlZnJlc2goKTtcbiAgICAgICAgaWYgKGZvY3VzZWRDZWxsID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHRoZSBkb20gaXMgbm90IGFjdHVhbGx5IGZvY3VzZWQgb24gYSBjZWxsLCB0aGVuIHdlIGRvbid0IHRyeSB0byByZWZvY3VzLiB0aGUgcHJvYmxlbSB0aGlzXG4gICAgICAgIC8vIHNvbHZlcyBpcyB3aXRoIGVkaXRpbmcgLSBpZiB0aGUgdXNlciBpcyBlZGl0aW5nLCBlZyBmb2N1cyBpcyBvbiBhIHRleHQgZmllbGQsIGFuZCBub3Qgb24gdGhlXG4gICAgICAgIC8vIGNlbGwgaXRzZWxmLCB0aGVuIHRoZSBjZWxsIGNhbiBiZSByZWdpc3RlcmVkIGFzIGhhdmluZyBmb2N1cywgaG93ZXZlciBpdCdzIHRoZSB0ZXh0IGZpZWxkIHRoYXRcbiAgICAgICAgLy8gaGFzIHRoZSBmb2N1cyBhbmQgbm90IHRoZSBjZWxsIGRpdi4gdGhlcmVmb3JlLCB3aGVuIHRoZSByZWZyZXNoIGlzIGZpbmlzaGVkLCB0aGUgZ3JpZCB3aWxsIGZvY3VzXG4gICAgICAgIC8vIHRoZSBjZWxsLCBhbmQgbm90IHRoZSB0ZXh0ZmllbGQuIHRoYXQgbWVhbnMgaWYgdGhlIHVzZXIgaXMgaW4gYSB0ZXh0IGZpZWxkLCBhbmQgdGhlIGdyaWQgcmVmcmVzaGVzLFxuICAgICAgICAvLyB0aGUgZm9jdXMgaXMgbG9zdCBmcm9tIHRoZSB0ZXh0IGZpZWxkLiB3ZSBkbyBub3Qgd2FudCB0aGlzLlxuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgdmFyIGFjdGl2ZUVsZW1lbnQgPSBlRG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgICAgICAgdmFyIGNlbGxEb21EYXRhID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tRGF0YShhY3RpdmVFbGVtZW50LCBDZWxsQ3RybC5ET01fREFUQV9LRVlfQ0VMTF9DVFJMKTtcbiAgICAgICAgdmFyIHJvd0RvbURhdGEgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21EYXRhKGFjdGl2ZUVsZW1lbnQsIFJvd0N0cmwuRE9NX0RBVEFfS0VZX1JPV19DVFJMKTtcbiAgICAgICAgdmFyIGdyaWRFbGVtZW50Rm9jdXNlZCA9IGNlbGxEb21EYXRhIHx8IHJvd0RvbURhdGE7XG4gICAgICAgIHJldHVybiBncmlkRWxlbWVudEZvY3VzZWQgPyBmb2N1c2VkQ2VsbCA6IG51bGw7XG4gICAgfTtcbiAgICAvLyBnZXRzIGNhbGxlZCBmcm9tOlxuICAgIC8vICspIGluaXRpYWxpc2F0aW9uIChpbiByZWdpc3RlckdyaWRDb21wKSBwYXJhbXMgPSBudWxsXG4gICAgLy8gKykgb25Eb21MYXlvdXRDaGFuZ2VkLCBwYXJhbXMgPSBudWxsXG4gICAgLy8gKykgb25QYWdlTG9hZGVkLCByZWN5Y2xlUm93cywgYW5pbWF0ZSwgbmV3RGF0YSwgbmV3UGFnZSBmcm9tIGV2ZW50LCBvbmx5Qm9keT10cnVlXG4gICAgLy8gKykgb25QaW5uZWRSb3dEYXRhQ2hhbmdlZCwgcmVjeWNsZVJvd3MgPSB0cnVlXG4gICAgLy8gKykgcmVkcmF3Um93cyAoZnJvbSBHcmlkIEFQSSksIHJlY3ljbGVSb3dzID0gdHJ1ZS9mYWxzZVxuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5yZWRyYXdBZnRlck1vZGVsVXBkYXRlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICBpZiAocGFyYW1zID09PSB2b2lkIDApIHsgcGFyYW1zID0ge307IH1cbiAgICAgICAgdGhpcy5nZXRMb2NrT25SZWZyZXNoKCk7XG4gICAgICAgIHZhciBmb2N1c2VkQ2VsbCA9IHRoaXMuZ2V0Q2VsbFRvUmVzdG9yZUZvY3VzVG9BZnRlclJlZnJlc2gocGFyYW1zKTtcbiAgICAgICAgdGhpcy51cGRhdGVDb250YWluZXJIZWlnaHRzKCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsVG9Ub3BJZk5ld0RhdGEocGFyYW1zKTtcbiAgICAgICAgLy8gbmV2ZXIgcmVjeWNsZSByb3dzIHdoZW4gcHJpbnQgbGF5b3V0LCB3ZSBkcmF3IGVhY2ggcm93IGFnYWluIGZyb20gc2NyYXRjaC4gdGhpcyBpcyBiZWNhdXNlIHByaW50IGxheW91dFxuICAgICAgICAvLyB1c2VzIG5vcm1hbCBkb20gbGF5b3V0IHRvIHB1dCBjZWxscyBpbnRvIGRvbSAtIGl0IGRvZXNuJ3QgYWxsb3cgcmVvcmRlcmluZyByb3dzLlxuICAgICAgICB2YXIgcmVjeWNsZVJvd3MgPSAhdGhpcy5wcmludExheW91dCAmJiAhIXBhcmFtcy5yZWN5Y2xlUm93cztcbiAgICAgICAgdmFyIGFuaW1hdGUgPSBwYXJhbXMuYW5pbWF0ZSAmJiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0FuaW1hdGVSb3dzKCk7XG4gICAgICAgIC8vIGFmdGVyIG1vZGVsVXBkYXRlLCByb3cgaW5kZXhlcyBjYW4gY2hhbmdlLCBzbyB3ZSBjbGVhciBvdXQgdGhlIHJvd3NCeUluZGV4IG1hcCxcbiAgICAgICAgLy8gaG93ZXZlciB3ZSBjYW4gcmV1c2UgdGhlIHJvd3MsIHNvIHdlIGtlZXAgdGhlbSBidXQgaW5kZXggYnkgcm93Tm9kZS5pZFxuICAgICAgICB2YXIgcm93c1RvUmVjeWNsZSA9IHJlY3ljbGVSb3dzID8gdGhpcy5yZWN5Y2xlUm93cygpIDogbnVsbDtcbiAgICAgICAgaWYgKCFyZWN5Y2xlUm93cykge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVBbGxSb3dDb21wcygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpc0ZvY3VzZWRDZWxsR2V0dGluZ1JlY3ljbGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGZvY3VzZWRDZWxsID09IG51bGwgfHwgcm93c1RvUmVjeWNsZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlcyA9IGZhbHNlO1xuICAgICAgICAgICAgaXRlcmF0ZU9iamVjdChyb3dzVG9SZWN5Y2xlLCBmdW5jdGlvbiAoa2V5LCByb3dDb21wKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvd05vZGUgPSByb3dDb21wLmdldFJvd05vZGUoKTtcbiAgICAgICAgICAgICAgICB2YXIgcm93SW5kZXhFcXVhbCA9IHJvd05vZGUucm93SW5kZXggPT0gZm9jdXNlZENlbGwucm93SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIHBpbm5lZEVxdWFsID0gcm93Tm9kZS5yb3dQaW5uZWQgPT0gZm9jdXNlZENlbGwucm93UGlubmVkO1xuICAgICAgICAgICAgICAgIGlmIChyb3dJbmRleEVxdWFsICYmIHBpbm5lZEVxdWFsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgZm9jdXNlZENlbGxSZWN5Y2xlZCA9IGlzRm9jdXNlZENlbGxHZXR0aW5nUmVjeWNsZWQoKTtcbiAgICAgICAgdGhpcy5yZWRyYXcocm93c1RvUmVjeWNsZSwgYW5pbWF0ZSk7XG4gICAgICAgIHRoaXMuZ3JpZEJvZHlDdHJsLnVwZGF0ZVJvd0NvdW50KCk7XG4gICAgICAgIGlmICghcGFyYW1zLm9ubHlCb2R5KSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hGbG9hdGluZ1Jvd0NvbXBzKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwYXRjaERpc3BsYXllZFJvd3NDaGFuZ2VkKCk7XG4gICAgICAgIC8vIGlmIHdlIGZvY3VzIGEgY2VsbCB0aGF0J3MgYWxyZWFkeSBmb2N1c2VkLCB0aGVuIHdlIGdldCBhbiB1bm5lY2Vzc2FyeSAnY2VsbEZvY3VzZWQnIGV2ZW50IGZpcmVkLlxuICAgICAgICAvLyB0aGlzIHdhcyBoYXBwZW5pbmcgd2hlbiB1c2VyIGNsaWNrZWQgJ2V4cGFuZCcgb24gYSByb3dHcm91cCwgdGhlbiBjZWxsRm9jdXNlZCB3YXMgZ2V0dGluZyBmaXJlZCB0d2ljZS5cbiAgICAgICAgaWYgKCFmb2N1c2VkQ2VsbFJlY3ljbGVkKSB7XG4gICAgICAgICAgICB0aGlzLnJlc3RvcmVGb2N1c2VkQ2VsbChmb2N1c2VkQ2VsbCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWxlYXNlTG9ja09uUmVmcmVzaCgpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnNjcm9sbFRvVG9wSWZOZXdEYXRhID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgc2Nyb2xsVG9Ub3AgPSBwYXJhbXMubmV3RGF0YSB8fCBwYXJhbXMubmV3UGFnZTtcbiAgICAgICAgdmFyIHN1cHByZXNzU2Nyb2xsVG9Ub3AgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzU2Nyb2xsT25OZXdEYXRhKCk7XG4gICAgICAgIGlmIChzY3JvbGxUb1RvcCAmJiAhc3VwcHJlc3NTY3JvbGxUb1RvcCkge1xuICAgICAgICAgICAgdGhpcy5ncmlkQm9keUN0cmwuZ2V0U2Nyb2xsRmVhdHVyZSgpLnNjcm9sbFRvVG9wKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS51cGRhdGVDb250YWluZXJIZWlnaHRzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB3aGVuIGRvaW5nIHByaW50IGxheW91dCwgd2UgZG9uJ3QgZXhwbGljaXRseSBzZXQgaGVpZ2h0IG9uIHRoZSBjb250YWluZXJzXG4gICAgICAgIGlmICh0aGlzLnByaW50TGF5b3V0KSB7XG4gICAgICAgICAgICB0aGlzLnJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2Uuc2V0TW9kZWxIZWlnaHQobnVsbCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbnRhaW5lckhlaWdodCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldEN1cnJlbnRQYWdlSGVpZ2h0KCk7XG4gICAgICAgIC8vIHdlIG5lZWQgYXQgbGVhc3QgMSBwaXhlbCBmb3IgdGhlIGhvcml6b250YWwgc2Nyb2xsIHRvIHdvcmsuIHNvIGlmIHRoZXJlIGFyZSBub3cgcm93cyxcbiAgICAgICAgLy8gd2Ugc3RpbGwgd2FudCB0aGUgc2Nyb2xsIHRvIGJlIHByZXNlbnQsIG90aGVyd2lzZSB0aGVyZSB3b3VsZCBiZSBubyB3YXkgdG8gc2Nyb2xsIHRoZSBoZWFkZXJcbiAgICAgICAgLy8gd2hpY2ggbWlnaHQgYmUgbmVlZGVkIHVzIHVzZXIgd2FudHMgdG8gYWNjZXNzIGNvbHVtbnNcbiAgICAgICAgLy8gb24gdGhlIFJIUyAtIGFuZCBpZiB0aGF0IHdhcyB3aGVyZSB0aGUgZmlsdGVyIHdhcyB0aGF0IGNhdXNlIG5vIHJvd3MgdG8gYmUgcHJlc2VudGVkLCB0aGVyZVxuICAgICAgICAvLyBpcyBubyB3YXkgdG8gcmVtb3ZlIHRoZSBmaWx0ZXIuXG4gICAgICAgIGlmIChjb250YWluZXJIZWlnaHQgPT09IDApIHtcbiAgICAgICAgICAgIGNvbnRhaW5lckhlaWdodCA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLnNldE1vZGVsSGVpZ2h0KGNvbnRhaW5lckhlaWdodCk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZ2V0TG9ja09uUmVmcmVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVmcmVzaEluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFHIEdyaWQ6IGNhbm5vdCBnZXQgZ3JpZCB0byBkcmF3IHJvd3Mgd2hlbiBpdCBpcyBpbiB0aGUgbWlkZGxlIG9mIGRyYXdpbmcgcm93cy4gXCIgK1xuICAgICAgICAgICAgICAgIFwiWW91ciBjb2RlIHByb2JhYmx5IGNhbGxlZCBhIGdyaWQgQVBJIG1ldGhvZCB3aGlsZSB0aGUgZ3JpZCB3YXMgaW4gdGhlIHJlbmRlciBzdGFnZS4gVG8gb3ZlcmNvbWUgXCIgK1xuICAgICAgICAgICAgICAgIFwidGhpcywgcHV0IHRoZSBBUEkgY2FsbCBpbnRvIGEgdGltZW91dCwgZS5nLiBpbnN0ZWFkIG9mIGFwaS5yZWRyYXdSb3dzKCksIFwiICtcbiAgICAgICAgICAgICAgICBcImNhbGwgc2V0VGltZW91dChmdW5jdGlvbigpIHsgYXBpLnJlZHJhd1Jvd3MoKTsgfSwgMCkuIFRvIHNlZSB3aGF0IHBhcnQgb2YgeW91ciBjb2RlIFwiICtcbiAgICAgICAgICAgICAgICBcInRoYXQgY2F1c2VkIHRoZSByZWZyZXNoIGNoZWNrIHRoaXMgc3RhY2t0cmFjZS5cIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWZyZXNoSW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUucmVsZWFzZUxvY2tPblJlZnJlc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVmcmVzaEluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5pc1JlZnJlc2hJblByb2dyZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoSW5Qcm9ncmVzcztcbiAgICB9O1xuICAgIC8vIHNldHMgdGhlIGZvY3VzIHRvIHRoZSBwcm92aWRlZCBjZWxsLCBpZiB0aGUgY2VsbCBpcyBwcm92aWRlZC4gdGhpcyB3YXksIHRoZSB1c2VyIGNhbiBjYWxsIHJlZnJlc2ggd2l0aG91dFxuICAgIC8vIHdvcnJ5IGFib3V0IHRoZSBmb2N1cyBiZWVuIGxvc3QuIHRoaXMgaXMgaW1wb3J0YW50IHdoZW4gdGhlIHVzZXIgaXMgdXNpbmcga2V5Ym9hcmQgbmF2aWdhdGlvbiB0byBkbyBlZGl0c1xuICAgIC8vIGFuZCB0aGUgY2VsbEVkaXRvciBpcyBjYWxsaW5nICdyZWZyZXNoJyB0byBnZXQgb3RoZXIgY2VsbHMgdG8gdXBkYXRlIChhcyBvdGhlciBjZWxscyBtaWdodCBkZXBlbmQgb24gdGhlXG4gICAgLy8gZWRpdGVkIGNlbGwpLlxuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5yZXN0b3JlRm9jdXNlZENlbGwgPSBmdW5jdGlvbiAoY2VsbFBvc2l0aW9uKSB7XG4gICAgICAgIGlmIChjZWxsUG9zaXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNTZXJ2aWNlLnNldEZvY3VzZWRDZWxsKHtcbiAgICAgICAgICAgICAgICByb3dJbmRleDogY2VsbFBvc2l0aW9uLnJvd0luZGV4LFxuICAgICAgICAgICAgICAgIGNvbHVtbjogY2VsbFBvc2l0aW9uLmNvbHVtbixcbiAgICAgICAgICAgICAgICByb3dQaW5uZWQ6IGNlbGxQb3NpdGlvbi5yb3dQaW5uZWQsXG4gICAgICAgICAgICAgICAgZm9yY2VCcm93c2VyRm9jdXM6IHRydWUsXG4gICAgICAgICAgICAgICAgcHJldmVudFNjcm9sbE9uQnJvd3NlckZvY3VzOiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnN0b3BFZGl0aW5nID0gZnVuY3Rpb24gKGNhbmNlbCkge1xuICAgICAgICBpZiAoY2FuY2VsID09PSB2b2lkIDApIHsgY2FuY2VsID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy5nZXRBbGxSb3dDdHJscygpLmZvckVhY2goZnVuY3Rpb24gKHJvd0N0cmwpIHtcbiAgICAgICAgICAgIHJvd0N0cmwuc3RvcEVkaXRpbmcoY2FuY2VsKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZ2V0QWxsQ2VsbEN0cmxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzID0gW107XG4gICAgICAgIHRoaXMuZ2V0QWxsUm93Q3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChyb3dDdHJsKSB7IHJldHVybiByZXMgPSByZXMuY29uY2F0KHJvd0N0cmwuZ2V0QWxsQ2VsbEN0cmxzKCkpOyB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRBbGxSb3dDdHJscyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHN0aWNreVJvd0N0cmxzID0gKHRoaXMuc3RpY2t5Um93RmVhdHVyZSAmJiB0aGlzLnN0aWNreVJvd0ZlYXR1cmUuZ2V0U3RpY2t5Um93Q3RybHMoKSkgfHwgW107XG4gICAgICAgIHZhciByZXMgPSBfX3NwcmVhZCQ4KHRoaXMudG9wUm93Q3RybHMsIHRoaXMuYm90dG9tUm93Q3RybHMsIHN0aWNreVJvd0N0cmxzKTtcbiAgICAgICAgT2JqZWN0LmtleXModGhpcy5yb3dDdHJsc0J5Um93SW5kZXgpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gcmVzLnB1c2goX3RoaXMucm93Q3RybHNCeVJvd0luZGV4W2tleV0pOyB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5hZGRSZW5kZXJlZFJvd0xpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50TmFtZSwgcm93SW5kZXgsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciByb3dDb21wID0gdGhpcy5yb3dDdHJsc0J5Um93SW5kZXhbcm93SW5kZXhdO1xuICAgICAgICBpZiAocm93Q29tcCkge1xuICAgICAgICAgICAgcm93Q29tcC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZmxhc2hDZWxscyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PT0gdm9pZCAwKSB7IHBhcmFtcyA9IHt9OyB9XG4gICAgICAgIHZhciBmbGFzaERlbGF5ID0gcGFyYW1zLmZsYXNoRGVsYXksIGZhZGVEZWxheSA9IHBhcmFtcy5mYWRlRGVsYXk7XG4gICAgICAgIHRoaXMuZ2V0Q2VsbEN0cmxzKHBhcmFtcy5yb3dOb2RlcywgcGFyYW1zLmNvbHVtbnMpXG4gICAgICAgICAgICAuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHsgcmV0dXJuIGNlbGxDdHJsLmZsYXNoQ2VsbCh7IGZsYXNoRGVsYXk6IGZsYXNoRGVsYXksIGZhZGVEZWxheTogZmFkZURlbGF5IH0pOyB9KTtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5yZWZyZXNoQ2VsbHMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmIChwYXJhbXMgPT09IHZvaWQgMCkgeyBwYXJhbXMgPSB7fTsgfVxuICAgICAgICB2YXIgcmVmcmVzaENlbGxQYXJhbXMgPSB7XG4gICAgICAgICAgICBmb3JjZVJlZnJlc2g6IHBhcmFtcy5mb3JjZSxcbiAgICAgICAgICAgIG5ld0RhdGE6IGZhbHNlLFxuICAgICAgICAgICAgc3VwcHJlc3NGbGFzaDogcGFyYW1zLnN1cHByZXNzRmxhc2hcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRDZWxsQ3RybHMocGFyYW1zLnJvd05vZGVzLCBwYXJhbXMuY29sdW1ucylcbiAgICAgICAgICAgIC5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkge1xuICAgICAgICAgICAgaWYgKGNlbGxDdHJsLnJlZnJlc2hTaG91bGREZXN0cm95KCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcm93Q3RybCA9IGNlbGxDdHJsLmdldFJvd0N0cmwoKTtcbiAgICAgICAgICAgICAgICBpZiAocm93Q3RybCkge1xuICAgICAgICAgICAgICAgICAgICByb3dDdHJsLnJlZnJlc2hDZWxsKGNlbGxDdHJsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjZWxsQ3RybC5yZWZyZXNoQ2VsbChyZWZyZXNoQ2VsbFBhcmFtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmdldEZ1bGxXaWR0aFJvd0N0cmxzKHBhcmFtcy5yb3dOb2RlcykuZm9yRWFjaChmdW5jdGlvbiAoZnVsbFdpZHRoUm93Q3RybCkge1xuICAgICAgICAgICAgZnVsbFdpZHRoUm93Q3RybC5yZWZyZXNoRnVsbFdpZHRoKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldENlbGxSZW5kZXJlckluc3RhbmNlcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIHJlcyA9IHRoaXMuZ2V0Q2VsbEN0cmxzKHBhcmFtcy5yb3dOb2RlcywgcGFyYW1zLmNvbHVtbnMpXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChjZWxsQ3RybCkgeyByZXR1cm4gY2VsbEN0cmwuZ2V0Q2VsbFJlbmRlcmVyKCk7IH0pXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uIChyZW5kZXJlcikgeyByZXR1cm4gcmVuZGVyZXIgIT0gbnVsbDsgfSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZ2V0Q2VsbEVkaXRvckluc3RhbmNlcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB0aGlzLmdldENlbGxDdHJscyhwYXJhbXMucm93Tm9kZXMsIHBhcmFtcy5jb2x1bW5zKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkge1xuICAgICAgICAgICAgdmFyIGNlbGxFZGl0b3IgPSBjZWxsQ3RybC5nZXRDZWxsRWRpdG9yKCk7XG4gICAgICAgICAgICBpZiAoY2VsbEVkaXRvcikge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGNlbGxFZGl0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRFZGl0aW5nQ2VsbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXMgPSBbXTtcbiAgICAgICAgdGhpcy5nZXRBbGxDZWxsQ3RybHMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsQ3RybCkge1xuICAgICAgICAgICAgaWYgKGNlbGxDdHJsLmlzRWRpdGluZygpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNlbGxQb3NpdGlvbiA9IGNlbGxDdHJsLmdldENlbGxQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGNlbGxQb3NpdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLm1hcFJvd05vZGVzID0gZnVuY3Rpb24gKHJvd05vZGVzKSB7XG4gICAgICAgIGlmICghcm93Tm9kZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzID0ge1xuICAgICAgICAgICAgdG9wOiB7fSxcbiAgICAgICAgICAgIGJvdHRvbToge30sXG4gICAgICAgICAgICBub3JtYWw6IHt9XG4gICAgICAgIH07XG4gICAgICAgIHJvd05vZGVzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHZhciBpZCA9IHJvd05vZGUuaWQ7XG4gICAgICAgICAgICBpZiAocm93Tm9kZS5yb3dQaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfVE9QKSB7XG4gICAgICAgICAgICAgICAgcmVzLnRvcFtpZF0gPSByb3dOb2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocm93Tm9kZS5yb3dQaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfQk9UVE9NKSB7XG4gICAgICAgICAgICAgICAgcmVzLmJvdHRvbVtpZF0gPSByb3dOb2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzLm5vcm1hbFtpZF0gPSByb3dOb2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5pc1Jvd0luTWFwID0gZnVuY3Rpb24gKHJvd05vZGUsIHJvd0lkc01hcCkge1xuICAgICAgICAvLyBza2lwIHRoaXMgcm93IGlmIGl0IGlzIG1pc3NpbmcgZnJvbSB0aGUgcHJvdmlkZWQgbGlzdFxuICAgICAgICB2YXIgaWQgPSByb3dOb2RlLmlkO1xuICAgICAgICB2YXIgZmxvYXRpbmcgPSByb3dOb2RlLnJvd1Bpbm5lZDtcbiAgICAgICAgaWYgKGZsb2F0aW5nID09PSBDb25zdGFudHMuUElOTkVEX0JPVFRPTSkge1xuICAgICAgICAgICAgcmV0dXJuIHJvd0lkc01hcC5ib3R0b21baWRdICE9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZsb2F0aW5nID09PSBDb25zdGFudHMuUElOTkVEX1RPUCkge1xuICAgICAgICAgICAgcmV0dXJuIHJvd0lkc01hcC50b3BbaWRdICE9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd0lkc01hcC5ub3JtYWxbaWRdICE9IG51bGw7XG4gICAgfTtcbiAgICAvLyByZXR1cm5zIENlbGxDdHJsJ3MgdGhhdCBtYXRjaCB0aGUgcHJvdmlkZWQgcm93Tm9kZXMgYW5kIGNvbHVtbnMuIGVnIGlmIG9uZSByb3cgbm9kZVxuICAgIC8vIGFuZCB0d28gY29sdW1ucyBwcm92aWRlZCwgdGhhdCBpZGVudGlmaWVzIDQgY2VsbHMsIHNvIDQgQ2VsbEN0cmwncyByZXR1cm5lZC5cbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZ2V0Q2VsbEN0cmxzID0gZnVuY3Rpb24gKHJvd05vZGVzLCBjb2x1bW5zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciByb3dJZHNNYXAgPSB0aGlzLm1hcFJvd05vZGVzKHJvd05vZGVzKTtcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB2YXIgY29sSWRzTWFwO1xuICAgICAgICBpZiAoZXhpc3RzKGNvbHVtbnMpKSB7XG4gICAgICAgICAgICBjb2xJZHNNYXAgPSB7fTtcbiAgICAgICAgICAgIGNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAoY29sS2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbiA9IF90aGlzLmNvbHVtbk1vZGVsLmdldEdyaWRDb2x1bW4oY29sS2V5KTtcbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RzKGNvbHVtbikpIHtcbiAgICAgICAgICAgICAgICAgICAgY29sSWRzTWFwW2NvbHVtbi5nZXRJZCgpXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByb2Nlc3NSb3cgPSBmdW5jdGlvbiAocm93Q29tcCkge1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSByb3dDb21wLmdldFJvd05vZGUoKTtcbiAgICAgICAgICAgIC8vIHNraXAgdGhpcyByb3cgaWYgaXQgaXMgbWlzc2luZyBmcm9tIHRoZSBwcm92aWRlZCBsaXN0XG4gICAgICAgICAgICBpZiAocm93SWRzTWFwICE9IG51bGwgJiYgIV90aGlzLmlzUm93SW5NYXAocm93Tm9kZSwgcm93SWRzTWFwKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJvd0NvbXAuZ2V0QWxsQ2VsbEN0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoY2VsbEN0cmwpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29sSWQgPSBjZWxsQ3RybC5nZXRDb2x1bW4oKS5nZXRJZCgpO1xuICAgICAgICAgICAgICAgIHZhciBleGNsdWRlQ29sRnJvbVJlZnJlc2ggPSBjb2xJZHNNYXAgJiYgIWNvbElkc01hcFtjb2xJZF07XG4gICAgICAgICAgICAgICAgaWYgKGV4Y2x1ZGVDb2xGcm9tUmVmcmVzaCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGNlbGxDdHJsKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMucm93Q3RybHNCeVJvd0luZGV4LCBmdW5jdGlvbiAoaW5kZXgsIHJvd0NvbXApIHtcbiAgICAgICAgICAgIHByb2Nlc3NSb3cocm93Q29tcCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodGhpcy50b3BSb3dDdHJscykge1xuICAgICAgICAgICAgdGhpcy50b3BSb3dDdHJscy5mb3JFYWNoKHByb2Nlc3NSb3cpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmJvdHRvbVJvd0N0cmxzKSB7XG4gICAgICAgICAgICB0aGlzLmJvdHRvbVJvd0N0cmxzLmZvckVhY2gocHJvY2Vzc1Jvdyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlbW92ZUFsbFJvd0NvbXBzKCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlbW92ZUFsbFJvd0NvbXBzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93SW5kZXhlc1RvUmVtb3ZlID0gT2JqZWN0LmtleXModGhpcy5yb3dDdHJsc0J5Um93SW5kZXgpO1xuICAgICAgICB0aGlzLnJlbW92ZVJvd0N0cmxzKHJvd0luZGV4ZXNUb1JlbW92ZSk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUucmVjeWNsZVJvd3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHJlbW92ZSBhbGwgc3R1YiBub2RlcywgdGhleSBjYW4ndCBiZSByZXVzZWQsIGFzIG5vIHJvd05vZGUgaWRcbiAgICAgICAgdmFyIHN0dWJOb2RlSW5kZXhlcyA9IFtdO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMucm93Q3RybHNCeVJvd0luZGV4LCBmdW5jdGlvbiAoaW5kZXgsIHJvd0NvbXApIHtcbiAgICAgICAgICAgIHZhciBzdHViTm9kZSA9IHJvd0NvbXAuZ2V0Um93Tm9kZSgpLmlkID09IG51bGw7XG4gICAgICAgICAgICBpZiAoc3R1Yk5vZGUpIHtcbiAgICAgICAgICAgICAgICBzdHViTm9kZUluZGV4ZXMucHVzaChpbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJlbW92ZVJvd0N0cmxzKHN0dWJOb2RlSW5kZXhlcyk7XG4gICAgICAgIC8vIHRoZW4gY2xlYXIgb3V0IHJvd0NvbXBzQnlJbmRleCwgYnV0IGJlZm9yZSB0aGF0IHRha2UgYSBjb3B5LCBidXQgaW5kZXggYnkgaWQsIG5vdCByb3dJbmRleFxuICAgICAgICB2YXIgY3RybHNCeUlkTWFwID0ge307XG4gICAgICAgIGl0ZXJhdGVPYmplY3QodGhpcy5yb3dDdHJsc0J5Um93SW5kZXgsIGZ1bmN0aW9uIChpbmRleCwgcm93Q29tcCkge1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSByb3dDb21wLmdldFJvd05vZGUoKTtcbiAgICAgICAgICAgIGN0cmxzQnlJZE1hcFtyb3dOb2RlLmlkXSA9IHJvd0NvbXA7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJvd0N0cmxzQnlSb3dJbmRleCA9IHt9O1xuICAgICAgICByZXR1cm4gY3RybHNCeUlkTWFwO1xuICAgIH07XG4gICAgLy8gdGFrZXMgYXJyYXkgb2Ygcm93IGluZGV4ZXNcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUucmVtb3ZlUm93Q3RybHMgPSBmdW5jdGlvbiAocm93c1RvUmVtb3ZlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIGlmIG5vIGZyb21JbmRleCB0aGVuIHNldCB0byAtMSwgd2hpY2ggd2lsbCByZWZyZXNoIGV2ZXJ5dGhpbmdcbiAgICAgICAgLy8gbGV0IHJlYWxGcm9tSW5kZXggPSAtMTtcbiAgICAgICAgcm93c1RvUmVtb3ZlLmZvckVhY2goZnVuY3Rpb24gKGluZGV4VG9SZW1vdmUpIHtcbiAgICAgICAgICAgIHZhciByb3dDdHJsID0gX3RoaXMucm93Q3RybHNCeVJvd0luZGV4W2luZGV4VG9SZW1vdmVdO1xuICAgICAgICAgICAgaWYgKHJvd0N0cmwpIHtcbiAgICAgICAgICAgICAgICByb3dDdHJsLmRlc3Ryb3lGaXJzdFBhc3MoKTtcbiAgICAgICAgICAgICAgICByb3dDdHJsLmRlc3Ryb3lTZWNvbmRQYXNzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgX3RoaXMucm93Q3RybHNCeVJvd0luZGV4W2luZGV4VG9SZW1vdmVdO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIGdldHMgY2FsbGVkIHdoZW4gcm93cyBkb24ndCBjaGFuZ2UsIGJ1dCB2aWV3cG9ydCBkb2VzLCBzbyBhZnRlcjpcbiAgICAvLyAxKSBoZWlnaHQgb2YgZ3JpZCBib2R5IGNoYW5nZXMsIGllIG51bWJlciBvZiBkaXNwbGF5ZWQgcm93cyBoYXMgY2hhbmdlZFxuICAgIC8vIDIpIGdyaWQgc2Nyb2xsZWQgdG8gbmV3IHBvc2l0aW9uXG4gICAgLy8gMykgZW5zdXJlIGluZGV4IHZpc2libGUgKHdoaWNoIGlzIGEgc2Nyb2xsKVxuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5yZWRyYXdBZnRlclNjcm9sbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNlbGxGb2N1c2VkO1xuICAgICAgICAvLyBvbmx5IHRyeSB0byByZWZvY3VzIGNlbGxzIHNoaWZ0aW5nIGluIGFuZCBvdXQgb2Ygc3RpY2t5IGNvbnRhaW5lclxuICAgICAgICAvLyBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBmb2N1cyAoeyBwcmV2ZW50U2Nyb2xsIH0pXG4gICAgICAgIGlmICh0aGlzLnN0aWNreVJvd0ZlYXR1cmUgJiYgYnJvd3NlclN1cHBvcnRzUHJldmVudFNjcm9sbCgpKSB7XG4gICAgICAgICAgICBjZWxsRm9jdXNlZCA9IHRoaXMuZ2V0Q2VsbFRvUmVzdG9yZUZvY3VzVG9BZnRlclJlZnJlc2goKSB8fCB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5nZXRMb2NrT25SZWZyZXNoKCk7XG4gICAgICAgIHRoaXMucmVkcmF3KG51bGwsIGZhbHNlLCB0cnVlKTtcbiAgICAgICAgdGhpcy5yZWxlYXNlTG9ja09uUmVmcmVzaCgpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoRGlzcGxheWVkUm93c0NoYW5nZWQoKTtcbiAgICAgICAgaWYgKGNlbGxGb2N1c2VkICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBuZXdGb2N1c2VkQ2VsbCA9IHRoaXMuZ2V0Q2VsbFRvUmVzdG9yZUZvY3VzVG9BZnRlclJlZnJlc2goKTtcbiAgICAgICAgICAgIGlmIChjZWxsRm9jdXNlZCAhPSBudWxsICYmIG5ld0ZvY3VzZWRDZWxsID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFuaW1hdGlvbkZyYW1lU2VydmljZS5mbHVzaEFsbEZyYW1lcygpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZUZvY3VzZWRDZWxsKGNlbGxGb2N1c2VkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlbW92ZVJvd0NvbXBzTm90VG9EcmF3ID0gZnVuY3Rpb24gKGluZGV4ZXNUb0RyYXcpIHtcbiAgICAgICAgLy8gZm9yIHNwZWVkeSBsb29rdXAsIGR1bXAgaW50byBtYXBcbiAgICAgICAgdmFyIGluZGV4ZXNUb0RyYXdNYXAgPSB7fTtcbiAgICAgICAgaW5kZXhlc1RvRHJhdy5mb3JFYWNoKGZ1bmN0aW9uIChpbmRleCkgeyByZXR1cm4gKGluZGV4ZXNUb0RyYXdNYXBbaW5kZXhdID0gdHJ1ZSk7IH0pO1xuICAgICAgICB2YXIgZXhpc3RpbmdJbmRleGVzID0gT2JqZWN0LmtleXModGhpcy5yb3dDdHJsc0J5Um93SW5kZXgpO1xuICAgICAgICB2YXIgaW5kZXhlc05vdFRvRHJhdyA9IGV4aXN0aW5nSW5kZXhlcy5maWx0ZXIoZnVuY3Rpb24gKGluZGV4KSB7IHJldHVybiAhaW5kZXhlc1RvRHJhd01hcFtpbmRleF07IH0pO1xuICAgICAgICB0aGlzLnJlbW92ZVJvd0N0cmxzKGluZGV4ZXNOb3RUb0RyYXcpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmNhbGN1bGF0ZUluZGV4ZXNUb0RyYXcgPSBmdW5jdGlvbiAocm93c1RvUmVjeWNsZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBhbGwgaW4gYWxsIGluZGV4ZXMgaW4gdGhlIHZpZXdwb3J0XG4gICAgICAgIHZhciBpbmRleGVzVG9EcmF3ID0gY3JlYXRlQXJyYXlPZk51bWJlcnModGhpcy5maXJzdFJlbmRlcmVkUm93LCB0aGlzLmxhc3RSZW5kZXJlZFJvdyk7XG4gICAgICAgIHZhciBjaGVja1Jvd1RvRHJhdyA9IGZ1bmN0aW9uIChpbmRleFN0ciwgcm93Q29tcCkge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gcm93Q29tcC5nZXRSb3dOb2RlKCkucm93SW5kZXg7XG4gICAgICAgICAgICBpZiAoaW5kZXggPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpbmRleCA8IF90aGlzLmZpcnN0UmVuZGVyZWRSb3cgfHwgaW5kZXggPiBfdGhpcy5sYXN0UmVuZGVyZWRSb3cpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuZG9Ob3RVblZpcnR1YWxpc2VSb3cocm93Q29tcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXhlc1RvRHJhdy5wdXNoKGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIGlmIHdlIGFyZSByZWRyYXdpbmcgZHVlIHRvIHNjcm9sbGluZyBjaGFuZ2UsIHRoZW4gb2xkIHJvd3MgYXJlIGluIHRoaXMucm93Q29tcHNCeUluZGV4XG4gICAgICAgIGl0ZXJhdGVPYmplY3QodGhpcy5yb3dDdHJsc0J5Um93SW5kZXgsIGNoZWNrUm93VG9EcmF3KTtcbiAgICAgICAgLy8gaWYgd2UgYXJlIHJlZHJhd2luZyBkdWUgdG8gbW9kZWwgdXBkYXRlLCB0aGVuIG9sZCByb3dzIGFyZSBpbiByb3dzVG9SZWN5Y2xlXG4gICAgICAgIGl0ZXJhdGVPYmplY3Qocm93c1RvUmVjeWNsZSwgY2hlY2tSb3dUb0RyYXcpO1xuICAgICAgICBpbmRleGVzVG9EcmF3LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEgLSBiOyB9KTtcbiAgICAgICAgaW5kZXhlc1RvRHJhdyA9IGluZGV4ZXNUb0RyYXcuZmlsdGVyKGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSBfdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93KGluZGV4KTtcbiAgICAgICAgICAgIHJldHVybiByb3dOb2RlICYmICFyb3dOb2RlLnN0aWNreTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBpbmRleGVzVG9EcmF3O1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlZHJhdyA9IGZ1bmN0aW9uIChyb3dzVG9SZWN5Y2xlLCBhbmltYXRlLCBhZnRlclNjcm9sbCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoYW5pbWF0ZSA9PT0gdm9pZCAwKSB7IGFuaW1hdGUgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoYWZ0ZXJTY3JvbGwgPT09IHZvaWQgMCkgeyBhZnRlclNjcm9sbCA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMucm93Q29udGFpbmVySGVpZ2h0U2VydmljZS51cGRhdGVPZmZzZXQoKTtcbiAgICAgICAgdGhpcy53b3JrT3V0Rmlyc3RBbmRMYXN0Um93c1RvUmVuZGVyKCk7XG4gICAgICAgIGlmICh0aGlzLnN0aWNreVJvd0ZlYXR1cmUpIHtcbiAgICAgICAgICAgIHRoaXMuc3RpY2t5Um93RmVhdHVyZS5jaGVja1N0aWNreVJvd3MoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0aGUgcm93IGNhbiBhbHJlYWR5IGV4aXN0IGFuZCBiZSBpbiB0aGUgZm9sbG93aW5nOlxuICAgICAgICAvLyByb3dzVG9SZWN5Y2xlIC0+IGlmIG1vZGVsIGNoYW5nZSwgdGhlbiB0aGUgaW5kZXggbWF5IGJlIGRpZmZlcmVudCwgaG93ZXZlciByb3cgbWF5XG4gICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0IGhlcmUgZnJvbSBwcmV2aW91cyB0aW1lIChtYXBwZWQgYnkgaWQpLlxuICAgICAgICAvLyB0aGlzLnJvd0NvbXBzQnlJbmRleCAtPiBpZiBqdXN0IGEgc2Nyb2xsLCB0aGVuIHRoaXMgd2lsbCBjb250YWluIHdoYXQgaXMgY3VycmVudGx5IGluIHRoZSB2aWV3cG9ydFxuICAgICAgICAvLyB0aGlzIGlzIGFsbCB0aGUgaW5kZXhlcyB3ZSB3YW50LCBpbmNsdWRpbmcgdGhvc2UgdGhhdCBhbHJlYWR5IGV4aXN0LCBzbyB0aGlzIG1ldGhvZFxuICAgICAgICAvLyB3aWxsIGVuZCB1cCBnb2luZyB0aHJvdWdoIGVhY2ggaW5kZXggYW5kIGRyYXdpbmcgb25seSBpZiB0aGUgcm93IGRvZXNuJ3QgYWxyZWFkeSBleGlzdFxuICAgICAgICB2YXIgaW5kZXhlc1RvRHJhdyA9IHRoaXMuY2FsY3VsYXRlSW5kZXhlc1RvRHJhdyhyb3dzVG9SZWN5Y2xlKTtcbiAgICAgICAgdGhpcy5yZW1vdmVSb3dDb21wc05vdFRvRHJhdyhpbmRleGVzVG9EcmF3KTtcbiAgICAgICAgLy8gbmV2ZXIgYW5pbWF0ZSB3aGVuIGRvaW5nIHByaW50IGxheW91dCAtIGFzIHdlIHdhbnQgdG8gZ2V0IHRoaW5ncyByZWFkeSB0byBwcmludCBhcyBxdWlja2x5IGFzIHBvc3NpYmxlLFxuICAgICAgICAvLyBvdGhlcndpc2Ugd2UgcmlzayB0aGUgcHJpbnRlciBwcmludGluZyBhIHJvdyB0aGF0J3MgaGFsZiBmYWRlZCAoaGFsZiB3YXkgdGhyb3VnaCBmYWRpbmcgaW4pXG4gICAgICAgIGlmICh0aGlzLnByaW50TGF5b3V0KSB7XG4gICAgICAgICAgICBhbmltYXRlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaW5kZXhlc1RvRHJhdy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dJbmRleCkge1xuICAgICAgICAgICAgdmFyIHJvd0N0cmwgPSBfdGhpcy5jcmVhdGVPclVwZGF0ZVJvd0N0cmwocm93SW5kZXgsIHJvd3NUb1JlY3ljbGUsIGFuaW1hdGUsIGFmdGVyU2Nyb2xsKTtcbiAgICAgICAgICAgIGlmIChleGlzdHMocm93Q3RybCkpIDtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChyb3dzVG9SZWN5Y2xlKSB7XG4gICAgICAgICAgICB2YXIgdXNlQW5pbWF0aW9uRnJhbWUgPSBhZnRlclNjcm9sbCAmJiAhdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0FuaW1hdGlvbkZyYW1lKCkgJiYgIXRoaXMucHJpbnRMYXlvdXQ7XG4gICAgICAgICAgICBpZiAodXNlQW5pbWF0aW9uRnJhbWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJlYW5zLmFuaW1hdGlvbkZyYW1lU2VydmljZS5hZGREZXN0cm95VGFzayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRlc3Ryb3lSb3dDdHJscyhyb3dzVG9SZWN5Y2xlLCBhbmltYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMudXBkYXRlQWxsUm93Q3RybHMoKTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZGlzcGF0Y2hEaXNwbGF5ZWRSb3dzQ2hhbmdlZCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXN0cm95Um93Q3RybHMocm93c1RvUmVjeWNsZSwgYW5pbWF0ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVBbGxSb3dDdHJscygpO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmRpc3BhdGNoRGlzcGxheWVkUm93c0NoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudCA9IHsgdHlwZTogRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9ST1dTX0NIQU5HRUQgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUub25EaXNwbGF5ZWRDb2x1bW5zQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHBpbm5pbmdMZWZ0ID0gdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpbm5pbmdMZWZ0KCk7XG4gICAgICAgIHZhciBwaW5uaW5nUmlnaHQgPSB0aGlzLmNvbHVtbk1vZGVsLmlzUGlubmluZ1JpZ2h0KCk7XG4gICAgICAgIHZhciBhdExlYXN0T25lQ2hhbmdlZCA9IHRoaXMucGlubmluZ0xlZnQgIT09IHBpbm5pbmdMZWZ0IHx8IHBpbm5pbmdSaWdodCAhPT0gdGhpcy5waW5uaW5nUmlnaHQ7XG4gICAgICAgIGlmIChhdExlYXN0T25lQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5waW5uaW5nTGVmdCA9IHBpbm5pbmdMZWZ0O1xuICAgICAgICAgICAgdGhpcy5waW5uaW5nUmlnaHQgPSBwaW5uaW5nUmlnaHQ7XG4gICAgICAgICAgICBpZiAodGhpcy5lbWJlZEZ1bGxXaWR0aFJvd3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlZHJhd0Z1bGxXaWR0aEVtYmVkZGVkUm93cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyB3aGVuIGVtYmVkZGluZywgd2hhdCBnZXRzIHNob3dlZCBpbiBlYWNoIHNlY3Rpb24gZGVwZW5kcyBvbiB3aGF0IGlzIHBpbm5lZC4gZWcgaWYgZW1iZWRkaW5nIGdyb3VwIGV4cGFuZCAvIGNvbGxhcHNlLFxuICAgIC8vIHRoZW4gaXQgc2hvdWxkIGdvIGludG8gdGhlIHBpbm5lZCBsZWZ0IGFyZWEgaWYgcGlubmluZyBsZWZ0LCBvciB0aGUgY2VudGVyIGFyZWEgaWYgbm90IHBpbm5pbmcuXG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLnJlZHJhd0Z1bGxXaWR0aEVtYmVkZGVkUm93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gaWYgZWl0aGVyIG9mIHRoZSBwaW5uZWQgcGFuZWxzIGhhcyBzaG93biAvIGhpZGRlbiwgdGhlbiBuZWVkIHRvIHJlZHJhdyB0aGUgZnVsbFdpZHRoIGJpdHMgd2hlblxuICAgICAgICAvLyBlbWJlZGRlZCwgYXMgd2hhdCBhcHBlYXJzIGluIGVhY2ggc2VjdGlvbiBkZXBlbmRzIG9uIHdoZXRoZXIgd2UgYXJlIHBpbm5lZCBvciBub3RcbiAgICAgICAgdmFyIHJvd3NUb1JlbW92ZSA9IFtdO1xuICAgICAgICB0aGlzLmdldEZ1bGxXaWR0aFJvd0N0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoZnVsbFdpZHRoQ3RybCkge1xuICAgICAgICAgICAgdmFyIHJvd0luZGV4ID0gZnVsbFdpZHRoQ3RybC5nZXRSb3dOb2RlKCkucm93SW5kZXg7XG4gICAgICAgICAgICByb3dzVG9SZW1vdmUucHVzaChyb3dJbmRleC50b1N0cmluZygpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVmcmVzaEZsb2F0aW5nUm93Q29tcHMoKTtcbiAgICAgICAgdGhpcy5yZW1vdmVSb3dDdHJscyhyb3dzVG9SZW1vdmUpO1xuICAgICAgICB0aGlzLnJlZHJhd0FmdGVyU2Nyb2xsKCk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZ2V0RnVsbFdpZHRoUm93Q3RybHMgPSBmdW5jdGlvbiAocm93Tm9kZXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJvd05vZGVzTWFwID0gdGhpcy5tYXBSb3dOb2Rlcyhyb3dOb2Rlcyk7XG4gICAgICAgIHJldHVybiBnZXRBbGxWYWx1ZXNJbk9iamVjdCh0aGlzLnJvd0N0cmxzQnlSb3dJbmRleCkuZmlsdGVyKGZ1bmN0aW9uIChyb3dDdHJsKSB7XG4gICAgICAgICAgICAvLyBpbmNsdWRlIGp1c3QgZnVsbCB3aWR0aFxuICAgICAgICAgICAgaWYgKCFyb3dDdHJsLmlzRnVsbFdpZHRoKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiBSb3cgTm9kZXMgcHJvdmlkZWQsIHdlIGV4Y2x1ZGUgd2hlcmUgUm93IE5vZGUgaXMgbWlzc2luZ1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSByb3dDdHJsLmdldFJvd05vZGUoKTtcbiAgICAgICAgICAgIGlmIChyb3dOb2Rlc01hcCAhPSBudWxsICYmICFfdGhpcy5pc1Jvd0luTWFwKHJvd05vZGUsIHJvd05vZGVzTWFwKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5yZWZyZXNoRnVsbFdpZHRoUm93cyA9IGZ1bmN0aW9uIChyb3dOb2Rlc1RvUmVmcmVzaCkge1xuICAgICAgICB2YXIgcm93c1RvUmVtb3ZlID0gW107XG4gICAgICAgIHZhciBzZWxlY3RpdmVseVJlZnJlc2hpbmcgPSAhIXJvd05vZGVzVG9SZWZyZXNoO1xuICAgICAgICB2YXIgaWRzVG9SZWZyZXNoID0gc2VsZWN0aXZlbHlSZWZyZXNoaW5nID8ge30gOiB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChzZWxlY3RpdmVseVJlZnJlc2hpbmcgJiYgaWRzVG9SZWZyZXNoKSB7XG4gICAgICAgICAgICByb3dOb2Rlc1RvUmVmcmVzaC5mb3JFYWNoKGZ1bmN0aW9uIChyKSB7IHJldHVybiBpZHNUb1JlZnJlc2hbci5pZF0gPSB0cnVlOyB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldEZ1bGxXaWR0aFJvd0N0cmxzKCkuZm9yRWFjaChmdW5jdGlvbiAoZnVsbFdpZHRoUm93Q3RybCkge1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSBmdWxsV2lkdGhSb3dDdHJsLmdldFJvd05vZGUoKTtcbiAgICAgICAgICAgIGlmIChzZWxlY3RpdmVseVJlZnJlc2hpbmcgJiYgaWRzVG9SZWZyZXNoKSB7XG4gICAgICAgICAgICAgICAgLy8gd2UgcmVmcmVzaCBpZiBhKSB0aGlzIG5vZGUgaXMgcHJlc2VudCBvciBiKSB0aGlzIHBhcmVudHMgbm9kZXMgaXMgcHJlc2VudC4gY2hlY2tpbmcgcGFyZW50XG4gICAgICAgICAgICAgICAgLy8gbm9kZSBpcyBpbXBvcnRhbnQgZm9yIG1hc3Rlci9kZXRhaWwsIGFzIHdlIHdhbnQgZGV0YWlsIHRvIHJlZnJlc2ggb24gY2hhbmdlcyB0byBwYXJlbnQgbm9kZS5cbiAgICAgICAgICAgICAgICAvLyBpdCdzIGFsc28gcG9zc2libGUsIGlmIHVzZXIgaXMgcHJvdmlkZXIgdGhlaXIgb3duIGZ1bGxXaWR0aCwgdGhhdCBkZXRhaWxzIHBhbmVscyBjb250YWluXG4gICAgICAgICAgICAgICAgLy8gc29tZSBpbmZvIG9uIHRoZSBwYXJlbnQsIGVnIGlmIGluIHRyZWUgZGF0YSBhbmQgY2hpbGQgcm93IHNob3dzIHNvbWUgZGF0YSBmcm9tIHBhcmVudCByb3cgYWxzby5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50SWQgPSAocm93Tm9kZS5sZXZlbCA+IDAgJiYgcm93Tm9kZS5wYXJlbnQpID8gcm93Tm9kZS5wYXJlbnQuaWQgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdmFyIHNraXBUaGlzTm9kZSA9ICFpZHNUb1JlZnJlc2hbcm93Tm9kZS5pZF0gJiYgIWlkc1RvUmVmcmVzaFtwYXJlbnRJZF07XG4gICAgICAgICAgICAgICAgaWYgKHNraXBUaGlzTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGZ1bGxXaWR0aFJvd3NSZWZyZXNoZWQgPSBmdWxsV2lkdGhSb3dDdHJsLnJlZnJlc2hGdWxsV2lkdGgoKTtcbiAgICAgICAgICAgIGlmICghZnVsbFdpZHRoUm93c1JlZnJlc2hlZCkge1xuICAgICAgICAgICAgICAgIHZhciByb3dJbmRleCA9IGZ1bGxXaWR0aFJvd0N0cmwuZ2V0Um93Tm9kZSgpLnJvd0luZGV4O1xuICAgICAgICAgICAgICAgIHJvd3NUb1JlbW92ZS5wdXNoKHJvd0luZGV4LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZW1vdmVSb3dDdHJscyhyb3dzVG9SZW1vdmUpO1xuICAgICAgICB0aGlzLnJlZHJhd0FmdGVyU2Nyb2xsKCk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuY3JlYXRlT3JVcGRhdGVSb3dDdHJsID0gZnVuY3Rpb24gKHJvd0luZGV4LCByb3dzVG9SZWN5Y2xlLCBhbmltYXRlLCBhZnRlclNjcm9sbCkge1xuICAgICAgICB2YXIgcm93Tm9kZTtcbiAgICAgICAgdmFyIHJvd0N0cmwgPSB0aGlzLnJvd0N0cmxzQnlSb3dJbmRleFtyb3dJbmRleF07XG4gICAgICAgIC8vIGlmIG5vIHJvdyBjb21wLCBzZWUgaWYgd2UgY2FuIGdldCBpdCBmcm9tIHRoZSBwcmV2aW91cyByb3dDb21wc1xuICAgICAgICBpZiAoIXJvd0N0cmwpIHtcbiAgICAgICAgICAgIHJvd05vZGUgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRSb3cocm93SW5kZXgpO1xuICAgICAgICAgICAgaWYgKGV4aXN0cyhyb3dOb2RlKSAmJiBleGlzdHMocm93c1RvUmVjeWNsZSkgJiYgcm93c1RvUmVjeWNsZVtyb3dOb2RlLmlkXSAmJiByb3dOb2RlLmFscmVhZHlSZW5kZXJlZCkge1xuICAgICAgICAgICAgICAgIHJvd0N0cmwgPSByb3dzVG9SZWN5Y2xlW3Jvd05vZGUuaWRdO1xuICAgICAgICAgICAgICAgIHJvd3NUb1JlY3ljbGVbcm93Tm9kZS5pZF0gPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBjcmVhdGluZ05ld1Jvd0N0cmwgPSAhcm93Q3RybDtcbiAgICAgICAgaWYgKGNyZWF0aW5nTmV3Um93Q3RybCkge1xuICAgICAgICAgICAgLy8gY3JlYXRlIGEgbmV3IG9uZVxuICAgICAgICAgICAgaWYgKCFyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZSA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFJvdyhyb3dJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXhpc3RzKHJvd05vZGUpKSB7XG4gICAgICAgICAgICAgICAgcm93Q3RybCA9IHRoaXMuY3JlYXRlUm93Q29uKHJvd05vZGUsIGFuaW1hdGUsIGFmdGVyU2Nyb2xsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgc2hvdWxkIG5ldmVyIGhhcHBlbiAtIGlmIHNvbWVob3cgd2UgYXJlIHRyeWluZyB0byBjcmVhdGVcbiAgICAgICAgICAgICAgICAvLyBhIHJvdyBmb3IgYSByb3dOb2RlIHRoYXQgZG9lcyBub3QgZXhpc3QuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChyb3dOb2RlKSB7XG4gICAgICAgICAgICAvLyBzZXQgbm9kZSBhcyAnYWxyZWFkeVJlbmRlcmVkJyB0byBlbnN1cmUgd2Ugb25seSByZWN5Y2xlIHJvd0NvbXBzIHRoYXQgaGF2ZSBiZWVuIHJlbmRlcmVkLCB0aGlzIGVuc3VyZXNcbiAgICAgICAgICAgIC8vIHdlIGRvbid0IHJldXNlIHJvd0NvbXBzIHRoYXQgaGF2ZSBiZWVuIHJlbW92ZWQgYW5kIHRoZW4gcmUtYWRkZWQgaW4gdGhlIHNhbWUgYmF0Y2ggdHJhbnNhY3Rpb24uXG4gICAgICAgICAgICByb3dOb2RlLmFscmVhZHlSZW5kZXJlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yb3dDdHJsc0J5Um93SW5kZXhbcm93SW5kZXhdID0gcm93Q3RybDtcbiAgICAgICAgcmV0dXJuIHJvd0N0cmw7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZGVzdHJveVJvd0N0cmxzID0gZnVuY3Rpb24gKHJvd0N0cmxzTWFwLCBhbmltYXRlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBleGVjdXRlSW5BV2hpbGVGdW5jcyA9IFtdO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHJvd0N0cmxzTWFwLCBmdW5jdGlvbiAobm9kZUlkLCByb3dDdHJsKSB7XG4gICAgICAgICAgICAvLyBpZiByb3cgd2FzIHVzZWQsIHRoZW4gaXQncyBudWxsXG4gICAgICAgICAgICBpZiAoIXJvd0N0cmwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3RoaXMuY2FjaGVkUm93Q3RybHMgJiYgcm93Q3RybC5pc0NhY2hlYWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuY2FjaGVkUm93Q3RybHMuYWRkUm93KHJvd0N0cmwpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJvd0N0cmwuZGVzdHJveUZpcnN0UGFzcygpO1xuICAgICAgICAgICAgaWYgKGFuaW1hdGUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy56b21iaWVSb3dDdHJsc1tyb3dDdHJsLmdldEluc3RhbmNlSWQoKV0gPSByb3dDdHJsO1xuICAgICAgICAgICAgICAgIGV4ZWN1dGVJbkFXaGlsZUZ1bmNzLnB1c2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByb3dDdHJsLmRlc3Ryb3lTZWNvbmRQYXNzKCk7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBfdGhpcy56b21iaWVSb3dDdHJsc1tyb3dDdHJsLmdldEluc3RhbmNlSWQoKV07XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByb3dDdHJsLmRlc3Ryb3lTZWNvbmRQYXNzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYW5pbWF0ZSkge1xuICAgICAgICAgICAgLy8gdGhpcyBlbnN1cmVzIHdlIGZpcmUgZGlzcGxheWVkUm93c0NoYW5nZWQgQUZURVIgYWxsIHRoZSAnZXhlY3V0ZUluQVdoaWxlRnVuY3MnIGdldFxuICAgICAgICAgICAgLy8gZXhlY3V0ZWQsIGFzIHdlIGFkZGVkIGl0IHRvIHRoZSBlbmQgb2YgdGhlIGxpc3QuXG4gICAgICAgICAgICBleGVjdXRlSW5BV2hpbGVGdW5jcy5wdXNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy51cGRhdGVBbGxSb3dDdHJscygpO1xuICAgICAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoRGlzcGxheWVkUm93c0NoYW5nZWQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZXhlY3V0ZUluQVdoaWxlKGV4ZWN1dGVJbkFXaGlsZUZ1bmNzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLndvcmtPdXRGaXJzdEFuZExhc3RSb3dzVG9SZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBuZXdGaXJzdDtcbiAgICAgICAgdmFyIG5ld0xhc3Q7XG4gICAgICAgIGlmICghdGhpcy5wYWdpbmF0aW9uUHJveHkuaXNSb3dzVG9SZW5kZXIoKSkge1xuICAgICAgICAgICAgbmV3Rmlyc3QgPSAwO1xuICAgICAgICAgICAgbmV3TGFzdCA9IC0xOyAvLyBzZXR0aW5nIHRvIC0xIG1lYW5zIG5vdGhpbmcgaW4gcmFuZ2VcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnByaW50TGF5b3V0KSB7XG4gICAgICAgICAgICBuZXdGaXJzdCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VGaXJzdFJvdygpO1xuICAgICAgICAgICAgbmV3TGFzdCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VMYXN0Um93KCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgYnVmZmVyUGl4ZWxzID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93QnVmZmVySW5QaXhlbHMoKTtcbiAgICAgICAgICAgIHZhciBncmlkQm9keUN0cmwgPSB0aGlzLmN0cmxzU2VydmljZS5nZXRHcmlkQm9keUN0cmwoKTtcbiAgICAgICAgICAgIHZhciBzdXBwcmVzc1Jvd1ZpcnR1YWxpc2F0aW9uID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1Jvd1ZpcnR1YWxpc2F0aW9uKCk7XG4gICAgICAgICAgICB2YXIgcm93SGVpZ2h0c0NoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBmaXJzdFBpeGVsID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIGxhc3RQaXhlbCA9IHZvaWQgMDtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFnaW5hdGlvbk9mZnNldCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBpeGVsT2Zmc2V0KCk7XG4gICAgICAgICAgICAgICAgdmFyIF9hID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Q3VycmVudFBhZ2VQaXhlbFJhbmdlKCksIHBhZ2VGaXJzdFBpeGVsID0gX2EucGFnZUZpcnN0UGl4ZWwsIHBhZ2VMYXN0UGl4ZWwgPSBfYS5wYWdlTGFzdFBpeGVsO1xuICAgICAgICAgICAgICAgIHZhciBkaXZTdHJldGNoT2Zmc2V0ID0gdGhpcy5yb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLmdldERpdlN0cmV0Y2hPZmZzZXQoKTtcbiAgICAgICAgICAgICAgICB2YXIgYm9keVZSYW5nZSA9IGdyaWRCb2R5Q3RybC5nZXRTY3JvbGxGZWF0dXJlKCkuZ2V0VlNjcm9sbFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgdmFyIGJvZHlUb3BQaXhlbCA9IGJvZHlWUmFuZ2UudG9wO1xuICAgICAgICAgICAgICAgIHZhciBib2R5Qm90dG9tUGl4ZWwgPSBib2R5VlJhbmdlLmJvdHRvbTtcbiAgICAgICAgICAgICAgICBpZiAoc3VwcHJlc3NSb3dWaXJ0dWFsaXNhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdFBpeGVsID0gcGFnZUZpcnN0UGl4ZWwgKyBkaXZTdHJldGNoT2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICBsYXN0UGl4ZWwgPSBwYWdlTGFzdFBpeGVsICsgZGl2U3RyZXRjaE9mZnNldDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0UGl4ZWwgPSBNYXRoLm1heChib2R5VG9wUGl4ZWwgKyBwYWdpbmF0aW9uT2Zmc2V0IC0gYnVmZmVyUGl4ZWxzLCBwYWdlRmlyc3RQaXhlbCkgKyBkaXZTdHJldGNoT2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICBsYXN0UGl4ZWwgPSBNYXRoLm1pbihib2R5Qm90dG9tUGl4ZWwgKyBwYWdpbmF0aW9uT2Zmc2V0ICsgYnVmZmVyUGl4ZWxzLCBwYWdlTGFzdFBpeGVsKSArIGRpdlN0cmV0Y2hPZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RWaXNpYmxlVlBpeGVsID0gTWF0aC5tYXgoYm9keVRvcFBpeGVsICsgcGFnaW5hdGlvbk9mZnNldCwgcGFnZUZpcnN0UGl4ZWwpICsgZGl2U3RyZXRjaE9mZnNldDtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcm93cyB3ZSBhcmUgYWJvdXQgdG8gZGlzcGxheSBnZXQgdGhlaXIgaGVpZ2h0cyBjaGFuZ2VkLCB0aGVuIHRoYXQgdXBzZXRzIHRoZSBjYWxjcyBmcm9tIGFib3ZlLlxuICAgICAgICAgICAgICAgIHJvd0hlaWdodHNDaGFuZ2VkID0gdGhpcy5lbnN1cmVBbGxSb3dzSW5SYW5nZUhhdmVIZWlnaHRzQ2FsY3VsYXRlZChmaXJzdFBpeGVsLCBsYXN0UGl4ZWwpO1xuICAgICAgICAgICAgfSB3aGlsZSAocm93SGVpZ2h0c0NoYW5nZWQpO1xuICAgICAgICAgICAgdmFyIGZpcnN0Um93SW5kZXggPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRSb3dJbmRleEF0UGl4ZWwoZmlyc3RQaXhlbCk7XG4gICAgICAgICAgICB2YXIgbGFzdFJvd0luZGV4ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93SW5kZXhBdFBpeGVsKGxhc3RQaXhlbCk7XG4gICAgICAgICAgICB2YXIgcGFnZUZpcnN0Um93ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0UGFnZUZpcnN0Um93KCk7XG4gICAgICAgICAgICB2YXIgcGFnZUxhc3RSb3cgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlTGFzdFJvdygpO1xuICAgICAgICAgICAgLy8gYWRqdXN0LCBpbiBjYXNlIGJ1ZmZlciBleHRlbmRlZCBhY3R1YWwgc2l6ZVxuICAgICAgICAgICAgaWYgKGZpcnN0Um93SW5kZXggPCBwYWdlRmlyc3RSb3cpIHtcbiAgICAgICAgICAgICAgICBmaXJzdFJvd0luZGV4ID0gcGFnZUZpcnN0Um93O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxhc3RSb3dJbmRleCA+IHBhZ2VMYXN0Um93KSB7XG4gICAgICAgICAgICAgICAgbGFzdFJvd0luZGV4ID0gcGFnZUxhc3RSb3c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXdGaXJzdCA9IGZpcnN0Um93SW5kZXg7XG4gICAgICAgICAgICBuZXdMYXN0ID0gbGFzdFJvd0luZGV4O1xuICAgICAgICB9XG4gICAgICAgIC8vIHNvbWV0aW1lcyB1c2VyIGRvZXNuJ3Qgc2V0IENTUyByaWdodCBhbmQgZW5kcyB1cCB3aXRoIGdyaWQgd2l0aCBubyBoZWlnaHQgYW5kIGdyaWQgZW5kcyB1cFxuICAgICAgICAvLyB0cnlpbmcgdG8gcmVuZGVyIGFsbCB0aGUgcm93cywgZWcgMTAsMDAwKyByb3dzLiB0aGlzIHdpbGwga2lsbCB0aGUgYnJvd3Nlci4gc28gaW5zdGVhZCBvZlxuICAgICAgICAvLyBraWxsaW5nIHRoZSBicm93c2VyLCB3ZSBsaW1pdCB0aGUgbnVtYmVyIG9mIHJvd3MuIGp1c3QgaW4gY2FzZSBzb21lIHVzZSBjYXNlIHdlIGRpZG4ndCB0aGlua1xuICAgICAgICAvLyBvZiwgd2UgYWxzbyBoYXZlIGEgcHJvcGVydHkgdG8gbm90IGRvIHRoaXMgb3BlcmF0aW9uLlxuICAgICAgICB2YXIgcm93TGF5b3V0Tm9ybWFsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tTGF5b3V0KCkgPT09IENvbnN0YW50cy5ET01fTEFZT1VUX05PUk1BTDtcbiAgICAgICAgdmFyIHN1cHByZXNzUm93Q291bnRSZXN0cmljdGlvbiA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NNYXhSZW5kZXJlZFJvd1Jlc3RyaWN0aW9uKCk7XG4gICAgICAgIHZhciByb3dCdWZmZXJNYXhTaXplID0gTWF0aC5tYXgodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93QnVmZmVyKCksIDUwMCk7XG4gICAgICAgIGlmIChyb3dMYXlvdXROb3JtYWwgJiYgIXN1cHByZXNzUm93Q291bnRSZXN0cmljdGlvbikge1xuICAgICAgICAgICAgaWYgKG5ld0xhc3QgLSBuZXdGaXJzdCA+IHJvd0J1ZmZlck1heFNpemUpIHtcbiAgICAgICAgICAgICAgICBuZXdMYXN0ID0gbmV3Rmlyc3QgKyByb3dCdWZmZXJNYXhTaXplO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBmaXJzdERpZmZlcnMgPSBuZXdGaXJzdCAhPT0gdGhpcy5maXJzdFJlbmRlcmVkUm93O1xuICAgICAgICB2YXIgbGFzdERpZmZlcnMgPSBuZXdMYXN0ICE9PSB0aGlzLmxhc3RSZW5kZXJlZFJvdztcbiAgICAgICAgaWYgKGZpcnN0RGlmZmVycyB8fCBsYXN0RGlmZmVycykge1xuICAgICAgICAgICAgdGhpcy5maXJzdFJlbmRlcmVkUm93ID0gbmV3Rmlyc3Q7XG4gICAgICAgICAgICB0aGlzLmxhc3RSZW5kZXJlZFJvdyA9IG5ld0xhc3Q7XG4gICAgICAgICAgICB2YXIgZXZlbnRfMSA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfVklFV1BPUlRfQ0hBTkdFRCxcbiAgICAgICAgICAgICAgICBmaXJzdFJvdzogbmV3Rmlyc3QsXG4gICAgICAgICAgICAgICAgbGFzdFJvdzogbmV3TGFzdFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnRfMSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBvbmx5IGJlIGZpcmVkIG9uY2UsIGFuZCBpcyBxdWV1ZWQgdW50aWwgYWZ0ZXIgdGhlIGJyb3dzZXIgbmV4dCByZW5kZXJzLlxuICAgICAqIFRoaXMgYWxsb3dzIHVzIHRvIGZpcmUgYW4gZXZlbnQgZHVyaW5nIHRoZSBzdGFydCBvZiB0aGUgcmVuZGVyIGN5Y2xlLCB3aGVuIHdlIGZpcnN0IHNlZSBkYXRhIGJlaW5nIHJlbmRlcmVkXG4gICAgICogYnV0IG5vdCBleGVjdXRlIHRoZSBldmVudCB1bnRpbCBhbGwgb2YgdGhlIGRhdGEgaGFzIGZpbmlzaGVkIGJlaW5nIHJlbmRlcmVkIHRvIHRoZSBkb20uXG4gICAgICovXG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmRpc3BhdGNoRmlyc3REYXRhUmVuZGVyZWRFdmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuZGF0YUZpcnN0UmVuZGVyZWRGaXJlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGF0YUZpcnN0UmVuZGVyZWRGaXJlZCA9IHRydWU7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9GSVJTVF9EQVRBX1JFTkRFUkVELFxuICAgICAgICAgICAgZmlyc3RSb3c6IHRoaXMuZmlyc3RSZW5kZXJlZFJvdyxcbiAgICAgICAgICAgIGxhc3RSb3c6IHRoaXMubGFzdFJlbmRlcmVkUm93LFxuICAgICAgICB9O1xuICAgICAgICAvLyBTZWUgQUctNzAxOFxuICAgICAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmJlYW5zLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZW5zdXJlQWxsUm93c0luUmFuZ2VIYXZlSGVpZ2h0c0NhbGN1bGF0ZWQgPSBmdW5jdGlvbiAodG9wUGl4ZWwsIGJvdHRvbVBpeGVsKSB7XG4gICAgICAgIC8vIGVuc3VyZVJvd0hlaWdodHNWaXNpYmxlIG9ubHkgd29ya3Mgd2l0aCBDU1JNLCBhcyBpdCdzIHRoZSBvbmx5IHJvdyBtb2RlbCB0aGF0IGFsbG93cyBsYXp5IHJvdyBoZWlnaHQgY2FsY3MuXG4gICAgICAgIC8vIGFsbCB0aGUgb3RoZXIgcm93IG1vZGVscyBqdXN0IGhhcmQgY29kZSBzbyB0aGUgbWV0aG9kIGp1c3QgcmV0dXJucyBiYWNrIGZhbHNlXG4gICAgICAgIHZhciByZXMgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5lbnN1cmVSb3dIZWlnaHRzVmFsaWQodG9wUGl4ZWwsIGJvdHRvbVBpeGVsLCAtMSwgLTEpO1xuICAgICAgICBpZiAocmVzKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUNvbnRhaW5lckhlaWdodHMoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldEZpcnN0VmlzaWJsZVZlcnRpY2FsUGl4ZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZpcnN0VmlzaWJsZVZQaXhlbDtcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRGaXJzdFZpcnR1YWxSZW5kZXJlZFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlyc3RSZW5kZXJlZFJvdztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRMYXN0VmlydHVhbFJlbmRlcmVkUm93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0UmVuZGVyZWRSb3c7XG4gICAgfTtcbiAgICAvLyBjaGVjayB0aGF0IG5vbmUgb2YgdGhlIHJvd3MgdG8gcmVtb3ZlIGFyZSBlZGl0aW5nIG9yIGZvY3VzZWQgYXM6XG4gICAgLy8gYSkgaWYgZWRpdGluZywgd2Ugd2FudCB0byBrZWVwIHRoZW0sIG90aGVyd2lzZSB0aGUgdXNlciB3aWxsIGxvb3NlIHRoZSBjb250ZXh0IG9mIHRoZSBlZGl0LFxuICAgIC8vICAgIGVnIHVzZXIgc3RhcnRzIGVkaXRpbmcsIGVudGVycyBzb21lIHRleHQsIHRoZW4gc2Nyb2xscyBkb3duIGFuZCB0aGVuIHVwLCBuZXh0IHRpbWUgcm93IHJlbmRlcmVkXG4gICAgLy8gICAgdGhlIGVkaXQgaXMgcmVzZXQgLSBzbyB3ZSB3YW50IHRvIGtlZXAgaXQgcmVuZGVyZWQuXG4gICAgLy8gYikgaWYgZm9jdXNlZCwgd2Ugd2FudCBvdCBrZWVwIGtleWJvYXJkIGZvY3VzLCBzbyBpZiB1c2VyIGN0cmwrYywgaXQgZ29lcyB0byBjbGlwYm9hcmQsXG4gICAgLy8gICAgb3RoZXJ3aXNlIHRoZSB1c2VyIGNhbiByYW5nZSBzZWxlY3QgYW5kIGRyYWcgKHdpdGggZm9jdXMgY2VsbCBnb2luZyBvdXQgb2YgdGhlIHZpZXdwb3J0KVxuICAgIC8vICAgIGFuZCB0aGVuIGN0cmwrYywgbm90aGluZyB3aWxsIGhhcHBlbiBpZiBjZWxsIGlzIHJlbW92ZWQgZnJvbSBkb20uXG4gICAgLy8gYykgaWYgZGV0YWlsIHJlY29yZCBvZiBtYXN0ZXIgZGV0YWlsLCBhcyB1c2VycyBjb21wbGFpbmVkIHRoYXQgdGhlIGNvbnRleHQgb2YgZGV0YWlsIHJvd3NcbiAgICAvLyAgICB3YXMgZ2V0dGluZyBsb3N0IHdoZW4gZGV0YWlsIHJvdyBvdXQgb2Ygdmlldy4gZWcgdXNlciBleHBhbmRzIHRvIHNob3cgZGV0YWlsIHJvdyxcbiAgICAvLyAgICB0aGVuIG1hbmlwdWxhdGVzIHRoZSBkZXRhaWwgcGFuZWwgKGVnIHNvcnRzIHRoZSBkZXRhaWwgZ3JpZCksIHRoZW4gY29udGV4dCBpcyBsb3N0XG4gICAgLy8gICAgYWZ0ZXIgZGV0YWlsIHBhbmVsIGlzIHNjcm9sbGVkIG91dCBvZiAvIGludG8gdmlldy5cbiAgICBSb3dSZW5kZXJlci5wcm90b3R5cGUuZG9Ob3RVblZpcnR1YWxpc2VSb3cgPSBmdW5jdGlvbiAocm93Q29tcCkge1xuICAgICAgICB2YXIgUkVNT1ZFX1JPVyA9IGZhbHNlO1xuICAgICAgICB2YXIgS0VFUF9ST1cgPSB0cnVlO1xuICAgICAgICB2YXIgcm93Tm9kZSA9IHJvd0NvbXAuZ2V0Um93Tm9kZSgpO1xuICAgICAgICB2YXIgcm93SGFzRm9jdXMgPSB0aGlzLmZvY3VzU2VydmljZS5pc1Jvd05vZGVGb2N1c2VkKHJvd05vZGUpO1xuICAgICAgICB2YXIgcm93SXNFZGl0aW5nID0gcm93Q29tcC5pc0VkaXRpbmcoKTtcbiAgICAgICAgdmFyIHJvd0lzRGV0YWlsID0gcm93Tm9kZS5kZXRhaWw7XG4gICAgICAgIHZhciBtaWdodFdhbnRUb0tlZXBSb3cgPSByb3dIYXNGb2N1cyB8fCByb3dJc0VkaXRpbmcgfHwgcm93SXNEZXRhaWw7XG4gICAgICAgIC8vIGlmIHdlIGRlZmZvIGRvbid0IHdhbnQgdG8ga2VlcCBpdCxcbiAgICAgICAgaWYgKCFtaWdodFdhbnRUb0tlZXBSb3cpIHtcbiAgICAgICAgICAgIHJldHVybiBSRU1PVkVfUk9XO1xuICAgICAgICB9XG4gICAgICAgIC8vIGVkaXRpbmcgcm93LCBvbmx5IHJlbW92ZSBpZiBpdCBpcyBubyBsb25nZXIgcmVuZGVyZWQsIGVnIGZpbHRlcmVkIG91dCBvciBuZXcgZGF0YSBzZXQuXG4gICAgICAgIC8vIHRoZSByZWFzb24gd2Ugd2FudCB0byBrZWVwIGlzIGlmIHVzZXIgaXMgc2Nyb2xsaW5nIHVwIGFuZCBkb3duLCB3ZSBkb24ndCB3YW50IHRvIGxvb3NlXG4gICAgICAgIC8vIHRoZSBjb250ZXh0IG9mIHRoZSBlZGl0aW5nIGluIHByb2Nlc3MuXG4gICAgICAgIHZhciByb3dOb2RlUHJlc2VudCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmlzUm93UHJlc2VudChyb3dOb2RlKTtcbiAgICAgICAgcmV0dXJuIHJvd05vZGVQcmVzZW50ID8gS0VFUF9ST1cgOiBSRU1PVkVfUk9XO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmNyZWF0ZVJvd0NvbiA9IGZ1bmN0aW9uIChyb3dOb2RlLCBhbmltYXRlLCBhZnRlclNjcm9sbCkge1xuICAgICAgICB2YXIgcm93Q3RybEZyb21DYWNoZSA9IHRoaXMuY2FjaGVkUm93Q3RybHMgPyB0aGlzLmNhY2hlZFJvd0N0cmxzLmdldFJvdyhyb3dOb2RlKSA6IG51bGw7XG4gICAgICAgIGlmIChyb3dDdHJsRnJvbUNhY2hlKSB7XG4gICAgICAgICAgICByZXR1cm4gcm93Q3RybEZyb21DYWNoZTtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBkb24ndCB1c2UgYW5pbWF0aW9ucyBmcmFtZXMgZm9yIHByaW50aW5nLCBzbyB0aGUgdXNlciBjYW4gcHV0IHRoZSBncmlkIGludG8gcHJpbnQgbW9kZVxuICAgICAgICAvLyBhbmQgaW1tZWRpYXRlbHkgcHJpbnQgLSBvdGhlcndpc2UgdGhlIHVzZXIgd291bGQgaGF2ZSB0byB3YWl0IGZvciB0aGUgcm93cyB0byBkcmF3IGluIHRoZSBiYWNrZ3JvdW5kXG4gICAgICAgIC8vICh2aWEgdGhlIGFuaW1hdGlvbiBmcmFtZXMpIHdoaWNoIGlzIGF3a3dhcmQgdG8gZG8gZnJvbSBjb2RlLlxuICAgICAgICAvLyB3ZSBvbmx5IGRvIHRoZSBhbmltYXRpb24gZnJhbWVzIGFmdGVyIHNjcm9sbGluZywgYXMgdGhpcyBpcyB3aGVyZSB3ZSB3YW50IHRoZSBzbW9vdGggdXNlciBleHBlcmllbmNlLlxuICAgICAgICAvLyBoYXZpbmcgYW5pbWF0aW9uIGZyYW1lcyBmb3Igb3RoZXIgdGltZXMgbWFrZXMgdGhlIGdyaWQgbG9vayAnanVtcHknLlxuICAgICAgICB2YXIgc3VwcHJlc3NBbmltYXRpb25GcmFtZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NBbmltYXRpb25GcmFtZSgpO1xuICAgICAgICB2YXIgdXNlQW5pbWF0aW9uRnJhbWVGb3JDcmVhdGUgPSBhZnRlclNjcm9sbCAmJiAhc3VwcHJlc3NBbmltYXRpb25GcmFtZSAmJiAhdGhpcy5wcmludExheW91dDtcbiAgICAgICAgdmFyIHJlcyA9IG5ldyBSb3dDdHJsKHJvd05vZGUsIHRoaXMuYmVhbnMsIGFuaW1hdGUsIHVzZUFuaW1hdGlvbkZyYW1lRm9yQ3JlYXRlLCB0aGlzLnByaW50TGF5b3V0KTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgIFJvd1JlbmRlcmVyLnByb3RvdHlwZS5nZXRSZW5kZXJlZE5vZGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVuZGVyZWRSb3dzID0gdGhpcy5yb3dDdHJsc0J5Um93SW5kZXg7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhyZW5kZXJlZFJvd3MpLm1hcChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiByZW5kZXJlZFJvd3Nba2V5XS5nZXRSb3dOb2RlKCk7IH0pO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldFJvd0J5UG9zaXRpb24gPSBmdW5jdGlvbiAocm93UG9zaXRpb24pIHtcbiAgICAgICAgdmFyIHJvd0N0cmw7XG4gICAgICAgIHZhciByb3dJbmRleCA9IHJvd1Bvc2l0aW9uLnJvd0luZGV4O1xuICAgICAgICBzd2l0Y2ggKHJvd1Bvc2l0aW9uLnJvd1Bpbm5lZCkge1xuICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX1RPUDpcbiAgICAgICAgICAgICAgICByb3dDdHJsID0gdGhpcy50b3BSb3dDdHJsc1tyb3dJbmRleF07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfQk9UVE9NOlxuICAgICAgICAgICAgICAgIHJvd0N0cmwgPSB0aGlzLmJvdHRvbVJvd0N0cmxzW3Jvd0luZGV4XTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcm93Q3RybCA9IHRoaXMucm93Q3RybHNCeVJvd0luZGV4W3Jvd0luZGV4XTtcbiAgICAgICAgICAgICAgICBpZiAoIXJvd0N0cmwpIHtcbiAgICAgICAgICAgICAgICAgICAgcm93Q3RybCA9IHRoaXMuZ2V0U3RpY2t5VG9wUm93Q3RybHMoKS5maW5kKGZ1bmN0aW9uIChjdHJsKSB7IHJldHVybiBjdHJsLmdldFJvd05vZGUoKS5yb3dJbmRleCA9PT0gcm93SW5kZXg7IH0pIHx8IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dDdHJsO1xuICAgIH07XG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoZ3JpZFJvdykge1xuICAgICAgICBzd2l0Y2ggKGdyaWRSb3cucm93UGlubmVkKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfVE9QOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBpbm5lZFJvd01vZGVsLmdldFBpbm5lZFRvcFJvd0RhdGEoKVtncmlkUm93LnJvd0luZGV4XTtcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9CT1RUT006XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkQm90dG9tUm93RGF0YSgpW2dyaWRSb3cucm93SW5kZXhdO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXRSb3coZ3JpZFJvdy5yb3dJbmRleCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIHJldHVybnMgdHJ1ZSBpZiBhbnkgcm93IGJldHdlZW4gc3RhcnRJbmRleCBhbmQgZW5kSW5kZXggaXMgcmVuZGVyZWQuIHVzZWQgYnlcbiAgICAvLyBTU1JNIG9yIElSTSwgYXMgdGhleSBkb24ndCB3YW50IHRvIHB1cmdlIHZpc2libGUgYmxvY2tzIGZyb20gY2FjaGUuXG4gICAgUm93UmVuZGVyZXIucHJvdG90eXBlLmlzUmFuZ2VJblJlbmRlcmVkVmlld3BvcnQgPSBmdW5jdGlvbiAoc3RhcnRJbmRleCwgZW5kSW5kZXgpIHtcbiAgICAgICAgLy8gcGFyZW50IGNsb3NlZCBtZWFucyB0aGUgcGFyZW50IG5vZGUgaXMgbm90IGV4cGFuZGVkLCB0aHVzIHRoZXNlIGJsb2NrcyBhcmUgbm90IHZpc2libGVcbiAgICAgICAgdmFyIHBhcmVudENsb3NlZCA9IHN0YXJ0SW5kZXggPT0gbnVsbCB8fCBlbmRJbmRleCA9PSBudWxsO1xuICAgICAgICBpZiAocGFyZW50Q2xvc2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJsb2NrQWZ0ZXJWaWV3cG9ydCA9IHN0YXJ0SW5kZXggPiB0aGlzLmxhc3RSZW5kZXJlZFJvdztcbiAgICAgICAgdmFyIGJsb2NrQmVmb3JlVmlld3BvcnQgPSBlbmRJbmRleCA8IHRoaXMuZmlyc3RSZW5kZXJlZFJvdztcbiAgICAgICAgdmFyIGJsb2NrSW5zaWRlVmlld3BvcnQgPSAhYmxvY2tCZWZvcmVWaWV3cG9ydCAmJiAhYmxvY2tBZnRlclZpZXdwb3J0O1xuICAgICAgICByZXR1cm4gYmxvY2tJbnNpZGVWaWV3cG9ydDtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkMTMoW1xuICAgICAgICBBdXRvd2lyZWQoXCJhbmltYXRpb25GcmFtZVNlcnZpY2VcIilcbiAgICBdLCBSb3dSZW5kZXJlci5wcm90b3R5cGUsIFwiYW5pbWF0aW9uRnJhbWVTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQxMyhbXG4gICAgICAgIEF1dG93aXJlZChcInBhZ2luYXRpb25Qcm94eVwiKVxuICAgIF0sIFJvd1JlbmRlcmVyLnByb3RvdHlwZSwgXCJwYWdpbmF0aW9uUHJveHlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEzKFtcbiAgICAgICAgQXV0b3dpcmVkKFwiY29sdW1uTW9kZWxcIilcbiAgICBdLCBSb3dSZW5kZXJlci5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEzKFtcbiAgICAgICAgQXV0b3dpcmVkKFwicGlubmVkUm93TW9kZWxcIilcbiAgICBdLCBSb3dSZW5kZXJlci5wcm90b3R5cGUsIFwicGlubmVkUm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEzKFtcbiAgICAgICAgQXV0b3dpcmVkKFwicm93TW9kZWxcIilcbiAgICBdLCBSb3dSZW5kZXJlci5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEzKFtcbiAgICAgICAgQXV0b3dpcmVkKFwiZm9jdXNTZXJ2aWNlXCIpXG4gICAgXSwgUm93UmVuZGVyZXIucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTMoW1xuICAgICAgICBBdXRvd2lyZWQoXCJiZWFuc1wiKVxuICAgIF0sIFJvd1JlbmRlcmVyLnByb3RvdHlwZSwgXCJiZWFuc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTMoW1xuICAgICAgICBBdXRvd2lyZWQoXCJyb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlXCIpXG4gICAgXSwgUm93UmVuZGVyZXIucHJvdG90eXBlLCBcInJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEzKFtcbiAgICAgICAgQXV0b3dpcmVkKFwiY3RybHNTZXJ2aWNlXCIpXG4gICAgXSwgUm93UmVuZGVyZXIucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTMoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93UmVuZGVyZXIucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgUm93UmVuZGVyZXIgPSBfX2RlY29yYXRlJDEzKFtcbiAgICAgICAgQmVhbihcInJvd1JlbmRlcmVyXCIpXG4gICAgXSwgUm93UmVuZGVyZXIpO1xuICAgIHJldHVybiBSb3dSZW5kZXJlcjtcbn0oQmVhblN0dWIpKTtcbnZhciBSb3dDdHJsQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUm93Q3RybENhY2hlKG1heENvdW50KSB7XG4gICAgICAgIC8vIG1hcCBmb3IgZmFzdCBhY2Nlc3NcbiAgICAgICAgdGhpcy5lbnRyaWVzTWFwID0ge307XG4gICAgICAgIC8vIGxpc3QgZm9yIGtlZXBpbmcgb3JkZXJcbiAgICAgICAgdGhpcy5lbnRyaWVzTGlzdCA9IFtdO1xuICAgICAgICB0aGlzLm1heENvdW50ID0gbWF4Q291bnQ7XG4gICAgfVxuICAgIFJvd0N0cmxDYWNoZS5wcm90b3R5cGUuYWRkUm93ID0gZnVuY3Rpb24gKHJvd0N0cmwpIHtcbiAgICAgICAgdGhpcy5lbnRyaWVzTWFwW3Jvd0N0cmwuZ2V0Um93Tm9kZSgpLmlkXSA9IHJvd0N0cmw7XG4gICAgICAgIHRoaXMuZW50cmllc0xpc3QucHVzaChyb3dDdHJsKTtcbiAgICAgICAgcm93Q3RybC5zZXRDYWNoZWQodHJ1ZSk7XG4gICAgICAgIGlmICh0aGlzLmVudHJpZXNMaXN0Lmxlbmd0aCA+IHRoaXMubWF4Q291bnQpIHtcbiAgICAgICAgICAgIHZhciByb3dDdHJsVG9EZXN0cm95ID0gdGhpcy5lbnRyaWVzTGlzdFswXTtcbiAgICAgICAgICAgIHJvd0N0cmxUb0Rlc3Ryb3kuZGVzdHJveUZpcnN0UGFzcygpO1xuICAgICAgICAgICAgcm93Q3RybFRvRGVzdHJveS5kZXN0cm95U2Vjb25kUGFzcygpO1xuICAgICAgICAgICAgdGhpcy5yZW1vdmVGcm9tQ2FjaGUocm93Q3RybFRvRGVzdHJveSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0N0cmxDYWNoZS5wcm90b3R5cGUuZ2V0Um93ID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgaWYgKHJvd05vZGUgPT0gbnVsbCB8fCByb3dOb2RlLmlkID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXMgPSB0aGlzLmVudHJpZXNNYXBbcm93Tm9kZS5pZF07XG4gICAgICAgIGlmICghcmVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUZyb21DYWNoZShyZXMpO1xuICAgICAgICByZXMuc2V0Q2FjaGVkKGZhbHNlKTtcbiAgICAgICAgLy8gdGhpcyBjYW4gaGFwcGVuIGlmIHVzZXIgcmVsb2FkcyBkYXRhLCBhbmQgYSBuZXcgUm93Tm9kZSBpcyByZXVzaW5nXG4gICAgICAgIC8vIHRoZSBzYW1lIElEIGFzIHRoZSBvbGQgb25lXG4gICAgICAgIHZhciByb3dOb2RlTWlzbWF0Y2ggPSByZXMuZ2V0Um93Tm9kZSgpICE9IHJvd05vZGU7XG4gICAgICAgIHJldHVybiByb3dOb2RlTWlzbWF0Y2ggPyBudWxsIDogcmVzO1xuICAgIH07XG4gICAgUm93Q3RybENhY2hlLnByb3RvdHlwZS5yZW1vdmVGcm9tQ2FjaGUgPSBmdW5jdGlvbiAocm93Q3RybCkge1xuICAgICAgICB2YXIgcm93Tm9kZUlkID0gcm93Q3RybC5nZXRSb3dOb2RlKCkuaWQ7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmVudHJpZXNNYXBbcm93Tm9kZUlkXTtcbiAgICAgICAgcmVtb3ZlRnJvbUFycmF5KHRoaXMuZW50cmllc0xpc3QsIHJvd0N0cmwpO1xuICAgIH07XG4gICAgUm93Q3RybENhY2hlLnByb3RvdHlwZS5nZXRFbnRyaWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lbnRyaWVzTGlzdDtcbiAgICB9O1xuICAgIHJldHVybiBSb3dDdHJsQ2FjaGU7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDE5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxMiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFZhbHVlRm9ybWF0dGVyU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMTkoVmFsdWVGb3JtYXR0ZXJTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFZhbHVlRm9ybWF0dGVyU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBWYWx1ZUZvcm1hdHRlclNlcnZpY2UucHJvdG90eXBlLmZvcm1hdFZhbHVlID0gZnVuY3Rpb24gKGNvbHVtbiwgbm9kZSwgdmFsdWUsIHN1cHBsaWVkRm9ybWF0dGVyLCB1c2VGb3JtYXR0ZXJGcm9tQ29sdW1uKSB7XG4gICAgICAgIGlmICh1c2VGb3JtYXR0ZXJGcm9tQ29sdW1uID09PSB2b2lkIDApIHsgdXNlRm9ybWF0dGVyRnJvbUNvbHVtbiA9IHRydWU7IH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IG51bGw7XG4gICAgICAgIHZhciBmb3JtYXR0ZXI7XG4gICAgICAgIHZhciBjb2xEZWYgPSBjb2x1bW4uZ2V0Q29sRGVmKCk7XG4gICAgICAgIGlmIChzdXBwbGllZEZvcm1hdHRlcikge1xuICAgICAgICAgICAgLy8gdXNlIHN1cHBsaWVkIGZvcm1hdHRlciBpZiBwcm92aWRlZCwgZS5nLiBzZXQgZmlsdGVyIGl0ZW1zIGNhbiBoYXZlIHRoZWlyIG93biB2YWx1ZSBmb3JtYXR0ZXJzXG4gICAgICAgICAgICBmb3JtYXR0ZXIgPSBzdXBwbGllZEZvcm1hdHRlcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh1c2VGb3JtYXR0ZXJGcm9tQ29sdW1uKSB7XG4gICAgICAgICAgICAvLyBpZiByb3cgaXMgcGlubmVkLCBnaXZlIHByZWZlcmVuY2UgdG8gdGhlIHBpbm5lZCBmb3JtYXR0ZXJcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IG5vZGUgJiYgbm9kZS5yb3dQaW5uZWQgJiYgY29sRGVmLnBpbm5lZFJvd1ZhbHVlRm9ybWF0dGVyID9cbiAgICAgICAgICAgICAgICBjb2xEZWYucGlubmVkUm93VmFsdWVGb3JtYXR0ZXIgOiBjb2xEZWYudmFsdWVGb3JtYXR0ZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdHRlcikge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgbm9kZTogbm9kZSxcbiAgICAgICAgICAgICAgICBkYXRhOiBub2RlID8gbm9kZS5kYXRhIDogbnVsbCxcbiAgICAgICAgICAgICAgICBjb2xEZWY6IGNvbERlZixcbiAgICAgICAgICAgICAgICBjb2x1bW46IGNvbHVtbixcbiAgICAgICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICAgICAgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5leHByZXNzaW9uU2VydmljZS5ldmFsdWF0ZShmb3JtYXR0ZXIsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29sRGVmLnJlZkRhdGEpIHtcbiAgICAgICAgICAgIHJldHVybiBjb2xEZWYucmVmRGF0YVt2YWx1ZV0gfHwgJyc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgZG9uJ3QgZG8gdGhpcywgdGhlbiBhcnJheXMgZ2V0IGRpc3BsYXllZCBhcyAxLDIsMywgYnV0IHdlIHdhbnQgMSwgMiwgMyAoaS5lLiB3aXRoIHNwYWNlcylcbiAgICAgICAgaWYgKHJlc3VsdCA9PSBudWxsICYmIEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZS5qb2luKCcsICcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDEyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdleHByZXNzaW9uU2VydmljZScpXG4gICAgXSwgVmFsdWVGb3JtYXR0ZXJTZXJ2aWNlLnByb3RvdHlwZSwgXCJleHByZXNzaW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIFZhbHVlRm9ybWF0dGVyU2VydmljZSA9IF9fZGVjb3JhdGUkMTIoW1xuICAgICAgICBCZWFuKCd2YWx1ZUZvcm1hdHRlclNlcnZpY2UnKVxuICAgIF0sIFZhbHVlRm9ybWF0dGVyU2VydmljZSk7XG4gICAgcmV0dXJuIFZhbHVlRm9ybWF0dGVyU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxOCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMTEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBQaW5uZWRSb3dNb2RlbCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMTgoUGlubmVkUm93TW9kZWwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUGlubmVkUm93TW9kZWwoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0UGlubmVkVG9wUm93RGF0YSh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRQaW5uZWRUb3BSb3dEYXRhKCkpO1xuICAgICAgICB0aGlzLnNldFBpbm5lZEJvdHRvbVJvd0RhdGEodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0UGlubmVkQm90dG9tUm93RGF0YSgpKTtcbiAgICB9O1xuICAgIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gKGZsb2F0aW5nKSB7XG4gICAgICAgIHZhciByb3dzID0gZmxvYXRpbmcgPT09IENvbnN0YW50cy5QSU5ORURfVE9QID8gdGhpcy5waW5uZWRUb3BSb3dzIDogdGhpcy5waW5uZWRCb3R0b21Sb3dzO1xuICAgICAgICByZXR1cm4gbWlzc2luZ09yRW1wdHkocm93cyk7XG4gICAgfTtcbiAgICBQaW5uZWRSb3dNb2RlbC5wcm90b3R5cGUuaXNSb3dzVG9SZW5kZXIgPSBmdW5jdGlvbiAoZmxvYXRpbmcpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLmlzRW1wdHkoZmxvYXRpbmcpO1xuICAgIH07XG4gICAgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLmdldFJvd0F0UGl4ZWwgPSBmdW5jdGlvbiAocGl4ZWwsIGZsb2F0aW5nKSB7XG4gICAgICAgIHZhciByb3dzID0gZmxvYXRpbmcgPT09IENvbnN0YW50cy5QSU5ORURfVE9QID8gdGhpcy5waW5uZWRUb3BSb3dzIDogdGhpcy5waW5uZWRCb3R0b21Sb3dzO1xuICAgICAgICBpZiAobWlzc2luZ09yRW1wdHkocm93cykpIHtcbiAgICAgICAgICAgIHJldHVybiAwOyAvLyB0aGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIGp1c3QgaW4gY2FzZSwgMCBpcyBncmFjZWZ1bCBmYWlsdXJlXG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcm93Tm9kZSA9IHJvd3NbaV07XG4gICAgICAgICAgICB2YXIgcm93VG9wUGl4ZWwgPSByb3dOb2RlLnJvd1RvcCArIHJvd05vZGUucm93SGVpZ2h0IC0gMTtcbiAgICAgICAgICAgIC8vIG9ubHkgbmVlZCB0byByYW5nZSBjaGVjayBhZ2FpbnN0IHRoZSB0b3AgcGl4ZWwsIGFzIHdlIGFyZSBnb2luZyB0aHJvdWdoIHRoZSBsaXN0XG4gICAgICAgICAgICAvLyBpbiBvcmRlciwgZmlyc3Qgcm93IHRvIGhpdCB0aGUgcGl4ZWwgd2luc1xuICAgICAgICAgICAgaWYgKHJvd1RvcFBpeGVsID49IHBpeGVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd3MubGVuZ3RoIC0gMTtcbiAgICB9O1xuICAgIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZS5zZXRQaW5uZWRUb3BSb3dEYXRhID0gZnVuY3Rpb24gKHJvd0RhdGEpIHtcbiAgICAgICAgdGhpcy5waW5uZWRUb3BSb3dzID0gdGhpcy5jcmVhdGVOb2Rlc0Zyb21EYXRhKHJvd0RhdGEsIHRydWUpO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfUElOTkVEX1JPV19EQVRBX0NIQU5HRURcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBQaW5uZWRSb3dNb2RlbC5wcm90b3R5cGUuc2V0UGlubmVkQm90dG9tUm93RGF0YSA9IGZ1bmN0aW9uIChyb3dEYXRhKSB7XG4gICAgICAgIHRoaXMucGlubmVkQm90dG9tUm93cyA9IHRoaXMuY3JlYXRlTm9kZXNGcm9tRGF0YShyb3dEYXRhLCBmYWxzZSk7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9QSU5ORURfUk9XX0RBVEFfQ0hBTkdFRFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZS5jcmVhdGVOb2Rlc0Zyb21EYXRhID0gZnVuY3Rpb24gKGFsbERhdGEsIGlzVG9wKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciByb3dOb2RlcyA9IFtdO1xuICAgICAgICBpZiAoYWxsRGF0YSkge1xuICAgICAgICAgICAgdmFyIG5leHRSb3dUb3BfMSA9IDA7XG4gICAgICAgICAgICBhbGxEYXRhLmZvckVhY2goZnVuY3Rpb24gKGRhdGFJdGVtLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciByb3dOb2RlID0gbmV3IFJvd05vZGUoX3RoaXMuYmVhbnMpO1xuICAgICAgICAgICAgICAgIHJvd05vZGUuZGF0YSA9IGRhdGFJdGVtO1xuICAgICAgICAgICAgICAgIHZhciBpZFByZWZpeCA9IGlzVG9wID8gUm93Tm9kZS5JRF9QUkVGSVhfVE9QX1BJTk5FRCA6IFJvd05vZGUuSURfUFJFRklYX0JPVFRPTV9QSU5ORUQ7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5pZCA9IGlkUHJlZml4ICsgaW5kZXg7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5yb3dQaW5uZWQgPSBpc1RvcCA/IENvbnN0YW50cy5QSU5ORURfVE9QIDogQ29uc3RhbnRzLlBJTk5FRF9CT1RUT007XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5zZXRSb3dUb3AobmV4dFJvd1RvcF8xKTtcbiAgICAgICAgICAgICAgICByb3dOb2RlLnNldFJvd0hlaWdodChfdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93SGVpZ2h0Rm9yTm9kZShyb3dOb2RlKS5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIHJvd05vZGUuc2V0Um93SW5kZXgoaW5kZXgpO1xuICAgICAgICAgICAgICAgIG5leHRSb3dUb3BfMSArPSByb3dOb2RlLnJvd0hlaWdodDtcbiAgICAgICAgICAgICAgICByb3dOb2Rlcy5wdXNoKHJvd05vZGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd05vZGVzO1xuICAgIH07XG4gICAgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLmdldFBpbm5lZFRvcFJvd0RhdGEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbm5lZFRvcFJvd3M7XG4gICAgfTtcbiAgICBQaW5uZWRSb3dNb2RlbC5wcm90b3R5cGUuZ2V0UGlubmVkQm90dG9tUm93RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkQm90dG9tUm93cztcbiAgICB9O1xuICAgIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZS5nZXRQaW5uZWRUb3BUb3RhbEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VG90YWxIZWlnaHQodGhpcy5waW5uZWRUb3BSb3dzKTtcbiAgICB9O1xuICAgIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZS5nZXRQaW5uZWRUb3BSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkVG9wUm93cyA/IHRoaXMucGlubmVkVG9wUm93cy5sZW5ndGggOiAwO1xuICAgIH07XG4gICAgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLmdldFBpbm5lZEJvdHRvbVJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waW5uZWRCb3R0b21Sb3dzID8gdGhpcy5waW5uZWRCb3R0b21Sb3dzLmxlbmd0aCA6IDA7XG4gICAgfTtcbiAgICBQaW5uZWRSb3dNb2RlbC5wcm90b3R5cGUuZ2V0UGlubmVkVG9wUm93ID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBpbm5lZFRvcFJvd3NbaW5kZXhdO1xuICAgIH07XG4gICAgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLmdldFBpbm5lZEJvdHRvbVJvdyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waW5uZWRCb3R0b21Sb3dzW2luZGV4XTtcbiAgICB9O1xuICAgIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZS5mb3JFYWNoUGlubmVkVG9wUm93ID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIGlmIChtaXNzaW5nT3JFbXB0eSh0aGlzLnBpbm5lZFRvcFJvd3MpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5waW5uZWRUb3BSb3dzLmZvckVhY2goY2FsbGJhY2spO1xuICAgIH07XG4gICAgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLmZvckVhY2hQaW5uZWRCb3R0b21Sb3cgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKG1pc3NpbmdPckVtcHR5KHRoaXMucGlubmVkQm90dG9tUm93cykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBpbm5lZEJvdHRvbVJvd3MuZm9yRWFjaChjYWxsYmFjayk7XG4gICAgfTtcbiAgICBQaW5uZWRSb3dNb2RlbC5wcm90b3R5cGUuZ2V0UGlubmVkQm90dG9tVG90YWxIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFRvdGFsSGVpZ2h0KHRoaXMucGlubmVkQm90dG9tUm93cyk7XG4gICAgfTtcbiAgICBQaW5uZWRSb3dNb2RlbC5wcm90b3R5cGUuZ2V0VG90YWxIZWlnaHQgPSBmdW5jdGlvbiAocm93Tm9kZXMpIHtcbiAgICAgICAgaWYgKCFyb3dOb2RlcyB8fCByb3dOb2Rlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsYXN0Tm9kZSA9IGxhc3Qocm93Tm9kZXMpO1xuICAgICAgICByZXR1cm4gbGFzdE5vZGUucm93VG9wICsgbGFzdE5vZGUucm93SGVpZ2h0O1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQxMShbXG4gICAgICAgIEF1dG93aXJlZCgnYmVhbnMnKVxuICAgIF0sIFBpbm5lZFJvd01vZGVsLnByb3RvdHlwZSwgXCJiZWFuc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMTEoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUGlubmVkUm93TW9kZWwucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgUGlubmVkUm93TW9kZWwgPSBfX2RlY29yYXRlJDExKFtcbiAgICAgICAgQmVhbigncGlubmVkUm93TW9kZWwnKVxuICAgIF0sIFBpbm5lZFJvd01vZGVsKTtcbiAgICByZXR1cm4gUGlubmVkUm93TW9kZWw7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBTZXJ2ZXJTaWRlVHJhbnNhY3Rpb25SZXN1bHRTdGF0dXM7XG4oZnVuY3Rpb24gKFNlcnZlclNpZGVUcmFuc2FjdGlvblJlc3VsdFN0YXR1cykge1xuICAgIC8qKiBUcmFuc2FjdGlvbiB3YXMgc3VjY2Vzc2Z1bGx5IGFwcGxpZWQgKi9cbiAgICBTZXJ2ZXJTaWRlVHJhbnNhY3Rpb25SZXN1bHRTdGF0dXNbXCJBcHBsaWVkXCJdID0gXCJBcHBsaWVkXCI7XG4gICAgLyoqXG4gICAgICogU3RvcmUgd2FzIG5vdCBmb3VuZCwgdHJhbnNhY3Rpb24gbm90IGFwcGxpZWQuXG4gICAgICogRWl0aGVyIGludmFsaWQgcm91dGUsIG9yIHRoZSBwYXJlbnQgcm93IGhhcyBub3QgeWV0IGJlZW4gZXhwYW5kZWQuXG4gICAgICovXG4gICAgU2VydmVyU2lkZVRyYW5zYWN0aW9uUmVzdWx0U3RhdHVzW1wiU3RvcmVOb3RGb3VuZFwiXSA9IFwiU3RvcmVOb3RGb3VuZFwiO1xuICAgIC8qKlxuICAgICAqIFN0b3JlIGlzIGxvYWRpbmcsIHRyYW5zYWN0aW9uIG5vdCBhcHBsaWVkLlxuICAgICAqL1xuICAgIFNlcnZlclNpZGVUcmFuc2FjdGlvblJlc3VsdFN0YXR1c1tcIlN0b3JlTG9hZGluZ1wiXSA9IFwiU3RvcmVMb2FkaW5nXCI7XG4gICAgLyoqXG4gICAgICogU3RvcmUgaXMgbG9hZGluZyAoYXMgbWF4IGxvYWRzIGV4Y2VlZGVkKSwgdHJhbnNhY3Rpb24gbm90IGFwcGxpZWQuXG4gICAgICovXG4gICAgU2VydmVyU2lkZVRyYW5zYWN0aW9uUmVzdWx0U3RhdHVzW1wiU3RvcmVXYWl0aW5nVG9Mb2FkXCJdID0gXCJTdG9yZVdhaXRpbmdUb0xvYWRcIjtcbiAgICAvKipcbiAgICAgKiBTdG9yZSBsb2FkIGF0dGVtcHQgZmFpbGVkLCB0cmFuc2FjdGlvbiBub3QgYXBwbGllZC5cbiAgICAgKi9cbiAgICBTZXJ2ZXJTaWRlVHJhbnNhY3Rpb25SZXN1bHRTdGF0dXNbXCJTdG9yZUxvYWRpbmdGYWlsZWRcIl0gPSBcIlN0b3JlTG9hZGluZ0ZhaWxlZFwiO1xuICAgIC8qKlxuICAgICAqIFN0b3JlIGlzIHR5cGUgUGFydGlhbCwgd2hpY2ggZG9lc24ndCBhY2NlcHQgdHJhbnNhY3Rpb25zXG4gICAgICovXG4gICAgU2VydmVyU2lkZVRyYW5zYWN0aW9uUmVzdWx0U3RhdHVzW1wiU3RvcmVXcm9uZ1R5cGVcIl0gPSBcIlN0b3JlV3JvbmdUeXBlXCI7XG4gICAgLyoqXG4gICAgICogVHJhbnNhY3Rpb24gd2FzIGNhbmNlbGxlZCwgZHVlIHRvIGdyaWQuXG4gICAgICogQ2FsbGJhY2sgaXNBcHBseVNlcnZlclNpZGVUcmFuc2FjdGlvbigpIHJldHVybmluZyBmYWxzZVxuICAgICAqL1xuICAgIFNlcnZlclNpZGVUcmFuc2FjdGlvblJlc3VsdFN0YXR1c1tcIkNhbmNlbGxlZFwiXSA9IFwiQ2FuY2VsbGVkXCI7XG59KShTZXJ2ZXJTaWRlVHJhbnNhY3Rpb25SZXN1bHRTdGF0dXMgfHwgKFNlcnZlclNpZGVUcmFuc2FjdGlvblJlc3VsdFN0YXR1cyA9IHt9KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbi8vIHdoZW4gZG9pbmcgdHJhbnNhY3Rpb25zLCBvciBjaGFuZ2UgZGV0ZWN0aW9uLCBhbmQgZ3JvdXBpbmcgaXMgcHJlc2VudFxuLy8gaW4gdGhlIGRhdGEsIHRoZXJlIGlzIG5vIG5lZWQgZm9yIHRoZSBDbGllbnRTaWRlUm93TW9kZWwgdG8gdXBkYXRlIGVhY2hcbi8vIGdyb3VwIGFmdGVyIGFuIHVwZGF0ZSwgb255IHBhcnRzIHRoYXQgd2VyZSBpbXBhY3RlZCBieSB0aGUgY2hhbmdlLlxuLy8gdGhpcyBjbGFzcyBrZWVwcyB0cmFjayBvZiBhbGwgZ3JvdXBzIHRoYXQgd2VyZSBpbXBhY3RlZCBieSBhIHRyYW5zYWN0aW9uLlxuLy8gdGhlIHRoZSBkaWZmZXJlbnQgQ1NSTSBvcGVyYXRpb25zIChmaWx0ZXIsIHNvcnQgZXRjKSB1c2UgdGhlIGZvckVhY2ggbWV0aG9kXG4vLyB0byB2aXNpdCBlYWNoIGdyb3VwIHRoYXQgd2FzIGNoYW5nZWQuXG52YXIgQ2hhbmdlZFBhdGggPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ2hhbmdlZFBhdGgoa2VlcGluZ0NvbHVtbnMsIHJvb3ROb2RlKSB7XG4gICAgICAgIC8vIHdoZXRoZXIgY2hhbmdlZCBwYXRoIGlzIGFjdGl2ZSBvZiBub3QuIGl0IGlzIGFjdGl2ZSB3aGVuIGEpIGRvaW5nXG4gICAgICAgIC8vIGEgdHJhbnNhY3Rpb24gdXBkYXRlIG9yIGIpIGRvaW5nIGNoYW5nZSBkZXRlY3Rpb24uIGlmIHdlIGFyZSBkb2luZ1xuICAgICAgICAvLyBhIENTUk0gcmVmcmVzaCBmb3Igb3RoZXIgcmVhc29ucyAoYWZ0ZXIgc29ydCBvciBmaWx0ZXIsIG9yIHVzZXIgY2FsbGluZ1xuICAgICAgICAvLyBzZXRSb3dEYXRhKCkgd2l0aG91dCBkZWx0YSBtb2RlKSB0aGVuIHdlIGFyZSBub3QgYWN0aXZlLiB3ZSBhcmUgYWxzb1xuICAgICAgICAvLyBtYXJrZWQgYXMgbm90IGFjdGl2ZSBpZiBzZWNvbmRhcnkgY29sdW1ucyBjaGFuZ2UgaW4gcGl2b3QgKGFzIHRoaXMgaW1wYWN0c1xuICAgICAgICAvLyBhZ2dyZWdhdGlvbnMpXG4gICAgICAgIHRoaXMuYWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgLy8gZm9yIGVhY2ggbm9kZSBpbiB0aGUgY2hhbmdlIHBhdGgsIHdlIGFsc28gc3RvcmUgd2hpY2ggY29sdW1ucyBuZWVkXG4gICAgICAgIC8vIHRvIGJlIHJlLWFnZ3JlZ2F0ZWQuXG4gICAgICAgIHRoaXMubm9kZUlkc1RvQ29sdW1ucyA9IHt9O1xuICAgICAgICAvLyBmb3IgcXVpY2sgbG9va3VwLCBhbGwgaXRlbXMgaW4gdGhlIGNoYW5nZSBwYXRoIGFyZSBtYXBwZWQgYnkgbm9kZUlkXG4gICAgICAgIHRoaXMubWFwVG9JdGVtcyA9IHt9O1xuICAgICAgICB0aGlzLmtlZXBpbmdDb2x1bW5zID0ga2VlcGluZ0NvbHVtbnM7XG4gICAgICAgIHRoaXMucGF0aFJvb3QgPSB7XG4gICAgICAgICAgICByb3dOb2RlOiByb290Tm9kZSxcbiAgICAgICAgICAgIGNoaWxkcmVuOiBudWxsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMubWFwVG9JdGVtc1tyb290Tm9kZS5pZF0gPSB0aGlzLnBhdGhSb290O1xuICAgIH1cbiAgICAvLyBjYW4gYmUgc2V0IGluYWN0aXZlIGJ5OlxuICAgIC8vIGEpIENsaWVudFNpZGVSb3dNb2RlbCwgaWYgbm8gdHJhbnNhY3Rpb25zIG9yXG4gICAgLy8gYikgUGl2b3RTZXJ2aWNlLCBpZiBzZWNvbmRhcnkgY29sdW1ucyBjaGFuZ2VkXG4gICAgQ2hhbmdlZFBhdGgucHJvdG90eXBlLnNldEluYWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgIH07XG4gICAgQ2hhbmdlZFBhdGgucHJvdG90eXBlLmlzQWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmU7XG4gICAgfTtcbiAgICBDaGFuZ2VkUGF0aC5wcm90b3R5cGUuZGVwdGhGaXJzdFNlYXJjaENoYW5nZWRQYXRoID0gZnVuY3Rpb24gKHBhdGhJdGVtLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAocGF0aEl0ZW0uY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0aEl0ZW0uY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlcHRoRmlyc3RTZWFyY2hDaGFuZ2VkUGF0aChwYXRoSXRlbS5jaGlsZHJlbltpXSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhbGxiYWNrKHBhdGhJdGVtLnJvd05vZGUpO1xuICAgIH07XG4gICAgQ2hhbmdlZFBhdGgucHJvdG90eXBlLmRlcHRoRmlyc3RTZWFyY2hFdmVyeXRoaW5nID0gZnVuY3Rpb24gKHJvd05vZGUsIGNhbGxiYWNrLCB0cmF2ZXJzZUV2ZXJ5dGhpbmcpIHtcbiAgICAgICAgaWYgKHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwW2ldO1xuICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVwdGhGaXJzdFNlYXJjaEV2ZXJ5dGhpbmcocm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXBbaV0sIGNhbGxiYWNrLCB0cmF2ZXJzZUV2ZXJ5dGhpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0cmF2ZXJzZUV2ZXJ5dGhpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2FsbGJhY2socm93Tm9kZSk7XG4gICAgfTtcbiAgICAvLyB0cmF2ZXJzZUxlYWZOb2RlcyAtPiB1c2VkIHdoZW4gTk9UIGRvaW5nIGNoYW5nZWQgcGF0aCwgaWUgdHJhdmVyc2luZyBldmVyeXRoaW5nLiB0aGUgY2FsbGJhY2tcbiAgICAvLyB3aWxsIGJlIGNhbGxlZCBmb3IgY2hpbGQgbm9kZXMgaW4gYWRkaXRpb24gdG8gcGFyZW50IG5vZGVzLlxuICAgIENoYW5nZWRQYXRoLnByb3RvdHlwZS5mb3JFYWNoQ2hhbmdlZE5vZGVEZXB0aEZpcnN0ID0gZnVuY3Rpb24gKGNhbGxiYWNrLCB0cmF2ZXJzZUxlYWZOb2RlcywgaW5jbHVkZVVuY2hhbmdlZE5vZGVzKSB7XG4gICAgICAgIGlmICh0cmF2ZXJzZUxlYWZOb2RlcyA9PT0gdm9pZCAwKSB7IHRyYXZlcnNlTGVhZk5vZGVzID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKGluY2x1ZGVVbmNoYW5nZWROb2RlcyA9PT0gdm9pZCAwKSB7IGluY2x1ZGVVbmNoYW5nZWROb2RlcyA9IGZhbHNlOyB9XG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZSAmJiAhaW5jbHVkZVVuY2hhbmdlZE5vZGVzKSB7XG4gICAgICAgICAgICAvLyBpZiB3ZSBhcmUgYWN0aXZlLCB0aGVuIHVzZSB0aGUgY2hhbmdlIHBhdGggdG8gY2FsbGJhY2tcbiAgICAgICAgICAgIC8vIG9ubHkgZm9yIHVwZGF0ZWQgZ3JvdXBzXG4gICAgICAgICAgICB0aGlzLmRlcHRoRmlyc3RTZWFyY2hDaGFuZ2VkUGF0aCh0aGlzLnBhdGhSb290LCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyB3ZSBhcmUgbm90IGFjdGl2ZSwgc28gY2FsbGJhY2sgZm9yIGV2ZXJ5dGhpbmcsIHdhbGsgdGhlIGVudGlyZSBwYXRoXG4gICAgICAgICAgICB0aGlzLmRlcHRoRmlyc3RTZWFyY2hFdmVyeXRoaW5nKHRoaXMucGF0aFJvb3Qucm93Tm9kZSwgY2FsbGJhY2ssIHRyYXZlcnNlTGVhZk5vZGVzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2hhbmdlZFBhdGgucHJvdG90eXBlLmV4ZWN1dGVGcm9tUm9vdE5vZGUgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sodGhpcy5wYXRoUm9vdC5yb3dOb2RlKTtcbiAgICB9O1xuICAgIENoYW5nZWRQYXRoLnByb3RvdHlwZS5jcmVhdGVQYXRoSXRlbXMgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICB2YXIgcG9pbnRlciA9IHJvd05vZGU7XG4gICAgICAgIHZhciBuZXdFbnRyeUNvdW50ID0gMDtcbiAgICAgICAgd2hpbGUgKCF0aGlzLm1hcFRvSXRlbXNbcG9pbnRlci5pZF0pIHtcbiAgICAgICAgICAgIHZhciBuZXdFbnRyeSA9IHtcbiAgICAgICAgICAgICAgICByb3dOb2RlOiBwb2ludGVyLFxuICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBudWxsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5tYXBUb0l0ZW1zW3BvaW50ZXIuaWRdID0gbmV3RW50cnk7XG4gICAgICAgICAgICBuZXdFbnRyeUNvdW50Kys7XG4gICAgICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ld0VudHJ5Q291bnQ7XG4gICAgfTtcbiAgICBDaGFuZ2VkUGF0aC5wcm90b3R5cGUucG9wdWxhdGVDb2x1bW5zTWFwID0gZnVuY3Rpb24gKHJvd05vZGUsIGNvbHVtbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLmtlZXBpbmdDb2x1bW5zIHx8ICFjb2x1bW5zKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBvaW50ZXIgPSByb3dOb2RlO1xuICAgICAgICB3aGlsZSAocG9pbnRlcikge1xuICAgICAgICAgICAgLy8gaWYgY29sdW1ucywgYWRkIHRoZSBjb2x1bW5zIGluIGFsbCB0aGUgd2F5IHRvIHBhcmVudCwgbWVyZ2luZ1xuICAgICAgICAgICAgLy8gaW4gYW55IG90aGVyIGNvbHVtbnMgdGhhdCBtaWdodCBiZSB0aGVyZSBhbHJlYWR5XG4gICAgICAgICAgICBpZiAoIXRoaXMubm9kZUlkc1RvQ29sdW1uc1twb2ludGVyLmlkXSkge1xuICAgICAgICAgICAgICAgIHRoaXMubm9kZUlkc1RvQ29sdW1uc1twb2ludGVyLmlkXSA9IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIF90aGlzLm5vZGVJZHNUb0NvbHVtbnNbcG9pbnRlci5pZF1bY29sLmdldElkKCldID0gdHJ1ZTsgfSk7XG4gICAgICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENoYW5nZWRQYXRoLnByb3RvdHlwZS5saW5rUGF0aEl0ZW1zID0gZnVuY3Rpb24gKHJvd05vZGUsIG5ld0VudHJ5Q291bnQpIHtcbiAgICAgICAgdmFyIHBvaW50ZXIgPSByb3dOb2RlO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5ld0VudHJ5Q291bnQ7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRoaXNJdGVtID0gdGhpcy5tYXBUb0l0ZW1zW3BvaW50ZXIuaWRdO1xuICAgICAgICAgICAgdmFyIHBhcmVudEl0ZW0gPSB0aGlzLm1hcFRvSXRlbXNbcG9pbnRlci5wYXJlbnQuaWRdO1xuICAgICAgICAgICAgaWYgKCFwYXJlbnRJdGVtLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50SXRlbS5jaGlsZHJlbiA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyZW50SXRlbS5jaGlsZHJlbi5wdXNoKHRoaXNJdGVtKTtcbiAgICAgICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLnBhcmVudDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gY2FsbGVkIGJ5XG4gICAgLy8gMSkgY2hhbmdlIGRldGVjdGlvbiAocHJvdmlkZXMgY29scykgYW5kXG4gICAgLy8gMikgZ3JvdXBTdGFnZSBpZiBkb2luZyB0cmFuc2FjdGlvbiB1cGRhdGUgKGRvZXNuJ3QgcHJvdmlkZSBjb2xzKVxuICAgIENoYW5nZWRQYXRoLnByb3RvdHlwZS5hZGRQYXJlbnROb2RlID0gZnVuY3Rpb24gKHJvd05vZGUsIGNvbHVtbnMpIHtcbiAgICAgICAgaWYgKCFyb3dOb2RlIHx8IHJvd05vZGUuaXNSb3dQaW5uZWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIGNhbm5vdCBkbyAgYm90aCBzdGVwcyBiZWxvdyBpbiB0aGUgc2FtZSBsb29wIGFzXG4gICAgICAgIC8vIHRoZSBzZWNvbmQgbG9vcCBoYXMgYSBkZXBlbmRlbmN5IG9uIHRoZSBmaXJzdCBsb29wLlxuICAgICAgICAvLyBpZSB0aGUgaGllcmFyY2h5IGNhbm5vdCBiZSBzdGl0Y2hlZCB1cCB5ZXQgYmVjYXVzZVxuICAgICAgICAvLyB3ZSBkb24ndCBoYXZlIGl0IGJ1aWx0IHlldFxuICAgICAgICAvLyBjcmVhdGUgdGhlIG5ldyBQYXRoSXRlbSBvYmplY3RzLlxuICAgICAgICB2YXIgbmV3RW50cnlDb3VudCA9IHRoaXMuY3JlYXRlUGF0aEl0ZW1zKHJvd05vZGUpO1xuICAgICAgICAvLyBsaW5rIGluIHRoZSBub2RlIGl0ZW1zXG4gICAgICAgIHRoaXMubGlua1BhdGhJdGVtcyhyb3dOb2RlLCBuZXdFbnRyeUNvdW50KTtcbiAgICAgICAgLy8gdXBkYXRlIGNvbHVtbnNcbiAgICAgICAgdGhpcy5wb3B1bGF0ZUNvbHVtbnNNYXAocm93Tm9kZSwgY29sdW1ucyk7XG4gICAgfTtcbiAgICBDaGFuZ2VkUGF0aC5wcm90b3R5cGUuY2FuU2tpcCA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFjdGl2ZSAmJiAhdGhpcy5tYXBUb0l0ZW1zW3Jvd05vZGUuaWRdO1xuICAgIH07XG4gICAgQ2hhbmdlZFBhdGgucHJvdG90eXBlLmdldFZhbHVlQ29sdW1uc0Zvck5vZGUgPSBmdW5jdGlvbiAocm93Tm9kZSwgdmFsdWVDb2x1bW5zKSB7XG4gICAgICAgIGlmICghdGhpcy5rZWVwaW5nQ29sdW1ucykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlQ29sdW1ucztcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sc0ZvclRoaXNOb2RlID0gdGhpcy5ub2RlSWRzVG9Db2x1bW5zW3Jvd05vZGUuaWRdO1xuICAgICAgICB2YXIgcmVzdWx0ID0gdmFsdWVDb2x1bW5zLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2xzRm9yVGhpc05vZGVbY29sLmdldElkKCldOyB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIENoYW5nZWRQYXRoLnByb3RvdHlwZS5nZXROb3RWYWx1ZUNvbHVtbnNGb3JOb2RlID0gZnVuY3Rpb24gKHJvd05vZGUsIHZhbHVlQ29sdW1ucykge1xuICAgICAgICBpZiAoIXRoaXMua2VlcGluZ0NvbHVtbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2xzRm9yVGhpc05vZGUgPSB0aGlzLm5vZGVJZHNUb0NvbHVtbnNbcm93Tm9kZS5pZF07XG4gICAgICAgIHZhciByZXN1bHQgPSB2YWx1ZUNvbHVtbnMuZmlsdGVyKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuICFjb2xzRm9yVGhpc05vZGVbY29sLmdldElkKCldOyB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIHJldHVybiBDaGFuZ2VkUGF0aDtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkMTcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBSb3dOb2RlQmxvY2sgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDE3KFJvd05vZGVCbG9jaywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSb3dOb2RlQmxvY2soaWQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3RhdGUgPSBSb3dOb2RlQmxvY2suU1RBVEVfV0FJVElOR19UT19MT0FEO1xuICAgICAgICBfdGhpcy52ZXJzaW9uID0gMDtcbiAgICAgICAgX3RoaXMuaWQgPSBpZDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSb3dOb2RlQmxvY2sucHJvdG90eXBlLmdldElkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pZDtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9jay5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IFJvd05vZGVCbG9jay5TVEFURV9MT0FESU5HO1xuICAgICAgICB0aGlzLmxvYWRGcm9tRGF0YXNvdXJjZSgpO1xuICAgIH07XG4gICAgUm93Tm9kZUJsb2NrLnByb3RvdHlwZS5nZXRWZXJzaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52ZXJzaW9uO1xuICAgIH07XG4gICAgUm93Tm9kZUJsb2NrLnByb3RvdHlwZS5zZXRTdGF0ZVdhaXRpbmdUb0xvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGluIGNhc2UgYW55IGN1cnJlbnQgbG9hZHMgaW4gcHJvZ3Jlc3MsIHRoaXMgd2lsbCBoYXZlIHRoZWlyIHJlc3VsdHMgaWdub3JlZFxuICAgICAgICB0aGlzLnZlcnNpb24rKztcbiAgICAgICAgdGhpcy5zdGF0ZSA9IFJvd05vZGVCbG9jay5TVEFURV9XQUlUSU5HX1RPX0xPQUQ7XG4gICAgfTtcbiAgICBSb3dOb2RlQmxvY2sucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9jay5wcm90b3R5cGUucGFnZUxvYWRGYWlsZWQgPSBmdW5jdGlvbiAodmVyc2lvbikge1xuICAgICAgICB2YXIgcmVxdWVzdE1vc3RSZWNlbnRBbmRMaXZlID0gdGhpcy5pc1JlcXVlc3RNb3N0UmVjZW50QW5kTGl2ZSh2ZXJzaW9uKTtcbiAgICAgICAgaWYgKHJlcXVlc3RNb3N0UmVjZW50QW5kTGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IFJvd05vZGVCbG9jay5TVEFURV9GQUlMRUQ7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NTZXJ2ZXJGYWlsKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaXNwYXRjaExvYWRDb21wbGV0ZWQoZmFsc2UpO1xuICAgIH07XG4gICAgUm93Tm9kZUJsb2NrLnByb3RvdHlwZS5zdWNjZXNzID0gZnVuY3Rpb24gKHZlcnNpb24sIHBhcmFtcykge1xuICAgICAgICB0aGlzLnN1Y2Nlc3NDb21tb24odmVyc2lvbiwgcGFyYW1zKTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9jay5wcm90b3R5cGUucGFnZUxvYWRlZCA9IGZ1bmN0aW9uICh2ZXJzaW9uLCByb3dzLCBsYXN0Um93KSB7XG4gICAgICAgIHRoaXMuc3VjY2Vzc0NvbW1vbih2ZXJzaW9uLCB7IHJvd0RhdGE6IHJvd3MsIHJvd0NvdW50OiBsYXN0Um93IH0pO1xuICAgIH07XG4gICAgUm93Tm9kZUJsb2NrLnByb3RvdHlwZS5pc1JlcXVlc3RNb3N0UmVjZW50QW5kTGl2ZSA9IGZ1bmN0aW9uICh2ZXJzaW9uKSB7XG4gICAgICAgIC8vIHRoaXNJc01vc3RSZWNlbnRSZXF1ZXN0IC0gaWYgYmxvY2sgd2FzIHJlZnJlc2hlZCwgdGhlbiBhbm90aGVyIHJlcXVlc3RcbiAgICAgICAgLy8gY291bGQgb2YgYmVlbiBzZW50IGFmdGVyIHRoaXMgb25lLlxuICAgICAgICB2YXIgdGhpc0lzTW9zdFJlY2VudFJlcXVlc3QgPSB2ZXJzaW9uID09PSB0aGlzLnZlcnNpb247XG4gICAgICAgIC8vIHdlQXJlTm90RGVzdHJveWVkIC0gaWYgSW5maW5pdGVTdG9yZSBpcyBwdXJnZWQsIHRoZW4gYmxvY2tzIGFyZSBkZXN0cm95ZWRcbiAgICAgICAgLy8gYW5kIG5ldyBibG9ja3MgY3JlYXRlZC4gc28gZGF0YSBsb2FkcyBvZiBvbGQgYmxvY2tzIGFyZSBkaXNjYXJkZWQuXG4gICAgICAgIHZhciB3ZUFyZU5vdERlc3Ryb3llZCA9IHRoaXMuaXNBbGl2ZSgpO1xuICAgICAgICByZXR1cm4gdGhpc0lzTW9zdFJlY2VudFJlcXVlc3QgJiYgd2VBcmVOb3REZXN0cm95ZWQ7XG4gICAgfTtcbiAgICBSb3dOb2RlQmxvY2sucHJvdG90eXBlLnN1Y2Nlc3NDb21tb24gPSBmdW5jdGlvbiAodmVyc2lvbiwgcGFyYW1zKSB7XG4gICAgICAgIC8vIG5lZWQgdG8gZGlzcGF0Y2ggbG9hZCBjb21wbGV0ZSBiZWZvcmUgcHJvY2Vzc2luZyB0aGUgZGF0YSwgYXMgUGFnaW5hdGlvbkNvbXAgY2hlY2tzXG4gICAgICAgIC8vIFJvd05vZGVCbG9ja0xvYWRlciB0byBzZWUgaWYgaXQgaXMgc3RpbGwgbG9hZGluZywgc28gdGhlIFJvd05vZGVCbG9ja0xvYWRlciBuZWVkcyB0b1xuICAgICAgICAvLyBiZSB1cGRhdGVkIGZpcnN0ICh2aWEgTG9hZENvbXBsZXRlIGV2ZW50KSBiZWZvcmUgUGFnaW5hdGlvbkNvbXAgdXBkYXRlcyAodmlhIHByb2Nlc3NTZXJ2ZXJSZXN1bHQgbWV0aG9kKVxuICAgICAgICB0aGlzLmRpc3BhdGNoTG9hZENvbXBsZXRlZCgpO1xuICAgICAgICB2YXIgcmVxdWVzdE1vc3RSZWNlbnRBbmRMaXZlID0gdGhpcy5pc1JlcXVlc3RNb3N0UmVjZW50QW5kTGl2ZSh2ZXJzaW9uKTtcbiAgICAgICAgaWYgKHJlcXVlc3RNb3N0UmVjZW50QW5kTGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IFJvd05vZGVCbG9jay5TVEFURV9MT0FERUQ7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NTZXJ2ZXJSZXN1bHQocGFyYW1zKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZUJsb2NrLnByb3RvdHlwZS5kaXNwYXRjaExvYWRDb21wbGV0ZWQgPSBmdW5jdGlvbiAoc3VjY2Vzcykge1xuICAgICAgICBpZiAoc3VjY2VzcyA9PT0gdm9pZCAwKSB7IHN1Y2Nlc3MgPSB0cnVlOyB9XG4gICAgICAgIC8vIHdlIGZpcmUgZXZlbnQgcmVnYXJkbGVzcyBvZiBwcm9jZXNzaW5nIGRhdGEgb3Igbm93LCBhcyB3ZSB3YW50XG4gICAgICAgIC8vIHRoZSBjb25jdXJyZW50TG9hZFJlcXVlc3RzIGNvdW50IHRvIGJlIHJlZHVjZWQgaW4gQmxvY2tMb2FkZXJcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogUm93Tm9kZUJsb2NrLkVWRU5UX0xPQURfQ09NUExFVEUsXG4gICAgICAgICAgICBzdWNjZXNzOiBzdWNjZXNzLFxuICAgICAgICAgICAgYmxvY2s6IHRoaXNcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9jay5FVkVOVF9MT0FEX0NPTVBMRVRFID0gJ2xvYWRDb21wbGV0ZSc7XG4gICAgUm93Tm9kZUJsb2NrLlNUQVRFX1dBSVRJTkdfVE9fTE9BRCA9ICduZWVkc0xvYWRpbmcnO1xuICAgIFJvd05vZGVCbG9jay5TVEFURV9MT0FESU5HID0gJ2xvYWRpbmcnO1xuICAgIFJvd05vZGVCbG9jay5TVEFURV9MT0FERUQgPSAnbG9hZGVkJztcbiAgICBSb3dOb2RlQmxvY2suU1RBVEVfRkFJTEVEID0gJ2ZhaWxlZCc7XG4gICAgcmV0dXJuIFJvd05vZGVCbG9jaztcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxNiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMTAgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3BhcmFtJDYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3BhcmFtKSB8fCBmdW5jdGlvbiAocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XG59O1xudmFyIFJvd05vZGVCbG9ja0xvYWRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMTYoUm93Tm9kZUJsb2NrTG9hZGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJvd05vZGVCbG9ja0xvYWRlcigpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmFjdGl2ZUJsb2NrTG9hZHNDb3VudCA9IDA7XG4gICAgICAgIF90aGlzLmJsb2NrcyA9IFtdO1xuICAgICAgICBfdGhpcy5hY3RpdmUgPSB0cnVlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFJvd05vZGVCbG9ja0xvYWRlcl8xID0gUm93Tm9kZUJsb2NrTG9hZGVyO1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5tYXhDb25jdXJyZW50UmVxdWVzdHMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRNYXhDb25jdXJyZW50RGF0YXNvdXJjZVJlcXVlc3RzKCk7XG4gICAgICAgIHZhciBibG9ja0xvYWREZWJvdW5jZU1pbGxpcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEJsb2NrTG9hZERlYm91bmNlTWlsbGlzKCk7XG4gICAgICAgIGlmIChibG9ja0xvYWREZWJvdW5jZU1pbGxpcyAmJiBibG9ja0xvYWREZWJvdW5jZU1pbGxpcyA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tCbG9ja1RvTG9hZERlYm91bmNlID0gXy5kZWJvdW5jZSh0aGlzLnBlcmZvcm1DaGVja0Jsb2Nrc1RvTG9hZC5iaW5kKHRoaXMpLCBibG9ja0xvYWREZWJvdW5jZU1pbGxpcyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUuc2V0QmVhbnMgPSBmdW5jdGlvbiAobG9nZ2VyRmFjdG9yeSkge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlckZhY3RvcnkuY3JlYXRlKCdSb3dOb2RlQmxvY2tMb2FkZXInKTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUuYWRkQmxvY2sgPSBmdW5jdGlvbiAoYmxvY2spIHtcbiAgICAgICAgdGhpcy5ibG9ja3MucHVzaChibG9jayk7XG4gICAgICAgIC8vIG5vdGUgdGhhdCB3ZSBkbyBub3QgcmVtb3ZlIHRoaXMgbGlzdGVuZXIgd2hlbiByZW1vdmluZyB0aGUgYmxvY2suIHRoaXMgaXMgYmVjYXVzZSB0aGVcbiAgICAgICAgLy8gY2FjaGUgY2FuIGdldCBkZXN0cm95ZWQgKGFuZCBjb250YWluaW5nIGJsb2Nrcykgd2hlbiBhIGJsb2NrIGlzIGxvYWRpbmcuIGhvd2V2ZXIgdGhlIGxvYWRpbmcgYmxvY2tcbiAgICAgICAgLy8gaXMgc3RpbGwgY291bnRlZCBhcyBhbiBhY3RpdmUgbG9hZGluZyBibG9jayBhbmQgd2UgbXVzdCBkZWNyZW1lbnQgYWN0aXZlQmxvY2tMb2Fkc0NvdW50IHdoZW4gaXQgZmluaXNoZXMuXG4gICAgICAgIGJsb2NrLmFkZEV2ZW50TGlzdGVuZXIoUm93Tm9kZUJsb2NrLkVWRU5UX0xPQURfQ09NUExFVEUsIHRoaXMubG9hZENvbXBsZXRlLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmNoZWNrQmxvY2tUb0xvYWQoKTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUucmVtb3ZlQmxvY2sgPSBmdW5jdGlvbiAoYmxvY2spIHtcbiAgICAgICAgXy5yZW1vdmVGcm9tQXJyYXkodGhpcy5ibG9ja3MsIGJsb2NrKTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuYWN0aXZlID0gZmFsc2U7XG4gICAgfTtcbiAgICBSb3dOb2RlQmxvY2tMb2FkZXIucHJvdG90eXBlLmxvYWRDb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hY3RpdmVCbG9ja0xvYWRzQ291bnQtLTtcbiAgICAgICAgdGhpcy5jaGVja0Jsb2NrVG9Mb2FkKCk7XG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZUJsb2NrTG9hZHNDb3VudCA9PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBSb3dOb2RlQmxvY2tMb2FkZXJfMS5CTE9DS19MT0FERVJfRklOSVNIRURfRVZFTlQgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUuY2hlY2tCbG9ja1RvTG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2hlY2tCbG9ja1RvTG9hZERlYm91bmNlKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrQmxvY2tUb0xvYWREZWJvdW5jZSgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wZXJmb3JtQ2hlY2tCbG9ja3NUb0xvYWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Tm9kZUJsb2NrTG9hZGVyLnByb3RvdHlwZS5wZXJmb3JtQ2hlY2tCbG9ja3NUb0xvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByaW50Q2FjaGVTdGF0dXMoKTtcbiAgICAgICAgaWYgKHRoaXMubWF4Q29uY3VycmVudFJlcXVlc3RzICE9IG51bGwgJiYgdGhpcy5hY3RpdmVCbG9ja0xvYWRzQ291bnQgPj0gdGhpcy5tYXhDb25jdXJyZW50UmVxdWVzdHMpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmxvZyhcImNoZWNrQmxvY2tUb0xvYWQ6IG1heCBsb2FkcyBleGNlZWRlZFwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbG9hZEF2YWlsYWJpbGl0eSA9IHRoaXMubWF4Q29uY3VycmVudFJlcXVlc3RzICE9PSB1bmRlZmluZWQgPyB0aGlzLm1heENvbmN1cnJlbnRSZXF1ZXN0cyAtIHRoaXMuYWN0aXZlQmxvY2tMb2Fkc0NvdW50IDogdW5kZWZpbmVkO1xuICAgICAgICB2YXIgYmxvY2tzVG9Mb2FkID0gdGhpcy5ibG9ja3MuZmlsdGVyKGZ1bmN0aW9uIChibG9jaykgeyByZXR1cm4gKGJsb2NrLmdldFN0YXRlKCkgPT09IFJvd05vZGVCbG9jay5TVEFURV9XQUlUSU5HX1RPX0xPQUQpOyB9KS5zbGljZSgwLCBsb2FkQXZhaWxhYmlsaXR5KTtcbiAgICAgICAgdGhpcy5hY3RpdmVCbG9ja0xvYWRzQ291bnQgKz0gYmxvY2tzVG9Mb2FkLmxlbmd0aDtcbiAgICAgICAgYmxvY2tzVG9Mb2FkLmZvckVhY2goZnVuY3Rpb24gKGJsb2NrKSB7IHJldHVybiBibG9jay5sb2FkKCk7IH0pO1xuICAgICAgICB0aGlzLnByaW50Q2FjaGVTdGF0dXMoKTtcbiAgICB9O1xuICAgIFJvd05vZGVCbG9ja0xvYWRlci5wcm90b3R5cGUuZ2V0QmxvY2tTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICB0aGlzLmJsb2Nrcy5mb3JFYWNoKGZ1bmN0aW9uIChibG9jaykge1xuICAgICAgICAgICAgdmFyIF9hID0gYmxvY2suZ2V0QmxvY2tTdGF0ZUpzb24oKSwgaWQgPSBfYS5pZCwgc3RhdGUgPSBfYS5zdGF0ZTtcbiAgICAgICAgICAgIHJlc3VsdFtpZF0gPSBzdGF0ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBSb3dOb2RlQmxvY2tMb2FkZXIucHJvdG90eXBlLnByaW50Q2FjaGVTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmxvZ2dlci5pc0xvZ2dpbmcoKSkge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwicHJpbnRDYWNoZVN0YXR1czogYWN0aXZlUGFnZUxvYWRzQ291bnQgPSBcIiArIHRoaXMuYWN0aXZlQmxvY2tMb2Fkc0NvdW50ICsgXCIsXCJcbiAgICAgICAgICAgICAgICArIChcIiBibG9ja3MgPSBcIiArIEpTT04uc3RyaW5naWZ5KHRoaXMuZ2V0QmxvY2tTdGF0ZSgpKSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSb3dOb2RlQmxvY2tMb2FkZXIucHJvdG90eXBlLmlzTG9hZGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlQmxvY2tMb2Fkc0NvdW50ID4gMDtcbiAgICB9O1xuICAgIHZhciBSb3dOb2RlQmxvY2tMb2FkZXJfMTtcbiAgICBSb3dOb2RlQmxvY2tMb2FkZXIuQkxPQ0tfTE9BREVSX0ZJTklTSEVEX0VWRU5UID0gJ2Jsb2NrTG9hZGVyRmluaXNoZWQnO1xuICAgIF9fZGVjb3JhdGUkMTAoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93Tm9kZUJsb2NrTG9hZGVyLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMTAoW1xuICAgICAgICBfX3BhcmFtJDYoMCwgUXVhbGlmaWVyKCdsb2dnZXJGYWN0b3J5JykpXG4gICAgXSwgUm93Tm9kZUJsb2NrTG9hZGVyLnByb3RvdHlwZSwgXCJzZXRCZWFuc1wiLCBudWxsKTtcbiAgICBSb3dOb2RlQmxvY2tMb2FkZXIgPSBSb3dOb2RlQmxvY2tMb2FkZXJfMSA9IF9fZGVjb3JhdGUkMTAoW1xuICAgICAgICBCZWFuKCdyb3dOb2RlQmxvY2tMb2FkZXInKVxuICAgIF0sIFJvd05vZGVCbG9ja0xvYWRlcik7XG4gICAgcmV0dXJuIFJvd05vZGVCbG9ja0xvYWRlcjtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxNSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkJCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFBhZ2luYXRpb25Qcm94eSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMTUoUGFnaW5hdGlvblByb3h5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFBhZ2luYXRpb25Qcm94eSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmN1cnJlbnRQYWdlID0gMDtcbiAgICAgICAgX3RoaXMudG9wRGlzcGxheWVkUm93SW5kZXggPSAwO1xuICAgICAgICBfdGhpcy5ib3R0b21EaXNwbGF5ZWRSb3dJbmRleCA9IDA7XG4gICAgICAgIF90aGlzLnBpeGVsT2Zmc2V0ID0gMDtcbiAgICAgICAgX3RoaXMubWFzdGVyUm93Q291bnQgPSAwO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hY3RpdmUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1BhZ2luYXRpb24oKTtcbiAgICAgICAgdGhpcy5wYWdpbmF0ZUNoaWxkUm93cyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUGFnaW5hdGVDaGlsZFJvd3MoKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9NT0RFTF9VUERBVEVELCB0aGlzLm9uTW9kZWxVcGRhdGVkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgJ3BhZ2luYXRpb25QYWdlU2l6ZScsIHRoaXMub25QYWdpbmF0aW9uUGFnZVNpemVDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm9uTW9kZWxVcGRhdGVkKCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmVuc3VyZVJvd0hlaWdodHNWYWxpZCA9IGZ1bmN0aW9uIChzdGFydFBpeGVsLCBlbmRQaXhlbCwgc3RhcnRMaW1pdEluZGV4LCBlbmRMaW1pdEluZGV4KSB7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLnJvd01vZGVsLmVuc3VyZVJvd0hlaWdodHNWYWxpZChzdGFydFBpeGVsLCBlbmRQaXhlbCwgdGhpcy5nZXRQYWdlRmlyc3RSb3coKSwgdGhpcy5nZXRQYWdlTGFzdFJvdygpKTtcbiAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVQYWdlcygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLm9uTW9kZWxVcGRhdGVkID0gZnVuY3Rpb24gKG1vZGVsVXBkYXRlZEV2ZW50KSB7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlUGFnZXMoKTtcbiAgICAgICAgdmFyIHBhZ2luYXRpb25DaGFuZ2VkRXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfUEFHSU5BVElPTl9DSEFOR0VELFxuICAgICAgICAgICAgYW5pbWF0ZTogbW9kZWxVcGRhdGVkRXZlbnQgPyBtb2RlbFVwZGF0ZWRFdmVudC5hbmltYXRlIDogZmFsc2UsXG4gICAgICAgICAgICBuZXdEYXRhOiBtb2RlbFVwZGF0ZWRFdmVudCA/IG1vZGVsVXBkYXRlZEV2ZW50Lm5ld0RhdGEgOiBmYWxzZSxcbiAgICAgICAgICAgIG5ld1BhZ2U6IG1vZGVsVXBkYXRlZEV2ZW50ID8gbW9kZWxVcGRhdGVkRXZlbnQubmV3UGFnZSA6IGZhbHNlLFxuICAgICAgICAgICAga2VlcFJlbmRlcmVkUm93czogbW9kZWxVcGRhdGVkRXZlbnQgPyBtb2RlbFVwZGF0ZWRFdmVudC5rZWVwUmVuZGVyZWRSb3dzIDogZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChwYWdpbmF0aW9uQ2hhbmdlZEV2ZW50KTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUub25QYWdpbmF0aW9uUGFnZVNpemVDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNhbGN1bGF0ZVBhZ2VzKCk7XG4gICAgICAgIHZhciBwYWdpbmF0aW9uQ2hhbmdlZEV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX1BBR0lOQVRJT05fQ0hBTkdFRCxcbiAgICAgICAgICAgIGFuaW1hdGU6IGZhbHNlLFxuICAgICAgICAgICAgbmV3RGF0YTogZmFsc2UsXG4gICAgICAgICAgICBuZXdQYWdlOiBmYWxzZSxcbiAgICAgICAgICAgIC8vIGltcG9ydGFudCB0byBrZWVwIHJlbmRlcmVkIHJvd3MsIG90aGVyd2lzZSBldmVyeSB0aW1lIGdyaWQgaXMgcmVzaXplZCxcbiAgICAgICAgICAgIC8vIHdlIHdvdWxkIGRlc3Ryb3kgYWxsIHRoZSByb3dzLlxuICAgICAgICAgICAga2VlcFJlbmRlcmVkUm93czogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHBhZ2luYXRpb25DaGFuZ2VkRXZlbnQpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nb1RvUGFnZSA9IGZ1bmN0aW9uIChwYWdlKSB7XG4gICAgICAgIGlmICghdGhpcy5hY3RpdmUgfHwgdGhpcy5jdXJyZW50UGFnZSA9PT0gcGFnZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3VycmVudFBhZ2UgPSBwYWdlO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfTU9ERUxfVVBEQVRFRCxcbiAgICAgICAgICAgIGFuaW1hdGU6IGZhbHNlLFxuICAgICAgICAgICAga2VlcFJlbmRlcmVkUm93czogZmFsc2UsXG4gICAgICAgICAgICBuZXdEYXRhOiBmYWxzZSxcbiAgICAgICAgICAgIG5ld1BhZ2U6IHRydWVcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vbk1vZGVsVXBkYXRlZChldmVudCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldFBpeGVsT2Zmc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5waXhlbE9mZnNldDtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ2V0Um93ID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd01vZGVsLmdldFJvdyhpbmRleCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93TW9kZWwuZ2V0Um93Tm9kZShpZCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldFJvd0luZGV4QXRQaXhlbCA9IGZ1bmN0aW9uIChwaXhlbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXRSb3dJbmRleEF0UGl4ZWwocGl4ZWwpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nZXRDdXJyZW50UGFnZUhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKG1pc3NpbmcodGhpcy50b3BSb3dCb3VuZHMpIHx8IG1pc3NpbmcodGhpcy5ib3R0b21Sb3dCb3VuZHMpKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWF0aC5tYXgodGhpcy5ib3R0b21Sb3dCb3VuZHMucm93VG9wICsgdGhpcy5ib3R0b21Sb3dCb3VuZHMucm93SGVpZ2h0IC0gdGhpcy50b3BSb3dCb3VuZHMucm93VG9wLCAwKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ2V0Q3VycmVudFBhZ2VQaXhlbFJhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFnZUZpcnN0UGl4ZWwgPSB0aGlzLnRvcFJvd0JvdW5kcyA/IHRoaXMudG9wUm93Qm91bmRzLnJvd1RvcCA6IDA7XG4gICAgICAgIHZhciBwYWdlTGFzdFBpeGVsID0gdGhpcy5ib3R0b21Sb3dCb3VuZHMgPyB0aGlzLmJvdHRvbVJvd0JvdW5kcy5yb3dUb3AgKyB0aGlzLmJvdHRvbVJvd0JvdW5kcy5yb3dIZWlnaHQgOiAwO1xuICAgICAgICByZXR1cm4geyBwYWdlRmlyc3RQaXhlbDogcGFnZUZpcnN0UGl4ZWwsIHBhZ2VMYXN0UGl4ZWw6IHBhZ2VMYXN0UGl4ZWwgfTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuaXNSb3dQcmVzZW50ID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnJvd01vZGVsLmlzUm93UHJlc2VudChyb3dOb2RlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub2RlSXNJblBhZ2UgPSByb3dOb2RlLnJvd0luZGV4ID49IHRoaXMudG9wRGlzcGxheWVkUm93SW5kZXggJiYgcm93Tm9kZS5yb3dJbmRleCA8PSB0aGlzLmJvdHRvbURpc3BsYXllZFJvd0luZGV4O1xuICAgICAgICByZXR1cm4gbm9kZUlzSW5QYWdlO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5pc0VtcHR5KCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmlzUm93c1RvUmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5pc1Jvd3NUb1JlbmRlcigpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nZXROb2Rlc0luUmFuZ2VGb3JTZWxlY3Rpb24gPSBmdW5jdGlvbiAoZmlyc3RJblJhbmdlLCBsYXN0SW5SYW5nZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXROb2Rlc0luUmFuZ2VGb3JTZWxlY3Rpb24oZmlyc3RJblJhbmdlLCBsYXN0SW5SYW5nZSk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmZvckVhY2hOb2RlID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd01vZGVsLmZvckVhY2hOb2RlKGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93TW9kZWwuZ2V0VHlwZSgpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nZXRSb3dCb3VuZHMgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgdmFyIHJlcyA9IHRoaXMucm93TW9kZWwuZ2V0Um93Qm91bmRzKGluZGV4KTtcbiAgICAgICAgcmVzLnJvd0luZGV4ID0gaW5kZXg7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldFBhZ2VGaXJzdFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9wUm93Qm91bmRzID8gdGhpcy50b3BSb3dCb3VuZHMucm93SW5kZXggOiAtMTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ2V0UGFnZUxhc3RSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvdHRvbVJvd0JvdW5kcyA/IHRoaXMuYm90dG9tUm93Qm91bmRzLnJvd0luZGV4IDogLTE7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldFJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXRSb3dDb3VudCgpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nZXRQYWdlRm9ySW5kZXggPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoaW5kZXggLyB0aGlzLnBhZ2VTaXplKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ29Ub1BhZ2VXaXRoSW5kZXggPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmFjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYWdlTnVtYmVyID0gdGhpcy5nZXRQYWdlRm9ySW5kZXgoaW5kZXgpO1xuICAgICAgICB0aGlzLmdvVG9QYWdlKHBhZ2VOdW1iZXIpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5pc1Jvd0luUGFnZSA9IGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgaWYgKCF0aGlzLmFjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd1BhZ2UgPSB0aGlzLmdldFBhZ2VGb3JJbmRleChyb3cucm93SW5kZXgpO1xuICAgICAgICByZXR1cm4gcm93UGFnZSA9PT0gdGhpcy5jdXJyZW50UGFnZTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuaXNMYXN0UGFnZUZvdW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5pc0xhc3RSb3dJbmRleEtub3duKCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldEN1cnJlbnRQYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50UGFnZTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ29Ub05leHRQYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmdvVG9QYWdlKHRoaXMuY3VycmVudFBhZ2UgKyAxKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuZ29Ub1ByZXZpb3VzUGFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5nb1RvUGFnZSh0aGlzLmN1cnJlbnRQYWdlIC0gMSk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdvVG9GaXJzdFBhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZ29Ub1BhZ2UoMCk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdvVG9MYXN0UGFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd0NvdW50ID0gdGhpcy5yb3dNb2RlbC5nZXRSb3dDb3VudCgpO1xuICAgICAgICB2YXIgbGFzdFBhZ2UgPSBNYXRoLmZsb29yKHJvd0NvdW50IC8gdGhpcy5wYWdlU2l6ZSk7XG4gICAgICAgIHRoaXMuZ29Ub1BhZ2UobGFzdFBhZ2UpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nZXRQYWdlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnZVNpemU7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmdldFRvdGFsUGFnZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRvdGFsUGFnZXM7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLnNldFBhZ2VTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBzaG93IHB1dCB0aGlzIGludG8gc3VwZXIgY2xhc3NcbiAgICAgICAgdGhpcy5wYWdlU2l6ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFBhZ2luYXRpb25QYWdlU2l6ZSgpO1xuICAgICAgICBpZiAodGhpcy5wYWdlU2l6ZSA9PSBudWxsIHx8IHRoaXMucGFnZVNpemUgPCAxKSB7XG4gICAgICAgICAgICB0aGlzLnBhZ2VTaXplID0gMTAwO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmNhbGN1bGF0ZVBhZ2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0UGFnZVNpemUoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnBhZ2luYXRlQ2hpbGRSb3dzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVQYWdlc0FsbFJvd3MoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlUGFnZXNNYXN0ZXJSb3dzT25seSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVkUGFnZXNOb3RBY3RpdmUoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRvcFJvd0JvdW5kcyA9IHRoaXMucm93TW9kZWwuZ2V0Um93Qm91bmRzKHRoaXMudG9wRGlzcGxheWVkUm93SW5kZXgpO1xuICAgICAgICBpZiAodGhpcy50b3BSb3dCb3VuZHMpIHtcbiAgICAgICAgICAgIHRoaXMudG9wUm93Qm91bmRzLnJvd0luZGV4ID0gdGhpcy50b3BEaXNwbGF5ZWRSb3dJbmRleDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJvdHRvbVJvd0JvdW5kcyA9IHRoaXMucm93TW9kZWwuZ2V0Um93Qm91bmRzKHRoaXMuYm90dG9tRGlzcGxheWVkUm93SW5kZXgpO1xuICAgICAgICBpZiAodGhpcy5ib3R0b21Sb3dCb3VuZHMpIHtcbiAgICAgICAgICAgIHRoaXMuYm90dG9tUm93Qm91bmRzLnJvd0luZGV4ID0gdGhpcy5ib3R0b21EaXNwbGF5ZWRSb3dJbmRleDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFBpeGVsT2Zmc2V0KGV4aXN0cyh0aGlzLnRvcFJvd0JvdW5kcykgPyB0aGlzLnRvcFJvd0JvdW5kcy5yb3dUb3AgOiAwKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUuc2V0UGl4ZWxPZmZzZXQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMucGl4ZWxPZmZzZXQgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5waXhlbE9mZnNldCA9IHZhbHVlO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHsgdHlwZTogRXZlbnRzLkVWRU5UX1BBR0lOQVRJT05fUElYRUxfT0ZGU0VUX0NIQU5HRUQgfSk7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLnNldFplcm9Sb3dzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm1hc3RlclJvd0NvdW50ID0gMDtcbiAgICAgICAgdGhpcy50b3BEaXNwbGF5ZWRSb3dJbmRleCA9IDA7XG4gICAgICAgIHRoaXMuYm90dG9tRGlzcGxheWVkUm93SW5kZXggPSAtMTtcbiAgICAgICAgdGhpcy5jdXJyZW50UGFnZSA9IDA7XG4gICAgICAgIHRoaXMudG90YWxQYWdlcyA9IDA7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmNhbGN1bGF0ZVBhZ2VzTWFzdGVyUm93c09ubHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGNvbnN0IGNzcm0gPSA8Q2xpZW50U2lkZVJvd01vZGVsPiB0aGlzLnJvd01vZGVsO1xuICAgICAgICAvLyBjb25zdCByb290Tm9kZSA9IGNzcm0uZ2V0Um9vdE5vZGUoKTtcbiAgICAgICAgLy8gY29uc3QgbWFzdGVyUm93cyA9IHJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0O1xuICAgICAgICB0aGlzLm1hc3RlclJvd0NvdW50ID0gdGhpcy5yb3dNb2RlbC5nZXRUb3BMZXZlbFJvd0NvdW50KCk7XG4gICAgICAgIC8vIHdlIHNheSA8PTAgKHJhdGhlciB0aGFuID0wKSBhcyB2aWV3cG9ydCByZXR1cm5zIC0xIHdoZW4gbm8gcm93c1xuICAgICAgICBpZiAodGhpcy5tYXN0ZXJSb3dDb3VudCA8PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnNldFplcm9Sb3dzKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hc3Rlckxhc3RSb3dJbmRleCA9IHRoaXMubWFzdGVyUm93Q291bnQgLSAxO1xuICAgICAgICB0aGlzLnRvdGFsUGFnZXMgPSBNYXRoLmZsb29yKChtYXN0ZXJMYXN0Um93SW5kZXgpIC8gdGhpcy5wYWdlU2l6ZSkgKyAxO1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50UGFnZSA+PSB0aGlzLnRvdGFsUGFnZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFBhZ2UgPSB0aGlzLnRvdGFsUGFnZXMgLSAxO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNOdW1lcmljKHRoaXMuY3VycmVudFBhZ2UpIHx8IHRoaXMuY3VycmVudFBhZ2UgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRQYWdlID0gMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWFzdGVyUGFnZVN0YXJ0SW5kZXggPSB0aGlzLnBhZ2VTaXplICogdGhpcy5jdXJyZW50UGFnZTtcbiAgICAgICAgdmFyIG1hc3RlclBhZ2VFbmRJbmRleCA9ICh0aGlzLnBhZ2VTaXplICogKHRoaXMuY3VycmVudFBhZ2UgKyAxKSkgLSAxO1xuICAgICAgICBpZiAobWFzdGVyUGFnZUVuZEluZGV4ID4gbWFzdGVyTGFzdFJvd0luZGV4KSB7XG4gICAgICAgICAgICBtYXN0ZXJQYWdlRW5kSW5kZXggPSBtYXN0ZXJMYXN0Um93SW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b3BEaXNwbGF5ZWRSb3dJbmRleCA9IHRoaXMucm93TW9kZWwuZ2V0VG9wTGV2ZWxSb3dEaXNwbGF5ZWRJbmRleChtYXN0ZXJQYWdlU3RhcnRJbmRleCk7XG4gICAgICAgIC8vIG1hc3RlclJvd3NbbWFzdGVyUGFnZVN0YXJ0SW5kZXhdLnJvd0luZGV4O1xuICAgICAgICBpZiAobWFzdGVyUGFnZUVuZEluZGV4ID09PSBtYXN0ZXJMYXN0Um93SW5kZXgpIHtcbiAgICAgICAgICAgIC8vIGlmIHNob3dpbmcgdGhlIGxhc3QgbWFzdGVyIHJvdywgdGhlbiB3ZSB3YW50IHRvIHNob3cgdGhlIHZlcnkgbGFzdCByb3cgb2YgdGhlIG1vZGVsXG4gICAgICAgICAgICB0aGlzLmJvdHRvbURpc3BsYXllZFJvd0luZGV4ID0gdGhpcy5yb3dNb2RlbC5nZXRSb3dDb3VudCgpIC0gMTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBmaXJzdEluZGV4Tm90VG9TaG93ID0gdGhpcy5yb3dNb2RlbC5nZXRUb3BMZXZlbFJvd0Rpc3BsYXllZEluZGV4KG1hc3RlclBhZ2VFbmRJbmRleCArIDEpO1xuICAgICAgICAgICAgLy9tYXN0ZXJSb3dzW21hc3RlclBhZ2VFbmRJbmRleCArIDFdLnJvd0luZGV4O1xuICAgICAgICAgICAgLy8gdGhpcyBnZXRzIHRoZSBpbmRleCBvZiB0aGUgbGFzdCBjaGlsZCAtIGVnIGN1cnJlbnQgcm93IGlzIG9wZW4sIHdlIHdhbnQgdG8gZGlzcGxheSBhbGwgY2hpbGRyZW4sXG4gICAgICAgICAgICAvLyB0aGUgaW5kZXggb2YgdGhlIGxhc3QgY2hpbGQgaXMgb25lIGxlc3MgdGhhbiB0aGUgaW5kZXggb2YgdGhlIG5leHQgcGFyZW50IHJvdy5cbiAgICAgICAgICAgIHRoaXMuYm90dG9tRGlzcGxheWVkUm93SW5kZXggPSBmaXJzdEluZGV4Tm90VG9TaG93IC0gMTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZS5nZXRNYXN0ZXJSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFzdGVyUm93Q291bnQ7XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmNhbGN1bGF0ZVBhZ2VzQWxsUm93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5tYXN0ZXJSb3dDb3VudCA9IHRoaXMucm93TW9kZWwuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgaWYgKHRoaXMubWFzdGVyUm93Q291bnQgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuc2V0WmVyb1Jvd3MoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF4Um93SW5kZXggPSB0aGlzLm1hc3RlclJvd0NvdW50IC0gMTtcbiAgICAgICAgdGhpcy50b3RhbFBhZ2VzID0gTWF0aC5mbG9vcigobWF4Um93SW5kZXgpIC8gdGhpcy5wYWdlU2l6ZSkgKyAxO1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50UGFnZSA+PSB0aGlzLnRvdGFsUGFnZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFBhZ2UgPSB0aGlzLnRvdGFsUGFnZXMgLSAxO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNOdW1lcmljKHRoaXMuY3VycmVudFBhZ2UpIHx8IHRoaXMuY3VycmVudFBhZ2UgPCAwKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRQYWdlID0gMDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnRvcERpc3BsYXllZFJvd0luZGV4ID0gdGhpcy5wYWdlU2l6ZSAqIHRoaXMuY3VycmVudFBhZ2U7XG4gICAgICAgIHRoaXMuYm90dG9tRGlzcGxheWVkUm93SW5kZXggPSAodGhpcy5wYWdlU2l6ZSAqICh0aGlzLmN1cnJlbnRQYWdlICsgMSkpIC0gMTtcbiAgICAgICAgaWYgKHRoaXMuYm90dG9tRGlzcGxheWVkUm93SW5kZXggPiBtYXhSb3dJbmRleCkge1xuICAgICAgICAgICAgdGhpcy5ib3R0b21EaXNwbGF5ZWRSb3dJbmRleCA9IG1heFJvd0luZGV4O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQYWdpbmF0aW9uUHJveHkucHJvdG90eXBlLmNhbGN1bGF0ZWRQYWdlc05vdEFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5wYWdlU2l6ZSA9IHRoaXMucm93TW9kZWwuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgdGhpcy50b3RhbFBhZ2VzID0gMTtcbiAgICAgICAgdGhpcy5jdXJyZW50UGFnZSA9IDA7XG4gICAgICAgIHRoaXMudG9wRGlzcGxheWVkUm93SW5kZXggPSAwO1xuICAgICAgICB0aGlzLmJvdHRvbURpc3BsYXllZFJvd0luZGV4ID0gdGhpcy5yb3dNb2RlbC5nZXRSb3dDb3VudCgpIC0gMTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkJChbXG4gICAgICAgIEF1dG93aXJlZCgncm93TW9kZWwnKVxuICAgIF0sIFBhZ2luYXRpb25Qcm94eS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJCQoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUGFnaW5hdGlvblByb3h5LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIFBhZ2luYXRpb25Qcm94eSA9IF9fZGVjb3JhdGUkJChbXG4gICAgICAgIEJlYW4oJ3BhZ2luYXRpb25Qcm94eScpXG4gICAgXSwgUGFnaW5hdGlvblByb3h5KTtcbiAgICByZXR1cm4gUGFnaW5hdGlvblByb3h5O1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDE0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRfID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgU3R5bGluZ1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDE0KFN0eWxpbmdTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFN0eWxpbmdTZXJ2aWNlKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFN0eWxpbmdTZXJ2aWNlLnByb3RvdHlwZS5wcm9jZXNzQWxsQ2VsbENsYXNzZXMgPSBmdW5jdGlvbiAoY29sRGVmLCBwYXJhbXMsIG9uQXBwbGljYWJsZUNsYXNzLCBvbk5vdEFwcGxpY2FibGVDbGFzcykge1xuICAgICAgICB0aGlzLnByb2Nlc3NDbGFzc1J1bGVzKGNvbERlZi5jZWxsQ2xhc3NSdWxlcywgcGFyYW1zLCBvbkFwcGxpY2FibGVDbGFzcywgb25Ob3RBcHBsaWNhYmxlQ2xhc3MpO1xuICAgICAgICB0aGlzLnByb2Nlc3NTdGF0aWNDZWxsQ2xhc3Nlcyhjb2xEZWYsIHBhcmFtcywgb25BcHBsaWNhYmxlQ2xhc3MpO1xuICAgIH07XG4gICAgU3R5bGluZ1NlcnZpY2UucHJvdG90eXBlLnByb2Nlc3NDbGFzc1J1bGVzID0gZnVuY3Rpb24gKGNsYXNzUnVsZXMsIHBhcmFtcywgb25BcHBsaWNhYmxlQ2xhc3MsIG9uTm90QXBwbGljYWJsZUNsYXNzKSB7XG4gICAgICAgIGlmIChjbGFzc1J1bGVzID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY2xhc3NOYW1lcyA9IE9iamVjdC5rZXlzKGNsYXNzUnVsZXMpO1xuICAgICAgICB2YXIgY2xhc3Nlc1RvQXBwbHkgPSB7fTtcbiAgICAgICAgdmFyIGNsYXNzZXNUb1JlbW92ZSA9IHt9O1xuICAgICAgICB2YXIgX2xvb3BfMSA9IGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NOYW1lID0gY2xhc3NOYW1lc1tpXTtcbiAgICAgICAgICAgIHZhciBydWxlID0gY2xhc3NSdWxlc1tjbGFzc05hbWVdO1xuICAgICAgICAgICAgdmFyIHJlc3VsdE9mUnVsZTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcnVsZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRPZlJ1bGUgPSB0aGlzXzEuZXhwcmVzc2lvblNlcnZpY2UuZXZhbHVhdGUocnVsZSwgcGFyYW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBydWxlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0T2ZSdWxlID0gcnVsZShwYXJhbXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaW4gY2FzZSBjbGFzc05hbWUgPSAnbXktY2xhc3MxIG15LWNsYXNzMicsIHdlIG5lZWQgdG8gc3BsaXQgaW50byBpbmRpdmlkdWFsIGNsYXNzIG5hbWVzXG4gICAgICAgICAgICBjbGFzc05hbWUuc3BsaXQoJyAnKS5mb3JFYWNoKGZ1bmN0aW9uIChzaW5nbGVDbGFzcykge1xuICAgICAgICAgICAgICAgIGlmIChzaW5nbGVDbGFzcyA9PSBudWxsIHx8IHNpbmdsZUNsYXNzLnRyaW0oKSA9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc3VsdE9mUnVsZSA/IGNsYXNzZXNUb0FwcGx5W3NpbmdsZUNsYXNzXSA9IHRydWUgOiBjbGFzc2VzVG9SZW1vdmVbc2luZ2xlQ2xhc3NdID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgdGhpc18xID0gdGhpcztcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjbGFzc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBfbG9vcF8xKGkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHdlIHJlbW92ZSBhbGwgY2xhc3NlcyBmaXJzdCwgdGhlbiBhZGQgYWxsIGNsYXNzZXMgc2Vjb25kLFxuICAgICAgICAvLyBpbiBjYXNlIGEgY2xhc3MgYXBwZWFycyBpbiBtb3JlIHRoYW4gb25lIHJ1bGUsIHRoaXMgbWVhbnMgaXQgd2lsbCBiZSBhZGRlZFxuICAgICAgICAvLyBpZiBhcHBlYXJzIGluIGF0IGxlYXN0IG9uZSB0cnV0aHkgcnVsZVxuICAgICAgICBpZiAob25Ob3RBcHBsaWNhYmxlQ2xhc3MpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKGNsYXNzZXNUb1JlbW92ZSkuZm9yRWFjaChvbk5vdEFwcGxpY2FibGVDbGFzcyk7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmtleXMoY2xhc3Nlc1RvQXBwbHkpLmZvckVhY2gob25BcHBsaWNhYmxlQ2xhc3MpO1xuICAgIH07XG4gICAgU3R5bGluZ1NlcnZpY2UucHJvdG90eXBlLmdldFN0YXRpY0NlbGxDbGFzc2VzID0gZnVuY3Rpb24gKGNvbERlZiwgcGFyYW1zKSB7XG4gICAgICAgIHZhciBjZWxsQ2xhc3MgPSBjb2xEZWYuY2VsbENsYXNzO1xuICAgICAgICBpZiAoIWNlbGxDbGFzcykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjbGFzc09yQ2xhc3NlcztcbiAgICAgICAgaWYgKHR5cGVvZiBjZWxsQ2xhc3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHZhciBjZWxsQ2xhc3NGdW5jID0gY2VsbENsYXNzO1xuICAgICAgICAgICAgY2xhc3NPckNsYXNzZXMgPSBjZWxsQ2xhc3NGdW5jKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjbGFzc09yQ2xhc3NlcyA9IGNlbGxDbGFzcztcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGNsYXNzT3JDbGFzc2VzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY2xhc3NPckNsYXNzZXMgPSBbY2xhc3NPckNsYXNzZXNdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbGFzc09yQ2xhc3NlcyB8fCBbXTtcbiAgICB9O1xuICAgIFN0eWxpbmdTZXJ2aWNlLnByb3RvdHlwZS5wcm9jZXNzU3RhdGljQ2VsbENsYXNzZXMgPSBmdW5jdGlvbiAoY29sRGVmLCBwYXJhbXMsIG9uQXBwbGljYWJsZUNsYXNzKSB7XG4gICAgICAgIHZhciBjbGFzc09yQ2xhc3NlcyA9IHRoaXMuZ2V0U3RhdGljQ2VsbENsYXNzZXMoY29sRGVmLCBwYXJhbXMpO1xuICAgICAgICBjbGFzc09yQ2xhc3Nlcy5mb3JFYWNoKGZ1bmN0aW9uIChjc3NDbGFzc0l0ZW0pIHtcbiAgICAgICAgICAgIG9uQXBwbGljYWJsZUNsYXNzKGNzc0NsYXNzSXRlbSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRfKFtcbiAgICAgICAgQXV0b3dpcmVkKCdleHByZXNzaW9uU2VydmljZScpXG4gICAgXSwgU3R5bGluZ1NlcnZpY2UucHJvdG90eXBlLCBcImV4cHJlc3Npb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgU3R5bGluZ1NlcnZpY2UgPSBfX2RlY29yYXRlJF8oW1xuICAgICAgICBCZWFuKCdzdHlsaW5nU2VydmljZScpXG4gICAgXSwgU3R5bGluZ1NlcnZpY2UpO1xuICAgIHJldHVybiBTdHlsaW5nU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxMyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIEFnUmFkaW9CdXR0b24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDEzKEFnUmFkaW9CdXR0b24sIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdSYWRpb0J1dHRvbihjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIGNvbmZpZywgJ2FnLXJhZGlvLWJ1dHRvbicsICdyYWRpbycpIHx8IHRoaXM7XG4gICAgfVxuICAgIEFnUmFkaW9CdXR0b24ucHJvdG90eXBlLmlzU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVJbnB1dC5jaGVja2VkO1xuICAgIH07XG4gICAgQWdSYWRpb0J1dHRvbi5wcm90b3R5cGUudG9nZ2xlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5lSW5wdXQuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBkbyBub3QgYWxsb3cgYW4gYWN0aXZlIHJhZGlvIGJ1dHRvbiB0byBiZSBkZXNlbGVjdGVkXG4gICAgICAgIGlmICghdGhpcy5pc1NlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnUmFkaW9CdXR0b24ucHJvdG90eXBlLmFkZElucHV0TGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmFkZElucHV0TGlzdGVuZXJzLmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ0hFQ0tCT1hfQ0hBTkdFRCwgdGhpcy5vbkNoYW5nZS5iaW5kKHRoaXMpKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFRoaXMgZW5zdXJlcyB0aGF0IGlmIGFub3RoZXIgcmFkaW8gYnV0dG9uIGluIHRoZSBzYW1lIG5hbWVkIGdyb3VwIGlzIHNlbGVjdGVkLCB3ZSBkZXNlbGVjdCB0aGlzIHJhZGlvIGJ1dHRvbi5cbiAgICAgKiBCeSBkZWZhdWx0IHRoZSBicm93c2VyIGRvZXMgdGhpcyBmb3IgeW91LCBidXQgd2UgYXJlIG1hbmFnaW5nIGNsYXNzZXMgb3Vyc2VsdmVzIGluIG9yZGVyIHRvIGVuc3VyZSBpbnB1dFxuICAgICAqIGVsZW1lbnRzIGFyZSBzdHlsZWQgY29ycmVjdGx5IGluIElFMTEsIGFuZCB0aGUgRE9NICdjaGFuZ2VkJyBldmVudCBpcyBvbmx5IGZpcmVkIHdoZW4gYSBidXR0b24gaXMgc2VsZWN0ZWQsXG4gICAgICogbm90IGRlc2VsZWN0ZWQsIHNvIHdlIG5lZWQgdG8gdXNlIG91ciBvd24gZXZlbnQuXG4gICAgICovXG4gICAgQWdSYWRpb0J1dHRvbi5wcm90b3R5cGUub25DaGFuZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50LnNlbGVjdGVkICYmXG4gICAgICAgICAgICBldmVudC5uYW1lICYmXG4gICAgICAgICAgICB0aGlzLmVJbnB1dC5uYW1lICYmXG4gICAgICAgICAgICB0aGlzLmVJbnB1dC5uYW1lID09PSBldmVudC5uYW1lICYmXG4gICAgICAgICAgICBldmVudC5pZCAmJlxuICAgICAgICAgICAgdGhpcy5lSW5wdXQuaWQgIT09IGV2ZW50LmlkKSB7XG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKGZhbHNlLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEFnUmFkaW9CdXR0b247XG59KEFnQ2hlY2tib3gpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyQxMiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIEFnVG9nZ2xlQnV0dG9uID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxMihBZ1RvZ2dsZUJ1dHRvbiwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ1RvZ2dsZUJ1dHRvbihjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIGNvbmZpZywgJ2FnLXRvZ2dsZS1idXR0b24nKSB8fCB0aGlzO1xuICAgIH1cbiAgICBBZ1RvZ2dsZUJ1dHRvbi5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUsIHNpbGVudCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnNldFZhbHVlLmNhbGwodGhpcywgdmFsdWUsIHNpbGVudCk7XG4gICAgICAgIHRoaXMuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctc2VsZWN0ZWQnLCB0aGlzLmdldFZhbHVlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIHJldHVybiBBZ1RvZ2dsZUJ1dHRvbjtcbn0oQWdDaGVja2JveCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDExID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgQWdJbnB1dFRleHRGaWVsZCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMTEoQWdJbnB1dFRleHRGaWVsZCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ0lucHV0VGV4dEZpZWxkKGNvbmZpZywgY2xhc3NOYW1lLCBpbnB1dFR5cGUpIHtcbiAgICAgICAgaWYgKGNsYXNzTmFtZSA9PT0gdm9pZCAwKSB7IGNsYXNzTmFtZSA9ICdhZy10ZXh0LWZpZWxkJzsgfVxuICAgICAgICBpZiAoaW5wdXRUeXBlID09PSB2b2lkIDApIHsgaW5wdXRUeXBlID0gJ3RleHQnOyB9XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBjb25maWcsIGNsYXNzTmFtZSwgaW5wdXRUeXBlKSB8fCB0aGlzO1xuICAgIH1cbiAgICBBZ0lucHV0VGV4dEZpZWxkLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QuY2FsbCh0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmFsbG93ZWRDaGFyUGF0dGVybikge1xuICAgICAgICAgICAgdGhpcy5wcmV2ZW50RGlzYWxsb3dlZENoYXJhY3RlcnMoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdJbnB1dFRleHRGaWVsZC5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUsIHNpbGVudCkge1xuICAgICAgICB2YXIgcmV0ID0gX3N1cGVyLnByb3RvdHlwZS5zZXRWYWx1ZS5jYWxsKHRoaXMsIHZhbHVlLCBzaWxlbnQpO1xuICAgICAgICBpZiAodGhpcy5lSW5wdXQudmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmVJbnB1dC52YWx1ZSA9IGV4aXN0cyh2YWx1ZSkgPyB2YWx1ZSA6ICcnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfTtcbiAgICBBZ0lucHV0VGV4dEZpZWxkLnByb3RvdHlwZS5wcmV2ZW50RGlzYWxsb3dlZENoYXJhY3RlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwYXR0ZXJuID0gbmV3IFJlZ0V4cChcIltcIiArIHRoaXMuY29uZmlnLmFsbG93ZWRDaGFyUGF0dGVybiArIFwiXVwiKTtcbiAgICAgICAgdmFyIHByZXZlbnREaXNhbGxvd2VkQ2hhcmFjdGVycyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50LmtleSAmJiAhcGF0dGVybi50ZXN0KGV2ZW50LmtleSkpIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVJbnB1dCwgJ2tleXByZXNzJywgcHJldmVudERpc2FsbG93ZWRDaGFyYWN0ZXJzKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lSW5wdXQsICdwYXN0ZScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgX2E7XG4gICAgICAgICAgICB2YXIgdGV4dCA9IChfYSA9IGUuY2xpcGJvYXJkRGF0YSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldERhdGEoJ3RleHQnKTtcbiAgICAgICAgICAgIGlmICh0ZXh0ICYmIHRleHQuc3BsaXQoJycpLnNvbWUoZnVuY3Rpb24gKGMpIHsgcmV0dXJuICFwYXR0ZXJuLnRlc3QoYyk7IH0pKSB7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBBZ0lucHV0VGV4dEZpZWxkO1xufShBZ0Fic3RyYWN0SW5wdXRGaWVsZCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJDEwID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgQWdJbnB1dFRleHRBcmVhID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQxMChBZ0lucHV0VGV4dEFyZWEsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdJbnB1dFRleHRBcmVhKGNvbmZpZykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgY29uZmlnLCAnYWctdGV4dC1hcmVhJywgbnVsbCwgJ3RleHRhcmVhJykgfHwgdGhpcztcbiAgICB9XG4gICAgQWdJbnB1dFRleHRBcmVhLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSwgc2lsZW50KSB7XG4gICAgICAgIHZhciByZXQgPSBfc3VwZXIucHJvdG90eXBlLnNldFZhbHVlLmNhbGwodGhpcywgdmFsdWUsIHNpbGVudCk7XG4gICAgICAgIHRoaXMuZUlucHV0LnZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfTtcbiAgICBBZ0lucHV0VGV4dEFyZWEucHJvdG90eXBlLnNldENvbHMgPSBmdW5jdGlvbiAoY29scykge1xuICAgICAgICB0aGlzLmVJbnB1dC5jb2xzID0gY29scztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0lucHV0VGV4dEFyZWEucHJvdG90eXBlLnNldFJvd3MgPSBmdW5jdGlvbiAocm93cykge1xuICAgICAgICB0aGlzLmVJbnB1dC5yb3dzID0gcm93cztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICByZXR1cm4gQWdJbnB1dFRleHRBcmVhO1xufShBZ0Fic3RyYWN0SW5wdXRGaWVsZCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJCQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBBZ0lucHV0TnVtYmVyRmllbGQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJCQoQWdJbnB1dE51bWJlckZpZWxkLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnSW5wdXROdW1iZXJGaWVsZChjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIGNvbmZpZywgJ2FnLW51bWJlci1maWVsZCcsICdudW1iZXInKSB8fCB0aGlzO1xuICAgIH1cbiAgICBBZ0lucHV0TnVtYmVyRmllbGQucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucG9zdENvbnN0cnVjdC5jYWxsKHRoaXMpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVJbnB1dCwgJ2JsdXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZmxvYXRlZFZhbHVlID0gcGFyc2VGbG9hdChfdGhpcy5lSW5wdXQudmFsdWUpO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gaXNOYU4oZmxvYXRlZFZhbHVlKSA/ICcnIDogX3RoaXMubm9ybWFsaXplVmFsdWUoZmxvYXRlZFZhbHVlLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgaWYgKF90aGlzLnZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZUlucHV0LCAnd2hlZWwnLCB0aGlzLm9uV2hlZWwuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuZUlucHV0LnN0ZXAgPSAnYW55JztcbiAgICB9O1xuICAgIEFnSW5wdXROdW1iZXJGaWVsZC5wcm90b3R5cGUub25XaGVlbCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIC8vIFByZXZlbnQgZGVmYXVsdCBzY3JvbGwgZXZlbnRzIGZyb20gaW5jcmVtZW50aW5nIC8gZGVjcmVtZW50aW5nIHRoZSBpbnB1dCwgc2luY2UgaXRzIGluY29uc2lzdGVudCBiZXR3ZWVuIGJyb3dzZXJzXG4gICAgICAgIGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ID09PSB0aGlzLmVJbnB1dCkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ0lucHV0TnVtYmVyRmllbGQucHJvdG90eXBlLm5vcm1hbGl6ZVZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wcmVjaXNpb24pIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5hZGp1c3RQcmVjaXNpb24odmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB2YWwgPSBwYXJzZUZsb2F0KHZhbHVlKTtcbiAgICAgICAgaWYgKHRoaXMubWluICE9IG51bGwgJiYgdmFsIDwgdGhpcy5taW4pIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5taW4udG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLm1heCAhPSBudWxsICYmIHZhbCA+IHRoaXMubWF4KSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMubWF4LnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG4gICAgQWdJbnB1dE51bWJlckZpZWxkLnByb3RvdHlwZS5hZGp1c3RQcmVjaXNpb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMucHJlY2lzaW9uKSB7XG4gICAgICAgICAgICB2YXIgZmxvYXRTdHJpbmcgPSBwYXJzZUZsb2F0KHZhbHVlKS50b0ZpeGVkKHRoaXMucHJlY2lzaW9uKTtcbiAgICAgICAgICAgIHZhbHVlID0gcGFyc2VGbG9hdChmbG9hdFN0cmluZykudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcbiAgICBBZ0lucHV0TnVtYmVyRmllbGQucHJvdG90eXBlLnNldE1pbiA9IGZ1bmN0aW9uIChtaW4pIHtcbiAgICAgICAgaWYgKHRoaXMubWluID09PSBtaW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWluID0gbWluO1xuICAgICAgICBhZGRPclJlbW92ZUF0dHJpYnV0ZSh0aGlzLmVJbnB1dCwgJ21pbicsIG1pbik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdJbnB1dE51bWJlckZpZWxkLnByb3RvdHlwZS5zZXRNYXggPSBmdW5jdGlvbiAobWF4KSB7XG4gICAgICAgIGlmICh0aGlzLm1heCA9PT0gbWF4KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1heCA9IG1heDtcbiAgICAgICAgYWRkT3JSZW1vdmVBdHRyaWJ1dGUodGhpcy5lSW5wdXQsICdtYXgnLCBtYXgpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnSW5wdXROdW1iZXJGaWVsZC5wcm90b3R5cGUuc2V0UHJlY2lzaW9uID0gZnVuY3Rpb24gKHByZWNpc2lvbikge1xuICAgICAgICB0aGlzLnByZWNpc2lvbiA9IHByZWNpc2lvbjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0lucHV0TnVtYmVyRmllbGQucHJvdG90eXBlLnNldFN0ZXAgPSBmdW5jdGlvbiAoc3RlcCkge1xuICAgICAgICBpZiAodGhpcy5zdGVwID09PSBzdGVwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0ZXAgPSBzdGVwO1xuICAgICAgICBhZGRPclJlbW92ZUF0dHJpYnV0ZSh0aGlzLmVJbnB1dCwgJ3N0ZXAnLCBzdGVwKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0lucHV0TnVtYmVyRmllbGQucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBzaWxlbnQpIHtcbiAgICAgICAgdmFsdWUgPSB0aGlzLmFkanVzdFByZWNpc2lvbih2YWx1ZSk7XG4gICAgICAgIHZhciBub3JtYWxpemVkVmFsdWUgPSB0aGlzLm5vcm1hbGl6ZVZhbHVlKHZhbHVlKTtcbiAgICAgICAgaWYgKHZhbHVlICE9IG5vcm1hbGl6ZWRWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9zdXBlci5wcm90b3R5cGUuc2V0VmFsdWUuY2FsbCh0aGlzLCB2YWx1ZSwgc2lsZW50KTtcbiAgICB9O1xuICAgIHJldHVybiBBZ0lucHV0TnVtYmVyRmllbGQ7XG59KEFnSW5wdXRUZXh0RmllbGQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRfID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgQWdJbnB1dFJhbmdlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRfKEFnSW5wdXRSYW5nZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ0lucHV0UmFuZ2UoY29uZmlnKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBjb25maWcsICdhZy1yYW5nZS1maWVsZCcsICdyYW5nZScpIHx8IHRoaXM7XG4gICAgfVxuICAgIEFnSW5wdXRSYW5nZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0LmNhbGwodGhpcyk7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29uZmlnLCBtaW4gPSBfYS5taW4sIG1heCA9IF9hLm1heCwgc3RlcCA9IF9hLnN0ZXA7XG4gICAgICAgIGlmIChtaW4gIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zZXRNaW5WYWx1ZShtaW4pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXggIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zZXRNYXhWYWx1ZShtYXgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0U3RlcChzdGVwIHx8IDEpO1xuICAgIH07XG4gICAgQWdJbnB1dFJhbmdlLnByb3RvdHlwZS5hZGRJbnB1dExpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lSW5wdXQsICdpbnB1dCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgdmFsdWUgPSBlLnRhcmdldC52YWx1ZTtcbiAgICAgICAgICAgIF90aGlzLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBZ0lucHV0UmFuZ2UucHJvdG90eXBlLnNldE1pblZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMubWluID0gdmFsdWU7XG4gICAgICAgIHRoaXMuZUlucHV0LnNldEF0dHJpYnV0ZSgnbWluJywgdmFsdWUudG9TdHJpbmcoKSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdJbnB1dFJhbmdlLnByb3RvdHlwZS5zZXRNYXhWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgICAgICB0aGlzLmVJbnB1dC5zZXRBdHRyaWJ1dGUoJ21heCcsIHZhbHVlLnRvU3RyaW5nKCkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnSW5wdXRSYW5nZS5wcm90b3R5cGUuc2V0U3RlcCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB0aGlzLmVJbnB1dC5zZXRBdHRyaWJ1dGUoJ3N0ZXAnLCB2YWx1ZS50b1N0cmluZygpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0lucHV0UmFuZ2UucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBzaWxlbnQpIHtcbiAgICAgICAgaWYgKHRoaXMubWluICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhbHVlID0gTWF0aC5tYXgocGFyc2VGbG9hdCh2YWx1ZSksIHRoaXMubWluKS50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm1heCAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IE1hdGgubWluKHBhcnNlRmxvYXQodmFsdWUpLCB0aGlzLm1heCkudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmV0ID0gX3N1cGVyLnByb3RvdHlwZS5zZXRWYWx1ZS5jYWxsKHRoaXMsIHZhbHVlLCBzaWxlbnQpO1xuICAgICAgICB0aGlzLmVJbnB1dC52YWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH07XG4gICAgcmV0dXJuIEFnSW5wdXRSYW5nZTtcbn0oQWdBYnN0cmFjdElucHV0RmllbGQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRaID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRaID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdTbGlkZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJFooQWdTbGlkZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdTbGlkZXIoY29uZmlnKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNvbmZpZywgQWdTbGlkZXIuVEVNUExBVEUpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmxhYmVsQWxpZ25tZW50ID0gJ3RvcCc7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWdTbGlkZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZVNsaWRlci5hZGRDc3NDbGFzcygnYWctc2xpZGVyLWZpZWxkJyk7XG4gICAgfTtcbiAgICBBZ1NsaWRlci5wcm90b3R5cGUub25WYWx1ZUNoYW5nZSA9IGZ1bmN0aW9uIChjYWxsYmFja0ZuKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBldmVudENoYW5nZWQgPSBBZ0Fic3RyYWN0RmllbGQuRVZFTlRfQ0hBTkdFRDtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lVGV4dCwgZXZlbnRDaGFuZ2VkLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgdGV4dFZhbHVlID0gcGFyc2VGbG9hdChfdGhpcy5lVGV4dC5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgIF90aGlzLmVTbGlkZXIuc2V0VmFsdWUodGV4dFZhbHVlLnRvU3RyaW5nKCksIHRydWUpO1xuICAgICAgICAgICAgY2FsbGJhY2tGbih0ZXh0VmFsdWUgfHwgMCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmVTbGlkZXIsIGV2ZW50Q2hhbmdlZCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHNsaWRlclZhbHVlID0gX3RoaXMuZVNsaWRlci5nZXRWYWx1ZSgpO1xuICAgICAgICAgICAgX3RoaXMuZVRleHQuc2V0VmFsdWUoc2xpZGVyVmFsdWUsIHRydWUpO1xuICAgICAgICAgICAgY2FsbGJhY2tGbihwYXJzZUZsb2F0KHNsaWRlclZhbHVlKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnU2xpZGVyLnByb3RvdHlwZS5zZXRTbGlkZXJXaWR0aCA9IGZ1bmN0aW9uICh3aWR0aCkge1xuICAgICAgICB0aGlzLmVTbGlkZXIuc2V0V2lkdGgod2lkdGgpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnU2xpZGVyLnByb3RvdHlwZS5zZXRUZXh0RmllbGRXaWR0aCA9IGZ1bmN0aW9uICh3aWR0aCkge1xuICAgICAgICB0aGlzLmVUZXh0LnNldFdpZHRoKHdpZHRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ1NsaWRlci5wcm90b3R5cGUuc2V0TWluVmFsdWUgPSBmdW5jdGlvbiAobWluVmFsdWUpIHtcbiAgICAgICAgdGhpcy5lU2xpZGVyLnNldE1pblZhbHVlKG1pblZhbHVlKTtcbiAgICAgICAgdGhpcy5lVGV4dC5zZXRNaW4obWluVmFsdWUpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnU2xpZGVyLnByb3RvdHlwZS5zZXRNYXhWYWx1ZSA9IGZ1bmN0aW9uIChtYXhWYWx1ZSkge1xuICAgICAgICB0aGlzLmVTbGlkZXIuc2V0TWF4VmFsdWUobWF4VmFsdWUpO1xuICAgICAgICB0aGlzLmVUZXh0LnNldE1heChtYXhWYWx1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdTbGlkZXIucHJvdG90eXBlLmdldFZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lVGV4dC5nZXRWYWx1ZSgpO1xuICAgIH07XG4gICAgQWdTbGlkZXIucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLmdldFZhbHVlKCkgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVUZXh0LnNldFZhbHVlKHZhbHVlLCB0cnVlKTtcbiAgICAgICAgdGhpcy5lU2xpZGVyLnNldFZhbHVlKHZhbHVlLCB0cnVlKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KHsgdHlwZTogQWdBYnN0cmFjdEZpZWxkLkVWRU5UX0NIQU5HRUQgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdTbGlkZXIucHJvdG90eXBlLnNldFN0ZXAgPSBmdW5jdGlvbiAoc3RlcCkge1xuICAgICAgICB0aGlzLmVTbGlkZXIuc2V0U3RlcChzdGVwKTtcbiAgICAgICAgdGhpcy5lVGV4dC5zZXRTdGVwKHN0ZXApO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnU2xpZGVyLlRFTVBMQVRFID0gXCI8ZGl2IGNsYXNzPVxcXCJhZy1zbGlkZXJcXFwiPlxcbiAgICAgICAgICAgIDxsYWJlbCByZWY9XFxcImVMYWJlbFxcXCI+PC9sYWJlbD5cXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy13cmFwcGVyIGFnLXNsaWRlci13cmFwcGVyXFxcIj5cXG4gICAgICAgICAgICAgICAgPGFnLWlucHV0LXJhbmdlIHJlZj1cXFwiZVNsaWRlclxcXCI+PC9hZy1pbnB1dC1yYW5nZT5cXG4gICAgICAgICAgICAgICAgPGFnLWlucHV0LW51bWJlci1maWVsZCByZWY9XFxcImVUZXh0XFxcIj48L2FnLWlucHV0LW51bWJlci1maWVsZD5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkWihbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlTGFiZWwnKVxuICAgIF0sIEFnU2xpZGVyLnByb3RvdHlwZSwgXCJlTGFiZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFooW1xuICAgICAgICBSZWZTZWxlY3RvcignZVNsaWRlcicpXG4gICAgXSwgQWdTbGlkZXIucHJvdG90eXBlLCBcImVTbGlkZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFooW1xuICAgICAgICBSZWZTZWxlY3RvcignZVRleHQnKVxuICAgIF0sIEFnU2xpZGVyLnByb3RvdHlwZSwgXCJlVGV4dFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkWihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBZ1NsaWRlci5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICByZXR1cm4gQWdTbGlkZXI7XG59KEFnQWJzdHJhY3RMYWJlbCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJFkgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJFkgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBBZ0FuZ2xlU2VsZWN0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRZKEFnQW5nbGVTZWxlY3QsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdBbmdsZVNlbGVjdChjb25maWcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY29uZmlnLCBBZ0FuZ2xlU2VsZWN0LlRFTVBMQVRFKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yYWRpdXMgPSAwO1xuICAgICAgICBfdGhpcy5vZmZzZXRYID0gMDtcbiAgICAgICAgX3RoaXMub2Zmc2V0WSA9IDA7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuZHJhZ0xpc3RlbmVyID0ge1xuICAgICAgICAgICAgZUVsZW1lbnQ6IHRoaXMuZVBhcmVudENpcmNsZSxcbiAgICAgICAgICAgIGRyYWdTdGFydFBpeGVsczogMCxcbiAgICAgICAgICAgIG9uRHJhZ1N0YXJ0OiBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnBhcmVudENpcmNsZVJlY3QgPSBfdGhpcy5lUGFyZW50Q2lyY2xlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uRHJhZ2dpbmc6IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5jYWxjdWxhdGVBbmdsZURyYWcoZSk7IH0sXG4gICAgICAgICAgICBvbkRyYWdTdG9wOiBmdW5jdGlvbiAoKSB7IH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kcmFnU2VydmljZS5hZGREcmFnU291cmNlKHRoaXMuZHJhZ0xpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5lQW5nbGVWYWx1ZVxuICAgICAgICAgICAgLnNldExhYmVsKCcnKVxuICAgICAgICAgICAgLnNldExhYmVsV2lkdGgoNSlcbiAgICAgICAgICAgIC5zZXRJbnB1dFdpZHRoKDQ1KVxuICAgICAgICAgICAgLnNldE1pbigwKVxuICAgICAgICAgICAgLnNldE1heCgzNjApXG4gICAgICAgICAgICAuc2V0VmFsdWUoXCJcIiArIHRoaXMuZGVncmVlcylcbiAgICAgICAgICAgIC5vblZhbHVlQ2hhbmdlKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSAnMCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWx1ZSA9IF90aGlzLmVBbmdsZVZhbHVlLm5vcm1hbGl6ZVZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgIHZhciBmbG9hdFZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoZmxvYXRWYWx1ZSA+IDE4MCkge1xuICAgICAgICAgICAgICAgIGZsb2F0VmFsdWUgPSBmbG9hdFZhbHVlIC0gMzYwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuc2V0VmFsdWUoZmxvYXRWYWx1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnVwZGF0ZU51bWJlcklucHV0KCk7XG4gICAgICAgIGlmIChleGlzdHModGhpcy5nZXRWYWx1ZSgpKSkge1xuICAgICAgICAgICAgdGhpcy5lQW5nbGVWYWx1ZS5zZXRWYWx1ZSh0aGlzLm5vcm1hbGl6ZU5lZ2F0aXZlVmFsdWUodGhpcy5nZXRWYWx1ZSgpKS50b1N0cmluZygpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLCBBZ0Fic3RyYWN0RmllbGQuRVZFTlRfQ0hBTkdFRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGVEb2N1bWVudCA9IF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICAgICAgaWYgKF90aGlzLmVBbmdsZVZhbHVlLmdldElucHV0RWxlbWVudCgpLmNvbnRhaW5zKGVEb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZU51bWJlcklucHV0KCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUudXBkYXRlTnVtYmVySW5wdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBub3JtYWxpemVkVmFsdWUgPSB0aGlzLm5vcm1hbGl6ZU5lZ2F0aXZlVmFsdWUodGhpcy5nZXRWYWx1ZSgpKTtcbiAgICAgICAgdGhpcy5lQW5nbGVWYWx1ZS5zZXRWYWx1ZShub3JtYWxpemVkVmFsdWUudG9TdHJpbmcoKSk7XG4gICAgfTtcbiAgICBBZ0FuZ2xlU2VsZWN0LnByb3RvdHlwZS5wb3NpdGlvbkNoaWxkQ2lyY2xlID0gZnVuY3Rpb24gKHJhZGlhbnMpIHtcbiAgICAgICAgdmFyIHJlY3QgPSB0aGlzLnBhcmVudENpcmNsZVJlY3QgfHwgeyB3aWR0aDogMjQsIGhlaWdodDogMjQgfTtcbiAgICAgICAgdmFyIGVDaGlsZENpcmNsZSA9IHRoaXMuZUNoaWxkQ2lyY2xlO1xuICAgICAgICB2YXIgY2VudGVyWCA9IHJlY3Qud2lkdGggLyAyO1xuICAgICAgICB2YXIgY2VudGVyWSA9IHJlY3QuaGVpZ2h0IC8gMjtcbiAgICAgICAgZUNoaWxkQ2lyY2xlLnN0eWxlLmxlZnQgPSBjZW50ZXJYICsgTWF0aC5jb3MocmFkaWFucykgKiA4ICsgXCJweFwiO1xuICAgICAgICBlQ2hpbGRDaXJjbGUuc3R5bGUudG9wID0gY2VudGVyWSArIE1hdGguc2luKHJhZGlhbnMpICogOCArIFwicHhcIjtcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLmNhbGN1bGF0ZVBvbGFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgeCA9IHRoaXMub2Zmc2V0WDtcbiAgICAgICAgdmFyIHkgPSB0aGlzLm9mZnNldFk7XG4gICAgICAgIHZhciByYWRpYW5zID0gTWF0aC5hdGFuMih5LCB4KTtcbiAgICAgICAgdGhpcy5kZWdyZWVzID0gdGhpcy50b0RlZ3JlZXMocmFkaWFucyk7XG4gICAgICAgIHRoaXMucmFkaXVzID0gTWF0aC5zcXJ0KCh4ICogeCkgKyAoeSAqIHkpKTtcbiAgICAgICAgdGhpcy5wb3NpdGlvbkNoaWxkQ2lyY2xlKHJhZGlhbnMpO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUuY2FsY3VsYXRlQ2FydGVzaWFuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmFkaWFucyA9IHRoaXMudG9SYWRpYW5zKHRoaXMuZ2V0VmFsdWUoKSk7XG4gICAgICAgIHZhciByYWRpdXMgPSB0aGlzLmdldFJhZGl1cygpO1xuICAgICAgICB0aGlzXG4gICAgICAgICAgICAuc2V0T2Zmc2V0WChNYXRoLmNvcyhyYWRpYW5zKSAqIHJhZGl1cylcbiAgICAgICAgICAgIC5zZXRPZmZzZXRZKE1hdGguc2luKHJhZGlhbnMpICogcmFkaXVzKTtcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLnNldE9mZnNldFggPSBmdW5jdGlvbiAob2Zmc2V0KSB7XG4gICAgICAgIGlmICh0aGlzLm9mZnNldFggIT09IG9mZnNldCkge1xuICAgICAgICAgICAgdGhpcy5vZmZzZXRYID0gb2Zmc2V0O1xuICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVQb2xhcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUuc2V0T2Zmc2V0WSA9IGZ1bmN0aW9uIChvZmZzZXQpIHtcbiAgICAgICAgaWYgKHRoaXMub2Zmc2V0WSAhPT0gb2Zmc2V0KSB7XG4gICAgICAgICAgICB0aGlzLm9mZnNldFkgPSBvZmZzZXQ7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZVBvbGFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0FuZ2xlU2VsZWN0LnByb3RvdHlwZS5jYWxjdWxhdGVBbmdsZURyYWcgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgcmVjdCA9IHRoaXMucGFyZW50Q2lyY2xlUmVjdDtcbiAgICAgICAgdmFyIGNlbnRlclggPSByZWN0LndpZHRoIC8gMjtcbiAgICAgICAgdmFyIGNlbnRlclkgPSByZWN0LmhlaWdodCAvIDI7XG4gICAgICAgIHZhciB4ID0gZS5jbGllbnRYIC0gcmVjdC5sZWZ0O1xuICAgICAgICB2YXIgeSA9IGUuY2xpZW50WSAtIHJlY3QudG9wO1xuICAgICAgICB2YXIgZHggPSB4IC0gY2VudGVyWDtcbiAgICAgICAgdmFyIGR5ID0geSAtIGNlbnRlclk7XG4gICAgICAgIHZhciByYWRpYW5zID0gTWF0aC5hdGFuMihkeSwgZHgpO1xuICAgICAgICB0aGlzLnNldFZhbHVlKHJhZGlhbnMsIHRydWUpO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUudG9EZWdyZWVzID0gZnVuY3Rpb24gKHJhZGlhbnMpIHtcbiAgICAgICAgcmV0dXJuIHJhZGlhbnMgLyBNYXRoLlBJICogMTgwO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUudG9SYWRpYW5zID0gZnVuY3Rpb24gKGRlZ3JlZXMpIHtcbiAgICAgICAgcmV0dXJuIGRlZ3JlZXMgLyAxODAgKiBNYXRoLlBJO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUubm9ybWFsaXplTmVnYXRpdmVWYWx1ZSA9IGZ1bmN0aW9uIChkZWdyZWVzKSB7XG4gICAgICAgIHJldHVybiBkZWdyZWVzIDwgMCA/IDM2MCArIGRlZ3JlZXMgOiBkZWdyZWVzO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUubm9ybWFsaXplQW5nbGUxODAgPSBmdW5jdGlvbiAocmFkaWFucykge1xuICAgICAgICByYWRpYW5zICU9IE1hdGguUEkgKiAyO1xuICAgICAgICBpZiAocmFkaWFucyA8IC1NYXRoLlBJKSB7XG4gICAgICAgICAgICByYWRpYW5zICs9IE1hdGguUEkgKiAyO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJhZGlhbnMgPj0gTWF0aC5QSSkge1xuICAgICAgICAgICAgcmFkaWFucyAtPSBNYXRoLlBJICogMjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmFkaWFucztcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLmdldFJhZGl1cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmFkaXVzO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUuc2V0UmFkaXVzID0gZnVuY3Rpb24gKHIpIHtcbiAgICAgICAgaWYgKHRoaXMucmFkaXVzID09PSByKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJhZGl1cyA9IHI7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlQ2FydGVzaWFuKCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUub25WYWx1ZUNoYW5nZSA9IGZ1bmN0aW9uIChjYWxsYmFja0ZuKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMsIEFnQWJzdHJhY3RGaWVsZC5FVkVOVF9DSEFOR0VELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjYWxsYmFja0ZuKF90aGlzLmRlZ3JlZXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0FuZ2xlU2VsZWN0LnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uIChyYWRpYW5zKSB7XG4gICAgICAgIHJldHVybiByYWRpYW5zID8gdGhpcy50b1JhZGlhbnModGhpcy5kZWdyZWVzKSA6IHRoaXMuZGVncmVlcztcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKGRlZ3JlZXMsIHJhZGlhbnMpIHtcbiAgICAgICAgdmFyIHJhZGlhbnNWYWx1ZTtcbiAgICAgICAgaWYgKCFyYWRpYW5zKSB7XG4gICAgICAgICAgICByYWRpYW5zVmFsdWUgPSB0aGlzLm5vcm1hbGl6ZUFuZ2xlMTgwKHRoaXMudG9SYWRpYW5zKGRlZ3JlZXMpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJhZGlhbnNWYWx1ZSA9IGRlZ3JlZXM7XG4gICAgICAgIH1cbiAgICAgICAgZGVncmVlcyA9IHRoaXMudG9EZWdyZWVzKHJhZGlhbnNWYWx1ZSk7XG4gICAgICAgIGlmICh0aGlzLmRlZ3JlZXMgIT09IGRlZ3JlZXMpIHtcbiAgICAgICAgICAgIHRoaXMuZGVncmVlcyA9IE1hdGguZmxvb3IoZGVncmVlcyk7XG4gICAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUNhcnRlc2lhbigpO1xuICAgICAgICAgICAgdGhpcy5wb3NpdGlvbkNoaWxkQ2lyY2xlKHJhZGlhbnNWYWx1ZSk7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBBZ0Fic3RyYWN0RmllbGQuRVZFTlRfQ0hBTkdFRCB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLnNldFdpZHRoID0gZnVuY3Rpb24gKHdpZHRoKSB7XG4gICAgICAgIHNldEZpeGVkV2lkdGgodGhpcy5nZXRHdWkoKSwgd2lkdGgpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLnNldERpc2FibGVkID0gZnVuY3Rpb24gKGRpc2FibGVkKSB7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuc2V0RGlzYWJsZWQuY2FsbCh0aGlzLCBkaXNhYmxlZCk7XG4gICAgICAgIHRoaXMuZUFuZ2xlVmFsdWUuc2V0RGlzYWJsZWQoZGlzYWJsZWQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZHJhZ1NlcnZpY2UucmVtb3ZlRHJhZ1NvdXJjZSh0aGlzLmRyYWdMaXN0ZW5lcik7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgQWdBbmdsZVNlbGVjdC5URU1QTEFURSA9IFwiPGRpdiBjbGFzcz1cXFwiYWctYW5nbGUtc2VsZWN0XFxcIj5cXG4gICAgICAgICAgICA8ZGl2IHJlZj1cXFwiZUxhYmVsXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy13cmFwcGVyIGFnLWFuZ2xlLXNlbGVjdC13cmFwcGVyXFxcIj5cXG4gICAgICAgICAgICAgICAgPGRpdiByZWY9XFxcImVBbmdsZVNlbGVjdEZpZWxkXFxcIiBjbGFzcz1cXFwiYWctYW5nbGUtc2VsZWN0LWZpZWxkXFxcIj5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlUGFyZW50Q2lyY2xlXFxcIiBjbGFzcz1cXFwiYWctYW5nbGUtc2VsZWN0LXBhcmVudC1jaXJjbGVcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlQ2hpbGRDaXJjbGVcXFwiIGNsYXNzPVxcXCJhZy1hbmdsZS1zZWxlY3QtY2hpbGQtY2lyY2xlXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgICAgICAgICAgPGFnLWlucHV0LW51bWJlci1maWVsZCByZWY9XFxcImVBbmdsZVZhbHVlXFxcIj48L2FnLWlucHV0LW51bWJlci1maWVsZD5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkWShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlTGFiZWwnKVxuICAgIF0sIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLCBcImVMYWJlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkWShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlUGFyZW50Q2lyY2xlJylcbiAgICBdLCBBZ0FuZ2xlU2VsZWN0LnByb3RvdHlwZSwgXCJlUGFyZW50Q2lyY2xlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRZKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VDaGlsZENpcmNsZScpXG4gICAgXSwgQWdBbmdsZVNlbGVjdC5wcm90b3R5cGUsIFwiZUNoaWxkQ2lyY2xlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRZKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VBbmdsZVZhbHVlJylcbiAgICBdLCBBZ0FuZ2xlU2VsZWN0LnByb3RvdHlwZSwgXCJlQW5nbGVWYWx1ZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkWShbXG4gICAgICAgIEF1dG93aXJlZCgnZHJhZ1NlcnZpY2UnKVxuICAgIF0sIEFnQW5nbGVTZWxlY3QucHJvdG90eXBlLCBcImRyYWdTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIEFnQW5nbGVTZWxlY3Q7XG59KEFnQWJzdHJhY3RMYWJlbCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJFggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJFggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3JlYWQkOSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBBZ0NvbG9yUGFuZWwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJFgoQWdDb2xvclBhbmVsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnQ29sb3JQYW5lbChjb25maWcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgQWdDb2xvclBhbmVsLlRFTVBMQVRFKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5IID0gMTsgLy8gaW4gdGhlIFswLCAxXSByYW5nZVxuICAgICAgICBfdGhpcy5TID0gMTsgLy8gaW4gdGhlIFswLCAxXSByYW5nZVxuICAgICAgICBfdGhpcy5CID0gMTsgLy8gaW4gdGhlIFswLCAxXSByYW5nZVxuICAgICAgICBfdGhpcy5BID0gMTsgLy8gaW4gdGhlIFswLCAxXSByYW5nZVxuICAgICAgICBfdGhpcy5pc1NwZWN0cnVtRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNTcGVjdHJ1bUh1ZURyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmlzU3BlY3RydW1BbHBoYURyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmNvbG9yQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5waWNrZXIgPSBjb25maWcucGlja2VyO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICB0aGlzLmluaXRSZWNlbnRDb2xvcnMoKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5zcGVjdHJ1bVZhbCwgJ21vdXNlZG93bicsIHRoaXMub25TcGVjdHJ1bURyYWdnZXJEb3duLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlR3VpLCAnbW91c2Vtb3ZlJywgdGhpcy5vblNwZWN0cnVtRHJhZ2dlck1vdmUuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuc3BlY3RydW1IdWUsICdtb3VzZWRvd24nLCB0aGlzLm9uU3BlY3RydW1IdWVEb3duLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlR3VpLCAnbW91c2Vtb3ZlJywgdGhpcy5vblNwZWN0cnVtSHVlTW92ZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5zcGVjdHJ1bUFscGhhLCAnbW91c2Vkb3duJywgdGhpcy5vblNwZWN0cnVtQWxwaGFEb3duLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlR3VpLCAnbW91c2Vtb3ZlJywgdGhpcy5vblNwZWN0cnVtQWxwaGFNb3ZlLmJpbmQodGhpcykpO1xuICAgICAgICAvLyBMaXN0ZW5pbmcgdG8gYG1vdXNldXBgIG9uIHRoZSBkb2N1bWVudCBvbiBwdXJwb3NlLiBUaGUgdXNlciBtaWdodCByZWxlYXNlIHRoZSBtb3VzZSBidXR0b25cbiAgICAgICAgLy8gb3V0c2lkZSB0aGUgVUkgY29udHJvbC4gV2hlbiB0aGUgbW91c2UgcmV0dXJucyBiYWNrIHRvIHRoZSBjb250cm9sJ3MgYXJlYSwgdGhlIGRyYWdnaW5nXG4gICAgICAgIC8vIG9mIHRoZSB0aHVtYiBpcyBub3QgZXhwZWN0ZWQgYW5kIHNlZW4gYXMgYSBidWcuXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGRvY3VtZW50LCAnbW91c2V1cCcsIHRoaXMub25Nb3VzZVVwLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLnJlY2VudENvbG9ycywgJ2NsaWNrJywgdGhpcy5vblJlY2VudENvbG9yQ2xpY2suYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBBZ0NvbG9yUGFuZWwucHJvdG90eXBlLnJlZnJlc2hTcGVjdHJ1bVJlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNwZWN0cnVtVmFsUmVjdCA9IHRoaXMuc3BlY3RydW1WYWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgfTtcbiAgICBBZ0NvbG9yUGFuZWwucHJvdG90eXBlLnJlZnJlc2hIdWVSZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcGVjdHJ1bUh1ZVJlY3QgPSB0aGlzLnNwZWN0cnVtSHVlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH07XG4gICAgQWdDb2xvclBhbmVsLnByb3RvdHlwZS5yZWZyZXNoQWxwaGFSZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcGVjdHJ1bUFscGhhUmVjdCA9IHRoaXMuc3BlY3RydW1BbHBoYS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUub25TcGVjdHJ1bURyYWdnZXJEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoU3BlY3RydW1SZWN0KCk7XG4gICAgICAgIHRoaXMuaXNTcGVjdHJ1bURyYWdnaW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tb3ZlRHJhZ2dlcihlKTtcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUub25TcGVjdHJ1bURyYWdnZXJNb3ZlID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNTcGVjdHJ1bURyYWdnaW5nKSB7XG4gICAgICAgICAgICB0aGlzLm1vdmVEcmFnZ2VyKGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ0NvbG9yUGFuZWwucHJvdG90eXBlLm9uU3BlY3RydW1IdWVEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoSHVlUmVjdCgpO1xuICAgICAgICB0aGlzLmlzU3BlY3RydW1IdWVEcmFnZ2luZyA9IHRydWU7XG4gICAgICAgIHRoaXMubW92ZUh1ZVNsaWRlcihlKTtcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUub25TcGVjdHJ1bUh1ZU1vdmUgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5pc1NwZWN0cnVtSHVlRHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHRoaXMubW92ZUh1ZVNsaWRlcihlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdDb2xvclBhbmVsLnByb3RvdHlwZS5vblNwZWN0cnVtQWxwaGFEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoQWxwaGFSZWN0KCk7XG4gICAgICAgIHRoaXMuaXNTcGVjdHJ1bUFscGhhRHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICB0aGlzLm1vdmVBbHBoYVNsaWRlcihlKTtcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUub25TcGVjdHJ1bUFscGhhTW92ZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICh0aGlzLmlzU3BlY3RydW1BbHBoYURyYWdnaW5nKSB7XG4gICAgICAgICAgICB0aGlzLm1vdmVBbHBoYVNsaWRlcihlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdDb2xvclBhbmVsLnByb3RvdHlwZS5vbk1vdXNlVXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuaXNTcGVjdHJ1bURyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNTcGVjdHJ1bUh1ZURyYWdnaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNTcGVjdHJ1bUFscGhhRHJhZ2dpbmcgPSBmYWxzZTtcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUubW92ZURyYWdnZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgdmFsUmVjdCA9IHRoaXMuc3BlY3RydW1WYWxSZWN0O1xuICAgICAgICBpZiAodmFsUmVjdCkge1xuICAgICAgICAgICAgdmFyIHggPSBlLmNsaWVudFggLSB2YWxSZWN0LmxlZnQ7XG4gICAgICAgICAgICB2YXIgeSA9IGUuY2xpZW50WSAtIHZhbFJlY3QudG9wO1xuICAgICAgICAgICAgeCA9IE1hdGgubWF4KHgsIDApO1xuICAgICAgICAgICAgeCA9IE1hdGgubWluKHgsIHZhbFJlY3Qud2lkdGgpO1xuICAgICAgICAgICAgeSA9IE1hdGgubWF4KHksIDApO1xuICAgICAgICAgICAgeSA9IE1hdGgubWluKHksIHZhbFJlY3QuaGVpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U3BlY3RydW1WYWx1ZSh4IC8gdmFsUmVjdC53aWR0aCwgMSAtIHkgLyB2YWxSZWN0LmhlaWdodCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUubW92ZUh1ZVNsaWRlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBodWVSZWN0ID0gdGhpcy5zcGVjdHJ1bUh1ZVJlY3Q7XG4gICAgICAgIGlmIChodWVSZWN0KSB7XG4gICAgICAgICAgICB2YXIgc2xpZGVyID0gdGhpcy5zcGVjdHJ1bUh1ZVNsaWRlcjtcbiAgICAgICAgICAgIHZhciBzbGlkZXJSZWN0ID0gc2xpZGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgdmFyIHggPSBlLmNsaWVudFggLSBodWVSZWN0LmxlZnQ7XG4gICAgICAgICAgICB4ID0gTWF0aC5tYXgoeCwgMCk7XG4gICAgICAgICAgICB4ID0gTWF0aC5taW4oeCwgaHVlUmVjdC53aWR0aCk7XG4gICAgICAgICAgICB0aGlzLkggPSAxIC0geCAvIGh1ZVJlY3Qud2lkdGg7XG4gICAgICAgICAgICBzbGlkZXIuc3R5bGUubGVmdCA9ICh4ICsgc2xpZGVyUmVjdC53aWR0aCAvIDIpICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUubW92ZUFscGhhU2xpZGVyID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGFscGhhUmVjdCA9IHRoaXMuc3BlY3RydW1BbHBoYVJlY3Q7XG4gICAgICAgIGlmIChhbHBoYVJlY3QpIHtcbiAgICAgICAgICAgIHZhciBzbGlkZXIgPSB0aGlzLnNwZWN0cnVtQWxwaGFTbGlkZXI7XG4gICAgICAgICAgICB2YXIgc2xpZGVyUmVjdCA9IHNsaWRlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHZhciB4ID0gZS5jbGllbnRYIC0gYWxwaGFSZWN0LmxlZnQ7XG4gICAgICAgICAgICB4ID0gTWF0aC5tYXgoeCwgMCk7XG4gICAgICAgICAgICB4ID0gTWF0aC5taW4oeCwgYWxwaGFSZWN0LndpZHRoKTtcbiAgICAgICAgICAgIHRoaXMuQSA9IHggLyBhbHBoYVJlY3Qud2lkdGg7XG4gICAgICAgICAgICBzbGlkZXIuc3R5bGUubGVmdCA9ICh4ICsgc2xpZGVyUmVjdC53aWR0aCAvIDIpICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY29sb3IgPSBDb2xvci5mcm9tSFNCKHRoaXMuSCAqIDM2MCwgdGhpcy5TLCB0aGlzLkIsIHRoaXMuQSk7XG4gICAgICAgIHZhciBzcGVjdHJ1bUNvbG9yID0gQ29sb3IuZnJvbUhTQih0aGlzLkggKiAzNjAsIDEsIDEpO1xuICAgICAgICB2YXIgcmdiYUNvbG9yID0gY29sb3IudG9SZ2JhU3RyaW5nKCk7XG4gICAgICAgIC8vIHRoZSByZWNlbnQgY29sb3IgbGlzdCBuZWVkcyB0byBrbm93IGNvbG9yIGhhcyBhY3R1YWxseSBjaGFuZ2VkXG4gICAgICAgIHZhciBjb2xvclBpY2tlciA9IHRoaXMucGlja2VyO1xuICAgICAgICB2YXIgZXhpc3RpbmdDb2xvciA9IENvbG9yLmZyb21TdHJpbmcoY29sb3JQaWNrZXIuZ2V0VmFsdWUoKSk7XG4gICAgICAgIGlmIChleGlzdGluZ0NvbG9yLnRvUmdiYVN0cmluZygpICE9PSByZ2JhQ29sb3IpIHtcbiAgICAgICAgICAgIHRoaXMuY29sb3JDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBjb2xvclBpY2tlci5zZXRWYWx1ZShyZ2JhQ29sb3IpO1xuICAgICAgICB0aGlzLnNwZWN0cnVtQ29sb3Iuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gc3BlY3RydW1Db2xvci50b1JnYmFTdHJpbmcoKTtcbiAgICAgICAgdGhpcy5zcGVjdHJ1bURyYWdnZXIuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gcmdiYUNvbG9yO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHNhdHVyYXRpb24gSW4gdGhlIFswLCAxXSBpbnRlcnZhbC5cbiAgICAgKiBAcGFyYW0gYnJpZ2h0bmVzcyBJbiB0aGUgWzAsIDFdIGludGVydmFsLlxuICAgICAqL1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUuc2V0U3BlY3RydW1WYWx1ZSA9IGZ1bmN0aW9uIChzYXR1cmF0aW9uLCBicmlnaHRuZXNzKSB7XG4gICAgICAgIHZhciB2YWxSZWN0ID0gdGhpcy5zcGVjdHJ1bVZhbFJlY3QgfHwgdGhpcy5yZWZyZXNoU3BlY3RydW1SZWN0KCk7XG4gICAgICAgIGlmICh2YWxSZWN0KSB7XG4gICAgICAgICAgICB2YXIgZHJhZ2dlciA9IHRoaXMuc3BlY3RydW1EcmFnZ2VyO1xuICAgICAgICAgICAgdmFyIGRyYWdnZXJSZWN0ID0gZHJhZ2dlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHNhdHVyYXRpb24gPSBNYXRoLm1heCgwLCBzYXR1cmF0aW9uKTtcbiAgICAgICAgICAgIHNhdHVyYXRpb24gPSBNYXRoLm1pbigxLCBzYXR1cmF0aW9uKTtcbiAgICAgICAgICAgIGJyaWdodG5lc3MgPSBNYXRoLm1heCgwLCBicmlnaHRuZXNzKTtcbiAgICAgICAgICAgIGJyaWdodG5lc3MgPSBNYXRoLm1pbigxLCBicmlnaHRuZXNzKTtcbiAgICAgICAgICAgIHRoaXMuUyA9IHNhdHVyYXRpb247XG4gICAgICAgICAgICB0aGlzLkIgPSBicmlnaHRuZXNzO1xuICAgICAgICAgICAgZHJhZ2dlci5zdHlsZS5sZWZ0ID0gKHNhdHVyYXRpb24gKiB2YWxSZWN0LndpZHRoIC0gZHJhZ2dlclJlY3Qud2lkdGggLyAyKSArICdweCc7XG4gICAgICAgICAgICBkcmFnZ2VyLnN0eWxlLnRvcCA9ICgoMSAtIGJyaWdodG5lc3MpICogdmFsUmVjdC5oZWlnaHQgLSBkcmFnZ2VyUmVjdC5oZWlnaHQgLyAyKSArICdweCc7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ0NvbG9yUGFuZWwucHJvdG90eXBlLmluaXRSZWNlbnRDb2xvcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZWNlbnRDb2xvcnMgPSBBZ0NvbG9yUGFuZWwucmVjZW50Q29sb3JzO1xuICAgICAgICB2YXIgaW5uZXJIdG1sID0gcmVjZW50Q29sb3JzLm1hcChmdW5jdGlvbiAoY29sb3IsIGluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm4gXCI8ZGl2IGNsYXNzPVxcXCJhZy1yZWNlbnQtY29sb3JcXFwiIGlkPVwiICsgaW5kZXggKyBcIiBzdHlsZT1cXFwiYmFja2dyb3VuZC1jb2xvcjogXCIgKyBjb2xvciArIFwiOyB3aWR0aDogMTVweDsgaGVpZ2h0OiAxNXB4O1xcXCIgcmVjZW50LWNvbG9yPVxcXCJcIiArIGNvbG9yICsgXCJcXFwiPjwvZGl2PlwiO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZWNlbnRDb2xvcnMuaW5uZXJIVE1MID0gaW5uZXJIdG1sLmpvaW4oJycpO1xuICAgIH07XG4gICAgQWdDb2xvclBhbmVsLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgICAgdmFyIGNvbG9yID0gQ29sb3IuZnJvbVN0cmluZyh2YWwpO1xuICAgICAgICB2YXIgX2EgPSBfX3JlYWQkOShjb2xvci50b0hTQigpLCAzKSwgaCA9IF9hWzBdLCBzID0gX2FbMV0sIGIgPSBfYVsyXTtcbiAgICAgICAgdGhpcy5IID0gKGlzTmFOKGgpID8gMCA6IGgpIC8gMzYwO1xuICAgICAgICB0aGlzLkEgPSBjb2xvci5hO1xuICAgICAgICB2YXIgc3BlY3RydW1IdWVSZWN0ID0gdGhpcy5zcGVjdHJ1bUh1ZVJlY3QgfHwgdGhpcy5yZWZyZXNoSHVlUmVjdCgpO1xuICAgICAgICB2YXIgc3BlY3RydW1BbHBoYVJlY3QgPSB0aGlzLnNwZWN0cnVtQWxwaGFSZWN0IHx8IHRoaXMucmVmcmVzaEFscGhhUmVjdCgpO1xuICAgICAgICB0aGlzLnNwZWN0cnVtSHVlU2xpZGVyLnN0eWxlLmxlZnQgPSAoKHRoaXMuSCAtIDEpICogLXNwZWN0cnVtSHVlUmVjdC53aWR0aCkgKyBcInB4XCI7XG4gICAgICAgIHRoaXMuc3BlY3RydW1BbHBoYVNsaWRlci5zdHlsZS5sZWZ0ID0gKHRoaXMuQSAqIHNwZWN0cnVtQWxwaGFSZWN0LndpZHRoKSArIFwicHhcIjtcbiAgICAgICAgdGhpcy5zZXRTcGVjdHJ1bVZhbHVlKHMsIGIpO1xuICAgIH07XG4gICAgQWdDb2xvclBhbmVsLnByb3RvdHlwZS5vblJlY2VudENvbG9yQ2xpY2sgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgdGFyZ2V0ID0gZS50YXJnZXQ7XG4gICAgICAgIGlmICghZXhpc3RzKHRhcmdldC5pZCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaWQgPSBwYXJzZUludCh0YXJnZXQuaWQsIDEwKTtcbiAgICAgICAgdGhpcy5zZXRWYWx1ZShBZ0NvbG9yUGFuZWwucmVjZW50Q29sb3JzW2lkXSk7XG4gICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgIH07XG4gICAgQWdDb2xvclBhbmVsLnByb3RvdHlwZS5hZGRSZWNlbnRDb2xvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbG9yID0gQ29sb3IuZnJvbUhTQih0aGlzLkggKiAzNjAsIHRoaXMuUywgdGhpcy5CLCB0aGlzLkEpO1xuICAgICAgICB2YXIgcmdiYUNvbG9yID0gY29sb3IudG9SZ2JhU3RyaW5nKCk7XG4gICAgICAgIHZhciByZWNlbnRDb2xvcnMgPSBBZ0NvbG9yUGFuZWwucmVjZW50Q29sb3JzO1xuICAgICAgICBpZiAoIXRoaXMuY29sb3JDaGFuZ2VkIHx8IHJlY2VudENvbG9yc1swXSA9PT0gcmdiYUNvbG9yKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVtb3ZlIGR1cGxpY2F0ZSBjb2xvclxuICAgICAgICByZWNlbnRDb2xvcnMgPSByZWNlbnRDb2xvcnMuZmlsdGVyKGZ1bmN0aW9uIChjdXJyZW50Q29sb3IpIHsgcmV0dXJuIGN1cnJlbnRDb2xvciAhPSByZ2JhQ29sb3I7IH0pO1xuICAgICAgICAvLyBhZGQgY29sb3IgdG8gaGVhZFxuICAgICAgICByZWNlbnRDb2xvcnMgPSBbcmdiYUNvbG9yXS5jb25jYXQocmVjZW50Q29sb3JzKTtcbiAgICAgICAgLy8gZW5zdXJlIHdlIGRvbid0IGV4Y2VlZCBtYXggbnVtYmVyIG9mIHJlY2VudCBjb2xvcnNcbiAgICAgICAgaWYgKHJlY2VudENvbG9ycy5sZW5ndGggPiBBZ0NvbG9yUGFuZWwubWF4UmVjZW50Q29sb3JzKSB7XG4gICAgICAgICAgICByZWNlbnRDb2xvcnMgPSByZWNlbnRDb2xvcnMuc2xpY2UoMCwgQWdDb2xvclBhbmVsLm1heFJlY2VudENvbG9ycyk7XG4gICAgICAgIH1cbiAgICAgICAgQWdDb2xvclBhbmVsLnJlY2VudENvbG9ycyA9IHJlY2VudENvbG9ycztcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRSZWNlbnRDb2xvcigpO1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIEFnQ29sb3JQYW5lbC5tYXhSZWNlbnRDb2xvcnMgPSA4O1xuICAgIEFnQ29sb3JQYW5lbC5yZWNlbnRDb2xvcnMgPSBbXTtcbiAgICBBZ0NvbG9yUGFuZWwuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWNvbG9yLXBhbmVsXFxcIj5cXG4gICAgICAgICAgICA8ZGl2IHJlZj1cXFwic3BlY3RydW1Db2xvclxcXCIgY2xhc3M9XFxcImFnLXNwZWN0cnVtLWNvbG9yXFxcIj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctc3BlY3RydW0tc2F0IGFnLXNwZWN0cnVtLWZpbGxcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgPGRpdiByZWY9XFxcInNwZWN0cnVtVmFsXFxcIiBjbGFzcz1cXFwiYWctc3BlY3RydW0tdmFsIGFnLXNwZWN0cnVtLWZpbGxcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJzcGVjdHJ1bURyYWdnZXJcXFwiIGNsYXNzPVxcXCJhZy1zcGVjdHJ1bS1kcmFnZ2VyXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1zcGVjdHJ1bS10b29sc1xcXCI+XFxuICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJzcGVjdHJ1bUh1ZVxcXCIgY2xhc3M9XFxcImFnLXNwZWN0cnVtLWh1ZSBhZy1zcGVjdHJ1bS10b29sXFxcIj5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLXNwZWN0cnVtLWh1ZS1iYWNrZ3JvdW5kXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJzcGVjdHJ1bUh1ZVNsaWRlclxcXCIgY2xhc3M9XFxcImFnLXNwZWN0cnVtLXNsaWRlclxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgICAgICA8ZGl2IHJlZj1cXFwic3BlY3RydW1BbHBoYVxcXCIgY2xhc3M9XFxcImFnLXNwZWN0cnVtLWFscGhhIGFnLXNwZWN0cnVtLXRvb2xcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctc3BlY3RydW0tYWxwaGEtYmFja2dyb3VuZFxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgICAgICAgICA8ZGl2IHJlZj1cXFwic3BlY3RydW1BbHBoYVNsaWRlclxcXCIgY2xhc3M9XFxcImFnLXNwZWN0cnVtLXNsaWRlclxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgICAgICA8ZGl2IHJlZj1cXFwicmVjZW50Q29sb3JzXFxcIiBjbGFzcz1cXFwiYWctcmVjZW50LWNvbG9yc1xcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICA8L2Rpdj5cIjtcbiAgICBfX2RlY29yYXRlJFgoW1xuICAgICAgICBSZWZTZWxlY3Rvcignc3BlY3RydW1Db2xvcicpXG4gICAgXSwgQWdDb2xvclBhbmVsLnByb3RvdHlwZSwgXCJzcGVjdHJ1bUNvbG9yXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRYKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ3NwZWN0cnVtVmFsJylcbiAgICBdLCBBZ0NvbG9yUGFuZWwucHJvdG90eXBlLCBcInNwZWN0cnVtVmFsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRYKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ3NwZWN0cnVtRHJhZ2dlcicpXG4gICAgXSwgQWdDb2xvclBhbmVsLnByb3RvdHlwZSwgXCJzcGVjdHJ1bURyYWdnZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFgoW1xuICAgICAgICBSZWZTZWxlY3Rvcignc3BlY3RydW1IdWUnKVxuICAgIF0sIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUsIFwic3BlY3RydW1IdWVcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFgoW1xuICAgICAgICBSZWZTZWxlY3Rvcignc3BlY3RydW1IdWVTbGlkZXInKVxuICAgIF0sIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUsIFwic3BlY3RydW1IdWVTbGlkZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFgoW1xuICAgICAgICBSZWZTZWxlY3Rvcignc3BlY3RydW1BbHBoYScpXG4gICAgXSwgQWdDb2xvclBhbmVsLnByb3RvdHlwZSwgXCJzcGVjdHJ1bUFscGhhXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRYKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ3NwZWN0cnVtQWxwaGFTbGlkZXInKVxuICAgIF0sIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUsIFwic3BlY3RydW1BbHBoYVNsaWRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkWChbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdyZWNlbnRDb2xvcnMnKVxuICAgIF0sIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUsIFwicmVjZW50Q29sb3JzXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRYKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIEFnQ29sb3JQYW5lbC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gQWdDb2xvclBhbmVsO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRXID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRXID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdQYW5lbCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkVyhBZ1BhbmVsLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnUGFuZWwoY29uZmlnKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIEFnUGFuZWwuZ2V0VGVtcGxhdGUoY29uZmlnKSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY2xvc2FibGUgPSB0cnVlO1xuICAgICAgICBfdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWdQYW5lbC5nZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uIChjb25maWcpIHtcbiAgICAgICAgdmFyIGNzc0lkZW50aWZpZXIgPSAoY29uZmlnICYmIGNvbmZpZy5jc3NJZGVudGlmaWVyKSB8fCAnZGVmYXVsdCc7XG4gICAgICAgIHJldHVybiAvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiYWctcGFuZWwgYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItcGFuZWxcXFwiIHRhYmluZGV4PVxcXCItMVxcXCI+XFxuICAgICAgICAgICAgPGRpdiByZWY9XFxcImVUaXRsZUJhclxcXCIgY2xhc3M9XFxcImFnLXBhbmVsLXRpdGxlLWJhciBhZy1cIiArIGNzc0lkZW50aWZpZXIgKyBcIi1wYW5lbC10aXRsZS1iYXIgYWctdW5zZWxlY3RhYmxlXFxcIj5cXG4gICAgICAgICAgICAgICAgPHNwYW4gcmVmPVxcXCJlVGl0bGVcXFwiIGNsYXNzPVxcXCJhZy1wYW5lbC10aXRsZS1iYXItdGl0bGUgYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItcGFuZWwtdGl0bGUtYmFyLXRpdGxlXFxcIj48L3NwYW4+XFxuICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlVGl0bGVCYXJCdXR0b25zXFxcIiBjbGFzcz1cXFwiYWctcGFuZWwtdGl0bGUtYmFyLWJ1dHRvbnMgYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItcGFuZWwtdGl0bGUtYmFyLWJ1dHRvbnNcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlQ29udGVudFdyYXBwZXJcXFwiIGNsYXNzPVxcXCJhZy1wYW5lbC1jb250ZW50LXdyYXBwZXIgYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItcGFuZWwtY29udGVudC13cmFwcGVyXFxcIj48L2Rpdj5cXG4gICAgICAgIDwvZGl2PlwiO1xuICAgIH07XG4gICAgQWdQYW5lbC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIF9hID0gdGhpcy5jb25maWcsIGNvbXBvbmVudCA9IF9hLmNvbXBvbmVudCwgY2xvc2FibGUgPSBfYS5jbG9zYWJsZSwgaGlkZVRpdGxlQmFyID0gX2EuaGlkZVRpdGxlQmFyLCB0aXRsZSA9IF9hLnRpdGxlLCBfYiA9IF9hLm1pbldpZHRoLCBtaW5XaWR0aCA9IF9iID09PSB2b2lkIDAgPyAyNTAgOiBfYiwgd2lkdGggPSBfYS53aWR0aCwgX2MgPSBfYS5taW5IZWlnaHQsIG1pbkhlaWdodCA9IF9jID09PSB2b2lkIDAgPyAyNTAgOiBfYywgaGVpZ2h0ID0gX2EuaGVpZ2h0LCBjZW50ZXJlZCA9IF9hLmNlbnRlcmVkLCBwb3B1cCA9IF9hLnBvcHVwLCB4ID0gX2EueCwgeSA9IF9hLnk7XG4gICAgICAgIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZSA9IG5ldyBQb3NpdGlvbmFibGVGZWF0dXJlKHRoaXMuZ2V0R3VpKCksIHtcbiAgICAgICAgICAgIG1pbldpZHRoOiBtaW5XaWR0aCwgd2lkdGg6IHdpZHRoLCBtaW5IZWlnaHQ6IG1pbkhlaWdodCwgaGVpZ2h0OiBoZWlnaHQsIGNlbnRlcmVkOiBjZW50ZXJlZCwgeDogeCwgeTogeSwgcG9wdXA6IHBvcHVwLFxuICAgICAgICAgICAgY2FsY3VsYXRlVG9wQnVmZmVyOiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5wb3NpdGlvbmFibGVGZWF0dXJlLmdldEhlaWdodCgpIC0gX3RoaXMuZ2V0Qm9keUhlaWdodCgpOyB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZSk7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgaWYgKGNvbXBvbmVudCkge1xuICAgICAgICAgICAgdGhpcy5zZXRCb2R5Q29tcG9uZW50KGNvbXBvbmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFoaWRlVGl0bGVCYXIpIHtcbiAgICAgICAgICAgIGlmICh0aXRsZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VGl0bGUodGl0bGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRDbG9zYWJsZShjbG9zYWJsZSAhPSBudWxsID8gY2xvc2FibGUgOiB0aGlzLmNsb3NhYmxlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZVRpdGxlQmFyLmNsYXNzTGlzdC5hZGQoJ2FnLWhpZGRlbicpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZVRpdGxlQmFyLCAnbW91c2Vkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBlRG9jdW1lbnQgPSBfdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgICAgIGlmIChlR3VpLmNvbnRhaW5zKGUucmVsYXRlZFRhcmdldCkgfHxcbiAgICAgICAgICAgICAgICBlR3VpLmNvbnRhaW5zKGVEb2N1bWVudC5hY3RpdmVFbGVtZW50KSB8fFxuICAgICAgICAgICAgICAgIF90aGlzLmVUaXRsZUJhckJ1dHRvbnMuY29udGFpbnMoZS50YXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBmb2N1c0VsID0gX3RoaXMuZUNvbnRlbnRXcmFwcGVyLnF1ZXJ5U2VsZWN0b3IoJ2J1dHRvbiwgW2hyZWZdLCBpbnB1dCwgc2VsZWN0LCB0ZXh0YXJlYSwgW3RhYmluZGV4XScpO1xuICAgICAgICAgICAgaWYgKGZvY3VzRWwpIHtcbiAgICAgICAgICAgICAgICBmb2N1c0VsLmZvY3VzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocG9wdXAgJiYgdGhpcy5wb3NpdGlvbmFibGVGZWF0dXJlLmlzUG9zaXRpb25lZCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucmVuZGVyQ29tcG9uZW50KSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckNvbXBvbmVudCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZS5pbml0aWFsaXNlUG9zaXRpb24oKTtcbiAgICAgICAgdGhpcy5lQ29udGVudFdyYXBwZXIuc3R5bGUuaGVpZ2h0ID0gJzAnO1xuICAgIH07XG4gICAgQWdQYW5lbC5wcm90b3R5cGUucmVuZGVyQ29tcG9uZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIGVHdWkuZm9jdXMoKTtcbiAgICAgICAgdGhpcy5jbG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGVHdWkucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChlR3VpKTtcbiAgICAgICAgICAgIF90aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEFnUGFuZWwucHJvdG90eXBlLmdldEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZS5nZXRIZWlnaHQoKTtcbiAgICB9O1xuICAgIEFnUGFuZWwucHJvdG90eXBlLnNldEhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgdGhpcy5wb3NpdGlvbmFibGVGZWF0dXJlLnNldEhlaWdodChoZWlnaHQpO1xuICAgIH07XG4gICAgQWdQYW5lbC5wcm90b3R5cGUuZ2V0V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uYWJsZUZlYXR1cmUuZ2V0V2lkdGgoKTtcbiAgICB9O1xuICAgIEFnUGFuZWwucHJvdG90eXBlLnNldFdpZHRoID0gZnVuY3Rpb24gKHdpZHRoKSB7XG4gICAgICAgIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZS5zZXRXaWR0aCh3aWR0aCk7XG4gICAgfTtcbiAgICBBZ1BhbmVsLnByb3RvdHlwZS5zZXRDbG9zYWJsZSA9IGZ1bmN0aW9uIChjbG9zYWJsZSkge1xuICAgICAgICBpZiAoY2xvc2FibGUgIT09IHRoaXMuY2xvc2FibGUpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2FibGUgPSBjbG9zYWJsZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2xvc2FibGUpIHtcbiAgICAgICAgICAgIHZhciBjbG9zZUJ1dHRvbkNvbXAgPSB0aGlzLmNsb3NlQnV0dG9uQ29tcCA9IG5ldyBDb21wb25lbnQoQWdQYW5lbC5DTE9TRV9CVE5fVEVNUExBVEUpO1xuICAgICAgICAgICAgdGhpcy5nZXRDb250ZXh0KCkuY3JlYXRlQmVhbihjbG9zZUJ1dHRvbkNvbXApO1xuICAgICAgICAgICAgdmFyIGVHdWkgPSBjbG9zZUJ1dHRvbkNvbXAuZ2V0R3VpKCk7XG4gICAgICAgICAgICB2YXIgY2hpbGQgPSBjcmVhdGVJY29uTm9TcGFuKCdjbG9zZScsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyKTtcbiAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC5hZGQoJ2FnLXBhbmVsLXRpdGxlLWJhci1idXR0b24taWNvbicpO1xuICAgICAgICAgICAgZUd1aS5hcHBlbmRDaGlsZChjaGlsZCk7XG4gICAgICAgICAgICB0aGlzLmFkZFRpdGxlQmFyQnV0dG9uKGNsb3NlQnV0dG9uQ29tcCk7XG4gICAgICAgICAgICBjbG9zZUJ1dHRvbkNvbXAuYWRkTWFuYWdlZExpc3RlbmVyKGVHdWksICdjbGljaycsIHRoaXMub25CdENsb3NlLmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuY2xvc2VCdXR0b25Db21wKSB7XG4gICAgICAgICAgICB2YXIgZUd1aSA9IHRoaXMuY2xvc2VCdXR0b25Db21wLmdldEd1aSgpO1xuICAgICAgICAgICAgZUd1aS5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKGVHdWkpO1xuICAgICAgICAgICAgdGhpcy5jbG9zZUJ1dHRvbkNvbXAgPSB0aGlzLmRlc3Ryb3lCZWFuKHRoaXMuY2xvc2VCdXR0b25Db21wKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdQYW5lbC5wcm90b3R5cGUuc2V0Qm9keUNvbXBvbmVudCA9IGZ1bmN0aW9uIChib2R5Q29tcG9uZW50KSB7XG4gICAgICAgIGJvZHlDb21wb25lbnQuc2V0UGFyZW50Q29tcG9uZW50KHRoaXMpO1xuICAgICAgICB0aGlzLmVDb250ZW50V3JhcHBlci5hcHBlbmRDaGlsZChib2R5Q29tcG9uZW50LmdldEd1aSgpKTtcbiAgICB9O1xuICAgIEFnUGFuZWwucHJvdG90eXBlLmFkZFRpdGxlQmFyQnV0dG9uID0gZnVuY3Rpb24gKGJ1dHRvbiwgcG9zaXRpb24pIHtcbiAgICAgICAgdmFyIGVUaXRsZUJhckJ1dHRvbnMgPSB0aGlzLmVUaXRsZUJhckJ1dHRvbnM7XG4gICAgICAgIHZhciBidXR0b25zID0gZVRpdGxlQmFyQnV0dG9ucy5jaGlsZHJlbjtcbiAgICAgICAgdmFyIGxlbiA9IGJ1dHRvbnMubGVuZ3RoO1xuICAgICAgICBpZiAocG9zaXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgcG9zaXRpb24gPSBsZW47XG4gICAgICAgIH1cbiAgICAgICAgcG9zaXRpb24gPSBNYXRoLm1heCgwLCBNYXRoLm1pbihwb3NpdGlvbiwgbGVuKSk7XG4gICAgICAgIGJ1dHRvbi5hZGRDc3NDbGFzcygnYWctcGFuZWwtdGl0bGUtYmFyLWJ1dHRvbicpO1xuICAgICAgICB2YXIgZUd1aSA9IGJ1dHRvbi5nZXRHdWkoKTtcbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKSB7XG4gICAgICAgICAgICBlVGl0bGVCYXJCdXR0b25zLmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJiZWdpbicsIGVHdWkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHBvc2l0aW9uID09PSBsZW4pIHtcbiAgICAgICAgICAgIGVUaXRsZUJhckJ1dHRvbnMuaW5zZXJ0QWRqYWNlbnRFbGVtZW50KCdiZWZvcmVlbmQnLCBlR3VpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGJ1dHRvbnNbcG9zaXRpb24gLSAxXS5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyZW5kJywgZUd1aSk7XG4gICAgICAgIH1cbiAgICAgICAgYnV0dG9uLnNldFBhcmVudENvbXBvbmVudCh0aGlzKTtcbiAgICB9O1xuICAgIEFnUGFuZWwucHJvdG90eXBlLmdldEJvZHlIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBnZXRJbm5lckhlaWdodCh0aGlzLmVDb250ZW50V3JhcHBlcik7XG4gICAgfTtcbiAgICBBZ1BhbmVsLnByb3RvdHlwZS5nZXRCb2R5V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBnZXRJbm5lcldpZHRoKHRoaXMuZUNvbnRlbnRXcmFwcGVyKTtcbiAgICB9O1xuICAgIEFnUGFuZWwucHJvdG90eXBlLnNldFRpdGxlID0gZnVuY3Rpb24gKHRpdGxlKSB7XG4gICAgICAgIHRoaXMuZVRpdGxlLmlubmVyVGV4dCA9IHRpdGxlO1xuICAgIH07XG4gICAgLy8gY2FsbGVkIHdoZW4gdXNlciBoaXRzIHRoZSAneCcgaW4gdGhlIHRvcCByaWdodFxuICAgIEFnUGFuZWwucHJvdG90eXBlLm9uQnRDbG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgIH07XG4gICAgQWdQYW5lbC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VCdXR0b25Db21wKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlQnV0dG9uQ29tcCA9IHRoaXMuZGVzdHJveUJlYW4odGhpcy5jbG9zZUJ1dHRvbkNvbXApO1xuICAgICAgICB9XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgaWYgKGVHdWkgJiYgZUd1aS5vZmZzZXRQYXJlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIEFnUGFuZWwuQ0xPU0VfQlROX1RFTVBMQVRFID0gXCI8ZGl2IGNsYXNzPVxcXCJhZy1idXR0b25cXFwiPjwvZGl2PlwiO1xuICAgIF9fZGVjb3JhdGUkVyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlQ29udGVudFdyYXBwZXInKVxuICAgIF0sIEFnUGFuZWwucHJvdG90eXBlLCBcImVDb250ZW50V3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkVyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVGl0bGVCYXInKVxuICAgIF0sIEFnUGFuZWwucHJvdG90eXBlLCBcImVUaXRsZUJhclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkVyhbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVGl0bGVCYXJCdXR0b25zJylcbiAgICBdLCBBZ1BhbmVsLnByb3RvdHlwZSwgXCJlVGl0bGVCYXJCdXR0b25zXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRXKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VUaXRsZScpXG4gICAgXSwgQWdQYW5lbC5wcm90b3R5cGUsIFwiZVRpdGxlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRXKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIEFnUGFuZWwucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEFnUGFuZWw7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJFYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2Fzc2lnbiQyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiQyID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbih0KSB7XG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSlcbiAgICAgICAgICAgICAgICB0W3BdID0gc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdDtcbiAgICB9O1xuICAgIHJldHVybiBfX2Fzc2lnbiQyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xudmFyIF9fZGVjb3JhdGUkViA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEFnRGlhbG9nID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRWKEFnRGlhbG9nLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnRGlhbG9nKGNvbmZpZykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBfX2Fzc2lnbiQyKF9fYXNzaWduJDIoe30sIGNvbmZpZyksIHsgcG9wdXA6IHRydWUgfSkpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmlzTWF4aW1pemFibGUgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuaXNNYXhpbWl6ZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMubWF4aW1pemVMaXN0ZW5lcnMgPSBbXTtcbiAgICAgICAgX3RoaXMucmVzaXplTGlzdGVuZXJEZXN0cm95ID0gbnVsbDtcbiAgICAgICAgX3RoaXMubGFzdFBvc2l0aW9uID0ge1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgIGhlaWdodDogMFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnRGlhbG9nLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIHZhciBfYSA9IHRoaXMuY29uZmlnLCBtb3ZhYmxlID0gX2EubW92YWJsZSwgcmVzaXphYmxlID0gX2EucmVzaXphYmxlLCBtYXhpbWl6YWJsZSA9IF9hLm1heGltaXphYmxlO1xuICAgICAgICB0aGlzLmFkZENzc0NsYXNzKCdhZy1kaWFsb2cnKTtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0LmNhbGwodGhpcyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGVHdWksICdmb2N1c2luJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChlR3VpLmNvbnRhaW5zKGUucmVsYXRlZFRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5wb3B1cFNlcnZpY2UuYnJpbmdQb3B1cFRvRnJvbnQoZUd1aSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAobW92YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRNb3ZhYmxlKG1vdmFibGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXhpbWl6YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRNYXhpbWl6YWJsZShtYXhpbWl6YWJsZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc2l6YWJsZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRSZXNpemFibGUocmVzaXphYmxlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdEaWFsb2cucHJvdG90eXBlLnJlbmRlckNvbXBvbmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNvbmZpZywgYWx3YXlzT25Ub3AgPSBfYS5hbHdheXNPblRvcCwgbW9kYWwgPSBfYS5tb2RhbCwgdGl0bGUgPSBfYS50aXRsZTtcbiAgICAgICAgdmFyIHRyYW5zbGF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciBhZGRQb3B1cFJlcyA9IHRoaXMucG9wdXBTZXJ2aWNlLmFkZFBvcHVwKHtcbiAgICAgICAgICAgIG1vZGFsOiBtb2RhbCxcbiAgICAgICAgICAgIGVDaGlsZDogZUd1aSxcbiAgICAgICAgICAgIGNsb3NlT25Fc2M6IHRydWUsXG4gICAgICAgICAgICBjbG9zZWRDYWxsYmFjazogdGhpcy5kZXN0cm95LmJpbmQodGhpcyksXG4gICAgICAgICAgICBhbHdheXNPblRvcDogYWx3YXlzT25Ub3AsXG4gICAgICAgICAgICBhcmlhTGFiZWw6IHRpdGxlIHx8IHRyYW5zbGF0ZSgnYXJpYUxhYmVsRGlhbG9nJywgJ0RpYWxvZycpXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoYWRkUG9wdXBSZXMpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2UgPSBhZGRQb3B1cFJlcy5oaWRlRnVuYztcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdEaWFsb2cucHJvdG90eXBlLnRvZ2dsZU1heGltaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uYWJsZUZlYXR1cmUuZ2V0UG9zaXRpb24oKTtcbiAgICAgICAgaWYgKHRoaXMuaXNNYXhpbWl6ZWQpIHtcbiAgICAgICAgICAgIHZhciBfYSA9IHRoaXMubGFzdFBvc2l0aW9uLCB4ID0gX2EueCwgeSA9IF9hLnksIHdpZHRoID0gX2Eud2lkdGgsIGhlaWdodCA9IF9hLmhlaWdodDtcbiAgICAgICAgICAgIHRoaXMuc2V0V2lkdGgod2lkdGgpO1xuICAgICAgICAgICAgdGhpcy5zZXRIZWlnaHQoaGVpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZS5vZmZzZXRFbGVtZW50KHgsIHkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sYXN0UG9zaXRpb24ud2lkdGggPSB0aGlzLmdldFdpZHRoKCk7XG4gICAgICAgICAgICB0aGlzLmxhc3RQb3NpdGlvbi5oZWlnaHQgPSB0aGlzLmdldEhlaWdodCgpO1xuICAgICAgICAgICAgdGhpcy5sYXN0UG9zaXRpb24ueCA9IHBvc2l0aW9uLng7XG4gICAgICAgICAgICB0aGlzLmxhc3RQb3NpdGlvbi55ID0gcG9zaXRpb24ueTtcbiAgICAgICAgICAgIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZS5vZmZzZXRFbGVtZW50KDAsIDApO1xuICAgICAgICAgICAgdGhpcy5zZXRIZWlnaHQoJzEwMCUnKTtcbiAgICAgICAgICAgIHRoaXMuc2V0V2lkdGgoJzEwMCUnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmlzTWF4aW1pemVkID0gIXRoaXMuaXNNYXhpbWl6ZWQ7XG4gICAgICAgIHRoaXMucmVmcmVzaE1heGltaXplSWNvbigpO1xuICAgIH07XG4gICAgQWdEaWFsb2cucHJvdG90eXBlLnJlZnJlc2hNYXhpbWl6ZUljb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNldERpc3BsYXllZCh0aGlzLm1heGltaXplSWNvbiwgIXRoaXMuaXNNYXhpbWl6ZWQpO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5taW5pbWl6ZUljb24sIHRoaXMuaXNNYXhpbWl6ZWQpO1xuICAgIH07XG4gICAgQWdEaWFsb2cucHJvdG90eXBlLmNsZWFyTWF4aW1pemVibGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLm1heGltaXplTGlzdGVuZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5tYXhpbWl6ZUxpc3RlbmVycy5mb3JFYWNoKGZ1bmN0aW9uIChkZXN0cm95TGlzdGVuZXIpIHsgcmV0dXJuIGRlc3Ryb3lMaXN0ZW5lcigpOyB9KTtcbiAgICAgICAgICAgIHRoaXMubWF4aW1pemVMaXN0ZW5lcnMubGVuZ3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXNpemVMaXN0ZW5lckRlc3Ryb3kpIHtcbiAgICAgICAgICAgIHRoaXMucmVzaXplTGlzdGVuZXJEZXN0cm95KCk7XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZUxpc3RlbmVyRGVzdHJveSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnRGlhbG9nLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm1heGltaXplQnV0dG9uQ29tcCA9IHRoaXMuZGVzdHJveUJlYW4odGhpcy5tYXhpbWl6ZUJ1dHRvbkNvbXApO1xuICAgICAgICB0aGlzLmNsZWFyTWF4aW1pemVibGVMaXN0ZW5lcnMoKTtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBBZ0RpYWxvZy5wcm90b3R5cGUuc2V0UmVzaXphYmxlID0gZnVuY3Rpb24gKHJlc2l6YWJsZSkge1xuICAgICAgICB0aGlzLnBvc2l0aW9uYWJsZUZlYXR1cmUuc2V0UmVzaXphYmxlKHJlc2l6YWJsZSk7XG4gICAgfTtcbiAgICBBZ0RpYWxvZy5wcm90b3R5cGUuc2V0TW92YWJsZSA9IGZ1bmN0aW9uIChtb3ZhYmxlKSB7XG4gICAgICAgIHRoaXMucG9zaXRpb25hYmxlRmVhdHVyZS5zZXRNb3ZhYmxlKG1vdmFibGUsIHRoaXMuZVRpdGxlQmFyKTtcbiAgICB9O1xuICAgIEFnRGlhbG9nLnByb3RvdHlwZS5zZXRNYXhpbWl6YWJsZSA9IGZ1bmN0aW9uIChtYXhpbWl6YWJsZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIW1heGltaXphYmxlKSB7XG4gICAgICAgICAgICB0aGlzLmNsZWFyTWF4aW1pemVibGVMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heGltaXplQnV0dG9uQ29tcCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveUJlYW4odGhpcy5tYXhpbWl6ZUJ1dHRvbkNvbXApO1xuICAgICAgICAgICAgICAgIHRoaXMubWF4aW1pemVCdXR0b25Db21wID0gdGhpcy5tYXhpbWl6ZUljb24gPSB0aGlzLm1pbmltaXplSWNvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZVRpdGxlQmFyID0gdGhpcy5lVGl0bGVCYXI7XG4gICAgICAgIGlmICghZVRpdGxlQmFyIHx8IG1heGltaXphYmxlID09PSB0aGlzLmlzTWF4aW1pemFibGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF4aW1pemVCdXR0b25Db21wID0gdGhpcy5tYXhpbWl6ZUJ1dHRvbkNvbXAgPVxuICAgICAgICAgICAgdGhpcy5jcmVhdGVCZWFuKG5ldyBDb21wb25lbnQoLyogaHRtbCAqLyBcIjxkaXYgY2xhc3M9XFxcImFnLWRpYWxvZy1idXR0b25cXFwiPjwvc3Bhbj5cIikpO1xuICAgICAgICB2YXIgZUd1aSA9IG1heGltaXplQnV0dG9uQ29tcC5nZXRHdWkoKTtcbiAgICAgICAgZUd1aS5hcHBlbmRDaGlsZCh0aGlzLm1heGltaXplSWNvbiA9IGNyZWF0ZUljb25Ob1NwYW4oJ21heGltaXplJywgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIpKTtcbiAgICAgICAgdGhpcy5tYXhpbWl6ZUljb24uY2xhc3NMaXN0LmFkZCgnYWctcGFuZWwtdGl0bGUtYmFyLWJ1dHRvbi1pY29uJyk7XG4gICAgICAgIGVHdWkuYXBwZW5kQ2hpbGQodGhpcy5taW5pbWl6ZUljb24gPSBjcmVhdGVJY29uTm9TcGFuKCdtaW5pbWl6ZScsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyKSk7XG4gICAgICAgIHRoaXMubWluaW1pemVJY29uLmNsYXNzTGlzdC5hZGQoJ2FnLXBhbmVsLXRpdGxlLWJhci1idXR0b24taWNvbicsICdhZy1oaWRkZW4nKTtcbiAgICAgICAgbWF4aW1pemVCdXR0b25Db21wLmFkZE1hbmFnZWRMaXN0ZW5lcihlR3VpLCAnY2xpY2snLCB0aGlzLnRvZ2dsZU1heGltaXplLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZFRpdGxlQmFyQnV0dG9uKG1heGltaXplQnV0dG9uQ29tcCwgMCk7XG4gICAgICAgIHRoaXMubWF4aW1pemVMaXN0ZW5lcnMucHVzaCh0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlVGl0bGVCYXIsICdkYmxjbGljaycsIHRoaXMudG9nZ2xlTWF4aW1pemUuYmluZCh0aGlzKSkpO1xuICAgICAgICB0aGlzLnJlc2l6ZUxpc3RlbmVyRGVzdHJveSA9IHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMsICdyZXNpemUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5pc01heGltaXplZCA9IGZhbHNlO1xuICAgICAgICAgICAgX3RoaXMucmVmcmVzaE1heGltaXplSWNvbigpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkVihbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBBZ0RpYWxvZy5wcm90b3R5cGUsIFwicG9wdXBTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgcmV0dXJuIEFnRGlhbG9nO1xufShBZ1BhbmVsKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkVSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIEFnQ29sb3JQaWNrZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJFUoQWdDb2xvclBpY2tlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ0NvbG9yUGlja2VyKGNvbmZpZykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBjb25maWcsICdhZy1jb2xvci1waWNrZXInLCAnY29sb3JQaWNrZXInKSB8fCB0aGlzO1xuICAgICAgICBpZiAoY29uZmlnICYmIGNvbmZpZy5jb2xvcikge1xuICAgICAgICAgICAgX3RoaXMudmFsdWUgPSBjb25maWcuY29sb3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBZ0NvbG9yUGlja2VyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QuY2FsbCh0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUodGhpcy52YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnQ29sb3JQaWNrZXIucHJvdG90eXBlLnNob3dQaWNrZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlR3VpUmVjdCA9IHRoaXMuZ2V0R3VpKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBjb2xvckRpYWxvZyA9IHRoaXMuY3JlYXRlQmVhbihuZXcgQWdEaWFsb2coe1xuICAgICAgICAgICAgY2xvc2FibGU6IGZhbHNlLFxuICAgICAgICAgICAgbW9kYWw6IHRydWUsXG4gICAgICAgICAgICBoaWRlVGl0bGVCYXI6IHRydWUsXG4gICAgICAgICAgICBtaW5XaWR0aDogMTkwLFxuICAgICAgICAgICAgd2lkdGg6IDE5MCxcbiAgICAgICAgICAgIGhlaWdodDogMjUwLFxuICAgICAgICAgICAgeDogZUd1aVJlY3QucmlnaHQgLSAxOTAsXG4gICAgICAgICAgICB5OiBlR3VpUmVjdC50b3AgLSAyNTBcbiAgICAgICAgfSkpO1xuICAgICAgICB0aGlzLmlzUGlja2VyRGlzcGxheWVkID0gdHJ1ZTtcbiAgICAgICAgY29sb3JEaWFsb2cuYWRkQ3NzQ2xhc3MoJ2FnLWNvbG9yLWRpYWxvZycpO1xuICAgICAgICBzZXRBcmlhRXhwYW5kZWQodGhpcy5lV3JhcHBlciwgdHJ1ZSk7XG4gICAgICAgIHZhciBjb2xvclBhbmVsID0gdGhpcy5jcmVhdGVCZWFuKG5ldyBBZ0NvbG9yUGFuZWwoeyBwaWNrZXI6IHRoaXMgfSkpO1xuICAgICAgICBjb2xvclBhbmVsLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjb2xvckRpYWxvZy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5kZXN0cm95QmVhbihjb2xvckRpYWxvZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBjb2xvckRpYWxvZy5zZXRQYXJlbnRDb21wb25lbnQodGhpcyk7XG4gICAgICAgIGNvbG9yRGlhbG9nLnNldEJvZHlDb21wb25lbnQoY29sb3JQYW5lbCk7XG4gICAgICAgIGNvbG9yUGFuZWwuc2V0VmFsdWUodGhpcy5nZXRWYWx1ZSgpKTtcbiAgICAgICAgY29sb3JEaWFsb2cuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gaGVyZSB3ZSBjaGVjayBpZiB0aGUgcGlja2VyIHdhcyBhbHJlYWR5IGJlaW5nXG4gICAgICAgICAgICAvLyBkZXN0cm95ZWQgdG8gYXZvaWQgYSBzdGFjayBvdmVyZmxvd1xuICAgICAgICAgICAgaWYgKCFfdGhpcy5pc0Rlc3Ryb3lpbmdQaWNrZXIpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc0Rlc3Ryb3lpbmdQaWNrZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGlmIChjb2xvclBhbmVsLmlzQWxpdmUoKSkge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5kZXN0cm95QmVhbihjb2xvclBhbmVsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pc0Rlc3Ryb3lpbmdQaWNrZXIgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgICAgICBzZXRBcmlhRXhwYW5kZWQoX3RoaXMuZVdyYXBwZXIsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5nZXRGb2N1c2FibGVFbGVtZW50KCkuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmlzUGlja2VyRGlzcGxheWVkID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29sb3JEaWFsb2c7XG4gICAgfTtcbiAgICBBZ0NvbG9yUGlja2VyLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uIChjb2xvcikge1xuICAgICAgICBpZiAodGhpcy52YWx1ZSA9PT0gY29sb3IpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZURpc3BsYXlGaWVsZC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBjb2xvcjtcbiAgICAgICAgcmV0dXJuIF9zdXBlci5wcm90b3R5cGUuc2V0VmFsdWUuY2FsbCh0aGlzLCBjb2xvcik7XG4gICAgfTtcbiAgICBBZ0NvbG9yUGlja2VyLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfTtcbiAgICByZXR1cm4gQWdDb2xvclBpY2tlcjtcbn0oQWdQaWNrZXJGaWVsZCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJFQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJFUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBBZ0dyb3VwQ29tcG9uZW50ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRUKEFnR3JvdXBDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdHcm91cENvbXBvbmVudChwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PT0gdm9pZCAwKSB7IHBhcmFtcyA9IHt9OyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIEFnR3JvdXBDb21wb25lbnQuZ2V0VGVtcGxhdGUocGFyYW1zKSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuc3VwcHJlc3NFbmFibGVkQ2hlY2tib3ggPSB0cnVlO1xuICAgICAgICBfdGhpcy5zdXBwcmVzc09wZW5DbG9zZUljb25zID0gZmFsc2U7XG4gICAgICAgIHZhciB0aXRsZSA9IHBhcmFtcy50aXRsZSwgZW5hYmxlZCA9IHBhcmFtcy5lbmFibGVkLCBpdGVtcyA9IHBhcmFtcy5pdGVtcywgc3VwcHJlc3NFbmFibGVkQ2hlY2tib3ggPSBwYXJhbXMuc3VwcHJlc3NFbmFibGVkQ2hlY2tib3gsIHN1cHByZXNzT3BlbkNsb3NlSWNvbnMgPSBwYXJhbXMuc3VwcHJlc3NPcGVuQ2xvc2VJY29ucztcbiAgICAgICAgX3RoaXMudGl0bGUgPSB0aXRsZTtcbiAgICAgICAgX3RoaXMuY3NzSWRlbnRpZmllciA9IHBhcmFtcy5jc3NJZGVudGlmaWVyIHx8ICdkZWZhdWx0JztcbiAgICAgICAgX3RoaXMuZW5hYmxlZCA9IGVuYWJsZWQgIT0gbnVsbCA/IGVuYWJsZWQgOiB0cnVlO1xuICAgICAgICBfdGhpcy5pdGVtcyA9IGl0ZW1zIHx8IFtdO1xuICAgICAgICBfdGhpcy5hbGlnbkl0ZW1zID0gcGFyYW1zLmFsaWduSXRlbXMgfHwgJ2NlbnRlcic7XG4gICAgICAgIGlmIChzdXBwcmVzc0VuYWJsZWRDaGVja2JveCAhPSBudWxsKSB7XG4gICAgICAgICAgICBfdGhpcy5zdXBwcmVzc0VuYWJsZWRDaGVja2JveCA9IHN1cHByZXNzRW5hYmxlZENoZWNrYm94O1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdXBwcmVzc09wZW5DbG9zZUljb25zICE9IG51bGwpIHtcbiAgICAgICAgICAgIF90aGlzLnN1cHByZXNzT3BlbkNsb3NlSWNvbnMgPSBzdXBwcmVzc09wZW5DbG9zZUljb25zO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWdHcm91cENvbXBvbmVudC5nZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIGNzc0lkZW50aWZpZXIgPSBwYXJhbXMuY3NzSWRlbnRpZmllciB8fCAnZGVmYXVsdCc7XG4gICAgICAgIHZhciBkaXJlY3Rpb24gPSBwYXJhbXMuZGlyZWN0aW9uIHx8ICd2ZXJ0aWNhbCc7XG4gICAgICAgIHJldHVybiAvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiYWctZ3JvdXAgYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItZ3JvdXBcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctZ3JvdXAtdGl0bGUtYmFyIGFnLVwiICsgY3NzSWRlbnRpZmllciArIFwiLWdyb3VwLXRpdGxlLWJhciBhZy11bnNlbGVjdGFibGVcXFwiIHJlZj1cXFwiZVRpdGxlQmFyXFxcIiByb2xlPVxcXCJidXR0b25cXFwiPlxcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwiYWctZ3JvdXAtdGl0bGUtYmFyLWljb24gYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItZ3JvdXAtdGl0bGUtYmFyLWljb25cXFwiIHJlZj1cXFwiZUdyb3VwT3BlbmVkSWNvblxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj48L3NwYW4+XFxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJhZy1ncm91cC10aXRsZS1iYXItaWNvbiBhZy1cIiArIGNzc0lkZW50aWZpZXIgKyBcIi1ncm91cC10aXRsZS1iYXItaWNvblxcXCIgcmVmPVxcXCJlR3JvdXBDbG9zZWRJY29uXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgPHNwYW4gcmVmPVxcXCJlVGl0bGVcXFwiIGNsYXNzPVxcXCJhZy1ncm91cC10aXRsZSBhZy1cIiArIGNzc0lkZW50aWZpZXIgKyBcIi1ncm91cC10aXRsZVxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlVG9vbGJhclxcXCIgY2xhc3M9XFxcImFnLWdyb3VwLXRvb2xiYXIgYWctXCIgKyBjc3NJZGVudGlmaWVyICsgXCItZ3JvdXAtdG9vbGJhclxcXCI+XFxuICAgICAgICAgICAgICAgIDxhZy1jaGVja2JveCByZWY9XFxcImNiR3JvdXBFbmFibGVkXFxcIj48L2FnLWNoZWNrYm94PlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJlQ29udGFpbmVyXFxcIiBjbGFzcz1cXFwiYWctZ3JvdXAtY29udGFpbmVyIGFnLWdyb3VwLWNvbnRhaW5lci1cIiArIGRpcmVjdGlvbiArIFwiIGFnLVwiICsgY3NzSWRlbnRpZmllciArIFwiLWdyb3VwLWNvbnRhaW5lclxcXCI+PC9kaXY+XFxuICAgICAgICA8L2Rpdj5cIjtcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLml0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGluaXRpYWxJdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgICAgICAgICB0aGlzLml0ZW1zID0gW107XG4gICAgICAgICAgICB0aGlzLmFkZEl0ZW1zKGluaXRpYWxJdGVtcyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxvY2FsZVRleHRGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdGhpcy5jYkdyb3VwRW5hYmxlZC5zZXRMYWJlbChsb2NhbGVUZXh0RnVuYygnZW5hYmxlZCcsICdFbmFibGVkJykpO1xuICAgICAgICBpZiAodGhpcy50aXRsZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRUaXRsZSh0aGlzLnRpdGxlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5lbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnNldEVuYWJsZWQodGhpcy5lbmFibGVkKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldEFsaWduSXRlbXModGhpcy5hbGlnbkl0ZW1zKTtcbiAgICAgICAgdGhpcy5oaWRlRW5hYmxlZENoZWNrYm94KHRoaXMuc3VwcHJlc3NFbmFibGVkQ2hlY2tib3gpO1xuICAgICAgICB0aGlzLmhpZGVPcGVuQ2xvc2VJY29ucyh0aGlzLnN1cHByZXNzT3BlbkNsb3NlSWNvbnMpO1xuICAgICAgICB0aGlzLnNldHVwRXhwYW5kQ29udHJhY3QoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoQXJpYVN0YXR1cygpO1xuICAgICAgICB0aGlzLnJlZnJlc2hDaGlsZERpc3BsYXkoKTtcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLnNldHVwRXhwYW5kQ29udHJhY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZUdyb3VwQ2xvc2VkSWNvbi5hcHBlbmRDaGlsZChjcmVhdGVJY29uKCdjb2x1bW5TZWxlY3RDbG9zZWQnLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgbnVsbCkpO1xuICAgICAgICB0aGlzLmVHcm91cE9wZW5lZEljb24uYXBwZW5kQ2hpbGQoY3JlYXRlSWNvbignY29sdW1uU2VsZWN0T3BlbicsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBudWxsKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZVRpdGxlQmFyLCAnY2xpY2snLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy50b2dnbGVHcm91cEV4cGFuZCgpOyB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5lVGl0bGVCYXIsICdrZXlkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoZS5rZXkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuRU5URVI6XG4gICAgICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlNQQUNFOlxuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLnRvZ2dsZUdyb3VwRXhwYW5kKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5SSUdIVDpcbiAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuTEVGVDpcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy50b2dnbGVHcm91cEV4cGFuZChlLmtleSA9PT0gS2V5Q29kZS5SSUdIVCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLnJlZnJlc2hBcmlhU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuc3VwcHJlc3NPcGVuQ2xvc2VJY29ucykge1xuICAgICAgICAgICAgc2V0QXJpYUV4cGFuZGVkKHRoaXMuZVRpdGxlQmFyLCB0aGlzLmV4cGFuZGVkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUucmVmcmVzaENoaWxkRGlzcGxheSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNob3dJY29uID0gIXRoaXMuc3VwcHJlc3NPcGVuQ2xvc2VJY29ucztcbiAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZVRvb2xiYXIsIHRoaXMuZXhwYW5kZWQgJiYgIXRoaXMuc3VwcHJlc3NFbmFibGVkQ2hlY2tib3gpO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lR3JvdXBPcGVuZWRJY29uLCBzaG93SWNvbiAmJiB0aGlzLmV4cGFuZGVkKTtcbiAgICAgICAgc2V0RGlzcGxheWVkKHRoaXMuZUdyb3VwQ2xvc2VkSWNvbiwgc2hvd0ljb24gJiYgIXRoaXMuZXhwYW5kZWQpO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUuaXNFeHBhbmRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwYW5kZWQ7XG4gICAgfTtcbiAgICBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZS5zZXRBbGlnbkl0ZW1zID0gZnVuY3Rpb24gKGFsaWdubWVudCkge1xuICAgICAgICBpZiAodGhpcy5hbGlnbkl0ZW1zICE9PSBhbGlnbm1lbnQpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlQ3NzQ2xhc3MoXCJhZy1ncm91cC1pdGVtLWFsaWdubWVudC1cIiArIHRoaXMuYWxpZ25JdGVtcyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hbGlnbkl0ZW1zID0gYWxpZ25tZW50O1xuICAgICAgICB2YXIgbmV3Q2xzID0gXCJhZy1ncm91cC1pdGVtLWFsaWdubWVudC1cIiArIHRoaXMuYWxpZ25JdGVtcztcbiAgICAgICAgdGhpcy5hZGRDc3NDbGFzcyhuZXdDbHMpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLnRvZ2dsZUdyb3VwRXhwYW5kID0gZnVuY3Rpb24gKGV4cGFuZGVkKSB7XG4gICAgICAgIGlmICh0aGlzLnN1cHByZXNzT3BlbkNsb3NlSWNvbnMpIHtcbiAgICAgICAgICAgIHRoaXMuZXhwYW5kZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoQ2hpbGREaXNwbGF5KCk7XG4gICAgICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lQ29udGFpbmVyLCB0cnVlKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGV4cGFuZGVkID0gZXhwYW5kZWQgIT0gbnVsbCA/IGV4cGFuZGVkIDogIXRoaXMuZXhwYW5kZWQ7XG4gICAgICAgIGlmICh0aGlzLmV4cGFuZGVkID09PSBleHBhbmRlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5leHBhbmRlZCA9IGV4cGFuZGVkO1xuICAgICAgICB0aGlzLnJlZnJlc2hBcmlhU3RhdHVzKCk7XG4gICAgICAgIHRoaXMucmVmcmVzaENoaWxkRGlzcGxheSgpO1xuICAgICAgICBzZXREaXNwbGF5ZWQodGhpcy5lQ29udGFpbmVyLCBleHBhbmRlZCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudCh7IHR5cGU6IHRoaXMuZXhwYW5kZWQgPyBBZ0dyb3VwQ29tcG9uZW50LkVWRU5UX0VYUEFOREVEIDogQWdHcm91cENvbXBvbmVudC5FVkVOVF9DT0xMQVBTRUQgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUuYWRkSXRlbXMgPSBmdW5jdGlvbiAoaXRlbXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaXRlbXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkgeyByZXR1cm4gX3RoaXMuYWRkSXRlbShpdGVtKTsgfSk7XG4gICAgfTtcbiAgICBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZS5hZGRJdGVtID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRoaXMuZUNvbnRhaW5lcjtcbiAgICAgICAgdmFyIGVsID0gaXRlbSBpbnN0YW5jZW9mIENvbXBvbmVudCA/IGl0ZW0uZ2V0R3VpKCkgOiBpdGVtO1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKCdhZy1ncm91cC1pdGVtJywgXCJhZy1cIiArIHRoaXMuY3NzSWRlbnRpZmllciArIFwiLWdyb3VwLWl0ZW1cIik7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgIHRoaXMuaXRlbXMucHVzaChlbCk7XG4gICAgfTtcbiAgICBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZS5oaWRlSXRlbSA9IGZ1bmN0aW9uIChoaWRlLCBpbmRleCkge1xuICAgICAgICB2YXIgaXRlbVRvSGlkZSA9IHRoaXMuaXRlbXNbaW5kZXhdO1xuICAgICAgICBpdGVtVG9IaWRlLmNsYXNzTGlzdC50b2dnbGUoJ2FnLWhpZGRlbicsIGhpZGUpO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUuc2V0VGl0bGUgPSBmdW5jdGlvbiAodGl0bGUpIHtcbiAgICAgICAgdGhpcy5lVGl0bGUuaW5uZXJUZXh0ID0gdGl0bGU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUuYWRkQ3NzQ2xhc3NUb1RpdGxlQmFyID0gZnVuY3Rpb24gKGNzc0NsYXNzKSB7XG4gICAgICAgIHRoaXMuZVRpdGxlQmFyLmNsYXNzTGlzdC5hZGQoY3NzQ2xhc3MpO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUuc2V0RW5hYmxlZCA9IGZ1bmN0aW9uIChlbmFibGVkLCBza2lwVG9nZ2xlKSB7XG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IGVuYWJsZWQ7XG4gICAgICAgIHRoaXMucmVmcmVzaERpc2FibGVkU3R5bGVzKCk7XG4gICAgICAgIHRoaXMudG9nZ2xlR3JvdXBFeHBhbmQoZW5hYmxlZCk7XG4gICAgICAgIGlmICghc2tpcFRvZ2dsZSkge1xuICAgICAgICAgICAgdGhpcy5jYkdyb3VwRW5hYmxlZC5zZXRWYWx1ZShlbmFibGVkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLmlzRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5hYmxlZDtcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLm9uRW5hYmxlQ2hhbmdlID0gZnVuY3Rpb24gKGNhbGxiYWNrRm4pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jYkdyb3VwRW5hYmxlZC5vblZhbHVlQ2hhbmdlKGZ1bmN0aW9uIChuZXdTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIF90aGlzLnNldEVuYWJsZWQobmV3U2VsZWN0aW9uLCB0cnVlKTtcbiAgICAgICAgICAgIGNhbGxiYWNrRm4obmV3U2VsZWN0aW9uKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUuaGlkZUVuYWJsZWRDaGVja2JveCA9IGZ1bmN0aW9uIChoaWRlKSB7XG4gICAgICAgIHRoaXMuc3VwcHJlc3NFbmFibGVkQ2hlY2tib3ggPSBoaWRlO1xuICAgICAgICB0aGlzLnJlZnJlc2hDaGlsZERpc3BsYXkoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoRGlzYWJsZWRTdHlsZXMoKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZS5oaWRlT3BlbkNsb3NlSWNvbnMgPSBmdW5jdGlvbiAoaGlkZSkge1xuICAgICAgICB0aGlzLnN1cHByZXNzT3BlbkNsb3NlSWNvbnMgPSBoaWRlO1xuICAgICAgICBpZiAoaGlkZSkge1xuICAgICAgICAgICAgdGhpcy50b2dnbGVHcm91cEV4cGFuZCh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuICAgIEFnR3JvdXBDb21wb25lbnQucHJvdG90eXBlLnJlZnJlc2hEaXNhYmxlZFN0eWxlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1kaXNhYmxlZCcsICF0aGlzLmVuYWJsZWQpO1xuICAgICAgICBpZiAodGhpcy5zdXBwcmVzc0VuYWJsZWRDaGVja2JveCAmJiAhdGhpcy5lbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmVUaXRsZUJhci5jbGFzc0xpc3QuYWRkKCdhZy1kaXNhYmxlZC1ncm91cC10aXRsZS1iYXInKTtcbiAgICAgICAgICAgIHRoaXMuZVRpdGxlQmFyLnJlbW92ZUF0dHJpYnV0ZSgndGFiaW5kZXgnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZVRpdGxlQmFyLmNsYXNzTGlzdC5yZW1vdmUoJ2FnLWRpc2FibGVkLWdyb3VwLXRpdGxlLWJhcicpO1xuICAgICAgICAgICAgdGhpcy5lVGl0bGVCYXIuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICcwJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoJ2FnLWRpc2FibGVkLWdyb3VwLWNvbnRhaW5lcicsICF0aGlzLmVuYWJsZWQpO1xuICAgIH07XG4gICAgQWdHcm91cENvbXBvbmVudC5FVkVOVF9FWFBBTkRFRCA9ICdleHBhbmRlZCc7XG4gICAgQWdHcm91cENvbXBvbmVudC5FVkVOVF9DT0xMQVBTRUQgPSAnY29sbGFwc2VkJztcbiAgICBfX2RlY29yYXRlJFUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVRpdGxlQmFyJylcbiAgICBdLCBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZSwgXCJlVGl0bGVCYXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUdyb3VwT3BlbmVkSWNvbicpXG4gICAgXSwgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUsIFwiZUdyb3VwT3BlbmVkSWNvblwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkVShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlR3JvdXBDbG9zZWRJY29uJylcbiAgICBdLCBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZSwgXCJlR3JvdXBDbG9zZWRJY29uXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRVKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VUb29sYmFyJylcbiAgICBdLCBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZSwgXCJlVG9vbGJhclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkVShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdjYkdyb3VwRW5hYmxlZCcpXG4gICAgXSwgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUsIFwiY2JHcm91cEVuYWJsZWRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVRpdGxlJylcbiAgICBdLCBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZSwgXCJlVGl0bGVcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUNvbnRhaW5lcicpXG4gICAgXSwgQWdHcm91cENvbXBvbmVudC5wcm90b3R5cGUsIFwiZUNvbnRhaW5lclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkVShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBZ0dyb3VwQ29tcG9uZW50LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBBZ0dyb3VwQ29tcG9uZW50O1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRTID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRUID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgVGFiR3VhcmRDdHJsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRTKFRhYkd1YXJkQ3RybCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBUYWJHdWFyZEN0cmwocGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnNraXBUYWJHdWFyZEZvY3VzID0gZmFsc2U7XG4gICAgICAgIHZhciBjb21wID0gcGFyYW1zLmNvbXAsIGVUb3BHdWFyZCA9IHBhcmFtcy5lVG9wR3VhcmQsIGVCb3R0b21HdWFyZCA9IHBhcmFtcy5lQm90dG9tR3VhcmQsIGZvY3VzSW5uZXJFbGVtZW50ID0gcGFyYW1zLmZvY3VzSW5uZXJFbGVtZW50LCBvbkZvY3VzSW4gPSBwYXJhbXMub25Gb2N1c0luLCBvbkZvY3VzT3V0ID0gcGFyYW1zLm9uRm9jdXNPdXQsIHNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uID0gcGFyYW1zLnNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uLCBvblRhYktleURvd24gPSBwYXJhbXMub25UYWJLZXlEb3duLCBoYW5kbGVLZXlEb3duID0gcGFyYW1zLmhhbmRsZUtleURvd24sIGVGb2N1c2FibGVFbGVtZW50ID0gcGFyYW1zLmVGb2N1c2FibGVFbGVtZW50O1xuICAgICAgICBfdGhpcy5jb21wID0gY29tcDtcbiAgICAgICAgX3RoaXMuZVRvcEd1YXJkID0gZVRvcEd1YXJkO1xuICAgICAgICBfdGhpcy5lQm90dG9tR3VhcmQgPSBlQm90dG9tR3VhcmQ7XG4gICAgICAgIF90aGlzLnByb3ZpZGVkRm9jdXNJbm5lckVsZW1lbnQgPSBmb2N1c0lubmVyRWxlbWVudDtcbiAgICAgICAgX3RoaXMuZUZvY3VzYWJsZUVsZW1lbnQgPSBlRm9jdXNhYmxlRWxlbWVudDtcbiAgICAgICAgX3RoaXMucHJvdmlkZWRGb2N1c0luID0gb25Gb2N1c0luO1xuICAgICAgICBfdGhpcy5wcm92aWRlZEZvY3VzT3V0ID0gb25Gb2N1c091dDtcbiAgICAgICAgX3RoaXMucHJvdmlkZWRTaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvbiA9IHNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uO1xuICAgICAgICBfdGhpcy5wcm92aWRlZE9uVGFiS2V5RG93biA9IG9uVGFiS2V5RG93bjtcbiAgICAgICAgX3RoaXMucHJvdmlkZWRIYW5kbGVLZXlEb3duID0gaGFuZGxlS2V5RG93bjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IE1hbmFnZWRGb2N1c0ZlYXR1cmUodGhpcy5lRm9jdXNhYmxlRWxlbWVudCwge1xuICAgICAgICAgICAgc2hvdWxkU3RvcEV2ZW50UHJvcGFnYXRpb246IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnNob3VsZFN0b3BFdmVudFByb3BhZ2F0aW9uKCk7IH0sXG4gICAgICAgICAgICBvblRhYktleURvd246IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblRhYktleURvd24oZSk7IH0sXG4gICAgICAgICAgICBoYW5kbGVLZXlEb3duOiBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMuaGFuZGxlS2V5RG93bihlKTsgfSxcbiAgICAgICAgICAgIG9uRm9jdXNJbjogZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLm9uRm9jdXNJbihlKTsgfSxcbiAgICAgICAgICAgIG9uRm9jdXNPdXQ6IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkZvY3VzT3V0KGUpOyB9XG4gICAgICAgIH0pKTtcbiAgICAgICAgdGhpcy5hY3RpdmF0ZVRhYkd1YXJkcygpO1xuICAgICAgICBbdGhpcy5lVG9wR3VhcmQsIHRoaXMuZUJvdHRvbUd1YXJkXS5mb3JFYWNoKGZ1bmN0aW9uIChndWFyZCkgeyByZXR1cm4gX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGd1YXJkLCAnZm9jdXMnLCBfdGhpcy5vbkZvY3VzLmJpbmQoX3RoaXMpKTsgfSk7XG4gICAgfTtcbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5wcm92aWRlZEhhbmRsZUtleURvd24pIHtcbiAgICAgICAgICAgIHRoaXMucHJvdmlkZWRIYW5kbGVLZXlEb3duKGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLnRhYkd1YXJkc0FyZUFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5lVG9wR3VhcmQgJiYgdGhpcy5lVG9wR3VhcmQuaGFzQXR0cmlidXRlKCd0YWJJbmRleCcpO1xuICAgIH07XG4gICAgVGFiR3VhcmRDdHJsLnByb3RvdHlwZS5zaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJvdmlkZWRTaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvdmlkZWRTaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ3RybC5wcm90b3R5cGUuYWN0aXZhdGVUYWJHdWFyZHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY29tcC5zZXRUYWJJbmRleCh0aGlzLmdldEdyaWRUYWJJbmRleCgpKTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ3RybC5wcm90b3R5cGUuZGVhY3RpdmF0ZVRhYkd1YXJkcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb21wLnNldFRhYkluZGV4KCk7XG4gICAgfTtcbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLm9uRm9jdXMgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAodGhpcy5za2lwVGFiR3VhcmRGb2N1cykge1xuICAgICAgICAgICAgdGhpcy5za2lwVGFiR3VhcmRGb2N1cyA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmcm9tQm90dG9tID0gZS50YXJnZXQgPT09IHRoaXMuZUJvdHRvbUd1YXJkO1xuICAgICAgICBpZiAodGhpcy5wcm92aWRlZEZvY3VzSW5uZXJFbGVtZW50KSB7XG4gICAgICAgICAgICB0aGlzLnByb3ZpZGVkRm9jdXNJbm5lckVsZW1lbnQoZnJvbUJvdHRvbSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmZvY3VzSW5uZXJFbGVtZW50KGZyb21Cb3R0b20pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLm9uRm9jdXNJbiA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICh0aGlzLnByb3ZpZGVkRm9jdXNJbiAmJiB0aGlzLnByb3ZpZGVkRm9jdXNJbihlKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVhY3RpdmF0ZVRhYkd1YXJkcygpO1xuICAgIH07XG4gICAgVGFiR3VhcmRDdHJsLnByb3RvdHlwZS5vbkZvY3VzT3V0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKHRoaXMucHJvdmlkZWRGb2N1c091dCAmJiB0aGlzLnByb3ZpZGVkRm9jdXNPdXQoZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuZUZvY3VzYWJsZUVsZW1lbnQuY29udGFpbnMoZS5yZWxhdGVkVGFyZ2V0KSkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmF0ZVRhYkd1YXJkcygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLm9uVGFiS2V5RG93biA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLnByb3ZpZGVkT25UYWJLZXlEb3duKSB7XG4gICAgICAgICAgICB0aGlzLnByb3ZpZGVkT25UYWJLZXlEb3duKGUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChlLmRlZmF1bHRQcmV2ZW50ZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdGFiR3VhcmRzQXJlQWN0aXZlID0gdGhpcy50YWJHdWFyZHNBcmVBY3RpdmUoKTtcbiAgICAgICAgaWYgKHRhYkd1YXJkc0FyZUFjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5kZWFjdGl2YXRlVGFiR3VhcmRzKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5leHRSb290ID0gdGhpcy5nZXROZXh0Rm9jdXNhYmxlRWxlbWVudChlLnNoaWZ0S2V5KTtcbiAgICAgICAgaWYgKHRhYkd1YXJkc0FyZUFjdGl2ZSkge1xuICAgICAgICAgICAgLy8gZW5zdXJlIHRoZSB0YWIgZ3VhcmRzIGFyZSBvbmx5IHJlLWluc3RhdGVkIG9uY2UgdGhlIGV2ZW50IGhhcyBmaW5pc2hlZCBwcm9jZXNzaW5nLCB0byBhdm9pZCB0aGUgYnJvd3NlclxuICAgICAgICAgICAgLy8gdGFiYmluZyB0byB0aGUgdGFiIGd1YXJkIGZyb20gaW5zaWRlIHRoZSBjb21wb25lbnRcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuYWN0aXZhdGVUYWJHdWFyZHMoKTsgfSwgMCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFuZXh0Um9vdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIG5leHRSb290LmZvY3VzKCk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ3RybC5wcm90b3R5cGUuZ2V0R3JpZFRhYkluZGV4ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0R3JpZFRhYkluZGV4KCk7XG4gICAgfTtcbiAgICBUYWJHdWFyZEN0cmwucHJvdG90eXBlLmZvY3VzSW5uZXJFbGVtZW50ID0gZnVuY3Rpb24gKGZyb21Cb3R0b20pIHtcbiAgICAgICAgaWYgKGZyb21Cb3R0b20gPT09IHZvaWQgMCkgeyBmcm9tQm90dG9tID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIGZvY3VzYWJsZSA9IHRoaXMuZm9jdXNTZXJ2aWNlLmZpbmRGb2N1c2FibGVFbGVtZW50cyh0aGlzLmVGb2N1c2FibGVFbGVtZW50KTtcbiAgICAgICAgaWYgKHRoaXMudGFiR3VhcmRzQXJlQWN0aXZlKCkpIHtcbiAgICAgICAgICAgIC8vIHJlbW92ZSB0YWIgZ3VhcmRzIGZyb20gdGhpcyBjb21wb25lbnQgZnJvbSBsaXN0IG9mIGZvY3VzYWJsZSBlbGVtZW50c1xuICAgICAgICAgICAgZm9jdXNhYmxlLnNwbGljZSgwLCAxKTtcbiAgICAgICAgICAgIGZvY3VzYWJsZS5zcGxpY2UoZm9jdXNhYmxlLmxlbmd0aCAtIDEsIDEpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZm9jdXNhYmxlLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvY3VzYWJsZVtmcm9tQm90dG9tID8gZm9jdXNhYmxlLmxlbmd0aCAtIDEgOiAwXS5mb2N1cygpO1xuICAgIH07XG4gICAgVGFiR3VhcmRDdHJsLnByb3RvdHlwZS5nZXROZXh0Rm9jdXNhYmxlRWxlbWVudCA9IGZ1bmN0aW9uIChiYWNrd2FyZHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9jdXNTZXJ2aWNlLmZpbmROZXh0Rm9jdXNhYmxlRWxlbWVudCh0aGlzLmVGb2N1c2FibGVFbGVtZW50LCBmYWxzZSwgYmFja3dhcmRzKTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ3RybC5wcm90b3R5cGUuZm9yY2VGb2N1c091dE9mQ29udGFpbmVyID0gZnVuY3Rpb24gKHVwKSB7XG4gICAgICAgIGlmICh1cCA9PT0gdm9pZCAwKSB7IHVwID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIHRhYkd1YXJkVG9Gb2N1cyA9IHVwID8gdGhpcy5lVG9wR3VhcmQgOiB0aGlzLmVCb3R0b21HdWFyZDtcbiAgICAgICAgdGhpcy5hY3RpdmF0ZVRhYkd1YXJkcygpO1xuICAgICAgICB0aGlzLnNraXBUYWJHdWFyZEZvY3VzID0gdHJ1ZTtcbiAgICAgICAgdGFiR3VhcmRUb0ZvY3VzLmZvY3VzKCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJFQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZvY3VzU2VydmljZScpXG4gICAgXSwgVGFiR3VhcmRDdHJsLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFQoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgVGFiR3VhcmRDdHJsLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBUYWJHdWFyZEN0cmw7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkUiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fcmVhZCQ4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIF9fc3ByZWFkJDcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3NwcmVhZCkgfHwgZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhciA9IGFyLmNvbmNhdChfX3JlYWQkOChhcmd1bWVudHNbaV0pKTtcbiAgICByZXR1cm4gYXI7XG59O1xudmFyIFRhYkd1YXJkQ29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkUihUYWJHdWFyZENvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVGFiR3VhcmRDb21wKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFRhYkd1YXJkQ29tcC5wcm90b3R5cGUuaW5pdGlhbGlzZVRhYkd1YXJkID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB0aGlzLmVUb3BHdWFyZCA9IHRoaXMuY3JlYXRlVGFiR3VhcmQoJ3RvcCcpO1xuICAgICAgICB0aGlzLmVCb3R0b21HdWFyZCA9IHRoaXMuY3JlYXRlVGFiR3VhcmQoJ2JvdHRvbScpO1xuICAgICAgICB0aGlzLmVGb2N1c2FibGVFbGVtZW50ID0gdGhpcy5nZXRGb2N1c2FibGVFbGVtZW50KCk7XG4gICAgICAgIHZhciB0YWJHdWFyZHMgPSBbdGhpcy5lVG9wR3VhcmQsIHRoaXMuZUJvdHRvbUd1YXJkXTtcbiAgICAgICAgdmFyIGNvbXBQcm94eSA9IHtcbiAgICAgICAgICAgIHNldFRhYkluZGV4OiBmdW5jdGlvbiAodGFiSW5kZXgpIHtcbiAgICAgICAgICAgICAgICB0YWJHdWFyZHMuZm9yRWFjaChmdW5jdGlvbiAodGFiR3VhcmQpIHsgcmV0dXJuIHRhYkluZGV4ICE9IG51bGwgPyB0YWJHdWFyZC5zZXRBdHRyaWJ1dGUoJ3RhYkluZGV4JywgdGFiSW5kZXgpIDogdGFiR3VhcmQucmVtb3ZlQXR0cmlidXRlKCd0YWJJbmRleCcpOyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5hZGRUYWJHdWFyZHModGhpcy5lVG9wR3VhcmQsIHRoaXMuZUJvdHRvbUd1YXJkKTtcbiAgICAgICAgdGhpcy50YWJHdWFyZEN0cmwgPSB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBUYWJHdWFyZEN0cmwoe1xuICAgICAgICAgICAgY29tcDogY29tcFByb3h5LFxuICAgICAgICAgICAgZVRvcEd1YXJkOiB0aGlzLmVUb3BHdWFyZCxcbiAgICAgICAgICAgIGVCb3R0b21HdWFyZDogdGhpcy5lQm90dG9tR3VhcmQsXG4gICAgICAgICAgICBlRm9jdXNhYmxlRWxlbWVudDogdGhpcy5lRm9jdXNhYmxlRWxlbWVudCxcbiAgICAgICAgICAgIG9uRm9jdXNJbjogcGFyYW1zLm9uRm9jdXNJbixcbiAgICAgICAgICAgIG9uRm9jdXNPdXQ6IHBhcmFtcy5vbkZvY3VzT3V0LFxuICAgICAgICAgICAgZm9jdXNJbm5lckVsZW1lbnQ6IHBhcmFtcy5mb2N1c0lubmVyRWxlbWVudCxcbiAgICAgICAgICAgIGhhbmRsZUtleURvd246IHBhcmFtcy5oYW5kbGVLZXlEb3duLFxuICAgICAgICAgICAgb25UYWJLZXlEb3duOiBwYXJhbXMub25UYWJLZXlEb3duLFxuICAgICAgICAgICAgc2hvdWxkU3RvcEV2ZW50UHJvcGFnYXRpb246IHBhcmFtcy5zaG91bGRTdG9wRXZlbnRQcm9wYWdhdGlvblxuICAgICAgICB9KSk7XG4gICAgfTtcbiAgICBUYWJHdWFyZENvbXAucHJvdG90eXBlLmNyZWF0ZVRhYkd1YXJkID0gZnVuY3Rpb24gKHNpZGUpIHtcbiAgICAgICAgdmFyIHRhYkd1YXJkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHRhYkd1YXJkLmNsYXNzTGlzdC5hZGQoJ2FnLXRhYi1ndWFyZCcsIFwiYWctdGFiLWd1YXJkLVwiICsgc2lkZSk7XG4gICAgICAgIHNldEFyaWFSb2xlKHRhYkd1YXJkLCAncHJlc2VudGF0aW9uJyk7XG4gICAgICAgIHJldHVybiB0YWJHdWFyZDtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ29tcC5wcm90b3R5cGUuYWRkVGFiR3VhcmRzID0gZnVuY3Rpb24gKHRvcFRhYkd1YXJkLCBib3R0b21UYWJHdWFyZCkge1xuICAgICAgICB0aGlzLmVGb2N1c2FibGVFbGVtZW50Lmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJiZWdpbicsIHRvcFRhYkd1YXJkKTtcbiAgICAgICAgdGhpcy5lRm9jdXNhYmxlRWxlbWVudC5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2JlZm9yZWVuZCcsIGJvdHRvbVRhYkd1YXJkKTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ29tcC5wcm90b3R5cGUucmVtb3ZlQWxsQ2hpbGRyZW5FeGNlcHRUYWJHdWFyZHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0YWJHdWFyZHMgPSBbdGhpcy5lVG9wR3VhcmQsIHRoaXMuZUJvdHRvbUd1YXJkXTtcbiAgICAgICAgY2xlYXJFbGVtZW50KHRoaXMuZ2V0Rm9jdXNhYmxlRWxlbWVudCgpKTtcbiAgICAgICAgdGhpcy5hZGRUYWJHdWFyZHMuYXBwbHkodGhpcywgX19zcHJlYWQkNyh0YWJHdWFyZHMpKTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ29tcC5wcm90b3R5cGUuZm9yY2VGb2N1c091dE9mQ29udGFpbmVyID0gZnVuY3Rpb24gKHVwKSB7XG4gICAgICAgIGlmICh1cCA9PT0gdm9pZCAwKSB7IHVwID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy50YWJHdWFyZEN0cmwuZm9yY2VGb2N1c091dE9mQ29udGFpbmVyKHVwKTtcbiAgICB9O1xuICAgIFRhYkd1YXJkQ29tcC5wcm90b3R5cGUuYXBwZW5kQ2hpbGQgPSBmdW5jdGlvbiAobmV3Q2hpbGQsIGNvbnRhaW5lcikge1xuICAgICAgICBpZiAoIWlzTm9kZU9yRWxlbWVudChuZXdDaGlsZCkpIHtcbiAgICAgICAgICAgIG5ld0NoaWxkID0gbmV3Q2hpbGQuZ2V0R3VpKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJvdHRvbVRhYkd1YXJkID0gdGhpcy5lQm90dG9tR3VhcmQ7XG4gICAgICAgIGlmIChib3R0b21UYWJHdWFyZCkge1xuICAgICAgICAgICAgYm90dG9tVGFiR3VhcmQuaW5zZXJ0QWRqYWNlbnRFbGVtZW50KCdiZWZvcmViZWdpbicsIG5ld0NoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIF9zdXBlci5wcm90b3R5cGUuYXBwZW5kQ2hpbGQuY2FsbCh0aGlzLCBuZXdDaGlsZCwgY29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIFRhYkd1YXJkQ29tcDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkUSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXNzaWduJDEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2Fzc2lnbikgfHwgZnVuY3Rpb24gKCkge1xuICAgIF9fYXNzaWduJDEgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKVxuICAgICAgICAgICAgICAgIHRbcF0gPSBzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0O1xuICAgIH07XG4gICAgcmV0dXJuIF9fYXNzaWduJDEuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgX19kZWNvcmF0ZSRTID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdNZW51TGlzdCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkUShBZ01lbnVMaXN0LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnTWVudUxpc3QobGV2ZWwpIHtcbiAgICAgICAgaWYgKGxldmVsID09PSB2b2lkIDApIHsgbGV2ZWwgPSAxOyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIC8qIGh0bWwgKi8gXCI8ZGl2IGNsYXNzPVxcXCJhZy1tZW51LWxpc3RcXFwiIHJvbGU9XFxcInRyZWVcXFwiPjwvZGl2PlwiKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5sZXZlbCA9IGxldmVsO1xuICAgICAgICBfdGhpcy5tZW51SXRlbXMgPSBbXTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBZ01lbnVMaXN0LnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmluaXRpYWxpc2VUYWJHdWFyZCh7XG4gICAgICAgICAgICBvblRhYktleURvd246IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblRhYktleURvd24oZSk7IH0sXG4gICAgICAgICAgICBoYW5kbGVLZXlEb3duOiBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMuaGFuZGxlS2V5RG93bihlKTsgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLm9uVGFiS2V5RG93biA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBwYXJlbnQgPSB0aGlzLmdldFBhcmVudENvbXBvbmVudCgpO1xuICAgICAgICB2YXIgcGFyZW50R3VpID0gcGFyZW50ICYmIHBhcmVudC5nZXRHdWkoKTtcbiAgICAgICAgdmFyIGlzTWFuYWdlZCA9IHBhcmVudEd1aSAmJiBwYXJlbnRHdWkuY2xhc3NMaXN0LmNvbnRhaW5zKCdhZy1mb2N1cy1tYW5hZ2VkJyk7XG4gICAgICAgIGlmICghaXNNYW5hZ2VkKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VJZklzQ2hpbGQoZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmhhbmRsZUtleURvd24gPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICBzd2l0Y2ggKGUua2V5KSB7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuVVA6XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuUklHSFQ6XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuRE9XTjpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5MRUZUOlxuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZU5hdktleShlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEtleUNvZGUuRVNDQVBFOlxuICAgICAgICAgICAgICAgIHZhciB0b3BNZW51ID0gdGhpcy5maW5kVG9wTWVudSgpO1xuICAgICAgICAgICAgICAgIGlmICh0b3BNZW51KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzSW50byh0b3BNZW51LmdldEd1aSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmNsZWFyQWN0aXZlSXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuYWN0aXZlTWVudUl0ZW0pIHtcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlTWVudUl0ZW0uZGVhY3RpdmF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5hY3RpdmVNZW51SXRlbSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmFkZE1lbnVJdGVtcyA9IGZ1bmN0aW9uIChtZW51SXRlbXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKG1lbnVJdGVtcyA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbWVudUl0ZW1zLmZvckVhY2goZnVuY3Rpb24gKG1lbnVJdGVtT3JTdHJpbmcpIHtcbiAgICAgICAgICAgIGlmIChtZW51SXRlbU9yU3RyaW5nID09PSAnc2VwYXJhdG9yJykge1xuICAgICAgICAgICAgICAgIF90aGlzLmFkZFNlcGFyYXRvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG1lbnVJdGVtT3JTdHJpbmcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogdW5yZWNvZ25pc2VkIG1lbnUgaXRlbSBcIiArIG1lbnVJdGVtT3JTdHJpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuYWRkSXRlbShtZW51SXRlbU9yU3RyaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBZ01lbnVMaXN0LnByb3RvdHlwZS5hZGRJdGVtID0gZnVuY3Rpb24gKG1lbnVJdGVtRGVmKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtZW51SXRlbSA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEFnTWVudUl0ZW1Db21wb25lbnQoX19hc3NpZ24kMShfX2Fzc2lnbiQxKHt9LCBtZW51SXRlbURlZiksIHsgaXNBbm90aGVyU3ViTWVudU9wZW46IGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLm1lbnVJdGVtcy5zb21lKGZ1bmN0aW9uIChtKSB7IHJldHVybiBtLmlzU3ViTWVudU9wZW4oKTsgfSk7IH0gfSkpKTtcbiAgICAgICAgbWVudUl0ZW0uc2V0UGFyZW50Q29tcG9uZW50KHRoaXMpO1xuICAgICAgICBzZXRBcmlhTGV2ZWwobWVudUl0ZW0uZ2V0R3VpKCksIHRoaXMubGV2ZWwpO1xuICAgICAgICB0aGlzLm1lbnVJdGVtcy5wdXNoKG1lbnVJdGVtKTtcbiAgICAgICAgdGhpcy5hcHBlbmRDaGlsZChtZW51SXRlbS5nZXRHdWkoKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKG1lbnVJdGVtLCBBZ01lbnVJdGVtQ29tcG9uZW50LkVWRU5UX01FTlVfSVRFTV9TRUxFQ1RFRCwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBfdGhpcy5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKG1lbnVJdGVtLCBBZ01lbnVJdGVtQ29tcG9uZW50LkVWRU5UX01FTlVfSVRFTV9BQ1RJVkFURUQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLmFjdGl2ZU1lbnVJdGVtICYmIF90aGlzLmFjdGl2ZU1lbnVJdGVtICE9PSBldmVudC5tZW51SXRlbSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmFjdGl2ZU1lbnVJdGVtLmRlYWN0aXZhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmFjdGl2ZU1lbnVJdGVtID0gZXZlbnQubWVudUl0ZW07XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQWdNZW51TGlzdC5wcm90b3R5cGUuYWN0aXZhdGVGaXJzdEl0ZW0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpdGVtID0gdGhpcy5tZW51SXRlbXMuZmlsdGVyKGZ1bmN0aW9uIChjdXJyZW50SXRlbSkgeyByZXR1cm4gIWN1cnJlbnRJdGVtLmlzRGlzYWJsZWQoKTsgfSlbMF07XG4gICAgICAgIGlmICghaXRlbSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGl0ZW0uYWN0aXZhdGUoKTtcbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmFkZFNlcGFyYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlcGFyYXRvckh0bWwgPSAvKiBodG1sICovIFwiXFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctbWVudS1zZXBhcmF0b3JcXFwiIGFyaWEtaGlkZGVuPVxcXCJ0cnVlXFxcIj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctbWVudS1zZXBhcmF0b3ItcGFydFxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLW1lbnUtc2VwYXJhdG9yLXBhcnRcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1tZW51LXNlcGFyYXRvci1wYXJ0XFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctbWVudS1zZXBhcmF0b3ItcGFydFxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgPC9kaXY+XCI7XG4gICAgICAgIHRoaXMuYXBwZW5kQ2hpbGQobG9hZFRlbXBsYXRlKHNlcGFyYXRvckh0bWwpKTtcbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmZpbmRUb3BNZW51ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcGFyZW50ID0gdGhpcy5nZXRQYXJlbnRDb21wb25lbnQoKTtcbiAgICAgICAgaWYgKCFwYXJlbnQgJiYgdGhpcyBpbnN0YW5jZW9mIEFnTWVudUxpc3QpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICB2YXIgbmV4dFBhcmVudCA9IHBhcmVudCAmJiBwYXJlbnQuZ2V0UGFyZW50Q29tcG9uZW50ICYmIHBhcmVudC5nZXRQYXJlbnRDb21wb25lbnQoKTtcbiAgICAgICAgICAgIGlmICghbmV4dFBhcmVudCB8fCAoIShuZXh0UGFyZW50IGluc3RhbmNlb2YgQWdNZW51TGlzdCB8fCBuZXh0UGFyZW50IGluc3RhbmNlb2YgQWdNZW51SXRlbUNvbXBvbmVudCkpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJlbnQgPSBuZXh0UGFyZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwYXJlbnQgaW5zdGFuY2VvZiBBZ01lbnVMaXN0ID8gcGFyZW50IDogdW5kZWZpbmVkO1xuICAgIH07XG4gICAgQWdNZW51TGlzdC5wcm90b3R5cGUuaGFuZGxlTmF2S2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlVQOlxuICAgICAgICAgICAgY2FzZSBLZXlDb2RlLkRPV046XG4gICAgICAgICAgICAgICAgdmFyIG5leHRJdGVtID0gdGhpcy5maW5kTmV4dEl0ZW0oa2V5ID09PSBLZXlDb2RlLlVQKTtcbiAgICAgICAgICAgICAgICBpZiAobmV4dEl0ZW0gJiYgbmV4dEl0ZW0gIT09IHRoaXMuYWN0aXZlTWVudUl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dEl0ZW0uYWN0aXZhdGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZWZ0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKSA/IEtleUNvZGUuUklHSFQgOiBLZXlDb2RlLkxFRlQ7XG4gICAgICAgIGlmIChrZXkgPT09IGxlZnQpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VJZklzQ2hpbGQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub3BlbkNoaWxkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmNsb3NlSWZJc0NoaWxkID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHBhcmVudEl0ZW0gPSB0aGlzLmdldFBhcmVudENvbXBvbmVudCgpO1xuICAgICAgICBpZiAocGFyZW50SXRlbSAmJiBwYXJlbnRJdGVtIGluc3RhbmNlb2YgQWdNZW51SXRlbUNvbXBvbmVudCkge1xuICAgICAgICAgICAgaWYgKGUpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJlbnRJdGVtLmNsb3NlU3ViTWVudSgpO1xuICAgICAgICAgICAgcGFyZW50SXRlbS5nZXRHdWkoKS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVMaXN0LnByb3RvdHlwZS5vcGVuQ2hpbGQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZU1lbnVJdGVtKSB7XG4gICAgICAgICAgICB0aGlzLmFjdGl2ZU1lbnVJdGVtLm9wZW5TdWJNZW51KHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVMaXN0LnByb3RvdHlwZS5maW5kTmV4dEl0ZW0gPSBmdW5jdGlvbiAodXApIHtcbiAgICAgICAgdmFyIGl0ZW1zID0gdGhpcy5tZW51SXRlbXMuZmlsdGVyKGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiAhaXRlbS5pc0Rpc2FibGVkKCk7IH0pO1xuICAgICAgICBpZiAoIWl0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5hY3RpdmVNZW51SXRlbSkge1xuICAgICAgICAgICAgcmV0dXJuIHVwID8gbGFzdChpdGVtcykgOiBpdGVtc1swXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXApIHtcbiAgICAgICAgICAgIGl0ZW1zLnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV4dEl0ZW07XG4gICAgICAgIHZhciBmb3VuZEN1cnJlbnQgPSBmYWxzZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGl0ZW0gPSBpdGVtc1tpXTtcbiAgICAgICAgICAgIGlmICghZm91bmRDdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0gPT09IHRoaXMuYWN0aXZlTWVudUl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgZm91bmRDdXJyZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXh0SXRlbSA9IGl0ZW07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV4dEl0ZW0gfHwgdGhpcy5hY3RpdmVNZW51SXRlbTtcbiAgICB9O1xuICAgIEFnTWVudUxpc3QucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY2xlYXJBY3RpdmVJdGVtKCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRTKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIEFnTWVudUxpc3QucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkUyhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBBZ01lbnVMaXN0LnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBBZ01lbnVMaXN0O1xufShUYWJHdWFyZENvbXApKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRQID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRSID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdNZW51UGFuZWwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJFAoQWdNZW51UGFuZWwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQWdNZW51UGFuZWwod3JhcHBlZENvbXBvbmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy53cmFwcGVkQ29tcG9uZW50ID0gd3JhcHBlZENvbXBvbmVudDtcbiAgICAgICAgX3RoaXMuc2V0VGVtcGxhdGVGcm9tRWxlbWVudCh3cmFwcGVkQ29tcG9uZW50LmdldEd1aSgpKTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBBZ01lbnVQYW5lbC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5pbml0aWFsaXNlVGFiR3VhcmQoe1xuICAgICAgICAgICAgb25UYWJLZXlEb3duOiBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25UYWJLZXlEb3duKGUpOyB9LFxuICAgICAgICAgICAgaGFuZGxlS2V5RG93bjogZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLmhhbmRsZUtleURvd24oZSk7IH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBZ01lbnVQYW5lbC5wcm90b3R5cGUuaGFuZGxlS2V5RG93biA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmIChlLmtleSA9PT0gS2V5Q29kZS5FU0NBUEUpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVQYW5lbC5wcm90b3R5cGUub25UYWJLZXlEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUuZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xvc2VQYW5lbCgpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfTtcbiAgICBBZ01lbnVQYW5lbC5wcm90b3R5cGUuY2xvc2VQYW5lbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1lbnVJdGVtID0gdGhpcy5wYXJlbnRDb21wb25lbnQ7XG4gICAgICAgIG1lbnVJdGVtLmNsb3NlU3ViTWVudSgpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIG1lbnVJdGVtLmdldEd1aSgpLmZvY3VzKCk7IH0sIDApO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRSKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIEFnTWVudVBhbmVsLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBBZ01lbnVQYW5lbDtcbn0oVGFiR3VhcmRDb21wKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkTyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkUSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEFnTWVudUl0ZW1Db21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJE8oQWdNZW51SXRlbUNvbXBvbmVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBZ01lbnVJdGVtQ29tcG9uZW50KHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIF90aGlzLmlzQWN0aXZlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnN1Yk1lbnVJc09wZW4gPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuc2V0VGVtcGxhdGUoLyogaHRtbCAqLyBcIjxkaXYgY2xhc3M9XFxcIlwiICsgX3RoaXMuZ2V0Q2xhc3NOYW1lKCkgKyBcIlxcXCIgdGFiaW5kZXg9XFxcIi0xXFxcIiByb2xlPVxcXCJ0cmVlaXRlbVxcXCI+PC9kaXY+XCIpO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkSWNvbigpO1xuICAgICAgICB0aGlzLmFkZE5hbWUoKTtcbiAgICAgICAgdGhpcy5hZGRTaG9ydGN1dCgpO1xuICAgICAgICB0aGlzLmFkZFN1Yk1lbnUoKTtcbiAgICAgICAgdGhpcy5hZGRUb29sdGlwKCk7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgaWYgKHRoaXMucGFyYW1zLmRpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmFkZENzc0NsYXNzKHRoaXMuZ2V0Q2xhc3NOYW1lKCdkaXNhYmxlZCcpKTtcbiAgICAgICAgICAgIHNldEFyaWFEaXNhYmxlZChlR3VpLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYWRkR3VpRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25JdGVtU2VsZWN0ZWQoZSk7IH0pO1xuICAgICAgICAgICAgdGhpcy5hZGRHdWlFdmVudExpc3RlbmVyKCdrZXlkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoZS5rZXkgPT09IEtleUNvZGUuRU5URVIgfHwgZS5rZXkgPT09IEtleUNvZGUuU1BBQ0UpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5vbkl0ZW1TZWxlY3RlZChlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuYWRkR3VpRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBQcmV2ZW50IGV2ZW50IGJ1YmJsaW5nIHRvIG90aGVyIGV2ZW50IGhhbmRsZXJzIHN1Y2ggYXMgUG9wdXBTZXJ2aWNlIHRyaWdnZXJpbmdcbiAgICAgICAgICAgICAgICAvLyBwcmVtYXR1cmUgY2xvc2luZyBvZiBhbnkgb3BlbiBzdWItbWVudSBwb3B1cC5cbiAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5hZGRHdWlFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25Nb3VzZUVudGVyKCk7IH0pO1xuICAgICAgICAgICAgdGhpcy5hZGRHdWlFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMub25Nb3VzZUxlYXZlKCk7IH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5jc3NDbGFzc2VzKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmFtcy5jc3NDbGFzc2VzLmZvckVhY2goZnVuY3Rpb24gKGl0KSB7IHJldHVybiBfdGhpcy5hZGRDc3NDbGFzcyhpdCk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LnByb3RvdHlwZS5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLnBhcmFtcy5kaXNhYmxlZDtcbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLm9wZW5TdWJNZW51ID0gZnVuY3Rpb24gKGFjdGl2YXRlRmlyc3RJdGVtKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChhY3RpdmF0ZUZpcnN0SXRlbSA9PT0gdm9pZCAwKSB7IGFjdGl2YXRlRmlyc3RJdGVtID0gZmFsc2U7IH1cbiAgICAgICAgdGhpcy5jbG9zZVN1Yk1lbnUoKTtcbiAgICAgICAgaWYgKCF0aGlzLnBhcmFtcy5zdWJNZW51KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVQb3B1cCA9IGxvYWRUZW1wbGF0ZSgvKiBodG1sICovIFwiPGRpdiBjbGFzcz1cXFwiYWctbWVudVxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj48L2Rpdj5cIik7XG4gICAgICAgIHZhciBkZXN0cm95U3ViTWVudTtcbiAgICAgICAgaWYgKHRoaXMucGFyYW1zLnN1Yk1lbnUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRMZXZlbCA9IGdldEFyaWFMZXZlbCh0aGlzLmdldEd1aSgpKTtcbiAgICAgICAgICAgIHZhciBuZXh0TGV2ZWwgPSBpc05hTihjdXJyZW50TGV2ZWwpID8gMSA6IChjdXJyZW50TGV2ZWwgKyAxKTtcbiAgICAgICAgICAgIHZhciBjaGlsZE1lbnVfMSA9IHRoaXMuY3JlYXRlQmVhbihuZXcgQWdNZW51TGlzdChuZXh0TGV2ZWwpKTtcbiAgICAgICAgICAgIGNoaWxkTWVudV8xLnNldFBhcmVudENvbXBvbmVudCh0aGlzKTtcbiAgICAgICAgICAgIGNoaWxkTWVudV8xLmFkZE1lbnVJdGVtcyh0aGlzLnBhcmFtcy5zdWJNZW51KTtcbiAgICAgICAgICAgIGVQb3B1cC5hcHBlbmRDaGlsZChjaGlsZE1lbnVfMS5nZXRHdWkoKSk7XG4gICAgICAgICAgICAvLyBidWJibGUgbWVudSBpdGVtIHNlbGVjdGVkIGV2ZW50c1xuICAgICAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoY2hpbGRNZW51XzEsIEFnTWVudUl0ZW1Db21wb25lbnQuRVZFTlRfTUVOVV9JVEVNX1NFTEVDVEVELCBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMuZGlzcGF0Y2hFdmVudChlKTsgfSk7XG4gICAgICAgICAgICBjaGlsZE1lbnVfMS5hZGRHdWlFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuY2FuY2VsRGVhY3RpdmF0ZSgpOyB9KTtcbiAgICAgICAgICAgIGRlc3Ryb3lTdWJNZW51ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZGVzdHJveUJlYW4oY2hpbGRNZW51XzEpOyB9O1xuICAgICAgICAgICAgaWYgKGFjdGl2YXRlRmlyc3RJdGVtKSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBjaGlsZE1lbnVfMS5hY3RpdmF0ZUZpcnN0SXRlbSgpOyB9LCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBzdWJNZW51XzEgPSB0aGlzLnBhcmFtcy5zdWJNZW51O1xuICAgICAgICAgICAgdmFyIG1lbnVQYW5lbCA9IHRoaXMuY3JlYXRlQmVhbihuZXcgQWdNZW51UGFuZWwoc3ViTWVudV8xKSk7XG4gICAgICAgICAgICBtZW51UGFuZWwuc2V0UGFyZW50Q29tcG9uZW50KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHN1Yk1lbnVHdWlfMSA9IG1lbnVQYW5lbC5nZXRHdWkoKTtcbiAgICAgICAgICAgIHZhciBtb3VzZUV2ZW50XzEgPSAnbW91c2VlbnRlcic7XG4gICAgICAgICAgICB2YXIgbW91c2VFbnRlckxpc3RlbmVyXzEgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5jYW5jZWxEZWFjdGl2YXRlKCk7IH07XG4gICAgICAgICAgICBzdWJNZW51R3VpXzEuYWRkRXZlbnRMaXN0ZW5lcihtb3VzZUV2ZW50XzEsIG1vdXNlRW50ZXJMaXN0ZW5lcl8xKTtcbiAgICAgICAgICAgIGRlc3Ryb3lTdWJNZW51ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gc3ViTWVudUd1aV8xLnJlbW92ZUV2ZW50TGlzdGVuZXIobW91c2VFdmVudF8xLCBtb3VzZUVudGVyTGlzdGVuZXJfMSk7IH07XG4gICAgICAgICAgICBlUG9wdXAuYXBwZW5kQ2hpbGQoc3ViTWVudUd1aV8xKTtcbiAgICAgICAgICAgIGlmIChzdWJNZW51XzEuYWZ0ZXJHdWlBdHRhY2hlZCkge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gc3ViTWVudV8xLmFmdGVyR3VpQXR0YWNoZWQoKTsgfSwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVHdWkgPSB0aGlzLmdldEd1aSgpO1xuICAgICAgICB2YXIgcG9zaXRpb25DYWxsYmFjayA9IHRoaXMucG9wdXBTZXJ2aWNlLnBvc2l0aW9uUG9wdXBGb3JNZW51LmJpbmQodGhpcy5wb3B1cFNlcnZpY2UsIHsgZXZlbnRTb3VyY2U6IGVHdWksIGVQb3B1cDogZVBvcHVwIH0pO1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIGFkZFBvcHVwUmVzID0gdGhpcy5wb3B1cFNlcnZpY2UuYWRkUG9wdXAoe1xuICAgICAgICAgICAgbW9kYWw6IHRydWUsXG4gICAgICAgICAgICBlQ2hpbGQ6IGVQb3B1cCxcbiAgICAgICAgICAgIHBvc2l0aW9uQ2FsbGJhY2s6IHBvc2l0aW9uQ2FsbGJhY2ssXG4gICAgICAgICAgICBhbmNob3JUb0VsZW1lbnQ6IGVHdWksXG4gICAgICAgICAgICBhcmlhTGFiZWw6IHRyYW5zbGF0ZSgnYXJpYUxhYmVsU3ViTWVudScsICdTdWJNZW51JylcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc3ViTWVudUlzT3BlbiA9IHRydWU7XG4gICAgICAgIHNldEFyaWFFeHBhbmRlZChlR3VpLCB0cnVlKTtcbiAgICAgICAgdGhpcy5oaWRlU3ViTWVudSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChhZGRQb3B1cFJlcykge1xuICAgICAgICAgICAgICAgIGFkZFBvcHVwUmVzLmhpZGVGdW5jKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5zdWJNZW51SXNPcGVuID0gZmFsc2U7XG4gICAgICAgICAgICBzZXRBcmlhRXhwYW5kZWQoZUd1aSwgZmFsc2UpO1xuICAgICAgICAgICAgZGVzdHJveVN1Yk1lbnUoKTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmNsb3NlU3ViTWVudSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmhpZGVTdWJNZW51KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5oaWRlU3ViTWVudSgpO1xuICAgICAgICB0aGlzLmhpZGVTdWJNZW51ID0gbnVsbDtcbiAgICAgICAgc2V0QXJpYUV4cGFuZGVkKHRoaXMuZ2V0R3VpKCksIGZhbHNlKTtcbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmlzU3ViTWVudU9wZW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1Yk1lbnVJc09wZW47XG4gICAgfTtcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LnByb3RvdHlwZS5hY3RpdmF0ZSA9IGZ1bmN0aW9uIChvcGVuU3ViTWVudSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNhbmNlbEFjdGl2YXRlKCk7XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXNBY3RpdmUgPSB0cnVlO1xuICAgICAgICB0aGlzLmFkZENzc0NsYXNzKHRoaXMuZ2V0Q2xhc3NOYW1lKCdhY3RpdmUnKSk7XG4gICAgICAgIHRoaXMuZ2V0R3VpKCkuZm9jdXMoKTtcbiAgICAgICAgaWYgKG9wZW5TdWJNZW51ICYmIHRoaXMucGFyYW1zLnN1Yk1lbnUpIHtcbiAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaXNBbGl2ZSgpICYmIF90aGlzLmlzQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLm9wZW5TdWJNZW51KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgMzAwKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uSXRlbUFjdGl2YXRlZCgpO1xuICAgIH07XG4gICAgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUuZGVhY3RpdmF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYW5jZWxEZWFjdGl2YXRlKCk7XG4gICAgICAgIHRoaXMucmVtb3ZlQ3NzQ2xhc3ModGhpcy5nZXRDbGFzc05hbWUoJ2FjdGl2ZScpKTtcbiAgICAgICAgdGhpcy5pc0FjdGl2ZSA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5zdWJNZW51SXNPcGVuKSB7XG4gICAgICAgICAgICB0aGlzLmhpZGVTdWJNZW51KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmFkZEljb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5wYXJhbXMuY2hlY2tlZCAmJiAhdGhpcy5wYXJhbXMuaWNvbiAmJiB0aGlzLnBhcmFtcy5pc0NvbXBhY3QpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaWNvbiA9IGxvYWRUZW1wbGF0ZSgvKiBodG1sICovIFwiPHNwYW4gcmVmPVxcXCJlSWNvblxcXCIgY2xhc3M9XFxcIlwiICsgdGhpcy5nZXRDbGFzc05hbWUoJ3BhcnQnKSArIFwiIFwiICsgdGhpcy5nZXRDbGFzc05hbWUoJ2ljb24nKSArIFwiXFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPjwvc3Bhbj5cIik7XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5jaGVja2VkKSB7XG4gICAgICAgICAgICBpY29uLmFwcGVuZENoaWxkKGNyZWF0ZUljb25Ob1NwYW4oJ2NoZWNrJywgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnBhcmFtcy5pY29uKSB7XG4gICAgICAgICAgICBpZiAoaXNOb2RlT3JFbGVtZW50KHRoaXMucGFyYW1zLmljb24pKSB7XG4gICAgICAgICAgICAgICAgaWNvbi5hcHBlbmRDaGlsZCh0aGlzLnBhcmFtcy5pY29uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiB0aGlzLnBhcmFtcy5pY29uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGljb24uaW5uZXJIVE1MID0gdGhpcy5wYXJhbXMuaWNvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogbWVudSBpdGVtIGljb24gbXVzdCBiZSBET00gbm9kZSBvciBzdHJpbmcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKGljb24pO1xuICAgIH07XG4gICAgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUuYWRkTmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnBhcmFtcy5uYW1lICYmIHRoaXMucGFyYW1zLmlzQ29tcGFjdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuYW1lID0gbG9hZFRlbXBsYXRlKC8qIGh0bWwgKi8gXCI8c3BhbiByZWY9XFxcImVOYW1lXFxcIiBjbGFzcz1cXFwiXCIgKyB0aGlzLmdldENsYXNzTmFtZSgncGFydCcpICsgXCIgXCIgKyB0aGlzLmdldENsYXNzTmFtZSgndGV4dCcpICsgXCJcXFwiPlwiICsgKHRoaXMucGFyYW1zLm5hbWUgfHwgJycpICsgXCI8L3NwYW4+XCIpO1xuICAgICAgICB0aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKG5hbWUpO1xuICAgIH07XG4gICAgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUuYWRkVG9vbHRpcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnBhcmFtcy50b29sdGlwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50b29sdGlwID0gdGhpcy5wYXJhbXMudG9vbHRpcDtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlQnJvd3NlclRvb2x0aXBzKCkpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0R3VpKCkuc2V0QXR0cmlidXRlKCd0aXRsZScsIHRoaXMudG9vbHRpcCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBDdXN0b21Ub29sdGlwRmVhdHVyZSh0aGlzKSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmdldFRvb2x0aXBQYXJhbXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogJ21lbnUnLFxuICAgICAgICAgICAgdmFsdWU6IHRoaXMudG9vbHRpcFxuICAgICAgICB9O1xuICAgIH07XG4gICAgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUuYWRkU2hvcnRjdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5wYXJhbXMuc2hvcnRjdXQgJiYgdGhpcy5wYXJhbXMuaXNDb21wYWN0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNob3J0Y3V0ID0gbG9hZFRlbXBsYXRlKC8qIGh0bWwgKi8gXCI8c3BhbiByZWY9XFxcImVTaG9ydGN1dFxcXCIgY2xhc3M9XFxcIlwiICsgdGhpcy5nZXRDbGFzc05hbWUoJ3BhcnQnKSArIFwiIFwiICsgdGhpcy5nZXRDbGFzc05hbWUoJ3Nob3J0Y3V0JykgKyBcIlxcXCI+XCIgKyAodGhpcy5wYXJhbXMuc2hvcnRjdXQgfHwgJycpICsgXCI8L3NwYW4+XCIpO1xuICAgICAgICB0aGlzLmdldEd1aSgpLmFwcGVuZENoaWxkKHNob3J0Y3V0KTtcbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmFkZFN1Yk1lbnUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5wYXJhbXMuc3ViTWVudSAmJiB0aGlzLnBhcmFtcy5pc0NvbXBhY3QpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcG9pbnRlciA9IGxvYWRUZW1wbGF0ZSgvKiBodG1sICovIFwiPHNwYW4gcmVmPVxcXCJlUG9wdXBQb2ludGVyXFxcIiBjbGFzcz1cXFwiXCIgKyB0aGlzLmdldENsYXNzTmFtZSgncGFydCcpICsgXCIgXCIgKyB0aGlzLmdldENsYXNzTmFtZSgncG9wdXAtcG9pbnRlcicpICsgXCJcXFwiPjwvc3Bhbj5cIik7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgaWYgKHRoaXMucGFyYW1zLnN1Yk1lbnUpIHtcbiAgICAgICAgICAgIHZhciBpY29uTmFtZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkgPyAnc21hbGxMZWZ0JyA6ICdzbWFsbFJpZ2h0JztcbiAgICAgICAgICAgIHNldEFyaWFFeHBhbmRlZChlR3VpLCBmYWxzZSk7XG4gICAgICAgICAgICBwb2ludGVyLmFwcGVuZENoaWxkKGNyZWF0ZUljb25Ob1NwYW4oaWNvbk5hbWUsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyKSk7XG4gICAgICAgIH1cbiAgICAgICAgZUd1aS5hcHBlbmRDaGlsZChwb2ludGVyKTtcbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLm9uSXRlbVNlbGVjdGVkID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5hY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMucGFyYW1zLmFjdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vcGVuU3ViTWVudShldmVudCAmJiBldmVudC50eXBlID09PSAna2V5ZG93bicpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhcmFtcy5zdWJNZW51ICYmICF0aGlzLnBhcmFtcy5hY3Rpb24pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZSA9IHtcbiAgICAgICAgICAgIHR5cGU6IEFnTWVudUl0ZW1Db21wb25lbnQuRVZFTlRfTUVOVV9JVEVNX1NFTEVDVEVELFxuICAgICAgICAgICAgYWN0aW9uOiB0aGlzLnBhcmFtcy5hY3Rpb24sXG4gICAgICAgICAgICBjaGVja2VkOiB0aGlzLnBhcmFtcy5jaGVja2VkLFxuICAgICAgICAgICAgY3NzQ2xhc3NlczogdGhpcy5wYXJhbXMuY3NzQ2xhc3NlcyxcbiAgICAgICAgICAgIGRpc2FibGVkOiB0aGlzLnBhcmFtcy5kaXNhYmxlZCxcbiAgICAgICAgICAgIGljb246IHRoaXMucGFyYW1zLmljb24sXG4gICAgICAgICAgICBuYW1lOiB0aGlzLnBhcmFtcy5uYW1lLFxuICAgICAgICAgICAgc2hvcnRjdXQ6IHRoaXMucGFyYW1zLnNob3J0Y3V0LFxuICAgICAgICAgICAgc3ViTWVudTogdGhpcy5wYXJhbXMuc3ViTWVudSxcbiAgICAgICAgICAgIHRvb2x0aXA6IHRoaXMucGFyYW1zLnRvb2x0aXAsXG4gICAgICAgICAgICBldmVudDogZXZlbnRcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KGUpO1xuICAgIH07XG4gICAgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUub25JdGVtQWN0aXZhdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBBZ01lbnVJdGVtQ29tcG9uZW50LkVWRU5UX01FTlVfSVRFTV9BQ1RJVkFURUQsXG4gICAgICAgICAgICBtZW51SXRlbTogdGhpcyxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQucHJvdG90eXBlLmNhbmNlbEFjdGl2YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5hY3RpdmF0ZVRpbWVvdXRJZCkge1xuICAgICAgICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aGlzLmFjdGl2YXRlVGltZW91dElkKTtcbiAgICAgICAgICAgIHRoaXMuYWN0aXZhdGVUaW1lb3V0SWQgPSAwO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LnByb3RvdHlwZS5jYW5jZWxEZWFjdGl2YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5kZWFjdGl2YXRlVGltZW91dElkKSB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMuZGVhY3RpdmF0ZVRpbWVvdXRJZCk7XG4gICAgICAgICAgICB0aGlzLmRlYWN0aXZhdGVUaW1lb3V0SWQgPSAwO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LnByb3RvdHlwZS5vbk1vdXNlRW50ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuY2FuY2VsRGVhY3RpdmF0ZSgpO1xuICAgICAgICBpZiAodGhpcy5wYXJhbXMuaXNBbm90aGVyU3ViTWVudU9wZW4oKSkge1xuICAgICAgICAgICAgLy8gd2FpdCB0byBzZWUgaWYgdGhlIHVzZXIgZW50ZXJzIHRoZSBvcGVuIHN1Yi1tZW51XG4gICAgICAgICAgICB0aGlzLmFjdGl2YXRlVGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuYWN0aXZhdGUodHJ1ZSk7IH0sIEFnTWVudUl0ZW1Db21wb25lbnQuQUNUSVZBVElPTl9ERUxBWSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBhY3RpdmF0ZSBpbW1lZGlhdGVseVxuICAgICAgICAgICAgdGhpcy5hY3RpdmF0ZSh0cnVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUub25Nb3VzZUxlYXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmNhbmNlbEFjdGl2YXRlKCk7XG4gICAgICAgIGlmICh0aGlzLmlzU3ViTWVudU9wZW4oKSkge1xuICAgICAgICAgICAgLy8gd2FpdCB0byBzZWUgaWYgdGhlIHVzZXIgZW50ZXJzIHRoZSBzdWItbWVudVxuICAgICAgICAgICAgdGhpcy5kZWFjdGl2YXRlVGltZW91dElkID0gd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZGVhY3RpdmF0ZSgpOyB9LCBBZ01lbnVJdGVtQ29tcG9uZW50LkFDVElWQVRJT05fREVMQVkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gZGUtYWN0aXZhdGUgaW1tZWRpYXRlbHlcbiAgICAgICAgICAgIHRoaXMuZGVhY3RpdmF0ZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LnByb3RvdHlwZS5nZXRDbGFzc05hbWUgPSBmdW5jdGlvbiAoc3VmZml4KSB7XG4gICAgICAgIHZhciBwcmVmaXggPSB0aGlzLnBhcmFtcy5pc0NvbXBhY3QgPyAnYWctY29tcGFjdC1tZW51LW9wdGlvbicgOiAnYWctbWVudS1vcHRpb24nO1xuICAgICAgICByZXR1cm4gc3VmZml4ID8gcHJlZml4ICsgXCItXCIgKyBzdWZmaXggOiBwcmVmaXg7XG4gICAgfTtcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LkVWRU5UX01FTlVfSVRFTV9TRUxFQ1RFRCA9ICdtZW51SXRlbVNlbGVjdGVkJztcbiAgICBBZ01lbnVJdGVtQ29tcG9uZW50LkVWRU5UX01FTlVfSVRFTV9BQ1RJVkFURUQgPSAnbWVudUl0ZW1BY3RpdmF0ZWQnO1xuICAgIEFnTWVudUl0ZW1Db21wb25lbnQuQUNUSVZBVElPTl9ERUxBWSA9IDgwO1xuICAgIF9fZGVjb3JhdGUkUShbXG4gICAgICAgIEF1dG93aXJlZCgncG9wdXBTZXJ2aWNlJylcbiAgICBdLCBBZ01lbnVJdGVtQ29tcG9uZW50LnByb3RvdHlwZSwgXCJwb3B1cFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFEoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgQWdNZW51SXRlbUNvbXBvbmVudC5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICByZXR1cm4gQWdNZW51SXRlbUNvbXBvbmVudDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkTiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkUCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcmVhZCQ3ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIF9fc3ByZWFkJDYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3NwcmVhZCkgfHwgZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhciA9IGFyLmNvbmNhdChfX3JlYWQkNyhhcmd1bWVudHNbaV0pKTtcbiAgICByZXR1cm4gYXI7XG59O1xudmFyIEZvY3VzU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkTihGb2N1c1NlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRm9jdXNTZXJ2aWNlKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIEZvY3VzU2VydmljZV8xID0gRm9jdXNTZXJ2aWNlO1xuICAgIC8qKlxuICAgICAqIEFkZHMgYSBncmlkQ29yZSB0byB0aGUgbGlzdCBvZiB0aGUgZ3JpZENvcmVzIG1vbml0b3JpbmcgS2V5Ym9hcmQgTW9kZVxuICAgICAqIGluIGEgc3BlY2lmaWMgSFRNTERvY3VtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIGRvYyB7RG9jdW1lbnR9IC0gVGhlIERvY3VtZW50IGNvbnRhaW5pbmcgdGhlIGdyaWRDb3JlLlxuICAgICAqIEBwYXJhbSBncmlkQ29yZSB7R3JpZENvbXB9IC0gVGhlIEdyaWRDb3JlIHRvIGJlIG1vbml0b3JlZC5cbiAgICAgKi9cbiAgICBGb2N1c1NlcnZpY2UuYWRkS2V5Ym9hcmRNb2RlRXZlbnRzID0gZnVuY3Rpb24gKGRvYywgY29udHJvbGxlcikge1xuICAgICAgICB2YXIgZG9jQ29udHJvbGxlcnMgPSBGb2N1c1NlcnZpY2VfMS5pbnN0YW5jZXNNb25pdG9yZWQuZ2V0KGRvYyk7XG4gICAgICAgIGlmIChkb2NDb250cm9sbGVycyAmJiBkb2NDb250cm9sbGVycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZiAoZG9jQ29udHJvbGxlcnMuaW5kZXhPZihjb250cm9sbGVyKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBkb2NDb250cm9sbGVycy5wdXNoKGNvbnRyb2xsZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgRm9jdXNTZXJ2aWNlXzEuaW5zdGFuY2VzTW9uaXRvcmVkLnNldChkb2MsIFtjb250cm9sbGVyXSk7XG4gICAgICAgICAgICBkb2MuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIEZvY3VzU2VydmljZV8xLnRvZ2dsZUtleWJvYXJkTW9kZSk7XG4gICAgICAgICAgICBkb2MuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgRm9jdXNTZXJ2aWNlXzEudG9nZ2xlS2V5Ym9hcmRNb2RlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGdyaWRDb3JlIGZyb20gdGhlIGxpc3Qgb2YgdGhlIGdyaWRDb3JlcyBtb25pdG9yaW5nIEtleWJvYXJkIE1vZGVcbiAgICAgKiBpbiBhIHNwZWNpZmljIEhUTUxEb2N1bWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBkb2Mge0RvY3VtZW50fSAtIFRoZSBEb2N1bWVudCBjb250YWluaW5nIHRoZSBncmlkQ29yZS5cbiAgICAgKiBAcGFyYW0gZ3JpZENvcmUge0dyaWRDb21wfSAtIFRoZSBHcmlkQ29yZSB0byBiZSByZW1vdmVkLlxuICAgICAqL1xuICAgIEZvY3VzU2VydmljZS5yZW1vdmVLZXlib2FyZE1vZGVFdmVudHMgPSBmdW5jdGlvbiAoZG9jLCBjb250cm9sbGVyKSB7XG4gICAgICAgIHZhciBkb2NDb250cm9sbGVycyA9IEZvY3VzU2VydmljZV8xLmluc3RhbmNlc01vbml0b3JlZC5nZXQoZG9jKTtcbiAgICAgICAgdmFyIG5ld0NvbnRyb2xsZXJzID0gW107XG4gICAgICAgIGlmIChkb2NDb250cm9sbGVycyAmJiBkb2NDb250cm9sbGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIG5ld0NvbnRyb2xsZXJzID0gX19zcHJlYWQkNihkb2NDb250cm9sbGVycykuZmlsdGVyKGZ1bmN0aW9uIChjdXJyZW50R3JpZENvcmUpIHsgcmV0dXJuIGN1cnJlbnRHcmlkQ29yZSAhPT0gY29udHJvbGxlcjsgfSk7XG4gICAgICAgICAgICBGb2N1c1NlcnZpY2VfMS5pbnN0YW5jZXNNb25pdG9yZWQuc2V0KGRvYywgbmV3Q29udHJvbGxlcnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdDb250cm9sbGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgRm9jdXNTZXJ2aWNlXzEudG9nZ2xlS2V5Ym9hcmRNb2RlKTtcbiAgICAgICAgICAgIGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBGb2N1c1NlcnZpY2VfMS50b2dnbGVLZXlib2FyZE1vZGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCBieSBga2V5ZG93bmAgYW5kIGBtb3VzZWRvd25gIGV2ZW50cyBvbiBhbGwgRG9jdW1lbnRzIG1vbml0b3JpbmdcbiAgICAgKiBLZXlib2FyZE1vZGUuIEl0IHdpbGwgdGhlbiBmaXJlIGEgS0VZQk9BUkRfRk9DVVMsIE1PVVNFX0ZPQ1VTIG9uIGVhY2ggZ3JpZENvcmUgcHJlc2VudCBpblxuICAgICAqIHRoZSBEb2N1bWVudCBhbGxvd2luZyBlYWNoIGdyaWRDb3JlIHRvIG1haW50YWluIGEgc3RhdGUgZm9yIEtleWJvYXJkTW9kZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBldmVudCB7S2V5Ym9hcmRFdmVudCB8IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50fSAtIFRoZSBldmVudCB0cmlnZ2VyZWQuXG4gICAgICovXG4gICAgRm9jdXNTZXJ2aWNlLnRvZ2dsZUtleWJvYXJkTW9kZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgaXNLZXlib2FyZEFjdGl2ZSA9IEZvY3VzU2VydmljZV8xLmtleWJvYXJkTW9kZUFjdGl2ZTtcbiAgICAgICAgdmFyIGlzS2V5Ym9hcmRFdmVudCA9IGV2ZW50LnR5cGUgPT09ICdrZXlkb3duJztcbiAgICAgICAgaWYgKGlzS2V5Ym9hcmRFdmVudCkge1xuICAgICAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBrZXlzIHNob3VsZCBub3QgdG9nZ2xlIGtleWJvYXJkIG1vZGUuXG4gICAgICAgICAgICBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5IHx8IGV2ZW50LmFsdEtleSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNLZXlib2FyZEFjdGl2ZSAmJiBpc0tleWJvYXJkRXZlbnQgfHwgIWlzS2V5Ym9hcmRBY3RpdmUgJiYgIWlzS2V5Ym9hcmRFdmVudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIEZvY3VzU2VydmljZV8xLmtleWJvYXJkTW9kZUFjdGl2ZSA9IGlzS2V5Ym9hcmRFdmVudDtcbiAgICAgICAgdmFyIGRvYyA9IGV2ZW50LnRhcmdldC5vd25lckRvY3VtZW50O1xuICAgICAgICBpZiAoIWRvYykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb250cm9sbGVyc0ZvckRvYyA9IEZvY3VzU2VydmljZV8xLmluc3RhbmNlc01vbml0b3JlZC5nZXQoZG9jKTtcbiAgICAgICAgaWYgKGNvbnRyb2xsZXJzRm9yRG9jKSB7XG4gICAgICAgICAgICBjb250cm9sbGVyc0ZvckRvYy5mb3JFYWNoKGZ1bmN0aW9uIChjb250cm9sbGVyKSB7XG4gICAgICAgICAgICAgICAgY29udHJvbGxlci5kaXNwYXRjaEV2ZW50KHsgdHlwZTogaXNLZXlib2FyZEV2ZW50ID8gRXZlbnRzLkVWRU5UX0tFWUJPQVJEX0ZPQ1VTIDogRXZlbnRzLkVWRU5UX01PVVNFX0ZPQ1VTIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGNsZWFyRm9jdXNlZENlbGxMaXN0ZW5lciA9IHRoaXMuY2xlYXJGb2N1c2VkQ2VsbC5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9NT0RFX0NIQU5HRUQsIGNsZWFyRm9jdXNlZENlbGxMaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTkVXX0NPTFVNTlNfTE9BREVELCB0aGlzLm9uQ29sdW1uRXZlcnl0aGluZ0NoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX0dST1VQX09QRU5FRCwgY2xlYXJGb2N1c2VkQ2VsbExpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIGNsZWFyRm9jdXNlZENlbGxMaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuY3RybHNTZXJ2aWNlLndoZW5SZWFkeShmdW5jdGlvbiAocCkge1xuICAgICAgICAgICAgX3RoaXMuZ3JpZEN0cmwgPSBwLmdyaWRDdHJsO1xuICAgICAgICAgICAgdmFyIGRvYyA9IF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICAgICAgRm9jdXNTZXJ2aWNlXzEuYWRkS2V5Ym9hcmRNb2RlRXZlbnRzKGRvYywgX3RoaXMuZ3JpZEN0cmwpO1xuICAgICAgICAgICAgX3RoaXMuYWRkRGVzdHJveUZ1bmMoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudW5yZWdpc3RlckdyaWRDb21wQ29udHJvbGxlcihfdGhpcy5ncmlkQ3RybCk7IH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUudW5yZWdpc3RlckdyaWRDb21wQ29udHJvbGxlciA9IGZ1bmN0aW9uIChncmlkQ29tcENvbnRyb2xsZXIpIHtcbiAgICAgICAgdmFyIGRvYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIEZvY3VzU2VydmljZV8xLnJlbW92ZUtleWJvYXJkTW9kZUV2ZW50cyhkb2MsIGdyaWRDb21wQ29udHJvbGxlcik7XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLm9uQ29sdW1uRXZlcnl0aGluZ0NoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGlmIHRoZSBjb2x1bW5zIGNoYW5nZSwgY2hlY2sgYW5kIHNlZSBpZiB0aGlzIGNvbHVtbiBzdGlsbCBleGlzdHMuIGlmIGl0IGRvZXMsIHRoZW5cbiAgICAgICAgLy8gd2UgY2FuIGtlZXAgdGhlIGZvY3VzZWQgY2VsbC4gaWYgaXQgZG9lc24ndCwgdGhlbiB3ZSBuZWVkIHRvIGRyb3AgdGhlIGZvY3VzZWQgY2VsbC5cbiAgICAgICAgaWYgKCF0aGlzLmZvY3VzZWRDZWxsUG9zaXRpb24pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sID0gdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uLmNvbHVtbjtcbiAgICAgICAgdmFyIGNvbEZyb21Db2x1bW5Nb2RlbCA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JpZENvbHVtbihjb2wuZ2V0SWQoKSk7XG4gICAgICAgIGlmIChjb2wgIT09IGNvbEZyb21Db2x1bW5Nb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5jbGVhckZvY3VzZWRDZWxsKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuaXNLZXlib2FyZE1vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBGb2N1c1NlcnZpY2VfMS5rZXlib2FyZE1vZGVBY3RpdmU7XG4gICAgfTtcbiAgICAvLyB3ZSBjaGVjayBpZiB0aGUgYnJvd3NlciBpcyBmb2N1c2luZyBzb21ldGhpbmcsIGFuZCBpZiBpdCBpcywgYW5kXG4gICAgLy8gaXQncyB0aGUgY2VsbCB3ZSB0aGluayBpcyBmb2N1c2VkLCB0aGVuIHJldHVybiB0aGUgY2VsbC4gc28gdGhpc1xuICAgIC8vIG1ldGhvZHMgcmV0dXJucyB0aGUgY2VsbCBpZiBhKSB3ZSB0aGluayBpdCBoYXMgZm9jdXMgYW5kIGIpIHRoZVxuICAgIC8vIGJyb3dzZXIgdGhpbmtzIGl0IGhhcyBmb2N1cy4gdGhpcyB0aGVuIHJldHVybnMgbm90aGluZyBpZiB3ZVxuICAgIC8vIGZpcnN0IGZvY3VzIGEgY2VsbCwgdGhlbiBzZWNvbmQgY2xpY2sgb3V0c2lkZSB0aGUgZ3JpZCwgYXMgdGhlbiB0aGVcbiAgICAvLyBncmlkIGNlbGwgd2lsbCBzdGlsbCBiZSBmb2N1c2VkIGFzIGZhciBhcyB0aGUgZ3JpZCBpcyBjb25jZXJuZWQsXG4gICAgLy8gaG93ZXZlciB0aGUgYnJvd3NlciBmb2N1cyB3aWxsIGhhdmUgbW92ZWQgc29tZXdoZXJlIGVsc2UuXG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5nZXRGb2N1c0NlbGxUb1VzZUFmdGVyUmVmcmVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzRm9jdXNBZnRlclJlZnJlc2goKSB8fCAhdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvLyB3ZSBjaGVjayB0aGF0IHRoZSBicm93c2VyIGlzIGFjdHVhbGx5IGZvY3VzaW5nIG9uIHRoZSBncmlkLCBpZiBpdCBpcyBub3QsIHRoZW5cbiAgICAgICAgLy8gd2UgaGF2ZSBub3RoaW5nIHRvIHdvcnJ5IGFib3V0LiB3ZSBjaGVjayBmb3IgUk9XIGRhdGEsIGFzIHRoaXMgY292ZXJzIGJvdGggZm9jdXNlZCBSb3dzIChmb3IgRnVsbCBXaWR0aCBSb3dzKVxuICAgICAgICAvLyBhbmQgQ2VsbHMgKGNvdmVycyBjZWxscyBhcyBjZWxscyBsaXZlIGluIHJvd3MpXG4gICAgICAgIGlmICh0aGlzLmlzRG9tRGF0YU1pc3NpbmdJbkhpZXJhcmNoeShlRG9jdW1lbnQuYWN0aXZlRWxlbWVudCwgUm93Q3RybC5ET01fREFUQV9LRVlfUk9XX0NUUkwpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5nZXRGb2N1c0hlYWRlclRvVXNlQWZ0ZXJSZWZyZXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NGb2N1c0FmdGVyUmVmcmVzaCgpIHx8ICF0aGlzLmZvY3VzZWRIZWFkZXJQb3NpdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2UgY2hlY2sgdGhhdCB0aGUgYnJvd3NlciBpcyBhY3R1YWxseSBmb2N1c2luZyBvbiB0aGUgZ3JpZCwgaWYgaXQgaXMgbm90LCB0aGVuXG4gICAgICAgIC8vIHdlIGhhdmUgbm90aGluZyB0byB3b3JyeSBhYm91dFxuICAgICAgICBpZiAodGhpcy5pc0RvbURhdGFNaXNzaW5nSW5IaWVyYXJjaHkoZURvY3VtZW50LmFjdGl2ZUVsZW1lbnQsIEFic3RyYWN0SGVhZGVyQ2VsbEN0cmwuRE9NX0RBVEFfS0VZX0hFQURFUl9DVFJMKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9jdXNlZEhlYWRlclBvc2l0aW9uO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5pc0RvbURhdGFNaXNzaW5nSW5IaWVyYXJjaHkgPSBmdW5jdGlvbiAoZUJyb3dzZXJDZWxsLCBrZXkpIHtcbiAgICAgICAgdmFyIGVQb2ludGVyID0gZUJyb3dzZXJDZWxsO1xuICAgICAgICB3aGlsZSAoZVBvaW50ZXIpIHtcbiAgICAgICAgICAgIHZhciBkYXRhID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tRGF0YShlUG9pbnRlciwga2V5KTtcbiAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZVBvaW50ZXIgPSBlUG9pbnRlci5wYXJlbnROb2RlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5jbGVhckZvY3VzZWRDZWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZvY3VzZWRDZWxsUG9zaXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLm9uQ2VsbEZvY3VzZWQoZmFsc2UsIGZhbHNlKTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuZ2V0Rm9jdXNlZENlbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvY3VzZWRDZWxsUG9zaXRpb247XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLnNldEZvY3VzZWRDZWxsID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgY29sdW1uID0gcGFyYW1zLmNvbHVtbiwgcm93SW5kZXggPSBwYXJhbXMucm93SW5kZXgsIHJvd1Bpbm5lZCA9IHBhcmFtcy5yb3dQaW5uZWQsIF9hID0gcGFyYW1zLmZvcmNlQnJvd3NlckZvY3VzLCBmb3JjZUJyb3dzZXJGb2N1cyA9IF9hID09PSB2b2lkIDAgPyBmYWxzZSA6IF9hLCBfYiA9IHBhcmFtcy5wcmV2ZW50U2Nyb2xsT25Ccm93c2VyRm9jdXMsIHByZXZlbnRTY3JvbGxPbkJyb3dzZXJGb2N1cyA9IF9iID09PSB2b2lkIDAgPyBmYWxzZSA6IF9iO1xuICAgICAgICB2YXIgZ3JpZENvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JpZENvbHVtbihjb2x1bW4pO1xuICAgICAgICAvLyBpZiBjb2x1bW4gZG9lc24ndCBleGlzdCwgdGhlbiBibGFuayB0aGUgZm9jdXNlZCBjZWxsIGFuZCByZXR1cm4uIHRoaXMgY2FuIGhhcHBlbiB3aGVuIHVzZXIgc2V0cyBuZXcgY29sdW1ucyxcbiAgICAgICAgLy8gYW5kIHRoZSBmb2N1c2VkIGNlbGwgaXMgaW4gYSBjb2x1bW4gdGhhdCBubyBsb25nZXIgZXhpc3RzLiBhZnRlciBjb2x1bW5zIGNoYW5nZSwgdGhlIGdyaWQgcmVmcmVzaGVzIGFuZCB0cmllc1xuICAgICAgICAvLyB0byByZS1mb2N1cyB0aGUgZm9jdXNlZCBjZWxsLlxuICAgICAgICBpZiAoIWdyaWRDb2x1bW4pIHtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNlZENlbGxQb3NpdGlvbiA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uID0gZ3JpZENvbHVtbiA/IHtcbiAgICAgICAgICAgIHJvd0luZGV4OiByb3dJbmRleCxcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogbWFrZU51bGwocm93UGlubmVkKSxcbiAgICAgICAgICAgIGNvbHVtbjogZ3JpZENvbHVtblxuICAgICAgICB9IDogbnVsbDtcbiAgICAgICAgdGhpcy5vbkNlbGxGb2N1c2VkKGZvcmNlQnJvd3NlckZvY3VzLCBwcmV2ZW50U2Nyb2xsT25Ccm93c2VyRm9jdXMpO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5pc0NlbGxGb2N1c2VkID0gZnVuY3Rpb24gKGNlbGxQb3NpdGlvbikge1xuICAgICAgICBpZiAodGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uLmNvbHVtbiA9PT0gY2VsbFBvc2l0aW9uLmNvbHVtbiAmJlxuICAgICAgICAgICAgdGhpcy5pc1Jvd0ZvY3VzZWQoY2VsbFBvc2l0aW9uLnJvd0luZGV4LCBjZWxsUG9zaXRpb24ucm93UGlubmVkKTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuaXNSb3dOb2RlRm9jdXNlZCA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzUm93Rm9jdXNlZChyb3dOb2RlLnJvd0luZGV4LCByb3dOb2RlLnJvd1Bpbm5lZCk7XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLmlzSGVhZGVyV3JhcHBlckZvY3VzZWQgPSBmdW5jdGlvbiAoaGVhZGVyQ3RybCkge1xuICAgICAgICBpZiAodGhpcy5mb2N1c2VkSGVhZGVyUG9zaXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2x1bW4gPSBoZWFkZXJDdHJsLmdldENvbHVtbkdyb3VwQ2hpbGQoKTtcbiAgICAgICAgdmFyIGhlYWRlclJvd0luZGV4ID0gaGVhZGVyQ3RybC5nZXRSb3dJbmRleCgpO1xuICAgICAgICB2YXIgcGlubmVkID0gaGVhZGVyQ3RybC5nZXRQaW5uZWQoKTtcbiAgICAgICAgdmFyIF9hID0gdGhpcy5mb2N1c2VkSGVhZGVyUG9zaXRpb24sIGZvY3VzZWRDb2x1bW4gPSBfYS5jb2x1bW4sIGZvY3VzZWRIZWFkZXJSb3dJbmRleCA9IF9hLmhlYWRlclJvd0luZGV4O1xuICAgICAgICByZXR1cm4gY29sdW1uID09PSBmb2N1c2VkQ29sdW1uICYmXG4gICAgICAgICAgICBoZWFkZXJSb3dJbmRleCA9PT0gZm9jdXNlZEhlYWRlclJvd0luZGV4ICYmXG4gICAgICAgICAgICBwaW5uZWQgPT0gZm9jdXNlZENvbHVtbi5nZXRQaW5uZWQoKTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuY2xlYXJGb2N1c2VkSGVhZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZvY3VzZWRIZWFkZXJQb3NpdGlvbiA9IG51bGw7XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLmdldEZvY3VzZWRIZWFkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvY3VzZWRIZWFkZXJQb3NpdGlvbjtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuc2V0Rm9jdXNlZEhlYWRlciA9IGZ1bmN0aW9uIChoZWFkZXJSb3dJbmRleCwgY29sdW1uKSB7XG4gICAgICAgIHRoaXMuZm9jdXNlZEhlYWRlclBvc2l0aW9uID0geyBoZWFkZXJSb3dJbmRleDogaGVhZGVyUm93SW5kZXgsIGNvbHVtbjogY29sdW1uIH07XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLmZvY3VzSGVhZGVyUG9zaXRpb24gPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBkaXJlY3Rpb24gPSBwYXJhbXMuZGlyZWN0aW9uLCBmcm9tVGFiID0gcGFyYW1zLmZyb21UYWIsIGFsbG93VXNlck92ZXJyaWRlID0gcGFyYW1zLmFsbG93VXNlck92ZXJyaWRlLCBldmVudCA9IHBhcmFtcy5ldmVudDtcbiAgICAgICAgdmFyIGhlYWRlclBvc2l0aW9uID0gcGFyYW1zLmhlYWRlclBvc2l0aW9uO1xuICAgICAgICBpZiAoYWxsb3dVc2VyT3ZlcnJpZGUpIHtcbiAgICAgICAgICAgIHZhciBncmlkT3B0aW9uc1dyYXBwZXIgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlcjtcbiAgICAgICAgICAgIHZhciBjdXJyZW50UG9zaXRpb24gPSB0aGlzLmdldEZvY3VzZWRIZWFkZXIoKTtcbiAgICAgICAgICAgIHZhciBoZWFkZXJSb3dDb3VudCA9IHRoaXMuaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UuZ2V0SGVhZGVyUm93Q291bnQoKTtcbiAgICAgICAgICAgIGlmIChmcm9tVGFiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVzZXJGdW5jID0gZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFRhYlRvTmV4dEhlYWRlckZ1bmMoKTtcbiAgICAgICAgICAgICAgICBpZiAodXNlckZ1bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmFtc18xID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmFja3dhcmRzOiBkaXJlY3Rpb24gPT09ICdCZWZvcmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNIZWFkZXJQb3NpdGlvbjogY3VycmVudFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dEhlYWRlclBvc2l0aW9uOiBoZWFkZXJQb3NpdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlclJvd0NvdW50OiBoZWFkZXJSb3dDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyUG9zaXRpb24gPSB1c2VyRnVuYyhwYXJhbXNfMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHVzZXJGdW5jID0gZ3JpZE9wdGlvbnNXcmFwcGVyLmdldE5hdmlnYXRlVG9OZXh0SGVhZGVyRnVuYygpO1xuICAgICAgICAgICAgICAgIGlmICh1c2VyRnVuYyAmJiBldmVudCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyYW1zXzIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk6IGV2ZW50LmtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzSGVhZGVyUG9zaXRpb246IGN1cnJlbnRQb3NpdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRIZWFkZXJQb3NpdGlvbjogaGVhZGVyUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJSb3dDb3VudDogaGVhZGVyUm93Q291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudDogZXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlclBvc2l0aW9uID0gdXNlckZ1bmMocGFyYW1zXzIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWhlYWRlclBvc2l0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhlYWRlclBvc2l0aW9uLmhlYWRlclJvd0luZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9jdXNHcmlkVmlldyhoZWFkZXJQb3NpdGlvbi5jb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGVhZGVyTmF2aWdhdGlvblNlcnZpY2Uuc2Nyb2xsVG9Db2x1bW4oaGVhZGVyUG9zaXRpb24uY29sdW1uLCBkaXJlY3Rpb24pO1xuICAgICAgICB2YXIgaGVhZGVyUm93Q29udGFpbmVyQ3RybCA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEhlYWRlclJvd0NvbnRhaW5lckN0cmwoaGVhZGVyUG9zaXRpb24uY29sdW1uLmdldFBpbm5lZCgpKTtcbiAgICAgICAgLy8gdGhpcyB3aWxsIGF1dG9tYXRpY2FsbHkgY2FsbCB0aGUgc2V0Rm9jdXNlZEhlYWRlciBtZXRob2QgYWJvdmVcbiAgICAgICAgdmFyIGZvY3VzU3VjY2VzcyA9IGhlYWRlclJvd0NvbnRhaW5lckN0cmwuZm9jdXNIZWFkZXIoaGVhZGVyUG9zaXRpb24uaGVhZGVyUm93SW5kZXgsIGhlYWRlclBvc2l0aW9uLmNvbHVtbiwgZXZlbnQpO1xuICAgICAgICByZXR1cm4gZm9jdXNTdWNjZXNzO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5mb2N1c0ZpcnN0SGVhZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmlyc3RDb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldEFsbERpc3BsYXllZENvbHVtbnMoKVswXTtcbiAgICAgICAgaWYgKCFmaXJzdENvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaXJzdENvbHVtbi5nZXRQYXJlbnQoKSkge1xuICAgICAgICAgICAgZmlyc3RDb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldENvbHVtbkdyb3VwQXRMZXZlbChmaXJzdENvbHVtbiwgMCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9jdXNIZWFkZXJQb3NpdGlvbih7XG4gICAgICAgICAgICBoZWFkZXJQb3NpdGlvbjogeyBoZWFkZXJSb3dJbmRleDogMCwgY29sdW1uOiBmaXJzdENvbHVtbiB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5mb2N1c0xhc3RIZWFkZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGhlYWRlclJvd0luZGV4ID0gdGhpcy5oZWFkZXJOYXZpZ2F0aW9uU2VydmljZS5nZXRIZWFkZXJSb3dDb3VudCgpIC0gMTtcbiAgICAgICAgdmFyIGNvbHVtbiA9IGxhc3QodGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c0hlYWRlclBvc2l0aW9uKHtcbiAgICAgICAgICAgIGhlYWRlclBvc2l0aW9uOiB7IGhlYWRlclJvd0luZGV4OiBoZWFkZXJSb3dJbmRleCwgY29sdW1uOiBjb2x1bW4gfSxcbiAgICAgICAgICAgIGV2ZW50OiBldmVudFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuaXNBbnlDZWxsRm9jdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5pc1Jvd0ZvY3VzZWQgPSBmdW5jdGlvbiAocm93SW5kZXgsIGZsb2F0aW5nKSB7XG4gICAgICAgIGlmICh0aGlzLmZvY3VzZWRDZWxsUG9zaXRpb24gPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmZvY3VzZWRDZWxsUG9zaXRpb24ucm93SW5kZXggPT09IHJvd0luZGV4ICYmIHRoaXMuZm9jdXNlZENlbGxQb3NpdGlvbi5yb3dQaW5uZWQgPT09IG1ha2VOdWxsKGZsb2F0aW5nKTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuZmluZEZvY3VzYWJsZUVsZW1lbnRzID0gZnVuY3Rpb24gKHJvb3ROb2RlLCBleGNsdWRlLCBvbmx5VW5tYW5hZ2VkKSB7XG4gICAgICAgIGlmIChvbmx5VW5tYW5hZ2VkID09PSB2b2lkIDApIHsgb25seVVubWFuYWdlZCA9IGZhbHNlOyB9XG4gICAgICAgIHZhciBmb2N1c2FibGVTdHJpbmcgPSBDb25zdGFudHMuRk9DVVNBQkxFX1NFTEVDVE9SO1xuICAgICAgICB2YXIgZXhjbHVkZVN0cmluZyA9IENvbnN0YW50cy5GT0NVU0FCTEVfRVhDTFVERTtcbiAgICAgICAgaWYgKGV4Y2x1ZGUpIHtcbiAgICAgICAgICAgIGV4Y2x1ZGVTdHJpbmcgKz0gJywgJyArIGV4Y2x1ZGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9ubHlVbm1hbmFnZWQpIHtcbiAgICAgICAgICAgIGV4Y2x1ZGVTdHJpbmcgKz0gJywgW3RhYmluZGV4PVwiLTFcIl0nO1xuICAgICAgICB9XG4gICAgICAgIHZhciBub2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5hcHBseShyb290Tm9kZS5xdWVyeVNlbGVjdG9yQWxsKGZvY3VzYWJsZVN0cmluZykpO1xuICAgICAgICB2YXIgZXhjbHVkZU5vZGVzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KHJvb3ROb2RlLnF1ZXJ5U2VsZWN0b3JBbGwoZXhjbHVkZVN0cmluZykpO1xuICAgICAgICBpZiAoIWV4Y2x1ZGVOb2Rlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGlmZiA9IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLmZpbHRlcihmdW5jdGlvbiAoZWxlbWVudCkgeyByZXR1cm4gYi5pbmRleE9mKGVsZW1lbnQpID09PSAtMTsgfSk7IH07XG4gICAgICAgIHJldHVybiBkaWZmKG5vZGVzLCBleGNsdWRlTm9kZXMpO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5mb2N1c0ludG8gPSBmdW5jdGlvbiAocm9vdE5vZGUsIHVwLCBvbmx5VW5tYW5hZ2VkKSB7XG4gICAgICAgIGlmICh1cCA9PT0gdm9pZCAwKSB7IHVwID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKG9ubHlVbm1hbmFnZWQgPT09IHZvaWQgMCkgeyBvbmx5VW5tYW5hZ2VkID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIGZvY3VzYWJsZUVsZW1lbnRzID0gdGhpcy5maW5kRm9jdXNhYmxlRWxlbWVudHMocm9vdE5vZGUsIG51bGwsIG9ubHlVbm1hbmFnZWQpO1xuICAgICAgICB2YXIgdG9Gb2N1cyA9IHVwID8gbGFzdChmb2N1c2FibGVFbGVtZW50cykgOiBmb2N1c2FibGVFbGVtZW50c1swXTtcbiAgICAgICAgaWYgKHRvRm9jdXMpIHtcbiAgICAgICAgICAgIHRvRm9jdXMuZm9jdXMoKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEZvY3VzU2VydmljZS5wcm90b3R5cGUuZmluZE5leHRGb2N1c2FibGVFbGVtZW50ID0gZnVuY3Rpb24gKHJvb3ROb2RlLCBvbmx5TWFuYWdlZCwgYmFja3dhcmRzKSB7XG4gICAgICAgIGlmIChyb290Tm9kZSA9PT0gdm9pZCAwKSB7IHJvb3ROb2RlID0gdGhpcy5lR3JpZERpdjsgfVxuICAgICAgICB2YXIgZm9jdXNhYmxlID0gdGhpcy5maW5kRm9jdXNhYmxlRWxlbWVudHMocm9vdE5vZGUsIG9ubHlNYW5hZ2VkID8gJzpub3QoW3RhYmluZGV4PVwiLTFcIl0pJyA6IG51bGwpO1xuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgdmFyIGFjdGl2ZUVsID0gZURvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG4gICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgIGlmIChvbmx5TWFuYWdlZCkge1xuICAgICAgICAgICAgY3VycmVudEluZGV4ID0gZm9jdXNhYmxlLmZpbmRJbmRleChmdW5jdGlvbiAoZWwpIHsgcmV0dXJuIGVsLmNvbnRhaW5zKGFjdGl2ZUVsKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjdXJyZW50SW5kZXggPSBmb2N1c2FibGUuaW5kZXhPZihhY3RpdmVFbCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5leHRJbmRleCA9IGN1cnJlbnRJbmRleCArIChiYWNrd2FyZHMgPyAtMSA6IDEpO1xuICAgICAgICBpZiAobmV4dEluZGV4IDwgMCB8fCBuZXh0SW5kZXggPj0gZm9jdXNhYmxlLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZvY3VzYWJsZVtuZXh0SW5kZXhdO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5pc0ZvY3VzVW5kZXJNYW5hZ2VkQ29tcG9uZW50ID0gZnVuY3Rpb24gKHJvb3ROb2RlKSB7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgbWFuYWdlZENvbnRhaW5lcnMgPSByb290Tm9kZS5xdWVyeVNlbGVjdG9yQWxsKFwiLlwiICsgTWFuYWdlZEZvY3VzRmVhdHVyZS5GT0NVU19NQU5BR0VEX0NMQVNTKTtcbiAgICAgICAgaWYgKCFtYW5hZ2VkQ29udGFpbmVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1hbmFnZWRDb250YWluZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAobWFuYWdlZENvbnRhaW5lcnNbaV0uY29udGFpbnMoZURvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5maW5kVGFiYmFibGVQYXJlbnQgPSBmdW5jdGlvbiAobm9kZSwgbGltaXQpIHtcbiAgICAgICAgaWYgKGxpbWl0ID09PSB2b2lkIDApIHsgbGltaXQgPSA1OyB9XG4gICAgICAgIHZhciBjb3VudGVyID0gMDtcbiAgICAgICAgd2hpbGUgKG5vZGUgJiYgZ2V0VGFiSW5kZXgobm9kZSkgPT09IG51bGwgJiYgKytjb3VudGVyIDw9IGxpbWl0KSB7XG4gICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIGlmIChnZXRUYWJJbmRleChub2RlKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLm9uQ2VsbEZvY3VzZWQgPSBmdW5jdGlvbiAoZm9yY2VCcm93c2VyRm9jdXMsIHByZXZlbnRTY3JvbGxPbkJyb3dzZXJGb2N1cykge1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfQ0VMTF9GT0NVU0VELFxuICAgICAgICAgICAgZm9yY2VCcm93c2VyRm9jdXM6IGZvcmNlQnJvd3NlckZvY3VzLFxuICAgICAgICAgICAgcHJldmVudFNjcm9sbE9uQnJvd3NlckZvY3VzOiBwcmV2ZW50U2Nyb2xsT25Ccm93c2VyRm9jdXMsXG4gICAgICAgICAgICByb3dJbmRleDogbnVsbCxcbiAgICAgICAgICAgIGNvbHVtbjogbnVsbCxcbiAgICAgICAgICAgIGZsb2F0aW5nOiBudWxsLFxuICAgICAgICAgICAgcm93UGlubmVkOiBudWxsLFxuICAgICAgICAgICAgaXNGdWxsV2lkdGhDZWxsOiBmYWxzZVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uKSB7XG4gICAgICAgICAgICB2YXIgcm93SW5kZXggPSBldmVudC5yb3dJbmRleCA9IHRoaXMuZm9jdXNlZENlbGxQb3NpdGlvbi5yb3dJbmRleDtcbiAgICAgICAgICAgIHZhciByb3dQaW5uZWQgPSBldmVudC5yb3dQaW5uZWQgPSB0aGlzLmZvY3VzZWRDZWxsUG9zaXRpb24ucm93UGlubmVkO1xuICAgICAgICAgICAgZXZlbnQuY29sdW1uID0gdGhpcy5mb2N1c2VkQ2VsbFBvc2l0aW9uLmNvbHVtbjtcbiAgICAgICAgICAgIHZhciByb3dDdHJsID0gdGhpcy5yb3dSZW5kZXJlci5nZXRSb3dCeVBvc2l0aW9uKHsgcm93SW5kZXg6IHJvd0luZGV4LCByb3dQaW5uZWQ6IHJvd1Bpbm5lZCB9KTtcbiAgICAgICAgICAgIGlmIChyb3dDdHJsKSB7XG4gICAgICAgICAgICAgICAgZXZlbnQuaXNGdWxsV2lkdGhDZWxsID0gcm93Q3RybC5pc0Z1bGxXaWR0aCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZS5mb2N1c0dyaWRWaWV3ID0gZnVuY3Rpb24gKGNvbHVtbiwgYmFja3dhcmRzKSB7XG4gICAgICAgIC8vIGlmIHN1cHByZXNzQ2VsbEZvY3VzIGlzIGB0cnVlYCwgaXQgbWVhbnMgdGhlIHVzZXIgZG9lcyBub3Qgd2FudCB0b1xuICAgICAgICAvLyBuYXZpZ2F0ZSBiZXR3ZWVuIHRoZSBjZWxscyB1c2luZyB0YWIuIEluc3RlYWQsIHdlIHB1dCBmb2N1cyBvbiBlaXRoZXJcbiAgICAgICAgLy8gdGhlIGhlYWRlciBvciBhZnRlciB0aGUgZ3JpZCwgZGVwZW5kaW5nIG9uIHdoZXRoZXIgdGFiIG9yIHNoaWZ0LXRhYiB3YXMgcHJlc3NlZC5cbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NDZWxsRm9jdXMoKSkge1xuICAgICAgICAgICAgaWYgKGJhY2t3YXJkcykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZvY3VzTGFzdEhlYWRlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9jdXNOZXh0R3JpZENvcmVDb250YWluZXIoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXh0Um93ID0gYmFja3dhcmRzXG4gICAgICAgICAgICA/IHRoaXMucm93UG9zaXRpb25VdGlscy5nZXRMYXN0Um93KClcbiAgICAgICAgICAgIDogdGhpcy5yb3dQb3NpdGlvblV0aWxzLmdldEZpcnN0Um93KCk7XG4gICAgICAgIGlmICghbmV4dFJvdykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dJbmRleCA9IG5leHRSb3cucm93SW5kZXgsIHJvd1Bpbm5lZCA9IG5leHRSb3cucm93UGlubmVkO1xuICAgICAgICB2YXIgZm9jdXNlZEhlYWRlciA9IHRoaXMuZ2V0Rm9jdXNlZEhlYWRlcigpO1xuICAgICAgICBpZiAoIWNvbHVtbiAmJiBmb2N1c2VkSGVhZGVyKSB7XG4gICAgICAgICAgICBjb2x1bW4gPSBmb2N1c2VkSGVhZGVyLmNvbHVtbjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocm93SW5kZXggPT0gbnVsbCB8fCAhY29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5lbnN1cmVDZWxsVmlzaWJsZSh7IHJvd0luZGV4OiByb3dJbmRleCwgY29sdW1uOiBjb2x1bW4sIHJvd1Bpbm5lZDogcm93UGlubmVkIH0pO1xuICAgICAgICB0aGlzLnNldEZvY3VzZWRDZWxsKHtcbiAgICAgICAgICAgIHJvd0luZGV4OiByb3dJbmRleCxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgcm93UGlubmVkOiBtYWtlTnVsbChyb3dQaW5uZWQpLFxuICAgICAgICAgICAgZm9yY2VCcm93c2VyRm9jdXM6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLnJhbmdlU2VydmljZSkge1xuICAgICAgICAgICAgdmFyIGNlbGxQb3NpdGlvbiA9IHsgcm93SW5kZXg6IHJvd0luZGV4LCByb3dQaW5uZWQ6IHJvd1Bpbm5lZCwgY29sdW1uOiBjb2x1bW4gfTtcbiAgICAgICAgICAgIHRoaXMucmFuZ2VTZXJ2aWNlLnNldFJhbmdlVG9DZWxsKGNlbGxQb3NpdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgICBGb2N1c1NlcnZpY2UucHJvdG90eXBlLmZvY3VzTmV4dEdyaWRDb3JlQ29udGFpbmVyID0gZnVuY3Rpb24gKGJhY2t3YXJkcykge1xuICAgICAgICBpZiAodGhpcy5ncmlkQ3RybC5mb2N1c05leHRJbm5lckNvbnRhaW5lcihiYWNrd2FyZHMpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWJhY2t3YXJkcyAmJiAhdGhpcy5ncmlkQ3RybC5pc0RldGFpbEdyaWQoKSkge1xuICAgICAgICAgICAgdGhpcy5ncmlkQ3RybC5mb3JjZUZvY3VzT3V0T2ZDb250YWluZXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICB2YXIgRm9jdXNTZXJ2aWNlXzE7XG4gICAgRm9jdXNTZXJ2aWNlLkFHX0tFWUJPQVJEX0ZPQ1VTID0gJ2FnLWtleWJvYXJkLWZvY3VzJztcbiAgICBGb2N1c1NlcnZpY2Uua2V5Ym9hcmRNb2RlQWN0aXZlID0gZmFsc2U7XG4gICAgRm9jdXNTZXJ2aWNlLmluc3RhbmNlc01vbml0b3JlZCA9IG5ldyBNYXAoKTtcbiAgICBfX2RlY29yYXRlJFAoW1xuICAgICAgICBBdXRvd2lyZWQoJ2VHcmlkRGl2JylcbiAgICBdLCBGb2N1c1NlcnZpY2UucHJvdG90eXBlLCBcImVHcmlkRGl2XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRQKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkUChbXG4gICAgICAgIEF1dG93aXJlZCgnaGVhZGVyTmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIEZvY3VzU2VydmljZS5wcm90b3R5cGUsIFwiaGVhZGVyTmF2aWdhdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFAoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd1JlbmRlcmVyJylcbiAgICBdLCBGb2N1c1NlcnZpY2UucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRQKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dQb3NpdGlvblV0aWxzJylcbiAgICBdLCBGb2N1c1NlcnZpY2UucHJvdG90eXBlLCBcInJvd1Bvc2l0aW9uVXRpbHNcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFAoW1xuICAgICAgICBPcHRpb25hbCgncmFuZ2VTZXJ2aWNlJylcbiAgICBdLCBGb2N1c1NlcnZpY2UucHJvdG90eXBlLCBcInJhbmdlU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkUChbXG4gICAgICAgIEF1dG93aXJlZCgnbmF2aWdhdGlvblNlcnZpY2UnKVxuICAgIF0sIEZvY3VzU2VydmljZS5wcm90b3R5cGUsIFwibmF2aWdhdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFAoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZSwgXCJjdHJsc1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJFAoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgRm9jdXNTZXJ2aWNlLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIEZvY3VzU2VydmljZSA9IEZvY3VzU2VydmljZV8xID0gX19kZWNvcmF0ZSRQKFtcbiAgICAgICAgQmVhbignZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBGb2N1c1NlcnZpY2UpO1xuICAgIHJldHVybiBGb2N1c1NlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkTSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkTyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcmVhZCQ2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIF9fc3ByZWFkJDUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3NwcmVhZCkgfHwgZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhciA9IGFyLmNvbmNhdChfX3JlYWQkNihhcmd1bWVudHNbaV0pKTtcbiAgICByZXR1cm4gYXI7XG59O1xudmFyIERJUkVDVElPTjtcbihmdW5jdGlvbiAoRElSRUNUSU9OKSB7XG4gICAgRElSRUNUSU9OW0RJUkVDVElPTltcInZlcnRpY2FsXCJdID0gMF0gPSBcInZlcnRpY2FsXCI7XG4gICAgRElSRUNUSU9OW0RJUkVDVElPTltcImhvcml6b250YWxcIl0gPSAxXSA9IFwiaG9yaXpvbnRhbFwiO1xufSkoRElSRUNUSU9OIHx8IChESVJFQ1RJT04gPSB7fSkpO1xudmFyIGluc3RhbmNlSWRTZXEgPSAwO1xudmFyIFBvcHVwU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkTShQb3B1cFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUG9wdXBTZXJ2aWNlKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucG9wdXBMaXN0ID0gW107XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmN0cmxzU2VydmljZS53aGVuUmVhZHkoZnVuY3Rpb24gKHApIHtcbiAgICAgICAgICAgIF90aGlzLmdyaWRDdHJsID0gcC5ncmlkQ3RybDtcbiAgICAgICAgICAgIF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihfdGhpcy5ncmlkQ3RybCwgRXZlbnRzLkVWRU5UX0tFWUJPQVJEX0ZPQ1VTLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMucG9wdXBMaXN0LmZvckVhY2goZnVuY3Rpb24gKHBvcHVwKSB7IHJldHVybiBwb3B1cC5lbGVtZW50LmNsYXNzTGlzdC5hZGQoRm9jdXNTZXJ2aWNlLkFHX0tFWUJPQVJEX0ZPQ1VTKTsgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihfdGhpcy5ncmlkQ3RybCwgRXZlbnRzLkVWRU5UX01PVVNFX0ZPQ1VTLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMucG9wdXBMaXN0LmZvckVhY2goZnVuY3Rpb24gKHBvcHVwKSB7IHJldHVybiBwb3B1cC5lbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoRm9jdXNTZXJ2aWNlLkFHX0tFWUJPQVJEX0ZPQ1VTKTsgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLmdldFBvcHVwUGFyZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZVBvcHVwUGFyZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0UG9wdXBQYXJlbnQoKTtcbiAgICAgICAgaWYgKGVQb3B1cFBhcmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGVQb3B1cFBhcmVudDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5ncmlkQ3RybC5nZXRHdWkoKTtcbiAgICB9O1xuICAgIFBvcHVwU2VydmljZS5wcm90b3R5cGUucG9zaXRpb25Qb3B1cEZvck1lbnUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBzb3VyY2VSZWN0ID0gcGFyYW1zLmV2ZW50U291cmNlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB2YXIgcGFyZW50UmVjdCA9IHRoaXMuZ2V0UGFyZW50UmVjdCgpO1xuICAgICAgICB2YXIgeSA9IHRoaXMua2VlcFhZV2l0aGluQm91bmRzKHBhcmFtcy5lUG9wdXAsIHNvdXJjZVJlY3QudG9wIC0gcGFyZW50UmVjdC50b3AsIERJUkVDVElPTi52ZXJ0aWNhbCk7XG4gICAgICAgIHZhciBtaW5XaWR0aCA9IChwYXJhbXMuZVBvcHVwLmNsaWVudFdpZHRoID4gMCkgPyBwYXJhbXMuZVBvcHVwLmNsaWVudFdpZHRoIDogMjAwO1xuICAgICAgICBwYXJhbXMuZVBvcHVwLnN0eWxlLm1pbldpZHRoID0gbWluV2lkdGggKyBcInB4XCI7XG4gICAgICAgIHZhciB3aWR0aE9mUGFyZW50ID0gcGFyZW50UmVjdC5yaWdodCAtIHBhcmVudFJlY3QubGVmdDtcbiAgICAgICAgdmFyIG1heFggPSB3aWR0aE9mUGFyZW50IC0gbWluV2lkdGg7XG4gICAgICAgIC8vIHRoZSB4IHBvc2l0aW9uIG9mIHRoZSBwb3B1cCBkZXBlbmRzIG9uIFJUTCBvciBMVFIuIGZvciBub3JtYWwgY2FzZXMsIExUUiwgd2UgcHV0IHRoZSBjaGlsZCBwb3B1cFxuICAgICAgICAvLyB0byB0aGUgcmlnaHQsIHVubGVzcyBpdCBkb2Vzbid0IGZpdCBhbmQgd2UgdGhlbiBwdXQgaXQgdG8gdGhlIGxlZnQuIGZvciBSVEwgaXQncyB0aGUgb3RoZXIgd2F5IGFyb3VuZCxcbiAgICAgICAgLy8gd2UgdHJ5IHBsYWNlIGl0IGZpcnN0IHRvIHRoZSBsZWZ0LCBhbmQgdGhlbiBpZiBub3QgdG8gdGhlIHJpZ2h0LlxuICAgICAgICB2YXIgeDtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkpIHtcbiAgICAgICAgICAgIC8vIGZvciBSVEwsIHRyeSBsZWZ0IGZpcnN0XG4gICAgICAgICAgICB4ID0geExlZnRQb3NpdGlvbigpO1xuICAgICAgICAgICAgaWYgKHggPCAwKSB7XG4gICAgICAgICAgICAgICAgeCA9IHhSaWdodFBvc2l0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeCA+IG1heFgpIHtcbiAgICAgICAgICAgICAgICB4ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZvciBMVFIsIHRyeSByaWdodCBmaXJzdFxuICAgICAgICAgICAgeCA9IHhSaWdodFBvc2l0aW9uKCk7XG4gICAgICAgICAgICBpZiAoeCA+IG1heFgpIHtcbiAgICAgICAgICAgICAgICB4ID0geExlZnRQb3NpdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHggPCAwKSB7XG4gICAgICAgICAgICAgICAgeCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcGFyYW1zLmVQb3B1cC5zdHlsZS5sZWZ0ID0geCArIFwicHhcIjtcbiAgICAgICAgcGFyYW1zLmVQb3B1cC5zdHlsZS50b3AgPSB5ICsgXCJweFwiO1xuICAgICAgICBmdW5jdGlvbiB4UmlnaHRQb3NpdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBzb3VyY2VSZWN0LnJpZ2h0IC0gcGFyZW50UmVjdC5sZWZ0IC0gMjtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB4TGVmdFBvc2l0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZVJlY3QubGVmdCAtIHBhcmVudFJlY3QubGVmdCAtIG1pbldpZHRoO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLnBvc2l0aW9uUG9wdXBVbmRlck1vdXNlRXZlbnQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBlUG9wdXAgPSBwYXJhbXMuZVBvcHVwLCBudWRnZVggPSBwYXJhbXMubnVkZ2VYLCBudWRnZVkgPSBwYXJhbXMubnVkZ2VZO1xuICAgICAgICB2YXIgX2EgPSB0aGlzLmNhbGN1bGF0ZVBvaW50ZXJBbGlnbihwYXJhbXMubW91c2VFdmVudCksIHggPSBfYS54LCB5ID0gX2EueTtcbiAgICAgICAgdGhpcy5wb3NpdGlvblBvcHVwKHtcbiAgICAgICAgICAgIGVQb3B1cDogZVBvcHVwLFxuICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgIHk6IHksXG4gICAgICAgICAgICBudWRnZVg6IG51ZGdlWCxcbiAgICAgICAgICAgIG51ZGdlWTogbnVkZ2VZLFxuICAgICAgICAgICAga2VlcFdpdGhpbkJvdW5kczogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jYWxsUG9zdFByb2Nlc3NQb3B1cChwYXJhbXMudHlwZSwgcGFyYW1zLmVQb3B1cCwgbnVsbCwgcGFyYW1zLm1vdXNlRXZlbnQsIHBhcmFtcy5jb2x1bW4sIHBhcmFtcy5yb3dOb2RlKTtcbiAgICB9O1xuICAgIFBvcHVwU2VydmljZS5wcm90b3R5cGUuY2FsY3VsYXRlUG9pbnRlckFsaWduID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHBhcmVudFJlY3QgPSB0aGlzLmdldFBhcmVudFJlY3QoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IGUuY2xpZW50WCAtIHBhcmVudFJlY3QubGVmdCxcbiAgICAgICAgICAgIHk6IGUuY2xpZW50WSAtIHBhcmVudFJlY3QudG9wXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLnBvc2l0aW9uUG9wdXBVbmRlckNvbXBvbmVudCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIHNvdXJjZVJlY3QgPSBwYXJhbXMuZXZlbnRTb3VyY2UuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBhbGlnblNpZGUgPSBwYXJhbXMuYWxpZ25TaWRlIHx8ICdsZWZ0JztcbiAgICAgICAgdmFyIHBhcmVudFJlY3QgPSB0aGlzLmdldFBhcmVudFJlY3QoKTtcbiAgICAgICAgdmFyIHggPSBzb3VyY2VSZWN0LmxlZnQgLSBwYXJlbnRSZWN0LmxlZnQ7XG4gICAgICAgIGlmIChhbGlnblNpZGUgPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgIHggLT0gKHBhcmFtcy5lUG9wdXAub2Zmc2V0V2lkdGggLSBzb3VyY2VSZWN0LndpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBvc2l0aW9uUG9wdXAoe1xuICAgICAgICAgICAgZVBvcHVwOiBwYXJhbXMuZVBvcHVwLFxuICAgICAgICAgICAgbnVkZ2VYOiBwYXJhbXMubnVkZ2VYLFxuICAgICAgICAgICAgbnVkZ2VZOiBwYXJhbXMubnVkZ2VZLFxuICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgIHk6IHNvdXJjZVJlY3QudG9wIC0gcGFyZW50UmVjdC50b3AgKyBzb3VyY2VSZWN0LmhlaWdodCxcbiAgICAgICAgICAgIGtlZXBXaXRoaW5Cb3VuZHM6IHBhcmFtcy5rZWVwV2l0aGluQm91bmRzXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNhbGxQb3N0UHJvY2Vzc1BvcHVwKHBhcmFtcy50eXBlLCBwYXJhbXMuZVBvcHVwLCBwYXJhbXMuZXZlbnRTb3VyY2UsIG51bGwsIHBhcmFtcy5jb2x1bW4sIHBhcmFtcy5yb3dOb2RlKTtcbiAgICB9O1xuICAgIFBvcHVwU2VydmljZS5wcm90b3R5cGUucG9zaXRpb25Qb3B1cE92ZXJDb21wb25lbnQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBzb3VyY2VSZWN0ID0gcGFyYW1zLmV2ZW50U291cmNlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB2YXIgcGFyZW50UmVjdCA9IHRoaXMuZ2V0UGFyZW50UmVjdCgpO1xuICAgICAgICB0aGlzLnBvc2l0aW9uUG9wdXAoe1xuICAgICAgICAgICAgZVBvcHVwOiBwYXJhbXMuZVBvcHVwLFxuICAgICAgICAgICAgbnVkZ2VYOiBwYXJhbXMubnVkZ2VYLFxuICAgICAgICAgICAgbnVkZ2VZOiBwYXJhbXMubnVkZ2VZLFxuICAgICAgICAgICAgeDogc291cmNlUmVjdC5sZWZ0IC0gcGFyZW50UmVjdC5sZWZ0LFxuICAgICAgICAgICAgeTogc291cmNlUmVjdC50b3AgLSBwYXJlbnRSZWN0LnRvcCxcbiAgICAgICAgICAgIGtlZXBXaXRoaW5Cb3VuZHM6IHBhcmFtcy5rZWVwV2l0aGluQm91bmRzXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNhbGxQb3N0UHJvY2Vzc1BvcHVwKHBhcmFtcy50eXBlLCBwYXJhbXMuZVBvcHVwLCBwYXJhbXMuZXZlbnRTb3VyY2UsIG51bGwsIHBhcmFtcy5jb2x1bW4sIHBhcmFtcy5yb3dOb2RlKTtcbiAgICB9O1xuICAgIFBvcHVwU2VydmljZS5wcm90b3R5cGUuY2FsbFBvc3RQcm9jZXNzUG9wdXAgPSBmdW5jdGlvbiAodHlwZSwgZVBvcHVwLCBldmVudFNvdXJjZSwgbW91c2VFdmVudCwgY29sdW1uLCByb3dOb2RlKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFBvc3RQcm9jZXNzUG9wdXBGdW5jKCk7XG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICBjb2x1bW46IGNvbHVtbixcbiAgICAgICAgICAgICAgICByb3dOb2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgICAgIGVQb3B1cDogZVBvcHVwLFxuICAgICAgICAgICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgICAgICAgICAgZXZlbnRTb3VyY2U6IGV2ZW50U291cmNlLFxuICAgICAgICAgICAgICAgIG1vdXNlRXZlbnQ6IG1vdXNlRXZlbnRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjYWxsYmFjayhwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLnBvc2l0aW9uUG9wdXAgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBlUG9wdXAgPSBwYXJhbXMuZVBvcHVwLCBrZWVwV2l0aGluQm91bmRzID0gcGFyYW1zLmtlZXBXaXRoaW5Cb3VuZHMsIG51ZGdlWCA9IHBhcmFtcy5udWRnZVgsIG51ZGdlWSA9IHBhcmFtcy5udWRnZVk7XG4gICAgICAgIHZhciB4ID0gcGFyYW1zLngsIHkgPSBwYXJhbXMueTtcbiAgICAgICAgaWYgKG51ZGdlWCkge1xuICAgICAgICAgICAgeCArPSBudWRnZVg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG51ZGdlWSkge1xuICAgICAgICAgICAgeSArPSBudWRnZVk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgcG9wdXAgaXMgb3ZlcmZsb3dpbmcgdG8gdGhlIGJvdHRvbSwgbW92ZSBpdCB1cFxuICAgICAgICBpZiAoa2VlcFdpdGhpbkJvdW5kcykge1xuICAgICAgICAgICAgeCA9IHRoaXMua2VlcFhZV2l0aGluQm91bmRzKGVQb3B1cCwgeCwgRElSRUNUSU9OLmhvcml6b250YWwpO1xuICAgICAgICAgICAgeSA9IHRoaXMua2VlcFhZV2l0aGluQm91bmRzKGVQb3B1cCwgeSwgRElSRUNUSU9OLnZlcnRpY2FsKTtcbiAgICAgICAgfVxuICAgICAgICBlUG9wdXAuc3R5bGUubGVmdCA9IHggKyBcInB4XCI7XG4gICAgICAgIGVQb3B1cC5zdHlsZS50b3AgPSB5ICsgXCJweFwiO1xuICAgIH07XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5nZXRBY3RpdmVQb3B1cHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBvcHVwTGlzdC5tYXAoZnVuY3Rpb24gKHBvcHVwKSB7IHJldHVybiBwb3B1cC5lbGVtZW50OyB9KTtcbiAgICB9O1xuICAgIFBvcHVwU2VydmljZS5wcm90b3R5cGUuZ2V0UG9wdXBMaXN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3B1cExpc3Q7XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLmdldFBhcmVudFJlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHN1YnRyYWN0IHRoZSBwb3B1cCBwYXJlbnQgYm9yZGVycywgYmVjYXVzZSBwb3B1cFBhcmVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3RcbiAgICAgICAgLy8gcmV0dXJucyB0aGUgcmVjdCBvdXRzaWRlIHRoZSBib3JkZXJzLCBidXQgdGhlIDAsMCBjb29yZGluYXRlIGZvciBhYnNvbHV0ZVxuICAgICAgICAvLyBwb3NpdGlvbmluZyBpcyBpbnNpZGUgdGhlIGJvcmRlciwgbGVhZGluZyB0aGUgcG9wdXAgdG8gYmUgb2ZmIGJ5IHRoZSB3aWR0aFxuICAgICAgICAvLyBvZiB0aGUgYm9yZGVyXG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgcG9wdXBQYXJlbnQgPSB0aGlzLmdldFBvcHVwUGFyZW50KCk7XG4gICAgICAgIGlmIChwb3B1cFBhcmVudCA9PT0gZURvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgICAgIHBvcHVwUGFyZW50ID0gZURvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChnZXRDb21wdXRlZFN0eWxlKHBvcHVwUGFyZW50KS5wb3NpdGlvbiA9PT0gJ3N0YXRpYycpIHtcbiAgICAgICAgICAgIHBvcHVwUGFyZW50ID0gcG9wdXBQYXJlbnQub2Zmc2V0UGFyZW50O1xuICAgICAgICB9XG4gICAgICAgIHZhciBzdHlsZSA9IGdldENvbXB1dGVkU3R5bGUocG9wdXBQYXJlbnQpO1xuICAgICAgICB2YXIgYm91bmRzID0gcG9wdXBQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0b3A6IGJvdW5kcy50b3AgKyBwYXJzZUZsb2F0KHN0eWxlLmJvcmRlclRvcFdpZHRoKSB8fCAwLFxuICAgICAgICAgICAgbGVmdDogYm91bmRzLmxlZnQgKyBwYXJzZUZsb2F0KHN0eWxlLmJvcmRlckxlZnRXaWR0aCkgfHwgMCxcbiAgICAgICAgICAgIHJpZ2h0OiBib3VuZHMucmlnaHQgKyBwYXJzZUZsb2F0KHN0eWxlLmJvcmRlclJpZ2h0V2lkdGgpIHx8IDAsXG4gICAgICAgICAgICBib3R0b206IGJvdW5kcy5ib3R0b20gKyBwYXJzZUZsb2F0KHN0eWxlLmJvcmRlckJvdHRvbVdpZHRoKSB8fCAwLFxuICAgICAgICB9O1xuICAgIH07XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5rZWVwWFlXaXRoaW5Cb3VuZHMgPSBmdW5jdGlvbiAoZVBvcHVwLCBwb3NpdGlvbiwgZGlyZWN0aW9uKSB7XG4gICAgICAgIHZhciBpc1ZlcnRpY2FsID0gZGlyZWN0aW9uID09PSBESVJFQ1RJT04udmVydGljYWw7XG4gICAgICAgIHZhciBzaXplUHJvcGVydHkgPSBpc1ZlcnRpY2FsID8gJ2NsaWVudEhlaWdodCcgOiAnY2xpZW50V2lkdGgnO1xuICAgICAgICB2YXIgYW5jaG9yUHJvcGVydHkgPSBpc1ZlcnRpY2FsID8gJ3RvcCcgOiAnbGVmdCc7XG4gICAgICAgIHZhciBvZmZzZXRQcm9wZXJ0eSA9IGlzVmVydGljYWwgPyAnb2Zmc2V0SGVpZ2h0JyA6ICdvZmZzZXRXaWR0aCc7XG4gICAgICAgIHZhciBzY3JvbGxQb3NpdGlvblByb3BlcnR5ID0gaXNWZXJ0aWNhbCA/ICdzY3JvbGxUb3AnIDogJ3Njcm9sbExlZnQnO1xuICAgICAgICB2YXIgZURvY3VtZW50ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9jdW1lbnQoKTtcbiAgICAgICAgdmFyIGRvY0VsZW1lbnQgPSBlRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICB2YXIgcG9wdXBQYXJlbnQgPSB0aGlzLmdldFBvcHVwUGFyZW50KCk7XG4gICAgICAgIHZhciBwYXJlbnRSZWN0ID0gcG9wdXBQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBkb2N1bWVudFJlY3QgPSBlRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB2YXIgaXNCb2R5ID0gcG9wdXBQYXJlbnQgPT09IGVEb2N1bWVudC5ib2R5O1xuICAgICAgICB2YXIgb2Zmc2V0U2l6ZSA9IGVQb3B1cFtvZmZzZXRQcm9wZXJ0eV07XG4gICAgICAgIHZhciBnZXRTaXplID0gaXNWZXJ0aWNhbCA/IGdldEFic29sdXRlSGVpZ2h0IDogZ2V0QWJzb2x1dGVXaWR0aDtcbiAgICAgICAgdmFyIHNpemVPZlBhcmVudCA9IGlzQm9keSA/IChnZXRTaXplKGRvY0VsZW1lbnQpICsgZG9jRWxlbWVudFtzY3JvbGxQb3NpdGlvblByb3BlcnR5XSkgOiBwb3B1cFBhcmVudFtzaXplUHJvcGVydHldO1xuICAgICAgICBpZiAoaXNCb2R5KSB7XG4gICAgICAgICAgICBzaXplT2ZQYXJlbnQgLT0gTWF0aC5hYnMoZG9jdW1lbnRSZWN0W2FuY2hvclByb3BlcnR5XSAtIHBhcmVudFJlY3RbYW5jaG9yUHJvcGVydHldKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF4ID0gc2l6ZU9mUGFyZW50IC0gb2Zmc2V0U2l6ZTtcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KHBvc2l0aW9uLCAwKSwgTWF0aC5hYnMobWF4KSk7XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLmtlZXBQb3B1cFBvc2l0aW9uZWRSZWxhdGl2ZVRvID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZVBhcmVudCA9IHRoaXMuZ2V0UG9wdXBQYXJlbnQoKTtcbiAgICAgICAgdmFyIHBhcmVudFJlY3QgPSBlUGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB2YXIgc291cmNlUmVjdCA9IHBhcmFtcy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB2YXIgaW5pdGlhbERpZmZUb3AgPSBwYXJlbnRSZWN0LnRvcCAtIHNvdXJjZVJlY3QudG9wO1xuICAgICAgICB2YXIgaW5pdGlhbERpZmZMZWZ0ID0gcGFyZW50UmVjdC5sZWZ0IC0gc291cmNlUmVjdC5sZWZ0O1xuICAgICAgICB2YXIgbGFzdERpZmZUb3AgPSBpbml0aWFsRGlmZlRvcDtcbiAgICAgICAgdmFyIGxhc3REaWZmTGVmdCA9IGluaXRpYWxEaWZmTGVmdDtcbiAgICAgICAgdmFyIHRvcFB4ID0gcGFyYW1zLmVQb3B1cC5zdHlsZS50b3A7XG4gICAgICAgIHZhciB0b3AgPSBwYXJzZUludCh0b3BQeC5zdWJzdHJpbmcoMCwgdG9wUHgubGVuZ3RoIC0gMSksIDEwKTtcbiAgICAgICAgdmFyIGxlZnRQeCA9IHBhcmFtcy5lUG9wdXAuc3R5bGUubGVmdDtcbiAgICAgICAgdmFyIGxlZnQgPSBwYXJzZUludChsZWZ0UHguc3Vic3RyaW5nKDAsIGxlZnRQeC5sZW5ndGggLSAxKSwgMTApO1xuICAgICAgICByZXR1cm4gbmV3IEFnUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgX3RoaXMuZ2V0RnJhbWV3b3JrT3ZlcnJpZGVzKCkuc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBwUmVjdCA9IGVQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIHNSZWN0ID0gcGFyYW1zLmVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnROb3RJbkRvbSA9IHNSZWN0LnRvcCA9PSAwICYmIHNSZWN0LmxlZnQgPT0gMCAmJiBzUmVjdC5oZWlnaHQgPT0gMCAmJiBzUmVjdC53aWR0aCA9PSAwO1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50Tm90SW5Eb20pIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmhpZGVQb3B1cCgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50RGlmZlRvcCA9IHBSZWN0LnRvcCAtIHNSZWN0LnRvcDtcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudERpZmZUb3AgIT0gbGFzdERpZmZUb3ApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1RvcCA9IF90aGlzLmtlZXBYWVdpdGhpbkJvdW5kcyhwYXJhbXMuZVBvcHVwLCB0b3AgKyBpbml0aWFsRGlmZlRvcCAtIGN1cnJlbnREaWZmVG9wLCBESVJFQ1RJT04udmVydGljYWwpO1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXMuZVBvcHVwLnN0eWxlLnRvcCA9IG5ld1RvcCArIFwicHhcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGFzdERpZmZUb3AgPSBjdXJyZW50RGlmZlRvcDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudERpZmZMZWZ0ID0gcFJlY3QubGVmdCAtIHNSZWN0LmxlZnQ7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREaWZmTGVmdCAhPSBsYXN0RGlmZkxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0xlZnQgPSBfdGhpcy5rZWVwWFlXaXRoaW5Cb3VuZHMocGFyYW1zLmVQb3B1cCwgbGVmdCArIGluaXRpYWxEaWZmTGVmdCAtIGN1cnJlbnREaWZmTGVmdCwgRElSRUNUSU9OLmhvcml6b250YWwpO1xuICAgICAgICAgICAgICAgICAgICBwYXJhbXMuZVBvcHVwLnN0eWxlLmxlZnQgPSBuZXdMZWZ0ICsgXCJweFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsYXN0RGlmZkxlZnQgPSBjdXJyZW50RGlmZkxlZnQ7XG4gICAgICAgICAgICB9LCAyMDApLnRoZW4oZnVuY3Rpb24gKGludGVydmFsSWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW50ZXJ2YWxJZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbChpbnRlcnZhbElkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5hZGRQb3B1cCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbW9kYWwgPSBwYXJhbXMubW9kYWwsIGVDaGlsZCA9IHBhcmFtcy5lQ2hpbGQsIGNsb3NlT25Fc2MgPSBwYXJhbXMuY2xvc2VPbkVzYywgY2xvc2VkQ2FsbGJhY2sgPSBwYXJhbXMuY2xvc2VkQ2FsbGJhY2ssIGNsaWNrID0gcGFyYW1zLmNsaWNrLCBhbHdheXNPblRvcCA9IHBhcmFtcy5hbHdheXNPblRvcCwgYWZ0ZXJHdWlBdHRhY2hlZCA9IHBhcmFtcy5hZnRlckd1aUF0dGFjaGVkLCBwb3NpdGlvbkNhbGxiYWNrID0gcGFyYW1zLnBvc2l0aW9uQ2FsbGJhY2ssIGFuY2hvclRvRWxlbWVudCA9IHBhcmFtcy5hbmNob3JUb0VsZW1lbnQsIGFyaWFMYWJlbCA9IHBhcmFtcy5hcmlhTGFiZWw7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB2YXIgZGVzdHJveVBvc2l0aW9uVHJhY2tlciA9IG5ldyBBZ1Byb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmV0dXJuIHJlc29sdmUoZnVuY3Rpb24gKCkgeyB9KTsgfSk7XG4gICAgICAgIGlmICghZURvY3VtZW50KSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ2FnLWdyaWQ6IGNvdWxkIG5vdCBmaW5kIHRoZSBkb2N1bWVudCwgZG9jdW1lbnQgaXMgZW1wdHknKTtcbiAgICAgICAgICAgIHJldHVybiB7IGhpZGVGdW5jOiBmdW5jdGlvbiAoKSB7IH0sIHN0b3BBbmNob3JpbmdQcm9taXNlOiBkZXN0cm95UG9zaXRpb25UcmFja2VyIH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBvcyA9IHRoaXMucG9wdXBMaXN0LmZpbmRJbmRleChmdW5jdGlvbiAocG9wdXApIHsgcmV0dXJuIHBvcHVwLmVsZW1lbnQgPT09IGVDaGlsZDsgfSk7XG4gICAgICAgIGlmIChwb3MgIT09IC0xKSB7XG4gICAgICAgICAgICB2YXIgcG9wdXAgPSB0aGlzLnBvcHVwTGlzdFtwb3NdO1xuICAgICAgICAgICAgcmV0dXJuIHsgaGlkZUZ1bmM6IHBvcHVwLmhpZGVGdW5jLCBzdG9wQW5jaG9yaW5nUHJvbWlzZTogcG9wdXAuc3RvcEFuY2hvcmluZ1Byb21pc2UgfTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZVBvcHVwUGFyZW50ID0gdGhpcy5nZXRQb3B1cFBhcmVudCgpO1xuICAgICAgICBpZiAoZUNoaWxkLnN0eWxlLnRvcCA9PSBudWxsKSB7XG4gICAgICAgICAgICBlQ2hpbGQuc3R5bGUudG9wID0gJzBweCc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVDaGlsZC5zdHlsZS5sZWZ0ID09IG51bGwpIHtcbiAgICAgICAgICAgIGVDaGlsZC5zdHlsZS5sZWZ0ID0gJzBweCc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWRkIGVudiBDU1MgY2xhc3MgdG8gY2hpbGQsIGluIGNhc2UgdXNlciBwcm92aWRlZCBhIHBvcHVwIHBhcmVudCwgd2hpY2ggbWVhbnNcbiAgICAgICAgLy8gdGhlbWUgY2xhc3MgbWF5IGJlIG1pc3NpbmdcbiAgICAgICAgdmFyIGVXcmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHZhciBhbGxUaGVtZXMgPSB0aGlzLmVudmlyb25tZW50LmdldFRoZW1lKCkuYWxsVGhlbWVzO1xuICAgICAgICBpZiAoYWxsVGhlbWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgKF9hID0gZVdyYXBwZXIuY2xhc3NMaXN0KS5hZGQuYXBwbHkoX2EsIF9fc3ByZWFkJDUoYWxsVGhlbWVzKSk7XG4gICAgICAgIH1cbiAgICAgICAgZVdyYXBwZXIuY2xhc3NMaXN0LmFkZCgnYWctcG9wdXAnKTtcbiAgICAgICAgZUNoaWxkLmNsYXNzTGlzdC5hZGQodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKSA/ICdhZy1ydGwnIDogJ2FnLWx0cicsICdhZy1wb3B1cC1jaGlsZCcpO1xuICAgICAgICBpZiAoIWVDaGlsZC5oYXNBdHRyaWJ1dGUoJ3JvbGUnKSkge1xuICAgICAgICAgICAgc2V0QXJpYVJvbGUoZUNoaWxkLCAnZGlhbG9nJyk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0QXJpYUxhYmVsKGVDaGlsZCwgYXJpYUxhYmVsKTtcbiAgICAgICAgaWYgKHRoaXMuZm9jdXNTZXJ2aWNlLmlzS2V5Ym9hcmRNb2RlKCkpIHtcbiAgICAgICAgICAgIGVDaGlsZC5jbGFzc0xpc3QuYWRkKEZvY3VzU2VydmljZS5BR19LRVlCT0FSRF9GT0NVUyk7XG4gICAgICAgIH1cbiAgICAgICAgZVdyYXBwZXIuYXBwZW5kQ2hpbGQoZUNoaWxkKTtcbiAgICAgICAgZVBvcHVwUGFyZW50LmFwcGVuZENoaWxkKGVXcmFwcGVyKTtcbiAgICAgICAgaWYgKGFsd2F5c09uVG9wKSB7XG4gICAgICAgICAgICB0aGlzLnNldEFsd2F5c09uVG9wKGVXcmFwcGVyLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYnJpbmdQb3B1cFRvRnJvbnQoZVdyYXBwZXIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwb3B1cEhpZGRlbiA9IGZhbHNlO1xuICAgICAgICB2YXIgaGlkZVBvcHVwT25LZXlib2FyZEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoIWVXcmFwcGVyLmNvbnRhaW5zKGVEb2N1bWVudC5hY3RpdmVFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBrZXkgPSBldmVudC5rZXk7XG4gICAgICAgICAgICBpZiAoa2V5ID09PSBLZXlDb2RlLkVTQ0FQRSkge1xuICAgICAgICAgICAgICAgIGhpZGVQb3B1cCh7IGtleWJvYXJkRXZlbnQ6IGV2ZW50IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgaGlkZVBvcHVwT25Nb3VzZUV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7IHJldHVybiBoaWRlUG9wdXAoeyBtb3VzZUV2ZW50OiBldmVudCB9KTsgfTtcbiAgICAgICAgdmFyIGhpZGVQb3B1cE9uVG91Y2hFdmVudCA9IGZ1bmN0aW9uIChldmVudCkgeyByZXR1cm4gaGlkZVBvcHVwKHsgdG91Y2hFdmVudDogZXZlbnQgfSk7IH07XG4gICAgICAgIHZhciBoaWRlUG9wdXAgPSBmdW5jdGlvbiAocG9wdXBQYXJhbXMpIHtcbiAgICAgICAgICAgIGlmIChwb3B1cFBhcmFtcyA9PT0gdm9pZCAwKSB7IHBvcHVwUGFyYW1zID0ge307IH1cbiAgICAgICAgICAgIHZhciBtb3VzZUV2ZW50ID0gcG9wdXBQYXJhbXMubW91c2VFdmVudCwgdG91Y2hFdmVudCA9IHBvcHVwUGFyYW1zLnRvdWNoRXZlbnQsIGtleWJvYXJkRXZlbnQgPSBwb3B1cFBhcmFtcy5rZXlib2FyZEV2ZW50O1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgLy8gd2UgZG9uJ3QgaGlkZSBwb3B1cCBpZiB0aGUgZXZlbnQgd2FzIG9uIHRoZSBjaGlsZCwgb3IgYW55XG4gICAgICAgICAgICAvLyBjaGlsZHJlbiBvZiB0aGlzIGNoaWxkXG4gICAgICAgICAgICBfdGhpcy5pc0V2ZW50RnJvbUN1cnJlbnRQb3B1cCh7IG1vdXNlRXZlbnQ6IG1vdXNlRXZlbnQsIHRvdWNoRXZlbnQ6IHRvdWNoRXZlbnQgfSwgZUNoaWxkKSB8fFxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBldmVudCB0byBjbG9zZSBpcyBhY3R1YWxseSB0aGUgb3BlbiBldmVudCwgdGhlbiBpZ25vcmUgaXRcbiAgICAgICAgICAgICAgICBfdGhpcy5pc0V2ZW50U2FtZUNoYWluQXNPcmlnaW5hbEV2ZW50KHsgb3JpZ2luYWxNb3VzZUV2ZW50OiBjbGljaywgbW91c2VFdmVudDogbW91c2VFdmVudCwgdG91Y2hFdmVudDogdG91Y2hFdmVudCB9KSB8fFxuICAgICAgICAgICAgICAgIC8vIHRoaXMgbWV0aG9kIHNob3VsZCBvbmx5IGJlIGNhbGxlZCBvbmNlLiB0aGUgY2xpZW50IGNhbiBoYXZlIGRpZmZlcmVudFxuICAgICAgICAgICAgICAgIC8vIHBhdGhzLCBlYWNoIG9uZSB3YW50aW5nIHRvIGNsb3NlLCBzbyB0aGlzIG1ldGhvZCBtYXkgYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzLlxuICAgICAgICAgICAgICAgIHBvcHVwSGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9wdXBIaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgZVBvcHVwUGFyZW50LnJlbW92ZUNoaWxkKGVXcmFwcGVyKTtcbiAgICAgICAgICAgIGVEb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgaGlkZVBvcHVwT25LZXlib2FyZEV2ZW50KTtcbiAgICAgICAgICAgIGVEb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBoaWRlUG9wdXBPbk1vdXNlRXZlbnQpO1xuICAgICAgICAgICAgZURvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBoaWRlUG9wdXBPblRvdWNoRXZlbnQpO1xuICAgICAgICAgICAgZURvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgaGlkZVBvcHVwT25Nb3VzZUV2ZW50KTtcbiAgICAgICAgICAgIF90aGlzLmV2ZW50U2VydmljZS5yZW1vdmVFdmVudExpc3RlbmVyKEV2ZW50cy5FVkVOVF9EUkFHX1NUQVJURUQsIGhpZGVQb3B1cE9uTW91c2VFdmVudCk7XG4gICAgICAgICAgICBpZiAoY2xvc2VkQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBjbG9zZWRDYWxsYmFjayhtb3VzZUV2ZW50IHx8IHRvdWNoRXZlbnQgfHwga2V5Ym9hcmRFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5wb3B1cExpc3QgPSBfdGhpcy5wb3B1cExpc3QuZmlsdGVyKGZ1bmN0aW9uIChwb3B1cCkgeyByZXR1cm4gcG9wdXAuZWxlbWVudCAhPT0gZUNoaWxkOyB9KTtcbiAgICAgICAgICAgIGlmIChkZXN0cm95UG9zaXRpb25UcmFja2VyKSB7XG4gICAgICAgICAgICAgICAgZGVzdHJveVBvc2l0aW9uVHJhY2tlci50aGVuKGZ1bmN0aW9uIChkZXN0cm95RnVuYykgeyByZXR1cm4gZGVzdHJveUZ1bmMgJiYgZGVzdHJveUZ1bmMoKTsgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGlmIChhZnRlckd1aUF0dGFjaGVkKSB7XG4gICAgICAgICAgICBhZnRlckd1aUF0dGFjaGVkKHsgaGlkZVBvcHVwOiBoaWRlUG9wdXAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgYWRkIHRoZXNlIGxpc3RlbmVycyBub3csIHRoZW4gdGhlIGN1cnJlbnQgbW91c2VcbiAgICAgICAgLy8gY2xpY2sgd2lsbCBiZSBpbmNsdWRlZCwgd2hpY2ggd2UgZG9uJ3Qgd2FudFxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoY2xvc2VPbkVzYykge1xuICAgICAgICAgICAgICAgIGVEb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgaGlkZVBvcHVwT25LZXlib2FyZEV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtb2RhbCkge1xuICAgICAgICAgICAgICAgIGVEb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBoaWRlUG9wdXBPbk1vdXNlRXZlbnQpO1xuICAgICAgICAgICAgICAgIF90aGlzLmV2ZW50U2VydmljZS5hZGRFdmVudExpc3RlbmVyKEV2ZW50cy5FVkVOVF9EUkFHX1NUQVJURUQsIGhpZGVQb3B1cE9uTW91c2VFdmVudCk7XG4gICAgICAgICAgICAgICAgZURvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBoaWRlUG9wdXBPblRvdWNoRXZlbnQpO1xuICAgICAgICAgICAgICAgIGVEb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGhpZGVQb3B1cE9uTW91c2VFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDApO1xuICAgICAgICBpZiAocG9zaXRpb25DYWxsYmFjaykge1xuICAgICAgICAgICAgcG9zaXRpb25DYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhbmNob3JUb0VsZW1lbnQpIHtcbiAgICAgICAgICAgIC8vIGtlZXBzIHBvcHVwIHBvc2l0aW9uZWQgdW5kZXIgY3JlYXRlZCwgZWcgaWYgY29udGV4dCBtZW51LCBpZiB1c2VyIHNjcm9sbHNcbiAgICAgICAgICAgIC8vIHVzaW5nIHRvdWNocGFkIGFuZCB0aGUgY2VsbCBtb3ZlcywgaXQgbW92ZXMgdGhlIHBvcHVwIHRvIGtlZXAgaXQgd2l0aCB0aGUgY2VsbC5cbiAgICAgICAgICAgIGRlc3Ryb3lQb3NpdGlvblRyYWNrZXIgPSB0aGlzLmtlZXBQb3B1cFBvc2l0aW9uZWRSZWxhdGl2ZVRvKHtcbiAgICAgICAgICAgICAgICBlbGVtZW50OiBhbmNob3JUb0VsZW1lbnQsXG4gICAgICAgICAgICAgICAgZVBvcHVwOiBlQ2hpbGQsXG4gICAgICAgICAgICAgICAgaGlkZVBvcHVwOiBoaWRlUG9wdXBcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucG9wdXBMaXN0LnB1c2goe1xuICAgICAgICAgICAgZWxlbWVudDogZUNoaWxkLFxuICAgICAgICAgICAgd3JhcHBlcjogZVdyYXBwZXIsXG4gICAgICAgICAgICBoaWRlRnVuYzogaGlkZVBvcHVwLFxuICAgICAgICAgICAgc3RvcEFuY2hvcmluZ1Byb21pc2U6IGRlc3Ryb3lQb3NpdGlvblRyYWNrZXIsXG4gICAgICAgICAgICBpbnN0YW5jZUlkOiBpbnN0YW5jZUlkU2VxKyssXG4gICAgICAgICAgICBpc0FuY2hvcmVkOiAhIWFuY2hvclRvRWxlbWVudFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGhpZGVGdW5jOiBoaWRlUG9wdXAsXG4gICAgICAgICAgICBzdG9wQW5jaG9yaW5nUHJvbWlzZTogZGVzdHJveVBvc2l0aW9uVHJhY2tlclxuICAgICAgICB9O1xuICAgIH07XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5oYXNBbmNob3JlZFBvcHVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wb3B1cExpc3Quc29tZShmdW5jdGlvbiAocG9wdXApIHsgcmV0dXJuIHBvcHVwLmlzQW5jaG9yZWQ7IH0pO1xuICAgIH07XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5pc0V2ZW50RnJvbUN1cnJlbnRQb3B1cCA9IGZ1bmN0aW9uIChwYXJhbXMsIHRhcmdldCkge1xuICAgICAgICB2YXIgbW91c2VFdmVudCA9IHBhcmFtcy5tb3VzZUV2ZW50LCB0b3VjaEV2ZW50ID0gcGFyYW1zLnRvdWNoRXZlbnQ7XG4gICAgICAgIHZhciBldmVudCA9IG1vdXNlRXZlbnQgPyBtb3VzZUV2ZW50IDogdG91Y2hFdmVudDtcbiAgICAgICAgaWYgKCFldmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbmRleE9mVGhpc0NoaWxkID0gdGhpcy5wb3B1cExpc3QuZmluZEluZGV4KGZ1bmN0aW9uIChwb3B1cCkgeyByZXR1cm4gcG9wdXAuZWxlbWVudCA9PT0gdGFyZ2V0OyB9KTtcbiAgICAgICAgaWYgKGluZGV4T2ZUaGlzQ2hpbGQgPT09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IGluZGV4T2ZUaGlzQ2hpbGQ7IGkgPCB0aGlzLnBvcHVwTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHBvcHVwID0gdGhpcy5wb3B1cExpc3RbaV07XG4gICAgICAgICAgICBpZiAoaXNFbGVtZW50SW5FdmVudFBhdGgocG9wdXAuZWxlbWVudCwgZXZlbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgdGhlIHVzZXIgZGlkIG5vdCB3cml0ZSB0aGVpciBvd24gQ3VzdG9tIEVsZW1lbnQgdG8gYmUgcmVuZGVyZWQgYXMgcG9wdXBcbiAgICAgICAgLy8gYW5kIHRoaXMgY29tcG9uZW50IGhhcyBhbiBhZGRpdGlvbmFsIHBvcHVwIGVsZW1lbnQsIHRoZXkgc2hvdWxkIGhhdmUgdGhlXG4gICAgICAgIC8vIGBhZy1jdXN0b20tY29tcG9uZW50LXBvcHVwYCBjbGFzcyB0byBiZSBkZXRlY3RlZCBhcyBwYXJ0IG9mIHRoZSBDdXN0b20gQ29tcG9uZW50XG4gICAgICAgIHJldHVybiB0aGlzLmlzRWxlbWVudFdpdGhpbkN1c3RvbVBvcHVwKGV2ZW50LnRhcmdldCk7XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLmlzRWxlbWVudFdpdGhpbkN1c3RvbVBvcHVwID0gZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgIHZhciBlRG9jdW1lbnQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb2N1bWVudCgpO1xuICAgICAgICB3aGlsZSAoZWwgJiYgZWwgIT09IGVEb2N1bWVudC5ib2R5KSB7XG4gICAgICAgICAgICBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdhZy1jdXN0b20tY29tcG9uZW50LXBvcHVwJykgfHwgZWwucGFyZW50RWxlbWVudCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWwgPSBlbC5wYXJlbnRFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIC8vIGluIHNvbWUgYnJvd3NlcnMsIHRoZSBjb250ZXh0IG1lbnUgZXZlbnQgY2FuIGJlIGZpcmVkIGJlZm9yZSB0aGUgY2xpY2sgZXZlbnQsIHdoaWNoIG1lYW5zXG4gICAgLy8gdGhlIGNvbnRleHQgbWVudSBldmVudCBjb3VsZCBvcGVuIHRoZSBwb3B1cCwgYnV0IHRoZW4gdGhlIGNsaWNrIGV2ZW50IGNsb3NlcyBpdCBzdHJhaWdodCBhd2F5LlxuICAgIFBvcHVwU2VydmljZS5wcm90b3R5cGUuaXNFdmVudFNhbWVDaGFpbkFzT3JpZ2luYWxFdmVudCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIG9yaWdpbmFsTW91c2VFdmVudCA9IHBhcmFtcy5vcmlnaW5hbE1vdXNlRXZlbnQsIG1vdXNlRXZlbnQgPSBwYXJhbXMubW91c2VFdmVudCwgdG91Y2hFdmVudCA9IHBhcmFtcy50b3VjaEV2ZW50O1xuICAgICAgICAvLyB3ZSBjaGVjayB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIGV2ZW50LCB0byBzZWUgaWYgaXQncyB0aGUgc2FtZSBldmVudC4gdGhlcmUgaXMgYSAxIC8gMTAwMCBjaGFuY2UgdGhhdFxuICAgICAgICAvLyB0aGUgZXZlbnQgaXMgYSBkaWZmZXJlbnQgZXZlbnQsIGhvd2V2ZXIgdGhhdCBpcyBhbiBlZGdlIGNhc2UgdGhhdCBpcyBub3QgdmVyeSByZWxldmFudCAodGhlIHVzZXIgY2xpY2tpbmdcbiAgICAgICAgLy8gdHdpY2Ugb24gdGhlIHNhbWUgbG9jYXRpb24gaXNuJ3QgYSBub3JtYWwgcGF0aCkuXG4gICAgICAgIC8vIGV2ZW50IGNvdWxkIGJlIG1vdXNlIGV2ZW50IG9yIHRvdWNoIGV2ZW50LlxuICAgICAgICB2YXIgbW91c2VFdmVudE9yVG91Y2ggPSBudWxsO1xuICAgICAgICBpZiAobW91c2VFdmVudCkge1xuICAgICAgICAgICAgLy8gbW91c2UgZXZlbnQgY2FuIGJlIHVzZWQgZGlyZWN0aW9uLCBpdCBoYXMgY29vcmRpbmF0ZXNcbiAgICAgICAgICAgIG1vdXNlRXZlbnRPclRvdWNoID0gbW91c2VFdmVudDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0b3VjaEV2ZW50KSB7XG4gICAgICAgICAgICAvLyB0b3VjaCBldmVudCBkb2Vzbid0IGhhdmUgY29vcmRpbmF0ZXMsIG5lZWQgaXQncyB0b3VjaCBvYmplY3RcbiAgICAgICAgICAgIG1vdXNlRXZlbnRPclRvdWNoID0gdG91Y2hFdmVudC50b3VjaGVzWzBdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtb3VzZUV2ZW50T3JUb3VjaCAmJiBvcmlnaW5hbE1vdXNlRXZlbnQpIHtcbiAgICAgICAgICAgIC8vIGZvciB4LCBhbGxvdyA0cHggbWFyZ2luLCB0byBjb3ZlciBpUGFkcywgd2hlcmUgdG91Y2ggKHdoaWNoIG9wZW5zIG1lbnUpIGlzIGZvbGxvd2VkXG4gICAgICAgICAgICAvLyBieSBicm93c2VyIGNsaWNrICh3aGVuIHlvdSBmaW5nZXIgdXAsIHRvdWNoIGlzIGludGVycnVwdGVkIGFzIGNsaWNrIGluIGJyb3dzZXIpXG4gICAgICAgICAgICB2YXIgc2NyZWVuWF8xID0gbW91c2VFdmVudCA/IG1vdXNlRXZlbnQuc2NyZWVuWCA6IDA7XG4gICAgICAgICAgICB2YXIgc2NyZWVuWV8xID0gbW91c2VFdmVudCA/IG1vdXNlRXZlbnQuc2NyZWVuWSA6IDA7XG4gICAgICAgICAgICB2YXIgeE1hdGNoID0gTWF0aC5hYnMob3JpZ2luYWxNb3VzZUV2ZW50LnNjcmVlblggLSBzY3JlZW5YXzEpIDwgNTtcbiAgICAgICAgICAgIHZhciB5TWF0Y2ggPSBNYXRoLmFicyhvcmlnaW5hbE1vdXNlRXZlbnQuc2NyZWVuWSAtIHNjcmVlbllfMSkgPCA1O1xuICAgICAgICAgICAgaWYgKHhNYXRjaCAmJiB5TWF0Y2gpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLmdldFdyYXBwZXIgPSBmdW5jdGlvbiAoZVBvcHVwKSB7XG4gICAgICAgIHdoaWxlICghZVBvcHVwLmNsYXNzTGlzdC5jb250YWlucygnYWctcG9wdXAnKSAmJiBlUG9wdXAucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgZVBvcHVwID0gZVBvcHVwLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVQb3B1cC5jbGFzc0xpc3QuY29udGFpbnMoJ2FnLXBvcHVwJykgPyBlUG9wdXAgOiBudWxsO1xuICAgIH07XG4gICAgUG9wdXBTZXJ2aWNlLnByb3RvdHlwZS5zZXRBbHdheXNPblRvcCA9IGZ1bmN0aW9uIChlUG9wdXAsIGFsd2F5c09uVG9wKSB7XG4gICAgICAgIHZhciBlV3JhcHBlciA9IHRoaXMuZ2V0V3JhcHBlcihlUG9wdXApO1xuICAgICAgICBpZiAoIWVXcmFwcGVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZVdyYXBwZXIuY2xhc3NMaXN0LnRvZ2dsZSgnYWctYWx3YXlzLW9uLXRvcCcsICEhYWx3YXlzT25Ub3ApO1xuICAgICAgICBpZiAoYWx3YXlzT25Ub3ApIHtcbiAgICAgICAgICAgIHRoaXMuYnJpbmdQb3B1cFRvRnJvbnQoZVdyYXBwZXIpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBQb3B1cFNlcnZpY2UucHJvdG90eXBlLmJyaW5nUG9wdXBUb0Zyb250ID0gZnVuY3Rpb24gKGVQb3B1cCkge1xuICAgICAgICB2YXIgcGFyZW50ID0gdGhpcy5nZXRQb3B1cFBhcmVudCgpO1xuICAgICAgICB2YXIgcG9wdXBMaXN0ID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwocGFyZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5hZy1wb3B1cCcpKTtcbiAgICAgICAgdmFyIHBvcHVwTGVuID0gcG9wdXBMaXN0Lmxlbmd0aDtcbiAgICAgICAgdmFyIGFsd2F5c09uVG9wTGlzdCA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHBhcmVudC5xdWVyeVNlbGVjdG9yQWxsKCcuYWctcG9wdXAuYWctYWx3YXlzLW9uLXRvcCcpKTtcbiAgICAgICAgdmFyIG9uVG9wTGVuZ3RoID0gYWx3YXlzT25Ub3BMaXN0Lmxlbmd0aDtcbiAgICAgICAgdmFyIGVXcmFwcGVyID0gdGhpcy5nZXRXcmFwcGVyKGVQb3B1cCk7XG4gICAgICAgIGlmICghZVdyYXBwZXIgfHwgcG9wdXBMZW4gPD0gMSB8fCAhcGFyZW50LmNvbnRhaW5zKGVQb3B1cCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcG9zID0gcG9wdXBMaXN0LmluZGV4T2YoZVdyYXBwZXIpO1xuICAgICAgICB2YXIgaW5uZXJFbHMgPSBlV3JhcHBlci5xdWVyeVNlbGVjdG9yQWxsKCdkaXYnKTtcbiAgICAgICAgdmFyIGlubmVyRWxzU2Nyb2xsTWFwID0gW107XG4gICAgICAgIGlubmVyRWxzLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBpZiAoZWwuc2Nyb2xsVG9wICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgaW5uZXJFbHNTY3JvbGxNYXAucHVzaChbZWwsIGVsLnNjcm9sbFRvcF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG9uVG9wTGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgaXNQb3B1cEFsd2F5c09uVG9wID0gZVdyYXBwZXIuY2xhc3NMaXN0LmNvbnRhaW5zKCdhZy1hbHdheXMtb24tdG9wJyk7XG4gICAgICAgICAgICBpZiAoaXNQb3B1cEFsd2F5c09uVG9wKSB7XG4gICAgICAgICAgICAgICAgaWYgKHBvcyAhPT0gcG9wdXBMZW4gLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGxhc3QoYWx3YXlzT25Ub3BMaXN0KS5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyZW5kJywgZVdyYXBwZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHBvcyAhPT0gcG9wdXBMZW4gLSBvblRvcExlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICBhbHdheXNPblRvcExpc3RbMF0uaW5zZXJ0QWRqYWNlbnRFbGVtZW50KCdiZWZvcmViZWdpbicsIGVXcmFwcGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChwb3MgIT09IHBvcHVwTGVuIC0gMSkge1xuICAgICAgICAgICAgbGFzdChwb3B1cExpc3QpLmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJlbmQnLCBlV3JhcHBlcik7XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKGlubmVyRWxzU2Nyb2xsTWFwLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRFbCA9IGlubmVyRWxzU2Nyb2xsTWFwLnBvcCgpO1xuICAgICAgICAgICAgY3VycmVudEVsWzBdLnNjcm9sbFRvcCA9IGN1cnJlbnRFbFsxXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgdHlwZTogJ3BvcHVwVG9Gcm9udCcsXG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgIGVXcmFwcGVyOiBlV3JhcHBlclxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KHBhcmFtcyk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJE8oW1xuICAgICAgICBBdXRvd2lyZWQoJ2Vudmlyb25tZW50JylcbiAgICBdLCBQb3B1cFNlcnZpY2UucHJvdG90eXBlLCBcImVudmlyb25tZW50XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIFBvcHVwU2VydmljZS5wcm90b3R5cGUsIFwiZm9jdXNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRPKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIFBvcHVwU2VydmljZS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRPKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFBvcHVwU2VydmljZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICBQb3B1cFNlcnZpY2UgPSBfX2RlY29yYXRlJE8oW1xuICAgICAgICBCZWFuKCdwb3B1cFNlcnZpY2UnKVxuICAgIF0sIFBvcHVwU2VydmljZSk7XG4gICAgcmV0dXJuIFBvcHVwU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRMID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSROID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgVmlydHVhbExpc3QgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEwoVmlydHVhbExpc3QsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVmlydHVhbExpc3QoY3NzSWRlbnRpZmllciwgYXJpYVJvbGUsIGxpc3ROYW1lKSB7XG4gICAgICAgIGlmIChjc3NJZGVudGlmaWVyID09PSB2b2lkIDApIHsgY3NzSWRlbnRpZmllciA9ICdkZWZhdWx0JzsgfVxuICAgICAgICBpZiAoYXJpYVJvbGUgPT09IHZvaWQgMCkgeyBhcmlhUm9sZSA9ICdsaXN0Ym94JzsgfVxuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBWaXJ0dWFsTGlzdC5nZXRUZW1wbGF0ZShjc3NJZGVudGlmaWVyKSkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY3NzSWRlbnRpZmllciA9IGNzc0lkZW50aWZpZXI7XG4gICAgICAgIF90aGlzLmFyaWFSb2xlID0gYXJpYVJvbGU7XG4gICAgICAgIF90aGlzLmxpc3ROYW1lID0gbGlzdE5hbWU7XG4gICAgICAgIF90aGlzLnJlbmRlcmVkUm93cyA9IG5ldyBNYXAoKTtcbiAgICAgICAgX3RoaXMucm93SGVpZ2h0ID0gMjA7XG4gICAgICAgIF90aGlzLmlzRGVzdHJveWVkID0gZmFsc2U7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkU2Nyb2xsTGlzdGVuZXIoKTtcbiAgICAgICAgdGhpcy5yb3dIZWlnaHQgPSB0aGlzLmdldEl0ZW1IZWlnaHQoKTtcbiAgICAgICAgdGhpcy5hZGRSZXNpemVPYnNlcnZlcigpO1xuICAgICAgICB0aGlzLmluaXRpYWxpc2VUYWJHdWFyZCh7XG4gICAgICAgICAgICBvbkZvY3VzSW46IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vbkZvY3VzSW4oZSk7IH0sXG4gICAgICAgICAgICBvbkZvY3VzT3V0OiBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMub25Gb2N1c091dChlKTsgfSxcbiAgICAgICAgICAgIGZvY3VzSW5uZXJFbGVtZW50OiBmdW5jdGlvbiAoZnJvbUJvdHRvbSkgeyByZXR1cm4gX3RoaXMuZm9jdXNJbm5lckVsZW1lbnQoZnJvbUJvdHRvbSk7IH0sXG4gICAgICAgICAgICBvblRhYktleURvd246IGZ1bmN0aW9uIChlKSB7IHJldHVybiBfdGhpcy5vblRhYktleURvd24oZSk7IH0sXG4gICAgICAgICAgICBoYW5kbGVLZXlEb3duOiBmdW5jdGlvbiAoZSkgeyByZXR1cm4gX3RoaXMuaGFuZGxlS2V5RG93bihlKTsgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zZXRBcmlhUHJvcGVydGllcygpO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLnNldEFyaWFQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdHJhbnNsYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIGxpc3ROYW1lID0gdHJhbnNsYXRlKCdhcmlhRGVmYXVsdExpc3ROYW1lJywgdGhpcy5saXN0TmFtZSB8fCAnTGlzdCcpO1xuICAgICAgICB2YXIgYXJpYUVsID0gdGhpcy5lQ29udGFpbmVyO1xuICAgICAgICBzZXRBcmlhUm9sZShhcmlhRWwsIHRoaXMuYXJpYVJvbGUpO1xuICAgICAgICBzZXRBcmlhTGFiZWwoYXJpYUVsLCBsaXN0TmFtZSk7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuYWRkUmVzaXplT2JzZXJ2ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lciA9IHRoaXMuZHJhd1ZpcnR1YWxSb3dzLmJpbmQodGhpcyk7XG4gICAgICAgIHZhciBkZXN0cm95T2JzZXJ2ZXIgPSB0aGlzLnJlc2l6ZU9ic2VydmVyU2VydmljZS5vYnNlcnZlUmVzaXplKHRoaXMuZ2V0R3VpKCksIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhkZXN0cm95T2JzZXJ2ZXIpO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLmZvY3VzSW5uZXJFbGVtZW50ID0gZnVuY3Rpb24gKGZyb21Cb3R0b20pIHtcbiAgICAgICAgdGhpcy5mb2N1c1Jvdyhmcm9tQm90dG9tID8gdGhpcy5tb2RlbC5nZXRSb3dDb3VudCgpIC0gMSA6IDApO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLm9uRm9jdXNJbiA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldDtcbiAgICAgICAgaWYgKHRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoJ2FnLXZpcnR1YWwtbGlzdC1pdGVtJykpIHtcbiAgICAgICAgICAgIHRoaXMubGFzdEZvY3VzZWRSb3dJbmRleCA9IGdldEFyaWFQb3NJblNldCh0YXJnZXQpIC0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUub25Gb2N1c091dCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGlmICghdGhpcy5nZXRGb2N1c2FibGVFbGVtZW50KCkuY29udGFpbnMoZS5yZWxhdGVkVGFyZ2V0KSkge1xuICAgICAgICAgICAgdGhpcy5sYXN0Rm9jdXNlZFJvd0luZGV4ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuaGFuZGxlS2V5RG93biA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHN3aXRjaCAoZS5rZXkpIHtcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5VUDpcbiAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm5hdmlnYXRlKGUua2V5ID09PSBLZXlDb2RlLlVQKSkge1xuICAgICAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUub25UYWJLZXlEb3duID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKHRoaXMubmF2aWdhdGUoZS5zaGlmdEtleSkpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZvY3VzIG9uIHRoZSBmaXJzdCBvciBsYXN0IGZvY3VzYWJsZSBlbGVtZW50IHRvIGVuc3VyZSB0aGF0IGFueSBvdGhlciBoYW5kbGVycyBzdGFydCBmcm9tIHRoZXJlXG4gICAgICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5mb2N1c0ludG8odGhpcy5nZXRHdWkoKSwgIWUuc2hpZnRLZXkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUubmF2aWdhdGUgPSBmdW5jdGlvbiAodXApIHtcbiAgICAgICAgaWYgKHRoaXMubGFzdEZvY3VzZWRSb3dJbmRleCA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5leHRSb3cgPSB0aGlzLmxhc3RGb2N1c2VkUm93SW5kZXggKyAodXAgPyAtMSA6IDEpO1xuICAgICAgICBpZiAobmV4dFJvdyA8IDAgfHwgbmV4dFJvdyA+PSB0aGlzLm1vZGVsLmdldFJvd0NvdW50KCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvY3VzUm93KG5leHRSb3cpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIFZpcnR1YWxMaXN0LnByb3RvdHlwZS5nZXRMYXN0Rm9jdXNlZFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGFzdEZvY3VzZWRSb3dJbmRleDtcbiAgICB9O1xuICAgIFZpcnR1YWxMaXN0LnByb3RvdHlwZS5mb2N1c1JvdyA9IGZ1bmN0aW9uIChyb3dOdW1iZXIpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5lbnN1cmVJbmRleFZpc2libGUocm93TnVtYmVyKTtcbiAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHJlbmRlcmVkUm93ID0gX3RoaXMucmVuZGVyZWRSb3dzLmdldChyb3dOdW1iZXIpO1xuICAgICAgICAgICAgaWYgKHJlbmRlcmVkUm93KSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyZWRSb3cuZURpdi5mb2N1cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAxMCk7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuZ2V0Q29tcG9uZW50QXQgPSBmdW5jdGlvbiAocm93SW5kZXgpIHtcbiAgICAgICAgdmFyIGNvbXAgPSB0aGlzLnJlbmRlcmVkUm93cy5nZXQocm93SW5kZXgpO1xuICAgICAgICByZXR1cm4gY29tcCAmJiBjb21wLnJvd0NvbXBvbmVudDtcbiAgICB9O1xuICAgIFZpcnR1YWxMaXN0LnByb3RvdHlwZS5mb3JFYWNoUmVuZGVyZWRSb3cgPSBmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICB0aGlzLnJlbmRlcmVkUm93cy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7IHJldHVybiBmdW5jKHZhbHVlLnJvd0NvbXBvbmVudCwga2V5KTsgfSk7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5nZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uIChjc3NJZGVudGlmaWVyKSB7XG4gICAgICAgIHJldHVybiAvKiBodG1sICovIFwiXFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctdmlydHVhbC1saXN0LXZpZXdwb3J0IGFnLVwiICsgY3NzSWRlbnRpZmllciArIFwiLXZpcnR1YWwtbGlzdC12aWV3cG9ydFxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctdmlydHVhbC1saXN0LWNvbnRhaW5lciBhZy1cIiArIGNzc0lkZW50aWZpZXIgKyBcIi12aXJ0dWFsLWxpc3QtY29udGFpbmVyXFxcIiByZWY9XFxcImVDb250YWluZXJcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgIDwvZGl2PlwiO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLmdldEl0ZW1IZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRMaXN0SXRlbUhlaWdodCgpO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLmVuc3VyZUluZGV4VmlzaWJsZSA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICB2YXIgbGFzdFJvdyA9IHRoaXMubW9kZWwuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgaWYgKHR5cGVvZiBpbmRleCAhPT0gJ251bWJlcicgfHwgaW5kZXggPCAwIHx8IGluZGV4ID49IGxhc3RSb3cpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogaW52YWxpZCByb3cgaW5kZXggZm9yIGVuc3VyZUluZGV4VmlzaWJsZTogJyArIGluZGV4KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93VG9wUGl4ZWwgPSBpbmRleCAqIHRoaXMucm93SGVpZ2h0O1xuICAgICAgICB2YXIgcm93Qm90dG9tUGl4ZWwgPSByb3dUb3BQaXhlbCArIHRoaXMucm93SGVpZ2h0O1xuICAgICAgICB2YXIgZUd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIHZhciB2aWV3cG9ydFRvcFBpeGVsID0gZUd1aS5zY3JvbGxUb3A7XG4gICAgICAgIHZhciB2aWV3cG9ydEhlaWdodCA9IGVHdWkub2Zmc2V0SGVpZ2h0O1xuICAgICAgICB2YXIgdmlld3BvcnRCb3R0b21QaXhlbCA9IHZpZXdwb3J0VG9wUGl4ZWwgKyB2aWV3cG9ydEhlaWdodDtcbiAgICAgICAgdmFyIHZpZXdwb3J0U2Nyb2xsZWRQYXN0Um93ID0gdmlld3BvcnRUb3BQaXhlbCA+IHJvd1RvcFBpeGVsO1xuICAgICAgICB2YXIgdmlld3BvcnRTY3JvbGxlZEJlZm9yZVJvdyA9IHZpZXdwb3J0Qm90dG9tUGl4ZWwgPCByb3dCb3R0b21QaXhlbDtcbiAgICAgICAgaWYgKHZpZXdwb3J0U2Nyb2xsZWRQYXN0Um93KSB7XG4gICAgICAgICAgICAvLyBpZiByb3cgaXMgYmVmb3JlLCBzY3JvbGwgdXAgd2l0aCByb3cgYXQgdG9wXG4gICAgICAgICAgICBlR3VpLnNjcm9sbFRvcCA9IHJvd1RvcFBpeGVsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHZpZXdwb3J0U2Nyb2xsZWRCZWZvcmVSb3cpIHtcbiAgICAgICAgICAgIC8vIGlmIHJvdyBpcyBiZWxvdywgc2Nyb2xsIGRvd24gd2l0aCByb3cgYXQgYm90dG9tXG4gICAgICAgICAgICB2YXIgbmV3U2Nyb2xsUG9zaXRpb24gPSByb3dCb3R0b21QaXhlbCAtIHZpZXdwb3J0SGVpZ2h0O1xuICAgICAgICAgICAgZUd1aS5zY3JvbGxUb3AgPSBuZXdTY3JvbGxQb3NpdGlvbjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLnNldENvbXBvbmVudENyZWF0b3IgPSBmdW5jdGlvbiAoY29tcG9uZW50Q3JlYXRvcikge1xuICAgICAgICB0aGlzLmNvbXBvbmVudENyZWF0b3IgPSBjb21wb25lbnRDcmVhdG9yO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLmdldFJvd0hlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm93SGVpZ2h0O1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLmdldFNjcm9sbFRvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0R3VpKCkuc2Nyb2xsVG9wO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLnNldFJvd0hlaWdodCA9IGZ1bmN0aW9uIChyb3dIZWlnaHQpIHtcbiAgICAgICAgdGhpcy5yb3dIZWlnaHQgPSByb3dIZWlnaHQ7XG4gICAgICAgIHRoaXMucmVmcmVzaCgpO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLm1vZGVsID09IG51bGwgfHwgdGhpcy5pc0Rlc3Ryb3llZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dDb3VudCA9IHRoaXMubW9kZWwuZ2V0Um93Q291bnQoKTtcbiAgICAgICAgdGhpcy5lQ29udGFpbmVyLnN0eWxlLmhlaWdodCA9IHJvd0NvdW50ICogdGhpcy5yb3dIZWlnaHQgKyBcInB4XCI7XG4gICAgICAgIC8vIGVuc3VyZSBoZWlnaHQgaXMgYXBwbGllZCBiZWZvcmUgYXR0ZW1wdGluZyB0byByZWRyYXcgcm93c1xuICAgICAgICB3YWl0VW50aWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZUNvbnRhaW5lci5jbGllbnRIZWlnaHQgPj0gcm93Q291bnQgKiBfdGhpcy5yb3dIZWlnaHQ7IH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5pc0Rlc3Ryb3llZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLmNsZWFyVmlydHVhbFJvd3MoKTtcbiAgICAgICAgICAgIF90aGlzLmRyYXdWaXJ0dWFsUm93cygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFZpcnR1YWxMaXN0LnByb3RvdHlwZS5jbGVhclZpcnR1YWxSb3dzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJlbmRlcmVkUm93cy5mb3JFYWNoKGZ1bmN0aW9uIChfLCByb3dJbmRleCkgeyByZXR1cm4gX3RoaXMucmVtb3ZlUm93KHJvd0luZGV4KTsgfSk7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuZHJhd1ZpcnR1YWxSb3dzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNBbGl2ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGd1aSA9IHRoaXMuZ2V0R3VpKCk7XG4gICAgICAgIHZhciB0b3BQaXhlbCA9IGd1aS5zY3JvbGxUb3A7XG4gICAgICAgIHZhciBib3R0b21QaXhlbCA9IHRvcFBpeGVsICsgZ3VpLm9mZnNldEhlaWdodDtcbiAgICAgICAgdmFyIGZpcnN0Um93ID0gTWF0aC5mbG9vcih0b3BQaXhlbCAvIHRoaXMucm93SGVpZ2h0KTtcbiAgICAgICAgdmFyIGxhc3RSb3cgPSBNYXRoLmZsb29yKGJvdHRvbVBpeGVsIC8gdGhpcy5yb3dIZWlnaHQpO1xuICAgICAgICB0aGlzLmVuc3VyZVJvd3NSZW5kZXJlZChmaXJzdFJvdywgbGFzdFJvdyk7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuZW5zdXJlUm93c1JlbmRlcmVkID0gZnVuY3Rpb24gKHN0YXJ0LCBmaW5pc2gpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgLy8gcmVtb3ZlIGFueSByb3dzIHRoYXQgYXJlIG5vIGxvbmdlciByZXF1aXJlZFxuICAgICAgICB0aGlzLnJlbmRlcmVkUm93cy5mb3JFYWNoKGZ1bmN0aW9uIChfLCByb3dJbmRleCkge1xuICAgICAgICAgICAgaWYgKChyb3dJbmRleCA8IHN0YXJ0IHx8IHJvd0luZGV4ID4gZmluaXNoKSAmJiByb3dJbmRleCAhPT0gX3RoaXMubGFzdEZvY3VzZWRSb3dJbmRleCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnJlbW92ZVJvdyhyb3dJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBpbnNlcnQgYW55IHJlcXVpcmVkIG5ldyByb3dzXG4gICAgICAgIGZvciAodmFyIHJvd0luZGV4ID0gc3RhcnQ7IHJvd0luZGV4IDw9IGZpbmlzaDsgcm93SW5kZXgrKykge1xuICAgICAgICAgICAgaWYgKHRoaXMucmVuZGVyZWRSb3dzLmhhcyhyb3dJbmRleCkpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGNoZWNrIHRoaXMgcm93IGFjdHVhbGx5IGV4aXN0cyAoaW4gY2FzZSBvdmVyZmxvdyBidWZmZXIgd2luZG93IGV4Y2VlZHMgcmVhbCBkYXRhKVxuICAgICAgICAgICAgaWYgKHJvd0luZGV4IDwgdGhpcy5tb2RlbC5nZXRSb3dDb3VudCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnNlcnRSb3cocm93SW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuaW5zZXJ0Um93ID0gZnVuY3Rpb24gKHJvd0luZGV4KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB2YWx1ZSA9IHRoaXMubW9kZWwuZ2V0Um93KHJvd0luZGV4KTtcbiAgICAgICAgdmFyIGVEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZURpdi5jbGFzc0xpc3QuYWRkKCdhZy12aXJ0dWFsLWxpc3QtaXRlbScsIFwiYWctXCIgKyB0aGlzLmNzc0lkZW50aWZpZXIgKyBcIi12aXJ0dWFsLWxpc3QtaXRlbVwiKTtcbiAgICAgICAgc2V0QXJpYVJvbGUoZURpdiwgdGhpcy5hcmlhUm9sZSA9PT0gJ3RyZWUnID8gJ3RyZWVpdGVtJyA6ICdvcHRpb24nKTtcbiAgICAgICAgc2V0QXJpYVNldFNpemUoZURpdiwgdGhpcy5tb2RlbC5nZXRSb3dDb3VudCgpKTtcbiAgICAgICAgc2V0QXJpYVBvc0luU2V0KGVEaXYsIHJvd0luZGV4ICsgMSk7XG4gICAgICAgIGVEaXYuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICctMScpO1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMubW9kZWwuaXNSb3dTZWxlY3RlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdmFyIGlzU2VsZWN0ZWQgPSB0aGlzLm1vZGVsLmlzUm93U2VsZWN0ZWQocm93SW5kZXgpO1xuICAgICAgICAgICAgc2V0QXJpYVNlbGVjdGVkKGVEaXYsICEhaXNTZWxlY3RlZCk7XG4gICAgICAgICAgICBzZXRBcmlhQ2hlY2tlZChlRGl2LCBpc1NlbGVjdGVkKTtcbiAgICAgICAgfVxuICAgICAgICBlRGl2LnN0eWxlLmhlaWdodCA9IHRoaXMucm93SGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICBlRGl2LnN0eWxlLnRvcCA9IHRoaXMucm93SGVpZ2h0ICogcm93SW5kZXggKyBcInB4XCI7XG4gICAgICAgIHZhciByb3dDb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudENyZWF0b3IodmFsdWUsIGVEaXYpO1xuICAgICAgICByb3dDb21wb25lbnQuYWRkR3VpRXZlbnRMaXN0ZW5lcignZm9jdXNpbicsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLmxhc3RGb2N1c2VkUm93SW5kZXggPSByb3dJbmRleDsgfSk7XG4gICAgICAgIGVEaXYuYXBwZW5kQ2hpbGQocm93Q29tcG9uZW50LmdldEd1aSgpKTtcbiAgICAgICAgLy8ga2VlcCB0aGUgRE9NIG9yZGVyIGNvbnNpc3RlbnQgd2l0aCB0aGUgb3JkZXIgb2YgdGhlIHJvd3NcbiAgICAgICAgaWYgKHRoaXMucmVuZGVyZWRSb3dzLmhhcyhyb3dJbmRleCAtIDEpKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVkUm93cy5nZXQocm93SW5kZXggLSAxKS5lRGl2Lmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJlbmQnLCBlRGl2KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnJlbmRlcmVkUm93cy5oYXMocm93SW5kZXggKyAxKSkge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJlZFJvd3MuZ2V0KHJvd0luZGV4ICsgMSkuZURpdi5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2JlZm9yZWJlZ2luJywgZURpdik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmVDb250YWluZXIuYXBwZW5kQ2hpbGQoZURpdik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJlZFJvd3Muc2V0KHJvd0luZGV4LCB7IHJvd0NvbXBvbmVudDogcm93Q29tcG9uZW50LCBlRGl2OiBlRGl2IH0pO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLnJlbW92ZVJvdyA9IGZ1bmN0aW9uIChyb3dJbmRleCkge1xuICAgICAgICB2YXIgY29tcG9uZW50ID0gdGhpcy5yZW5kZXJlZFJvd3MuZ2V0KHJvd0luZGV4KTtcbiAgICAgICAgdGhpcy5lQ29udGFpbmVyLnJlbW92ZUNoaWxkKGNvbXBvbmVudC5lRGl2KTtcbiAgICAgICAgdGhpcy5kZXN0cm95QmVhbihjb21wb25lbnQucm93Q29tcG9uZW50KTtcbiAgICAgICAgdGhpcy5yZW5kZXJlZFJvd3MuZGVsZXRlKHJvd0luZGV4KTtcbiAgICB9O1xuICAgIFZpcnR1YWxMaXN0LnByb3RvdHlwZS5hZGRTY3JvbGxMaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hZGRHdWlFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5kcmF3VmlydHVhbFJvd3MoKTsgfSk7XG4gICAgfTtcbiAgICBWaXJ0dWFsTGlzdC5wcm90b3R5cGUuc2V0TW9kZWwgPSBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgdGhpcy5tb2RlbCA9IG1vZGVsO1xuICAgIH07XG4gICAgVmlydHVhbExpc3QucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzRGVzdHJveWVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGVhclZpcnR1YWxSb3dzKCk7XG4gICAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlO1xuICAgICAgICBfc3VwZXIucHJvdG90eXBlLmRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkTihbXG4gICAgICAgIEF1dG93aXJlZCgncmVzaXplT2JzZXJ2ZXJTZXJ2aWNlJylcbiAgICBdLCBWaXJ0dWFsTGlzdC5wcm90b3R5cGUsIFwicmVzaXplT2JzZXJ2ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSROKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIFZpcnR1YWxMaXN0LnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJE4oW1xuICAgICAgICBSZWZTZWxlY3RvcignZUNvbnRhaW5lcicpXG4gICAgXSwgVmlydHVhbExpc3QucHJvdG90eXBlLCBcImVDb250YWluZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJE4oW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgVmlydHVhbExpc3QucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFZpcnR1YWxMaXN0O1xufShUYWJHdWFyZENvbXApKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIE9VVFNJREVfQU5HVUxBUl9FVkVOVFMgPSBbJ21vdXNlb3ZlcicsICdtb3VzZW91dCcsICdtb3VzZWVudGVyJywgJ21vdXNlbGVhdmUnXTtcbnZhciBQQVNTSVZFX0VWRU5UUyA9IFsndG91Y2hzdGFydCcsICd0b3VjaGVuZCcsICd0b3VjaG1vdmUnLCAndG91Y2hjYW5jZWwnXTtcbi8qKiBUaGUgYmFzZSBmcmFtZXdvcmtzLCBlZyBSZWFjdCAmIEFuZ3VsYXIsIG92ZXJyaWRlIHRoaXMgYmVhbiB3aXRoIGltcGxlbWVudGF0aW9ucyBzcGVjaWZpYyB0byB0aGVpciByZXF1aXJlbWVudC4gKi9cbnZhciBWYW5pbGxhRnJhbWV3b3JrT3ZlcnJpZGVzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFZhbmlsbGFGcmFtZXdvcmtPdmVycmlkZXMoKSB7XG4gICAgICAgIHRoaXMuaXNPdXRzaWRlQW5ndWxhciA9IGZ1bmN0aW9uIChldmVudFR5cGUpIHsgcmV0dXJuIGluY2x1ZGVzKE9VVFNJREVfQU5HVUxBUl9FVkVOVFMsIGV2ZW50VHlwZSk7IH07XG4gICAgfVxuICAgIC8vIGZvciBWYW5pbGxhIEpTLCB3ZSB1c2Ugc2ltcGxlIHRpbWVvdXRcbiAgICBWYW5pbGxhRnJhbWV3b3JrT3ZlcnJpZGVzLnByb3RvdHlwZS5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKGFjdGlvbiwgdGltZW91dCkge1xuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChhY3Rpb24sIHRpbWVvdXQpO1xuICAgIH07XG4gICAgVmFuaWxsYUZyYW1ld29ya092ZXJyaWRlcy5wcm90b3R5cGUuc2V0SW50ZXJ2YWwgPSBmdW5jdGlvbiAoYWN0aW9uLCB0aW1lb3V0KSB7XG4gICAgICAgIHJldHVybiBuZXcgQWdQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgICAgICByZXNvbHZlKHdpbmRvdy5zZXRJbnRlcnZhbChhY3Rpb24sIHRpbWVvdXQpKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBmb3IgVmFuaWxsYSBKUywgd2UganVzdCBhZGQgdGhlIGV2ZW50IHRvIHRoZSBlbGVtZW50XG4gICAgVmFuaWxsYUZyYW1ld29ya092ZXJyaWRlcy5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChlbGVtZW50LCB0eXBlLCBsaXN0ZW5lciwgdXNlQ2FwdHVyZSkge1xuICAgICAgICB2YXIgaXNQYXNzaXZlID0gaW5jbHVkZXMoUEFTU0lWRV9FVkVOVFMsIHR5cGUpO1xuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIsIHsgY2FwdHVyZTogISF1c2VDYXB0dXJlLCBwYXNzaXZlOiBpc1Bhc3NpdmUgfSk7XG4gICAgfTtcbiAgICAvLyBmb3IgVmFuaWxsYSBKUywgd2UganVzdCBleGVjdXRlIHRoZSBsaXN0ZW5lclxuICAgIFZhbmlsbGFGcmFtZXdvcmtPdmVycmlkZXMucHJvdG90eXBlLmRpc3BhdGNoRXZlbnQgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lciwgZ2xvYmFsKSB7XG4gICAgICAgIGxpc3RlbmVyKCk7XG4gICAgfTtcbiAgICBWYW5pbGxhRnJhbWV3b3JrT3ZlcnJpZGVzLnByb3RvdHlwZS5mcmFtZXdvcmtDb21wb25lbnQgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIFZhbmlsbGFGcmFtZXdvcmtPdmVycmlkZXMucHJvdG90eXBlLmlzRnJhbWV3b3JrQ29tcG9uZW50ID0gZnVuY3Rpb24gKGNvbXApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgcmV0dXJuIFZhbmlsbGFGcmFtZXdvcmtPdmVycmlkZXM7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJEsgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJE0gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3JlYWQkNSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCQ0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19zcHJlYWQpIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXIgPSBhci5jb25jYXQoX19yZWFkJDUoYXJndW1lbnRzW2ldKSk7XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBDZWxsTmF2aWdhdGlvblNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEsoQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENlbGxOYXZpZ2F0aW9uU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICAvLyByZXR1cm5zIG51bGwgaWYgbm8gY2VsbCB0byBmb2N1cyBvbiwgaWUgYXQgdGhlIGVuZCBvZiB0aGUgZ3JpZFxuICAgIENlbGxOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0TmV4dENlbGxUb0ZvY3VzID0gZnVuY3Rpb24gKGtleSwgZm9jdXNlZENlbGwsIGN0cmxQcmVzc2VkKSB7XG4gICAgICAgIGlmIChjdHJsUHJlc3NlZCA9PT0gdm9pZCAwKSB7IGN0cmxQcmVzc2VkID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKGN0cmxQcmVzc2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXROZXh0Q2VsbFRvRm9jdXNXaXRoQ3RybFByZXNzZWQoa2V5LCBmb2N1c2VkQ2VsbCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TmV4dENlbGxUb0ZvY3VzV2l0aG91dEN0cmxQcmVzc2VkKGtleSwgZm9jdXNlZENlbGwpO1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROZXh0Q2VsbFRvRm9jdXNXaXRoQ3RybFByZXNzZWQgPSBmdW5jdGlvbiAoa2V5LCBmb2N1c2VkQ2VsbCkge1xuICAgICAgICB2YXIgdXBLZXkgPSBrZXkgPT09IEtleUNvZGUuVVA7XG4gICAgICAgIHZhciBkb3duS2V5ID0ga2V5ID09PSBLZXlDb2RlLkRPV047XG4gICAgICAgIHZhciBsZWZ0S2V5ID0ga2V5ID09PSBLZXlDb2RlLkxFRlQ7XG4gICAgICAgIHZhciBjb2x1bW47XG4gICAgICAgIHZhciByb3dJbmRleDtcbiAgICAgICAgaWYgKHVwS2V5IHx8IGRvd25LZXkpIHtcbiAgICAgICAgICAgIHJvd0luZGV4ID0gdXBLZXkgPyB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlRmlyc3RSb3coKSA6IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VMYXN0Um93KCk7XG4gICAgICAgICAgICBjb2x1bW4gPSBmb2N1c2VkQ2VsbC5jb2x1bW47XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgYWxsQ29sdW1ucyA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucygpO1xuICAgICAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKTtcbiAgICAgICAgICAgIHJvd0luZGV4ID0gZm9jdXNlZENlbGwucm93SW5kZXg7XG4gICAgICAgICAgICBjb2x1bW4gPSBsZWZ0S2V5ICE9PSBpc1J0bCA/IGFsbENvbHVtbnNbMF0gOiBsYXN0KGFsbENvbHVtbnMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByb3dJbmRleDogcm93SW5kZXgsXG4gICAgICAgICAgICByb3dQaW5uZWQ6IG51bGwsXG4gICAgICAgICAgICBjb2x1bW46IGNvbHVtblxuICAgICAgICB9O1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROZXh0Q2VsbFRvRm9jdXNXaXRob3V0Q3RybFByZXNzZWQgPSBmdW5jdGlvbiAoa2V5LCBmb2N1c2VkQ2VsbCkge1xuICAgICAgICAvLyBzdGFydGluZyB3aXRoIHRoZSBwcm92aWRlZCBjZWxsLCB3ZSBrZWVwIG1vdmluZyB1bnRpbCB3ZSBmaW5kIGEgY2VsbCB3ZSBjYW5cbiAgICAgICAgLy8gZm9jdXMgb24uXG4gICAgICAgIHZhciBwb2ludGVyID0gZm9jdXNlZENlbGw7XG4gICAgICAgIHZhciBmaW5pc2hlZCA9IGZhbHNlO1xuICAgICAgICAvLyBmaW5pc2hlZCB3aWxsIGJlIHRydWUgd2hlbiBlaXRoZXI6XG4gICAgICAgIC8vIGEpIGNlbGwgZm91bmQgdGhhdCB3ZSBjYW4gZm9jdXMgb25cbiAgICAgICAgLy8gYikgcnVuIG91dCBvZiBjZWxscyAoaWUgdGhlIG1ldGhvZCByZXR1cm5zIG51bGwpXG4gICAgICAgIHdoaWxlICghZmluaXNoZWQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBLZXlDb2RlLlVQOlxuICAgICAgICAgICAgICAgICAgICBwb2ludGVyID0gdGhpcy5nZXRDZWxsQWJvdmUocG9pbnRlcik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgICAgICAgICBwb2ludGVyID0gdGhpcy5nZXRDZWxsQmVsb3cocG9pbnRlcik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgS2V5Q29kZS5SSUdIVDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXIgPSB0aGlzLmdldENlbGxUb0xlZnQocG9pbnRlcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyID0gdGhpcy5nZXRDZWxsVG9SaWdodChwb2ludGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEtleUNvZGUuTEVGVDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRW5hYmxlUnRsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXIgPSB0aGlzLmdldENlbGxUb1JpZ2h0KHBvaW50ZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRlciA9IHRoaXMuZ2V0Q2VsbFRvTGVmdChwb2ludGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBwb2ludGVyID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiB1bmtub3duIGtleSBmb3IgbmF2aWdhdGlvbiAnICsga2V5KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocG9pbnRlcikge1xuICAgICAgICAgICAgICAgIGZpbmlzaGVkID0gdGhpcy5pc0NlbGxHb29kVG9Gb2N1c09uKHBvaW50ZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZmluaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwb2ludGVyO1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5pc0NlbGxHb29kVG9Gb2N1c09uID0gZnVuY3Rpb24gKGdyaWRDZWxsKSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSBncmlkQ2VsbC5jb2x1bW47XG4gICAgICAgIHZhciByb3dOb2RlO1xuICAgICAgICBzd2l0Y2ggKGdyaWRDZWxsLnJvd1Bpbm5lZCkge1xuICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX1RPUDpcbiAgICAgICAgICAgICAgICByb3dOb2RlID0gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRUb3BSb3coZ3JpZENlbGwucm93SW5kZXgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX0JPVFRPTTpcbiAgICAgICAgICAgICAgICByb3dOb2RlID0gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Sb3coZ3JpZENlbGwucm93SW5kZXgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByb3dOb2RlID0gdGhpcy5yb3dNb2RlbC5nZXRSb3coZ3JpZENlbGwucm93SW5kZXgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcm93Tm9kZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzdXBwcmVzc05hdmlnYWJsZSA9IGNvbHVtbi5pc1N1cHByZXNzTmF2aWdhYmxlKHJvd05vZGUpO1xuICAgICAgICByZXR1cm4gIXN1cHByZXNzTmF2aWdhYmxlO1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRDZWxsVG9MZWZ0ID0gZnVuY3Rpb24gKGxhc3RDZWxsKSB7XG4gICAgICAgIGlmICghbGFzdENlbGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb2xUb0xlZnQgPSB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbEJlZm9yZShsYXN0Q2VsbC5jb2x1bW4pO1xuICAgICAgICBpZiAoIWNvbFRvTGVmdCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvd0luZGV4OiBsYXN0Q2VsbC5yb3dJbmRleCxcbiAgICAgICAgICAgIGNvbHVtbjogY29sVG9MZWZ0LFxuICAgICAgICAgICAgcm93UGlubmVkOiBsYXN0Q2VsbC5yb3dQaW5uZWRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENlbGxOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0Q2VsbFRvUmlnaHQgPSBmdW5jdGlvbiAobGFzdENlbGwpIHtcbiAgICAgICAgaWYgKCFsYXN0Q2VsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbFRvUmlnaHQgPSB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbEFmdGVyKGxhc3RDZWxsLmNvbHVtbik7XG4gICAgICAgIC8vIGlmIGFscmVhZHkgb24gcmlnaHQsIGRvIG5vdGhpbmdcbiAgICAgICAgaWYgKCFjb2xUb1JpZ2h0KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93SW5kZXg6IGxhc3RDZWxsLnJvd0luZGV4LFxuICAgICAgICAgICAgY29sdW1uOiBjb2xUb1JpZ2h0LFxuICAgICAgICAgICAgcm93UGlubmVkOiBsYXN0Q2VsbC5yb3dQaW5uZWRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENlbGxOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0Um93QmVsb3cgPSBmdW5jdGlvbiAocm93UG9zaXRpb24pIHtcbiAgICAgICAgLy8gaWYgYWxyZWFkeSBvbiB0b3Agcm93LCBkbyBub3RoaW5nXG4gICAgICAgIHZhciBpbmRleCA9IHJvd1Bvc2l0aW9uLnJvd0luZGV4O1xuICAgICAgICB2YXIgcGlubmVkID0gcm93UG9zaXRpb24ucm93UGlubmVkO1xuICAgICAgICBpZiAodGhpcy5pc0xhc3RSb3dJbkNvbnRhaW5lcihyb3dQb3NpdGlvbikpIHtcbiAgICAgICAgICAgIHN3aXRjaCAocGlubmVkKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX0JPVFRPTTpcbiAgICAgICAgICAgICAgICAgICAgLy8gbmV2ZXIgYW55IHJvd3MgYWZ0ZXIgcGlubmVkIGJvdHRvbVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfVE9QOlxuICAgICAgICAgICAgICAgICAgICAvLyBpZiBvbiBsYXN0IHJvdyBvZiBwaW5uZWQgdG9wLCB0aGVuIG5leHQgcm93IGlzIG1haW4gYm9keSAoaWYgcm93cyBleGlzdCksXG4gICAgICAgICAgICAgICAgICAgIC8vIG90aGVyd2lzZSBpdCdzIHRoZSBwaW5uZWQgYm90dG9tXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJvd01vZGVsLmlzUm93c1RvUmVuZGVyKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHJvd0luZGV4OiB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlRmlyc3RSb3coKSwgcm93UGlubmVkOiBudWxsIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucGlubmVkUm93TW9kZWwuaXNSb3dzVG9SZW5kZXIoQ29uc3RhbnRzLlBJTk5FRF9CT1RUT00pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyByb3dJbmRleDogMCwgcm93UGlubmVkOiBDb25zdGFudHMuUElOTkVEX0JPVFRPTSB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIGluIHRoZSBtYWluIGJvZHksIHRoZW4gdHJ5IHBpbm5lZCBib3R0b20sIG90aGVyd2lzZSByZXR1cm4gbm90aGluZ1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5waW5uZWRSb3dNb2RlbC5pc1Jvd3NUb1JlbmRlcihDb25zdGFudHMuUElOTkVEX0JPVFRPTSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHJvd0luZGV4OiAwLCByb3dQaW5uZWQ6IENvbnN0YW50cy5QSU5ORURfQk9UVE9NIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLnJvd01vZGVsLmdldFJvdyhyb3dQb3NpdGlvbi5yb3dJbmRleCk7XG4gICAgICAgIHZhciBuZXh0U3RpY2t5UG9zaXRpb24gPSB0aGlzLmdldE5leHRTdGlja3lQb3NpdGlvbihyb3dOb2RlKTtcbiAgICAgICAgaWYgKG5leHRTdGlja3lQb3NpdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIG5leHRTdGlja3lQb3NpdGlvbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyByb3dJbmRleDogaW5kZXggKyAxLCByb3dQaW5uZWQ6IHBpbm5lZCB9O1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROZXh0U3RpY2t5UG9zaXRpb24gPSBmdW5jdGlvbiAocm93Tm9kZSwgdXApIHtcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwUm93c1N0aWNreSgpIHx8ICFyb3dOb2RlIHx8ICFyb3dOb2RlLnN0aWNreSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzdGlja3lSb3dDdHJscyA9IF9fc3ByZWFkJDQodGhpcy5yb3dSZW5kZXJlci5nZXRTdGlja3lUb3BSb3dDdHJscygpKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBhLmdldFJvd05vZGUoKS5yb3dJbmRleCAtIGIuZ2V0Um93Tm9kZSgpLnJvd0luZGV4OyB9KTtcbiAgICAgICAgdmFyIGRpZmYgPSB1cCA/IC0xIDogMTtcbiAgICAgICAgdmFyIGlkeCA9IHN0aWNreVJvd0N0cmxzLmZpbmRJbmRleChmdW5jdGlvbiAoY3RybCkgeyByZXR1cm4gY3RybC5nZXRSb3dOb2RlKCkucm93SW5kZXggPT09IHJvd05vZGUucm93SW5kZXg7IH0pO1xuICAgICAgICB2YXIgbmV4dEN0cmwgPSBzdGlja3lSb3dDdHJsc1tpZHggKyBkaWZmXTtcbiAgICAgICAgaWYgKG5leHRDdHJsKSB7XG4gICAgICAgICAgICByZXR1cm4geyByb3dJbmRleDogbmV4dEN0cmwuZ2V0Um93Tm9kZSgpLnJvd0luZGV4LCByb3dQaW5uZWQ6IG51bGwgfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRDZWxsQmVsb3cgPSBmdW5jdGlvbiAobGFzdENlbGwpIHtcbiAgICAgICAgaWYgKCFsYXN0Q2VsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd0JlbG93ID0gdGhpcy5nZXRSb3dCZWxvdyhsYXN0Q2VsbCk7XG4gICAgICAgIGlmIChyb3dCZWxvdykge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICByb3dJbmRleDogcm93QmVsb3cucm93SW5kZXgsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBsYXN0Q2VsbC5jb2x1bW4sXG4gICAgICAgICAgICAgICAgcm93UGlubmVkOiByb3dCZWxvdy5yb3dQaW5uZWRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBDZWxsTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmlzTGFzdFJvd0luQ29udGFpbmVyID0gZnVuY3Rpb24gKHJvd1Bvc2l0aW9uKSB7XG4gICAgICAgIHZhciBwaW5uZWQgPSByb3dQb3NpdGlvbi5yb3dQaW5uZWQ7XG4gICAgICAgIHZhciBpbmRleCA9IHJvd1Bvc2l0aW9uLnJvd0luZGV4O1xuICAgICAgICBpZiAocGlubmVkID09PSBDb25zdGFudHMuUElOTkVEX1RPUCkge1xuICAgICAgICAgICAgdmFyIGxhc3RUb3BJbmRleCA9IHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkVG9wUm93RGF0YSgpLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICByZXR1cm4gbGFzdFRvcEluZGV4IDw9IGluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChwaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfQk9UVE9NKSB7XG4gICAgICAgICAgICB2YXIgbGFzdEJvdHRvbUluZGV4ID0gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Sb3dEYXRhKCkubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIHJldHVybiBsYXN0Qm90dG9tSW5kZXggPD0gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxhc3RCb2R5SW5kZXggPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlTGFzdFJvdygpO1xuICAgICAgICByZXR1cm4gbGFzdEJvZHlJbmRleCA8PSBpbmRleDtcbiAgICB9O1xuICAgIENlbGxOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0Um93QWJvdmUgPSBmdW5jdGlvbiAocm93UG9zaXRpb24pIHtcbiAgICAgICAgLy8gaWYgYWxyZWFkeSBvbiB0b3Agcm93LCBkbyBub3RoaW5nXG4gICAgICAgIHZhciBpbmRleCA9IHJvd1Bvc2l0aW9uLnJvd0luZGV4O1xuICAgICAgICB2YXIgcGlubmVkID0gcm93UG9zaXRpb24ucm93UGlubmVkO1xuICAgICAgICB2YXIgaXNGaXJzdFJvdyA9IHBpbm5lZCA/IGluZGV4ID09PSAwIDogaW5kZXggPT09IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VGaXJzdFJvdygpO1xuICAgICAgICAvLyBpZiBhbHJlYWR5IG9uIHRvcCByb3csIGRvIG5vdGhpbmdcbiAgICAgICAgaWYgKGlzRmlyc3RSb3cpIHtcbiAgICAgICAgICAgIGlmIChwaW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfVE9QKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBpbm5lZCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnBpbm5lZFJvd01vZGVsLmlzUm93c1RvUmVuZGVyKENvbnN0YW50cy5QSU5ORURfVE9QKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRMYXN0RmxvYXRpbmdUb3BSb3coKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBsYXN0IGZsb2F0aW5nIGJvdHRvbVxuICAgICAgICAgICAgaWYgKHRoaXMucm93TW9kZWwuaXNSb3dzVG9SZW5kZXIoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldExhc3RCb2R5Q2VsbCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucGlubmVkUm93TW9kZWwuaXNSb3dzVG9SZW5kZXIoQ29uc3RhbnRzLlBJTk5FRF9UT1ApKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGFzdEZsb2F0aW5nVG9wUm93KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93Tm9kZSA9IHRoaXMucm93TW9kZWwuZ2V0Um93KHJvd1Bvc2l0aW9uLnJvd0luZGV4KTtcbiAgICAgICAgdmFyIG5leHRTdGlja3lQb3NpdGlvbiA9IHRoaXMuZ2V0TmV4dFN0aWNreVBvc2l0aW9uKHJvd05vZGUsIHRydWUpO1xuICAgICAgICBpZiAobmV4dFN0aWNreVBvc2l0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV4dFN0aWNreVBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHJvd0luZGV4OiBpbmRleCAtIDEsIHJvd1Bpbm5lZDogcGlubmVkIH07XG4gICAgfTtcbiAgICBDZWxsTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmdldENlbGxBYm92ZSA9IGZ1bmN0aW9uIChsYXN0Q2VsbCkge1xuICAgICAgICBpZiAoIWxhc3RDZWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93QWJvdmUgPSB0aGlzLmdldFJvd0Fib3ZlKHsgcm93SW5kZXg6IGxhc3RDZWxsLnJvd0luZGV4LCByb3dQaW5uZWQ6IGxhc3RDZWxsLnJvd1Bpbm5lZCB9KTtcbiAgICAgICAgaWYgKHJvd0Fib3ZlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHJvd0luZGV4OiByb3dBYm92ZS5yb3dJbmRleCxcbiAgICAgICAgICAgICAgICBjb2x1bW46IGxhc3RDZWxsLmNvbHVtbixcbiAgICAgICAgICAgICAgICByb3dQaW5uZWQ6IHJvd0Fib3ZlLnJvd1Bpbm5lZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIENlbGxOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUuZ2V0TGFzdEJvZHlDZWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGFzdEJvZHlSb3cgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlTGFzdFJvdygpO1xuICAgICAgICByZXR1cm4geyByb3dJbmRleDogbGFzdEJvZHlSb3csIHJvd1Bpbm5lZDogbnVsbCB9O1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRMYXN0RmxvYXRpbmdUb3BSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBsYXN0RmxvYXRpbmdSb3cgPSB0aGlzLnBpbm5lZFJvd01vZGVsLmdldFBpbm5lZFRvcFJvd0RhdGEoKS5sZW5ndGggLSAxO1xuICAgICAgICByZXR1cm4geyByb3dJbmRleDogbGFzdEZsb2F0aW5nUm93LCByb3dQaW5uZWQ6IENvbnN0YW50cy5QSU5ORURfVE9QIH07XG4gICAgfTtcbiAgICBDZWxsTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmdldE5leHRUYWJiZWRDZWxsID0gZnVuY3Rpb24gKGdyaWRDZWxsLCBiYWNrd2FyZHMpIHtcbiAgICAgICAgaWYgKGJhY2t3YXJkcykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TmV4dFRhYmJlZENlbGxCYWNrd2FyZHMoZ3JpZENlbGwpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldE5leHRUYWJiZWRDZWxsRm9yd2FyZHMoZ3JpZENlbGwpO1xuICAgIH07XG4gICAgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROZXh0VGFiYmVkQ2VsbEZvcndhcmRzID0gZnVuY3Rpb24gKGdyaWRDZWxsKSB7XG4gICAgICAgIHZhciBkaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7XG4gICAgICAgIHZhciBuZXdSb3dJbmRleCA9IGdyaWRDZWxsLnJvd0luZGV4O1xuICAgICAgICB2YXIgbmV3RmxvYXRpbmcgPSBncmlkQ2VsbC5yb3dQaW5uZWQ7XG4gICAgICAgIC8vIG1vdmUgYWxvbmcgdG8gdGhlIG5leHQgY2VsbFxuICAgICAgICB2YXIgbmV3Q29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2xBZnRlcihncmlkQ2VsbC5jb2x1bW4pO1xuICAgICAgICAvLyBjaGVjayBpZiBlbmQgb2YgdGhlIHJvdywgYW5kIGlmIHNvLCBnbyBmb3J3YXJkIGEgcm93XG4gICAgICAgIGlmICghbmV3Q29sdW1uKSB7XG4gICAgICAgICAgICBuZXdDb2x1bW4gPSBkaXNwbGF5ZWRDb2x1bW5zWzBdO1xuICAgICAgICAgICAgdmFyIHJvd0JlbG93ID0gdGhpcy5nZXRSb3dCZWxvdyhncmlkQ2VsbCk7XG4gICAgICAgICAgICBpZiAobWlzc2luZyhyb3dCZWxvdykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIElmIHdlIGFyZSB0YWJiaW5nIGFuZCB0aGVyZSBpcyBhIHBhZ2luZyBwYW5lbCBwcmVzZW50LCB0YWJiaW5nIHNob3VsZCBnb1xuICAgICAgICAgICAgLy8gdG8gdGhlIHBhZ2luZyBwYW5lbCBpbnN0ZWFkIG9mIGxvYWRpbmcgdGhlIG5leHQgcGFnZS5cbiAgICAgICAgICAgIGlmICghcm93QmVsb3cucm93UGlubmVkICYmICF0aGlzLnBhZ2luYXRpb25Qcm94eS5pc1Jvd0luUGFnZShyb3dCZWxvdykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld1Jvd0luZGV4ID0gcm93QmVsb3cgPyByb3dCZWxvdy5yb3dJbmRleCA6IG51bGw7XG4gICAgICAgICAgICBuZXdGbG9hdGluZyA9IHJvd0JlbG93ID8gcm93QmVsb3cucm93UGlubmVkIDogbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyByb3dJbmRleDogbmV3Um93SW5kZXgsIGNvbHVtbjogbmV3Q29sdW1uLCByb3dQaW5uZWQ6IG5ld0Zsb2F0aW5nIH07XG4gICAgfTtcbiAgICBDZWxsTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLmdldE5leHRUYWJiZWRDZWxsQmFja3dhcmRzID0gZnVuY3Rpb24gKGdyaWRDZWxsKSB7XG4gICAgICAgIHZhciBkaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7XG4gICAgICAgIHZhciBuZXdSb3dJbmRleCA9IGdyaWRDZWxsLnJvd0luZGV4O1xuICAgICAgICB2YXIgbmV3RmxvYXRpbmcgPSBncmlkQ2VsbC5yb3dQaW5uZWQ7XG4gICAgICAgIC8vIG1vdmUgYWxvbmcgdG8gdGhlIG5leHQgY2VsbFxuICAgICAgICB2YXIgbmV3Q29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2xCZWZvcmUoZ3JpZENlbGwuY29sdW1uKTtcbiAgICAgICAgLy8gY2hlY2sgaWYgZW5kIG9mIHRoZSByb3csIGFuZCBpZiBzbywgZ28gZm9yd2FyZCBhIHJvd1xuICAgICAgICBpZiAoIW5ld0NvbHVtbikge1xuICAgICAgICAgICAgbmV3Q29sdW1uID0gbGFzdChkaXNwbGF5ZWRDb2x1bW5zKTtcbiAgICAgICAgICAgIHZhciByb3dBYm92ZSA9IHRoaXMuZ2V0Um93QWJvdmUoeyByb3dJbmRleDogZ3JpZENlbGwucm93SW5kZXgsIHJvd1Bpbm5lZDogZ3JpZENlbGwucm93UGlubmVkIH0pO1xuICAgICAgICAgICAgaWYgKG1pc3Npbmcocm93QWJvdmUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBJZiB3ZSBhcmUgdGFiYmluZyBhbmQgdGhlcmUgaXMgYSBwYWdpbmcgcGFuZWwgcHJlc2VudCwgdGFiYmluZyBzaG91bGQgZ29cbiAgICAgICAgICAgIC8vIHRvIHRoZSBwYWdpbmcgcGFuZWwgaW5zdGVhZCBvZiBsb2FkaW5nIHRoZSBuZXh0IHBhZ2UuXG4gICAgICAgICAgICBpZiAoIXJvd0Fib3ZlLnJvd1Bpbm5lZCAmJiAhdGhpcy5wYWdpbmF0aW9uUHJveHkuaXNSb3dJblBhZ2Uocm93QWJvdmUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXdSb3dJbmRleCA9IHJvd0Fib3ZlID8gcm93QWJvdmUucm93SW5kZXggOiBudWxsO1xuICAgICAgICAgICAgbmV3RmxvYXRpbmcgPSByb3dBYm92ZSA/IHJvd0Fib3ZlLnJvd1Bpbm5lZCA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgcm93SW5kZXg6IG5ld1Jvd0luZGV4LCBjb2x1bW46IG5ld0NvbHVtbiwgcm93UGlubmVkOiBuZXdGbG9hdGluZyB9O1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRNKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkTShbXG4gICAgICAgIEF1dG93aXJlZCgncm93TW9kZWwnKVxuICAgIF0sIENlbGxOYXZpZ2F0aW9uU2VydmljZS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJE0oW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd1JlbmRlcmVyJylcbiAgICBdLCBDZWxsTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRNKFtcbiAgICAgICAgQXV0b3dpcmVkKCdwaW5uZWRSb3dNb2RlbCcpXG4gICAgXSwgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJwaW5uZWRSb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkTShbXG4gICAgICAgIEF1dG93aXJlZCgncGFnaW5hdGlvblByb3h5JylcbiAgICBdLCBDZWxsTmF2aWdhdGlvblNlcnZpY2UucHJvdG90eXBlLCBcInBhZ2luYXRpb25Qcm94eVwiLCB2b2lkIDApO1xuICAgIENlbGxOYXZpZ2F0aW9uU2VydmljZSA9IF9fZGVjb3JhdGUkTShbXG4gICAgICAgIEJlYW4oJ2NlbGxOYXZpZ2F0aW9uU2VydmljZScpXG4gICAgXSwgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlKTtcbiAgICByZXR1cm4gQ2VsbE5hdmlnYXRpb25TZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJEogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJEwgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3BhcmFtJDUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3BhcmFtKSB8fCBmdW5jdGlvbiAocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XG59O1xudmFyIEFsaWduZWRHcmlkc1NlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEooQWxpZ25lZEdyaWRzU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBbGlnbmVkR3JpZHNTZXJ2aWNlKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgLy8gZmxhZyB0byBtYXJrIGlmIHdlIGFyZSBjb25zdW1pbmcuIHRvIGF2b2lkIGN5Y2xpYyBldmVudHMgKGllIG90aGVyIGdyaWQgZmlyaW5nIGJhY2sgdG8gbWFzdGVyXG4gICAgICAgIC8vIHdoaWxlIHByb2Nlc3NpbmcgYSBtYXN0ZXIgZXZlbnQpIHdlIG1hcmsgdGhpcyBpZiBjb25zdW1pbmcgYW4gZXZlbnQsIGFuZCBpZiB3ZSBhcmUsIHRoZW5cbiAgICAgICAgLy8gd2UgZG9uJ3QgZmlyZSBiYWNrIGFueSBldmVudHMuXG4gICAgICAgIF90aGlzLmNvbnN1bWluZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLnNldEJlYW5zID0gZnVuY3Rpb24gKGxvZ2dlckZhY3RvcnkpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXJGYWN0b3J5LmNyZWF0ZSgnQWxpZ25lZEdyaWRzU2VydmljZScpO1xuICAgIH07XG4gICAgQWxpZ25lZEdyaWRzU2VydmljZS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQsIHRoaXMuZmlyZUNvbHVtbkV2ZW50LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9WSVNJQkxFLCB0aGlzLmZpcmVDb2x1bW5FdmVudC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUElOTkVELCB0aGlzLmZpcmVDb2x1bW5FdmVudC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fR1JPVVBfT1BFTkVELCB0aGlzLmZpcmVDb2x1bW5FdmVudC5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUkVTSVpFRCwgdGhpcy5maXJlQ29sdW1uRXZlbnQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQk9EWV9TQ1JPTEwsIHRoaXMuZmlyZVNjcm9sbEV2ZW50LmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgLy8gY29tbW9uIGxvZ2ljIGFjcm9zcyBhbGwgdGhlIGZpcmUgbWV0aG9kc1xuICAgIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLmZpcmVFdmVudCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAvLyBpZiB3ZSBhcmUgYWxyZWFkeSBjb25zdW1pbmcsIHRoZW4gd2UgYXJlIGFjdGluZyBvbiBhbiBldmVudCBmcm9tIGEgbWFzdGVyLFxuICAgICAgICAvLyBzbyB3ZSBkb24ndCBjYXVzZSBhIGN5Y2xpYyBmaXJpbmcgb2YgZXZlbnRzXG4gICAgICAgIGlmICh0aGlzLmNvbnN1bWluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGl0ZXJhdGUgdGhyb3VnaCB0aGUgYWxpZ25lZCBncmlkcywgYW5kIHBhc3MgZWFjaCBhbGlnbmVkIGdyaWQgc2VydmljZSB0byB0aGUgY2FsbGJhY2tcbiAgICAgICAgdmFyIG90aGVyR3JpZHMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBbGlnbmVkR3JpZHMoKTtcbiAgICAgICAgaWYgKG90aGVyR3JpZHMpIHtcbiAgICAgICAgICAgIG90aGVyR3JpZHMuZm9yRWFjaChmdW5jdGlvbiAob3RoZXJHcmlkT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmIChvdGhlckdyaWRPcHRpb25zLmFwaSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYWxpZ25lZEdyaWRTZXJ2aWNlID0gb3RoZXJHcmlkT3B0aW9ucy5hcGkuX19nZXRBbGlnbmVkR3JpZFNlcnZpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soYWxpZ25lZEdyaWRTZXJ2aWNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gY29tbW9uIGxvZ2ljIGFjcm9zcyBhbGwgY29uc3VtZSBtZXRob2RzLiB2ZXJ5IGxpdHRsZSBjb21tb24gbG9naWMsIGhvd2V2ZXIgZXh0cmFjdGluZ1xuICAgIC8vIGd1YXJhbnRlZXMgY29uc2lzdGVuY3kgYWNyb3NzIHRoZSBtZXRob2RzLlxuICAgIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLm9uRXZlbnQgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5jb25zdW1pbmcgPSB0cnVlO1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB0aGlzLmNvbnN1bWluZyA9IGZhbHNlO1xuICAgIH07XG4gICAgQWxpZ25lZEdyaWRzU2VydmljZS5wcm90b3R5cGUuZmlyZUNvbHVtbkV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHRoaXMuZmlyZUV2ZW50KGZ1bmN0aW9uIChhbGlnbmVkR3JpZHNTZXJ2aWNlKSB7XG4gICAgICAgICAgICBhbGlnbmVkR3JpZHNTZXJ2aWNlLm9uQ29sdW1uRXZlbnQoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLmZpcmVTY3JvbGxFdmVudCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQuZGlyZWN0aW9uICE9PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZpcmVFdmVudChmdW5jdGlvbiAoYWxpZ25lZEdyaWRzU2VydmljZSkge1xuICAgICAgICAgICAgYWxpZ25lZEdyaWRzU2VydmljZS5vblNjcm9sbEV2ZW50KGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBbGlnbmVkR3JpZHNTZXJ2aWNlLnByb3RvdHlwZS5vblNjcm9sbEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMub25FdmVudChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZ3JpZEJvZHlDb24gPSBfdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgICAgICBncmlkQm9keUNvbi5nZXRTY3JvbGxGZWF0dXJlKCkuc2V0SG9yaXpvbnRhbFNjcm9sbFBvc2l0aW9uKGV2ZW50LmxlZnQpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLmdldE1hc3RlckNvbHVtbnMgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICBpZiAoZXZlbnQuY29sdW1ucykge1xuICAgICAgICAgICAgZXZlbnQuY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChjb2x1bW4pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZXZlbnQuY29sdW1uKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaChldmVudC5jb2x1bW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBBbGlnbmVkR3JpZHNTZXJ2aWNlLnByb3RvdHlwZS5nZXRDb2x1bW5JZHMgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICBpZiAoZXZlbnQuY29sdW1ucykge1xuICAgICAgICAgICAgZXZlbnQuY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChjb2x1bW4uZ2V0Q29sSWQoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChldmVudC5jb2x1bW4pIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGV2ZW50LmNvbHVtbi5nZXRDb2xJZCgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgQWxpZ25lZEdyaWRzU2VydmljZS5wcm90b3R5cGUub25Db2x1bW5FdmVudCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLm9uRXZlbnQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoIChldmVudC50eXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBFdmVudHMuRVZFTlRfQ09MVU1OX01PVkVEOlxuICAgICAgICAgICAgICAgIGNhc2UgRXZlbnRzLkVWRU5UX0NPTFVNTl9WSVNJQkxFOlxuICAgICAgICAgICAgICAgIGNhc2UgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSU5ORUQ6XG4gICAgICAgICAgICAgICAgY2FzZSBFdmVudHMuRVZFTlRfQ09MVU1OX1JFU0laRUQ6XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb2xFdmVudCA9IGV2ZW50O1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5wcm9jZXNzQ29sdW1uRXZlbnQoY29sRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEV2ZW50cy5FVkVOVF9DT0xVTU5fR1JPVVBfT1BFTkVEOlxuICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXBPcGVuZWRFdmVudCA9IGV2ZW50O1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5wcm9jZXNzR3JvdXBPcGVuZWRFdmVudChncm91cE9wZW5lZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBFdmVudHMuRVZFTlRfQ09MVU1OX1BJVk9UX0NIQU5HRUQ6XG4gICAgICAgICAgICAgICAgICAgIC8vIHdlIGNhbm5vdCBzdXBwb3J0IHBpdm90aW5nIHdpdGggYWxpZ25lZCBncmlkcyBhcyB0aGUgY29sdW1ucyB3aWxsIGJlIG91dCBvZiBzeW5jIGFzIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBncmlkcyB3aWxsIGhhdmUgY29sdW1ucyBjcmVhdGVkIGJhc2VkIG9uIHRoZSByb3cgZGF0YSBvZiB0aGUgZ3JpZC5cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBwaXZvdGluZyBpcyBub3Qgc3VwcG9ydGVkIHdpdGggYWxpZ25lZCBncmlkcy4gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAnWW91IGNhbiBvbmx5IHVzZSBvbmUgb2YgdGhlc2UgZmVhdHVyZXMgYXQgYSB0aW1lIGluIGEgZ3JpZC4nKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQWxpZ25lZEdyaWRzU2VydmljZS5wcm90b3R5cGUucHJvY2Vzc0dyb3VwT3BlbmVkRXZlbnQgPSBmdW5jdGlvbiAoZ3JvdXBPcGVuZWRFdmVudCkge1xuICAgICAgICAvLyBsaWtld2lzZSBmb3IgY29sdW1uIGdyb3VwXG4gICAgICAgIHZhciBtYXN0ZXJDb2x1bW5Hcm91cCA9IGdyb3VwT3BlbmVkRXZlbnQuY29sdW1uR3JvdXA7XG4gICAgICAgIHZhciBvdGhlckNvbHVtbkdyb3VwID0gbnVsbDtcbiAgICAgICAgaWYgKG1hc3RlckNvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICB2YXIgZ3JvdXBJZCA9IG1hc3RlckNvbHVtbkdyb3VwLmdldEdyb3VwSWQoKTtcbiAgICAgICAgICAgIG90aGVyQ29sdW1uR3JvdXAgPSB0aGlzLmNvbHVtbk1vZGVsLmdldFByb3ZpZGVkQ29sdW1uR3JvdXAoZ3JvdXBJZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1hc3RlckNvbHVtbkdyb3VwICYmICFvdGhlckNvbHVtbkdyb3VwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnZXIubG9nKCdvbkNvbHVtbkV2ZW50LT4gcHJvY2Vzc2luZyAnICsgZ3JvdXBPcGVuZWRFdmVudCArICcgZXhwYW5kZWQgPSAnICsgbWFzdGVyQ29sdW1uR3JvdXAuaXNFeHBhbmRlZCgpKTtcbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5Hcm91cE9wZW5lZChvdGhlckNvbHVtbkdyb3VwLCBtYXN0ZXJDb2x1bW5Hcm91cC5pc0V4cGFuZGVkKCksIFwiYWxpZ25lZEdyaWRDaGFuZ2VkXCIpO1xuICAgIH07XG4gICAgQWxpZ25lZEdyaWRzU2VydmljZS5wcm90b3R5cGUucHJvY2Vzc0NvbHVtbkV2ZW50ID0gZnVuY3Rpb24gKGNvbEV2ZW50KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgLy8gdGhlIGNvbHVtbiBpbiB0aGUgZXZlbnQgaXMgZnJvbSB0aGUgbWFzdGVyIGdyaWQuIG5lZWQgdG9cbiAgICAgICAgLy8gbG9vayB1cCB0aGUgZXF1aXZhbGVudCBmcm9tIHRoaXMgKG90aGVyKSBncmlkXG4gICAgICAgIHZhciBtYXN0ZXJDb2x1bW4gPSBjb2xFdmVudC5jb2x1bW47XG4gICAgICAgIHZhciBvdGhlckNvbHVtbiA9IG51bGw7XG4gICAgICAgIGlmIChtYXN0ZXJDb2x1bW4pIHtcbiAgICAgICAgICAgIG90aGVyQ29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5Q29sdW1uKG1hc3RlckNvbHVtbi5nZXRDb2xJZCgpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBldmVudCB3YXMgd2l0aCByZXNwZWN0IHRvIGEgbWFzdGVyIGNvbHVtbiwgdGhhdCBpcyBub3QgcHJlc2VudCBpbiB0aGlzXG4gICAgICAgIC8vIGdyaWQsIHRoZW4gd2UgaWdub3JlIHRoZSBldmVudFxuICAgICAgICBpZiAobWFzdGVyQ29sdW1uICYmICFvdGhlckNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGluIHRpbWUsIGFsbCB0aGUgbWV0aG9kcyBiZWxvdyBzaG91bGQgdXNlIHRoZSBjb2x1bW4gaWRzLCBpdCdzIGEgbW9yZSBnZW5lcmljIHdheVxuICAgICAgICAvLyBvZiBoYW5kbGluZyBjb2x1bW5zLCBhbmQgYWxzbyBhbGxvd3MgZm9yIHNpbmdsZSBvciBtdWx0aSBjb2x1bW4gZXZlbnRzXG4gICAgICAgIHZhciBtYXN0ZXJDb2x1bW5zID0gdGhpcy5nZXRNYXN0ZXJDb2x1bW5zKGNvbEV2ZW50KTtcbiAgICAgICAgc3dpdGNoIChjb2xFdmVudC50eXBlKSB7XG4gICAgICAgICAgICBjYXNlIEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQ6XG4gICAgICAgICAgICAgICAgLy8gd2hlbiB0aGUgdXNlciBtb3ZlcyBjb2x1bW5zIHZpYSBzZXRDb2x1bW5TdGF0ZSwgd2UgY2FuJ3QgZGVwZW5kIG9uIG1vdmluZyBzcGVjaWZpYyBjb2x1bW5zXG4gICAgICAgICAgICAgICAgLy8gdG8gYW4gaW5kZXgsIGFzIHRoZXJlIG1heWJlIGJlIG1hbnkgaW5kZXhlcyBjb2x1bW5zIG1vdmVkIHRvIChhcyB3YXNuJ3QgcmVzdWx0IG9mIGEgbW91c2UgZHJhZykuXG4gICAgICAgICAgICAgICAgLy8gc28gb25seSB3YXkgdG8gYmUgc3VyZSBpcyBtYXRjaCB0aGUgb3JkZXIgb2YgYWxsIGNvbHVtbnMgdXNpbmcgQ29sdW1uIFN0YXRlLlxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1vdmVkRXZlbnQgPSBjb2xFdmVudDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNyY0NvbFN0YXRlID0gY29sRXZlbnQuY29sdW1uQXBpLmdldENvbHVtblN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkZXN0Q29sU3RhdGUgPSBzcmNDb2xTdGF0ZS5tYXAoZnVuY3Rpb24gKHMpIHsgcmV0dXJuICh7IGNvbElkOiBzLmNvbElkIH0pOyB9KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5hcHBseUNvbHVtblN0YXRlKHsgc3RhdGU6IGRlc3RDb2xTdGF0ZSwgYXBwbHlPcmRlcjogdHJ1ZSB9LCBcImFsaWduZWRHcmlkQ2hhbmdlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwib25Db2x1bW5FdmVudC0+IHByb2Nlc3NpbmcgXCIgKyBjb2xFdmVudC50eXBlICsgXCIgdG9JbmRleCA9IFwiICsgbW92ZWRFdmVudC50b0luZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEV2ZW50cy5FVkVOVF9DT0xVTU5fVklTSUJMRTpcbiAgICAgICAgICAgICAgICAvLyB3aGVuIHRoZSB1c2VyIGNoYW5nZXMgdmlzaWJpbGl0eSB2aWEgc2V0Q29sdW1uU3RhdGUsIHdlIGNhbid0IGRlcGVuZCBvbiB2aXNpYmlsaXR5IGZsYWcgaW4gZXZlbnRcbiAgICAgICAgICAgICAgICAvLyBhcyB0aGVyZSBtYXliZSBiZSBtaXggb2YgdHJ1ZS9mYWxzZSAoYXMgd2Fzbid0IHJlc3VsdCBvZiBhIG1vdXNlIGNsaWNrIHRvIHNldCB2aXNpYmxpdHkpLlxuICAgICAgICAgICAgICAgIC8vIHNvIG9ubHkgd2F5IHRvIGJlIHN1cmUgaXMgbWF0Y2ggdGhlIHZpc2liaWxpdHkgb2YgYWxsIGNvbHVtbnMgdXNpbmcgQ29sdW1uIFN0YXRlLlxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpc2libGVFdmVudCA9IGNvbEV2ZW50O1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3JjQ29sU3RhdGUgPSBjb2xFdmVudC5jb2x1bW5BcGkuZ2V0Q29sdW1uU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlc3RDb2xTdGF0ZSA9IHNyY0NvbFN0YXRlLm1hcChmdW5jdGlvbiAocykgeyByZXR1cm4gKHsgY29sSWQ6IHMuY29sSWQsIGhpZGU6IHMuaGlkZSB9KTsgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwuYXBwbHlDb2x1bW5TdGF0ZSh7IHN0YXRlOiBkZXN0Q29sU3RhdGUgfSwgXCJhbGlnbmVkR3JpZENoYW5nZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmxvZyhcIm9uQ29sdW1uRXZlbnQtPiBwcm9jZXNzaW5nIFwiICsgY29sRXZlbnQudHlwZSArIFwiIHZpc2libGUgPSBcIiArIHZpc2libGVFdmVudC52aXNpYmxlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEV2ZW50cy5FVkVOVF9DT0xVTU5fUElOTkVEOlxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBpbm5lZEV2ZW50ID0gY29sRXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzcmNDb2xTdGF0ZSA9IGNvbEV2ZW50LmNvbHVtbkFwaS5nZXRDb2x1bW5TdGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVzdENvbFN0YXRlID0gc3JjQ29sU3RhdGUubWFwKGZ1bmN0aW9uIChzKSB7IHJldHVybiAoeyBjb2xJZDogcy5jb2xJZCwgcGlubmVkOiBzLnBpbm5lZCB9KTsgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwuYXBwbHlDb2x1bW5TdGF0ZSh7IHN0YXRlOiBkZXN0Q29sU3RhdGUgfSwgXCJhbGlnbmVkR3JpZENoYW5nZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmxvZyhcIm9uQ29sdW1uRXZlbnQtPiBwcm9jZXNzaW5nIFwiICsgY29sRXZlbnQudHlwZSArIFwiIHBpbm5lZCA9IFwiICsgcGlubmVkRXZlbnQucGlubmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEV2ZW50cy5FVkVOVF9DT0xVTU5fUkVTSVpFRDpcbiAgICAgICAgICAgICAgICB2YXIgcmVzaXplZEV2ZW50ID0gY29sRXZlbnQ7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbldpZHRoc18xID0ge307XG4gICAgICAgICAgICAgICAgbWFzdGVyQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMubG9nZ2VyLmxvZyhcIm9uQ29sdW1uRXZlbnQtPiBwcm9jZXNzaW5nIFwiICsgY29sRXZlbnQudHlwZSArIFwiIGFjdHVhbFdpZHRoID0gXCIgKyBjb2x1bW4uZ2V0QWN0dWFsV2lkdGgoKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbldpZHRoc18xW2NvbHVtbi5nZXRJZCgpXSA9IHsga2V5OiBjb2x1bW4uZ2V0Q29sSWQoKSwgbmV3V2lkdGg6IGNvbHVtbi5nZXRBY3R1YWxXaWR0aCgpIH07XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3Qgc2V0IGZsZXggY29sdW1ucyB3aWR0aFxuICAgICAgICAgICAgICAgIChfYSA9IHJlc2l6ZWRFdmVudC5mbGV4Q29sdW1ucykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmZvckVhY2goZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29sdW1uV2lkdGhzXzFbY29sLmdldElkKCldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgY29sdW1uV2lkdGhzXzFbY29sLmdldElkKCldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5XaWR0aHMoT2JqZWN0LnZhbHVlcyhjb2x1bW5XaWR0aHNfMSksIGZhbHNlLCByZXNpemVkRXZlbnQuZmluaXNoZWQsIFwiYWxpZ25lZEdyaWRDaGFuZ2VkXCIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHZhciBncmlkQm9keUNvbiA9IHRoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRCb2R5Q3RybCgpO1xuICAgICAgICB2YXIgaXNWZXJ0aWNhbFNjcm9sbFNob3dpbmcgPSBncmlkQm9keUNvbi5pc1ZlcnRpY2FsU2Nyb2xsU2hvd2luZygpO1xuICAgICAgICB2YXIgYWxpZ25lZEdyaWRzID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QWxpZ25lZEdyaWRzKCk7XG4gICAgICAgIGlmIChhbGlnbmVkR3JpZHMpIHtcbiAgICAgICAgICAgIGFsaWduZWRHcmlkcy5mb3JFYWNoKGZ1bmN0aW9uIChncmlkKSB7XG4gICAgICAgICAgICAgICAgaWYgKGdyaWQuYXBpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyaWQuYXBpLnNldEFsd2F5c1Nob3dWZXJ0aWNhbFNjcm9sbChpc1ZlcnRpY2FsU2Nyb2xsU2hvd2luZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkTChbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRMKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEFsaWduZWRHcmlkc1NlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkTChbXG4gICAgICAgIF9fcGFyYW0kNSgwLCBRdWFsaWZpZXIoJ2xvZ2dlckZhY3RvcnknKSlcbiAgICBdLCBBbGlnbmVkR3JpZHNTZXJ2aWNlLnByb3RvdHlwZSwgXCJzZXRCZWFuc1wiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJEwoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgQWxpZ25lZEdyaWRzU2VydmljZS5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBBbGlnbmVkR3JpZHNTZXJ2aWNlID0gX19kZWNvcmF0ZSRMKFtcbiAgICAgICAgQmVhbignYWxpZ25lZEdyaWRzU2VydmljZScpXG4gICAgXSwgQWxpZ25lZEdyaWRzU2VydmljZSk7XG4gICAgcmV0dXJuIEFsaWduZWRHcmlkc1NlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkSSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkSyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcGFyYW0kNCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcGFyYW0pIHx8IGZ1bmN0aW9uIChwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cbn07XG52YXIgU2VsZWN0aW9uU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkSShTZWxlY3Rpb25TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNlbGVjdGlvblNlcnZpY2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUuc2V0QmVhbnMgPSBmdW5jdGlvbiAobG9nZ2VyRmFjdG9yeSkge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlckZhY3RvcnkuY3JlYXRlKCdzZWxlY3Rpb25TZXJ2aWNlJyk7XG4gICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICB9O1xuICAgIFNlbGVjdGlvblNlcnZpY2UucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZ3JvdXBTZWxlY3RzQ2hpbGRyZW4gPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU2VsZWN0c0NoaWxkcmVuKCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfUk9XX1NFTEVDVEVELCB0aGlzLm9uUm93U2VsZWN0ZWQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5zZXRMYXN0U2VsZWN0ZWROb2RlID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgdGhpcy5sYXN0U2VsZWN0ZWROb2RlID0gcm93Tm9kZTtcbiAgICB9O1xuICAgIFNlbGVjdGlvblNlcnZpY2UucHJvdG90eXBlLmdldExhc3RTZWxlY3RlZE5vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxhc3RTZWxlY3RlZE5vZGU7XG4gICAgfTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRTZWxlY3RlZE5vZGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VsZWN0ZWROb2RlcyA9IFtdO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMuc2VsZWN0ZWROb2RlcywgZnVuY3Rpb24gKGtleSwgcm93Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHJvd05vZGUpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RlZE5vZGVzLnB1c2gocm93Tm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gc2VsZWN0ZWROb2RlcztcbiAgICB9O1xuICAgIFNlbGVjdGlvblNlcnZpY2UucHJvdG90eXBlLmdldFNlbGVjdGVkUm93cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNlbGVjdGVkUm93cyA9IFtdO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMuc2VsZWN0ZWROb2RlcywgZnVuY3Rpb24gKGtleSwgcm93Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHJvd05vZGUgJiYgcm93Tm9kZS5kYXRhKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ZWRSb3dzLnB1c2gocm93Tm9kZS5kYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBzZWxlY3RlZFJvd3M7XG4gICAgfTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5yZW1vdmVHcm91cHNGcm9tU2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMuc2VsZWN0ZWROb2RlcywgZnVuY3Rpb24gKGtleSwgcm93Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHJvd05vZGUgJiYgcm93Tm9kZS5ncm91cCkge1xuICAgICAgICAgICAgICAgIF90aGlzLnNlbGVjdGVkTm9kZXNbcm93Tm9kZS5pZF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gc2hvdWxkIG9ubHkgYmUgY2FsbGVkIGlmIGdyb3VwU2VsZWN0c0NoaWxkcmVuPXRydWVcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS51cGRhdGVHcm91cHNGcm9tQ2hpbGRyZW5TZWxlY3Rpb25zID0gZnVuY3Rpb24gKGNoYW5nZWRQYXRoKSB7XG4gICAgICAgIC8vIHdlIG9ubHkgZG8gdGhpcyB3aGVuIGdyb3VwIHNlbGVjdGlvbiBzdGF0ZSBkZXBlbmRzIG9uIHNlbGVjdGVkIGNoaWxkcmVuXG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFNlbGVjdHNDaGlsZHJlbigpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWxzbyBvbmx5IGRvIGl0IGlmIENTUk0gKGNvZGUgc2hvdWxkIG5ldmVyIGFsbG93IHRoaXMgYW55d2F5KVxuICAgICAgICBpZiAodGhpcy5yb3dNb2RlbC5nZXRUeXBlKCkgIT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjbGllbnRTaWRlUm93TW9kZWwgPSB0aGlzLnJvd01vZGVsO1xuICAgICAgICB2YXIgcm9vdE5vZGUgPSBjbGllbnRTaWRlUm93TW9kZWwuZ2V0Um9vdE5vZGUoKTtcbiAgICAgICAgaWYgKCFjaGFuZ2VkUGF0aCkge1xuICAgICAgICAgICAgY2hhbmdlZFBhdGggPSBuZXcgQ2hhbmdlZFBhdGgodHJ1ZSwgcm9vdE5vZGUpO1xuICAgICAgICAgICAgY2hhbmdlZFBhdGguc2V0SW5hY3RpdmUoKTtcbiAgICAgICAgfVxuICAgICAgICBjaGFuZ2VkUGF0aC5mb3JFYWNoQ2hhbmdlZE5vZGVEZXB0aEZpcnN0KGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICBpZiAocm93Tm9kZSAhPT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ZWQgPSByb3dOb2RlLmNhbGN1bGF0ZVNlbGVjdGVkRnJvbUNoaWxkcmVuKCk7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5zZWxlY3RUaGlzTm9kZShzZWxlY3RlZCA9PT0gbnVsbCA/IGZhbHNlIDogc2VsZWN0ZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gY2xpZW50U2lkZVJvd01vZGVsLmdldFRvcExldmVsTm9kZXMoKSEuZm9yRWFjaCgocm93Tm9kZTogUm93Tm9kZSkgPT4ge1xuICAgICAgICAvLyAgICAgcm93Tm9kZS5kZXB0aEZpcnN0U2VhcmNoKChub2RlKSA9PiB7XG4gICAgICAgIC8vICAgICAgICAgaWYgKG5vZGUuZ3JvdXApIHtcbiAgICAgICAgLy8gICAgICAgICB9XG4gICAgICAgIC8vICAgICB9KTtcbiAgICAgICAgLy8gfSk7XG4gICAgfTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXROb2RlRm9ySWRJZlNlbGVjdGVkID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkTm9kZXNbaWRdO1xuICAgIH07XG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUuY2xlYXJPdGhlck5vZGVzID0gZnVuY3Rpb24gKHJvd05vZGVUb0tlZXBTZWxlY3RlZCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZ3JvdXBzVG9SZWZyZXNoID0ge307XG4gICAgICAgIHZhciB1cGRhdGVkQ291bnQgPSAwO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMuc2VsZWN0ZWROb2RlcywgZnVuY3Rpb24gKGtleSwgb3RoZXJSb3dOb2RlKSB7XG4gICAgICAgICAgICBpZiAob3RoZXJSb3dOb2RlICYmIG90aGVyUm93Tm9kZS5pZCAhPT0gcm93Tm9kZVRvS2VlcFNlbGVjdGVkLmlkKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvd05vZGUgPSBfdGhpcy5zZWxlY3RlZE5vZGVzW290aGVyUm93Tm9kZS5pZF07XG4gICAgICAgICAgICAgICAgdXBkYXRlZENvdW50ICs9IHJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoe1xuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU2VsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgc3VwcHJlc3NGaW5pc2hBY3Rpb25zOiB0cnVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmdyb3VwU2VsZWN0c0NoaWxkcmVuICYmIG90aGVyUm93Tm9kZS5wYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBzVG9SZWZyZXNoW290aGVyUm93Tm9kZS5wYXJlbnQuaWRdID0gb3RoZXJSb3dOb2RlLnBhcmVudDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpdGVyYXRlT2JqZWN0KGdyb3Vwc1RvUmVmcmVzaCwgZnVuY3Rpb24gKGtleSwgZ3JvdXApIHtcbiAgICAgICAgICAgIHZhciBzZWxlY3RlZCA9IGdyb3VwLmNhbGN1bGF0ZVNlbGVjdGVkRnJvbUNoaWxkcmVuKCk7XG4gICAgICAgICAgICBncm91cC5zZWxlY3RUaGlzTm9kZShzZWxlY3RlZCA9PT0gbnVsbCA/IGZhbHNlIDogc2VsZWN0ZWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHVwZGF0ZWRDb3VudDtcbiAgICB9O1xuICAgIFNlbGVjdGlvblNlcnZpY2UucHJvdG90eXBlLm9uUm93U2VsZWN0ZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIHJvd05vZGUgPSBldmVudC5ub2RlO1xuICAgICAgICAvLyB3ZSBkbyBub3Qgc3RvcmUgdGhlIGdyb3VwIHJvd3Mgd2hlbiB0aGUgZ3JvdXBzIHNlbGVjdCBjaGlsZHJlblxuICAgICAgICBpZiAodGhpcy5ncm91cFNlbGVjdHNDaGlsZHJlbiAmJiByb3dOb2RlLmdyb3VwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJvd05vZGUuaXNTZWxlY3RlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkTm9kZXNbcm93Tm9kZS5pZF0gPSByb3dOb2RlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZE5vZGVzW3Jvd05vZGUuaWRdID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5zeW5jSW5Sb3dOb2RlID0gZnVuY3Rpb24gKHJvd05vZGUsIG9sZE5vZGUpIHtcbiAgICAgICAgdGhpcy5zeW5jSW5PbGRSb3dOb2RlKHJvd05vZGUsIG9sZE5vZGUpO1xuICAgICAgICB0aGlzLnN5bmNJbk5ld1Jvd05vZGUocm93Tm9kZSk7XG4gICAgfTtcbiAgICAvLyBpZiB0aGUgaWQgaGFzIGNoYW5nZWQgZm9yIHRoZSBub2RlLCB0aGVuIHRoaXMgbWVhbnMgdGhlIHJvd05vZGVcbiAgICAvLyBpcyBnZXR0aW5nIHVzZWQgZm9yIGEgZGlmZmVyZW50IGRhdGEgaXRlbSwgd2hpY2ggYnJlYWtzXG4gICAgLy8gb3VyIHNlbGVjdGVkTm9kZXMsIGFzIHRoZSBub2RlIG5vdyBpcyBtYXBwZWQgYnkgdGhlIG9sZCBpZFxuICAgIC8vIHdoaWNoIGlzIGluY29uc2lzdGVudC4gc28gdG8ga2VlcCB0aGUgb2xkIG5vZGUgYXMgc2VsZWN0ZWQsXG4gICAgLy8gd2Ugc3dhcCBpbiB0aGUgY2xvbmUgKHdpdGggdGhlIG9sZCBpZCBhbmQgb2xkIGRhdGEpLiB0aGlzIG1lYW5zXG4gICAgLy8gdGhlIG9sZE5vZGUgaXMgZWZmZWN0aXZlbHkgYSBkYWVtb24gd2Uga2VlcCBhIHJlZmVyZW5jZSB0byxcbiAgICAvLyBzbyBpZiBjbGllbnQgY2FsbHMgYXBpLmdldFNlbGVjdGVkTm9kZXMoKSwgaXQgZ2V0cyB0aGUgZGFlbW9uXG4gICAgLy8gaW4gdGhlIHJlc3VsdC4gd2hlbiB0aGUgY2xpZW50IHVuLXNlbGVjdHMsIHRoZSByZWZlcmVuY2UgdG8gdGhlXG4gICAgLy8gZGFlbW9uIGlzIHJlbW92ZWQuIHRoZSBkYWVtb24sIGJlY2F1c2UgaXQncyBhbiBvbGROb2RlLCBpcyBub3RcbiAgICAvLyB1c2VkIGJ5IHRoZSBncmlkIGZvciByZW5kZXJpbmcsIGl0J3MgYSBjb3B5IG9mIHdoYXQgdGhlIG5vZGUgdXNlZFxuICAgIC8vIHRvIGJlIGxpa2UgYmVmb3JlIHRoZSBpZCB3YXMgY2hhbmdlZC5cbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5zeW5jSW5PbGRSb3dOb2RlID0gZnVuY3Rpb24gKHJvd05vZGUsIG9sZE5vZGUpIHtcbiAgICAgICAgdmFyIG9sZE5vZGVIYXNEaWZmZXJlbnRJZCA9IGV4aXN0cyhvbGROb2RlKSAmJiAocm93Tm9kZS5pZCAhPT0gb2xkTm9kZS5pZCk7XG4gICAgICAgIGlmIChvbGROb2RlSGFzRGlmZmVyZW50SWQgJiYgb2xkTm9kZSkge1xuICAgICAgICAgICAgdmFyIGlkID0gb2xkTm9kZS5pZDtcbiAgICAgICAgICAgIHZhciBvbGROb2RlU2VsZWN0ZWQgPSB0aGlzLnNlbGVjdGVkTm9kZXNbaWRdID09IHJvd05vZGU7XG4gICAgICAgICAgICBpZiAob2xkTm9kZVNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZE5vZGVzW29sZE5vZGUuaWRdID0gb2xkTm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUuc3luY0luTmV3Um93Tm9kZSA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIGlmIChleGlzdHModGhpcy5zZWxlY3RlZE5vZGVzW3Jvd05vZGUuaWRdKSkge1xuICAgICAgICAgICAgcm93Tm9kZS5zZXRTZWxlY3RlZEluaXRpYWxWYWx1ZSh0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWROb2Rlc1tyb3dOb2RlLmlkXSA9IHJvd05vZGU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByb3dOb2RlLnNldFNlbGVjdGVkSW5pdGlhbFZhbHVlKGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmxvZygncmVzZXQnKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZE5vZGVzID0ge307XG4gICAgICAgIHRoaXMubGFzdFNlbGVjdGVkTm9kZSA9IG51bGw7XG4gICAgfTtcbiAgICAvLyByZXR1cm5zIGEgbGlzdCBvZiBhbGwgbm9kZXMgYXQgJ2Jlc3QgY29zdCcgLSBhIGZlYXR1cmUgdG8gYmUgdXNlZFxuICAgIC8vIHdpdGggZ3JvdXBzIC8gdHJlZXMuIGlmIGEgZ3JvdXAgaGFzIGFsbCBpdCdzIGNoaWxkcmVuIHNlbGVjdGVkLFxuICAgIC8vIHRoZW4gdGhlIGdyb3VwIGFwcGVhcnMgaW4gdGhlIHJlc3VsdCwgYnV0IG5vdCB0aGUgY2hpbGRyZW4uXG4gICAgLy8gRGVzaWduZWQgZm9yIHVzZSB3aXRoICdjaGlsZHJlbicgYXMgdGhlIGdyb3VwIHNlbGVjdGlvbiB0eXBlLFxuICAgIC8vIHdoZXJlIGdyb3VwcyBkb24ndCBhY3R1YWxseSBhcHBlYXIgaW4gdGhlIHNlbGVjdGlvbiBub3JtYWxseS5cbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5nZXRCZXN0Q29zdE5vZGVTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJvd01vZGVsLmdldFR5cGUoKSAhPT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0NMSUVOVF9TSURFKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGBnZXRCZXN0Q29zdE5vZGVTZWxlY3Rpb25gIGlzIG9ubHkgYXZhaWxhYmxlIHdoZW4gdXNpbmcgbm9ybWFsIHJvdyBtb2RlbCcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjbGllbnRTaWRlUm93TW9kZWwgPSB0aGlzLnJvd01vZGVsO1xuICAgICAgICB2YXIgdG9wTGV2ZWxOb2RlcyA9IGNsaWVudFNpZGVSb3dNb2RlbC5nZXRUb3BMZXZlbE5vZGVzKCk7XG4gICAgICAgIGlmICh0b3BMZXZlbE5vZGVzID09PSBudWxsKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGBzZWxlY3RBbGxgIG5vdCBhdmFpbGFibGUgZG9pbmcgYHJvd01vZGVsPXZpcnR1YWxgJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAvLyByZWN1cnNpdmUgZnVuY3Rpb24sIHRvIGZpbmQgdGhlIHNlbGVjdGVkIG5vZGVzXG4gICAgICAgIGZ1bmN0aW9uIHRyYXZlcnNlKG5vZGVzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IG5vZGVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBub2RlID0gbm9kZXNbaV07XG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuaXNTZWxlY3RlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgbm90IHNlbGVjdGVkLCB0aGVuIGlmIGl0J3MgYSBncm91cCwgYW5kIHRoZSBncm91cFxuICAgICAgICAgICAgICAgICAgICAvLyBoYXMgY2hpbGRyZW4sIGNvbnRpbnVlIHRvIHNlYXJjaCBmb3Igc2VsZWN0aW9uc1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF5YmVHcm91cCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXliZUdyb3VwLmdyb3VwICYmIG1heWJlR3JvdXAuY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYXZlcnNlKG1heWJlR3JvdXAuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRyYXZlcnNlKHRvcExldmVsTm9kZXMpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUuc2V0Um93TW9kZWwgPSBmdW5jdGlvbiAocm93TW9kZWwpIHtcbiAgICAgICAgdGhpcy5yb3dNb2RlbCA9IHJvd01vZGVsO1xuICAgIH07XG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUuaXNFbXB0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvdW50ID0gMDtcbiAgICAgICAgaXRlcmF0ZU9iamVjdCh0aGlzLnNlbGVjdGVkTm9kZXMsIGZ1bmN0aW9uIChub2RlSWQsIHJvd05vZGUpIHtcbiAgICAgICAgICAgIGlmIChyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgY291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjb3VudCA9PT0gMDtcbiAgICB9O1xuICAgIFNlbGVjdGlvblNlcnZpY2UucHJvdG90eXBlLmRlc2VsZWN0QWxsUm93Tm9kZXMgPSBmdW5jdGlvbiAoanVzdEZpbHRlcmVkKSB7XG4gICAgICAgIGlmIChqdXN0RmlsdGVyZWQgPT09IHZvaWQgMCkgeyBqdXN0RmlsdGVyZWQgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiAocm93Tm9kZSkgeyByZXR1cm4gcm93Tm9kZS5zZWxlY3RUaGlzTm9kZShmYWxzZSk7IH07XG4gICAgICAgIHZhciByb3dNb2RlbENsaWVudFNpZGUgPSB0aGlzLnJvd01vZGVsLmdldFR5cGUoKSA9PT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0NMSUVOVF9TSURFO1xuICAgICAgICBpZiAoanVzdEZpbHRlcmVkKSB7XG4gICAgICAgICAgICBpZiAoIXJvd01vZGVsQ2xpZW50U2lkZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHNlbGVjdGluZyBqdXN0IGZpbHRlcmVkIG9ubHkgd29ya3Mgd2l0aCBJbiBNZW1vcnkgUm93IE1vZGVsJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNsaWVudFNpZGVSb3dNb2RlbCA9IHRoaXMucm93TW9kZWw7XG4gICAgICAgICAgICBjbGllbnRTaWRlUm93TW9kZWwuZm9yRWFjaE5vZGVBZnRlckZpbHRlcihjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpdGVyYXRlT2JqZWN0KHRoaXMuc2VsZWN0ZWROb2RlcywgZnVuY3Rpb24gKGlkLCByb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhlIHJlZmVyZW5jZSBjYW4gYmUgdG8gbnVsbCwgYXMgd2UgbmV2ZXIgJ2RlbGV0ZScgZnJvbSB0aGUgbWFwXG4gICAgICAgICAgICAgICAgaWYgKHJvd05vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2socm93Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyB0aGlzIGNsZWFycyBkb3duIHRoZSBtYXAgKHdoZXJlYXMgYWJvdmUgb25seSBzZXRzIHRoZSBpdGVtcyBpbiBtYXAgdG8gJ3VuZGVmaW5lZCcpXG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlIGFib3ZlIGRvZXMgbm90IGNsZWFuIHVwIHRoZSBwYXJlbnQgcm93cyBpZiB0aGV5IGFyZSBzZWxlY3RlZFxuICAgICAgICBpZiAocm93TW9kZWxDbGllbnRTaWRlICYmIHRoaXMuZ3JvdXBTZWxlY3RzQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlR3JvdXBzRnJvbUNoaWxkcmVuU2VsZWN0aW9ucygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9TRUxFQ1RJT05fQ0hBTkdFRCxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5zZWxlY3RBbGxSb3dOb2RlcyA9IGZ1bmN0aW9uIChqdXN0RmlsdGVyZWQpIHtcbiAgICAgICAgaWYgKGp1c3RGaWx0ZXJlZCA9PT0gdm9pZCAwKSB7IGp1c3RGaWx0ZXJlZCA9IGZhbHNlOyB9XG4gICAgICAgIGlmICh0aGlzLnJvd01vZGVsLmdldFR5cGUoKSAhPT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0NMSUVOVF9TSURFKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzZWxlY3RBbGwgb25seSBhdmFpbGFibGUgd2l0aCBub3JtYWwgcm93IG1vZGVsLCBpZSBub3QgXCIgKyB0aGlzLnJvd01vZGVsLmdldFR5cGUoKSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNsaWVudFNpZGVSb3dNb2RlbCA9IHRoaXMucm93TW9kZWw7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7IHJldHVybiByb3dOb2RlLnNlbGVjdFRoaXNOb2RlKHRydWUpOyB9O1xuICAgICAgICBpZiAoanVzdEZpbHRlcmVkKSB7XG4gICAgICAgICAgICBjbGllbnRTaWRlUm93TW9kZWwuZm9yRWFjaE5vZGVBZnRlckZpbHRlcihjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjbGllbnRTaWRlUm93TW9kZWwuZm9yRWFjaE5vZGUoY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoZSBhYm92ZSBkb2VzIG5vdCBjbGVhbiB1cCB0aGUgcGFyZW50IHJvd3MgaWYgdGhleSBhcmUgc2VsZWN0ZWRcbiAgICAgICAgaWYgKHRoaXMucm93TW9kZWwuZ2V0VHlwZSgpID09PSBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfQ0xJRU5UX1NJREUgJiYgdGhpcy5ncm91cFNlbGVjdHNDaGlsZHJlbikge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVHcm91cHNGcm9tQ2hpbGRyZW5TZWxlY3Rpb25zKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX1NFTEVDVElPTl9DSEFOR0VELFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEBtZXRob2RcbiAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAqL1xuICAgIFNlbGVjdGlvblNlcnZpY2UucHJvdG90eXBlLnNlbGVjdE5vZGUgPSBmdW5jdGlvbiAocm93Tm9kZSwgdHJ5TXVsdGkpIHtcbiAgICAgICAgaWYgKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHJvd05vZGUuc2V0U2VsZWN0ZWRQYXJhbXMoeyBuZXdWYWx1ZTogdHJ1ZSwgY2xlYXJTZWxlY3Rpb246ICF0cnlNdWx0aSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqXG4gICAgICogQG1ldGhvZFxuICAgICAqIEBkZXByZWNhdGVkXG4gICAgICovXG4gICAgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUuZGVzZWxlY3RJbmRleCA9IGZ1bmN0aW9uIChyb3dJbmRleCkge1xuICAgICAgICB2YXIgbm9kZSA9IHRoaXMucm93TW9kZWwuZ2V0Um93KHJvd0luZGV4KTtcbiAgICAgICAgdGhpcy5kZXNlbGVjdE5vZGUobm9kZSk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAbWV0aG9kXG4gICAgICogQGRlcHJlY2F0ZWRcbiAgICAgKi9cbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5kZXNlbGVjdE5vZGUgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICBpZiAocm93Tm9kZSkge1xuICAgICAgICAgICAgcm93Tm9kZS5zZXRTZWxlY3RlZFBhcmFtcyh7IG5ld1ZhbHVlOiBmYWxzZSwgY2xlYXJTZWxlY3Rpb246IGZhbHNlIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAbWV0aG9kXG4gICAgICogQGRlcHJlY2F0ZWRcbiAgICAgKi9cbiAgICBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5zZWxlY3RJbmRleCA9IGZ1bmN0aW9uIChpbmRleCwgdHJ5TXVsdGkpIHtcbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLnJvd01vZGVsLmdldFJvdyhpbmRleCk7XG4gICAgICAgIHRoaXMuc2VsZWN0Tm9kZShub2RlLCB0cnlNdWx0aSk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJEsoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJyb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkSyhbXG4gICAgICAgIF9fcGFyYW0kNCgwLCBRdWFsaWZpZXIoJ2xvZ2dlckZhY3RvcnknKSlcbiAgICBdLCBTZWxlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJzZXRCZWFuc1wiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJEsoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgU2VsZWN0aW9uU2VydmljZS5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBTZWxlY3Rpb25TZXJ2aWNlID0gX19kZWNvcmF0ZSRLKFtcbiAgICAgICAgQmVhbignc2VsZWN0aW9uU2VydmljZScpXG4gICAgXSwgU2VsZWN0aW9uU2VydmljZSk7XG4gICAgcmV0dXJuIFNlbGVjdGlvblNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2RlY29yYXRlJEogPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBDb2x1bW5BcGkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29sdW1uQXBpKCkge1xuICAgIH1cbiAgICAvKiogR2V0cyB0aGUgZ3JpZCB0byBzaXplIHRoZSBjb2x1bW5zIHRvIHRoZSBzcGVjaWZpZWQgd2lkdGggaW4gcGl4ZWxzLCBlLmcuIGBzaXplQ29sdW1uc1RvRml0KDkwMClgLiBUbyBoYXZlIHRoZSBncmlkIGZpdCB0aGUgY29sdW1ucyB0byB0aGUgZ3JpZCdzIHdpZHRoLCB1c2UgdGhlIEdyaWQgQVBJIGBncmlkQXBpLnNpemVDb2x1bW5zVG9GaXQoKWAgaW5zdGVhZC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNpemVDb2x1bW5zVG9GaXQgPSBmdW5jdGlvbiAoZ3JpZFdpZHRoKSB7XG4gICAgICAgIC8vIEFHLTM0MDMgdmFsaWRhdGUgdGhhdCBncmlkV2lkdGggaXMgcHJvdmlkZWQgYmVjYXVzZSB0aGlzIG1ldGhvZCBoYXMgdGhlIHNhbWUgbmFtZSBhc1xuICAgICAgICAvLyBhIG1ldGhvZCBvbiB0aGUgZ3JpZCBBUEkgdGhhdCB0YWtlcyBubyBhcmd1bWVudHMsIGFuZCBpdCdzIGVhc3kgdG8gY29uZnVzZSB0aGUgdHdvXG4gICAgICAgIGlmICh0eXBlb2YgZ3JpZFdpZHRoID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBtaXNzaW5nIHBhcmFtZXRlciB0byBjb2x1bW5BcGkuc2l6ZUNvbHVtbnNUb0ZpdChncmlkV2lkdGgpJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zaXplQ29sdW1uc1RvRml0KGdyaWRXaWR0aCwgJ2FwaScpO1xuICAgIH07XG4gICAgLyoqIENhbGwgdGhpcyBpZiB5b3Ugd2FudCB0byBvcGVuIG9yIGNsb3NlIGEgY29sdW1uIGdyb3VwLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0Q29sdW1uR3JvdXBPcGVuZWQgPSBmdW5jdGlvbiAoZ3JvdXAsIG5ld1ZhbHVlKSB7IHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uR3JvdXBPcGVuZWQoZ3JvdXAsIG5ld1ZhbHVlLCAnYXBpJyk7IH07XG4gICAgLyoqIFJldHVybnMgdGhlIGNvbHVtbiBncm91cCB3aXRoIHRoZSBnaXZlbiBuYW1lLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0Q29sdW1uR3JvdXAgPSBmdW5jdGlvbiAobmFtZSwgaW5zdGFuY2VJZCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRDb2x1bW5Hcm91cChuYW1lLCBpbnN0YW5jZUlkKTsgfTtcbiAgICAvKiogUmV0dXJucyB0aGUgcHJvdmlkZWQgY29sdW1uIGdyb3VwIHdpdGggdGhlIGdpdmVuIG5hbWUuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRQcm92aWRlZENvbHVtbkdyb3VwID0gZnVuY3Rpb24gKG5hbWUpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cChuYW1lKTsgfTtcbiAgICAvKiogUmV0dXJucyB0aGUgZGlzcGxheSBuYW1lIGZvciBhIGNvbHVtbi4gVXNlZnVsIGlmIHlvdSBhcmUgZG9pbmcgeW91ciBvd24gaGVhZGVyIHJlbmRlcmluZyBhbmQgd2FudCB0aGUgZ3JpZCB0byB3b3JrIG91dCBpZiBgaGVhZGVyVmFsdWVHZXR0ZXJgIGlzIHVzZWQsIG9yIGlmIHlvdSBhcmUgZG9pbmcgeW91ciBvd24gY29sdW1uIG1hbmFnZW1lbnQgR1VJLCB0byBrbm93IHdoYXQgdG8gc2hvdyBhcyB0aGUgY29sdW1uIG5hbWUuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXREaXNwbGF5TmFtZUZvckNvbHVtbiA9IGZ1bmN0aW9uIChjb2x1bW4sIGxvY2F0aW9uKSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXlOYW1lRm9yQ29sdW1uKGNvbHVtbiwgbG9jYXRpb24pIHx8ICcnOyB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBkaXNwbGF5IG5hbWUgZm9yIGEgY29sdW1uIGdyb3VwICh3aGVuIGdyb3VwaW5nIGNvbHVtbnMpLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW5Hcm91cCA9IGZ1bmN0aW9uIChjb2x1bW5Hcm91cCwgbG9jYXRpb24pIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW5Hcm91cChjb2x1bW5Hcm91cCwgbG9jYXRpb24pIHx8ICcnOyB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBjb2x1bW4gd2l0aCB0aGUgZ2l2ZW4gYGNvbEtleWAsIHdoaWNoIGNhbiBlaXRoZXIgYmUgdGhlIGBjb2xJZGAgKGEgc3RyaW5nKSBvciB0aGUgYGNvbERlZmAgKGFuIG9iamVjdCkuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRDb2x1bW4gPSBmdW5jdGlvbiAoa2V5KSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldFByaW1hcnlDb2x1bW4oa2V5KTsgfTtcbiAgICAvKiogUmV0dXJucyBhbGwgdGhlIGNvbHVtbnMsIHJlZ2FyZGxlc3Mgb2YgdmlzaWJsZSBvciBub3QuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRDb2x1bW5zID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxQcmltYXJ5Q29sdW1ucygpOyB9O1xuICAgIC8qKiBBcHBsaWVzIHRoZSBzdGF0ZSBvZiB0aGUgY29sdW1ucyBmcm9tIGEgcHJldmlvdXMgc3RhdGUuIFJldHVybnMgYGZhbHNlYCBpZiBvbmUgb3IgbW9yZSBjb2x1bW5zIGNvdWxkIG5vdCBiZSBmb3VuZC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmFwcGx5Q29sdW1uU3RhdGUgPSBmdW5jdGlvbiAocGFyYW1zKSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmFwcGx5Q29sdW1uU3RhdGUocGFyYW1zLCAnYXBpJyk7IH07XG4gICAgLyoqIEdldHMgdGhlIHN0YXRlIG9mIHRoZSBjb2x1bW5zLiBUeXBpY2FsbHkgdXNlZCB3aGVuIHNhdmluZyBjb2x1bW4gc3RhdGUuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRDb2x1bW5TdGF0ZSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0Q29sdW1uU3RhdGUoKTsgfTtcbiAgICAvKiogU2V0cyB0aGUgc3RhdGUgYmFjayB0byBtYXRjaCB0aGUgb3JpZ2luYWxseSBwcm92aWRlZCBjb2x1bW4gZGVmaW5pdGlvbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5yZXNldENvbHVtblN0YXRlID0gZnVuY3Rpb24gKCkgeyB0aGlzLmNvbHVtbk1vZGVsLnJlc2V0Q29sdW1uU3RhdGUoJ2FwaScpOyB9O1xuICAgIC8qKiBHZXRzIHRoZSBzdGF0ZSBvZiB0aGUgY29sdW1uIGdyb3Vwcy4gVHlwaWNhbGx5IHVzZWQgd2hlbiBzYXZpbmcgY29sdW1uIGdyb3VwIHN0YXRlLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0Q29sdW1uR3JvdXBTdGF0ZSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0Q29sdW1uR3JvdXBTdGF0ZSgpOyB9O1xuICAgIC8qKiBTZXRzIHRoZSBzdGF0ZSBvZiB0aGUgY29sdW1uIGdyb3VwIHN0YXRlIGZyb20gYSBwcmV2aW91cyBzdGF0ZS4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldENvbHVtbkdyb3VwU3RhdGUgPSBmdW5jdGlvbiAoc3RhdGVJdGVtcykgeyB0aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbkdyb3VwU3RhdGUoc3RhdGVJdGVtcywgJ2FwaScpOyB9O1xuICAgIC8qKiBTZXRzIHRoZSBzdGF0ZSBiYWNrIHRvIG1hdGNoIHRoZSBvcmlnaW5hbGx5IHByb3ZpZGVkIGNvbHVtbiBkZWZpbml0aW9ucy4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnJlc2V0Q29sdW1uR3JvdXBTdGF0ZSA9IGZ1bmN0aW9uICgpIHsgdGhpcy5jb2x1bW5Nb2RlbC5yZXNldENvbHVtbkdyb3VwU3RhdGUoJ2FwaScpOyB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiBwaW5uaW5nIGxlZnQgb3IgcmlnaHQsIG90aGVyd2lzZSBgZmFsc2VgLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuaXNQaW5uaW5nID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpbm5pbmdMZWZ0KCkgfHwgdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpbm5pbmdSaWdodCgpOyB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiBwaW5uaW5nIGxlZnQsIG90aGVyd2lzZSBgZmFsc2VgLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuaXNQaW5uaW5nTGVmdCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuaXNQaW5uaW5nTGVmdCgpOyB9O1xuICAgIC8qKiBSZXR1cm5zIGB0cnVlYCBpZiBwaW5uaW5nIHJpZ2h0LCBvdGhlcndpc2UgYGZhbHNlYC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmlzUGlubmluZ1JpZ2h0ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpbm5pbmdSaWdodCgpOyB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBjb2x1bW4gdG8gdGhlIHJpZ2h0IG9mIHRoZSBwcm92aWRlZCBjb2x1bW4sIHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gb3BlbiAvIGNsb3NlZCBjb2x1bW4gZ3JvdXBzIGFuZCB2aXNpYmxlIGNvbHVtbnMuIFRoaXMgaXMgdXNlZnVsIGlmIHlvdSBuZWVkIHRvIGtub3cgd2hhdCBjb2x1bW4gaXMgYmVzaWRlIHlvdXJzIGUuZy4gaWYgaW1wbGVtZW50aW5nIHlvdXIgb3duIGNlbGwgbmF2aWdhdGlvbi4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmdldERpc3BsYXllZENvbEFmdGVyID0gZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2xBZnRlcihjb2wpOyB9O1xuICAgIC8qKiBTYW1lIGFzIGBnZXRWaXNpYmxlQ29sQWZ0ZXJgIGV4Y2VwdCBnaXZlcyBjb2x1bW4gdG8gdGhlIGxlZnQuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXREaXNwbGF5ZWRDb2xCZWZvcmUgPSBmdW5jdGlvbiAoY29sKSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbEJlZm9yZShjb2wpOyB9O1xuICAgIC8qKiBTZXRzIHRoZSB2aXNpYmlsaXR5IG9mIGEgY29sdW1uLiBLZXkgY2FuIGJlIHRoZSBjb2x1bW4gSUQgb3IgYENvbHVtbmAgb2JqZWN0LiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0Q29sdW1uVmlzaWJsZSA9IGZ1bmN0aW9uIChrZXksIHZpc2libGUpIHsgdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5WaXNpYmxlKGtleSwgdmlzaWJsZSwgJ2FwaScpOyB9O1xuICAgIC8qKiBTYW1lIGFzIGBzZXRDb2x1bW5WaXNpYmxlYCwgYnV0IHByb3ZpZGUgYSBsaXN0IG9mIGNvbHVtbiBrZXlzLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0Q29sdW1uc1Zpc2libGUgPSBmdW5jdGlvbiAoa2V5cywgdmlzaWJsZSkgeyB0aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbnNWaXNpYmxlKGtleXMsIHZpc2libGUsICdhcGknKTsgfTtcbiAgICAvKiogU2V0cyB0aGUgY29sdW1uIHBpbm5lZCAvIHVucGlubmVkLiBLZXkgY2FuIGJlIHRoZSBjb2x1bW4gSUQsIGZpZWxkLCBgQ29sRGVmYCBvYmplY3Qgb3IgYENvbHVtbmAgb2JqZWN0LiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0Q29sdW1uUGlubmVkID0gZnVuY3Rpb24gKGtleSwgcGlubmVkKSB7IHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uUGlubmVkKGtleSwgcGlubmVkLCAnYXBpJyk7IH07XG4gICAgLyoqIFNhbWUgYXMgYHNldENvbHVtblBpbm5lZGAsIGJ1dCBwcm92aWRlIGEgbGlzdCBvZiBjb2x1bW4ga2V5cy4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldENvbHVtbnNQaW5uZWQgPSBmdW5jdGlvbiAoa2V5cywgcGlubmVkKSB7IHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uc1Bpbm5lZChrZXlzLCBwaW5uZWQsICdhcGknKTsgfTtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFsbCB0aGUgZ3JpZCBjb2x1bW5zLCBzYW1lIGFzIGBnZXRDb2x1bW5zKClgLCBleGNlcHRcbiAgICAgKlxuICAgICAqICBhKSBpdCBoYXMgdGhlIG9yZGVyIG9mIHRoZSBjb2x1bW5zIHRoYXQgYXJlIHByZXNlbnRlZCBpbiB0aGUgZ3JpZFxuICAgICAqXG4gICAgICogIGIpIGl0J3MgYWZ0ZXIgdGhlICdwaXZvdCcgc3RlcCwgc28gaWYgcGl2b3RpbmcsIGhhcyB0aGUgdmFsdWUgY29sdW1ucyBmb3IgdGhlIHBpdm90LlxuICAgICAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0QWxsR3JpZENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldEFsbEdyaWRDb2x1bW5zKCk7IH07XG4gICAgLyoqIFNhbWUgYXMgYGdldEFsbERpc3BsYXllZENvbHVtbnNgIGJ1dCBqdXN0IGZvciB0aGUgcGlubmVkIGxlZnQgcG9ydGlvbiBvZiB0aGUgZ3JpZC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmdldERpc3BsYXllZExlZnRDb2x1bW5zID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRMZWZ0Q29sdW1ucygpOyB9O1xuICAgIC8qKiBTYW1lIGFzIGBnZXRBbGxEaXNwbGF5ZWRDb2x1bW5zYCBidXQganVzdCBmb3IgdGhlIGNlbnRlciBwb3J0aW9uIG9mIHRoZSBncmlkLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0RGlzcGxheWVkQ2VudGVyQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkQ2VudGVyQ29sdW1ucygpOyB9O1xuICAgIC8qKiBTYW1lIGFzIGBnZXRBbGxEaXNwbGF5ZWRDb2x1bW5zYCBidXQganVzdCBmb3IgdGhlIHBpbm5lZCByaWdodCBwb3J0aW9uIG9mIHRoZSBncmlkLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0RGlzcGxheWVkUmlnaHRDb2x1bW5zID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRSaWdodENvbHVtbnMoKTsgfTtcbiAgICAvKiogUmV0dXJucyBhbGwgY29sdW1ucyBjdXJyZW50bHkgZGlzcGxheWVkIChlLmcuIGFyZSB2aXNpYmxlIGFuZCBpZiBpbiBhIGdyb3VwLCB0aGUgZ3JvdXAgaXMgc2hvd2luZyB0aGUgY29sdW1ucykgZm9yIHRoZSBwaW5uZWQgbGVmdCwgY2VudHJlIGFuZCBwaW5uZWQgcmlnaHQgcG9ydGlvbnMgb2YgdGhlIGdyaWQuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7IH07XG4gICAgLyoqIFNhbWUgYXMgYGdldEFsbEdyaWRDb2x1bW5zKClgLCBleGNlcHQgb25seSByZXR1cm5zIHJlbmRlcmVkIGNvbHVtbnMsIGkuZS4gY29sdW1ucyB0aGF0IGFyZSBub3Qgd2l0aGluIHRoZSB2aWV3cG9ydCBhbmQgdGhlcmVmb3JlIG5vdCByZW5kZXJlZCwgZHVlIHRvIGNvbHVtbiB2aXJ0dWFsaXNhdGlvbiwgYXJlIG5vdCBkaXNwbGF5ZWQuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRBbGxEaXNwbGF5ZWRWaXJ0dWFsQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0Vmlld3BvcnRDb2x1bW5zKCk7IH07XG4gICAgLyoqIE1vdmVzIGEgY29sdW1uIHRvIGB0b0luZGV4YC4gVGhlIGNvbHVtbiBpcyBmaXJzdCByZW1vdmVkLCB0aGVuIGFkZGVkIGF0IHRoZSBgdG9JbmRleGAgbG9jYXRpb24sIHRodXMgaW5kZXggbG9jYXRpb25zIHdpbGwgY2hhbmdlIHRvIHRoZSByaWdodCBvZiB0aGUgY29sdW1uIGFmdGVyIHRoZSByZW1vdmFsLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUubW92ZUNvbHVtbiA9IGZ1bmN0aW9uIChrZXksIHRvSW5kZXgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBrZXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAvLyBtb3ZlQ29sdW1uIHVzZWQgdG8gdGFrZSBpbmRleGVzLCBzbyB0aGlzIGlzIGFkdmlzaW5nIHVzZXIgd2hvIGhhc24ndCBtb3ZlZCB0byBuZXcgbWV0aG9kIG5hbWVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogeW91IGFyZSB1c2luZyBtb3ZlQ29sdW1uKGZyb21JbmRleCwgdG9JbmRleCkgLSBtb3ZlQ29sdW1uIHRha2VzIGEgY29sdW1uIGtleSBhbmQgYSBkZXN0aW5hdGlvbiBpbmRleCwgbm90IHR3byBpbmRleGVzLCB0byBtb3ZlIHdpdGggaW5kZXhlcyB1c2UgbW92ZUNvbHVtbkJ5SW5kZXgoZnJvbSx0bykgaW5zdGVhZCcpO1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5tb3ZlQ29sdW1uQnlJbmRleChrZXksIHRvSW5kZXgsICdhcGknKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY29sdW1uTW9kZWwubW92ZUNvbHVtbihrZXksIHRvSW5kZXgsICdhcGknKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLyoqIFNhbWUgYXMgYG1vdmVDb2x1bW5gIGJ1dCB3b3JrcyBvbiBpbmRleCBsb2NhdGlvbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5tb3ZlQ29sdW1uQnlJbmRleCA9IGZ1bmN0aW9uIChmcm9tSW5kZXgsIHRvSW5kZXgpIHsgdGhpcy5jb2x1bW5Nb2RlbC5tb3ZlQ29sdW1uQnlJbmRleChmcm9tSW5kZXgsIHRvSW5kZXgsICdhcGknKTsgfTtcbiAgICAvKiogU2FtZSBhcyBgbW92ZUNvbHVtbmAgYnV0IHdvcmtzIG9uIGxpc3QuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5tb3ZlQ29sdW1ucyA9IGZ1bmN0aW9uIChjb2x1bW5zVG9Nb3ZlS2V5cywgdG9JbmRleCkgeyB0aGlzLmNvbHVtbk1vZGVsLm1vdmVDb2x1bW5zKGNvbHVtbnNUb01vdmVLZXlzLCB0b0luZGV4LCAnYXBpJyk7IH07XG4gICAgLyoqIE1vdmUgdGhlIGNvbHVtbiB0byBhIG5ldyBwb3NpdGlvbiBpbiB0aGUgcm93IGdyb3VwaW5nIG9yZGVyLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUubW92ZVJvd0dyb3VwQ29sdW1uID0gZnVuY3Rpb24gKGZyb21JbmRleCwgdG9JbmRleCkgeyB0aGlzLmNvbHVtbk1vZGVsLm1vdmVSb3dHcm91cENvbHVtbihmcm9tSW5kZXgsIHRvSW5kZXgpOyB9O1xuICAgIC8qKiBTZXRzIHRoZSBhZ2cgZnVuY3Rpb24gZm9yIGEgY29sdW1uLiBgYWdnRnVuY2AgY2FuIGJlIG9uZSBvZiBgJ21pbicgfCAnbWF4JyB8ICdzdW0nYC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldENvbHVtbkFnZ0Z1bmMgPSBmdW5jdGlvbiAoa2V5LCBhZ2dGdW5jKSB7IHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uQWdnRnVuYyhrZXksIGFnZ0Z1bmMpOyB9O1xuICAgIC8qKiBTZXRzIHRoZSBjb2x1bW4gd2lkdGggb24gYSBzaW5nbGUgY29sdW1uLiBUaGUgZmluaXNoZWQgZmxhZyBnZXRzIGluY2x1ZGVkIGluIHRoZSByZXN1bHRpbmcgZXZlbnQgYW5kIG5vdCB1c2VkIGludGVybmFsbHkgYnkgdGhlIGdyaWQuIFRoZSBmaW5pc2hlZCBmbGFnIGlzIGludGVuZGVkIGZvciBkcmFnZ2luZywgd2hlcmUgYSBkcmFnZ2luZyBhY3Rpb24gd2lsbCBwcm9kdWNlIG1hbnkgYGNvbHVtbldpZHRoYCBldmVudHMsIHNvIHRoZSBjb25zdW1lciBvZiBldmVudHMga25vd3Mgd2hlbiBpdCByZWNlaXZlcyB0aGUgbGFzdCBldmVudCBpbiBhIHN0cmVhbS4gVGhlIGZpbmlzaGVkIHBhcmFtZXRlciBpcyBvcHRpb25hbCwgYW5kIGRlZmF1bHRzIHRvIGB0cnVlYC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldENvbHVtbldpZHRoID0gZnVuY3Rpb24gKGtleSwgbmV3V2lkdGgsIGZpbmlzaGVkLCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKGZpbmlzaGVkID09PSB2b2lkIDApIHsgZmluaXNoZWQgPSB0cnVlOyB9XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uV2lkdGhzKFt7IGtleToga2V5LCBuZXdXaWR0aDogbmV3V2lkdGggfV0sIGZhbHNlLCBmaW5pc2hlZCwgc291cmNlKTtcbiAgICB9O1xuICAgIC8qKiBTZXRzIHRoZSBjb2x1bW4gd2lkdGhzIG9uIG11bHRpcGxlIGNvbHVtbnMuIFRoaXMgbWV0aG9kIG9mZmVycyBiZXR0ZXIgcGVyZm9ybWFuY2UgdGhhbiBjYWxsaW5nIGBzZXRDb2x1bW5XaWR0aGAgbXVsdGlwbGUgdGltZXMuIFRoZSBmaW5pc2hlZCBmbGFnIGdldHMgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdGluZyBldmVudCBhbmQgbm90IHVzZWQgaW50ZXJuYWxseSBieSB0aGUgZ3JpZC4gVGhlIGZpbmlzaGVkIGZsYWcgaXMgaW50ZW5kZWQgZm9yIGRyYWdnaW5nLCB3aGVyZSBhIGRyYWdnaW5nIGFjdGlvbiB3aWxsIHByb2R1Y2UgbWFueSBgY29sdW1uV2lkdGhgIGV2ZW50cywgc28gdGhlIGNvbnN1bWVyIG9mIGV2ZW50cyBrbm93cyB3aGVuIGl0IHJlY2VpdmVzIHRoZSBsYXN0IGV2ZW50IGluIGEgc3RyZWFtLiBUaGUgZmluaXNoZWQgcGFyYW1ldGVyIGlzIG9wdGlvbmFsLCBhbmQgZGVmYXVsdHMgdG8gYHRydWVgLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0Q29sdW1uV2lkdGhzID0gZnVuY3Rpb24gKGNvbHVtbldpZHRocywgZmluaXNoZWQsIHNvdXJjZSkge1xuICAgICAgICBpZiAoZmluaXNoZWQgPT09IHZvaWQgMCkgeyBmaW5pc2hlZCA9IHRydWU7IH1cbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5XaWR0aHMoY29sdW1uV2lkdGhzLCBmYWxzZSwgZmluaXNoZWQsIHNvdXJjZSk7XG4gICAgfTtcbiAgICAvKiogU2V0IHRoZSBwaXZvdCBtb2RlLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0UGl2b3RNb2RlID0gZnVuY3Rpb24gKHBpdm90TW9kZSkgeyB0aGlzLmNvbHVtbk1vZGVsLnNldFBpdm90TW9kZShwaXZvdE1vZGUpOyB9O1xuICAgIC8qKiBHZXQgdGhlIHBpdm90IG1vZGUuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5pc1Bpdm90TW9kZSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuaXNQaXZvdE1vZGUoKTsgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgVXNlIGBnZXRQaXZvdFJlc3VsdENvbHVtbmAgaW5zdGVhZCAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0U2Vjb25kYXJ5UGl2b3RDb2x1bW4gPSBmdW5jdGlvbiAocGl2b3RLZXlzLCB2YWx1ZUNvbEtleSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHZlcnNpb24gMjguMC54IGdldFNlY29uZGFyeVBpdm90Q29sdW1uIGhhcyBiZWVuIHJlbmFtZWQsIHBsZWFzZSB1c2UgZ2V0UGl2b3RSZXN1bHRDb2x1bW4gaW5zdGVhZCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQaXZvdFJlc3VsdENvbHVtbihwaXZvdEtleXMsIHZhbHVlQ29sS2V5KTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBwaXZvdCByZXN1bHQgY29sdW1uIGZvciB0aGUgZ2l2ZW4gYHBpdm90S2V5c2AgYW5kIGB2YWx1ZUNvbElkYC4gVXNlZnVsIHRvIHRoZW4gY2FsbCBvcGVyYXRpb25zIG9uIHRoZSBwaXZvdCBjb2x1bW4uICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRQaXZvdFJlc3VsdENvbHVtbiA9IGZ1bmN0aW9uIChwaXZvdEtleXMsIHZhbHVlQ29sS2V5KSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldFNlY29uZGFyeVBpdm90Q29sdW1uKHBpdm90S2V5cywgdmFsdWVDb2xLZXkpOyB9O1xuICAgIC8qKiBTZXQgdGhlIHZhbHVlIGNvbHVtbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5zZXRWYWx1ZUNvbHVtbnMgPSBmdW5jdGlvbiAoY29sS2V5cykgeyB0aGlzLmNvbHVtbk1vZGVsLnNldFZhbHVlQ29sdW1ucyhjb2xLZXlzLCAnYXBpJyk7IH07XG4gICAgLyoqIEdldCB2YWx1ZSBjb2x1bW5zLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0VmFsdWVDb2x1bW5zID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRWYWx1ZUNvbHVtbnMoKTsgfTtcbiAgICAvKiogUmVtb3ZlIGEgdmFsdWUgY29sdW1uLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUucmVtb3ZlVmFsdWVDb2x1bW4gPSBmdW5jdGlvbiAoY29sS2V5KSB7IHRoaXMuY29sdW1uTW9kZWwucmVtb3ZlVmFsdWVDb2x1bW4oY29sS2V5LCAnYXBpJyk7IH07XG4gICAgLyoqIFNhbWUgYXMgYHJlbW92ZVZhbHVlQ29sdW1uc2AgYnV0IHByb3ZpZGUgYSBsaXN0LiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUucmVtb3ZlVmFsdWVDb2x1bW5zID0gZnVuY3Rpb24gKGNvbEtleXMpIHsgdGhpcy5jb2x1bW5Nb2RlbC5yZW1vdmVWYWx1ZUNvbHVtbnMoY29sS2V5cywgJ2FwaScpOyB9O1xuICAgIC8qKiBBZGQgYSB2YWx1ZSBjb2x1bW4uICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5hZGRWYWx1ZUNvbHVtbiA9IGZ1bmN0aW9uIChjb2xLZXkpIHsgdGhpcy5jb2x1bW5Nb2RlbC5hZGRWYWx1ZUNvbHVtbihjb2xLZXksICdhcGknKTsgfTtcbiAgICAvKiogU2FtZSBhcyBgYWRkVmFsdWVDb2x1bW5gIGJ1dCBwcm92aWRlIGEgbGlzdC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmFkZFZhbHVlQ29sdW1ucyA9IGZ1bmN0aW9uIChjb2xLZXlzKSB7IHRoaXMuY29sdW1uTW9kZWwuYWRkVmFsdWVDb2x1bW5zKGNvbEtleXMsICdhcGknKTsgfTtcbiAgICAvKiogU2V0IHRoZSByb3cgZ3JvdXAgY29sdW1ucy4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldFJvd0dyb3VwQ29sdW1ucyA9IGZ1bmN0aW9uIChjb2xLZXlzKSB7IHRoaXMuY29sdW1uTW9kZWwuc2V0Um93R3JvdXBDb2x1bW5zKGNvbEtleXMsICdhcGknKTsgfTtcbiAgICAvKiogUmVtb3ZlIGEgY29sdW1uIGZyb20gdGhlIHJvdyBncm91cHMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5yZW1vdmVSb3dHcm91cENvbHVtbiA9IGZ1bmN0aW9uIChjb2xLZXkpIHsgdGhpcy5jb2x1bW5Nb2RlbC5yZW1vdmVSb3dHcm91cENvbHVtbihjb2xLZXksICdhcGknKTsgfTtcbiAgICAvKiogU2FtZSBhcyBgcmVtb3ZlUm93R3JvdXBDb2x1bW5gIGJ1dCBwcm92aWRlIGEgbGlzdCBvZiBjb2x1bW5zLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUucmVtb3ZlUm93R3JvdXBDb2x1bW5zID0gZnVuY3Rpb24gKGNvbEtleXMpIHsgdGhpcy5jb2x1bW5Nb2RlbC5yZW1vdmVSb3dHcm91cENvbHVtbnMoY29sS2V5cywgJ2FwaScpOyB9O1xuICAgIC8qKiBBZGQgYSBjb2x1bW4gdG8gdGhlIHJvdyBncm91cHMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5hZGRSb3dHcm91cENvbHVtbiA9IGZ1bmN0aW9uIChjb2xLZXkpIHsgdGhpcy5jb2x1bW5Nb2RlbC5hZGRSb3dHcm91cENvbHVtbihjb2xLZXksICdhcGknKTsgfTtcbiAgICAvKiogU2FtZSBhcyBgYWRkUm93R3JvdXBDb2x1bW5gIGJ1dCBwcm92aWRlIGEgbGlzdCBvZiBjb2x1bW5zLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuYWRkUm93R3JvdXBDb2x1bW5zID0gZnVuY3Rpb24gKGNvbEtleXMpIHsgdGhpcy5jb2x1bW5Nb2RlbC5hZGRSb3dHcm91cENvbHVtbnMoY29sS2V5cywgJ2FwaScpOyB9O1xuICAgIC8qKiBHZXQgcm93IGdyb3VwIGNvbHVtbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRSb3dHcm91cENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldFJvd0dyb3VwQ29sdW1ucygpOyB9O1xuICAgIC8qKiBTZXQgdGhlIHBpdm90IGNvbHVtbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5zZXRQaXZvdENvbHVtbnMgPSBmdW5jdGlvbiAoY29sS2V5cykgeyB0aGlzLmNvbHVtbk1vZGVsLnNldFBpdm90Q29sdW1ucyhjb2xLZXlzLCAnYXBpJyk7IH07XG4gICAgLyoqIFJlbW92ZSBhIHBpdm90IGNvbHVtbi4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnJlbW92ZVBpdm90Q29sdW1uID0gZnVuY3Rpb24gKGNvbEtleSkgeyB0aGlzLmNvbHVtbk1vZGVsLnJlbW92ZVBpdm90Q29sdW1uKGNvbEtleSwgJ2FwaScpOyB9O1xuICAgIC8qKiBTYW1lIGFzIGByZW1vdmVQaXZvdENvbHVtbmAgYnV0IHByb3ZpZGUgYSBsaXN0IG9mIGNvbHVtbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5yZW1vdmVQaXZvdENvbHVtbnMgPSBmdW5jdGlvbiAoY29sS2V5cykgeyB0aGlzLmNvbHVtbk1vZGVsLnJlbW92ZVBpdm90Q29sdW1ucyhjb2xLZXlzLCAnYXBpJyk7IH07XG4gICAgLyoqIEFkZCBhIHBpdm90IGNvbHVtbi4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmFkZFBpdm90Q29sdW1uID0gZnVuY3Rpb24gKGNvbEtleSkgeyB0aGlzLmNvbHVtbk1vZGVsLmFkZFBpdm90Q29sdW1uKGNvbEtleSwgJ2FwaScpOyB9O1xuICAgIC8qKiBTYW1lIGFzIGBhZGRQaXZvdENvbHVtbmAgYnV0IHByb3ZpZGUgYSBsaXN0IG9mIGNvbHVtbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5hZGRQaXZvdENvbHVtbnMgPSBmdW5jdGlvbiAoY29sS2V5cykgeyB0aGlzLmNvbHVtbk1vZGVsLmFkZFBpdm90Q29sdW1ucyhjb2xLZXlzLCAnYXBpJyk7IH07XG4gICAgLyoqIEdldCB0aGUgcGl2b3QgY29sdW1ucy4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmdldFBpdm90Q29sdW1ucyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0UGl2b3RDb2x1bW5zKCk7IH07XG4gICAgLyoqIFNhbWUgYXMgYGdldEFsbERpc3BsYXllZENvbHVtbkdyb3Vwc2AgYnV0IGp1c3QgZm9yIHRoZSBwaW5uZWQgbGVmdCBwb3J0aW9uIG9mIHRoZSBncmlkLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0TGVmdERpc3BsYXllZENvbHVtbkdyb3VwcyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheWVkVHJlZUxlZnQoKTsgfTtcbiAgICAvKiogU2FtZSBhcyBgZ2V0QWxsRGlzcGxheWVkQ29sdW1uR3JvdXBzYCBidXQganVzdCBmb3IgdGhlIGNlbnRlciBwb3J0aW9uIG9mIHRoZSBncmlkLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0Q2VudGVyRGlzcGxheWVkQ29sdW1uR3JvdXBzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRUcmVlQ2VudHJlKCk7IH07XG4gICAgLyoqIFNhbWUgYXMgYGdldEFsbERpc3BsYXllZENvbHVtbkdyb3Vwc2AgYnV0IGp1c3QgZm9yIHRoZSBwaW5uZWQgcmlnaHQgcG9ydGlvbiBvZiB0aGUgZ3JpZC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmdldFJpZ2h0RGlzcGxheWVkQ29sdW1uR3JvdXBzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRUcmVlUmlnaHQoKTsgfTtcbiAgICAvKiogUmV0dXJucyBhbGwgJ3Jvb3QnIGNvbHVtbiBoZWFkZXJzLiBJZiB5b3UgYXJlIG5vdCBncm91cGluZyBjb2x1bW5zLCB0aGVzZSByZXR1cm4gdGhlIGNvbHVtbnMuIElmIHlvdSBhcmUgZ3JvdXBpbmcsIHRoZXNlIHJldHVybiB0aGUgdG9wIGxldmVsIGdyb3VwcyAtIHlvdSBjYW4gbmF2aWdhdGUgZG93biB0aHJvdWdoIGVhY2ggb25lIHRvIGdldCB0aGUgb3RoZXIgbG93ZXIgbGV2ZWwgaGVhZGVycyBhbmQgZmluYWxseSB0aGUgY29sdW1ucyBhdCB0aGUgYm90dG9tLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0QWxsRGlzcGxheWVkQ29sdW1uR3JvdXBzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRUcmVlcygpOyB9O1xuICAgIC8qKiBBdXRvLXNpemVzIGEgY29sdW1uIGJhc2VkIG9uIGl0cyBjb250ZW50cy4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmF1dG9TaXplQ29sdW1uID0gZnVuY3Rpb24gKGtleSwgc2tpcEhlYWRlcikgeyByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5hdXRvU2l6ZUNvbHVtbihrZXksIHNraXBIZWFkZXIsICdhcGknKTsgfTtcbiAgICAvKiogU2FtZSBhcyBgYXV0b1NpemVDb2x1bW5gLCBidXQgcHJvdmlkZSBhIGxpc3Qgb2YgY29sdW1uIGtleXMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5hdXRvU2l6ZUNvbHVtbnMgPSBmdW5jdGlvbiAoa2V5cywgc2tpcEhlYWRlcikge1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLmF1dG9TaXplQ29sdW1ucyh7IGNvbHVtbnM6IGtleXMsIHNraXBIZWFkZXI6IHNraXBIZWFkZXIgfSk7XG4gICAgfTtcbiAgICAvKiogQ2FsbHMgYGF1dG9TaXplQ29sdW1uc2Agb24gYWxsIGRpc3BsYXllZCBjb2x1bW5zLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuYXV0b1NpemVBbGxDb2x1bW5zID0gZnVuY3Rpb24gKHNraXBIZWFkZXIpIHsgdGhpcy5jb2x1bW5Nb2RlbC5hdXRvU2l6ZUFsbENvbHVtbnMoc2tpcEhlYWRlciwgJ2FwaScpOyB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBVc2UgYHNldFBpdm90UmVzdWx0Q29sdW1uc2AgaW5zdGVhZC4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldFNlY29uZGFyeUNvbHVtbnMgPSBmdW5jdGlvbiAoY29sRGVmcykge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHZlcnNpb24gMjguMC54IHNldFNlY29uZGFyeUNvbHVtbnMgaGFzIGJlZW4gcmVuYW1lZCwgcGxlYXNlIHVzZSBzZXRQaXZvdFJlc3VsdENvbHVtbnMgaW5zdGVhZCcpO1xuICAgICAgICB0aGlzLnNldFBpdm90UmVzdWx0Q29sdW1ucyhjb2xEZWZzKTtcbiAgICB9O1xuICAgIC8qKiBTZXQgdGhlIHBpdm90IHJlc3VsdCBjb2x1bW5zLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0UGl2b3RSZXN1bHRDb2x1bW5zID0gZnVuY3Rpb24gKGNvbERlZnMpIHsgdGhpcy5jb2x1bW5Nb2RlbC5zZXRTZWNvbmRhcnlDb2x1bW5zKGNvbERlZnMsICdhcGknKTsgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgVXNlIGBnZXRQaXZvdFJlc3VsdENvbHVtbnNgIGluc3RlYWQuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRTZWNvbmRhcnlDb2x1bW5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHNpbmNlIHZlcnNpb24gMjguMC54IGdldFNlY29uZGFyeUNvbHVtbnMgaGFzIGJlZW4gcmVuYW1lZCwgcGxlYXNlIHVzZSBnZXRQaXZvdFJlc3VsdENvbHVtbnMgaW5zdGVhZCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQaXZvdFJlc3VsdENvbHVtbnMoKTtcbiAgICB9O1xuICAgIC8qKiBSZXR1cm5zIHRoZSBncmlkJ3MgcGl2b3QgcmVzdWx0IGNvbHVtbnMuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRQaXZvdFJlc3VsdENvbHVtbnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldFNlY29uZGFyeUNvbHVtbnMoKTsgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgVXNlIGBnZXRDb2x1bW5zYCBpbnN0ZWFkLiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0UHJpbWFyeUNvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogc2luY2UgdmVyc2lvbiAyOC4wLnggZ2V0UHJpbWFyeUNvbHVtbnMgaGFzIGJlZW4gcmVuYW1lZCwgcGxlYXNlIHVzZSBnZXRDb2x1bW5zIGluc3RlYWQnKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1ucygpO1xuICAgIH07XG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5jbGVhbkRvd25SZWZlcmVuY2VzVG9Bdm9pZE1lbW9yeUxlYWtJbkNhc2VBcHBsaWNhdGlvbklzS2VlcGluZ1JlZmVyZW5jZVRvRGVzdHJveWVkR3JpZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gc29tZSB1c2VycyB3ZXJlIHJhaXNpbmcgc3VwcG9ydCBpc3N1ZXMgd2l0aCByZWdhcmRzIG1lbW9yeSBsZWFrcy4gdGhlIHByb2JsZW0gd2FzIHRoZSBjdXN0b21lcnMgYXBwbGljYXRpb25zXG4gICAgICAgIC8vIHdlcmUga2VlcGluZyByZWZlcmVuY2VzIHRvIHRoZSBBUEkuIHRyeWluZyB0byBlZHVjYXRlIHRoZW0gYWxsIHdvdWxkIGJlIGRpZmZpY3VsdCwgZWFzaWVyIHRvIGp1c3QgcmVtb3ZlXG4gICAgICAgIC8vIGFsbCByZWZlcmVuY2VzIGluIHRoZSBBUEkgc28gYXQgbGVhc3QgdGhlIGNvcmUgZ3JpZCBjYW4gYmUgZ2FyYmFnZSBjb2xsZWN0ZWQuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIHdhaXQgYWJvdXQgMTAwbXMgYmVmb3JlIGNsZWFyaW5nIGRvd24gdGhlIHJlZmVyZW5jZXMsIGluIGNhc2UgdXNlciBoYXMgc29tZSBjbGVhbnVwIHRvIGRvLFxuICAgICAgICAvLyBhbmQgbmVlZHMgdG8gZGVmZXJlbmNlIHRoZSBBUEkgZmlyc3RcbiAgICAgICAgc2V0VGltZW91dChfLnJlbW92ZUFsbFJlZmVyZW5jZXMuYmluZCh3aW5kb3csIHRoaXMsICdDb2x1bW4gQVBJJyksIDEwMCk7XG4gICAgfTtcbiAgICAvLyBiZWxvdyBnb2VzIHRocm91Z2ggZGVwcmVjYXRlZCBpdGVtcywgcHJpbnRzIG1lc3NhZ2UgdG8gdXNlciwgdGhlbiBjYWxscyB0aGUgbmV3IHZlcnNpb24gb2YgdGhlIHNhbWUgbWV0aG9kXG4gICAgLy8gcHVibGljIGdldENvbHVtbkRlZnMoKTogKENvbERlZiB8IENvbEdyb3VwRGVmKVtdIHtcbiAgICAvLyAgICAgdGhpcy5zZXRDb2x1bW5Hcm91cE9wZW5lZChncm91cCwgbmV3VmFsdWUpO1xuICAgIC8vICAgICByZXR1cm4gbnVsbDtcbiAgICAvLyB9XG4gICAgLyoqIEBkZXByZWNhdGVkIFVzZSBgZ2V0Q29sdW1uc2AgaW5zdGVhZCAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuZ2V0QWxsQ29sdW1ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBzaW5jZSB2ZXJzaW9uIDI4LjAueCBnZXRBbGxDb2x1bW5zIGhhcyBiZWVuIHJlbmFtZWQsIHBsZWFzZSB1c2UgZ2V0Q29sdW1ucyBpbnN0ZWFkJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbHVtbnMoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBjb2x1bW5Hcm91cE9wZW5lZCBubyBsb25nZXIgZXhpc3RzLCB1c2Ugc2V0Q29sdW1uR3JvdXBPcGVuZWQgKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmNvbHVtbkdyb3VwT3BlbmVkID0gZnVuY3Rpb24gKGdyb3VwLCBuZXdWYWx1ZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBjb2x1bW5Hcm91cE9wZW5lZCBubyBsb25nZXIgZXhpc3RzLCB1c2Ugc2V0Q29sdW1uR3JvdXBPcGVuZWQnKTtcbiAgICAgICAgdGhpcy5zZXRDb2x1bW5Hcm91cE9wZW5lZChncm91cCwgbmV3VmFsdWUpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIGhpZGVDb2x1bW5zIGlzIGRlcHJlY2F0ZWQsIHVzZSBzZXRDb2x1bW5zVmlzaWJsZSAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuaGlkZUNvbHVtbnMgPSBmdW5jdGlvbiAoY29sSWRzLCBoaWRlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGhpZGVDb2x1bW5zIGlzIGRlcHJlY2F0ZWQsIHVzZSBzZXRDb2x1bW5zVmlzaWJsZScpO1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLnNldENvbHVtbnNWaXNpYmxlKGNvbElkcywgIWhpZGUsICdhcGknKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBoaWRlQ29sdW1uIGlzIGRlcHJlY2F0ZWQsIHVzZSBzZXRDb2x1bW5WaXNpYmxlICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5oaWRlQ29sdW1uID0gZnVuY3Rpb24gKGNvbElkLCBoaWRlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGhpZGVDb2x1bW4gaXMgZGVwcmVjYXRlZCwgdXNlIHNldENvbHVtblZpc2libGUnKTtcbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5WaXNpYmxlKGNvbElkLCAhaGlkZSwgJ2FwaScpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIHNldFN0YXRlIGlzIGRlcHJlY2F0ZWQsIHVzZSBzZXRDb2x1bW5TdGF0ZSAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0U3RhdGUgPSBmdW5jdGlvbiAoY29sdW1uU3RhdGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogc2V0U3RhdGUgaXMgZGVwcmVjYXRlZCwgdXNlIHNldENvbHVtblN0YXRlJyk7XG4gICAgICAgIHJldHVybiB0aGlzLnNldENvbHVtblN0YXRlKGNvbHVtblN0YXRlKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBnZXRTdGF0ZSBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0Q29sdW1uU3RhdGUgKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBnZXRTdGF0ZSBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0Q29sdW1uU3RhdGUnKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uU3RhdGUoKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCByZXNldFN0YXRlIGlzIGRlcHJlY2F0ZWQsIHVzZSByZXNldENvbHVtblN0YXRlICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5yZXNldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiByZXNldFN0YXRlIGlzIGRlcHJlY2F0ZWQsIHVzZSByZXNldENvbHVtblN0YXRlJyk7XG4gICAgICAgIHRoaXMucmVzZXRDb2x1bW5TdGF0ZSgpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIGdldEFnZ3JlZ2F0aW9uQ29sdW1ucyBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0VmFsdWVDb2x1bW5zICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRBZ2dyZWdhdGlvbkNvbHVtbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGdldEFnZ3JlZ2F0aW9uQ29sdW1ucyBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0VmFsdWVDb2x1bW5zJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmdldFZhbHVlQ29sdW1ucygpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIHJlbW92ZUFnZ3JlZ2F0aW9uQ29sdW1uIGlzIGRlcHJlY2F0ZWQsIHVzZSByZW1vdmVWYWx1ZUNvbHVtbiAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUucmVtb3ZlQWdncmVnYXRpb25Db2x1bW4gPSBmdW5jdGlvbiAoY29sS2V5KSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHJlbW92ZUFnZ3JlZ2F0aW9uQ29sdW1uIGlzIGRlcHJlY2F0ZWQsIHVzZSByZW1vdmVWYWx1ZUNvbHVtbicpO1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLnJlbW92ZVZhbHVlQ29sdW1uKGNvbEtleSwgJ2FwaScpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIHJlbW92ZUFnZ3JlZ2F0aW9uQ29sdW1ucyBpcyBkZXByZWNhdGVkLCB1c2UgcmVtb3ZlVmFsdWVDb2x1bW5zICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5yZW1vdmVBZ2dyZWdhdGlvbkNvbHVtbnMgPSBmdW5jdGlvbiAoY29sS2V5cykge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiByZW1vdmVBZ2dyZWdhdGlvbkNvbHVtbnMgaXMgZGVwcmVjYXRlZCwgdXNlIHJlbW92ZVZhbHVlQ29sdW1ucycpO1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLnJlbW92ZVZhbHVlQ29sdW1ucyhjb2xLZXlzLCAnYXBpJyk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgYWRkQWdncmVnYXRpb25Db2x1bW4gaXMgZGVwcmVjYXRlZCwgdXNlIGFkZFZhbHVlQ29sdW1uICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5hZGRBZ2dyZWdhdGlvbkNvbHVtbiA9IGZ1bmN0aW9uIChjb2xLZXkpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogYWRkQWdncmVnYXRpb25Db2x1bW4gaXMgZGVwcmVjYXRlZCwgdXNlIGFkZFZhbHVlQ29sdW1uJyk7XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuYWRkVmFsdWVDb2x1bW4oY29sS2V5LCAnYXBpJyk7XG4gICAgfTtcbiAgICAvKiogQGRlcHJlY2F0ZWQgYWRkQWdncmVnYXRpb25Db2x1bW5zIGlzIGRlcHJlY2F0ZWQsIHVzZSBhZGRWYWx1ZUNvbHVtbnMgKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmFkZEFnZ3JlZ2F0aW9uQ29sdW1ucyA9IGZ1bmN0aW9uIChjb2xLZXlzKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGFkZEFnZ3JlZ2F0aW9uQ29sdW1ucyBpcyBkZXByZWNhdGVkLCB1c2UgYWRkVmFsdWVDb2x1bW5zJyk7XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuYWRkVmFsdWVDb2x1bW5zKGNvbEtleXMsICdhcGknKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBzZXRDb2x1bW5BZ2dGdW5jdGlvbiBpcyBkZXByZWNhdGVkLCB1c2Ugc2V0Q29sdW1uQWdnRnVuYyAqL1xuICAgIENvbHVtbkFwaS5wcm90b3R5cGUuc2V0Q29sdW1uQWdnRnVuY3Rpb24gPSBmdW5jdGlvbiAoY29sdW1uLCBhZ2dGdW5jKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHNldENvbHVtbkFnZ0Z1bmN0aW9uIGlzIGRlcHJlY2F0ZWQsIHVzZSBzZXRDb2x1bW5BZ2dGdW5jJyk7XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwuc2V0Q29sdW1uQWdnRnVuYyhjb2x1bW4sIGFnZ0Z1bmMsICdhcGknKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBnZXREaXNwbGF5TmFtZUZvckNvbCBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLmdldERpc3BsYXlOYW1lRm9yQ29sID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBnZXREaXNwbGF5TmFtZUZvckNvbCBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW4nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW4oY29sdW1uLCBudWxsKTtcbiAgICB9O1xuICAgIC8qKiBAZGVwcmVjYXRlZCBzZXRDb2x1bW5TdGF0ZSBpcyBkZXByZWNhdGVkLCB1c2UgYXBwbHlDb2x1bW5TdGF0ZS4gKi9cbiAgICBDb2x1bW5BcGkucHJvdG90eXBlLnNldENvbHVtblN0YXRlID0gZnVuY3Rpb24gKGNvbHVtblN0YXRlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHNldENvbHVtblN0YXRlIGlzIGRlcHJlY2F0ZWQsIHVzZSBhcHBseUNvbHVtblN0YXRlJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbHVtbk1vZGVsLmFwcGx5Q29sdW1uU3RhdGUoeyBzdGF0ZTogY29sdW1uU3RhdGUsIGFwcGx5T3JkZXI6IHRydWUgfSwgJ2FwaScpO1xuICAgIH07XG4gICAgLyoqIEBkZXByZWNhdGVkIGdldE9yaWdpbmFsQ29sdW1uR3JvdXAgaXMgZGVwcmVjYXRlZCwgdXNlIGdldFByb3ZpZGVkQ29sdW1uR3JvdXAuICovXG4gICAgQ29sdW1uQXBpLnByb3RvdHlwZS5nZXRPcmlnaW5hbENvbHVtbkdyb3VwID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogZ2V0T3JpZ2luYWxDb2x1bW5Hcm91cCBpcyBkZXByZWNhdGVkLCB1c2UgZ2V0UHJvdmlkZWRDb2x1bW5Hcm91cCcpO1xuICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcm92aWRlZENvbHVtbkdyb3VwKG5hbWUpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRKKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgQ29sdW1uQXBpLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkSihbXG4gICAgICAgIFByZURlc3Ryb3lcbiAgICBdLCBDb2x1bW5BcGkucHJvdG90eXBlLCBcImNsZWFuRG93blJlZmVyZW5jZXNUb0F2b2lkTWVtb3J5TGVha0luQ2FzZUFwcGxpY2F0aW9uSXNLZWVwaW5nUmVmZXJlbmNlVG9EZXN0cm95ZWRHcmlkXCIsIG51bGwpO1xuICAgIENvbHVtbkFwaSA9IF9fZGVjb3JhdGUkSihbXG4gICAgICAgIEJlYW4oJ2NvbHVtbkFwaScpXG4gICAgXSwgQ29sdW1uQXBpKTtcbiAgICByZXR1cm4gQ29sdW1uQXBpO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRIID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRJID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgVmFsdWVTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRIKFZhbHVlU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBWYWx1ZVNlcnZpY2UoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5pbml0aWFsaXNlZCA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIFZhbHVlU2VydmljZS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jZWxsRXhwcmVzc2lvbnMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZUNlbGxFeHByZXNzaW9ucygpO1xuICAgICAgICB0aGlzLmluaXRpYWxpc2VkID0gdHJ1ZTtcbiAgICAgICAgLy8gV2UgbGlzdGVuIHRvIG91ciBvd24gZXZlbnQgYW5kIHVzZSBpdCB0byBjYWxsIHRoZSBjb2x1bW5TcGVjaWZpYyBjYWxsYmFjayxcbiAgICAgICAgLy8gdGhpcyB3YXkgdGhlIGhhbmRsZXIgY2FsbHMgYXJlIGNvcnJlY3RseSBpbnRlcmxlYXZlZCB3aXRoIG90aGVyIGdsb2JhbCBldmVudHNcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuYWRkRXZlbnRMaXN0ZW5lcihFdmVudHMuRVZFTlRfQ0VMTF9WQUxVRV9DSEFOR0VELCBmdW5jdGlvbiAoZXZlbnQpIHsgcmV0dXJuIF90aGlzLmNhbGxDb2x1bW5DZWxsVmFsdWVDaGFuZ2VkSGFuZGxlcihldmVudCk7IH0sIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnVzZUFzeW5jRXZlbnRzKCkpO1xuICAgIH07XG4gICAgVmFsdWVTZXJ2aWNlLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uIChjb2x1bW4sIHJvd05vZGUsIGZvckZpbHRlciwgaWdub3JlQWdnRGF0YSkge1xuICAgICAgICBpZiAoZm9yRmlsdGVyID09PSB2b2lkIDApIHsgZm9yRmlsdGVyID0gZmFsc2U7IH1cbiAgICAgICAgaWYgKGlnbm9yZUFnZ0RhdGEgPT09IHZvaWQgMCkgeyBpZ25vcmVBZ2dEYXRhID0gZmFsc2U7IH1cbiAgICAgICAgLy8gaGFjayAtIHRoZSBncmlkIGlzIGdldHRpbmcgcmVmcmVzaGVkIGJlZm9yZSB0aGlzIGJlYW4gZ2V0cyBpbml0aWFsaXNlZCwgcmFjZSBjb25kaXRpb24uXG4gICAgICAgIC8vIHJlYWxseSBzaG91bGQgaGF2ZSBhIHdheSBzbyB0aGV5IGdldCBpbml0aWFsaXNlZCBpbiB0aGUgcmlnaHQgb3JkZXI/Pz9cbiAgICAgICAgaWYgKCF0aGlzLmluaXRpYWxpc2VkKSB7XG4gICAgICAgICAgICB0aGlzLmluaXQoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJvd05vZGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwdWxsIHRoZXNlIG91dCB0byBtYWtlIGNvZGUgYmVsb3cgZWFzaWVyIHRvIHJlYWRcbiAgICAgICAgdmFyIGNvbERlZiA9IGNvbHVtbi5nZXRDb2xEZWYoKTtcbiAgICAgICAgdmFyIGZpZWxkID0gY29sRGVmLmZpZWxkO1xuICAgICAgICB2YXIgY29sSWQgPSBjb2x1bW4uZ2V0SWQoKTtcbiAgICAgICAgdmFyIGRhdGEgPSByb3dOb2RlLmRhdGE7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIC8vIGlmIHRoZXJlIGlzIGEgdmFsdWUgZ2V0dGVyLCB0aGlzIGdldHMgcHJlY2VkZW5jZSBvdmVyIGEgZmllbGRcbiAgICAgICAgdmFyIGdyb3VwRGF0YUV4aXN0cyA9IHJvd05vZGUuZ3JvdXBEYXRhICYmIHJvd05vZGUuZ3JvdXBEYXRhW2NvbElkXSAhPT0gdW5kZWZpbmVkO1xuICAgICAgICB2YXIgYWdnRGF0YUV4aXN0cyA9ICFpZ25vcmVBZ2dEYXRhICYmIHJvd05vZGUuYWdnRGF0YSAmJiByb3dOb2RlLmFnZ0RhdGFbY29sSWRdICE9PSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChmb3JGaWx0ZXIgJiYgY29sRGVmLmZpbHRlclZhbHVlR2V0dGVyKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmV4ZWN1dGVGaWx0ZXJWYWx1ZUdldHRlcihjb2xEZWYuZmlsdGVyVmFsdWVHZXR0ZXIsIGRhdGEsIGNvbHVtbiwgcm93Tm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNUcmVlRGF0YSgpICYmIGFnZ0RhdGFFeGlzdHMpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHJvd05vZGUuYWdnRGF0YVtjb2xJZF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNUcmVlRGF0YSgpICYmIGNvbERlZi52YWx1ZUdldHRlcikge1xuICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5leGVjdXRlVmFsdWVHZXR0ZXIoY29sRGVmLnZhbHVlR2V0dGVyLCBkYXRhLCBjb2x1bW4sIHJvd05vZGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKSAmJiAoZmllbGQgJiYgZGF0YSkpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGdldFZhbHVlVXNpbmdGaWVsZChkYXRhLCBmaWVsZCwgY29sdW1uLmlzRmllbGRDb250YWluc0RvdHMoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZ3JvdXBEYXRhRXhpc3RzKSB7XG4gICAgICAgICAgICByZXN1bHQgPSByb3dOb2RlLmdyb3VwRGF0YVtjb2xJZF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoYWdnRGF0YUV4aXN0cykge1xuICAgICAgICAgICAgcmVzdWx0ID0gcm93Tm9kZS5hZ2dEYXRhW2NvbElkXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb2xEZWYudmFsdWVHZXR0ZXIpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuZXhlY3V0ZVZhbHVlR2V0dGVyKGNvbERlZi52YWx1ZUdldHRlciwgZGF0YSwgY29sdW1uLCByb3dOb2RlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChmaWVsZCAmJiBkYXRhKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBnZXRWYWx1ZVVzaW5nRmllbGQoZGF0YSwgZmllbGQsIGNvbHVtbi5pc0ZpZWxkQ29udGFpbnNEb3RzKCkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoZSByZXN1bHQgY291bGQgYmUgYW4gZXhwcmVzc2lvbiBpdHNlbGYsIGlmIHdlIGFyZSBhbGxvd2luZyBjZWxsIHZhbHVlcyB0byBiZSBleHByZXNzaW9uc1xuICAgICAgICBpZiAodGhpcy5jZWxsRXhwcmVzc2lvbnMgJiYgKHR5cGVvZiByZXN1bHQgPT09ICdzdHJpbmcnKSAmJiByZXN1bHQuaW5kZXhPZignPScpID09PSAwKSB7XG4gICAgICAgICAgICB2YXIgY2VsbFZhbHVlR2V0dGVyID0gcmVzdWx0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuZXhlY3V0ZVZhbHVlR2V0dGVyKGNlbGxWYWx1ZUdldHRlciwgZGF0YSwgY29sdW1uLCByb3dOb2RlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBvcGVuZWRHcm91cCA9IHRoaXMuZ2V0T3BlbmVkR3JvdXAocm93Tm9kZSwgY29sdW1uKTtcbiAgICAgICAgICAgIGlmIChvcGVuZWRHcm91cCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wZW5lZEdyb3VwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBWYWx1ZVNlcnZpY2UucHJvdG90eXBlLmdldE9wZW5lZEdyb3VwID0gZnVuY3Rpb24gKHJvd05vZGUsIGNvbHVtbikge1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU2hvd09wZW5lZEdyb3VwKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29sRGVmID0gY29sdW1uLmdldENvbERlZigpO1xuICAgICAgICBpZiAoIWNvbERlZi5zaG93Um93R3JvdXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2hvd1Jvd0dyb3VwID0gY29sdW1uLmdldENvbERlZigpLnNob3dSb3dHcm91cDtcbiAgICAgICAgdmFyIHBvaW50ZXIgPSByb3dOb2RlLnBhcmVudDtcbiAgICAgICAgd2hpbGUgKHBvaW50ZXIgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHBvaW50ZXIucm93R3JvdXBDb2x1bW4gJiYgKHNob3dSb3dHcm91cCA9PT0gdHJ1ZSB8fCBzaG93Um93R3JvdXAgPT09IHBvaW50ZXIucm93R3JvdXBDb2x1bW4uZ2V0SWQoKSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcG9pbnRlci5rZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwb2ludGVyID0gcG9pbnRlci5wYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZhbHVlIG9mIGEgR3JpZENlbGxcbiAgICAgKiBAcGFyYW0gcm93Tm9kZSBUaGUgYFJvd05vZGVgIHRvIGJlIHVwZGF0ZWRcbiAgICAgKiBAcGFyYW0gY29sS2V5IFRoZSBgQ29sdW1uYCB0byBiZSB1cGRhdGVkXG4gICAgICogQHBhcmFtIG5ld1ZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gYmUgc2V0XG4gICAgICogQHBhcmFtIGV2ZW50U291cmNlIFRoZSBldmVudCBzb3VyY2VcbiAgICAgKiBAcmV0dXJucyBgVHJ1ZWAgaWYgdGhlIHZhbHVlIGhhcyBiZWVuIHVwZGF0ZWQsIG90aGVyd2lzZWBGYWxzZWAuXG4gICAgICovXG4gICAgVmFsdWVTZXJ2aWNlLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uIChyb3dOb2RlLCBjb2xLZXksIG5ld1ZhbHVlLCBldmVudFNvdXJjZSkge1xuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5Q29sdW1uKGNvbEtleSk7XG4gICAgICAgIGlmICghcm93Tm9kZSB8fCAhY29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhpcyB3aWxsIG9ubHkgaGFwcGVuIGlmIHVzZXIgaXMgdHJ5aW5nIHRvIHBhc3RlIGludG8gYSBncm91cCByb3csIHdoaWNoIGRvZXNuJ3QgbWFrZSBzZW5zZVxuICAgICAgICAvLyB0aGUgdXNlciBzaG91bGQgbm90IGJlIHRyeWluZyB0byBwYXN0ZSBpbnRvIGdyb3VwIHJvd3NcbiAgICAgICAgaWYgKG1pc3Npbmcocm93Tm9kZS5kYXRhKSkge1xuICAgICAgICAgICAgcm93Tm9kZS5kYXRhID0ge307XG4gICAgICAgIH1cbiAgICAgICAgLy8gZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdlIGFyZSBhbHNvIHJldHJpZXZpbmcgdGhlIG5ld1ZhbHVlSGFuZGxlciBhcyB3ZWxsIGFzIHRoZSB2YWx1ZVNldHRlclxuICAgICAgICB2YXIgX2EgPSBjb2x1bW4uZ2V0Q29sRGVmKCksIGZpZWxkID0gX2EuZmllbGQsIG5ld1ZhbHVlSGFuZGxlciA9IF9hLm5ld1ZhbHVlSGFuZGxlciwgdmFsdWVTZXR0ZXIgPSBfYS52YWx1ZVNldHRlcjtcbiAgICAgICAgLy8gbmVlZCBlaXRoZXIgYSBmaWVsZCBvciBhIG5ld1ZhbHVlSGFuZGxlciBmb3IgdGhpcyB0byB3b3JrXG4gICAgICAgIGlmIChtaXNzaW5nKGZpZWxkKSAmJiBtaXNzaW5nKG5ld1ZhbHVlSGFuZGxlcikgJiYgbWlzc2luZyh2YWx1ZVNldHRlcikpIHtcbiAgICAgICAgICAgIC8vIHdlIGRvbid0IHRlbGwgdXNlciBhYm91dCBuZXdWYWx1ZUhhbmRsZXIsIGFzIHRoYXQgaXMgZGVwcmVjYXRlZFxuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogeW91IG5lZWQgZWl0aGVyIGZpZWxkIG9yIHZhbHVlU2V0dGVyIHNldCBvbiBjb2xEZWYgZm9yIGVkaXRpbmcgdG8gd29ya1wiKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgbm9kZTogcm93Tm9kZSxcbiAgICAgICAgICAgIGRhdGE6IHJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgIG9sZFZhbHVlOiB0aGlzLmdldFZhbHVlKGNvbHVtbiwgcm93Tm9kZSksXG4gICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICBjb2xEZWY6IGNvbHVtbi5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICBjb250ZXh0OiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KClcbiAgICAgICAgfTtcbiAgICAgICAgcGFyYW1zLm5ld1ZhbHVlID0gbmV3VmFsdWU7XG4gICAgICAgIHZhciB2YWx1ZVdhc0RpZmZlcmVudDtcbiAgICAgICAgaWYgKG5ld1ZhbHVlSGFuZGxlciAmJiBleGlzdHMobmV3VmFsdWVIYW5kbGVyKSkge1xuICAgICAgICAgICAgdmFsdWVXYXNEaWZmZXJlbnQgPSBuZXdWYWx1ZUhhbmRsZXIocGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChleGlzdHModmFsdWVTZXR0ZXIpKSB7XG4gICAgICAgICAgICB2YWx1ZVdhc0RpZmZlcmVudCA9IHRoaXMuZXhwcmVzc2lvblNlcnZpY2UuZXZhbHVhdGUodmFsdWVTZXR0ZXIsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZVdhc0RpZmZlcmVudCA9IHRoaXMuc2V0VmFsdWVVc2luZ0ZpZWxkKHJvd05vZGUuZGF0YSwgZmllbGQsIG5ld1ZhbHVlLCBjb2x1bW4uaXNGaWVsZENvbnRhaW5zRG90cygpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpbiBjYXNlIHVzZXIgZm9yZ290IHRvIHJldHVybiBzb21ldGhpbmcgKHBvc3NpYmxlIGlmIHRoZXkgYXJlIG5vdCB1c2luZyBUeXBlU2NyaXB0XG4gICAgICAgIC8vIGFuZCBqdXN0IGZvcmdvdCwgb3IgdXNpbmcgYW4gb2xkIG5ld1ZhbHVlSGFuZGxlciB3ZSBkaWRuJ3QgYWx3YXlzIGV4cGVjdCBhIHJldHVyblxuICAgICAgICAvLyB2YWx1ZSBoZXJlKSwgd2UgZGVmYXVsdCB0aGUgcmV0dXJuIHZhbHVlIHRvIHRydWUsIHNvIHdlIGFsd2F5cyByZWZyZXNoLlxuICAgICAgICBpZiAodmFsdWVXYXNEaWZmZXJlbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdmFsdWVXYXNEaWZmZXJlbnQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIG5vIGNoYW5nZSB0byB0aGUgdmFsdWUsIHRoZW4gbm8gbmVlZCB0byBkbyB0aGUgdXBkYXRpbmcsIG9yIG5vdGlmeWluZyB2aWEgZXZlbnRzLlxuICAgICAgICAvLyBvdGhlcndpc2UgdGhlIHVzZXIgY291bGQgYmUgdGFiYmluZyBhcm91bmQgdGhlIGdyaWQsIGFuZCBjZWxsVmFsdWVDaGFuZ2Ugd291bGQgZ2V0IGNhbGxlZFxuICAgICAgICAvLyBhbGwgdGhlIHRpbWUuXG4gICAgICAgIGlmICghdmFsdWVXYXNEaWZmZXJlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyByZXNldCBxdWljayBmaWx0ZXIgb24gdGhpcyByb3dcbiAgICAgICAgcm93Tm9kZS5yZXNldFF1aWNrRmlsdGVyQWdncmVnYXRlVGV4dCgpO1xuICAgICAgICB0aGlzLnZhbHVlQ2FjaGUub25EYXRhQ2hhbmdlZCgpO1xuICAgICAgICBwYXJhbXMubmV3VmFsdWUgPSB0aGlzLmdldFZhbHVlKGNvbHVtbiwgcm93Tm9kZSk7XG4gICAgICAgIHZhciBldmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9DRUxMX1ZBTFVFX0NIQU5HRUQsXG4gICAgICAgICAgICBldmVudDogbnVsbCxcbiAgICAgICAgICAgIHJvd0luZGV4OiByb3dOb2RlLnJvd0luZGV4LFxuICAgICAgICAgICAgcm93UGlubmVkOiByb3dOb2RlLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIGNvbHVtbjogcGFyYW1zLmNvbHVtbixcbiAgICAgICAgICAgIGFwaTogcGFyYW1zLmFwaSxcbiAgICAgICAgICAgIGNvbHVtbkFwaTogcGFyYW1zLmNvbHVtbkFwaSxcbiAgICAgICAgICAgIGNvbERlZjogcGFyYW1zLmNvbERlZixcbiAgICAgICAgICAgIGNvbnRleHQ6IHBhcmFtcy5jb250ZXh0LFxuICAgICAgICAgICAgZGF0YTogcm93Tm9kZS5kYXRhLFxuICAgICAgICAgICAgbm9kZTogcm93Tm9kZSxcbiAgICAgICAgICAgIG9sZFZhbHVlOiBwYXJhbXMub2xkVmFsdWUsXG4gICAgICAgICAgICBuZXdWYWx1ZTogcGFyYW1zLm5ld1ZhbHVlLFxuICAgICAgICAgICAgdmFsdWU6IHBhcmFtcy5uZXdWYWx1ZSxcbiAgICAgICAgICAgIHNvdXJjZTogZXZlbnRTb3VyY2VcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgVmFsdWVTZXJ2aWNlLnByb3RvdHlwZS5jYWxsQ29sdW1uQ2VsbFZhbHVlQ2hhbmdlZEhhbmRsZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIG9uQ2VsbFZhbHVlQ2hhbmdlZCA9IGV2ZW50LmNvbERlZi5vbkNlbGxWYWx1ZUNoYW5nZWQ7XG4gICAgICAgIGlmICh0eXBlb2Ygb25DZWxsVmFsdWVDaGFuZ2VkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBvbkNlbGxWYWx1ZUNoYW5nZWQoe1xuICAgICAgICAgICAgICAgIG5vZGU6IGV2ZW50Lm5vZGUsXG4gICAgICAgICAgICAgICAgZGF0YTogZXZlbnQuZGF0YSxcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZTogZXZlbnQub2xkVmFsdWUsXG4gICAgICAgICAgICAgICAgbmV3VmFsdWU6IGV2ZW50Lm5ld1ZhbHVlLFxuICAgICAgICAgICAgICAgIGNvbERlZjogZXZlbnQuY29sRGVmLFxuICAgICAgICAgICAgICAgIGNvbHVtbjogZXZlbnQuY29sdW1uLFxuICAgICAgICAgICAgICAgIGFwaTogZXZlbnQuYXBpLFxuICAgICAgICAgICAgICAgIGNvbHVtbkFwaTogZXZlbnQuY29sdW1uQXBpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IGV2ZW50LmNvbnRleHRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWYWx1ZVNlcnZpY2UucHJvdG90eXBlLnNldFZhbHVlVXNpbmdGaWVsZCA9IGZ1bmN0aW9uIChkYXRhLCBmaWVsZCwgbmV3VmFsdWUsIGlzRmllbGRDb250YWluc0RvdHMpIHtcbiAgICAgICAgaWYgKCFmaWVsZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIG5vICcuJywgdGhlbiBpdCdzIG5vdCBhIGRlZXAgdmFsdWVcbiAgICAgICAgdmFyIHZhbHVlc0FyZVNhbWUgPSBmYWxzZTtcbiAgICAgICAgaWYgKCFpc0ZpZWxkQ29udGFpbnNEb3RzKSB7XG4gICAgICAgICAgICAvLyBzb2Z0IGNvbXBhcmlzb24gdG8gbWF0Y2ggc3RyaW5ncyBhbmQgbnVtYmVyc1xuICAgICAgICAgICAgdmFsdWVzQXJlU2FtZSA9IGRhdGFbZmllbGRdID09IG5ld1ZhbHVlO1xuICAgICAgICAgICAgaWYgKCF2YWx1ZXNBcmVTYW1lKSB7XG4gICAgICAgICAgICAgICAgZGF0YVtmaWVsZF0gPSBuZXdWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSBpdCBpcyBhIGRlZXAgdmFsdWUsIHNvIG5lZWQgdG8gZGlnIGZvciBpdFxuICAgICAgICAgICAgdmFyIGZpZWxkUGllY2VzID0gZmllbGQuc3BsaXQoJy4nKTtcbiAgICAgICAgICAgIHZhciBjdXJyZW50T2JqZWN0ID0gZGF0YTtcbiAgICAgICAgICAgIHdoaWxlIChmaWVsZFBpZWNlcy5sZW5ndGggPiAwICYmIGN1cnJlbnRPYmplY3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgZmllbGRQaWVjZSA9IGZpZWxkUGllY2VzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgaWYgKGZpZWxkUGllY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzb2Z0IGNvbXBhcmlzb24gdG8gbWF0Y2ggc3RyaW5ncyBhbmQgbnVtYmVyc1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZXNBcmVTYW1lID0gY3VycmVudE9iamVjdFtmaWVsZFBpZWNlXSA9PSBuZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWx1ZXNBcmVTYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50T2JqZWN0W2ZpZWxkUGllY2VdID0gbmV3VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRPYmplY3QgPSBjdXJyZW50T2JqZWN0W2ZpZWxkUGllY2VdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gIXZhbHVlc0FyZVNhbWU7XG4gICAgfTtcbiAgICBWYWx1ZVNlcnZpY2UucHJvdG90eXBlLmV4ZWN1dGVGaWx0ZXJWYWx1ZUdldHRlciA9IGZ1bmN0aW9uICh2YWx1ZUdldHRlciwgZGF0YSwgY29sdW1uLCByb3dOb2RlKSB7XG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBkYXRhOiBkYXRhLFxuICAgICAgICAgICAgbm9kZTogcm93Tm9kZSxcbiAgICAgICAgICAgIGNvbHVtbjogY29sdW1uLFxuICAgICAgICAgICAgY29sRGVmOiBjb2x1bW4uZ2V0Q29sRGVmKCksXG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKSxcbiAgICAgICAgICAgIGdldFZhbHVlOiB0aGlzLmdldFZhbHVlQ2FsbGJhY2suYmluZCh0aGlzLCByb3dOb2RlKVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcy5leHByZXNzaW9uU2VydmljZS5ldmFsdWF0ZSh2YWx1ZUdldHRlciwgcGFyYW1zKTtcbiAgICB9O1xuICAgIFZhbHVlU2VydmljZS5wcm90b3R5cGUuZXhlY3V0ZVZhbHVlR2V0dGVyID0gZnVuY3Rpb24gKHZhbHVlR2V0dGVyLCBkYXRhLCBjb2x1bW4sIHJvd05vZGUpIHtcbiAgICAgICAgdmFyIGNvbElkID0gY29sdW1uLmdldElkKCk7XG4gICAgICAgIC8vIGlmIGluc2lkZSB0aGUgc2FtZSB0dXJuLCBqdXN0IHJldHVybiBiYWNrIHRoZSB2YWx1ZSB3ZSBnb3QgbGFzdCB0aW1lXG4gICAgICAgIHZhciB2YWx1ZUZyb21DYWNoZSA9IHRoaXMudmFsdWVDYWNoZS5nZXRWYWx1ZShyb3dOb2RlLCBjb2xJZCk7XG4gICAgICAgIGlmICh2YWx1ZUZyb21DYWNoZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVGcm9tQ2FjaGU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgICBub2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICBjb2xEZWY6IGNvbHVtbi5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgIGFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCksXG4gICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpLFxuICAgICAgICAgICAgZ2V0VmFsdWU6IHRoaXMuZ2V0VmFsdWVDYWxsYmFjay5iaW5kKHRoaXMsIHJvd05vZGUpXG4gICAgICAgIH07XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmV4cHJlc3Npb25TZXJ2aWNlLmV2YWx1YXRlKHZhbHVlR2V0dGVyLCBwYXJhbXMpO1xuICAgICAgICAvLyBpZiBhIHR1cm4gaXMgYWN0aXZlLCBzdG9yZSB0aGUgdmFsdWUgaW4gY2FzZSB0aGUgZ3JpZCBhc2tzIGZvciBpdCBhZ2FpblxuICAgICAgICB0aGlzLnZhbHVlQ2FjaGUuc2V0VmFsdWUocm93Tm9kZSwgY29sSWQsIHJlc3VsdCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBWYWx1ZVNlcnZpY2UucHJvdG90eXBlLmdldFZhbHVlQ2FsbGJhY2sgPSBmdW5jdGlvbiAobm9kZSwgZmllbGQpIHtcbiAgICAgICAgdmFyIG90aGVyQ29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5Q29sdW1uKGZpZWxkKTtcbiAgICAgICAgaWYgKG90aGVyQ29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRWYWx1ZShvdGhlckNvbHVtbiwgbm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICAvLyB1c2VkIGJ5IHJvdyBncm91cGluZyBhbmQgcGl2b3QsIHRvIGdldCBrZXkgZm9yIGEgcm93LiBjb2wgY2FuIGJlIGEgcGl2b3QgY29sIG9yIGEgcm93IGdyb3VwaW5nIGNvbFxuICAgIFZhbHVlU2VydmljZS5wcm90b3R5cGUuZ2V0S2V5Rm9yTm9kZSA9IGZ1bmN0aW9uIChjb2wsIHJvd05vZGUpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5nZXRWYWx1ZShjb2wsIHJvd05vZGUpO1xuICAgICAgICB2YXIga2V5Q3JlYXRvciA9IGNvbC5nZXRDb2xEZWYoKS5rZXlDcmVhdG9yO1xuICAgICAgICB2YXIgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIGlmIChrZXlDcmVhdG9yKSB7XG4gICAgICAgICAgICB2YXIga2V5UGFyYW1zID0ge1xuICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICBjb2xEZWY6IGNvbC5nZXRDb2xEZWYoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW46IGNvbCxcbiAgICAgICAgICAgICAgICBub2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgICAgIGRhdGE6IHJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbHVtbkFwaTogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCksXG4gICAgICAgICAgICAgICAgY29udGV4dDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29udGV4dCgpXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzdWx0ID0ga2V5Q3JlYXRvcihrZXlQYXJhbXMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGFscmVhZHkgYSBzdHJpbmcsIG9yIG1pc3NpbmcsIGp1c3QgcmV0dXJuIGl0XG4gICAgICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnc3RyaW5nJyB8fCByZXN1bHQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSBTdHJpbmcocmVzdWx0KTtcbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgICAgICAgIGRvT25jZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBhIGNvbHVtbiB5b3UgYXJlIGdyb3VwaW5nIG9yIHBpdm90aW5nIGJ5IGhhcyBvYmplY3RzIGFzIHZhbHVlcy4gSWYgeW91IHdhbnQgdG8gZ3JvdXAgYnkgY29tcGxleCBvYmplY3RzIHRoZW4gZWl0aGVyIGEpIHVzZSBhIGNvbERlZi5rZXlDcmVhdG9yIChzZSBBRyBHcmlkIGRvY3MpIG9yIGIpIHRvIHRvU3RyaW5nKCkgb24gdGhlIG9iamVjdCB0byByZXR1cm4gYSBrZXknKTtcbiAgICAgICAgICAgIH0sICdnZXRLZXlGb3JOb2RlIC0gd2FybiBhYm91dCBbb2JqZWN0LG9iamVjdF0nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRJKFtcbiAgICAgICAgQXV0b3dpcmVkKCdleHByZXNzaW9uU2VydmljZScpXG4gICAgXSwgVmFsdWVTZXJ2aWNlLnByb3RvdHlwZSwgXCJleHByZXNzaW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkSShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIFZhbHVlU2VydmljZS5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJEkoW1xuICAgICAgICBBdXRvd2lyZWQoJ3ZhbHVlQ2FjaGUnKVxuICAgIF0sIFZhbHVlU2VydmljZS5wcm90b3R5cGUsIFwidmFsdWVDYWNoZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkSShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBWYWx1ZVNlcnZpY2UucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgVmFsdWVTZXJ2aWNlID0gX19kZWNvcmF0ZSRJKFtcbiAgICAgICAgQmVhbigndmFsdWVTZXJ2aWNlJylcbiAgICBdLCBWYWx1ZVNlcnZpY2UpO1xuICAgIHJldHVybiBWYWx1ZVNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkRyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkSCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcGFyYW0kMyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcGFyYW0pIHx8IGZ1bmN0aW9uIChwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cbn07XG52YXIgRXhwcmVzc2lvblNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEcoRXhwcmVzc2lvblNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRXhwcmVzc2lvblNlcnZpY2UoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5leHByZXNzaW9uVG9GdW5jdGlvbkNhY2hlID0ge307XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgRXhwcmVzc2lvblNlcnZpY2UucHJvdG90eXBlLnNldEJlYW5zID0gZnVuY3Rpb24gKGxvZ2dlckZhY3RvcnkpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIgPSBsb2dnZXJGYWN0b3J5LmNyZWF0ZSgnRXhwcmVzc2lvblNlcnZpY2UnKTtcbiAgICB9O1xuICAgIEV4cHJlc3Npb25TZXJ2aWNlLnByb3RvdHlwZS5ldmFsdWF0ZSA9IGZ1bmN0aW9uIChleHByZXNzaW9uT3JGdW5jLCBwYXJhbXMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBleHByZXNzaW9uT3JGdW5jID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyB2YWx1ZUdldHRlciBpcyBhIGZ1bmN0aW9uLCBzbyBqdXN0IGNhbGwgaXRcbiAgICAgICAgICAgIHZhciBmdW5jID0gZXhwcmVzc2lvbk9yRnVuYztcbiAgICAgICAgICAgIHJldHVybiBmdW5jKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGV4cHJlc3Npb25PckZ1bmMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyB2YWx1ZUdldHRlciBpcyBhbiBleHByZXNzaW9uLCBzbyBleGVjdXRlIHRoZSBleHByZXNzaW9uXG4gICAgICAgICAgICB2YXIgZXhwcmVzc2lvbiA9IGV4cHJlc3Npb25PckZ1bmM7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5ldmFsdWF0ZUV4cHJlc3Npb24oZXhwcmVzc2lvbiwgcGFyYW1zKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHZhbHVlIHNob3VsZCBiZSBlaXRoZXIgYSBzdHJpbmcgb3IgYSBmdW5jdGlvbicsIGV4cHJlc3Npb25PckZ1bmMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBFeHByZXNzaW9uU2VydmljZS5wcm90b3R5cGUuZXZhbHVhdGVFeHByZXNzaW9uID0gZnVuY3Rpb24gKGV4cHJlc3Npb24sIHBhcmFtcykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIGphdmFTY3JpcHRGdW5jdGlvbiA9IHRoaXMuY3JlYXRlRXhwcmVzc2lvbkZ1bmN0aW9uKGV4cHJlc3Npb24pO1xuICAgICAgICAgICAgLy8gdGhlIHBhcmFtcyBkb24ndCBoYXZlIGFsbCB0aGVzZSB2YWx1ZXMsIHJhdGhlciB3ZSBhZGQgZXZlcnkgcG9zc2libGVcbiAgICAgICAgICAgIC8vIHZhbHVlIGEgcGFyYW1zIGNhbiBoYXZlLCB3aGljaCBtYWtlcyB3aGF0ZXZlciBpcyBpbiB0aGUgcGFyYW1zIGF2YWlsYWJsZS5cbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBqYXZhU2NyaXB0RnVuY3Rpb24ocGFyYW1zLnZhbHVlLCBwYXJhbXMuY29udGV4dCwgcGFyYW1zLm9sZFZhbHVlLCBwYXJhbXMubmV3VmFsdWUsIHBhcmFtcy52YWx1ZSwgcGFyYW1zLm5vZGUsIHBhcmFtcy5kYXRhLCBwYXJhbXMuY29sRGVmLCBwYXJhbXMucm93SW5kZXgsIHBhcmFtcy5hcGksIHBhcmFtcy5jb2x1bW5BcGksIHBhcmFtcy5nZXRWYWx1ZSwgcGFyYW1zLmNvbHVtbiwgcGFyYW1zLmNvbHVtbkdyb3VwKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIHRoZSBleHByZXNzaW9uIGZhaWxlZCwgd2hpY2ggY2FuIGhhcHBlbiwgYXMgaXQncyB0aGUgY2xpZW50IHRoYXRcbiAgICAgICAgICAgIC8vIHByb3ZpZGVzIHRoZSBleHByZXNzaW9uLiBzbyBwcmludCBhIG5pY2UgbWVzc2FnZVxuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmxvZygnUHJvY2Vzc2luZyBvZiB0aGUgZXhwcmVzc2lvbiBmYWlsZWQnKTtcbiAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZVxuICAgICAgICAgICAgY29uc29sZS5sb2coJ0V4cHJlc3Npb24gPSAnICsgZXhwcmVzc2lvbik7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdQYXJhbXMgPScsIHBhcmFtcyk7XG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdFeGNlcHRpb24gPSAnICsgZSk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgRXhwcmVzc2lvblNlcnZpY2UucHJvdG90eXBlLmNyZWF0ZUV4cHJlc3Npb25GdW5jdGlvbiA9IGZ1bmN0aW9uIChleHByZXNzaW9uKSB7XG4gICAgICAgIC8vIGNoZWNrIGNhY2hlIGZpcnN0XG4gICAgICAgIGlmICh0aGlzLmV4cHJlc3Npb25Ub0Z1bmN0aW9uQ2FjaGVbZXhwcmVzc2lvbl0pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cHJlc3Npb25Ub0Z1bmN0aW9uQ2FjaGVbZXhwcmVzc2lvbl07XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgbm90IGZvdW5kIGluIGNhY2hlLCByZXR1cm4gdGhlIGZ1bmN0aW9uXG4gICAgICAgIHZhciBmdW5jdGlvbkJvZHkgPSB0aGlzLmNyZWF0ZUZ1bmN0aW9uQm9keShleHByZXNzaW9uKTtcbiAgICAgICAgdmFyIHRoZUZ1bmN0aW9uID0gbmV3IEZ1bmN0aW9uKCd4LCBjdHgsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgdmFsdWUsIG5vZGUsIGRhdGEsIGNvbERlZiwgcm93SW5kZXgsIGFwaSwgY29sdW1uQXBpLCBnZXRWYWx1ZSwgY29sdW1uLCBjb2x1bW5Hcm91cCcsIGZ1bmN0aW9uQm9keSk7XG4gICAgICAgIC8vIHN0b3JlIGluIGNhY2hlXG4gICAgICAgIHRoaXMuZXhwcmVzc2lvblRvRnVuY3Rpb25DYWNoZVtleHByZXNzaW9uXSA9IHRoZUZ1bmN0aW9uO1xuICAgICAgICByZXR1cm4gdGhlRnVuY3Rpb247XG4gICAgfTtcbiAgICBFeHByZXNzaW9uU2VydmljZS5wcm90b3R5cGUuY3JlYXRlRnVuY3Rpb25Cb2R5ID0gZnVuY3Rpb24gKGV4cHJlc3Npb24pIHtcbiAgICAgICAgLy8gaWYgdGhlIGV4cHJlc3Npb24gaGFzIHRoZSAncmV0dXJuJyB3b3JkIGluIGl0LCB0aGVuIHVzZSBhcyBpcyxcbiAgICAgICAgLy8gaWYgbm90LCB0aGVuIHdyYXAgaXQgd2l0aCByZXR1cm4gYW5kICc7JyB0byBtYWtlIGEgZnVuY3Rpb25cbiAgICAgICAgaWYgKGV4cHJlc3Npb24uaW5kZXhPZigncmV0dXJuJykgPj0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGV4cHJlc3Npb247XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3JldHVybiAnICsgZXhwcmVzc2lvbiArICc7JztcbiAgICAgICAgfVxuICAgIH07XG4gICAgX19kZWNvcmF0ZSRIKFtcbiAgICAgICAgX19wYXJhbSQzKDAsIFF1YWxpZmllcignbG9nZ2VyRmFjdG9yeScpKVxuICAgIF0sIEV4cHJlc3Npb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJzZXRCZWFuc1wiLCBudWxsKTtcbiAgICBFeHByZXNzaW9uU2VydmljZSA9IF9fZGVjb3JhdGUkSChbXG4gICAgICAgIEJlYW4oJ2V4cHJlc3Npb25TZXJ2aWNlJylcbiAgICBdLCBFeHByZXNzaW9uU2VydmljZSk7XG4gICAgcmV0dXJuIEV4cHJlc3Npb25TZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJEYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJEcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBUZW1wbGF0ZVNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEYoVGVtcGxhdGVTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFRlbXBsYXRlU2VydmljZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLnRlbXBsYXRlQ2FjaGUgPSB7fTtcbiAgICAgICAgX3RoaXMud2FpdGluZ0NhbGxiYWNrcyA9IHt9O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIC8vIHJldHVybnMgdGhlIHRlbXBsYXRlIGlmIGl0IGlzIGxvYWRlZCwgb3IgbnVsbCBpZiBpdCBpcyBub3QgbG9hZGVkXG4gICAgLy8gYnV0IHdpbGwgY2FsbCB0aGUgY2FsbGJhY2sgd2hlbiBpdCBpcyBsb2FkZWRcbiAgICBUZW1wbGF0ZVNlcnZpY2UucHJvdG90eXBlLmdldFRlbXBsYXRlID0gZnVuY3Rpb24gKHVybCwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHRlbXBsYXRlRnJvbUNhY2hlID0gdGhpcy50ZW1wbGF0ZUNhY2hlW3VybF07XG4gICAgICAgIGlmICh0ZW1wbGF0ZUZyb21DYWNoZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRlbXBsYXRlRnJvbUNhY2hlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjYWxsYmFja0xpc3QgPSB0aGlzLndhaXRpbmdDYWxsYmFja3NbdXJsXTtcbiAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICBpZiAoIWNhbGxiYWNrTGlzdCkge1xuICAgICAgICAgICAgLy8gZmlyc3QgdGltZSB0aGlzIHdhcyBjYWxsZWQsIHNvIG5lZWQgYSBuZXcgbGlzdCBmb3IgY2FsbGJhY2tzXG4gICAgICAgICAgICBjYWxsYmFja0xpc3QgPSBbXTtcbiAgICAgICAgICAgIHRoaXMud2FpdGluZ0NhbGxiYWNrc1t1cmxdID0gY2FsbGJhY2tMaXN0O1xuICAgICAgICAgICAgLy8gYW5kIGFsc28gbmVlZCB0byBkbyB0aGUgaHR0cCByZXF1ZXN0XG4gICAgICAgICAgICB2YXIgY2xpZW50ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICBjbGllbnQub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoYXQuaGFuZGxlSHR0cFJlc3VsdCh0aGlzLCB1cmwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNsaWVudC5vcGVuKFwiR0VUXCIsIHVybCk7XG4gICAgICAgICAgICBjbGllbnQuc2VuZCgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFkZCB0aGlzIGNhbGxiYWNrXG4gICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2tMaXN0LnB1c2goY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNhbGxlciBuZWVkcyB0byB3YWl0IGZvciB0ZW1wbGF0ZSB0byBsb2FkLCBzbyByZXR1cm4gbnVsbFxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9O1xuICAgIFRlbXBsYXRlU2VydmljZS5wcm90b3R5cGUuaGFuZGxlSHR0cFJlc3VsdCA9IGZ1bmN0aW9uIChodHRwUmVzdWx0LCB1cmwpIHtcbiAgICAgICAgaWYgKGh0dHBSZXN1bHQuc3RhdHVzICE9PSAyMDAgfHwgaHR0cFJlc3VsdC5yZXNwb25zZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogVW5hYmxlIHRvIGdldCB0ZW1wbGF0ZSBlcnJvciBcIiArIGh0dHBSZXN1bHQuc3RhdHVzICsgXCIgLSBcIiArIHVybCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzcG9uc2Ugc3VjY2Vzcywgc28gcHJvY2VzcyBpdFxuICAgICAgICAvLyBpbiBJRTkgdGhlIHJlc3BvbnNlIGlzIGluIC0gcmVzcG9uc2VUZXh0XG4gICAgICAgIHRoaXMudGVtcGxhdGVDYWNoZVt1cmxdID0gaHR0cFJlc3VsdC5yZXNwb25zZSB8fCBodHRwUmVzdWx0LnJlc3BvbnNlVGV4dDtcbiAgICAgICAgLy8gaW5mb3JtIGFsbCBsaXN0ZW5lcnMgdGhhdCB0aGlzIGlzIG5vdyBpbiB0aGUgY2FjaGVcbiAgICAgICAgdmFyIGNhbGxiYWNrcyA9IHRoaXMud2FpdGluZ0NhbGxiYWNrc1t1cmxdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbGxiYWNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gY2FsbGJhY2tzW2ldO1xuICAgICAgICAgICAgLy8gd2UgY291bGQgcGFzcyB0aGUgY2FsbGJhY2sgdGhlIHJlc3BvbnNlLCBob3dldmVyIHdlIGtub3cgdGhlIGNsaWVudCBvZiB0aGlzIGNvZGVcbiAgICAgICAgICAgIC8vIGlzIHRoZSBjZWxsIHJlbmRlcmVyLCBhbmQgaXQgcGFzc2VzIHRoZSAnY2VsbFJlZnJlc2gnIG1ldGhvZCBpbiBhcyB0aGUgY2FsbGJhY2tcbiAgICAgICAgICAgIC8vIHdoaWNoIGRvZXNuJ3QgdGFrZSBhbnkgcGFyYW1ldGVycy5cbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFRlbXBsYXRlU2VydmljZSA9IF9fZGVjb3JhdGUkRyhbXG4gICAgICAgIEJlYW4oJ3RlbXBsYXRlU2VydmljZScpXG4gICAgXSwgVGVtcGxhdGVTZXJ2aWNlKTtcbiAgICByZXR1cm4gVGVtcGxhdGVTZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJEUgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJEYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3BhcmFtJDIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3BhcmFtKSB8fCBmdW5jdGlvbiAocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XG59O1xudmFyIExvZ2dlckZhY3RvcnkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEUoTG9nZ2VyRmFjdG9yeSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBMb2dnZXJGYWN0b3J5KCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIExvZ2dlckZhY3RvcnkucHJvdG90eXBlLnNldEJlYW5zID0gZnVuY3Rpb24gKGdyaWRPcHRpb25zV3JhcHBlcikge1xuICAgICAgICB0aGlzLmxvZ2dpbmcgPSBncmlkT3B0aW9uc1dyYXBwZXIuaXNEZWJ1ZygpO1xuICAgIH07XG4gICAgTG9nZ2VyRmFjdG9yeS5wcm90b3R5cGUuY3JlYXRlID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMb2dnZXIobmFtZSwgdGhpcy5pc0xvZ2dpbmcuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBMb2dnZXJGYWN0b3J5LnByb3RvdHlwZS5pc0xvZ2dpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvZ2dpbmc7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJEYoW1xuICAgICAgICBfX3BhcmFtJDIoMCwgUXVhbGlmaWVyKCdncmlkT3B0aW9uc1dyYXBwZXInKSlcbiAgICBdLCBMb2dnZXJGYWN0b3J5LnByb3RvdHlwZSwgXCJzZXRCZWFuc1wiLCBudWxsKTtcbiAgICBMb2dnZXJGYWN0b3J5ID0gX19kZWNvcmF0ZSRGKFtcbiAgICAgICAgQmVhbignbG9nZ2VyRmFjdG9yeScpXG4gICAgXSwgTG9nZ2VyRmFjdG9yeSk7XG4gICAgcmV0dXJuIExvZ2dlckZhY3Rvcnk7XG59KEJlYW5TdHViKSk7XG52YXIgTG9nZ2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExvZ2dlcihuYW1lLCBpc0xvZ2dpbmdGdW5jKSB7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuaXNMb2dnaW5nRnVuYyA9IGlzTG9nZ2luZ0Z1bmM7XG4gICAgfVxuICAgIExvZ2dlci5wcm90b3R5cGUuaXNMb2dnaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc0xvZ2dpbmdGdW5jKCk7XG4gICAgfTtcbiAgICBMb2dnZXIucHJvdG90eXBlLmxvZyA9IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gICAgICAgIGlmICh0aGlzLmlzTG9nZ2luZ0Z1bmMoKSkge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmxvZygnQUcgR3JpZC4nICsgdGhpcy5uYW1lICsgJzogJyArIG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gTG9nZ2VyO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyREID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRFID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgR3JpZEN0cmwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEQoR3JpZEN0cmwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gR3JpZEN0cmwoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgR3JpZEN0cmwucHJvdG90eXBlLnNldENvbXAgPSBmdW5jdGlvbiAodmlldywgZUdyaWREaXYsIGVHdWkpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy52aWV3ID0gdmlldztcbiAgICAgICAgdGhpcy5lR3JpZEhvc3REaXYgPSBlR3JpZERpdjtcbiAgICAgICAgdGhpcy5lR3VpID0gZUd1aTtcbiAgICAgICAgLy8gdGhpcyBkcm9wIHRhcmdldCBpcyBqdXN0IHVzZWQgdG8gc2VlIGlmIHRoZSBkcm9wIGV2ZW50IGlzIGluc2lkZSB0aGUgZ3JpZFxuICAgICAgICB0aGlzLmRyYWdBbmREcm9wU2VydmljZS5hZGREcm9wVGFyZ2V0KHtcbiAgICAgICAgICAgIGdldENvbnRhaW5lcjogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZUd1aTsgfSxcbiAgICAgICAgICAgIGlzSW50ZXJlc3RlZEluOiBmdW5jdGlvbiAodHlwZSkgeyByZXR1cm4gdHlwZSA9PT0gRHJhZ1NvdXJjZVR5cGUuSGVhZGVyQ2VsbCB8fCB0eXBlID09PSBEcmFnU291cmNlVHlwZS5Ub29sUGFuZWw7IH0sXG4gICAgICAgICAgICBnZXRJY29uTmFtZTogZnVuY3Rpb24gKCkgeyByZXR1cm4gRHJhZ0FuZERyb3BTZXJ2aWNlLklDT05fTk9UX0FMTE9XRUQ7IH0sXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRTZXJ2aWNlLnN0YW1wVG9wTGV2ZWxHcmlkQ29tcFdpdGhHcmlkSW5zdGFuY2UoZUdyaWREaXYpO1xuICAgICAgICB0aGlzLmNyZWF0ZU1hbmFnZWRCZWFuKG5ldyBMYXlvdXRGZWF0dXJlKHRoaXMudmlldykpO1xuICAgICAgICAvLyBpbXBvcnRhbnQgdG8gc2V0IHJ0bCBiZWZvcmUgZG9MYXlvdXQsIGFzIHNldHRpbmcgdGhlIFJUTCBjbGFzcyBpbXBhY3RzIHRoZSBzY3JvbGwgcG9zaXRpb24sXG4gICAgICAgIC8vIHdoaWNoIGRvTGF5b3V0IGluZGlyZWN0bHkgZGVwZW5kcyBvblxuICAgICAgICB0aGlzLmFkZFJ0bFN1cHBvcnQoKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcywgRXZlbnRzLkVWRU5UX0tFWUJPQVJEX0ZPQ1VTLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy52aWV3LmFkZE9yUmVtb3ZlS2V5Ym9hcmRGb2N1c0NsYXNzKHRydWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcywgRXZlbnRzLkVWRU5UX01PVVNFX0ZPQ1VTLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy52aWV3LmFkZE9yUmVtb3ZlS2V5Ym9hcmRGb2N1c0NsYXNzKGZhbHNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciB1bnN1YnNjcmliZUZyb21SZXNpemUgPSB0aGlzLnJlc2l6ZU9ic2VydmVyU2VydmljZS5vYnNlcnZlUmVzaXplKHRoaXMuZUdyaWRIb3N0RGl2LCB0aGlzLm9uR3JpZFNpemVDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZERlc3Ryb3lGdW5jKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHVuc3Vic2NyaWJlRnJvbVJlc2l6ZSgpOyB9KTtcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2UucmVnaXN0ZXJHcmlkQ3RybCh0aGlzKTtcbiAgICB9O1xuICAgIEdyaWRDdHJsLnByb3RvdHlwZS5pc0RldGFpbEdyaWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfYSwgX2I7XG4gICAgICAgIHZhciBlbCA9IHRoaXMuZm9jdXNTZXJ2aWNlLmZpbmRUYWJiYWJsZVBhcmVudCh0aGlzLmdldEd1aSgpKTtcbiAgICAgICAgcmV0dXJuICgoX2IgPSAoX2EgPSBlbCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldEF0dHJpYnV0ZSgncm93LWlkJykpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5zdGFydHNXaXRoKCdkZXRhaWwnKSkgfHwgZmFsc2U7XG4gICAgfTtcbiAgICBHcmlkQ3RybC5wcm90b3R5cGUuc2hvd0Ryb3Bab25lcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5Sb3dHcm91cGluZ01vZHVsZSk7XG4gICAgfTtcbiAgICBHcmlkQ3RybC5wcm90b3R5cGUuc2hvd1NpZGVCYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBNb2R1bGVSZWdpc3RyeS5pc1JlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuU2lkZUJhck1vZHVsZSk7XG4gICAgfTtcbiAgICBHcmlkQ3RybC5wcm90b3R5cGUuc2hvd1N0YXR1c0JhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5TdGF0dXNCYXJNb2R1bGUpO1xuICAgIH07XG4gICAgR3JpZEN0cmwucHJvdG90eXBlLnNob3dXYXRlcm1hcmsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBNb2R1bGVSZWdpc3RyeS5pc1JlZ2lzdGVyZWQoTW9kdWxlTmFtZXMuRW50ZXJwcmlzZUNvcmVNb2R1bGUpO1xuICAgIH07XG4gICAgR3JpZEN0cmwucHJvdG90eXBlLm9uR3JpZFNpemVDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfR1JJRF9TSVpFX0NIQU5HRUQsXG4gICAgICAgICAgICBjbGllbnRXaWR0aDogdGhpcy5lR3JpZEhvc3REaXYuY2xpZW50V2lkdGgsXG4gICAgICAgICAgICBjbGllbnRIZWlnaHQ6IHRoaXMuZUdyaWRIb3N0RGl2LmNsaWVudEhlaWdodFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIEdyaWRDdHJsLnByb3RvdHlwZS5hZGRSdGxTdXBwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY3NzQ2xhc3MgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpID8gJ2FnLXJ0bCcgOiAnYWctbHRyJztcbiAgICAgICAgdGhpcy52aWV3LnNldFJ0bENsYXNzKGNzc0NsYXNzKTtcbiAgICB9O1xuICAgIEdyaWRDdHJsLnByb3RvdHlwZS5kZXN0cm95R3JpZFVpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnZpZXcuZGVzdHJveUdyaWRVaSgpO1xuICAgIH07XG4gICAgR3JpZEN0cmwucHJvdG90eXBlLmdldEd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUd1aTtcbiAgICB9O1xuICAgIEdyaWRDdHJsLnByb3RvdHlwZS5zZXRSZXNpemVDdXJzb3IgPSBmdW5jdGlvbiAob24pIHtcbiAgICAgICAgdGhpcy52aWV3LnNldEN1cnNvcihvbiA/ICdldy1yZXNpemUnIDogbnVsbCk7XG4gICAgfTtcbiAgICBHcmlkQ3RybC5wcm90b3R5cGUuZGlzYWJsZVVzZXJTZWxlY3QgPSBmdW5jdGlvbiAob24pIHtcbiAgICAgICAgdGhpcy52aWV3LnNldFVzZXJTZWxlY3Qob24gPyAnbm9uZScgOiBudWxsKTtcbiAgICB9O1xuICAgIEdyaWRDdHJsLnByb3RvdHlwZS5mb2N1c05leHRJbm5lckNvbnRhaW5lciA9IGZ1bmN0aW9uIChiYWNrd2FyZHMpIHtcbiAgICAgICAgdmFyIGVEb2N1bWVudCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldERvY3VtZW50KCk7XG4gICAgICAgIHZhciBmb2N1c2FibGVDb250YWluZXJzID0gdGhpcy52aWV3LmdldEZvY3VzYWJsZUNvbnRhaW5lcnMoKTtcbiAgICAgICAgdmFyIGlkeFdpdGhGb2N1cyA9IGZvY3VzYWJsZUNvbnRhaW5lcnMuZmluZEluZGV4KGZ1bmN0aW9uIChjb250YWluZXIpIHsgcmV0dXJuIGNvbnRhaW5lci5jb250YWlucyhlRG9jdW1lbnQuYWN0aXZlRWxlbWVudCk7IH0pO1xuICAgICAgICB2YXIgbmV4dElkeCA9IGlkeFdpdGhGb2N1cyArIChiYWNrd2FyZHMgPyAtMSA6IDEpO1xuICAgICAgICBpZiAobmV4dElkeCA8PSAwIHx8IG5leHRJZHggPj0gZm9jdXNhYmxlQ29udGFpbmVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c1NlcnZpY2UuZm9jdXNJbnRvKGZvY3VzYWJsZUNvbnRhaW5lcnNbbmV4dElkeF0pO1xuICAgIH07XG4gICAgR3JpZEN0cmwucHJvdG90eXBlLmZvY3VzSW5uZXJFbGVtZW50ID0gZnVuY3Rpb24gKGZyb21Cb3R0b20pIHtcbiAgICAgICAgdmFyIGZvY3VzYWJsZUNvbnRhaW5lcnMgPSB0aGlzLnZpZXcuZ2V0Rm9jdXNhYmxlQ29udGFpbmVycygpO1xuICAgICAgICBpZiAoZnJvbUJvdHRvbSkge1xuICAgICAgICAgICAgaWYgKGZvY3VzYWJsZUNvbnRhaW5lcnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZvY3VzU2VydmljZS5mb2N1c0ludG8obGFzdChmb2N1c2FibGVDb250YWluZXJzKSwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbGFzdENvbHVtbiA9IGxhc3QodGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCkpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9jdXNTZXJ2aWNlLmZvY3VzR3JpZFZpZXcobGFzdENvbHVtbiwgdHJ1ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5mb2N1c1NlcnZpY2UuZm9jdXNGaXJzdEhlYWRlcigpO1xuICAgIH07XG4gICAgR3JpZEN0cmwucHJvdG90eXBlLmZvcmNlRm9jdXNPdXRPZkNvbnRhaW5lciA9IGZ1bmN0aW9uICh1cCkge1xuICAgICAgICBpZiAodXAgPT09IHZvaWQgMCkgeyB1cCA9IGZhbHNlOyB9XG4gICAgICAgIHRoaXMudmlldy5mb3JjZUZvY3VzT3V0T2ZDb250YWluZXIodXApO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRFKFtcbiAgICAgICAgQXV0b3dpcmVkKCdmb2N1c1NlcnZpY2UnKVxuICAgIF0sIEdyaWRDdHJsLnByb3RvdHlwZSwgXCJmb2N1c1NlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJEUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jlc2l6ZU9ic2VydmVyU2VydmljZScpXG4gICAgXSwgR3JpZEN0cmwucHJvdG90eXBlLCBcInJlc2l6ZU9ic2VydmVyU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkRShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEdyaWRDdHJsLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkRShbXG4gICAgICAgIEF1dG93aXJlZCgnY3RybHNTZXJ2aWNlJylcbiAgICBdLCBHcmlkQ3RybC5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRFKFtcbiAgICAgICAgQXV0b3dpcmVkKCdtb3VzZUV2ZW50U2VydmljZScpXG4gICAgXSwgR3JpZEN0cmwucHJvdG90eXBlLCBcIm1vdXNlRXZlbnRTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRFKFtcbiAgICAgICAgQXV0b3dpcmVkKCdkcmFnQW5kRHJvcFNlcnZpY2UnKVxuICAgIF0sIEdyaWRDdHJsLnByb3RvdHlwZSwgXCJkcmFnQW5kRHJvcFNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICByZXR1cm4gR3JpZEN0cmw7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkQyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkRCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEdyaWRDb21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRDKEdyaWRDb21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEdyaWRDb21wKGVHcmlkRGl2KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHVuZGVmaW5lZCkgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuZUdyaWREaXYgPSBlR3JpZERpdjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBHcmlkQ29tcC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5sb2dnZXIgPSB0aGlzLmxvZ2dlckZhY3RvcnkuY3JlYXRlKCdHcmlkQ29tcCcpO1xuICAgICAgICB2YXIgY29tcFByb3h5ID0ge1xuICAgICAgICAgICAgZGVzdHJveUdyaWRVaTogZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMuZGVzdHJveUJlYW4oX3RoaXMpOyB9LFxuICAgICAgICAgICAgc2V0UnRsQ2xhc3M6IGZ1bmN0aW9uIChjc3NDbGFzcykgeyByZXR1cm4gX3RoaXMuYWRkQ3NzQ2xhc3MoY3NzQ2xhc3MpOyB9LFxuICAgICAgICAgICAgYWRkT3JSZW1vdmVLZXlib2FyZEZvY3VzQ2xhc3M6IGZ1bmN0aW9uIChhZGRPclJlbW92ZSkgeyByZXR1cm4gX3RoaXMuYWRkT3JSZW1vdmVDc3NDbGFzcyhGb2N1c1NlcnZpY2UuQUdfS0VZQk9BUkRfRk9DVVMsIGFkZE9yUmVtb3ZlKTsgfSxcbiAgICAgICAgICAgIGZvcmNlRm9jdXNPdXRPZkNvbnRhaW5lcjogdGhpcy5mb3JjZUZvY3VzT3V0T2ZDb250YWluZXIuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHVwZGF0ZUxheW91dENsYXNzZXM6IHRoaXMudXBkYXRlTGF5b3V0Q2xhc3Nlcy5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgZ2V0Rm9jdXNhYmxlQ29udGFpbmVyczogdGhpcy5nZXRGb2N1c2FibGVDb250YWluZXJzLmJpbmQodGhpcyksXG4gICAgICAgICAgICBzZXRVc2VyU2VsZWN0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5nZXRHdWkoKS5zdHlsZS51c2VyU2VsZWN0ID0gdmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogJyc7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkuc3R5bGUud2Via2l0VXNlclNlbGVjdCA9IHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6ICcnO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldEN1cnNvcjogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZ2V0R3VpKCkuc3R5bGUuY3Vyc29yID0gdmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY3RybCA9IHRoaXMuY3JlYXRlTWFuYWdlZEJlYW4obmV3IEdyaWRDdHJsKCkpO1xuICAgICAgICB2YXIgdGVtcGxhdGUgPSB0aGlzLmNyZWF0ZVRlbXBsYXRlKCk7XG4gICAgICAgIHRoaXMuc2V0VGVtcGxhdGUodGVtcGxhdGUpO1xuICAgICAgICB0aGlzLmN0cmwuc2V0Q29tcChjb21wUHJveHksIHRoaXMuZUdyaWREaXYsIHRoaXMuZ2V0R3VpKCkpO1xuICAgICAgICB0aGlzLmluc2VydEdyaWRJbnRvRG9tKCk7XG4gICAgICAgIHRoaXMuaW5pdGlhbGlzZVRhYkd1YXJkKHtcbiAgICAgICAgICAgIC8vIHdlIHdhbnQgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgYmVoYXZpb3VyIHRvIGRvIG5vdGhpbmcgZm9yIG9uVGFiS2V5RG93blxuICAgICAgICAgICAgb25UYWJLZXlEb3duOiBmdW5jdGlvbiAoKSB7IHJldHVybiB1bmRlZmluZWQ7IH0sXG4gICAgICAgICAgICBmb2N1c0lubmVyRWxlbWVudDogZnVuY3Rpb24gKGZyb21Cb3R0b20pIHsgcmV0dXJuIF90aGlzLmN0cmwuZm9jdXNJbm5lckVsZW1lbnQoZnJvbUJvdHRvbSk7IH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBHcmlkQ29tcC5wcm90b3R5cGUuaW5zZXJ0R3JpZEludG9Eb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlR3VpID0gdGhpcy5nZXRHdWkoKTtcbiAgICAgICAgdGhpcy5lR3JpZERpdi5hcHBlbmRDaGlsZChlR3VpKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5lR3JpZERpdi5yZW1vdmVDaGlsZChlR3VpKTtcbiAgICAgICAgICAgIF90aGlzLmxvZ2dlci5sb2coJ0dyaWQgcmVtb3ZlZCBmcm9tIERPTScpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEdyaWRDb21wLnByb3RvdHlwZS51cGRhdGVMYXlvdXRDbGFzc2VzID0gZnVuY3Rpb24gKGNzc0NsYXNzLCBwYXJhbXMpIHtcbiAgICAgICAgdmFyIGVSb290V3JhcHBlckJvZHlDbGFzc0xpc3QgPSB0aGlzLmVSb290V3JhcHBlckJvZHkuY2xhc3NMaXN0O1xuICAgICAgICBlUm9vdFdyYXBwZXJCb2R5Q2xhc3NMaXN0LnRvZ2dsZShMYXlvdXRDc3NDbGFzc2VzLkFVVE9fSEVJR0hULCBwYXJhbXMuYXV0b0hlaWdodCk7XG4gICAgICAgIGVSb290V3JhcHBlckJvZHlDbGFzc0xpc3QudG9nZ2xlKExheW91dENzc0NsYXNzZXMuTk9STUFMLCBwYXJhbXMubm9ybWFsKTtcbiAgICAgICAgZVJvb3RXcmFwcGVyQm9keUNsYXNzTGlzdC50b2dnbGUoTGF5b3V0Q3NzQ2xhc3Nlcy5QUklOVCwgcGFyYW1zLnByaW50KTtcbiAgICAgICAgdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKExheW91dENzc0NsYXNzZXMuQVVUT19IRUlHSFQsIHBhcmFtcy5hdXRvSGVpZ2h0KTtcbiAgICAgICAgdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKExheW91dENzc0NsYXNzZXMuTk9STUFMLCBwYXJhbXMubm9ybWFsKTtcbiAgICAgICAgdGhpcy5hZGRPclJlbW92ZUNzc0NsYXNzKExheW91dENzc0NsYXNzZXMuUFJJTlQsIHBhcmFtcy5wcmludCk7XG4gICAgfTtcbiAgICBHcmlkQ29tcC5wcm90b3R5cGUuY3JlYXRlVGVtcGxhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkcm9wWm9uZXMgPSB0aGlzLmN0cmwuc2hvd0Ryb3Bab25lcygpID8gJzxhZy1ncmlkLWhlYWRlci1kcm9wLXpvbmVzPjwvYWctZ3JpZC1oZWFkZXItZHJvcC16b25lcz4nIDogJyc7XG4gICAgICAgIHZhciBzaWRlQmFyID0gdGhpcy5jdHJsLnNob3dTaWRlQmFyKCkgPyAnPGFnLXNpZGUtYmFyIHJlZj1cInNpZGVCYXJcIj48L2FnLXNpZGUtYmFyPicgOiAnJztcbiAgICAgICAgdmFyIHN0YXR1c0JhciA9IHRoaXMuY3RybC5zaG93U3RhdHVzQmFyKCkgPyAnPGFnLXN0YXR1cy1iYXIgcmVmPVwic3RhdHVzQmFyXCI+PC9hZy1zdGF0dXMtYmFyPicgOiAnJztcbiAgICAgICAgdmFyIHdhdGVybWFyayA9IHRoaXMuY3RybC5zaG93V2F0ZXJtYXJrKCkgPyAnPGFnLXdhdGVybWFyaz48L2FnLXdhdGVybWFyaz4nIDogJyc7XG4gICAgICAgIHZhciB0ZW1wbGF0ZSA9IC8qIGh0bWwgKi8gXCI8ZGl2IGNsYXNzPVxcXCJhZy1yb290LXdyYXBwZXJcXFwiIHJvbGU9XFxcInByZXNlbnRhdGlvblxcXCI+XFxuICAgICAgICAgICAgICAgIFwiICsgZHJvcFpvbmVzICsgXCJcXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctcm9vdC13cmFwcGVyLWJvZHlcXFwiIHJlZj1cXFwicm9vdFdyYXBwZXJCb2R5XFxcIiByb2xlPVxcXCJwcmVzZW50YXRpb25cXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgPGFnLWdyaWQtYm9keSByZWY9XFxcImdyaWRCb2R5XFxcIj48L2FnLWdyaWQtYm9keT5cXG4gICAgICAgICAgICAgICAgICAgIFwiICsgc2lkZUJhciArIFwiXFxuICAgICAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgICAgICBcIiArIHN0YXR1c0JhciArIFwiXFxuICAgICAgICAgICAgICAgIDxhZy1wYWdpbmF0aW9uPjwvYWctcGFnaW5hdGlvbj5cXG4gICAgICAgICAgICAgICAgXCIgKyB3YXRlcm1hcmsgKyBcIlxcbiAgICAgICAgICAgIDwvZGl2PlwiO1xuICAgICAgICByZXR1cm4gdGVtcGxhdGU7XG4gICAgfTtcbiAgICBHcmlkQ29tcC5wcm90b3R5cGUuZ2V0Rm9jdXNhYmxlRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZVJvb3RXcmFwcGVyQm9keTtcbiAgICB9O1xuICAgIEdyaWRDb21wLnByb3RvdHlwZS5nZXRGb2N1c2FibGVDb250YWluZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZm9jdXNhYmxlQ29udGFpbmVycyA9IFtcbiAgICAgICAgICAgIHRoaXMuZ3JpZEJvZHlDb21wLmdldEd1aSgpXG4gICAgICAgIF07XG4gICAgICAgIGlmICh0aGlzLnNpZGVCYXJDb21wKSB7XG4gICAgICAgICAgICBmb2N1c2FibGVDb250YWluZXJzLnB1c2godGhpcy5zaWRlQmFyQ29tcC5nZXRHdWkoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZvY3VzYWJsZUNvbnRhaW5lcnMuZmlsdGVyKGZ1bmN0aW9uIChlbCkgeyByZXR1cm4gaXNWaXNpYmxlKGVsKTsgfSk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJEQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2xvZ2dlckZhY3RvcnknKVxuICAgIF0sIEdyaWRDb21wLnByb3RvdHlwZSwgXCJsb2dnZXJGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSREKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2dyaWRCb2R5JylcbiAgICBdLCBHcmlkQ29tcC5wcm90b3R5cGUsIFwiZ3JpZEJvZHlDb21wXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSREKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ3NpZGVCYXInKVxuICAgIF0sIEdyaWRDb21wLnByb3RvdHlwZSwgXCJzaWRlQmFyQ29tcFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkRChbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdyb290V3JhcHBlckJvZHknKVxuICAgIF0sIEdyaWRDb21wLnByb3RvdHlwZSwgXCJlUm9vdFdyYXBwZXJCb2R5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSREKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIEdyaWRDb21wLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIHJldHVybiBHcmlkQ29tcDtcbn0oVGFiR3VhcmRDb21wKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkQiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkQyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcmVhZCQ0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIF9fc3ByZWFkJDMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3NwcmVhZCkgfHwgZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhciA9IGFyLmNvbmNhdChfX3JlYWQkNChhcmd1bWVudHNbaV0pKTtcbiAgICByZXR1cm4gYXI7XG59O1xudmFyIFNvcnRDb250cm9sbGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRCKFNvcnRDb250cm9sbGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNvcnRDb250cm9sbGVyKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFNvcnRDb250cm9sbGVyXzEgPSBTb3J0Q29udHJvbGxlcjtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUucHJvZ3Jlc3NTb3J0ID0gZnVuY3Rpb24gKGNvbHVtbiwgbXVsdGlTb3J0LCBzb3VyY2UpIHtcbiAgICAgICAgdmFyIG5leHREaXJlY3Rpb24gPSB0aGlzLmdldE5leHRTb3J0RGlyZWN0aW9uKGNvbHVtbik7XG4gICAgICAgIHRoaXMuc2V0U29ydEZvckNvbHVtbihjb2x1bW4sIG5leHREaXJlY3Rpb24sIG11bHRpU29ydCwgc291cmNlKTtcbiAgICB9O1xuICAgIFNvcnRDb250cm9sbGVyLnByb3RvdHlwZS5zZXRTb3J0Rm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbiwgc29ydCwgbXVsdGlTb3J0LCBzb3VyY2UpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICAvLyBhdXRvIGNvcnJlY3QgLSBpZiBzb3J0IG5vdCBsZWdhbCB2YWx1ZSwgdGhlbiBzZXQgaXQgdG8gJ25vIHNvcnQnICh3aGljaCBpcyBudWxsKVxuICAgICAgICBpZiAoc29ydCAhPT0gQ29uc3RhbnRzLlNPUlRfQVNDICYmIHNvcnQgIT09IENvbnN0YW50cy5TT1JUX0RFU0MpIHtcbiAgICAgICAgICAgIHNvcnQgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpc0NvbHVtbnNTb3J0aW5nQ291cGxlZFRvR3JvdXAgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0NvbHVtbnNTb3J0aW5nQ291cGxlZFRvR3JvdXAoKTtcbiAgICAgICAgdmFyIGNvbHVtbnNUb1VwZGF0ZSA9IFtjb2x1bW5dO1xuICAgICAgICBpZiAoaXNDb2x1bW5zU29ydGluZ0NvdXBsZWRUb0dyb3VwKSB7XG4gICAgICAgICAgICBpZiAoY29sdW1uLmdldENvbERlZigpLnNob3dSb3dHcm91cCkge1xuICAgICAgICAgICAgICAgIHZhciByb3dHcm91cENvbHVtbnMgPSB0aGlzLmNvbHVtbk1vZGVsLmdldFNvdXJjZUNvbHVtbnNGb3JHcm91cENvbHVtbihjb2x1bW4pO1xuICAgICAgICAgICAgICAgIHZhciBzb3J0YWJsZVJvd0dyb3VwQ29sdW1ucyA9IChfYSA9IHJvd0dyb3VwQ29sdW1ucykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuZ2V0Q29sRGVmKCkuc29ydGFibGU7IH0pO1xuICAgICAgICAgICAgICAgIGlmIChzb3J0YWJsZVJvd0dyb3VwQ29sdW1ucykge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5zVG9VcGRhdGUgPSBfX3NwcmVhZCQzKFtjb2x1bW5dLCBzb3J0YWJsZVJvd0dyb3VwQ29sdW1ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbHVtbnNUb1VwZGF0ZS5mb3JFYWNoKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5zZXRTb3J0KHNvcnQsIHNvdXJjZSk7IH0pO1xuICAgICAgICB2YXIgZG9pbmdNdWx0aVNvcnQgPSAobXVsdGlTb3J0IHx8IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQWx3YXlzTXVsdGlTb3J0KCkpICYmICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTXVsdGlTb3J0KCk7XG4gICAgICAgIC8vIGNsZWFyIHNvcnQgb24gYWxsIGNvbHVtbnMgZXhjZXB0IHRob3NlIGNoYW5nZWQsIGFuZCB1cGRhdGUgdGhlIGljb25zXG4gICAgICAgIGlmICghZG9pbmdNdWx0aVNvcnQpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJTb3J0QmFyVGhlc2VDb2x1bW5zKGNvbHVtbnNUb1VwZGF0ZSwgc291cmNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBzb3J0SW5kZXggdXNlZCBmb3Iga25vd2luZyBvcmRlciBvZiBjb2xzIHdoZW4gbXVsdGktY29sIHNvcnRcbiAgICAgICAgdGhpcy51cGRhdGVTb3J0SW5kZXgoY29sdW1uKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaFNvcnRDaGFuZ2VkRXZlbnRzKHNvdXJjZSk7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUudXBkYXRlU29ydEluZGV4ID0gZnVuY3Rpb24gKGxhc3RDb2xUb0NoYW5nZSkge1xuICAgICAgICB2YXIgaXNDb3VwbGVkID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNDb2x1bW5zU29ydGluZ0NvdXBsZWRUb0dyb3VwKCk7XG4gICAgICAgIHZhciBncm91cFBhcmVudCA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JvdXBEaXNwbGF5Q29sdW1uRm9yR3JvdXAobGFzdENvbFRvQ2hhbmdlLmdldElkKCkpO1xuICAgICAgICB2YXIgbGFzdFNvcnRJbmRleENvbCA9IGlzQ291cGxlZCA/IGdyb3VwUGFyZW50IHx8IGxhc3RDb2xUb0NoYW5nZSA6IGxhc3RDb2xUb0NoYW5nZTtcbiAgICAgICAgdmFyIGFsbFNvcnRlZENvbHMgPSB0aGlzLmdldEluZGV4YWJsZUNvbHVtbnNPcmRlcmVkKCk7XG4gICAgICAgIC8vIHJlc2V0IHNvcnQgaW5kZXggb24gZXZlcnl0aGluZ1xuICAgICAgICB0aGlzLmNvbHVtbk1vZGVsLmdldFByaW1hcnlBbmRTZWNvbmRhcnlBbmRBdXRvQ29sdW1ucygpLmZvckVhY2goZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gY29sLnNldFNvcnRJbmRleChudWxsKTsgfSk7XG4gICAgICAgIHZhciBhbGxTb3J0ZWRDb2xzV2l0aG91dENoYW5nZXMgPSBhbGxTb3J0ZWRDb2xzLmZpbHRlcihmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wgIT09IGxhc3RTb3J0SW5kZXhDb2w7IH0pO1xuICAgICAgICB2YXIgc29ydGVkQ29sc1dpdGhJbmRpY2VzID0gISFsYXN0U29ydEluZGV4Q29sLmdldFNvcnQoKSA/IF9fc3ByZWFkJDMoYWxsU29ydGVkQ29sc1dpdGhvdXRDaGFuZ2VzLCBbbGFzdFNvcnRJbmRleENvbF0pIDogYWxsU29ydGVkQ29sc1dpdGhvdXRDaGFuZ2VzO1xuICAgICAgICBzb3J0ZWRDb2xzV2l0aEluZGljZXMuZm9yRWFjaChmdW5jdGlvbiAoY29sLCBpZHgpIHsgcmV0dXJuIChjb2wuc2V0U29ydEluZGV4KGlkeCkpOyB9KTtcbiAgICB9O1xuICAgIC8vIGdldHMgY2FsbGVkIGJ5IEFQSSwgc28gaWYgZGF0YSBjaGFuZ2VzLCB1c2UgY2FuIGNhbGwgdGhpcywgd2hpY2ggd2lsbCBlbmQgdXBcbiAgICAvLyB3b3JraW5nIG91dCB0aGUgc29ydCBvcmRlciBhZ2FpbiBvZiB0aGUgcm93cy5cbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUub25Tb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaFNvcnRDaGFuZ2VkRXZlbnRzKHNvdXJjZSk7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUuaXNTb3J0QWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBwdWxsIG91dCBhbGwgdGhlIGNvbHVtbnMgdGhhdCBoYXZlIHNvcnRpbmcgc2V0XG4gICAgICAgIHZhciBhbGxDb2xzID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5QW5kQXV0b0NvbHVtbnMoKTtcbiAgICAgICAgdmFyIHNvcnRlZENvbHMgPSBhbGxDb2xzLmZpbHRlcihmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiAhIWNvbHVtbi5nZXRTb3J0KCk7IH0pO1xuICAgICAgICByZXR1cm4gc29ydGVkQ29scyAmJiBzb3J0ZWRDb2xzLmxlbmd0aCA+IDA7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUuZGlzcGF0Y2hTb3J0Q2hhbmdlZEV2ZW50cyA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX1NPUlRfQ0hBTkdFRCxcbiAgICAgICAgICAgIHNvdXJjZTogc291cmNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgU29ydENvbnRyb2xsZXIucHJvdG90eXBlLmNsZWFyU29ydEJhclRoZXNlQ29sdW1ucyA9IGZ1bmN0aW9uIChjb2x1bW5zVG9Ta2lwLCBzb3VyY2UpIHtcbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5QW5kQXV0b0NvbHVtbnMoKS5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5Ub0NsZWFyKSB7XG4gICAgICAgICAgICAvLyBEbyBub3QgY2xlYXIgaWYgZWl0aGVyIGhvbGRpbmcgc2hpZnQsIG9yIGlmIGNvbHVtbiBpbiBxdWVzdGlvbiB3YXMgY2xpY2tlZFxuICAgICAgICAgICAgaWYgKCFjb2x1bW5zVG9Ta2lwLmluY2x1ZGVzKGNvbHVtblRvQ2xlYXIpKSB7XG4gICAgICAgICAgICAgICAgLy8gc2V0dGluZyB0byAndW5kZWZpbmVkJyBhcyBudWxsIG1lYW5zICdub25lJyByYXRoZXIgdGhhbiBjbGVhcmVkLCBvdGhlcndpc2UgaXNzdWUgd2lsbCBhcmlzZVxuICAgICAgICAgICAgICAgIC8vIGlmIHNvcnQgb3JkZXIgaXM6IFsnZGVzYycsIG51bGwgLCAnYXNjJ10sIGFzIGl0IHdpbGwgc3RhcnQgYXQgbnVsbCByYXRoZXIgdGhhbiAnZGVzYycuXG4gICAgICAgICAgICAgICAgY29sdW1uVG9DbGVhci5zZXRTb3J0KHVuZGVmaW5lZCwgc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUuZ2V0TmV4dFNvcnREaXJlY3Rpb24gPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHZhciBzb3J0aW5nT3JkZXI7XG4gICAgICAgIGlmIChjb2x1bW4uZ2V0Q29sRGVmKCkuc29ydGluZ09yZGVyKSB7XG4gICAgICAgICAgICBzb3J0aW5nT3JkZXIgPSBjb2x1bW4uZ2V0Q29sRGVmKCkuc29ydGluZ09yZGVyO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFNvcnRpbmdPcmRlcigpKSB7XG4gICAgICAgICAgICBzb3J0aW5nT3JkZXIgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRTb3J0aW5nT3JkZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNvcnRpbmdPcmRlciA9IFNvcnRDb250cm9sbGVyXzEuREVGQVVMVF9TT1JUSU5HX09SREVSO1xuICAgICAgICB9XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShzb3J0aW5nT3JkZXIpIHx8IHNvcnRpbmdPcmRlci5sZW5ndGggPD0gMCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogc29ydGluZ09yZGVyIG11c3QgYmUgYW4gYXJyYXkgd2l0aCBhdCBsZWFzdCBvbmUgZWxlbWVudCwgY3VycmVudGx5IGl0J3MgXCIgKyBzb3J0aW5nT3JkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGN1cnJlbnRJbmRleCA9IHNvcnRpbmdPcmRlci5pbmRleE9mKGNvbHVtbi5nZXRTb3J0KCkpO1xuICAgICAgICB2YXIgbm90SW5BcnJheSA9IGN1cnJlbnRJbmRleCA8IDA7XG4gICAgICAgIHZhciBsYXN0SXRlbUluQXJyYXkgPSBjdXJyZW50SW5kZXggPT0gc29ydGluZ09yZGVyLmxlbmd0aCAtIDE7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIGlmIChub3RJbkFycmF5IHx8IGxhc3RJdGVtSW5BcnJheSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gc29ydGluZ09yZGVyWzBdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gc29ydGluZ09yZGVyW2N1cnJlbnRJbmRleCArIDFdO1xuICAgICAgICB9XG4gICAgICAgIC8vIHZlcmlmeSB0aGUgc29ydCB0eXBlIGV4aXN0cywgYXMgdGhlIHVzZXIgY291bGQgcHJvdmlkZSB0aGUgc29ydGluZ09yZGVyLCBuZWVkIHRvIG1ha2Ugc3VyZSBpdCdzIHZhbGlkXG4gICAgICAgIGlmIChTb3J0Q29udHJvbGxlcl8xLkRFRkFVTFRfU09SVElOR19PUkRFUi5pbmRleE9mKHJlc3VsdCkgPCAwKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IGludmFsaWQgc29ydCB0eXBlICcgKyByZXN1bHQpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIFNvcnRDb250cm9sbGVyLnByb3RvdHlwZS5nZXRDb2x1bW5zT3JkZXJlZEZvclNvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHB1bGwgb3V0IGFsbCB0aGUgY29sdW1ucyB0aGF0IGhhdmUgc29ydGluZyBzZXRcbiAgICAgICAgdmFyIGFsbENvbHVtbnNJbmNsdWRpbmdBdXRvID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRQcmltYXJ5QW5kU2Vjb25kYXJ5QW5kQXV0b0NvbHVtbnMoKTtcbiAgICAgICAgLy8gd2hlbiBib3RoIGNvbHMgYXJlIG1pc3Npbmcgc29ydEluZGV4LCB3ZSB1c2UgdGhlIHBvc2l0aW9uIG9mIHRoZSBjb2wgaW4gYWxsIGNvbHMgbGlzdC5cbiAgICAgICAgLy8gdGhpcyBtZWFucyBpZiBjb2xEZWZzIG9ubHkgaGF2ZSBzb3J0LCBidXQgbm8gc29ydEluZGV4LCB3ZSBkZXRlcm1pbmlzdGljYWxseSBwaWNrIHdoaWNoXG4gICAgICAgIC8vIGNvbHMgaXMgc29ydGVkIGJ5IGZpcnN0LlxuICAgICAgICB2YXIgYWxsQ29sc0luZGV4ZXMgPSB7fTtcbiAgICAgICAgYWxsQ29sdW1uc0luY2x1ZGluZ0F1dG8uZm9yRWFjaChmdW5jdGlvbiAoY29sLCBpbmRleCkgeyByZXR1cm4gYWxsQ29sc0luZGV4ZXNbY29sLmdldElkKCldID0gaW5kZXg7IH0pO1xuICAgICAgICAvLyBwdXQgdGhlIGNvbHVtbnMgaW4gb3JkZXIgb2Ygd2hpY2ggb25lIGdvdCBzb3J0ZWQgZmlyc3RcbiAgICAgICAgYWxsQ29sdW1uc0luY2x1ZGluZ0F1dG8uc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgdmFyIGlBID0gYS5nZXRTb3J0SW5kZXgoKTtcbiAgICAgICAgICAgIHZhciBpQiA9IGIuZ2V0U29ydEluZGV4KCk7XG4gICAgICAgICAgICBpZiAoaUEgIT0gbnVsbCAmJiBpQiAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlBIC0gaUI7IC8vIGJvdGggcHJlc2VudCwgbm9ybWFsIGNvbXBhcmlzb25cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlBID09IG51bGwgJiYgaUIgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIGJvdGggbWlzc2luZywgY29tcGFyZSB1c2luZyBjb2x1bW4gcG9zaXRpb25zXG4gICAgICAgICAgICAgICAgdmFyIHBvc0EgPSBhbGxDb2xzSW5kZXhlc1thLmdldElkKCldO1xuICAgICAgICAgICAgICAgIHZhciBwb3NCID0gYWxsQ29sc0luZGV4ZXNbYi5nZXRJZCgpXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcG9zQSA+IHBvc0IgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpQiA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIC0xOyAvLyBpQiBtaXNzaW5nXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMTsgLy8gaUEgbWlzc2luZ1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGFsbENvbHVtbnNJbmNsdWRpbmdBdXRvO1xuICAgIH07XG4gICAgU29ydENvbnRyb2xsZXIucHJvdG90eXBlLmdldEluZGV4YWJsZUNvbHVtbnNPcmRlcmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQ29sdW1uc1NvcnRpbmdDb3VwbGVkVG9Hcm91cCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRDb2x1bW5zV2l0aFNvcnRpbmdPcmRlcmVkKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uc09yZGVyZWRGb3JTb3J0KClcbiAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKGNvbCkge1xuICAgICAgICAgICAgdmFyIF9hO1xuICAgICAgICAgICAgaWYgKCEhY29sLmdldENvbERlZigpLnNob3dSb3dHcm91cCkge1xuICAgICAgICAgICAgICAgIGlmIChjb2wuZ2V0Q29sRGVmKCkuZmllbGQgJiYgY29sLmdldFNvcnQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZUNvbHMgPSBfdGhpcy5jb2x1bW5Nb2RlbC5nZXRTb3VyY2VDb2x1bW5zRm9yR3JvdXBDb2x1bW4oY29sKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKF9hID0gc291cmNlQ29scykgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLnNvbWUoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gISFjb2wuZ2V0U29ydCgpOyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAhIWNvbC5nZXRTb3J0KCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgU29ydENvbnRyb2xsZXIucHJvdG90eXBlLmdldENvbHVtbnNXaXRoU29ydGluZ09yZGVyZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHB1bGwgb3V0IGFsbCB0aGUgY29sdW1ucyB0aGF0IGhhdmUgc29ydGluZyBzZXRcbiAgICAgICAgdmFyIG9yZGVyZWRDb2x1bW5zID0gdGhpcy5nZXRDb2x1bW5zT3JkZXJlZEZvclNvcnQoKTtcbiAgICAgICAgcmV0dXJuIG9yZGVyZWRDb2x1bW5zLmZpbHRlcihmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiAhIWNvbHVtbi5nZXRTb3J0KCk7IH0pO1xuICAgIH07XG4gICAgLy8gdXNlZCBieSBzZXJ2ZXIgc2lkZSByb3cgbW9kZWxzLCB0byBzZW50IHNvcnQgdG8gc2VydmVyXG4gICAgU29ydENvbnRyb2xsZXIucHJvdG90eXBlLmdldFNvcnRNb2RlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uc1dpdGhTb3J0aW5nT3JkZXJlZCgpLm1hcChmdW5jdGlvbiAoY29sdW1uKSB7IHJldHVybiAoe1xuICAgICAgICAgICAgc29ydDogY29sdW1uLmdldFNvcnQoKSxcbiAgICAgICAgICAgIGNvbElkOiBjb2x1bW4uZ2V0SWQoKVxuICAgICAgICB9KTsgfSk7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUuZ2V0U29ydE9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENvbHVtbnNXaXRoU29ydGluZ09yZGVyZWQoKS5tYXAoZnVuY3Rpb24gKGNvbHVtbikgeyByZXR1cm4gKHtcbiAgICAgICAgICAgIHNvcnQ6IGNvbHVtbi5nZXRTb3J0KCksXG4gICAgICAgICAgICBjb2x1bW46IGNvbHVtblxuICAgICAgICB9KTsgfSk7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUuY2FuQ29sdW1uRGlzcGxheU1peGVkU29ydCA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgdmFyIGlzQ29sdW1uU29ydENvdXBsaW5nQWN0aXZlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNDb2x1bW5zU29ydGluZ0NvdXBsZWRUb0dyb3VwKCk7XG4gICAgICAgIHZhciBpc0dyb3VwRGlzcGxheUNvbHVtbiA9ICEhY29sdW1uLmdldENvbERlZigpLnNob3dSb3dHcm91cDtcbiAgICAgICAgcmV0dXJuIGlzQ29sdW1uU29ydENvdXBsaW5nQWN0aXZlICYmIGlzR3JvdXBEaXNwbGF5Q29sdW1uO1xuICAgIH07XG4gICAgU29ydENvbnRyb2xsZXIucHJvdG90eXBlLmdldERpc3BsYXlTb3J0Rm9yQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHZhciBsaW5rZWRDb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRTb3VyY2VDb2x1bW5zRm9yR3JvdXBDb2x1bW4oY29sdW1uKTtcbiAgICAgICAgaWYgKCF0aGlzLmNhbkNvbHVtbkRpc3BsYXlNaXhlZFNvcnQoY29sdW1uKSB8fCAhKChfYSA9IGxpbmtlZENvbHVtbnMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5sZW5ndGgpKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sdW1uLmdldFNvcnQoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBjb2x1bW4gaGFzIHVuaXF1ZSBkYXRhLCBpdHMgc29ydGluZyBpcyBpbmRlcGVuZGVudCAtIGJ1dCBjYW4gc3RpbGwgYmUgbWl4ZWRcbiAgICAgICAgdmFyIGNvbHVtbkhhc1VuaXF1ZURhdGEgPSAhIWNvbHVtbi5nZXRDb2xEZWYoKS5maWVsZDtcbiAgICAgICAgdmFyIHNvcnRhYmxlQ29sdW1ucyA9IGNvbHVtbkhhc1VuaXF1ZURhdGEgPyBfX3NwcmVhZCQzKFtjb2x1bW5dLCBsaW5rZWRDb2x1bW5zKSA6IGxpbmtlZENvbHVtbnM7XG4gICAgICAgIHZhciBmaXJzdFNvcnQgPSBzb3J0YWJsZUNvbHVtbnNbMF0uZ2V0U29ydCgpO1xuICAgICAgICAvLyB0aGUgPT0gaXMgaW50ZW50aW9uYWwsIGFzIG51bGwgYW5kIHVuZGVmaW5lZCBib3RoIHJlcHJlc2VudCBubyBzb3J0LCB3aGljaCBtZWFucyB0aGV5IGFyZSBlcXVpdmFsZW50XG4gICAgICAgIHZhciBhbGxNYXRjaCA9IHNvcnRhYmxlQ29sdW1ucy5ldmVyeShmdW5jdGlvbiAoY29sKSB7IHJldHVybiBjb2wuZ2V0U29ydCgpID09IGZpcnN0U29ydDsgfSk7XG4gICAgICAgIGlmICghYWxsTWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiAnbWl4ZWQnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaXJzdFNvcnQ7XG4gICAgfTtcbiAgICBTb3J0Q29udHJvbGxlci5wcm90b3R5cGUuZ2V0RGlzcGxheVNvcnRJbmRleEZvckNvbHVtbiA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGlzQ29sdW1uU29ydENvdXBsaW5nQWN0aXZlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNDb2x1bW5zU29ydGluZ0NvdXBsZWRUb0dyb3VwKCk7XG4gICAgICAgIGlmICghaXNDb2x1bW5Tb3J0Q291cGxpbmdBY3RpdmUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENvbHVtbnNXaXRoU29ydGluZ09yZGVyZWQoKS5pbmRleE9mKGNvbHVtbik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRpc3BsYXlDb2x1bW4gPSB0aGlzLmNvbHVtbk1vZGVsLmdldEdyb3VwRGlzcGxheUNvbHVtbkZvckdyb3VwKGNvbHVtbi5nZXRJZCgpKTtcbiAgICAgICAgaWYgKGRpc3BsYXlDb2x1bW4pIHtcbiAgICAgICAgICAgIGlmICghIWNvbHVtbi5nZXRTb3J0KCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXREaXNwbGF5U29ydEluZGV4Rm9yQ29sdW1uKGRpc3BsYXlDb2x1bW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFsbFNvcnRlZENvbHMgPSB0aGlzLmdldEluZGV4YWJsZUNvbHVtbnNPcmRlcmVkKClcbiAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gIV90aGlzLmNvbHVtbk1vZGVsLmdldEdyb3VwRGlzcGxheUNvbHVtbkZvckdyb3VwKGNvbC5nZXRJZCgpKTsgfSk7XG4gICAgICAgIHJldHVybiBhbGxTb3J0ZWRDb2xzLmluZGV4T2YoY29sdW1uKTtcbiAgICB9O1xuICAgIHZhciBTb3J0Q29udHJvbGxlcl8xO1xuICAgIFNvcnRDb250cm9sbGVyLkRFRkFVTFRfU09SVElOR19PUkRFUiA9IFtDb25zdGFudHMuU09SVF9BU0MsIENvbnN0YW50cy5TT1JUX0RFU0MsIG51bGxdO1xuICAgIF9fZGVjb3JhdGUkQyhbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIFNvcnRDb250cm9sbGVyLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIFNvcnRDb250cm9sbGVyID0gU29ydENvbnRyb2xsZXJfMSA9IF9fZGVjb3JhdGUkQyhbXG4gICAgICAgIEJlYW4oJ3NvcnRDb250cm9sbGVyJylcbiAgICBdLCBTb3J0Q29udHJvbGxlcik7XG4gICAgcmV0dXJuIFNvcnRDb250cm9sbGVyO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJEEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJEIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBDb2x1bW5Ib3ZlclNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJEEoQ29sdW1uSG92ZXJTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbHVtbkhvdmVyU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBDb2x1bW5Ib3ZlclNlcnZpY2UucHJvdG90eXBlLnNldE1vdXNlT3ZlciA9IGZ1bmN0aW9uIChjb2x1bW5zKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRDb2x1bW5zID0gY29sdW1ucztcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0NPTFVNTl9IT1ZFUl9DSEFOR0VEXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ29sdW1uSG92ZXJTZXJ2aWNlLnByb3RvdHlwZS5jbGVhck1vdXNlT3ZlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZENvbHVtbnMgPSBudWxsO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfQ09MVU1OX0hPVkVSX0NIQU5HRURcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBDb2x1bW5Ib3ZlclNlcnZpY2UucHJvdG90eXBlLmlzSG92ZXJlZCA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5zZWxlY3RlZENvbHVtbnMgJiYgdGhpcy5zZWxlY3RlZENvbHVtbnMuaW5kZXhPZihjb2x1bW4pID49IDA7XG4gICAgfTtcbiAgICBDb2x1bW5Ib3ZlclNlcnZpY2UgPSBfX2RlY29yYXRlJEIoW1xuICAgICAgICBCZWFuKCdjb2x1bW5Ib3ZlclNlcnZpY2UnKVxuICAgIF0sIENvbHVtbkhvdmVyU2VydmljZSk7XG4gICAgcmV0dXJuIENvbHVtbkhvdmVyU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyR6ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRBID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ29sdW1uQW5pbWF0aW9uU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkeihDb2x1bW5BbmltYXRpb25TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbHVtbkFuaW1hdGlvblNlcnZpY2UoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5leGVjdXRlTmV4dEZ1bmNzID0gW107XG4gICAgICAgIF90aGlzLmV4ZWN1dGVMYXRlckZ1bmNzID0gW107XG4gICAgICAgIF90aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5hbmltYXRpb25UaHJlYWRDb3VudCA9IDA7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQ29sdW1uQW5pbWF0aW9uU2VydmljZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uIChwKSB7IHJldHVybiBfdGhpcy5ncmlkQm9keUN0cmwgPSBwLmdyaWRCb2R5Q3RybDsgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5BbmltYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5pc0FjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlO1xuICAgIH07XG4gICAgQ29sdW1uQW5pbWF0aW9uU2VydmljZS5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmFjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ29sdW1uTW92ZUFuaW1hdGlvbigpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgZG9pbmcgUlRMLCB3ZSBkb24ndCBhbmltYXRlIG9wZW4gLyBjbG9zZSBhcyBkdWUgdG8gaG93IHRoZSBwaXhlbHMgYXJlIGludmVydGVkLFxuICAgICAgICAvLyB0aGUgYW5pbWF0aW9uIG1vdmVzIGFsbCB0aGUgcm93IHRoZSB0aGUgcmlnaHQgcmF0aGVyIHRoYW4gdG8gdGhlIGxlZnQgKGllIGl0J3MgdGhlIHN0YXRpY1xuICAgICAgICAvLyBjb2x1bW5zIHRoYXQgYWN0dWFsbHkgZ2V0IHRoZWlyIGNvb3JkaW5hdGVzIHVwZGF0ZWQpXG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbnN1cmVBbmltYXRpb25Dc3NDbGFzc1ByZXNlbnQoKTtcbiAgICAgICAgdGhpcy5hY3RpdmUgPSB0cnVlO1xuICAgIH07XG4gICAgQ29sdW1uQW5pbWF0aW9uU2VydmljZS5wcm90b3R5cGUuZmluaXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuYWN0aXZlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5mbHVzaCgpO1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgIH07XG4gICAgQ29sdW1uQW5pbWF0aW9uU2VydmljZS5wcm90b3R5cGUuZXhlY3V0ZU5leHRWTVR1cm4gPSBmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICBpZiAodGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZU5leHRGdW5jcy5wdXNoKGZ1bmMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZnVuYygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDb2x1bW5BbmltYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5leGVjdXRlTGF0ZXJWTVR1cm4gPSBmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICBpZiAodGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZUxhdGVyRnVuY3MucHVzaChmdW5jKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZ1bmMoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ29sdW1uQW5pbWF0aW9uU2VydmljZS5wcm90b3R5cGUuZW5zdXJlQW5pbWF0aW9uQ3NzQ2xhc3NQcmVzZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyB1cCB0aGUgY291bnQsIHNvIHdlIGNhbiB0ZWxsIGlmIHNvbWVvbmUgZWxzZSBoYXMgdXBkYXRlZCB0aGUgY291bnRcbiAgICAgICAgLy8gYnkgdGhlIHRpbWUgdGhlICd3YWl0JyBmdW5jIGV4ZWN1dGVzXG4gICAgICAgIHRoaXMuYW5pbWF0aW9uVGhyZWFkQ291bnQrKztcbiAgICAgICAgdmFyIGFuaW1hdGlvblRocmVhZENvdW50Q29weSA9IHRoaXMuYW5pbWF0aW9uVGhyZWFkQ291bnQ7XG4gICAgICAgIHRoaXMuZ3JpZEJvZHlDdHJsLnNldENvbHVtbk1vdmluZ0Nzcyh0cnVlKTtcbiAgICAgICAgdGhpcy5leGVjdXRlTGF0ZXJGdW5jcy5wdXNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIG9ubHkgcmVtb3ZlIHRoZSBjbGFzcyBpZiB0aGlzIHRocmVhZCB3YXMgdGhlIGxhc3Qgb25lIHRvIHVwZGF0ZSBpdFxuICAgICAgICAgICAgaWYgKF90aGlzLmFuaW1hdGlvblRocmVhZENvdW50ID09PSBhbmltYXRpb25UaHJlYWRDb3VudENvcHkpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5ncmlkQm9keUN0cmwuc2V0Q29sdW1uTW92aW5nQ3NzKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDb2x1bW5BbmltYXRpb25TZXJ2aWNlLnByb3RvdHlwZS5mbHVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vd0Z1bmNzID0gdGhpcy5leGVjdXRlTmV4dEZ1bmNzO1xuICAgICAgICB0aGlzLmV4ZWN1dGVOZXh0RnVuY3MgPSBbXTtcbiAgICAgICAgdmFyIHdhaXRGdW5jcyA9IHRoaXMuZXhlY3V0ZUxhdGVyRnVuY3M7XG4gICAgICAgIHRoaXMuZXhlY3V0ZUxhdGVyRnVuY3MgPSBbXTtcbiAgICAgICAgaWYgKG5vd0Z1bmNzLmxlbmd0aCA9PT0gMCAmJiB3YWl0RnVuY3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gbm93RnVuY3MuZm9yRWFjaChmdW5jdGlvbiAoZnVuYykgeyByZXR1cm4gZnVuYygpOyB9KTsgfSwgMCk7XG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdhaXRGdW5jcy5mb3JFYWNoKGZ1bmN0aW9uIChmdW5jKSB7IHJldHVybiBmdW5jKCk7IH0pOyB9LCAzMDApO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRBKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIENvbHVtbkFuaW1hdGlvblNlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkQShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBDb2x1bW5BbmltYXRpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIENvbHVtbkFuaW1hdGlvblNlcnZpY2UgPSBfX2RlY29yYXRlJEEoW1xuICAgICAgICBCZWFuKCdjb2x1bW5BbmltYXRpb25TZXJ2aWNlJylcbiAgICBdLCBDb2x1bW5BbmltYXRpb25TZXJ2aWNlKTtcbiAgICByZXR1cm4gQ29sdW1uQW5pbWF0aW9uU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyR5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSR6ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQXV0b0dyb3VwQ29sU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkeShBdXRvR3JvdXBDb2xTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEF1dG9Hcm91cENvbFNlcnZpY2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQXV0b0dyb3VwQ29sU2VydmljZV8xID0gQXV0b0dyb3VwQ29sU2VydmljZTtcbiAgICBBdXRvR3JvdXBDb2xTZXJ2aWNlLnByb3RvdHlwZS5jcmVhdGVBdXRvR3JvdXBDb2x1bW5zID0gZnVuY3Rpb24gKGV4aXN0aW5nQ29scywgcm93R3JvdXBDb2x1bW5zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBncm91cEF1dG9Db2x1bW5zID0gW107XG4gICAgICAgIHZhciBkb2luZ1RyZWVEYXRhID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNUcmVlRGF0YSgpO1xuICAgICAgICB2YXIgZG9pbmdNdWx0aUF1dG9Db2x1bW4gPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwTXVsdGlBdXRvQ29sdW1uKCk7XG4gICAgICAgIGlmIChkb2luZ1RyZWVEYXRhICYmIGRvaW5nTXVsdGlBdXRvQ29sdW1uKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IHlvdSBjYW5ub3QgbWl4IGdyb3VwTXVsdGlBdXRvQ29sdW1uIHdpdGggdHJlZURhdGEsIG9ubHkgb25lIGNvbHVtbiBjYW4gYmUgdXNlZCB0byBkaXNwbGF5IGdyb3VwcyB3aGVuIGRvaW5nIHRyZWUgZGF0YScpO1xuICAgICAgICAgICAgZG9pbmdNdWx0aUF1dG9Db2x1bW4gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBkb2luZyBncm91cE11bHRpQXV0b0NvbHVtbiwgdGhlbiB3ZSBjYWxsIHRoZSBtZXRob2QgbXVsdGlwbGUgdGltZXMsIG9uY2VcbiAgICAgICAgLy8gZm9yIGVhY2ggY29sdW1uIHdlIGFyZSBncm91cGluZyBieVxuICAgICAgICBpZiAoZG9pbmdNdWx0aUF1dG9Db2x1bW4pIHtcbiAgICAgICAgICAgIHJvd0dyb3VwQ29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dHcm91cENvbCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBncm91cEF1dG9Db2x1bW5zLnB1c2goX3RoaXMuY3JlYXRlT25lQXV0b0dyb3VwQ29sdW1uKGV4aXN0aW5nQ29scywgcm93R3JvdXBDb2wsIGluZGV4KSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdyb3VwQXV0b0NvbHVtbnMucHVzaCh0aGlzLmNyZWF0ZU9uZUF1dG9Hcm91cENvbHVtbihleGlzdGluZ0NvbHMpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ3JvdXBBdXRvQ29sdW1ucztcbiAgICB9O1xuICAgIC8vIHJvd0dyb3VwQ29sIGFuZCBpbmRleCBhcmUgbWlzc2luZyBpZiBncm91cE11bHRpQXV0b0NvbHVtbj1mYWxzZVxuICAgIEF1dG9Hcm91cENvbFNlcnZpY2UucHJvdG90eXBlLmNyZWF0ZU9uZUF1dG9Hcm91cENvbHVtbiA9IGZ1bmN0aW9uIChleGlzdGluZ0NvbHMsIHJvd0dyb3VwQ29sLCBpbmRleCkge1xuICAgICAgICAvLyBpZiBvbmUgcHJvdmlkZWQgYnkgdXNlciwgdXNlIGl0LCBvdGhlcndpc2UgY3JlYXRlIG9uZVxuICAgICAgICB2YXIgZGVmYXVsdEF1dG9Db2xEZWYgPSB0aGlzLmdlbmVyYXRlRGVmYXVsdENvbERlZihyb3dHcm91cENvbCk7XG4gICAgICAgIC8vIGlmIGRvaW5nIG11bHRpLCBzZXQgdGhlIGZpZWxkXG4gICAgICAgIHZhciBjb2xJZDtcbiAgICAgICAgaWYgKHJvd0dyb3VwQ29sKSB7XG4gICAgICAgICAgICBjb2xJZCA9IENvbnN0YW50cy5HUk9VUF9BVVRPX0NPTFVNTl9JRCArIFwiLVwiICsgcm93R3JvdXBDb2wuZ2V0SWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbElkID0gQXV0b0dyb3VwQ29sU2VydmljZV8xLkdST1VQX0FVVE9fQ09MVU1OX0JVTkRMRV9JRDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXNlckF1dG9Db2xEZWYgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBdXRvR3JvdXBDb2x1bW5EZWYoKTtcbiAgICAgICAgbWVyZ2VEZWVwKGRlZmF1bHRBdXRvQ29sRGVmLCB1c2VyQXV0b0NvbERlZik7XG4gICAgICAgIGRlZmF1bHRBdXRvQ29sRGVmID0gdGhpcy5jb2x1bW5GYWN0b3J5Lm1lcmdlQ29sRGVmcyhkZWZhdWx0QXV0b0NvbERlZik7XG4gICAgICAgIGRlZmF1bHRBdXRvQ29sRGVmLmNvbElkID0gY29sSWQ7XG4gICAgICAgIC8vIEZvciB0cmVlIGRhdGEgdGhlIGZpbHRlciBpcyBhbHdheXMgYWxsb3dlZFxuICAgICAgICBpZiAoIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKSkge1xuICAgICAgICAgICAgLy8gd2Ugd291bGQgb25seSBhbGxvdyBmaWx0ZXIgaWYgdGhlIHVzZXIgaGFzIHByb3ZpZGVkIGZpZWxkIG9yIHZhbHVlIGdldHRlci4gb3RoZXJ3aXNlIHRoZSBmaWx0ZXJcbiAgICAgICAgICAgIC8vIHdvdWxkIG5vdCBiZSBhYmxlIHRvIHdvcmsuXG4gICAgICAgICAgICB2YXIgbm9GaWVsZE9yVmFsdWVHZXR0ZXIgPSBtaXNzaW5nKGRlZmF1bHRBdXRvQ29sRGVmLmZpZWxkKSAmJiBtaXNzaW5nKGRlZmF1bHRBdXRvQ29sRGVmLnZhbHVlR2V0dGVyKSAmJiBtaXNzaW5nKGRlZmF1bHRBdXRvQ29sRGVmLmZpbHRlclZhbHVlR2V0dGVyKTtcbiAgICAgICAgICAgIGlmIChub0ZpZWxkT3JWYWx1ZUdldHRlcikge1xuICAgICAgICAgICAgICAgIGRlZmF1bHRBdXRvQ29sRGVmLmZpbHRlciA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHNob3dpbmcgbWFueSBjb2xzLCB3ZSBkb24ndCB3YW50IHRvIHNob3cgbW9yZSB0aGFuIG9uZSB3aXRoIGEgY2hlY2tib3ggZm9yIHNlbGVjdGlvblxuICAgICAgICBpZiAoaW5kZXggJiYgaW5kZXggPiAwKSB7XG4gICAgICAgICAgICBkZWZhdWx0QXV0b0NvbERlZi5oZWFkZXJDaGVja2JveFNlbGVjdGlvbiA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBleGlzdGluZ0NvbCA9IGV4aXN0aW5nQ29scy5maW5kKGZ1bmN0aW9uIChjb2wpIHsgcmV0dXJuIGNvbC5nZXRJZCgpID09IGNvbElkOyB9KTtcbiAgICAgICAgaWYgKGV4aXN0aW5nQ29sKSB7XG4gICAgICAgICAgICBleGlzdGluZ0NvbC5zZXRDb2xEZWYoZGVmYXVsdEF1dG9Db2xEZWYsIG51bGwpO1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5GYWN0b3J5LmFwcGx5Q29sdW1uU3RhdGUoZXhpc3RpbmdDb2wsIGRlZmF1bHRBdXRvQ29sRGVmKTtcbiAgICAgICAgICAgIHJldHVybiBleGlzdGluZ0NvbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV3Q29sID0gbmV3IENvbHVtbihkZWZhdWx0QXV0b0NvbERlZiwgbnVsbCwgY29sSWQsIHRydWUpO1xuICAgICAgICB0aGlzLmNvbnRleHQuY3JlYXRlQmVhbihuZXdDb2wpO1xuICAgICAgICByZXR1cm4gbmV3Q29sO1xuICAgIH07XG4gICAgQXV0b0dyb3VwQ29sU2VydmljZS5wcm90b3R5cGUuZ2VuZXJhdGVEZWZhdWx0Q29sRGVmID0gZnVuY3Rpb24gKHJvd0dyb3VwQ29sKSB7XG4gICAgICAgIHZhciB1c2VyRGVmID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXV0b0dyb3VwQ29sdW1uRGVmKCk7XG4gICAgICAgIHZhciBsb2NhbGVUZXh0RnVuYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldExvY2FsZVRleHRGdW5jKCk7XG4gICAgICAgIHZhciByZXMgPSB7XG4gICAgICAgICAgICBoZWFkZXJOYW1lOiBsb2NhbGVUZXh0RnVuYygnZ3JvdXAnLCAnR3JvdXAnKVxuICAgICAgICB9O1xuICAgICAgICB2YXIgdXNlckhhc1Byb3ZpZGVkR3JvdXBDZWxsUmVuZGVyZXIgPSB1c2VyRGVmICYmXG4gICAgICAgICAgICAodXNlckRlZi5jZWxsUmVuZGVyZXIgfHwgdXNlckRlZi5jZWxsUmVuZGVyZXJGcmFtZXdvcmsgfHwgdXNlckRlZi5jZWxsUmVuZGVyZXJTZWxlY3Rvcik7XG4gICAgICAgIC8vIG9ubHkgYWRkIHRoZSBkZWZhdWx0IGdyb3VwIGNlbGwgcmVuZGVyZXIgaWYgdXNlciBoYXNuJ3QgcHJvdmlkZWQgb25lXG4gICAgICAgIGlmICghdXNlckhhc1Byb3ZpZGVkR3JvdXBDZWxsUmVuZGVyZXIpIHtcbiAgICAgICAgICAgIHJlcy5jZWxsUmVuZGVyZXIgPSAnYWdHcm91cENlbGxSZW5kZXJlcic7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2UgbmV2ZXIgYWxsb3cgbW92aW5nIHRoZSBncm91cCBjb2x1bW5cbiAgICAgICAgLy8gZGVmYXVsdEF1dG9Db2xEZWYuc3VwcHJlc3NNb3ZhYmxlID0gdHJ1ZTtcbiAgICAgICAgaWYgKHJvd0dyb3VwQ29sKSB7XG4gICAgICAgICAgICB2YXIgY29sRGVmID0gcm93R3JvdXBDb2wuZ2V0Q29sRGVmKCk7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKHJlcywge1xuICAgICAgICAgICAgICAgIC8vIGNlbGxSZW5kZXJlclBhcmFtcy5ncm91cEtleTogY29sRGVmVG9Db3B5LmZpZWxkO1xuICAgICAgICAgICAgICAgIGhlYWRlck5hbWU6IHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW4ocm93R3JvdXBDb2wsICdoZWFkZXInKSxcbiAgICAgICAgICAgICAgICBoZWFkZXJWYWx1ZUdldHRlcjogY29sRGVmLmhlYWRlclZhbHVlR2V0dGVyXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChjb2xEZWYuY2VsbFJlbmRlcmVyIHx8IGNvbERlZi5jZWxsUmVuZGVyZXJGcmFtZXdvcmspIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHJlcywge1xuICAgICAgICAgICAgICAgICAgICBjZWxsUmVuZGVyZXJQYXJhbXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlubmVyUmVuZGVyZXI6IGNvbERlZi5jZWxsUmVuZGVyZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbm5lclJlbmRlcmVyRnJhbWV3b3JrOiBjb2xEZWYuY2VsbFJlbmRlcmVyRnJhbWV3b3JrLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJSZW5kZXJlclBhcmFtczogY29sRGVmLmNlbGxSZW5kZXJlclBhcmFtc1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMuc2hvd1Jvd0dyb3VwID0gcm93R3JvdXBDb2wuZ2V0Q29sSWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlcy5zaG93Um93R3JvdXAgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICB2YXIgQXV0b0dyb3VwQ29sU2VydmljZV8xO1xuICAgIEF1dG9Hcm91cENvbFNlcnZpY2UuR1JPVVBfQVVUT19DT0xVTU5fQlVORExFX0lEID0gQ29uc3RhbnRzLkdST1VQX0FVVE9fQ09MVU1OX0lEO1xuICAgIF9fZGVjb3JhdGUkeihbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIEF1dG9Hcm91cENvbFNlcnZpY2UucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSR6KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5GYWN0b3J5JylcbiAgICBdLCBBdXRvR3JvdXBDb2xTZXJ2aWNlLnByb3RvdHlwZSwgXCJjb2x1bW5GYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgQXV0b0dyb3VwQ29sU2VydmljZSA9IEF1dG9Hcm91cENvbFNlcnZpY2VfMSA9IF9fZGVjb3JhdGUkeihbXG4gICAgICAgIEJlYW4oJ2F1dG9Hcm91cENvbFNlcnZpY2UnKVxuICAgIF0sIEF1dG9Hcm91cENvbFNlcnZpY2UpO1xuICAgIHJldHVybiBBdXRvR3JvdXBDb2xTZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJHggPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJHkgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBQYWdpbmF0aW9uQXV0b1BhZ2VTaXplU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkeChQYWdpbmF0aW9uQXV0b1BhZ2VTaXplU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBQYWdpbmF0aW9uQXV0b1BhZ2VTaXplU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBQYWdpbmF0aW9uQXV0b1BhZ2VTaXplU2VydmljZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uIChwKSB7XG4gICAgICAgICAgICBfdGhpcy5jZW50ZXJSb3dDb250YWluZXJDb24gPSBwLmNlbnRlclJvd0NvbnRhaW5lckN0cmw7XG4gICAgICAgICAgICBfdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoX3RoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQk9EWV9IRUlHSFRfQ0hBTkdFRCwgX3RoaXMub25Cb2R5SGVpZ2h0Q2hhbmdlZC5iaW5kKF90aGlzKSk7XG4gICAgICAgICAgICBfdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoX3RoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfU0NST0xMX1ZJU0lCSUxJVFlfQ0hBTkdFRCwgX3RoaXMub25TY3JvbGxWaXNpYmlsaXR5Q2hhbmdlZC5iaW5kKF90aGlzKSk7XG4gICAgICAgICAgICBfdGhpcy5jaGVja1BhZ2VTaXplKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgUGFnaW5hdGlvbkF1dG9QYWdlU2l6ZVNlcnZpY2UucHJvdG90eXBlLm5vdEFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1BhZ2luYXRpb25BdXRvUGFnZVNpemUoKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25BdXRvUGFnZVNpemVTZXJ2aWNlLnByb3RvdHlwZS5vblNjcm9sbFZpc2liaWxpdHlDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNoZWNrUGFnZVNpemUoKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25BdXRvUGFnZVNpemVTZXJ2aWNlLnByb3RvdHlwZS5vbkJvZHlIZWlnaHRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNoZWNrUGFnZVNpemUoKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25BdXRvUGFnZVNpemVTZXJ2aWNlLnByb3RvdHlwZS5jaGVja1BhZ2VTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ub3RBY3RpdmUoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dIZWlnaHQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dIZWlnaHRBc051bWJlcigpO1xuICAgICAgICB2YXIgYm9keUhlaWdodCA9IHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ29uLmdldFZpZXdwb3J0U2l6ZUZlYXR1cmUoKS5nZXRCb2R5SGVpZ2h0KCk7XG4gICAgICAgIGlmIChib2R5SGVpZ2h0ID4gMCkge1xuICAgICAgICAgICAgdmFyIG5ld1BhZ2VTaXplID0gTWF0aC5mbG9vcihib2R5SGVpZ2h0IC8gcm93SGVpZ2h0KTtcbiAgICAgICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnNldFByb3BlcnR5KCdwYWdpbmF0aW9uUGFnZVNpemUnLCBuZXdQYWdlU2l6ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkeShbXG4gICAgICAgIEF1dG93aXJlZCgnY3RybHNTZXJ2aWNlJylcbiAgICBdLCBQYWdpbmF0aW9uQXV0b1BhZ2VTaXplU2VydmljZS5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSR5KFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFBhZ2luYXRpb25BdXRvUGFnZVNpemVTZXJ2aWNlLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIFBhZ2luYXRpb25BdXRvUGFnZVNpemVTZXJ2aWNlID0gX19kZWNvcmF0ZSR5KFtcbiAgICAgICAgQmVhbigncGFnaW5hdGlvbkF1dG9QYWdlU2l6ZVNlcnZpY2UnKVxuICAgIF0sIFBhZ2luYXRpb25BdXRvUGFnZVNpemVTZXJ2aWNlKTtcbiAgICByZXR1cm4gUGFnaW5hdGlvbkF1dG9QYWdlU2l6ZVNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkdyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkeCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFZhbHVlQ2FjaGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJHcoVmFsdWVDYWNoZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBWYWx1ZUNhY2hlKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMuY2FjaGVWZXJzaW9uID0gMDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBWYWx1ZUNhY2hlLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVmFsdWVDYWNoZSgpO1xuICAgICAgICB0aGlzLm5ldmVyRXhwaXJlcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVmFsdWVDYWNoZU5ldmVyRXhwaXJlcygpO1xuICAgIH07XG4gICAgVmFsdWVDYWNoZS5wcm90b3R5cGUub25EYXRhQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMubmV2ZXJFeHBpcmVzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5leHBpcmUoKTtcbiAgICB9O1xuICAgIFZhbHVlQ2FjaGUucHJvdG90eXBlLmV4cGlyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jYWNoZVZlcnNpb24rKztcbiAgICB9O1xuICAgIFZhbHVlQ2FjaGUucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHJvd05vZGUsIGNvbElkLCB2YWx1ZSkge1xuICAgICAgICBpZiAodGhpcy5hY3RpdmUpIHtcbiAgICAgICAgICAgIGlmIChyb3dOb2RlLl9fY2FjaGVWZXJzaW9uICE9PSB0aGlzLmNhY2hlVmVyc2lvbikge1xuICAgICAgICAgICAgICAgIHJvd05vZGUuX19jYWNoZVZlcnNpb24gPSB0aGlzLmNhY2hlVmVyc2lvbjtcbiAgICAgICAgICAgICAgICByb3dOb2RlLl9fY2FjaGVEYXRhID0ge307XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByb3dOb2RlLl9fY2FjaGVEYXRhW2NvbElkXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWYWx1ZUNhY2hlLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uIChyb3dOb2RlLCBjb2xJZCkge1xuICAgICAgICBpZiAoIXRoaXMuYWN0aXZlIHx8IHJvd05vZGUuX19jYWNoZVZlcnNpb24gIT09IHRoaXMuY2FjaGVWZXJzaW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dOb2RlLl9fY2FjaGVEYXRhW2NvbElkXTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkeChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBWYWx1ZUNhY2hlLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIFZhbHVlQ2FjaGUgPSBfX2RlY29yYXRlJHgoW1xuICAgICAgICBCZWFuKCd2YWx1ZUNhY2hlJylcbiAgICBdLCBWYWx1ZUNhY2hlKTtcbiAgICByZXR1cm4gVmFsdWVDYWNoZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyR2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSR3ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ2hhbmdlRGV0ZWN0aW9uU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkdihDaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENoYW5nZURldGVjdGlvblNlcnZpY2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQ2hhbmdlRGV0ZWN0aW9uU2VydmljZS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucm93TW9kZWwuZ2V0VHlwZSgpID09PSBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfQ0xJRU5UX1NJREUpIHtcbiAgICAgICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsID0gdGhpcy5yb3dNb2RlbDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NFTExfVkFMVUVfQ0hBTkdFRCwgdGhpcy5vbkNlbGxWYWx1ZUNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgfTtcbiAgICBDaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZS5vbkNlbGxWYWx1ZUNoYW5nZWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgLy8gQ2xpcGJvYXJkIHNlcnZpY2UgbWFuYWdlcyBpdHMgb3duIGNoYW5nZSBkZXRlY3Rpb24sIHNvIG5vIG5lZWQgdG8gZG8gaXQgaGVyZS5cbiAgICAgICAgLy8gVGhlIGNsaXBib2FyZCBtYW5hZ2VzIGl0cyBvd24gYXMgb3RoZXJ3aXNlIHRoaXMgd291bGQgaGFwcGVuIG9uY2UgZm9yIGV2ZXJ5IGNlbGxcbiAgICAgICAgLy8gdGhhdCBnb3QgdXBkYXRlZCBhcyBwYXJ0IG9mIGEgcGFzdGUgb3BlcmF0aW9uLCBzbyBlLmcuIGlmIDEwMCBjZWxscyBpbiBhIHBhc3RlIG9wZXJhdGlvbixcbiAgICAgICAgLy8gdGhpcyBkb0NoYW5nZURldGVjdGlvbiB3b3VsZCBnZXQgY2FsbGVkIDEwMCB0aW1lcyAob25jZSBmb3IgZWFjaCBjZWxsKSwgaW5zdGVhZCBjbGlwYm9hcmRcbiAgICAgICAgLy8gc2VydmljZSBleGVjdXRlcyB0aGUgbG9naWMgd2UgaGF2ZSBoZXJlIG9uY2UgKGluIGVzc2VuY2UgYmF0Y2hpbmcgdXAgYWxsIGNlbGwgY2hhbmdlc1xuICAgICAgICAvLyBpbnRvIG9uZSBjaGFuZ2UgZGV0ZWN0aW9uKS5cbiAgICAgICAgaWYgKGV2ZW50LnNvdXJjZSA9PT0gQ29uc3RhbnRzLlNPVVJDRV9QQVNURSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZG9DaGFuZ2VEZXRlY3Rpb24oZXZlbnQubm9kZSwgZXZlbnQuY29sdW1uKTtcbiAgICB9O1xuICAgIENoYW5nZURldGVjdGlvblNlcnZpY2UucHJvdG90eXBlLmRvQ2hhbmdlRGV0ZWN0aW9uID0gZnVuY3Rpb24gKHJvd05vZGUsIGNvbHVtbikge1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0NoYW5nZURldGVjdGlvbigpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gc3RlcCAxIG9mIGNoYW5nZSBkZXRlY3Rpb24gaXMgdG8gdXBkYXRlIHRoZSBhZ2dyZWdhdGVkIHZhbHVlc1xuICAgICAgICBpZiAodGhpcy5jbGllbnRTaWRlUm93TW9kZWwgJiYgIXJvd05vZGUuaXNSb3dQaW5uZWQoKSkge1xuICAgICAgICAgICAgdmFyIG9ubHlDaGFuZ2VkQ29sdW1ucyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQWdncmVnYXRlT25seUNoYW5nZWRDb2x1bW5zKCk7XG4gICAgICAgICAgICB2YXIgY2hhbmdlZFBhdGggPSBuZXcgQ2hhbmdlZFBhdGgob25seUNoYW5nZWRDb2x1bW5zLCB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5nZXRSb290Tm9kZSgpKTtcbiAgICAgICAgICAgIGNoYW5nZWRQYXRoLmFkZFBhcmVudE5vZGUocm93Tm9kZS5wYXJlbnQsIFtjb2x1bW5dKTtcbiAgICAgICAgICAgIHRoaXMuY2xpZW50U2lkZVJvd01vZGVsLmRvQWdncmVnYXRlKGNoYW5nZWRQYXRoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBzdGVwIDIgb2YgY2hhbmdlIGRldGVjdGlvbiBpcyB0byByZWZyZXNoIHRoZSBjZWxsc1xuICAgICAgICB0aGlzLnJvd1JlbmRlcmVyLnJlZnJlc2hDZWxscygpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSR3KFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dNb2RlbCcpXG4gICAgXSwgQ2hhbmdlRGV0ZWN0aW9uU2VydmljZS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJHcoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd1JlbmRlcmVyJylcbiAgICBdLCBDaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJyb3dSZW5kZXJlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkdyhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBDaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIENoYW5nZURldGVjdGlvblNlcnZpY2UgPSBfX2RlY29yYXRlJHcoW1xuICAgICAgICBCZWFuKCdjaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlJylcbiAgICBdLCBDaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlKTtcbiAgICByZXR1cm4gQ2hhbmdlRGV0ZWN0aW9uU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyR1ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSR2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQWdDb21wb25lbnRVdGlscyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkdShBZ0NvbXBvbmVudFV0aWxzLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnQ29tcG9uZW50VXRpbHMoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQWdDb21wb25lbnRVdGlscy5wcm90b3R5cGUuYWRhcHRGdW5jdGlvbiA9IGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWUsIGpzQ29tcEZ1bmMpIHtcbiAgICAgICAgdmFyIG1ldGFkYXRhID0gdGhpcy5jb21wb25lbnRNZXRhZGF0YVByb3ZpZGVyLnJldHJpZXZlKHByb3BlcnR5TmFtZSk7XG4gICAgICAgIGlmIChtZXRhZGF0YSAmJiBtZXRhZGF0YS5mdW5jdGlvbkFkYXB0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YS5mdW5jdGlvbkFkYXB0ZXIoanNDb21wRnVuYyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICBBZ0NvbXBvbmVudFV0aWxzLnByb3RvdHlwZS5hZGFwdENlbGxSZW5kZXJlckZ1bmN0aW9uID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBBZGFwdGVyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZnVuY3Rpb24gQWRhcHRlcigpIHtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEFkYXB0ZXIucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIEFkYXB0ZXIucHJvdG90eXBlLmdldEd1aSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lR3VpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIEFkYXB0ZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrUmVzdWx0ID0gY2FsbGJhY2socGFyYW1zKTtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHR5cGVvZiBjYWxsYmFja1Jlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycgfHwgdHlwZSA9PT0gJ251bWJlcicgfHwgdHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZUd1aSA9IGxvYWRUZW1wbGF0ZSgnPHNwYW4+JyArIGNhbGxiYWNrUmVzdWx0ICsgJzwvc3Bhbj4nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2tSZXN1bHQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVHdWkgPSBsb2FkVGVtcGxhdGUoJzxzcGFuPjwvc3Bhbj4nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmVHdWkgPSBjYWxsYmFja1Jlc3VsdDtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gQWRhcHRlcjtcbiAgICAgICAgfSgpKTtcbiAgICAgICAgcmV0dXJuIEFkYXB0ZXI7XG4gICAgfTtcbiAgICBBZ0NvbXBvbmVudFV0aWxzLnByb3RvdHlwZS5kb2VzSW1wbGVtZW50SUNvbXBvbmVudCA9IGZ1bmN0aW9uIChjYW5kaWRhdGUpIHtcbiAgICAgICAgaWYgKCFjYW5kaWRhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FuZGlkYXRlLnByb3RvdHlwZSAmJiAnZ2V0R3VpJyBpbiBjYW5kaWRhdGUucHJvdG90eXBlO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSR2KFtcbiAgICAgICAgQXV0b3dpcmVkKFwiY29tcG9uZW50TWV0YWRhdGFQcm92aWRlclwiKVxuICAgIF0sIEFnQ29tcG9uZW50VXRpbHMucHJvdG90eXBlLCBcImNvbXBvbmVudE1ldGFkYXRhUHJvdmlkZXJcIiwgdm9pZCAwKTtcbiAgICBBZ0NvbXBvbmVudFV0aWxzID0gX19kZWNvcmF0ZSR2KFtcbiAgICAgICAgQmVhbihcImFnQ29tcG9uZW50VXRpbHNcIilcbiAgICBdLCBBZ0NvbXBvbmVudFV0aWxzKTtcbiAgICByZXR1cm4gQWdDb21wb25lbnRVdGlscztcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyR0ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSR1ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ29tcG9uZW50TWV0YWRhdGFQcm92aWRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkdChDb21wb25lbnRNZXRhZGF0YVByb3ZpZGVyLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbXBvbmVudE1ldGFkYXRhUHJvdmlkZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQ29tcG9uZW50TWV0YWRhdGFQcm92aWRlci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnRNZXRhRGF0YSA9IHtcbiAgICAgICAgICAgIGRhdGVDb21wb25lbnQ6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbJ2dldERhdGUnLCAnc2V0RGF0ZSddLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogWydhZnRlckd1aUF0dGFjaGVkJywgJ3NldElucHV0UGxhY2Vob2xkZXInLCAnc2V0SW5wdXRBcmlhTGFiZWwnXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRldGFpbENlbGxSZW5kZXJlcjoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFtdLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogWydyZWZyZXNoJ10sXG4gICAgICAgICAgICAgICAgZnVuY3Rpb25BZGFwdGVyOiB0aGlzLmFnQ29tcG9uZW50VXRpbHMuYWRhcHRDZWxsUmVuZGVyZXJGdW5jdGlvbi5iaW5kKHRoaXMuYWdDb21wb25lbnRVdGlscylcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoZWFkZXJDb21wb25lbnQ6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbXSxcbiAgICAgICAgICAgICAgICBvcHRpb25hbE1ldGhvZExpc3Q6IFsncmVmcmVzaCddXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGVhZGVyR3JvdXBDb21wb25lbnQ6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbXSxcbiAgICAgICAgICAgICAgICBvcHRpb25hbE1ldGhvZExpc3Q6IFtdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbG9hZGluZ0NlbGxSZW5kZXJlcjoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFtdLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogW11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsb2FkaW5nT3ZlcmxheUNvbXBvbmVudDoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFtdLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogW11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBub1Jvd3NPdmVybGF5Q29tcG9uZW50OiB7XG4gICAgICAgICAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdDogW10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZsb2F0aW5nRmlsdGVyQ29tcG9uZW50OiB7XG4gICAgICAgICAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdDogWydvblBhcmVudE1vZGVsQ2hhbmdlZCddLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogWydhZnRlckd1aUF0dGFjaGVkJ11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmbG9hdGluZ0ZpbHRlcldyYXBwZXJDb21wb25lbnQ6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbXSxcbiAgICAgICAgICAgICAgICBvcHRpb25hbE1ldGhvZExpc3Q6IFtdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2VsbFJlbmRlcmVyOiB7XG4gICAgICAgICAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdDogW10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbJ3JlZnJlc2gnLCAnYWZ0ZXJHdWlBdHRhY2hlZCddLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uQWRhcHRlcjogdGhpcy5hZ0NvbXBvbmVudFV0aWxzLmFkYXB0Q2VsbFJlbmRlcmVyRnVuY3Rpb24uYmluZCh0aGlzLmFnQ29tcG9uZW50VXRpbHMpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2VsbEVkaXRvcjoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFsnZ2V0VmFsdWUnXSxcbiAgICAgICAgICAgICAgICBvcHRpb25hbE1ldGhvZExpc3Q6IFsnaXNQb3B1cCcsICdpc0NhbmNlbEJlZm9yZVN0YXJ0JywgJ2lzQ2FuY2VsQWZ0ZXJFbmQnLCAnZ2V0UG9wdXBQb3NpdGlvbicsICdmb2N1c0luJywgJ2ZvY3VzT3V0JywgJ2FmdGVyR3VpQXR0YWNoZWQnXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlubmVyUmVuZGVyZXI6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbXSxcbiAgICAgICAgICAgICAgICBvcHRpb25hbE1ldGhvZExpc3Q6IFsnYWZ0ZXJHdWlBdHRhY2hlZCddLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uQWRhcHRlcjogdGhpcy5hZ0NvbXBvbmVudFV0aWxzLmFkYXB0Q2VsbFJlbmRlcmVyRnVuY3Rpb24uYmluZCh0aGlzLmFnQ29tcG9uZW50VXRpbHMpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVsbFdpZHRoQ2VsbFJlbmRlcmVyOiB7XG4gICAgICAgICAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdDogW10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbJ3JlZnJlc2gnLCAnYWZ0ZXJHdWlBdHRhY2hlZCddLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uQWRhcHRlcjogdGhpcy5hZ0NvbXBvbmVudFV0aWxzLmFkYXB0Q2VsbFJlbmRlcmVyRnVuY3Rpb24uYmluZCh0aGlzLmFnQ29tcG9uZW50VXRpbHMpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGlubmVkUm93Q2VsbFJlbmRlcmVyOiB7XG4gICAgICAgICAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdDogW10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbJ3JlZnJlc2gnLCAnYWZ0ZXJHdWlBdHRhY2hlZCddLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uQWRhcHRlcjogdGhpcy5hZ0NvbXBvbmVudFV0aWxzLmFkYXB0Q2VsbFJlbmRlcmVyRnVuY3Rpb24uYmluZCh0aGlzLmFnQ29tcG9uZW50VXRpbHMpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ3JvdXBSb3dSZW5kZXJlcjoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFtdLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogWydhZnRlckd1aUF0dGFjaGVkJ10sXG4gICAgICAgICAgICAgICAgZnVuY3Rpb25BZGFwdGVyOiB0aGlzLmFnQ29tcG9uZW50VXRpbHMuYWRhcHRDZWxsUmVuZGVyZXJGdW5jdGlvbi5iaW5kKHRoaXMuYWdDb21wb25lbnRVdGlscylcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmaWx0ZXI6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbJ2lzRmlsdGVyQWN0aXZlJywgJ2RvZXNGaWx0ZXJQYXNzJywgJ2dldE1vZGVsJywgJ3NldE1vZGVsJ10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbJ2FmdGVyR3VpQXR0YWNoZWQnLCAnb25OZXdSb3dzTG9hZGVkJywgJ2dldE1vZGVsQXNTdHJpbmcnLCAnb25GbG9hdGluZ0ZpbHRlckNoYW5nZWQnLCAnb25BbnlGaWx0ZXJDaGFuZ2VkJ11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmaWx0ZXJDb21wb25lbnQ6IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnlNZXRob2RMaXN0OiBbJ2lzRmlsdGVyQWN0aXZlJywgJ2RvZXNGaWx0ZXJQYXNzJywgJ2dldE1vZGVsJywgJ3NldE1vZGVsJ10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbJ2FmdGVyR3VpQXR0YWNoZWQnLCAnb25OZXdSb3dzTG9hZGVkJywgJ2dldE1vZGVsQXNTdHJpbmcnLCAnb25GbG9hdGluZ0ZpbHRlckNoYW5nZWQnLCAnb25BbnlGaWx0ZXJDaGFuZ2VkJ11cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdGF0dXNQYW5lbDoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFtdLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogWydhZnRlckd1aUF0dGFjaGVkJ10sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdG9vbFBhbmVsOiB7XG4gICAgICAgICAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdDogW10sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWxNZXRob2RMaXN0OiBbJ3JlZnJlc2gnLCAnYWZ0ZXJHdWlBdHRhY2hlZCddXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdG9vbHRpcENvbXBvbmVudDoge1xuICAgICAgICAgICAgICAgIG1hbmRhdG9yeU1ldGhvZExpc3Q6IFtdLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdDogW11cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENvbXBvbmVudE1ldGFkYXRhUHJvdmlkZXIucHJvdG90eXBlLnJldHJpZXZlID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50TWV0YURhdGFbbmFtZV07XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJHUoW1xuICAgICAgICBBdXRvd2lyZWQoXCJhZ0NvbXBvbmVudFV0aWxzXCIpXG4gICAgXSwgQ29tcG9uZW50TWV0YWRhdGFQcm92aWRlci5wcm90b3R5cGUsIFwiYWdDb21wb25lbnRVdGlsc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkdShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBDb21wb25lbnRNZXRhZGF0YVByb3ZpZGVyLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIENvbXBvbmVudE1ldGFkYXRhUHJvdmlkZXIgPSBfX2RlY29yYXRlJHUoW1xuICAgICAgICBCZWFuKFwiY29tcG9uZW50TWV0YWRhdGFQcm92aWRlclwiKVxuICAgIF0sIENvbXBvbmVudE1ldGFkYXRhUHJvdmlkZXIpO1xuICAgIHJldHVybiBDb21wb25lbnRNZXRhZGF0YVByb3ZpZGVyO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJHMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJHQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBNQVRfR1JJRF9TSVpFID0gODtcbnZhciBCQVNFX0dSSURfU0laRSA9IDQ7XG52YXIgQkFMSEFNX0dSSURfU0laRSA9IDQ7XG52YXIgQUxQSU5FX0dSSURfU0laRSA9IDY7XG52YXIgSEFSRF9DT0RFRF9TSVpFUyA9IHtcbiAgICAvLyB0aGlzIGl0ZW0gaXMgcmVxdWlyZWQgZm9yIGN1c3RvbSB0aGVtZXNcbiAgICAnYWctdGhlbWUtY3VzdG9tJzoge1xuICAgICAgICBoZWFkZXJIZWlnaHQ6IDI1LFxuICAgICAgICBoZWFkZXJDZWxsTWluV2lkdGg6IDI0LFxuICAgICAgICBsaXN0SXRlbUhlaWdodDogQkFTRV9HUklEX1NJWkUgKiA1LFxuICAgICAgICByb3dIZWlnaHQ6IDI1LFxuICAgICAgICBjaGFydE1lbnVQYW5lbFdpZHRoOiAyMjBcbiAgICB9LFxuICAgICdhZy10aGVtZS1tYXRlcmlhbCc6IHtcbiAgICAgICAgaGVhZGVySGVpZ2h0OiBNQVRfR1JJRF9TSVpFICogNyxcbiAgICAgICAgaGVhZGVyQ2VsbE1pbldpZHRoOiA0OCxcbiAgICAgICAgbGlzdEl0ZW1IZWlnaHQ6IE1BVF9HUklEX1NJWkUgKiA0LFxuICAgICAgICByb3dIZWlnaHQ6IE1BVF9HUklEX1NJWkUgKiA2LFxuICAgICAgICBjaGFydE1lbnVQYW5lbFdpZHRoOiAyNDBcbiAgICB9LFxuICAgICdhZy10aGVtZS1iYWxoYW0nOiB7XG4gICAgICAgIGhlYWRlckhlaWdodDogQkFMSEFNX0dSSURfU0laRSAqIDgsXG4gICAgICAgIGhlYWRlckNlbGxNaW5XaWR0aDogMjQsXG4gICAgICAgIGxpc3RJdGVtSGVpZ2h0OiBCQUxIQU1fR1JJRF9TSVpFICogNixcbiAgICAgICAgcm93SGVpZ2h0OiBCQUxIQU1fR1JJRF9TSVpFICogNyxcbiAgICAgICAgY2hhcnRNZW51UGFuZWxXaWR0aDogMjIwXG4gICAgfSxcbiAgICAnYWctdGhlbWUtYWxwaW5lJzoge1xuICAgICAgICBoZWFkZXJIZWlnaHQ6IEFMUElORV9HUklEX1NJWkUgKiA4LFxuICAgICAgICBoZWFkZXJDZWxsTWluV2lkdGg6IDM2LFxuICAgICAgICBsaXN0SXRlbUhlaWdodDogQUxQSU5FX0dSSURfU0laRSAqIDQsXG4gICAgICAgIHJvd0hlaWdodDogQUxQSU5FX0dSSURfU0laRSAqIDcsXG4gICAgICAgIGNoYXJ0TWVudVBhbmVsV2lkdGg6IDI0MFxuICAgIH1cbn07XG4vKipcbiAqIHRoaXMgb2JqZWN0IGNvbnRhaW5zIGEgbGlzdCBvZiBTYXNzIHZhcmlhYmxlcyBhbmQgYW4gYXJyYXlcbiAqIG9mIENTUyBzdHlsZXMgcmVxdWlyZWQgdG8gZ2V0IHRoZSBjb3JyZWN0IHZhbHVlLlxuICogZWcuICR2aXJ0dWFsLWl0ZW0taGVpZ2h0IHJlcXVpcmVzIGEgc3RydWN0dXJlLCBzbyB3ZSBjYW4gZ2V0IGl0cyBoZWlnaHQuXG4gKiA8ZGl2IGNsYXNzPVwiYWctdGhlbWUtYmFsaGFtXCI+XG4gKiAgICAgPGRpdiBjbGFzcz1cImFnLXZpcnR1YWwtbGlzdC1jb250YWluZXJcIj5cbiAqICAgICAgICAgPGRpdiBjbGFzcz1cImFnLXZpcnR1YWwtbGlzdC1pdGVtXCI+PC9kaXY+XG4gKiAgICAgPC9kaXY+XG4gKiA8L2Rpdj5cbiAqL1xudmFyIFNBU1NfUFJPUEVSVFlfQlVJTERFUiA9IHtcbiAgICBoZWFkZXJIZWlnaHQ6IFsnYWctaGVhZGVyLXJvdyddLFxuICAgIGhlYWRlckNlbGxNaW5XaWR0aDogWydhZy1oZWFkZXItY2VsbCddLFxuICAgIGxpc3RJdGVtSGVpZ2h0OiBbJ2FnLXZpcnR1YWwtbGlzdC1pdGVtJ10sXG4gICAgcm93SGVpZ2h0OiBbJ2FnLXJvdyddLFxuICAgIGNoYXJ0TWVudVBhbmVsV2lkdGg6IFsnYWctY2hhcnQtZG9ja2VkLWNvbnRhaW5lciddXG59O1xudmFyIENBTENVTEFURURfU0laRVMgPSB7fTtcbnZhciBFbnZpcm9ubWVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkcyhFbnZpcm9ubWVudCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBFbnZpcm9ubWVudC5wcm90b3R5cGUuZ2V0U2Fzc1ZhcmlhYmxlID0gZnVuY3Rpb24gKHRoZW1lLCBrZXkpIHtcbiAgICAgICAgdmFyIHVzZVRoZW1lID0gJ2FnLXRoZW1lLScgKyAodGhlbWUubWF0Y2goJ21hdGVyaWFsJykgPyAnbWF0ZXJpYWwnIDogdGhlbWUubWF0Y2goJ2JhbGhhbScpID8gJ2JhbGhhbScgOiB0aGVtZS5tYXRjaCgnYWxwaW5lJykgPyAnYWxwaW5lJyA6ICdjdXN0b20nKTtcbiAgICAgICAgdmFyIGRlZmF1bHRWYWx1ZSA9IEhBUkRfQ09ERURfU0laRVNbdXNlVGhlbWVdW2tleV07XG4gICAgICAgIHZhciBjYWxjdWxhdGVkVmFsdWUgPSAwO1xuICAgICAgICBpZiAoIUNBTENVTEFURURfU0laRVNbdGhlbWVdKSB7XG4gICAgICAgICAgICBDQUxDVUxBVEVEX1NJWkVTW3RoZW1lXSA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaXplID0gQ0FMQ1VMQVRFRF9TSVpFU1t0aGVtZV1ba2V5XTtcbiAgICAgICAgaWYgKHNpemUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHNpemU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFNBU1NfUFJPUEVSVFlfQlVJTERFUltrZXldKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NMaXN0ID0gU0FTU19QUk9QRVJUWV9CVUlMREVSW2tleV07XG4gICAgICAgICAgICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBkaXYuY2xhc3NMaXN0LmFkZCh0aGVtZSk7XG4gICAgICAgICAgICBkaXYuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICAgICAgdmFyIGVsID0gY2xhc3NMaXN0LnJlZHVjZShmdW5jdGlvbiAocHJldkVsLCBjdXJyZW50Q2xhc3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnREaXYuc3R5bGUucG9zaXRpb24gPSAnc3RhdGljJztcbiAgICAgICAgICAgICAgICBjdXJyZW50RGl2LmNsYXNzTGlzdC5hZGQoY3VycmVudENsYXNzKTtcbiAgICAgICAgICAgICAgICBwcmV2RWwuYXBwZW5kQ2hpbGQoY3VycmVudERpdik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnREaXY7XG4gICAgICAgICAgICB9LCBkaXYpO1xuICAgICAgICAgICAgaWYgKGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgICAgICAgICAgdmFyIHNpemVOYW1lID0ga2V5LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignaGVpZ2h0JykgIT09IC0xID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICAgICAgICAgICAgICAgIGNhbGN1bGF0ZWRWYWx1ZSA9IHBhcnNlSW50KHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsKVtzaXplTmFtZV0sIDEwKTtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGRpdik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgQ0FMQ1VMQVRFRF9TSVpFU1t0aGVtZV1ba2V5XSA9IGNhbGN1bGF0ZWRWYWx1ZSB8fCBkZWZhdWx0VmFsdWU7XG4gICAgICAgIHJldHVybiBDQUxDVUxBVEVEX1NJWkVTW3RoZW1lXVtrZXldO1xuICAgIH07XG4gICAgRW52aXJvbm1lbnQucHJvdG90eXBlLmlzVGhlbWVEYXJrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdGhlbWUgPSB0aGlzLmdldFRoZW1lKCkudGhlbWU7XG4gICAgICAgIHJldHVybiAhIXRoZW1lICYmIHRoZW1lLmluZGV4T2YoJ2RhcmsnKSA+PSAwO1xuICAgIH07XG4gICAgRW52aXJvbm1lbnQucHJvdG90eXBlLmNoYXJ0TWVudVBhbmVsV2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB0aGVtZSA9IHRoaXMuZ2V0VGhlbWUoKS50aGVtZUZhbWlseTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2Fzc1ZhcmlhYmxlKHRoZW1lLCAnY2hhcnRNZW51UGFuZWxXaWR0aCcpO1xuICAgIH07XG4gICAgRW52aXJvbm1lbnQucHJvdG90eXBlLmdldFRoZW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVnID0gL1xcYmFnLShtYXRlcmlhbHwoPzp0aGVtZS0oW1xcd1xcLV0qKSkpXFxiL2c7XG4gICAgICAgIHZhciBlbCA9IHRoaXMuZUdyaWREaXY7XG4gICAgICAgIHZhciB0aGVtZU1hdGNoID0gbnVsbDtcbiAgICAgICAgdmFyIGFsbFRoZW1lcyA9IFtdO1xuICAgICAgICB3aGlsZSAoZWwpIHtcbiAgICAgICAgICAgIHRoZW1lTWF0Y2ggPSByZWcuZXhlYyhlbC5jbGFzc05hbWUpO1xuICAgICAgICAgICAgaWYgKCF0aGVtZU1hdGNoKSB7XG4gICAgICAgICAgICAgICAgZWwgPSBlbC5wYXJlbnRFbGVtZW50IHx8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVkID0gZWwuY2xhc3NOYW1lLm1hdGNoKHJlZyk7XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWxsVGhlbWVzID0gbWF0Y2hlZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGVtZU1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4geyBhbGxUaGVtZXM6IGFsbFRoZW1lcyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciB0aGVtZSA9IHRoZW1lTWF0Y2hbMF07XG4gICAgICAgIHZhciB1c2luZ09sZFRoZW1lID0gdGhlbWVNYXRjaFsyXSA9PT0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAodXNpbmdPbGRUaGVtZSkge1xuICAgICAgICAgICAgdmFyIG5ld1RoZW1lXzEgPSB0aGVtZS5yZXBsYWNlKCdhZy0nLCAnYWctdGhlbWUtJyk7XG4gICAgICAgICAgICBkb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKFwiQUcgR3JpZDogQXMgb2YgdjE5IG9sZCB0aGVtZSBhcmUgbm8gbG9uZ2VyIHByb3ZpZGVkLiBQbGVhc2UgcmVwbGFjZSBcIiArIHRoZW1lICsgXCIgd2l0aCBcIiArIG5ld1RoZW1lXzEgKyBcIi5cIik7IH0sICd1c2luZy1vbGQtdGhlbWUnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB0aGVtZTogdGhlbWUsIGVsOiBlbCwgdGhlbWVGYW1pbHk6IHRoZW1lLnJlcGxhY2UoLy1kYXJrJC8sICcnKSwgYWxsVGhlbWVzOiBhbGxUaGVtZXMgfTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkdChbXG4gICAgICAgIEF1dG93aXJlZCgnZUdyaWREaXYnKVxuICAgIF0sIEVudmlyb25tZW50LnByb3RvdHlwZSwgXCJlR3JpZERpdlwiLCB2b2lkIDApO1xuICAgIEVudmlyb25tZW50ID0gX19kZWNvcmF0ZSR0KFtcbiAgICAgICAgQmVhbignZW52aXJvbm1lbnQnKVxuICAgIF0sIEVudmlyb25tZW50KTtcbiAgICByZXR1cm4gRW52aXJvbm1lbnQ7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkciA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkcyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIF9fcGFyYW0kMSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcGFyYW0pIHx8IGZ1bmN0aW9uIChwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cbn07XG4vKipcbiAqIFRoaXMgY2xhc3Mgc29sdmVzIHRoZSAnbWF4IGhlaWdodCcgcHJvYmxlbSwgd2hlcmUgdGhlIHVzZXIgbWlnaHQgd2FudCB0byBzaG93IG1vcmUgZGF0YSB0aGFuXG4gKiB0aGUgbWF4IGRpdiBoZWlnaHQgYWN0dWFsbHkgYWxsb3dzLlxuICovXG52YXIgUm93Q29udGFpbmVySGVpZ2h0U2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkcihSb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICAvLyB0aGUgc2Nyb2xsWSBwb3NpdGlvblxuICAgICAgICBfdGhpcy5zY3JvbGxZID0gMDtcbiAgICAgICAgLy8gaG93IHRhbGwgdGhlIGJvZHkgaXNcbiAgICAgICAgX3RoaXMudWlCb2R5SGVpZ2h0ID0gMDtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLnByb3RvdHlwZS5hZ1dpcmUgPSBmdW5jdGlvbiAobG9nZ2VyRmFjdG9yeSkge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlckZhY3RvcnkuY3JlYXRlKFwiUm93Q29udGFpbmVySGVpZ2h0U2VydmljZVwiKTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQk9EWV9IRUlHSFRfQ0hBTkdFRCwgdGhpcy51cGRhdGVPZmZzZXQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMubWF4RGl2SGVpZ2h0ID0gZ2V0TWF4RGl2SGVpZ2h0KCk7XG4gICAgICAgIHRoaXMubG9nZ2VyLmxvZygnbWF4RGl2SGVpZ2h0ID0gJyArIHRoaXMubWF4RGl2SGVpZ2h0KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLmlzU3RyZXRjaGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RyZXRjaGluZztcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLmdldERpdlN0cmV0Y2hPZmZzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpdlN0cmV0Y2hPZmZzZXQ7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLnByb3RvdHlwZS51cGRhdGVPZmZzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zdHJldGNoaW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGdyaWRCb2R5Q29uID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgIHZhciBuZXdTY3JvbGxZID0gZ3JpZEJvZHlDb24uZ2V0U2Nyb2xsRmVhdHVyZSgpLmdldFZTY3JvbGxQb3NpdGlvbigpLnRvcDtcbiAgICAgICAgdmFyIG5ld0JvZHlIZWlnaHQgPSB0aGlzLmdldFVpQm9keUhlaWdodCgpO1xuICAgICAgICB2YXIgYXRMZWFzdE9uZUNoYW5nZWQgPSBuZXdTY3JvbGxZICE9PSB0aGlzLnNjcm9sbFkgfHwgbmV3Qm9keUhlaWdodCAhPT0gdGhpcy51aUJvZHlIZWlnaHQ7XG4gICAgICAgIGlmIChhdExlYXN0T25lQ2hhbmdlZCkge1xuICAgICAgICAgICAgdGhpcy5zY3JvbGxZID0gbmV3U2Nyb2xsWTtcbiAgICAgICAgICAgIHRoaXMudWlCb2R5SGVpZ2h0ID0gbmV3Qm9keUhlaWdodDtcbiAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlT2Zmc2V0KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLmNhbGN1bGF0ZU9mZnNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRVaUNvbnRhaW5lckhlaWdodCh0aGlzLm1heERpdkhlaWdodCk7XG4gICAgICAgIHRoaXMucGl4ZWxzVG9TaGF2ZSA9IHRoaXMubW9kZWxIZWlnaHQgLSB0aGlzLnVpQ29udGFpbmVySGVpZ2h0O1xuICAgICAgICB0aGlzLm1heFNjcm9sbFkgPSB0aGlzLnVpQ29udGFpbmVySGVpZ2h0IC0gdGhpcy51aUJvZHlIZWlnaHQ7XG4gICAgICAgIHZhciBzY3JvbGxQZXJjZW50ID0gdGhpcy5zY3JvbGxZIC8gdGhpcy5tYXhTY3JvbGxZO1xuICAgICAgICB2YXIgZGl2U3RyZXRjaE9mZnNldCA9IHNjcm9sbFBlcmNlbnQgKiB0aGlzLnBpeGVsc1RvU2hhdmU7XG4gICAgICAgIHRoaXMubG9nZ2VyLmxvZyhcIkRpdiBTdHJldGNoIE9mZnNldCA9IFwiICsgZGl2U3RyZXRjaE9mZnNldCArIFwiIChcIiArIHRoaXMucGl4ZWxzVG9TaGF2ZSArIFwiICogXCIgKyBzY3JvbGxQZXJjZW50ICsgXCIpXCIpO1xuICAgICAgICB0aGlzLnNldERpdlN0cmV0Y2hPZmZzZXQoZGl2U3RyZXRjaE9mZnNldCk7XG4gICAgfTtcbiAgICBSb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlLnByb3RvdHlwZS5zZXRVaUNvbnRhaW5lckhlaWdodCA9IGZ1bmN0aW9uIChoZWlnaHQpIHtcbiAgICAgICAgaWYgKGhlaWdodCAhPT0gdGhpcy51aUNvbnRhaW5lckhlaWdodCkge1xuICAgICAgICAgICAgdGhpcy51aUNvbnRhaW5lckhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBFdmVudHMuRVZFTlRfUk9XX0NPTlRBSU5FUl9IRUlHSFRfQ0hBTkdFRCB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Q29udGFpbmVySGVpZ2h0U2VydmljZS5wcm90b3R5cGUuY2xlYXJPZmZzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0VWlDb250YWluZXJIZWlnaHQodGhpcy5tb2RlbEhlaWdodCk7XG4gICAgICAgIHRoaXMucGl4ZWxzVG9TaGF2ZSA9IDA7XG4gICAgICAgIHRoaXMuc2V0RGl2U3RyZXRjaE9mZnNldCgwKTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLnNldERpdlN0cmV0Y2hPZmZzZXQgPSBmdW5jdGlvbiAobmV3T2Zmc2V0KSB7XG4gICAgICAgIC8vIGJlY2F1c2Ugd2UgYXJlIHRhbGtpbmcgcGl4ZWxzLCBubyBwb2ludCBpbiBjb25mdXNpbmcgdGhpbmdzIHdpdGggaGFsZiBudW1iZXJzXG4gICAgICAgIHZhciBuZXdPZmZzZXRGbG9vciA9IHR5cGVvZiBuZXdPZmZzZXQgPT09ICdudW1iZXInID8gTWF0aC5mbG9vcihuZXdPZmZzZXQpIDogbnVsbDtcbiAgICAgICAgaWYgKHRoaXMuZGl2U3RyZXRjaE9mZnNldCA9PT0gbmV3T2Zmc2V0Rmxvb3IpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpdlN0cmV0Y2hPZmZzZXQgPSBuZXdPZmZzZXRGbG9vcjtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh7IHR5cGU6IEV2ZW50cy5FVkVOVF9IRUlHSFRfU0NBTEVfQ0hBTkdFRCB9KTtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLnNldE1vZGVsSGVpZ2h0ID0gZnVuY3Rpb24gKG1vZGVsSGVpZ2h0KSB7XG4gICAgICAgIHRoaXMubW9kZWxIZWlnaHQgPSBtb2RlbEhlaWdodDtcbiAgICAgICAgdGhpcy5zdHJldGNoaW5nID0gbW9kZWxIZWlnaHQgIT0gbnVsbCAvLyBudWxsIGhhcHBlbnMgd2hlbiBpbiBwcmludCBsYXlvdXRcbiAgICAgICAgICAgICYmIHRoaXMubWF4RGl2SGVpZ2h0ID4gMFxuICAgICAgICAgICAgJiYgbW9kZWxIZWlnaHQgPiB0aGlzLm1heERpdkhlaWdodDtcbiAgICAgICAgaWYgKHRoaXMuc3RyZXRjaGluZykge1xuICAgICAgICAgICAgdGhpcy5jYWxjdWxhdGVPZmZzZXQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJPZmZzZXQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93Q29udGFpbmVySGVpZ2h0U2VydmljZS5wcm90b3R5cGUuZ2V0VWlDb250YWluZXJIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVpQ29udGFpbmVySGVpZ2h0O1xuICAgIH07XG4gICAgUm93Q29udGFpbmVySGVpZ2h0U2VydmljZS5wcm90b3R5cGUuZ2V0UmVhbFBpeGVsUG9zaXRpb24gPSBmdW5jdGlvbiAobW9kZWxQaXhlbCkge1xuICAgICAgICByZXR1cm4gbW9kZWxQaXhlbCAtIHRoaXMuZGl2U3RyZXRjaE9mZnNldDtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLmdldFVpQm9keUhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGdyaWRCb2R5Q29uID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0R3JpZEJvZHlDdHJsKCk7XG4gICAgICAgIHZhciBwb3MgPSBncmlkQm9keUNvbi5nZXRTY3JvbGxGZWF0dXJlKCkuZ2V0VlNjcm9sbFBvc2l0aW9uKCk7XG4gICAgICAgIHJldHVybiBwb3MuYm90dG9tIC0gcG9zLnRvcDtcbiAgICB9O1xuICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLmdldFNjcm9sbFBvc2l0aW9uRm9yUGl4ZWwgPSBmdW5jdGlvbiAocm93VG9wKSB7XG4gICAgICAgIGlmICh0aGlzLnBpeGVsc1RvU2hhdmUgPD0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHJvd1RvcDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbW9kZWxNYXhTY3JvbGwgPSB0aGlzLm1vZGVsSGVpZ2h0IC0gdGhpcy5nZXRVaUJvZHlIZWlnaHQoKTtcbiAgICAgICAgdmFyIHNjcm9sbFBlcmNlbnQgPSByb3dUb3AgLyBtb2RlbE1heFNjcm9sbDtcbiAgICAgICAgdmFyIHNjcm9sbFBpeGVsID0gdGhpcy5tYXhTY3JvbGxZICogc2Nyb2xsUGVyY2VudDtcbiAgICAgICAgcmV0dXJuIHNjcm9sbFBpeGVsO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRzKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkcyhbXG4gICAgICAgIF9fcGFyYW0kMSgwLCBRdWFsaWZpZXIoXCJsb2dnZXJGYWN0b3J5XCIpKVxuICAgIF0sIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UucHJvdG90eXBlLCBcImFnV2lyZVwiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlJHMoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93Q29udGFpbmVySGVpZ2h0U2VydmljZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICBSb3dDb250YWluZXJIZWlnaHRTZXJ2aWNlID0gX19kZWNvcmF0ZSRzKFtcbiAgICAgICAgQmVhbigncm93Q29udGFpbmVySGVpZ2h0U2VydmljZScpXG4gICAgXSwgUm93Q29udGFpbmVySGVpZ2h0U2VydmljZSk7XG4gICAgcmV0dXJuIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkcSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkciA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFNlbGVjdGFibGVTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRxKFNlbGVjdGFibGVTZXJ2aWNlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFNlbGVjdGFibGVTZXJ2aWNlKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFNlbGVjdGFibGVTZXJ2aWNlLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmdyb3VwU2VsZWN0c0NoaWxkcmVuID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFNlbGVjdHNDaGlsZHJlbigpO1xuICAgICAgICB0aGlzLmlzUm93U2VsZWN0YWJsZUZ1bmMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRJc1Jvd1NlbGVjdGFibGVGdW5jKCk7XG4gICAgfTtcbiAgICBTZWxlY3RhYmxlU2VydmljZS5wcm90b3R5cGUudXBkYXRlU2VsZWN0YWJsZUFmdGVyR3JvdXBpbmcgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICBpZiAodGhpcy5pc1Jvd1NlbGVjdGFibGVGdW5jKSB7XG4gICAgICAgICAgICB2YXIgbmV4dENoaWxkcmVuRnVuYyA9IGZ1bmN0aW9uIChub2RlKSB7IHJldHVybiBub2RlLmNoaWxkcmVuQWZ0ZXJHcm91cDsgfTtcbiAgICAgICAgICAgIHRoaXMucmVjdXJzZURvd24ocm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXAsIG5leHRDaGlsZHJlbkZ1bmMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTZWxlY3RhYmxlU2VydmljZS5wcm90b3R5cGUucmVjdXJzZURvd24gPSBmdW5jdGlvbiAoY2hpbGRyZW4sIG5leHRDaGlsZHJlbkZ1bmMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFjaGlsZHJlbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkcmVuLmZvckVhY2goZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICAgICAgICBpZiAoIWNoaWxkLmdyb3VwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSAvLyBvbmx5IGludGVyZXN0ZWQgaW4gZ3JvdXBzXG4gICAgICAgICAgICBpZiAoY2hpbGQuaGFzQ2hpbGRyZW4oKSkge1xuICAgICAgICAgICAgICAgIF90aGlzLnJlY3Vyc2VEb3duKG5leHRDaGlsZHJlbkZ1bmMoY2hpbGQpLCBuZXh0Q2hpbGRyZW5GdW5jKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciByb3dTZWxlY3RhYmxlO1xuICAgICAgICAgICAgaWYgKF90aGlzLmdyb3VwU2VsZWN0c0NoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gaGF2ZSB0aGlzIGdyb3VwIHNlbGVjdGFibGUgaWYgYXQgbGVhc3Qgb25lIGRpcmVjdCBjaGlsZCBpcyBzZWxlY3RhYmxlXG4gICAgICAgICAgICAgICAgdmFyIGZpcnN0U2VsZWN0YWJsZSA9IChuZXh0Q2hpbGRyZW5GdW5jKGNoaWxkKSB8fCBbXSkuZmluZChmdW5jdGlvbiAocm93Tm9kZSkgeyByZXR1cm4gcm93Tm9kZS5zZWxlY3RhYmxlID09PSB0cnVlOyB9KTtcbiAgICAgICAgICAgICAgICByb3dTZWxlY3RhYmxlID0gZXhpc3RzKGZpcnN0U2VsZWN0YWJsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBkaXJlY3RseSByZXRyaWV2ZSBzZWxlY3RhYmxlIHZhbHVlIGZyb20gdXNlciBjYWxsYmFja1xuICAgICAgICAgICAgICAgIHJvd1NlbGVjdGFibGUgPSBfdGhpcy5pc1Jvd1NlbGVjdGFibGVGdW5jID8gX3RoaXMuaXNSb3dTZWxlY3RhYmxlRnVuYyhjaGlsZCkgOiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoaWxkLnNldFJvd1NlbGVjdGFibGUocm93U2VsZWN0YWJsZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRyKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFNlbGVjdGFibGVTZXJ2aWNlLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIFNlbGVjdGFibGVTZXJ2aWNlID0gX19kZWNvcmF0ZSRyKFtcbiAgICAgICAgQmVhbignc2VsZWN0YWJsZVNlcnZpY2UnKVxuICAgIF0sIFNlbGVjdGFibGVTZXJ2aWNlKTtcbiAgICByZXR1cm4gU2VsZWN0YWJsZVNlcnZpY2U7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkcCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkcSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFBhZ2luYXRpb25Db21wID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRwKFBhZ2luYXRpb25Db21wLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIFBhZ2luYXRpb25Db21wKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wcmV2aW91c0FuZEZpcnN0QnV0dG9uc0Rpc2FibGVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLm5leHRCdXR0b25EaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5sYXN0QnV0dG9uRGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBQYWdpbmF0aW9uQ29tcC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGlzUnRsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNFbmFibGVSdGwoKTtcbiAgICAgICAgdGhpcy5zZXRUZW1wbGF0ZSh0aGlzLmdldFRlbXBsYXRlKCkpO1xuICAgICAgICB0aGlzLmJ0Rmlyc3QuaW5zZXJ0QWRqYWNlbnRFbGVtZW50KCdhZnRlcmJlZ2luJywgY3JlYXRlSWNvbk5vU3Bhbihpc1J0bCA/ICdsYXN0JyA6ICdmaXJzdCcsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyKSk7XG4gICAgICAgIHRoaXMuYnRQcmV2aW91cy5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyYmVnaW4nLCBjcmVhdGVJY29uTm9TcGFuKGlzUnRsID8gJ25leHQnIDogJ3ByZXZpb3VzJywgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIpKTtcbiAgICAgICAgdGhpcy5idE5leHQuaW5zZXJ0QWRqYWNlbnRFbGVtZW50KCdhZnRlcmJlZ2luJywgY3JlYXRlSWNvbk5vU3Bhbihpc1J0bCA/ICdwcmV2aW91cycgOiAnbmV4dCcsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyKSk7XG4gICAgICAgIHRoaXMuYnRMYXN0Lmluc2VydEFkamFjZW50RWxlbWVudCgnYWZ0ZXJiZWdpbicsIGNyZWF0ZUljb25Ob1NwYW4oaXNSdGwgPyAnZmlyc3QnIDogJ2xhc3QnLCB0aGlzLmdyaWRPcHRpb25zV3JhcHBlcikpO1xuICAgICAgICB2YXIgaXNQYWdpbmcgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1BhZ2luYXRpb24oKTtcbiAgICAgICAgdmFyIHBhZ2luYXRpb25QYW5lbEVuYWJsZWQgPSBpc1BhZ2luZyAmJiAhdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc1BhZ2luYXRpb25QYW5lbCgpO1xuICAgICAgICBpZiAoIXBhZ2luYXRpb25QYW5lbEVuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0RGlzcGxheWVkKGZhbHNlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BBR0lOQVRJT05fQ0hBTkdFRCwgdGhpcy5vblBhZ2luYXRpb25DaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICBbXG4gICAgICAgICAgICB7IGVsOiB0aGlzLmJ0Rmlyc3QsIGZuOiB0aGlzLm9uQnRGaXJzdC5iaW5kKHRoaXMpIH0sXG4gICAgICAgICAgICB7IGVsOiB0aGlzLmJ0UHJldmlvdXMsIGZuOiB0aGlzLm9uQnRQcmV2aW91cy5iaW5kKHRoaXMpIH0sXG4gICAgICAgICAgICB7IGVsOiB0aGlzLmJ0TmV4dCwgZm46IHRoaXMub25CdE5leHQuYmluZCh0aGlzKSB9LFxuICAgICAgICAgICAgeyBlbDogdGhpcy5idExhc3QsIGZuOiB0aGlzLm9uQnRMYXN0LmJpbmQodGhpcykgfVxuICAgICAgICBdLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICAgIHZhciBlbCA9IGl0ZW0uZWwsIGZuID0gaXRlbS5mbjtcbiAgICAgICAgICAgIF90aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcihlbCwgJ2NsaWNrJywgZm4pO1xuICAgICAgICAgICAgX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKGVsLCAna2V5ZG93bicsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGUua2V5ID09PSBLZXlDb2RlLkVOVEVSIHx8IGUua2V5ID09PSBLZXlDb2RlLlNQQUNFKSB7XG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMub25QYWdpbmF0aW9uQ2hhbmdlZCgpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLm9uUGFnaW5hdGlvbkNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZW5hYmxlT3JEaXNhYmxlQnV0dG9ucygpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJvd0xhYmVscygpO1xuICAgICAgICB0aGlzLnNldEN1cnJlbnRQYWdlTGFiZWwoKTtcbiAgICAgICAgdGhpcy5zZXRUb3RhbExhYmVscygpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLm9uQnRGaXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnByZXZpb3VzQW5kRmlyc3RCdXR0b25zRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMucGFnaW5hdGlvblByb3h5LmdvVG9GaXJzdFBhZ2UoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLnNldEN1cnJlbnRQYWdlTGFiZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwYWdlc0V4aXN0ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0VG90YWxQYWdlcygpID4gMDtcbiAgICAgICAgdmFyIGN1cnJlbnRQYWdlID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Q3VycmVudFBhZ2UoKTtcbiAgICAgICAgdmFyIHRvRGlzcGxheSA9IHBhZ2VzRXhpc3QgPyBjdXJyZW50UGFnZSArIDEgOiAwO1xuICAgICAgICB0aGlzLmxiQ3VycmVudC5pbm5lckhUTUwgPSB0aGlzLmZvcm1hdE51bWJlcih0b0Rpc3BsYXkpO1xuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLmZvcm1hdE51bWJlciA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgdXNlckZ1bmMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRQYWdpbmF0aW9uTnVtYmVyRm9ybWF0dGVyRnVuYygpO1xuICAgICAgICBpZiAodXNlckZ1bmMpIHtcbiAgICAgICAgICAgIHZhciBwYXJhbXMgPSB7IHZhbHVlOiB2YWx1ZSB9O1xuICAgICAgICAgICAgcmV0dXJuIHVzZXJGdW5jKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxvY2FsZVRleHRGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIHRob3VzYW5kU2VwYXJhdG9yID0gbG9jYWxlVGV4dEZ1bmMoJ3Rob3VzYW5kU2VwYXJhdG9yJywgJywnKTtcbiAgICAgICAgdmFyIGRlY2ltYWxTZXBhcmF0b3IgPSBsb2NhbGVUZXh0RnVuYygnZGVjaW1hbFNlcGFyYXRvcicsICcuJyk7XG4gICAgICAgIHJldHVybiBmb3JtYXROdW1iZXJDb21tYXModmFsdWUsIHRob3VzYW5kU2VwYXJhdG9yLCBkZWNpbWFsU2VwYXJhdG9yKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZS5nZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGxvY2FsZVRleHRGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKTtcbiAgICAgICAgdmFyIHN0clBhZ2UgPSBsb2NhbGVUZXh0RnVuYygncGFnZScsICdQYWdlJyk7XG4gICAgICAgIHZhciBzdHJUbyA9IGxvY2FsZVRleHRGdW5jKCd0bycsICd0bycpO1xuICAgICAgICB2YXIgc3RyT2YgPSBsb2NhbGVUZXh0RnVuYygnb2YnLCAnb2YnKTtcbiAgICAgICAgdmFyIHN0ckZpcnN0ID0gbG9jYWxlVGV4dEZ1bmMoJ2ZpcnN0UGFnZScsICdGaXJzdCBQYWdlJyk7XG4gICAgICAgIHZhciBzdHJQcmV2aW91cyA9IGxvY2FsZVRleHRGdW5jKCdwcmV2aW91c1BhZ2UnLCAnUHJldmlvdXMgUGFnZScpO1xuICAgICAgICB2YXIgc3RyTmV4dCA9IGxvY2FsZVRleHRGdW5jKCduZXh0UGFnZScsICdOZXh0IFBhZ2UnKTtcbiAgICAgICAgdmFyIHN0ckxhc3QgPSBsb2NhbGVUZXh0RnVuYygnbGFzdFBhZ2UnLCAnTGFzdCBQYWdlJyk7XG4gICAgICAgIHZhciBjb21wSWQgPSB0aGlzLmdldENvbXBJZCgpO1xuICAgICAgICByZXR1cm4gLyogaHRtbCAqLyBcIjxkaXYgY2xhc3M9XFxcImFnLXBhZ2luZy1wYW5lbCBhZy11bnNlbGVjdGFibGVcXFwiIGlkPVxcXCJhZy1cIiArIGNvbXBJZCArIFwiXFxcIj5cXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImFnLXBhZ2luZy1yb3ctc3VtbWFyeS1wYW5lbFxcXCIgcm9sZT1cXFwic3RhdHVzXFxcIj5cXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGlkPVxcXCJhZy1cIiArIGNvbXBJZCArIFwiLWZpcnN0LXJvd1xcXCIgcmVmPVxcXCJsYkZpcnN0Um93T25QYWdlXFxcIiBjbGFzcz1cXFwiYWctcGFnaW5nLXJvdy1zdW1tYXJ5LXBhbmVsLW51bWJlclxcXCI+PC9zcGFuPlxcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gaWQ9XFxcImFnLVwiICsgY29tcElkICsgXCItdG9cXFwiPlwiICsgc3RyVG8gKyBcIjwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGlkPVxcXCJhZy1cIiArIGNvbXBJZCArIFwiLWxhc3Qtcm93XFxcIiByZWY9XFxcImxiTGFzdFJvd09uUGFnZVxcXCIgY2xhc3M9XFxcImFnLXBhZ2luZy1yb3ctc3VtbWFyeS1wYW5lbC1udW1iZXJcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGlkPVxcXCJhZy1cIiArIGNvbXBJZCArIFwiLW9mXFxcIj5cIiArIHN0ck9mICsgXCI8L3NwYW4+XFxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBpZD1cXFwiYWctXCIgKyBjb21wSWQgKyBcIi1yb3ctY291bnRcXFwiIHJlZj1cXFwibGJSZWNvcmRDb3VudFxcXCIgY2xhc3M9XFxcImFnLXBhZ2luZy1yb3ctc3VtbWFyeS1wYW5lbC1udW1iZXJcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgPC9zcGFuPlxcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwiYWctcGFnaW5nLXBhZ2Utc3VtbWFyeS1wYW5lbFxcXCIgcm9sZT1cXFwicHJlc2VudGF0aW9uXFxcIj5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJidEZpcnN0XFxcIiBjbGFzcz1cXFwiYWctcGFnaW5nLWJ1dHRvblxcXCIgcm9sZT1cXFwiYnV0dG9uXFxcIiBhcmlhLWxhYmVsPVxcXCJcIiArIHN0ckZpcnN0ICsgXCJcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgICAgICAgICAgPGRpdiByZWY9XFxcImJ0UHJldmlvdXNcXFwiIGNsYXNzPVxcXCJhZy1wYWdpbmctYnV0dG9uXFxcIiByb2xlPVxcXCJidXR0b25cXFwiIGFyaWEtbGFiZWw9XFxcIlwiICsgc3RyUHJldmlvdXMgKyBcIlxcXCI+PC9kaXY+XFxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwiYWctcGFnaW5nLWRlc2NyaXB0aW9uXFxcIiByb2xlPVxcXCJzdGF0dXNcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGlkPVxcXCJhZy1cIiArIGNvbXBJZCArIFwiLXN0YXJ0LXBhZ2VcXFwiPlwiICsgc3RyUGFnZSArIFwiPC9zcGFuPlxcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGlkPVxcXCJhZy1cIiArIGNvbXBJZCArIFwiLXN0YXJ0LXBhZ2UtbnVtYmVyXFxcIiByZWY9XFxcImxiQ3VycmVudFxcXCIgY2xhc3M9XFxcImFnLXBhZ2luZy1udW1iZXJcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBpZD1cXFwiYWctXCIgKyBjb21wSWQgKyBcIi1vZi1wYWdlXFxcIj5cIiArIHN0ck9mICsgXCI8L3NwYW4+XFxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gaWQ9XFxcImFnLVwiICsgY29tcElkICsgXCItb2YtcGFnZS1udW1iZXJcXFwiIHJlZj1cXFwibGJUb3RhbFxcXCIgY2xhc3M9XFxcImFnLXBhZ2luZy1udW1iZXJcXFwiPjwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJidE5leHRcXFwiIGNsYXNzPVxcXCJhZy1wYWdpbmctYnV0dG9uXFxcIiByb2xlPVxcXCJidXR0b25cXFwiIGFyaWEtbGFiZWw9XFxcIlwiICsgc3RyTmV4dCArIFwiXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgcmVmPVxcXCJidExhc3RcXFwiIGNsYXNzPVxcXCJhZy1wYWdpbmctYnV0dG9uXFxcIiByb2xlPVxcXCJidXR0b25cXFwiIGFyaWEtbGFiZWw9XFxcIlwiICsgc3RyTGFzdCArIFwiXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICAgICAgPC9zcGFuPlxcbiAgICAgICAgICAgIDwvZGl2PlwiO1xuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLm9uQnROZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMubmV4dEJ1dHRvbkRpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnBhZ2luYXRpb25Qcm94eS5nb1RvTmV4dFBhZ2UoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLm9uQnRQcmV2aW91cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnByZXZpb3VzQW5kRmlyc3RCdXR0b25zRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMucGFnaW5hdGlvblByb3h5LmdvVG9QcmV2aW91c1BhZ2UoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLm9uQnRMYXN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMubGFzdEJ1dHRvbkRpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnBhZ2luYXRpb25Qcm94eS5nb1RvTGFzdFBhZ2UoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLmVuYWJsZU9yRGlzYWJsZUJ1dHRvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjdXJyZW50UGFnZSA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldEN1cnJlbnRQYWdlKCk7XG4gICAgICAgIHZhciBtYXhSb3dGb3VuZCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmlzTGFzdFBhZ2VGb3VuZCgpO1xuICAgICAgICB2YXIgdG90YWxQYWdlcyA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFRvdGFsUGFnZXMoKTtcbiAgICAgICAgdGhpcy5wcmV2aW91c0FuZEZpcnN0QnV0dG9uc0Rpc2FibGVkID0gY3VycmVudFBhZ2UgPT09IDA7XG4gICAgICAgIHRoaXMudG9nZ2xlQnV0dG9uRGlzYWJsZWQodGhpcy5idEZpcnN0LCB0aGlzLnByZXZpb3VzQW5kRmlyc3RCdXR0b25zRGlzYWJsZWQpO1xuICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbkRpc2FibGVkKHRoaXMuYnRQcmV2aW91cywgdGhpcy5wcmV2aW91c0FuZEZpcnN0QnV0dG9uc0Rpc2FibGVkKTtcbiAgICAgICAgdmFyIHplcm9QYWdlc1RvRGlzcGxheSA9IHRoaXMuaXNaZXJvUGFnZXNUb0Rpc3BsYXkoKTtcbiAgICAgICAgdmFyIG9uTGFzdFBhZ2UgPSBtYXhSb3dGb3VuZCAmJiBjdXJyZW50UGFnZSA9PT0gKHRvdGFsUGFnZXMgLSAxKTtcbiAgICAgICAgdGhpcy5uZXh0QnV0dG9uRGlzYWJsZWQgPSBvbkxhc3RQYWdlIHx8IHplcm9QYWdlc1RvRGlzcGxheTtcbiAgICAgICAgdGhpcy5sYXN0QnV0dG9uRGlzYWJsZWQgPSAhbWF4Um93Rm91bmQgfHwgemVyb1BhZ2VzVG9EaXNwbGF5IHx8IGN1cnJlbnRQYWdlID09PSAodG90YWxQYWdlcyAtIDEpO1xuICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbkRpc2FibGVkKHRoaXMuYnROZXh0LCB0aGlzLm5leHRCdXR0b25EaXNhYmxlZCk7XG4gICAgICAgIHRoaXMudG9nZ2xlQnV0dG9uRGlzYWJsZWQodGhpcy5idExhc3QsIHRoaXMubGFzdEJ1dHRvbkRpc2FibGVkKTtcbiAgICB9O1xuICAgIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZS50b2dnbGVCdXR0b25EaXNhYmxlZCA9IGZ1bmN0aW9uIChidXR0b24sIGRpc2FibGVkKSB7XG4gICAgICAgIHNldEFyaWFEaXNhYmxlZChidXR0b24sIGRpc2FibGVkKTtcbiAgICAgICAgYnV0dG9uLmNsYXNzTGlzdC50b2dnbGUoJ2FnLWRpc2FibGVkJywgZGlzYWJsZWQpO1xuICAgICAgICBpZiAoZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGJ1dHRvbi5yZW1vdmVBdHRyaWJ1dGUoJ3RhYmluZGV4Jyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBidXR0b24uc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICcwJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZS51cGRhdGVSb3dMYWJlbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjdXJyZW50UGFnZSA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldEN1cnJlbnRQYWdlKCk7XG4gICAgICAgIHZhciBwYWdlU2l6ZSA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFBhZ2VTaXplKCk7XG4gICAgICAgIHZhciBtYXhSb3dGb3VuZCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmlzTGFzdFBhZ2VGb3VuZCgpO1xuICAgICAgICB2YXIgcm93Q291bnQgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5pc0xhc3RQYWdlRm91bmQoKSA/XG4gICAgICAgICAgICB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRNYXN0ZXJSb3dDb3VudCgpIDogbnVsbDtcbiAgICAgICAgdmFyIHN0YXJ0Um93O1xuICAgICAgICB2YXIgZW5kUm93O1xuICAgICAgICBpZiAodGhpcy5pc1plcm9QYWdlc1RvRGlzcGxheSgpKSB7XG4gICAgICAgICAgICBzdGFydFJvdyA9IGVuZFJvdyA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzdGFydFJvdyA9IChwYWdlU2l6ZSAqIGN1cnJlbnRQYWdlKSArIDE7XG4gICAgICAgICAgICBlbmRSb3cgPSBzdGFydFJvdyArIHBhZ2VTaXplIC0gMTtcbiAgICAgICAgICAgIGlmIChtYXhSb3dGb3VuZCAmJiBlbmRSb3cgPiByb3dDb3VudCkge1xuICAgICAgICAgICAgICAgIGVuZFJvdyA9IHJvd0NvdW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubGJGaXJzdFJvd09uUGFnZS5pbm5lckhUTUwgPSB0aGlzLmZvcm1hdE51bWJlcihzdGFydFJvdyk7XG4gICAgICAgIGlmICh0aGlzLnJvd05vZGVCbG9ja0xvYWRlci5pc0xvYWRpbmcoKSkge1xuICAgICAgICAgICAgdGhpcy5sYkxhc3RSb3dPblBhZ2UuaW5uZXJIVE1MID0gJz8nO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sYkxhc3RSb3dPblBhZ2UuaW5uZXJIVE1MID0gdGhpcy5mb3JtYXROdW1iZXIoZW5kUm93KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLmlzWmVyb1BhZ2VzVG9EaXNwbGF5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWF4Um93Rm91bmQgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5pc0xhc3RQYWdlRm91bmQoKTtcbiAgICAgICAgdmFyIHRvdGFsUGFnZXMgPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRUb3RhbFBhZ2VzKCk7XG4gICAgICAgIHJldHVybiBtYXhSb3dGb3VuZCAmJiB0b3RhbFBhZ2VzID09PSAwO1xuICAgIH07XG4gICAgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLnNldFRvdGFsTGFiZWxzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbGFzdFBhZ2VGb3VuZCA9IHRoaXMucGFnaW5hdGlvblByb3h5LmlzTGFzdFBhZ2VGb3VuZCgpO1xuICAgICAgICB2YXIgdG90YWxQYWdlcyA9IHRoaXMucGFnaW5hdGlvblByb3h5LmdldFRvdGFsUGFnZXMoKTtcbiAgICAgICAgdmFyIHJvd0NvdW50ID0gbGFzdFBhZ2VGb3VuZCA/IHRoaXMucGFnaW5hdGlvblByb3h5LmdldE1hc3RlclJvd0NvdW50KCkgOiBudWxsO1xuICAgICAgICAvLyBXaGVuIGBwaXZvdE1vZGU9dHJ1ZWAgYW5kIG5vIGdyb3VwaW5nIG9yIHZhbHVlIGNvbHVtbnMgZXhpc3QsIGEgc2luZ2xlICdoaWRkZW4nIGdyb3VwIHJvdyAocm9vdCBub2RlKSBpcyBpblxuICAgICAgICAvLyB0aGUgZ3JpZCBhbmQgdGhlIHBhZ2luYXRpb24gdG90YWxzIHdpbGwgY29ycmVjdGx5IGRpc3BsYXkgdG90YWwgPSAxLiBIb3dldmVyIHRoaXMgaXMgY29uZnVzaW5nIHRvIHVzZXJzIGFzXG4gICAgICAgIC8vIHRoZXkgY2FuJ3Qgc2VlIGl0LiBUbyBhZGRyZXNzIHRoaXMgVVggaXNzdWUgd2Ugc2ltcGx5IHNldCB0aGUgdG90YWxzIHRvIHplcm8gaW4gdGhlIHBhZ2luYXRpb24gcGFuZWwuXG4gICAgICAgIGlmIChyb3dDb3VudCA9PT0gMSkge1xuICAgICAgICAgICAgdmFyIGZpcnN0Um93ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuZ2V0Um93KDApO1xuICAgICAgICAgICAgLy8gYSBncm91cCBub2RlIHdpdGggbm8gZ3JvdXAgb3IgYWdnIGRhdGEgd2lsbCBub3QgYmUgdmlzaWJsZSB0byB1c2Vyc1xuICAgICAgICAgICAgdmFyIGhpZGRlbkdyb3VwUm93ID0gZmlyc3RSb3cgJiYgZmlyc3RSb3cuZ3JvdXAgJiYgIShmaXJzdFJvdy5ncm91cERhdGEgfHwgZmlyc3RSb3cuYWdnRGF0YSk7XG4gICAgICAgICAgICBpZiAoaGlkZGVuR3JvdXBSb3cpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFRvdGFsTGFiZWxzVG9aZXJvKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChsYXN0UGFnZUZvdW5kKSB7XG4gICAgICAgICAgICB0aGlzLmxiVG90YWwuaW5uZXJIVE1MID0gdGhpcy5mb3JtYXROdW1iZXIodG90YWxQYWdlcyk7XG4gICAgICAgICAgICB0aGlzLmxiUmVjb3JkQ291bnQuaW5uZXJIVE1MID0gdGhpcy5mb3JtYXROdW1iZXIocm93Q291bnQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIG1vcmVUZXh0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0TG9jYWxlVGV4dEZ1bmMoKSgnbW9yZScsICdtb3JlJyk7XG4gICAgICAgICAgICB0aGlzLmxiVG90YWwuaW5uZXJIVE1MID0gbW9yZVRleHQ7XG4gICAgICAgICAgICB0aGlzLmxiUmVjb3JkQ291bnQuaW5uZXJIVE1MID0gbW9yZVRleHQ7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZS5zZXRUb3RhbExhYmVsc1RvWmVybyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5sYkZpcnN0Um93T25QYWdlLmlubmVySFRNTCA9IHRoaXMuZm9ybWF0TnVtYmVyKDApO1xuICAgICAgICB0aGlzLmxiQ3VycmVudC5pbm5lckhUTUwgPSB0aGlzLmZvcm1hdE51bWJlcigwKTtcbiAgICAgICAgdGhpcy5sYkxhc3RSb3dPblBhZ2UuaW5uZXJIVE1MID0gdGhpcy5mb3JtYXROdW1iZXIoMCk7XG4gICAgICAgIHRoaXMubGJUb3RhbC5pbm5lckhUTUwgPSB0aGlzLmZvcm1hdE51bWJlcigwKTtcbiAgICAgICAgdGhpcy5sYlJlY29yZENvdW50LmlubmVySFRNTCA9IHRoaXMuZm9ybWF0TnVtYmVyKDApO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRxKFtcbiAgICAgICAgQXV0b3dpcmVkKCdwYWdpbmF0aW9uUHJveHknKVxuICAgIF0sIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZSwgXCJwYWdpbmF0aW9uUHJveHlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJHEoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd05vZGVCbG9ja0xvYWRlcicpXG4gICAgXSwgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLCBcInJvd05vZGVCbG9ja0xvYWRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkcShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdidEZpcnN0JylcbiAgICBdLCBQYWdpbmF0aW9uQ29tcC5wcm90b3R5cGUsIFwiYnRGaXJzdFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkcShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdidFByZXZpb3VzJylcbiAgICBdLCBQYWdpbmF0aW9uQ29tcC5wcm90b3R5cGUsIFwiYnRQcmV2aW91c1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkcShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdidE5leHQnKVxuICAgIF0sIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZSwgXCJidE5leHRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJHEoW1xuICAgICAgICBSZWZTZWxlY3RvcignYnRMYXN0JylcbiAgICBdLCBQYWdpbmF0aW9uQ29tcC5wcm90b3R5cGUsIFwiYnRMYXN0XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRxKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2xiUmVjb3JkQ291bnQnKVxuICAgIF0sIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZSwgXCJsYlJlY29yZENvdW50XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRxKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2xiRmlyc3RSb3dPblBhZ2UnKVxuICAgIF0sIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZSwgXCJsYkZpcnN0Um93T25QYWdlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRxKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2xiTGFzdFJvd09uUGFnZScpXG4gICAgXSwgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLCBcImxiTGFzdFJvd09uUGFnZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkcShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdsYkN1cnJlbnQnKVxuICAgIF0sIFBhZ2luYXRpb25Db21wLnByb3RvdHlwZSwgXCJsYkN1cnJlbnRcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJHEoW1xuICAgICAgICBSZWZTZWxlY3RvcignbGJUb3RhbCcpXG4gICAgXSwgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLCBcImxiVG90YWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJHEoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUGFnaW5hdGlvbkNvbXAucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIFBhZ2luYXRpb25Db21wO1xufShDb21wb25lbnQpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRvID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRwID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgTG9hZGluZ1R5cGU7XG4oZnVuY3Rpb24gKExvYWRpbmdUeXBlKSB7XG4gICAgTG9hZGluZ1R5cGVbTG9hZGluZ1R5cGVbXCJMb2FkaW5nXCJdID0gMF0gPSBcIkxvYWRpbmdcIjtcbiAgICBMb2FkaW5nVHlwZVtMb2FkaW5nVHlwZVtcIk5vUm93c1wiXSA9IDFdID0gXCJOb1Jvd3NcIjtcbn0pKExvYWRpbmdUeXBlIHx8IChMb2FkaW5nVHlwZSA9IHt9KSk7XG52YXIgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJG8oT3ZlcmxheVdyYXBwZXJDb21wb25lbnQsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gT3ZlcmxheVdyYXBwZXJDb21wb25lbnQoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIE92ZXJsYXlXcmFwcGVyQ29tcG9uZW50LlRFTVBMQVRFKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5pblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmRlc3Ryb3lSZXF1ZXN0ZWQgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMubWFudWFsbHlEaXNwbGF5ZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUudXBkYXRlTGF5b3V0Q2xhc3NlcyA9IGZ1bmN0aW9uIChjc3NDbGFzcywgcGFyYW1zKSB7XG4gICAgICAgIHZhciBvdmVybGF5V3JhcHBlckNsYXNzTGlzdCA9IHRoaXMuZU92ZXJsYXlXcmFwcGVyLmNsYXNzTGlzdDtcbiAgICAgICAgb3ZlcmxheVdyYXBwZXJDbGFzc0xpc3QudG9nZ2xlKExheW91dENzc0NsYXNzZXMuQVVUT19IRUlHSFQsIHBhcmFtcy5hdXRvSGVpZ2h0KTtcbiAgICAgICAgb3ZlcmxheVdyYXBwZXJDbGFzc0xpc3QudG9nZ2xlKExheW91dENzc0NsYXNzZXMuTk9STUFMLCBwYXJhbXMubm9ybWFsKTtcbiAgICAgICAgb3ZlcmxheVdyYXBwZXJDbGFzc0xpc3QudG9nZ2xlKExheW91dENzc0NsYXNzZXMuUFJJTlQsIHBhcmFtcy5wcmludCk7XG4gICAgfTtcbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgTGF5b3V0RmVhdHVyZSh0aGlzKSk7XG4gICAgICAgIHRoaXMuc2V0RGlzcGxheWVkKGZhbHNlKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ST1dfREFUQV9VUERBVEVELCB0aGlzLm9uUm93RGF0YVVwZGF0ZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTkVXX0NPTFVNTlNfTE9BREVELCB0aGlzLm9uTmV3Q29sdW1uc0xvYWRlZC5iaW5kKHRoaXMpKTtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzUm93TW9kZWxEZWZhdWx0KCkgJiYgIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0RhdGEoKSkge1xuICAgICAgICAgICAgdGhpcy5zaG93TG9hZGluZ092ZXJsYXkoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdyaWRBcGkucmVnaXN0ZXJPdmVybGF5V3JhcHBlckNvbXAodGhpcyk7XG4gICAgfTtcbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUuc2V0V3JhcHBlclR5cGVDbGFzcyA9IGZ1bmN0aW9uIChsb2FkaW5nVHlwZSkge1xuICAgICAgICB2YXIgb3ZlcmxheVdyYXBwZXJDbGFzc0xpc3QgPSB0aGlzLmVPdmVybGF5V3JhcHBlci5jbGFzc0xpc3Q7XG4gICAgICAgIG92ZXJsYXlXcmFwcGVyQ2xhc3NMaXN0LnRvZ2dsZSgnYWctb3ZlcmxheS1sb2FkaW5nLXdyYXBwZXInLCBsb2FkaW5nVHlwZSA9PT0gTG9hZGluZ1R5cGUuTG9hZGluZyk7XG4gICAgICAgIG92ZXJsYXlXcmFwcGVyQ2xhc3NMaXN0LnRvZ2dsZSgnYWctb3ZlcmxheS1uby1yb3dzLXdyYXBwZXInLCBsb2FkaW5nVHlwZSA9PT0gTG9hZGluZ1R5cGUuTm9Sb3dzKTtcbiAgICB9O1xuICAgIE92ZXJsYXlXcmFwcGVyQ29tcG9uZW50LnByb3RvdHlwZS5zaG93TG9hZGluZ092ZXJsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTG9hZGluZ092ZXJsYXkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwYXJhbXMgPSB7fTtcbiAgICAgICAgdmFyIGNvbXBEZXRhaWxzID0gdGhpcy51c2VyQ29tcG9uZW50RmFjdG9yeS5nZXRMb2FkaW5nT3ZlcmxheUNvbXBEZXRhaWxzKHBhcmFtcyk7XG4gICAgICAgIHZhciBwcm9taXNlID0gY29tcERldGFpbHMubmV3QWdTdGFja0luc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuc2hvd092ZXJsYXkocHJvbWlzZSwgTG9hZGluZ1R5cGUuTG9hZGluZyk7XG4gICAgfTtcbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUuc2hvd05vUm93c092ZXJsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTm9Sb3dzT3ZlcmxheSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHBhcmFtcyA9IHt9O1xuICAgICAgICB2YXIgY29tcERldGFpbHMgPSB0aGlzLnVzZXJDb21wb25lbnRGYWN0b3J5LmdldE5vUm93c092ZXJsYXlDb21wRGV0YWlscyhwYXJhbXMpO1xuICAgICAgICB2YXIgcHJvbWlzZSA9IGNvbXBEZXRhaWxzLm5ld0FnU3RhY2tJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLnNob3dPdmVybGF5KHByb21pc2UsIExvYWRpbmdUeXBlLk5vUm93cyk7XG4gICAgfTtcbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUuc2hvd092ZXJsYXkgPSBmdW5jdGlvbiAod29ya0l0ZW0sIHR5cGUpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuaW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0V3JhcHBlclR5cGVDbGFzcyh0eXBlKTtcbiAgICAgICAgdGhpcy5kZXN0cm95QWN0aXZlT3ZlcmxheSgpO1xuICAgICAgICB0aGlzLmluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICBpZiAod29ya0l0ZW0pIHtcbiAgICAgICAgICAgIHdvcmtJdGVtLnRoZW4oZnVuY3Rpb24gKGNvbXApIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5pblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgX3RoaXMuZU92ZXJsYXlXcmFwcGVyLmFwcGVuZENoaWxkKGNvbXAuZ2V0R3VpKCkpO1xuICAgICAgICAgICAgICAgIF90aGlzLmFjdGl2ZU92ZXJsYXkgPSBjb21wO1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5kZXN0cm95UmVxdWVzdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmRlc3Ryb3lSZXF1ZXN0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuZGVzdHJveUFjdGl2ZU92ZXJsYXkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1hbnVhbGx5RGlzcGxheWVkID0gdGhpcy5jb2x1bW5Nb2RlbC5pc1JlYWR5KCkgJiYgIXRoaXMucGFnaW5hdGlvblByb3h5LmlzRW1wdHkoKTtcbiAgICAgICAgdGhpcy5zZXREaXNwbGF5ZWQodHJ1ZSk7XG4gICAgfTtcbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUuZGVzdHJveUFjdGl2ZU92ZXJsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuZGVzdHJveVJlcXVlc3RlZCA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmFjdGl2ZU92ZXJsYXkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdGl2ZU92ZXJsYXkgPSB0aGlzLmdldENvbnRleHQoKS5kZXN0cm95QmVhbih0aGlzLmFjdGl2ZU92ZXJsYXkpO1xuICAgICAgICBjbGVhckVsZW1lbnQodGhpcy5lT3ZlcmxheVdyYXBwZXIpO1xuICAgIH07XG4gICAgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQucHJvdG90eXBlLmhpZGVPdmVybGF5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm1hbnVhbGx5RGlzcGxheWVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZGVzdHJveUFjdGl2ZU92ZXJsYXkoKTtcbiAgICAgICAgdGhpcy5zZXREaXNwbGF5ZWQoZmFsc2UpO1xuICAgIH07XG4gICAgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveUFjdGl2ZU92ZXJsYXkoKTtcbiAgICAgICAgX3N1cGVyLnByb3RvdHlwZS5kZXN0cm95LmNhbGwodGhpcyk7XG4gICAgfTtcbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUuc2hvd09ySGlkZU92ZXJsYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpc0VtcHR5ID0gdGhpcy5wYWdpbmF0aW9uUHJveHkuaXNFbXB0eSgpO1xuICAgICAgICB2YXIgaXNTdXBwcmVzc05vUm93c092ZXJsYXkgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTm9Sb3dzT3ZlcmxheSgpO1xuICAgICAgICBpZiAoaXNFbXB0eSAmJiAhaXNTdXBwcmVzc05vUm93c092ZXJsYXkpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd05vUm93c092ZXJsYXkoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZU92ZXJsYXkoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQucHJvdG90eXBlLm9uUm93RGF0YVVwZGF0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2hvd09ySGlkZU92ZXJsYXkoKTtcbiAgICB9O1xuICAgIE92ZXJsYXlXcmFwcGVyQ29tcG9uZW50LnByb3RvdHlwZS5vbk5ld0NvbHVtbnNMb2FkZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGhpZGUgb3ZlcmxheSBpZiBjb2x1bW5zIGFuZCByb3dzIGV4aXN0LCB0aGlzIGNhbiBoYXBwZW4gaWYgY29sdW1ucyBhcmUgbG9hZGVkIGFmdGVyIGRhdGEuXG4gICAgICAgIC8vIHRoaXMgcHJvYmxlbSBleGlzdHMgYmVmb3JlIG9mIHRoZSByYWNlIGNvbmRpdGlvbiBiZXR3ZWVuIHRoZSBzZXJ2aWNlcyAoY29sdW1uIGNvbnRyb2xsZXIgaW4gdGhpcyBjYXNlKVxuICAgICAgICAvLyBhbmQgdGhlIHZpZXcgKGdyaWQgcGFuZWwpLiBpZiB0aGUgbW9kZWwgYmVhbnMgd2VyZSBhbGwgaW5pdGlhbGlzZWQgZmlyc3QsIGFuZCB0aGVuIHRoZSB2aWV3IGJlYW5zIHNlY29uZCxcbiAgICAgICAgLy8gdGhpcyByYWNlIGNvbmRpdGlvbiB3b3VsZCBub3QgaGFwcGVuLlxuICAgICAgICBpZiAodGhpcy5jb2x1bW5Nb2RlbC5pc1JlYWR5KCkgJiYgIXRoaXMucGFnaW5hdGlvblByb3h5LmlzRW1wdHkoKSAmJiAhdGhpcy5tYW51YWxseURpc3BsYXllZCkge1xuICAgICAgICAgICAgdGhpcy5oaWRlT3ZlcmxheSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyB3cmFwcGluZyBpbiBvdXRlciBkaXYsIGFuZCB3cmFwcGVyLCBpcyBuZWVkZWQgdG8gY2VudGVyIHRoZSBsb2FkaW5nIGljb25cbiAgICAvLyBUaGUgaWRlYSBmb3IgY2VudGVyaW5nIGNhbWUgZnJvbSBoZXJlOiBodHRwOi8vd3d3LnZhbnNlb2Rlc2lnbi5jb20vY3NzL3ZlcnRpY2FsLWNlbnRlcmluZy9cbiAgICBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5URU1QTEFURSA9IFwiXFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1vdmVybGF5XFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiYWctb3ZlcmxheS1wYW5lbFxcXCI+XFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLW92ZXJsYXktd3JhcHBlclxcXCIgcmVmPVxcXCJlT3ZlcmxheVdyYXBwZXJcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgPC9kaXY+XCI7XG4gICAgX19kZWNvcmF0ZSRwKFtcbiAgICAgICAgQXV0b3dpcmVkKCd1c2VyQ29tcG9uZW50RmFjdG9yeScpXG4gICAgXSwgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQucHJvdG90eXBlLCBcInVzZXJDb21wb25lbnRGYWN0b3J5XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRwKFtcbiAgICAgICAgQXV0b3dpcmVkKCdwYWdpbmF0aW9uUHJveHknKVxuICAgIF0sIE92ZXJsYXlXcmFwcGVyQ29tcG9uZW50LnByb3RvdHlwZSwgXCJwYWdpbmF0aW9uUHJveHlcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJHAoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRBcGknKVxuICAgIF0sIE92ZXJsYXlXcmFwcGVyQ29tcG9uZW50LnByb3RvdHlwZSwgXCJncmlkQXBpXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRwKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRwKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VPdmVybGF5V3JhcHBlcicpXG4gICAgXSwgT3ZlcmxheVdyYXBwZXJDb21wb25lbnQucHJvdG90eXBlLCBcImVPdmVybGF5V3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkcChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBPdmVybGF5V3JhcHBlckNvbXBvbmVudC5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICByZXR1cm4gT3ZlcmxheVdyYXBwZXJDb21wb25lbnQ7XG59KENvbXBvbmVudCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19leHRlbmRzJG4gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJG8gPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBSb3dQb3NpdGlvblV0aWxzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRuKFJvd1Bvc2l0aW9uVXRpbHMsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUm93UG9zaXRpb25VdGlscygpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBSb3dQb3NpdGlvblV0aWxzLnByb3RvdHlwZS5nZXRGaXJzdFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd0luZGV4ID0gMDtcbiAgICAgICAgdmFyIHJvd1Bpbm5lZDtcbiAgICAgICAgaWYgKHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkVG9wUm93Q291bnQoKSkge1xuICAgICAgICAgICAgcm93UGlubmVkID0gQ29uc3RhbnRzLlBJTk5FRF9UT1A7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5yb3dNb2RlbC5nZXRSb3dDb3VudCgpKSB7XG4gICAgICAgICAgICByb3dQaW5uZWQgPSBudWxsO1xuICAgICAgICAgICAgcm93SW5kZXggPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlRmlyc3RSb3coKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnBpbm5lZFJvd01vZGVsLmdldFBpbm5lZEJvdHRvbVJvd0NvdW50KCkpIHtcbiAgICAgICAgICAgIHJvd1Bpbm5lZCA9IENvbnN0YW50cy5QSU5ORURfQk9UVE9NO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dQaW5uZWQgPT09IHVuZGVmaW5lZCA/IG51bGwgOiB7IHJvd0luZGV4OiByb3dJbmRleCwgcm93UGlubmVkOiByb3dQaW5uZWQgfTtcbiAgICB9O1xuICAgIFJvd1Bvc2l0aW9uVXRpbHMucHJvdG90eXBlLmdldExhc3RSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dJbmRleDtcbiAgICAgICAgdmFyIHJvd1Bpbm5lZCA9IG51bGw7XG4gICAgICAgIHZhciBwaW5uZWRCb3R0b21Db3VudCA9IHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkQm90dG9tUm93Q291bnQoKTtcbiAgICAgICAgdmFyIHBpbm5lZFRvcENvdW50ID0gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRUb3BSb3dDb3VudCgpO1xuICAgICAgICBpZiAocGlubmVkQm90dG9tQ291bnQpIHtcbiAgICAgICAgICAgIHJvd1Bpbm5lZCA9IENvbnN0YW50cy5QSU5ORURfQk9UVE9NO1xuICAgICAgICAgICAgcm93SW5kZXggPSBwaW5uZWRCb3R0b21Db3VudCAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5yb3dNb2RlbC5nZXRSb3dDb3VudCgpKSB7XG4gICAgICAgICAgICByb3dQaW5uZWQgPSBudWxsO1xuICAgICAgICAgICAgcm93SW5kZXggPSB0aGlzLnBhZ2luYXRpb25Qcm94eS5nZXRQYWdlTGFzdFJvdygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHBpbm5lZFRvcENvdW50KSB7XG4gICAgICAgICAgICByb3dQaW5uZWQgPSBDb25zdGFudHMuUElOTkVEX1RPUDtcbiAgICAgICAgICAgIHJvd0luZGV4ID0gcGlubmVkVG9wQ291bnQgLSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dJbmRleCA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IHsgcm93SW5kZXg6IHJvd0luZGV4LCByb3dQaW5uZWQ6IHJvd1Bpbm5lZCB9O1xuICAgIH07XG4gICAgUm93UG9zaXRpb25VdGlscy5wcm90b3R5cGUuZ2V0Um93Tm9kZSA9IGZ1bmN0aW9uIChncmlkUm93KSB7XG4gICAgICAgIHN3aXRjaCAoZ3JpZFJvdy5yb3dQaW5uZWQpIHtcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9UT1A6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkVG9wUm93RGF0YSgpW2dyaWRSb3cucm93SW5kZXhdO1xuICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX0JPVFRPTTpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Sb3dEYXRhKClbZ3JpZFJvdy5yb3dJbmRleF07XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvd01vZGVsLmdldFJvdyhncmlkUm93LnJvd0luZGV4KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUm93UG9zaXRpb25VdGlscy5wcm90b3R5cGUuc2FtZVJvdyA9IGZ1bmN0aW9uIChyb3dBLCByb3dCKSB7XG4gICAgICAgIC8vIGlmIGJvdGggbWlzc2luZ1xuICAgICAgICBpZiAoIXJvd0EgJiYgIXJvd0IpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIG9ubHkgb25lIG1pc3NpbmdcbiAgICAgICAgaWYgKChyb3dBICYmICFyb3dCKSB8fCAoIXJvd0EgJiYgcm93QikpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBvdGhlcndpc2UgY29tcGFyZSAodXNlID09IHRvIGNvbXBhcmUgcm93UGlubmVkIGJlY2F1c2UgaXQgY2FuIGJlIG51bGwgb3IgdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gcm93QS5yb3dJbmRleCA9PT0gcm93Qi5yb3dJbmRleCAmJiByb3dBLnJvd1Bpbm5lZCA9PSByb3dCLnJvd1Bpbm5lZDtcbiAgICB9O1xuICAgIC8vIHRlc3RzIGlmIHRoaXMgcm93IHNlbGVjdGlvbiBpcyBiZWZvcmUgdGhlIG90aGVyIHJvdyBzZWxlY3Rpb25cbiAgICBSb3dQb3NpdGlvblV0aWxzLnByb3RvdHlwZS5iZWZvcmUgPSBmdW5jdGlvbiAocm93QSwgcm93Qikge1xuICAgICAgICBzd2l0Y2ggKHJvd0Eucm93UGlubmVkKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfVE9QOlxuICAgICAgICAgICAgICAgIC8vIHdlIHdlIGFyZSBmbG9hdGluZyB0b3AsIGFuZCBvdGhlciBpc24ndCwgdGhlbiB3ZSBhcmUgYWx3YXlzIGJlZm9yZVxuICAgICAgICAgICAgICAgIGlmIChyb3dCLnJvd1Bpbm5lZCAhPT0gQ29uc3RhbnRzLlBJTk5FRF9UT1ApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBDb25zdGFudHMuUElOTkVEX0JPVFRPTTpcbiAgICAgICAgICAgICAgICAvLyBpZiB3ZSBhcmUgZmxvYXRpbmcgYm90dG9tLCBhbmQgdGhlIG90aGVyIGlzbid0LCB0aGVuIHdlIGFyZSBuZXZlciBiZWZvcmVcbiAgICAgICAgICAgICAgICBpZiAocm93Qi5yb3dQaW5uZWQgIT09IENvbnN0YW50cy5QSU5ORURfQk9UVE9NKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIC8vIGlmIHdlIGFyZSBub3QgZmxvYXRpbmcsIGJ1dCB0aGUgb3RoZXIgb25lIGlzIGZsb2F0aW5nLi4uXG4gICAgICAgICAgICAgICAgaWYgKGV4aXN0cyhyb3dCLnJvd1Bpbm5lZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvd0Iucm93UGlubmVkICE9PSBDb25zdGFudHMuUElOTkVEX1RPUDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd0Eucm93SW5kZXggPCByb3dCLnJvd0luZGV4O1xuICAgIH07XG4gICAgUm93UG9zaXRpb25VdGlscy5wcm90b3R5cGUucm93TWF4ID0gZnVuY3Rpb24gKHJvd3MpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG1heDtcbiAgICAgICAgcm93cy5mb3JFYWNoKGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgICAgIGlmIChtYXggPT09IHVuZGVmaW5lZCB8fCBfdGhpcy5iZWZvcmUobWF4LCByb3cpKSB7XG4gICAgICAgICAgICAgICAgbWF4ID0gcm93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG1heDtcbiAgICB9O1xuICAgIFJvd1Bvc2l0aW9uVXRpbHMucHJvdG90eXBlLnJvd01pbiA9IGZ1bmN0aW9uIChyb3dzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBtaW47XG4gICAgICAgIHJvd3MuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgICAgICBpZiAobWluID09PSB1bmRlZmluZWQgfHwgX3RoaXMuYmVmb3JlKHJvdywgbWluKSkge1xuICAgICAgICAgICAgICAgIG1pbiA9IHJvdztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtaW47XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJG8oW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBSb3dQb3NpdGlvblV0aWxzLnByb3RvdHlwZSwgXCJyb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkbyhbXG4gICAgICAgIEF1dG93aXJlZCgncGlubmVkUm93TW9kZWwnKVxuICAgIF0sIFJvd1Bvc2l0aW9uVXRpbHMucHJvdG90eXBlLCBcInBpbm5lZFJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRvKFtcbiAgICAgICAgQXV0b3dpcmVkKCdwYWdpbmF0aW9uUHJveHknKVxuICAgIF0sIFJvd1Bvc2l0aW9uVXRpbHMucHJvdG90eXBlLCBcInBhZ2luYXRpb25Qcm94eVwiLCB2b2lkIDApO1xuICAgIFJvd1Bvc2l0aW9uVXRpbHMgPSBfX2RlY29yYXRlJG8oW1xuICAgICAgICBCZWFuKCdyb3dQb3NpdGlvblV0aWxzJylcbiAgICBdLCBSb3dQb3NpdGlvblV0aWxzKTtcbiAgICByZXR1cm4gUm93UG9zaXRpb25VdGlscztcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRtID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRuID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ2VsbFBvc2l0aW9uVXRpbHMgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJG0oQ2VsbFBvc2l0aW9uVXRpbHMsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ2VsbFBvc2l0aW9uVXRpbHMoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQ2VsbFBvc2l0aW9uVXRpbHMucHJvdG90eXBlLmNyZWF0ZUlkID0gZnVuY3Rpb24gKGNlbGxQb3NpdGlvbikge1xuICAgICAgICB2YXIgcm93SW5kZXggPSBjZWxsUG9zaXRpb24ucm93SW5kZXgsIHJvd1Bpbm5lZCA9IGNlbGxQb3NpdGlvbi5yb3dQaW5uZWQsIGNvbHVtbiA9IGNlbGxQb3NpdGlvbi5jb2x1bW47XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUlkRnJvbVZhbHVlcyhyb3dJbmRleCwgY29sdW1uLCByb3dQaW5uZWQpO1xuICAgIH07XG4gICAgQ2VsbFBvc2l0aW9uVXRpbHMucHJvdG90eXBlLmNyZWF0ZUlkRnJvbVZhbHVlcyA9IGZ1bmN0aW9uIChyb3dJbmRleCwgY29sdW1uLCByb3dQaW5uZWQpIHtcbiAgICAgICAgcmV0dXJuIHJvd0luZGV4ICsgXCIuXCIgKyAocm93UGlubmVkID09IG51bGwgPyAnbnVsbCcgOiByb3dQaW5uZWQpICsgXCIuXCIgKyBjb2x1bW4uZ2V0SWQoKTtcbiAgICB9O1xuICAgIENlbGxQb3NpdGlvblV0aWxzLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiAoY2VsbEEsIGNlbGxCKSB7XG4gICAgICAgIHZhciBjb2xzTWF0Y2ggPSBjZWxsQS5jb2x1bW4gPT09IGNlbGxCLmNvbHVtbjtcbiAgICAgICAgdmFyIGZsb2F0aW5nTWF0Y2ggPSBjZWxsQS5yb3dQaW5uZWQgPT09IGNlbGxCLnJvd1Bpbm5lZDtcbiAgICAgICAgdmFyIGluZGV4TWF0Y2ggPSBjZWxsQS5yb3dJbmRleCA9PT0gY2VsbEIucm93SW5kZXg7XG4gICAgICAgIHJldHVybiBjb2xzTWF0Y2ggJiYgZmxvYXRpbmdNYXRjaCAmJiBpbmRleE1hdGNoO1xuICAgIH07XG4gICAgQ2VsbFBvc2l0aW9uVXRpbHMgPSBfX2RlY29yYXRlJG4oW1xuICAgICAgICBCZWFuKCdjZWxsUG9zaXRpb25VdGlscycpXG4gICAgXSwgQ2VsbFBvc2l0aW9uVXRpbHMpO1xuICAgIHJldHVybiBDZWxsUG9zaXRpb25VdGlscztcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRsID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgVW5kb1JlZG9BY3Rpb24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVW5kb1JlZG9BY3Rpb24oY2VsbFZhbHVlQ2hhbmdlcykge1xuICAgICAgICB0aGlzLmNlbGxWYWx1ZUNoYW5nZXMgPSBjZWxsVmFsdWVDaGFuZ2VzO1xuICAgIH1cbiAgICByZXR1cm4gVW5kb1JlZG9BY3Rpb247XG59KCkpO1xudmFyIFJhbmdlVW5kb1JlZG9BY3Rpb24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJGwoUmFuZ2VVbmRvUmVkb0FjdGlvbiwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBSYW5nZVVuZG9SZWRvQWN0aW9uKGNlbGxWYWx1ZUNoYW5nZXMsIGluaXRpYWxSYW5nZSwgZmluYWxSYW5nZSwgcmFuZ2VzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGNlbGxWYWx1ZUNoYW5nZXMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmluaXRpYWxSYW5nZSA9IGluaXRpYWxSYW5nZTtcbiAgICAgICAgX3RoaXMuZmluYWxSYW5nZSA9IGZpbmFsUmFuZ2U7XG4gICAgICAgIF90aGlzLnJhbmdlcyA9IHJhbmdlcztcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICByZXR1cm4gUmFuZ2VVbmRvUmVkb0FjdGlvbjtcbn0oVW5kb1JlZG9BY3Rpb24pKTtcbnZhciBVbmRvUmVkb1N0YWNrID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFVuZG9SZWRvU3RhY2sobWF4U3RhY2tTaXplKSB7XG4gICAgICAgIHRoaXMuYWN0aW9uU3RhY2sgPSBbXTtcbiAgICAgICAgdGhpcy5tYXhTdGFja1NpemUgPSBtYXhTdGFja1NpemUgPyBtYXhTdGFja1NpemUgOiBVbmRvUmVkb1N0YWNrLkRFRkFVTFRfU1RBQ0tfU0laRTtcbiAgICAgICAgdGhpcy5hY3Rpb25TdGFjayA9IG5ldyBBcnJheSh0aGlzLm1heFN0YWNrU2l6ZSk7XG4gICAgfVxuICAgIFVuZG9SZWRvU3RhY2sucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aW9uU3RhY2sucG9wKCk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1N0YWNrLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgdmFyIHNob3VsZEFkZEFjdGlvbnMgPSBpdGVtLmNlbGxWYWx1ZUNoYW5nZXMgJiYgaXRlbS5jZWxsVmFsdWVDaGFuZ2VzLmxlbmd0aCA+IDA7XG4gICAgICAgIGlmICghc2hvdWxkQWRkQWN0aW9ucykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmFjdGlvblN0YWNrLmxlbmd0aCA9PT0gdGhpcy5tYXhTdGFja1NpemUpIHtcbiAgICAgICAgICAgIHRoaXMuYWN0aW9uU3RhY2suc2hpZnQoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmFjdGlvblN0YWNrLnB1c2goaXRlbSk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1N0YWNrLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hY3Rpb25TdGFjayA9IFtdO1xuICAgIH07XG4gICAgVW5kb1JlZG9TdGFjay5wcm90b3R5cGUuZ2V0Q3VycmVudFN0YWNrU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aW9uU3RhY2subGVuZ3RoO1xuICAgIH07XG4gICAgVW5kb1JlZG9TdGFjay5ERUZBVUxUX1NUQUNLX1NJWkUgPSAxMDtcbiAgICByZXR1cm4gVW5kb1JlZG9TdGFjaztcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkayA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fYXNzaWduID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19hc3NpZ24pIHx8IGZ1bmN0aW9uICgpIHtcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24odCkge1xuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpXG4gICAgICAgICAgICAgICAgdFtwXSA9IHNbcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfTtcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG52YXIgX19kZWNvcmF0ZSRtID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX19yZWFkJDMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3JlYWQpIHx8IGZ1bmN0aW9uIChvLCBuKSB7XG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICAgIGlmICghbSkgcmV0dXJuIG87XG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XG4gICAgdHJ5IHtcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XG4gICAgfVxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XG4gICAgfVxuICAgIHJldHVybiBhcjtcbn07XG52YXIgX19zcHJlYWQkMiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCQzKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG52YXIgVW5kb1JlZG9TZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRrKFVuZG9SZWRvU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBVbmRvUmVkb1NlcnZpY2UoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5jZWxsVmFsdWVDaGFuZ2VzID0gW107XG4gICAgICAgIF90aGlzLmFjdGl2ZUNlbGxFZGl0ID0gbnVsbDtcbiAgICAgICAgX3RoaXMuYWN0aXZlUm93RWRpdCA9IG51bGw7XG4gICAgICAgIF90aGlzLmlzUGFzdGluZyA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc1JhbmdlSW5BY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgX3RoaXMub25DZWxsVmFsdWVDaGFuZ2VkID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgZXZlbnRDZWxsID0geyBjb2x1bW46IGV2ZW50LmNvbHVtbiwgcm93SW5kZXg6IGV2ZW50LnJvd0luZGV4LCByb3dQaW5uZWQ6IGV2ZW50LnJvd1Bpbm5lZCB9O1xuICAgICAgICAgICAgdmFyIGlzQ2VsbEVkaXRpbmcgPSBfdGhpcy5hY3RpdmVDZWxsRWRpdCAhPT0gbnVsbCAmJiBfdGhpcy5jZWxsUG9zaXRpb25VdGlscy5lcXVhbHMoX3RoaXMuYWN0aXZlQ2VsbEVkaXQsIGV2ZW50Q2VsbCk7XG4gICAgICAgICAgICB2YXIgaXNSb3dFZGl0aW5nID0gX3RoaXMuYWN0aXZlUm93RWRpdCAhPT0gbnVsbCAmJiBfdGhpcy5yb3dQb3NpdGlvblV0aWxzLnNhbWVSb3coX3RoaXMuYWN0aXZlUm93RWRpdCwgZXZlbnRDZWxsKTtcbiAgICAgICAgICAgIHZhciBzaG91bGRDYXB0dXJlQWN0aW9uID0gaXNDZWxsRWRpdGluZyB8fCBpc1Jvd0VkaXRpbmcgfHwgX3RoaXMuaXNQYXN0aW5nIHx8IF90aGlzLmlzUmFuZ2VJbkFjdGlvbjtcbiAgICAgICAgICAgIGlmICghc2hvdWxkQ2FwdHVyZUFjdGlvbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciByb3dQaW5uZWQgPSBldmVudC5yb3dQaW5uZWQsIHJvd0luZGV4ID0gZXZlbnQucm93SW5kZXgsIGNvbHVtbiA9IGV2ZW50LmNvbHVtbiwgb2xkVmFsdWUgPSBldmVudC5vbGRWYWx1ZSwgdmFsdWUgPSBldmVudC52YWx1ZTtcbiAgICAgICAgICAgIHZhciBjZWxsVmFsdWVDaGFuZ2UgPSB7XG4gICAgICAgICAgICAgICAgcm93UGlubmVkOiByb3dQaW5uZWQsXG4gICAgICAgICAgICAgICAgcm93SW5kZXg6IHJvd0luZGV4LFxuICAgICAgICAgICAgICAgIGNvbHVtbklkOiBjb2x1bW4uZ2V0Q29sSWQoKSxcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgb2xkVmFsdWU6IG9sZFZhbHVlXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX3RoaXMuY2VsbFZhbHVlQ2hhbmdlcy5wdXNoKGNlbGxWYWx1ZUNoYW5nZSk7XG4gICAgICAgIH07XG4gICAgICAgIF90aGlzLmNsZWFyU3RhY2tzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMudW5kb1N0YWNrLmNsZWFyKCk7XG4gICAgICAgICAgICBfdGhpcy5yZWRvU3RhY2suY2xlYXIoKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNVbmRvUmVkb0NlbGxFZGl0aW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdW5kb1JlZG9MaW1pdCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFVuZG9SZWRvQ2VsbEVkaXRpbmdMaW1pdCgpO1xuICAgICAgICBpZiAodW5kb1JlZG9MaW1pdCA8PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51bmRvU3RhY2sgPSBuZXcgVW5kb1JlZG9TdGFjayh1bmRvUmVkb0xpbWl0KTtcbiAgICAgICAgdGhpcy5yZWRvU3RhY2sgPSBuZXcgVW5kb1JlZG9TdGFjayh1bmRvUmVkb0xpbWl0KTtcbiAgICAgICAgdGhpcy5hZGRSb3dFZGl0aW5nTGlzdGVuZXJzKCk7XG4gICAgICAgIHRoaXMuYWRkQ2VsbEVkaXRpbmdMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5hZGRQYXN0ZUxpc3RlbmVycygpO1xuICAgICAgICB0aGlzLmFkZEZpbGxMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5hZGRDZWxsS2V5TGlzdGVuZXJzKCk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ0VMTF9WQUxVRV9DSEFOR0VELCB0aGlzLm9uQ2VsbFZhbHVlQ2hhbmdlZCk7XG4gICAgICAgIC8vIHVuZG8gLyByZWRvIGlzIHJlc3RyaWN0ZWQgdG8gYWN0dWFsIGVkaXRpbmcgc28gd2UgY2xlYXIgdGhlIHN0YWNrcyB3aGVuIG90aGVyIG9wZXJhdGlvbnMgYXJlXG4gICAgICAgIC8vIHBlcmZvcm1lZCB0aGF0IGNoYW5nZSB0aGUgb3JkZXIgb2YgdGhlIHJvdyAvIGNvbHMuXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTU9ERUxfVVBEQVRFRCwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmICghZS5rZWVwVW5kb1JlZG9TdGFjaykge1xuICAgICAgICAgICAgICAgIF90aGlzLmNsZWFyU3RhY2tzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9NT0RFX0NIQU5HRUQsIHRoaXMuY2xlYXJTdGFja3MpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX05FV19DT0xVTU5TX0xPQURFRCwgdGhpcy5jbGVhclN0YWNrcyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX0dST1VQX09QRU5FRCwgdGhpcy5jbGVhclN0YWNrcyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1JPV19HUk9VUF9DSEFOR0VELCB0aGlzLmNsZWFyU3RhY2tzKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fTU9WRUQsIHRoaXMuY2xlYXJTdGFja3MpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSU5ORUQsIHRoaXMuY2xlYXJTdGFja3MpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9WSVNJQkxFLCB0aGlzLmNsZWFyU3RhY2tzKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ST1dfRFJBR19FTkQsIHRoaXMuY2xlYXJTdGFja3MpO1xuICAgICAgICB0aGlzLmN0cmxzU2VydmljZS53aGVuUmVhZHkoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuZ3JpZEJvZHlDdHJsID0gX3RoaXMuY3RybHNTZXJ2aWNlLmdldEdyaWRCb2R5Q3RybCgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFVuZG9SZWRvU2VydmljZS5wcm90b3R5cGUuZ2V0Q3VycmVudFVuZG9TdGFja1NpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVuZG9TdGFjayA/IHRoaXMudW5kb1N0YWNrLmdldEN1cnJlbnRTdGFja1NpemUoKSA6IDA7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLmdldEN1cnJlbnRSZWRvU3RhY2tTaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWRvU3RhY2sgPyB0aGlzLnJlZG9TdGFjay5nZXRDdXJyZW50U3RhY2tTaXplKCkgOiAwO1xuICAgIH07XG4gICAgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZS51bmRvID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudW5kb1N0YWNrKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHVuZG9BY3Rpb24gPSB0aGlzLnVuZG9TdGFjay5wb3AoKTtcbiAgICAgICAgaWYgKCF1bmRvQWN0aW9uIHx8ICF1bmRvQWN0aW9uLmNlbGxWYWx1ZUNoYW5nZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByb2Nlc3NBY3Rpb24odW5kb0FjdGlvbiwgZnVuY3Rpb24gKGNlbGxWYWx1ZUNoYW5nZSkgeyByZXR1cm4gY2VsbFZhbHVlQ2hhbmdlLm9sZFZhbHVlOyB9KTtcbiAgICAgICAgaWYgKHVuZG9BY3Rpb24gaW5zdGFuY2VvZiBSYW5nZVVuZG9SZWRvQWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NSYW5nZSh1bmRvQWN0aW9uLnJhbmdlcyB8fCBbdW5kb0FjdGlvbi5pbml0aWFsUmFuZ2VdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc0NlbGwodW5kb0FjdGlvbi5jZWxsVmFsdWVDaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlZG9TdGFjay5wdXNoKHVuZG9BY3Rpb24pO1xuICAgIH07XG4gICAgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZS5yZWRvID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMucmVkb1N0YWNrKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlZG9BY3Rpb24gPSB0aGlzLnJlZG9TdGFjay5wb3AoKTtcbiAgICAgICAgaWYgKCFyZWRvQWN0aW9uIHx8ICFyZWRvQWN0aW9uLmNlbGxWYWx1ZUNoYW5nZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByb2Nlc3NBY3Rpb24ocmVkb0FjdGlvbiwgZnVuY3Rpb24gKGNlbGxWYWx1ZUNoYW5nZSkgeyByZXR1cm4gY2VsbFZhbHVlQ2hhbmdlLm5ld1ZhbHVlOyB9KTtcbiAgICAgICAgaWYgKHJlZG9BY3Rpb24gaW5zdGFuY2VvZiBSYW5nZVVuZG9SZWRvQWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NSYW5nZShyZWRvQWN0aW9uLnJhbmdlcyB8fCBbcmVkb0FjdGlvbi5maW5hbFJhbmdlXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NDZWxsKHJlZG9BY3Rpb24uY2VsbFZhbHVlQ2hhbmdlcyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51bmRvU3RhY2sucHVzaChyZWRvQWN0aW9uKTtcbiAgICB9O1xuICAgIFVuZG9SZWRvU2VydmljZS5wcm90b3R5cGUucHJvY2Vzc0FjdGlvbiA9IGZ1bmN0aW9uIChhY3Rpb24sIHZhbHVlRXh0cmFjdG9yKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGFjdGlvbi5jZWxsVmFsdWVDaGFuZ2VzLmZvckVhY2goZnVuY3Rpb24gKGNlbGxWYWx1ZUNoYW5nZSkge1xuICAgICAgICAgICAgdmFyIHJvd0luZGV4ID0gY2VsbFZhbHVlQ2hhbmdlLnJvd0luZGV4LCByb3dQaW5uZWQgPSBjZWxsVmFsdWVDaGFuZ2Uucm93UGlubmVkLCBjb2x1bW5JZCA9IGNlbGxWYWx1ZUNoYW5nZS5jb2x1bW5JZDtcbiAgICAgICAgICAgIHZhciByb3dQb3NpdGlvbiA9IHsgcm93SW5kZXg6IHJvd0luZGV4LCByb3dQaW5uZWQ6IHJvd1Bpbm5lZCB9O1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRSb3cgPSBfdGhpcy5nZXRSb3dOb2RlKHJvd1Bvc2l0aW9uKTtcbiAgICAgICAgICAgIC8vIGNoZWNrcyBpZiB0aGUgcm93IGhhcyBiZWVuIGZpbHRlcmVkIG91dFxuICAgICAgICAgICAgaWYgKCFjdXJyZW50Um93LmRpc3BsYXllZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBleHRyYWN0ZWRWYWx1ZSA9IHZhbHVlRXh0cmFjdG9yKGNlbGxWYWx1ZUNoYW5nZSk7XG4gICAgICAgICAgICAvLyB3aGVuIHZhbHVlcyBhcmUgJ2NvbXBsZXggb2JqZWN0cycgd2UgbmVlZCB0byBpbnZva2UgdGhlaXIgYHRvU3RyaW5nKClgIHRvIG9idGFpbiB2YWx1ZVxuICAgICAgICAgICAgdmFyIHZhbHVlID0gKHR5cGVvZiBleHRyYWN0ZWRWYWx1ZS50b1N0cmluZyA9PT0gJ2Z1bmN0aW9uJykgPyBleHRyYWN0ZWRWYWx1ZS50b1N0cmluZygpIDogZXh0cmFjdGVkVmFsdWU7XG4gICAgICAgICAgICBjdXJyZW50Um93LnNldERhdGFWYWx1ZShjb2x1bW5JZCwgdmFsdWUpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFVuZG9SZWRvU2VydmljZS5wcm90b3R5cGUucHJvY2Vzc1JhbmdlID0gZnVuY3Rpb24gKHJhbmdlcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgbGFzdEZvY3VzZWRDZWxsO1xuICAgICAgICB0aGlzLnJhbmdlU2VydmljZS5yZW1vdmVBbGxDZWxsUmFuZ2VzKHRydWUpO1xuICAgICAgICByYW5nZXMuZm9yRWFjaChmdW5jdGlvbiAocmFuZ2UsIGlkeCkge1xuICAgICAgICAgICAgaWYgKCFyYW5nZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdGFydFJvdyA9IHJhbmdlLnN0YXJ0Um93O1xuICAgICAgICAgICAgdmFyIGVuZFJvdyA9IHJhbmdlLmVuZFJvdztcbiAgICAgICAgICAgIGlmIChpZHggPT09IHJhbmdlcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgbGFzdEZvY3VzZWRDZWxsID0ge1xuICAgICAgICAgICAgICAgICAgICByb3dQaW5uZWQ6IHN0YXJ0Um93LnJvd1Bpbm5lZCxcbiAgICAgICAgICAgICAgICAgICAgcm93SW5kZXg6IHN0YXJ0Um93LnJvd0luZGV4LFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JZDogcmFuZ2Uuc3RhcnRDb2x1bW4uZ2V0Q29sSWQoKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgX3RoaXMuc2V0TGFzdEZvY3VzZWRDZWxsKGxhc3RGb2N1c2VkQ2VsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2VsbFJhbmdlUGFyYW1zID0ge1xuICAgICAgICAgICAgICAgIHJvd1N0YXJ0SW5kZXg6IHN0YXJ0Um93LnJvd0luZGV4LFxuICAgICAgICAgICAgICAgIHJvd1N0YXJ0UGlubmVkOiBzdGFydFJvdy5yb3dQaW5uZWQsXG4gICAgICAgICAgICAgICAgcm93RW5kSW5kZXg6IGVuZFJvdy5yb3dJbmRleCxcbiAgICAgICAgICAgICAgICByb3dFbmRQaW5uZWQ6IGVuZFJvdy5yb3dQaW5uZWQsXG4gICAgICAgICAgICAgICAgY29sdW1uU3RhcnQ6IHJhbmdlLnN0YXJ0Q29sdW1uLFxuICAgICAgICAgICAgICAgIGNvbHVtbnM6IHJhbmdlLmNvbHVtbnNcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBfdGhpcy5yYW5nZVNlcnZpY2UuYWRkQ2VsbFJhbmdlKGNlbGxSYW5nZVBhcmFtcyk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZS5wcm9jZXNzQ2VsbCA9IGZ1bmN0aW9uIChjZWxsVmFsdWVDaGFuZ2VzKSB7XG4gICAgICAgIHZhciBjZWxsVmFsdWVDaGFuZ2UgPSBjZWxsVmFsdWVDaGFuZ2VzWzBdO1xuICAgICAgICB2YXIgcm93SW5kZXggPSBjZWxsVmFsdWVDaGFuZ2Uucm93SW5kZXgsIHJvd1Bpbm5lZCA9IGNlbGxWYWx1ZUNoYW5nZS5yb3dQaW5uZWQ7XG4gICAgICAgIHZhciByb3dQb3NpdGlvbiA9IHsgcm93SW5kZXg6IHJvd0luZGV4LCByb3dQaW5uZWQ6IHJvd1Bpbm5lZCB9O1xuICAgICAgICB2YXIgcm93ID0gdGhpcy5nZXRSb3dOb2RlKHJvd1Bvc2l0aW9uKTtcbiAgICAgICAgdmFyIGxhc3RGb2N1c2VkQ2VsbCA9IHtcbiAgICAgICAgICAgIHJvd1Bpbm5lZDogY2VsbFZhbHVlQ2hhbmdlLnJvd1Bpbm5lZCxcbiAgICAgICAgICAgIHJvd0luZGV4OiByb3cucm93SW5kZXgsXG4gICAgICAgICAgICBjb2x1bW5JZDogY2VsbFZhbHVlQ2hhbmdlLmNvbHVtbklkXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2V0TGFzdEZvY3VzZWRDZWxsKGxhc3RGb2N1c2VkQ2VsbCwgdHJ1ZSk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLnNldExhc3RGb2N1c2VkQ2VsbCA9IGZ1bmN0aW9uIChsYXN0Rm9jdXNlZENlbGwsIHNldFJhbmdlVG9DZWxsKSB7XG4gICAgICAgIHZhciByb3dJbmRleCA9IGxhc3RGb2N1c2VkQ2VsbC5yb3dJbmRleCwgY29sdW1uSWQgPSBsYXN0Rm9jdXNlZENlbGwuY29sdW1uSWQsIHJvd1Bpbm5lZCA9IGxhc3RGb2N1c2VkQ2VsbC5yb3dQaW5uZWQ7XG4gICAgICAgIHZhciBzY3JvbGxGZWF0dXJlID0gdGhpcy5ncmlkQm9keUN0cmwuZ2V0U2Nyb2xsRmVhdHVyZSgpO1xuICAgICAgICB2YXIgY29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRHcmlkQ29sdW1uKGNvbHVtbklkKTtcbiAgICAgICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzY3JvbGxGZWF0dXJlLmVuc3VyZUluZGV4VmlzaWJsZShyb3dJbmRleCk7XG4gICAgICAgIHNjcm9sbEZlYXR1cmUuZW5zdXJlQ29sdW1uVmlzaWJsZShjb2x1bW4pO1xuICAgICAgICB2YXIgY2VsbFBvc2l0aW9uID0geyByb3dJbmRleDogcm93SW5kZXgsIGNvbHVtbjogY29sdW1uLCByb3dQaW5uZWQ6IHJvd1Bpbm5lZCB9O1xuICAgICAgICB0aGlzLmZvY3VzU2VydmljZS5zZXRGb2N1c2VkQ2VsbChfX2Fzc2lnbihfX2Fzc2lnbih7fSwgY2VsbFBvc2l0aW9uKSwgeyBmb3JjZUJyb3dzZXJGb2N1czogdHJ1ZSB9KSk7XG4gICAgICAgIGlmIChzZXRSYW5nZVRvQ2VsbCkge1xuICAgICAgICAgICAgdGhpcy5yYW5nZVNlcnZpY2Uuc2V0UmFuZ2VUb0NlbGwoY2VsbFBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZS5hZGRSb3dFZGl0aW5nTGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1JPV19FRElUSU5HX1NUQVJURUQsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBfdGhpcy5hY3RpdmVSb3dFZGl0ID0geyByb3dJbmRleDogZS5yb3dJbmRleCwgcm93UGlubmVkOiBlLnJvd1Bpbm5lZCB9O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ST1dfRURJVElOR19TVE9QUEVELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYWN0aW9uID0gbmV3IFVuZG9SZWRvQWN0aW9uKF90aGlzLmNlbGxWYWx1ZUNoYW5nZXMpO1xuICAgICAgICAgICAgX3RoaXMucHVzaEFjdGlvbnNUb1VuZG9TdGFjayhhY3Rpb24pO1xuICAgICAgICAgICAgX3RoaXMuYWN0aXZlUm93RWRpdCA9IG51bGw7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZS5hZGRDZWxsRWRpdGluZ0xpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DRUxMX0VESVRJTkdfU1RBUlRFRCwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIF90aGlzLmFjdGl2ZUNlbGxFZGl0ID0geyBjb2x1bW46IGUuY29sdW1uLCByb3dJbmRleDogZS5yb3dJbmRleCwgcm93UGlubmVkOiBlLnJvd1Bpbm5lZCB9O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DRUxMX0VESVRJTkdfU1RPUFBFRCwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIF90aGlzLmFjdGl2ZUNlbGxFZGl0ID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBzaG91bGRQdXNoQWN0aW9uID0gZS52YWx1ZUNoYW5nZWQgJiYgIV90aGlzLmFjdGl2ZVJvd0VkaXQgJiYgIV90aGlzLmlzUGFzdGluZyAmJiAhX3RoaXMuaXNSYW5nZUluQWN0aW9uO1xuICAgICAgICAgICAgaWYgKHNob3VsZFB1c2hBY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB2YXIgYWN0aW9uID0gbmV3IFVuZG9SZWRvQWN0aW9uKF90aGlzLmNlbGxWYWx1ZUNoYW5nZXMpO1xuICAgICAgICAgICAgICAgIF90aGlzLnB1c2hBY3Rpb25zVG9VbmRvU3RhY2soYWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLmFkZFBhc3RlTGlzdGVuZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BBU1RFX1NUQVJULCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5pc1Bhc3RpbmcgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9QQVNURV9FTkQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhY3Rpb24gPSBuZXcgVW5kb1JlZG9BY3Rpb24oX3RoaXMuY2VsbFZhbHVlQ2hhbmdlcyk7XG4gICAgICAgICAgICBfdGhpcy5wdXNoQWN0aW9uc1RvVW5kb1N0YWNrKGFjdGlvbik7XG4gICAgICAgICAgICBfdGhpcy5pc1Bhc3RpbmcgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLmFkZEZpbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRklMTF9TVEFSVCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuaXNSYW5nZUluQWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRklMTF9FTkQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgdmFyIGFjdGlvbiA9IG5ldyBSYW5nZVVuZG9SZWRvQWN0aW9uKF90aGlzLmNlbGxWYWx1ZUNoYW5nZXMsIGV2ZW50LmluaXRpYWxSYW5nZSwgZXZlbnQuZmluYWxSYW5nZSk7XG4gICAgICAgICAgICBfdGhpcy5wdXNoQWN0aW9uc1RvVW5kb1N0YWNrKGFjdGlvbik7XG4gICAgICAgICAgICBfdGhpcy5pc1JhbmdlSW5BY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLmFkZENlbGxLZXlMaXN0ZW5lcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfS0VZX1NIT1JUQ1VUX0NIQU5HRURfQ0VMTF9TVEFSVCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuaXNSYW5nZUluQWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfS0VZX1NIT1JUQ1VUX0NIQU5HRURfQ0VMTF9FTkQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhY3Rpb247XG4gICAgICAgICAgICBpZiAoX3RoaXMucmFuZ2VTZXJ2aWNlICYmIF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJhbmdlU2VsZWN0aW9uKCkpIHtcbiAgICAgICAgICAgICAgICBhY3Rpb24gPSBuZXcgUmFuZ2VVbmRvUmVkb0FjdGlvbihfdGhpcy5jZWxsVmFsdWVDaGFuZ2VzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgX19zcHJlYWQkMihfdGhpcy5yYW5nZVNlcnZpY2UuZ2V0Q2VsbFJhbmdlcygpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhY3Rpb24gPSBuZXcgVW5kb1JlZG9BY3Rpb24oX3RoaXMuY2VsbFZhbHVlQ2hhbmdlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5wdXNoQWN0aW9uc1RvVW5kb1N0YWNrKGFjdGlvbik7XG4gICAgICAgICAgICBfdGhpcy5pc1JhbmdlSW5BY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLnB1c2hBY3Rpb25zVG9VbmRvU3RhY2sgPSBmdW5jdGlvbiAoYWN0aW9uKSB7XG4gICAgICAgIHRoaXMudW5kb1N0YWNrLnB1c2goYWN0aW9uKTtcbiAgICAgICAgdGhpcy5jZWxsVmFsdWVDaGFuZ2VzID0gW107XG4gICAgICAgIHRoaXMucmVkb1N0YWNrLmNsZWFyKCk7XG4gICAgfTtcbiAgICBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoZ3JpZFJvdykge1xuICAgICAgICBzd2l0Y2ggKGdyaWRSb3cucm93UGlubmVkKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfVE9QOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBpbm5lZFJvd01vZGVsLmdldFBpbm5lZFRvcFJvd0RhdGEoKVtncmlkUm93LnJvd0luZGV4XTtcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9CT1RUT006XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkQm90dG9tUm93RGF0YSgpW2dyaWRSb3cucm93SW5kZXhdO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dNb2RlbC5nZXRSb3coZ3JpZFJvdy5yb3dJbmRleCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkbShbXG4gICAgICAgIEF1dG93aXJlZCgnZm9jdXNTZXJ2aWNlJylcbiAgICBdLCBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkbShbXG4gICAgICAgIEF1dG93aXJlZCgnY3RybHNTZXJ2aWNlJylcbiAgICBdLCBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLCBcImN0cmxzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkbShbXG4gICAgICAgIEF1dG93aXJlZCgncm93TW9kZWwnKVxuICAgIF0sIFVuZG9SZWRvU2VydmljZS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJG0oW1xuICAgICAgICBBdXRvd2lyZWQoJ3Bpbm5lZFJvd01vZGVsJylcbiAgICBdLCBVbmRvUmVkb1NlcnZpY2UucHJvdG90eXBlLCBcInBpbm5lZFJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRtKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjZWxsUG9zaXRpb25VdGlscycpXG4gICAgXSwgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZSwgXCJjZWxsUG9zaXRpb25VdGlsc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkbShbXG4gICAgICAgIEF1dG93aXJlZCgncm93UG9zaXRpb25VdGlscycpXG4gICAgXSwgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZSwgXCJyb3dQb3NpdGlvblV0aWxzXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRtKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgVW5kb1JlZG9TZXJ2aWNlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkbShbXG4gICAgICAgIE9wdGlvbmFsKCdyYW5nZVNlcnZpY2UnKVxuICAgIF0sIFVuZG9SZWRvU2VydmljZS5wcm90b3R5cGUsIFwicmFuZ2VTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRtKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFVuZG9SZWRvU2VydmljZS5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBVbmRvUmVkb1NlcnZpY2UgPSBfX2RlY29yYXRlJG0oW1xuICAgICAgICBCZWFuKCd1bmRvUmVkb1NlcnZpY2UnKVxuICAgIF0sIFVuZG9SZWRvU2VydmljZSk7XG4gICAgcmV0dXJuIFVuZG9SZWRvU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRqID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRsID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgSGVhZGVyUG9zaXRpb25VdGlscyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkaihIZWFkZXJQb3NpdGlvblV0aWxzLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEhlYWRlclBvc2l0aW9uVXRpbHMoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgSGVhZGVyUG9zaXRpb25VdGlscy5wcm90b3R5cGUuZmluZEhlYWRlciA9IGZ1bmN0aW9uIChmb2N1c2VkSGVhZGVyLCBkaXJlY3Rpb24pIHtcbiAgICAgICAgdmFyIG5leHRDb2x1bW47XG4gICAgICAgIHZhciBnZXRHcm91cE1ldGhvZDtcbiAgICAgICAgdmFyIGdldENvbE1ldGhvZDtcbiAgICAgICAgaWYgKGZvY3VzZWRIZWFkZXIuY29sdW1uIGluc3RhbmNlb2YgQ29sdW1uR3JvdXApIHtcbiAgICAgICAgICAgIGdldEdyb3VwTWV0aG9kID0gXCJnZXREaXNwbGF5ZWRHcm91cFwiICsgZGlyZWN0aW9uO1xuICAgICAgICAgICAgbmV4dENvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWxbZ2V0R3JvdXBNZXRob2RdKGZvY3VzZWRIZWFkZXIuY29sdW1uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGdldENvbE1ldGhvZCA9IFwiZ2V0RGlzcGxheWVkQ29sXCIgKyBkaXJlY3Rpb247XG4gICAgICAgICAgICBuZXh0Q29sdW1uID0gdGhpcy5jb2x1bW5Nb2RlbFtnZXRDb2xNZXRob2RdKGZvY3VzZWRIZWFkZXIuY29sdW1uKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV4dENvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBjb2x1bW46IG5leHRDb2x1bW4sXG4gICAgICAgICAgICAgICAgaGVhZGVyUm93SW5kZXg6IGZvY3VzZWRIZWFkZXIuaGVhZGVyUm93SW5kZXhcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEhlYWRlclBvc2l0aW9uVXRpbHMucHJvdG90eXBlLmZpbmRDb2xBdEVkZ2VGb3JIZWFkZXJSb3cgPSBmdW5jdGlvbiAobGV2ZWwsIHBvc2l0aW9uKSB7XG4gICAgICAgIHZhciBkaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRBbGxEaXNwbGF5ZWRDb2x1bW5zKCk7XG4gICAgICAgIHZhciBjb2x1bW4gPSBkaXNwbGF5ZWRDb2x1bW5zW3Bvc2l0aW9uID09PSAnc3RhcnQnID8gMCA6IGRpc3BsYXllZENvbHVtbnMubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmICghY29sdW1uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNoaWxkQ29udGFpbmVyID0gdGhpcy5jdHJsc1NlcnZpY2UuZ2V0SGVhZGVyUm93Q29udGFpbmVyQ3RybChjb2x1bW4uZ2V0UGlubmVkKCkpO1xuICAgICAgICB2YXIgdHlwZSA9IGNoaWxkQ29udGFpbmVyLmdldFJvd1R5cGUobGV2ZWwpO1xuICAgICAgICBpZiAodHlwZSA9PSBIZWFkZXJSb3dUeXBlLkNPTFVNTl9HUk9VUCkge1xuICAgICAgICAgICAgdmFyIGNvbHVtbkdyb3VwID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRDb2x1bW5Hcm91cEF0TGV2ZWwoY29sdW1uLCBsZXZlbCk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGhlYWRlclJvd0luZGV4OiBsZXZlbCxcbiAgICAgICAgICAgICAgICBjb2x1bW46IGNvbHVtbkdyb3VwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvLyBpZiB0eXBlPT1udWxsLCBtZWFucyB0aGUgaGVhZGVyIGxldmVsIGRpZG4ndCBleGlzdFxuICAgICAgICAgICAgaGVhZGVyUm93SW5kZXg6IHR5cGUgPT0gbnVsbCA/IC0xIDogbGV2ZWwsXG4gICAgICAgICAgICBjb2x1bW46IGNvbHVtblxuICAgICAgICB9O1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRsKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgSGVhZGVyUG9zaXRpb25VdGlscy5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGwoW1xuICAgICAgICBBdXRvd2lyZWQoJ2N0cmxzU2VydmljZScpXG4gICAgXSwgSGVhZGVyUG9zaXRpb25VdGlscy5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgSGVhZGVyUG9zaXRpb25VdGlscyA9IF9fZGVjb3JhdGUkbChbXG4gICAgICAgIEJlYW4oJ2hlYWRlclBvc2l0aW9uVXRpbHMnKVxuICAgIF0sIEhlYWRlclBvc2l0aW9uVXRpbHMpO1xuICAgIHJldHVybiBIZWFkZXJQb3NpdGlvblV0aWxzO1xufShCZWFuU3R1YikpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG52YXIgX19kZWNvcmF0ZSRrID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ29sdW1uRGVmRmFjdG9yeSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb2x1bW5EZWZGYWN0b3J5KCkge1xuICAgIH1cbiAgICBDb2x1bW5EZWZGYWN0b3J5LnByb3RvdHlwZS5idWlsZENvbHVtbkRlZnMgPSBmdW5jdGlvbiAoY29scywgcm93R3JvdXBDb2x1bW5zLCBwaXZvdENvbHVtbnMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB2YXIgY29sR3JvdXBEZWZzID0ge307XG4gICAgICAgIGNvbHMuZm9yRWFjaChmdW5jdGlvbiAoY29sKSB7XG4gICAgICAgICAgICB2YXIgY29sRGVmID0gX3RoaXMuY3JlYXRlRGVmRnJvbUNvbHVtbihjb2wsIHJvd0dyb3VwQ29sdW1ucywgcGl2b3RDb2x1bW5zKTtcbiAgICAgICAgICAgIHZhciBhZGRUb1Jlc3VsdCA9IHRydWU7XG4gICAgICAgICAgICB2YXIgY2hpbGREZWYgPSBjb2xEZWY7XG4gICAgICAgICAgICB2YXIgcG9pbnRlciA9IGNvbC5nZXRPcmlnaW5hbFBhcmVudCgpO1xuICAgICAgICAgICAgd2hpbGUgKHBvaW50ZXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50RGVmID0gbnVsbDtcbiAgICAgICAgICAgICAgICAvLyB3ZSBkb24ndCBpbmNsdWRlIHBhZGRpbmcgZ3JvdXBzLCBhcyB0aGUgY29sdW1uIGdyb3VwcyBwcm92aWRlZFxuICAgICAgICAgICAgICAgIC8vIGJ5IGFwcGxpY2F0aW9uIGRpZG4ndCBoYXZlIHRoZXNlLiB0aGUgd2hvbGUgcG9pbnQgb2YgcGFkZGluZyBncm91cHNcbiAgICAgICAgICAgICAgICAvLyBpcyB0byBiYWxhbmNlIHRoZSBjb2x1bW4gdHJlZSB0aGF0IHRoZSB1c2VyIHByb3ZpZGVkLlxuICAgICAgICAgICAgICAgIGlmIChwb2ludGVyLmlzUGFkZGluZygpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50ZXIgPSBwb2ludGVyLmdldE9yaWdpbmFsUGFyZW50KCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiBjb2xEZWYgZm9yIHRoaXMgZ3JvdXAgYWxyZWFkeSBleGlzdHMsIHVzZSBpdFxuICAgICAgICAgICAgICAgIHZhciBleGlzdGluZ1BhcmVudERlZiA9IGNvbEdyb3VwRGVmc1twb2ludGVyLmdldEdyb3VwSWQoKV07XG4gICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nUGFyZW50RGVmKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nUGFyZW50RGVmLmNoaWxkcmVuLnB1c2goY2hpbGREZWYpO1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBhZGRlZCB0byByZXN1bHQsIGl0IHdvdWxkIGJlIHRoZSBzZWNvbmQgdGltZSB3ZSBkaWQgaXRcbiAgICAgICAgICAgICAgICAgICAgYWRkVG9SZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byBjb250aW51ZSB1cCB0aGUgdHJlZSwgYXMgaXQgaGFzIGFscmVhZHkgYmVlblxuICAgICAgICAgICAgICAgICAgICAvLyBkb25lIGZvciB0aGlzIGdyb3VwXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXJlbnREZWYgPSBfdGhpcy5jcmVhdGVEZWZGcm9tR3JvdXAocG9pbnRlcik7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudERlZikge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnREZWYuY2hpbGRyZW4gPSBbY2hpbGREZWZdO1xuICAgICAgICAgICAgICAgICAgICBjb2xHcm91cERlZnNbcGFyZW50RGVmLmdyb3VwSWRdID0gcGFyZW50RGVmO1xuICAgICAgICAgICAgICAgICAgICBjaGlsZERlZiA9IHBhcmVudERlZjtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRlciA9IHBvaW50ZXIuZ2V0T3JpZ2luYWxQYXJlbnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYWRkVG9SZXN1bHQpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChjaGlsZERlZik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ29sdW1uRGVmRmFjdG9yeS5wcm90b3R5cGUuY3JlYXRlRGVmRnJvbUdyb3VwID0gZnVuY3Rpb24gKGdyb3VwKSB7XG4gICAgICAgIHZhciBkZWZDbG9uZWQgPSBkZWVwQ2xvbmVEZWZpbml0aW9uKGdyb3VwLmdldENvbEdyb3VwRGVmKCksIFsnY2hpbGRyZW4nXSk7XG4gICAgICAgIGlmIChkZWZDbG9uZWQpIHtcbiAgICAgICAgICAgIGRlZkNsb25lZC5ncm91cElkID0gZ3JvdXAuZ2V0R3JvdXBJZCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkZWZDbG9uZWQ7XG4gICAgfTtcbiAgICBDb2x1bW5EZWZGYWN0b3J5LnByb3RvdHlwZS5jcmVhdGVEZWZGcm9tQ29sdW1uID0gZnVuY3Rpb24gKGNvbCwgcm93R3JvdXBDb2x1bW5zLCBwaXZvdENvbHVtbnMpIHtcbiAgICAgICAgdmFyIGNvbERlZkNsb25lZCA9IGRlZXBDbG9uZURlZmluaXRpb24oY29sLmdldENvbERlZigpKTtcbiAgICAgICAgY29sRGVmQ2xvbmVkLmNvbElkID0gY29sLmdldENvbElkKCk7XG4gICAgICAgIGNvbERlZkNsb25lZC53aWR0aCA9IGNvbC5nZXRBY3R1YWxXaWR0aCgpO1xuICAgICAgICBjb2xEZWZDbG9uZWQucm93R3JvdXAgPSBjb2wuaXNSb3dHcm91cEFjdGl2ZSgpO1xuICAgICAgICBjb2xEZWZDbG9uZWQucm93R3JvdXBJbmRleCA9IGNvbC5pc1Jvd0dyb3VwQWN0aXZlKCkgPyByb3dHcm91cENvbHVtbnMuaW5kZXhPZihjb2wpIDogbnVsbDtcbiAgICAgICAgY29sRGVmQ2xvbmVkLnBpdm90ID0gY29sLmlzUGl2b3RBY3RpdmUoKTtcbiAgICAgICAgY29sRGVmQ2xvbmVkLnBpdm90SW5kZXggPSBjb2wuaXNQaXZvdEFjdGl2ZSgpID8gcGl2b3RDb2x1bW5zLmluZGV4T2YoY29sKSA6IG51bGw7XG4gICAgICAgIGNvbERlZkNsb25lZC5hZ2dGdW5jID0gY29sLmlzVmFsdWVBY3RpdmUoKSA/IGNvbC5nZXRBZ2dGdW5jKCkgOiBudWxsO1xuICAgICAgICBjb2xEZWZDbG9uZWQuaGlkZSA9IGNvbC5pc1Zpc2libGUoKSA/IHVuZGVmaW5lZCA6IHRydWU7XG4gICAgICAgIGNvbERlZkNsb25lZC5waW5uZWQgPSBjb2wuaXNQaW5uZWQoKSA/IGNvbC5nZXRQaW5uZWQoKSA6IG51bGw7XG4gICAgICAgIGNvbERlZkNsb25lZC5zb3J0ID0gY29sLmdldFNvcnQoKSA/IGNvbC5nZXRTb3J0KCkgOiBudWxsO1xuICAgICAgICBjb2xEZWZDbG9uZWQuc29ydEluZGV4ID0gY29sLmdldFNvcnRJbmRleCgpICE9IG51bGwgPyBjb2wuZ2V0U29ydEluZGV4KCkgOiBudWxsO1xuICAgICAgICByZXR1cm4gY29sRGVmQ2xvbmVkO1xuICAgIH07XG4gICAgQ29sdW1uRGVmRmFjdG9yeSA9IF9fZGVjb3JhdGUkayhbXG4gICAgICAgIEJlYW4oJ2NvbHVtbkRlZkZhY3RvcnknKVxuICAgIF0sIENvbHVtbkRlZkZhY3RvcnkpO1xuICAgIHJldHVybiBDb2x1bW5EZWZGYWN0b3J5O1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZGVjb3JhdGUkaiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFJvd0Nzc0NsYXNzQ2FsY3VsYXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBSb3dDc3NDbGFzc0NhbGN1bGF0b3IoKSB7XG4gICAgfVxuICAgIFJvd0Nzc0NsYXNzQ2FsY3VsYXRvci5wcm90b3R5cGUuZ2V0SW5pdGlhbFJvd0NsYXNzZXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBjbGFzc2VzID0gW107XG4gICAgICAgIGlmIChleGlzdHMocGFyYW1zLmV4dHJhQ3NzQ2xhc3MpKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFyYW1zLmV4dHJhQ3NzQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICAgIGNsYXNzZXMucHVzaCgnYWctcm93Jyk7XG4gICAgICAgIGNsYXNzZXMucHVzaChwYXJhbXMucm93Rm9jdXNlZCA/ICdhZy1yb3ctZm9jdXMnIDogJ2FnLXJvdy1uby1mb2N1cycpO1xuICAgICAgICBpZiAocGFyYW1zLmZhZGVSb3dJbikge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhZy1vcGFjaXR5LXplcm8nKTtcbiAgICAgICAgfVxuICAgICAgICBjbGFzc2VzLnB1c2gocGFyYW1zLnJvd0lzRXZlbiA/ICdhZy1yb3ctZXZlbicgOiAnYWctcm93LW9kZCcpO1xuICAgICAgICBpZiAocGFyYW1zLnJvd05vZGUuaXNSb3dQaW5uZWQoKSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhZy1yb3ctcGlubmVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy5yb3dOb2RlLmlzU2VsZWN0ZWQoKSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhZy1yb3ctc2VsZWN0ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zLnJvd05vZGUuZm9vdGVyKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2FnLXJvdy1mb290ZXInKTtcbiAgICAgICAgfVxuICAgICAgICBjbGFzc2VzLnB1c2goJ2FnLXJvdy1sZXZlbC0nICsgcGFyYW1zLnJvd0xldmVsKTtcbiAgICAgICAgaWYgKHBhcmFtcy5yb3dOb2RlLnN0dWIpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnYWctcm93LWxvYWRpbmcnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zLmZ1bGxXaWR0aFJvdykge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhZy1mdWxsLXdpZHRoLXJvdycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJhbXMuZXhwYW5kYWJsZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhZy1yb3ctZ3JvdXAnKTtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJhbXMucm93Tm9kZS5leHBhbmRlZCA/ICdhZy1yb3ctZ3JvdXAtZXhwYW5kZWQnIDogJ2FnLXJvdy1ncm91cC1jb250cmFjdGVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcmFtcy5yb3dOb2RlLmRyYWdnaW5nKSB7XG4gICAgICAgICAgICBjbGFzc2VzLnB1c2goJ2FnLXJvdy1kcmFnZ2luZycpO1xuICAgICAgICB9XG4gICAgICAgIHB1c2hBbGwoY2xhc3NlcywgdGhpcy5wcm9jZXNzQ2xhc3Nlc0Zyb21HcmlkT3B0aW9ucyhwYXJhbXMucm93Tm9kZSkpO1xuICAgICAgICBwdXNoQWxsKGNsYXNzZXMsIHRoaXMucHJlUHJvY2Vzc1Jvd0NsYXNzUnVsZXMocGFyYW1zLnJvd05vZGUpKTtcbiAgICAgICAgLy8gd2UgdXNlIGFic29sdXRlIHBvc2l0aW9uIHVubGVzcyB3ZSBhcmUgZG9pbmcgcHJpbnQgbGF5b3V0XG4gICAgICAgIGNsYXNzZXMucHVzaChwYXJhbXMucHJpbnRMYXlvdXQgPyAnYWctcm93LXBvc2l0aW9uLXJlbGF0aXZlJyA6ICdhZy1yb3ctcG9zaXRpb24tYWJzb2x1dGUnKTtcbiAgICAgICAgaWYgKHBhcmFtcy5maXJzdFJvd09uUGFnZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKCdhZy1yb3ctZmlyc3QnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zLmxhc3RSb3dPblBhZ2UpIHtcbiAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnYWctcm93LWxhc3QnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFyYW1zLmZ1bGxXaWR0aFJvdykge1xuICAgICAgICAgICAgaWYgKHBhcmFtcy5waW5uZWQgPT09IENvbnN0YW50cy5QSU5ORURfTEVGVCkge1xuICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnYWctY2VsbC1sYXN0LWxlZnQtcGlubmVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFyYW1zLnBpbm5lZCA9PT0gQ29uc3RhbnRzLlBJTk5FRF9SSUdIVCkge1xuICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCgnYWctY2VsbC1maXJzdC1yaWdodC1waW5uZWQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2xhc3NlcztcbiAgICB9O1xuICAgIFJvd0Nzc0NsYXNzQ2FsY3VsYXRvci5wcm90b3R5cGUucHJvY2Vzc0NsYXNzZXNGcm9tR3JpZE9wdGlvbnMgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICB2YXIgcmVzID0gW107XG4gICAgICAgIHZhciBwcm9jZXNzID0gZnVuY3Rpb24gKHJvd0Nscykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByb3dDbHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2gocm93Q2xzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocm93Q2xzKSkge1xuICAgICAgICAgICAgICAgIHJvd0Nscy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7IHJldHVybiByZXMucHVzaChlKTsgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIHBhcnQgMSAtIHJvd0NsYXNzXG4gICAgICAgIHZhciByb3dDbGFzcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0NsYXNzKCk7XG4gICAgICAgIGlmIChyb3dDbGFzcykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByb3dDbGFzcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogcm93Q2xhc3Mgc2hvdWxkIG5vdCBiZSBhIGZ1bmN0aW9uLCBwbGVhc2UgdXNlIGdldFJvd0NsYXNzIGluc3RlYWQnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcm9jZXNzKHJvd0NsYXNzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwYXJ0IDIgLSByb3dDbGFzc0Z1bmNcbiAgICAgICAgdmFyIHJvd0NsYXNzRnVuYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0NsYXNzRnVuYygpO1xuICAgICAgICBpZiAocm93Q2xhc3NGdW5jKSB7XG4gICAgICAgICAgICB2YXIgcGFyYW1zID0ge1xuICAgICAgICAgICAgICAgIGRhdGE6IHJvd05vZGUuZGF0YSxcbiAgICAgICAgICAgICAgICBub2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgICAgIHJvd0luZGV4OiByb3dOb2RlLnJvd0luZGV4XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIHJvd0NsYXNzRnVuY1Jlc3VsdCA9IHJvd0NsYXNzRnVuYyhwYXJhbXMpO1xuICAgICAgICAgICAgcHJvY2Vzcyhyb3dDbGFzc0Z1bmNSZXN1bHQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSb3dDc3NDbGFzc0NhbGN1bGF0b3IucHJvdG90eXBlLnByZVByb2Nlc3NSb3dDbGFzc1J1bGVzID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB0aGlzLnByb2Nlc3NSb3dDbGFzc1J1bGVzKHJvd05vZGUsIGZ1bmN0aW9uIChjbGFzc05hbWUpIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKGNsYXNzTmFtZSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChjbGFzc05hbWUpIHtcbiAgICAgICAgICAgIC8vIG5vdCBjYXRlcmVkIGZvciwgaWYgY3JlYXRpbmcsIG5vIG5lZWRcbiAgICAgICAgICAgIC8vIHRvIHJlbW92ZSBjbGFzcyBhcyBpdCB3YXMgbmV2ZXIgdGhlcmVcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBSb3dDc3NDbGFzc0NhbGN1bGF0b3IucHJvdG90eXBlLnByb2Nlc3NSb3dDbGFzc1J1bGVzID0gZnVuY3Rpb24gKHJvd05vZGUsIG9uQXBwbGljYWJsZUNsYXNzLCBvbk5vdEFwcGxpY2FibGVDbGFzcykge1xuICAgICAgICB2YXIgcm93Q2xhc3NQYXJhbXMgPSB7XG4gICAgICAgICAgICBkYXRhOiByb3dOb2RlLmRhdGEsXG4gICAgICAgICAgICBub2RlOiByb3dOb2RlLFxuICAgICAgICAgICAgcm93SW5kZXg6IHJvd05vZGUucm93SW5kZXgsXG4gICAgICAgICAgICBhcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgY29sdW1uQXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN0eWxpbmdTZXJ2aWNlLnByb2Nlc3NDbGFzc1J1bGVzKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLnJvd0NsYXNzUnVsZXMoKSwgcm93Q2xhc3NQYXJhbXMsIG9uQXBwbGljYWJsZUNsYXNzLCBvbk5vdEFwcGxpY2FibGVDbGFzcyk7XG4gICAgfTtcbiAgICBSb3dDc3NDbGFzc0NhbGN1bGF0b3IucHJvdG90eXBlLmNhbGN1bGF0ZVJvd0xldmVsID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgaWYgKHJvd05vZGUuZ3JvdXApIHtcbiAgICAgICAgICAgIHJldHVybiByb3dOb2RlLmxldmVsO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIGEgbGVhZiwgYW5kIGEgcGFyZW50IGV4aXN0cywgcHV0IGEgbGV2ZWwgb2YgdGhlIHBhcmVudCwgZWxzZSBwdXQgbGV2ZWwgb2YgMCBmb3IgdG9wIGxldmVsIGl0ZW1cbiAgICAgICAgcmV0dXJuIHJvd05vZGUucGFyZW50ID8gKHJvd05vZGUucGFyZW50LmxldmVsICsgMSkgOiAwO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRqKFtcbiAgICAgICAgQXV0b3dpcmVkKCdzdHlsaW5nU2VydmljZScpXG4gICAgXSwgUm93Q3NzQ2xhc3NDYWxjdWxhdG9yLnByb3RvdHlwZSwgXCJzdHlsaW5nU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkaihbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZE9wdGlvbnNXcmFwcGVyJylcbiAgICBdLCBSb3dDc3NDbGFzc0NhbGN1bGF0b3IucHJvdG90eXBlLCBcImdyaWRPcHRpb25zV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIFJvd0Nzc0NsYXNzQ2FsY3VsYXRvciA9IF9fZGVjb3JhdGUkaihbXG4gICAgICAgIEJlYW4oJ3Jvd0Nzc0NsYXNzQ2FsY3VsYXRvcicpXG4gICAgXSwgUm93Q3NzQ2xhc3NDYWxjdWxhdG9yKTtcbiAgICByZXR1cm4gUm93Q3NzQ2xhc3NDYWxjdWxhdG9yO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZGVjb3JhdGUkaSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xuLy8gdGhpcyBsb2dpYyBpcyB1c2VkIGJ5IGJvdGggU1NSTSBhbmQgQ1NSTVxudmFyIFJvd05vZGVTb3J0ZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUm93Tm9kZVNvcnRlcigpIHtcbiAgICB9XG4gICAgUm93Tm9kZVNvcnRlci5wcm90b3R5cGUuZG9GdWxsU29ydCA9IGZ1bmN0aW9uIChyb3dOb2Rlcywgc29ydE9wdGlvbnMpIHtcbiAgICAgICAgdmFyIG1hcHBlciA9IGZ1bmN0aW9uIChyb3dOb2RlLCBwb3MpIHsgcmV0dXJuICh7IGN1cnJlbnRQb3M6IHBvcywgcm93Tm9kZTogcm93Tm9kZSB9KTsgfTtcbiAgICAgICAgdmFyIHNvcnRlZFJvd05vZGVzID0gcm93Tm9kZXMubWFwKG1hcHBlcik7XG4gICAgICAgIHNvcnRlZFJvd05vZGVzLnNvcnQodGhpcy5jb21wYXJlUm93Tm9kZXMuYmluZCh0aGlzLCBzb3J0T3B0aW9ucykpO1xuICAgICAgICByZXR1cm4gc29ydGVkUm93Tm9kZXMubWFwKGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiBpdGVtLnJvd05vZGU7IH0pO1xuICAgIH07XG4gICAgUm93Tm9kZVNvcnRlci5wcm90b3R5cGUuY29tcGFyZVJvd05vZGVzID0gZnVuY3Rpb24gKHNvcnRPcHRpb25zLCBzb3J0ZWROb2RlQSwgc29ydGVkTm9kZUIpIHtcbiAgICAgICAgdmFyIG5vZGVBID0gc29ydGVkTm9kZUEucm93Tm9kZTtcbiAgICAgICAgdmFyIG5vZGVCID0gc29ydGVkTm9kZUIucm93Tm9kZTtcbiAgICAgICAgLy8gSXRlcmF0ZSBjb2x1bW5zLCByZXR1cm4gdGhlIGZpcnN0IHRoYXQgZG9lc24ndCBtYXRjaFxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gc29ydE9wdGlvbnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzb3J0T3B0aW9uID0gc29ydE9wdGlvbnNbaV07XG4gICAgICAgICAgICB2YXIgaXNEZXNjZW5kaW5nID0gc29ydE9wdGlvbi5zb3J0ID09PSBDb25zdGFudHMuU09SVF9ERVNDO1xuICAgICAgICAgICAgdmFyIHZhbHVlQSA9IHRoaXMuZ2V0VmFsdWUobm9kZUEsIHNvcnRPcHRpb24uY29sdW1uKTtcbiAgICAgICAgICAgIHZhciB2YWx1ZUIgPSB0aGlzLmdldFZhbHVlKG5vZGVCLCBzb3J0T3B0aW9uLmNvbHVtbik7XG4gICAgICAgICAgICB2YXIgY29tcGFyYXRvclJlc3VsdCA9IHZvaWQgMDtcbiAgICAgICAgICAgIHZhciBwcm92aWRlZENvbXBhcmF0b3IgPSB0aGlzLmdldENvbXBhcmF0b3Ioc29ydE9wdGlvbiwgbm9kZUEpO1xuICAgICAgICAgICAgaWYgKHByb3ZpZGVkQ29tcGFyYXRvcikge1xuICAgICAgICAgICAgICAgIC8vaWYgY29tcGFyYXRvciBwcm92aWRlZCwgdXNlIGl0XG4gICAgICAgICAgICAgICAgY29tcGFyYXRvclJlc3VsdCA9IHByb3ZpZGVkQ29tcGFyYXRvcih2YWx1ZUEsIHZhbHVlQiwgbm9kZUEsIG5vZGVCLCBpc0Rlc2NlbmRpbmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy9vdGhlcndpc2UgZG8gb3VyIG93biBjb21wYXJpc29uXG4gICAgICAgICAgICAgICAgY29tcGFyYXRvclJlc3VsdCA9IF8uZGVmYXVsdENvbXBhcmF0b3IodmFsdWVBLCB2YWx1ZUIsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQWNjZW50ZWRTb3J0KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdXNlciBwcm92aWRlZCBjb21wYXJhdG9ycyBjYW4gcmV0dXJuICdOYU4nIGlmIHRoZXkgZG9uJ3QgY29ycmVjdGx5IGhhbmRsZSAndW5kZWZpbmVkJyB2YWx1ZXMsIHRoaXNcbiAgICAgICAgICAgIC8vIHR5cGljYWxseSBvY2N1cnMgd2hlbiB0aGUgY29tcGFyYXRvciBpcyB1c2VkIG9uIGEgZ3JvdXAgcm93XG4gICAgICAgICAgICB2YXIgdmFsaWRSZXN1bHQgPSAhaXNOYU4oY29tcGFyYXRvclJlc3VsdCk7XG4gICAgICAgICAgICBpZiAodmFsaWRSZXN1bHQgJiYgY29tcGFyYXRvclJlc3VsdCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzb3J0T3B0aW9uLnNvcnQgPT09IENvbnN0YW50cy5TT1JUX0FTQyA/IGNvbXBhcmF0b3JSZXN1bHQgOiBjb21wYXJhdG9yUmVzdWx0ICogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQWxsIG1hdGNoZWQsIHdlIG1ha2UgaXMgc28gdGhhdCB0aGUgb3JpZ2luYWwgc29ydCBvcmRlciBpcyBrZXB0OlxuICAgICAgICByZXR1cm4gc29ydGVkTm9kZUEuY3VycmVudFBvcyAtIHNvcnRlZE5vZGVCLmN1cnJlbnRQb3M7XG4gICAgfTtcbiAgICBSb3dOb2RlU29ydGVyLnByb3RvdHlwZS5nZXRDb21wYXJhdG9yID0gZnVuY3Rpb24gKHNvcnRPcHRpb24sIHJvd05vZGUpIHtcbiAgICAgICAgdmFyIGNvbHVtbiA9IHNvcnRPcHRpb24uY29sdW1uO1xuICAgICAgICAvLyBjb21wYXJhdG9yIG9uIGNvbCBnZXQgcHJlZmVyZW5jZSBvdmVyIGV2ZXJ5dGhpbmcgZWxzZVxuICAgICAgICB2YXIgY29tcGFyYXRvck9uQ29sID0gY29sdW1uLmdldENvbERlZigpLmNvbXBhcmF0b3I7XG4gICAgICAgIGlmIChjb21wYXJhdG9yT25Db2wgIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbXBhcmF0b3JPbkNvbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbHVtbi5nZXRDb2xEZWYoKS5zaG93Um93R3JvdXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBhICdmaWVsZCcgaXMgc3VwcGxpZWQgb24gdGhlIGF1dG9Hcm91cENvbHVtbkRlZiB3ZSBuZWVkIHRvIHVzZSB0aGUgYXNzb2NpYXRlZCBjb2x1bW4gY29tcGFyYXRvclxuICAgICAgICB2YXIgZ3JvdXBMZWFmRmllbGQgPSAhcm93Tm9kZS5ncm91cCAmJiBjb2x1bW4uZ2V0Q29sRGVmKCkuZmllbGQ7XG4gICAgICAgIGlmICghZ3JvdXBMZWFmRmllbGQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJpbWFyeUNvbHVtbiA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0UHJpbWFyeUNvbHVtbihncm91cExlYWZGaWVsZCk7XG4gICAgICAgIGlmICghcHJpbWFyeUNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcmltYXJ5Q29sdW1uLmdldENvbERlZigpLmNvbXBhcmF0b3I7XG4gICAgfTtcbiAgICBSb3dOb2RlU29ydGVyLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uIChub2RlLCBjb2x1bW4pIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgdmFyIHByaW1hcnlDb2x1bW5zU29ydEdyb3VwcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQ29sdW1uc1NvcnRpbmdDb3VwbGVkVG9Hcm91cCgpO1xuICAgICAgICBpZiAoIXByaW1hcnlDb2x1bW5zU29ydEdyb3Vwcykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVTZXJ2aWNlLmdldFZhbHVlKGNvbHVtbiwgbm9kZSwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNOb2RlR3JvdXBlZEF0TGV2ZWwgPSBub2RlLnJvd0dyb3VwQ29sdW1uID09PSBjb2x1bW47XG4gICAgICAgIGlmIChpc05vZGVHcm91cGVkQXRMZXZlbCkge1xuICAgICAgICAgICAgdmFyIGlzR3JvdXBSb3dzID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cFVzZUVudGlyZVJvdyh0aGlzLmNvbHVtbk1vZGVsLmlzUGl2b3RBY3RpdmUoKSk7XG4gICAgICAgICAgICBpZiAoaXNHcm91cFJvd3MpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgY29sdW1uIGhhcyBhIHByb3ZpZGVkIGEga2V5Q3JlYXRvciwgd2UgaGF2ZSB0byB1c2UgdGhlIGtleSwgYXMgdGhlIGdyb3VwIGNvdWxkIGJlXG4gICAgICAgICAgICAgICAgLy8gaXJyZWxldmFudCB0byB0aGUgY29sdW1uIHZhbHVlXG4gICAgICAgICAgICAgICAgdmFyIGtleUNyZWF0b3IgPSBjb2x1bW4uZ2V0Q29sRGVmKCkua2V5Q3JlYXRvcjtcbiAgICAgICAgICAgICAgICBpZiAoa2V5Q3JlYXRvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbm9kZS5rZXk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBncm91cCB3YXMgZ2VuZXJhdGVkIGZyb20gdGhlIGNvbHVtbiBkYXRhLCBhbGwgdGhlIGxlYWYgY2hpbGRyZW4gc2hvdWxkIHJldHVybiB0aGUgc2FtZVxuICAgICAgICAgICAgICAgIC8vIHZhbHVlXG4gICAgICAgICAgICAgICAgdmFyIGxlYWZDaGlsZCA9IChfYSA9IG5vZGUuYWxsTGVhZkNoaWxkcmVuKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2FbMF07XG4gICAgICAgICAgICAgICAgaWYgKGxlYWZDaGlsZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZVNlcnZpY2UuZ2V0VmFsdWUoY29sdW1uLCBsZWFmQ2hpbGQsIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGlzcGxheUNvbCA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0R3JvdXBEaXNwbGF5Q29sdW1uRm9yR3JvdXAoY29sdW1uLmdldElkKCkpO1xuICAgICAgICAgICAgaWYgKCFkaXNwbGF5Q29sKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAoX2IgPSBub2RlLmdyb3VwRGF0YSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iW2Rpc3BsYXlDb2wuZ2V0SWQoKV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5vZGUuZ3JvdXAgJiYgY29sdW1uLmdldENvbERlZigpLnNob3dSb3dHcm91cCkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZVNlcnZpY2UuZ2V0VmFsdWUoY29sdW1uLCBub2RlLCBmYWxzZSwgZmFsc2UpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRpKFtcbiAgICAgICAgQXV0b3dpcmVkKCdncmlkT3B0aW9uc1dyYXBwZXInKVxuICAgIF0sIFJvd05vZGVTb3J0ZXIucHJvdG90eXBlLCBcImdyaWRPcHRpb25zV3JhcHBlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkaShbXG4gICAgICAgIEF1dG93aXJlZCgndmFsdWVTZXJ2aWNlJylcbiAgICBdLCBSb3dOb2RlU29ydGVyLnByb3RvdHlwZSwgXCJ2YWx1ZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGkoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBSb3dOb2RlU29ydGVyLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIFJvd05vZGVTb3J0ZXIgPSBfX2RlY29yYXRlJGkoW1xuICAgICAgICBCZWFuKCdyb3dOb2RlU29ydGVyJylcbiAgICBdLCBSb3dOb2RlU29ydGVyKTtcbiAgICByZXR1cm4gUm93Tm9kZVNvcnRlcjtcbn0oKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkaSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkaCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEN0cmxzU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkaShDdHJsc1NlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gQ3RybHNTZXJ2aWNlKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMucmVhZHkgPSBmYWxzZTtcbiAgICAgICAgX3RoaXMucmVhZHlDYWxsYmFja3MgPSBbXTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBDdHJsc1NlcnZpY2VfMSA9IEN0cmxzU2VydmljZTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLmNoZWNrUmVhZHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVhZHkgPVxuICAgICAgICAgICAgdGhpcy5ncmlkQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5ncmlkQm9keUN0cmwgIT0gbnVsbFxuICAgICAgICAgICAgICAgICYmIHRoaXMuY2VudGVyUm93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5sZWZ0Um93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5yaWdodFJvd0NvbnRhaW5lckN0cmwgIT0gbnVsbFxuICAgICAgICAgICAgICAgICYmIHRoaXMuYm90dG9tQ2VudGVyUm93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5ib3R0b21MZWZ0Um93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5ib3R0b21SaWdodFJvd0NvbnRhaW5lckN0cmwgIT0gbnVsbFxuICAgICAgICAgICAgICAgICYmIHRoaXMudG9wQ2VudGVyUm93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy50b3BMZWZ0Um93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy50b3BSaWdodFJvd0NvbnRhaW5lckN0cmwgIT0gbnVsbFxuICAgICAgICAgICAgICAgICYmIHRoaXMuc3RpY2t5VG9wQ2VudGVyUm93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5zdGlja3lUb3BMZWZ0Um93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5zdGlja3lUb3BSaWdodFJvd0NvbnRhaW5lckN0cmwgIT0gbnVsbFxuICAgICAgICAgICAgICAgICYmIHRoaXMuY2VudGVySGVhZGVyUm93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5sZWZ0SGVhZGVyUm93Q29udGFpbmVyQ3RybCAhPSBudWxsXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5yaWdodEhlYWRlclJvd0NvbnRhaW5lckN0cmwgIT0gbnVsbFxuICAgICAgICAgICAgICAgICYmIHRoaXMuZmFrZUhTY3JvbGxDdHJsICE9IG51bGxcbiAgICAgICAgICAgICAgICAmJiB0aGlzLmdyaWRIZWFkZXJDdHJsICE9IG51bGw7XG4gICAgICAgIGlmICh0aGlzLnJlYWR5KSB7XG4gICAgICAgICAgICB2YXIgcF8xID0gdGhpcy5jcmVhdGVSZWFkeVBhcmFtcygpO1xuICAgICAgICAgICAgdGhpcy5yZWFkeUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjKHBfMSk7IH0pO1xuICAgICAgICAgICAgdGhpcy5yZWFkeUNhbGxiYWNrcy5sZW5ndGggPSAwO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLndoZW5SZWFkeSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICBpZiAodGhpcy5yZWFkeSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5jcmVhdGVSZWFkeVBhcmFtcygpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVhZHlDYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUuY3JlYXRlUmVhZHlQYXJhbXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjZW50ZXJSb3dDb250YWluZXJDdHJsOiB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBsZWZ0Um93Q29udGFpbmVyQ3RybDogdGhpcy5sZWZ0Um93Q29udGFpbmVyQ3RybCxcbiAgICAgICAgICAgIHJpZ2h0Um93Q29udGFpbmVyQ3RybDogdGhpcy5yaWdodFJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBib3R0b21DZW50ZXJSb3dDb250YWluZXJDdHJsOiB0aGlzLmJvdHRvbUNlbnRlclJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBib3R0b21MZWZ0Um93Q29udGFpbmVyQ3RybDogdGhpcy5ib3R0b21MZWZ0Um93Q29udGFpbmVyQ3RybCxcbiAgICAgICAgICAgIGJvdHRvbVJpZ2h0Um93Q29udGFpbmVyQ3RybDogdGhpcy5ib3R0b21SaWdodFJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICB0b3BDZW50ZXJSb3dDb250YWluZXJDdHJsOiB0aGlzLnRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICB0b3BMZWZ0Um93Q29udGFpbmVyQ3RybDogdGhpcy50b3BMZWZ0Um93Q29udGFpbmVyQ3RybCxcbiAgICAgICAgICAgIHRvcFJpZ2h0Um93Q29udGFpbmVyQ3RybDogdGhpcy50b3BSaWdodFJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBzdGlja3lUb3BDZW50ZXJSb3dDb250YWluZXJDdHJsOiB0aGlzLnN0aWNreVRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBzdGlja3lUb3BMZWZ0Um93Q29udGFpbmVyQ3RybDogdGhpcy5zdGlja3lUb3BMZWZ0Um93Q29udGFpbmVyQ3RybCxcbiAgICAgICAgICAgIHN0aWNreVRvcFJpZ2h0Um93Q29udGFpbmVyQ3RybDogdGhpcy5zdGlja3lUb3BSaWdodFJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBjZW50ZXJIZWFkZXJSb3dDb250YWluZXJDdHJsOiB0aGlzLmNlbnRlckhlYWRlclJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBsZWZ0SGVhZGVyUm93Q29udGFpbmVyQ3RybDogdGhpcy5sZWZ0SGVhZGVyUm93Q29udGFpbmVyQ3RybCxcbiAgICAgICAgICAgIHJpZ2h0SGVhZGVyUm93Q29udGFpbmVyQ3RybDogdGhpcy5yaWdodEhlYWRlclJvd0NvbnRhaW5lckN0cmwsXG4gICAgICAgICAgICBmYWtlSFNjcm9sbEN0cmw6IHRoaXMuZmFrZUhTY3JvbGxDdHJsLFxuICAgICAgICAgICAgZ3JpZEJvZHlDdHJsOiB0aGlzLmdyaWRCb2R5Q3RybCxcbiAgICAgICAgICAgIGdyaWRDdHJsOiB0aGlzLmdyaWRDdHJsLFxuICAgICAgICAgICAgZ3JpZEhlYWRlckN0cmw6IHRoaXMuZ3JpZEhlYWRlckN0cmwsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyRmFrZUhTY3JvbGxDdHJsID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy5mYWtlSFNjcm9sbEN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJHcmlkSGVhZGVyQ3RybCA9IGZ1bmN0aW9uIChncmlkSGVhZGVyQ3RybCkge1xuICAgICAgICB0aGlzLmdyaWRIZWFkZXJDdHJsID0gZ3JpZEhlYWRlckN0cmw7XG4gICAgICAgIHRoaXMuY2hlY2tSZWFkeSgpO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5yZWdpc3RlckNlbnRlclJvd0NvbnRhaW5lckN0cmwgPSBmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICB0aGlzLmNlbnRlclJvd0NvbnRhaW5lckN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJMZWZ0Um93Q29udGFpbmVyQ3RybCA9IGZ1bmN0aW9uIChjdHJsKSB7XG4gICAgICAgIHRoaXMubGVmdFJvd0NvbnRhaW5lckN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJSaWdodFJvd0NvbnRhaW5lckN0cmwgPSBmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICB0aGlzLnJpZ2h0Um93Q29udGFpbmVyQ3RybCA9IGN0cmw7XG4gICAgICAgIHRoaXMuY2hlY2tSZWFkeSgpO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5yZWdpc3RlclRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwgPSBmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICB0aGlzLnRvcENlbnRlclJvd0NvbnRhaW5lckN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJUb3BMZWZ0Um93Q29udGFpbmVyQ29uID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy50b3BMZWZ0Um93Q29udGFpbmVyQ3RybCA9IGN0cmw7XG4gICAgICAgIHRoaXMuY2hlY2tSZWFkeSgpO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5yZWdpc3RlclRvcFJpZ2h0Um93Q29udGFpbmVyQ3RybCA9IGZ1bmN0aW9uIChjdHJsKSB7XG4gICAgICAgIHRoaXMudG9wUmlnaHRSb3dDb250YWluZXJDdHJsID0gY3RybDtcbiAgICAgICAgdGhpcy5jaGVja1JlYWR5KCk7XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyU3RpY2t5VG9wQ2VudGVyUm93Q29udGFpbmVyQ3RybCA9IGZ1bmN0aW9uIChjdHJsKSB7XG4gICAgICAgIHRoaXMuc3RpY2t5VG9wQ2VudGVyUm93Q29udGFpbmVyQ3RybCA9IGN0cmw7XG4gICAgICAgIHRoaXMuY2hlY2tSZWFkeSgpO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5yZWdpc3RlclN0aWNreVRvcExlZnRSb3dDb250YWluZXJDb24gPSBmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICB0aGlzLnN0aWNreVRvcExlZnRSb3dDb250YWluZXJDdHJsID0gY3RybDtcbiAgICAgICAgdGhpcy5jaGVja1JlYWR5KCk7XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyU3RpY2t5VG9wUmlnaHRSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy5zdGlja3lUb3BSaWdodFJvd0NvbnRhaW5lckN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJCb3R0b21DZW50ZXJSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy5ib3R0b21DZW50ZXJSb3dDb250YWluZXJDdHJsID0gY3RybDtcbiAgICAgICAgdGhpcy5jaGVja1JlYWR5KCk7XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyQm90dG9tTGVmdFJvd0NvbnRhaW5lckN0cmwgPSBmdW5jdGlvbiAoY3RybCkge1xuICAgICAgICB0aGlzLmJvdHRvbUxlZnRSb3dDb250YWluZXJDdHJsID0gY3RybDtcbiAgICAgICAgdGhpcy5jaGVja1JlYWR5KCk7XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyQm90dG9tUmlnaHRSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy5ib3R0b21SaWdodFJvd0NvbnRhaW5lckN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJIZWFkZXJDb250YWluZXIgPSBmdW5jdGlvbiAoY3RybCwgcGlubmVkKSB7XG4gICAgICAgIHN3aXRjaCAocGlubmVkKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfTEVGVDpcbiAgICAgICAgICAgICAgICB0aGlzLmxlZnRIZWFkZXJSb3dDb250YWluZXJDdHJsID0gY3RybDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ29uc3RhbnRzLlBJTk5FRF9SSUdIVDpcbiAgICAgICAgICAgICAgICB0aGlzLnJpZ2h0SGVhZGVyUm93Q29udGFpbmVyQ3RybCA9IGN0cmw7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRoaXMuY2VudGVySGVhZGVyUm93Q29udGFpbmVyQ3RybCA9IGN0cmw7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jaGVja1JlYWR5KCk7XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLnJlZ2lzdGVyR3JpZEJvZHlDdHJsID0gZnVuY3Rpb24gKGN0cmwpIHtcbiAgICAgICAgdGhpcy5ncmlkQm9keUN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUucmVnaXN0ZXJHcmlkQ3RybCA9IGZ1bmN0aW9uIChjdHJsKSB7XG4gICAgICAgIHRoaXMuZ3JpZEN0cmwgPSBjdHJsO1xuICAgICAgICB0aGlzLmNoZWNrUmVhZHkoKTtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUuZ2V0RmFrZUhTY3JvbGxDdHJsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5mYWtlSFNjcm9sbEN0cmw7XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLmdldEdyaWRIZWFkZXJDdHJsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkSGVhZGVyQ3RybDtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUuZ2V0R3JpZEN0cmwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRDdHJsO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5nZXRDZW50ZXJSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jZW50ZXJSb3dDb250YWluZXJDdHJsO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5nZXRUb3BDZW50ZXJSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b3BDZW50ZXJSb3dDb250YWluZXJDdHJsO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5nZXRCb3R0b21DZW50ZXJSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ib3R0b21DZW50ZXJSb3dDb250YWluZXJDdHJsO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5nZXRTdGlja3lUb3BDZW50ZXJSb3dDb250YWluZXJDdHJsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGlja3lUb3BDZW50ZXJSb3dDb250YWluZXJDdHJsO1xuICAgIH07XG4gICAgQ3RybHNTZXJ2aWNlLnByb3RvdHlwZS5nZXRHcmlkQm9keUN0cmwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRCb2R5Q3RybDtcbiAgICB9O1xuICAgIEN0cmxzU2VydmljZS5wcm90b3R5cGUuZ2V0SGVhZGVyUm93Q29udGFpbmVyQ3RybHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBbdGhpcy5sZWZ0SGVhZGVyUm93Q29udGFpbmVyQ3RybCwgdGhpcy5yaWdodEhlYWRlclJvd0NvbnRhaW5lckN0cmwsIHRoaXMuY2VudGVySGVhZGVyUm93Q29udGFpbmVyQ3RybF07XG4gICAgfTtcbiAgICBDdHJsc1NlcnZpY2UucHJvdG90eXBlLmdldEhlYWRlclJvd0NvbnRhaW5lckN0cmwgPSBmdW5jdGlvbiAocGlubmVkKSB7XG4gICAgICAgIHN3aXRjaCAocGlubmVkKSB7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfTEVGVDogcmV0dXJuIHRoaXMubGVmdEhlYWRlclJvd0NvbnRhaW5lckN0cmw7XG4gICAgICAgICAgICBjYXNlIENvbnN0YW50cy5QSU5ORURfUklHSFQ6IHJldHVybiB0aGlzLnJpZ2h0SGVhZGVyUm93Q29udGFpbmVyQ3RybDtcbiAgICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiB0aGlzLmNlbnRlckhlYWRlclJvd0NvbnRhaW5lckN0cmw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHZhciBDdHJsc1NlcnZpY2VfMTtcbiAgICBDdHJsc1NlcnZpY2UuTkFNRSA9ICdjdHJsc1NlcnZpY2UnO1xuICAgIEN0cmxzU2VydmljZSA9IEN0cmxzU2VydmljZV8xID0gX19kZWNvcmF0ZSRoKFtcbiAgICAgICAgQmVhbihDdHJsc1NlcnZpY2VfMS5OQU1FKVxuICAgIF0sIEN0cmxzU2VydmljZSk7XG4gICAgcmV0dXJuIEN0cmxzU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRoID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRnID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ3RybHNGYWN0b3J5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRoKEN0cmxzRmFjdG9yeSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDdHJsc0ZhY3RvcnkoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5yZWdpc3RyeSA9IHt9O1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEN0cmxzRmFjdG9yeS5wcm90b3R5cGUucmVnaXN0ZXIgPSBmdW5jdGlvbiAobWV0YSkge1xuICAgICAgICB0aGlzLnJlZ2lzdHJ5W21ldGEuY29udHJvbGxlck5hbWVdID0gbWV0YS5jb250cm9sbGVyQ2xhc3M7XG4gICAgfTtcbiAgICBDdHJsc0ZhY3RvcnkucHJvdG90eXBlLmdldEluc3RhbmNlID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgdmFyIENvbnRyb2xsZXJDbGFzcyA9IHRoaXMucmVnaXN0cnlbbmFtZV07XG4gICAgICAgIGlmIChDb250cm9sbGVyQ2xhc3MgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IENvbnRyb2xsZXJDbGFzcygpO1xuICAgIH07XG4gICAgQ3RybHNGYWN0b3J5ID0gX19kZWNvcmF0ZSRnKFtcbiAgICAgICAgQmVhbignY3RybHNGYWN0b3J5JylcbiAgICBdLCBDdHJsc0ZhY3RvcnkpO1xuICAgIHJldHVybiBDdHJsc0ZhY3Rvcnk7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkZyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkZiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEZha2VIU2Nyb2xsQ3RybCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkZyhGYWtlSFNjcm9sbEN0cmwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRmFrZUhTY3JvbGxDdHJsKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUuc2V0Q29tcCA9IGZ1bmN0aW9uICh2aWV3LCBlR3VpLCBlVmlld3BvcnQsIGVDb250YWluZXIpIHtcbiAgICAgICAgdGhpcy52aWV3ID0gdmlldztcbiAgICAgICAgdGhpcy5lVmlld3BvcnQgPSBlVmlld3BvcnQ7XG4gICAgICAgIHRoaXMuZUNvbnRhaW5lciA9IGVDb250YWluZXI7XG4gICAgICAgIHRoaXMuZUd1aSA9IGVHdWk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfU0NST0xMX1ZJU0lCSUxJVFlfQ0hBTkdFRCwgdGhpcy5vblNjcm9sbFZpc2liaWxpdHlDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICAvLyBXaGVuIGRvaW5nIHByaW50aW5nLCB0aGlzIGNoYW5nZXMgd2hldGhlciBjb2xzIGFyZSBwaW5uZWQgb3Igbm90XG4gICAgICAgIHZhciBzcGFjZXJXaWR0aHNMaXN0ZW5lciA9IHRoaXMuc2V0RmFrZUhTY3JvbGxTcGFjZXJXaWR0aHMuYmluZCh0aGlzKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19DSEFOR0VELCBzcGFjZXJXaWR0aHNMaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRElTUExBWUVEX0NPTFVNTlNfV0lEVEhfQ0hBTkdFRCwgc3BhY2VyV2lkdGhzTGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfRE9NX0xBWU9VVCwgc3BhY2VyV2lkdGhzTGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1BJTk5FRF9ST1dfREFUQV9DSEFOR0VELCB0aGlzLm9uUGlubmVkUm93RGF0YUNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMub25TY3JvbGxWaXNpYmlsaXR5Q2hhbmdlZCgpO1xuICAgICAgICB0aGlzLmN0cmxzU2VydmljZS5yZWdpc3RlckZha2VIU2Nyb2xsQ3RybCh0aGlzKTtcbiAgICAgICAgdGhpcy52aWV3LmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWFwcGxlLXNjcm9sbGJhcicsIGlzTWFjT3NVc2VyQWdlbnQoKSB8fCBpc0lPU1VzZXJBZ2VudCgpKTtcbiAgICB9O1xuICAgIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUuYWRkQWN0aXZlTGlzdGVuZXJUb2dnbGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgYWN0aXZhdGVFdmVudHMgPSBbJ21vdXNlZW50ZXInLCAnbW91c2Vkb3duJywgJ3RvdWNoc3RhcnQnXTtcbiAgICAgICAgdmFyIGRlYWN0aXZhdGVFdmVudHMgPSBbJ21vdXNlbGVhdmUnLCAndG91Y2hlbmQnXTtcbiAgICAgICAgYWN0aXZhdGVFdmVudHMuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnROYW1lKSB7IHJldHVybiBfdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIoX3RoaXMuZUd1aSwgZXZlbnROYW1lLCBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy52aWV3LmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLXNjcm9sbGJhci1hY3RpdmUnLCB0cnVlKTsgfSk7IH0pO1xuICAgICAgICBkZWFjdGl2YXRlRXZlbnRzLmZvckVhY2goZnVuY3Rpb24gKGV2ZW50TmFtZSkgeyByZXR1cm4gX3RoaXMuYWRkTWFuYWdlZExpc3RlbmVyKF90aGlzLmVHdWksIGV2ZW50TmFtZSwgZnVuY3Rpb24gKCkgeyByZXR1cm4gX3RoaXMudmlldy5hZGRPclJlbW92ZUNzc0NsYXNzKCdhZy1zY3JvbGxiYXItYWN0aXZlJywgZmFsc2UpOyB9KTsgfSk7XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLmluaXRpYWxpc2VJbnZpc2libGVTY3JvbGxiYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmludmlzaWJsZVNjcm9sbGJhciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbmFibGVSdGwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0VuYWJsZVJ0bCgpO1xuICAgICAgICB0aGlzLmludmlzaWJsZVNjcm9sbGJhciA9IGlzSW52aXNpYmxlU2Nyb2xsYmFyKCk7XG4gICAgICAgIGlmICh0aGlzLmludmlzaWJsZVNjcm9sbGJhcikge1xuICAgICAgICAgICAgdGhpcy5oaWRlQW5kU2hvd0ludmlzaWJsZVNjcm9sbEFzTmVlZGVkKCk7XG4gICAgICAgICAgICB0aGlzLmFkZEFjdGl2ZUxpc3RlbmVyVG9nZ2xlcygpO1xuICAgICAgICAgICAgdGhpcy5yZWZyZXNoQ29tcEJvdHRvbSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLm9uUGlubmVkUm93RGF0YUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVmcmVzaENvbXBCb3R0b20oKTtcbiAgICB9O1xuICAgIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUucmVmcmVzaENvbXBCb3R0b20gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbnZpc2libGVTY3JvbGxiYXIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYm90dG9tUGlubmVkSGVpZ2h0ID0gdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Ub3RhbEhlaWdodCgpO1xuICAgICAgICB0aGlzLnZpZXcuc2V0Qm90dG9tKGJvdHRvbVBpbm5lZEhlaWdodCk7XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLm9uU2Nyb2xsVmlzaWJpbGl0eUNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGluaXRpYWxpc2VJbnZpc2libGVTY3JvbGxiYXIgc2hvdWxkIG9ubHkgYmUgY2FsbGVkIG9uY2UsIGJ1dCB0aGUgcmVhc29uXG4gICAgICAgIC8vIHRoaXMgY2FuJ3QgYmUgaW5zaWRlIGBzZXRDb21wYCBvciBgUG9zdENvbnN0cnVjdGAgaXMgdGhlIERPTSBtaWdodCBub3RcbiAgICAgICAgLy8gYmUgcmVhZHksIHNvIHdlIGNhbGwgaXQgdW50aWwgZXZlbnR1YWxseSwgaXQgZ2V0cyBjYWxjdWxhdGVkLlxuICAgICAgICBpZiAodGhpcy5pbnZpc2libGVTY3JvbGxiYXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXNlSW52aXNpYmxlU2Nyb2xsYmFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRTY3JvbGxWaXNpYmxlKCk7XG4gICAgICAgIHRoaXMuc2V0RmFrZUhTY3JvbGxTcGFjZXJXaWR0aHMoKTtcbiAgICB9O1xuICAgIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUuaGlkZUFuZFNob3dJbnZpc2libGVTY3JvbGxBc05lZWRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9CT0RZX1NDUk9MTCwgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAgICAgaWYgKHBhcmFtcy5kaXJlY3Rpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgICAgIF90aGlzLnZpZXcuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctc2Nyb2xsYmFyLXNjcm9sbGluZycsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9CT0RZX1NDUk9MTF9FTkQsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIF90aGlzLnZpZXcuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctc2Nyb2xsYmFyLXNjcm9sbGluZycsIGZhbHNlKTsgfSk7XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLnNldEZha2VIU2Nyb2xsU3BhY2VyV2lkdGhzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdlNjcm9sbFNob3dpbmcgPSB0aGlzLnNjcm9sbFZpc2libGVTZXJ2aWNlLmlzVmVydGljYWxTY3JvbGxTaG93aW5nKCk7XG4gICAgICAgIC8vIHdlIHBhZCB0aGUgcmlnaHQgYmFzZWQgb24gYSkgaWYgY29scyBhcmUgcGlubmVkIHRvIHRoZSByaWdodCBhbmRcbiAgICAgICAgLy8gYikgaWYgdiBzY3JvbGwgaXMgc2hvd2luZyBvbiB0aGUgcmlnaHQgKG5vcm1hbCBwb3NpdGlvbiBvZiBzY3JvbGwpXG4gICAgICAgIHZhciByaWdodFNwYWNpbmcgPSB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbHVtbnNSaWdodFdpZHRoKCk7XG4gICAgICAgIHZhciBzY3JvbGxPblJpZ2h0ID0gIXRoaXMuZW5hYmxlUnRsICYmIHZTY3JvbGxTaG93aW5nO1xuICAgICAgICB2YXIgc2Nyb2xsYmFyV2lkdGggPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRTY3JvbGxiYXJXaWR0aCgpO1xuICAgICAgICBpZiAoc2Nyb2xsT25SaWdodCkge1xuICAgICAgICAgICAgcmlnaHRTcGFjaW5nICs9IHNjcm9sbGJhcldpZHRoO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudmlldy5zZXRSaWdodFNwYWNlckZpeGVkV2lkdGgocmlnaHRTcGFjaW5nKTtcbiAgICAgICAgdGhpcy52aWV3LmluY2x1ZGVSaWdodFNwYWNlclNjcm9sbGVyQ3NzKCdhZy1zY3JvbGxlci1jb3JuZXInLCByaWdodFNwYWNpbmcgPD0gc2Nyb2xsYmFyV2lkdGgpO1xuICAgICAgICAvLyB3ZSBwYWQgdGhlIGxlZnQgYmFzZWQgb24gYSkgaWYgY29scyBhcmUgcGlubmVkIHRvIHRoZSBsZWZ0IGFuZFxuICAgICAgICAvLyBiKSBpZiB2IHNjcm9sbCBpcyBzaG93aW5nIG9uIHRoZSBsZWZ0IChoYXBwZW5zIGluIExUUiBsYXlvdXQgb25seSlcbiAgICAgICAgdmFyIGxlZnRTcGFjaW5nID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXREaXNwbGF5ZWRDb2x1bW5zTGVmdFdpZHRoKCk7XG4gICAgICAgIHZhciBzY3JvbGxPbkxlZnQgPSB0aGlzLmVuYWJsZVJ0bCAmJiB2U2Nyb2xsU2hvd2luZztcbiAgICAgICAgaWYgKHNjcm9sbE9uTGVmdCkge1xuICAgICAgICAgICAgbGVmdFNwYWNpbmcgKz0gc2Nyb2xsYmFyV2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52aWV3LnNldExlZnRTcGFjZXJGaXhlZFdpZHRoKGxlZnRTcGFjaW5nKTtcbiAgICAgICAgdGhpcy52aWV3LmluY2x1ZGVMZWZ0U3BhY2VyU2Nyb2xsZXJDc3MoJ2FnLXNjcm9sbGVyLWNvcm5lcicsIGxlZnRTcGFjaW5nIDw9IHNjcm9sbGJhcldpZHRoKTtcbiAgICB9O1xuICAgIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUuc2V0U2Nyb2xsVmlzaWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGhTY3JvbGxTaG93aW5nID0gdGhpcy5zY3JvbGxWaXNpYmxlU2VydmljZS5pc0hvcml6b250YWxTY3JvbGxTaG93aW5nKCk7XG4gICAgICAgIHZhciBpbnZpc2libGVTY3JvbGxiYXIgPSB0aGlzLmludmlzaWJsZVNjcm9sbGJhcjtcbiAgICAgICAgdmFyIGlzU3VwcHJlc3NIb3Jpem9udGFsU2Nyb2xsID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0hvcml6b250YWxTY3JvbGwoKTtcbiAgICAgICAgdmFyIHNjcm9sbGJhcldpZHRoID0gaFNjcm9sbFNob3dpbmcgPyAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0U2Nyb2xsYmFyV2lkdGgoKSB8fCAwKSA6IDA7XG4gICAgICAgIHZhciBhZGp1c3RlZFNjcm9sbGJhcldpZHRoID0gKHNjcm9sbGJhcldpZHRoID09PSAwICYmIGludmlzaWJsZVNjcm9sbGJhcikgPyAxNSA6IHNjcm9sbGJhcldpZHRoO1xuICAgICAgICB2YXIgc2Nyb2xsQ29udGFpbmVyU2l6ZSA9ICFpc1N1cHByZXNzSG9yaXpvbnRhbFNjcm9sbCA/IGFkanVzdGVkU2Nyb2xsYmFyV2lkdGggOiAwO1xuICAgICAgICB0aGlzLnZpZXcuYWRkT3JSZW1vdmVDc3NDbGFzcygnYWctc2Nyb2xsYmFyLWludmlzaWJsZScsIGludmlzaWJsZVNjcm9sbGJhcik7XG4gICAgICAgIHRoaXMudmlldy5zZXRIZWlnaHQoc2Nyb2xsQ29udGFpbmVyU2l6ZSk7XG4gICAgICAgIHRoaXMudmlldy5zZXRWaWV3cG9ydEhlaWdodChzY3JvbGxDb250YWluZXJTaXplKTtcbiAgICAgICAgdGhpcy52aWV3LnNldENvbnRhaW5lckhlaWdodChzY3JvbGxDb250YWluZXJTaXplKTtcbiAgICAgICAgdGhpcy52aWV3LmFkZE9yUmVtb3ZlQ3NzQ2xhc3MoJ2FnLWhpZGRlbicsICFoU2Nyb2xsU2hvd2luZyk7XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLmdldFZpZXdwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lVmlld3BvcnQ7XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLmdldENvbnRhaW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZUNvbnRhaW5lcjtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUkZihbXG4gICAgICAgIEF1dG93aXJlZCgnc2Nyb2xsVmlzaWJsZVNlcnZpY2UnKVxuICAgIF0sIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUsIFwic2Nyb2xsVmlzaWJsZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGYoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBGYWtlSFNjcm9sbEN0cmwucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRmKFtcbiAgICAgICAgQXV0b3dpcmVkKCdjdHJsc1NlcnZpY2UnKVxuICAgIF0sIEZha2VIU2Nyb2xsQ3RybC5wcm90b3R5cGUsIFwiY3RybHNTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRmKFtcbiAgICAgICAgQXV0b3dpcmVkKCdwaW5uZWRSb3dNb2RlbCcpXG4gICAgXSwgRmFrZUhTY3JvbGxDdHJsLnByb3RvdHlwZSwgXCJwaW5uZWRSb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIHJldHVybiBGYWtlSFNjcm9sbEN0cmw7XG59KEJlYW5TdHViKSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkZiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkZSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEZha2VIU2Nyb2xsQ29tcCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkZihGYWtlSFNjcm9sbENvbXAsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRmFrZUhTY3JvbGxDb21wKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgRmFrZUhTY3JvbGxDb21wLlRFTVBMQVRFKSB8fCB0aGlzO1xuICAgIH1cbiAgICBGYWtlSFNjcm9sbENvbXAucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBjb21wUHJveHkgPSB7XG4gICAgICAgICAgICBhZGRPclJlbW92ZUNzc0NsYXNzOiBmdW5jdGlvbiAoY3NzQ2xhc3NOYW1lLCBvbikgeyByZXR1cm4gX3RoaXMuYWRkT3JSZW1vdmVDc3NDbGFzcyhjc3NDbGFzc05hbWUsIG9uKTsgfSxcbiAgICAgICAgICAgIHNldEhlaWdodDogZnVuY3Rpb24gKGhlaWdodCkgeyByZXR1cm4gc2V0Rml4ZWRIZWlnaHQoX3RoaXMuZ2V0R3VpKCksIGhlaWdodCk7IH0sXG4gICAgICAgICAgICBzZXRCb3R0b206IGZ1bmN0aW9uIChib3R0b20pIHsgcmV0dXJuIF90aGlzLmdldEd1aSgpLnN0eWxlLmJvdHRvbSA9IGJvdHRvbSArIFwicHhcIjsgfSxcbiAgICAgICAgICAgIHNldENvbnRhaW5lckhlaWdodDogZnVuY3Rpb24gKGhlaWdodCkgeyByZXR1cm4gc2V0Rml4ZWRIZWlnaHQoX3RoaXMuZUNvbnRhaW5lciwgaGVpZ2h0KTsgfSxcbiAgICAgICAgICAgIHNldFZpZXdwb3J0SGVpZ2h0OiBmdW5jdGlvbiAoaGVpZ2h0KSB7IHJldHVybiBzZXRGaXhlZEhlaWdodChfdGhpcy5lVmlld3BvcnQsIGhlaWdodCk7IH0sXG4gICAgICAgICAgICBzZXRSaWdodFNwYWNlckZpeGVkV2lkdGg6IGZ1bmN0aW9uICh3aWR0aCkgeyByZXR1cm4gc2V0Rml4ZWRXaWR0aChfdGhpcy5lUmlnaHRTcGFjZXIsIHdpZHRoKTsgfSxcbiAgICAgICAgICAgIHNldExlZnRTcGFjZXJGaXhlZFdpZHRoOiBmdW5jdGlvbiAod2lkdGgpIHsgcmV0dXJuIHNldEZpeGVkV2lkdGgoX3RoaXMuZUxlZnRTcGFjZXIsIHdpZHRoKTsgfSxcbiAgICAgICAgICAgIGluY2x1ZGVMZWZ0U3BhY2VyU2Nyb2xsZXJDc3M6IGZ1bmN0aW9uIChjc3NDbGFzcywgaW5jbHVkZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5lTGVmdFNwYWNlci5jbGFzc0xpc3QudG9nZ2xlKGNzc0NsYXNzLCBpbmNsdWRlKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbmNsdWRlUmlnaHRTcGFjZXJTY3JvbGxlckNzczogZnVuY3Rpb24gKGNzc0NsYXNzLCBpbmNsdWRlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmVSaWdodFNwYWNlci5jbGFzc0xpc3QudG9nZ2xlKGNzc0NsYXNzLCBpbmNsdWRlKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHZhciBjdHJsID0gdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgRmFrZUhTY3JvbGxDdHJsKCkpO1xuICAgICAgICBjdHJsLnNldENvbXAoY29tcFByb3h5LCB0aGlzLmdldEd1aSgpLCB0aGlzLmVWaWV3cG9ydCwgdGhpcy5lQ29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5jcmVhdGVNYW5hZ2VkQmVhbihuZXcgQ2VudGVyV2lkdGhGZWF0dXJlKGZ1bmN0aW9uICh3aWR0aCkgeyByZXR1cm4gX3RoaXMuZUNvbnRhaW5lci5zdHlsZS53aWR0aCA9IHdpZHRoICsgXCJweFwiOyB9KSk7XG4gICAgfTtcbiAgICBGYWtlSFNjcm9sbENvbXAuVEVNUExBVEUgPSBcIjxkaXYgY2xhc3M9XFxcImFnLWJvZHktaG9yaXpvbnRhbC1zY3JvbGxcXFwiIGFyaWEtaGlkZGVuPVxcXCJ0cnVlXFxcIj5cXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1ob3Jpem9udGFsLWxlZnQtc3BhY2VyXFxcIiByZWY9XFxcImVMZWZ0U3BhY2VyXFxcIj48L2Rpdj5cXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhZy1ib2R5LWhvcml6b250YWwtc2Nyb2xsLXZpZXdwb3J0XFxcIiByZWY9XFxcImVWaWV3cG9ydFxcXCI+XFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLWJvZHktaG9yaXpvbnRhbC1zY3JvbGwtY29udGFpbmVyXFxcIiByZWY9XFxcImVDb250YWluZXJcXFwiPjwvZGl2PlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImFnLWhvcml6b250YWwtcmlnaHQtc3BhY2VyXFxcIiByZWY9XFxcImVSaWdodFNwYWNlclxcXCI+PC9kaXY+XFxuICAgICAgICA8L2Rpdj5cIjtcbiAgICBfX2RlY29yYXRlJGUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZUxlZnRTcGFjZXInKVxuICAgIF0sIEZha2VIU2Nyb2xsQ29tcC5wcm90b3R5cGUsIFwiZUxlZnRTcGFjZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGUoW1xuICAgICAgICBSZWZTZWxlY3RvcignZVJpZ2h0U3BhY2VyJylcbiAgICBdLCBGYWtlSFNjcm9sbENvbXAucHJvdG90eXBlLCBcImVSaWdodFNwYWNlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkZShbXG4gICAgICAgIFJlZlNlbGVjdG9yKCdlVmlld3BvcnQnKVxuICAgIF0sIEZha2VIU2Nyb2xsQ29tcC5wcm90b3R5cGUsIFwiZVZpZXdwb3J0XCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRlKFtcbiAgICAgICAgUmVmU2VsZWN0b3IoJ2VDb250YWluZXInKVxuICAgIF0sIEZha2VIU2Nyb2xsQ29tcC5wcm90b3R5cGUsIFwiZUNvbnRhaW5lclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkZShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBGYWtlSFNjcm9sbENvbXAucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEZha2VIU2Nyb2xsQ29tcDtcbn0oQ29tcG9uZW50KSk7XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBfX2V4dGVuZHMkZSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkZCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIFBpbm5lZFdpZHRoU2VydmljZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkZShQaW5uZWRXaWR0aFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUGlubmVkV2lkdGhTZXJ2aWNlKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIFBpbm5lZFdpZHRoU2VydmljZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVyID0gdGhpcy5jaGVja0NvbnRhaW5lcldpZHRocy5iaW5kKHRoaXMpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0RJU1BMQVlFRF9DT0xVTU5TX0NIQU5HRUQsIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9ESVNQTEFZRURfQ09MVU1OU19XSURUSF9DSEFOR0VELCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCBHcmlkT3B0aW9uc1dyYXBwZXIuUFJPUF9ET01fTEFZT1VULCBsaXN0ZW5lcik7XG4gICAgfTtcbiAgICBQaW5uZWRXaWR0aFNlcnZpY2UucHJvdG90eXBlLmNoZWNrQ29udGFpbmVyV2lkdGhzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcHJpbnRMYXlvdXQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREb21MYXlvdXQoKSA9PT0gQ29uc3RhbnRzLkRPTV9MQVlPVVRfUFJJTlQ7XG4gICAgICAgIHZhciBuZXdMZWZ0V2lkdGggPSBwcmludExheW91dCA/IDAgOiB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbHVtbnNMZWZ0V2lkdGgoKTtcbiAgICAgICAgdmFyIG5ld1JpZ2h0V2lkdGggPSBwcmludExheW91dCA/IDAgOiB0aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXllZENvbHVtbnNSaWdodFdpZHRoKCk7XG4gICAgICAgIGlmIChuZXdMZWZ0V2lkdGggIT0gdGhpcy5sZWZ0V2lkdGgpIHtcbiAgICAgICAgICAgIHRoaXMubGVmdFdpZHRoID0gbmV3TGVmdFdpZHRoO1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudCh7IHR5cGU6IEV2ZW50cy5FVkVOVF9MRUZUX1BJTk5FRF9XSURUSF9DSEFOR0VEIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXdSaWdodFdpZHRoICE9IHRoaXMucmlnaHRXaWR0aCkge1xuICAgICAgICAgICAgdGhpcy5yaWdodFdpZHRoID0gbmV3UmlnaHRXaWR0aDtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoeyB0eXBlOiBFdmVudHMuRVZFTlRfUklHSFRfUElOTkVEX1dJRFRIX0NIQU5HRUQgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFBpbm5lZFdpZHRoU2VydmljZS5wcm90b3R5cGUuZ2V0UGlubmVkUmlnaHRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmlnaHRXaWR0aDtcbiAgICB9O1xuICAgIFBpbm5lZFdpZHRoU2VydmljZS5wcm90b3R5cGUuZ2V0UGlubmVkTGVmdFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sZWZ0V2lkdGg7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJGQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBQaW5uZWRXaWR0aFNlcnZpY2UucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRkKFtcbiAgICAgICAgUG9zdENvbnN0cnVjdFxuICAgIF0sIFBpbm5lZFdpZHRoU2VydmljZS5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICBQaW5uZWRXaWR0aFNlcnZpY2UgPSBfX2RlY29yYXRlJGQoW1xuICAgICAgICBCZWFuKCdwaW5uZWRXaWR0aFNlcnZpY2UnKVxuICAgIF0sIFBpbm5lZFdpZHRoU2VydmljZSk7XG4gICAgcmV0dXJuIFBpbm5lZFdpZHRoU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fZXh0ZW5kcyRkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRjID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgUm93Tm9kZUV2ZW50VGhyb3R0bGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJGQoUm93Tm9kZUV2ZW50VGhyb3R0bGUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gUm93Tm9kZUV2ZW50VGhyb3R0bGUoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5ldmVudHMgPSBbXTtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBSb3dOb2RlRXZlbnRUaHJvdHRsZS5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucm93TW9kZWwuZ2V0VHlwZSgpID09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERSkge1xuICAgICAgICAgICAgdGhpcy5jbGllbnRTaWRlUm93TW9kZWwgPSB0aGlzLnJvd01vZGVsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBiZWNhdXNlIHRoZSB1c2VyIGNhbiBjYWxsIHJvd05vZGUuc2V0RXhwYW5kZWQoKSBtYW55IHRpbWVzIGluIG9uZSBWTSB0dXJuLFxuICAgIC8vIHdlIHRocm90dGxlIHRoZSBjYWxscyB0byBDbGllbnRTaWRlUm93TW9kZWwgdXNpbmcgYW5pbWF0aW9uRnJhbWVTZXJ2aWNlLiB0aGlzIG1lYW5zIGZvciAxMDBcbiAgICAvLyByb3cgbm9kZXMgZ2V0dGluZyBleHBhbmRlZCwgd2Ugb25seSB1cGRhdGUgdGhlIENTUk0gb25jZSwgYW5kIHRoZW4gd2UgZmlyZSBhbGwgZXZlbnRzIGFmdGVyXG4gICAgLy8gQ1NSTSBoYXMgdXBkYXRlZC5cbiAgICAvL1xuICAgIC8vIGlmIHdlIGRpZCBub3QgZG8gdGhpcywgdGhlbiB0aGUgdXNlciBjb3VsZCBjYWxsIHNldEV4cGFuZGVkIG9uIDEwMCsgcm93cywgY2F1c2luZyB0aGUgZ3JpZFxuICAgIC8vIHRvIHJlLXJlbmRlciAxMDArIHRpbWVzLCB3aGljaCB3b3VsZCBiZSBhIHBlcmZvcm1hbmNlIGxhZy5cbiAgICAvL1xuICAgIC8vIHdlIHVzZSBhbmltYXRpb25GcmFtZVNlcnZpY2VcbiAgICAvLyByYXRoZXIgdGhhbiBfLmRlYm91bmNlKCkgc28gdGhpcyB3aWxsIGdldCBkb25lIGlmIGFueW9uZSBmbHVzaGVzIHRoZSBhbmltYXRpb25GcmFtZVNlcnZpY2VcbiAgICAvLyAoZWcgdXNlciBjYWxscyBhcGkuZW5zdXJlUm93VmlzaWJsZSgpLCB3aGljaCBpbiB0dXJuIGZsdXNoZXMgKS5cbiAgICBSb3dOb2RlRXZlbnRUaHJvdHRsZS5wcm90b3R5cGUuZGlzcGF0Y2hFeHBhbmRlZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyBpZiBub3QgdXNpbmcgQ1NSTSwgd2UgZG9uJ3QgZGVib3VuY2UuIG90aGVyd2lzZSB0aGlzIGJyZWFrcyB0aGUgU1NSTS5cbiAgICAgICAgaWYgKHRoaXMuY2xpZW50U2lkZVJvd01vZGVsID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXZlbnRzLnB1c2goZXZlbnQpO1xuICAgICAgICB2YXIgZnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jbGllbnRTaWRlUm93TW9kZWwpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5jbGllbnRTaWRlUm93TW9kZWwub25Sb3dHcm91cE9wZW5lZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3RoaXMuZXZlbnRzLmZvckVhY2goZnVuY3Rpb24gKGUpIHsgcmV0dXJuIF90aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGUpOyB9KTtcbiAgICAgICAgICAgIF90aGlzLmV2ZW50cyA9IFtdO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5kaXNwYXRjaEV4cGFuZGVkRGVib3VuY2VkID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFeHBhbmRlZERlYm91bmNlZCA9IHRoaXMuYW5pbWF0aW9uRnJhbWVTZXJ2aWNlLmRlYm91bmNlKGZ1bmMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFeHBhbmRlZERlYm91bmNlZCgpO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSRjKFtcbiAgICAgICAgQXV0b3dpcmVkKCdhbmltYXRpb25GcmFtZVNlcnZpY2UnKVxuICAgIF0sIFJvd05vZGVFdmVudFRocm90dGxlLnByb3RvdHlwZSwgXCJhbmltYXRpb25GcmFtZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGMoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBSb3dOb2RlRXZlbnRUaHJvdHRsZS5wcm90b3R5cGUsIFwicm93TW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGMoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgUm93Tm9kZUV2ZW50VGhyb3R0bGUucHJvdG90eXBlLCBcInBvc3RDb25zdHJ1Y3RcIiwgbnVsbCk7XG4gICAgUm93Tm9kZUV2ZW50VGhyb3R0bGUgPSBfX2RlY29yYXRlJGMoW1xuICAgICAgICBCZWFuKCdyb3dOb2RlRXZlbnRUaHJvdHRsZScpXG4gICAgXSwgUm93Tm9kZUV2ZW50VGhyb3R0bGUpO1xuICAgIHJldHVybiBSb3dOb2RlRXZlbnRUaHJvdHRsZTtcbn0oQmVhblN0dWIpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIF9fcmVhZCQyID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIF9fc3ByZWFkJDEgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX3NwcmVhZCkgfHwgZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhciA9IGFyLmNvbmNhdChfX3JlYWQkMihhcmd1bWVudHNbaV0pKTtcbiAgICByZXR1cm4gYXI7XG59O1xuLy8gY3JlYXRlcyBKYXZhU2NyaXB0IHZhbmlsbGEgR3JpZCwgaW5jbHVkaW5nIEphdmFTY3JpcHQgKGFnLXN0YWNrKSBjb21wb25lbnRzLCB3aGljaCBjYW5cbi8vIGJlIHdyYXBwZWQgYnkgdGhlIGZyYW1ld29yayB3cmFwcGVyc1xudmFyIEdyaWQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gR3JpZChlR3JpZERpdiwgZ3JpZE9wdGlvbnMsIHBhcmFtcykge1xuICAgICAgICBpZiAoIWdyaWRPcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBubyBncmlkT3B0aW9ucyBwcm92aWRlZCB0byB0aGUgZ3JpZCcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnMgPSBncmlkT3B0aW9ucztcbiAgICAgICAgbmV3IEdyaWRDb3JlQ3JlYXRvcigpLmNyZWF0ZShlR3JpZERpdiwgZ3JpZE9wdGlvbnMsIGZ1bmN0aW9uIChjb250ZXh0KSB7XG4gICAgICAgICAgICB2YXIgZ3JpZENvbXAgPSBuZXcgR3JpZENvbXAoZUdyaWREaXYpO1xuICAgICAgICAgICAgY29udGV4dC5jcmVhdGVCZWFuKGdyaWRDb21wKTtcbiAgICAgICAgfSwgdW5kZWZpbmVkLCBwYXJhbXMpO1xuICAgIH1cbiAgICBHcmlkLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9ucyAmJiB0aGlzLmdyaWRPcHRpb25zLmFwaSkge1xuICAgICAgICAgICAgdGhpcy5ncmlkT3B0aW9ucy5hcGkuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gR3JpZDtcbn0oKSk7XG4vLyBjcmVhdGVkIHNlcnZpY2VzIG9mIGdyaWQgb25seSwgbm8gVUksIHNvIGZyYW1ld29ya3MgY2FuIHVzZSB0aGlzIGlmIHByb3ZpZGluZ1xuLy8gdGhlaXIgb3duIFVJXG52YXIgR3JpZENvcmVDcmVhdG9yID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEdyaWRDb3JlQ3JlYXRvcigpIHtcbiAgICB9XG4gICAgR3JpZENvcmVDcmVhdG9yLnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAoZUdyaWREaXYsIGdyaWRPcHRpb25zLCBjcmVhdGVVaSwgYWNjZXB0Q2hhbmdlcywgcGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBkZWJ1ZyA9ICEhZ3JpZE9wdGlvbnMuZGVidWc7XG4gICAgICAgIHZhciByZWdpc3RlcmVkTW9kdWxlcyA9IHRoaXMuZ2V0UmVnaXN0ZXJlZE1vZHVsZXMocGFyYW1zKTtcbiAgICAgICAgdmFyIGJlYW5DbGFzc2VzID0gdGhpcy5jcmVhdGVCZWFuc0xpc3QoZ3JpZE9wdGlvbnMucm93TW9kZWxUeXBlLCByZWdpc3RlcmVkTW9kdWxlcyk7XG4gICAgICAgIHZhciBwcm92aWRlZEJlYW5JbnN0YW5jZXMgPSB0aGlzLmNyZWF0ZVByb3ZpZGVkQmVhbnMoZUdyaWREaXYsIGdyaWRPcHRpb25zLCBwYXJhbXMpO1xuICAgICAgICBpZiAoIWJlYW5DbGFzc2VzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gLy8gaGFwcGVucyB3aGVuIG5vIHJvdyBtb2RlbCBmb3VuZFxuICAgICAgICB2YXIgY29udGV4dFBhcmFtcyA9IHtcbiAgICAgICAgICAgIHByb3ZpZGVkQmVhbkluc3RhbmNlczogcHJvdmlkZWRCZWFuSW5zdGFuY2VzLFxuICAgICAgICAgICAgYmVhbkNsYXNzZXM6IGJlYW5DbGFzc2VzLFxuICAgICAgICAgICAgZGVidWc6IGRlYnVnXG4gICAgICAgIH07XG4gICAgICAgIHZhciBsb2dnZXIgPSBuZXcgTG9nZ2VyKCdBRyBHcmlkJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gZ3JpZE9wdGlvbnMuZGVidWc7IH0pO1xuICAgICAgICB2YXIgY29udGV4dExvZ2dlciA9IG5ldyBMb2dnZXIoJ0NvbnRleHQnLCBmdW5jdGlvbiAoKSB7IHJldHVybiBjb250ZXh0UGFyYW1zLmRlYnVnOyB9KTtcbiAgICAgICAgdmFyIGNvbnRleHQgPSBuZXcgQ29udGV4dChjb250ZXh0UGFyYW1zLCBjb250ZXh0TG9nZ2VyKTtcbiAgICAgICAgdmFyIGJlYW5zID0gY29udGV4dC5nZXRCZWFuKCdiZWFucycpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyTW9kdWxlVXNlckNvbXBvbmVudHMoYmVhbnMsIHJlZ2lzdGVyZWRNb2R1bGVzKTtcbiAgICAgICAgdGhpcy5yZWdpc3RlclN0YWNrQ29tcG9uZW50cyhiZWFucywgcmVnaXN0ZXJlZE1vZHVsZXMpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyQ29udHJvbGxlcnMoYmVhbnMsIHJlZ2lzdGVyZWRNb2R1bGVzKTtcbiAgICAgICAgY3JlYXRlVWkoY29udGV4dCk7XG4gICAgICAgIC8vIHdlIHdhaXQgdW50aWwgdGhlIFVJIGhhcyBmaW5pc2hlZCBpbml0aWFsaXNpbmcgYmVmb3JlIHNldHRpbmcgaW4gY29sdW1ucyBhbmQgcm93c1xuICAgICAgICBiZWFucy5jdHJsc1NlcnZpY2Uud2hlblJlYWR5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLnNldENvbHVtbnNBbmREYXRhKGJlYW5zKTtcbiAgICAgICAgICAgIF90aGlzLmRpc3BhdGNoR3JpZFJlYWR5RXZlbnQoYmVhbnMpO1xuICAgICAgICAgICAgdmFyIGlzRW50ZXJwcmlzZSA9IE1vZHVsZVJlZ2lzdHJ5LmlzUmVnaXN0ZXJlZChNb2R1bGVOYW1lcy5FbnRlcnByaXNlQ29yZU1vZHVsZSk7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiaW5pdGlhbGlzZWQgc3VjY2Vzc2Z1bGx5LCBlbnRlcnByaXNlID0gXCIgKyBpc0VudGVycHJpc2UpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGFjY2VwdENoYW5nZXMpIHtcbiAgICAgICAgICAgIGFjY2VwdENoYW5nZXMoY29udGV4dCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUucmVnaXN0ZXJDb250cm9sbGVycyA9IGZ1bmN0aW9uIChiZWFucywgcmVnaXN0ZXJlZE1vZHVsZXMpIHtcbiAgICAgICAgcmVnaXN0ZXJlZE1vZHVsZXMuZm9yRWFjaChmdW5jdGlvbiAobW9kdWxlKSB7XG4gICAgICAgICAgICBpZiAobW9kdWxlLmNvbnRyb2xsZXJzKSB7XG4gICAgICAgICAgICAgICAgbW9kdWxlLmNvbnRyb2xsZXJzLmZvckVhY2goZnVuY3Rpb24gKG1ldGEpIHsgcmV0dXJuIGJlYW5zLmN0cmxzRmFjdG9yeS5yZWdpc3RlcihtZXRhKTsgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgR3JpZENvcmVDcmVhdG9yLnByb3RvdHlwZS5yZWdpc3RlclN0YWNrQ29tcG9uZW50cyA9IGZ1bmN0aW9uIChiZWFucywgcmVnaXN0ZXJlZE1vZHVsZXMpIHtcbiAgICAgICAgdmFyIGFnU3RhY2tDb21wb25lbnRzID0gdGhpcy5jcmVhdGVBZ1N0YWNrQ29tcG9uZW50c0xpc3QocmVnaXN0ZXJlZE1vZHVsZXMpO1xuICAgICAgICBiZWFucy5hZ1N0YWNrQ29tcG9uZW50c1JlZ2lzdHJ5LnNldHVwQ29tcG9uZW50cyhhZ1N0YWNrQ29tcG9uZW50cyk7XG4gICAgfTtcbiAgICBHcmlkQ29yZUNyZWF0b3IucHJvdG90eXBlLmdldFJlZ2lzdGVyZWRNb2R1bGVzID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgcGFzc2VkVmlhQ29uc3RydWN0b3IgPSBwYXJhbXMgPyBwYXJhbXMubW9kdWxlcyA6IG51bGw7XG4gICAgICAgIHZhciByZWdpc3RlcmVkID0gTW9kdWxlUmVnaXN0cnkuZ2V0UmVnaXN0ZXJlZE1vZHVsZXMoKTtcbiAgICAgICAgdmFyIGFsbE1vZHVsZXMgPSBbXTtcbiAgICAgICAgdmFyIG1hcE5hbWVzID0ge307XG4gICAgICAgIC8vIGFkZHMgdG8gbGlzdCBhbmQgcmVtb3ZlcyBkdXBsaWNhdGVzXG4gICAgICAgIGZ1bmN0aW9uIGFkZE1vZHVsZShtb2R1bGVCYXNlZCwgbW9kKSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRJbmRpdmlkdWFsTW9kdWxlKGN1cnJlbnRNb2R1bGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW1hcE5hbWVzW2N1cnJlbnRNb2R1bGUubW9kdWxlTmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgbWFwTmFtZXNbY3VycmVudE1vZHVsZS5tb2R1bGVOYW1lXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGFsbE1vZHVsZXMucHVzaChjdXJyZW50TW9kdWxlKTtcbiAgICAgICAgICAgICAgICAgICAgTW9kdWxlUmVnaXN0cnkucmVnaXN0ZXIoY3VycmVudE1vZHVsZSwgbW9kdWxlQmFzZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFkZEluZGl2aWR1YWxNb2R1bGUobW9kKTtcbiAgICAgICAgICAgIGlmIChtb2QuZGVwZW5kYW50TW9kdWxlcykge1xuICAgICAgICAgICAgICAgIG1vZC5kZXBlbmRhbnRNb2R1bGVzLmZvckVhY2goYWRkTW9kdWxlLmJpbmQobnVsbCwgbW9kdWxlQmFzZWQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocGFzc2VkVmlhQ29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIHBhc3NlZFZpYUNvbnN0cnVjdG9yLmZvckVhY2goYWRkTW9kdWxlLmJpbmQobnVsbCwgdHJ1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZWdpc3RlcmVkKSB7XG4gICAgICAgICAgICByZWdpc3RlcmVkLmZvckVhY2goYWRkTW9kdWxlLmJpbmQobnVsbCwgIU1vZHVsZVJlZ2lzdHJ5LmlzUGFja2FnZUJhc2VkKCkpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWxsTW9kdWxlcztcbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUucmVnaXN0ZXJNb2R1bGVVc2VyQ29tcG9uZW50cyA9IGZ1bmN0aW9uIChiZWFucywgcmVnaXN0ZXJlZE1vZHVsZXMpIHtcbiAgICAgICAgdmFyIG1vZHVsZVVzZXJDb21wcyA9IHRoaXMuZXh0cmFjdE1vZHVsZUVudGl0eShyZWdpc3RlcmVkTW9kdWxlcywgZnVuY3Rpb24gKG1vZHVsZSkgeyByZXR1cm4gbW9kdWxlLnVzZXJDb21wb25lbnRzID8gbW9kdWxlLnVzZXJDb21wb25lbnRzIDogW107IH0pO1xuICAgICAgICBtb2R1bGVVc2VyQ29tcHMuZm9yRWFjaChmdW5jdGlvbiAoY29tcE1ldGEpIHtcbiAgICAgICAgICAgIGJlYW5zLnVzZXJDb21wb25lbnRSZWdpc3RyeS5yZWdpc3RlckRlZmF1bHRDb21wb25lbnQoY29tcE1ldGEuY29tcG9uZW50TmFtZSwgY29tcE1ldGEuY29tcG9uZW50Q2xhc3MpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUuY3JlYXRlUHJvdmlkZWRCZWFucyA9IGZ1bmN0aW9uIChlR3JpZERpdiwgZ3JpZE9wdGlvbnMsIHBhcmFtcykge1xuICAgICAgICB2YXIgZnJhbWV3b3JrT3ZlcnJpZGVzID0gcGFyYW1zID8gcGFyYW1zLmZyYW1ld29ya092ZXJyaWRlcyA6IG51bGw7XG4gICAgICAgIGlmIChtaXNzaW5nKGZyYW1ld29ya092ZXJyaWRlcykpIHtcbiAgICAgICAgICAgIGZyYW1ld29ya092ZXJyaWRlcyA9IG5ldyBWYW5pbGxhRnJhbWV3b3JrT3ZlcnJpZGVzKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNlZWQgPSB7XG4gICAgICAgICAgICBncmlkT3B0aW9uczogZ3JpZE9wdGlvbnMsXG4gICAgICAgICAgICBlR3JpZERpdjogZUdyaWREaXYsXG4gICAgICAgICAgICBnbG9iYWxFdmVudExpc3RlbmVyOiBwYXJhbXMgPyBwYXJhbXMuZ2xvYmFsRXZlbnRMaXN0ZW5lciA6IG51bGwsXG4gICAgICAgICAgICBmcmFtZXdvcmtPdmVycmlkZXM6IGZyYW1ld29ya092ZXJyaWRlc1xuICAgICAgICB9O1xuICAgICAgICBpZiAocGFyYW1zICYmIHBhcmFtcy5wcm92aWRlZEJlYW5JbnN0YW5jZXMpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oc2VlZCwgcGFyYW1zLnByb3ZpZGVkQmVhbkluc3RhbmNlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNlZWQ7XG4gICAgfTtcbiAgICBHcmlkQ29yZUNyZWF0b3IucHJvdG90eXBlLmNyZWF0ZUFnU3RhY2tDb21wb25lbnRzTGlzdCA9IGZ1bmN0aW9uIChyZWdpc3RlcmVkTW9kdWxlcykge1xuICAgICAgICB2YXIgY29tcG9uZW50cyA9IFtcbiAgICAgICAgICAgIHsgY29tcG9uZW50TmFtZTogJ0FnQ2hlY2tib3gnLCBjb21wb25lbnRDbGFzczogQWdDaGVja2JveCB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdSYWRpb0J1dHRvbicsIGNvbXBvbmVudENsYXNzOiBBZ1JhZGlvQnV0dG9uIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ1RvZ2dsZUJ1dHRvbicsIGNvbXBvbmVudENsYXNzOiBBZ1RvZ2dsZUJ1dHRvbiB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdJbnB1dFRleHRGaWVsZCcsIGNvbXBvbmVudENsYXNzOiBBZ0lucHV0VGV4dEZpZWxkIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ0lucHV0VGV4dEFyZWEnLCBjb21wb25lbnRDbGFzczogQWdJbnB1dFRleHRBcmVhIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ0lucHV0TnVtYmVyRmllbGQnLCBjb21wb25lbnRDbGFzczogQWdJbnB1dE51bWJlckZpZWxkIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ0lucHV0UmFuZ2UnLCBjb21wb25lbnRDbGFzczogQWdJbnB1dFJhbmdlIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ1NlbGVjdCcsIGNvbXBvbmVudENsYXNzOiBBZ1NlbGVjdCB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdTbGlkZXInLCBjb21wb25lbnRDbGFzczogQWdTbGlkZXIgfSxcbiAgICAgICAgICAgIHsgY29tcG9uZW50TmFtZTogJ0FnQW5nbGVTZWxlY3QnLCBjb21wb25lbnRDbGFzczogQWdBbmdsZVNlbGVjdCB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdDb2xvclBpY2tlcicsIGNvbXBvbmVudENsYXNzOiBBZ0NvbG9yUGlja2VyIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ0dyaWRCb2R5JywgY29tcG9uZW50Q2xhc3M6IEdyaWRCb2R5Q29tcCB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdIZWFkZXJSb290JywgY29tcG9uZW50Q2xhc3M6IEdyaWRIZWFkZXJDb21wIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ1NvcnRJbmRpY2F0b3InLCBjb21wb25lbnRDbGFzczogU29ydEluZGljYXRvckNvbXAgfSxcbiAgICAgICAgICAgIHsgY29tcG9uZW50TmFtZTogJ0FnUGFnaW5hdGlvbicsIGNvbXBvbmVudENsYXNzOiBQYWdpbmF0aW9uQ29tcCB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdPdmVybGF5V3JhcHBlcicsIGNvbXBvbmVudENsYXNzOiBPdmVybGF5V3JhcHBlckNvbXBvbmVudCB9LFxuICAgICAgICAgICAgeyBjb21wb25lbnROYW1lOiAnQWdHcm91cENvbXBvbmVudCcsIGNvbXBvbmVudENsYXNzOiBBZ0dyb3VwQ29tcG9uZW50IH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ1BhbmVsJywgY29tcG9uZW50Q2xhc3M6IEFnUGFuZWwgfSxcbiAgICAgICAgICAgIHsgY29tcG9uZW50TmFtZTogJ0FnRGlhbG9nJywgY29tcG9uZW50Q2xhc3M6IEFnRGlhbG9nIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ1Jvd0NvbnRhaW5lcicsIGNvbXBvbmVudENsYXNzOiBSb3dDb250YWluZXJDb21wIH0sXG4gICAgICAgICAgICB7IGNvbXBvbmVudE5hbWU6ICdBZ0Zha2VIb3Jpem9udGFsU2Nyb2xsJywgY29tcG9uZW50Q2xhc3M6IEZha2VIU2Nyb2xsQ29tcCB9XG4gICAgICAgIF07XG4gICAgICAgIHZhciBtb2R1bGVBZ1N0YWNrQ29tcHMgPSB0aGlzLmV4dHJhY3RNb2R1bGVFbnRpdHkocmVnaXN0ZXJlZE1vZHVsZXMsIGZ1bmN0aW9uIChtb2R1bGUpIHsgcmV0dXJuIG1vZHVsZS5hZ1N0YWNrQ29tcG9uZW50cyA/IG1vZHVsZS5hZ1N0YWNrQ29tcG9uZW50cyA6IFtdOyB9KTtcbiAgICAgICAgY29tcG9uZW50cyA9IGNvbXBvbmVudHMuY29uY2F0KG1vZHVsZUFnU3RhY2tDb21wcyk7XG4gICAgICAgIHJldHVybiBjb21wb25lbnRzO1xuICAgIH07XG4gICAgR3JpZENvcmVDcmVhdG9yLnByb3RvdHlwZS5jcmVhdGVCZWFuc0xpc3QgPSBmdW5jdGlvbiAocm93TW9kZWxUeXBlLCByZWdpc3RlcmVkTW9kdWxlcykge1xuICAgICAgICB2YXIgcm93TW9kZWxDbGFzcyA9IHRoaXMuZ2V0Um93TW9kZWxDbGFzcyhyb3dNb2RlbFR5cGUsIHJlZ2lzdGVyZWRNb2R1bGVzKTtcbiAgICAgICAgaWYgKCFyb3dNb2RlbENsYXNzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gYmVhbnMgc2hvdWxkIG9ubHkgY29udGFpbiBTRVJWSUNFUywgaXQgc2hvdWxkIE5FVkVSIGNvbnRhaW4gQ09NUE9ORU5UU1xuICAgICAgICB2YXIgYmVhbnMgPSBbXG4gICAgICAgICAgICByb3dNb2RlbENsYXNzLCBCZWFucywgUm93UG9zaXRpb25VdGlscywgQ2VsbFBvc2l0aW9uVXRpbHMsIEhlYWRlclBvc2l0aW9uVXRpbHMsXG4gICAgICAgICAgICBQYWdpbmF0aW9uQXV0b1BhZ2VTaXplU2VydmljZSwgR3JpZEFwaSwgVXNlckNvbXBvbmVudFJlZ2lzdHJ5LCBBZ0NvbXBvbmVudFV0aWxzLFxuICAgICAgICAgICAgQ29tcG9uZW50TWV0YWRhdGFQcm92aWRlciwgUmVzaXplT2JzZXJ2ZXJTZXJ2aWNlLCBVc2VyQ29tcG9uZW50RmFjdG9yeSxcbiAgICAgICAgICAgIFJvd0NvbnRhaW5lckhlaWdodFNlcnZpY2UsIEhvcml6b250YWxSZXNpemVTZXJ2aWNlLFxuICAgICAgICAgICAgUGlubmVkUm93TW9kZWwsIERyYWdTZXJ2aWNlLCBEaXNwbGF5ZWRHcm91cENyZWF0b3IsIEV2ZW50U2VydmljZSwgR3JpZE9wdGlvbnNXcmFwcGVyLFxuICAgICAgICAgICAgUG9wdXBTZXJ2aWNlLCBTZWxlY3Rpb25TZXJ2aWNlLCBGaWx0ZXJNYW5hZ2VyLCBDb2x1bW5Nb2RlbCwgSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UsXG4gICAgICAgICAgICBQYWdpbmF0aW9uUHJveHksIFJvd1JlbmRlcmVyLCBFeHByZXNzaW9uU2VydmljZSwgQ29sdW1uRmFjdG9yeSwgVGVtcGxhdGVTZXJ2aWNlLFxuICAgICAgICAgICAgQWxpZ25lZEdyaWRzU2VydmljZSwgTmF2aWdhdGlvblNlcnZpY2UsIFZhbHVlQ2FjaGUsIFZhbHVlU2VydmljZSwgTG9nZ2VyRmFjdG9yeSxcbiAgICAgICAgICAgIENvbHVtblV0aWxzLCBBdXRvV2lkdGhDYWxjdWxhdG9yLCBTdGFuZGFyZE1lbnVGYWN0b3J5LCBEcmFnQW5kRHJvcFNlcnZpY2UsIENvbHVtbkFwaSxcbiAgICAgICAgICAgIEZvY3VzU2VydmljZSwgTW91c2VFdmVudFNlcnZpY2UsIEVudmlyb25tZW50LCBDZWxsTmF2aWdhdGlvblNlcnZpY2UsIFZhbHVlRm9ybWF0dGVyU2VydmljZSxcbiAgICAgICAgICAgIFN0eWxpbmdTZXJ2aWNlLCBTY3JvbGxWaXNpYmxlU2VydmljZSwgU29ydENvbnRyb2xsZXIsIENvbHVtbkhvdmVyU2VydmljZSwgQ29sdW1uQW5pbWF0aW9uU2VydmljZSxcbiAgICAgICAgICAgIFNlbGVjdGFibGVTZXJ2aWNlLCBBdXRvR3JvdXBDb2xTZXJ2aWNlLCBDaGFuZ2VEZXRlY3Rpb25TZXJ2aWNlLCBBbmltYXRpb25GcmFtZVNlcnZpY2UsXG4gICAgICAgICAgICBVbmRvUmVkb1NlcnZpY2UsIEFnU3RhY2tDb21wb25lbnRzUmVnaXN0cnksIENvbHVtbkRlZkZhY3RvcnksXG4gICAgICAgICAgICBSb3dDc3NDbGFzc0NhbGN1bGF0b3IsIFJvd05vZGVCbG9ja0xvYWRlciwgUm93Tm9kZVNvcnRlciwgQ3RybHNTZXJ2aWNlLFxuICAgICAgICAgICAgUGlubmVkV2lkdGhTZXJ2aWNlLCBSb3dOb2RlRXZlbnRUaHJvdHRsZSwgQ3RybHNGYWN0b3J5XG4gICAgICAgIF07XG4gICAgICAgIHZhciBtb2R1bGVCZWFucyA9IHRoaXMuZXh0cmFjdE1vZHVsZUVudGl0eShyZWdpc3RlcmVkTW9kdWxlcywgZnVuY3Rpb24gKG1vZHVsZSkgeyByZXR1cm4gbW9kdWxlLmJlYW5zID8gbW9kdWxlLmJlYW5zIDogW107IH0pO1xuICAgICAgICBiZWFucy5wdXNoLmFwcGx5KGJlYW5zLCBfX3NwcmVhZCQxKG1vZHVsZUJlYW5zKSk7XG4gICAgICAgIC8vIGNoZWNrIGZvciBkdXBsaWNhdGVzLCBhcyBkaWZmZXJlbnQgbW9kdWxlcyBjb3VsZCBpbmNsdWRlIHRoZSBzYW1lIGJlYW5zIHRoYXRcbiAgICAgICAgLy8gdGhleSBkZXBlbmQgb24sIGVnIENsaWVudFNpZGVSb3dNb2RlbCBpbiBlbnRlcnByaXNlLCBhbmQgQ2xpZW50U2lkZVJvd01vZGVsIGluIGNvbW11bml0eVxuICAgICAgICB2YXIgYmVhbnNOb0R1cGxpY2F0ZXMgPSBbXTtcbiAgICAgICAgYmVhbnMuZm9yRWFjaChmdW5jdGlvbiAoYmVhbikge1xuICAgICAgICAgICAgaWYgKGJlYW5zTm9EdXBsaWNhdGVzLmluZGV4T2YoYmVhbikgPCAwKSB7XG4gICAgICAgICAgICAgICAgYmVhbnNOb0R1cGxpY2F0ZXMucHVzaChiZWFuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBiZWFuc05vRHVwbGljYXRlcztcbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUuZXh0cmFjdE1vZHVsZUVudGl0eSA9IGZ1bmN0aW9uIChtb2R1bGVFbnRpdGllcywgZXh0cmFjdG9yKSB7XG4gICAgICAgIHJldHVybiBbXS5jb25jYXQuYXBwbHkoW10sIF9fc3ByZWFkJDEobW9kdWxlRW50aXRpZXMubWFwKGV4dHJhY3RvcikpKTtcbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUuc2V0Q29sdW1uc0FuZERhdGEgPSBmdW5jdGlvbiAoYmVhbnMpIHtcbiAgICAgICAgdmFyIGNvbHVtbkRlZnMgPSBiZWFucy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uRGVmcygpO1xuICAgICAgICBiZWFucy5jb2x1bW5Nb2RlbC5zZXRDb2x1bW5EZWZzKGNvbHVtbkRlZnMgfHwgW10sIFwiZ3JpZEluaXRpYWxpemluZ1wiKTtcbiAgICAgICAgYmVhbnMucm93TW9kZWwuc3RhcnQoKTtcbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUuZGlzcGF0Y2hHcmlkUmVhZHlFdmVudCA9IGZ1bmN0aW9uIChiZWFucykge1xuICAgICAgICB2YXIgcmVhZHlFdmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9HUklEX1JFQURZLFxuICAgICAgICB9O1xuICAgICAgICBiZWFucy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChyZWFkeUV2ZW50KTtcbiAgICB9O1xuICAgIEdyaWRDb3JlQ3JlYXRvci5wcm90b3R5cGUuZ2V0Um93TW9kZWxDbGFzcyA9IGZ1bmN0aW9uIChyb3dNb2RlbFR5cGUsIHJlZ2lzdGVyZWRNb2R1bGVzKSB7XG4gICAgICAgIC8vIGRlZmF1bHQgdG8gY2xpZW50IHNpZGVcbiAgICAgICAgaWYgKCFyb3dNb2RlbFR5cGUpIHtcbiAgICAgICAgICAgIHJvd01vZGVsVHlwZSA9IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93TW9kZWxDbGFzc2VzID0ge307XG4gICAgICAgIHJlZ2lzdGVyZWRNb2R1bGVzLmZvckVhY2goZnVuY3Rpb24gKG1vZHVsZSkge1xuICAgICAgICAgICAgaXRlcmF0ZU9iamVjdChtb2R1bGUucm93TW9kZWxzLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHJvd01vZGVsQ2xhc3Nlc1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciByb3dNb2RlbENsYXNzID0gcm93TW9kZWxDbGFzc2VzW3Jvd01vZGVsVHlwZV07XG4gICAgICAgIGlmIChleGlzdHMocm93TW9kZWxDbGFzcykpIHtcbiAgICAgICAgICAgIHJldHVybiByb3dNb2RlbENsYXNzO1xuICAgICAgICB9XG4gICAgICAgIGlmIChNb2R1bGVSZWdpc3RyeS5pc1BhY2thZ2VCYXNlZCgpKSB7XG4gICAgICAgICAgICBpZiAoW0NvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9WSUVXUE9SVCwgQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX1NFUlZFUl9TSURFXS5pbmNsdWRlcyhyb3dNb2RlbFR5cGUpKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgcGFja2FnZSBiYXNlZCBvbmx5IHRoZSBlbnRlcnByaXNlIHJvdyBtb2RlbHMgY291bGQgYmUgbWlzc2luZy5cbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQUcgR3JpZDogUm93IE1vZGVsIFxcXCJcIiArIHJvd01vZGVsVHlwZSArIFwiXFxcIiBub3QgZm91bmQuIFBsZWFzZSBlbnN1cmUgdGhlIHBhY2thZ2UgJ2FnLWdyaWQtZW50ZXJwcmlzZScgaXMgaW1wb3J0ZWQuIFBsZWFzZSBzZWU6IGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL2phdmFzY3JpcHQtZ3JpZC9wYWNrYWdlcy9cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBjb3VsZCBub3QgZmluZCByb3cgbW9kZWwgZm9yIHJvd01vZGVsVHlwZSAnICsgcm93TW9kZWxUeXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChyb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9JTkZJTklURSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBSb3cgTW9kZWwgXFxcIkluZmluaXRlXFxcIiBub3QgZm91bmQuIFBsZWFzZSBlbnN1cmUgdGhlIFwiICsgTW9kdWxlTmFtZXMuSW5maW5pdGVSb3dNb2RlbE1vZHVsZSArIFwiIG1vZHVsZSBpcyByZWdpc3RlcmVkLiBQbGVhc2Ugc2VlOiBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9qYXZhc2NyaXB0LWdyaWQvbW9kdWxlcy9cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChyb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9WSUVXUE9SVCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBSb3cgTW9kZWwgXFxcIlZpZXdwb3J0XFxcIiBub3QgZm91bmQuIFBsZWFzZSBlbnN1cmUgdGhlIEFHIEdyaWQgRW50ZXJwcmlzZSBNb2R1bGUgXCIgKyBNb2R1bGVOYW1lcy5WaWV3cG9ydFJvd01vZGVsTW9kdWxlICsgXCIgbW9kdWxlIGlzIHJlZ2lzdGVyZWQuIFBsZWFzZSBzZWU6IGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL2phdmFzY3JpcHQtZ3JpZC9tb2R1bGVzL1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHJvd01vZGVsVHlwZSA9PT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX1NFUlZFUl9TSURFKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkFHIEdyaWQ6IFJvdyBNb2RlbCBcXFwiU2VydmVyIFNpZGVcXFwiIG5vdCBmb3VuZC4gUGxlYXNlIGVuc3VyZSB0aGUgQUcgR3JpZCBFbnRlcnByaXNlIE1vZHVsZSBcIiArIE1vZHVsZU5hbWVzLlNlcnZlclNpZGVSb3dNb2RlbE1vZHVsZSArIFwiIG1vZHVsZSBpcyByZWdpc3RlcmVkLiBQbGVhc2Ugc2VlOiBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9qYXZhc2NyaXB0LWdyaWQvbW9kdWxlcy9cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChyb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBSb3cgTW9kZWwgXFxcIkNsaWVudCBTaWRlXFxcIiBub3QgZm91bmQuIFBsZWFzZSBlbnN1cmUgdGhlIFwiICsgTW9kdWxlTmFtZXMuQ2xpZW50U2lkZVJvd01vZGVsTW9kdWxlICsgXCIgbW9kdWxlIGlzIHJlZ2lzdGVyZWQuIFBsZWFzZSBzZWU6IGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL2phdmFzY3JpcHQtZ3JpZC9tb2R1bGVzL1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IGNvdWxkIG5vdCBmaW5kIHJvdyBtb2RlbCBmb3Igcm93TW9kZWxUeXBlICcgKyByb3dNb2RlbFR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gR3JpZENvcmVDcmVhdG9yO1xufSgpKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xuZnVuY3Rpb24gZGVmYXVsdEdyb3VwQ29tcGFyYXRvcih2YWx1ZUEsIHZhbHVlQiwgbm9kZUEsIG5vZGVCLCBhY2NlbnRlZENvbXBhcmUpIHtcbiAgICBpZiAoYWNjZW50ZWRDb21wYXJlID09PSB2b2lkIDApIHsgYWNjZW50ZWRDb21wYXJlID0gZmFsc2U7IH1cbiAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFNpbmNlIGFnLWdyaWQgMTEuMC4wIGRlZmF1bHRHcm91cENvbXBhcmF0b3IgaXMgbm90IG5lY2Vzc2FyeS4gWW91IGNhbiByZW1vdmUgdGhpcyBmcm9tIHlvdXIgY29sRGVmJyk7XG4gICAgdmFyIG5vZGVBSXNHcm91cCA9IGV4aXN0cyhub2RlQSkgJiYgbm9kZUEuZ3JvdXA7XG4gICAgdmFyIG5vZGVCSXNHcm91cCA9IGV4aXN0cyhub2RlQikgJiYgbm9kZUIuZ3JvdXA7XG4gICAgdmFyIGJvdGhBcmVHcm91cHMgPSBub2RlQUlzR3JvdXAgJiYgbm9kZUJJc0dyb3VwO1xuICAgIHZhciBib3RoQXJlTm9ybWFsID0gIW5vZGVBSXNHcm91cCAmJiAhbm9kZUJJc0dyb3VwO1xuICAgIGlmIChib3RoQXJlR3JvdXBzKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0Q29tcGFyYXRvcihub2RlQS5rZXksIG5vZGVCLmtleSwgYWNjZW50ZWRDb21wYXJlKTtcbiAgICB9XG4gICAgaWYgKGJvdGhBcmVOb3JtYWwpIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRDb21wYXJhdG9yKHZhbHVlQSwgdmFsdWVCLCBhY2NlbnRlZENvbXBhcmUpO1xuICAgIH1cbiAgICBpZiAobm9kZUFJc0dyb3VwKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICByZXR1cm4gLTE7XG59XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBCYXNlQ29tcG9uZW50V3JhcHBlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlQ29tcG9uZW50V3JhcHBlcigpIHtcbiAgICB9XG4gICAgQmFzZUNvbXBvbmVudFdyYXBwZXIucHJvdG90eXBlLndyYXAgPSBmdW5jdGlvbiAoT3JpZ2luYWxDb25zdHJ1Y3RvciwgbWFuZGF0b3J5TWV0aG9kTGlzdCwgb3B0aW9uYWxNZXRob2RMaXN0LCBjb21wb25lbnRUeXBlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChvcHRpb25hbE1ldGhvZExpc3QgPT09IHZvaWQgMCkgeyBvcHRpb25hbE1ldGhvZExpc3QgPSBbXTsgfVxuICAgICAgICB2YXIgd3JhcHBlciA9IHRoaXMuY3JlYXRlV3JhcHBlcihPcmlnaW5hbENvbnN0cnVjdG9yLCBjb21wb25lbnRUeXBlKTtcbiAgICAgICAgbWFuZGF0b3J5TWV0aG9kTGlzdC5mb3JFYWNoKChmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xuICAgICAgICAgICAgX3RoaXMuY3JlYXRlTWV0aG9kKHdyYXBwZXIsIG1ldGhvZE5hbWUsIHRydWUpO1xuICAgICAgICB9KSk7XG4gICAgICAgIG9wdGlvbmFsTWV0aG9kTGlzdC5mb3JFYWNoKChmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xuICAgICAgICAgICAgX3RoaXMuY3JlYXRlTWV0aG9kKHdyYXBwZXIsIG1ldGhvZE5hbWUsIGZhbHNlKTtcbiAgICAgICAgfSkpO1xuICAgICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9O1xuICAgIEJhc2VDb21wb25lbnRXcmFwcGVyLnByb3RvdHlwZS51bndyYXAgPSBmdW5jdGlvbiAoY29tcCkge1xuICAgICAgICByZXR1cm4gY29tcDtcbiAgICB9O1xuICAgIEJhc2VDb21wb25lbnRXcmFwcGVyLnByb3RvdHlwZS5jcmVhdGVNZXRob2QgPSBmdW5jdGlvbiAod3JhcHBlciwgbWV0aG9kTmFtZSwgbWFuZGF0b3J5KSB7XG4gICAgICAgIHdyYXBwZXIuYWRkTWV0aG9kKG1ldGhvZE5hbWUsIHRoaXMuY3JlYXRlTWV0aG9kUHJveHkod3JhcHBlciwgbWV0aG9kTmFtZSwgbWFuZGF0b3J5KSk7XG4gICAgfTtcbiAgICBCYXNlQ29tcG9uZW50V3JhcHBlci5wcm90b3R5cGUuY3JlYXRlTWV0aG9kUHJveHkgPSBmdW5jdGlvbiAod3JhcHBlciwgbWV0aG9kTmFtZSwgbWFuZGF0b3J5KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAod3JhcHBlci5oYXNNZXRob2QobWV0aG9kTmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd3JhcHBlci5jYWxsTWV0aG9kKG1ldGhvZE5hbWUsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWFuZGF0b3J5KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBGcmFtZXdvcmsgY29tcG9uZW50IGlzIG1pc3NpbmcgdGhlIG1ldGhvZCAnICsgbWV0aG9kTmFtZSArICcoKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZUNvbXBvbmVudFdyYXBwZXI7XG59KCkpO1xuXG4vKipcbiAqIEBhZy1ncmlkLWNvbW11bml0eS9jb3JlIC0gQWR2YW5jZWQgRGF0YSBHcmlkIC8gRGF0YSBUYWJsZSBzdXBwb3J0aW5nIEphdmFzY3JpcHQgLyBUeXBlc2NyaXB0IC8gUmVhY3QgLyBBbmd1bGFyIC8gVnVlXG4gKiBAdmVyc2lvbiB2MjguMi4wXG4gKiBAbGluayBodHRwczovL3d3dy5hZy1ncmlkLmNvbS9cbiAqIEBsaWNlbnNlIE1JVFxuICovXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBJZiB5b3UgdXBkYXRlIHRoZXNlLCB0aGVuIGFsc28gdXBkYXRlIHRoZSBgaW50ZWdyYXRlZC1jaGFydHMtdG9vbGJhcmAgZG9jcy4gKlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbnZhciBERUZBVUxUX0NIQVJUX0dST1VQUyA9IHtcbiAgICBjb2x1bW5Hcm91cDogW1xuICAgICAgICAnY29sdW1uJyxcbiAgICAgICAgJ3N0YWNrZWRDb2x1bW4nLFxuICAgICAgICAnbm9ybWFsaXplZENvbHVtbidcbiAgICBdLFxuICAgIGJhckdyb3VwOiBbXG4gICAgICAgICdiYXInLFxuICAgICAgICAnc3RhY2tlZEJhcicsXG4gICAgICAgICdub3JtYWxpemVkQmFyJ1xuICAgIF0sXG4gICAgcGllR3JvdXA6IFtcbiAgICAgICAgJ3BpZScsXG4gICAgICAgICdkb3VnaG51dCdcbiAgICBdLFxuICAgIGxpbmVHcm91cDogW1xuICAgICAgICAnbGluZSdcbiAgICBdLFxuICAgIHNjYXR0ZXJHcm91cDogW1xuICAgICAgICAnc2NhdHRlcicsXG4gICAgICAgICdidWJibGUnXG4gICAgXSxcbiAgICBhcmVhR3JvdXA6IFtcbiAgICAgICAgJ2FyZWEnLFxuICAgICAgICAnc3RhY2tlZEFyZWEnLFxuICAgICAgICAnbm9ybWFsaXplZEFyZWEnXG4gICAgXSxcbiAgICBoaXN0b2dyYW1Hcm91cDogW1xuICAgICAgICAnaGlzdG9ncmFtJ1xuICAgIF0sXG4gICAgY29tYmluYXRpb25Hcm91cDogW1xuICAgICAgICAnY29sdW1uTGluZUNvbWJvJyxcbiAgICAgICAgJ2FyZWFDb2x1bW5Db21ibycsXG4gICAgICAgICdjdXN0b21Db21ibydcbiAgICBdXG59O1xudmFyIENIQVJUX1RPT0xfUEFORUxfQUxMT1dfTElTVCA9IFtcbiAgICAnY2hhcnRTZXR0aW5ncycsXG4gICAgJ2NoYXJ0RGF0YScsXG4gICAgJ2NoYXJ0Rm9ybWF0J1xuXTtcbnZhciBDSEFSVF9UT09MQkFSX0FMTE9XX0xJU1QgPSBbXG4gICAgJ2NoYXJ0VW5saW5rJyxcbiAgICAnY2hhcnRMaW5rJyxcbiAgICAnY2hhcnREb3dubG9hZCdcbl07XG52YXIgQ0hBUlRfVE9PTF9QQU5FTF9NRU5VX09QVElPTlMgPSB7XG4gICAgc2V0dGluZ3M6IFwiY2hhcnRTZXR0aW5nc1wiLFxuICAgIGRhdGE6IFwiY2hhcnREYXRhXCIsXG4gICAgZm9ybWF0OiBcImNoYXJ0Rm9ybWF0XCJcbn07XG5cbi8qKlxuICogQGFnLWdyaWQtY29tbXVuaXR5L2NvcmUgLSBBZHZhbmNlZCBEYXRhIEdyaWQgLyBEYXRhIFRhYmxlIHN1cHBvcnRpbmcgSmF2YXNjcmlwdCAvIFR5cGVzY3JpcHQgLyBSZWFjdCAvIEFuZ3VsYXIgLyBWdWVcbiAqIEB2ZXJzaW9uIHYyOC4yLjBcbiAqIEBsaW5rIGh0dHBzOi8vd3d3LmFnLWdyaWQuY29tL1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cbnZhciBCYXJDb2x1bW5MYWJlbFBsYWNlbWVudDtcbihmdW5jdGlvbiAoQmFyQ29sdW1uTGFiZWxQbGFjZW1lbnQpIHtcbiAgICBCYXJDb2x1bW5MYWJlbFBsYWNlbWVudFtcIkluc2lkZUJhc2VcIl0gPSBcImluc2lkZUJhc2VcIjtcbiAgICBCYXJDb2x1bW5MYWJlbFBsYWNlbWVudFtcIkluc2lkZUVuZFwiXSA9IFwiaW5zaWRlRW5kXCI7XG4gICAgQmFyQ29sdW1uTGFiZWxQbGFjZW1lbnRbXCJDZW50ZXJcIl0gPSBcImNlbnRlclwiO1xuICAgIEJhckNvbHVtbkxhYmVsUGxhY2VtZW50W1wiT3V0c2lkZUVuZFwiXSA9IFwib3V0c2lkZUVuZFwiO1xufSkoQmFyQ29sdW1uTGFiZWxQbGFjZW1lbnQgfHwgKEJhckNvbHVtbkxhYmVsUGxhY2VtZW50ID0ge30pKTtcblxuLyoqXG4gKiBAYWctZ3JpZC1jb21tdW5pdHkvY29yZSAtIEFkdmFuY2VkIERhdGEgR3JpZCAvIERhdGEgVGFibGUgc3VwcG9ydGluZyBKYXZhc2NyaXB0IC8gVHlwZXNjcmlwdCAvIFJlYWN0IC8gQW5ndWxhciAvIFZ1ZVxuICogQHZlcnNpb24gdjI4LjIuMFxuICogQGxpbmsgaHR0cHM6Ly93d3cuYWctZ3JpZC5jb20vXG4gKiBAbGljZW5zZSBNSVRcbiAqL1xudmFyIGdsb2JhbE9iaiA9IHR5cGVvZiBnbG9iYWwgPT09ICd1bmRlZmluZWQnID8ge30gOiBnbG9iYWw7XG5nbG9iYWxPYmouSFRNTEVsZW1lbnQgPSB0eXBlb2YgSFRNTEVsZW1lbnQgPT09ICd1bmRlZmluZWQnID8ge30gOiBIVE1MRWxlbWVudDtcbmdsb2JhbE9iai5IVE1MQnV0dG9uRWxlbWVudCA9IHR5cGVvZiBIVE1MQnV0dG9uRWxlbWVudCA9PT0gJ3VuZGVmaW5lZCcgPyB7fSA6IEhUTUxCdXR0b25FbGVtZW50O1xuZ2xvYmFsT2JqLkhUTUxTZWxlY3RFbGVtZW50ID0gdHlwZW9mIEhUTUxTZWxlY3RFbGVtZW50ID09PSAndW5kZWZpbmVkJyA/IHt9IDogSFRNTFNlbGVjdEVsZW1lbnQ7XG5nbG9iYWxPYmouSFRNTElucHV0RWxlbWVudCA9IHR5cGVvZiBIVE1MSW5wdXRFbGVtZW50ID09PSAndW5kZWZpbmVkJyA/IHt9IDogSFRNTElucHV0RWxlbWVudDtcbmdsb2JhbE9iai5Ob2RlID0gdHlwZW9mIE5vZGUgPT09ICd1bmRlZmluZWQnID8ge30gOiBOb2RlO1xuZ2xvYmFsT2JqLk1vdXNlRXZlbnQgPSB0eXBlb2YgTW91c2VFdmVudCA9PT0gJ3VuZGVmaW5lZCcgPyB7fSA6IE1vdXNlRXZlbnQ7XG5cbnZhciBfX3JlYWQkMSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fcmVhZCkgfHwgZnVuY3Rpb24gKG8sIG4pIHtcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgaWYgKCFtKSByZXR1cm4gbztcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgICB0cnkge1xuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcbiAgICB9XG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XG4gICAgZmluYWxseSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgICB9XG4gICAgcmV0dXJuIGFyO1xufTtcbnZhciBfX3NwcmVhZCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fc3ByZWFkKSB8fCBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIGFyID0gYXIuY29uY2F0KF9fcmVhZCQxKGFyZ3VtZW50c1tpXSkpO1xuICAgIHJldHVybiBhcjtcbn07XG52YXIgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENsaWVudFNpZGVOb2RlTWFuYWdlcihyb290Tm9kZSwgZ3JpZE9wdGlvbnNXcmFwcGVyLCBldmVudFNlcnZpY2UsIGNvbHVtbk1vZGVsLCBzZWxlY3Rpb25TZXJ2aWNlLCBiZWFucykge1xuICAgICAgICB0aGlzLm5leHRJZCA9IDA7XG4gICAgICAgIC8vIHdoZW4gdXNlciBpcyBwcm92aWRlIHRoZSBpZCdzLCB3ZSBhbHNvIGtlZXAgYSBtYXAgb2YgaWRzIHRvIHJvdyBub2RlcyBmb3IgY29udmVuaWVuY2VcbiAgICAgICAgdGhpcy5hbGxOb2Rlc01hcCA9IHt9O1xuICAgICAgICB0aGlzLnJvb3ROb2RlID0gcm9vdE5vZGU7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyID0gZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZSA9IGV2ZW50U2VydmljZTtcbiAgICAgICAgdGhpcy5jb2x1bW5Nb2RlbCA9IGNvbHVtbk1vZGVsO1xuICAgICAgICB0aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZSA9IHNlbGVjdGlvblNlcnZpY2U7XG4gICAgICAgIHRoaXMucm9vdE5vZGUuZ3JvdXAgPSB0cnVlO1xuICAgICAgICB0aGlzLnJvb3ROb2RlLmxldmVsID0gLTE7XG4gICAgICAgIHRoaXMucm9vdE5vZGUuaWQgPSBDbGllbnRTaWRlTm9kZU1hbmFnZXIuUk9PVF9OT0RFX0lEO1xuICAgICAgICB0aGlzLnJvb3ROb2RlLmFsbExlYWZDaGlsZHJlbiA9IFtdO1xuICAgICAgICB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCA9IFtdO1xuICAgICAgICB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0ID0gW107XG4gICAgICAgIHRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlckFnZ0ZpbHRlciA9IFtdO1xuICAgICAgICB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJGaWx0ZXIgPSBbXTtcbiAgICAgICAgLy8gaWYgd2UgbWFrZSB0aGlzIGNsYXNzIGEgYmVhbiwgdGhlbiBjYW4gYW5ub3RhdGUgcG9zdENvbnN0cnVjdFxuICAgICAgICB0aGlzLnBvc3RDb25zdHJ1Y3QoKTtcbiAgICB9XG4gICAgLy8gQFBvc3RDb25zdHJ1Y3QgLSB0aGlzIGlzIG5vdCBhIGJlYW4sIHNvIHBvc3RDb25zdHJ1Y3QgY2FsbGVkIGJ5IGNvbnN0cnVjdG9yXG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5wb3N0Q29uc3RydWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBmdW5jIGJlbG93IGRvZXNuJ3QgaGF2ZSAndGhpcycgcG9pbnRlciwgc28gbmVlZCB0byBwdWxsIG91dCB0aGVzZSBiaXRzXG4gICAgICAgIHRoaXMuc3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2RlcyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2RlcygpO1xuICAgICAgICB0aGlzLmlzUm93TWFzdGVyRnVuYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldElzUm93TWFzdGVyRnVuYygpO1xuICAgICAgICB0aGlzLmRvaW5nVHJlZURhdGEgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1RyZWVEYXRhKCk7XG4gICAgICAgIHRoaXMuZG9pbmdNYXN0ZXJEZXRhaWwgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc01hc3RlckRldGFpbCgpO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5nZXRDb3B5T2ZOb2Rlc01hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF8uY2xvbmVPYmplY3QodGhpcy5hbGxOb2Rlc01hcCk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlTm9kZU1hbmFnZXIucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWxsTm9kZXNNYXBbaWRdO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5zZXRSb3dEYXRhID0gZnVuY3Rpb24gKHJvd0RhdGEpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHR5cGVvZiByb3dEYXRhID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiByb3dEYXRhIG11c3QgYmUgYW4gYXJyYXksIGhvd2V2ZXIgeW91IHBhc3NlZCBpbiBhIHN0cmluZy4gSWYgeW91IGFyZSBsb2FkaW5nIEpTT04sIG1ha2Ugc3VyZSB5b3UgY29udmVydCB0aGUgSlNPTiBzdHJpbmcgdG8gSmF2YVNjcmlwdCBvYmplY3RzIGZpcnN0Jyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvb3ROb2RlID0gdGhpcy5yb290Tm9kZTtcbiAgICAgICAgdmFyIHNpYmxpbmcgPSB0aGlzLnJvb3ROb2RlLnNpYmxpbmc7XG4gICAgICAgIHJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJGaWx0ZXIgPSBudWxsO1xuICAgICAgICByb290Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXAgPSBudWxsO1xuICAgICAgICByb290Tm9kZS5jaGlsZHJlbkFmdGVyQWdnRmlsdGVyID0gbnVsbDtcbiAgICAgICAgcm9vdE5vZGUuY2hpbGRyZW5BZnRlclNvcnQgPSBudWxsO1xuICAgICAgICByb290Tm9kZS5jaGlsZHJlbk1hcHBlZCA9IG51bGw7XG4gICAgICAgIHJvb3ROb2RlLnVwZGF0ZUhhc0NoaWxkcmVuKCk7XG4gICAgICAgIHRoaXMubmV4dElkID0gMDtcbiAgICAgICAgdGhpcy5hbGxOb2Rlc01hcCA9IHt9O1xuICAgICAgICBpZiAocm93RGF0YSkge1xuICAgICAgICAgICAgLy8gd2UgdXNlIHJvb3ROb2RlIGFzIHRoZSBwYXJlbnQsIGhvd2V2ZXIgaWYgdXNpbmcgYWctZ3JpZC1lbnRlcnByaXNlLCB0aGUgZ3JvdXBpbmcgc3RhZ2VcbiAgICAgICAgICAgIC8vIHNldHMgdGhlIHBhcmVudCBub2RlIG9uIGVhY2ggcm93IChldmVuIGlmIHdlIGFyZSBub3QgZ3JvdXBpbmcpLiBzbyBzZXR0aW5nIHBhcmVudCBub2RlXG4gICAgICAgICAgICAvLyBoZXJlIGlzIGZvciBiZW5lZml0IG9mIGFnLWdyaWQtY29tbXVuaXR5IHVzZXJzXG4gICAgICAgICAgICByb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4gPSByb3dEYXRhLm1hcChmdW5jdGlvbiAoZGF0YUl0ZW0pIHsgcmV0dXJuIF90aGlzLmNyZWF0ZU5vZGUoZGF0YUl0ZW0sIF90aGlzLnJvb3ROb2RlLCBDbGllbnRTaWRlTm9kZU1hbmFnZXIuVE9QX0xFVkVMKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4gPSBbXTtcbiAgICAgICAgICAgIHJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzaWJsaW5nKSB7XG4gICAgICAgICAgICBzaWJsaW5nLmNoaWxkcmVuQWZ0ZXJGaWx0ZXIgPSByb290Tm9kZS5jaGlsZHJlbkFmdGVyRmlsdGVyO1xuICAgICAgICAgICAgc2libGluZy5jaGlsZHJlbkFmdGVyR3JvdXAgPSByb290Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXA7XG4gICAgICAgICAgICBzaWJsaW5nLmNoaWxkcmVuQWZ0ZXJBZ2dGaWx0ZXIgPSByb290Tm9kZS5jaGlsZHJlbkFmdGVyQWdnRmlsdGVyO1xuICAgICAgICAgICAgc2libGluZy5jaGlsZHJlbkFmdGVyU29ydCA9IHJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0O1xuICAgICAgICAgICAgc2libGluZy5jaGlsZHJlbk1hcHBlZCA9IHJvb3ROb2RlLmNoaWxkcmVuTWFwcGVkO1xuICAgICAgICAgICAgc2libGluZy5hbGxMZWFmQ2hpbGRyZW4gPSByb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW47XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENsaWVudFNpZGVOb2RlTWFuYWdlci5wcm90b3R5cGUudXBkYXRlUm93RGF0YSA9IGZ1bmN0aW9uIChyb3dEYXRhVHJhbiwgcm93Tm9kZU9yZGVyKSB7XG4gICAgICAgIHZhciByb3dOb2RlVHJhbnNhY3Rpb24gPSB7XG4gICAgICAgICAgICByZW1vdmU6IFtdLFxuICAgICAgICAgICAgdXBkYXRlOiBbXSxcbiAgICAgICAgICAgIGFkZDogW11cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIG5vZGVzVG9VbnNlbGVjdCA9IFtdO1xuICAgICAgICB0aGlzLmV4ZWN1dGVSZW1vdmUocm93RGF0YVRyYW4sIHJvd05vZGVUcmFuc2FjdGlvbiwgbm9kZXNUb1Vuc2VsZWN0KTtcbiAgICAgICAgdGhpcy5leGVjdXRlVXBkYXRlKHJvd0RhdGFUcmFuLCByb3dOb2RlVHJhbnNhY3Rpb24sIG5vZGVzVG9VbnNlbGVjdCk7XG4gICAgICAgIHRoaXMuZXhlY3V0ZUFkZChyb3dEYXRhVHJhbiwgcm93Tm9kZVRyYW5zYWN0aW9uKTtcbiAgICAgICAgdGhpcy51cGRhdGVTZWxlY3Rpb24obm9kZXNUb1Vuc2VsZWN0KTtcbiAgICAgICAgaWYgKHJvd05vZGVPcmRlcikge1xuICAgICAgICAgICAgXy5zb3J0Um93Tm9kZXNCeU9yZGVyKHRoaXMucm9vdE5vZGUuYWxsTGVhZkNoaWxkcmVuLCByb3dOb2RlT3JkZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dOb2RlVHJhbnNhY3Rpb247XG4gICAgfTtcbiAgICBDbGllbnRTaWRlTm9kZU1hbmFnZXIucHJvdG90eXBlLnVwZGF0ZVNlbGVjdGlvbiA9IGZ1bmN0aW9uIChub2Rlc1RvVW5zZWxlY3QpIHtcbiAgICAgICAgdmFyIHNlbGVjdGlvbkNoYW5nZWQgPSBub2Rlc1RvVW5zZWxlY3QubGVuZ3RoID4gMDtcbiAgICAgICAgaWYgKHNlbGVjdGlvbkNoYW5nZWQpIHtcbiAgICAgICAgICAgIG5vZGVzVG9VbnNlbGVjdC5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5zZXRTZWxlY3RlZChmYWxzZSwgZmFsc2UsIHRydWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2UgZG8gdGhpcyByZWdhcmRsZXNzIG9mIG5vZGVzIHRvIHVuc2VsZWN0IG9yIG5vdCwgYXMgaXQncyBwb3NzaWJsZVxuICAgICAgICAvLyBhIG5ldyBub2RlIHdhcyBpbnNlcnRlZCwgc28gYSBwYXJlbnQgdGhhdCB3YXMgcHJldmlvdXNseSBzZWxlY3RlZCAoYXMgYWxsXG4gICAgICAgIC8vIGNoaWxkcmVuIHdlcmUgc2VsZWN0ZWQpIHNob3VsZCBub3QgYmUgdHJpLXN0YXRlIChhcyBuZXcgb25lIHVuc2VsZWN0ZWQgYWdhaW5zdFxuICAgICAgICAvLyBhbGwgb3RoZXIgc2VsZWN0ZWQgY2hpbGRyZW4pLlxuICAgICAgICB0aGlzLnNlbGVjdGlvblNlcnZpY2UudXBkYXRlR3JvdXBzRnJvbUNoaWxkcmVuU2VsZWN0aW9ucygpO1xuICAgICAgICBpZiAoc2VsZWN0aW9uQ2hhbmdlZCkge1xuICAgICAgICAgICAgdmFyIGV2ZW50XzEgPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX1NFTEVDVElPTl9DSEFOR0VEXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5leGVjdXRlQWRkID0gZnVuY3Rpb24gKHJvd0RhdGFUcmFuLCByb3dOb2RlVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIGFkZCA9IHJvd0RhdGFUcmFuLmFkZCwgYWRkSW5kZXggPSByb3dEYXRhVHJhbi5hZGRJbmRleDtcbiAgICAgICAgaWYgKF8ubWlzc2luZ09yRW1wdHkoYWRkKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNyZWF0ZSBuZXcgcm93IG5vZGVzIGZvciBlYWNoIGRhdGEgaXRlbVxuICAgICAgICB2YXIgbmV3Tm9kZXMgPSBhZGQubWFwKGZ1bmN0aW9uIChpdGVtKSB7IHJldHVybiBfdGhpcy5jcmVhdGVOb2RlKGl0ZW0sIF90aGlzLnJvb3ROb2RlLCBDbGllbnRTaWRlTm9kZU1hbmFnZXIuVE9QX0xFVkVMKTsgfSk7XG4gICAgICAgIC8vIGFkZCBuZXcgcm93IG5vZGVzIHRvIHRoZSByb290IG5vZGVzICdhbGxMZWFmQ2hpbGRyZW4nXG4gICAgICAgIHZhciB1c2VJbmRleCA9IHR5cGVvZiBhZGRJbmRleCA9PT0gJ251bWJlcicgJiYgYWRkSW5kZXggPj0gMDtcbiAgICAgICAgdmFyIG5vZGVzQmVmb3JlSW5kZXg7XG4gICAgICAgIHZhciBub2Rlc0FmdGVySW5kZXg7XG4gICAgICAgIGlmICh1c2VJbmRleCkge1xuICAgICAgICAgICAgLy8gbmV3IHJvd3MgYXJlIGluc2VydGVkIGluIG9uZSBnbyBieSBjb25jYXRlbmF0aW5nIHRoZW0gaW4gYmV0d2VlbiB0aGUgZXhpc3Rpbmcgcm93cyBhdCB0aGUgZGVzaXJlZCBpbmRleC5cbiAgICAgICAgICAgIC8vIHRoaXMgaXMgbXVjaCBmYXN0ZXIgdGhhbiBzcGxpY2luZyB0aGVtIGluZGl2aWR1YWxseSBpbnRvICdhbGxMZWFmQ2hpbGRyZW4nIHdoZW4gdGhlcmUgYXJlIGxhcmdlIGluc2VydHMuXG4gICAgICAgICAgICAvLyBhbGxMZWFmQ2hpbGRyZW4gY2FuIGJlIG91dCBvZiBvcmRlciwgc28gd2UgbG9vcCBvdmVyIGFsbCB0aGUgTm9kZXMgdG8gZmluZCB0aGUgY29ycmVjdCBpbmRleCB0aGF0XG4gICAgICAgICAgICAvLyByZXByZXNlbnRzIHRoZSBwb3NpdGlvbiBgYWRkSW5kZXhgIGludGVuZGVkIHRvIGJlLlxuICAgICAgICAgICAgdmFyIGFsbExlYWZDaGlsZHJlbl8xID0gdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW47XG4gICAgICAgICAgICAvLyBpZiBhZGRJbmRleCBpcyAwLCBpdCBzaG91bGQgYWx3YXlzIGJlIGFkZGVkIGF0IHRoZSBzdGFydCBvZiB0aGUgYXJyYXlcbiAgICAgICAgICAgIC8vIHRoZXJlIGlzIG5vIG5lZWQgdG8gdmVyaWZ5IHRoZSBvcmRlciBvZiBub2RlIGJ5IG5vZGVJbmRleC5cbiAgICAgICAgICAgIHZhciBub3JtYWxpemVkQWRkSW5kZXggPSBhZGRJbmRleCA9PT0gMCA/IDAgOiAoYWxsTGVhZkNoaWxkcmVuXzEucmVkdWNlKGZ1bmN0aW9uIChwcmV2SWR4LCBjdXJyTm9kZSwgY3VycklkeCkge1xuICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICB2YXIgcm93SW5kZXggPSBjdXJyTm9kZS5yb3dJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgcHJldlZhbHVlQXRJbmRleCA9IChfYSA9IGFsbExlYWZDaGlsZHJlbl8xW3ByZXZJZHhdKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2Eucm93SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIHNob3VsZFVwZGF0ZUluZGV4ID0gcm93SW5kZXggIT0gbnVsbCAmJiBwcmV2VmFsdWVBdEluZGV4ICE9IG51bGwgJiYgcm93SW5kZXggPCBhZGRJbmRleCAmJiByb3dJbmRleCA+IHByZXZWYWx1ZUF0SW5kZXg7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNob3VsZFVwZGF0ZUluZGV4ID8gY3VycklkeCA6IHByZXZJZHg7XG4gICAgICAgICAgICB9LCAwKSArIDEpO1xuICAgICAgICAgICAgbm9kZXNCZWZvcmVJbmRleCA9IGFsbExlYWZDaGlsZHJlbl8xLnNsaWNlKDAsIG5vcm1hbGl6ZWRBZGRJbmRleCk7XG4gICAgICAgICAgICBub2Rlc0FmdGVySW5kZXggPSBhbGxMZWFmQ2hpbGRyZW5fMS5zbGljZShub3JtYWxpemVkQWRkSW5kZXgsIGFsbExlYWZDaGlsZHJlbl8xLmxlbmd0aCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBub2Rlc0JlZm9yZUluZGV4ID0gdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW47XG4gICAgICAgICAgICBub2Rlc0FmdGVySW5kZXggPSBbXTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvb3ROb2RlLmFsbExlYWZDaGlsZHJlbiA9IF9fc3ByZWFkKG5vZGVzQmVmb3JlSW5kZXgsIG5ld05vZGVzLCBub2Rlc0FmdGVySW5kZXgpO1xuICAgICAgICBpZiAodGhpcy5yb290Tm9kZS5zaWJsaW5nKSB7XG4gICAgICAgICAgICB0aGlzLnJvb3ROb2RlLnNpYmxpbmcuYWxsTGVhZkNoaWxkcmVuID0gdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW47XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWRkIG5ldyByb3cgbm9kZXMgdG8gdGhlIHRyYW5zYWN0aW9uIGFkZCBpdGVtc1xuICAgICAgICByb3dOb2RlVHJhbnNhY3Rpb24uYWRkID0gbmV3Tm9kZXM7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlTm9kZU1hbmFnZXIucHJvdG90eXBlLmV4ZWN1dGVSZW1vdmUgPSBmdW5jdGlvbiAocm93RGF0YVRyYW4sIHJvd05vZGVUcmFuc2FjdGlvbiwgbm9kZXNUb1Vuc2VsZWN0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciByZW1vdmUgPSByb3dEYXRhVHJhbi5yZW1vdmU7XG4gICAgICAgIGlmIChfLm1pc3NpbmdPckVtcHR5KHJlbW92ZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93SWRzUmVtb3ZlZCA9IHt9O1xuICAgICAgICByZW1vdmUuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSBfdGhpcy5sb29rdXBSb3dOb2RlKGl0ZW0pO1xuICAgICAgICAgICAgaWYgKCFyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZG8gZGVsZXRlIC0gc2V0dGluZyAnc3VwcHJlc3NGaW5pc2hBY3Rpb25zID0gdHJ1ZScgdG8gZW5zdXJlIEVWRU5UX1NFTEVDVElPTl9DSEFOR0VEIGlzIG5vdCByYWlzZWQgZm9yXG4gICAgICAgICAgICAvLyBlYWNoIHJvdyBub2RlIHVwZGF0ZWQsIGluc3RlYWQgaXQgaXMgcmFpc2VkIG9uY2UgYnkgdGhlIGNhbGxpbmcgY29kZSBpZiBhbnkgc2VsZWN0ZWQgbm9kZXMgZXhpc3QuXG4gICAgICAgICAgICBpZiAocm93Tm9kZS5pc1NlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBub2Rlc1RvVW5zZWxlY3QucHVzaChyb3dOb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHNvIHJvdyByZW5kZXJlciBrbm93cyB0byBmYWRlIHJvdyBvdXQgKGFuZCBub3QgcmVwb3NpdGlvbiBpdClcbiAgICAgICAgICAgIHJvd05vZGUuY2xlYXJSb3dUb3BBbmRSb3dJbmRleCgpO1xuICAgICAgICAgICAgLy8gTk9URTogd2VyZSB3ZSBjb3VsZCByZW1vdmUgZnJvbSBhbGxMZWF2ZUNoaWxkcmVuLCBob3dldmVyIF8ucmVtb3ZlRnJvbUFycmF5KCkgaXMgZXhwZW5zaXZlLCBlc3BlY2lhbGx5XG4gICAgICAgICAgICAvLyBpZiBjYWxsZWQgbXVsdGlwbGUgdGltZXMgKGVnIGRlbGV0aW5nIGxvdHMgb2Ygcm93cykgYW5kIGlmIGFsbExlYWZDaGlsZHJlbiBpcyBhIGxhcmdlIGxpc3RcbiAgICAgICAgICAgIHJvd0lkc1JlbW92ZWRbcm93Tm9kZS5pZF0gPSB0cnVlO1xuICAgICAgICAgICAgLy8gXy5yZW1vdmVGcm9tQXJyYXkodGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4sIHJvd05vZGUpO1xuICAgICAgICAgICAgZGVsZXRlIF90aGlzLmFsbE5vZGVzTWFwW3Jvd05vZGUuaWRdO1xuICAgICAgICAgICAgcm93Tm9kZVRyYW5zYWN0aW9uLnJlbW92ZS5wdXNoKHJvd05vZGUpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4gPSB0aGlzLnJvb3ROb2RlLmFsbExlYWZDaGlsZHJlbi5maWx0ZXIoZnVuY3Rpb24gKHJvd05vZGUpIHsgcmV0dXJuICFyb3dJZHNSZW1vdmVkW3Jvd05vZGUuaWRdOyB9KTtcbiAgICAgICAgaWYgKHRoaXMucm9vdE5vZGUuc2libGluZykge1xuICAgICAgICAgICAgdGhpcy5yb290Tm9kZS5zaWJsaW5nLmFsbExlYWZDaGlsZHJlbiA9IHRoaXMucm9vdE5vZGUuYWxsTGVhZkNoaWxkcmVuO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDbGllbnRTaWRlTm9kZU1hbmFnZXIucHJvdG90eXBlLmV4ZWN1dGVVcGRhdGUgPSBmdW5jdGlvbiAocm93RGF0YVRyYW4sIHJvd05vZGVUcmFuc2FjdGlvbiwgbm9kZXNUb1Vuc2VsZWN0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB1cGRhdGUgPSByb3dEYXRhVHJhbi51cGRhdGU7XG4gICAgICAgIGlmIChfLm1pc3NpbmdPckVtcHR5KHVwZGF0ZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGUuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgdmFyIHJvd05vZGUgPSBfdGhpcy5sb29rdXBSb3dOb2RlKGl0ZW0pO1xuICAgICAgICAgICAgaWYgKCFyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcm93Tm9kZS51cGRhdGVEYXRhKGl0ZW0pO1xuICAgICAgICAgICAgaWYgKCFyb3dOb2RlLnNlbGVjdGFibGUgJiYgcm93Tm9kZS5pc1NlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgICBub2Rlc1RvVW5zZWxlY3QucHVzaChyb3dOb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLnNldE1hc3RlckZvclJvdyhyb3dOb2RlLCBpdGVtLCBDbGllbnRTaWRlTm9kZU1hbmFnZXIuVE9QX0xFVkVMLCBmYWxzZSk7XG4gICAgICAgICAgICByb3dOb2RlVHJhbnNhY3Rpb24udXBkYXRlLnB1c2gocm93Tm9kZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5sb29rdXBSb3dOb2RlID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdmFyIGdldFJvd0lkRnVuYyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0lkRnVuYygpO1xuICAgICAgICB2YXIgcm93Tm9kZTtcbiAgICAgICAgaWYgKGdldFJvd0lkRnVuYykge1xuICAgICAgICAgICAgLy8gZmluZCByb3dOb2RlIHVzaW5nIGlkXG4gICAgICAgICAgICB2YXIgaWQgPSBnZXRSb3dJZEZ1bmMoeyBkYXRhOiBkYXRhLCBsZXZlbDogMCB9KTtcbiAgICAgICAgICAgIHJvd05vZGUgPSB0aGlzLmFsbE5vZGVzTWFwW2lkXTtcbiAgICAgICAgICAgIGlmICghcm93Tm9kZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJBRyBHcmlkOiBjb3VsZCBub3QgZmluZCByb3cgaWQ9XCIgKyBpZCArIFwiLCBkYXRhIGl0ZW0gd2FzIG5vdCBmb3VuZCBmb3IgdGhpcyBpZFwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZpbmQgcm93Tm9kZSB1c2luZyBvYmplY3QgcmVmZXJlbmNlc1xuICAgICAgICAgICAgcm93Tm9kZSA9IHRoaXMucm9vdE5vZGUuYWxsTGVhZkNoaWxkcmVuLmZpbmQoZnVuY3Rpb24gKG5vZGUpIHsgcmV0dXJuIG5vZGUuZGF0YSA9PT0gZGF0YTsgfSk7XG4gICAgICAgICAgICBpZiAoIXJvd05vZGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQUcgR3JpZDogY291bGQgbm90IGZpbmQgZGF0YSBpdGVtIGFzIG9iamVjdCB3YXMgbm90IGZvdW5kXCIsIGRhdGEpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb25zaWRlciB1c2luZyBnZXRSb3dJZCB0byBoZWxwIHRoZSBHcmlkIGZpbmQgbWF0Y2hpbmcgcm93IGRhdGFcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd05vZGUgfHwgbnVsbDtcbiAgICB9O1xuICAgIENsaWVudFNpZGVOb2RlTWFuYWdlci5wcm90b3R5cGUuY3JlYXRlTm9kZSA9IGZ1bmN0aW9uIChkYXRhSXRlbSwgcGFyZW50LCBsZXZlbCkge1xuICAgICAgICB2YXIgbm9kZSA9IG5ldyBSb3dOb2RlKHRoaXMuYmVhbnMpO1xuICAgICAgICBub2RlLmdyb3VwID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2V0TWFzdGVyRm9yUm93KG5vZGUsIGRhdGFJdGVtLCBsZXZlbCwgdHJ1ZSk7XG4gICAgICAgIGlmIChwYXJlbnQgJiYgIXRoaXMuc3VwcHJlc3NQYXJlbnRzSW5Sb3dOb2Rlcykge1xuICAgICAgICAgICAgbm9kZS5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5sZXZlbCA9IGxldmVsO1xuICAgICAgICBub2RlLnNldERhdGFBbmRJZChkYXRhSXRlbSwgdGhpcy5uZXh0SWQudG9TdHJpbmcoKSk7XG4gICAgICAgIGlmICh0aGlzLmFsbE5vZGVzTWFwW25vZGUuaWRdKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJBRyBHcmlkOiBkdXBsaWNhdGUgbm9kZSBpZCAnXCIgKyBub2RlLmlkICsgXCInIGRldGVjdGVkIGZyb20gZ2V0Um93SWQgY2FsbGJhY2ssIHRoaXMgY291bGQgY2F1c2UgaXNzdWVzIGluIHlvdXIgZ3JpZC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hbGxOb2Rlc01hcFtub2RlLmlkXSA9IG5vZGU7XG4gICAgICAgIHRoaXMubmV4dElkKys7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5zZXRNYXN0ZXJGb3JSb3cgPSBmdW5jdGlvbiAocm93Tm9kZSwgZGF0YSwgbGV2ZWwsIHNldEV4cGFuZGVkKSB7XG4gICAgICAgIGlmICh0aGlzLmRvaW5nVHJlZURhdGEpIHtcbiAgICAgICAgICAgIHJvd05vZGUuc2V0TWFzdGVyKGZhbHNlKTtcbiAgICAgICAgICAgIGlmIChzZXRFeHBhbmRlZCkge1xuICAgICAgICAgICAgICAgIHJvd05vZGUuZXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIGRlZmF1bHQsIGZvciB3aGVuIGRvaW5nIGdyaWQgZGF0YVxuICAgICAgICAgICAgaWYgKHRoaXMuZG9pbmdNYXN0ZXJEZXRhaWwpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB3ZSBhcmUgZG9pbmcgbWFzdGVyIGRldGFpbCwgdGhlbiB0aGVcbiAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IGlzIHRoYXQgZXZlcnl0aGluZyBjYW4gYmUgYSBNYXN0ZXIgUm93LlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzUm93TWFzdGVyRnVuYykge1xuICAgICAgICAgICAgICAgICAgICByb3dOb2RlLnNldE1hc3Rlcih0aGlzLmlzUm93TWFzdGVyRnVuYyhkYXRhKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByb3dOb2RlLnNldE1hc3Rlcih0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByb3dOb2RlLnNldE1hc3RlcihmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2V0RXhwYW5kZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcm93R3JvdXBDb2x1bW5zID0gdGhpcy5jb2x1bW5Nb2RlbC5nZXRSb3dHcm91cENvbHVtbnMoKTtcbiAgICAgICAgICAgICAgICB2YXIgbnVtUm93R3JvdXBDb2x1bW5zID0gcm93R3JvdXBDb2x1bW5zID8gcm93R3JvdXBDb2x1bW5zLmxlbmd0aCA6IDA7XG4gICAgICAgICAgICAgICAgLy8gbmVlZCB0byB0YWtlIHJvdyBncm91cCBpbnRvIGFjY291bnQgd2hlbiBkZXRlcm1pbmluZyBsZXZlbFxuICAgICAgICAgICAgICAgIHZhciBtYXN0ZXJSb3dMZXZlbCA9IGxldmVsICsgbnVtUm93R3JvdXBDb2x1bW5zO1xuICAgICAgICAgICAgICAgIHJvd05vZGUuZXhwYW5kZWQgPSByb3dOb2RlLm1hc3RlciA/IHRoaXMuaXNFeHBhbmRlZChtYXN0ZXJSb3dMZXZlbCkgOiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLnByb3RvdHlwZS5pc0V4cGFuZGVkID0gZnVuY3Rpb24gKGxldmVsKSB7XG4gICAgICAgIHZhciBleHBhbmRCeURlZmF1bHQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRHcm91cERlZmF1bHRFeHBhbmRlZCgpO1xuICAgICAgICBpZiAoZXhwYW5kQnlEZWZhdWx0ID09PSAtMSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxldmVsIDwgZXhwYW5kQnlEZWZhdWx0O1xuICAgIH07XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLlRPUF9MRVZFTCA9IDA7XG4gICAgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyLlJPT1RfTk9ERV9JRCA9ICdST09UX05PREVfSUQnO1xuICAgIHJldHVybiBDbGllbnRTaWRlTm9kZU1hbmFnZXI7XG59KCkpO1xuXG52YXIgX19leHRlbmRzJGMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJGIgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBSZWN1cnNpb25UeXBlO1xuKGZ1bmN0aW9uIChSZWN1cnNpb25UeXBlKSB7XG4gICAgUmVjdXJzaW9uVHlwZVtSZWN1cnNpb25UeXBlW1wiTm9ybWFsXCJdID0gMF0gPSBcIk5vcm1hbFwiO1xuICAgIFJlY3Vyc2lvblR5cGVbUmVjdXJzaW9uVHlwZVtcIkFmdGVyRmlsdGVyXCJdID0gMV0gPSBcIkFmdGVyRmlsdGVyXCI7XG4gICAgUmVjdXJzaW9uVHlwZVtSZWN1cnNpb25UeXBlW1wiQWZ0ZXJGaWx0ZXJBbmRTb3J0XCJdID0gMl0gPSBcIkFmdGVyRmlsdGVyQW5kU29ydFwiO1xuICAgIFJlY3Vyc2lvblR5cGVbUmVjdXJzaW9uVHlwZVtcIlBpdm90Tm9kZXNcIl0gPSAzXSA9IFwiUGl2b3ROb2Rlc1wiO1xufSkoUmVjdXJzaW9uVHlwZSB8fCAoUmVjdXJzaW9uVHlwZSA9IHt9KSk7XG52YXIgQ2xpZW50U2lkZVJvd01vZGVsID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRjKENsaWVudFNpZGVSb3dNb2RlbCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBDbGllbnRTaWRlUm93TW9kZWwoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5vblJvd0hlaWdodENoYW5nZWRfZGVib3VuY2VkID0gXy5kZWJvdW5jZShfdGhpcy5vblJvd0hlaWdodENoYW5nZWQuYmluZChfdGhpcyksIDEwMCk7XG4gICAgICAgIF90aGlzLnJvd3NUb0Rpc3BsYXkgPSBbXTsgLy8gdGhlIHJvd3MgbWFwcGVkIHRvIHJvd3MgdG8gZGlzcGxheVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlZnJlc2hFdmVyeXRoaW5nRnVuYyA9IHRoaXMucmVmcmVzaE1vZGVsLmJpbmQodGhpcywgeyBzdGVwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5FVkVSWVRISU5HIH0pO1xuICAgICAgICB2YXIgYW5pbWF0ZSA9ICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQW5pbWF0aW9uRnJhbWUoKTtcbiAgICAgICAgdmFyIHJlZnJlc2hFdmVyeXRoaW5nQWZ0ZXJDb2xzQ2hhbmdlZEZ1bmMgPSB0aGlzLnJlZnJlc2hNb2RlbC5iaW5kKHRoaXMsIHtcbiAgICAgICAgICAgIHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLkVWRVJZVEhJTkcsXG4gICAgICAgICAgICBhZnRlckNvbHVtbnNDaGFuZ2VkOiB0cnVlLFxuICAgICAgICAgICAga2VlcFJlbmRlcmVkUm93czogdHJ1ZSxcbiAgICAgICAgICAgIGFuaW1hdGU6IGFuaW1hdGVcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTkVXX0NPTFVNTlNfTE9BREVELCByZWZyZXNoRXZlcnl0aGluZ0FmdGVyQ29sc0NoYW5nZWRGdW5jKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9DT0xVTU5fUk9XX0dST1VQX0NIQU5HRUQsIHJlZnJlc2hFdmVyeXRoaW5nRnVuYyk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1ZBTFVFX0NIQU5HRUQsIHRoaXMub25WYWx1ZUNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfQ09MVU1OX1BJVk9UX0NIQU5HRUQsIHRoaXMucmVmcmVzaE1vZGVsLmJpbmQodGhpcywgeyBzdGVwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5QSVZPVCB9KSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfRklMVEVSX0NIQU5HRUQsIHRoaXMub25GaWx0ZXJDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX1NPUlRfQ0hBTkdFRCwgdGhpcy5vblNvcnRDaGFuZ2VkLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmV2ZW50U2VydmljZSwgRXZlbnRzLkVWRU5UX0NPTFVNTl9QSVZPVF9NT0RFX0NIQU5HRUQsIHJlZnJlc2hFdmVyeXRoaW5nRnVuYyk7XG4gICAgICAgIHZhciByZWZyZXNoTWFwTGlzdGVuZXIgPSB0aGlzLnJlZnJlc2hNb2RlbC5iaW5kKHRoaXMsIHtcbiAgICAgICAgICAgIHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLk1BUCxcbiAgICAgICAgICAgIGtlZXBSZW5kZXJlZFJvd3M6IHRydWUsXG4gICAgICAgICAgICBhbmltYXRlOiBhbmltYXRlXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFkZE1hbmFnZWRMaXN0ZW5lcih0aGlzLmdyaWRPcHRpb25zV3JhcHBlciwgR3JpZE9wdGlvbnNXcmFwcGVyLlBST1BfR1JPVVBfUkVNT1ZFX1NJTkdMRV9DSElMRFJFTiwgcmVmcmVzaE1hcExpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIsIEdyaWRPcHRpb25zV3JhcHBlci5QUk9QX0dST1VQX1JFTU9WRV9MT1dFU1RfU0lOR0xFX0NISUxEUkVOLCByZWZyZXNoTWFwTGlzdGVuZXIpO1xuICAgICAgICB0aGlzLnJvb3ROb2RlID0gbmV3IFJvd05vZGUodGhpcy5iZWFucyk7XG4gICAgICAgIHRoaXMubm9kZU1hbmFnZXIgPSBuZXcgQ2xpZW50U2lkZU5vZGVNYW5hZ2VyKHRoaXMucm9vdE5vZGUsIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLCB0aGlzLmV2ZW50U2VydmljZSwgdGhpcy5jb2x1bW5Nb2RlbCwgdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLCB0aGlzLmJlYW5zKTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dEYXRhID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93RGF0YSgpO1xuICAgICAgICBpZiAocm93RGF0YSkge1xuICAgICAgICAgICAgdGhpcy5zZXRSb3dEYXRhKHJvd0RhdGEpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmVuc3VyZVJvd0hlaWdodHNWYWxpZCA9IGZ1bmN0aW9uIChzdGFydFBpeGVsLCBlbmRQaXhlbCwgc3RhcnRMaW1pdEluZGV4LCBlbmRMaW1pdEluZGV4KSB7XG4gICAgICAgIHZhciBhdExlYXN0T25lQ2hhbmdlO1xuICAgICAgICB2YXIgcmVzID0gZmFsc2U7XG4gICAgICAgIC8vIHdlIGRvIHRoaXMgbXVsdGlwbGUgdGltZXMgYXMgY2hhbmdpbmcgdGhlIHJvdyBoZWlnaHRzIGNhbiBhbHNvIGNoYW5nZSB0aGUgZmlyc3QgYW5kIGxhc3Qgcm93cyxcbiAgICAgICAgLy8gc28gdGhlIGZpcnN0IHBhc3MgY2FuIG1ha2UgbG90cyBvZiByb3dzIHNtYWxsZXIsIHdoaWNoIG1lYW5zIHRoZSBzZWNvbmQgcGFzcyB3ZSBlbmQgdXAgY2hhbmdpbmdcbiAgICAgICAgLy8gbW9yZSByb3dzLlxuICAgICAgICBkbyB7XG4gICAgICAgICAgICBhdExlYXN0T25lQ2hhbmdlID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgcm93QXRTdGFydFBpeGVsID0gdGhpcy5nZXRSb3dJbmRleEF0UGl4ZWwoc3RhcnRQaXhlbCk7XG4gICAgICAgICAgICB2YXIgcm93QXRFbmRQaXhlbCA9IHRoaXMuZ2V0Um93SW5kZXhBdFBpeGVsKGVuZFBpeGVsKTtcbiAgICAgICAgICAgIC8vIGtlZXAgY2hlY2sgdG8gY3VycmVudCBwYWdlIGlmIGRvaW5nIHBhZ2luYXRpb25cbiAgICAgICAgICAgIHZhciBmaXJzdFJvdyA9IE1hdGgubWF4KHJvd0F0U3RhcnRQaXhlbCwgc3RhcnRMaW1pdEluZGV4KTtcbiAgICAgICAgICAgIHZhciBsYXN0Um93ID0gTWF0aC5taW4ocm93QXRFbmRQaXhlbCwgZW5kTGltaXRJbmRleCk7XG4gICAgICAgICAgICBmb3IgKHZhciByb3dJbmRleCA9IGZpcnN0Um93OyByb3dJbmRleCA8PSBsYXN0Um93OyByb3dJbmRleCsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLmdldFJvdyhyb3dJbmRleCk7XG4gICAgICAgICAgICAgICAgaWYgKHJvd05vZGUucm93SGVpZ2h0RXN0aW1hdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByb3dIZWlnaHQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dIZWlnaHRGb3JOb2RlKHJvd05vZGUpO1xuICAgICAgICAgICAgICAgICAgICByb3dOb2RlLnNldFJvd0hlaWdodChyb3dIZWlnaHQuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgYXRMZWFzdE9uZUNoYW5nZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJlcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGF0TGVhc3RPbmVDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFJvd1RvcEFuZFJvd0luZGV4KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gd2hpbGUgKGF0TGVhc3RPbmVDaGFuZ2UpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5zZXRSb3dUb3BBbmRSb3dJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRlZmF1bHRSb3dIZWlnaHQgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREZWZhdWx0Um93SGVpZ2h0KCk7XG4gICAgICAgIHZhciBuZXh0Um93VG9wID0gMDtcbiAgICAgICAgLy8gbWFwcGluZyBkaXNwbGF5ZWQgcm93cyBpcyBub3QgbmVlZGVkIGZvciB0aGlzIG1ldGhvZCwgaG93ZXZlciBpdCdzIHVzZWQgaW5cbiAgICAgICAgLy8gY2xlYXJSb3dUb3BBbmRSb3dJbmRleCgpLCBhbmQgZ2l2ZW4gd2UgYXJlIGxvb3BpbmcgdGhyb3VnaCB0aGlzLnJvd3NUb0Rpc3BsYXkgaGVyZSxcbiAgICAgICAgLy8gd2UgY3JlYXRlIHRoZSBtYXAgaGVyZSBmb3IgcGVyZm9ybWFuY2UgcmVhc29ucywgc28gd2UgZG9uJ3QgbG9vcCBhIHNlY29uZCB0aW1lXG4gICAgICAgIC8vIGluIGNsZWFyUm93VG9wQW5kUm93SW5kZXgoKVxuICAgICAgICB2YXIgZGlzcGxheWVkUm93c01hcHBlZCA9IG5ldyBTZXQoKTtcbiAgICAgICAgLy8gd2UgZG9uJ3QgZXN0aW1hdGUgaWYgZG9pbmcgZnVsbEhlaWdodCBvciBhdXRvSGVpZ2h0LCBhcyBhbGwgcm93cyBnZXQgcmVuZGVyZWQgYWxsIHRoZSB0aW1lXG4gICAgICAgIC8vIHdpdGggdGhlc2UgdHdvIGxheW91dHMuXG4gICAgICAgIHZhciBhbGxvd0VzdGltYXRlID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RG9tTGF5b3V0KCkgPT09IENvbnN0YW50cy5ET01fTEFZT1VUX05PUk1BTDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJvd3NUb0Rpc3BsYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciByb3dOb2RlID0gdGhpcy5yb3dzVG9EaXNwbGF5W2ldO1xuICAgICAgICAgICAgaWYgKHJvd05vZGUuaWQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRpc3BsYXllZFJvd3NNYXBwZWQuYWRkKHJvd05vZGUuaWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJvd05vZGUucm93SGVpZ2h0ID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB2YXIgcm93SGVpZ2h0ID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93SGVpZ2h0Rm9yTm9kZShyb3dOb2RlLCBhbGxvd0VzdGltYXRlLCBkZWZhdWx0Um93SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICByb3dOb2RlLnNldFJvd0hlaWdodChyb3dIZWlnaHQuaGVpZ2h0LCByb3dIZWlnaHQuZXN0aW1hdGVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJvd05vZGUuc2V0Um93VG9wKG5leHRSb3dUb3ApO1xuICAgICAgICAgICAgcm93Tm9kZS5zZXRSb3dJbmRleChpKTtcbiAgICAgICAgICAgIG5leHRSb3dUb3AgKz0gcm93Tm9kZS5yb3dIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRpc3BsYXllZFJvd3NNYXBwZWQ7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmNsZWFyUm93VG9wQW5kUm93SW5kZXggPSBmdW5jdGlvbiAoY2hhbmdlZFBhdGgsIGRpc3BsYXllZFJvd3NNYXBwZWQpIHtcbiAgICAgICAgdmFyIGNoYW5nZWRQYXRoQWN0aXZlID0gY2hhbmdlZFBhdGguaXNBY3RpdmUoKTtcbiAgICAgICAgdmFyIGNsZWFySWZOb3REaXNwbGF5ZWQgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHJvd05vZGUgJiYgcm93Tm9kZS5pZCAhPSBudWxsICYmICFkaXNwbGF5ZWRSb3dzTWFwcGVkLmhhcyhyb3dOb2RlLmlkKSkge1xuICAgICAgICAgICAgICAgIHJvd05vZGUuY2xlYXJSb3dUb3BBbmRSb3dJbmRleCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgcmVjdXJzZSA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICBjbGVhcklmTm90RGlzcGxheWVkKHJvd05vZGUpO1xuICAgICAgICAgICAgY2xlYXJJZk5vdERpc3BsYXllZChyb3dOb2RlLmRldGFpbE5vZGUpO1xuICAgICAgICAgICAgY2xlYXJJZk5vdERpc3BsYXllZChyb3dOb2RlLnNpYmxpbmcpO1xuICAgICAgICAgICAgaWYgKHJvd05vZGUuaGFzQ2hpbGRyZW4oKSkge1xuICAgICAgICAgICAgICAgIGlmIChyb3dOb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiBhIGNoYW5nZWRQYXRoIGlzIGFjdGl2ZSwgaXQgbWVhbnMgd2UgYXJlIGhlcmUgYmVjYXVzZSBvZiBhIHRyYW5zYWN0aW9uIHVwZGF0ZSBvclxuICAgICAgICAgICAgICAgICAgICAvLyBhIGNoYW5nZSBkZXRlY3Rpb24uIG5laXRoZXIgb2YgdGhlc2UgaW1wYWN0cyB0aGUgb3Blbi9jbG9zZWQgc3RhdGUgb2YgZ3JvdXBzLiBzbyBpZlxuICAgICAgICAgICAgICAgICAgICAvLyBhIGdyb3VwIGlzIG5vdCBvcGVuIHRoaXMgdGltZSwgaXQgd2FzIG5vdCBvcGVuIGxhc3QgdGltZS4gc28gd2Uga25vdyBhbGwgY2xvc2VkIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAvLyBhbHJlYWR5IGhhdmUgdGhlaXIgdG9wIHBvc2l0aW9ucyBjbGVhcmVkLiBzbyB0aGVyZSBpcyBubyBuZWVkIHRvIHRyYXZlcnNlIGFsbCB0aGUgd2F5XG4gICAgICAgICAgICAgICAgICAgIC8vIHdoZW4gY2hhbmdlZFBhdGggaXMgYWN0aXZlIGFuZCB0aGUgcm93Tm9kZSBpcyBub3QgZXhwYW5kZWQuXG4gICAgICAgICAgICAgICAgICAgIHZhciBpc1Jvb3ROb2RlID0gcm93Tm9kZS5sZXZlbCA9PSAtMTsgLy8gd2UgbmVlZCB0byBnaXZlIHNwZWNpYWwgY29uc2lkZXJhdGlvbiBmb3Igcm9vdCBub2RlLFxuICAgICAgICAgICAgICAgICAgICAvLyBhcyBleHBhbmRlZD11bmRlZmluZWQgZm9yIHJvb3Qgbm9kZVxuICAgICAgICAgICAgICAgICAgICB2YXIgc2tpcENoaWxkcmVuID0gY2hhbmdlZFBhdGhBY3RpdmUgJiYgIWlzUm9vdE5vZGUgJiYgIXJvd05vZGUuZXhwYW5kZWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2tpcENoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cC5mb3JFYWNoKHJlY3Vyc2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZWN1cnNlKHRoaXMucm9vdE5vZGUpO1xuICAgIH07XG4gICAgLy8gcmV0dXJucyBmYWxzZSBpZiByb3cgd2FzIG1vdmVkLCBvdGhlcndpc2UgdHJ1ZVxuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZW5zdXJlUm93c0F0UGl4ZWwgPSBmdW5jdGlvbiAocm93Tm9kZXMsIHBpeGVsLCBpbmNyZW1lbnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKGluY3JlbWVudCA9PT0gdm9pZCAwKSB7IGluY3JlbWVudCA9IDA7IH1cbiAgICAgICAgdmFyIGluZGV4QXRQaXhlbE5vdyA9IHRoaXMuZ2V0Um93SW5kZXhBdFBpeGVsKHBpeGVsKTtcbiAgICAgICAgdmFyIHJvd05vZGVBdFBpeGVsTm93ID0gdGhpcy5nZXRSb3coaW5kZXhBdFBpeGVsTm93KTtcbiAgICAgICAgdmFyIGFuaW1hdGUgPSAhdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNTdXBwcmVzc0FuaW1hdGlvbkZyYW1lKCk7XG4gICAgICAgIGlmIChyb3dOb2RlQXRQaXhlbE5vdyA9PT0gcm93Tm9kZXNbMF0pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByb3dOb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICBfLnJlbW92ZUZyb21BcnJheShfdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4sIHJvd05vZGUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcm93Tm9kZXMuZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSwgaWR4KSB7XG4gICAgICAgICAgICBfLmluc2VydEludG9BcnJheShfdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4sIHJvd05vZGUsIE1hdGgubWF4KGluZGV4QXRQaXhlbE5vdyArIGluY3JlbWVudCwgMCkgKyBpZHgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5yZWZyZXNoTW9kZWwoe1xuICAgICAgICAgICAgc3RlcDogQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuRVZFUllUSElORyxcbiAgICAgICAgICAgIGtlZXBSZW5kZXJlZFJvd3M6IHRydWUsXG4gICAgICAgICAgICBrZWVwRWRpdGluZ1Jvd3M6IHRydWUsXG4gICAgICAgICAgICBhbmltYXRlOiBhbmltYXRlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuaGlnaGxpZ2h0Um93QXRQaXhlbCA9IGZ1bmN0aW9uIChyb3dOb2RlLCBwaXhlbCkge1xuICAgICAgICB2YXIgaW5kZXhBdFBpeGVsTm93ID0gcGl4ZWwgIT0gbnVsbCA/IHRoaXMuZ2V0Um93SW5kZXhBdFBpeGVsKHBpeGVsKSA6IG51bGw7XG4gICAgICAgIHZhciByb3dOb2RlQXRQaXhlbE5vdyA9IGluZGV4QXRQaXhlbE5vdyAhPSBudWxsID8gdGhpcy5nZXRSb3coaW5kZXhBdFBpeGVsTm93KSA6IG51bGw7XG4gICAgICAgIGlmICghcm93Tm9kZUF0UGl4ZWxOb3cgfHwgIXJvd05vZGUgfHwgcm93Tm9kZUF0UGl4ZWxOb3cgPT09IHJvd05vZGUgfHwgcGl4ZWwgPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGFzdEhpZ2hsaWdodGVkUm93KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0SGlnaGxpZ2h0ZWRSb3cuc2V0SGlnaGxpZ2h0ZWQobnVsbCk7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0SGlnaGxpZ2h0ZWRSb3cgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBoaWdobGlnaHQgPSB0aGlzLmdldEhpZ2hsaWdodFBvc2l0aW9uKHBpeGVsLCByb3dOb2RlQXRQaXhlbE5vdyk7XG4gICAgICAgIGlmICh0aGlzLmxhc3RIaWdobGlnaHRlZFJvdyAmJiB0aGlzLmxhc3RIaWdobGlnaHRlZFJvdyAhPT0gcm93Tm9kZUF0UGl4ZWxOb3cpIHtcbiAgICAgICAgICAgIHRoaXMubGFzdEhpZ2hsaWdodGVkUm93LnNldEhpZ2hsaWdodGVkKG51bGwpO1xuICAgICAgICAgICAgdGhpcy5sYXN0SGlnaGxpZ2h0ZWRSb3cgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJvd05vZGVBdFBpeGVsTm93LnNldEhpZ2hsaWdodGVkKGhpZ2hsaWdodCk7XG4gICAgICAgIHRoaXMubGFzdEhpZ2hsaWdodGVkUm93ID0gcm93Tm9kZUF0UGl4ZWxOb3c7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldEhpZ2hsaWdodFBvc2l0aW9uID0gZnVuY3Rpb24gKHBpeGVsLCByb3dOb2RlKSB7XG4gICAgICAgIGlmICghcm93Tm9kZSkge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gdGhpcy5nZXRSb3dJbmRleEF0UGl4ZWwocGl4ZWwpO1xuICAgICAgICAgICAgcm93Tm9kZSA9IHRoaXMuZ2V0Um93KGluZGV4IHx8IDApO1xuICAgICAgICAgICAgaWYgKCFyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFJvd0hpZ2hsaWdodFBvc2l0aW9uLkJlbG93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciByb3dUb3AgPSByb3dOb2RlLnJvd1RvcCwgcm93SGVpZ2h0ID0gcm93Tm9kZS5yb3dIZWlnaHQ7XG4gICAgICAgIHJldHVybiBwaXhlbCAtIHJvd1RvcCA8IHJvd0hlaWdodCAvIDIgPyBSb3dIaWdobGlnaHRQb3NpdGlvbi5BYm92ZSA6IFJvd0hpZ2hsaWdodFBvc2l0aW9uLkJlbG93O1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5nZXRMYXN0SGlnaGxpZ2h0ZWRSb3dOb2RlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0SGlnaGxpZ2h0ZWRSb3c7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmlzTGFzdFJvd0luZGV4S25vd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5nZXRSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucm93c1RvRGlzcGxheSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93c1RvRGlzcGxheS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldFRvcExldmVsUm93Q291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzaG93aW5nUm9vdE5vZGUgPSB0aGlzLnJvd3NUb0Rpc3BsYXkgJiYgdGhpcy5yb3dzVG9EaXNwbGF5WzBdID09PSB0aGlzLnJvb3ROb2RlO1xuICAgICAgICBpZiAoc2hvd2luZ1Jvb3ROb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZmlsdGVyZWRDaGlsZHJlbiA9IHRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlckFnZ0ZpbHRlcjtcbiAgICAgICAgcmV0dXJuIGZpbHRlcmVkQ2hpbGRyZW4gPyBmaWx0ZXJlZENoaWxkcmVuLmxlbmd0aCA6IDA7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldFRvcExldmVsUm93RGlzcGxheWVkSW5kZXggPSBmdW5jdGlvbiAodG9wTGV2ZWxJbmRleCkge1xuICAgICAgICB2YXIgc2hvd2luZ1Jvb3ROb2RlID0gdGhpcy5yb3dzVG9EaXNwbGF5ICYmIHRoaXMucm93c1RvRGlzcGxheVswXSA9PT0gdGhpcy5yb290Tm9kZTtcbiAgICAgICAgaWYgKHNob3dpbmdSb290Tm9kZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRvcExldmVsSW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvd05vZGUgPSB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0W3RvcExldmVsSW5kZXhdO1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cEhpZGVPcGVuUGFyZW50cygpKSB7XG4gICAgICAgICAgICAvLyBpZiBoaWRlT3BlblBhcmVudHMsIGFuZCB0aGlzIHJvdyBvcGVuLCB0aGVuIHRoaXMgcm93IGlzIG5vdyBkaXNwbGF5ZWQgYXQgdGhpcyBpbmRleCwgZmlyc3QgY2hpbGQgaXNcbiAgICAgICAgICAgIHdoaWxlIChyb3dOb2RlLmV4cGFuZGVkICYmIHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQgJiYgcm93Tm9kZS5jaGlsZHJlbkFmdGVyU29ydC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZSA9IHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnRbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJvd05vZGUucm93SW5kZXg7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldFJvd0JvdW5kcyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICBpZiAoXy5taXNzaW5nKHRoaXMucm93c1RvRGlzcGxheSkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciByb3dOb2RlID0gdGhpcy5yb3dzVG9EaXNwbGF5W2luZGV4XTtcbiAgICAgICAgaWYgKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgcm93VG9wOiByb3dOb2RlLnJvd1RvcCxcbiAgICAgICAgICAgICAgICByb3dIZWlnaHQ6IHJvd05vZGUucm93SGVpZ2h0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5vblJvd0dyb3VwT3BlbmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYW5pbWF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQW5pbWF0ZVJvd3MoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoTW9kZWwoeyBzdGVwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5NQVAsIGtlZXBSZW5kZXJlZFJvd3M6IHRydWUsIGFuaW1hdGU6IGFuaW1hdGUgfSk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLm9uRmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQuYWZ0ZXJEYXRhQ2hhbmdlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFuaW1hdGUgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0FuaW1hdGVSb3dzKCk7XG4gICAgICAgIHZhciBwcmltYXJ5T3JRdWlja0ZpbHRlckNoYW5nZWQgPSBldmVudC5jb2x1bW5zLmxlbmd0aCA9PT0gMCB8fCBldmVudC5jb2x1bW5zLnNvbWUoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gY29sLmlzUHJpbWFyeSgpOyB9KTtcbiAgICAgICAgdmFyIHN0ZXAgPSBwcmltYXJ5T3JRdWlja0ZpbHRlckNoYW5nZWQgPyBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5GSUxURVIgOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5GSUxURVJfQUdHUkVHQVRFUztcbiAgICAgICAgdGhpcy5yZWZyZXNoTW9kZWwoeyBzdGVwOiBzdGVwLCBrZWVwUmVuZGVyZWRSb3dzOiB0cnVlLCBhbmltYXRlOiBhbmltYXRlIH0pO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5vblNvcnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgYW5pbWF0ZSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzQW5pbWF0ZVJvd3MoKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoTW9kZWwoeyBzdGVwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5TT1JULCBrZWVwUmVuZGVyZWRSb3dzOiB0cnVlLCBhbmltYXRlOiBhbmltYXRlLCBrZWVwRWRpdGluZ1Jvd3M6IHRydWUgfSk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBDb25zdGFudHMuUk9XX01PREVMX1RZUEVfQ0xJRU5UX1NJREU7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLm9uVmFsdWVDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90QWN0aXZlKCkpIHtcbiAgICAgICAgICAgIHRoaXMucmVmcmVzaE1vZGVsKHsgc3RlcDogQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuUElWT1QgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hNb2RlbCh7IHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLkFHR1JFR0FURSB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5jcmVhdGVDaGFuZ2VQYXRoID0gZnVuY3Rpb24gKHJvd05vZGVUcmFuc2FjdGlvbnMpIHtcbiAgICAgICAgLy8gZm9yIHVwZGF0ZXMsIGlmIHRoZSByb3cgaXMgdXBkYXRlZCBhdCBhbGwsIHRoZW4gd2UgcmUtY2FsYyBhbGwgdGhlIHZhbHVlc1xuICAgICAgICAvLyBpbiB0aGF0IHJvdy4gd2UgY291bGQgY29tcGFyZSBlYWNoIHZhbHVlIHRvIGVhY2ggb2xkIHZhbHVlLCBob3dldmVyIGlmIHdlXG4gICAgICAgIC8vIGRpZCB0aGlzLCB3ZSB3b3VsZCBiZSBjYWxsaW5nIHRoZSB2YWx1ZVNlcnZpY2UgdHdpY2UsIG9uY2Ugb24gdGhlIG9sZCB2YWx1ZVxuICAgICAgICAvLyBhbmQgb25jZSBvbiB0aGUgbmV3IHZhbHVlLiBzbyBpdCdzIGxlc3MgdmFsdWVHZXR0ZXIgY2FsbHMgaWYgd2UganVzdCBhc3N1bWVcbiAgICAgICAgLy8gZWFjaCBjb2x1bW4gaXMgZGlmZmVyZW50LiB0aGF0IHdheSB0aGUgY2hhbmdlZFBhdGggaXMgdXNlZCBzbyB0aGF0IG9ubHlcbiAgICAgICAgLy8gdGhlIGltcGFjdGVkIHBhcmVudCByb3dzIGFyZSByZWNhbGN1bGF0ZWQsIHBhcmVudHMgd2hvJ3MgY2hpbGRyZW4gaGF2ZVxuICAgICAgICAvLyBub3QgY2hhbmdlZCBhcmUgbm90IGltcGFjdGVkLlxuICAgICAgICB2YXIgbm9UcmFuc2FjdGlvbnMgPSBfLm1pc3NpbmdPckVtcHR5KHJvd05vZGVUcmFuc2FjdGlvbnMpO1xuICAgICAgICB2YXIgY2hhbmdlZFBhdGggPSBuZXcgQ2hhbmdlZFBhdGgoZmFsc2UsIHRoaXMucm9vdE5vZGUpO1xuICAgICAgICBpZiAobm9UcmFuc2FjdGlvbnMgfHwgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNUcmVlRGF0YSgpKSB7XG4gICAgICAgICAgICBjaGFuZ2VkUGF0aC5zZXRJbmFjdGl2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaGFuZ2VkUGF0aDtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuaXNTdXBwcmVzc01vZGVsVXBkYXRlQWZ0ZXJVcGRhdGVUcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTW9kZWxVcGRhdGVBZnRlclVwZGF0ZVRyYW5zYWN0aW9uKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyByZXR1cm4gdHJ1ZSBpZiB3ZSBhcmUgb25seSBkb2luZyB1cGRhdGUgdHJhbnNhY3Rpb25zXG4gICAgICAgIGlmIChwYXJhbXMucm93Tm9kZVRyYW5zYWN0aW9ucyA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRyYW5zV2l0aEFkZHNPckRlbGV0ZXMgPSBwYXJhbXMucm93Tm9kZVRyYW5zYWN0aW9ucy5maWx0ZXIoZnVuY3Rpb24gKHR4KSB7XG4gICAgICAgICAgICByZXR1cm4gKHR4LmFkZCAhPSBudWxsICYmIHR4LmFkZC5sZW5ndGggPiAwKSB8fCAodHgucmVtb3ZlICE9IG51bGwgJiYgdHgucmVtb3ZlLmxlbmd0aCA+IDApO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHRyYW5zYWN0aW9uc0NvbnRhaW5VcGRhdGVzT25seSA9IHRyYW5zV2l0aEFkZHNPckRlbGV0ZXMgPT0gbnVsbCB8fCB0cmFuc1dpdGhBZGRzT3JEZWxldGVzLmxlbmd0aCA9PSAwO1xuICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb25zQ29udGFpblVwZGF0ZXNPbmx5O1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5yZWZyZXNoTW9kZWwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIGlmICh0aGlzLmlzU3VwcHJlc3NNb2RlbFVwZGF0ZUFmdGVyVXBkYXRlVHJhbnNhY3Rpb24ocGFyYW1zKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoaXMgZ29lcyB0aHJvdWdoIHRoZSBwaXBlbGluZSBvZiBzdGFnZXMuIHdoYXQncyBpbiBteSBoZWFkIGlzIHNpbWlsYXJcbiAgICAgICAgLy8gdG8gdGhlIGRpYWdyYW0gb24gdGhpcyBwYWdlOlxuICAgICAgICAvLyBodHRwOi8vY29tbW9ucy5hcGFjaGUub3JnL3NhbmRib3gvY29tbW9ucy1waXBlbGluZS9waXBlbGluZV9iYXNpY3MuaHRtbFxuICAgICAgICAvLyBob3dldmVyIHdlIHdhbnQgdG8ga2VlcCB0aGUgcmVzdWx0cyBvZiBlYWNoIHN0YWdlLCBoZW5jZSB3ZSBtYW51YWxseSBjYWxsXG4gICAgICAgIC8vIGVhY2ggc3RlcCByYXRoZXIgdGhhbiBoYXZlIHRoZW0gY2hhaW4gZWFjaCBvdGhlci5cbiAgICAgICAgLy8gZmFsbHRocm91Z2ggaW4gYmVsb3cgc3dpdGNoIGlzIG9uIHB1cnBvc2UsXG4gICAgICAgIC8vIGVnIGlmIFNURVBfRklMVEVSLCB0aGVuIGFsbCBzdGVwcyBiZWxvdyB0aGlzXG4gICAgICAgIC8vIHN0ZXAgZ2V0IGRvbmVcbiAgICAgICAgLy8gbGV0IHN0YXJ0OiBudW1iZXI7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCc9PT09PT09IHN0YXJ0ID09PT09PT0nKTtcbiAgICAgICAgdmFyIGNoYW5nZWRQYXRoID0gdGhpcy5jcmVhdGVDaGFuZ2VQYXRoKHBhcmFtcy5yb3dOb2RlVHJhbnNhY3Rpb25zKTtcbiAgICAgICAgc3dpdGNoIChwYXJhbXMuc3RlcCkge1xuICAgICAgICAgICAgY2FzZSBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5FVkVSWVRISU5HOlxuICAgICAgICAgICAgICAgIHRoaXMuZG9Sb3dHcm91cGluZyhwYXJhbXMuZ3JvdXBTdGF0ZSwgcGFyYW1zLnJvd05vZGVUcmFuc2FjdGlvbnMsIHBhcmFtcy5yb3dOb2RlT3JkZXIsIGNoYW5nZWRQYXRoLCAhIXBhcmFtcy5hZnRlckNvbHVtbnNDaGFuZ2VkKTtcbiAgICAgICAgICAgIGNhc2UgQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuRklMVEVSOlxuICAgICAgICAgICAgICAgIHRoaXMuZG9GaWx0ZXIoY2hhbmdlZFBhdGgpO1xuICAgICAgICAgICAgY2FzZSBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5QSVZPVDpcbiAgICAgICAgICAgICAgICB0aGlzLmRvUGl2b3QoY2hhbmdlZFBhdGgpO1xuICAgICAgICAgICAgY2FzZSBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5BR0dSRUdBVEU6IC8vIGRlcGVuZHMgb24gYWdnIGZpZWxkc1xuICAgICAgICAgICAgICAgIHRoaXMuZG9BZ2dyZWdhdGUoY2hhbmdlZFBhdGgpO1xuICAgICAgICAgICAgY2FzZSBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5GSUxURVJfQUdHUkVHQVRFUzpcbiAgICAgICAgICAgICAgICB0aGlzLmRvRmlsdGVyQWdncmVnYXRlcyhjaGFuZ2VkUGF0aCk7XG4gICAgICAgICAgICBjYXNlIENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLlNPUlQ6XG4gICAgICAgICAgICAgICAgdGhpcy5kb1NvcnQocGFyYW1zLnJvd05vZGVUcmFuc2FjdGlvbnMsIGNoYW5nZWRQYXRoKTtcbiAgICAgICAgICAgIGNhc2UgQ2xpZW50U2lkZVJvd01vZGVsU3RlcHMuTUFQOlxuICAgICAgICAgICAgICAgIHRoaXMuZG9Sb3dzVG9EaXNwbGF5KCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc2V0IGFsbCByb3cgdG9wcyB0byBudWxsLCB0aGVuIHNldCByb3cgdG9wcyBvbiBhbGwgdmlzaWJsZSByb3dzLiBpZiB3ZSBkb24ndFxuICAgICAgICAvLyBkbyB0aGlzLCB0aGVuIHRoZSBhbGdvcml0aG0gYmVsb3cgb25seSBzZXRzIHJvdyB0b3BzLCBvbGQgcm93IHRvcHMgZnJvbSBvbGQgcm93c1xuICAgICAgICAvLyB3aWxsIHN0aWxsIGxpZSBhcm91bmRcbiAgICAgICAgdmFyIGRpc3BsYXllZE5vZGVzTWFwcGVkID0gdGhpcy5zZXRSb3dUb3BBbmRSb3dJbmRleCgpO1xuICAgICAgICB0aGlzLmNsZWFyUm93VG9wQW5kUm93SW5kZXgoY2hhbmdlZFBhdGgsIGRpc3BsYXllZE5vZGVzTWFwcGVkKTtcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX01PREVMX1VQREFURUQsXG4gICAgICAgICAgICBhbmltYXRlOiBwYXJhbXMuYW5pbWF0ZSxcbiAgICAgICAgICAgIGtlZXBSZW5kZXJlZFJvd3M6IHBhcmFtcy5rZWVwUmVuZGVyZWRSb3dzLFxuICAgICAgICAgICAgbmV3RGF0YTogcGFyYW1zLm5ld0RhdGEsXG4gICAgICAgICAgICBuZXdQYWdlOiBmYWxzZSxcbiAgICAgICAgICAgIGtlZXBVbmRvUmVkb1N0YWNrOiBwYXJhbXMua2VlcFVuZG9SZWRvU3RhY2tcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmlzRW1wdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByb3dzTWlzc2luZyA9IF8ubWlzc2luZyh0aGlzLnJvb3ROb2RlLmFsbExlYWZDaGlsZHJlbikgfHwgdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4ubGVuZ3RoID09PSAwO1xuICAgICAgICByZXR1cm4gXy5taXNzaW5nKHRoaXMucm9vdE5vZGUpIHx8IHJvd3NNaXNzaW5nIHx8ICF0aGlzLmNvbHVtbk1vZGVsLmlzUmVhZHkoKTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuaXNSb3dzVG9SZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBfLmV4aXN0cyh0aGlzLnJvd3NUb0Rpc3BsYXkpICYmIHRoaXMucm93c1RvRGlzcGxheS5sZW5ndGggPiAwO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5nZXROb2Rlc0luUmFuZ2VGb3JTZWxlY3Rpb24gPSBmdW5jdGlvbiAoZmlyc3RJblJhbmdlLCBsYXN0SW5SYW5nZSkge1xuICAgICAgICAvLyBpZiBsYXN0U2VsZWN0ZWROb2RlIGlzIG1pc3NpbmcsIHdlIHN0YXJ0IGF0IHRoZSBmaXJzdCByb3dcbiAgICAgICAgdmFyIGZpcnN0Um93SGl0ID0gIWxhc3RJblJhbmdlO1xuICAgICAgICB2YXIgbGFzdFJvd0hpdCA9IGZhbHNlO1xuICAgICAgICB2YXIgbGFzdFJvdztcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIgZ3JvdXBzU2VsZWN0Q2hpbGRyZW4gPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwU2VsZWN0c0NoaWxkcmVuKCk7XG4gICAgICAgIHRoaXMuZm9yRWFjaE5vZGVBZnRlckZpbHRlckFuZFNvcnQoZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHZhciBsb29raW5nRm9yTGFzdFJvdyA9IGZpcnN0Um93SGl0ICYmICFsYXN0Um93SGl0O1xuICAgICAgICAgICAgLy8gY2hlY2sgaWYgd2UgbmVlZCB0byBmbGlwIHRoZSBzZWxlY3Qgc3dpdGNoXG4gICAgICAgICAgICBpZiAoIWZpcnN0Um93SGl0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvd05vZGUgPT09IGxhc3RJblJhbmdlIHx8IHJvd05vZGUgPT09IGZpcnN0SW5SYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdFJvd0hpdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHNraXBUaGlzR3JvdXBOb2RlID0gcm93Tm9kZS5ncm91cCAmJiBncm91cHNTZWxlY3RDaGlsZHJlbjtcbiAgICAgICAgICAgIGlmICghc2tpcFRoaXNHcm91cE5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5SYW5nZSA9IGZpcnN0Um93SGl0ICYmICFsYXN0Um93SGl0O1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE9mTGFzdFJvdyA9IHJvd05vZGUuaXNQYXJlbnRPZk5vZGUobGFzdFJvdyk7XG4gICAgICAgICAgICAgICAgaWYgKGluUmFuZ2UgfHwgY2hpbGRPZkxhc3RSb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gocm93Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxvb2tpbmdGb3JMYXN0Um93KSB7XG4gICAgICAgICAgICAgICAgaWYgKHJvd05vZGUgPT09IGxhc3RJblJhbmdlIHx8IHJvd05vZGUgPT09IGZpcnN0SW5SYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICBsYXN0Um93SGl0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJvd05vZGUgPT09IGxhc3RJblJhbmdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0Um93ID0gbGFzdEluUmFuZ2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0Um93ID0gZmlyc3RJblJhbmdlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuc2V0RGF0YXNvdXJjZSA9IGZ1bmN0aW9uIChkYXRhc291cmNlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FHIEdyaWQ6IHNob3VsZCBuZXZlciBjYWxsIHNldERhdGFzb3VyY2Ugb24gY2xpZW50U2lkZVJvd0NvbnRyb2xsZXInKTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZ2V0VG9wTGV2ZWxOb2RlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vdE5vZGUgPyB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCA6IG51bGw7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldFJvb3ROb2RlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb290Tm9kZTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZ2V0Um93ID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd3NUb0Rpc3BsYXlbaW5kZXhdO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5pc1Jvd1ByZXNlbnQgPSBmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dzVG9EaXNwbGF5LmluZGV4T2Yocm93Tm9kZSkgPj0gMDtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZ2V0Um93SW5kZXhBdFBpeGVsID0gZnVuY3Rpb24gKHBpeGVsVG9NYXRjaCkge1xuICAgICAgICBpZiAodGhpcy5pc0VtcHR5KCkgfHwgdGhpcy5yb3dzVG9EaXNwbGF5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIC8vIGRvIGJpbmFyeSBzZWFyY2ggb2YgdHJlZVxuICAgICAgICAvLyBodHRwOi8vb2xpLm1lLnVrLzIwMTMvMDYvMDgvc2VhcmNoaW5nLWphdmFzY3JpcHQtYXJyYXlzLXdpdGgtYS1iaW5hcnktc2VhcmNoL1xuICAgICAgICB2YXIgYm90dG9tUG9pbnRlciA9IDA7XG4gICAgICAgIHZhciB0b3BQb2ludGVyID0gdGhpcy5yb3dzVG9EaXNwbGF5Lmxlbmd0aCAtIDE7XG4gICAgICAgIC8vIHF1aWNrIGNoZWNrLCBpZiB0aGUgcGl4ZWwgaXMgb3V0IG9mIGJvdW5kcywgdGhlbiByZXR1cm4gbGFzdCByb3dcbiAgICAgICAgaWYgKHBpeGVsVG9NYXRjaCA8PSAwKSB7XG4gICAgICAgICAgICAvLyBpZiBwaXhlbCBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgemVybywgaXQncyBhbHdheXMgdGhlIGZpcnN0IHJvd1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxhc3ROb2RlID0gXy5sYXN0KHRoaXMucm93c1RvRGlzcGxheSk7XG4gICAgICAgIGlmIChsYXN0Tm9kZS5yb3dUb3AgPD0gcGl4ZWxUb01hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3dzVG9EaXNwbGF5Lmxlbmd0aCAtIDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9sZEJvdHRvbVBvaW50ZXIgPSAtMTtcbiAgICAgICAgdmFyIG9sZFRvcFBvaW50ZXIgPSAtMTtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgIHZhciBtaWRQb2ludGVyID0gTWF0aC5mbG9vcigoYm90dG9tUG9pbnRlciArIHRvcFBvaW50ZXIpIC8gMik7XG4gICAgICAgICAgICB2YXIgY3VycmVudFJvd05vZGUgPSB0aGlzLnJvd3NUb0Rpc3BsYXlbbWlkUG9pbnRlcl07XG4gICAgICAgICAgICBpZiAodGhpcy5pc1Jvd0luUGl4ZWwoY3VycmVudFJvd05vZGUsIHBpeGVsVG9NYXRjaCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWlkUG9pbnRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjdXJyZW50Um93Tm9kZS5yb3dUb3AgPCBwaXhlbFRvTWF0Y2gpIHtcbiAgICAgICAgICAgICAgICBib3R0b21Qb2ludGVyID0gbWlkUG9pbnRlciArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChjdXJyZW50Um93Tm9kZS5yb3dUb3AgPiBwaXhlbFRvTWF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0b3BQb2ludGVyID0gbWlkUG9pbnRlciAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpbmZpbml0ZSBsb29wcyBoYXBwZW4gd2hlbiB0aGVyZSBpcyBzcGFjZSBiZXR3ZWVuIHJvd3MuIHRoaXMgY2FuIGhhcHBlblxuICAgICAgICAgICAgLy8gd2hlbiBBdXRvIEhlaWdodCBpcyBhY3RpdmUsIGNvcyB3ZSByZS1jYWxjdWxhdGUgcm93IHRvcHMgYXN5bmNyb25vdXNseVxuICAgICAgICAgICAgLy8gd2hlbiByb3cgaGVpZ2h0cyBjaGFuZ2UsIHdoaWNoIGNhbiB0ZW1wb3Jhcmx5IHJlc3VsdCBpbiBnYXBzIGJldHdlZW4gcm93cy5cbiAgICAgICAgICAgIHZhciBjYXVnaHRJbkluZmluaXRlTG9vcCA9IG9sZEJvdHRvbVBvaW50ZXIgPT09IGJvdHRvbVBvaW50ZXJcbiAgICAgICAgICAgICAgICAmJiBvbGRUb3BQb2ludGVyID09PSB0b3BQb2ludGVyO1xuICAgICAgICAgICAgaWYgKGNhdWdodEluSW5maW5pdGVMb29wKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1pZFBvaW50ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvbGRCb3R0b21Qb2ludGVyID0gYm90dG9tUG9pbnRlcjtcbiAgICAgICAgICAgIG9sZFRvcFBvaW50ZXIgPSB0b3BQb2ludGVyO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmlzUm93SW5QaXhlbCA9IGZ1bmN0aW9uIChyb3dOb2RlLCBwaXhlbFRvTWF0Y2gpIHtcbiAgICAgICAgdmFyIHRvcFBpeGVsID0gcm93Tm9kZS5yb3dUb3A7XG4gICAgICAgIHZhciBib3R0b21QaXhlbCA9IHJvd05vZGUucm93VG9wICsgcm93Tm9kZS5yb3dIZWlnaHQ7XG4gICAgICAgIHZhciBwaXhlbEluUm93ID0gdG9wUGl4ZWwgPD0gcGl4ZWxUb01hdGNoICYmIGJvdHRvbVBpeGVsID4gcGl4ZWxUb01hdGNoO1xuICAgICAgICByZXR1cm4gcGl4ZWxJblJvdztcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZm9yRWFjaExlYWZOb2RlID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICh0aGlzLnJvb3ROb2RlLmFsbExlYWZDaGlsZHJlbikge1xuICAgICAgICAgICAgdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSwgaW5kZXgpIHsgcmV0dXJuIGNhbGxiYWNrKHJvd05vZGUsIGluZGV4KTsgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZm9yRWFjaE5vZGUgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5yZWN1cnNpdmVseVdhbGtOb2Rlc0FuZENhbGxiYWNrKHRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwLCBjYWxsYmFjaywgUmVjdXJzaW9uVHlwZS5Ob3JtYWwsIDApO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5mb3JFYWNoTm9kZUFmdGVyRmlsdGVyID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMucmVjdXJzaXZlbHlXYWxrTm9kZXNBbmRDYWxsYmFjayh0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJBZ2dGaWx0ZXIsIGNhbGxiYWNrLCBSZWN1cnNpb25UeXBlLkFmdGVyRmlsdGVyLCAwKTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZm9yRWFjaE5vZGVBZnRlckZpbHRlckFuZFNvcnQgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5yZWN1cnNpdmVseVdhbGtOb2Rlc0FuZENhbGxiYWNrKHRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlclNvcnQsIGNhbGxiYWNrLCBSZWN1cnNpb25UeXBlLkFmdGVyRmlsdGVyQW5kU29ydCwgMCk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmZvckVhY2hQaXZvdE5vZGUgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5yZWN1cnNpdmVseVdhbGtOb2Rlc0FuZENhbGxiYWNrKFt0aGlzLnJvb3ROb2RlXSwgY2FsbGJhY2ssIFJlY3Vyc2lvblR5cGUuUGl2b3ROb2RlcywgMCk7XG4gICAgfTtcbiAgICAvLyBpdGVyYXRlcyB0aHJvdWdoIGVhY2ggaXRlbSBpbiBtZW1vcnksIGFuZCBjYWxscyB0aGUgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICAvLyBub2RlcyAtIHRoZSByb3dOb2RlcyB0byB0cmF2ZXJzZVxuICAgIC8vIGNhbGxiYWNrIC0gdGhlIHVzZXIgcHJvdmlkZWQgY2FsbGJhY2tcbiAgICAvLyByZWN1cnNpb24gdHlwZSAtIG5lZWQgdGhpcyB0byBrbm93IHdoYXQgY2hpbGQgbm9kZXMgdG8gcmVjdXJzZSwgZWcgaWYgbG9va2luZyBhdCBhbGwgbm9kZXMsIG9yIGZpbHRlcmVkIG5vdGVzIGV0Y1xuICAgIC8vIGluZGV4IC0gd29ya3Mgc2ltaWxhciB0byB0aGUgaW5kZXggaW4gZm9yRWFjaCBpbiBqYXZhc2NyaXB0J3MgYXJyYXkgZnVuY3Rpb25cbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLnJlY3Vyc2l2ZWx5V2Fsa05vZGVzQW5kQ2FsbGJhY2sgPSBmdW5jdGlvbiAobm9kZXMsIGNhbGxiYWNrLCByZWN1cnNpb25UeXBlLCBpbmRleCkge1xuICAgICAgICBpZiAoIW5vZGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgICAgIGNhbGxiYWNrKG5vZGUsIGluZGV4KyspO1xuICAgICAgICAgICAgLy8gZ28gdG8gdGhlIG5leHQgbGV2ZWwgaWYgaXQgaXMgYSBncm91cFxuICAgICAgICAgICAgaWYgKG5vZGUuaGFzQ2hpbGRyZW4oKSkge1xuICAgICAgICAgICAgICAgIC8vIGRlcGVuZGluZyBvbiB0aGUgcmVjdXJzaW9uIHR5cGUsIHdlIHBpY2sgYSBkaWZmZXJlbmNlIHNldCBvZiBjaGlsZHJlblxuICAgICAgICAgICAgICAgIHZhciBub2RlQ2hpbGRyZW4gPSBudWxsO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAocmVjdXJzaW9uVHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFJlY3Vyc2lvblR5cGUuTm9ybWFsOlxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbkFmdGVyR3JvdXA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBSZWN1cnNpb25UeXBlLkFmdGVyRmlsdGVyOlxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbkFmdGVyQWdnRmlsdGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgUmVjdXJzaW9uVHlwZS5BZnRlckZpbHRlckFuZFNvcnQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlQ2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuQWZ0ZXJTb3J0O1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgUmVjdXJzaW9uVHlwZS5QaXZvdE5vZGVzOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZm9yIHBpdm90LCB3ZSBkb24ndCBnbyBiZWxvdyBsZWFmR3JvdXAgbGV2ZWxzXG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlQ2hpbGRyZW4gPSAhbm9kZS5sZWFmR3JvdXAgPyBub2RlLmNoaWxkcmVuQWZ0ZXJTb3J0IDogbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobm9kZUNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ID0gdGhpcy5yZWN1cnNpdmVseVdhbGtOb2Rlc0FuZENhbGxiYWNrKG5vZGVDaGlsZHJlbiwgY2FsbGJhY2ssIHJlY3Vyc2lvblR5cGUsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH07XG4gICAgLy8gaXQncyBwb3NzaWJsZSB0byByZWNvbXB1dGUgdGhlIGFnZ3JlZ2F0ZSB3aXRob3V0IGRvaW5nIHRoZSBvdGhlciBwYXJ0c1xuICAgIC8vICsgZ3JpZEFwaS5yZWNvbXB1dGVBZ2dyZWdhdGVzKClcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmRvQWdncmVnYXRlID0gZnVuY3Rpb24gKGNoYW5nZWRQYXRoKSB7XG4gICAgICAgIGlmICh0aGlzLmFnZ3JlZ2F0aW9uU3RhZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuYWdncmVnYXRpb25TdGFnZS5leGVjdXRlKHsgcm93Tm9kZTogdGhpcy5yb290Tm9kZSwgY2hhbmdlZFBhdGg6IGNoYW5nZWRQYXRoIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmRvRmlsdGVyQWdncmVnYXRlcyA9IGZ1bmN0aW9uIChjaGFuZ2VkUGF0aCkge1xuICAgICAgICBpZiAodGhpcy5maWx0ZXJBZ2dyZWdhdGVzU3RhZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsdGVyQWdncmVnYXRlc1N0YWdlLmV4ZWN1dGUoeyByb3dOb2RlOiB0aGlzLnJvb3ROb2RlLCBjaGFuZ2VkUGF0aDogY2hhbmdlZFBhdGggfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBJZiBmaWx0ZXJBZ2dyZWdhdGVzU3RhZ2UgaXMgdW5kZWZpbmVkLCB0aGVuIHNvIGlzIHRoZSBncm91cGluZyBzdGFnZSwgc28gYWxsIGNoaWxkcmVuIHNob3VsZCBiZSBvbiB0aGUgcm9vdE5vZGUuXG4gICAgICAgICAgICB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJBZ2dGaWx0ZXIgPSB0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJGaWx0ZXI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vICsgZ3JpZEFwaS5leHBhbmRBbGwoKVxuICAgIC8vICsgZ3JpZEFwaS5jb2xsYXBzZUFsbCgpXG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5leHBhbmRPckNvbGxhcHNlQWxsID0gZnVuY3Rpb24gKGV4cGFuZCkge1xuICAgICAgICB2YXIgdXNpbmdUcmVlRGF0YSA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKTtcbiAgICAgICAgdmFyIHVzaW5nUGl2b3RNb2RlID0gdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90QWN0aXZlKCk7XG4gICAgICAgIHZhciByZWN1cnNpdmVFeHBhbmRPckNvbGxhcHNlID0gZnVuY3Rpb24gKHJvd05vZGVzKSB7XG4gICAgICAgICAgICBpZiAoIXJvd05vZGVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcm93Tm9kZXMuZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBhY3Rpb25Sb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvd05vZGUuZXhwYW5kZWQgPSBleHBhbmQ7XG4gICAgICAgICAgICAgICAgICAgIHJlY3Vyc2l2ZUV4cGFuZE9yQ29sbGFwc2Uocm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXApO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKHVzaW5nVHJlZURhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhhc0NoaWxkcmVuID0gXy5leGlzdHMocm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGFzQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvblJvdygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHVzaW5nUGl2b3RNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub3RMZWFmR3JvdXAgPSAhcm93Tm9kZS5sZWFmR3JvdXA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChub3RMZWFmR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvblJvdygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGlzUm93R3JvdXAgPSByb3dOb2RlLmdyb3VwO1xuICAgICAgICAgICAgICAgIGlmIChpc1Jvd0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvblJvdygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5yb290Tm9kZSkge1xuICAgICAgICAgICAgcmVjdXJzaXZlRXhwYW5kT3JDb2xsYXBzZSh0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWZyZXNoTW9kZWwoeyBzdGVwOiBDbGllbnRTaWRlUm93TW9kZWxTdGVwcy5NQVAgfSk7XG4gICAgICAgIHZhciBldmVudFNvdXJjZSA9IGV4cGFuZCA/ICdleHBhbmRBbGwnIDogJ2NvbGxhcHNlQWxsJztcbiAgICAgICAgdmFyIGV2ZW50ID0ge1xuICAgICAgICAgICAgdHlwZTogRXZlbnRzLkVWRU5UX0VYUEFORF9DT0xMQVBTRV9BTEwsXG4gICAgICAgICAgICBzb3VyY2U6IGV2ZW50U291cmNlXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5kb1NvcnQgPSBmdW5jdGlvbiAocm93Tm9kZVRyYW5zYWN0aW9ucywgY2hhbmdlZFBhdGgpIHtcbiAgICAgICAgdGhpcy5zb3J0U3RhZ2UuZXhlY3V0ZSh7XG4gICAgICAgICAgICByb3dOb2RlOiB0aGlzLnJvb3ROb2RlLFxuICAgICAgICAgICAgcm93Tm9kZVRyYW5zYWN0aW9uczogcm93Tm9kZVRyYW5zYWN0aW9ucyxcbiAgICAgICAgICAgIGNoYW5nZWRQYXRoOiBjaGFuZ2VkUGF0aFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZG9Sb3dHcm91cGluZyA9IGZ1bmN0aW9uIChncm91cFN0YXRlLCByb3dOb2RlVHJhbnNhY3Rpb25zLCByb3dOb2RlT3JkZXIsIGNoYW5nZWRQYXRoLCBhZnRlckNvbHVtbnNDaGFuZ2VkKSB7XG4gICAgICAgIGlmICh0aGlzLmdyb3VwU3RhZ2UpIHtcbiAgICAgICAgICAgIGlmIChyb3dOb2RlVHJhbnNhY3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ncm91cFN0YWdlLmV4ZWN1dGUoe1xuICAgICAgICAgICAgICAgICAgICByb3dOb2RlOiB0aGlzLnJvb3ROb2RlLFxuICAgICAgICAgICAgICAgICAgICByb3dOb2RlVHJhbnNhY3Rpb25zOiByb3dOb2RlVHJhbnNhY3Rpb25zLFxuICAgICAgICAgICAgICAgICAgICByb3dOb2RlT3JkZXI6IHJvd05vZGVPcmRlcixcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlZFBhdGg6IGNoYW5nZWRQYXRoXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmdyb3VwU3RhZ2UuZXhlY3V0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHJvd05vZGU6IHRoaXMucm9vdE5vZGUsXG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZWRQYXRoOiBjaGFuZ2VkUGF0aCxcbiAgICAgICAgICAgICAgICAgICAgYWZ0ZXJDb2x1bW5zQ2hhbmdlZDogYWZ0ZXJDb2x1bW5zQ2hhbmdlZFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIHNldCBvcGVuL2Nsb3NlZCBzdGF0ZSBvbiBncm91cHNcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVHcm91cFN0YXRlKGdyb3VwU3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBTZWxlY3RzQ2hpbGRyZW4oKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS51cGRhdGVHcm91cHNGcm9tQ2hpbGRyZW5TZWxlY3Rpb25zKGNoYW5nZWRQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwID0gdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW47XG4gICAgICAgICAgICBpZiAodGhpcy5yb290Tm9kZS5zaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb290Tm9kZS5zaWJsaW5nLmNoaWxkcmVuQWZ0ZXJHcm91cCA9IHRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yb290Tm9kZS51cGRhdGVIYXNDaGlsZHJlbigpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLnJlc3RvcmVHcm91cFN0YXRlID0gZnVuY3Rpb24gKGdyb3VwU3RhdGUpIHtcbiAgICAgICAgaWYgKCFncm91cFN0YXRlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgXy50cmF2ZXJzZU5vZGVzV2l0aEtleSh0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCwgZnVuY3Rpb24gKG5vZGUsIGtleSkge1xuICAgICAgICAgICAgLy8gaWYgdGhlIGdyb3VwIHdhcyBvcGVuIGxhc3QgdGltZSwgdGhlbiBvcGVuIGl0IHRoaXMgdGltZS4gaG93ZXZlclxuICAgICAgICAgICAgLy8gaWYgd2FzIG5vdCBvcGVuIGxhc3QgdGltZSwgdGhlbiBkb24ndCB0b3VjaCB0aGUgZ3JvdXAsIHNvIHRoZSAnZ3JvdXBEZWZhdWx0RXhwYW5kZWQnXG4gICAgICAgICAgICAvLyBzZXR0aW5nIHdpbGwgdGFrZSBlZmZlY3QuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGdyb3VwU3RhdGVba2V5XSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5leHBhbmRlZCA9IGdyb3VwU3RhdGVba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmRvRmlsdGVyID0gZnVuY3Rpb24gKGNoYW5nZWRQYXRoKSB7XG4gICAgICAgIHRoaXMuZmlsdGVyU3RhZ2UuZXhlY3V0ZSh7IHJvd05vZGU6IHRoaXMucm9vdE5vZGUsIGNoYW5nZWRQYXRoOiBjaGFuZ2VkUGF0aCB9KTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZG9QaXZvdCA9IGZ1bmN0aW9uIChjaGFuZ2VkUGF0aCkge1xuICAgICAgICBpZiAodGhpcy5waXZvdFN0YWdlKSB7XG4gICAgICAgICAgICB0aGlzLnBpdm90U3RhZ2UuZXhlY3V0ZSh7IHJvd05vZGU6IHRoaXMucm9vdE5vZGUsIGNoYW5nZWRQYXRoOiBjaGFuZ2VkUGF0aCB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5nZXRHcm91cFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMucm9vdE5vZGUuY2hpbGRyZW5BZnRlckdyb3VwIHx8ICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1JlbWVtYmVyR3JvdXBTdGF0ZVdoZW5OZXdEYXRhKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgICAgXy50cmF2ZXJzZU5vZGVzV2l0aEtleSh0aGlzLnJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCwgZnVuY3Rpb24gKG5vZGUsIGtleSkgeyByZXR1cm4gcmVzdWx0W2tleV0gPSBub2RlLmV4cGFuZGVkOyB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZ2V0Q29weU9mTm9kZXNNYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5vZGVNYW5hZ2VyLmdldENvcHlPZk5vZGVzTWFwKCk7XG4gICAgfTtcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgLy8gYWx0aG91Z2ggaWQgaXMgdHlwZWQgYSBzdHJpbmcsIHRoaXMgY291bGQgYmUgY2FsbGVkIGJ5IHRoZSB1c2VyLCBhbmQgdGhleSBjb3VsZCBoYXZlIHBhc3NlZCBhIG51bWJlclxuICAgICAgICB2YXIgaWRJc0dyb3VwID0gdHlwZW9mIGlkID09ICdzdHJpbmcnICYmIGlkLmluZGV4T2YoUm93Tm9kZS5JRF9QUkVGSVhfUk9XX0dST1VQKSA9PSAwO1xuICAgICAgICBpZiAoaWRJc0dyb3VwKSB7XG4gICAgICAgICAgICAvLyBvbmx5IG9uZSB1c2VycyBjb21wbGFpbmVkIGFib3V0IGdldFJvd05vZGUgbm90IHdvcmtpbmcgZm9yIGdyb3VwcywgYWZ0ZXIgeWVhcnMgb2ZcbiAgICAgICAgICAgIC8vIHRoaXMgd29ya2luZyBmb3Igbm9ybWFsIHJvd3MuIHNvIGhhdmUgZG9uZSBxdWljayBpbXBsZW1lbnRhdGlvbi4gaWYgdXNlcnMgY29tcGxhaW5cbiAgICAgICAgICAgIC8vIGFib3V0IHBlcmZvcm1hbmNlLCB0aGVuIEdyb3VwU3RhZ2Ugc2hvdWxkIHN0b3JlIC8gbWFuYWdlIGNyZWF0ZWQgZ3JvdXBzIGluIGEgbWFwLFxuICAgICAgICAgICAgLy8gd2hpY2ggaXMgYSBjaHVuayBvZiB3b3JrLlxuICAgICAgICAgICAgdmFyIHJlc18xID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5mb3JFYWNoTm9kZShmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlLmlkID09PSBpZCkge1xuICAgICAgICAgICAgICAgICAgICByZXNfMSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzXzE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZU1hbmFnZXIuZ2V0Um93Tm9kZShpZCk7XG4gICAgfTtcbiAgICAvLyByb3dzOiB0aGUgcm93cyB0byBwdXQgaW50byB0aGUgbW9kZWxcbiAgICBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLnNldFJvd0RhdGEgPSBmdW5jdGlvbiAocm93RGF0YSkge1xuICAgICAgICAvLyBubyBuZWVkIHRvIGludmFsaWRhdGUgY2FjaGUsIGFzIHRoZSBjYWNoZSBpcyBzdG9yZWQgb24gdGhlIHJvd05vZGUsXG4gICAgICAgIC8vIHNvIG5ldyByb3dOb2RlcyBtZWFucyB0aGUgY2FjaGUgaXMgd2lwZWQgYW55d2F5LlxuICAgICAgICAvLyByZW1lbWJlciBncm91cCBzdGF0ZSwgc28gd2UgY2FuIGV4cGFuZCBncm91cHMgdGhhdCBzaG91bGQgYmUgZXhwYW5kZWRcbiAgICAgICAgdmFyIGdyb3VwU3RhdGUgPSB0aGlzLmdldEdyb3VwU3RhdGUoKTtcbiAgICAgICAgdGhpcy5ub2RlTWFuYWdlci5zZXRSb3dEYXRhKHJvd0RhdGEpO1xuICAgICAgICAvLyAtIGNsZWFycyBzZWxlY3Rpb25cbiAgICAgICAgdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLnJlc2V0KCk7XG4gICAgICAgIC8vIC0gdXBkYXRlcyBmaWx0ZXJzXG4gICAgICAgIHRoaXMuZmlsdGVyTWFuYWdlci5vbk5ld1Jvd3NMb2FkZWQoJ3Jvd0RhdGFVcGRhdGVkJyk7XG4gICAgICAgIC8vIHRoaXMgZXZlbnQga2lja3Mgb2ZmOlxuICAgICAgICAvLyAtIHNob3dzICdubyByb3dzJyBvdmVybGF5IGlmIG5lZWRlZFxuICAgICAgICB2YXIgcm93RGF0YVVwZGF0ZWRFdmVudCA9IHtcbiAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9ST1dfREFUQV9VUERBVEVEXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQocm93RGF0YVVwZGF0ZWRFdmVudCk7XG4gICAgICAgIHRoaXMucmVmcmVzaE1vZGVsKHtcbiAgICAgICAgICAgIHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLkVWRVJZVEhJTkcsXG4gICAgICAgICAgICBncm91cFN0YXRlOiBncm91cFN0YXRlLFxuICAgICAgICAgICAgbmV3RGF0YTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuYmF0Y2hVcGRhdGVSb3dEYXRhID0gZnVuY3Rpb24gKHJvd0RhdGFUcmFuc2FjdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuYXBwbHlBc3luY1RyYW5zYWN0aW9uc1RpbWVvdXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5yb3dEYXRhVHJhbnNhY3Rpb25CYXRjaCA9IFtdO1xuICAgICAgICAgICAgdmFyIHdhaXRNaWxsaXMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBc3luY1RyYW5zYWN0aW9uV2FpdE1pbGxpcygpO1xuICAgICAgICAgICAgdGhpcy5hcHBseUFzeW5jVHJhbnNhY3Rpb25zVGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5leGVjdXRlQmF0Y2hVcGRhdGVSb3dEYXRhKCk7XG4gICAgICAgICAgICB9LCB3YWl0TWlsbGlzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd0RhdGFUcmFuc2FjdGlvbkJhdGNoLnB1c2goeyByb3dEYXRhVHJhbnNhY3Rpb246IHJvd0RhdGFUcmFuc2FjdGlvbiwgY2FsbGJhY2s6IGNhbGxiYWNrIH0pO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5mbHVzaEFzeW5jVHJhbnNhY3Rpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5hcHBseUFzeW5jVHJhbnNhY3Rpb25zVGltZW91dCAhPSBudWxsKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5hcHBseUFzeW5jVHJhbnNhY3Rpb25zVGltZW91dCk7XG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGVCYXRjaFVwZGF0ZVJvd0RhdGEoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5leGVjdXRlQmF0Y2hVcGRhdGVSb3dEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnZhbHVlQ2FjaGUub25EYXRhQ2hhbmdlZCgpO1xuICAgICAgICB2YXIgY2FsbGJhY2tGdW5jc0JvdW5kID0gW107XG4gICAgICAgIHZhciByb3dOb2RlVHJhbnMgPSBbXTtcbiAgICAgICAgLy8gVGhlIHJvd0dyb3VwIHN0YWdlIHVzZXMgcm93Tm9kZU9yZGVyIGlmIG9yZGVyIHdhcyBwcm92aWRlZC4gaWYgd2UgZGlkbid0IHBhc3MgJ3RydWUnIHRvXG4gICAgICAgIC8vIGNvbW1vblVwZGF0ZVJvd0RhdGEsIHVzaW5nIGFkZEluZGV4IHdvdWxkIGhhdmUgbm8gZWZmZWN0IHdoZW4gZ3JvdXBpbmcuXG4gICAgICAgIHZhciBmb3JjZVJvd05vZGVPcmRlciA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5yb3dEYXRhVHJhbnNhY3Rpb25CYXRjaCkge1xuICAgICAgICAgICAgdGhpcy5yb3dEYXRhVHJhbnNhY3Rpb25CYXRjaC5mb3JFYWNoKGZ1bmN0aW9uICh0cmFuSXRlbSkge1xuICAgICAgICAgICAgICAgIHZhciByb3dOb2RlVHJhbiA9IF90aGlzLm5vZGVNYW5hZ2VyLnVwZGF0ZVJvd0RhdGEodHJhbkl0ZW0ucm93RGF0YVRyYW5zYWN0aW9uLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIHJvd05vZGVUcmFucy5wdXNoKHJvd05vZGVUcmFuKTtcbiAgICAgICAgICAgICAgICBpZiAodHJhbkl0ZW0uY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tGdW5jc0JvdW5kLnB1c2godHJhbkl0ZW0uY2FsbGJhY2suYmluZChudWxsLCByb3dOb2RlVHJhbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRyYW5JdGVtLnJvd0RhdGFUcmFuc2FjdGlvbi5hZGRJbmRleCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yY2VSb3dOb2RlT3JkZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29tbW9uVXBkYXRlUm93RGF0YShyb3dOb2RlVHJhbnMsIHVuZGVmaW5lZCwgZm9yY2VSb3dOb2RlT3JkZXIpO1xuICAgICAgICAvLyBkbyBjYWxsYmFja3MgaW4gbmV4dCBWTSB0dXJuIHNvIGl0J3MgYXN5bmNcbiAgICAgICAgaWYgKGNhbGxiYWNrRnVuY3NCb3VuZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2tGdW5jc0JvdW5kLmZvckVhY2goZnVuY3Rpb24gKGZ1bmMpIHsgcmV0dXJuIGZ1bmMoKTsgfSk7XG4gICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocm93Tm9kZVRyYW5zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciBldmVudF8xID0ge1xuICAgICAgICAgICAgICAgIHR5cGU6IEV2ZW50cy5FVkVOVF9BU1lOQ19UUkFOU0FDVElPTlNfRkxVU0hFRCxcbiAgICAgICAgICAgICAgICByZXN1bHRzOiByb3dOb2RlVHJhbnNcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50XzEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucm93RGF0YVRyYW5zYWN0aW9uQmF0Y2ggPSBudWxsO1xuICAgICAgICB0aGlzLmFwcGx5QXN5bmNUcmFuc2FjdGlvbnNUaW1lb3V0ID0gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS51cGRhdGVSb3dEYXRhID0gZnVuY3Rpb24gKHJvd0RhdGFUcmFuLCByb3dOb2RlT3JkZXIpIHtcbiAgICAgICAgdGhpcy52YWx1ZUNhY2hlLm9uRGF0YUNoYW5nZWQoKTtcbiAgICAgICAgdmFyIHJvd05vZGVUcmFuID0gdGhpcy5ub2RlTWFuYWdlci51cGRhdGVSb3dEYXRhKHJvd0RhdGFUcmFuLCByb3dOb2RlT3JkZXIpO1xuICAgICAgICAvLyBpZiBkb2luZyBpbW11dGFibGVEYXRhLCBhZGRJbmRleCBpcyBuZXZlciBwcmVzZW50LiBob3dldmVyIGlmIGRvaW5nIHN0YW5kYXJkIHRyYW5zYWN0aW9uLCBhbmQgdXNlclxuICAgICAgICAvLyBwcm92aWRlZCBhZGRJbmRleCwgdGhlbiB0aGlzIGlzIHVzZWQgaW4gdXBkYXRlUm93RGF0YS4gSG93ZXZlciBpZiBkb2luZyBFbnRlcnByaXNlLCB0aGVuIHRoZSByb3dHcm91cFxuICAgICAgICAvLyBzdGFnZSBhbHNvIHVzZXMgdGhlXG4gICAgICAgIHZhciBmb3JjZVJvd05vZGVPcmRlciA9IHR5cGVvZiByb3dEYXRhVHJhbi5hZGRJbmRleCA9PT0gJ251bWJlcic7XG4gICAgICAgIHRoaXMuY29tbW9uVXBkYXRlUm93RGF0YShbcm93Tm9kZVRyYW5dLCByb3dOb2RlT3JkZXIsIGZvcmNlUm93Tm9kZU9yZGVyKTtcbiAgICAgICAgcmV0dXJuIHJvd05vZGVUcmFuO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5jcmVhdGVSb3dOb2RlT3JkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzdXBwcmVzc1NvcnRPcmRlciA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzU3VwcHJlc3NNYWludGFpblVuc29ydGVkT3JkZXIoKTtcbiAgICAgICAgaWYgKHN1cHByZXNzU29ydE9yZGVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9yZGVyTWFwID0ge307XG4gICAgICAgIGlmICh0aGlzLnJvb3ROb2RlICYmIHRoaXMucm9vdE5vZGUuYWxsTGVhZkNoaWxkcmVuKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5yb290Tm9kZS5hbGxMZWFmQ2hpbGRyZW4ubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB0aGlzLnJvb3ROb2RlLmFsbExlYWZDaGlsZHJlbltpbmRleF07XG4gICAgICAgICAgICAgICAgb3JkZXJNYXBbbm9kZS5pZF0gPSBpbmRleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3JkZXJNYXA7XG4gICAgfTtcbiAgICAvLyBjb21tb24gdG8gdXBkYXRlUm93RGF0YSBhbmQgYmF0Y2hVcGRhdGVSb3dEYXRhXG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5jb21tb25VcGRhdGVSb3dEYXRhID0gZnVuY3Rpb24gKHJvd05vZGVUcmFucywgcm93Tm9kZU9yZGVyLCBmb3JjZVJvd05vZGVPcmRlcikge1xuICAgICAgICB2YXIgYW5pbWF0ZSA9ICF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQW5pbWF0aW9uRnJhbWUoKTtcbiAgICAgICAgaWYgKGZvcmNlUm93Tm9kZU9yZGVyKSB7XG4gICAgICAgICAgICByb3dOb2RlT3JkZXIgPSB0aGlzLmNyZWF0ZVJvd05vZGVPcmRlcigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVmcmVzaE1vZGVsKHtcbiAgICAgICAgICAgIHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLkVWRVJZVEhJTkcsXG4gICAgICAgICAgICByb3dOb2RlVHJhbnNhY3Rpb25zOiByb3dOb2RlVHJhbnMsXG4gICAgICAgICAgICByb3dOb2RlT3JkZXI6IHJvd05vZGVPcmRlcixcbiAgICAgICAgICAgIGtlZXBSZW5kZXJlZFJvd3M6IHRydWUsXG4gICAgICAgICAgICBrZWVwRWRpdGluZ1Jvd3M6IHRydWUsXG4gICAgICAgICAgICBhbmltYXRlOiBhbmltYXRlXG4gICAgICAgIH0pO1xuICAgICAgICAvLyAtIHVwZGF0ZXMgZmlsdGVyc1xuICAgICAgICB0aGlzLmZpbHRlck1hbmFnZXIub25OZXdSb3dzTG9hZGVkKCdyb3dEYXRhVXBkYXRlZCcpO1xuICAgICAgICB2YXIgZXZlbnQgPSB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfUk9XX0RBVEFfVVBEQVRFRFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmV2ZW50U2VydmljZS5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUuZG9Sb3dzVG9EaXNwbGF5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJvd3NUb0Rpc3BsYXkgPSB0aGlzLmZsYXR0ZW5TdGFnZS5leGVjdXRlKHsgcm93Tm9kZTogdGhpcy5yb290Tm9kZSB9KTtcbiAgICB9O1xuICAgIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUub25Sb3dIZWlnaHRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlZnJlc2hNb2RlbCh7IHN0ZXA6IENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLk1BUCwga2VlcFJlbmRlcmVkUm93czogdHJ1ZSwga2VlcEVkaXRpbmdSb3dzOiB0cnVlLCBrZWVwVW5kb1JlZG9TdGFjazogdHJ1ZSB9KTtcbiAgICB9O1xuICAgIC8qKiBUaGlzIG1ldGhvZCBpcyBkZWJvdW5jZWQuIEl0IGlzIHVzZWQgZm9yIHJvdyBhdXRvLWhlaWdodC4gSWYgd2UgZG9uJ3QgZGVib3VuY2UsXG4gICAgICogdGhlbiB0aGUgUm93IE1vZGVscyB3aWxsIGVuZCB1cCByZWNhbGN1bGF0aW5nIGVhY2ggcm93IHBvc2l0aW9uXG4gICAgICogZm9yIGVhY2ggcm93IGhlaWdodCBjaGFuZ2UgYW5kIHJlc3VsdCBpbiB0aGUgUm93IFJlbmRlcmVyIGxheWluZyBvdXQgcm93cy5cbiAgICAgKiBUaGlzIGlzIHBhcnRpY3VsYXJseSBiYWQgaWYgdXNpbmcgcHJpbnQgbGF5b3V0LCBhbmQgc2hvd2luZyBlZyAxLDAwMCByb3dzLFxuICAgICAqIGVhY2ggcm93IHdpbGwgY2hhbmdlIGl0J3MgaGVpZ2h0LCBjYXVzaW5nIFJvdyBNb2RlbCB0byB1cGRhdGUgMSwwMDAgdGltZXMuXG4gICAgICovXG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5vblJvd0hlaWdodENoYW5nZWREZWJvdW5jZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub25Sb3dIZWlnaHRDaGFuZ2VkX2RlYm91bmNlZCgpO1xuICAgIH07XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZS5yZXNldFJvd0hlaWdodHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhdExlYXN0T25lID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZm9yRWFjaE5vZGUoZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHJvd05vZGUuc2V0Um93SGVpZ2h0KHJvd05vZGUucm93SGVpZ2h0LCB0cnVlKTtcbiAgICAgICAgICAgIC8vIHdlIGtlZXAgdGhlIGhlaWdodCBlYWNoIHJvdyBpcyBhdCwgaG93ZXZlciB3ZSBzZXQgZXN0aW1hdGVkPXRydWUgcmF0aGVyIHRoYW4gY2xlYXIgdGhlIGhlaWdodC5cbiAgICAgICAgICAgIC8vIHRoaXMgbWVhbnMgdGhlIGdyaWQgd2lsbCBub3QgcmVzZXQgdGhlIHJvdyBoZWlnaHRzIGJhY2sgdG8gZGVmYXVsdHMsIHJhdGhlciBpdCB3aWxsIHJlLWNhbGNcbiAgICAgICAgICAgIC8vIHRoZSBoZWlnaHQgZm9yIGVhY2ggcm93IGFzIHRoZSByb3cgaXMgZGlzcGxheWVkLiBvdGhlcndpc2UgdGhlIHNjcm9sbCB3aWxsIGp1bXAgd2hlbiBoZWlnaHRzIGFyZSByZXNldC5cbiAgICAgICAgICAgIHZhciBkZXRhaWxOb2RlID0gcm93Tm9kZS5kZXRhaWxOb2RlO1xuICAgICAgICAgICAgaWYgKGRldGFpbE5vZGUpIHtcbiAgICAgICAgICAgICAgICBkZXRhaWxOb2RlLnNldFJvd0hlaWdodChkZXRhaWxOb2RlLnJvd0hlaWdodCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhdExlYXN0T25lID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChhdExlYXN0T25lKSB7XG4gICAgICAgICAgICB0aGlzLm9uUm93SGVpZ2h0Q2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJGIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRiKFtcbiAgICAgICAgQXV0b3dpcmVkKCdzZWxlY3Rpb25TZXJ2aWNlJylcbiAgICBdLCBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLCBcInNlbGVjdGlvblNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZpbHRlck1hbmFnZXInKVxuICAgIF0sIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUsIFwiZmlsdGVyTWFuYWdlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkYihbXG4gICAgICAgIEF1dG93aXJlZCgndmFsdWVDYWNoZScpXG4gICAgXSwgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZSwgXCJ2YWx1ZUNhY2hlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRiKFtcbiAgICAgICAgQXV0b3dpcmVkKCdiZWFucycpXG4gICAgXSwgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZSwgXCJiZWFuc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkYihbXG4gICAgICAgIEF1dG93aXJlZCgnZmlsdGVyU3RhZ2UnKVxuICAgIF0sIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUsIFwiZmlsdGVyU3RhZ2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGIoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NvcnRTdGFnZScpXG4gICAgXSwgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZSwgXCJzb3J0U3RhZ2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZsYXR0ZW5TdGFnZScpXG4gICAgXSwgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZSwgXCJmbGF0dGVuU3RhZ2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGIoW1xuICAgICAgICBPcHRpb25hbCgnZ3JvdXBTdGFnZScpXG4gICAgXSwgQ2xpZW50U2lkZVJvd01vZGVsLnByb3RvdHlwZSwgXCJncm91cFN0YWdlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSRiKFtcbiAgICAgICAgT3B0aW9uYWwoJ2FnZ3JlZ2F0aW9uU3RhZ2UnKVxuICAgIF0sIENsaWVudFNpZGVSb3dNb2RlbC5wcm90b3R5cGUsIFwiYWdncmVnYXRpb25TdGFnZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkYihbXG4gICAgICAgIE9wdGlvbmFsKCdwaXZvdFN0YWdlJylcbiAgICBdLCBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLCBcInBpdm90U3RhZ2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJGIoW1xuICAgICAgICBPcHRpb25hbCgnZmlsdGVyQWdncmVnYXRlc1N0YWdlJylcbiAgICBdLCBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLCBcImZpbHRlckFnZ3JlZ2F0ZXNTdGFnZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkYihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBDbGllbnRTaWRlUm93TW9kZWwucHJvdG90eXBlLCBcImluaXRcIiwgbnVsbCk7XG4gICAgQ2xpZW50U2lkZVJvd01vZGVsID0gX19kZWNvcmF0ZSRiKFtcbiAgICAgICAgQmVhbigncm93TW9kZWwnKVxuICAgIF0sIENsaWVudFNpZGVSb3dNb2RlbCk7XG4gICAgcmV0dXJuIENsaWVudFNpZGVSb3dNb2RlbDtcbn0oQmVhblN0dWIpKTtcblxudmFyIF9fZXh0ZW5kcyRiID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSRhID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgRmlsdGVyU3RhZ2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJGIoRmlsdGVyU3RhZ2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRmlsdGVyU3RhZ2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgRmlsdGVyU3RhZ2UucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBjaGFuZ2VkUGF0aCA9IHBhcmFtcy5jaGFuZ2VkUGF0aDtcbiAgICAgICAgdGhpcy5maWx0ZXJTZXJ2aWNlLmZpbHRlcihjaGFuZ2VkUGF0aCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJGEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZpbHRlclNlcnZpY2UnKVxuICAgIF0sIEZpbHRlclN0YWdlLnByb3RvdHlwZSwgXCJmaWx0ZXJTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgRmlsdGVyU3RhZ2UgPSBfX2RlY29yYXRlJGEoW1xuICAgICAgICBCZWFuKCdmaWx0ZXJTdGFnZScpXG4gICAgXSwgRmlsdGVyU3RhZ2UpO1xuICAgIHJldHVybiBGaWx0ZXJTdGFnZTtcbn0oQmVhblN0dWIpKTtcblxudmFyIF9fZXh0ZW5kcyRhID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQ5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgU29ydFN0YWdlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyRhKFNvcnRTdGFnZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBTb3J0U3RhZ2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgU29ydFN0YWdlLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgc29ydE9wdGlvbnMgPSB0aGlzLnNvcnRDb250cm9sbGVyLmdldFNvcnRPcHRpb25zKCk7XG4gICAgICAgIHZhciBzb3J0QWN0aXZlID0gXy5leGlzdHMoc29ydE9wdGlvbnMpICYmIHNvcnRPcHRpb25zLmxlbmd0aCA+IDA7XG4gICAgICAgIHZhciBkZWx0YVNvcnQgPSBzb3J0QWN0aXZlXG4gICAgICAgICAgICAmJiBfLmV4aXN0cyhwYXJhbXMucm93Tm9kZVRyYW5zYWN0aW9ucylcbiAgICAgICAgICAgIC8vIGluIHRpbWUgd2UgY2FuIHJlbW92ZSB0aGlzIGNoZWNrLCBzbyB0aGF0IGRlbHRhIHNvcnQgaXMgYWx3YXlzXG4gICAgICAgICAgICAvLyBvbiBpZiB0cmFuc2FjdGlvbnMgYXJlIHByZXNlbnQuIGl0J3Mgb2ZmIGZvciBub3cgc28gdGhhdCB3ZSBjYW5cbiAgICAgICAgICAgIC8vIHNlbGVjdGl2ZWx5IHR1cm4gaXQgb24gYW5kIHRlc3QgaXQgd2l0aCBzb21lIHNlbGVjdCB1c2VycyBiZWZvcmVcbiAgICAgICAgICAgIC8vIHJvbGxpbmcgb3V0IHRvIGV2ZXJ5b25lLlxuICAgICAgICAgICAgJiYgdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNEZWx0YVNvcnQoKTtcbiAgICAgICAgdmFyIHNvcnRDb250YWluc0dyb3VwQ29sdW1ucyA9IHNvcnRPcHRpb25zLnNvbWUoZnVuY3Rpb24gKG9wdCkgeyByZXR1cm4gISFfdGhpcy5jb2x1bW5Nb2RlbC5nZXRHcm91cERpc3BsYXlDb2x1bW5Gb3JHcm91cChvcHQuY29sdW1uLmdldElkKCkpOyB9KTtcbiAgICAgICAgdGhpcy5zb3J0U2VydmljZS5zb3J0KHNvcnRPcHRpb25zLCBzb3J0QWN0aXZlLCBkZWx0YVNvcnQsIHBhcmFtcy5yb3dOb2RlVHJhbnNhY3Rpb25zLCBwYXJhbXMuY2hhbmdlZFBhdGgsIHNvcnRDb250YWluc0dyb3VwQ29sdW1ucyk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDkoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NvcnRTZXJ2aWNlJylcbiAgICBdLCBTb3J0U3RhZ2UucHJvdG90eXBlLCBcInNvcnRTZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQ5KFtcbiAgICAgICAgQXV0b3dpcmVkKCdzb3J0Q29udHJvbGxlcicpXG4gICAgXSwgU29ydFN0YWdlLnByb3RvdHlwZSwgXCJzb3J0Q29udHJvbGxlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkOShbXG4gICAgICAgIEF1dG93aXJlZCgnY29sdW1uTW9kZWwnKVxuICAgIF0sIFNvcnRTdGFnZS5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBTb3J0U3RhZ2UgPSBfX2RlY29yYXRlJDkoW1xuICAgICAgICBCZWFuKCdzb3J0U3RhZ2UnKVxuICAgIF0sIFNvcnRTdGFnZSk7XG4gICAgcmV0dXJuIFNvcnRTdGFnZTtcbn0oQmVhblN0dWIpKTtcblxudmFyIF9fZXh0ZW5kcyQ5ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQ4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgRmxhdHRlblN0YWdlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQ5KEZsYXR0ZW5TdGFnZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBGbGF0dGVuU3RhZ2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgRmxhdHRlblN0YWdlLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgcm9vdE5vZGUgPSBwYXJhbXMucm93Tm9kZTtcbiAgICAgICAgLy8gZXZlbiBpZiBub3QgZG9pbmcgZ3JvdXBpbmcsIHdlIGRvIHRoZSBtYXBwaW5nLCBhcyB0aGUgY2xpZW50IG1pZ2h0XG4gICAgICAgIC8vIG9mIHBhc3NlZCBpbiBkYXRhIHRoYXQgYWxyZWFkeSBoYXMgYSBncm91cGluZyBpbiBpdCBzb21ld2hlcmVcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAvLyBwdXR0aW5nIHZhbHVlIGludG8gYSB3cmFwcGVyIHNvIGl0J3MgcGFzc2VkIGJ5IHJlZmVyZW5jZVxuICAgICAgICB2YXIgbmV4dFJvd1RvcCA9IHsgdmFsdWU6IDAgfTtcbiAgICAgICAgdmFyIHNraXBMZWFmTm9kZXMgPSB0aGlzLmNvbHVtbk1vZGVsLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIC8vIGlmIHdlIGFyZSByZWR1Y2luZywgYW5kIG5vdCBncm91cGluZywgdGhlbiB3ZSB3YW50IHRvIHNob3cgdGhlIHJvb3Qgbm9kZSwgYXMgdGhhdFxuICAgICAgICAvLyBpcyB3aGVyZSB0aGUgcGl2b3QgdmFsdWVzIGFyZVxuICAgICAgICB2YXIgc2hvd1Jvb3ROb2RlID0gc2tpcExlYWZOb2RlcyAmJiByb290Tm9kZS5sZWFmR3JvdXA7XG4gICAgICAgIHZhciB0b3BMaXN0ID0gc2hvd1Jvb3ROb2RlID8gW3Jvb3ROb2RlXSA6IHJvb3ROb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0O1xuICAgICAgICB0aGlzLnJlY3Vyc2l2ZWx5QWRkVG9Sb3dzVG9EaXNwbGF5KHRvcExpc3QsIHJlc3VsdCwgbmV4dFJvd1RvcCwgc2tpcExlYWZOb2RlcywgMCk7XG4gICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRoZSBmb290ZXIgdG90YWwgaWYgdGhlIGdyaXMgaXMgZW1wdHlcbiAgICAgICAgdmFyIGF0TGVhc3RPbmVSb3dQcmVzZW50ID0gcmVzdWx0Lmxlbmd0aCA+IDA7XG4gICAgICAgIHZhciBpbmNsdWRlR3JvdXBUb3RhbEZvb3RlciA9ICFzaG93Um9vdE5vZGVcbiAgICAgICAgICAgIC8vIGRvbid0IHNob3cgdG90YWwgZm9vdGVyIHdoZW4gc2hvd1Jvb3ROb2RlIGlzIHRydWUgKGkuZS4gaW4gcGl2b3QgbW9kZSBhbmQgbm8gZ3JvdXBzKVxuICAgICAgICAgICAgJiYgYXRMZWFzdE9uZVJvd1ByZXNlbnRcbiAgICAgICAgICAgICYmIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBJbmNsdWRlVG90YWxGb290ZXIoKTtcbiAgICAgICAgaWYgKGluY2x1ZGVHcm91cFRvdGFsRm9vdGVyKSB7XG4gICAgICAgICAgICB0aGlzLmVuc3VyZUZvb3Rlck5vZGVFeGlzdHMocm9vdE5vZGUpO1xuICAgICAgICAgICAgdGhpcy5hZGRSb3dOb2RlVG9Sb3dzVG9EaXNwbGF5KHJvb3ROb2RlLnNpYmxpbmcsIHJlc3VsdCwgbmV4dFJvd1RvcCwgMCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIEZsYXR0ZW5TdGFnZS5wcm90b3R5cGUucmVjdXJzaXZlbHlBZGRUb1Jvd3NUb0Rpc3BsYXkgPSBmdW5jdGlvbiAocm93c1RvRmxhdHRlbiwgcmVzdWx0LCBuZXh0Um93VG9wLCBza2lwTGVhZk5vZGVzLCB1aUxldmVsKSB7XG4gICAgICAgIGlmIChfLm1pc3NpbmdPckVtcHR5KHJvd3NUb0ZsYXR0ZW4pKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhpZGVPcGVuUGFyZW50cyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBIaWRlT3BlblBhcmVudHMoKTtcbiAgICAgICAgLy8gdGhlc2UgdHdvIGFyZSBtdXR1YWxseSBleGNsdXNpdmUsIHNvIGlmIGZpcnN0IHNldCwgd2UgZG9uJ3Qgc2V0IHRoZSBzZWNvbmRcbiAgICAgICAgdmFyIGdyb3VwUmVtb3ZlU2luZ2xlQ2hpbGRyZW4gPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwUmVtb3ZlU2luZ2xlQ2hpbGRyZW4oKTtcbiAgICAgICAgdmFyIGdyb3VwUmVtb3ZlTG93ZXN0U2luZ2xlQ2hpbGRyZW4gPSAhZ3JvdXBSZW1vdmVTaW5nbGVDaGlsZHJlbiAmJiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwUmVtb3ZlTG93ZXN0U2luZ2xlQ2hpbGRyZW4oKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dzVG9GbGF0dGVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcm93Tm9kZSA9IHJvd3NUb0ZsYXR0ZW5baV07XG4gICAgICAgICAgICAvLyBjaGVjayBhbGwgdGhlc2UgY2FzZXMsIGZvciB3b3JraW5nIG91dCBpZiB0aGlzIHJvdyBzaG91bGQgYmUgaW5jbHVkZWQgaW4gdGhlIGZpbmFsIG1hcHBlZCBsaXN0XG4gICAgICAgICAgICB2YXIgaXNQYXJlbnQgPSByb3dOb2RlLmhhc0NoaWxkcmVuKCk7XG4gICAgICAgICAgICB2YXIgaXNTa2lwcGVkTGVhZk5vZGUgPSBza2lwTGVhZk5vZGVzICYmICFpc1BhcmVudDtcbiAgICAgICAgICAgIHZhciBpc1JlbW92ZWRTaW5nbGVDaGlsZHJlbkdyb3VwID0gZ3JvdXBSZW1vdmVTaW5nbGVDaGlsZHJlbiAmJlxuICAgICAgICAgICAgICAgIGlzUGFyZW50ICYmXG4gICAgICAgICAgICAgICAgcm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXAubGVuZ3RoID09PSAxO1xuICAgICAgICAgICAgdmFyIGlzUmVtb3ZlZExvd2VzdFNpbmdsZUNoaWxkcmVuR3JvdXAgPSBncm91cFJlbW92ZUxvd2VzdFNpbmdsZUNoaWxkcmVuICYmXG4gICAgICAgICAgICAgICAgaXNQYXJlbnQgJiZcbiAgICAgICAgICAgICAgICByb3dOb2RlLmxlYWZHcm91cCAmJlxuICAgICAgICAgICAgICAgIHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwLmxlbmd0aCA9PT0gMTtcbiAgICAgICAgICAgIC8vIGhpZGUgb3BlbiBwYXJlbnRzIG1lYW5zIHdoZW4gZ3JvdXAgaXMgb3Blbiwgd2UgZG9uJ3Qgc2hvdyBpdC4gd2UgYWxzbyBuZWVkIHRvIG1ha2Ugc3VyZSB0aGVcbiAgICAgICAgICAgIC8vIGdyb3VwIGlzIGV4cGFuZGFibGUgaW4gdGhlIGZpcnN0IHBsYWNlIChhcyBsZWFmIGdyb3VwcyBhcmUgbm90IGV4cGFuZGFibGUgaWYgcGl2b3QgbW9kZSBpcyBvbikuXG4gICAgICAgICAgICAvLyB0aGUgVUkgd2lsbCBuZXZlciBhbGxvdyBleHBhbmRpbmcgbGVhZiAgZ3JvdXBzLCBob3dldmVyIHRoZSB1c2VyIG1pZ2h0IHZpYSB0aGUgQVBJIChvciBtZW51IG9wdGlvbiAnZXhwYW5kIGFsbCcpXG4gICAgICAgICAgICB2YXIgbmV2ZXJBbGxvd1RvRXhwYW5kID0gc2tpcExlYWZOb2RlcyAmJiByb3dOb2RlLmxlYWZHcm91cDtcbiAgICAgICAgICAgIHZhciBpc0hpZGRlbk9wZW5QYXJlbnQgPSBoaWRlT3BlblBhcmVudHMgJiYgcm93Tm9kZS5leHBhbmRlZCAmJiAhcm93Tm9kZS5tYXN0ZXIgJiYgKCFuZXZlckFsbG93VG9FeHBhbmQpO1xuICAgICAgICAgICAgdmFyIHRoaXNSb3dTaG91bGRCZVJlbmRlcmVkID0gIWlzU2tpcHBlZExlYWZOb2RlICYmICFpc0hpZGRlbk9wZW5QYXJlbnQgJiZcbiAgICAgICAgICAgICAgICAhaXNSZW1vdmVkU2luZ2xlQ2hpbGRyZW5Hcm91cCAmJiAhaXNSZW1vdmVkTG93ZXN0U2luZ2xlQ2hpbGRyZW5Hcm91cDtcbiAgICAgICAgICAgIGlmICh0aGlzUm93U2hvdWxkQmVSZW5kZXJlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkUm93Tm9kZVRvUm93c1RvRGlzcGxheShyb3dOb2RlLCByZXN1bHQsIG5leHRSb3dUb3AsIHVpTGV2ZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgd2UgYXJlIHBpdm90aW5nLCB3ZSBuZXZlciBtYXAgYmVsb3cgdGhlIGxlYWYgZ3JvdXBcbiAgICAgICAgICAgIGlmIChza2lwTGVhZk5vZGVzICYmIHJvd05vZGUubGVhZkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhjbHVkZWRQYXJlbnQgPSBpc1JlbW92ZWRTaW5nbGVDaGlsZHJlbkdyb3VwIHx8IGlzUmVtb3ZlZExvd2VzdFNpbmdsZUNoaWxkcmVuR3JvdXA7XG4gICAgICAgICAgICAgICAgLy8gd2UgdHJhdmVyc2UgdGhlIGdyb3VwIGlmIGl0IGlzIGV4cGVuZGVkLCBob3dldmVyIHdlIGFsd2F5cyB0cmF2ZXJzZSBpZiB0aGUgcGFyZW50IG5vZGVcbiAgICAgICAgICAgICAgICAvLyB3YXMgcmVtb3ZlZCAoYXMgdGhlIGdyb3VwIHdpbGwgbmV2ZXIgYmUgb3BlbmVkIGlmIGl0IGlzIG5vdCBkaXNwbGF5ZWQsIHdlIHNob3cgdGhlIGNoaWxkcmVuIGluc3RlYWQpXG4gICAgICAgICAgICAgICAgaWYgKHJvd05vZGUuZXhwYW5kZWQgfHwgZXhjbHVkZWRQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHBhcmVudCB3YXMgZXhjbHVkZWQsIHRoZW4gdWkgbGV2ZWwgaXMgdGhhdCBvZiB0aGUgcGFyZW50XG4gICAgICAgICAgICAgICAgICAgIHZhciB1aUxldmVsRm9yQ2hpbGRyZW4gPSBleGNsdWRlZFBhcmVudCA/IHVpTGV2ZWwgOiB1aUxldmVsICsgMTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWN1cnNpdmVseUFkZFRvUm93c1RvRGlzcGxheShyb3dOb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0LCByZXN1bHQsIG5leHRSb3dUb3AsIHNraXBMZWFmTm9kZXMsIHVpTGV2ZWxGb3JDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgICAgIC8vIHB1dCBhIGZvb3RlciBpbiBpZiB1c2VyIGlzIGxvb2tpbmcgZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwSW5jbHVkZUZvb3RlcigpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuc3VyZUZvb3Rlck5vZGVFeGlzdHMocm93Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZFJvd05vZGVUb1Jvd3NUb0Rpc3BsYXkocm93Tm9kZS5zaWJsaW5nLCByZXN1bHQsIG5leHRSb3dUb3AsIHVpTGV2ZWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAocm93Tm9kZS5tYXN0ZXIgJiYgcm93Tm9kZS5leHBhbmRlZCkge1xuICAgICAgICAgICAgICAgIHZhciBkZXRhaWxOb2RlID0gdGhpcy5jcmVhdGVEZXRhaWxOb2RlKHJvd05vZGUpO1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkUm93Tm9kZVRvUm93c1RvRGlzcGxheShkZXRhaWxOb2RlLCByZXN1bHQsIG5leHRSb3dUb3AsIHVpTGV2ZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBkdXBsaWNhdGVkIG1ldGhvZCwgaXQncyBhbHNvIGluIGZsb2F0aW5nUm93TW9kZWxcbiAgICBGbGF0dGVuU3RhZ2UucHJvdG90eXBlLmFkZFJvd05vZGVUb1Jvd3NUb0Rpc3BsYXkgPSBmdW5jdGlvbiAocm93Tm9kZSwgcmVzdWx0LCBuZXh0Um93VG9wLCB1aUxldmVsKSB7XG4gICAgICAgIHZhciBpc0dyb3VwTXVsdGlBdXRvQ29sdW1uID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cE11bHRpQXV0b0NvbHVtbigpO1xuICAgICAgICByZXN1bHQucHVzaChyb3dOb2RlKTtcbiAgICAgICAgcm93Tm9kZS5zZXRVaUxldmVsKGlzR3JvdXBNdWx0aUF1dG9Db2x1bW4gPyAwIDogdWlMZXZlbCk7XG4gICAgfTtcbiAgICBGbGF0dGVuU3RhZ2UucHJvdG90eXBlLmVuc3VyZUZvb3Rlck5vZGVFeGlzdHMgPSBmdW5jdGlvbiAoZ3JvdXBOb2RlKSB7XG4gICAgICAgIC8vIG9ubHkgY3JlYXRlIGZvb3RlciBub2RlIG9uY2UsIG90aGVyd2lzZSB3ZSBoYXZlIGRhZW1vbnMgYW5kXG4gICAgICAgIC8vIHRoZSBhbmltYXRlIHNjcmV3cyB1cCB3aXRoIHRoZSBkYWVtb25zIGhhbmdpbmcgYXJvdW5kXG4gICAgICAgIGlmIChfLmV4aXN0cyhncm91cE5vZGUuc2libGluZykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZm9vdGVyTm9kZSA9IG5ldyBSb3dOb2RlKHRoaXMuYmVhbnMpO1xuICAgICAgICBPYmplY3Qua2V5cyhncm91cE5vZGUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgZm9vdGVyTm9kZVtrZXldID0gZ3JvdXBOb2RlW2tleV07XG4gICAgICAgIH0pO1xuICAgICAgICBmb290ZXJOb2RlLmZvb3RlciA9IHRydWU7XG4gICAgICAgIGZvb3Rlck5vZGUuc2V0Um93VG9wKG51bGwpO1xuICAgICAgICBmb290ZXJOb2RlLnNldFJvd0luZGV4KG51bGwpO1xuICAgICAgICAvLyBtYW51YWxseSBzZXQgb2xkUm93VG9wIHRvIG51bGwgc28gd2UgZGlzY2FyZCBhbnlcbiAgICAgICAgLy8gcHJldmlvdXMgaW5mb3JtYXRpb24gYWJvdXQgaXRzIHBvc2l0aW9uLlxuICAgICAgICBmb290ZXJOb2RlLm9sZFJvd1RvcCA9IG51bGw7XG4gICAgICAgIGlmIChfLmV4aXN0cyhmb290ZXJOb2RlLmlkKSkge1xuICAgICAgICAgICAgZm9vdGVyTm9kZS5pZCA9ICdyb3dHcm91cEZvb3Rlcl8nICsgZm9vdGVyTm9kZS5pZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBnZXQgYm90aCBoZWFkZXIgYW5kIGZvb3RlciB0byByZWZlcmVuY2UgZWFjaCBvdGhlciBhcyBzaWJsaW5ncy4gdGhpcyBpcyBuZXZlciB1bmRvbmUsXG4gICAgICAgIC8vIG9ubHkgb3ZlcndyaXR0ZW4uIHNvIGlmIGEgZ3JvdXAgaXMgZXhwYW5kZWQsIHRoZW4gY29udHJhY3RlZCwgaXQgd2lsbCBoYXZlIGEgZ2hvc3RcbiAgICAgICAgLy8gc2libGluZyAtIGJ1dCB0aGF0J3MgZmluZSwgYXMgd2UgY2FuIGlnbm9yZSB0aGlzIGlmIHRoZSBoZWFkZXIgaXMgY29udHJhY3RlZC5cbiAgICAgICAgZm9vdGVyTm9kZS5zaWJsaW5nID0gZ3JvdXBOb2RlO1xuICAgICAgICBncm91cE5vZGUuc2libGluZyA9IGZvb3Rlck5vZGU7XG4gICAgfTtcbiAgICBGbGF0dGVuU3RhZ2UucHJvdG90eXBlLmNyZWF0ZURldGFpbE5vZGUgPSBmdW5jdGlvbiAobWFzdGVyTm9kZSkge1xuICAgICAgICBpZiAoXy5leGlzdHMobWFzdGVyTm9kZS5kZXRhaWxOb2RlKSkge1xuICAgICAgICAgICAgcmV0dXJuIG1hc3Rlck5vZGUuZGV0YWlsTm9kZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGV0YWlsTm9kZSA9IG5ldyBSb3dOb2RlKHRoaXMuYmVhbnMpO1xuICAgICAgICBkZXRhaWxOb2RlLmRldGFpbCA9IHRydWU7XG4gICAgICAgIGRldGFpbE5vZGUuc2VsZWN0YWJsZSA9IGZhbHNlO1xuICAgICAgICBkZXRhaWxOb2RlLnBhcmVudCA9IG1hc3Rlck5vZGU7XG4gICAgICAgIGlmIChfLmV4aXN0cyhtYXN0ZXJOb2RlLmlkKSkge1xuICAgICAgICAgICAgZGV0YWlsTm9kZS5pZCA9ICdkZXRhaWxfJyArIG1hc3Rlck5vZGUuaWQ7XG4gICAgICAgIH1cbiAgICAgICAgZGV0YWlsTm9kZS5kYXRhID0gbWFzdGVyTm9kZS5kYXRhO1xuICAgICAgICBkZXRhaWxOb2RlLmxldmVsID0gbWFzdGVyTm9kZS5sZXZlbCArIDE7XG4gICAgICAgIG1hc3Rlck5vZGUuZGV0YWlsTm9kZSA9IGRldGFpbE5vZGU7XG4gICAgICAgIHJldHVybiBkZXRhaWxOb2RlO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQ4KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgRmxhdHRlblN0YWdlLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkOChbXG4gICAgICAgIEF1dG93aXJlZCgnYmVhbnMnKVxuICAgIF0sIEZsYXR0ZW5TdGFnZS5wcm90b3R5cGUsIFwiYmVhbnNcIiwgdm9pZCAwKTtcbiAgICBGbGF0dGVuU3RhZ2UgPSBfX2RlY29yYXRlJDgoW1xuICAgICAgICBCZWFuKCdmbGF0dGVuU3RhZ2UnKVxuICAgIF0sIEZsYXR0ZW5TdGFnZSk7XG4gICAgcmV0dXJuIEZsYXR0ZW5TdGFnZTtcbn0oQmVhblN0dWIpKTtcblxudmFyIF9fZXh0ZW5kcyQ4ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQ3ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgU29ydFNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDgoU29ydFNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gU29ydFNlcnZpY2UoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgU29ydFNlcnZpY2UucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucG9zdFNvcnRGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0UG9zdFNvcnRGdW5jKCk7XG4gICAgfTtcbiAgICBTb3J0U2VydmljZS5wcm90b3R5cGUuc29ydCA9IGZ1bmN0aW9uIChzb3J0T3B0aW9ucywgc29ydEFjdGl2ZSwgdXNlRGVsdGFTb3J0LCByb3dOb2RlVHJhbnNhY3Rpb25zLCBjaGFuZ2VkUGF0aCwgc29ydENvbnRhaW5zR3JvdXBDb2x1bW5zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBncm91cE1haW50YWluT3JkZXIgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwTWFpbnRhaW5PcmRlcigpO1xuICAgICAgICB2YXIgZ3JvdXBDb2x1bW5zUHJlc2VudCA9IHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsR3JpZENvbHVtbnMoKS5zb21lKGZ1bmN0aW9uIChjKSB7IHJldHVybiBjLmlzUm93R3JvdXBBY3RpdmUoKTsgfSk7XG4gICAgICAgIHZhciBhbGxEaXJ0eU5vZGVzID0ge307XG4gICAgICAgIGlmICh1c2VEZWx0YVNvcnQgJiYgcm93Tm9kZVRyYW5zYWN0aW9ucykge1xuICAgICAgICAgICAgYWxsRGlydHlOb2RlcyA9IHRoaXMuY2FsY3VsYXRlRGlydHlOb2Rlcyhyb3dOb2RlVHJhbnNhY3Rpb25zKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNQaXZvdE1vZGUgPSB0aGlzLmNvbHVtbk1vZGVsLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICAvLyB3ZSBjbGVhciBvdXQgdGhlICdwdWxsIGRvd24gb3BlbiBwYXJlbnRzJyBmaXJzdCwgYXMgdGhlIHZhbHVlcyBtaXggdXAgdGhlIHNvcnRpbmdcbiAgICAgICAgICAgIF90aGlzLnB1bGxEb3duR3JvdXBEYXRhRm9ySGlkZU9wZW5QYXJlbnRzKHJvd05vZGUuY2hpbGRyZW5BZnRlckFnZ0ZpbHRlciwgdHJ1ZSk7XG4gICAgICAgICAgICAvLyBJdCdzIHBvaW50bGVzcyB0byBzb3J0IHJvd3Mgd2hpY2ggYXJlbid0IGJlaW5nIGRpc3BsYXllZC4gaW4gcGl2b3QgbW9kZSB3ZSBkb24ndCBuZWVkIHRvIHNvcnQgdGhlIGxlYWYgZ3JvdXAgY2hpbGRyZW4uXG4gICAgICAgICAgICB2YXIgc2tpcFNvcnRpbmdQaXZvdExlYWZzID0gaXNQaXZvdE1vZGUgJiYgcm93Tm9kZS5sZWFmR3JvdXA7XG4gICAgICAgICAgICAvLyBKYXZhc2NyaXB0IHNvcnQgaXMgbm9uIGRldGVybWluaXN0aWMgd2hlbiBhbGwgdGhlIGFycmF5IGl0ZW1zIGFyZSBlcXVhbHMsIGllIENvbXBhcmF0b3IgYWx3YXlzIHJldHVybnMgMCxcbiAgICAgICAgICAgIC8vIHNvIHRvIGVuc3VyZSB0aGUgYXJyYXkga2VlcHMgaXRzIG9yZGVyLCBhZGQgYW4gYWRkaXRpb25hbCBzb3J0aW5nIGNvbmRpdGlvbiBtYW51YWxseSwgaW4gdGhpcyBjYXNlIHdlXG4gICAgICAgICAgICAvLyBhcmUgZ29pbmcgdG8gaW5zcGVjdCB0aGUgb3JpZ2luYWwgYXJyYXkgcG9zaXRpb24uIFRoaXMgaXMgd2hhdCBzb3J0ZWRSb3dOb2RlcyBpcyBmb3IuXG4gICAgICAgICAgICB2YXIgc2tpcFNvcnRpbmdHcm91cHMgPSBncm91cE1haW50YWluT3JkZXIgJiYgZ3JvdXBDb2x1bW5zUHJlc2VudCAmJiAhcm93Tm9kZS5sZWFmR3JvdXAgJiYgIXNvcnRDb250YWluc0dyb3VwQ29sdW1ucztcbiAgICAgICAgICAgIGlmICghc29ydEFjdGl2ZSB8fCBza2lwU29ydGluZ0dyb3VwcyB8fCBza2lwU29ydGluZ1Bpdm90TGVhZnMpIHtcbiAgICAgICAgICAgICAgICAvLyB3aGVuICdncm91cE1haW50YWluT3JkZXInIGlzIGVuYWJsZWQgd2Ugc2tpcCBzb3J0aW5nIGdyb3VwcyB1bmxlc3Mgd2UgYXJlIHNvcnRpbmcgb24gZ3JvdXAgY29sdW1uc1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlblRvQmVTb3J0ZWQgPSByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJBZ2dGaWx0ZXIuc2xpY2UoMCk7XG4gICAgICAgICAgICAgICAgaWYgKGdyb3VwTWFpbnRhaW5PcmRlciAmJiByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbmRleGVkT3JkZXJzXzEgPSByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0LnJlZHVjZShmdW5jdGlvbiAoYWNjLCByb3csIGlkeCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjW3Jvdy5pZF0gPSBpZHg7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICAgICAgICAgICAgICB9LCB7fSk7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuVG9CZVNvcnRlZC5zb3J0KGZ1bmN0aW9uIChyb3cxLCByb3cyKSB7IHJldHVybiAoaW5kZXhlZE9yZGVyc18xW3JvdzEuaWRdIHx8IDApIC0gKGluZGV4ZWRPcmRlcnNfMVtyb3cyLmlkXSB8fCAwKTsgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQgPSBjaGlsZHJlblRvQmVTb3J0ZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh1c2VEZWx0YVNvcnQpIHtcbiAgICAgICAgICAgICAgICByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0ID0gX3RoaXMuZG9EZWx0YVNvcnQocm93Tm9kZSwgYWxsRGlydHlOb2RlcywgY2hhbmdlZFBhdGgsIHNvcnRPcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQgPSBfdGhpcy5yb3dOb2RlU29ydGVyLmRvRnVsbFNvcnQocm93Tm9kZS5jaGlsZHJlbkFmdGVyQWdnRmlsdGVyLCBzb3J0T3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocm93Tm9kZS5zaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5zaWJsaW5nLmNoaWxkcmVuQWZ0ZXJTb3J0ID0gcm93Tm9kZS5jaGlsZHJlbkFmdGVyU29ydDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZUNoaWxkSW5kZXhlcyhyb3dOb2RlKTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5wb3N0U29ydEZ1bmMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyYW1zID0geyBub2Rlczogcm93Tm9kZS5jaGlsZHJlbkFmdGVyU29ydCB9O1xuICAgICAgICAgICAgICAgIF90aGlzLnBvc3RTb3J0RnVuYyhwYXJhbXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAoY2hhbmdlZFBhdGgpIHtcbiAgICAgICAgICAgIGNoYW5nZWRQYXRoLmZvckVhY2hDaGFuZ2VkTm9kZURlcHRoRmlyc3QoY2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlR3JvdXBEYXRhRm9ySGlkZU9wZW5QYXJlbnRzKGNoYW5nZWRQYXRoKTtcbiAgICB9O1xuICAgIFNvcnRTZXJ2aWNlLnByb3RvdHlwZS5jYWxjdWxhdGVEaXJ0eU5vZGVzID0gZnVuY3Rpb24gKHJvd05vZGVUcmFuc2FjdGlvbnMpIHtcbiAgICAgICAgdmFyIGRpcnR5Tm9kZXMgPSB7fTtcbiAgICAgICAgdmFyIGFkZE5vZGVzRnVuYyA9IGZ1bmN0aW9uIChyb3dOb2Rlcykge1xuICAgICAgICAgICAgaWYgKHJvd05vZGVzKSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZXMuZm9yRWFjaChmdW5jdGlvbiAocm93Tm9kZSkgeyByZXR1cm4gZGlydHlOb2Rlc1tyb3dOb2RlLmlkXSA9IHRydWU7IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvLyBhbGwgbGVhZiBsZXZlbCBub2RlcyBpbiB0aGUgdHJhbnNhY3Rpb24gd2VyZSBpbXBhY3RlZFxuICAgICAgICBpZiAocm93Tm9kZVRyYW5zYWN0aW9ucykge1xuICAgICAgICAgICAgcm93Tm9kZVRyYW5zYWN0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uICh0cmFuKSB7XG4gICAgICAgICAgICAgICAgYWRkTm9kZXNGdW5jKHRyYW4uYWRkKTtcbiAgICAgICAgICAgICAgICBhZGROb2Rlc0Z1bmModHJhbi51cGRhdGUpO1xuICAgICAgICAgICAgICAgIGFkZE5vZGVzRnVuYyh0cmFuLnJlbW92ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlydHlOb2RlcztcbiAgICB9O1xuICAgIFNvcnRTZXJ2aWNlLnByb3RvdHlwZS5kb0RlbHRhU29ydCA9IGZ1bmN0aW9uIChyb3dOb2RlLCBhbGxUb3VjaGVkTm9kZXMsIGNoYW5nZWRQYXRoLCBzb3J0T3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdW5zb3J0ZWRSb3dzID0gcm93Tm9kZS5jaGlsZHJlbkFmdGVyQWdnRmlsdGVyO1xuICAgICAgICB2YXIgb2xkU29ydGVkUm93cyA9IHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQ7XG4gICAgICAgIGlmICghb2xkU29ydGVkUm93cykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm93Tm9kZVNvcnRlci5kb0Z1bGxTb3J0KHVuc29ydGVkUm93cywgc29ydE9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1bnRvdWNoZWRSb3dzTWFwID0ge307XG4gICAgICAgIHZhciB0b3VjaGVkUm93cyA9IFtdO1xuICAgICAgICB1bnNvcnRlZFJvd3MuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgICAgICBpZiAoYWxsVG91Y2hlZE5vZGVzW3Jvdy5pZF0gfHwgIWNoYW5nZWRQYXRoLmNhblNraXAocm93KSkge1xuICAgICAgICAgICAgICAgIHRvdWNoZWRSb3dzLnB1c2gocm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHVudG91Y2hlZFJvd3NNYXBbcm93LmlkXSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgc29ydGVkVW50b3VjaGVkUm93cyA9IG9sZFNvcnRlZFJvd3MuZmlsdGVyKGZ1bmN0aW9uIChjaGlsZCkgeyByZXR1cm4gdW50b3VjaGVkUm93c01hcFtjaGlsZC5pZF07IH0pO1xuICAgICAgICB2YXIgbWFwTm9kZVRvU29ydGVkTm9kZSA9IGZ1bmN0aW9uIChyb3dOb2RlLCBwb3MpIHsgcmV0dXJuICh7IGN1cnJlbnRQb3M6IHBvcywgcm93Tm9kZTogcm93Tm9kZSB9KTsgfTtcbiAgICAgICAgdmFyIHNvcnRlZENoYW5nZWRSb3dzID0gdG91Y2hlZFJvd3NcbiAgICAgICAgICAgIC5tYXAobWFwTm9kZVRvU29ydGVkTm9kZSlcbiAgICAgICAgICAgIC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBfdGhpcy5yb3dOb2RlU29ydGVyLmNvbXBhcmVSb3dOb2Rlcyhzb3J0T3B0aW9ucywgYSwgYik7IH0pO1xuICAgICAgICByZXR1cm4gdGhpcy5tZXJnZVNvcnRlZEFycmF5cyhzb3J0T3B0aW9ucywgc29ydGVkQ2hhbmdlZFJvd3MsIHNvcnRlZFVudG91Y2hlZFJvd3MubWFwKG1hcE5vZGVUb1NvcnRlZE5vZGUpKS5tYXAoZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICB2YXIgcm93Tm9kZSA9IF9hLnJvd05vZGU7XG4gICAgICAgICAgICByZXR1cm4gcm93Tm9kZTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBNZXJnZSB0d28gc29ydGVkIGFycmF5cyBpbnRvIGVhY2ggb3RoZXJcbiAgICBTb3J0U2VydmljZS5wcm90b3R5cGUubWVyZ2VTb3J0ZWRBcnJheXMgPSBmdW5jdGlvbiAoc29ydE9wdGlvbnMsIGFycjEsIGFycjIpIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdO1xuICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgIHZhciBqID0gMDtcbiAgICAgICAgLy8gVHJhdmVyc2UgYm90aCBhcnJheSwgYWRkaW5nIHRoZW0gaW4gb3JkZXJcbiAgICAgICAgd2hpbGUgKGkgPCBhcnIxLmxlbmd0aCAmJiBqIDwgYXJyMi5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGN1cnJlbnQgZWxlbWVudCBvZiBmaXJzdFxuICAgICAgICAgICAgLy8gYXJyYXkgaXMgc21hbGxlciB0aGFuIGN1cnJlbnQgZWxlbWVudFxuICAgICAgICAgICAgLy8gb2Ygc2Vjb25kIGFycmF5LiBJZiB5ZXMsIHN0b3JlIGZpcnN0XG4gICAgICAgICAgICAvLyBhcnJheSBlbGVtZW50IGFuZCBpbmNyZW1lbnQgZmlyc3QgYXJyYXlcbiAgICAgICAgICAgIC8vIGluZGV4LiBPdGhlcndpc2UgZG8gc2FtZSB3aXRoIHNlY29uZCBhcnJheVxuICAgICAgICAgICAgdmFyIGNvbXBhcmVSZXN1bHQgPSB0aGlzLnJvd05vZGVTb3J0ZXIuY29tcGFyZVJvd05vZGVzKHNvcnRPcHRpb25zLCBhcnIxW2ldLCBhcnIyW2pdKTtcbiAgICAgICAgICAgIGlmIChjb21wYXJlUmVzdWx0IDwgMCkge1xuICAgICAgICAgICAgICAgIHJlcy5wdXNoKGFycjFbaSsrXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChhcnIyW2orK10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGFkZCByZW1haW5pbmcgZnJvbSBhcnIxXG4gICAgICAgIHdoaWxlIChpIDwgYXJyMS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKGFycjFbaSsrXSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gYWRkIHJlbWFpbmluZyBmcm9tIGFycjJcbiAgICAgICAgd2hpbGUgKGogPCBhcnIyLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVzLnB1c2goYXJyMltqKytdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgU29ydFNlcnZpY2UucHJvdG90eXBlLnVwZGF0ZUNoaWxkSW5kZXhlcyA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIGlmIChfLm1pc3Npbmcocm93Tm9kZS5jaGlsZHJlbkFmdGVyU29ydCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbGlzdFRvU29ydCA9IHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQ7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlzdFRvU29ydC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNoaWxkID0gbGlzdFRvU29ydFtpXTtcbiAgICAgICAgICAgIHZhciBmaXJzdENoaWxkID0gaSA9PT0gMDtcbiAgICAgICAgICAgIHZhciBsYXN0Q2hpbGQgPSBpID09PSByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJTb3J0Lmxlbmd0aCAtIDE7XG4gICAgICAgICAgICBjaGlsZC5zZXRGaXJzdENoaWxkKGZpcnN0Q2hpbGQpO1xuICAgICAgICAgICAgY2hpbGQuc2V0TGFzdENoaWxkKGxhc3RDaGlsZCk7XG4gICAgICAgICAgICBjaGlsZC5zZXRDaGlsZEluZGV4KGkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTb3J0U2VydmljZS5wcm90b3R5cGUudXBkYXRlR3JvdXBEYXRhRm9ySGlkZU9wZW5QYXJlbnRzID0gZnVuY3Rpb24gKGNoYW5nZWRQYXRoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cEhpZGVPcGVuUGFyZW50cygpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKSkge1xuICAgICAgICAgICAgdmFyIG1zZ18xID0gXCJBRyBHcmlkOiBUaGUgcHJvcGVydHkgaGlkZU9wZW5QYXJlbnRzIGRvc2Ugbm90IHdvcmsgd2l0aCBUcmVlIERhdGEuIFRoaXMgaXMgYmVjYXVzZSBUcmVlIERhdGEgaGFzIHZhbHVlcyBhdCB0aGUgZ3JvdXAgbGV2ZWwsIGl0IGRvZXNuJ3QgbWFrZSBzZW5zZSB0byBoaWRlIHRoZW0gKGFzIG9wcG9zZWQgdG8gUm93IEdyb3VwaW5nLCB3aGljaCBvbmx5IGhhcyBBZ2dyZWdhdGVkIFZhbHVlcyBhdCB0aGUgZ3JvdXAgbGV2ZWwpLlwiO1xuICAgICAgICAgICAgXy5kb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKG1zZ18xKTsgfSwgJ3NvcnRTZXJ2aWNlLmhpZGVPcGVuUGFyZW50c1dpdGhUcmVlRGF0YScpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIHJlY3Vyc2UgYnJlYWR0aCBmaXJzdCBvdmVyIGdyb3VwIG5vZGVzIGFmdGVyIHNvcnQgdG8gJ3B1bGwgZG93bicgZ3JvdXAgZGF0YSB0byBjaGlsZCBncm91cHNcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgIF90aGlzLnB1bGxEb3duR3JvdXBEYXRhRm9ySGlkZU9wZW5QYXJlbnRzKHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQsIGZhbHNlKTtcbiAgICAgICAgICAgIHJvd05vZGUuY2hpbGRyZW5BZnRlclNvcnQuZm9yRWFjaChmdW5jdGlvbiAoY2hpbGQpIHtcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGQuaGFzQ2hpbGRyZW4oKSkge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhjaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGlmIChjaGFuZ2VkUGF0aCkge1xuICAgICAgICAgICAgY2hhbmdlZFBhdGguZXhlY3V0ZUZyb21Sb290Tm9kZShmdW5jdGlvbiAocm93Tm9kZSkgeyByZXR1cm4gY2FsbGJhY2socm93Tm9kZSk7IH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBTb3J0U2VydmljZS5wcm90b3R5cGUucHVsbERvd25Hcm91cERhdGFGb3JIaWRlT3BlblBhcmVudHMgPSBmdW5jdGlvbiAocm93Tm9kZXMsIGNsZWFyT3BlcmF0aW9uKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNHcm91cEhpZGVPcGVuUGFyZW50cygpIHx8IF8ubWlzc2luZyhyb3dOb2RlcykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByb3dOb2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZFJvd05vZGUpIHtcbiAgICAgICAgICAgIHZhciBncm91cERpc3BsYXlDb2xzID0gX3RoaXMuY29sdW1uTW9kZWwuZ2V0R3JvdXBEaXNwbGF5Q29sdW1ucygpO1xuICAgICAgICAgICAgZ3JvdXBEaXNwbGF5Q29scy5mb3JFYWNoKGZ1bmN0aW9uIChncm91cERpc3BsYXlDb2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2hvd1Jvd0dyb3VwID0gZ3JvdXBEaXNwbGF5Q29sLmdldENvbERlZigpLnNob3dSb3dHcm91cDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNob3dSb3dHcm91cCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogZ3JvdXBIaWRlT3BlblBhcmVudHMgb25seSB3b3JrcyB3aGVuIHNwZWNpZnlpbmcgc3BlY2lmaWMgY29sdW1ucyBmb3IgY29sRGVmLnNob3dSb3dHcm91cCcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBkaXNwbGF5aW5nR3JvdXBLZXkgPSBzaG93Um93R3JvdXA7XG4gICAgICAgICAgICAgICAgdmFyIHJvd0dyb3VwQ29sdW1uID0gX3RoaXMuY29sdW1uTW9kZWwuZ2V0UHJpbWFyeUNvbHVtbihkaXNwbGF5aW5nR3JvdXBLZXkpO1xuICAgICAgICAgICAgICAgIHZhciB0aGlzUm93Tm9kZU1hdGNoZXMgPSByb3dHcm91cENvbHVtbiA9PT0gY2hpbGRSb3dOb2RlLnJvd0dyb3VwQ29sdW1uO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzUm93Tm9kZU1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY2xlYXJPcGVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgZG9pbmcgYSBjbGVhciBvcGVyYXRpb24sIHdlIGNsZWFyIGRvd24gdGhlIHZhbHVlIGZvciBldmVyeSBwb3NzaWJsZSBncm91cCBjb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgY2hpbGRSb3dOb2RlLnNldEdyb3VwVmFsdWUoZ3JvdXBEaXNwbGF5Q29sLmdldElkKCksIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiBkb2luZyBhIHNldCBvcGVyYXRpb24sIHdlIHNldCBvbmx5IHdoZXJlIHRoZSBwdWxsIGRvd24gaXMgdG8gb2NjdXJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudFRvU3RlYWxGcm9tID0gY2hpbGRSb3dOb2RlLmdldEZpcnN0Q2hpbGRPZkZpcnN0Q2hpbGQocm93R3JvdXBDb2x1bW4pO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50VG9TdGVhbEZyb20pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkUm93Tm9kZS5zZXRHcm91cFZhbHVlKGdyb3VwRGlzcGxheUNvbC5nZXRJZCgpLCBwYXJlbnRUb1N0ZWFsRnJvbS5rZXkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgX19kZWNvcmF0ZSQ3KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5Nb2RlbCcpXG4gICAgXSwgU29ydFNlcnZpY2UucHJvdG90eXBlLCBcImNvbHVtbk1vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQ3KFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dOb2RlU29ydGVyJylcbiAgICBdLCBTb3J0U2VydmljZS5wcm90b3R5cGUsIFwicm93Tm9kZVNvcnRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkNyhbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBTb3J0U2VydmljZS5wcm90b3R5cGUsIFwiaW5pdFwiLCBudWxsKTtcbiAgICBTb3J0U2VydmljZSA9IF9fZGVjb3JhdGUkNyhbXG4gICAgICAgIEJlYW4oJ3NvcnRTZXJ2aWNlJylcbiAgICBdLCBTb3J0U2VydmljZSk7XG4gICAgcmV0dXJuIFNvcnRTZXJ2aWNlO1xufShCZWFuU3R1YikpO1xuXG52YXIgX19leHRlbmRzJDcgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDYgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBGaWx0ZXJTZXJ2aWNlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQ3KEZpbHRlclNlcnZpY2UsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gRmlsdGVyU2VydmljZSgpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBGaWx0ZXJTZXJ2aWNlLnByb3RvdHlwZS5maWx0ZXIgPSBmdW5jdGlvbiAoY2hhbmdlZFBhdGgpIHtcbiAgICAgICAgdmFyIGZpbHRlckFjdGl2ZSA9IHRoaXMuZmlsdGVyTWFuYWdlci5pc0NvbHVtbkZpbHRlclByZXNlbnQoKVxuICAgICAgICAgICAgfHwgdGhpcy5maWx0ZXJNYW5hZ2VyLmlzUXVpY2tGaWx0ZXJQcmVzZW50KClcbiAgICAgICAgICAgIHx8IHRoaXMuZmlsdGVyTWFuYWdlci5pc0V4dGVybmFsRmlsdGVyUHJlc2VudCgpO1xuICAgICAgICB0aGlzLmZpbHRlck5vZGVzKGZpbHRlckFjdGl2ZSwgY2hhbmdlZFBhdGgpO1xuICAgIH07XG4gICAgRmlsdGVyU2VydmljZS5wcm90b3R5cGUuZmlsdGVyTm9kZXMgPSBmdW5jdGlvbiAoZmlsdGVyQWN0aXZlLCBjaGFuZ2VkUGF0aCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZmlsdGVyQ2FsbGJhY2sgPSBmdW5jdGlvbiAocm93Tm9kZSwgaW5jbHVkZUNoaWxkTm9kZXMpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2l2ZWx5IGdldCBhbGwgY2hpbGRyZW4gdGhhdCBhcmUgZ3JvdXBzIHRvIGFsc28gZmlsdGVyXG4gICAgICAgICAgICBpZiAocm93Tm9kZS5oYXNDaGlsZHJlbigpKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVzdWx0IG9mIGZpbHRlciBmb3IgdGhpcyBub2RlLiB3aGVuIGZpbHRlcmluZyB0cmVlIGRhdGEsIGluY2x1ZGVDaGlsZE5vZGVzID0gdHJ1ZSB3aGVuIHBhcmVudCBwYXNzZXNcbiAgICAgICAgICAgICAgICBpZiAoZmlsdGVyQWN0aXZlICYmICFpbmNsdWRlQ2hpbGROb2Rlcykge1xuICAgICAgICAgICAgICAgICAgICByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJGaWx0ZXIgPSByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cC5maWx0ZXIoZnVuY3Rpb24gKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBncm91cCBpcyBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGlmIGl0IGhhcyBhbnkgY2hpbGRyZW4gb2YgaXQncyBvd24uXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBieSB0aGlzIHN0YWdlLCB0aGUgY2hpbGQgZ3JvdXBzIGFyZSBhbHJlYWR5IGZpbHRlcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcGFzc0JlY2F1c2VDaGlsZHJlbiA9IGNoaWxkTm9kZS5jaGlsZHJlbkFmdGVyRmlsdGVyICYmIGNoaWxkTm9kZS5jaGlsZHJlbkFmdGVyRmlsdGVyLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBib3RoIGxlYWYgbGV2ZWwgbm9kZXMgYW5kIHRyZWUgZGF0YSBub2RlcyBoYXZlIGRhdGEuIHRoZXNlIGdldCBhZGRlZCBpZlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGRhdGEgcGFzc2VzIHRoZSBmaWx0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYXNzQmVjYXVzZURhdGFQYXNzZXMgPSBjaGlsZE5vZGUuZGF0YVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICYmIF90aGlzLmZpbHRlck1hbmFnZXIuZG9lc1Jvd1Bhc3NGaWx0ZXIoeyByb3dOb2RlOiBjaGlsZE5vZGUgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBub3RlIC0gdHJlZSBkYXRhIG5vZGVzIHBhc3MgZWl0aGVyIGlmIGEpIHRoZXkgcGFzcyB0aGVtc2VsdmVzIG9yIGIpIGFueSBjaGlsZHJlbiBvZiB0aGF0IG5vZGUgcGFzc1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhc3NCZWNhdXNlQ2hpbGRyZW4gfHwgcGFzc0JlY2F1c2VEYXRhUGFzc2VzO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIG5vdCBmaWx0ZXJpbmcsIHRoZSByZXN1bHQgaXMgdGhlIG9yaWdpbmFsIGxpc3RcbiAgICAgICAgICAgICAgICAgICAgcm93Tm9kZS5jaGlsZHJlbkFmdGVyRmlsdGVyID0gcm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5jaGlsZHJlbkFmdGVyRmlsdGVyID0gcm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocm93Tm9kZS5zaWJsaW5nKSB7XG4gICAgICAgICAgICAgICAgcm93Tm9kZS5zaWJsaW5nLmNoaWxkcmVuQWZ0ZXJGaWx0ZXIgPSByb3dOb2RlLmNoaWxkcmVuQWZ0ZXJGaWx0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLmRvaW5nVHJlZURhdGFGaWx0ZXJpbmcoKSkge1xuICAgICAgICAgICAgdmFyIHRyZWVEYXRhRGVwdGhGaXJzdEZpbHRlcl8xID0gZnVuY3Rpb24gKHJvd05vZGUsIGFscmVhZHlGb3VuZEluUGFyZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gdHJlZSBkYXRhIGZpbHRlciB0cmF2ZXJzZXMgdGhlIGhpZXJhcmNoeSBkZXB0aCBmaXJzdCBhbmQgaW5jbHVkZXMgY2hpbGQgbm9kZXMgaWYgcGFyZW50IHBhc3Nlc1xuICAgICAgICAgICAgICAgIC8vIGZpbHRlciwgYW5kIHBhcmVudCBub2RlcyB3aWxsIGJlIGluY2x1ZGUgaWYgYW55IGNoaWxkcmVuIGV4aXN0LlxuICAgICAgICAgICAgICAgIGlmIChyb3dOb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvd05vZGUuY2hpbGRyZW5BZnRlckdyb3VwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gcm93Tm9kZS5jaGlsZHJlbkFmdGVyR3JvdXBbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmaXJzdCBjaGVjayBpZiBjdXJyZW50IG5vZGUgcGFzc2VzIGZpbHRlciBiZWZvcmUgaW52b2tpbmcgY2hpbGQgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBmb3VuZEluUGFyZW50ID0gYWxyZWFkeUZvdW5kSW5QYXJlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCBfdGhpcy5maWx0ZXJNYW5hZ2VyLmRvZXNSb3dQYXNzRmlsdGVyKHsgcm93Tm9kZTogY2hpbGROb2RlIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZS5jaGlsZHJlbkFmdGVyR3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmVlRGF0YURlcHRoRmlyc3RGaWx0ZXJfMShyb3dOb2RlLmNoaWxkcmVuQWZ0ZXJHcm91cFtpXSwgZm91bmRJblBhcmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXJDYWxsYmFjayhjaGlsZE5vZGUsIGZvdW5kSW5QYXJlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZpbHRlckNhbGxiYWNrKHJvd05vZGUsIGFscmVhZHlGb3VuZEluUGFyZW50KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgdHJlZURhdGFGaWx0ZXJDYWxsYmFjayA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7IHJldHVybiB0cmVlRGF0YURlcHRoRmlyc3RGaWx0ZXJfMShyb3dOb2RlLCBmYWxzZSk7IH07XG4gICAgICAgICAgICBjaGFuZ2VkUGF0aC5leGVjdXRlRnJvbVJvb3ROb2RlKHRyZWVEYXRhRmlsdGVyQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIGRlZmF1bHRGaWx0ZXJDYWxsYmFjayA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7IHJldHVybiBmaWx0ZXJDYWxsYmFjayhyb3dOb2RlLCBmYWxzZSk7IH07XG4gICAgICAgICAgICBjaGFuZ2VkUGF0aC5mb3JFYWNoQ2hhbmdlZE5vZGVEZXB0aEZpcnN0KGRlZmF1bHRGaWx0ZXJDYWxsYmFjaywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEZpbHRlclNlcnZpY2UucHJvdG90eXBlLmRvaW5nVHJlZURhdGFGaWx0ZXJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1RyZWVEYXRhKCkgJiYgIXRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzRXhjbHVkZUNoaWxkcmVuV2hlblRyZWVEYXRhRmlsdGVyaW5nKCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDYoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZpbHRlck1hbmFnZXInKVxuICAgIF0sIEZpbHRlclNlcnZpY2UucHJvdG90eXBlLCBcImZpbHRlck1hbmFnZXJcIiwgdm9pZCAwKTtcbiAgICBGaWx0ZXJTZXJ2aWNlID0gX19kZWNvcmF0ZSQ2KFtcbiAgICAgICAgQmVhbihcImZpbHRlclNlcnZpY2VcIilcbiAgICBdLCBGaWx0ZXJTZXJ2aWNlKTtcbiAgICByZXR1cm4gRmlsdGVyU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxudmFyIF9fZXh0ZW5kcyQ2ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQ1ID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgX19yZWFkID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19yZWFkKSB8fCBmdW5jdGlvbiAobywgbikge1xuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcbiAgICBpZiAoIW0pIHJldHVybiBvO1xuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xuICAgIHRyeSB7XG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxuICAgIH1cbiAgICByZXR1cm4gYXI7XG59O1xudmFyIEltbXV0YWJsZVNlcnZpY2UgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDYoSW1tdXRhYmxlU2VydmljZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBJbW11dGFibGVTZXJ2aWNlKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIEltbXV0YWJsZVNlcnZpY2UucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnJvd01vZGVsLmdldFR5cGUoKSA9PT0gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0NMSUVOVF9TSURFKSB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbCA9IHRoaXMucm93TW9kZWw7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEltbXV0YWJsZVNlcnZpY2UucHJvdG90eXBlLmlzQWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNJbW11dGFibGVEYXRhKCk7XG4gICAgfTtcbiAgICBJbW11dGFibGVTZXJ2aWNlLnByb3RvdHlwZS5zZXRSb3dEYXRhID0gZnVuY3Rpb24gKHJvd0RhdGEpIHtcbiAgICAgICAgdmFyIHRyYW5zYWN0aW9uQW5kTWFwID0gdGhpcy5jcmVhdGVUcmFuc2FjdGlvbkZvclJvd0RhdGEocm93RGF0YSk7XG4gICAgICAgIGlmICghdHJhbnNhY3Rpb25BbmRNYXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgX2EgPSBfX3JlYWQodHJhbnNhY3Rpb25BbmRNYXAsIDIpLCB0cmFuc2FjdGlvbiA9IF9hWzBdLCBvcmRlcklkTWFwID0gX2FbMV07XG4gICAgICAgIHZhciBub2RlVHJhbnNhY3Rpb24gPSB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC51cGRhdGVSb3dEYXRhKHRyYW5zYWN0aW9uLCBvcmRlcklkTWFwKTtcbiAgICAgICAgLy8gbmVlZCB0byBmb3JjZSB1cGRhdGluZyBvZiBmdWxsIHdpZHRoIHJvd3MgLSBub3RlIHRoaXMgd291bGRuJ3QgYmUgbmVjZXNzYXJ5IHRoZSBmdWxsIHdpZHRoIGNlbGwgY29tcCBsaXN0ZW5lZFxuICAgICAgICAvLyB0byB0aGUgZGF0YSBjaGFuZ2UgZXZlbnQgb24gdGhlIHJvdyBub2RlIGFuZCByZWZyZXNoZWQgaXRzZWxmLlxuICAgICAgICBpZiAobm9kZVRyYW5zYWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnJvd1JlbmRlcmVyLnJlZnJlc2hGdWxsV2lkdGhSb3dzKG5vZGVUcmFuc2FjdGlvbi51cGRhdGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBjb252ZXJ0cyB0aGUgc2V0Um93RGF0YSgpIGNvbW1hbmQgdG8gYSB0cmFuc2FjdGlvblxuICAgIEltbXV0YWJsZVNlcnZpY2UucHJvdG90eXBlLmNyZWF0ZVRyYW5zYWN0aW9uRm9yUm93RGF0YSA9IGZ1bmN0aW9uIChyb3dEYXRhKSB7XG4gICAgICAgIGlmIChfLm1pc3NpbmcodGhpcy5jbGllbnRTaWRlUm93TW9kZWwpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBRyBHcmlkOiBJbW11dGFibGVTZXJ2aWNlIG9ubHkgd29ya3Mgd2l0aCBDbGllbnRTaWRlUm93TW9kZWwnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZ2V0Um93SWRGdW5jID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93SWRGdW5jKCk7XG4gICAgICAgIGlmIChnZXRSb3dJZEZ1bmMgPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignQUcgR3JpZDogSW1tdXRhYmxlU2VydmljZSByZXF1aXJlcyBnZXRSb3dJZCgpIGNhbGxiYWNrIHRvIGJlIGltcGxlbWVudGVkLCB5b3VyIHJvdyBkYXRhIG5lZWRzIElEcyEnKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb252ZXJ0IHRoZSBkYXRhIGludG8gYSB0cmFuc2FjdGlvbiBvYmplY3QgYnkgd29ya2luZyBvdXQgYWRkcywgcmVtb3ZlcyBhbmQgdXBkYXRlc1xuICAgICAgICB2YXIgdHJhbnNhY3Rpb24gPSB7XG4gICAgICAgICAgICByZW1vdmU6IFtdLFxuICAgICAgICAgICAgdXBkYXRlOiBbXSxcbiAgICAgICAgICAgIGFkZDogW11cbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGV4aXN0aW5nTm9kZXNNYXAgPSB0aGlzLmNsaWVudFNpZGVSb3dNb2RlbC5nZXRDb3B5T2ZOb2Rlc01hcCgpO1xuICAgICAgICB2YXIgc3VwcHJlc3NTb3J0T3JkZXIgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzTWFpbnRhaW5VbnNvcnRlZE9yZGVyKCk7XG4gICAgICAgIHZhciBvcmRlck1hcCA9IHN1cHByZXNzU29ydE9yZGVyID8gdW5kZWZpbmVkIDoge307XG4gICAgICAgIGlmIChfLmV4aXN0cyhyb3dEYXRhKSkge1xuICAgICAgICAgICAgLy8gc3BsaXQgYWxsIHRoZSBuZXcgZGF0YSBpbiB0aGUgZm9sbG93aW5nOlxuICAgICAgICAgICAgLy8gaWYgbmV3LCBwdXNoIHRvICdhZGQnXG4gICAgICAgICAgICAvLyBpZiB1cGRhdGUsIHB1c2ggdG8gJ3VwZGF0ZSdcbiAgICAgICAgICAgIC8vIGlmIG5vdCBjaGFuZ2VkLCBkbyBub3QgaW5jbHVkZSBpbiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgICAgICAgIHJvd0RhdGEuZm9yRWFjaChmdW5jdGlvbiAoZGF0YSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaWQgPSBnZXRSb3dJZEZ1bmMoeyBkYXRhOiBkYXRhLCBsZXZlbDogMCB9KTtcbiAgICAgICAgICAgICAgICB2YXIgZXhpc3RpbmdOb2RlID0gZXhpc3RpbmdOb2Rlc01hcFtpZF07XG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyTWFwKSB7XG4gICAgICAgICAgICAgICAgICAgIG9yZGVyTWFwW2lkXSA9IGluZGV4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RpbmdOb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhSGFzQ2hhbmdlZCA9IGV4aXN0aW5nTm9kZS5kYXRhICE9PSBkYXRhO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YUhhc0NoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uLnVwZGF0ZS5wdXNoKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIG90aGVyd2lzZSwgaWYgZGF0YSBub3QgY2hhbmdlZCwgd2UganVzdCBkb24ndCBpbmNsdWRlIGl0IGFueXdoZXJlLCBhcyBpdCdzIG5vdCBhIGRlbHRhXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBmcm9tIGxpc3QsIHNvIHdlIGtub3cgdGhlIGl0ZW0gaXMgbm90IHRvIGJlIHJlbW92ZWRcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdOb2Rlc01hcFtpZF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbi5hZGQucHVzaChkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBhdCB0aGlzIHBvaW50LCBhbGwgcm93cyB0aGF0IGFyZSBsZWZ0LCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAgICBfLml0ZXJhdGVPYmplY3QoZXhpc3RpbmdOb2Rlc01hcCwgZnVuY3Rpb24gKGlkLCByb3dOb2RlKSB7XG4gICAgICAgICAgICBpZiAocm93Tm9kZSkge1xuICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uLnJlbW92ZS5wdXNoKHJvd05vZGUuZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gW3RyYW5zYWN0aW9uLCBvcmRlck1hcF07XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd01vZGVsJylcbiAgICBdLCBJbW11dGFibGVTZXJ2aWNlLnByb3RvdHlwZSwgXCJyb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkNShbXG4gICAgICAgIEF1dG93aXJlZCgncm93UmVuZGVyZXInKVxuICAgIF0sIEltbXV0YWJsZVNlcnZpY2UucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQ1KFtcbiAgICAgICAgQXV0b3dpcmVkKCdjb2x1bW5BcGknKVxuICAgIF0sIEltbXV0YWJsZVNlcnZpY2UucHJvdG90eXBlLCBcImNvbHVtbkFwaVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkNShbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZEFwaScpXG4gICAgXSwgSW1tdXRhYmxlU2VydmljZS5wcm90b3R5cGUsIFwiZ3JpZEFwaVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkNShbXG4gICAgICAgIEF1dG93aXJlZCgnZmlsdGVyTWFuYWdlcicpXG4gICAgXSwgSW1tdXRhYmxlU2VydmljZS5wcm90b3R5cGUsIFwiZmlsdGVyTWFuYWdlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkNShbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBJbW11dGFibGVTZXJ2aWNlLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIEltbXV0YWJsZVNlcnZpY2UgPSBfX2RlY29yYXRlJDUoW1xuICAgICAgICBCZWFuKCdpbW11dGFibGVTZXJ2aWNlJylcbiAgICBdLCBJbW11dGFibGVTZXJ2aWNlKTtcbiAgICByZXR1cm4gSW1tdXRhYmxlU2VydmljZTtcbn0oQmVhblN0dWIpKTtcblxudmFyIENsaWVudFNpZGVSb3dNb2RlbE1vZHVsZSA9IHtcbiAgICBtb2R1bGVOYW1lOiBNb2R1bGVOYW1lcy5DbGllbnRTaWRlUm93TW9kZWxNb2R1bGUsXG4gICAgYmVhbnM6IFtGaWx0ZXJTdGFnZSwgU29ydFN0YWdlLCBGbGF0dGVuU3RhZ2UsIFNvcnRTZXJ2aWNlLCBGaWx0ZXJTZXJ2aWNlLCBJbW11dGFibGVTZXJ2aWNlXSxcbiAgICByb3dNb2RlbHM6IHsgY2xpZW50U2lkZTogQ2xpZW50U2lkZVJvd01vZGVsIH1cbn07XG5cbnZhciBfX2V4dGVuZHMkNSA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkNCA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEluZmluaXRlQmxvY2sgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDUoSW5maW5pdGVCbG9jaywgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBJbmZpbml0ZUJsb2NrKGlkLCBwYXJlbnRDYWNoZSwgcGFyYW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGlkKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wYXJlbnRDYWNoZSA9IHBhcmVudENhY2hlO1xuICAgICAgICBfdGhpcy5wYXJhbXMgPSBwYXJhbXM7XG4gICAgICAgIC8vIHdlIGRvbid0IG5lZWQgdG8gY2FsY3VsYXRlIHRoZXNlIG5vdywgYXMgdGhlIGlucHV0cyBkb24ndCBjaGFuZ2UsXG4gICAgICAgIC8vIGhvd2V2ZXIgaXQgbWFrZXMgdGhlIGNvZGUgZWFzaWVyIHRvIHJlYWQgaWYgd2Ugd29yayB0aGVtIG91dCB1cCBmcm9udFxuICAgICAgICBfdGhpcy5zdGFydFJvdyA9IGlkICogcGFyYW1zLmJsb2NrU2l6ZTtcbiAgICAgICAgX3RoaXMuZW5kUm93ID0gX3RoaXMuc3RhcnRSb3cgKyBwYXJhbXMuYmxvY2tTaXplO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEluZmluaXRlQmxvY2sucHJvdG90eXBlLnBvc3RDb25zdHJ1Y3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlUm93Tm9kZXMoKTtcbiAgICB9O1xuICAgIEluZmluaXRlQmxvY2sucHJvdG90eXBlLmdldEJsb2NrU3RhdGVKc29uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaWQ6ICcnICsgdGhpcy5nZXRJZCgpLFxuICAgICAgICAgICAgc3RhdGU6IHtcbiAgICAgICAgICAgICAgICBibG9ja051bWJlcjogdGhpcy5nZXRJZCgpLFxuICAgICAgICAgICAgICAgIHN0YXJ0Um93OiB0aGlzLmdldFN0YXJ0Um93KCksXG4gICAgICAgICAgICAgICAgZW5kUm93OiB0aGlzLmdldEVuZFJvdygpLFxuICAgICAgICAgICAgICAgIHBhZ2VTdGF0dXM6IHRoaXMuZ2V0U3RhdGUoKVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH07XG4gICAgSW5maW5pdGVCbG9jay5wcm90b3R5cGUuc2V0RGF0YUFuZElkID0gZnVuY3Rpb24gKHJvd05vZGUsIGRhdGEsIGluZGV4KSB7XG4gICAgICAgIC8vIGlmIHRoZXJlJ3Mgbm8gaWQgYW5kIHRoZSByb3dOb2RlIHdhcyByZW5kZXJlZCBiZWZvcmUsIGl0IG1lYW5zIHRoaXNcbiAgICAgICAgLy8gd2FzIGEgcGxhY2Vob2xkZXIgcm93Tm9kZSBhbmQgc2hvdWxkIG5vdCBiZSByZWN5Y2xlZC4gU2V0dGluZ1xuICAgICAgICAvLyBgYWxyZWFkeVJlbmRlcmVkYCAgdG8gYGZhbHNlYCBmb3JjZXMgdGhlIHJvd1JlbmRlcmVyIHRvIGZsdXNoIGl0LlxuICAgICAgICBpZiAoIXJvd05vZGUuaWQgJiYgcm93Tm9kZS5hbHJlYWR5UmVuZGVyZWQpIHtcbiAgICAgICAgICAgIHJvd05vZGUuYWxyZWFkeVJlbmRlcmVkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF8uZXhpc3RzKGRhdGEpKSB7XG4gICAgICAgICAgICAvLyB0aGlzIG1lYW5zIGlmIHRoZSB1c2VyIGlzIG5vdCBwcm92aWRpbmcgaWQncyB3ZSBqdXN0IHVzZSB0aGVcbiAgICAgICAgICAgIC8vIGluZGV4IGZvciB0aGUgcm93LiB0aGlzIHdpbGwgYWxsb3cgc2VsZWN0aW9uIHRvIHdvcmsgKHRoYXQgaXMgYmFzZWRcbiAgICAgICAgICAgIC8vIG9uIGluZGV4KSBhcyBsb25nIHVzZXIgaXMgbm90IGluc2VydGluZyBvciBkZWxldGluZyByb3dzLFxuICAgICAgICAgICAgLy8gb3Igd2FudGluZyB0byBrZWVwIHNlbGVjdGlvbiBiZXR3ZWVuIHNlcnZlciBzaWRlIHNvcnRpbmcgb3IgZmlsdGVyaW5nXG4gICAgICAgICAgICByb3dOb2RlLnNldERhdGFBbmRJZChkYXRhLCBpbmRleC50b1N0cmluZygpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJvd05vZGUuc2V0RGF0YUFuZElkKHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSW5maW5pdGVCbG9jay5wcm90b3R5cGUubG9hZEZyb21EYXRhc291cmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcGFyYW1zID0gdGhpcy5jcmVhdGVMb2FkUGFyYW1zKCk7XG4gICAgICAgIGlmIChfLm1pc3NpbmcodGhpcy5wYXJhbXMuZGF0YXNvdXJjZS5nZXRSb3dzKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQUcgR3JpZDogZGF0YXNvdXJjZSBpcyBtaXNzaW5nIGdldFJvd3MgbWV0aG9kXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIHB1dCBpbiB0aW1lb3V0LCB0byBmb3JjZSByZXN1bHQgdG8gYmUgYXN5bmNcbiAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMucGFyYW1zLmRhdGFzb3VyY2UuZ2V0Um93cyhwYXJhbXMpO1xuICAgICAgICB9LCAwKTtcbiAgICB9O1xuICAgIEluZmluaXRlQmxvY2sucHJvdG90eXBlLnByb2Nlc3NTZXJ2ZXJGYWlsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyB0b2RvIC0gdGhpcyBtZXRob2QgaGFzIGJldHRlciBoYW5kbGluZyBpbiBTU1JNXG4gICAgfTtcbiAgICBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZS5jcmVhdGVMb2FkUGFyYW1zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBQUk9CTEVNIC4gLiAuIC4gd2hlbiB0aGUgdXNlciBzZXRzIHNvcnQgdmlhIGNvbERlZi5zb3J0LCB0aGVuIHRoaXMgY29kZVxuICAgICAgICAvLyBpcyBleGVjdXRpbmcgYmVmb3JlIHRoZSBzb3J0IGlzIHNldCB1cCwgc28gc2VydmVyIGlzIG5vdCBnZXR0aW5nIHRoZSBzb3J0XG4gICAgICAgIC8vIG1vZGVsLiBuZWVkIHRvIGNoYW5nZSB3aXRoIHJlZ2FyZHMgb3JkZXIgLSBzbyB0aGUgc2VydmVyIHNpZGUgcmVxdWVzdCBpc1xuICAgICAgICAvLyBBRlRFUiB0aHVzIGl0IGdldHMgdGhlIHJpZ2h0IHNvcnQgbW9kZWwuXG4gICAgICAgIHZhciBwYXJhbXMgPSB7XG4gICAgICAgICAgICBzdGFydFJvdzogdGhpcy5nZXRTdGFydFJvdygpLFxuICAgICAgICAgICAgZW5kUm93OiB0aGlzLmdldEVuZFJvdygpLFxuICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrOiB0aGlzLnBhZ2VMb2FkZWQuYmluZCh0aGlzLCB0aGlzLmdldFZlcnNpb24oKSksXG4gICAgICAgICAgICBmYWlsQ2FsbGJhY2s6IHRoaXMucGFnZUxvYWRGYWlsZWQuYmluZCh0aGlzLCB0aGlzLmdldFZlcnNpb24oKSksXG4gICAgICAgICAgICBzb3J0TW9kZWw6IHRoaXMucGFyYW1zLnNvcnRNb2RlbCxcbiAgICAgICAgICAgIGZpbHRlck1vZGVsOiB0aGlzLnBhcmFtcy5maWx0ZXJNb2RlbCxcbiAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH07XG4gICAgSW5maW5pdGVCbG9jay5wcm90b3R5cGUuZm9yRWFjaE5vZGUgPSBmdW5jdGlvbiAoY2FsbGJhY2ssIHNlcXVlbmNlLCByb3dDb3VudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJvd05vZGVzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgcm93SW5kZXggPSBfdGhpcy5zdGFydFJvdyArIGluZGV4O1xuICAgICAgICAgICAgaWYgKHJvd0luZGV4IDwgcm93Q291bnQpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhyb3dOb2RlLCBzZXF1ZW5jZS5uZXh0KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEluZmluaXRlQmxvY2sucHJvdG90eXBlLmdldExhc3RBY2Nlc3NlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGFzdEFjY2Vzc2VkO1xuICAgIH07XG4gICAgSW5maW5pdGVCbG9jay5wcm90b3R5cGUuZ2V0Um93ID0gZnVuY3Rpb24gKHJvd0luZGV4LCBkb250VG91Y2hMYXN0QWNjZXNzZWQpIHtcbiAgICAgICAgaWYgKGRvbnRUb3VjaExhc3RBY2Nlc3NlZCA9PT0gdm9pZCAwKSB7IGRvbnRUb3VjaExhc3RBY2Nlc3NlZCA9IGZhbHNlOyB9XG4gICAgICAgIGlmICghZG9udFRvdWNoTGFzdEFjY2Vzc2VkKSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RBY2Nlc3NlZCA9IHRoaXMucGFyYW1zLmxhc3RBY2Nlc3NlZFNlcXVlbmNlLm5leHQoKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbG9jYWxJbmRleCA9IHJvd0luZGV4IC0gdGhpcy5zdGFydFJvdztcbiAgICAgICAgcmV0dXJuIHRoaXMucm93Tm9kZXNbbG9jYWxJbmRleF07XG4gICAgfTtcbiAgICBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZS5nZXRTdGFydFJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhcnRSb3c7XG4gICAgfTtcbiAgICBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZS5nZXRFbmRSb3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVuZFJvdztcbiAgICB9O1xuICAgIC8vIGNyZWF0ZXMgZW1wdHkgcm93IG5vZGVzLCBkYXRhIGlzIG1pc3NpbmcgYXMgbm90IGxvYWRlZCB5ZXRcbiAgICBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZS5jcmVhdGVSb3dOb2RlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5yb3dOb2RlcyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFyYW1zLmJsb2NrU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcm93SW5kZXggPSB0aGlzLnN0YXJ0Um93ICsgaTtcbiAgICAgICAgICAgIHZhciByb3dOb2RlID0gbmV3IFJvd05vZGUodGhpcy5iZWFucyk7XG4gICAgICAgICAgICByb3dOb2RlLnNldFJvd0hlaWdodCh0aGlzLnBhcmFtcy5yb3dIZWlnaHQpO1xuICAgICAgICAgICAgcm93Tm9kZS51aUxldmVsID0gMDtcbiAgICAgICAgICAgIHJvd05vZGUuc2V0Um93SW5kZXgocm93SW5kZXgpO1xuICAgICAgICAgICAgcm93Tm9kZS5zZXRSb3dUb3AodGhpcy5wYXJhbXMucm93SGVpZ2h0ICogcm93SW5kZXgpO1xuICAgICAgICAgICAgdGhpcy5yb3dOb2Rlcy5wdXNoKHJvd05vZGUpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZS5wcm9jZXNzU2VydmVyUmVzdWx0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJvd05vZGVzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgZGF0YSA9IHBhcmFtcy5yb3dEYXRhID8gcGFyYW1zLnJvd0RhdGFbaW5kZXhdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgX3RoaXMuc2V0RGF0YUFuZElkKHJvd05vZGUsIGRhdGEsIF90aGlzLnN0YXJ0Um93ICsgaW5kZXgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGZpbmFsUm93Q291bnQgPSBwYXJhbXMucm93Q291bnQgIT0gbnVsbCAmJiBwYXJhbXMucm93Q291bnQgPj0gMCA/IHBhcmFtcy5yb3dDb3VudCA6IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5wYXJlbnRDYWNoZS5wYWdlTG9hZGVkKHRoaXMsIGZpbmFsUm93Q291bnQpO1xuICAgIH07XG4gICAgSW5maW5pdGVCbG9jay5wcm90b3R5cGUuZGVzdHJveVJvd05vZGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJvd05vZGVzLmZvckVhY2goZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgbmVlZGVkLCBzbyByb3cgcmVuZGVyIGtub3dzIHRvIGZhZGUgb3V0IHRoZSByb3csIG90aGVyd2lzZSBpdFxuICAgICAgICAgICAgLy8gc2VlcyByb3cgdG9wIGlzIHByZXNlbnQsIGFuZCB0aGlua3MgdGhlIHJvdyBzaG91bGQgYmUgc2hvd24uXG4gICAgICAgICAgICByb3dOb2RlLmNsZWFyUm93VG9wQW5kUm93SW5kZXgoKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDQoW1xuICAgICAgICBBdXRvd2lyZWQoJ2JlYW5zJylcbiAgICBdLCBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZSwgXCJiZWFuc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkNChbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZSwgXCJwb3N0Q29uc3RydWN0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkNChbXG4gICAgICAgIFByZURlc3Ryb3lcbiAgICBdLCBJbmZpbml0ZUJsb2NrLnByb3RvdHlwZSwgXCJkZXN0cm95Um93Tm9kZXNcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEluZmluaXRlQmxvY2s7XG59KFJvd05vZGVCbG9jaykpO1xuXG52YXIgX19leHRlbmRzJDQgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlJDMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbnZhciBfX3BhcmFtID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19wYXJhbSkgfHwgZnVuY3Rpb24gKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxufTtcbnZhciBJbmZpbml0ZUNhY2hlID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyQ0KEluZmluaXRlQ2FjaGUsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gSW5maW5pdGVDYWNoZShwYXJhbXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAgICAgX3RoaXMubGFzdFJvd0luZGV4S25vd24gPSBmYWxzZTtcbiAgICAgICAgX3RoaXMuYmxvY2tzID0ge307XG4gICAgICAgIF90aGlzLmJsb2NrQ291bnQgPSAwO1xuICAgICAgICBfdGhpcy5yb3dDb3VudCA9IHBhcmFtcy5pbml0aWFsUm93Q291bnQ7XG4gICAgICAgIF90aGlzLnBhcmFtcyA9IHBhcmFtcztcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBJbmZpbml0ZUNhY2hlLnByb3RvdHlwZS5zZXRCZWFucyA9IGZ1bmN0aW9uIChsb2dnZXJGYWN0b3J5KSB7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyRmFjdG9yeS5jcmVhdGUoJ0luZmluaXRlQ2FjaGUnKTtcbiAgICB9O1xuICAgIC8vIHRoZSByb3dSZW5kZXJlciB3aWxsIG5vdCBwYXNzIGRvbnRDcmVhdGVQYWdlLCBtZWFuaW5nIHdoZW4gcmVuZGVyaW5nIHRoZSBncmlkLFxuICAgIC8vIGl0IHdpbGwgd2FudCBuZXcgcGFnZXMgaW4gdGhlIGNhY2hlIGFzIGl0IGFza3MgZm9yIHJvd3MuIG9ubHkgd2hlbiB3ZSBhcmUgaW5zZXJ0aW5nIC9cbiAgICAvLyByZW1vdmluZyByb3dzIHZpYSB0aGUgYXBpIGlzIGRvbnRDcmVhdGVQYWdlIHNldCwgd2hlcmUgd2UgbW92ZSByb3dzIGJldHdlZW4gdGhlIHBhZ2VzLlxuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmdldFJvdyA9IGZ1bmN0aW9uIChyb3dJbmRleCwgZG9udENyZWF0ZVBhZ2UpIHtcbiAgICAgICAgaWYgKGRvbnRDcmVhdGVQYWdlID09PSB2b2lkIDApIHsgZG9udENyZWF0ZVBhZ2UgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgYmxvY2tJZCA9IE1hdGguZmxvb3Iocm93SW5kZXggLyB0aGlzLnBhcmFtcy5ibG9ja1NpemUpO1xuICAgICAgICB2YXIgYmxvY2sgPSB0aGlzLmJsb2Nrc1tibG9ja0lkXTtcbiAgICAgICAgaWYgKCFibG9jaykge1xuICAgICAgICAgICAgaWYgKGRvbnRDcmVhdGVQYWdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJsb2NrID0gdGhpcy5jcmVhdGVCbG9jayhibG9ja0lkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYmxvY2suZ2V0Um93KHJvd0luZGV4KTtcbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmNyZWF0ZUJsb2NrID0gZnVuY3Rpb24gKGJsb2NrTnVtYmVyKSB7XG4gICAgICAgIHZhciBuZXdCbG9jayA9IHRoaXMuY3JlYXRlQmVhbihuZXcgSW5maW5pdGVCbG9jayhibG9ja051bWJlciwgdGhpcywgdGhpcy5wYXJhbXMpKTtcbiAgICAgICAgdGhpcy5ibG9ja3NbbmV3QmxvY2suZ2V0SWQoKV0gPSBuZXdCbG9jaztcbiAgICAgICAgdGhpcy5ibG9ja0NvdW50Kys7XG4gICAgICAgIHRoaXMucHVyZ2VCbG9ja3NJZk5lZWRlZChuZXdCbG9jayk7XG4gICAgICAgIHRoaXMucGFyYW1zLnJvd05vZGVCbG9ja0xvYWRlci5hZGRCbG9jayhuZXdCbG9jayk7XG4gICAgICAgIHJldHVybiBuZXdCbG9jaztcbiAgICB9O1xuICAgIC8vIHdlIGhhdmUgdGhpcyBvbiBpbmZpbml0ZSByb3cgbW9kZWwgb25seSwgbm90IHNlcnZlciBzaWRlIHJvdyBtb2RlbCxcbiAgICAvLyBiZWNhdXNlIGZvciBzZXJ2ZXIgc2lkZSwgaXQgd291bGQgbGVhdmUgdGhlIGNoaWxkcmVuIGluIGluY29uc2lzdGVudFxuICAgIC8vIHN0YXRlIC0gZWcgaWYgYSBub2RlIGhhZCBjaGlsZHJlbiwgYnV0IGFmdGVyIHRoZSByZWZyZXNoIGl0IGhhZCBkYXRhXG4gICAgLy8gZm9yIGEgZGlmZmVyZW50IHJvdywgdGhlbiB0aGUgY2hpbGRyZW4gd291bGQgYmUgd2l0aCB0aGUgd3Jvbmcgcm93IG5vZGUuXG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUucmVmcmVzaENhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbm90aGluZ1RvUmVmcmVzaCA9IHRoaXMuYmxvY2tDb3VudCA9PSAwO1xuICAgICAgICBpZiAobm90aGluZ1RvUmVmcmVzaCkge1xuICAgICAgICAgICAgdGhpcy5wdXJnZUNhY2hlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5nZXRCbG9ja3NJbk9yZGVyKCkuZm9yRWFjaChmdW5jdGlvbiAoYmxvY2spIHsgcmV0dXJuIGJsb2NrLnNldFN0YXRlV2FpdGluZ1RvTG9hZCgpOyB9KTtcbiAgICAgICAgdGhpcy5wYXJhbXMucm93Tm9kZUJsb2NrTG9hZGVyLmNoZWNrQmxvY2tUb0xvYWQoKTtcbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmRlc3Ryb3lBbGxCbG9ja3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuZ2V0QmxvY2tzSW5PcmRlcigpLmZvckVhY2goZnVuY3Rpb24gKGJsb2NrKSB7IHJldHVybiBfdGhpcy5kZXN0cm95QmxvY2soYmxvY2spOyB9KTtcbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmdldFJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yb3dDb3VudDtcbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmlzTGFzdFJvd0luZGV4S25vd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxhc3RSb3dJbmRleEtub3duO1xuICAgIH07XG4gICAgLy8gYmxvY2sgY2FsbHMgdGhpcywgd2hlbiBwYWdlIGxvYWRlZFxuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLnBhZ2VMb2FkZWQgPSBmdW5jdGlvbiAoYmxvY2ssIGxhc3RSb3cpIHtcbiAgICAgICAgLy8gaWYgd2UgYXJlIG5vdCBhY3RpdmUsIHRoZW4gd2UgaWdub3JlIGFsbCBldmVudHMsIG90aGVyd2lzZSB3ZSBjb3VsZCBlbmQgdXAgZ2V0dGluZyB0aGVcbiAgICAgICAgLy8gZ3JpZCB0byByZWZyZXNoIGV2ZW4gdGhvdWdoIHdlIGFyZSBubyBsb25nZXIgdGhlIGFjdGl2ZSBjYWNoZVxuICAgICAgICBpZiAoIXRoaXMuaXNBbGl2ZSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwib25QYWdlTG9hZGVkOiBwYWdlID0gXCIgKyBibG9jay5nZXRJZCgpICsgXCIsIGxhc3RSb3cgPSBcIiArIGxhc3RSb3cpO1xuICAgICAgICB0aGlzLmNoZWNrUm93Q291bnQoYmxvY2ssIGxhc3RSb3cpO1xuICAgICAgICAvLyB3ZSBmaXJlIGNhY2hlVXBkYXRlZCBldmVuIGlmIHRoZSByb3cgY291bnQgaGFzIG5vdCBjaGFuZ2VkLCBhcyBzb21lIGl0ZW1zIG5lZWQgdXBkYXRpbmcgZXZlblxuICAgICAgICAvLyBpZiBubyBuZXcgcm93cyB0byByZW5kZXIuIGZvciBleGFtcGxlIHRoZSBwYWdpbmF0aW9uIHBhbmVsIGhhcyAnPycgYXMgdGhlIHRvdGFsIHJvd3Mgd2hlbiBsb2FkaW5nXG4gICAgICAgIC8vIGlzIHVuZGVyd2F5LCB3aGljaCB3b3VsZCBuZWVkIHRvIGdldCB1cGRhdGVkIHdoZW4gbG9hZGluZyBmaW5pc2hlcy5cbiAgICAgICAgdGhpcy5vbkNhY2hlVXBkYXRlZCgpO1xuICAgIH07XG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUucHVyZ2VCbG9ja3NJZk5lZWRlZCA9IGZ1bmN0aW9uIChibG9ja1RvRXhjbHVkZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAvLyB3ZSBleGNsdWRlIGNoZWNraW5nIGZvciB0aGUgcGFnZSBqdXN0IGNyZWF0ZWQsIGFzIHRoaXMgaGFzIHlldCB0byBiZSBhY2Nlc3NlZCBhbmQgaGVuY2VcbiAgICAgICAgLy8gdGhlIGxhc3RBY2Nlc3NlZCBzdGFtcCB3aWxsIG5vdCBiZSB1cGRhdGVkIGZvciB0aGUgZmlyc3QgdGltZSB5ZXRcbiAgICAgICAgdmFyIGJsb2Nrc0ZvclB1cmdpbmcgPSB0aGlzLmdldEJsb2Nrc0luT3JkZXIoKS5maWx0ZXIoZnVuY3Rpb24gKGIpIHsgcmV0dXJuIGIgIT0gYmxvY2tUb0V4Y2x1ZGU7IH0pO1xuICAgICAgICB2YXIgbGFzdEFjY2Vzc2VkQ29tcGFyYXRvciA9IGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBiLmdldExhc3RBY2Nlc3NlZCgpIC0gYS5nZXRMYXN0QWNjZXNzZWQoKTsgfTtcbiAgICAgICAgYmxvY2tzRm9yUHVyZ2luZy5zb3J0KGxhc3RBY2Nlc3NlZENvbXBhcmF0b3IpO1xuICAgICAgICAvLyB3ZSByZW1vdmUgKG1heEJsb2Nrc0luQ2FjaGUgLSAxKSBhcyB3ZSBhbHJlYWR5IGV4Y2x1ZGVkIHRoZSAnanVzdCBjcmVhdGVkJyBwYWdlLlxuICAgICAgICAvLyBpbiBvdGhlciB3b3JkcywgYWZ0ZXIgdGhlIHNwbGljZSBvcGVyYXRpb24gYmVsb3csIHdlIGhhdmUgdGFrZW4gb3V0IHRoZSBibG9ja3NcbiAgICAgICAgLy8gd2Ugd2FudCB0byBrZWVwLCB3aGljaCBtZWFucyB3ZSBhcmUgbGVmdCB3aXRoIGJsb2NrcyB0aGF0IHdlIGNhbiBwb3RlbnRpYWxseSBwdXJnZVxuICAgICAgICB2YXIgbWF4QmxvY2tzUHJvdmlkZWQgPSB0aGlzLnBhcmFtcy5tYXhCbG9ja3NJbkNhY2hlID4gMDtcbiAgICAgICAgdmFyIGJsb2Nrc1RvS2VlcCA9IG1heEJsb2Nrc1Byb3ZpZGVkID8gdGhpcy5wYXJhbXMubWF4QmxvY2tzSW5DYWNoZSAtIDEgOiBudWxsO1xuICAgICAgICB2YXIgZW1wdHlCbG9ja3NUb0tlZXAgPSBJbmZpbml0ZUNhY2hlLk1BWF9FTVBUWV9CTE9DS1NfVE9fS0VFUCAtIDE7XG4gICAgICAgIGJsb2Nrc0ZvclB1cmdpbmcuZm9yRWFjaChmdW5jdGlvbiAoYmxvY2ssIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgcHVyZ2VCZWNhdXNlQmxvY2tFbXB0eSA9IGJsb2NrLmdldFN0YXRlKCkgPT09IEluZmluaXRlQmxvY2suU1RBVEVfV0FJVElOR19UT19MT0FEICYmIGluZGV4ID49IGVtcHR5QmxvY2tzVG9LZWVwO1xuICAgICAgICAgICAgdmFyIHB1cmdlQmVjYXVzZUNhY2hlRnVsbCA9IG1heEJsb2Nrc1Byb3ZpZGVkID8gaW5kZXggPj0gYmxvY2tzVG9LZWVwIDogZmFsc2U7XG4gICAgICAgICAgICBpZiAocHVyZ2VCZWNhdXNlQmxvY2tFbXB0eSB8fCBwdXJnZUJlY2F1c2VDYWNoZUZ1bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgYmxvY2sgY3VycmVudGx5IGhhcyByb3dzIGJlZW4gZGlzcGxheWVkLCB0aGVuIGRvbid0IHJlbW92ZSBpdCBlaXRoZXIuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBjYW4gaGFwcGVuIGlmIHVzZXIgaGFzIG1heEJsb2Nrcz0yLCBhbmQgYmxvY2tTaXplPTUgKHRodXMgMTAgbWF4IHJvd3MgaW4gY2FjaGUpXG4gICAgICAgICAgICAgICAgLy8gYnV0IHRoZSBzY3JlZW4gaXMgc2hvd2luZyAyMCByb3dzLCBzbyBhdCBsZWFzdCA0IGJsb2NrcyBhcmUgbmVlZGVkLlxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Jsb2NrQ3VycmVudGx5RGlzcGxheWVkKGJsb2NrKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGRvbid0IHdhbnQgdG8gbG9vc2Uga2V5Ym9hcmQgZm9jdXMsIHNvIGtleWJvYXJkIG5hdmlnYXRpb24gY2FuIGNvbnRpbnVlLiBzbyBrZWVwIGZvY3VzZWQgYmxvY2tzLlxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5pc0Jsb2NrRm9jdXNlZChibG9jaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBhdCB0aGlzIHBvaW50LCBibG9jayBpcyBub3QgbmVlZGVkLCBzbyBidXJuIGJhYnkgYnVyblxuICAgICAgICAgICAgICAgIF90aGlzLnJlbW92ZUJsb2NrRnJvbUNhY2hlKGJsb2NrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBJbmZpbml0ZUNhY2hlLnByb3RvdHlwZS5pc0Jsb2NrRm9jdXNlZCA9IGZ1bmN0aW9uIChibG9jaykge1xuICAgICAgICB2YXIgZm9jdXNlZENlbGwgPSB0aGlzLmZvY3VzU2VydmljZS5nZXRGb2N1c0NlbGxUb1VzZUFmdGVyUmVmcmVzaCgpO1xuICAgICAgICBpZiAoIWZvY3VzZWRDZWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvY3VzZWRDZWxsLnJvd1Bpbm5lZCAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJsb2NrSW5kZXhTdGFydCA9IGJsb2NrLmdldFN0YXJ0Um93KCk7XG4gICAgICAgIHZhciBibG9ja0luZGV4RW5kID0gYmxvY2suZ2V0RW5kUm93KCk7XG4gICAgICAgIHZhciBoYXNGb2N1cyA9IGZvY3VzZWRDZWxsLnJvd0luZGV4ID49IGJsb2NrSW5kZXhTdGFydCAmJiBmb2N1c2VkQ2VsbC5yb3dJbmRleCA8IGJsb2NrSW5kZXhFbmQ7XG4gICAgICAgIHJldHVybiBoYXNGb2N1cztcbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmlzQmxvY2tDdXJyZW50bHlEaXNwbGF5ZWQgPSBmdW5jdGlvbiAoYmxvY2spIHtcbiAgICAgICAgdmFyIHN0YXJ0SW5kZXggPSBibG9jay5nZXRTdGFydFJvdygpO1xuICAgICAgICB2YXIgZW5kSW5kZXggPSBibG9jay5nZXRFbmRSb3coKSAtIDE7XG4gICAgICAgIHJldHVybiB0aGlzLnJvd1JlbmRlcmVyLmlzUmFuZ2VJblJlbmRlcmVkVmlld3BvcnQoc3RhcnRJbmRleCwgZW5kSW5kZXgpO1xuICAgIH07XG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUucmVtb3ZlQmxvY2tGcm9tQ2FjaGUgPSBmdW5jdGlvbiAoYmxvY2tUb1JlbW92ZSkge1xuICAgICAgICBpZiAoIWJsb2NrVG9SZW1vdmUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlc3Ryb3lCbG9jayhibG9ja1RvUmVtb3ZlKTtcbiAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gcmVtb3ZlIHRoZSAnbG9hZGVkJyBldmVudCBsaXN0ZW5lciwgYXMgdGhlXG4gICAgICAgIC8vIGNvbmN1cnJlbnQgbG9hZHMgY291bnQgbmVlZHMgdG8gYmUgdXBkYXRlZCB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlXG4gICAgICAgIC8vIGlmIHRoZSBwdXJnZWQgcGFnZSBpcyBpbiBsb2FkaW5nIHN0YXRlXG4gICAgfTtcbiAgICBJbmZpbml0ZUNhY2hlLnByb3RvdHlwZS5jaGVja1Jvd0NvdW50ID0gZnVuY3Rpb24gKGJsb2NrLCBsYXN0Um93KSB7XG4gICAgICAgIC8vIGlmIGNsaWVudCBwcm92aWRlZCBhIGxhc3Qgcm93LCB3ZSBhbHdheXMgdXNlIGl0LCBhcyBpdCBjb3VsZCBjaGFuZ2UgYmV0d2VlbiBzZXJ2ZXIgY2FsbHNcbiAgICAgICAgLy8gaWYgdXNlciBkZWxldGVkIGRhdGEgYW5kIHRoZW4gY2FsbGVkIHJlZnJlc2ggb24gdGhlIGdyaWQuXG4gICAgICAgIGlmICh0eXBlb2YgbGFzdFJvdyA9PT0gJ251bWJlcicgJiYgbGFzdFJvdyA+PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnJvd0NvdW50ID0gbGFzdFJvdztcbiAgICAgICAgICAgIHRoaXMubGFzdFJvd0luZGV4S25vd24gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCF0aGlzLmxhc3RSb3dJbmRleEtub3duKSB7XG4gICAgICAgICAgICAvLyBvdGhlcndpc2UsIHNlZSBpZiB3ZSBuZWVkIHRvIGFkZCBzb21lIHZpcnR1YWwgcm93c1xuICAgICAgICAgICAgdmFyIGxhc3RSb3dJbmRleCA9IChibG9jay5nZXRJZCgpICsgMSkgKiB0aGlzLnBhcmFtcy5ibG9ja1NpemU7XG4gICAgICAgICAgICB2YXIgbGFzdFJvd0luZGV4UGx1c092ZXJmbG93ID0gbGFzdFJvd0luZGV4ICsgdGhpcy5wYXJhbXMub3ZlcmZsb3dTaXplO1xuICAgICAgICAgICAgaWYgKHRoaXMucm93Q291bnQgPCBsYXN0Um93SW5kZXhQbHVzT3ZlcmZsb3cpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvd0NvdW50ID0gbGFzdFJvd0luZGV4UGx1c092ZXJmbG93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBJbmZpbml0ZUNhY2hlLnByb3RvdHlwZS5zZXRSb3dDb3VudCA9IGZ1bmN0aW9uIChyb3dDb3VudCwgbGFzdFJvd0luZGV4S25vd24pIHtcbiAgICAgICAgdGhpcy5yb3dDb3VudCA9IHJvd0NvdW50O1xuICAgICAgICAvLyBpZiB1bmRlZmluZWQgaXMgcGFzc2VkLCB3ZSBkbyBub3Qgc2V0IHRoaXMgdmFsdWUsIGlmIG9uZSBvZiB7dHJ1ZSxmYWxzZX1cbiAgICAgICAgLy8gaXMgcGFzc2VkLCB3ZSBkbyBzZXQgdGhlIHZhbHVlLlxuICAgICAgICBpZiAoXy5leGlzdHMobGFzdFJvd0luZGV4S25vd24pKSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RSb3dJbmRleEtub3duID0gbGFzdFJvd0luZGV4S25vd247XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgd2UgYXJlIHN0aWxsIHNlYXJjaGluZywgdGhlbiB0aGUgcm93IGNvdW50IG11c3Qgbm90IGVuZCBhdCB0aGUgZW5kXG4gICAgICAgIC8vIG9mIGEgcGFydGljdWxhciBwYWdlLCBvdGhlcndpc2UgdGhlIHNlYXJjaGluZyB3aWxsIG5vdCBwb3AgaW50byB0aGVcbiAgICAgICAgLy8gbmV4dCBwYWdlXG4gICAgICAgIGlmICghdGhpcy5sYXN0Um93SW5kZXhLbm93bikge1xuICAgICAgICAgICAgaWYgKHRoaXMucm93Q291bnQgJSB0aGlzLnBhcmFtcy5ibG9ja1NpemUgPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvd0NvdW50Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbkNhY2hlVXBkYXRlZCgpO1xuICAgIH07XG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUuZm9yRWFjaE5vZGVEZWVwID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBzZXF1ZW5jZSA9IG5ldyBOdW1iZXJTZXF1ZW5jZSgpO1xuICAgICAgICB0aGlzLmdldEJsb2Nrc0luT3JkZXIoKS5mb3JFYWNoKGZ1bmN0aW9uIChibG9jaykgeyByZXR1cm4gYmxvY2suZm9yRWFjaE5vZGUoY2FsbGJhY2ssIHNlcXVlbmNlLCBfdGhpcy5yb3dDb3VudCk7IH0pO1xuICAgIH07XG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUuZ2V0QmxvY2tzSW5PcmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gZ2V0IGFsbCBwYWdlIGlkJ3MgYXMgTlVNQkVSUyAobm90IHN0cmluZ3MsIGFzIHdlIG5lZWQgdG8gc29ydCBhcyBudW1iZXJzKSBhbmQgaW4gZGVzY2VuZGluZyBvcmRlclxuICAgICAgICB2YXIgYmxvY2tDb21wYXJhdG9yID0gZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEuZ2V0SWQoKSAtIGIuZ2V0SWQoKTsgfTtcbiAgICAgICAgdmFyIGJsb2NrcyA9IF8uZ2V0QWxsVmFsdWVzSW5PYmplY3QodGhpcy5ibG9ja3MpLnNvcnQoYmxvY2tDb21wYXJhdG9yKTtcbiAgICAgICAgcmV0dXJuIGJsb2NrcztcbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmRlc3Ryb3lCbG9jayA9IGZ1bmN0aW9uIChibG9jaykge1xuICAgICAgICBkZWxldGUgdGhpcy5ibG9ja3NbYmxvY2suZ2V0SWQoKV07XG4gICAgICAgIHRoaXMuZGVzdHJveUJlYW4oYmxvY2spO1xuICAgICAgICB0aGlzLmJsb2NrQ291bnQtLTtcbiAgICAgICAgdGhpcy5wYXJhbXMucm93Tm9kZUJsb2NrTG9hZGVyLnJlbW92ZUJsb2NrKGJsb2NrKTtcbiAgICB9O1xuICAgIC8vIGdldHMgY2FsbGVkIDEpIHJvdyBjb3VudCBjaGFuZ2VkIDIpIGNhY2hlIHB1cmdlZCAzKSBpdGVtcyBpbnNlcnRlZFxuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLm9uQ2FjaGVVcGRhdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc0FsaXZlKCkpIHtcbiAgICAgICAgICAgIC8vIGlmIHRoZSB2aXJ0dWFsUm93Q291bnQgaXMgc2hvcnRlbmVkLCB0aGVuIGl0J3MgcG9zc2libGUgYmxvY2tzIGV4aXN0IHRoYXQgYXJlIG5vIGxvbmdlclxuICAgICAgICAgICAgLy8gaW4gdGhlIHZhbGlkIHJhbmdlLiBzbyB3ZSBtdXN0IHJlbW92ZSB0aGVzZS4gdGhpcyBjYW4gaGFwcGVuIGlmIHVzZXIgZXhwbGljaXRseSBzZXRzXG4gICAgICAgICAgICAvLyB0aGUgdmlydHVhbCByb3cgY291bnQsIG9yIHRoZSBkYXRhc291cmNlIHJldHVybnMgYSByZXN1bHQgYW5kIHNldHMgbGFzdFJvdyB0byBzb21ldGhpbmdcbiAgICAgICAgICAgIC8vIGxlc3MgdGhhbiB2aXJ0dWFsUm93Q291bnQgKGNhbiBoYXBwZW4gaWYgdXNlciBzY3JvbGxzIGRvd24sIHNlcnZlciByZWR1Y2VzIGRhdGFzZXQgc2l6ZSkuXG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3lBbGxCbG9ja3NQYXN0VmlydHVhbFJvd0NvdW50KCk7XG4gICAgICAgICAgICAvLyB0aGlzIHJlc3VsdHMgaW4gYm90aCByb3cgbW9kZWxzIChpbmZpbml0ZSBhbmQgc2VydmVyIHNpZGUpIGZpcmluZyBNb2RlbFVwZGF0ZWQsXG4gICAgICAgICAgICAvLyBob3dldmVyIHNlcnZlciBzaWRlIHJvdyBtb2RlbCBhbHNvIHVwZGF0ZXMgdGhlIHJvdyBpbmRleGVzIGZpcnN0XG4gICAgICAgICAgICB2YXIgZXZlbnRfMSA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfU1RPUkVfVVBEQVRFRFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnRfMSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLmRlc3Ryb3lBbGxCbG9ja3NQYXN0VmlydHVhbFJvd0NvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgYmxvY2tzVG9EZXN0cm95ID0gW107XG4gICAgICAgIHRoaXMuZ2V0QmxvY2tzSW5PcmRlcigpLmZvckVhY2goZnVuY3Rpb24gKGJsb2NrKSB7XG4gICAgICAgICAgICB2YXIgc3RhcnRSb3cgPSBibG9jay5nZXRJZCgpICogX3RoaXMucGFyYW1zLmJsb2NrU2l6ZTtcbiAgICAgICAgICAgIGlmIChzdGFydFJvdyA+PSBfdGhpcy5yb3dDb3VudCkge1xuICAgICAgICAgICAgICAgIGJsb2Nrc1RvRGVzdHJveS5wdXNoKGJsb2NrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChibG9ja3NUb0Rlc3Ryb3kubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgYmxvY2tzVG9EZXN0cm95LmZvckVhY2goZnVuY3Rpb24gKGJsb2NrKSB7IHJldHVybiBfdGhpcy5kZXN0cm95QmxvY2soYmxvY2spOyB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUucHVyZ2VDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5nZXRCbG9ja3NJbk9yZGVyKCkuZm9yRWFjaChmdW5jdGlvbiAoYmxvY2spIHsgcmV0dXJuIF90aGlzLnJlbW92ZUJsb2NrRnJvbUNhY2hlKGJsb2NrKTsgfSk7XG4gICAgICAgIHRoaXMubGFzdFJvd0luZGV4S25vd24gPSBmYWxzZTtcbiAgICAgICAgLy8gaWYgemVybyByb3dzIGluIHRoZSBjYWNoZSwgd2UgbmVlZCB0byBnZXQgdGhlIFNTUk0gdG8gc3RhcnQgYXNraW5nIGZvciByb3dzIGFnYWluLlxuICAgICAgICAvLyBvdGhlcndpc2UgaWYgc2V0IHRvIHplcm8gcm93cyBsYXN0IHRpbWUsIGFuZCB3ZSBkb24ndCB1cGRhdGUgdGhlIHJvdyBjb3VudCwgdGhlbiBhZnRlclxuICAgICAgICAvLyB0aGUgcHVyZ2UgdGhlcmUgd2lsbCBzdGlsbCBiZSB6ZXJvIHJvd3MsIG1lYW5pbmcgdGhlIFNTUk0gd29uJ3QgcmVxdWVzdCBhbnkgcm93cy5cbiAgICAgICAgLy8gdG8ga2ljayB0aGluZ3Mgb2ZmLCBhdCBsZWFzdCBvbmUgcm93IG5lZWRzIHRvIGJlIGFza2VkIGZvci5cbiAgICAgICAgaWYgKHRoaXMucm93Q291bnQgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMucm93Q291bnQgPSB0aGlzLnBhcmFtcy5pbml0aWFsUm93Q291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbkNhY2hlVXBkYXRlZCgpO1xuICAgIH07XG4gICAgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUuZ2V0Um93Tm9kZXNJblJhbmdlID0gZnVuY3Rpb24gKGZpcnN0SW5SYW5nZSwgbGFzdEluUmFuZ2UpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIgbGFzdEJsb2NrSWQgPSAtMTtcbiAgICAgICAgdmFyIGluQWN0aXZlUmFuZ2UgPSBmYWxzZTtcbiAgICAgICAgdmFyIG51bWJlclNlcXVlbmNlID0gbmV3IE51bWJlclNlcXVlbmNlKCk7XG4gICAgICAgIC8vIGlmIG9ubHkgb25lIG5vZGUgcGFzc2VkLCB3ZSBzdGFydCB0aGUgc2VsZWN0aW9uIGF0IHRoZSB0b3BcbiAgICAgICAgaWYgKF8ubWlzc2luZyhmaXJzdEluUmFuZ2UpKSB7XG4gICAgICAgICAgICBpbkFjdGl2ZVJhbmdlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZm91bmRHYXBJblNlbGVjdGlvbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLmdldEJsb2Nrc0luT3JkZXIoKS5mb3JFYWNoKGZ1bmN0aW9uIChibG9jaykge1xuICAgICAgICAgICAgaWYgKGZvdW5kR2FwSW5TZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5BY3RpdmVSYW5nZSAmJiAobGFzdEJsb2NrSWQgKyAxICE9PSBibG9jay5nZXRJZCgpKSkge1xuICAgICAgICAgICAgICAgIGZvdW5kR2FwSW5TZWxlY3Rpb24gPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxhc3RCbG9ja0lkID0gYmxvY2suZ2V0SWQoKTtcbiAgICAgICAgICAgIGJsb2NrLmZvckVhY2hOb2RlKGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhpdEZpcnN0T3JMYXN0ID0gcm93Tm9kZSA9PT0gZmlyc3RJblJhbmdlIHx8IHJvd05vZGUgPT09IGxhc3RJblJhbmdlO1xuICAgICAgICAgICAgICAgIGlmIChpbkFjdGl2ZVJhbmdlIHx8IGhpdEZpcnN0T3JMYXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHJvd05vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaGl0Rmlyc3RPckxhc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5BY3RpdmVSYW5nZSA9ICFpbkFjdGl2ZVJhbmdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIG51bWJlclNlcXVlbmNlLCBfdGhpcy5yb3dDb3VudCk7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBpbkFjdGl2ZVJhbmdlIHdpbGwgYmUgc3RpbGwgdHJ1ZSBpZiB3ZSBuZXZlciBoaXQgdGhlIHNlY29uZCByb3dOb2RlXG4gICAgICAgIHZhciBpbnZhbGlkUmFuZ2UgPSBmb3VuZEdhcEluU2VsZWN0aW9uIHx8IGluQWN0aXZlUmFuZ2U7XG4gICAgICAgIHJldHVybiBpbnZhbGlkUmFuZ2UgPyBbXSA6IHJlc3VsdDtcbiAgICB9O1xuICAgIC8vIHRoaXMgcHJvcGVydHkgc2F5cyBob3cgbWFueSBlbXB0eSBibG9ja3Mgc2hvdWxkIGJlIGluIGEgY2FjaGUsIGVnIGlmIHNjcm9sbHMgZG93biBmYXN0IGFuZCBjcmVhdGVzIDEwXG4gICAgLy8gYmxvY2tzIGFsbCBmb3IgbG9hZGluZywgdGhlIGdyaWQgd2lsbCBvbmx5IGxvYWQgdGhlIGxhc3QgMiAtIGl0IHdpbGwgYXNzdW1lIHRoZSBibG9ja3MgdGhlIHVzZXIgcXVpY2tseVxuICAgIC8vIHNjcm9sbGVkIG92ZXIgYXJlIG5vdCBuZWVkZWQgdG8gYmUgbG9hZGVkLlxuICAgIEluZmluaXRlQ2FjaGUuTUFYX0VNUFRZX0JMT0NLU19UT19LRUVQID0gMjtcbiAgICBfX2RlY29yYXRlJDMoW1xuICAgICAgICBBdXRvd2lyZWQoJ3Jvd1JlbmRlcmVyJylcbiAgICBdLCBJbmZpbml0ZUNhY2hlLnByb3RvdHlwZSwgXCJyb3dSZW5kZXJlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMyhbXG4gICAgICAgIEF1dG93aXJlZChcImZvY3VzU2VydmljZVwiKVxuICAgIF0sIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLCBcImZvY3VzU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMyhbXG4gICAgICAgIF9fcGFyYW0oMCwgUXVhbGlmaWVyKCdsb2dnZXJGYWN0b3J5JykpXG4gICAgXSwgSW5maW5pdGVDYWNoZS5wcm90b3R5cGUsIFwic2V0QmVhbnNcIiwgbnVsbCk7XG4gICAgX19kZWNvcmF0ZSQzKFtcbiAgICAgICAgUHJlRGVzdHJveVxuICAgIF0sIEluZmluaXRlQ2FjaGUucHJvdG90eXBlLCBcImRlc3Ryb3lBbGxCbG9ja3NcIiwgbnVsbCk7XG4gICAgcmV0dXJuIEluZmluaXRlQ2FjaGU7XG59KEJlYW5TdHViKSk7XG5cbnZhciBfX2V4dGVuZHMkMyA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIF9fZGVjb3JhdGUkMiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZGVjb3JhdGUpIHx8IGZ1bmN0aW9uIChkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xudmFyIEluZmluaXRlUm93TW9kZWwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDMoSW5maW5pdGVSb3dNb2RlbCwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBJbmZpbml0ZVJvd01vZGVsKCkge1xuICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgfVxuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmdldFJvd0JvdW5kcyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93SGVpZ2h0OiB0aGlzLnJvd0hlaWdodCxcbiAgICAgICAgICAgIHJvd1RvcDogdGhpcy5yb3dIZWlnaHQgKiBpbmRleFxuICAgICAgICB9O1xuICAgIH07XG4gICAgLy8gd2UgZG9uJ3QgaW1wbGVtZW50IGFzIGxhenkgcm93IGhlaWdodHMgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGlzIHJvdyBtb2RlbFxuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmVuc3VyZVJvd0hlaWdodHNWYWxpZCA9IGZ1bmN0aW9uIChzdGFydFBpeGVsLCBlbmRQaXhlbCwgc3RhcnRMaW1pdEluZGV4LCBlbmRMaW1pdEluZGV4KSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuaXNSb3dNb2RlbEluZmluaXRlKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvd0hlaWdodCA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldFJvd0hlaWdodEFzTnVtYmVyKCk7XG4gICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5hZGREZXN0cm95RnVuYyhmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5kZXN0cm95Q2FjaGUoKTsgfSk7XG4gICAgICAgIHRoaXMudmVyaWZ5UHJvcHMoKTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLnZlcmlmeVByb3BzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0SW5pdGlhbEdyb3VwT3JkZXJDb21wYXJhdG9yKCkgIT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2VfMSA9IFwiQUcgR3JpZDogaW5pdGlhbEdyb3VwT3JkZXJDb21wYXJhdG9yIGNhbm5vdCBiZSB1c2VkIHdpdGggSW5maW5pdGUgUm93IE1vZGVsLiBJZiB1c2luZyBJbmZpbml0ZSBSb3cgTW9kZWwsIHRoZW4gc29ydGluZyBpcyBkb25lIG9uIHRoZSBzZXJ2ZXIgc2lkZSwgbm90aGluZyB0byBkbyB3aXRoIHRoZSBjbGllbnQuXCI7XG4gICAgICAgICAgICBfLmRvT25jZShmdW5jdGlvbiAoKSB7IHJldHVybiBjb25zb2xlLndhcm4obWVzc2FnZV8xKTsgfSwgJ0lSTS5Jbml0aWFsR3JvdXBPcmRlckNvbXBhcmF0b3InKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuc3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc2V0RGF0YXNvdXJjZSh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXREYXRhc291cmNlKCkpO1xuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuZGVzdHJveURhdGFzb3VyY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmRhdGFzb3VyY2UpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0Q29udGV4dCgpLmRlc3Ryb3lCZWFuKHRoaXMuZGF0YXNvdXJjZSk7XG4gICAgICAgICAgICB0aGlzLnJvd1JlbmRlcmVyLmRhdGFzb3VyY2VDaGFuZ2VkKCk7XG4gICAgICAgICAgICB0aGlzLmRhdGFzb3VyY2UgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9GSUxURVJfQ0hBTkdFRCwgdGhpcy5vbkZpbHRlckNoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfU09SVF9DSEFOR0VELCB0aGlzLm9uU29ydENoYW5nZWQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZExpc3RlbmVyKHRoaXMuZXZlbnRTZXJ2aWNlLCBFdmVudHMuRVZFTlRfTkVXX0NPTFVNTlNfTE9BREVELCB0aGlzLm9uQ29sdW1uRXZlcnl0aGluZy5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5hZGRNYW5hZ2VkTGlzdGVuZXIodGhpcy5ldmVudFNlcnZpY2UsIEV2ZW50cy5FVkVOVF9TVE9SRV9VUERBVEVELCB0aGlzLm9uQ2FjaGVVcGRhdGVkLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUub25GaWx0ZXJDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5vblNvcnRDaGFuZ2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5vbkNvbHVtbkV2ZXJ5dGhpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXNldFJlcXVpcmVkO1xuICAgICAgICAvLyBpZiBjYWNoZSBwYXJhbXMsIHdlIHJlcXVpcmUgcmVzZXQgb25seSBpZiBzb3J0IG1vZGVsIGhhcyBjaGFuZ2VkLiB3ZSBkb24ndCBuZWVkIHRvIGNoZWNrXG4gICAgICAgIC8vIGZvciBmaWx0ZXIgbW9kZWwsIGFzIHRoZSBmaWx0ZXIgbWFuYWdlciB3aWxsIGZpcmUgYW4gZXZlbnQgd2hlbiBjb2x1bW5zIGNoYW5nZSB0aGF0IHJlc3VsdFxuICAgICAgICAvLyBpbiB0aGUgZmlsdGVyIGNoYW5naW5nLlxuICAgICAgICBpZiAodGhpcy5jYWNoZVBhcmFtcykge1xuICAgICAgICAgICAgcmVzZXRSZXF1aXJlZCA9IHRoaXMuaXNTb3J0TW9kZWxEaWZmZXJlbnQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIG5vIGNhY2hlUGFyYW1zLCBtZWFucyBmaXJzdCB0aW1lIGNyZWF0aW5nIHRoZSBjYWNoZSwgc28gYWx3YXlzIGNyZWF0ZSBvbmVcbiAgICAgICAgICAgIHJlc2V0UmVxdWlyZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXNldFJlcXVpcmVkKSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmlzU29ydE1vZGVsRGlmZmVyZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gIV8uanNvbkVxdWFscyh0aGlzLmNhY2hlUGFyYW1zLnNvcnRNb2RlbCwgdGhpcy5zb3J0Q29udHJvbGxlci5nZXRTb3J0TW9kZWwoKSk7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gQ29uc3RhbnRzLlJPV19NT0RFTF9UWVBFX0lORklOSVRFO1xuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuc2V0RGF0YXNvdXJjZSA9IGZ1bmN0aW9uIChkYXRhc291cmNlKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveURhdGFzb3VyY2UoKTtcbiAgICAgICAgdGhpcy5kYXRhc291cmNlID0gZGF0YXNvdXJjZTtcbiAgICAgICAgLy8gb25seSByZXNldCBpZiB3ZSBoYXZlIGEgdmFsaWQgZGF0YXNvdXJjZSB0byB3b3JraW5nIHdpdGhcbiAgICAgICAgaWYgKGRhdGFzb3VyY2UpIHtcbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuaXNFbXB0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLmluZmluaXRlQ2FjaGU7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5pc1Jvd3NUb1JlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5pbmZpbml0ZUNhY2hlO1xuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuZ2V0Tm9kZXNJblJhbmdlRm9yU2VsZWN0aW9uID0gZnVuY3Rpb24gKGZpcnN0SW5SYW5nZSwgbGFzdEluUmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5maW5pdGVDYWNoZSA/IHRoaXMuaW5maW5pdGVDYWNoZS5nZXRSb3dOb2Rlc0luUmFuZ2UoZmlyc3RJblJhbmdlLCBsYXN0SW5SYW5nZSkgOiBbXTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBpbXBvcnRhbnQgdG8gcmV0dXJuIGhlcmUsIGFzIHRoZSB1c2VyIGNvdWxkIGJlIHNldHRpbmcgZmlsdGVyIG9yIHNvcnQgYmVmb3JlXG4gICAgICAgIC8vIGRhdGEtc291cmNlIGlzIHNldFxuICAgICAgICBpZiAoIXRoaXMuZGF0YXNvdXJjZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHVzZXIgaXMgcHJvdmlkaW5nIGlkJ3MsIHRoZW4gdGhpcyBtZWFucyB3ZSBjYW4ga2VlcCB0aGUgc2VsZWN0aW9uIGJldHdlZW4gZGF0YXNvdXJjZSBoaXRzLFxuICAgICAgICAvLyBhcyB0aGUgcm93cyB3aWxsIGtlZXAgdGhlaXIgdW5pcXVlIGlkJ3MgZXZlbiBpZiwgZm9yIGV4YW1wbGUsIHNlcnZlciBzaWRlIHNvcnRpbmcgb3IgZmlsdGVyaW5nXG4gICAgICAgIC8vIGlzIGRvbmUuXG4gICAgICAgIHZhciBnZXRSb3dJZEZ1bmMgPSB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRSb3dJZEZ1bmMoKTtcbiAgICAgICAgdmFyIHVzZXJHZW5lcmF0aW5nSWRzID0gZ2V0Um93SWRGdW5jICE9IG51bGw7XG4gICAgICAgIGlmICghdXNlckdlbmVyYXRpbmdJZHMpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU2VydmljZS5yZXNldCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzZXRDYWNoZSgpO1xuICAgICAgICB2YXIgZXZlbnQgPSB0aGlzLmNyZWF0ZU1vZGVsVXBkYXRlZEV2ZW50KCk7XG4gICAgICAgIHRoaXMuZXZlbnRTZXJ2aWNlLmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuY3JlYXRlTW9kZWxVcGRhdGVkRXZlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiBFdmVudHMuRVZFTlRfTU9ERUxfVVBEQVRFRCxcbiAgICAgICAgICAgIC8vIG5vdCBzdXJlIGlmIHRoZXNlIHNob3VsZCBhbGwgYmUgZmFsc2UgLSBub3RpY2VkIGlmIGFmdGVyIGltcGxlbWVudGluZyxcbiAgICAgICAgICAgIC8vIG1heWJlIHRoZXkgc2hvdWxkIGJlIHRydWU/XG4gICAgICAgICAgICBuZXdQYWdlOiBmYWxzZSxcbiAgICAgICAgICAgIG5ld0RhdGE6IGZhbHNlLFxuICAgICAgICAgICAga2VlcFJlbmRlcmVkUm93czogdHJ1ZSxcbiAgICAgICAgICAgIGFuaW1hdGU6IGZhbHNlXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5yZXNldENhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBpZiBub3QgZmlyc3QgdGltZSBjcmVhdGluZyBhIGNhY2hlLCBuZWVkIHRvIGRlc3Ryb3kgdGhlIG9sZCBvbmVcbiAgICAgICAgdGhpcy5kZXN0cm95Q2FjaGUoKTtcbiAgICAgICAgdGhpcy5jYWNoZVBhcmFtcyA9IHtcbiAgICAgICAgICAgIC8vIHRoZSB1c2VyIHByb3ZpZGVkIGRhdGFzb3VyY2VcbiAgICAgICAgICAgIGRhdGFzb3VyY2U6IHRoaXMuZGF0YXNvdXJjZSxcbiAgICAgICAgICAgIC8vIHNvcnQgYW5kIGZpbHRlciBtb2RlbFxuICAgICAgICAgICAgZmlsdGVyTW9kZWw6IHRoaXMuZmlsdGVyTWFuYWdlci5nZXRGaWx0ZXJNb2RlbCgpLFxuICAgICAgICAgICAgc29ydE1vZGVsOiB0aGlzLnNvcnRDb250cm9sbGVyLmdldFNvcnRNb2RlbCgpLFxuICAgICAgICAgICAgcm93Tm9kZUJsb2NrTG9hZGVyOiB0aGlzLnJvd05vZGVCbG9ja0xvYWRlcixcbiAgICAgICAgICAgIC8vIHByb3BlcnRpZXMgLSB0aGlzIHdheSB3ZSB0YWtlIGEgc25hcHNob3Qgb2YgdGhlbSwgc28gaWYgdXNlciBjaGFuZ2VzIGFueSwgdGhleSB3aWxsIGJlXG4gICAgICAgICAgICAvLyB1c2VkIG5leHQgdGltZSB3ZSBjcmVhdGUgYSBuZXcgY2FjaGUsIHdoaWNoIGlzIGdlbmVyYWxseSBhZnRlciBhIGZpbHRlciBvciBzb3J0IGNoYW5nZSxcbiAgICAgICAgICAgIC8vIG9yIGEgbmV3IGRhdGFzb3VyY2UgaXMgc2V0XG4gICAgICAgICAgICBpbml0aWFsUm93Q291bnQ6IHRoaXMuZGVmYXVsdElmSW52YWxpZCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRJbmZpbml0ZUluaXRpYWxSb3dDb3VudCgpLCAxKSxcbiAgICAgICAgICAgIG1heEJsb2Nrc0luQ2FjaGU6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldE1heEJsb2Nrc0luQ2FjaGUoKSxcbiAgICAgICAgICAgIHJvd0hlaWdodDogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Um93SGVpZ2h0QXNOdW1iZXIoKSxcbiAgICAgICAgICAgIC8vIGlmIHVzZXIgZG9lc24ndCBwcm92aWRlIG92ZXJmbG93LCB3ZSB1c2UgZGVmYXVsdCBvdmVyZmxvdyBvZiAxLCBzbyB1c2VyIGNhbiBzY3JvbGwgcGFzdFxuICAgICAgICAgICAgLy8gdGhlIGN1cnJlbnQgcGFnZSBhbmQgcmVxdWVzdCBmaXJzdCByb3cgb2YgbmV4dCBwYWdlXG4gICAgICAgICAgICBvdmVyZmxvd1NpemU6IHRoaXMuZGVmYXVsdElmSW52YWxpZCh0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDYWNoZU92ZXJmbG93U2l6ZSgpLCAxKSxcbiAgICAgICAgICAgIC8vIHBhZ2Ugc2l6ZSBuZWVkcyB0byBiZSAxIG9yIGdyZWF0ZXIuIGhhdmluZyBpdCBhdCAxIHdvdWxkIGJlIHNpbGx5LCBhcyB5b3Ugd291bGQgYmUgaGl0dGluZyB0aGVcbiAgICAgICAgICAgIC8vIHNlcnZlciBmb3Igb25lIHBhZ2UgYXQgYSB0aW1lLiBzbyB0aGUgZGVmYXVsdCBpZiBub3Qgc3BlY2lmaWVkIGlzIDEwMC5cbiAgICAgICAgICAgIGJsb2NrU2l6ZTogdGhpcy5kZWZhdWx0SWZJbnZhbGlkKHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENhY2hlQmxvY2tTaXplKCksIDEwMCksXG4gICAgICAgICAgICAvLyB0aGUgY2FjaGUgY291bGQgY3JlYXRlIHRoaXMsIGhvd2V2ZXIgaXQgaXMgYWxzbyB1c2VkIGJ5IHRoZSBwYWdlcywgc28gaGFuZHkgdG8gY3JlYXRlIGl0XG4gICAgICAgICAgICAvLyBoZXJlIGFzIHRoZSBzZXR0aW5ncyBhcmUgYWxzbyBwYXNzZWQgdG8gdGhlIHBhZ2VzXG4gICAgICAgICAgICBsYXN0QWNjZXNzZWRTZXF1ZW5jZTogbmV3IE51bWJlclNlcXVlbmNlKClcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5pbmZpbml0ZUNhY2hlID0gdGhpcy5jcmVhdGVCZWFuKG5ldyBJbmZpbml0ZUNhY2hlKHRoaXMuY2FjaGVQYXJhbXMpKTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmRlZmF1bHRJZkludmFsaWQgPSBmdW5jdGlvbiAodmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPiAwID8gdmFsdWUgOiBkZWZhdWx0VmFsdWU7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5kZXN0cm95Q2FjaGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmluZmluaXRlQ2FjaGUpIHtcbiAgICAgICAgICAgIHRoaXMuaW5maW5pdGVDYWNoZSA9IHRoaXMuZGVzdHJveUJlYW4odGhpcy5pbmZpbml0ZUNhY2hlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUub25DYWNoZVVwZGF0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudCA9IHRoaXMuY3JlYXRlTW9kZWxVcGRhdGVkRXZlbnQoKTtcbiAgICAgICAgdGhpcy5ldmVudFNlcnZpY2UuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5nZXRSb3cgPSBmdW5jdGlvbiAocm93SW5kZXgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmluZmluaXRlQ2FjaGUpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJvd0luZGV4ID49IHRoaXMuaW5maW5pdGVDYWNoZS5nZXRSb3dDb3VudCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZmluaXRlQ2FjaGUuZ2V0Um93KHJvd0luZGV4KTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmdldFJvd05vZGUgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgdGhpcy5mb3JFYWNoTm9kZShmdW5jdGlvbiAocm93Tm9kZSkge1xuICAgICAgICAgICAgaWYgKHJvd05vZGUuaWQgPT09IGlkKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcm93Tm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5mb3JFYWNoTm9kZSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICBpZiAodGhpcy5pbmZpbml0ZUNhY2hlKSB7XG4gICAgICAgICAgICB0aGlzLmluZmluaXRlQ2FjaGUuZm9yRWFjaE5vZGVEZWVwKGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuZ2V0VG9wTGV2ZWxSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Um93Q291bnQoKTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmdldFRvcExldmVsUm93RGlzcGxheWVkSW5kZXggPSBmdW5jdGlvbiAodG9wTGV2ZWxJbmRleCkge1xuICAgICAgICByZXR1cm4gdG9wTGV2ZWxJbmRleDtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmdldFJvd0luZGV4QXRQaXhlbCA9IGZ1bmN0aW9uIChwaXhlbCkge1xuICAgICAgICBpZiAodGhpcy5yb3dIZWlnaHQgIT09IDApIHsgLy8gYXZvaWQgZGl2aWRlIGJ5IHplcm8gZXJyb3JcbiAgICAgICAgICAgIHZhciByb3dJbmRleEZvclBpeGVsID0gTWF0aC5mbG9vcihwaXhlbCAvIHRoaXMucm93SGVpZ2h0KTtcbiAgICAgICAgICAgIHZhciBsYXN0Um93SW5kZXggPSB0aGlzLmdldFJvd0NvdW50KCkgLSAxO1xuICAgICAgICAgICAgaWYgKHJvd0luZGV4Rm9yUGl4ZWwgPiBsYXN0Um93SW5kZXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFzdFJvd0luZGV4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJvd0luZGV4Rm9yUGl4ZWw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5nZXRSb3dDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5maW5pdGVDYWNoZSA/IHRoaXMuaW5maW5pdGVDYWNoZS5nZXRSb3dDb3VudCgpIDogMDtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLmlzUm93UHJlc2VudCA9IGZ1bmN0aW9uIChyb3dOb2RlKSB7XG4gICAgICAgIHZhciBmb3VuZFJvd05vZGUgPSB0aGlzLmdldFJvd05vZGUocm93Tm9kZS5pZCk7XG4gICAgICAgIHJldHVybiAhIWZvdW5kUm93Tm9kZTtcbiAgICB9O1xuICAgIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLnJlZnJlc2hDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5maW5pdGVDYWNoZSkge1xuICAgICAgICAgICAgdGhpcy5pbmZpbml0ZUNhY2hlLnJlZnJlc2hDYWNoZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZS5wdXJnZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pbmZpbml0ZUNhY2hlKSB7XG4gICAgICAgICAgICB0aGlzLmluZmluaXRlQ2FjaGUucHVyZ2VDYWNoZSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICAvLyBmb3IgaVJvd01vZGVsXG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuaXNMYXN0Um93SW5kZXhLbm93biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaW5maW5pdGVDYWNoZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5maW5pdGVDYWNoZS5pc0xhc3RSb3dJbmRleEtub3duKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUuc2V0Um93Q291bnQgPSBmdW5jdGlvbiAocm93Q291bnQsIGxhc3RSb3dJbmRleEtub3duKSB7XG4gICAgICAgIGlmICh0aGlzLmluZmluaXRlQ2FjaGUpIHtcbiAgICAgICAgICAgIHRoaXMuaW5maW5pdGVDYWNoZS5zZXRSb3dDb3VudChyb3dDb3VudCwgbGFzdFJvd0luZGV4S25vd24pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDIoW1xuICAgICAgICBBdXRvd2lyZWQoJ2ZpbHRlck1hbmFnZXInKVxuICAgIF0sIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLCBcImZpbHRlck1hbmFnZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDIoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NvcnRDb250cm9sbGVyJylcbiAgICBdLCBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZSwgXCJzb3J0Q29udHJvbGxlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMihbXG4gICAgICAgIEF1dG93aXJlZCgnc2VsZWN0aW9uU2VydmljZScpXG4gICAgXSwgSW5maW5pdGVSb3dNb2RlbC5wcm90b3R5cGUsIFwic2VsZWN0aW9uU2VydmljZVwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMihbXG4gICAgICAgIEF1dG93aXJlZCgncm93UmVuZGVyZXInKVxuICAgIF0sIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLCBcInJvd1JlbmRlcmVyXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZSQyKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dOb2RlQmxvY2tMb2FkZXInKVxuICAgIF0sIEluZmluaXRlUm93TW9kZWwucHJvdG90eXBlLCBcInJvd05vZGVCbG9ja0xvYWRlclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMihbXG4gICAgICAgIFBvc3RDb25zdHJ1Y3RcbiAgICBdLCBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZSwgXCJpbml0XCIsIG51bGwpO1xuICAgIF9fZGVjb3JhdGUkMihbXG4gICAgICAgIFByZURlc3Ryb3lcbiAgICBdLCBJbmZpbml0ZVJvd01vZGVsLnByb3RvdHlwZSwgXCJkZXN0cm95RGF0YXNvdXJjZVwiLCBudWxsKTtcbiAgICBJbmZpbml0ZVJvd01vZGVsID0gX19kZWNvcmF0ZSQyKFtcbiAgICAgICAgQmVhbigncm93TW9kZWwnKVxuICAgIF0sIEluZmluaXRlUm93TW9kZWwpO1xuICAgIHJldHVybiBJbmZpbml0ZVJvd01vZGVsO1xufShCZWFuU3R1YikpO1xuXG52YXIgSW5maW5pdGVSb3dNb2RlbE1vZHVsZSA9IHtcbiAgICBtb2R1bGVOYW1lOiBNb2R1bGVOYW1lcy5JbmZpbml0ZVJvd01vZGVsTW9kdWxlLFxuICAgIHJvd01vZGVsczogeyBpbmZpbml0ZTogSW5maW5pdGVSb3dNb2RlbCB9XG59O1xuXG52YXIgQmFzZUNyZWF0b3IgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQmFzZUNyZWF0b3IoKSB7XG4gICAgfVxuICAgIEJhc2VDcmVhdG9yLnByb3RvdHlwZS5zZXRCZWFucyA9IGZ1bmN0aW9uIChiZWFucykge1xuICAgICAgICB0aGlzLmJlYW5zID0gYmVhbnM7XG4gICAgfTtcbiAgICBCYXNlQ3JlYXRvci5wcm90b3R5cGUuZ2V0RmlsZU5hbWUgPSBmdW5jdGlvbiAoZmlsZU5hbWUpIHtcbiAgICAgICAgdmFyIGV4dGVuc2lvbiA9IHRoaXMuZ2V0RGVmYXVsdEZpbGVFeHRlbnNpb24oKTtcbiAgICAgICAgaWYgKGZpbGVOYW1lID09IG51bGwgfHwgIWZpbGVOYW1lLmxlbmd0aCkge1xuICAgICAgICAgICAgZmlsZU5hbWUgPSB0aGlzLmdldERlZmF1bHRGaWxlTmFtZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaWxlTmFtZS5pbmRleE9mKCcuJykgPT09IC0xID8gZmlsZU5hbWUgKyBcIi5cIiArIGV4dGVuc2lvbiA6IGZpbGVOYW1lO1xuICAgIH07XG4gICAgQmFzZUNyZWF0b3IucHJvdG90eXBlLmdldERhdGEgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBzZXJpYWxpemluZ1Nlc3Npb24gPSB0aGlzLmNyZWF0ZVNlcmlhbGl6aW5nU2Vzc2lvbihwYXJhbXMpO1xuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuYmVhbnMuZ3JpZFNlcmlhbGl6ZXIuc2VyaWFsaXplKHNlcmlhbGl6aW5nU2Vzc2lvbiwgcGFyYW1zKTtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZUNyZWF0b3I7XG59KCkpO1xuXG52YXIgQmFzZUdyaWRTZXJpYWxpemluZ1Nlc3Npb24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQmFzZUdyaWRTZXJpYWxpemluZ1Nlc3Npb24oY29uZmlnKSB7XG4gICAgICAgIHRoaXMuZ3JvdXBDb2x1bW5zID0gW107XG4gICAgICAgIHZhciBjb2x1bW5Nb2RlbCA9IGNvbmZpZy5jb2x1bW5Nb2RlbCwgdmFsdWVTZXJ2aWNlID0gY29uZmlnLnZhbHVlU2VydmljZSwgZ3JpZE9wdGlvbnNXcmFwcGVyID0gY29uZmlnLmdyaWRPcHRpb25zV3JhcHBlciwgcHJvY2Vzc0NlbGxDYWxsYmFjayA9IGNvbmZpZy5wcm9jZXNzQ2VsbENhbGxiYWNrLCBwcm9jZXNzSGVhZGVyQ2FsbGJhY2sgPSBjb25maWcucHJvY2Vzc0hlYWRlckNhbGxiYWNrLCBwcm9jZXNzR3JvdXBIZWFkZXJDYWxsYmFjayA9IGNvbmZpZy5wcm9jZXNzR3JvdXBIZWFkZXJDYWxsYmFjaywgcHJvY2Vzc1Jvd0dyb3VwQ2FsbGJhY2sgPSBjb25maWcucHJvY2Vzc1Jvd0dyb3VwQ2FsbGJhY2s7XG4gICAgICAgIHRoaXMuY29sdW1uTW9kZWwgPSBjb2x1bW5Nb2RlbDtcbiAgICAgICAgdGhpcy52YWx1ZVNlcnZpY2UgPSB2YWx1ZVNlcnZpY2U7XG4gICAgICAgIHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyID0gZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICB0aGlzLnByb2Nlc3NDZWxsQ2FsbGJhY2sgPSBwcm9jZXNzQ2VsbENhbGxiYWNrO1xuICAgICAgICB0aGlzLnByb2Nlc3NIZWFkZXJDYWxsYmFjayA9IHByb2Nlc3NIZWFkZXJDYWxsYmFjaztcbiAgICAgICAgdGhpcy5wcm9jZXNzR3JvdXBIZWFkZXJDYWxsYmFjayA9IHByb2Nlc3NHcm91cEhlYWRlckNhbGxiYWNrO1xuICAgICAgICB0aGlzLnByb2Nlc3NSb3dHcm91cENhbGxiYWNrID0gcHJvY2Vzc1Jvd0dyb3VwQ2FsbGJhY2s7XG4gICAgfVxuICAgIEJhc2VHcmlkU2VyaWFsaXppbmdTZXNzaW9uLnByb3RvdHlwZS5wcmVwYXJlID0gZnVuY3Rpb24gKGNvbHVtbnNUb0V4cG9ydCkge1xuICAgICAgICB0aGlzLmdyb3VwQ29sdW1ucyA9IGNvbHVtbnNUb0V4cG9ydC5maWx0ZXIoZnVuY3Rpb24gKGNvbCkgeyByZXR1cm4gISFjb2wuZ2V0Q29sRGVmKCkuc2hvd1Jvd0dyb3VwOyB9KTtcbiAgICB9O1xuICAgIEJhc2VHcmlkU2VyaWFsaXppbmdTZXNzaW9uLnByb3RvdHlwZS5leHRyYWN0SGVhZGVyVmFsdWUgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHRoaXMuZ2V0SGVhZGVyTmFtZSh0aGlzLnByb2Nlc3NIZWFkZXJDYWxsYmFjaywgY29sdW1uKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6ICcnO1xuICAgIH07XG4gICAgQmFzZUdyaWRTZXJpYWxpemluZ1Nlc3Npb24ucHJvdG90eXBlLmV4dHJhY3RSb3dDZWxsVmFsdWUgPSBmdW5jdGlvbiAoY29sdW1uLCBpbmRleCwgYWNjdW11bGF0ZWRSb3dJbmRleCwgdHlwZSwgbm9kZSkge1xuICAgICAgICAvLyB3ZSByZW5kZXIgdGhlIGdyb3VwIHN1bW1hcnkgdGV4dCBlLmcuIFwiLT4gUGFyZW50IC0+IENoaWxkXCIuLi5cbiAgICAgICAgdmFyIGhpZGVPcGVuUGFyZW50cyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBIaWRlT3BlblBhcmVudHMoKTtcbiAgICAgICAgdmFyIHZhbHVlID0gKCFoaWRlT3BlblBhcmVudHMgJiYgdGhpcy5zaG91bGRSZW5kZXJHcm91cFN1bW1hcnlDZWxsKG5vZGUsIGNvbHVtbiwgaW5kZXgpKVxuICAgICAgICAgICAgPyB0aGlzLmNyZWF0ZVZhbHVlRm9yR3JvdXBOb2RlKG5vZGUpXG4gICAgICAgICAgICA6IHRoaXMudmFsdWVTZXJ2aWNlLmdldFZhbHVlKGNvbHVtbiwgbm9kZSk7XG4gICAgICAgIHZhciBwcm9jZXNzZWRWYWx1ZSA9IHRoaXMucHJvY2Vzc0NlbGwoe1xuICAgICAgICAgICAgYWNjdW11bGF0ZWRSb3dJbmRleDogYWNjdW11bGF0ZWRSb3dJbmRleCxcbiAgICAgICAgICAgIHJvd05vZGU6IG5vZGUsXG4gICAgICAgICAgICBjb2x1bW46IGNvbHVtbixcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgIHByb2Nlc3NDZWxsQ2FsbGJhY2s6IHRoaXMucHJvY2Vzc0NlbGxDYWxsYmFjayxcbiAgICAgICAgICAgIHR5cGU6IHR5cGVcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRWYWx1ZSAhPSBudWxsID8gcHJvY2Vzc2VkVmFsdWUgOiAnJztcbiAgICB9O1xuICAgIEJhc2VHcmlkU2VyaWFsaXppbmdTZXNzaW9uLnByb3RvdHlwZS5zaG91bGRSZW5kZXJHcm91cFN1bW1hcnlDZWxsID0gZnVuY3Rpb24gKG5vZGUsIGNvbHVtbiwgY3VycmVudENvbHVtbkluZGV4KSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgdmFyIGlzR3JvdXBOb2RlID0gbm9kZSAmJiBub2RlLmdyb3VwO1xuICAgICAgICAvLyBvbmx5IG9uIGdyb3VwIHJvd3NcbiAgICAgICAgaWYgKCFpc0dyb3VwTm9kZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjdXJyZW50Q29sdW1uR3JvdXBJbmRleCA9IHRoaXMuZ3JvdXBDb2x1bW5zLmluZGV4T2YoY29sdW1uKTtcbiAgICAgICAgaWYgKGN1cnJlbnRDb2x1bW5Hcm91cEluZGV4ICE9PSAtMSAmJiAoKF9hID0gbm9kZS5ncm91cERhdGEpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYVtjb2x1bW4uZ2V0SWQoKV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaXNHcm91cFVzZUVudGlyZVJvdyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBVc2VFbnRpcmVSb3codGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90TW9kZSgpKTtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRDb2x1bW5JbmRleCA9PT0gMCAmJiBpc0dyb3VwVXNlRW50aXJlUm93O1xuICAgIH07XG4gICAgQmFzZUdyaWRTZXJpYWxpemluZ1Nlc3Npb24ucHJvdG90eXBlLmdldEhlYWRlck5hbWUgPSBmdW5jdGlvbiAoY2FsbGJhY2ssIGNvbHVtbikge1xuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayh7XG4gICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0RGlzcGxheU5hbWVGb3JDb2x1bW4oY29sdW1uLCAnY3N2JywgdHJ1ZSk7XG4gICAgfTtcbiAgICBCYXNlR3JpZFNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUuY3JlYXRlVmFsdWVGb3JHcm91cE5vZGUgPSBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBpZiAodGhpcy5wcm9jZXNzUm93R3JvdXBDYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvY2Vzc1Jvd0dyb3VwQ2FsbGJhY2soe1xuICAgICAgICAgICAgICAgIG5vZGU6IG5vZGUsXG4gICAgICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHZhciBrZXlzID0gW25vZGUua2V5XTtcbiAgICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwTXVsdGlBdXRvQ29sdW1uKCkpIHtcbiAgICAgICAgICAgIHdoaWxlIChub2RlLnBhcmVudCkge1xuICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlLnBhcmVudDtcbiAgICAgICAgICAgICAgICBrZXlzLnB1c2gobm9kZS5rZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBrZXlzLnJldmVyc2UoKS5qb2luKCcgLT4gJyk7XG4gICAgfTtcbiAgICBCYXNlR3JpZFNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUucHJvY2Vzc0NlbGwgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBhY2N1bXVsYXRlZFJvd0luZGV4ID0gcGFyYW1zLmFjY3VtdWxhdGVkUm93SW5kZXgsIHJvd05vZGUgPSBwYXJhbXMucm93Tm9kZSwgY29sdW1uID0gcGFyYW1zLmNvbHVtbiwgdmFsdWUgPSBwYXJhbXMudmFsdWUsIHByb2Nlc3NDZWxsQ2FsbGJhY2sgPSBwYXJhbXMucHJvY2Vzc0NlbGxDYWxsYmFjaywgdHlwZSA9IHBhcmFtcy50eXBlO1xuICAgICAgICBpZiAocHJvY2Vzc0NlbGxDYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NDZWxsQ2FsbGJhY2soe1xuICAgICAgICAgICAgICAgIGFjY3VtdWxhdGVkUm93SW5kZXg6IGFjY3VtdWxhdGVkUm93SW5kZXgsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICAgICAgICAgICAgbm9kZTogcm93Tm9kZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgICAgICAgICAgYXBpOiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRBcGkoKSxcbiAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbHVtbkFwaSgpLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKSxcbiAgICAgICAgICAgICAgICB0eXBlOiB0eXBlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogJyc7XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZUdyaWRTZXJpYWxpemluZ1Nlc3Npb247XG59KCkpO1xuXG52YXIgRG93bmxvYWRlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBEb3dubG9hZGVyKCkge1xuICAgIH1cbiAgICBEb3dubG9hZGVyLmRvd25sb2FkID0gZnVuY3Rpb24gKGZpbGVOYW1lLCBjb250ZW50KSB7XG4gICAgICAgIHZhciB3aW4gPSBkb2N1bWVudC5kZWZhdWx0VmlldyB8fCB3aW5kb3c7XG4gICAgICAgIGlmICghd2luKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0FHIEdyaWQ6IFRoZXJlIGlzIG5vIGB3aW5kb3dgIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3VycmVudCBgZG9jdW1lbnRgJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgdmFyIHVybCA9IHdpbi5VUkwuY3JlYXRlT2JqZWN0VVJMKGNvbnRlbnQpO1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnaHJlZicsIHVybCk7XG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdkb3dubG9hZCcsIGZpbGVOYW1lKTtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICBlbGVtZW50LmRpc3BhdGNoRXZlbnQobmV3IE1vdXNlRXZlbnQoJ2NsaWNrJywge1xuICAgICAgICAgICAgYnViYmxlczogZmFsc2UsXG4gICAgICAgICAgICBjYW5jZWxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgdmlldzogd2luXG4gICAgICAgIH0pKTtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChlbGVtZW50KTtcbiAgICAgICAgd2luLnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgd2luLlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcbiAgICAgICAgfSwgMCk7XG4gICAgfTtcbiAgICByZXR1cm4gRG93bmxvYWRlcjtcbn0oKSk7XG5cbnZhciBfX2V4dGVuZHMkMiA9ICh1bmRlZmluZWQgJiYgdW5kZWZpbmVkLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xudmFyIExJTkVfU0VQQVJBVE9SJDEgPSAnXFxyXFxuJztcbnZhciBDc3ZTZXJpYWxpemluZ1Nlc3Npb24gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzJDIoQ3N2U2VyaWFsaXppbmdTZXNzaW9uLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENzdlNlcmlhbGl6aW5nU2Vzc2lvbihjb25maWcpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgY29uZmlnKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5pc0ZpcnN0TGluZSA9IHRydWU7XG4gICAgICAgIF90aGlzLnJlc3VsdCA9ICcnO1xuICAgICAgICB2YXIgc3VwcHJlc3NRdW90ZXMgPSBjb25maWcuc3VwcHJlc3NRdW90ZXMsIGNvbHVtblNlcGFyYXRvciA9IGNvbmZpZy5jb2x1bW5TZXBhcmF0b3I7XG4gICAgICAgIF90aGlzLnN1cHByZXNzUXVvdGVzID0gc3VwcHJlc3NRdW90ZXM7XG4gICAgICAgIF90aGlzLmNvbHVtblNlcGFyYXRvciA9IGNvbHVtblNlcGFyYXRvcjtcbiAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cbiAgICBDc3ZTZXJpYWxpemluZ1Nlc3Npb24ucHJvdG90eXBlLmFkZEN1c3RvbUNvbnRlbnQgPSBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIWNvbnRlbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAoIS9eXFxzKlxcbi8udGVzdChjb250ZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYmVnaW5OZXdMaW5lKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyByZXBsYWNlIHdoYXRldmVyIG5ld2xpbmVzIGFyZSBzdXBwbGllZCB3aXRoIHRoZSBzdHlsZSB3ZSdyZSB1c2luZ1xuICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQucmVwbGFjZSgvXFxyP1xcbi9nLCBMSU5FX1NFUEFSQVRPUiQxKTtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0ICs9IGNvbnRlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb250ZW50LmZvckVhY2goZnVuY3Rpb24gKHJvdykge1xuICAgICAgICAgICAgICAgIF90aGlzLmJlZ2luTmV3TGluZSgpO1xuICAgICAgICAgICAgICAgIHJvdy5mb3JFYWNoKGZ1bmN0aW9uIChjZWxsLCBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLnJlc3VsdCArPSBfdGhpcy5jb2x1bW5TZXBhcmF0b3I7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucmVzdWx0ICs9IF90aGlzLnB1dEluUXVvdGVzKGNlbGwuZGF0YS52YWx1ZSB8fCAnJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjZWxsLm1lcmdlQWNyb3NzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hcHBlbmRFbXB0eUNlbGxzKGNlbGwubWVyZ2VBY3Jvc3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ3N2U2VyaWFsaXppbmdTZXNzaW9uLnByb3RvdHlwZS5vbk5ld0hlYWRlckdyb3VwaW5nUm93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmJlZ2luTmV3TGluZSgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb25Db2x1bW46IHRoaXMub25OZXdIZWFkZXJHcm91cGluZ1Jvd0NvbHVtbi5iaW5kKHRoaXMpXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBDc3ZTZXJpYWxpemluZ1Nlc3Npb24ucHJvdG90eXBlLm9uTmV3SGVhZGVyR3JvdXBpbmdSb3dDb2x1bW4gPSBmdW5jdGlvbiAoY29sdW1uR3JvdXAsIGhlYWRlciwgaW5kZXgsIHNwYW4pIHtcbiAgICAgICAgaWYgKGluZGV4ICE9IDApIHtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0ICs9IHRoaXMuY29sdW1uU2VwYXJhdG9yO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzdWx0ICs9IHRoaXMucHV0SW5RdW90ZXMoaGVhZGVyKTtcbiAgICAgICAgdGhpcy5hcHBlbmRFbXB0eUNlbGxzKHNwYW4pO1xuICAgIH07XG4gICAgQ3N2U2VyaWFsaXppbmdTZXNzaW9uLnByb3RvdHlwZS5hcHBlbmRFbXB0eUNlbGxzID0gZnVuY3Rpb24gKGNvdW50KSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0ICs9IHRoaXMuY29sdW1uU2VwYXJhdG9yICsgdGhpcy5wdXRJblF1b3RlcyhcIlwiKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQ3N2U2VyaWFsaXppbmdTZXNzaW9uLnByb3RvdHlwZS5vbk5ld0hlYWRlclJvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5iZWdpbk5ld0xpbmUoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG9uQ29sdW1uOiB0aGlzLm9uTmV3SGVhZGVyUm93Q29sdW1uLmJpbmQodGhpcylcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENzdlNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUub25OZXdIZWFkZXJSb3dDb2x1bW4gPSBmdW5jdGlvbiAoY29sdW1uLCBpbmRleCkge1xuICAgICAgICBpZiAoaW5kZXggIT0gMCkge1xuICAgICAgICAgICAgdGhpcy5yZXN1bHQgKz0gdGhpcy5jb2x1bW5TZXBhcmF0b3I7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXN1bHQgKz0gdGhpcy5wdXRJblF1b3Rlcyh0aGlzLmV4dHJhY3RIZWFkZXJWYWx1ZShjb2x1bW4pKTtcbiAgICB9O1xuICAgIENzdlNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUub25OZXdCb2R5Um93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmJlZ2luTmV3TGluZSgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb25Db2x1bW46IHRoaXMub25OZXdCb2R5Um93Q29sdW1uLmJpbmQodGhpcylcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIENzdlNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUub25OZXdCb2R5Um93Q29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbiwgaW5kZXgsIG5vZGUpIHtcbiAgICAgICAgaWYgKGluZGV4ICE9IDApIHtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0ICs9IHRoaXMuY29sdW1uU2VwYXJhdG9yO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVzdWx0ICs9IHRoaXMucHV0SW5RdW90ZXModGhpcy5leHRyYWN0Um93Q2VsbFZhbHVlKGNvbHVtbiwgaW5kZXgsIGluZGV4LCBDb25zdGFudHMuRVhQT1JUX1RZUEVfQ1NWLCBub2RlKSk7XG4gICAgfTtcbiAgICBDc3ZTZXJpYWxpemluZ1Nlc3Npb24ucHJvdG90eXBlLnB1dEluUXVvdGVzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLnN1cHByZXNzUXVvdGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiAnXCJcIic7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN0cmluZ1ZhbHVlO1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgc3RyaW5nVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmFsdWUudG9TdHJpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHN0cmluZ1ZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignQUcgR3JpZDogdW5rbm93biB2YWx1ZSB0eXBlIGR1cmluZyBjc3YgY29udmVyc2lvbicpO1xuICAgICAgICAgICAgc3RyaW5nVmFsdWUgPSAnJztcbiAgICAgICAgfVxuICAgICAgICAvLyByZXBsYWNlIGVhY2ggXCIgd2l0aCBcIlwiIChpZSB0d28gc2V0cyBvZiBkb3VibGUgcXVvdGVzIGlzIGhvdyB0byBkbyBkb3VibGUgcXVvdGVzIGluIGNzdilcbiAgICAgICAgdmFyIHZhbHVlRXNjYXBlZCA9IHN0cmluZ1ZhbHVlLnJlcGxhY2UoL1wiL2csIFwiXFxcIlxcXCJcIik7XG4gICAgICAgIHJldHVybiAnXCInICsgdmFsdWVFc2NhcGVkICsgJ1wiJztcbiAgICB9O1xuICAgIENzdlNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlc3VsdDtcbiAgICB9O1xuICAgIENzdlNlcmlhbGl6aW5nU2Vzc2lvbi5wcm90b3R5cGUuYmVnaW5OZXdMaW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNGaXJzdExpbmUpIHtcbiAgICAgICAgICAgIHRoaXMucmVzdWx0ICs9IExJTkVfU0VQQVJBVE9SJDE7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc0ZpcnN0TGluZSA9IGZhbHNlO1xuICAgIH07XG4gICAgcmV0dXJuIENzdlNlcmlhbGl6aW5nU2Vzc2lvbjtcbn0oQmFzZUdyaWRTZXJpYWxpemluZ1Nlc3Npb24pKTtcblxudmFyIF9fZXh0ZW5kcyQxID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSQxID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgQ3N2Q3JlYXRvciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMkMShDc3ZDcmVhdG9yLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENzdkNyZWF0b3IoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgQ3N2Q3JlYXRvci5wcm90b3R5cGUucG9zdENvbnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRCZWFucyh7XG4gICAgICAgICAgICBncmlkU2VyaWFsaXplcjogdGhpcy5ncmlkU2VyaWFsaXplcixcbiAgICAgICAgICAgIGdyaWRPcHRpb25zV3JhcHBlcjogdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXJcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDc3ZDcmVhdG9yLnByb3RvdHlwZS5nZXRNZXJnZWRQYXJhbXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBiYXNlUGFyYW1zID0gdGhpcy5ncmlkT3B0aW9uc1dyYXBwZXIuZ2V0RGVmYXVsdEV4cG9ydFBhcmFtcygnY3N2Jyk7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBiYXNlUGFyYW1zLCBwYXJhbXMpO1xuICAgIH07XG4gICAgQ3N2Q3JlYXRvci5wcm90b3R5cGUuZXhwb3J0ID0gZnVuY3Rpb24gKHVzZXJQYXJhbXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNFeHBvcnRTdXBwcmVzc2VkKCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkFHIEdyaWQ6IEV4cG9ydCBjYW5jZWxsZWQuIEV4cG9ydCBpcyBub3QgYWxsb3dlZCBhcyBwZXIgeW91ciBjb25maWd1cmF0aW9uLlwiKTtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWVyZ2VkUGFyYW1zID0gdGhpcy5nZXRNZXJnZWRQYXJhbXModXNlclBhcmFtcyk7XG4gICAgICAgIHZhciBkYXRhID0gdGhpcy5nZXREYXRhKG1lcmdlZFBhcmFtcyk7XG4gICAgICAgIHZhciBwYWNrYWdlZEZpbGUgPSBuZXcgQmxvYihbXCJcXHVmZWZmXCIsIGRhdGFdLCB7IHR5cGU6ICd0ZXh0L3BsYWluJyB9KTtcbiAgICAgICAgRG93bmxvYWRlci5kb3dubG9hZCh0aGlzLmdldEZpbGVOYW1lKG1lcmdlZFBhcmFtcy5maWxlTmFtZSksIHBhY2thZ2VkRmlsZSk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH07XG4gICAgQ3N2Q3JlYXRvci5wcm90b3R5cGUuZXhwb3J0RGF0YUFzQ3N2ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gdGhpcy5leHBvcnQocGFyYW1zKTtcbiAgICB9O1xuICAgIENzdkNyZWF0b3IucHJvdG90eXBlLmdldERhdGFBc0NzdiA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdmFyIG1lcmdlZFBhcmFtcyA9IHRoaXMuZ2V0TWVyZ2VkUGFyYW1zKHBhcmFtcyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldERhdGEobWVyZ2VkUGFyYW1zKTtcbiAgICB9O1xuICAgIENzdkNyZWF0b3IucHJvdG90eXBlLmdldERlZmF1bHRGaWxlTmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICdleHBvcnQuY3N2JztcbiAgICB9O1xuICAgIENzdkNyZWF0b3IucHJvdG90eXBlLmdldERlZmF1bHRGaWxlRXh0ZW5zaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gJ2Nzdic7XG4gICAgfTtcbiAgICBDc3ZDcmVhdG9yLnByb3RvdHlwZS5jcmVhdGVTZXJpYWxpemluZ1Nlc3Npb24gPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICAgIHZhciBfYSA9IHRoaXMsIGNvbHVtbk1vZGVsID0gX2EuY29sdW1uTW9kZWwsIHZhbHVlU2VydmljZSA9IF9hLnZhbHVlU2VydmljZSwgZ3JpZE9wdGlvbnNXcmFwcGVyID0gX2EuZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICB2YXIgX2IgPSBwYXJhbXMsIHByb2Nlc3NDZWxsQ2FsbGJhY2sgPSBfYi5wcm9jZXNzQ2VsbENhbGxiYWNrLCBwcm9jZXNzSGVhZGVyQ2FsbGJhY2sgPSBfYi5wcm9jZXNzSGVhZGVyQ2FsbGJhY2ssIHByb2Nlc3NHcm91cEhlYWRlckNhbGxiYWNrID0gX2IucHJvY2Vzc0dyb3VwSGVhZGVyQ2FsbGJhY2ssIHByb2Nlc3NSb3dHcm91cENhbGxiYWNrID0gX2IucHJvY2Vzc1Jvd0dyb3VwQ2FsbGJhY2ssIHN1cHByZXNzUXVvdGVzID0gX2Iuc3VwcHJlc3NRdW90ZXMsIGNvbHVtblNlcGFyYXRvciA9IF9iLmNvbHVtblNlcGFyYXRvcjtcbiAgICAgICAgcmV0dXJuIG5ldyBDc3ZTZXJpYWxpemluZ1Nlc3Npb24oe1xuICAgICAgICAgICAgY29sdW1uTW9kZWw6IGNvbHVtbk1vZGVsLFxuICAgICAgICAgICAgdmFsdWVTZXJ2aWNlOiB2YWx1ZVNlcnZpY2UsXG4gICAgICAgICAgICBncmlkT3B0aW9uc1dyYXBwZXI6IGdyaWRPcHRpb25zV3JhcHBlcixcbiAgICAgICAgICAgIHByb2Nlc3NDZWxsQ2FsbGJhY2s6IHByb2Nlc3NDZWxsQ2FsbGJhY2sgfHwgdW5kZWZpbmVkLFxuICAgICAgICAgICAgcHJvY2Vzc0hlYWRlckNhbGxiYWNrOiBwcm9jZXNzSGVhZGVyQ2FsbGJhY2sgfHwgdW5kZWZpbmVkLFxuICAgICAgICAgICAgcHJvY2Vzc0dyb3VwSGVhZGVyQ2FsbGJhY2s6IHByb2Nlc3NHcm91cEhlYWRlckNhbGxiYWNrIHx8IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHByb2Nlc3NSb3dHcm91cENhbGxiYWNrOiBwcm9jZXNzUm93R3JvdXBDYWxsYmFjayB8fCB1bmRlZmluZWQsXG4gICAgICAgICAgICBzdXBwcmVzc1F1b3Rlczogc3VwcHJlc3NRdW90ZXMgfHwgZmFsc2UsXG4gICAgICAgICAgICBjb2x1bW5TZXBhcmF0b3I6IGNvbHVtblNlcGFyYXRvciB8fCAnLCdcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDc3ZDcmVhdG9yLnByb3RvdHlwZS5pc0V4cG9ydFN1cHByZXNzZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdyaWRPcHRpb25zV3JhcHBlci5pc1N1cHByZXNzQ3N2RXhwb3J0KCk7XG4gICAgfTtcbiAgICBfX2RlY29yYXRlJDEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBDc3ZDcmVhdG9yLnByb3RvdHlwZSwgXCJjb2x1bW5Nb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMShbXG4gICAgICAgIEF1dG93aXJlZCgndmFsdWVTZXJ2aWNlJylcbiAgICBdLCBDc3ZDcmVhdG9yLnByb3RvdHlwZSwgXCJ2YWx1ZVNlcnZpY2VcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEoW1xuICAgICAgICBBdXRvd2lyZWQoJ2dyaWRTZXJpYWxpemVyJylcbiAgICBdLCBDc3ZDcmVhdG9yLnByb3RvdHlwZSwgXCJncmlkU2VyaWFsaXplclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUkMShbXG4gICAgICAgIEF1dG93aXJlZCgnZ3JpZE9wdGlvbnNXcmFwcGVyJylcbiAgICBdLCBDc3ZDcmVhdG9yLnByb3RvdHlwZSwgXCJncmlkT3B0aW9uc1dyYXBwZXJcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlJDEoW1xuICAgICAgICBQb3N0Q29uc3RydWN0XG4gICAgXSwgQ3N2Q3JlYXRvci5wcm90b3R5cGUsIFwicG9zdENvbnN0cnVjdFwiLCBudWxsKTtcbiAgICBDc3ZDcmVhdG9yID0gX19kZWNvcmF0ZSQxKFtcbiAgICAgICAgQmVhbignY3N2Q3JlYXRvcicpXG4gICAgXSwgQ3N2Q3JlYXRvcik7XG4gICAgcmV0dXJuIENzdkNyZWF0b3I7XG59KEJhc2VDcmVhdG9yKSk7XG5cbnZhciBfX2V4dGVuZHMgPSAodW5kZWZpbmVkICYmIHVuZGVmaW5lZC5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG52YXIgUm93VHlwZTtcbihmdW5jdGlvbiAoUm93VHlwZSkge1xuICAgIFJvd1R5cGVbUm93VHlwZVtcIkhFQURFUl9HUk9VUElOR1wiXSA9IDBdID0gXCJIRUFERVJfR1JPVVBJTkdcIjtcbiAgICBSb3dUeXBlW1Jvd1R5cGVbXCJIRUFERVJcIl0gPSAxXSA9IFwiSEVBREVSXCI7XG4gICAgUm93VHlwZVtSb3dUeXBlW1wiQk9EWVwiXSA9IDJdID0gXCJCT0RZXCI7XG59KShSb3dUeXBlIHx8IChSb3dUeXBlID0ge30pKTtcbnZhciBHcmlkU2VyaWFsaXplciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoR3JpZFNlcmlhbGl6ZXIsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gR3JpZFNlcmlhbGl6ZXIoKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIgIT09IG51bGwgJiYgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG4gICAgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLnNlcmlhbGl6ZSA9IGZ1bmN0aW9uIChncmlkU2VyaWFsaXppbmdTZXNzaW9uLCBwYXJhbXMpIHtcbiAgICAgICAgaWYgKHBhcmFtcyA9PT0gdm9pZCAwKSB7IHBhcmFtcyA9IHt9OyB9XG4gICAgICAgIHZhciBjb2x1bW5zVG9FeHBvcnQgPSB0aGlzLmdldENvbHVtbnNUb0V4cG9ydChwYXJhbXMuYWxsQ29sdW1ucywgcGFyYW1zLmNvbHVtbktleXMpO1xuICAgICAgICB2YXIgc2VyaWFsaXplQ2hhaW4gPSBfLmNvbXBvc2UoXG4gICAgICAgIC8vIGZpcnN0IHBhc3MsIHB1dCBpbiB0aGUgaGVhZGVyIG5hbWVzIG9mIHRoZSBjb2xzXG4gICAgICAgIHRoaXMucHJlcGFyZVNlc3Npb24oY29sdW1uc1RvRXhwb3J0KSwgdGhpcy5wcmVwZW5kQ29udGVudChwYXJhbXMpLCB0aGlzLmV4cG9ydENvbHVtbkdyb3VwcyhwYXJhbXMsIGNvbHVtbnNUb0V4cG9ydCksIHRoaXMuZXhwb3J0SGVhZGVycyhwYXJhbXMsIGNvbHVtbnNUb0V4cG9ydCksIHRoaXMucHJvY2Vzc1Bpbm5lZFRvcFJvd3MocGFyYW1zLCBjb2x1bW5zVG9FeHBvcnQpLCB0aGlzLnByb2Nlc3NSb3dzKHBhcmFtcywgY29sdW1uc1RvRXhwb3J0KSwgdGhpcy5wcm9jZXNzUGlubmVkQm90dG9tUm93cyhwYXJhbXMsIGNvbHVtbnNUb0V4cG9ydCksIHRoaXMuYXBwZW5kQ29udGVudChwYXJhbXMpKTtcbiAgICAgICAgcmV0dXJuIHNlcmlhbGl6ZUNoYWluKGdyaWRTZXJpYWxpemluZ1Nlc3Npb24pLnBhcnNlKCk7XG4gICAgfTtcbiAgICBHcmlkU2VyaWFsaXplci5wcm90b3R5cGUucHJvY2Vzc1JvdyA9IGZ1bmN0aW9uIChncmlkU2VyaWFsaXppbmdTZXNzaW9uLCBwYXJhbXMsIGNvbHVtbnNUb0V4cG9ydCwgbm9kZSkge1xuICAgICAgICB2YXIgcm93U2tpcHBlciA9IHBhcmFtcy5zaG91bGRSb3dCZVNraXBwZWQgfHwgKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGZhbHNlOyB9KTtcbiAgICAgICAgdmFyIGdyaWRPcHRpb25zV3JhcHBlciA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyO1xuICAgICAgICB2YXIgY29udGV4dCA9IGdyaWRPcHRpb25zV3JhcHBlci5nZXRDb250ZXh0KCk7XG4gICAgICAgIHZhciBhcGkgPSBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0QXBpKCk7XG4gICAgICAgIHZhciBjb2x1bW5BcGkgPSBncmlkT3B0aW9uc1dyYXBwZXIuZ2V0Q29sdW1uQXBpKCk7XG4gICAgICAgIHZhciBza2lwU2luZ2xlQ2hpbGRyZW5Hcm91cCA9IGdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwUmVtb3ZlU2luZ2xlQ2hpbGRyZW4oKTtcbiAgICAgICAgdmFyIHNraXBMb3dlc3RTaW5nbGVDaGlsZHJlbkdyb3VwID0gZ3JpZE9wdGlvbnNXcmFwcGVyLmlzR3JvdXBSZW1vdmVMb3dlc3RTaW5nbGVDaGlsZHJlbigpO1xuICAgICAgICAvLyBpZiBvbmx5U2VsZWN0ZWQsIHdlIGlnbm9yZSBncm91cEhpZGVPcGVuUGFyZW50cyBhcyB0aGUgdXNlciBoYXMgZXhwbGljaXRseSBzZWxlY3RlZCB0aGUgcm93cyB0aGV5IHdpc2ggdG8gZXhwb3J0LlxuICAgICAgICAvLyBzaW1pbGFybHksIGlmIHNwZWNpZmljIHJvd05vZGVzIGFyZSBwcm92aWRlZCB3ZSBkbyB0aGUgc2FtZS4gKHRoZSBjbGlwYm9hcmQgc2VydmljZSB1c2VzIHJvd05vZGVzIHRvIGRlZmluZSB3aGljaCByb3dzIHRvIGV4cG9ydClcbiAgICAgICAgdmFyIGlzQ2xpcGJvYXJkRXhwb3J0ID0gcGFyYW1zLnJvd1Bvc2l0aW9ucyAhPSBudWxsO1xuICAgICAgICB2YXIgaXNFeHBsaWNpdEV4cG9ydFNlbGVjdGlvbiA9IGlzQ2xpcGJvYXJkRXhwb3J0IHx8ICEhcGFyYW1zLm9ubHlTZWxlY3RlZDtcbiAgICAgICAgdmFyIGhpZGVPcGVuUGFyZW50cyA9IGdyaWRPcHRpb25zV3JhcHBlci5pc0dyb3VwSGlkZU9wZW5QYXJlbnRzKCkgJiYgIWlzRXhwbGljaXRFeHBvcnRTZWxlY3Rpb247XG4gICAgICAgIHZhciBpc0xlYWZOb2RlID0gdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90TW9kZSgpID8gbm9kZS5sZWFmR3JvdXAgOiAhbm9kZS5ncm91cDtcbiAgICAgICAgdmFyIHNraXBSb3dHcm91cHMgPSBwYXJhbXMuc2tpcEdyb3VwcyB8fCBwYXJhbXMuc2tpcFJvd0dyb3VwcztcbiAgICAgICAgdmFyIHNob3VsZFNraXBMb3dlc3RHcm91cCA9IHNraXBMb3dlc3RTaW5nbGVDaGlsZHJlbkdyb3VwICYmIG5vZGUubGVhZkdyb3VwO1xuICAgICAgICB2YXIgc2hvdWxkU2tpcEN1cnJlbnRHcm91cCA9IG5vZGUuYWxsQ2hpbGRyZW5Db3VudCA9PT0gMSAmJiAoc2tpcFNpbmdsZUNoaWxkcmVuR3JvdXAgfHwgc2hvdWxkU2tpcExvd2VzdEdyb3VwKTtcbiAgICAgICAgaWYgKHNraXBSb3dHcm91cHMgJiYgcGFyYW1zLnNraXBHcm91cHMpIHtcbiAgICAgICAgICAgIF8uZG9PbmNlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnNvbGUud2FybignQUcgR3JpZDogU2luY2UgdjI1LjIgYHNraXBHcm91cHNgIGhhcyBiZWVuIHJlbmFtZWQgdG8gYHNraXBSb3dHcm91cHNgLicpOyB9LCAnZ3JpZFNlcmlhbGl6ZXItc2tpcEdyb3VwcycpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoIWlzTGVhZk5vZGUgJiYgKHBhcmFtcy5za2lwUm93R3JvdXBzIHx8IHNob3VsZFNraXBDdXJyZW50R3JvdXAgfHwgaGlkZU9wZW5QYXJlbnRzKSkgfHxcbiAgICAgICAgICAgIChwYXJhbXMub25seVNlbGVjdGVkICYmICFub2RlLmlzU2VsZWN0ZWQoKSkgfHxcbiAgICAgICAgICAgIChwYXJhbXMuc2tpcFBpbm5lZFRvcCAmJiBub2RlLnJvd1Bpbm5lZCA9PT0gJ3RvcCcpIHx8XG4gICAgICAgICAgICAocGFyYW1zLnNraXBQaW5uZWRCb3R0b20gJiYgbm9kZS5yb3dQaW5uZWQgPT09ICdib3R0b20nKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlIGFyZSBpbiBwaXZvdE1vZGUsIHRoZW4gdGhlIGdyaWQgd2lsbCBzaG93IHRoZSByb290IG5vZGUgb25seVxuICAgICAgICAvLyBpZiBpdCdzIG5vdCBhIGxlYWYgZ3JvdXBcbiAgICAgICAgdmFyIG5vZGVJc1Jvb3ROb2RlID0gbm9kZS5sZXZlbCA9PT0gLTE7XG4gICAgICAgIGlmIChub2RlSXNSb290Tm9kZSAmJiAhbm9kZS5sZWFmR3JvdXAgJiYgKCFub2RlLmZvb3RlciB8fCAhaXNDbGlwYm9hcmRFeHBvcnQpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNob3VsZFJvd0JlU2tpcHBlZCA9IHJvd1NraXBwZXIoeyBub2RlOiBub2RlLCBhcGk6IGFwaSwgY29sdW1uQXBpOiBjb2x1bW5BcGksIGNvbnRleHQ6IGNvbnRleHQgfSk7XG4gICAgICAgIGlmIChzaG91bGRSb3dCZVNraXBwZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcm93QWNjdW11bGF0b3IgPSBncmlkU2VyaWFsaXppbmdTZXNzaW9uLm9uTmV3Qm9keVJvdygpO1xuICAgICAgICBjb2x1bW5zVG9FeHBvcnQuZm9yRWFjaChmdW5jdGlvbiAoY29sdW1uLCBpbmRleCkge1xuICAgICAgICAgICAgcm93QWNjdW11bGF0b3Iub25Db2x1bW4oY29sdW1uLCBpbmRleCwgbm9kZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocGFyYW1zLmdldEN1c3RvbUNvbnRlbnRCZWxvd1Jvdykge1xuICAgICAgICAgICAgdmFyIGNvbnRlbnQgPSBwYXJhbXMuZ2V0Q3VzdG9tQ29udGVudEJlbG93Um93KHsgbm9kZTogbm9kZSwgYXBpOiBhcGksIGNvbHVtbkFwaTogY29sdW1uQXBpLCBjb250ZXh0OiBjb250ZXh0IH0pO1xuICAgICAgICAgICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICBncmlkU2VyaWFsaXppbmdTZXNzaW9uLmFkZEN1c3RvbUNvbnRlbnQoY29udGVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEdyaWRTZXJpYWxpemVyLnByb3RvdHlwZS5hcHBlbmRDb250ZW50ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGdyaWRTZXJpYWxpemluZ1Nlc3Npb24pIHtcbiAgICAgICAgICAgIHZhciBhcHBlbmRDb250ZW50ID0gcGFyYW1zLmN1c3RvbUZvb3RlciB8fCBwYXJhbXMuYXBwZW5kQ29udGVudDtcbiAgICAgICAgICAgIGlmIChhcHBlbmRDb250ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmFtcy5jdXN0b21Gb290ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgXy5kb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBTaW5jZSB2ZXJzaW9uIDI1LjIuMCB0aGUgYGN1c3RvbUZvb3RlcmAgcGFyYW0gaGFzIGJlZW4gZGVwcmVjYXRlZC4gVXNlIGBhcHBlbmRDb250ZW50YCBpbnN0ZWFkLicpOyB9LCAnZ3JpZFNlcmlhbGl6ZXItY3VzdG9tRm9vdGVyJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdyaWRTZXJpYWxpemluZ1Nlc3Npb24uYWRkQ3VzdG9tQ29udGVudChhcHBlbmRDb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBncmlkU2VyaWFsaXppbmdTZXNzaW9uO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLnByZXBlbmRDb250ZW50ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGdyaWRTZXJpYWxpemluZ1Nlc3Npb24pIHtcbiAgICAgICAgICAgIHZhciBwcmVwZW5kQ29udGVudCA9IHBhcmFtcy5jdXN0b21IZWFkZXIgfHwgcGFyYW1zLnByZXBlbmRDb250ZW50O1xuICAgICAgICAgICAgaWYgKHByZXBlbmRDb250ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmFtcy5jdXN0b21IZWFkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgXy5kb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBTaW5jZSB2ZXJzaW9uIDI1LjIuMCB0aGUgYGN1c3RvbUhlYWRlcmAgcGFyYW0gaGFzIGJlZW4gZGVwcmVjYXRlZC4gVXNlIGBwcmVwZW5kQ29udGVudGAgaW5zdGVhZC4nKTsgfSwgJ2dyaWRTZXJpYWxpemVyLWN1c3RvbUhlYWRlcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBncmlkU2VyaWFsaXppbmdTZXNzaW9uLmFkZEN1c3RvbUNvbnRlbnQocHJlcGVuZENvbnRlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGdyaWRTZXJpYWxpemluZ1Nlc3Npb247XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBHcmlkU2VyaWFsaXplci5wcm90b3R5cGUucHJlcGFyZVNlc3Npb24gPSBmdW5jdGlvbiAoY29sdW1uc1RvRXhwb3J0KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbikge1xuICAgICAgICAgICAgZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbi5wcmVwYXJlKGNvbHVtbnNUb0V4cG9ydCk7XG4gICAgICAgICAgICByZXR1cm4gZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbjtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEdyaWRTZXJpYWxpemVyLnByb3RvdHlwZS5leHBvcnRDb2x1bW5Hcm91cHMgPSBmdW5jdGlvbiAocGFyYW1zLCBjb2x1bW5zVG9FeHBvcnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChncmlkU2VyaWFsaXppbmdTZXNzaW9uKSB7XG4gICAgICAgICAgICBpZiAoIXBhcmFtcy5za2lwQ29sdW1uR3JvdXBIZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdyb3VwSW5zdGFuY2VJZENyZWF0b3IgPSBuZXcgR3JvdXBJbnN0YW5jZUlkQ3JlYXRvcigpO1xuICAgICAgICAgICAgICAgIHZhciBkaXNwbGF5ZWRHcm91cHMgPSBfdGhpcy5kaXNwbGF5ZWRHcm91cENyZWF0b3IuY3JlYXRlRGlzcGxheWVkR3JvdXBzKGNvbHVtbnNUb0V4cG9ydCwgX3RoaXMuY29sdW1uTW9kZWwuZ2V0R3JpZEJhbGFuY2VkVHJlZSgpLCBncm91cEluc3RhbmNlSWRDcmVhdG9yLCBudWxsKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZWN1cnNpdmVseUFkZEhlYWRlckdyb3VwcyhkaXNwbGF5ZWRHcm91cHMsIGdyaWRTZXJpYWxpemluZ1Nlc3Npb24sIHBhcmFtcy5wcm9jZXNzR3JvdXBIZWFkZXJDYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChwYXJhbXMuY29sdW1uR3JvdXBzKSB7XG4gICAgICAgICAgICAgICAgXy5kb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBTaW5jZSB2MjUuMiB0aGUgYGNvbHVtbkdyb3Vwc2AgcGFyYW0gaGFzIGRlcHJlY2F0ZWQsIGFuZCBncm91cHMgYXJlIGV4cG9ydGVkIGJ5IGRlZmF1bHQuJyk7IH0sICdncmlkU2VyaWFsaXplci1jb2x1bW5Hcm91cHMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBncmlkU2VyaWFsaXppbmdTZXNzaW9uO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLmV4cG9ydEhlYWRlcnMgPSBmdW5jdGlvbiAocGFyYW1zLCBjb2x1bW5zVG9FeHBvcnQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChncmlkU2VyaWFsaXppbmdTZXNzaW9uKSB7XG4gICAgICAgICAgICBpZiAoIXBhcmFtcy5za2lwSGVhZGVyICYmICFwYXJhbXMuc2tpcENvbHVtbkhlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JpZFJvd0l0ZXJhdG9yXzEgPSBncmlkU2VyaWFsaXppbmdTZXNzaW9uLm9uTmV3SGVhZGVyUm93KCk7XG4gICAgICAgICAgICAgICAgY29sdW1uc1RvRXhwb3J0LmZvckVhY2goZnVuY3Rpb24gKGNvbHVtbiwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JpZFJvd0l0ZXJhdG9yXzEub25Db2x1bW4oY29sdW1uLCBpbmRleCwgdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHBhcmFtcy5za2lwSGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgXy5kb09uY2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29uc29sZS53YXJuKCdBRyBHcmlkOiBTaW5jZSB2MjUuMiB0aGUgYHNraXBIZWFkZXJgIHBhcmFtIGhhcyBiZWVuIHJlbmFtZWQgdG8gYHNraXBDb2x1bW5IZWFkZXJzYC4nKTsgfSwgJ2dyaWRTZXJpYWxpemVyLXNraXBIZWFkZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBncmlkU2VyaWFsaXppbmdTZXNzaW9uO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLnByb2Nlc3NQaW5uZWRUb3BSb3dzID0gZnVuY3Rpb24gKHBhcmFtcywgY29sdW1uc1RvRXhwb3J0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbikge1xuICAgICAgICAgICAgdmFyIHByb2Nlc3NSb3cgPSBfdGhpcy5wcm9jZXNzUm93LmJpbmQoX3RoaXMsIGdyaWRTZXJpYWxpemluZ1Nlc3Npb24sIHBhcmFtcywgY29sdW1uc1RvRXhwb3J0KTtcbiAgICAgICAgICAgIGlmIChwYXJhbXMucm93UG9zaXRpb25zKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zLnJvd1Bvc2l0aW9uc1xuICAgICAgICAgICAgICAgICAgICAvLyBvbmx5IHBpbm5lZFRvcCByb3dzLCBvdGhlciBtb2RlbHMgYXJlIHByb2Nlc3NlZCBieSBgcHJvY2Vzc1Jvd3NgIGFuZCBgcHJvY2Vzc1Bpbm5lZEJvdHRvbXNSb3dzYFxuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uIChwb3NpdGlvbikgeyByZXR1cm4gcG9zaXRpb24ucm93UGlubmVkID09PSAndG9wJzsgfSlcbiAgICAgICAgICAgICAgICAgICAgLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEucm93SW5kZXggLSBiLnJvd0luZGV4OyB9KVxuICAgICAgICAgICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChwb3NpdGlvbikgeyByZXR1cm4gX3RoaXMucGlubmVkUm93TW9kZWwuZ2V0UGlubmVkVG9wUm93KHBvc2l0aW9uLnJvd0luZGV4KTsgfSlcbiAgICAgICAgICAgICAgICAgICAgLmZvckVhY2gocHJvY2Vzc1Jvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5waW5uZWRSb3dNb2RlbC5mb3JFYWNoUGlubmVkVG9wUm93KHByb2Nlc3NSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGdyaWRTZXJpYWxpemluZ1Nlc3Npb247XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBHcmlkU2VyaWFsaXplci5wcm90b3R5cGUucHJvY2Vzc1Jvd3MgPSBmdW5jdGlvbiAocGFyYW1zLCBjb2x1bW5zVG9FeHBvcnQpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChncmlkU2VyaWFsaXppbmdTZXNzaW9uKSB7XG4gICAgICAgICAgICAvLyB3aGVuIGluIHBpdm90IG1vZGUsIHdlIGFsd2F5cyByZW5kZXIgY29scyBvbiBzY3JlZW4sIG5ldmVyICdhbGwgY29sdW1ucydcbiAgICAgICAgICAgIHZhciByb3dNb2RlbCA9IF90aGlzLnJvd01vZGVsO1xuICAgICAgICAgICAgdmFyIHJvd01vZGVsVHlwZSA9IHJvd01vZGVsLmdldFR5cGUoKTtcbiAgICAgICAgICAgIHZhciB1c2luZ0Nzcm0gPSByb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9DTElFTlRfU0lERTtcbiAgICAgICAgICAgIHZhciB1c2luZ1Nzcm0gPSByb3dNb2RlbFR5cGUgPT09IENvbnN0YW50cy5ST1dfTU9ERUxfVFlQRV9TRVJWRVJfU0lERTtcbiAgICAgICAgICAgIHZhciBvbmx5U2VsZWN0ZWROb25TdGFuZGFyZE1vZGVsID0gIXVzaW5nQ3NybSAmJiBwYXJhbXMub25seVNlbGVjdGVkO1xuICAgICAgICAgICAgdmFyIHByb2Nlc3NSb3cgPSBfdGhpcy5wcm9jZXNzUm93LmJpbmQoX3RoaXMsIGdyaWRTZXJpYWxpemluZ1Nlc3Npb24sIHBhcmFtcywgY29sdW1uc1RvRXhwb3J0KTtcbiAgICAgICAgICAgIHZhciBfYSA9IHBhcmFtcy5leHBvcnRlZFJvd3MsIGV4cG9ydGVkUm93cyA9IF9hID09PSB2b2lkIDAgPyAnZmlsdGVyZWRBbmRTb3J0ZWQnIDogX2E7XG4gICAgICAgICAgICBpZiAocGFyYW1zLnJvd1Bvc2l0aW9ucykge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5yb3dQb3NpdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgLy8gcGlubmVkUm93cyBhcmUgcHJvY2Vzc2VkIGJ5IGBwcm9jZXNzUGlubmVkVG9wUm93c2AgYW5kIGBwcm9jZXNzUGlubmVkQm90dG9tc1Jvd3NgXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKHBvc2l0aW9uKSB7IHJldHVybiBwb3NpdGlvbi5yb3dQaW5uZWQgPT0gbnVsbDsgfSlcbiAgICAgICAgICAgICAgICAgICAgLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEucm93SW5kZXggLSBiLnJvd0luZGV4OyB9KVxuICAgICAgICAgICAgICAgICAgICAubWFwKGZ1bmN0aW9uIChwb3NpdGlvbikgeyByZXR1cm4gcm93TW9kZWwuZ2V0Um93KHBvc2l0aW9uLnJvd0luZGV4KTsgfSlcbiAgICAgICAgICAgICAgICAgICAgLmZvckVhY2gocHJvY2Vzc1Jvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChfdGhpcy5jb2x1bW5Nb2RlbC5pc1Bpdm90TW9kZSgpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHVzaW5nQ3NybSkge1xuICAgICAgICAgICAgICAgICAgICByb3dNb2RlbC5mb3JFYWNoUGl2b3ROb2RlKHByb2Nlc3NSb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbXVzdCBiZSBlbnRlcnByaXNlLCBzbyB3ZSBjYW4ganVzdCBsb29wIHRocm91Z2ggYWxsIHRoZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICByb3dNb2RlbC5mb3JFYWNoTm9kZShwcm9jZXNzUm93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBvbmx5U2VsZWN0ZWRBbGxQYWdlczogdXNlciBkb2luZyBwYWdpbmF0aW9uIGFuZCB3YW50cyBzZWxlY3RlZCBpdGVtcyBmcm9tXG4gICAgICAgICAgICAgICAgLy8gb3RoZXIgcGFnZXMsIHNvIGNhbm5vdCB1c2UgdGhlIHN0YW5kYXJkIHJvdyBtb2RlbCBhcyBpdCB3b24ndCBoYXZlIHJvd3MgZnJvbVxuICAgICAgICAgICAgICAgIC8vIG90aGVyIHBhZ2VzLlxuICAgICAgICAgICAgICAgIC8vIG9ubHlTZWxlY3RlZE5vblN0YW5kYXJkTW9kZWw6IGlmIHVzZXIgd2FudHMgc2VsZWN0ZWQgaW4gbm9uIHN0YW5kYXJkIHJvdyBtb2RlbFxuICAgICAgICAgICAgICAgIC8vIChlZyB2aWV3cG9ydCkgdGhlbiBhZ2FpbiBSb3dNb2RlbCBjYW5ub3QgYmUgdXNlZCwgc28gbmVlZCB0byB1c2Ugc2VsZWN0ZWQgaW5zdGVhZC5cbiAgICAgICAgICAgICAgICBpZiAocGFyYW1zLm9ubHlTZWxlY3RlZEFsbFBhZ2VzIHx8IG9ubHlTZWxlY3RlZE5vblN0YW5kYXJkTW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlbGVjdGVkTm9kZXMgPSBfdGhpcy5zZWxlY3Rpb25TZXJ2aWNlLmdldFNlbGVjdGVkTm9kZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWROb2Rlcy5mb3JFYWNoKHByb2Nlc3NSb3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaGVyZSBpcyBldmVyeXRoaW5nIGVsc2UgLSBpbmNsdWRpbmcgc3RhbmRhcmQgcm93IG1vZGVsIGFuZCBzZWxlY3RlZC4gd2UgZG9uJ3QgdXNlXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBzZWxlY3Rpb24gbW9kZWwgZXZlbiB3aGVuIGp1c3QgdXNpbmcgc2VsZWN0ZWQsIHNvIHRoYXQgdGhlIHJlc3VsdCBpcyB0aGUgb3JkZXJcbiAgICAgICAgICAgICAgICAgICAgLy8gb2YgdGhlIHJvd3MgYXBwZWFyaW5nIG9uIHRoZSBzY3JlZW4uXG4gICAgICAgICAgICAgICAgICAgIGlmIChleHBvcnRlZFJvd3MgPT09ICdhbGwnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dNb2RlbC5mb3JFYWNoTm9kZShwcm9jZXNzUm93KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh1c2luZ0Nzcm0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvd01vZGVsLmZvckVhY2hOb2RlQWZ0ZXJGaWx0ZXJBbmRTb3J0KHByb2Nlc3NSb3cpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHVzaW5nU3NybSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93TW9kZWwuZm9yRWFjaE5vZGVBZnRlckZpbHRlckFuZFNvcnQocHJvY2Vzc1Jvdyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dNb2RlbC5mb3JFYWNoTm9kZShwcm9jZXNzUm93KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBncmlkU2VyaWFsaXppbmdTZXNzaW9uO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLnByb2Nlc3NQaW5uZWRCb3R0b21Sb3dzID0gZnVuY3Rpb24gKHBhcmFtcywgY29sdW1uc1RvRXhwb3J0KSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbikge1xuICAgICAgICAgICAgdmFyIHByb2Nlc3NSb3cgPSBfdGhpcy5wcm9jZXNzUm93LmJpbmQoX3RoaXMsIGdyaWRTZXJpYWxpemluZ1Nlc3Npb24sIHBhcmFtcywgY29sdW1uc1RvRXhwb3J0KTtcbiAgICAgICAgICAgIGlmIChwYXJhbXMucm93UG9zaXRpb25zKSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zLnJvd1Bvc2l0aW9uc1xuICAgICAgICAgICAgICAgICAgICAvLyBvbmx5IHBpbm5lZEJvdHRvbSByb3dzLCBvdGhlciBtb2RlbHMgYXJlIHByb2Nlc3NlZCBieSBgcHJvY2Vzc1Jvd3NgIGFuZCBgcHJvY2Vzc1Bpbm5lZFRvcFJvd3NgXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKHBvc2l0aW9uKSB7IHJldHVybiBwb3NpdGlvbi5yb3dQaW5uZWQgPT09ICdib3R0b20nOyB9KVxuICAgICAgICAgICAgICAgICAgICAuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gYS5yb3dJbmRleCAtIGIucm93SW5kZXg7IH0pXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKHBvc2l0aW9uKSB7IHJldHVybiBfdGhpcy5waW5uZWRSb3dNb2RlbC5nZXRQaW5uZWRCb3R0b21Sb3cocG9zaXRpb24ucm93SW5kZXgpOyB9KVxuICAgICAgICAgICAgICAgICAgICAuZm9yRWFjaChwcm9jZXNzUm93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIF90aGlzLnBpbm5lZFJvd01vZGVsLmZvckVhY2hQaW5uZWRCb3R0b21Sb3cocHJvY2Vzc1Jvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbjtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEdyaWRTZXJpYWxpemVyLnByb3RvdHlwZS5nZXRDb2x1bW5zVG9FeHBvcnQgPSBmdW5jdGlvbiAoYWxsQ29sdW1ucywgY29sdW1uS2V5cykge1xuICAgICAgICBpZiAoYWxsQ29sdW1ucyA9PT0gdm9pZCAwKSB7IGFsbENvbHVtbnMgPSBmYWxzZTsgfVxuICAgICAgICB2YXIgaXNQaXZvdE1vZGUgPSB0aGlzLmNvbHVtbk1vZGVsLmlzUGl2b3RNb2RlKCk7XG4gICAgICAgIGlmIChjb2x1bW5LZXlzICYmIGNvbHVtbktleXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb2x1bW5Nb2RlbC5nZXRHcmlkQ29sdW1ucyhjb2x1bW5LZXlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWxsQ29sdW1ucyAmJiAhaXNQaXZvdE1vZGUpIHtcbiAgICAgICAgICAgIC8vIGFkZCBhdXRvIGdyb3VwIGNvbHVtbiBmb3IgdHJlZSBkYXRhXG4gICAgICAgICAgICB2YXIgY29sdW1ucyA9IHRoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmlzVHJlZURhdGEoKVxuICAgICAgICAgICAgICAgID8gdGhpcy5jb2x1bW5Nb2RlbC5nZXRHcmlkQ29sdW1ucyhbQ29uc3RhbnRzLkdST1VQX0FVVE9fQ09MVU1OX0lEXSlcbiAgICAgICAgICAgICAgICA6IFtdO1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbnMuY29uY2F0KHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsUHJpbWFyeUNvbHVtbnMoKSB8fCBbXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uTW9kZWwuZ2V0QWxsRGlzcGxheWVkQ29sdW1ucygpO1xuICAgIH07XG4gICAgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLnJlY3Vyc2l2ZWx5QWRkSGVhZGVyR3JvdXBzID0gZnVuY3Rpb24gKGRpc3BsYXllZEdyb3VwcywgZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbiwgcHJvY2Vzc0dyb3VwSGVhZGVyQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGRpcmVjdENoaWxkcmVuSGVhZGVyR3JvdXBzID0gW107XG4gICAgICAgIGRpc3BsYXllZEdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5Hcm91cENoaWxkKSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uR3JvdXAgPSBjb2x1bW5Hcm91cENoaWxkO1xuICAgICAgICAgICAgaWYgKCFjb2x1bW5Hcm91cC5nZXRDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbHVtbkdyb3VwLmdldENoaWxkcmVuKCkuZm9yRWFjaChmdW5jdGlvbiAoaXQpIHsgcmV0dXJuIGRpcmVjdENoaWxkcmVuSGVhZGVyR3JvdXBzLnB1c2goaXQpOyB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChkaXNwbGF5ZWRHcm91cHMubGVuZ3RoID4gMCAmJiBkaXNwbGF5ZWRHcm91cHNbMF0gaW5zdGFuY2VvZiBDb2x1bW5Hcm91cCkge1xuICAgICAgICAgICAgdGhpcy5kb0FkZEhlYWRlckhlYWRlcihncmlkU2VyaWFsaXppbmdTZXNzaW9uLCBkaXNwbGF5ZWRHcm91cHMsIHByb2Nlc3NHcm91cEhlYWRlckNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGlyZWN0Q2hpbGRyZW5IZWFkZXJHcm91cHMgJiYgZGlyZWN0Q2hpbGRyZW5IZWFkZXJHcm91cHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5yZWN1cnNpdmVseUFkZEhlYWRlckdyb3VwcyhkaXJlY3RDaGlsZHJlbkhlYWRlckdyb3VwcywgZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbiwgcHJvY2Vzc0dyb3VwSGVhZGVyQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBHcmlkU2VyaWFsaXplci5wcm90b3R5cGUuZG9BZGRIZWFkZXJIZWFkZXIgPSBmdW5jdGlvbiAoZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbiwgZGlzcGxheWVkR3JvdXBzLCBwcm9jZXNzR3JvdXBIZWFkZXJDYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZ3JpZFJvd0l0ZXJhdG9yID0gZ3JpZFNlcmlhbGl6aW5nU2Vzc2lvbi5vbk5ld0hlYWRlckdyb3VwaW5nUm93KCk7XG4gICAgICAgIHZhciBjb2x1bW5JbmRleCA9IDA7XG4gICAgICAgIGRpc3BsYXllZEdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChjb2x1bW5Hcm91cENoaWxkKSB7XG4gICAgICAgICAgICB2YXIgY29sdW1uR3JvdXAgPSBjb2x1bW5Hcm91cENoaWxkO1xuICAgICAgICAgICAgdmFyIG5hbWU7XG4gICAgICAgICAgICBpZiAocHJvY2Vzc0dyb3VwSGVhZGVyQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBuYW1lID0gcHJvY2Vzc0dyb3VwSGVhZGVyQ2FsbGJhY2soe1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Hcm91cDogY29sdW1uR3JvdXAsXG4gICAgICAgICAgICAgICAgICAgIGFwaTogX3RoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldEFwaSgpLFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5BcGk6IF90aGlzLmdyaWRPcHRpb25zV3JhcHBlci5nZXRDb2x1bW5BcGkoKSxcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDogX3RoaXMuZ3JpZE9wdGlvbnNXcmFwcGVyLmdldENvbnRleHQoKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbmFtZSA9IF90aGlzLmNvbHVtbk1vZGVsLmdldERpc3BsYXlOYW1lRm9yQ29sdW1uR3JvdXAoY29sdW1uR3JvdXAsICdoZWFkZXInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjb2xsYXBzaWJsZUdyb3VwUmFuZ2VzID0gY29sdW1uR3JvdXAuZ2V0TGVhZkNvbHVtbnMoKS5yZWR1Y2UoZnVuY3Rpb24gKGNvbGxhcHNpYmxlR3JvdXBzLCBjdXJyZW50Q29sdW1uLCBjdXJyZW50SWR4LCBhcnIpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdEdyb3VwID0gXy5sYXN0KGNvbGxhcHNpYmxlR3JvdXBzKTtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBTaG93ID0gY3VycmVudENvbHVtbi5nZXRDb2x1bW5Hcm91cFNob3coKSA9PT0gJ29wZW4nO1xuICAgICAgICAgICAgICAgIGlmICghZ3JvdXBTaG93KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0R3JvdXAgJiYgbGFzdEdyb3VwWzFdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RHcm91cFsxXSA9IGN1cnJlbnRJZHggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFsYXN0R3JvdXAgfHwgbGFzdEdyb3VwWzFdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdyb3VwID0gW2N1cnJlbnRJZHhdO1xuICAgICAgICAgICAgICAgICAgICBjb2xsYXBzaWJsZUdyb3Vwcy5wdXNoKGxhc3RHcm91cCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50SWR4ID09PSBhcnIubGVuZ3RoIC0gMSAmJiBsYXN0R3JvdXAgJiYgbGFzdEdyb3VwWzFdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdyb3VwWzFdID0gY3VycmVudElkeDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbGxhcHNpYmxlR3JvdXBzO1xuICAgICAgICAgICAgfSwgW10pO1xuICAgICAgICAgICAgZ3JpZFJvd0l0ZXJhdG9yLm9uQ29sdW1uKGNvbHVtbkdyb3VwLCBuYW1lIHx8ICcnLCBjb2x1bW5JbmRleCsrLCBjb2x1bW5Hcm91cC5nZXRMZWFmQ29sdW1ucygpLmxlbmd0aCAtIDEsIGNvbGxhcHNpYmxlR3JvdXBSYW5nZXMpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIF9fZGVjb3JhdGUoW1xuICAgICAgICBBdXRvd2lyZWQoJ2Rpc3BsYXllZEdyb3VwQ3JlYXRvcicpXG4gICAgXSwgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLCBcImRpc3BsYXllZEdyb3VwQ3JlYXRvclwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUoW1xuICAgICAgICBBdXRvd2lyZWQoJ2NvbHVtbk1vZGVsJylcbiAgICBdLCBHcmlkU2VyaWFsaXplci5wcm90b3R5cGUsIFwiY29sdW1uTW9kZWxcIiwgdm9pZCAwKTtcbiAgICBfX2RlY29yYXRlKFtcbiAgICAgICAgQXV0b3dpcmVkKCdyb3dNb2RlbCcpXG4gICAgXSwgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLCBcInJvd01vZGVsXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZShbXG4gICAgICAgIEF1dG93aXJlZCgncGlubmVkUm93TW9kZWwnKVxuICAgIF0sIEdyaWRTZXJpYWxpemVyLnByb3RvdHlwZSwgXCJwaW5uZWRSb3dNb2RlbFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUoW1xuICAgICAgICBBdXRvd2lyZWQoJ3NlbGVjdGlvblNlcnZpY2UnKVxuICAgIF0sIEdyaWRTZXJpYWxpemVyLnByb3RvdHlwZSwgXCJzZWxlY3Rpb25TZXJ2aWNlXCIsIHZvaWQgMCk7XG4gICAgX19kZWNvcmF0ZShbXG4gICAgICAgIEF1dG93aXJlZCgncm93UG9zaXRpb25VdGlscycpXG4gICAgXSwgR3JpZFNlcmlhbGl6ZXIucHJvdG90eXBlLCBcInJvd1Bvc2l0aW9uVXRpbHNcIiwgdm9pZCAwKTtcbiAgICBHcmlkU2VyaWFsaXplciA9IF9fZGVjb3JhdGUoW1xuICAgICAgICBCZWFuKFwiZ3JpZFNlcmlhbGl6ZXJcIilcbiAgICBdLCBHcmlkU2VyaWFsaXplcik7XG4gICAgcmV0dXJuIEdyaWRTZXJpYWxpemVyO1xufShCZWFuU3R1YikpO1xuXG52YXIgQ3N2RXhwb3J0TW9kdWxlID0ge1xuICAgIG1vZHVsZU5hbWU6IE1vZHVsZU5hbWVzLkNzdkV4cG9ydE1vZHVsZSxcbiAgICBiZWFuczogW0NzdkNyZWF0b3IsIEdyaWRTZXJpYWxpemVyXVxufTtcblxudmFyIExJTkVfU0VQQVJBVE9SID0gJ1xcclxcbic7XG52YXIgWG1sRmFjdG9yeSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBYbWxGYWN0b3J5KCkge1xuICAgIH1cbiAgICBYbWxGYWN0b3J5LmNyZWF0ZUhlYWRlciA9IGZ1bmN0aW9uIChoZWFkZXJFbGVtZW50KSB7XG4gICAgICAgIGlmIChoZWFkZXJFbGVtZW50ID09PSB2b2lkIDApIHsgaGVhZGVyRWxlbWVudCA9IHt9OyB9XG4gICAgICAgIHZhciBoZWFkZXJTdGFydCA9ICc8Pyc7XG4gICAgICAgIHZhciBoZWFkZXJFbmQgPSAnPz4nO1xuICAgICAgICB2YXIga2V5cyA9IFsndmVyc2lvbiddO1xuICAgICAgICBpZiAoIWhlYWRlckVsZW1lbnQudmVyc2lvbikge1xuICAgICAgICAgICAgaGVhZGVyRWxlbWVudC52ZXJzaW9uID0gXCIxLjBcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGVhZGVyRWxlbWVudC5lbmNvZGluZykge1xuICAgICAgICAgICAga2V5cy5wdXNoKCdlbmNvZGluZycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoZWFkZXJFbGVtZW50LnN0YW5kYWxvbmUpIHtcbiAgICAgICAgICAgIGtleXMucHVzaCgnc3RhbmRhbG9uZScpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhdHQgPSBrZXlzLm1hcChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBrZXkgKyBcIj1cXFwiXCIgKyBoZWFkZXJFbGVtZW50W2tleV0gKyBcIlxcXCJcIjsgfSkuam9pbignICcpO1xuICAgICAgICByZXR1cm4gaGVhZGVyU3RhcnQgKyBcInhtbCBcIiArIGF0dCArIFwiIFwiICsgaGVhZGVyRW5kO1xuICAgIH07XG4gICAgWG1sRmFjdG9yeS5jcmVhdGVYbWwgPSBmdW5jdGlvbiAoeG1sRWxlbWVudCwgYm9vbGVhblRyYW5zZm9ybWVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBwcm9wcyA9ICcnO1xuICAgICAgICBpZiAoeG1sRWxlbWVudC5wcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBpZiAoeG1sRWxlbWVudC5wcm9wZXJ0aWVzLnByZWZpeGVkQXR0cmlidXRlcykge1xuICAgICAgICAgICAgICAgIHhtbEVsZW1lbnQucHJvcGVydGllcy5wcmVmaXhlZEF0dHJpYnV0ZXMuZm9yRWFjaChmdW5jdGlvbiAocHJlZml4ZWRTZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMocHJlZml4ZWRTZXQubWFwKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzICs9IF90aGlzLnJldHVybkF0dHJpYnV0ZUlmUG9wdWxhdGVkKHByZWZpeGVkU2V0LnByZWZpeCArIGtleSwgcHJlZml4ZWRTZXQubWFwW2tleV0sIGJvb2xlYW5UcmFuc2Zvcm1lcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhtbEVsZW1lbnQucHJvcGVydGllcy5yYXdNYXApIHtcbiAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyh4bWxFbGVtZW50LnByb3BlcnRpZXMucmF3TWFwKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgKz0gX3RoaXMucmV0dXJuQXR0cmlidXRlSWZQb3B1bGF0ZWQoa2V5LCB4bWxFbGVtZW50LnByb3BlcnRpZXMucmF3TWFwW2tleV0sIGJvb2xlYW5UcmFuc2Zvcm1lcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJlc3VsdCA9ICc8JyArIHhtbEVsZW1lbnQubmFtZSArIHByb3BzO1xuICAgICAgICBpZiAoIXhtbEVsZW1lbnQuY2hpbGRyZW4gJiYgeG1sRWxlbWVudC50ZXh0Tm9kZSA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJy8+JyArIExJTkVfU0VQQVJBVE9SO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4bWxFbGVtZW50LnRleHROb2RlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnPicgKyB4bWxFbGVtZW50LnRleHROb2RlICsgJzwvJyArIHhtbEVsZW1lbnQubmFtZSArICc+JyArIExJTkVfU0VQQVJBVE9SO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCArPSAnPicgKyBMSU5FX1NFUEFSQVRPUjtcbiAgICAgICAgaWYgKHhtbEVsZW1lbnQuY2hpbGRyZW4pIHtcbiAgICAgICAgICAgIHhtbEVsZW1lbnQuY2hpbGRyZW4uZm9yRWFjaChmdW5jdGlvbiAoaXQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gX3RoaXMuY3JlYXRlWG1sKGl0LCBib29sZWFuVHJhbnNmb3JtZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdCArICc8LycgKyB4bWxFbGVtZW50Lm5hbWUgKyAnPicgKyBMSU5FX1NFUEFSQVRPUjtcbiAgICB9O1xuICAgIFhtbEZhY3RvcnkucmV0dXJuQXR0cmlidXRlSWZQb3B1bGF0ZWQgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSwgYm9vbGVhblRyYW5zZm9ybWVyKSB7XG4gICAgICAgIGlmICghdmFsdWUgJiYgdmFsdWUgIT09ICcnICYmIHZhbHVlICE9PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHhtbFZhbHVlID0gdmFsdWU7XG4gICAgICAgIGlmICgodHlwZW9mICh2YWx1ZSkgPT09ICdib29sZWFuJykpIHtcbiAgICAgICAgICAgIGlmIChib29sZWFuVHJhbnNmb3JtZXIpIHtcbiAgICAgICAgICAgICAgICB4bWxWYWx1ZSA9IGJvb2xlYW5UcmFuc2Zvcm1lcih2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFwiIFwiICsga2V5ICsgXCI9XFxcIlwiICsgeG1sVmFsdWUgKyBcIlxcXCJcIjtcbiAgICB9O1xuICAgIHJldHVybiBYbWxGYWN0b3J5O1xufSgpKTtcblxudmFyIF9fdmFsdWVzID0gKHVuZGVmaW5lZCAmJiB1bmRlZmluZWQuX192YWx1ZXMpIHx8IGZ1bmN0aW9uKG8pIHtcbiAgICB2YXIgcyA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wuaXRlcmF0b3IsIG0gPSBzICYmIG9bc10sIGkgPSAwO1xuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xufTtcbi8vIHRhYmxlIGZvciBjcmMgY2FsY3VsYXRpb25cbi8vIGZyb206IGh0dHBzOi8vcmVmZXJlbmNlc291cmNlLm1pY3Jvc29mdC5jb20vI1N5c3RlbS9zeXMvU3lzdGVtL0lPL2NvbXByZXNzaW9uL0NyYzMySGVscGVyLmNzLDNiMzE5NzhjN2Q3ZjcyNDYscmVmZXJlbmNlc1xudmFyIGNyY1RhYmxlID0gbmV3IFVpbnQzMkFycmF5KFtcbiAgICAweDAwMDAwMDAwLCAweDc3MDczMDk2LCAweGVlMGU2MTJjLCAweDk5MDk1MWJhLCAweDA3NmRjNDE5LCAweDcwNmFmNDhmLFxuICAgIDB4ZTk2M2E1MzUsIDB4OWU2NDk1YTMsIDB4MGVkYjg4MzIsIDB4NzlkY2I4YTQsIDB4ZTBkNWU5MWUsIDB4OTdkMmQ5ODgsXG4gICAgMHgwOWI2NGMyYiwgMHg3ZWIxN2NiZCwgMHhlN2I4MmQwNywgMHg5MGJmMWQ5MSwgMHgxZGI3MTA2NCwgMHg2YWIwMjBmMixcbiAgICAweGYzYjk3MTQ4LCAweDg0YmU0MWRlLCAweDFhZGFkNDdkLCAweDZkZGRlNGViLCAweGY0ZDRiNTUxLCAweDgzZDM4NWM3LFxuICAgIDB4MTM2Yzk4NTYsIDB4NjQ2YmE4YzAsIDB4ZmQ2MmY5N2EsIDB4OGE2NWM5ZWMsIDB4MTQwMTVjNGYsIDB4NjMwNjZjZDksXG4gICAgMHhmYTBmM2Q2MywgMHg4ZDA4MGRmNSwgMHgzYjZlMjBjOCwgMHg0YzY5MTA1ZSwgMHhkNTYwNDFlNCwgMHhhMjY3NzE3MixcbiAgICAweDNjMDNlNGQxLCAweDRiMDRkNDQ3LCAweGQyMGQ4NWZkLCAweGE1MGFiNTZiLCAweDM1YjVhOGZhLCAweDQyYjI5ODZjLFxuICAgIDB4ZGJiYmM5ZDYsIDB4YWNiY2Y5NDAsIDB4MzJkODZjZTMsIDB4NDVkZjVjNzUsIDB4ZGNkNjBkY2YsIDB4YWJkMTNkNTksXG4gICAgMHgyNmQ5MzBhYywgMHg1MWRlMDAzYSwgMHhjOGQ3NTE4MCwgMHhiZmQwNjExNiwgMHgyMWI0ZjRiNSwgMHg1NmIzYzQyMyxcbiAgICAweGNmYmE5NTk5LCAweGI4YmRhNTBmLCAweDI4MDJiODllLCAweDVmMDU4ODA4LCAweGM2MGNkOWIyLCAweGIxMGJlOTI0LFxuICAgIDB4MmY2ZjdjODcsIDB4NTg2ODRjMTEsIDB4YzE2MTFkYWIsIDB4YjY2NjJkM2QsIDB4NzZkYzQxOTAsIDB4MDFkYjcxMDYsXG4gICAgMHg5OGQyMjBiYywgMHhlZmQ1MTAyYSwgMHg3MWIxODU4OSwgMHgwNmI2YjUxZiwgMHg5ZmJmZTRhNSwgMHhlOGI4ZDQzMyxcbiAgICAweDc4MDdjOWEyLCAweDBmMDBmOTM0LCAweDk2MDlhODhlLCAweGUxMGU5ODE4LCAweDdmNmEwZGJiLCAweDA4NmQzZDJkLFxuICAgIDB4OTE2NDZjOTcsIDB4ZTY2MzVjMDEsIDB4NmI2YjUxZjQsIDB4MWM2YzYxNjIsIDB4ODU2NTMwZDgsIDB4ZjI2MjAwNGUsXG4gICAgMHg2YzA2OTVlZCwgMHgxYjAxYTU3YiwgMHg4MjA4ZjRjMSwgMHhmNTBmYzQ1NywgMHg2NWIwZDljNiwgMHgxMmI3ZTk1MCxcbiAgICAweDhiYmViOGVhLCAweGZjYjk4ODdjLCAweDYyZGQxZGRmLCAweDE1ZGEyZDQ5LCAweDhjZDM3Y2YzLCAweGZiZDQ0YzY1LFxuICAgIDB4NGRiMjYxNTgsIDB4M2FiNTUxY2UsIDB4YTNiYzAwNzQsIDB4ZDRiYjMwZTIsIDB4NGFkZmE1NDEsIDB4M2RkODk1ZDcsXG4gICAgMHhhNGQxYzQ2ZCwgMHhkM2Q2ZjRmYiwgMHg0MzY5ZTk2YSwgMHgzNDZlZDlmYywgMHhhZDY3ODg0NiwgMHhkYTYwYjhkMCxcbiAgICAweDQ0MDQyZDczLCAweDMzMDMxZGU1LCAweGFhMGE0YzVmLCAweGRkMGQ3Y2M5LCAweDUwMDU3MTNjLCAweDI3MDI0MWFhLFxuICAgIDB4YmUwYjEwMTAsIDB4YzkwYzIwODYsIDB4NTc2OGI1MjUsIDB4MjA2Zjg1YjMsIDB4Yjk2NmQ0MDksIDB4Y2U2MWU0OWYsXG4gICAgMHg1ZWRlZjkwZSwgMHgyOWQ5Yzk5OCwgMHhiMGQwOTgyMiwgMHhjN2Q3YThiNCwgMHg1OWIzM2QxNywgMHgyZWI0MGQ4MSxcbiAgICAweGI3YmQ1YzNiLCAweGMwYmE2Y2FkLCAweGVkYjg4MzIwLCAweDlhYmZiM2I2LCAweDAzYjZlMjBjLCAweDc0YjFkMjlhLFxuICAgIDB4ZWFkNTQ3MzksIDB4OWRkMjc3YWYsIDB4MDRkYjI2MTUsIDB4NzNkYzE2ODMsIDB4ZTM2MzBiMTIsIDB4OTQ2NDNiODQsXG4gICAgMHgwZDZkNmEzZSwgMHg3YTZhNWFhOCwgMHhlNDBlY2YwYiwgMHg5MzA5ZmY5ZCwgMHgwYTAwYWUyNywgMHg3ZDA3OWViMSxcbiAgICAweGYwMGY5MzQ0LCAweDg3MDhhM2QyLCAweDFlMDFmMjY4LCAweDY5MDZjMmZlLCAweGY3NjI1NzVkLCAweDgwNjU2N2NiLFxuICAgIDB4MTk2YzM2NzEsIDB4NmU2YjA2ZTcsIDB4ZmVkNDFiNzYsIDB4ODlkMzJiZTAsIDB4MTBkYTdhNWEsIDB4NjdkZDRhY2MsXG4gICAgMHhmOWI5ZGY2ZiwgMHg4ZWJlZWZmOSwgMHgxN2I3YmU0MywgMHg2MGIwOGVkNSwgMHhkNmQ2YTNlOCwgMHhhMWQxOTM3ZSxcbiAgICAweDM4ZDhjMmM0LCAweDRmZGZmMjUyLCAweGQxYmI2N2YxLCAweGE2YmM1NzY3LCAweDNmYjUwNmRkLCAweDQ4YjIzNjRiLFxuICAgIDB4ZDgwZDJiZGEsIDB4YWYwYTFiNGMsIDB4MzYwMzRhZjYsIDB4NDEwNDdhNjAsIDB4ZGY2MGVmYzMsIDB4YTg2N2RmNTUsXG4gICAgMHgzMTZlOGVlZiwgMHg0NjY5YmU3OSwgMHhjYjYxYjM4YywgMHhiYzY2ODMxYSwgMHgyNTZmZDJhMCwgMHg1MjY4ZTIzNixcbiAgICAweGNjMGM3Nzk1LCAweGJiMGI0NzAzLCAweDIyMDIxNmI5LCAweDU1MDUyNjJmLCAweGM1YmEzYmJlLCAweGIyYmQwYjI4LFxuICAgIDB4MmJiNDVhOTIsIDB4NWNiMzZhMDQsIDB4YzJkN2ZmYTcsIDB4YjVkMGNmMzEsIDB4MmNkOTllOGIsIDB4NWJkZWFlMWQsXG4gICAgMHg5YjY0YzJiMCwgMHhlYzYzZjIyNiwgMHg3NTZhYTM5YywgMHgwMjZkOTMwYSwgMHg5YzA5MDZhOSwgMHhlYjBlMzYzZixcbiAgICAweDcyMDc2Nzg1LCAweDA1MDA1NzEzLCAweDk1YmY0YTgyLCAweGUyYjg3YTE0LCAweDdiYjEyYmFlLCAweDBjYjYxYjM4LFxuICAgIDB4OTJkMjhlOWIsIDB4ZTVkNWJlMGQsIDB4N2NkY2VmYjcsIDB4MGJkYmRmMjEsIDB4ODZkM2QyZDQsIDB4ZjFkNGUyNDIsXG4gICAgMHg2OGRkYjNmOCwgMHgxZmRhODM2ZSwgMHg4MWJlMTZjZCwgMHhmNmI5MjY1YiwgMHg2ZmIwNzdlMSwgMHgxOGI3NDc3NyxcbiAgICAweDg4MDg1YWU2LCAweGZmMGY2YTcwLCAweDY2MDYzYmNhLCAweDExMDEwYjVjLCAweDhmNjU5ZWZmLCAweGY4NjJhZTY5LFxuICAgIDB4NjE2YmZmZDMsIDB4MTY2Y2NmNDUsIDB4YTAwYWUyNzgsIDB4ZDcwZGQyZWUsIDB4NGUwNDgzNTQsIDB4MzkwM2IzYzIsXG4gICAgMHhhNzY3MjY2MSwgMHhkMDYwMTZmNywgMHg0OTY5NDc0ZCwgMHgzZTZlNzdkYiwgMHhhZWQxNmE0YSwgMHhkOWQ2NWFkYyxcbiAgICAweDQwZGYwYjY2LCAweDM3ZDgzYmYwLCAweGE5YmNhZTUzLCAweGRlYmI5ZWM1LCAweDQ3YjJjZjdmLCAweDMwYjVmZmU5LFxuICAgIDB4YmRiZGYyMWMsIDB4Y2FiYWMyOGEsIDB4NTNiMzkzMzAsIDB4MjRiNGEzYTYsIDB4YmFkMDM2MDUsIDB4Y2RkNzA2OTMsXG4gICAgMHg1NGRlNTcyOSwgMHgyM2Q5NjdiZiwgMHhiMzY2N2EyZSwgMHhjNDYxNGFiOCwgMHg1ZDY4MWIwMiwgMHgyYTZmMmI5NCxcbiAgICAweGI0MGJiZTM3LCAweGMzMGM4ZWExLCAweDVhMDVkZjFiLCAweDJkMDJlZjhkXG5dKTtcbnZhciBaaXBDb250YWluZXIgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gWmlwQ29udGFpbmVyKCkge1xuICAgIH1cbiAgICBaaXBDb250YWluZXIuYWRkRm9sZGVycyA9IGZ1bmN0aW9uIChwYXRocykge1xuICAgICAgICBwYXRocy5mb3JFYWNoKHRoaXMuYWRkRm9sZGVyLmJpbmQodGhpcykpO1xuICAgIH07XG4gICAgWmlwQ29udGFpbmVyLmFkZEZvbGRlciA9IGZ1bmN0aW9uIChwYXRoKSB7XG4gICAgICAgIHRoaXMuZm9sZGVycy5wdXNoKHtcbiAgICAgICAgICAgIHBhdGg6IHBhdGgsXG4gICAgICAgICAgICBjcmVhdGVkOiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgaXNCYXNlNjQ6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgWmlwQ29udGFpbmVyLmFkZEZpbGUgPSBmdW5jdGlvbiAocGF0aCwgY29udGVudCwgaXNCYXNlNjQpIHtcbiAgICAgICAgaWYgKGlzQmFzZTY0ID09PSB2b2lkIDApIHsgaXNCYXNlNjQgPSBmYWxzZTsgfVxuICAgICAgICB0aGlzLmZpbGVzLnB1c2goe1xuICAgICAgICAgICAgcGF0aDogcGF0aCxcbiAgICAgICAgICAgIGNyZWF0ZWQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICBjb250ZW50OiBjb250ZW50LFxuICAgICAgICAgICAgaXNCYXNlNjQ6IGlzQmFzZTY0XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgWmlwQ29udGFpbmVyLmdldENvbnRlbnQgPSBmdW5jdGlvbiAobWltZVR5cGUpIHtcbiAgICAgICAgaWYgKG1pbWVUeXBlID09PSB2b2lkIDApIHsgbWltZVR5cGUgPSAnYXBwbGljYXRpb24vemlwJzsgfVxuICAgICAgICB2YXIgdGV4dE91dHB1dCA9IHRoaXMuYnVpbGRGaWxlU3RyZWFtKCk7XG4gICAgICAgIHZhciB1SW50OE91dHB1dCA9IHRoaXMuYnVpbGRVaW50OEFycmF5KHRleHRPdXRwdXQpO1xuICAgICAgICB0aGlzLmNsZWFyU3RyZWFtKCk7XG4gICAgICAgIHJldHVybiBuZXcgQmxvYihbdUludDhPdXRwdXRdLCB7IHR5cGU6IG1pbWVUeXBlIH0pO1xuICAgIH07XG4gICAgWmlwQ29udGFpbmVyLmNsZWFyU3RyZWFtID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZvbGRlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5maWxlcyA9IFtdO1xuICAgIH07XG4gICAgWmlwQ29udGFpbmVyLmJ1aWxkRmlsZVN0cmVhbSA9IGZ1bmN0aW9uIChmRGF0YSkge1xuICAgICAgICB2YXIgZV8xLCBfYTtcbiAgICAgICAgaWYgKGZEYXRhID09PSB2b2lkIDApIHsgZkRhdGEgPSAnJzsgfVxuICAgICAgICB2YXIgdG90YWxGaWxlcyA9IHRoaXMuZm9sZGVycy5jb25jYXQodGhpcy5maWxlcyk7XG4gICAgICAgIHZhciBsZW4gPSB0b3RhbEZpbGVzLmxlbmd0aDtcbiAgICAgICAgdmFyIGZvRGF0YSA9ICcnO1xuICAgICAgICB2YXIgbEwgPSAwO1xuICAgICAgICB2YXIgY0wgPSAwO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yICh2YXIgdG90YWxGaWxlc18xID0gX192YWx1ZXModG90YWxGaWxlcyksIHRvdGFsRmlsZXNfMV8xID0gdG90YWxGaWxlc18xLm5leHQoKTsgIXRvdGFsRmlsZXNfMV8xLmRvbmU7IHRvdGFsRmlsZXNfMV8xID0gdG90YWxGaWxlc18xLm5leHQoKSkge1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50RmlsZSA9IHRvdGFsRmlsZXNfMV8xLnZhbHVlO1xuICAgICAgICAgICAgICAgIHZhciBfYiA9IHRoaXMuZ2V0SGVhZGVyKGN1cnJlbnRGaWxlLCBsTCksIGZpbGVIZWFkZXIgPSBfYi5maWxlSGVhZGVyLCBmb2xkZXJIZWFkZXIgPSBfYi5mb2xkZXJIZWFkZXIsIGNvbnRlbnQgPSBfYi5jb250ZW50O1xuICAgICAgICAgICAgICAgIGxMICs9IGZpbGVIZWFkZXIubGVuZ3RoICsgY29udGVudC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY0wgKz0gZm9sZGVySGVhZGVyLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmRGF0YSArPSBmaWxlSGVhZGVyICsgY29udGVudDtcbiAgICAgICAgICAgICAgICBmb0RhdGEgKz0gZm9sZGVySGVhZGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlXzFfMSkgeyBlXzEgPSB7IGVycm9yOiBlXzFfMSB9OyB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodG90YWxGaWxlc18xXzEgJiYgIXRvdGFsRmlsZXNfMV8xLmRvbmUgJiYgKF9hID0gdG90YWxGaWxlc18xLnJldHVybikpIF9hLmNhbGwodG90YWxGaWxlc18xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkgeyBpZiAoZV8xKSB0aHJvdyBlXzEuZXJyb3I7IH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgZm9FbmQgPSB0aGlzLmJ1aWxkRm9sZGVyRW5kKGxlbiwgY0wsIGxMKTtcbiAgICAgICAgcmV0dXJuIGZEYXRhICsgZm9EYXRhICsgZm9FbmQ7XG4gICAgfTtcbiAgICBaaXBDb250YWluZXIuZ2V0SGVhZGVyID0gZnVuY3Rpb24gKGN1cnJlbnRGaWxlLCBvZmZzZXQpIHtcbiAgICAgICAgdmFyIGNvbnRlbnQgPSBjdXJyZW50RmlsZS5jb250ZW50LCBwYXRoID0gY3VycmVudEZpbGUucGF0aCwgY3JlYXRlZCA9IGN1cnJlbnRGaWxlLmNyZWF0ZWQsIGlzQmFzZTY0ID0gY3VycmVudEZpbGUuaXNCYXNlNjQ7XG4gICAgICAgIHZhciB1dGY4X2VuY29kZSA9IF8udXRmOF9lbmNvZGUsIGRlY1RvSGV4ID0gXy5kZWNUb0hleDtcbiAgICAgICAgdmFyIHV0ZlBhdGggPSB1dGY4X2VuY29kZShwYXRoKTtcbiAgICAgICAgdmFyIGlzVVRGOCA9IHV0ZlBhdGggIT09IHBhdGg7XG4gICAgICAgIHZhciB0aW1lID0gdGhpcy5jb252ZXJ0VGltZShjcmVhdGVkKTtcbiAgICAgICAgdmFyIGR0ID0gdGhpcy5jb252ZXJ0RGF0ZShjcmVhdGVkKTtcbiAgICAgICAgdmFyIGV4dHJhRmllbGRzID0gJyc7XG4gICAgICAgIGlmIChpc1VURjgpIHtcbiAgICAgICAgICAgIHZhciB1RXh0cmFGaWVsZFBhdGggPSBkZWNUb0hleCgxLCAxKSArIGRlY1RvSGV4KHRoaXMuZ2V0RnJvbUNyYzMyVGFibGUodXRmUGF0aCksIDQpICsgdXRmUGF0aDtcbiAgICAgICAgICAgIGV4dHJhRmllbGRzID0gXCJcXHg3NVxceDcwXCIgKyBkZWNUb0hleCh1RXh0cmFGaWVsZFBhdGgubGVuZ3RoLCAyKSArIHVFeHRyYUZpZWxkUGF0aDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgX2EgPSAhY29udGVudCA/IHsgc2l6ZTogMCwgY29udGVudDogJycgfSA6IHRoaXMuZ2V0Q29udmVydGVkQ29udGVudChjb250ZW50LCBpc0Jhc2U2NCksIHNpemUgPSBfYS5zaXplLCBjb252ZXJ0ZWRDb250ZW50ID0gX2EuY29udGVudDtcbiAgICAgICAgdmFyIGhlYWRlciA9ICdcXHgwQVxceDAwJyArXG4gICAgICAgICAgICAoaXNVVEY4ID8gJ1xceDAwXFx4MDgnIDogJ1xceDAwXFx4MDAnKSArXG4gICAgICAgICAgICAnXFx4MDBcXHgwMCcgK1xuICAgICAgICAgICAgZGVjVG9IZXgodGltZSwgMikgKyAvLyBsYXN0IG1vZGlmaWVkIHRpbWVcbiAgICAgICAgICAgIGRlY1RvSGV4KGR0LCAyKSArIC8vIGxhc3QgbW9kaWZpZWQgZGF0ZVxuICAgICAgICAgICAgZGVjVG9IZXgoc2l6ZSA/IHRoaXMuZ2V0RnJvbUNyYzMyVGFibGUoY29udmVydGVkQ29udGVudCkgOiAwLCA0KSArXG4gICAgICAgICAgICBkZWNUb0hleChzaXplLCA0KSArIC8vIGNvbXByZXNzZWQgc2l6ZVxuICAgICAgICAgICAgZGVjVG9IZXgoc2l6ZSwgNCkgKyAvLyB1bmNvbXByZXNzZWQgc2l6ZVxuICAgICAgICAgICAgZGVjVG9IZXgodXRmUGF0aC5sZW5ndGgsIDIpICsgLy8gZmlsZSBuYW1lIGxlbmd0aFxuICAgICAgICAgICAgZGVjVG9IZXgoZXh0cmFGaWVsZHMubGVuZ3RoLCAyKTsgLy8gZXh0cmEgZmllbGQgbGVuZ3RoXG4gICAgICAgIHZhciBmaWxlSGVhZGVyID0gJ1BLXFx4MDNcXHgwNCcgKyBoZWFkZXIgKyB1dGZQYXRoICsgZXh0cmFGaWVsZHM7XG4gICAgICAgIHZhciBmb2xkZXJIZWFkZXIgPSAnUEtcXHgwMVxceDAyJyArIC8vIGNlbnRyYWwgaGVhZGVyXG4gICAgICAgICAgICAnXFx4MTRcXHgwMCcgK1xuICAgICAgICAgICAgaGVhZGVyICsgLy8gZmlsZSBoZWFkZXJcbiAgICAgICAgICAgICdcXHgwMFxceDAwJyArXG4gICAgICAgICAgICAnXFx4MDBcXHgwMCcgK1xuICAgICAgICAgICAgJ1xceDAwXFx4MDAnICtcbiAgICAgICAgICAgIChjb250ZW50ID8gJ1xceDAwXFx4MDBcXHgwMFxceDAwJyA6ICdcXHgxMFxceDAwXFx4MDBcXHgwMCcpICsgLy8gZXh0ZXJuYWwgZmlsZSBhdHRyaWJ1dGVzXG4gICAgICAgICAgICBkZWNUb0hleChvZmZzZXQsIDQpICsgLy8gcmVsYXRpdmUgb2Zmc2V0IG9mIGxvY2FsIGhlYWRlclxuICAgICAgICAgICAgdXRmUGF0aCArIC8vIGZpbGUgbmFtZVxuICAgICAgICAgICAgZXh0cmFGaWVsZHM7IC8vIGV4dHJhIGZpZWxkXG4gICAgICAgIHJldHVybiB7IGZpbGVIZWFkZXI6IGZpbGVIZWFkZXIsIGZvbGRlckhlYWRlcjogZm9sZGVySGVhZGVyLCBjb250ZW50OiBjb252ZXJ0ZWRDb250ZW50IHx8ICcnIH07XG4gICAgfTtcbiAgICBaaXBDb250YWluZXIuZ2V0Q29udmVydGVkQ29udGVudCA9IGZ1bmN0aW9uIChjb250ZW50LCBpc0Jhc2U2NCkge1xuICAgICAgICBpZiAoaXNCYXNlNjQgPT09IHZvaWQgMCkgeyBpc0Jhc2U2NCA9IGZhbHNlOyB9XG4gICAgICAgIGlmIChpc0Jhc2U2NCkge1xuICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc3BsaXQoJztiYXNlNjQsJylbMV07XG4gICAgICAgIH1cbiAgICAgICAgY29udGVudCA9IGlzQmFzZTY0ID8gYXRvYihjb250ZW50KSA6IGNvbnRlbnQ7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzaXplOiBjb250ZW50Lmxlbmd0aCxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGNvbnRlbnRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIFppcENvbnRhaW5lci5idWlsZEZvbGRlckVuZCA9IGZ1bmN0aW9uICh0TGVuLCBjTGVuLCBsTGVuKSB7XG4gICAgICAgIHZhciBkZWNUb0hleCA9IF8uZGVjVG9IZXg7XG4gICAgICAgIHJldHVybiAnUEtcXHgwNVxceDA2JyArIC8vIGNlbnRyYWwgZm9sZGVyIGVuZFxuICAgICAgICAgICAgJ1xceDAwXFx4MDAnICtcbiAgICAgICAgICAgICdcXHgwMFxceDAwJyArXG4gICAgICAgICAgICBkZWNUb0hleCh0TGVuLCAyKSArIC8vIHRvdGFsIG51bWJlciBvZiBlbnRyaWVzIGluIHRoZSBjZW50cmFsIGZvbGRlclxuICAgICAgICAgICAgZGVjVG9IZXgodExlbiwgMikgKyAvLyB0b3RhbCBudW1iZXIgb2YgZW50cmllcyBpbiB0aGUgY2VudHJhbCBmb2xkZXJcbiAgICAgICAgICAgIGRlY1RvSGV4KGNMZW4sIDQpICsgLy8gc2l6ZSBvZiB0aGUgY2VudHJhbCBmb2xkZXJcbiAgICAgICAgICAgIGRlY1RvSGV4KGxMZW4sIDQpICsgLy8gY2VudHJhbCBmb2xkZXIgc3RhcnQgb2Zmc2V0XG4gICAgICAgICAgICAnXFx4MDBcXHgwMCc7XG4gICAgfTtcbiAgICBaaXBDb250YWluZXIuYnVpbGRVaW50OEFycmF5ID0gZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAgICAgICAgdmFyIHVpbnQ4ID0gbmV3IFVpbnQ4QXJyYXkoY29udGVudC5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVpbnQ4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB1aW50OFtpXSA9IGNvbnRlbnQuY2hhckNvZGVBdChpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdWludDg7XG4gICAgfTtcbiAgICBaaXBDb250YWluZXIuZ2V0RnJvbUNyYzMyVGFibGUgPSBmdW5jdGlvbiAoY29udGVudCkge1xuICAgICAgICBpZiAoIWNvbnRlbnQubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2l6ZSA9IGNvbnRlbnQubGVuZ3RoO1xuICAgICAgICB2YXIgaXRlcmFibGUgPSBuZXcgVWludDhBcnJheShzaXplKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgIGl0ZXJhYmxlW2ldID0gY29udGVudC5jaGFyQ29kZUF0KGkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjcmMgPSAwIF4gKC0xKTtcbiAgICAgICAgdmFyIGogPSAwO1xuICAgICAgICB2YXIgayA9IDA7XG4gICAgICAgIHZhciBsID0gMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgIGogPSBpdGVyYWJsZVtpXTtcbiAgICAgICAgICAgIGsgPSAoY3JjIF4gaikgJiAweEZGO1xuICAgICAgICAgICAgbCA9IGNyY1RhYmxlW2tdO1xuICAgICAgICAgICAgY3JjID0gKGNyYyA+Pj4gOCkgXiBsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjcmMgXiAoLTEpO1xuICAgIH07XG4gICAgWmlwQ29udGFpbmVyLmNvbnZlcnRUaW1lID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgdmFyIHRpbWUgPSBkYXRlLmdldEhvdXJzKCk7XG4gICAgICAgIHRpbWUgPDw9IDY7XG4gICAgICAgIHRpbWUgPSB0aW1lIHwgZGF0ZS5nZXRNaW51dGVzKCk7XG4gICAgICAgIHRpbWUgPDw9IDU7XG4gICAgICAgIHRpbWUgPSB0aW1lIHwgZGF0ZS5nZXRTZWNvbmRzKCkgLyAyO1xuICAgICAgICByZXR1cm4gdGltZTtcbiAgICB9O1xuICAgIFppcENvbnRhaW5lci5jb252ZXJ0RGF0ZSA9IGZ1bmN0aW9uIChkYXRlKSB7XG4gICAgICAgIHZhciBkdCA9IGRhdGUuZ2V0RnVsbFllYXIoKSAtIDE5ODA7XG4gICAgICAgIGR0IDw8PSA0O1xuICAgICAgICBkdCA9IGR0IHwgKGRhdGUuZ2V0TW9udGgoKSArIDEpO1xuICAgICAgICBkdCA8PD0gNTtcbiAgICAgICAgZHQgPSBkdCB8IGRhdGUuZ2V0RGF0ZSgpO1xuICAgICAgICByZXR1cm4gZHQ7XG4gICAgfTtcbiAgICBaaXBDb250YWluZXIuZm9sZGVycyA9IFtdO1xuICAgIFppcENvbnRhaW5lci5maWxlcyA9IFtdO1xuICAgIHJldHVybiBaaXBDb250YWluZXI7XG59KCkpO1xuXG52YXIgQWxsQ29tbXVuaXR5TW9kdWxlcyA9IFtDbGllbnRTaWRlUm93TW9kZWxNb2R1bGUsIEluZmluaXRlUm93TW9kZWxNb2R1bGUsIENzdkV4cG9ydE1vZHVsZV07XG5cbk1vZHVsZVJlZ2lzdHJ5LnJlZ2lzdGVyTW9kdWxlcyhBbGxDb21tdW5pdHlNb2R1bGVzKTtcblxuZXhwb3J0IHsgQWJzdHJhY3RIZWFkZXJDZWxsQ3RybCwgQWdBYnN0cmFjdEZpZWxkLCBBZ0FuZ2xlU2VsZWN0LCBBZ0NoZWNrYm94LCBBZ0NvbG9yUGlja2VyLCBBZ0RpYWxvZywgQWdHcm91cENvbXBvbmVudCwgQWdJbnB1dE51bWJlckZpZWxkLCBBZ0lucHV0UmFuZ2UsIEFnSW5wdXRUZXh0QXJlYSwgQWdJbnB1dFRleHRGaWVsZCwgQWdNZW51SXRlbUNvbXBvbmVudCwgQWdNZW51TGlzdCwgQWdNZW51UGFuZWwsIEFnUGFuZWwsIEFnUHJvbWlzZSwgQWdQcm9taXNlU3RhdHVzLCBBZ1JhZGlvQnV0dG9uLCBBZ1NlbGVjdCwgQWdTbGlkZXIsIEFnU3RhY2tDb21wb25lbnRzUmVnaXN0cnksIEFnVG9nZ2xlQnV0dG9uLCBBbGlnbmVkR3JpZHNTZXJ2aWNlLCBBbGxDb21tdW5pdHlNb2R1bGVzLCBBbmltYXRlU2hvd0NoYW5nZUNlbGxSZW5kZXJlciwgQW5pbWF0ZVNsaWRlQ2VsbFJlbmRlcmVyLCBBbmltYXRpb25GcmFtZVNlcnZpY2UsIEF1dG9TY3JvbGxTZXJ2aWNlLCBBdXRvV2lkdGhDYWxjdWxhdG9yLCBBdXRvd2lyZWQsIEJhckNvbHVtbkxhYmVsUGxhY2VtZW50LCBCYXNlQ29tcG9uZW50V3JhcHBlciwgQmFzZUNyZWF0b3IsIEJhc2VHcmlkU2VyaWFsaXppbmdTZXNzaW9uLCBCZWFuLCBCZWFuU3R1YiwgQmVhbnMsIEJvZHlEcm9wUGl2b3RUYXJnZXQsIEJvZHlEcm9wVGFyZ2V0LCBDSEFSVF9UT09MQkFSX0FMTE9XX0xJU1QsIENIQVJUX1RPT0xfUEFORUxfQUxMT1dfTElTVCwgQ0hBUlRfVE9PTF9QQU5FTF9NRU5VX09QVElPTlMsIENlbGxDb21wLCBDZWxsQ3RybCwgQ2VsbE5hdmlnYXRpb25TZXJ2aWNlLCBDZWxsUG9zaXRpb25VdGlscywgQ2VsbFJhbmdlVHlwZSwgQ2hhbmdlZFBhdGgsIENoZWNrYm94U2VsZWN0aW9uQ29tcG9uZW50LCBDbGllbnRTaWRlUm93TW9kZWxNb2R1bGUsIENsaWVudFNpZGVSb3dNb2RlbFN0ZXBzLCBDb2xEZWZVdGlsLCBDb2xvciwgQ29sdW1uLCBDb2x1bW5BcGksIENvbHVtbkZhY3RvcnksIENvbHVtbkdyb3VwLCBDb2x1bW5LZXlDcmVhdG9yLCBDb2x1bW5Nb2RlbCwgQ29sdW1uVXRpbHMsIENvbXBvbmVudCwgQ29tcG9uZW50VXRpbCwgQ29uc3RhbnRzLCBDb250ZXh0LCBDc3NDbGFzc0FwcGxpZXIsIENzc0NsYXNzTWFuYWdlciwgQ3N2Q3JlYXRvciwgQ3N2RXhwb3J0TW9kdWxlLCBDdHJsc1NlcnZpY2UsIEN1c3RvbVRvb2x0aXBGZWF0dXJlLCBERUZBVUxUX0NIQVJUX0dST1VQUywgRGF0ZUZpbHRlciwgRGlzcGxheWVkR3JvdXBDcmVhdG9yLCBEb3dubG9hZGVyLCBEcmFnQW5kRHJvcFNlcnZpY2UsIERyYWdTZXJ2aWNlLCBEcmFnU291cmNlVHlwZSwgRW52aXJvbm1lbnQsIEV2ZW50U2VydmljZSwgRXZlbnRzLCBFeGNlbEZhY3RvcnlNb2RlLCBFeHByZXNzaW9uU2VydmljZSwgRmlsdGVyTWFuYWdlciwgRmxvYXRpbmdGaWx0ZXJNYXBwZXIsIEZvY3VzU2VydmljZSwgR3JpZCwgR3JpZEFwaSwgR3JpZEJvZHlDb21wLCBHcmlkQm9keUN0cmwsIEdyaWRDb21wLCBHcmlkQ29yZUNyZWF0b3IsIEdyaWRDdHJsLCBHcmlkSGVhZGVyQ29tcCwgR3JpZEhlYWRlckN0cmwsIEdyaWRPcHRpb25zV3JhcHBlciwgR3JpZFNlcmlhbGl6ZXIsIEdyb3VwQ2VsbFJlbmRlcmVyLCBHcm91cENlbGxSZW5kZXJlckN0cmwsIEdyb3VwSW5zdGFuY2VJZENyZWF0b3IsIEhlYWRlckNlbGxDdHJsLCBIZWFkZXJGaWx0ZXJDZWxsQ29tcCwgSGVhZGVyRmlsdGVyQ2VsbEN0cmwsIEhlYWRlckdyb3VwQ2VsbEN0cmwsIEhlYWRlck5hdmlnYXRpb25EaXJlY3Rpb24sIEhlYWRlck5hdmlnYXRpb25TZXJ2aWNlLCBIZWFkZXJQb3NpdGlvblV0aWxzLCBIZWFkZXJSb3dDb21wLCBIZWFkZXJSb3dDb250YWluZXJDb21wLCBIZWFkZXJSb3dDb250YWluZXJDdHJsLCBIZWFkZXJSb3dDdHJsLCBIZWFkZXJSb3dUeXBlLCBIb3Jpem9udGFsRGlyZWN0aW9uLCBIb3Jpem9udGFsUmVzaXplU2VydmljZSwgSW5maW5pdGVSb3dNb2RlbE1vZHVsZSwgS2V5Q29kZSwgTGFyZ2VUZXh0Q2VsbEVkaXRvciwgTGF5b3V0Q3NzQ2xhc3NlcywgTG9nZ2VyLCBMb2dnZXJGYWN0b3J5LCBNYW5hZ2VkRm9jdXNGZWF0dXJlLCBNb2R1bGVOYW1lcywgTW9kdWxlUmVnaXN0cnksIE1vdXNlRXZlbnRTZXJ2aWNlLCBNb3ZlQ29sdW1uRmVhdHVyZSwgTmF2aWdhdGlvblNlcnZpY2UsIE51bWJlckZpbHRlciwgTnVtYmVyU2VxdWVuY2UsIE9wdGlvbmFsLCBQYWdpbmF0aW9uUHJveHksIFBpbm5lZFJvd01vZGVsLCBQb3B1cENvbXBvbmVudCwgUG9wdXBFZGl0b3JXcmFwcGVyLCBQb3B1cFNlbGVjdENlbGxFZGl0b3IsIFBvcHVwU2VydmljZSwgUG9wdXBUZXh0Q2VsbEVkaXRvciwgUG9zaXRpb25hYmxlRmVhdHVyZSwgUG9zdENvbnN0cnVjdCwgUHJlQ29uc3RydWN0LCBQcmVEZXN0cm95LCBQcm9wZXJ0eUtleXMsIFByb3ZpZGVkQ29sdW1uR3JvdXAsIFByb3ZpZGVkRmlsdGVyLCBRdWFsaWZpZXIsIFF1ZXJ5U2VsZWN0b3IsIFJlZlNlbGVjdG9yLCBSZXNpemVPYnNlcnZlclNlcnZpY2UsIFJvd0FuaW1hdGlvbkNzc0NsYXNzZXMsIFJvd0NvbnRhaW5lckNvbXAsIFJvd0NvbnRhaW5lckN0cmwsIFJvd0NvbnRhaW5lck5hbWUsIFJvd0NvbnRhaW5lclR5cGUsIFJvd0N0cmwsIFJvd0hpZ2hsaWdodFBvc2l0aW9uLCBSb3dOb2RlLCBSb3dOb2RlQmxvY2ssIFJvd05vZGVCbG9ja0xvYWRlciwgUm93Tm9kZVNvcnRlciwgUm93UG9zaXRpb25VdGlscywgUm93UmVuZGVyZXIsIFJvd1R5cGUsIFNjYWxhckZpbHRlciwgU2Nyb2xsVmlzaWJsZVNlcnZpY2UsIFNlbGVjdENlbGxFZGl0b3IsIFNlbGVjdGFibGVTZXJ2aWNlLCBTZWxlY3Rpb25IYW5kbGVUeXBlLCBTZWxlY3Rpb25TZXJ2aWNlLCBTZXJ2ZXJTaWRlVHJhbnNhY3Rpb25SZXN1bHRTdGF0dXMsIFNldExlZnRGZWF0dXJlLCBTaW1wbGVGaWx0ZXIsIFNvcnRDb250cm9sbGVyLCBTb3J0SW5kaWNhdG9yQ29tcCwgU3RhbmRhcmRNZW51RmFjdG9yeSwgU3R5bGluZ1NlcnZpY2UsIFRhYkd1YXJkQ29tcCwgVGFiR3VhcmRDdHJsLCBUYWJiZWRMYXlvdXQsIFRlbXBsYXRlU2VydmljZSwgVGV4dENlbGxFZGl0b3IsIFRleHRGaWx0ZXIsIFRleHRGbG9hdGluZ0ZpbHRlciwgVGltZXIsIFRvdWNoTGlzdGVuZXIsIFVzZXJDb21wb25lbnRGYWN0b3J5LCBVc2VyQ29tcG9uZW50UmVnaXN0cnksIFZhbHVlQ2FjaGUsIFZhbHVlRm9ybWF0dGVyU2VydmljZSwgVmFsdWVTZXJ2aWNlLCBWYW5pbGxhRnJhbWV3b3JrT3ZlcnJpZGVzLCBWZXJ0aWNhbERpcmVjdGlvbiwgVmlydHVhbExpc3QsIFhtbEZhY3RvcnksIFppcENvbnRhaW5lciwgXywgZGVmYXVsdEdyb3VwQ29tcGFyYXRvciwgZ2V0Um93Q29udGFpbmVyVHlwZUZvck5hbWUsIHNpbXBsZUh0dHBSZXF1ZXN0LCBzdHJpbmdUb0FycmF5IH07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/lib/AgGridColumn.js": /*!******************************************************!*\ !*** ./node_modules/ag-grid-vue/lib/AgGridColumn.js ***! \******************************************************/ /*! exports provided: AgGridColumn */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgGridColumn\", function() { return AgGridColumn; });\n/* harmony import */ var ag_grid_community__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ag-grid-community */ \"./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js\");\n\nvar AgGridColumn = /** @class */ (function () {\n function AgGridColumn() {\n }\n AgGridColumn.hasChildColumns = function (slots) {\n return slots && slots.default && slots.default.length > 0;\n };\n AgGridColumn.mapChildColumnDefs = function (slots) {\n return slots.default.map(function (column) {\n return AgGridColumn.toColDef(column);\n });\n };\n AgGridColumn.toColDef = function (column) {\n var colDef = AgGridColumn.createColDefFromGridColumn(column);\n if (column.children && column.children.length > 0) {\n colDef.children = AgGridColumn.getChildColDefs(column.children);\n }\n return colDef;\n };\n AgGridColumn.getChildColDefs = function (columnChildren) {\n return columnChildren.map(function (column) {\n return AgGridColumn.createColDefFromGridColumn(column);\n });\n };\n AgGridColumn.createColDefFromGridColumn = function (column) {\n var colDef = {};\n Object.assign(colDef, column.data.attrs);\n delete colDef.children;\n // booleans passed down just as is are here as property=\"\"\n // convert boolean props to a boolean here\n ag_grid_community__WEBPACK_IMPORTED_MODULE_0__[\"ColDefUtil\"].BOOLEAN_PROPERTIES.forEach(function (property) {\n var colDefAsAny = colDef;\n if (colDefAsAny[property] === '') {\n colDefAsAny[property] = true;\n }\n });\n return colDef;\n };\n return AgGridColumn;\n}());\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL0FnR3JpZENvbHVtbi5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9hZy1ncmlkLXZ1ZS9saWIvQWdHcmlkQ29sdW1uLmpzPzRhYmEiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29sRGVmVXRpbCB9IGZyb20gJ2FnLWdyaWQtY29tbXVuaXR5JztcbnZhciBBZ0dyaWRDb2x1bW4gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQWdHcmlkQ29sdW1uKCkge1xuICAgIH1cbiAgICBBZ0dyaWRDb2x1bW4uaGFzQ2hpbGRDb2x1bW5zID0gZnVuY3Rpb24gKHNsb3RzKSB7XG4gICAgICAgIHJldHVybiBzbG90cyAmJiBzbG90cy5kZWZhdWx0ICYmIHNsb3RzLmRlZmF1bHQubGVuZ3RoID4gMDtcbiAgICB9O1xuICAgIEFnR3JpZENvbHVtbi5tYXBDaGlsZENvbHVtbkRlZnMgPSBmdW5jdGlvbiAoc2xvdHMpIHtcbiAgICAgICAgcmV0dXJuIHNsb3RzLmRlZmF1bHQubWFwKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBBZ0dyaWRDb2x1bW4udG9Db2xEZWYoY29sdW1uKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBBZ0dyaWRDb2x1bW4udG9Db2xEZWYgPSBmdW5jdGlvbiAoY29sdW1uKSB7XG4gICAgICAgIHZhciBjb2xEZWYgPSBBZ0dyaWRDb2x1bW4uY3JlYXRlQ29sRGVmRnJvbUdyaWRDb2x1bW4oY29sdW1uKTtcbiAgICAgICAgaWYgKGNvbHVtbi5jaGlsZHJlbiAmJiBjb2x1bW4uY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29sRGVmLmNoaWxkcmVuID0gQWdHcmlkQ29sdW1uLmdldENoaWxkQ29sRGVmcyhjb2x1bW4uY2hpbGRyZW4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2xEZWY7XG4gICAgfTtcbiAgICBBZ0dyaWRDb2x1bW4uZ2V0Q2hpbGRDb2xEZWZzID0gZnVuY3Rpb24gKGNvbHVtbkNoaWxkcmVuKSB7XG4gICAgICAgIHJldHVybiBjb2x1bW5DaGlsZHJlbi5tYXAoZnVuY3Rpb24gKGNvbHVtbikge1xuICAgICAgICAgICAgcmV0dXJuIEFnR3JpZENvbHVtbi5jcmVhdGVDb2xEZWZGcm9tR3JpZENvbHVtbihjb2x1bW4pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEFnR3JpZENvbHVtbi5jcmVhdGVDb2xEZWZGcm9tR3JpZENvbHVtbiA9IGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgdmFyIGNvbERlZiA9IHt9O1xuICAgICAgICBPYmplY3QuYXNzaWduKGNvbERlZiwgY29sdW1uLmRhdGEuYXR0cnMpO1xuICAgICAgICBkZWxldGUgY29sRGVmLmNoaWxkcmVuO1xuICAgICAgICAvLyBib29sZWFucyBwYXNzZWQgZG93biBqdXN0IGFzIGlzIGFyZSBoZXJlIGFzIHByb3BlcnR5PVwiXCJcbiAgICAgICAgLy8gY29udmVydCBib29sZWFuIHByb3BzIHRvIGEgYm9vbGVhbiBoZXJlXG4gICAgICAgIENvbERlZlV0aWwuQk9PTEVBTl9QUk9QRVJUSUVTLmZvckVhY2goZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgICAgICB2YXIgY29sRGVmQXNBbnkgPSBjb2xEZWY7XG4gICAgICAgICAgICBpZiAoY29sRGVmQXNBbnlbcHJvcGVydHldID09PSAnJykge1xuICAgICAgICAgICAgICAgIGNvbERlZkFzQW55W3Byb3BlcnR5XSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY29sRGVmO1xuICAgIH07XG4gICAgcmV0dXJuIEFnR3JpZENvbHVtbjtcbn0oKSk7XG5leHBvcnQgeyBBZ0dyaWRDb2x1bW4gfTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/lib/AgGridColumn.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/lib/AgGridVue.js": /*!***************************************************!*\ !*** ./node_modules/ag-grid-vue/lib/AgGridVue.js ***! \***************************************************/ /*! exports provided: AgGridVue */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AgGridVue\", function() { return AgGridVue; });\n/* harmony import */ var vue_property_decorator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-property-decorator */ \"./node_modules/vue-property-decorator/lib/vue-property-decorator.js\");\n/* harmony import */ var ag_grid_community__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ag-grid-community */ \"./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js\");\n/* harmony import */ var _VueFrameworkComponentWrapper__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./VueFrameworkComponentWrapper */ \"./node_modules/ag-grid-vue/lib/VueFrameworkComponentWrapper.js\");\n/* harmony import */ var _Utils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Utils */ \"./node_modules/ag-grid-vue/lib/Utils.js\");\n/* harmony import */ var _AgGridColumn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AgGridColumn */ \"./node_modules/ag-grid-vue/lib/AgGridColumn.js\");\n/* harmony import */ var _VueFrameworkOverrides__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./VueFrameworkOverrides */ \"./node_modules/ag-grid-vue/lib/VueFrameworkOverrides.js\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n\n\n\n\n\nvar _a = Object(_Utils__WEBPACK_IMPORTED_MODULE_3__[\"getAgGridProperties\"])(), props = _a[0], watch = _a[1], model = _a[2];\nvar AgGridVue = /** @class */ (function (_super) {\n __extends(AgGridVue, _super);\n function AgGridVue() {\n var _this = _super !== null && _super.apply(this, arguments) || this;\n _this.gridCreated = false;\n _this.isDestroyed = false;\n _this.gridReadyFired = false;\n _this.emitRowModel = null;\n return _this;\n }\n AgGridVue_1 = AgGridVue;\n AgGridVue.kebabProperty = function (property) {\n return property.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n };\n // noinspection JSUnusedGlobalSymbols, JSMethodCanBeStatic\n AgGridVue.prototype.render = function (h) {\n return h('div');\n };\n AgGridVue.prototype.globalEventListener = function (eventType, event) {\n if (this.isDestroyed) {\n return;\n }\n if (eventType === 'gridReady') {\n this.gridReadyFired = true;\n }\n this.updateModelIfUsed(eventType);\n // only emit if someone is listening\n // we allow both kebab and camelCase event listeners, so check for both\n var kebabName = AgGridVue_1.kebabProperty(eventType);\n if (this.$listeners[kebabName]) {\n this.$emit(kebabName, event);\n }\n else if (this.$listeners[eventType]) {\n this.$emit(eventType, event);\n }\n };\n AgGridVue.prototype.processChanges = function (propertyName, currentValue, previousValue) {\n if (this.gridCreated) {\n if (this.skipChange(propertyName, currentValue, previousValue)) {\n return;\n }\n var changes = {};\n changes[propertyName] = {\n currentValue: currentValue,\n previousValue: previousValue,\n };\n ag_grid_community__WEBPACK_IMPORTED_MODULE_1__[\"ComponentUtil\"].processOnChange(changes, this.gridOptions, this.gridOptions.api, this.gridOptions.columnApi);\n }\n };\n // noinspection JSUnusedGlobalSymbols\n AgGridVue.prototype.mounted = function () {\n var _this = this;\n // we debounce the model update to prevent a flood of updates in the event there are many individual\n // cell/row updates\n this.emitRowModel = this.debounce(function () {\n _this.$emit('data-model-changed', Object.freeze(_this.getRowData()));\n }, 20);\n var frameworkComponentWrapper = new _VueFrameworkComponentWrapper__WEBPACK_IMPORTED_MODULE_2__[\"VueFrameworkComponentWrapper\"](this);\n var gridOptions = ag_grid_community__WEBPACK_IMPORTED_MODULE_1__[\"ComponentUtil\"].copyAttributesToGridOptions(this.gridOptions, this);\n this.checkForBindingConflicts();\n gridOptions.rowData = this.getRowDataBasedOnBindings();\n if (_AgGridColumn__WEBPACK_IMPORTED_MODULE_4__[\"AgGridColumn\"].hasChildColumns(this.$slots)) {\n gridOptions.columnDefs = _AgGridColumn__WEBPACK_IMPORTED_MODULE_4__[\"AgGridColumn\"].mapChildColumnDefs(this.$slots);\n }\n var gridParams = {\n globalEventListener: this.globalEventListener.bind(this),\n frameworkOverrides: new _VueFrameworkOverrides__WEBPACK_IMPORTED_MODULE_5__[\"VueFrameworkOverrides\"](this),\n providedBeanInstances: {\n frameworkComponentWrapper: frameworkComponentWrapper,\n },\n modules: this.modules,\n };\n new ag_grid_community__WEBPACK_IMPORTED_MODULE_1__[\"Grid\"](this.$el, gridOptions, gridParams);\n this.gridCreated = true;\n };\n // noinspection JSUnusedGlobalSymbols\n AgGridVue.prototype.destroyed = function () {\n if (this.gridCreated) {\n if (this.gridOptions.api) {\n this.gridOptions.api.destroy();\n }\n this.isDestroyed = true;\n }\n };\n AgGridVue.prototype.checkForBindingConflicts = function () {\n var thisAsAny = this;\n if ((thisAsAny.rowData || this.gridOptions.rowData) &&\n thisAsAny.rowDataModel) {\n console.warn('AG Grid: Using both rowData and rowDataModel. rowData will be ignored.');\n }\n };\n AgGridVue.prototype.getRowData = function () {\n var rowData = [];\n this.gridOptions.api.forEachNode(function (rowNode) {\n rowData.push(rowNode.data);\n });\n return rowData;\n };\n AgGridVue.prototype.updateModelIfUsed = function (eventType) {\n if (this.gridReadyFired &&\n this.$listeners['data-model-changed'] &&\n AgGridVue_1.ROW_DATA_EVENTS.indexOf(eventType) !== -1) {\n if (this.emitRowModel) {\n this.emitRowModel();\n }\n }\n };\n AgGridVue.prototype.getRowDataBasedOnBindings = function () {\n var thisAsAny = this;\n var rowDataModel = thisAsAny.rowDataModel;\n return rowDataModel ? rowDataModel :\n thisAsAny.rowData ? thisAsAny.rowData : thisAsAny.gridOptions.rowData;\n };\n /*\n * Prevents an infinite loop when using v-model for the rowData\n */\n AgGridVue.prototype.skipChange = function (propertyName, currentValue, previousValue) {\n if (this.gridReadyFired &&\n propertyName === 'rowData' &&\n this.$listeners['data-model-changed']) {\n if (currentValue === previousValue) {\n return true;\n }\n if (currentValue && previousValue) {\n var currentRowData = currentValue;\n var previousRowData = previousValue;\n if (currentRowData.length === previousRowData.length) {\n for (var i = 0; i < currentRowData.length; i++) {\n if (currentRowData[i] !== previousRowData[i]) {\n return false;\n }\n }\n return true;\n }\n }\n }\n return false;\n };\n AgGridVue.prototype.debounce = function (func, delay) {\n var timeout;\n return function () {\n var later = function () {\n func();\n };\n window.clearTimeout(timeout);\n timeout = window.setTimeout(later, delay);\n };\n };\n var AgGridVue_1;\n AgGridVue.ROW_DATA_EVENTS = ['rowDataChanged', 'rowDataUpdated', 'cellValueChanged', 'rowValueChanged'];\n __decorate([\n Object(vue_property_decorator__WEBPACK_IMPORTED_MODULE_0__[\"Prop\"])(Boolean)\n ], AgGridVue.prototype, \"autoParamsRefresh\", void 0);\n __decorate([\n Object(vue_property_decorator__WEBPACK_IMPORTED_MODULE_0__[\"Prop\"])({ default: function () { return []; } })\n ], AgGridVue.prototype, \"componentDependencies\", void 0);\n __decorate([\n Object(vue_property_decorator__WEBPACK_IMPORTED_MODULE_0__[\"Prop\"])({ default: function () { return []; } })\n ], AgGridVue.prototype, \"modules\", void 0);\n AgGridVue = AgGridVue_1 = __decorate([\n Object(ag_grid_community__WEBPACK_IMPORTED_MODULE_1__[\"Bean\"])('agGridVue'),\n Object(vue_property_decorator__WEBPACK_IMPORTED_MODULE_0__[\"Component\"])({\n props: props,\n watch: watch,\n model: model,\n })\n ], AgGridVue);\n return AgGridVue;\n}(vue_property_decorator__WEBPACK_IMPORTED_MODULE_0__[\"Vue\"]));\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL0FnR3JpZFZ1ZS5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9hZy1ncmlkLXZ1ZS9saWIvQWdHcmlkVnVlLmpzPzEyODMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19kZWNvcmF0ZSA9ICh0aGlzICYmIHRoaXMuX19kZWNvcmF0ZSkgfHwgZnVuY3Rpb24gKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcbn07XG5pbXBvcnQgeyBDb21wb25lbnQsIFByb3AsIFZ1ZSB9IGZyb20gJ3Z1ZS1wcm9wZXJ0eS1kZWNvcmF0b3InO1xuaW1wb3J0IHsgQmVhbiwgQ29tcG9uZW50VXRpbCwgR3JpZCB9IGZyb20gJ2FnLWdyaWQtY29tbXVuaXR5JztcbmltcG9ydCB7IFZ1ZUZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXIgfSBmcm9tICcuL1Z1ZUZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXInO1xuaW1wb3J0IHsgZ2V0QWdHcmlkUHJvcGVydGllcyB9IGZyb20gJy4vVXRpbHMnO1xuaW1wb3J0IHsgQWdHcmlkQ29sdW1uIH0gZnJvbSAnLi9BZ0dyaWRDb2x1bW4nO1xuaW1wb3J0IHsgVnVlRnJhbWV3b3JrT3ZlcnJpZGVzIH0gZnJvbSAnLi9WdWVGcmFtZXdvcmtPdmVycmlkZXMnO1xudmFyIF9hID0gZ2V0QWdHcmlkUHJvcGVydGllcygpLCBwcm9wcyA9IF9hWzBdLCB3YXRjaCA9IF9hWzFdLCBtb2RlbCA9IF9hWzJdO1xudmFyIEFnR3JpZFZ1ZSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQWdHcmlkVnVlLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFnR3JpZFZ1ZSgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLmdyaWRDcmVhdGVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmlzRGVzdHJveWVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmdyaWRSZWFkeUZpcmVkID0gZmFsc2U7XG4gICAgICAgIF90aGlzLmVtaXRSb3dNb2RlbCA9IG51bGw7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgQWdHcmlkVnVlXzEgPSBBZ0dyaWRWdWU7XG4gICAgQWdHcmlkVnVlLmtlYmFiUHJvcGVydHkgPSBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICAgICAgcmV0dXJuIHByb3BlcnR5LnJlcGxhY2UoLyhbYS16XSkoW0EtWl0pL2csICckMS0kMicpLnRvTG93ZXJDYXNlKCk7XG4gICAgfTtcbiAgICAvLyBub2luc3BlY3Rpb24gSlNVbnVzZWRHbG9iYWxTeW1ib2xzLCBKU01ldGhvZENhbkJlU3RhdGljXG4gICAgQWdHcmlkVnVlLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoaCkge1xuICAgICAgICByZXR1cm4gaCgnZGl2Jyk7XG4gICAgfTtcbiAgICBBZ0dyaWRWdWUucHJvdG90eXBlLmdsb2JhbEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBldmVudCkge1xuICAgICAgICBpZiAodGhpcy5pc0Rlc3Ryb3llZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmVudFR5cGUgPT09ICdncmlkUmVhZHknKSB7XG4gICAgICAgICAgICB0aGlzLmdyaWRSZWFkeUZpcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZU1vZGVsSWZVc2VkKGV2ZW50VHlwZSk7XG4gICAgICAgIC8vIG9ubHkgZW1pdCBpZiBzb21lb25lIGlzIGxpc3RlbmluZ1xuICAgICAgICAvLyB3ZSBhbGxvdyBib3RoIGtlYmFiIGFuZCBjYW1lbENhc2UgZXZlbnQgbGlzdGVuZXJzLCBzbyBjaGVjayBmb3IgYm90aFxuICAgICAgICB2YXIga2ViYWJOYW1lID0gQWdHcmlkVnVlXzEua2ViYWJQcm9wZXJ0eShldmVudFR5cGUpO1xuICAgICAgICBpZiAodGhpcy4kbGlzdGVuZXJzW2tlYmFiTmFtZV0pIHtcbiAgICAgICAgICAgIHRoaXMuJGVtaXQoa2ViYWJOYW1lLCBldmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy4kbGlzdGVuZXJzW2V2ZW50VHlwZV0pIHtcbiAgICAgICAgICAgIHRoaXMuJGVtaXQoZXZlbnRUeXBlLCBldmVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnR3JpZFZ1ZS5wcm90b3R5cGUucHJvY2Vzc0NoYW5nZXMgPSBmdW5jdGlvbiAocHJvcGVydHlOYW1lLCBjdXJyZW50VmFsdWUsIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZENyZWF0ZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNraXBDaGFuZ2UocHJvcGVydHlOYW1lLCBjdXJyZW50VmFsdWUsIHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNoYW5nZXMgPSB7fTtcbiAgICAgICAgICAgIGNoYW5nZXNbcHJvcGVydHlOYW1lXSA9IHtcbiAgICAgICAgICAgICAgICBjdXJyZW50VmFsdWU6IGN1cnJlbnRWYWx1ZSxcbiAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlOiBwcmV2aW91c1ZhbHVlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIENvbXBvbmVudFV0aWwucHJvY2Vzc09uQ2hhbmdlKGNoYW5nZXMsIHRoaXMuZ3JpZE9wdGlvbnMsIHRoaXMuZ3JpZE9wdGlvbnMuYXBpLCB0aGlzLmdyaWRPcHRpb25zLmNvbHVtbkFwaSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIC8vIG5vaW5zcGVjdGlvbiBKU1VudXNlZEdsb2JhbFN5bWJvbHNcbiAgICBBZ0dyaWRWdWUucHJvdG90eXBlLm1vdW50ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIC8vIHdlIGRlYm91bmNlIHRoZSBtb2RlbCB1cGRhdGUgdG8gcHJldmVudCBhIGZsb29kIG9mIHVwZGF0ZXMgaW4gdGhlIGV2ZW50IHRoZXJlIGFyZSBtYW55IGluZGl2aWR1YWxcbiAgICAgICAgLy8gY2VsbC9yb3cgdXBkYXRlc1xuICAgICAgICB0aGlzLmVtaXRSb3dNb2RlbCA9IHRoaXMuZGVib3VuY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuJGVtaXQoJ2RhdGEtbW9kZWwtY2hhbmdlZCcsIE9iamVjdC5mcmVlemUoX3RoaXMuZ2V0Um93RGF0YSgpKSk7XG4gICAgICAgIH0sIDIwKTtcbiAgICAgICAgdmFyIGZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXIgPSBuZXcgVnVlRnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlcih0aGlzKTtcbiAgICAgICAgdmFyIGdyaWRPcHRpb25zID0gQ29tcG9uZW50VXRpbC5jb3B5QXR0cmlidXRlc1RvR3JpZE9wdGlvbnModGhpcy5ncmlkT3B0aW9ucywgdGhpcyk7XG4gICAgICAgIHRoaXMuY2hlY2tGb3JCaW5kaW5nQ29uZmxpY3RzKCk7XG4gICAgICAgIGdyaWRPcHRpb25zLnJvd0RhdGEgPSB0aGlzLmdldFJvd0RhdGFCYXNlZE9uQmluZGluZ3MoKTtcbiAgICAgICAgaWYgKEFnR3JpZENvbHVtbi5oYXNDaGlsZENvbHVtbnModGhpcy4kc2xvdHMpKSB7XG4gICAgICAgICAgICBncmlkT3B0aW9ucy5jb2x1bW5EZWZzID0gQWdHcmlkQ29sdW1uLm1hcENoaWxkQ29sdW1uRGVmcyh0aGlzLiRzbG90cyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGdyaWRQYXJhbXMgPSB7XG4gICAgICAgICAgICBnbG9iYWxFdmVudExpc3RlbmVyOiB0aGlzLmdsb2JhbEV2ZW50TGlzdGVuZXIuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIGZyYW1ld29ya092ZXJyaWRlczogbmV3IFZ1ZUZyYW1ld29ya092ZXJyaWRlcyh0aGlzKSxcbiAgICAgICAgICAgIHByb3ZpZGVkQmVhbkluc3RhbmNlczoge1xuICAgICAgICAgICAgICAgIGZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXI6IGZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW9kdWxlczogdGhpcy5tb2R1bGVzLFxuICAgICAgICB9O1xuICAgICAgICBuZXcgR3JpZCh0aGlzLiRlbCwgZ3JpZE9wdGlvbnMsIGdyaWRQYXJhbXMpO1xuICAgICAgICB0aGlzLmdyaWRDcmVhdGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIC8vIG5vaW5zcGVjdGlvbiBKU1VudXNlZEdsb2JhbFN5bWJvbHNcbiAgICBBZ0dyaWRWdWUucHJvdG90eXBlLmRlc3Ryb3llZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZ3JpZENyZWF0ZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLmFwaSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ3JpZE9wdGlvbnMuYXBpLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaXNEZXN0cm95ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBBZ0dyaWRWdWUucHJvdG90eXBlLmNoZWNrRm9yQmluZGluZ0NvbmZsaWN0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHRoaXNBc0FueSA9IHRoaXM7XG4gICAgICAgIGlmICgodGhpc0FzQW55LnJvd0RhdGEgfHwgdGhpcy5ncmlkT3B0aW9ucy5yb3dEYXRhKSAmJlxuICAgICAgICAgICAgdGhpc0FzQW55LnJvd0RhdGFNb2RlbCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBVc2luZyBib3RoIHJvd0RhdGEgYW5kIHJvd0RhdGFNb2RlbC4gcm93RGF0YSB3aWxsIGJlIGlnbm9yZWQuJyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnR3JpZFZ1ZS5wcm90b3R5cGUuZ2V0Um93RGF0YSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd0RhdGEgPSBbXTtcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9ucy5hcGkuZm9yRWFjaE5vZGUoZnVuY3Rpb24gKHJvd05vZGUpIHtcbiAgICAgICAgICAgIHJvd0RhdGEucHVzaChyb3dOb2RlLmRhdGEpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJvd0RhdGE7XG4gICAgfTtcbiAgICBBZ0dyaWRWdWUucHJvdG90eXBlLnVwZGF0ZU1vZGVsSWZVc2VkID0gZnVuY3Rpb24gKGV2ZW50VHlwZSkge1xuICAgICAgICBpZiAodGhpcy5ncmlkUmVhZHlGaXJlZCAmJlxuICAgICAgICAgICAgdGhpcy4kbGlzdGVuZXJzWydkYXRhLW1vZGVsLWNoYW5nZWQnXSAmJlxuICAgICAgICAgICAgQWdHcmlkVnVlXzEuUk9XX0RBVEFfRVZFTlRTLmluZGV4T2YoZXZlbnRUeXBlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmVtaXRSb3dNb2RlbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdFJvd01vZGVsKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEFnR3JpZFZ1ZS5wcm90b3R5cGUuZ2V0Um93RGF0YUJhc2VkT25CaW5kaW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHRoaXNBc0FueSA9IHRoaXM7XG4gICAgICAgIHZhciByb3dEYXRhTW9kZWwgPSB0aGlzQXNBbnkucm93RGF0YU1vZGVsO1xuICAgICAgICByZXR1cm4gcm93RGF0YU1vZGVsID8gcm93RGF0YU1vZGVsIDpcbiAgICAgICAgICAgIHRoaXNBc0FueS5yb3dEYXRhID8gdGhpc0FzQW55LnJvd0RhdGEgOiB0aGlzQXNBbnkuZ3JpZE9wdGlvbnMucm93RGF0YTtcbiAgICB9O1xuICAgIC8qXG4gICAgICogUHJldmVudHMgYW4gaW5maW5pdGUgbG9vcCB3aGVuIHVzaW5nIHYtbW9kZWwgZm9yIHRoZSByb3dEYXRhXG4gICAgICovXG4gICAgQWdHcmlkVnVlLnByb3RvdHlwZS5za2lwQ2hhbmdlID0gZnVuY3Rpb24gKHByb3BlcnR5TmFtZSwgY3VycmVudFZhbHVlLCBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLmdyaWRSZWFkeUZpcmVkICYmXG4gICAgICAgICAgICBwcm9wZXJ0eU5hbWUgPT09ICdyb3dEYXRhJyAmJlxuICAgICAgICAgICAgdGhpcy4kbGlzdGVuZXJzWydkYXRhLW1vZGVsLWNoYW5nZWQnXSkge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSAmJiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRSb3dEYXRhID0gY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1Jvd0RhdGEgPSBwcmV2aW91c1ZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Um93RGF0YS5sZW5ndGggPT09IHByZXZpb3VzUm93RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjdXJyZW50Um93RGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRSb3dEYXRhW2ldICE9PSBwcmV2aW91c1Jvd0RhdGFbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIEFnR3JpZFZ1ZS5wcm90b3R5cGUuZGVib3VuY2UgPSBmdW5jdGlvbiAoZnVuYywgZGVsYXkpIHtcbiAgICAgICAgdmFyIHRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGF0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZnVuYygpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgICB0aW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQobGF0ZXIsIGRlbGF5KTtcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHZhciBBZ0dyaWRWdWVfMTtcbiAgICBBZ0dyaWRWdWUuUk9XX0RBVEFfRVZFTlRTID0gWydyb3dEYXRhQ2hhbmdlZCcsICdyb3dEYXRhVXBkYXRlZCcsICdjZWxsVmFsdWVDaGFuZ2VkJywgJ3Jvd1ZhbHVlQ2hhbmdlZCddO1xuICAgIF9fZGVjb3JhdGUoW1xuICAgICAgICBQcm9wKEJvb2xlYW4pXG4gICAgXSwgQWdHcmlkVnVlLnByb3RvdHlwZSwgXCJhdXRvUGFyYW1zUmVmcmVzaFwiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUoW1xuICAgICAgICBQcm9wKHsgZGVmYXVsdDogZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH0gfSlcbiAgICBdLCBBZ0dyaWRWdWUucHJvdG90eXBlLCBcImNvbXBvbmVudERlcGVuZGVuY2llc1wiLCB2b2lkIDApO1xuICAgIF9fZGVjb3JhdGUoW1xuICAgICAgICBQcm9wKHsgZGVmYXVsdDogZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH0gfSlcbiAgICBdLCBBZ0dyaWRWdWUucHJvdG90eXBlLCBcIm1vZHVsZXNcIiwgdm9pZCAwKTtcbiAgICBBZ0dyaWRWdWUgPSBBZ0dyaWRWdWVfMSA9IF9fZGVjb3JhdGUoW1xuICAgICAgICBCZWFuKCdhZ0dyaWRWdWUnKSxcbiAgICAgICAgQ29tcG9uZW50KHtcbiAgICAgICAgICAgIHByb3BzOiBwcm9wcyxcbiAgICAgICAgICAgIHdhdGNoOiB3YXRjaCxcbiAgICAgICAgICAgIG1vZGVsOiBtb2RlbCxcbiAgICAgICAgfSlcbiAgICBdLCBBZ0dyaWRWdWUpO1xuICAgIHJldHVybiBBZ0dyaWRWdWU7XG59KFZ1ZSkpO1xuZXhwb3J0IHsgQWdHcmlkVnVlIH07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/lib/AgGridVue.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/lib/Utils.js": /*!***********************************************!*\ !*** ./node_modules/ag-grid-vue/lib/Utils.js ***! \***********************************************/ /*! exports provided: getAgGridProperties */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getAgGridProperties\", function() { return getAgGridProperties; });\n/* harmony import */ var ag_grid_community__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ag-grid-community */ \"./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js\");\n\nvar getAgGridProperties = function () {\n var props = {\n gridOptions: {\n default: function () {\n return {};\n },\n },\n rowDataModel: undefined,\n };\n var watch = {\n rowDataModel: function (currentValue, previousValue) {\n this.processChanges('rowData', currentValue, previousValue);\n },\n };\n ag_grid_community__WEBPACK_IMPORTED_MODULE_0__[\"ComponentUtil\"].ALL_PROPERTIES.forEach(function (propertyName) {\n props[propertyName] = {};\n watch[propertyName] = function (currentValue, previousValue) {\n this.processChanges(propertyName, currentValue, previousValue);\n };\n });\n var model = {\n prop: 'rowDataModel',\n event: 'data-model-changed',\n };\n return [props, watch, model];\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL1V0aWxzLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2FnLWdyaWQtdnVlL2xpYi9VdGlscy5qcz8xOWJhIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudFV0aWwgfSBmcm9tICdhZy1ncmlkLWNvbW11bml0eSc7XG5leHBvcnQgdmFyIGdldEFnR3JpZFByb3BlcnRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHByb3BzID0ge1xuICAgICAgICBncmlkT3B0aW9uczoge1xuICAgICAgICAgICAgZGVmYXVsdDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHJvd0RhdGFNb2RlbDogdW5kZWZpbmVkLFxuICAgIH07XG4gICAgdmFyIHdhdGNoID0ge1xuICAgICAgICByb3dEYXRhTW9kZWw6IGZ1bmN0aW9uIChjdXJyZW50VmFsdWUsIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc0NoYW5nZXMoJ3Jvd0RhdGEnLCBjdXJyZW50VmFsdWUsIHByZXZpb3VzVmFsdWUpO1xuICAgICAgICB9LFxuICAgIH07XG4gICAgQ29tcG9uZW50VXRpbC5BTExfUFJPUEVSVElFUy5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgcHJvcHNbcHJvcGVydHlOYW1lXSA9IHt9O1xuICAgICAgICB3YXRjaFtwcm9wZXJ0eU5hbWVdID0gZnVuY3Rpb24gKGN1cnJlbnRWYWx1ZSwgcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ2hhbmdlcyhwcm9wZXJ0eU5hbWUsIGN1cnJlbnRWYWx1ZSwgcHJldmlvdXNWYWx1ZSk7XG4gICAgICAgIH07XG4gICAgfSk7XG4gICAgdmFyIG1vZGVsID0ge1xuICAgICAgICBwcm9wOiAncm93RGF0YU1vZGVsJyxcbiAgICAgICAgZXZlbnQ6ICdkYXRhLW1vZGVsLWNoYW5nZWQnLFxuICAgIH07XG4gICAgcmV0dXJuIFtwcm9wcywgd2F0Y2gsIG1vZGVsXTtcbn07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/lib/Utils.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/lib/VueComponentFactory.js": /*!*************************************************************!*\ !*** ./node_modules/ag-grid-vue/lib/VueComponentFactory.js ***! \*************************************************************/ /*! exports provided: VueComponentFactory */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VueComponentFactory\", function() { return VueComponentFactory; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm.js\");\n\nvar VueComponentFactory = /** @class */ (function () {\n function VueComponentFactory() {\n }\n VueComponentFactory.getComponentType = function (parent, component) {\n if (typeof component === 'string') {\n var componentInstance = this.searchForComponentInstance(parent, component);\n if (!componentInstance) {\n console.error(\"Could not find component with name of \" + component + \". Is it in Vue.components?\");\n return null;\n }\n return vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].extend(componentInstance);\n }\n else {\n // assume a type\n return component;\n }\n };\n VueComponentFactory.createAndMountComponent = function (params, componentType, parent) {\n var details = {\n data: {\n params: Object.freeze(params),\n },\n parent: parent,\n };\n if (parent.componentDependencies) {\n parent.componentDependencies.forEach(function (dependency) {\n return details[dependency] = parent[dependency];\n });\n }\n var component = new componentType(details);\n component.$mount();\n return component;\n };\n VueComponentFactory.searchForComponentInstance = function (parent, component, maxDepth, suppressError) {\n if (maxDepth === void 0) { maxDepth = 10; }\n if (suppressError === void 0) { suppressError = false; }\n var componentInstance = null;\n var currentParent = parent.$parent;\n var depth = 0;\n while (!componentInstance &&\n currentParent &&\n currentParent.$options &&\n (++depth < maxDepth)) {\n componentInstance = currentParent.$options.components[component];\n currentParent = currentParent.$parent;\n }\n if (!componentInstance && !suppressError) {\n console.error(\"Could not find component with name of \" + component + \". Is it in Vue.components?\");\n return null;\n }\n return componentInstance;\n };\n return VueComponentFactory;\n}());\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL1Z1ZUNvbXBvbmVudEZhY3RvcnkuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL1Z1ZUNvbXBvbmVudEZhY3RvcnkuanM/MTg3MiJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgVnVlIGZyb20gJ3Z1ZSc7XG52YXIgVnVlQ29tcG9uZW50RmFjdG9yeSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBWdWVDb21wb25lbnRGYWN0b3J5KCkge1xuICAgIH1cbiAgICBWdWVDb21wb25lbnRGYWN0b3J5LmdldENvbXBvbmVudFR5cGUgPSBmdW5jdGlvbiAocGFyZW50LCBjb21wb25lbnQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBjb21wb25lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB2YXIgY29tcG9uZW50SW5zdGFuY2UgPSB0aGlzLnNlYXJjaEZvckNvbXBvbmVudEluc3RhbmNlKHBhcmVudCwgY29tcG9uZW50KTtcbiAgICAgICAgICAgIGlmICghY29tcG9uZW50SW5zdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQ291bGQgbm90IGZpbmQgY29tcG9uZW50IHdpdGggbmFtZSBvZiBcIiArIGNvbXBvbmVudCArIFwiLiBJcyBpdCBpbiBWdWUuY29tcG9uZW50cz9cIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gVnVlLmV4dGVuZChjb21wb25lbnRJbnN0YW5jZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBhc3N1bWUgYSB0eXBlXG4gICAgICAgICAgICByZXR1cm4gY29tcG9uZW50O1xuICAgICAgICB9XG4gICAgfTtcbiAgICBWdWVDb21wb25lbnRGYWN0b3J5LmNyZWF0ZUFuZE1vdW50Q29tcG9uZW50ID0gZnVuY3Rpb24gKHBhcmFtcywgY29tcG9uZW50VHlwZSwgcGFyZW50KSB7XG4gICAgICAgIHZhciBkZXRhaWxzID0ge1xuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHBhcmFtczogT2JqZWN0LmZyZWV6ZShwYXJhbXMpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhcmVudDogcGFyZW50LFxuICAgICAgICB9O1xuICAgICAgICBpZiAocGFyZW50LmNvbXBvbmVudERlcGVuZGVuY2llcykge1xuICAgICAgICAgICAgcGFyZW50LmNvbXBvbmVudERlcGVuZGVuY2llcy5mb3JFYWNoKGZ1bmN0aW9uIChkZXBlbmRlbmN5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRldGFpbHNbZGVwZW5kZW5jeV0gPSBwYXJlbnRbZGVwZW5kZW5jeV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgY29tcG9uZW50ID0gbmV3IGNvbXBvbmVudFR5cGUoZGV0YWlscyk7XG4gICAgICAgIGNvbXBvbmVudC4kbW91bnQoKTtcbiAgICAgICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgICB9O1xuICAgIFZ1ZUNvbXBvbmVudEZhY3Rvcnkuc2VhcmNoRm9yQ29tcG9uZW50SW5zdGFuY2UgPSBmdW5jdGlvbiAocGFyZW50LCBjb21wb25lbnQsIG1heERlcHRoLCBzdXBwcmVzc0Vycm9yKSB7XG4gICAgICAgIGlmIChtYXhEZXB0aCA9PT0gdm9pZCAwKSB7IG1heERlcHRoID0gMTA7IH1cbiAgICAgICAgaWYgKHN1cHByZXNzRXJyb3IgPT09IHZvaWQgMCkgeyBzdXBwcmVzc0Vycm9yID0gZmFsc2U7IH1cbiAgICAgICAgdmFyIGNvbXBvbmVudEluc3RhbmNlID0gbnVsbDtcbiAgICAgICAgdmFyIGN1cnJlbnRQYXJlbnQgPSBwYXJlbnQuJHBhcmVudDtcbiAgICAgICAgdmFyIGRlcHRoID0gMDtcbiAgICAgICAgd2hpbGUgKCFjb21wb25lbnRJbnN0YW5jZSAmJlxuICAgICAgICAgICAgY3VycmVudFBhcmVudCAmJlxuICAgICAgICAgICAgY3VycmVudFBhcmVudC4kb3B0aW9ucyAmJlxuICAgICAgICAgICAgKCsrZGVwdGggPCBtYXhEZXB0aCkpIHtcbiAgICAgICAgICAgIGNvbXBvbmVudEluc3RhbmNlID0gY3VycmVudFBhcmVudC4kb3B0aW9ucy5jb21wb25lbnRzW2NvbXBvbmVudF07XG4gICAgICAgICAgICBjdXJyZW50UGFyZW50ID0gY3VycmVudFBhcmVudC4kcGFyZW50O1xuICAgICAgICB9XG4gICAgICAgIGlmICghY29tcG9uZW50SW5zdGFuY2UgJiYgIXN1cHByZXNzRXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgZmluZCBjb21wb25lbnQgd2l0aCBuYW1lIG9mIFwiICsgY29tcG9uZW50ICsgXCIuIElzIGl0IGluIFZ1ZS5jb21wb25lbnRzP1wiKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb21wb25lbnRJbnN0YW5jZTtcbiAgICB9O1xuICAgIHJldHVybiBWdWVDb21wb25lbnRGYWN0b3J5O1xufSgpKTtcbmV4cG9ydCB7IFZ1ZUNvbXBvbmVudEZhY3RvcnkgfTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/lib/VueComponentFactory.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/lib/VueFrameworkComponentWrapper.js": /*!**********************************************************************!*\ !*** ./node_modules/ag-grid-vue/lib/VueFrameworkComponentWrapper.js ***! \**********************************************************************/ /*! exports provided: VueFrameworkComponentWrapper */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VueFrameworkComponentWrapper\", function() { return VueFrameworkComponentWrapper; });\n/* harmony import */ var ag_grid_community__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ag-grid-community */ \"./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js\");\n/* harmony import */ var _VueComponentFactory__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VueComponentFactory */ \"./node_modules/ag-grid-vue/lib/VueComponentFactory.js\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n\nvar VueFrameworkComponentWrapper = /** @class */ (function (_super) {\n __extends(VueFrameworkComponentWrapper, _super);\n function VueFrameworkComponentWrapper(parent) {\n var _this = _super.call(this) || this;\n _this.parent = parent;\n return _this;\n }\n VueFrameworkComponentWrapper.prototype.createWrapper = function (component) {\n var that = this;\n var DynamicComponent = /** @class */ (function (_super) {\n __extends(DynamicComponent, _super);\n function DynamicComponent() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n DynamicComponent.prototype.init = function (params) {\n _super.prototype.init.call(this, params);\n };\n DynamicComponent.prototype.hasMethod = function (name) {\n return wrapper.getFrameworkComponentInstance()[name] != null;\n };\n DynamicComponent.prototype.callMethod = function (name, args) {\n var componentInstance = this.getFrameworkComponentInstance();\n var frameworkComponentInstance = wrapper.getFrameworkComponentInstance();\n return frameworkComponentInstance[name].apply(componentInstance, args);\n };\n DynamicComponent.prototype.addMethod = function (name, callback) {\n wrapper[name] = callback;\n };\n DynamicComponent.prototype.overrideProcessing = function (methodName) {\n return that.parent.autoParamsRefresh && methodName === 'refresh';\n };\n DynamicComponent.prototype.processMethod = function (methodName, args) {\n if (methodName === 'refresh') {\n this.getFrameworkComponentInstance().params = args[0];\n }\n if (this.hasMethod(methodName)) {\n return this.callMethod(methodName, args);\n }\n return methodName === 'refresh';\n };\n DynamicComponent.prototype.createComponent = function (params) {\n return that.createComponent(component, params);\n };\n return DynamicComponent;\n }(VueComponent));\n var wrapper = new DynamicComponent();\n return wrapper;\n };\n VueFrameworkComponentWrapper.prototype.createComponent = function (component, params) {\n var componentType = _VueComponentFactory__WEBPACK_IMPORTED_MODULE_1__[\"VueComponentFactory\"].getComponentType(this.parent, component);\n if (!componentType) {\n return;\n }\n return _VueComponentFactory__WEBPACK_IMPORTED_MODULE_1__[\"VueComponentFactory\"].createAndMountComponent(params, componentType, this.parent);\n };\n VueFrameworkComponentWrapper.prototype.createMethodProxy = function (wrapper, methodName, mandatory) {\n return function () {\n if (wrapper.overrideProcessing(methodName)) {\n return wrapper.processMethod(methodName, arguments);\n }\n if (wrapper.hasMethod(methodName)) {\n return wrapper.callMethod(methodName, arguments);\n }\n if (mandatory) {\n console.warn('AG Grid: Framework component is missing the method ' + methodName + '()');\n }\n return null;\n };\n };\n VueFrameworkComponentWrapper.prototype.destroy = function () {\n this.parent = null;\n };\n VueFrameworkComponentWrapper = __decorate([\n Object(ag_grid_community__WEBPACK_IMPORTED_MODULE_0__[\"Bean\"])('frameworkComponentWrapper')\n ], VueFrameworkComponentWrapper);\n return VueFrameworkComponentWrapper;\n}(ag_grid_community__WEBPACK_IMPORTED_MODULE_0__[\"BaseComponentWrapper\"]));\n\nvar VueComponent = /** @class */ (function () {\n function VueComponent() {\n }\n VueComponent.prototype.getGui = function () {\n return this.component.$el;\n };\n VueComponent.prototype.destroy = function () {\n if (this.getFrameworkComponentInstance() &&\n typeof this.getFrameworkComponentInstance().destroy === 'function') {\n this.getFrameworkComponentInstance().destroy();\n }\n this.component.$destroy();\n };\n VueComponent.prototype.getFrameworkComponentInstance = function () {\n return this.component;\n };\n VueComponent.prototype.init = function (params) {\n this.component = this.createComponent(params);\n };\n return VueComponent;\n}());\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL1Z1ZUZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXIuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL1Z1ZUZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXIuanM/Njc5ZCJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcbiAgICAgICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xufSkoKTtcbnZhciBfX2RlY29yYXRlID0gKHRoaXMgJiYgdGhpcy5fX2RlY29yYXRlKSB8fCBmdW5jdGlvbiAoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xufTtcbmltcG9ydCB7IEJhc2VDb21wb25lbnRXcmFwcGVyLCBCZWFuIH0gZnJvbSAnYWctZ3JpZC1jb21tdW5pdHknO1xuaW1wb3J0IHsgVnVlQ29tcG9uZW50RmFjdG9yeSB9IGZyb20gJy4vVnVlQ29tcG9uZW50RmFjdG9yeSc7XG52YXIgVnVlRnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoVnVlRnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlciwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBWdWVGcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyKHBhcmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgVnVlRnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlci5wcm90b3R5cGUuY3JlYXRlV3JhcHBlciA9IGZ1bmN0aW9uIChjb21wb25lbnQpIHtcbiAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICB2YXIgRHluYW1pY0NvbXBvbmVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgICAgIF9fZXh0ZW5kcyhEeW5hbWljQ29tcG9uZW50LCBfc3VwZXIpO1xuICAgICAgICAgICAgZnVuY3Rpb24gRHluYW1pY0NvbXBvbmVudCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBEeW5hbWljQ29tcG9uZW50LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAgICAgICAgIF9zdXBlci5wcm90b3R5cGUuaW5pdC5jYWxsKHRoaXMsIHBhcmFtcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgRHluYW1pY0NvbXBvbmVudC5wcm90b3R5cGUuaGFzTWV0aG9kID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd3JhcHBlci5nZXRGcmFtZXdvcmtDb21wb25lbnRJbnN0YW5jZSgpW25hbWVdICE9IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgRHluYW1pY0NvbXBvbmVudC5wcm90b3R5cGUuY2FsbE1ldGhvZCA9IGZ1bmN0aW9uIChuYW1lLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbXBvbmVudEluc3RhbmNlID0gdGhpcy5nZXRGcmFtZXdvcmtDb21wb25lbnRJbnN0YW5jZSgpO1xuICAgICAgICAgICAgICAgIHZhciBmcmFtZXdvcmtDb21wb25lbnRJbnN0YW5jZSA9IHdyYXBwZXIuZ2V0RnJhbWV3b3JrQ29tcG9uZW50SW5zdGFuY2UoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnJhbWV3b3JrQ29tcG9uZW50SW5zdGFuY2VbbmFtZV0uYXBwbHkoY29tcG9uZW50SW5zdGFuY2UsIGFyZ3MpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIER5bmFtaWNDb21wb25lbnQucHJvdG90eXBlLmFkZE1ldGhvZCA9IGZ1bmN0aW9uIChuYW1lLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIHdyYXBwZXJbbmFtZV0gPSBjYWxsYmFjaztcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBEeW5hbWljQ29tcG9uZW50LnByb3RvdHlwZS5vdmVycmlkZVByb2Nlc3NpbmcgPSBmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LnBhcmVudC5hdXRvUGFyYW1zUmVmcmVzaCAmJiBtZXRob2ROYW1lID09PSAncmVmcmVzaCc7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgRHluYW1pY0NvbXBvbmVudC5wcm90b3R5cGUucHJvY2Vzc01ldGhvZCA9IGZ1bmN0aW9uIChtZXRob2ROYW1lLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZE5hbWUgPT09ICdyZWZyZXNoJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEZyYW1ld29ya0NvbXBvbmVudEluc3RhbmNlKCkucGFyYW1zID0gYXJnc1swXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFzTWV0aG9kKG1ldGhvZE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxNZXRob2QobWV0aG9kTmFtZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtZXRob2ROYW1lID09PSAncmVmcmVzaCc7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgRHluYW1pY0NvbXBvbmVudC5wcm90b3R5cGUuY3JlYXRlQ29tcG9uZW50ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmNyZWF0ZUNvbXBvbmVudChjb21wb25lbnQsIHBhcmFtcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIER5bmFtaWNDb21wb25lbnQ7XG4gICAgICAgIH0oVnVlQ29tcG9uZW50KSk7XG4gICAgICAgIHZhciB3cmFwcGVyID0gbmV3IER5bmFtaWNDb21wb25lbnQoKTtcbiAgICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfTtcbiAgICBWdWVGcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyLnByb3RvdHlwZS5jcmVhdGVDb21wb25lbnQgPSBmdW5jdGlvbiAoY29tcG9uZW50LCBwYXJhbXMpIHtcbiAgICAgICAgdmFyIGNvbXBvbmVudFR5cGUgPSBWdWVDb21wb25lbnRGYWN0b3J5LmdldENvbXBvbmVudFR5cGUodGhpcy5wYXJlbnQsIGNvbXBvbmVudCk7XG4gICAgICAgIGlmICghY29tcG9uZW50VHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBWdWVDb21wb25lbnRGYWN0b3J5LmNyZWF0ZUFuZE1vdW50Q29tcG9uZW50KHBhcmFtcywgY29tcG9uZW50VHlwZSwgdGhpcy5wYXJlbnQpO1xuICAgIH07XG4gICAgVnVlRnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlci5wcm90b3R5cGUuY3JlYXRlTWV0aG9kUHJveHkgPSBmdW5jdGlvbiAod3JhcHBlciwgbWV0aG9kTmFtZSwgbWFuZGF0b3J5KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAod3JhcHBlci5vdmVycmlkZVByb2Nlc3NpbmcobWV0aG9kTmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd3JhcHBlci5wcm9jZXNzTWV0aG9kKG1ldGhvZE5hbWUsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAod3JhcHBlci5oYXNNZXRob2QobWV0aG9kTmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd3JhcHBlci5jYWxsTWV0aG9kKG1ldGhvZE5hbWUsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWFuZGF0b3J5KSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdBRyBHcmlkOiBGcmFtZXdvcmsgY29tcG9uZW50IGlzIG1pc3NpbmcgdGhlIG1ldGhvZCAnICsgbWV0aG9kTmFtZSArICcoKScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBWdWVGcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnBhcmVudCA9IG51bGw7XG4gICAgfTtcbiAgICBWdWVGcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyID0gX19kZWNvcmF0ZShbXG4gICAgICAgIEJlYW4oJ2ZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXInKVxuICAgIF0sIFZ1ZUZyYW1ld29ya0NvbXBvbmVudFdyYXBwZXIpO1xuICAgIHJldHVybiBWdWVGcmFtZXdvcmtDb21wb25lbnRXcmFwcGVyO1xufShCYXNlQ29tcG9uZW50V3JhcHBlcikpO1xuZXhwb3J0IHsgVnVlRnJhbWV3b3JrQ29tcG9uZW50V3JhcHBlciB9O1xudmFyIFZ1ZUNvbXBvbmVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBWdWVDb21wb25lbnQoKSB7XG4gICAgfVxuICAgIFZ1ZUNvbXBvbmVudC5wcm90b3R5cGUuZ2V0R3VpID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21wb25lbnQuJGVsO1xuICAgIH07XG4gICAgVnVlQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5nZXRGcmFtZXdvcmtDb21wb25lbnRJbnN0YW5jZSgpICYmXG4gICAgICAgICAgICB0eXBlb2YgdGhpcy5nZXRGcmFtZXdvcmtDb21wb25lbnRJbnN0YW5jZSgpLmRlc3Ryb3kgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0RnJhbWV3b3JrQ29tcG9uZW50SW5zdGFuY2UoKS5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb21wb25lbnQuJGRlc3Ryb3koKTtcbiAgICB9O1xuICAgIFZ1ZUNvbXBvbmVudC5wcm90b3R5cGUuZ2V0RnJhbWV3b3JrQ29tcG9uZW50SW5zdGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbXBvbmVudDtcbiAgICB9O1xuICAgIFZ1ZUNvbXBvbmVudC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgdGhpcy5jb21wb25lbnQgPSB0aGlzLmNyZWF0ZUNvbXBvbmVudChwYXJhbXMpO1xuICAgIH07XG4gICAgcmV0dXJuIFZ1ZUNvbXBvbmVudDtcbn0oKSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/lib/VueFrameworkComponentWrapper.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/lib/VueFrameworkOverrides.js": /*!***************************************************************!*\ !*** ./node_modules/ag-grid-vue/lib/VueFrameworkOverrides.js ***! \***************************************************************/ /*! exports provided: VueFrameworkOverrides */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"VueFrameworkOverrides\", function() { return VueFrameworkOverrides; });\n/* harmony import */ var ag_grid_community__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ag-grid-community */ \"./node_modules/ag-grid-community/dist/ag-grid-community.auto.esm.js\");\n/* harmony import */ var _VueComponentFactory__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VueComponentFactory */ \"./node_modules/ag-grid-vue/lib/VueComponentFactory.js\");\nvar __extends = (undefined && undefined.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\n\n\nvar VueFrameworkOverrides = /** @class */ (function (_super) {\n __extends(VueFrameworkOverrides, _super);\n function VueFrameworkOverrides(parent) {\n var _this = _super.call(this) || this;\n _this.parent = parent;\n return _this;\n }\n /*\n * vue components are specified in the \"components\" part of the vue component - as such we need a way to determine\n * if a given component is within that context - this method provides this\n * Note: This is only really used/necessary with cellRendererSelectors\n */\n VueFrameworkOverrides.prototype.frameworkComponent = function (name, components) {\n var foundInstance = !!_VueComponentFactory__WEBPACK_IMPORTED_MODULE_1__[\"VueComponentFactory\"].searchForComponentInstance(this.parent, name, 10, true);\n var result = foundInstance ? name : null;\n if (!result && components && components[name]) {\n var indirectName = components[name];\n foundInstance = !!_VueComponentFactory__WEBPACK_IMPORTED_MODULE_1__[\"VueComponentFactory\"].searchForComponentInstance(this.parent, indirectName, 10, true);\n result = foundInstance ? indirectName : null;\n }\n return result;\n };\n VueFrameworkOverrides.prototype.isFrameworkComponent = function (comp) {\n return typeof comp === 'object';\n };\n return VueFrameworkOverrides;\n}(ag_grid_community__WEBPACK_IMPORTED_MODULE_0__[\"VanillaFrameworkOverrides\"]));\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbGliL1Z1ZUZyYW1ld29ya092ZXJyaWRlcy5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9hZy1ncmlkLXZ1ZS9saWIvVnVlRnJhbWV3b3JrT3ZlcnJpZGVzLmpzP2FhYzUiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG5pbXBvcnQgeyBWYW5pbGxhRnJhbWV3b3JrT3ZlcnJpZGVzIH0gZnJvbSAnYWctZ3JpZC1jb21tdW5pdHknO1xuaW1wb3J0IHsgVnVlQ29tcG9uZW50RmFjdG9yeSB9IGZyb20gJy4vVnVlQ29tcG9uZW50RmFjdG9yeSc7XG52YXIgVnVlRnJhbWV3b3JrT3ZlcnJpZGVzID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhWdWVGcmFtZXdvcmtPdmVycmlkZXMsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVnVlRnJhbWV3b3JrT3ZlcnJpZGVzKHBhcmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG4gICAgLypcbiAgICAgKiB2dWUgY29tcG9uZW50cyBhcmUgc3BlY2lmaWVkIGluIHRoZSBcImNvbXBvbmVudHNcIiBwYXJ0IG9mIHRoZSB2dWUgY29tcG9uZW50IC0gYXMgc3VjaCB3ZSBuZWVkIGEgd2F5IHRvIGRldGVybWluZVxuICAgICAqIGlmIGEgZ2l2ZW4gY29tcG9uZW50IGlzIHdpdGhpbiB0aGF0IGNvbnRleHQgLSB0aGlzIG1ldGhvZCBwcm92aWRlcyB0aGlzXG4gICAgICogTm90ZTogVGhpcyBpcyBvbmx5IHJlYWxseSB1c2VkL25lY2Vzc2FyeSB3aXRoIGNlbGxSZW5kZXJlclNlbGVjdG9yc1xuICAgICAqL1xuICAgIFZ1ZUZyYW1ld29ya092ZXJyaWRlcy5wcm90b3R5cGUuZnJhbWV3b3JrQ29tcG9uZW50ID0gZnVuY3Rpb24gKG5hbWUsIGNvbXBvbmVudHMpIHtcbiAgICAgICAgdmFyIGZvdW5kSW5zdGFuY2UgPSAhIVZ1ZUNvbXBvbmVudEZhY3Rvcnkuc2VhcmNoRm9yQ29tcG9uZW50SW5zdGFuY2UodGhpcy5wYXJlbnQsIG5hbWUsIDEwLCB0cnVlKTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGZvdW5kSW5zdGFuY2UgPyBuYW1lIDogbnVsbDtcbiAgICAgICAgaWYgKCFyZXN1bHQgJiYgY29tcG9uZW50cyAmJiBjb21wb25lbnRzW25hbWVdKSB7XG4gICAgICAgICAgICB2YXIgaW5kaXJlY3ROYW1lID0gY29tcG9uZW50c1tuYW1lXTtcbiAgICAgICAgICAgIGZvdW5kSW5zdGFuY2UgPSAhIVZ1ZUNvbXBvbmVudEZhY3Rvcnkuc2VhcmNoRm9yQ29tcG9uZW50SW5zdGFuY2UodGhpcy5wYXJlbnQsIGluZGlyZWN0TmFtZSwgMTAsIHRydWUpO1xuICAgICAgICAgICAgcmVzdWx0ID0gZm91bmRJbnN0YW5jZSA/IGluZGlyZWN0TmFtZSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIFZ1ZUZyYW1ld29ya092ZXJyaWRlcy5wcm90b3R5cGUuaXNGcmFtZXdvcmtDb21wb25lbnQgPSBmdW5jdGlvbiAoY29tcCkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGNvbXAgPT09ICdvYmplY3QnO1xuICAgIH07XG4gICAgcmV0dXJuIFZ1ZUZyYW1ld29ya092ZXJyaWRlcztcbn0oVmFuaWxsYUZyYW1ld29ya092ZXJyaWRlcykpO1xuZXhwb3J0IHsgVnVlRnJhbWV3b3JrT3ZlcnJpZGVzIH07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/lib/VueFrameworkOverrides.js\n"); /***/ }), /***/ "./node_modules/ag-grid-vue/main.js": /*!******************************************!*\ !*** ./node_modules/ag-grid-vue/main.js ***! \******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\nfunction __export(m) {\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\n}\nObject.defineProperty(exports, \"__esModule\", { value: true });\n__export(__webpack_require__(/*! ./lib/AgGridVue */ \"./node_modules/ag-grid-vue/lib/AgGridVue.js\"));\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYWctZ3JpZC12dWUvbWFpbi5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9hZy1ncmlkLXZ1ZS9tYWluLmpzPzQwMWIiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5mdW5jdGlvbiBfX2V4cG9ydChtKSB7XG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xufVxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuX19leHBvcnQocmVxdWlyZShcIi4vbGliL0FnR3JpZFZ1ZVwiKSk7XG5cbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/ag-grid-vue/main.js\n"); /***/ }), /***/ "./node_modules/core-js/modules/_own-keys.js": /*!***************************************************!*\ !*** ./node_modules/core-js/modules/_own-keys.js ***! \***************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { eval("// all object keys, includes non-enumerable and symbols\nvar gOPN = __webpack_require__(/*! ./_object-gopn */ \"./node_modules/core-js/modules/_object-gopn.js\");\nvar gOPS = __webpack_require__(/*! ./_object-gops */ \"./node_modules/core-js/modules/_object-gops.js\");\nvar anObject = __webpack_require__(/*! ./_an-object */ \"./node_modules/core-js/modules/_an-object.js\");\nvar Reflect = __webpack_require__(/*! ./_global */ \"./node_modules/core-js/modules/_global.js\").Reflect;\nmodule.exports = Reflect && Reflect.ownKeys || function ownKeys(it) {\n var keys = gOPN.f(anObject(it));\n var getSymbols = gOPS.f;\n return getSymbols ? keys.concat(getSymbols(it)) : keys;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19vd24ta2V5cy5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX293bi1rZXlzLmpzPzk5MGIiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gYWxsIG9iamVjdCBrZXlzLCBpbmNsdWRlcyBub24tZW51bWVyYWJsZSBhbmQgc3ltYm9sc1xudmFyIGdPUE4gPSByZXF1aXJlKCcuL19vYmplY3QtZ29wbicpO1xudmFyIGdPUFMgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wcycpO1xudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgUmVmbGVjdCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLlJlZmxlY3Q7XG5tb2R1bGUuZXhwb3J0cyA9IFJlZmxlY3QgJiYgUmVmbGVjdC5vd25LZXlzIHx8IGZ1bmN0aW9uIG93bktleXMoaXQpIHtcbiAgdmFyIGtleXMgPSBnT1BOLmYoYW5PYmplY3QoaXQpKTtcbiAgdmFyIGdldFN5bWJvbHMgPSBnT1BTLmY7XG4gIHJldHVybiBnZXRTeW1ib2xzID8ga2V5cy5jb25jYXQoZ2V0U3ltYm9scyhpdCkpIDoga2V5cztcbn07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/core-js/modules/_own-keys.js\n"); /***/ }), /***/ "./node_modules/core-js/modules/_strict-method.js": /*!********************************************************!*\ !*** ./node_modules/core-js/modules/_strict-method.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\nvar fails = __webpack_require__(/*! ./_fails */ \"./node_modules/core-js/modules/_fails.js\");\n\nmodule.exports = function (method, arg) {\n return !!method && fails(function () {\n // eslint-disable-next-line no-useless-call\n arg ? method.call(null, function () { /* empty */ }, 1) : method.call(null);\n });\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19zdHJpY3QtbWV0aG9kLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc3RyaWN0LW1ldGhvZC5qcz8yZjIxIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4vX2ZhaWxzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG1ldGhvZCwgYXJnKSB7XG4gIHJldHVybiAhIW1ldGhvZCAmJiBmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY2FsbFxuICAgIGFyZyA/IG1ldGhvZC5jYWxsKG51bGwsIGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfSwgMSkgOiBtZXRob2QuY2FsbChudWxsKTtcbiAgfSk7XG59O1xuIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/core-js/modules/_strict-method.js\n"); /***/ }), /***/ "./node_modules/core-js/modules/es6.array.sort.js": /*!********************************************************!*\ !*** ./node_modules/core-js/modules/es6.array.sort.js ***! \********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\nvar $export = __webpack_require__(/*! ./_export */ \"./node_modules/core-js/modules/_export.js\");\nvar aFunction = __webpack_require__(/*! ./_a-function */ \"./node_modules/core-js/modules/_a-function.js\");\nvar toObject = __webpack_require__(/*! ./_to-object */ \"./node_modules/core-js/modules/_to-object.js\");\nvar fails = __webpack_require__(/*! ./_fails */ \"./node_modules/core-js/modules/_fails.js\");\nvar $sort = [].sort;\nvar test = [1, 2, 3];\n\n$export($export.P + $export.F * (fails(function () {\n // IE8-\n test.sort(undefined);\n}) || !fails(function () {\n // V8 bug\n test.sort(null);\n // Old WebKit\n}) || !__webpack_require__(/*! ./_strict-method */ \"./node_modules/core-js/modules/_strict-method.js\")($sort)), 'Array', {\n // 22.1.3.25 Array.prototype.sort(comparefn)\n sort: function sort(comparefn) {\n return comparefn === undefined\n ? $sort.call(toObject(this))\n : $sort.call(toObject(this), aFunction(comparefn));\n }\n});\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNi5hcnJheS5zb3J0LmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYuYXJyYXkuc29ydC5qcz81NWRkIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuL19mYWlscycpO1xudmFyICRzb3J0ID0gW10uc29ydDtcbnZhciB0ZXN0ID0gWzEsIDIsIDNdO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuRiAqIChmYWlscyhmdW5jdGlvbiAoKSB7XG4gIC8vIElFOC1cbiAgdGVzdC5zb3J0KHVuZGVmaW5lZCk7XG59KSB8fCAhZmFpbHMoZnVuY3Rpb24gKCkge1xuICAvLyBWOCBidWdcbiAgdGVzdC5zb3J0KG51bGwpO1xuICAvLyBPbGQgV2ViS2l0XG59KSB8fCAhcmVxdWlyZSgnLi9fc3RyaWN0LW1ldGhvZCcpKCRzb3J0KSksICdBcnJheScsIHtcbiAgLy8gMjIuMS4zLjI1IEFycmF5LnByb3RvdHlwZS5zb3J0KGNvbXBhcmVmbilcbiAgc29ydDogZnVuY3Rpb24gc29ydChjb21wYXJlZm4pIHtcbiAgICByZXR1cm4gY29tcGFyZWZuID09PSB1bmRlZmluZWRcbiAgICAgID8gJHNvcnQuY2FsbCh0b09iamVjdCh0aGlzKSlcbiAgICAgIDogJHNvcnQuY2FsbCh0b09iamVjdCh0aGlzKSwgYUZ1bmN0aW9uKGNvbXBhcmVmbikpO1xuICB9XG59KTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/core-js/modules/es6.array.sort.js\n"); /***/ }), /***/ "./node_modules/core-js/modules/es7.object.get-own-property-descriptors.js": /*!*********************************************************************************!*\ !*** ./node_modules/core-js/modules/es7.object.get-own-property-descriptors.js ***! \*********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { eval("// https://github.com/tc39/proposal-object-getownpropertydescriptors\nvar $export = __webpack_require__(/*! ./_export */ \"./node_modules/core-js/modules/_export.js\");\nvar ownKeys = __webpack_require__(/*! ./_own-keys */ \"./node_modules/core-js/modules/_own-keys.js\");\nvar toIObject = __webpack_require__(/*! ./_to-iobject */ \"./node_modules/core-js/modules/_to-iobject.js\");\nvar gOPD = __webpack_require__(/*! ./_object-gopd */ \"./node_modules/core-js/modules/_object-gopd.js\");\nvar createProperty = __webpack_require__(/*! ./_create-property */ \"./node_modules/core-js/modules/_create-property.js\");\n\n$export($export.S, 'Object', {\n getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) {\n var O = toIObject(object);\n var getDesc = gOPD.f;\n var keys = ownKeys(O);\n var result = {};\n var i = 0;\n var key, desc;\n while (keys.length > i) {\n desc = getDesc(O, key = keys[i++]);\n if (desc !== undefined) createProperty(result, key, desc);\n }\n return result;\n }\n});\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy5vYmplY3QuZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9ycy5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3JzLmpzPzhlNmUiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtb2JqZWN0LWdldG93bnByb3BlcnR5ZGVzY3JpcHRvcnNcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgb3duS2V5cyA9IHJlcXVpcmUoJy4vX293bi1rZXlzJyk7XG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIGdPUEQgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wZCcpO1xudmFyIGNyZWF0ZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9fY3JlYXRlLXByb3BlcnR5Jyk7XG5cbiRleHBvcnQoJGV4cG9ydC5TLCAnT2JqZWN0Jywge1xuICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzOiBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKG9iamVjdCkge1xuICAgIHZhciBPID0gdG9JT2JqZWN0KG9iamVjdCk7XG4gICAgdmFyIGdldERlc2MgPSBnT1BELmY7XG4gICAgdmFyIGtleXMgPSBvd25LZXlzKE8pO1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICB2YXIgaSA9IDA7XG4gICAgdmFyIGtleSwgZGVzYztcbiAgICB3aGlsZSAoa2V5cy5sZW5ndGggPiBpKSB7XG4gICAgICBkZXNjID0gZ2V0RGVzYyhPLCBrZXkgPSBrZXlzW2krK10pO1xuICAgICAgaWYgKGRlc2MgIT09IHVuZGVmaW5lZCkgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBrZXksIGRlc2MpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59KTtcbiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/core-js/modules/es7.object.get-own-property-descriptors.js\n"); /***/ }), /***/ "./node_modules/vue-class-component/dist/vue-class-component.esm.js": /*!**************************************************************************!*\ !*** ./node_modules/vue-class-component/dist/vue-class-component.esm.js ***! \**************************************************************************/ /*! exports provided: default, createDecorator, mixins */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"createDecorator\", function() { return createDecorator; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"mixins\", function() { return mixins; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm.js\");\n/**\n * vue-class-component v7.2.6\n * (c) 2015-present Evan You\n * @license MIT\n */\n\n\nfunction _typeof(obj) {\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function (obj) {\n return typeof obj;\n };\n } else {\n _typeof = function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}\n\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nfunction _toConsumableArray(arr) {\n return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();\n}\n\nfunction _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];\n\n return arr2;\n }\n}\n\nfunction _iterableToArray(iter) {\n if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter);\n}\n\nfunction _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance\");\n}\n\n// The rational behind the verbose Reflect-feature check below is the fact that there are polyfills\n// which add an implementation for Reflect.defineMetadata but not for Reflect.getOwnMetadataKeys.\n// Without this check consumers will encounter hard to track down runtime errors.\nfunction reflectionIsSupported() {\n return typeof Reflect !== 'undefined' && Reflect.defineMetadata && Reflect.getOwnMetadataKeys;\n}\nfunction copyReflectionMetadata(to, from) {\n forwardMetadata(to, from);\n Object.getOwnPropertyNames(from.prototype).forEach(function (key) {\n forwardMetadata(to.prototype, from.prototype, key);\n });\n Object.getOwnPropertyNames(from).forEach(function (key) {\n forwardMetadata(to, from, key);\n });\n}\n\nfunction forwardMetadata(to, from, propertyKey) {\n var metaKeys = propertyKey ? Reflect.getOwnMetadataKeys(from, propertyKey) : Reflect.getOwnMetadataKeys(from);\n metaKeys.forEach(function (metaKey) {\n var metadata = propertyKey ? Reflect.getOwnMetadata(metaKey, from, propertyKey) : Reflect.getOwnMetadata(metaKey, from);\n\n if (propertyKey) {\n Reflect.defineMetadata(metaKey, metadata, to, propertyKey);\n } else {\n Reflect.defineMetadata(metaKey, metadata, to);\n }\n });\n}\n\nvar fakeArray = {\n __proto__: []\n};\nvar hasProto = fakeArray instanceof Array;\nfunction createDecorator(factory) {\n return function (target, key, index) {\n var Ctor = typeof target === 'function' ? target : target.constructor;\n\n if (!Ctor.__decorators__) {\n Ctor.__decorators__ = [];\n }\n\n if (typeof index !== 'number') {\n index = undefined;\n }\n\n Ctor.__decorators__.push(function (options) {\n return factory(options, key, index);\n });\n };\n}\nfunction mixins() {\n for (var _len = arguments.length, Ctors = new Array(_len), _key = 0; _key < _len; _key++) {\n Ctors[_key] = arguments[_key];\n }\n\n return vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].extend({\n mixins: Ctors\n });\n}\nfunction isPrimitive(value) {\n var type = _typeof(value);\n\n return value == null || type !== 'object' && type !== 'function';\n}\nfunction warn(message) {\n if (typeof console !== 'undefined') {\n console.warn('[vue-class-component] ' + message);\n }\n}\n\nfunction collectDataFromConstructor(vm, Component) {\n // override _init to prevent to init as Vue instance\n var originalInit = Component.prototype._init;\n\n Component.prototype._init = function () {\n var _this = this;\n\n // proxy to actual vm\n var keys = Object.getOwnPropertyNames(vm); // 2.2.0 compat (props are no longer exposed as self properties)\n\n if (vm.$options.props) {\n for (var key in vm.$options.props) {\n if (!vm.hasOwnProperty(key)) {\n keys.push(key);\n }\n }\n }\n\n keys.forEach(function (key) {\n Object.defineProperty(_this, key, {\n get: function get() {\n return vm[key];\n },\n set: function set(value) {\n vm[key] = value;\n },\n configurable: true\n });\n });\n }; // should be acquired class property values\n\n\n var data = new Component(); // restore original _init to avoid memory leak (#209)\n\n Component.prototype._init = originalInit; // create plain data object\n\n var plainData = {};\n Object.keys(data).forEach(function (key) {\n if (data[key] !== undefined) {\n plainData[key] = data[key];\n }\n });\n\n if (true) {\n if (!(Component.prototype instanceof vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]) && Object.keys(plainData).length > 0) {\n warn('Component class must inherit Vue or its descendant class ' + 'when class property is used.');\n }\n }\n\n return plainData;\n}\n\nvar $internalHooks = ['data', 'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeDestroy', 'destroyed', 'beforeUpdate', 'updated', 'activated', 'deactivated', 'render', 'errorCaptured', 'serverPrefetch' // 2.6\n];\nfunction componentFactory(Component) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n options.name = options.name || Component._componentTag || Component.name; // prototype props.\n\n var proto = Component.prototype;\n Object.getOwnPropertyNames(proto).forEach(function (key) {\n if (key === 'constructor') {\n return;\n } // hooks\n\n\n if ($internalHooks.indexOf(key) > -1) {\n options[key] = proto[key];\n return;\n }\n\n var descriptor = Object.getOwnPropertyDescriptor(proto, key);\n\n if (descriptor.value !== void 0) {\n // methods\n if (typeof descriptor.value === 'function') {\n (options.methods || (options.methods = {}))[key] = descriptor.value;\n } else {\n // typescript decorated data\n (options.mixins || (options.mixins = [])).push({\n data: function data() {\n return _defineProperty({}, key, descriptor.value);\n }\n });\n }\n } else if (descriptor.get || descriptor.set) {\n // computed properties\n (options.computed || (options.computed = {}))[key] = {\n get: descriptor.get,\n set: descriptor.set\n };\n }\n });\n (options.mixins || (options.mixins = [])).push({\n data: function data() {\n return collectDataFromConstructor(this, Component);\n }\n }); // decorate options\n\n var decorators = Component.__decorators__;\n\n if (decorators) {\n decorators.forEach(function (fn) {\n return fn(options);\n });\n delete Component.__decorators__;\n } // find super\n\n\n var superProto = Object.getPrototypeOf(Component.prototype);\n var Super = superProto instanceof vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"] ? superProto.constructor : vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\n var Extended = Super.extend(options);\n forwardStaticMembers(Extended, Component, Super);\n\n if (reflectionIsSupported()) {\n copyReflectionMetadata(Extended, Component);\n }\n\n return Extended;\n}\nvar reservedPropertyNames = [// Unique id\n'cid', // Super Vue constructor\n'super', // Component options that will be used by the component\n'options', 'superOptions', 'extendOptions', 'sealedOptions', // Private assets\n'component', 'directive', 'filter'];\nvar shouldIgnore = {\n prototype: true,\n arguments: true,\n callee: true,\n caller: true\n};\n\nfunction forwardStaticMembers(Extended, Original, Super) {\n // We have to use getOwnPropertyNames since Babel registers methods as non-enumerable\n Object.getOwnPropertyNames(Original).forEach(function (key) {\n // Skip the properties that should not be overwritten\n if (shouldIgnore[key]) {\n return;\n } // Some browsers does not allow reconfigure built-in properties\n\n\n var extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key);\n\n if (extendedDescriptor && !extendedDescriptor.configurable) {\n return;\n }\n\n var descriptor = Object.getOwnPropertyDescriptor(Original, key); // If the user agent does not support `__proto__` or its family (IE <= 10),\n // the sub class properties may be inherited properties from the super class in TypeScript.\n // We need to exclude such properties to prevent to overwrite\n // the component options object which stored on the extended constructor (See #192).\n // If the value is a referenced value (object or function),\n // we can check equality of them and exclude it if they have the same reference.\n // If it is a primitive value, it will be forwarded for safety.\n\n if (!hasProto) {\n // Only `cid` is explicitly exluded from property forwarding\n // because we cannot detect whether it is a inherited property or not\n // on the no `__proto__` environment even though the property is reserved.\n if (key === 'cid') {\n return;\n }\n\n var superDescriptor = Object.getOwnPropertyDescriptor(Super, key);\n\n if (!isPrimitive(descriptor.value) && superDescriptor && superDescriptor.value === descriptor.value) {\n return;\n }\n } // Warn if the users manually declare reserved properties\n\n\n if ( true && reservedPropertyNames.indexOf(key) >= 0) {\n warn(\"Static property name '\".concat(key, \"' declared on class '\").concat(Original.name, \"' \") + 'conflicts with reserved property name of Vue internal. ' + 'It may cause unexpected behavior of the component. Consider renaming the property.');\n }\n\n Object.defineProperty(Extended, key, descriptor);\n });\n}\n\nfunction Component(options) {\n if (typeof options === 'function') {\n return componentFactory(options);\n }\n\n return function (Component) {\n return componentFactory(Component, options);\n };\n}\n\nComponent.registerHooks = function registerHooks(keys) {\n $internalHooks.push.apply($internalHooks, _toConsumableArray(keys));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Component);\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvdnVlLWNsYXNzLWNvbXBvbmVudC9kaXN0L3Z1ZS1jbGFzcy1jb21wb25lbnQuZXNtLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL3Z1ZS1jbGFzcy1jb21wb25lbnQvZGlzdC92dWUtY2xhc3MtY29tcG9uZW50LmVzbS5qcz8yZmUxIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICAqIHZ1ZS1jbGFzcy1jb21wb25lbnQgdjcuMi42XG4gICogKGMpIDIwMTUtcHJlc2VudCBFdmFuIFlvdVxuICAqIEBsaWNlbnNlIE1JVFxuICAqL1xuaW1wb3J0IFZ1ZSBmcm9tICd2dWUnO1xuXG5mdW5jdGlvbiBfdHlwZW9mKG9iaikge1xuICBpZiAodHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIpIHtcbiAgICBfdHlwZW9mID0gZnVuY3Rpb24gKG9iaikge1xuICAgICAgcmV0dXJuIHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICBfdHlwZW9mID0gZnVuY3Rpb24gKG9iaikge1xuICAgICAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBfdHlwZW9mKG9iaik7XG59XG5cbmZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBvYmopIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHtcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogdHJ1ZVxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIG9ialtrZXldID0gdmFsdWU7XG4gIH1cblxuICByZXR1cm4gb2JqO1xufVxuXG5mdW5jdGlvbiBfdG9Db25zdW1hYmxlQXJyYXkoYXJyKSB7XG4gIHJldHVybiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5KGFycikgfHwgX25vbkl0ZXJhYmxlU3ByZWFkKCk7XG59XG5cbmZ1bmN0aW9uIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGFyci5sZW5ndGgpOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSBhcnIyW2ldID0gYXJyW2ldO1xuXG4gICAgcmV0dXJuIGFycjI7XG4gIH1cbn1cblxuZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheShpdGVyKSB7XG4gIGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGl0ZXIpIHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpdGVyKSA9PT0gXCJbb2JqZWN0IEFyZ3VtZW50c11cIikgcmV0dXJuIEFycmF5LmZyb20oaXRlcik7XG59XG5cbmZ1bmN0aW9uIF9ub25JdGVyYWJsZVNwcmVhZCgpIHtcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlXCIpO1xufVxuXG4vLyBUaGUgcmF0aW9uYWwgYmVoaW5kIHRoZSB2ZXJib3NlIFJlZmxlY3QtZmVhdHVyZSBjaGVjayBiZWxvdyBpcyB0aGUgZmFjdCB0aGF0IHRoZXJlIGFyZSBwb2x5ZmlsbHNcbi8vIHdoaWNoIGFkZCBhbiBpbXBsZW1lbnRhdGlvbiBmb3IgUmVmbGVjdC5kZWZpbmVNZXRhZGF0YSBidXQgbm90IGZvciBSZWZsZWN0LmdldE93bk1ldGFkYXRhS2V5cy5cbi8vIFdpdGhvdXQgdGhpcyBjaGVjayBjb25zdW1lcnMgd2lsbCBlbmNvdW50ZXIgaGFyZCB0byB0cmFjayBkb3duIHJ1bnRpbWUgZXJyb3JzLlxuZnVuY3Rpb24gcmVmbGVjdGlvbklzU3VwcG9ydGVkKCkge1xuICByZXR1cm4gdHlwZW9mIFJlZmxlY3QgIT09ICd1bmRlZmluZWQnICYmIFJlZmxlY3QuZGVmaW5lTWV0YWRhdGEgJiYgUmVmbGVjdC5nZXRPd25NZXRhZGF0YUtleXM7XG59XG5mdW5jdGlvbiBjb3B5UmVmbGVjdGlvbk1ldGFkYXRhKHRvLCBmcm9tKSB7XG4gIGZvcndhcmRNZXRhZGF0YSh0bywgZnJvbSk7XG4gIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGZyb20ucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICBmb3J3YXJkTWV0YWRhdGEodG8ucHJvdG90eXBlLCBmcm9tLnByb3RvdHlwZSwga2V5KTtcbiAgfSk7XG4gIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGZyb20pLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIGZvcndhcmRNZXRhZGF0YSh0bywgZnJvbSwga2V5KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGZvcndhcmRNZXRhZGF0YSh0bywgZnJvbSwgcHJvcGVydHlLZXkpIHtcbiAgdmFyIG1ldGFLZXlzID0gcHJvcGVydHlLZXkgPyBSZWZsZWN0LmdldE93bk1ldGFkYXRhS2V5cyhmcm9tLCBwcm9wZXJ0eUtleSkgOiBSZWZsZWN0LmdldE93bk1ldGFkYXRhS2V5cyhmcm9tKTtcbiAgbWV0YUtleXMuZm9yRWFjaChmdW5jdGlvbiAobWV0YUtleSkge1xuICAgIHZhciBtZXRhZGF0YSA9IHByb3BlcnR5S2V5ID8gUmVmbGVjdC5nZXRPd25NZXRhZGF0YShtZXRhS2V5LCBmcm9tLCBwcm9wZXJ0eUtleSkgOiBSZWZsZWN0LmdldE93bk1ldGFkYXRhKG1ldGFLZXksIGZyb20pO1xuXG4gICAgaWYgKHByb3BlcnR5S2V5KSB7XG4gICAgICBSZWZsZWN0LmRlZmluZU1ldGFkYXRhKG1ldGFLZXksIG1ldGFkYXRhLCB0bywgcHJvcGVydHlLZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBSZWZsZWN0LmRlZmluZU1ldGFkYXRhKG1ldGFLZXksIG1ldGFkYXRhLCB0byk7XG4gICAgfVxuICB9KTtcbn1cblxudmFyIGZha2VBcnJheSA9IHtcbiAgX19wcm90b19fOiBbXVxufTtcbnZhciBoYXNQcm90byA9IGZha2VBcnJheSBpbnN0YW5jZW9mIEFycmF5O1xuZnVuY3Rpb24gY3JlYXRlRGVjb3JhdG9yKGZhY3RvcnkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSwgaW5kZXgpIHtcbiAgICB2YXIgQ3RvciA9IHR5cGVvZiB0YXJnZXQgPT09ICdmdW5jdGlvbicgPyB0YXJnZXQgOiB0YXJnZXQuY29uc3RydWN0b3I7XG5cbiAgICBpZiAoIUN0b3IuX19kZWNvcmF0b3JzX18pIHtcbiAgICAgIEN0b3IuX19kZWNvcmF0b3JzX18gPSBbXTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGluZGV4ICE9PSAnbnVtYmVyJykge1xuICAgICAgaW5kZXggPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgQ3Rvci5fX2RlY29yYXRvcnNfXy5wdXNoKGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICByZXR1cm4gZmFjdG9yeShvcHRpb25zLCBrZXksIGluZGV4KTtcbiAgICB9KTtcbiAgfTtcbn1cbmZ1bmN0aW9uIG1peGlucygpIHtcbiAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIEN0b3JzID0gbmV3IEFycmF5KF9sZW4pLCBfa2V5ID0gMDsgX2tleSA8IF9sZW47IF9rZXkrKykge1xuICAgIEN0b3JzW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICB9XG5cbiAgcmV0dXJuIFZ1ZS5leHRlbmQoe1xuICAgIG1peGluczogQ3RvcnNcbiAgfSk7XG59XG5mdW5jdGlvbiBpc1ByaW1pdGl2ZSh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IF90eXBlb2YodmFsdWUpO1xuXG4gIHJldHVybiB2YWx1ZSA9PSBudWxsIHx8IHR5cGUgIT09ICdvYmplY3QnICYmIHR5cGUgIT09ICdmdW5jdGlvbic7XG59XG5mdW5jdGlvbiB3YXJuKG1lc3NhZ2UpIHtcbiAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJykge1xuICAgIGNvbnNvbGUud2FybignW3Z1ZS1jbGFzcy1jb21wb25lbnRdICcgKyBtZXNzYWdlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb2xsZWN0RGF0YUZyb21Db25zdHJ1Y3Rvcih2bSwgQ29tcG9uZW50KSB7XG4gIC8vIG92ZXJyaWRlIF9pbml0IHRvIHByZXZlbnQgdG8gaW5pdCBhcyBWdWUgaW5zdGFuY2VcbiAgdmFyIG9yaWdpbmFsSW5pdCA9IENvbXBvbmVudC5wcm90b3R5cGUuX2luaXQ7XG5cbiAgQ29tcG9uZW50LnByb3RvdHlwZS5faW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgLy8gcHJveHkgdG8gYWN0dWFsIHZtXG4gICAgdmFyIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2bSk7IC8vIDIuMi4wIGNvbXBhdCAocHJvcHMgYXJlIG5vIGxvbmdlciBleHBvc2VkIGFzIHNlbGYgcHJvcGVydGllcylcblxuICAgIGlmICh2bS4kb3B0aW9ucy5wcm9wcykge1xuICAgICAgZm9yICh2YXIga2V5IGluIHZtLiRvcHRpb25zLnByb3BzKSB7XG4gICAgICAgIGlmICghdm0uaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgIGtleXMucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShfdGhpcywga2V5LCB7XG4gICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICAgIHJldHVybiB2bVtrZXldO1xuICAgICAgICB9LFxuICAgICAgICBzZXQ6IGZ1bmN0aW9uIHNldCh2YWx1ZSkge1xuICAgICAgICAgIHZtW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTsgLy8gc2hvdWxkIGJlIGFjcXVpcmVkIGNsYXNzIHByb3BlcnR5IHZhbHVlc1xuXG5cbiAgdmFyIGRhdGEgPSBuZXcgQ29tcG9uZW50KCk7IC8vIHJlc3RvcmUgb3JpZ2luYWwgX2luaXQgdG8gYXZvaWQgbWVtb3J5IGxlYWsgKCMyMDkpXG5cbiAgQ29tcG9uZW50LnByb3RvdHlwZS5faW5pdCA9IG9yaWdpbmFsSW5pdDsgLy8gY3JlYXRlIHBsYWluIGRhdGEgb2JqZWN0XG5cbiAgdmFyIHBsYWluRGF0YSA9IHt9O1xuICBPYmplY3Qua2V5cyhkYXRhKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICBpZiAoZGF0YVtrZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHBsYWluRGF0YVtrZXldID0gZGF0YVtrZXldO1xuICAgIH1cbiAgfSk7XG5cbiAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICBpZiAoIShDb21wb25lbnQucHJvdG90eXBlIGluc3RhbmNlb2YgVnVlKSAmJiBPYmplY3Qua2V5cyhwbGFpbkRhdGEpLmxlbmd0aCA+IDApIHtcbiAgICAgIHdhcm4oJ0NvbXBvbmVudCBjbGFzcyBtdXN0IGluaGVyaXQgVnVlIG9yIGl0cyBkZXNjZW5kYW50IGNsYXNzICcgKyAnd2hlbiBjbGFzcyBwcm9wZXJ0eSBpcyB1c2VkLicpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwbGFpbkRhdGE7XG59XG5cbnZhciAkaW50ZXJuYWxIb29rcyA9IFsnZGF0YScsICdiZWZvcmVDcmVhdGUnLCAnY3JlYXRlZCcsICdiZWZvcmVNb3VudCcsICdtb3VudGVkJywgJ2JlZm9yZURlc3Ryb3knLCAnZGVzdHJveWVkJywgJ2JlZm9yZVVwZGF0ZScsICd1cGRhdGVkJywgJ2FjdGl2YXRlZCcsICdkZWFjdGl2YXRlZCcsICdyZW5kZXInLCAnZXJyb3JDYXB0dXJlZCcsICdzZXJ2ZXJQcmVmZXRjaCcgLy8gMi42XG5dO1xuZnVuY3Rpb24gY29tcG9uZW50RmFjdG9yeShDb21wb25lbnQpIHtcbiAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuICBvcHRpb25zLm5hbWUgPSBvcHRpb25zLm5hbWUgfHwgQ29tcG9uZW50Ll9jb21wb25lbnRUYWcgfHwgQ29tcG9uZW50Lm5hbWU7IC8vIHByb3RvdHlwZSBwcm9wcy5cblxuICB2YXIgcHJvdG8gPSBDb21wb25lbnQucHJvdG90eXBlO1xuICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhwcm90bykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgaWYgKGtleSA9PT0gJ2NvbnN0cnVjdG9yJykge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gaG9va3NcblxuXG4gICAgaWYgKCRpbnRlcm5hbEhvb2tzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBvcHRpb25zW2tleV0gPSBwcm90b1trZXldO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBkZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihwcm90bywga2V5KTtcblxuICAgIGlmIChkZXNjcmlwdG9yLnZhbHVlICE9PSB2b2lkIDApIHtcbiAgICAgIC8vIG1ldGhvZHNcbiAgICAgIGlmICh0eXBlb2YgZGVzY3JpcHRvci52YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAob3B0aW9ucy5tZXRob2RzIHx8IChvcHRpb25zLm1ldGhvZHMgPSB7fSkpW2tleV0gPSBkZXNjcmlwdG9yLnZhbHVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gdHlwZXNjcmlwdCBkZWNvcmF0ZWQgZGF0YVxuICAgICAgICAob3B0aW9ucy5taXhpbnMgfHwgKG9wdGlvbnMubWl4aW5zID0gW10pKS5wdXNoKHtcbiAgICAgICAgICBkYXRhOiBmdW5jdGlvbiBkYXRhKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9kZWZpbmVQcm9wZXJ0eSh7fSwga2V5LCBkZXNjcmlwdG9yLnZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZGVzY3JpcHRvci5nZXQgfHwgZGVzY3JpcHRvci5zZXQpIHtcbiAgICAgIC8vIGNvbXB1dGVkIHByb3BlcnRpZXNcbiAgICAgIChvcHRpb25zLmNvbXB1dGVkIHx8IChvcHRpb25zLmNvbXB1dGVkID0ge30pKVtrZXldID0ge1xuICAgICAgICBnZXQ6IGRlc2NyaXB0b3IuZ2V0LFxuICAgICAgICBzZXQ6IGRlc2NyaXB0b3Iuc2V0XG4gICAgICB9O1xuICAgIH1cbiAgfSk7XG4gIChvcHRpb25zLm1peGlucyB8fCAob3B0aW9ucy5taXhpbnMgPSBbXSkpLnB1c2goe1xuICAgIGRhdGE6IGZ1bmN0aW9uIGRhdGEoKSB7XG4gICAgICByZXR1cm4gY29sbGVjdERhdGFGcm9tQ29uc3RydWN0b3IodGhpcywgQ29tcG9uZW50KTtcbiAgICB9XG4gIH0pOyAvLyBkZWNvcmF0ZSBvcHRpb25zXG5cbiAgdmFyIGRlY29yYXRvcnMgPSBDb21wb25lbnQuX19kZWNvcmF0b3JzX187XG5cbiAgaWYgKGRlY29yYXRvcnMpIHtcbiAgICBkZWNvcmF0b3JzLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XG4gICAgICByZXR1cm4gZm4ob3B0aW9ucyk7XG4gICAgfSk7XG4gICAgZGVsZXRlIENvbXBvbmVudC5fX2RlY29yYXRvcnNfXztcbiAgfSAvLyBmaW5kIHN1cGVyXG5cblxuICB2YXIgc3VwZXJQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihDb21wb25lbnQucHJvdG90eXBlKTtcbiAgdmFyIFN1cGVyID0gc3VwZXJQcm90byBpbnN0YW5jZW9mIFZ1ZSA/IHN1cGVyUHJvdG8uY29uc3RydWN0b3IgOiBWdWU7XG4gIHZhciBFeHRlbmRlZCA9IFN1cGVyLmV4dGVuZChvcHRpb25zKTtcbiAgZm9yd2FyZFN0YXRpY01lbWJlcnMoRXh0ZW5kZWQsIENvbXBvbmVudCwgU3VwZXIpO1xuXG4gIGlmIChyZWZsZWN0aW9uSXNTdXBwb3J0ZWQoKSkge1xuICAgIGNvcHlSZWZsZWN0aW9uTWV0YWRhdGEoRXh0ZW5kZWQsIENvbXBvbmVudCk7XG4gIH1cblxuICByZXR1cm4gRXh0ZW5kZWQ7XG59XG52YXIgcmVzZXJ2ZWRQcm9wZXJ0eU5hbWVzID0gWy8vIFVuaXF1ZSBpZFxuJ2NpZCcsIC8vIFN1cGVyIFZ1ZSBjb25zdHJ1Y3RvclxuJ3N1cGVyJywgLy8gQ29tcG9uZW50IG9wdGlvbnMgdGhhdCB3aWxsIGJlIHVzZWQgYnkgdGhlIGNvbXBvbmVudFxuJ29wdGlvbnMnLCAnc3VwZXJPcHRpb25zJywgJ2V4dGVuZE9wdGlvbnMnLCAnc2VhbGVkT3B0aW9ucycsIC8vIFByaXZhdGUgYXNzZXRzXG4nY29tcG9uZW50JywgJ2RpcmVjdGl2ZScsICdmaWx0ZXInXTtcbnZhciBzaG91bGRJZ25vcmUgPSB7XG4gIHByb3RvdHlwZTogdHJ1ZSxcbiAgYXJndW1lbnRzOiB0cnVlLFxuICBjYWxsZWU6IHRydWUsXG4gIGNhbGxlcjogdHJ1ZVxufTtcblxuZnVuY3Rpb24gZm9yd2FyZFN0YXRpY01lbWJlcnMoRXh0ZW5kZWQsIE9yaWdpbmFsLCBTdXBlcikge1xuICAvLyBXZSBoYXZlIHRvIHVzZSBnZXRPd25Qcm9wZXJ0eU5hbWVzIHNpbmNlIEJhYmVsIHJlZ2lzdGVycyBtZXRob2RzIGFzIG5vbi1lbnVtZXJhYmxlXG4gIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE9yaWdpbmFsKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAvLyBTa2lwIHRoZSBwcm9wZXJ0aWVzIHRoYXQgc2hvdWxkIG5vdCBiZSBvdmVyd3JpdHRlblxuICAgIGlmIChzaG91bGRJZ25vcmVba2V5XSkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gU29tZSBicm93c2VycyBkb2VzIG5vdCBhbGxvdyByZWNvbmZpZ3VyZSBidWlsdC1pbiBwcm9wZXJ0aWVzXG5cblxuICAgIHZhciBleHRlbmRlZERlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEV4dGVuZGVkLCBrZXkpO1xuXG4gICAgaWYgKGV4dGVuZGVkRGVzY3JpcHRvciAmJiAhZXh0ZW5kZWREZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBkZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPcmlnaW5hbCwga2V5KTsgLy8gSWYgdGhlIHVzZXIgYWdlbnQgZG9lcyBub3Qgc3VwcG9ydCBgX19wcm90b19fYCBvciBpdHMgZmFtaWx5IChJRSA8PSAxMCksXG4gICAgLy8gdGhlIHN1YiBjbGFzcyBwcm9wZXJ0aWVzIG1heSBiZSBpbmhlcml0ZWQgcHJvcGVydGllcyBmcm9tIHRoZSBzdXBlciBjbGFzcyBpbiBUeXBlU2NyaXB0LlxuICAgIC8vIFdlIG5lZWQgdG8gZXhjbHVkZSBzdWNoIHByb3BlcnRpZXMgdG8gcHJldmVudCB0byBvdmVyd3JpdGVcbiAgICAvLyB0aGUgY29tcG9uZW50IG9wdGlvbnMgb2JqZWN0IHdoaWNoIHN0b3JlZCBvbiB0aGUgZXh0ZW5kZWQgY29uc3RydWN0b3IgKFNlZSAjMTkyKS5cbiAgICAvLyBJZiB0aGUgdmFsdWUgaXMgYSByZWZlcmVuY2VkIHZhbHVlIChvYmplY3Qgb3IgZnVuY3Rpb24pLFxuICAgIC8vIHdlIGNhbiBjaGVjayBlcXVhbGl0eSBvZiB0aGVtIGFuZCBleGNsdWRlIGl0IGlmIHRoZXkgaGF2ZSB0aGUgc2FtZSByZWZlcmVuY2UuXG4gICAgLy8gSWYgaXQgaXMgYSBwcmltaXRpdmUgdmFsdWUsIGl0IHdpbGwgYmUgZm9yd2FyZGVkIGZvciBzYWZldHkuXG5cbiAgICBpZiAoIWhhc1Byb3RvKSB7XG4gICAgICAvLyBPbmx5IGBjaWRgIGlzIGV4cGxpY2l0bHkgZXhsdWRlZCBmcm9tIHByb3BlcnR5IGZvcndhcmRpbmdcbiAgICAgIC8vIGJlY2F1c2Ugd2UgY2Fubm90IGRldGVjdCB3aGV0aGVyIGl0IGlzIGEgaW5oZXJpdGVkIHByb3BlcnR5IG9yIG5vdFxuICAgICAgLy8gb24gdGhlIG5vIGBfX3Byb3RvX19gIGVudmlyb25tZW50IGV2ZW4gdGhvdWdoIHRoZSBwcm9wZXJ0eSBpcyByZXNlcnZlZC5cbiAgICAgIGlmIChrZXkgPT09ICdjaWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHN1cGVyRGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoU3VwZXIsIGtleSk7XG5cbiAgICAgIGlmICghaXNQcmltaXRpdmUoZGVzY3JpcHRvci52YWx1ZSkgJiYgc3VwZXJEZXNjcmlwdG9yICYmIHN1cGVyRGVzY3JpcHRvci52YWx1ZSA9PT0gZGVzY3JpcHRvci52YWx1ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSAvLyBXYXJuIGlmIHRoZSB1c2VycyBtYW51YWxseSBkZWNsYXJlIHJlc2VydmVkIHByb3BlcnRpZXNcblxuXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgcmVzZXJ2ZWRQcm9wZXJ0eU5hbWVzLmluZGV4T2Yoa2V5KSA+PSAwKSB7XG4gICAgICB3YXJuKFwiU3RhdGljIHByb3BlcnR5IG5hbWUgJ1wiLmNvbmNhdChrZXksIFwiJyBkZWNsYXJlZCBvbiBjbGFzcyAnXCIpLmNvbmNhdChPcmlnaW5hbC5uYW1lLCBcIicgXCIpICsgJ2NvbmZsaWN0cyB3aXRoIHJlc2VydmVkIHByb3BlcnR5IG5hbWUgb2YgVnVlIGludGVybmFsLiAnICsgJ0l0IG1heSBjYXVzZSB1bmV4cGVjdGVkIGJlaGF2aW9yIG9mIHRoZSBjb21wb25lbnQuIENvbnNpZGVyIHJlbmFtaW5nIHRoZSBwcm9wZXJ0eS4nKTtcbiAgICB9XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXh0ZW5kZWQsIGtleSwgZGVzY3JpcHRvcik7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBDb21wb25lbnQob3B0aW9ucykge1xuICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gY29tcG9uZW50RmFjdG9yeShvcHRpb25zKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoQ29tcG9uZW50KSB7XG4gICAgcmV0dXJuIGNvbXBvbmVudEZhY3RvcnkoQ29tcG9uZW50LCBvcHRpb25zKTtcbiAgfTtcbn1cblxuQ29tcG9uZW50LnJlZ2lzdGVySG9va3MgPSBmdW5jdGlvbiByZWdpc3Rlckhvb2tzKGtleXMpIHtcbiAgJGludGVybmFsSG9va3MucHVzaC5hcHBseSgkaW50ZXJuYWxIb29rcywgX3RvQ29uc3VtYWJsZUFycmF5KGtleXMpKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IENvbXBvbmVudDtcbmV4cG9ydCB7IGNyZWF0ZURlY29yYXRvciwgbWl4aW5zIH07XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/vue-class-component/dist/vue-class-component.esm.js\n"); /***/ }), /***/ "./node_modules/vue-property-decorator/lib/vue-property-decorator.js": /*!***************************************************************************!*\ !*** ./node_modules/vue-property-decorator/lib/vue-property-decorator.js ***! \***************************************************************************/ /*! exports provided: Component, Vue, Mixins, Inject, InjectReactive, Provide, ProvideReactive, Model, Prop, PropSync, Watch, Emit, Ref */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Inject\", function() { return Inject; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"InjectReactive\", function() { return InjectReactive; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Provide\", function() { return Provide; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"ProvideReactive\", function() { return ProvideReactive; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Model\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Prop\", function() { return Prop; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PropSync\", function() { return PropSync; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Watch\", function() { return Watch; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Emit\", function() { return Emit; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Ref\", function() { return Ref; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"Vue\", function() { return vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; });\n\n/* harmony import */ var vue_class_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-class-component */ \"./node_modules/vue-class-component/dist/vue-class-component.esm.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"Component\", function() { return vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"default\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"Mixins\", function() { return vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"mixins\"]; });\n\n/** vue-property-decorator verson 8.5.1 MIT LICENSE copyright 2020 kaorun343 */\n/// <reference types='reflect-metadata'/>\n\n\n\n\n/** Used for keying reactive provide/inject properties */\nvar reactiveInjectKey = '__reactiveInject__';\n/**\n * decorator of an inject\n * @param from key\n * @return PropertyDecorator\n */\nfunction Inject(options) {\n return Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, key) {\n if (typeof componentOptions.inject === 'undefined') {\n componentOptions.inject = {};\n }\n if (!Array.isArray(componentOptions.inject)) {\n componentOptions.inject[key] = options || key;\n }\n });\n}\n/**\n * decorator of a reactive inject\n * @param from key\n * @return PropertyDecorator\n */\nfunction InjectReactive(options) {\n return Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, key) {\n if (typeof componentOptions.inject === 'undefined') {\n componentOptions.inject = {};\n }\n if (!Array.isArray(componentOptions.inject)) {\n var fromKey_1 = !!options ? options.from || options : key;\n var defaultVal_1 = (!!options && options.default) || undefined;\n if (!componentOptions.computed)\n componentOptions.computed = {};\n componentOptions.computed[key] = function () {\n var obj = this[reactiveInjectKey];\n return obj ? obj[fromKey_1] : defaultVal_1;\n };\n componentOptions.inject[reactiveInjectKey] = reactiveInjectKey;\n }\n });\n}\nfunction produceProvide(original) {\n var provide = function () {\n var _this = this;\n var rv = typeof original === 'function' ? original.call(this) : original;\n rv = Object.create(rv || null);\n // set reactive services (propagates previous services if necessary)\n rv[reactiveInjectKey] = this[reactiveInjectKey] || {};\n for (var i in provide.managed) {\n rv[provide.managed[i]] = this[i];\n }\n var _loop_1 = function (i) {\n rv[provide.managedReactive[i]] = this_1[i]; // Duplicates the behavior of `@Provide`\n Object.defineProperty(rv[reactiveInjectKey], provide.managedReactive[i], {\n enumerable: true,\n get: function () { return _this[i]; },\n });\n };\n var this_1 = this;\n for (var i in provide.managedReactive) {\n _loop_1(i);\n }\n return rv;\n };\n provide.managed = {};\n provide.managedReactive = {};\n return provide;\n}\nfunction needToProduceProvide(original) {\n return (typeof original !== 'function' ||\n (!original.managed && !original.managedReactive));\n}\n/**\n * decorator of a provide\n * @param key key\n * @return PropertyDecorator | void\n */\nfunction Provide(key) {\n return Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, k) {\n var provide = componentOptions.provide;\n if (needToProduceProvide(provide)) {\n provide = componentOptions.provide = produceProvide(provide);\n }\n provide.managed[k] = key || k;\n });\n}\n/**\n * decorator of a reactive provide\n * @param key key\n * @return PropertyDecorator | void\n */\nfunction ProvideReactive(key) {\n return Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, k) {\n var provide = componentOptions.provide;\n // inject parent reactive services (if any)\n if (!Array.isArray(componentOptions.inject)) {\n componentOptions.inject = componentOptions.inject || {};\n componentOptions.inject[reactiveInjectKey] = {\n from: reactiveInjectKey,\n default: {},\n };\n }\n if (needToProduceProvide(provide)) {\n provide = componentOptions.provide = produceProvide(provide);\n }\n provide.managedReactive[k] = key || k;\n });\n}\n/** @see {@link https://github.com/vuejs/vue-class-component/blob/master/src/reflect.ts} */\nvar reflectMetadataIsSupported = typeof Reflect !== 'undefined' && typeof Reflect.getMetadata !== 'undefined';\nfunction applyMetadata(options, target, key) {\n if (reflectMetadataIsSupported) {\n if (!Array.isArray(options) &&\n typeof options !== 'function' &&\n typeof options.type === 'undefined') {\n var type = Reflect.getMetadata('design:type', target, key);\n if (type !== Object) {\n options.type = type;\n }\n }\n }\n}\n/**\n * decorator of model\n * @param event event name\n * @param options options\n * @return PropertyDecorator\n */\nfunction Model(event, options) {\n if (options === void 0) { options = {}; }\n return function (target, key) {\n applyMetadata(options, target, key);\n Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, k) {\n ;\n (componentOptions.props || (componentOptions.props = {}))[k] = options;\n componentOptions.model = { prop: k, event: event || k };\n })(target, key);\n };\n}\n/**\n * decorator of a prop\n * @param options the options for the prop\n * @return PropertyDecorator | void\n */\nfunction Prop(options) {\n if (options === void 0) { options = {}; }\n return function (target, key) {\n applyMetadata(options, target, key);\n Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, k) {\n ;\n (componentOptions.props || (componentOptions.props = {}))[k] = options;\n })(target, key);\n };\n}\n/**\n * decorator of a synced prop\n * @param propName the name to interface with from outside, must be different from decorated property\n * @param options the options for the synced prop\n * @return PropertyDecorator | void\n */\nfunction PropSync(propName, options) {\n if (options === void 0) { options = {}; }\n // @ts-ignore\n return function (target, key) {\n applyMetadata(options, target, key);\n Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, k) {\n ;\n (componentOptions.props || (componentOptions.props = {}))[propName] = options;\n (componentOptions.computed || (componentOptions.computed = {}))[k] = {\n get: function () {\n return this[propName];\n },\n set: function (value) {\n // @ts-ignore\n this.$emit(\"update:\" + propName, value);\n },\n };\n })(target, key);\n };\n}\n/**\n * decorator of a watch function\n * @param path the path or the expression to observe\n * @param WatchOption\n * @return MethodDecorator\n */\nfunction Watch(path, options) {\n if (options === void 0) { options = {}; }\n var _a = options.deep, deep = _a === void 0 ? false : _a, _b = options.immediate, immediate = _b === void 0 ? false : _b;\n return Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (componentOptions, handler) {\n if (typeof componentOptions.watch !== 'object') {\n componentOptions.watch = Object.create(null);\n }\n var watch = componentOptions.watch;\n if (typeof watch[path] === 'object' && !Array.isArray(watch[path])) {\n watch[path] = [watch[path]];\n }\n else if (typeof watch[path] === 'undefined') {\n watch[path] = [];\n }\n watch[path].push({ handler: handler, deep: deep, immediate: immediate });\n });\n}\n// Code copied from Vue/src/shared/util.js\nvar hyphenateRE = /\\B([A-Z])/g;\nvar hyphenate = function (str) { return str.replace(hyphenateRE, '-$1').toLowerCase(); };\n/**\n * decorator of an event-emitter function\n * @param event The name of the event\n * @return MethodDecorator\n */\nfunction Emit(event) {\n return function (_target, propertyKey, descriptor) {\n var key = hyphenate(propertyKey);\n var original = descriptor.value;\n descriptor.value = function emitter() {\n var _this = this;\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var emit = function (returnValue) {\n var emitName = event || key;\n if (returnValue === undefined) {\n if (args.length === 0) {\n _this.$emit(emitName);\n }\n else if (args.length === 1) {\n _this.$emit(emitName, args[0]);\n }\n else {\n _this.$emit.apply(_this, [emitName].concat(args));\n }\n }\n else {\n if (args.length === 0) {\n _this.$emit(emitName, returnValue);\n }\n else if (args.length === 1) {\n _this.$emit(emitName, returnValue, args[0]);\n }\n else {\n _this.$emit.apply(_this, [emitName, returnValue].concat(args));\n }\n }\n };\n var returnValue = original.apply(this, args);\n if (isPromise(returnValue)) {\n returnValue.then(emit);\n }\n else {\n emit(returnValue);\n }\n return returnValue;\n };\n };\n}\n/**\n * decorator of a ref prop\n * @param refKey the ref key defined in template\n */\nfunction Ref(refKey) {\n return Object(vue_class_component__WEBPACK_IMPORTED_MODULE_1__[\"createDecorator\"])(function (options, key) {\n options.computed = options.computed || {};\n options.computed[key] = {\n cache: false,\n get: function () {\n return this.$refs[refKey || key];\n },\n };\n });\n}\nfunction isPromise(obj) {\n return obj instanceof Promise || (obj && typeof obj.then === 'function');\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvdnVlLXByb3BlcnR5LWRlY29yYXRvci9saWIvdnVlLXByb3BlcnR5LWRlY29yYXRvci5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy92dWUtcHJvcGVydHktZGVjb3JhdG9yL2xpYi92dWUtcHJvcGVydHktZGVjb3JhdG9yLmpzPzYwYTMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIHZ1ZS1wcm9wZXJ0eS1kZWNvcmF0b3IgdmVyc29uIDguNS4xIE1JVCBMSUNFTlNFIGNvcHlyaWdodCAyMDIwIGthb3J1bjM0MyAqL1xuLy8vIDxyZWZlcmVuY2UgdHlwZXM9J3JlZmxlY3QtbWV0YWRhdGEnLz5cbid1c2Ugc3RyaWN0JztcbmltcG9ydCBWdWUgZnJvbSAndnVlJztcbmltcG9ydCBDb21wb25lbnQsIHsgY3JlYXRlRGVjb3JhdG9yLCBtaXhpbnMgfSBmcm9tICd2dWUtY2xhc3MtY29tcG9uZW50JztcbmV4cG9ydCB7IENvbXBvbmVudCwgVnVlLCBtaXhpbnMgYXMgTWl4aW5zIH07XG4vKiogVXNlZCBmb3Iga2V5aW5nIHJlYWN0aXZlIHByb3ZpZGUvaW5qZWN0IHByb3BlcnRpZXMgKi9cbnZhciByZWFjdGl2ZUluamVjdEtleSA9ICdfX3JlYWN0aXZlSW5qZWN0X18nO1xuLyoqXG4gKiBkZWNvcmF0b3Igb2YgYW4gaW5qZWN0XG4gKiBAcGFyYW0gZnJvbSBrZXlcbiAqIEByZXR1cm4gUHJvcGVydHlEZWNvcmF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEluamVjdChvcHRpb25zKSB7XG4gICAgcmV0dXJuIGNyZWF0ZURlY29yYXRvcihmdW5jdGlvbiAoY29tcG9uZW50T3B0aW9ucywga2V5KSB7XG4gICAgICAgIGlmICh0eXBlb2YgY29tcG9uZW50T3B0aW9ucy5pbmplY3QgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb21wb25lbnRPcHRpb25zLmluamVjdCA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb21wb25lbnRPcHRpb25zLmluamVjdCkpIHtcbiAgICAgICAgICAgIGNvbXBvbmVudE9wdGlvbnMuaW5qZWN0W2tleV0gPSBvcHRpb25zIHx8IGtleTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuLyoqXG4gKiBkZWNvcmF0b3Igb2YgYSByZWFjdGl2ZSBpbmplY3RcbiAqIEBwYXJhbSBmcm9tIGtleVxuICogQHJldHVybiBQcm9wZXJ0eURlY29yYXRvclxuICovXG5leHBvcnQgZnVuY3Rpb24gSW5qZWN0UmVhY3RpdmUob3B0aW9ucykge1xuICAgIHJldHVybiBjcmVhdGVEZWNvcmF0b3IoZnVuY3Rpb24gKGNvbXBvbmVudE9wdGlvbnMsIGtleSkge1xuICAgICAgICBpZiAodHlwZW9mIGNvbXBvbmVudE9wdGlvbnMuaW5qZWN0ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY29tcG9uZW50T3B0aW9ucy5pbmplY3QgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29tcG9uZW50T3B0aW9ucy5pbmplY3QpKSB7XG4gICAgICAgICAgICB2YXIgZnJvbUtleV8xID0gISFvcHRpb25zID8gb3B0aW9ucy5mcm9tIHx8IG9wdGlvbnMgOiBrZXk7XG4gICAgICAgICAgICB2YXIgZGVmYXVsdFZhbF8xID0gKCEhb3B0aW9ucyAmJiBvcHRpb25zLmRlZmF1bHQpIHx8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmICghY29tcG9uZW50T3B0aW9ucy5jb21wdXRlZClcbiAgICAgICAgICAgICAgICBjb21wb25lbnRPcHRpb25zLmNvbXB1dGVkID0ge307XG4gICAgICAgICAgICBjb21wb25lbnRPcHRpb25zLmNvbXB1dGVkW2tleV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9iaiA9IHRoaXNbcmVhY3RpdmVJbmplY3RLZXldO1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmogPyBvYmpbZnJvbUtleV8xXSA6IGRlZmF1bHRWYWxfMTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb21wb25lbnRPcHRpb25zLmluamVjdFtyZWFjdGl2ZUluamVjdEtleV0gPSByZWFjdGl2ZUluamVjdEtleTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuZnVuY3Rpb24gcHJvZHVjZVByb3ZpZGUob3JpZ2luYWwpIHtcbiAgICB2YXIgcHJvdmlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJ2ID0gdHlwZW9mIG9yaWdpbmFsID09PSAnZnVuY3Rpb24nID8gb3JpZ2luYWwuY2FsbCh0aGlzKSA6IG9yaWdpbmFsO1xuICAgICAgICBydiA9IE9iamVjdC5jcmVhdGUocnYgfHwgbnVsbCk7XG4gICAgICAgIC8vIHNldCByZWFjdGl2ZSBzZXJ2aWNlcyAocHJvcGFnYXRlcyBwcmV2aW91cyBzZXJ2aWNlcyBpZiBuZWNlc3NhcnkpXG4gICAgICAgIHJ2W3JlYWN0aXZlSW5qZWN0S2V5XSA9IHRoaXNbcmVhY3RpdmVJbmplY3RLZXldIHx8IHt9O1xuICAgICAgICBmb3IgKHZhciBpIGluIHByb3ZpZGUubWFuYWdlZCkge1xuICAgICAgICAgICAgcnZbcHJvdmlkZS5tYW5hZ2VkW2ldXSA9IHRoaXNbaV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIF9sb29wXzEgPSBmdW5jdGlvbiAoaSkge1xuICAgICAgICAgICAgcnZbcHJvdmlkZS5tYW5hZ2VkUmVhY3RpdmVbaV1dID0gdGhpc18xW2ldOyAvLyBEdXBsaWNhdGVzIHRoZSBiZWhhdmlvciBvZiBgQFByb3ZpZGVgXG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocnZbcmVhY3RpdmVJbmplY3RLZXldLCBwcm92aWRlLm1hbmFnZWRSZWFjdGl2ZVtpXSwge1xuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpc1tpXTsgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB2YXIgdGhpc18xID0gdGhpcztcbiAgICAgICAgZm9yICh2YXIgaSBpbiBwcm92aWRlLm1hbmFnZWRSZWFjdGl2ZSkge1xuICAgICAgICAgICAgX2xvb3BfMShpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcnY7XG4gICAgfTtcbiAgICBwcm92aWRlLm1hbmFnZWQgPSB7fTtcbiAgICBwcm92aWRlLm1hbmFnZWRSZWFjdGl2ZSA9IHt9O1xuICAgIHJldHVybiBwcm92aWRlO1xufVxuZnVuY3Rpb24gbmVlZFRvUHJvZHVjZVByb3ZpZGUob3JpZ2luYWwpIHtcbiAgICByZXR1cm4gKHR5cGVvZiBvcmlnaW5hbCAhPT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAoIW9yaWdpbmFsLm1hbmFnZWQgJiYgIW9yaWdpbmFsLm1hbmFnZWRSZWFjdGl2ZSkpO1xufVxuLyoqXG4gKiBkZWNvcmF0b3Igb2YgYSBwcm92aWRlXG4gKiBAcGFyYW0ga2V5IGtleVxuICogQHJldHVybiBQcm9wZXJ0eURlY29yYXRvciB8IHZvaWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFByb3ZpZGUoa2V5KSB7XG4gICAgcmV0dXJuIGNyZWF0ZURlY29yYXRvcihmdW5jdGlvbiAoY29tcG9uZW50T3B0aW9ucywgaykge1xuICAgICAgICB2YXIgcHJvdmlkZSA9IGNvbXBvbmVudE9wdGlvbnMucHJvdmlkZTtcbiAgICAgICAgaWYgKG5lZWRUb1Byb2R1Y2VQcm92aWRlKHByb3ZpZGUpKSB7XG4gICAgICAgICAgICBwcm92aWRlID0gY29tcG9uZW50T3B0aW9ucy5wcm92aWRlID0gcHJvZHVjZVByb3ZpZGUocHJvdmlkZSk7XG4gICAgICAgIH1cbiAgICAgICAgcHJvdmlkZS5tYW5hZ2VkW2tdID0ga2V5IHx8IGs7XG4gICAgfSk7XG59XG4vKipcbiAqIGRlY29yYXRvciBvZiBhIHJlYWN0aXZlIHByb3ZpZGVcbiAqIEBwYXJhbSBrZXkga2V5XG4gKiBAcmV0dXJuIFByb3BlcnR5RGVjb3JhdG9yIHwgdm9pZFxuICovXG5leHBvcnQgZnVuY3Rpb24gUHJvdmlkZVJlYWN0aXZlKGtleSkge1xuICAgIHJldHVybiBjcmVhdGVEZWNvcmF0b3IoZnVuY3Rpb24gKGNvbXBvbmVudE9wdGlvbnMsIGspIHtcbiAgICAgICAgdmFyIHByb3ZpZGUgPSBjb21wb25lbnRPcHRpb25zLnByb3ZpZGU7XG4gICAgICAgIC8vIGluamVjdCBwYXJlbnQgcmVhY3RpdmUgc2VydmljZXMgKGlmIGFueSlcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbXBvbmVudE9wdGlvbnMuaW5qZWN0KSkge1xuICAgICAgICAgICAgY29tcG9uZW50T3B0aW9ucy5pbmplY3QgPSBjb21wb25lbnRPcHRpb25zLmluamVjdCB8fCB7fTtcbiAgICAgICAgICAgIGNvbXBvbmVudE9wdGlvbnMuaW5qZWN0W3JlYWN0aXZlSW5qZWN0S2V5XSA9IHtcbiAgICAgICAgICAgICAgICBmcm9tOiByZWFjdGl2ZUluamVjdEtleSxcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiB7fSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5lZWRUb1Byb2R1Y2VQcm92aWRlKHByb3ZpZGUpKSB7XG4gICAgICAgICAgICBwcm92aWRlID0gY29tcG9uZW50T3B0aW9ucy5wcm92aWRlID0gcHJvZHVjZVByb3ZpZGUocHJvdmlkZSk7XG4gICAgICAgIH1cbiAgICAgICAgcHJvdmlkZS5tYW5hZ2VkUmVhY3RpdmVba10gPSBrZXkgfHwgaztcbiAgICB9KTtcbn1cbi8qKiBAc2VlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vdnVlanMvdnVlLWNsYXNzLWNvbXBvbmVudC9ibG9iL21hc3Rlci9zcmMvcmVmbGVjdC50c30gKi9cbnZhciByZWZsZWN0TWV0YWRhdGFJc1N1cHBvcnRlZCA9IHR5cGVvZiBSZWZsZWN0ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgUmVmbGVjdC5nZXRNZXRhZGF0YSAhPT0gJ3VuZGVmaW5lZCc7XG5mdW5jdGlvbiBhcHBseU1ldGFkYXRhKG9wdGlvbnMsIHRhcmdldCwga2V5KSB7XG4gICAgaWYgKHJlZmxlY3RNZXRhZGF0YUlzU3VwcG9ydGVkKSB7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvcHRpb25zKSAmJlxuICAgICAgICAgICAgdHlwZW9mIG9wdGlvbnMgIT09ICdmdW5jdGlvbicgJiZcbiAgICAgICAgICAgIHR5cGVvZiBvcHRpb25zLnR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB2YXIgdHlwZSA9IFJlZmxlY3QuZ2V0TWV0YWRhdGEoJ2Rlc2lnbjp0eXBlJywgdGFyZ2V0LCBrZXkpO1xuICAgICAgICAgICAgaWYgKHR5cGUgIT09IE9iamVjdCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMudHlwZSA9IHR5cGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4vKipcbiAqIGRlY29yYXRvciBvZiBtb2RlbFxuICogQHBhcmFtICBldmVudCBldmVudCBuYW1lXG4gKiBAcGFyYW0gb3B0aW9ucyBvcHRpb25zXG4gKiBAcmV0dXJuIFByb3BlcnR5RGVjb3JhdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNb2RlbChldmVudCwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkge1xuICAgICAgICBhcHBseU1ldGFkYXRhKG9wdGlvbnMsIHRhcmdldCwga2V5KTtcbiAgICAgICAgY3JlYXRlRGVjb3JhdG9yKGZ1bmN0aW9uIChjb21wb25lbnRPcHRpb25zLCBrKSB7XG4gICAgICAgICAgICA7XG4gICAgICAgICAgICAoY29tcG9uZW50T3B0aW9ucy5wcm9wcyB8fCAoY29tcG9uZW50T3B0aW9ucy5wcm9wcyA9IHt9KSlba10gPSBvcHRpb25zO1xuICAgICAgICAgICAgY29tcG9uZW50T3B0aW9ucy5tb2RlbCA9IHsgcHJvcDogaywgZXZlbnQ6IGV2ZW50IHx8IGsgfTtcbiAgICAgICAgfSkodGFyZ2V0LCBrZXkpO1xuICAgIH07XG59XG4vKipcbiAqIGRlY29yYXRvciBvZiBhIHByb3BcbiAqIEBwYXJhbSAgb3B0aW9ucyB0aGUgb3B0aW9ucyBmb3IgdGhlIHByb3BcbiAqIEByZXR1cm4gUHJvcGVydHlEZWNvcmF0b3IgfCB2b2lkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQcm9wKG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHtcbiAgICAgICAgYXBwbHlNZXRhZGF0YShvcHRpb25zLCB0YXJnZXQsIGtleSk7XG4gICAgICAgIGNyZWF0ZURlY29yYXRvcihmdW5jdGlvbiAoY29tcG9uZW50T3B0aW9ucywgaykge1xuICAgICAgICAgICAgO1xuICAgICAgICAgICAgKGNvbXBvbmVudE9wdGlvbnMucHJvcHMgfHwgKGNvbXBvbmVudE9wdGlvbnMucHJvcHMgPSB7fSkpW2tdID0gb3B0aW9ucztcbiAgICAgICAgfSkodGFyZ2V0LCBrZXkpO1xuICAgIH07XG59XG4vKipcbiAqIGRlY29yYXRvciBvZiBhIHN5bmNlZCBwcm9wXG4gKiBAcGFyYW0gcHJvcE5hbWUgdGhlIG5hbWUgdG8gaW50ZXJmYWNlIHdpdGggZnJvbSBvdXRzaWRlLCBtdXN0IGJlIGRpZmZlcmVudCBmcm9tIGRlY29yYXRlZCBwcm9wZXJ0eVxuICogQHBhcmFtIG9wdGlvbnMgdGhlIG9wdGlvbnMgZm9yIHRoZSBzeW5jZWQgcHJvcFxuICogQHJldHVybiBQcm9wZXJ0eURlY29yYXRvciB8IHZvaWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFByb3BTeW5jKHByb3BOYW1lLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICAvLyBAdHMtaWdub3JlXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkge1xuICAgICAgICBhcHBseU1ldGFkYXRhKG9wdGlvbnMsIHRhcmdldCwga2V5KTtcbiAgICAgICAgY3JlYXRlRGVjb3JhdG9yKGZ1bmN0aW9uIChjb21wb25lbnRPcHRpb25zLCBrKSB7XG4gICAgICAgICAgICA7XG4gICAgICAgICAgICAoY29tcG9uZW50T3B0aW9ucy5wcm9wcyB8fCAoY29tcG9uZW50T3B0aW9ucy5wcm9wcyA9IHt9KSlbcHJvcE5hbWVdID0gb3B0aW9ucztcbiAgICAgICAgICAgIChjb21wb25lbnRPcHRpb25zLmNvbXB1dGVkIHx8IChjb21wb25lbnRPcHRpb25zLmNvbXB1dGVkID0ge30pKVtrXSA9IHtcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLiRlbWl0KFwidXBkYXRlOlwiICsgcHJvcE5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSkodGFyZ2V0LCBrZXkpO1xuICAgIH07XG59XG4vKipcbiAqIGRlY29yYXRvciBvZiBhIHdhdGNoIGZ1bmN0aW9uXG4gKiBAcGFyYW0gIHBhdGggdGhlIHBhdGggb3IgdGhlIGV4cHJlc3Npb24gdG8gb2JzZXJ2ZVxuICogQHBhcmFtICBXYXRjaE9wdGlvblxuICogQHJldHVybiBNZXRob2REZWNvcmF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdhdGNoKHBhdGgsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgIHZhciBfYSA9IG9wdGlvbnMuZGVlcCwgZGVlcCA9IF9hID09PSB2b2lkIDAgPyBmYWxzZSA6IF9hLCBfYiA9IG9wdGlvbnMuaW1tZWRpYXRlLCBpbW1lZGlhdGUgPSBfYiA9PT0gdm9pZCAwID8gZmFsc2UgOiBfYjtcbiAgICByZXR1cm4gY3JlYXRlRGVjb3JhdG9yKGZ1bmN0aW9uIChjb21wb25lbnRPcHRpb25zLCBoYW5kbGVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgY29tcG9uZW50T3B0aW9ucy53YXRjaCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGNvbXBvbmVudE9wdGlvbnMud2F0Y2ggPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB3YXRjaCA9IGNvbXBvbmVudE9wdGlvbnMud2F0Y2g7XG4gICAgICAgIGlmICh0eXBlb2Ygd2F0Y2hbcGF0aF0gPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KHdhdGNoW3BhdGhdKSkge1xuICAgICAgICAgICAgd2F0Y2hbcGF0aF0gPSBbd2F0Y2hbcGF0aF1dO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiB3YXRjaFtwYXRoXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHdhdGNoW3BhdGhdID0gW107XG4gICAgICAgIH1cbiAgICAgICAgd2F0Y2hbcGF0aF0ucHVzaCh7IGhhbmRsZXI6IGhhbmRsZXIsIGRlZXA6IGRlZXAsIGltbWVkaWF0ZTogaW1tZWRpYXRlIH0pO1xuICAgIH0pO1xufVxuLy8gQ29kZSBjb3BpZWQgZnJvbSBWdWUvc3JjL3NoYXJlZC91dGlsLmpzXG52YXIgaHlwaGVuYXRlUkUgPSAvXFxCKFtBLVpdKS9nO1xudmFyIGh5cGhlbmF0ZSA9IGZ1bmN0aW9uIChzdHIpIHsgcmV0dXJuIHN0ci5yZXBsYWNlKGh5cGhlbmF0ZVJFLCAnLSQxJykudG9Mb3dlckNhc2UoKTsgfTtcbi8qKlxuICogZGVjb3JhdG9yIG9mIGFuIGV2ZW50LWVtaXR0ZXIgZnVuY3Rpb25cbiAqIEBwYXJhbSAgZXZlbnQgVGhlIG5hbWUgb2YgdGhlIGV2ZW50XG4gKiBAcmV0dXJuIE1ldGhvZERlY29yYXRvclxuICovXG5leHBvcnQgZnVuY3Rpb24gRW1pdChldmVudCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoX3RhcmdldCwgcHJvcGVydHlLZXksIGRlc2NyaXB0b3IpIHtcbiAgICAgICAgdmFyIGtleSA9IGh5cGhlbmF0ZShwcm9wZXJ0eUtleSk7XG4gICAgICAgIHZhciBvcmlnaW5hbCA9IGRlc2NyaXB0b3IudmFsdWU7XG4gICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiBlbWl0dGVyKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIGFyZ3NbX2ldID0gYXJndW1lbnRzW19pXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBlbWl0ID0gZnVuY3Rpb24gKHJldHVyblZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVtaXROYW1lID0gZXZlbnQgfHwga2V5O1xuICAgICAgICAgICAgICAgIGlmIChyZXR1cm5WYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuJGVtaXQoZW1pdE5hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGFyZ3MubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZW1pdChlbWl0TmFtZSwgYXJnc1swXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZW1pdC5hcHBseShfdGhpcywgW2VtaXROYW1lXS5jb25jYXQoYXJncykpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlbWl0KGVtaXROYW1lLCByZXR1cm5WYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYXJncy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIF90aGlzLiRlbWl0KGVtaXROYW1lLCByZXR1cm5WYWx1ZSwgYXJnc1swXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy4kZW1pdC5hcHBseShfdGhpcywgW2VtaXROYW1lLCByZXR1cm5WYWx1ZV0uY29uY2F0KGFyZ3MpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgcmV0dXJuVmFsdWUgPSBvcmlnaW5hbC5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICAgIGlmIChpc1Byb21pc2UocmV0dXJuVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuVmFsdWUudGhlbihlbWl0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGVtaXQocmV0dXJuVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgICAgICB9O1xuICAgIH07XG59XG4vKipcbiAqIGRlY29yYXRvciBvZiBhIHJlZiBwcm9wXG4gKiBAcGFyYW0gcmVmS2V5IHRoZSByZWYga2V5IGRlZmluZWQgaW4gdGVtcGxhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlZihyZWZLZXkpIHtcbiAgICByZXR1cm4gY3JlYXRlRGVjb3JhdG9yKGZ1bmN0aW9uIChvcHRpb25zLCBrZXkpIHtcbiAgICAgICAgb3B0aW9ucy5jb21wdXRlZCA9IG9wdGlvbnMuY29tcHV0ZWQgfHwge307XG4gICAgICAgIG9wdGlvbnMuY29tcHV0ZWRba2V5XSA9IHtcbiAgICAgICAgICAgIGNhY2hlOiBmYWxzZSxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiRyZWZzW3JlZktleSB8fCBrZXldO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGlzUHJvbWlzZShvYmopIHtcbiAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgUHJvbWlzZSB8fCAob2JqICYmIHR5cGVvZiBvYmoudGhlbiA9PT0gJ2Z1bmN0aW9uJyk7XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/vue-property-decorator/lib/vue-property-decorator.js\n"); /***/ }) }]);
Copyright ©2k19 -
Hexid
|
Tex7ure