@nova-ui/bits
Version:
SolarWinds Nova Framework
237 lines • 41.5 kB
JavaScript
import { Component, ElementRef, EventEmitter, Input, Output, Renderer2, ViewChild, ViewEncapsulation, } from "@angular/core";
import _assign from "lodash/assign";
import _isEqual from "lodash/isEqual";
import _values from "lodash/values";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
import { SorterDirection } from "./public-api";
import { SorterKeyboardService } from "./sorter-keyboard.service";
import { LoggerService } from "../../services/log-service";
import { MenuPopupComponent } from "../menu";
import { OVERLAY_WITH_POPUP_STYLES_CLASS } from "../overlay/constants";
import { OverlayComponent } from "../overlay/overlay-component/overlay.component";
import * as i0 from "@angular/core";
import * as i1 from "../../services/log-service";
import * as i2 from "./sorter-keyboard.service";
import * as i3 from "@angular/common";
import * as i4 from "../menu/menu-popup/menu-popup.component";
import * as i5 from "../button/button.component";
import * as i6 from "../overlay/overlay-component/overlay.component";
// <example-url>./../examples/index.html#/sorter</example-url>
export class SorterComponent {
constructor(logger, sorterKeyboardService, elRef, renderer) {
this.logger = logger;
this.sorterKeyboardService = sorterKeyboardService;
this.elRef = elRef;
this.renderer = renderer;
this.appendToBody = false;
this.sorterAction = new EventEmitter();
// mark this filter to be monitored by our datasource for any changes in order reset other filters(eg: pagination)
// before any new search is performed
this.detectFilterChanges = true;
this.onDestroy$ = new Subject();
this.items = [
{
itemsSource: [],
},
];
this.overlayConfig = {
panelClass: [OVERLAY_WITH_POPUP_STYLES_CLASS],
};
this.sortIcons = {
[SorterDirection.ascending]: "arrow-up",
[SorterDirection.descending]: "arrow-down",
};
this.menuKeyControlListeners = [];
}
ngOnInit() {
this.onAppendToBodyChange(this.appendToBody);
}
ngOnChanges(changes) {
if (changes.itemsSource &&
!_isEqual(changes.itemsSource.previousValue, changes.itemsSource.currentValue)) {
if (this.itemsSource?.length > 0 &&
typeof this.itemsSource[0] === "string") {
this.logger
.warn(`The 'string[]' type for the sorter's itemsSource input is deprecated as of Nova v9. \
Instead, use type 'IMenuItem[]' which is internationalizable with title and value properties for each item.`);
}
this.initSelectedItem();
this.initPopupItems();
}
if (changes.selectedItem &&
this.sortConfig?.sortBy !== changes.selectedItem.currentValue &&
!changes.selectedItem.firstChange) {
const oldValue = _assign({}, this.sortConfig, {
sortBy: changes.selectedItem.previousValue,
});
this.selectedItem = changes.selectedItem.currentValue;
this.sortConfig = _assign({}, this.sortConfig, {
sortBy: changes.selectedItem.currentValue,
});
this.triggerSorterAction(oldValue);
this.setPopupSelection();
}
if (changes.sortDirection &&
!changes.sortDirection.firstChange &&
this.sortConfig?.direction !== changes.sortDirection.currentValue) {
const oldValue = this.sortConfig;
this.sortDirection = changes.sortDirection.currentValue;
this.sortConfig = _assign({}, this.sortConfig, {
direction: this.sortDirection,
});
this.triggerSorterAction(oldValue);
}
if (changes.appendToBody) {
this.onAppendToBodyChange(changes.appendToBody.currentValue);
}
}
ngAfterViewInit() {
this.initSelectedItem();
this.initSortDirection();
this.sortConfig = {
sortBy: this.selectedItem,
direction: this.sortDirection,
};
this.overlay.clickOutside
.pipe(takeUntil(this.onDestroy$))
.subscribe((_) => this.overlay.hide());
this.updateOverlayWidth();
this.initKeyboardService();
this.menuKeyControlListeners.push(this.renderer.listen(this.elRef.nativeElement, "keydown", (event) => {
this.sorterKeyboardService.handleKeydown(event);
}));
}
select(item) {
// perform update only if the new value actually changes
if (this.selectedItem !== item.value) {
const oldValue = this.sortConfig;
this.selectedItem = item.value;
this.sortConfig = _assign({}, this.sortConfig, {
sortBy: item.value,
});
this.updateOverlayWidth();
this.triggerSorterAction(oldValue);
this.setPopupSelection();
this.overlay.hide();
}
}
toggleSortDirection() {
const oldValue = this.sortConfig;
this.sortDirection =
this.sortDirection === SorterDirection.ascending
? SorterDirection.descending
: SorterDirection.ascending;
this.sortConfig = _assign({}, this.sortConfig, {
direction: this.sortDirection,
});
this.sorterAction.emit({ newValue: this.sortConfig, oldValue });
}
getSelectedItem() {
return this.selectedItem;
}
getSelectedItemTitle() {
return this.items[0].itemsSource.find((item) => item.isSelected)?.title;
}
getSortIcon() {
return this.sortIcons[this.sortDirection];
}
getFilters() {
return {
type: "sorter",
value: { ...this.sortConfig },
};
}
updateOverlayWidth() {
this.overlayConfig.minWidth = this.toggleRef.nativeElement.offsetWidth;
}
getAriaLabelForSortingButton() {
return this.sortDirection === SorterDirection.descending
? `${this.getSelectedItemTitle()}. Sorter direction - descending`
: `${this.getSelectedItemTitle()}. Sorter direction - ascending`;
}
ngOnDestroy() {
this.menuKeyControlListeners.forEach((listener) => listener());
this.onDestroy$.next();
this.onDestroy$.complete();
}
toggleSorterMenu() {
this.overlay.toggle();
this.sorterKeyboardService.announceDropdown();
}
initSelectedItem() {
// skip initialization in case we already have a value
// or if the itemsSource are lazy loaded
if (this.selectedItem || !this.itemsSource?.length) {
return;
}
const firstItem = this.itemsSource[0];
this.selectedItem =
typeof firstItem === "string"
? firstItem
: firstItem.value;
}
initPopupItems() {
this.items[0].itemsSource = this.itemsSource.map((item) => {
const menuItem = typeof item === "string"
? { title: item, value: item }
: item;
menuItem.isSelected = this.selectedItem === menuItem.value;
return menuItem;
});
}
initSortDirection() {
if (_values(SorterDirection).indexOf(this.sortDirection) === -1) {
this.sortDirection = SorterDirection.ascending;
}
}
setPopupSelection() {
this.items[0].itemsSource.forEach((popupItem) => {
popupItem.isSelected = popupItem.value === this.selectedItem;
});
}
triggerSorterAction(oldValue) {
this.sorterAction.emit({ newValue: this.sortConfig, oldValue });
}
onAppendToBodyChange(appendToBody) {
this.customContainer = appendToBody ? undefined : this.popupArea;
}
initKeyboardService() {
this.sorterKeyboardService.menuItems = this.menuPopup?.menuItems;
this.sorterKeyboardService.overlay = this.overlay;
this.sorterKeyboardService.initKeyboardManager();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SorterComponent, deps: [{ token: i1.LoggerService }, { token: i2.SorterKeyboardService }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SorterComponent, selector: "nui-sorter", inputs: { appendToBody: "appendToBody", caption: "caption", itemsSource: "itemsSource", selectedItem: "selectedItem", sortDirection: "sortDirection" }, outputs: { sorterAction: "sorterAction" }, host: { classAttribute: "nui-sorter" }, providers: [SorterKeyboardService], viewQueries: [{ propertyName: "popupArea", first: true, predicate: ["popupArea"], descendants: true, static: true }, { propertyName: "overlay", first: true, predicate: OverlayComponent, descendants: true }, { propertyName: "menuPopup", first: true, predicate: ["popup"], descendants: true }, { propertyName: "toggleRef", first: true, predicate: ["toggleRef"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div>\n <label *ngIf=\"caption\" class=\"nui-sorter__label\">{{ caption }}</label>\n <div class=\"btn-group nui-sorter__popup\" #toggleRef>\n <button\n nui-button\n type=\"button\"\n class=\"nui-sorter__toggle-button\"\n [icon]=\"getSortIcon()\"\n [ariaLabel]=\"getAriaLabelForSortingButton()\"\n (click)=\"toggleSortDirection()\"\n >\n <span class=\"nui-sorter__display-value\">\n {{ getSelectedItemTitle() }}\n </span>\n </button>\n <button\n nui-button\n type=\"button\"\n class=\"nui-selector__toggle\"\n (click)=\"toggleSorterMenu()\"\n ariaLabel=\"Open Sorter Menu\"\n icon=\"caret-down\"\n ></button>\n </div>\n\n <div #popupArea></div>\n\n <nui-overlay\n #overlay\n [toggleReference]=\"toggleRef\"\n [overlayConfig]=\"overlayConfig\"\n [customContainer]=\"customContainer\"\n >\n <nui-menu-popup\n #popup\n [itemsSource]=\"items\"\n (menuItemClicked)=\"select($event)\"\n ></nui-menu-popup>\n </nui-overlay>\n</div>\n", styles: [".nui .nui-sorter{max-height:30px}.nui .nui-sorter .list-group{margin:5px 0}.nui .nui-sorter__label{display:block}.nui .nui-sorter__popup{display:flex}.nui .nui-sorter__toggle-button.nui-button{min-width:auto}.nui .nui-sorter .nui-popup .nui-popup__area{min-width:100%;border:none}.nui .nui-sorter .nui-popup .nui-popup__area [popupAreaContent]{padding:0}.nui .nui-sorter .nui-popup .nui-popup__area .nui-list .nui-list-item{border:0}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.MenuPopupComponent, selector: "nui-menu-popup", inputs: ["itemsSource", "size"], outputs: ["menuItemClicked"] }, { kind: "component", type: i5.ButtonComponent, selector: "[nui-button]", inputs: ["displayStyle", "icon", "iconColor", "iconRight", "isBusy", "isEmpty", "ariaLabel", "isRepeat", "size"] }, { kind: "component", type: i6.OverlayComponent, selector: "nui-overlay", inputs: ["overlayConfig", "toggleReference", "viewportMargin", "customContainer", "roleAttr"], outputs: ["clickOutside"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SorterComponent, decorators: [{
type: Component,
args: [{ selector: "nui-sorter", host: {
class: "nui-sorter",
}, encapsulation: ViewEncapsulation.None, providers: [SorterKeyboardService], template: "<div>\n <label *ngIf=\"caption\" class=\"nui-sorter__label\">{{ caption }}</label>\n <div class=\"btn-group nui-sorter__popup\" #toggleRef>\n <button\n nui-button\n type=\"button\"\n class=\"nui-sorter__toggle-button\"\n [icon]=\"getSortIcon()\"\n [ariaLabel]=\"getAriaLabelForSortingButton()\"\n (click)=\"toggleSortDirection()\"\n >\n <span class=\"nui-sorter__display-value\">\n {{ getSelectedItemTitle() }}\n </span>\n </button>\n <button\n nui-button\n type=\"button\"\n class=\"nui-selector__toggle\"\n (click)=\"toggleSorterMenu()\"\n ariaLabel=\"Open Sorter Menu\"\n icon=\"caret-down\"\n ></button>\n </div>\n\n <div #popupArea></div>\n\n <nui-overlay\n #overlay\n [toggleReference]=\"toggleRef\"\n [overlayConfig]=\"overlayConfig\"\n [customContainer]=\"customContainer\"\n >\n <nui-menu-popup\n #popup\n [itemsSource]=\"items\"\n (menuItemClicked)=\"select($event)\"\n ></nui-menu-popup>\n </nui-overlay>\n</div>\n", styles: [".nui .nui-sorter{max-height:30px}.nui .nui-sorter .list-group{margin:5px 0}.nui .nui-sorter__label{display:block}.nui .nui-sorter__popup{display:flex}.nui .nui-sorter__toggle-button.nui-button{min-width:auto}.nui .nui-sorter .nui-popup .nui-popup__area{min-width:100%;border:none}.nui .nui-sorter .nui-popup .nui-popup__area [popupAreaContent]{padding:0}.nui .nui-sorter .nui-popup .nui-popup__area .nui-list .nui-list-item{border:0}\n"] }]
}], ctorParameters: () => [{ type: i1.LoggerService }, { type: i2.SorterKeyboardService }, { type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { appendToBody: [{
type: Input
}], caption: [{
type: Input
}], itemsSource: [{
type: Input
}], selectedItem: [{
type: Input
}], sortDirection: [{
type: Input
}], sorterAction: [{
type: Output
}], popupArea: [{
type: ViewChild,
args: ["popupArea", { static: true }]
}], overlay: [{
type: ViewChild,
args: [OverlayComponent]
}], menuPopup: [{
type: ViewChild,
args: ["popup"]
}], toggleRef: [{
type: ViewChild,
args: ["toggleRef", { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ydGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc29ydGVyL3NvcnRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9zcmMvbGliL3NvcnRlci9zb3J0ZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBcUJBLE9BQU8sRUFFSCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBSUwsTUFBTSxFQUNOLFNBQVMsRUFFVCxTQUFTLEVBQ1QsaUJBQWlCLEdBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUNwQyxPQUFPLFFBQVEsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0QyxPQUFPLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDcEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsT0FBTyxFQUErQixlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDNUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFNbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUU3QyxPQUFPLEVBQUUsK0JBQStCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnREFBZ0QsQ0FBQzs7Ozs7Ozs7QUFFbEYsOERBQThEO0FBWTlELE1BQU0sT0FBTyxlQUFlO0lBNEN4QixZQUNZLE1BQXFCLEVBQ3JCLHFCQUE0QyxFQUM1QyxLQUFpQixFQUNqQixRQUFtQjtRQUhuQixXQUFNLEdBQU4sTUFBTSxDQUFlO1FBQ3JCLDBCQUFxQixHQUFyQixxQkFBcUIsQ0FBdUI7UUFDNUMsVUFBSyxHQUFMLEtBQUssQ0FBWTtRQUNqQixhQUFRLEdBQVIsUUFBUSxDQUFXO1FBN0N0QixpQkFBWSxHQUFZLEtBQUssQ0FBQztRQVk3QixpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFrQixDQUFDO1FBTTVELGtIQUFrSDtRQUNsSCxxQ0FBcUM7UUFDOUIsd0JBQW1CLEdBQUcsSUFBSSxDQUFDO1FBRzNCLGVBQVUsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO1FBQ2pDLFVBQUssR0FBaUI7WUFDekI7Z0JBQ0ksV0FBVyxFQUFFLEVBQUU7YUFDbEI7U0FDSixDQUFDO1FBQ0ssa0JBQWEsR0FBa0I7WUFDbEMsVUFBVSxFQUFFLENBQUMsK0JBQStCLENBQUM7U0FDaEQsQ0FBQztRQUlNLGNBQVMsR0FBOEI7WUFDM0MsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLEVBQUUsVUFBVTtZQUN2QyxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsRUFBRSxZQUFZO1NBQzdDLENBQUM7UUFDTSw0QkFBdUIsR0FBZSxFQUFFLENBQUM7SUFPOUMsQ0FBQztJQUVHLFFBQVE7UUFDWCxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFTSxXQUFXLENBQUMsT0FBc0I7UUFDckMsSUFDSSxPQUFPLENBQUMsV0FBVztZQUNuQixDQUFDLFFBQVEsQ0FDTCxPQUFPLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFDakMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQ25DLEVBQ0g7WUFDRSxJQUNJLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxHQUFHLENBQUM7Z0JBQzVCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQ3pDO2dCQUNFLElBQUksQ0FBQyxNQUFNO3FCQUNOLElBQUksQ0FBQzs4SUFDb0gsQ0FBQyxDQUFDO2FBQ25JO1lBQ0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1NBQ3pCO1FBRUQsSUFDSSxPQUFPLENBQUMsWUFBWTtZQUNwQixJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sS0FBSyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVk7WUFDN0QsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFDbkM7WUFDRSxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUU7Z0JBQzFDLE1BQU0sRUFBRSxPQUFPLENBQUMsWUFBWSxDQUFDLGFBQWE7YUFDN0MsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQztZQUN0RCxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDM0MsTUFBTSxFQUFFLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWTthQUM1QyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFbkMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7U0FDNUI7UUFFRCxJQUNJLE9BQU8sQ0FBQyxhQUFhO1lBQ3JCLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxXQUFXO1lBQ2xDLElBQUksQ0FBQyxVQUFVLEVBQUUsU0FBUyxLQUFLLE9BQU8sQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUNuRTtZQUNFLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7WUFDakMsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQztZQUN4RCxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDM0MsU0FBUyxFQUFFLElBQUksQ0FBQyxhQUFhO2FBQ2hDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN0QztRQUVELElBQUksT0FBTyxDQUFDLFlBQVksRUFBRTtZQUN0QixJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUNoRTtJQUNMLENBQUM7SUFFTSxlQUFlO1FBQ2xCLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRXpCLElBQUksQ0FBQyxVQUFVLEdBQUc7WUFDZCxNQUFNLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDekIsU0FBUyxFQUFFLElBQUksQ0FBQyxhQUFhO1NBQ2hDLENBQUM7UUFDRixJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVk7YUFDcEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDaEMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFFM0MsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FDN0IsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQ2hCLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUN4QixTQUFTLEVBQ1QsQ0FBQyxLQUFvQixFQUFFLEVBQUU7WUFDckIsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwRCxDQUFDLENBQ0osQ0FDSixDQUFDO0lBQ04sQ0FBQztJQUVNLE1BQU0sQ0FBQyxJQUFlO1FBQ3pCLHdEQUF3RDtRQUN4RCxJQUFJLElBQUksQ0FBQyxZQUFZLEtBQUssSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1lBRWpDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDM0MsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLO2FBQ3JCLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNuQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3ZCO0lBQ0wsQ0FBQztJQUVNLG1CQUFtQjtRQUN0QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBRWpDLElBQUksQ0FBQyxhQUFhO1lBQ2QsSUFBSSxDQUFDLGFBQWEsS0FBSyxlQUFlLENBQUMsU0FBUztnQkFDNUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxVQUFVO2dCQUM1QixDQUFDLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUMzQyxTQUFTLEVBQUUsSUFBSSxDQUFDLGFBQWE7U0FDaEMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFTSxlQUFlO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUM3QixDQUFDO0lBRU0sb0JBQW9CO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUNqQyxDQUFDLElBQWUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FDdkMsRUFBRSxLQUFLLENBQUM7SUFDYixDQUFDO0lBRU0sV0FBVztRQUNkLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVNLFVBQVU7UUFDYixPQUFPO1lBQ0gsSUFBSSxFQUFFLFFBQVE7WUFDZCxLQUFLLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUU7U0FDaEMsQ0FBQztJQUNOLENBQUM7SUFFTSxrQkFBa0I7UUFDckIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEdBQ3ZCLElBQUksQ0FBQyxTQUFTLENBQUMsYUFDbEIsQ0FBQyxXQUFXLENBQUM7SUFDbEIsQ0FBQztJQUVNLDRCQUE0QjtRQUMvQixPQUFPLElBQUksQ0FBQyxhQUFhLEtBQUssZUFBZSxDQUFDLFVBQVU7WUFDcEQsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixFQUFFLGlDQUFpQztZQUNqRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsZ0NBQWdDLENBQUM7SUFDekUsQ0FBQztJQUVNLFdBQVc7UUFDZCxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRU0sZ0JBQWdCO1FBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDbEQsQ0FBQztJQUVPLGdCQUFnQjtRQUNwQixzREFBc0Q7UUFDdEQsd0NBQXdDO1FBQ3hDLElBQUksSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFO1lBQ2hELE9BQU87U0FDVjtRQUVELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLFlBQVk7WUFDYixPQUFPLFNBQVMsS0FBSyxRQUFRO2dCQUN6QixDQUFDLENBQUMsU0FBUztnQkFDWCxDQUFDLENBQUUsU0FBdUIsQ0FBQyxLQUFLLENBQUM7SUFDN0MsQ0FBQztJQUVPLGNBQWM7UUFDbEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEdBQUksSUFBSSxDQUFDLFdBQXFCLENBQUMsR0FBRyxDQUN2RCxDQUFDLElBQXdCLEVBQUUsRUFBRTtZQUN6QixNQUFNLFFBQVEsR0FDVixPQUFPLElBQUksS0FBSyxRQUFRO2dCQUNwQixDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUU7Z0JBQzlCLENBQUMsQ0FBRSxJQUFrQixDQUFDO1lBQzlCLFFBQVEsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFlBQVksS0FBSyxRQUFRLENBQUMsS0FBSyxDQUFDO1lBQzNELE9BQU8sUUFBUSxDQUFDO1FBQ3BCLENBQUMsQ0FDSixDQUFDO0lBQ04sQ0FBQztJQUVPLGlCQUFpQjtRQUNyQixJQUFJLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQzdELElBQUksQ0FBQyxhQUFhLEdBQUcsZUFBZSxDQUFDLFNBQVMsQ0FBQztTQUNsRDtJQUNMLENBQUM7SUFFTyxpQkFBaUI7UUFDckIsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBb0IsRUFBRSxFQUFFO1lBQ3ZELFNBQVMsQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ2pFLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLG1CQUFtQixDQUFDLFFBQXFCO1FBQzdDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRU8sb0JBQW9CLENBQUMsWUFBcUI7UUFDOUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUNyRSxDQUFDO0lBRU8sbUJBQW1CO1FBQ3ZCLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUM7UUFDakUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ2xELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO0lBQ3JELENBQUM7K0dBdlFRLGVBQWU7bUdBQWYsZUFBZSxnUkFGYixDQUFDLHFCQUFxQixDQUFDLDBLQW9CdkIsZ0JBQWdCLGlRQ3JGL0IsMnNDQXdDQTs7NEZEMkJhLGVBQWU7a0JBVjNCLFNBQVM7K0JBQ0ksWUFBWSxRQUNoQjt3QkFDRixLQUFLLEVBQUUsWUFBWTtxQkFDdEIsaUJBR2MsaUJBQWlCLENBQUMsSUFBSSxhQUMxQixDQUFDLHFCQUFxQixDQUFDO3VLQUt6QixZQUFZO3NCQUFwQixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFNRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFFSSxZQUFZO3NCQUFyQixNQUFNO2dCQUVtQyxTQUFTO3NCQUFsRCxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ0osT0FBTztzQkFBMUMsU0FBUzt1QkFBQyxnQkFBZ0I7Z0JBQ0EsU0FBUztzQkFBbkMsU0FBUzt1QkFBQyxPQUFPO2dCQWlCZ0MsU0FBUztzQkFBMUQsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7IE92ZXJsYXlDb25maWcgfSBmcm9tIFwiQGFuZ3VsYXIvY2RrL292ZXJsYXlcIjtcbmltcG9ydCB7XG4gICAgQWZ0ZXJWaWV3SW5pdCxcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgSW5wdXQsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFJlbmRlcmVyMixcbiAgICBTaW1wbGVDaGFuZ2VzLFxuICAgIFZpZXdDaGlsZCxcbiAgICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCBfYXNzaWduIGZyb20gXCJsb2Rhc2gvYXNzaWduXCI7XG5pbXBvcnQgX2lzRXF1YWwgZnJvbSBcImxvZGFzaC9pc0VxdWFsXCI7XG5pbXBvcnQgX3ZhbHVlcyBmcm9tIFwibG9kYXNoL3ZhbHVlc1wiO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuaW1wb3J0IHsgSVNvcnRlZEl0ZW0sIElTb3J0ZXJDaGFuZ2VzLCBTb3J0ZXJEaXJlY3Rpb24gfSBmcm9tIFwiLi9wdWJsaWMtYXBpXCI7XG5pbXBvcnQgeyBTb3J0ZXJLZXlib2FyZFNlcnZpY2UgfSBmcm9tIFwiLi9zb3J0ZXIta2V5Ym9hcmQuc2VydmljZVwiO1xuaW1wb3J0IHtcbiAgICBJRmlsdGVyLFxuICAgIElGaWx0ZXJQdWIsXG4gICAgSVNvcnRlckZpbHRlcixcbn0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL2RhdGEtc291cmNlL3B1YmxpYy1hcGlcIjtcbmltcG9ydCB7IExvZ2dlclNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvbG9nLXNlcnZpY2VcIjtcbmltcG9ydCB7IE1lbnVQb3B1cENvbXBvbmVudCB9IGZyb20gXCIuLi9tZW51XCI7XG5pbXBvcnQgeyBJTWVudUdyb3VwLCBJTWVudUl0ZW0gfSBmcm9tIFwiLi4vbWVudS9wdWJsaWMtYXBpXCI7XG5pbXBvcnQgeyBPVkVSTEFZX1dJVEhfUE9QVVBfU1RZTEVTX0NMQVNTIH0gZnJvbSBcIi4uL292ZXJsYXkvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPdmVybGF5Q29tcG9uZW50IH0gZnJvbSBcIi4uL292ZXJsYXkvb3ZlcmxheS1jb21wb25lbnQvb3ZlcmxheS5jb21wb25lbnRcIjtcblxuLy8gPGV4YW1wbGUtdXJsPi4vLi4vZXhhbXBsZXMvaW5kZXguaHRtbCMvc29ydGVyPC9leGFtcGxlLXVybD5cblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibnVpLXNvcnRlclwiLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgY2xhc3M6IFwibnVpLXNvcnRlclwiLFxuICAgIH0sXG4gICAgdGVtcGxhdGVVcmw6IFwiLi9zb3J0ZXIuY29tcG9uZW50Lmh0bWxcIixcbiAgICBzdHlsZVVybHM6IFtcIi4vc29ydGVyLmNvbXBvbmVudC5sZXNzXCJdLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gICAgcHJvdmlkZXJzOiBbU29ydGVyS2V5Ym9hcmRTZXJ2aWNlXSxcbn0pXG5leHBvcnQgY2xhc3MgU29ydGVyQ29tcG9uZW50XG4gICAgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0LCBJRmlsdGVyUHViXG57XG4gICAgQElucHV0KCkgYXBwZW5kVG9Cb2R5OiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgY2FwdGlvbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0cmluZ1tdIHR5cGUgZm9yIGl0ZW1zU291cmNlIGlzIHRoZSBsZWdhY3kgbm9uLWkxOG4tZnJpZW5kbHkgdHlwZVxuICAgICAqIGFuZCBpdCBzaG91bGQgYmUgcmVtb3ZlZCBhcyBhbiBvcHRpb24gaW4gc2NvcGUgb2YgTlVJLTU4MDFcbiAgICAgKi9cbiAgICBASW5wdXQoKSBpdGVtc1NvdXJjZTogc3RyaW5nW10gfCBJTWVudUl0ZW1bXTtcblxuICAgIEBJbnB1dCgpIHNlbGVjdGVkSXRlbTogc3RyaW5nO1xuICAgIEBJbnB1dCgpIHNvcnREaXJlY3Rpb246IGFueTtcblxuICAgIEBPdXRwdXQoKSBzb3J0ZXJBY3Rpb24gPSBuZXcgRXZlbnRFbWl0dGVyPElTb3J0ZXJDaGFuZ2VzPigpO1xuXG4gICAgQFZpZXdDaGlsZChcInBvcHVwQXJlYVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBwb3B1cEFyZWE6IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZChPdmVybGF5Q29tcG9uZW50KSBwdWJsaWMgb3ZlcmxheTogT3ZlcmxheUNvbXBvbmVudDtcbiAgICBAVmlld0NoaWxkKFwicG9wdXBcIikgcHVibGljIG1lbnVQb3B1cDogTWVudVBvcHVwQ29tcG9uZW50O1xuXG4gICAgLy8gbWFyayB0aGlzIGZpbHRlciB0byBiZSBtb25pdG9yZWQgYnkgb3VyIGRhdGFzb3VyY2UgZm9yIGFueSBjaGFuZ2VzIGluIG9yZGVyIHJlc2V0IG90aGVyIGZpbHRlcnMoZWc6IHBhZ2luYXRpb24pXG4gICAgLy8gYmVmb3JlIGFueSBuZXcgc2VhcmNoIGlzIHBlcmZvcm1lZFxuICAgIHB1YmxpYyBkZXRlY3RGaWx0ZXJDaGFuZ2VzID0gdHJ1ZTtcblxuICAgIHB1YmxpYyBjdXN0b21Db250YWluZXI6IEVsZW1lbnRSZWYgfCB1bmRlZmluZWQ7XG4gICAgcHVibGljIG9uRGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAgIHB1YmxpYyBpdGVtczogSU1lbnVHcm91cFtdID0gW1xuICAgICAgICB7XG4gICAgICAgICAgICBpdGVtc1NvdXJjZTogW10sXG4gICAgICAgIH0sXG4gICAgXTtcbiAgICBwdWJsaWMgb3ZlcmxheUNvbmZpZzogT3ZlcmxheUNvbmZpZyA9IHtcbiAgICAgICAgcGFuZWxDbGFzczogW09WRVJMQVlfV0lUSF9QT1BVUF9TVFlMRVNfQ0xBU1NdLFxuICAgIH07XG5cbiAgICBAVmlld0NoaWxkKFwidG9nZ2xlUmVmXCIsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgdG9nZ2xlUmVmOiBFbGVtZW50UmVmO1xuICAgIHByaXZhdGUgc29ydENvbmZpZzogSVNvcnRlZEl0ZW07XG4gICAgcHJpdmF0ZSBzb3J0SWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAgIFtTb3J0ZXJEaXJlY3Rpb24uYXNjZW5kaW5nXTogXCJhcnJvdy11cFwiLFxuICAgICAgICBbU29ydGVyRGlyZWN0aW9uLmRlc2NlbmRpbmddOiBcImFycm93LWRvd25cIixcbiAgICB9O1xuICAgIHByaXZhdGUgbWVudUtleUNvbnRyb2xMaXN0ZW5lcnM6IEZ1bmN0aW9uW10gPSBbXTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIGxvZ2dlcjogTG9nZ2VyU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBzb3J0ZXJLZXlib2FyZFNlcnZpY2U6IFNvcnRlcktleWJvYXJkU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBlbFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyXG4gICAgKSB7fVxuXG4gICAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uQXBwZW5kVG9Cb2R5Q2hhbmdlKHRoaXMuYXBwZW5kVG9Cb2R5KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBjaGFuZ2VzLml0ZW1zU291cmNlICYmXG4gICAgICAgICAgICAhX2lzRXF1YWwoXG4gICAgICAgICAgICAgICAgY2hhbmdlcy5pdGVtc1NvdXJjZS5wcmV2aW91c1ZhbHVlLFxuICAgICAgICAgICAgICAgIGNoYW5nZXMuaXRlbXNTb3VyY2UuY3VycmVudFZhbHVlXG4gICAgICAgICAgICApXG4gICAgICAgICkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHRoaXMuaXRlbXNTb3VyY2U/Lmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAgICAgICB0eXBlb2YgdGhpcy5pdGVtc1NvdXJjZVswXSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXJcbiAgICAgICAgICAgICAgICAgICAgLndhcm4oYFRoZSAnc3RyaW5nW10nIHR5cGUgZm9yIHRoZSBzb3J0ZXIncyBpdGVtc1NvdXJjZSBpbnB1dCBpcyBkZXByZWNhdGVkIGFzIG9mIE5vdmEgdjkuIFxcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zdGVhZCwgdXNlIHR5cGUgJ0lNZW51SXRlbVtdJyB3aGljaCBpcyBpbnRlcm5hdGlvbmFsaXphYmxlIHdpdGggdGl0bGUgYW5kIHZhbHVlIHByb3BlcnRpZXMgZm9yIGVhY2ggaXRlbS5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaW5pdFNlbGVjdGVkSXRlbSgpO1xuICAgICAgICAgICAgdGhpcy5pbml0UG9wdXBJdGVtcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgY2hhbmdlcy5zZWxlY3RlZEl0ZW0gJiZcbiAgICAgICAgICAgIHRoaXMuc29ydENvbmZpZz8uc29ydEJ5ICE9PSBjaGFuZ2VzLnNlbGVjdGVkSXRlbS5jdXJyZW50VmFsdWUgJiZcbiAgICAgICAgICAgICFjaGFuZ2VzLnNlbGVjdGVkSXRlbS5maXJzdENoYW5nZVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IG9sZFZhbHVlID0gX2Fzc2lnbih7fSwgdGhpcy5zb3J0Q29uZmlnLCB7XG4gICAgICAgICAgICAgICAgc29ydEJ5OiBjaGFuZ2VzLnNlbGVjdGVkSXRlbS5wcmV2aW91c1ZhbHVlLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtID0gY2hhbmdlcy5zZWxlY3RlZEl0ZW0uY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgdGhpcy5zb3J0Q29uZmlnID0gX2Fzc2lnbih7fSwgdGhpcy5zb3J0Q29uZmlnLCB7XG4gICAgICAgICAgICAgICAgc29ydEJ5OiBjaGFuZ2VzLnNlbGVjdGVkSXRlbS5jdXJyZW50VmFsdWUsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy50cmlnZ2VyU29ydGVyQWN0aW9uKG9sZFZhbHVlKTtcblxuICAgICAgICAgICAgdGhpcy5zZXRQb3B1cFNlbGVjdGlvbigpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgY2hhbmdlcy5zb3J0RGlyZWN0aW9uICYmXG4gICAgICAgICAgICAhY2hhbmdlcy5zb3J0RGlyZWN0aW9uLmZpcnN0Q2hhbmdlICYmXG4gICAgICAgICAgICB0aGlzLnNvcnRDb25maWc/LmRpcmVjdGlvbiAhPT0gY2hhbmdlcy5zb3J0RGlyZWN0aW9uLmN1cnJlbnRWYWx1ZVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IG9sZFZhbHVlID0gdGhpcy5zb3J0Q29uZmlnO1xuICAgICAgICAgICAgdGhpcy5zb3J0RGlyZWN0aW9uID0gY2hhbmdlcy5zb3J0RGlyZWN0aW9uLmN1cnJlbnRWYWx1ZTtcbiAgICAgICAgICAgIHRoaXMuc29ydENvbmZpZyA9IF9hc3NpZ24oe30sIHRoaXMuc29ydENvbmZpZywge1xuICAgICAgICAgICAgICAgIGRpcmVjdGlvbjogdGhpcy5zb3J0RGlyZWN0aW9uLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHRoaXMudHJpZ2dlclNvcnRlckFjdGlvbihvbGRWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2hhbmdlcy5hcHBlbmRUb0JvZHkpIHtcbiAgICAgICAgICAgIHRoaXMub25BcHBlbmRUb0JvZHlDaGFuZ2UoY2hhbmdlcy5hcHBlbmRUb0JvZHkuY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW5pdFNlbGVjdGVkSXRlbSgpO1xuICAgICAgICB0aGlzLmluaXRTb3J0RGlyZWN0aW9uKCk7XG5cbiAgICAgICAgdGhpcy5zb3J0Q29uZmlnID0ge1xuICAgICAgICAgICAgc29ydEJ5OiB0aGlzLnNlbGVjdGVkSXRlbSxcbiAgICAgICAgICAgIGRpcmVjdGlvbjogdGhpcy5zb3J0RGlyZWN0aW9uLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLm92ZXJsYXkuY2xpY2tPdXRzaWRlXG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5vbkRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKF8pID0+IHRoaXMub3ZlcmxheS5oaWRlKCkpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlT3ZlcmxheVdpZHRoKCk7XG4gICAgICAgIHRoaXMuaW5pdEtleWJvYXJkU2VydmljZSgpO1xuICAgICAgICB0aGlzLm1lbnVLZXlDb250cm9sTGlzdGVuZXJzLnB1c2goXG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmxpc3RlbihcbiAgICAgICAgICAgICAgICB0aGlzLmVsUmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAgICAgXCJrZXlkb3duXCIsXG4gICAgICAgICAgICAgICAgKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc29ydGVyS2V5Ym9hcmRTZXJ2aWNlLmhhbmRsZUtleWRvd24oZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2VsZWN0KGl0ZW06IElNZW51SXRlbSk6IHZvaWQge1xuICAgICAgICAvLyBwZXJmb3JtIHVwZGF0ZSBvbmx5IGlmIHRoZSBuZXcgdmFsdWUgYWN0dWFsbHkgY2hhbmdlc1xuICAgICAgICBpZiAodGhpcy5zZWxlY3RlZEl0ZW0gIT09IGl0ZW0udmFsdWUpIHtcbiAgICAgICAgICAgIGNvbnN0IG9sZFZhbHVlID0gdGhpcy5zb3J0Q29uZmlnO1xuXG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkSXRlbSA9IGl0ZW0udmFsdWU7XG4gICAgICAgICAgICB0aGlzLnNvcnRDb25maWcgPSBfYXNzaWduKHt9LCB0aGlzLnNvcnRDb25maWcsIHtcbiAgICAgICAgICAgICAgICBzb3J0Qnk6IGl0ZW0udmFsdWUsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy51cGRhdGVPdmVybGF5V2lkdGgoKTtcbiAgICAgICAgICAgIHRoaXMudHJpZ2dlclNvcnRlckFjdGlvbihvbGRWYWx1ZSk7XG4gICAgICAgICAgICB0aGlzLnNldFBvcHVwU2VsZWN0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLm92ZXJsYXkuaGlkZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHRvZ2dsZVNvcnREaXJlY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG9sZFZhbHVlID0gdGhpcy5zb3J0Q29uZmlnO1xuXG4gICAgICAgIHRoaXMuc29ydERpcmVjdGlvbiA9XG4gICAgICAgICAgICB0aGlzLnNvcnREaXJlY3Rpb24gPT09IFNvcnRlckRpcmVjdGlvbi5hc2NlbmRpbmdcbiAgICAgICAgICAgICAgICA/IFNvcnRlckRpcmVjdGlvbi5kZXNjZW5kaW5nXG4gICAgICAgICAgICAgICAgOiBTb3J0ZXJEaXJlY3Rpb24uYXNjZW5kaW5nO1xuICAgICAgICB0aGlzLnNvcnRDb25maWcgPSBfYXNzaWduKHt9LCB0aGlzLnNvcnRDb25maWcsIHtcbiAgICAgICAgICAgIGRpcmVjdGlvbjogdGhpcy5zb3J0RGlyZWN0aW9uLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zb3J0ZXJBY3Rpb24uZW1pdCh7IG5ld1ZhbHVlOiB0aGlzLnNvcnRDb25maWcsIG9sZFZhbHVlIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEl0ZW0oKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRJdGVtO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTZWxlY3RlZEl0ZW1UaXRsZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5pdGVtc1swXS5pdGVtc1NvdXJjZS5maW5kKFxuICAgICAgICAgICAgKGl0ZW06IElNZW51SXRlbSkgPT4gaXRlbS5pc1NlbGVjdGVkXG4gICAgICAgICk/LnRpdGxlO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTb3J0SWNvbigpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5zb3J0SWNvbnNbdGhpcy5zb3J0RGlyZWN0aW9uXTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RmlsdGVycygpOiBJRmlsdGVyPElTb3J0ZXJGaWx0ZXI+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6IFwic29ydGVyXCIsXG4gICAgICAgICAgICB2YWx1ZTogeyAuLi50aGlzLnNvcnRDb25maWcgfSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlT3ZlcmxheVdpZHRoKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm92ZXJsYXlDb25maWcubWluV2lkdGggPSAoXG4gICAgICAgICAgICB0aGlzLnRvZ2dsZVJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50XG4gICAgICAgICkub2Zmc2V0V2lkdGg7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFyaWFMYWJlbEZvclNvcnRpbmdCdXR0b24oKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc29ydERpcmVjdGlvbiA9PT0gU29ydGVyRGlyZWN0aW9uLmRlc2NlbmRpbmdcbiAgICAgICAgICAgID8gYCR7dGhpcy5nZXRTZWxlY3RlZEl0ZW1UaXRsZSgpfS4gU29ydGVyIGRpcmVjdGlvbiAtIGRlc2NlbmRpbmdgXG4gICAgICAgICAgICA6IGAke3RoaXMuZ2V0U2VsZWN0ZWRJdGVtVGl0bGUoKX0uIFNvcnRlciBkaXJlY3Rpb24gLSBhc2NlbmRpbmdgO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tZW51S2V5Q29udHJvbExpc3RlbmVycy5mb3JFYWNoKChsaXN0ZW5lcikgPT4gbGlzdGVuZXIoKSk7XG4gICAgICAgIHRoaXMub25EZXN0cm95JC5uZXh0KCk7XG4gICAgICAgIHRoaXMub25EZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIHB1YmxpYyB0b2dnbGVTb3J0ZXJNZW51KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm92ZXJsYXkudG9nZ2xlKCk7XG4gICAgICAgIHRoaXMuc29ydGVyS2V5Ym9hcmRTZXJ2aWNlLmFubm91bmNlRHJvcGRvd24oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRTZWxlY3RlZEl0ZW0oKSB7XG4gICAgICAgIC8vIHNraXAgaW5pdGlhbGl6YXRpb24gaW4gY2FzZSB3ZSBhbHJlYWR5IGhhdmUgYSB2YWx1ZVxuICAgICAgICAvLyBvciBpZiB0aGUgaXRlbXNTb3VyY2UgYXJlIGxhenkgbG9hZGVkXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGVkSXRlbSB8fCAhdGhpcy5pdGVtc1NvdXJjZT8ubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaXJzdEl0ZW0gPSB0aGlzLml0ZW1zU291cmNlWzBdO1xuICAgICAgICB0aGlzLnNlbGVjdGVkSXRlbSA9XG4gICAgICAgICAgICB0eXBlb2YgZmlyc3RJdGVtID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBmaXJzdEl0ZW1cbiAgICAgICAgICAgICAgICA6IChmaXJzdEl0ZW0gYXMgSU1lbnVJdGVtKS52YWx1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRQb3B1cEl0ZW1zKCk6IHZvaWQge1xuICAgICAgICB0aGlzLml0ZW1zWzBdLml0ZW1zU291cmNlID0gKHRoaXMuaXRlbXNTb3VyY2UgYXMgYW55W10pLm1hcChcbiAgICAgICAgICAgIChpdGVtOiBzdHJpbmcgfCBJTWVudUl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBtZW51SXRlbTogSU1lbnVJdGVtID1cbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGl0ZW0gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID8geyB0aXRsZTogaXRlbSwgdmFsdWU6IGl0ZW0gfVxuICAgICAgICAgICAgICAgICAgICAgICAgOiAoaXRlbSBhcyBJTWVudUl0ZW0pO1xuICAgICAgICAgICAgICAgIG1lbnVJdGVtLmlzU2VsZWN0ZWQgPSB0aGlzLnNlbGVjdGVkSXRlbSA9PT0gbWVudUl0ZW0udmFsdWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1lbnVJdGVtO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFNvcnREaXJlY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGlmIChfdmFsdWVzKFNvcnRlckRpcmVjdGlvbikuaW5kZXhPZih0aGlzLnNvcnREaXJlY3Rpb24pID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zb3J0RGlyZWN0aW9uID0gU29ydGVyRGlyZWN0aW9uLmFzY2VuZGluZztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0UG9wdXBTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXRlbXNbMF0uaXRlbXNTb3VyY2UuZm9yRWFjaCgocG9wdXBJdGVtOiBJTWVudUl0ZW0pID0+IHtcbiAgICAgICAgICAgIHBvcHVwSXRlbS5pc1NlbGVjdGVkID0gcG9wdXBJdGVtLnZhbHVlID09PSB0aGlzLnNlbGVjdGVkSXRlbTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB0cmlnZ2VyU29ydGVyQWN0aW9uKG9sZFZhbHVlOiBJU29ydGVkSXRlbSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNvcnRlckFjdGlvbi5lbWl0KHsgbmV3VmFsdWU6IHRoaXMuc29ydENvbmZpZywgb2xkVmFsdWUgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkFwcGVuZFRvQm9keUNoYW5nZShhcHBlbmRUb0JvZHk6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdXN0b21Db250YWluZXIgPSBhcHBlbmRUb0JvZHkgPyB1bmRlZmluZWQgOiB0aGlzLnBvcHVwQXJlYTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRLZXlib2FyZFNlcnZpY2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc29ydGVyS2V5Ym9hcmRTZXJ2aWNlLm1lbnVJdGVtcyA9IHRoaXMubWVudVBvcHVwPy5tZW51SXRlbXM7XG4gICAgICAgIHRoaXMuc29ydGVyS2V5Ym9hcmRTZXJ2aWNlLm92ZXJsYXkgPSB0aGlzLm92ZXJsYXk7XG4gICAgICAgIHRoaXMuc29ydGVyS2V5Ym9hcmRTZXJ2aWNlLmluaXRLZXlib2FyZE1hbmFnZXIoKTtcbiAgICB9XG59XG4iLCI8ZGl2PlxuICAgIDxsYWJlbCAqbmdJZj1cImNhcHRpb25cIiBjbGFzcz1cIm51aS1zb3J0ZXJfX2xhYmVsXCI+e3sgY2FwdGlvbiB9fTwvbGFiZWw+XG4gICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBudWktc29ydGVyX19wb3B1cFwiICN0b2dnbGVSZWY+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG51aS1idXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJudWktc29ydGVyX190b2dnbGUtYnV0dG9uXCJcbiAgICAgICAgICAgIFtpY29uXT1cImdldFNvcnRJY29uKClcIlxuICAgICAgICAgICAgW2FyaWFMYWJlbF09XCJnZXRBcmlhTGFiZWxGb3JTb3J0aW5nQnV0dG9uKClcIlxuICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZVNvcnREaXJlY3Rpb24oKVwiXG4gICAgICAgID5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibnVpLXNvcnRlcl9fZGlzcGxheS12YWx1ZVwiPlxuICAgICAgICAgICAgICAgIHt7IGdldFNlbGVjdGVkSXRlbVRpdGxlKCkgfX1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG51aS1idXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJudWktc2VsZWN0b3JfX3RvZ2dsZVwiXG4gICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlU29ydGVyTWVudSgpXCJcbiAgICAgICAgICAgIGFyaWFMYWJlbD1cIk9wZW4gU29ydGVyIE1lbnVcIlxuICAgICAgICAgICAgaWNvbj1cImNhcmV0LWRvd25cIlxuICAgICAgICA+PC9idXR0b24+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2ICNwb3B1cEFyZWE+PC9kaXY+XG5cbiAgICA8bnVpLW92ZXJsYXlcbiAgICAgICAgI292ZXJsYXlcbiAgICAgICAgW3RvZ2dsZVJlZmVyZW5jZV09XCJ0b2dnbGVSZWZcIlxuICAgICAgICBbb3ZlcmxheUNvbmZpZ109XCJvdmVybGF5Q29uZmlnXCJcbiAgICAgICAgW2N1c3RvbUNvbnRhaW5lcl09XCJjdXN0b21Db250YWluZXJcIlxuICAgID5cbiAgICAgICAgPG51aS1tZW51LXBvcHVwXG4gICAgICAgICAgICAjcG9wdXBcbiAgICAgICAgICAgIFtpdGVtc1NvdXJjZV09XCJpdGVtc1wiXG4gICAgICAgICAgICAobWVudUl0ZW1DbGlja2VkKT1cInNlbGVjdCgkZXZlbnQpXCJcbiAgICAgICAgPjwvbnVpLW1lbnUtcG9wdXA+XG4gICAgPC9udWktb3ZlcmxheT5cbjwvZGl2PlxuIl19