UNPKG

ng-cornerstone

Version:

[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.git

189 lines 28.5 kB
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, } from '@angular/core'; import { Subject } from 'rxjs'; import { TOOL_CONFIG_MAP } from './tool.config'; import { addTool, Enums as csToolsEnums, state, ToolGroupManager } from '@cornerstonejs/tools'; import * as i0 from "@angular/core"; import * as i1 from "../core"; import * as i2 from "@angular/common"; import * as i3 from "../components/button/button.component"; import * as i4 from "../components/button/button-group.component"; export class ToolBarComponent { constructor(csService, cdr) { this.csService = csService; this.cdr = cdr; this.destroy$ = new Subject(); this.toolList = []; this.toolbarInit = new EventEmitter(); this.toolbarDestroy = new EventEmitter(); this.toolConfigList = []; this.cameraList = []; } ngOnChanges(changes) { const { toolList, activeViewportId } = changes; if (toolList && !toolList.isFirstChange()) { this.updateToolList(); } if (activeViewportId && !activeViewportId.isFirstChange()) { this.updateActiveViewport(this.activeViewportId); } } ngOnInit() { console.debug('Toolbar register:', this.toolGroupId); this.toolGroup = ToolGroupManager.createToolGroup(this.toolGroupId); this.updateToolList(); } ngAfterViewInit() { this.toolbarInit.emit(); this.csService.setToolGroup(this.toolGroup); } get renderingEngineId() { return this.csService.getRenderingEngineId(); } get renderingEngine() { return this.csService.getRenderingEngine(); } registerViewport(viewportId) { console.debug('Toolbar register viewport:', viewportId); this.toolGroup.addViewport(viewportId, this.renderingEngineId); } unregisterViewport(viewportId) { console.debug('Toolbar unregister viewport:', viewportId); this.toolGroup.removeViewports(this.renderingEngineId, viewportId); } updateToolList() { if (!this.toolGroup) { return; } const toolConfigList = []; const cameraList = []; this.toolList.forEach((toolEnum) => { const config = TOOL_CONFIG_MAP[toolEnum]; config.disabled = false; if (config.tool) { toolConfigList.push(config); const toolName = config.tool.toolName; const toolAlreadyAdded = state.tools[toolName] !== undefined; if (!toolAlreadyAdded) { addTool(config.tool); } if (!this.toolGroup.hasTool(config.name)) { this.toolGroup.addTool(config.name); } } else if (config.callback) { cameraList.push(config); } }); for (let i = 0; i < toolConfigList.length; i++) { const toolConfig = toolConfigList[i]; if (toolConfig.name) { this.toolGroup.setToolPassive(toolConfig.name); } } this.toolConfigList = toolConfigList; this.cameraList = cameraList; } updateActiveViewport(inputActiveViewportId) { const activeViewportId = inputActiveViewportId; if (!activeViewportId) { return; } // 保存旧的activeViewportId const previousViewportId = this.activeViewportId; // 更新当前的activeViewportId this.activeViewportId = activeViewportId; const viewport = this.renderingEngine.getViewport(this.activeViewportId); if (viewport) { const viewportType = viewport.type; this.toolConfigList.forEach((toolConfig) => { if (toolConfig.types.includes(viewportType)) { toolConfig.disabled = false; } else { toolConfig.disabled = true; } }); this.cameraList.map((cameraConfig) => { if (cameraConfig.types.includes(viewportType)) { cameraConfig.disabled = false; } else { cameraConfig.disabled = true; } }); // 确保新的viewport已添加到toolGroup中 if (!this.toolGroup.getViewportIds().includes(this.activeViewportId)) { this.registerViewport(this.activeViewportId); } // 重新激活当前工具,确保它能在新的viewport上操作 if (previousViewportId !== this.activeViewportId && this.currentTool) { // 先移除其他绑定,以确保工具干净地应用于新viewport const toolNames = this.toolConfigList.map((config) => config.name); toolNames.forEach((name) => { if (name !== this.currentTool?.name) { this.toolGroup.setToolPassive(name); } }); // 重新激活当前工具 this.toolGroup.setToolActive(this.currentTool.name, { bindings: [{ mouseButton: csToolsEnums.MouseBindings.Primary }], }); // 确保工具应用于当前viewport this.toolGroup.setViewportsCursorByToolName(this.currentTool.name); } this.cdr.detectChanges(); } } activeTool(names) { if (!names || names.length === 0) { return; } const pressedTool = this.toolConfigList.find((toolConfig) => toolConfig.name === names[0]); if (!pressedTool) { return; } if (pressedTool.tool) { if (this.currentTool) { this.toolGroup.setToolPassive(this.currentTool.name); } this.currentTool = pressedTool; this.toolGroup.setToolActive(pressedTool.name, { bindings: [{ mouseButton: csToolsEnums.MouseBindings.Primary }], }); this.toolGroup.setViewportsCursorByToolName(pressedTool.name); } } changeCamera(name) { if (!name) { return; } const cameraTool = this.cameraList.find((toolConfig) => toolConfig.name === name); if (cameraTool?.callback) { cameraTool.callback(this.renderingEngineId, this.activeViewportId, cameraTool.options); } } ngOnDestroy() { console.debug('Toolbar destroy: ', this.toolGroupId); this.toolbarDestroy.emit(this.toolGroupId); ToolGroupManager.destroyToolGroup(this.toolGroupId); this.destroy$.next(); this.destroy$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToolBarComponent, deps: [{ token: i1.CornerstoneService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ToolBarComponent, selector: "nc-tool-bar", inputs: { toolGroupId: "toolGroupId", toolList: "toolList", activeViewportId: "activeViewportId" }, outputs: { toolbarInit: "toolbarInit", toolbarDestroy: "toolbarDestroy" }, exportAs: ["ncToolBar"], usesOnChanges: true, ngImport: i0, template: "<nc-button-group (valueChange)=\"activeTool($event)\">\n <button\n nc-button\n *ngFor=\"let config of toolConfigList\"\n [isToggle]=\"!!config.tool\"\n [content]=\"'icon-text'\"\n [icon]=\"config.icon\"\n [text]=\"config.label\"\n [value]=\"config.name\"\n [disabled]=\"config.disabled ?? false\"\n ></button>\n</nc-button-group>\n<nc-button-group>\n <button\n nc-button\n *ngFor=\"let config of cameraList\"\n (click)=\"changeCamera(config.name)\"\n [content]=\"'icon-text'\"\n [icon]=\"config.icon\"\n [text]=\"config.label\"\n [disabled]=\"config.disabled ?? false\"\n ></button>\n</nc-button-group>\n", dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i3.ButtonComponent, selector: "button[nc-button], a[nc-button]", inputs: ["disabled", "tabIndex", "type", "shape", "content", "size", "isToggle", "icon", "text", "value"], outputs: ["pressedChange"], exportAs: ["ncButton"] }, { kind: "component", type: i4.ButtonGroupComponent, selector: "nc-button-group", inputs: ["disabled", "multiple"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToolBarComponent, decorators: [{ type: Component, args: [{ selector: 'nc-tool-bar', exportAs: 'ncToolBar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nc-button-group (valueChange)=\"activeTool($event)\">\n <button\n nc-button\n *ngFor=\"let config of toolConfigList\"\n [isToggle]=\"!!config.tool\"\n [content]=\"'icon-text'\"\n [icon]=\"config.icon\"\n [text]=\"config.label\"\n [value]=\"config.name\"\n [disabled]=\"config.disabled ?? false\"\n ></button>\n</nc-button-group>\n<nc-button-group>\n <button\n nc-button\n *ngFor=\"let config of cameraList\"\n (click)=\"changeCamera(config.name)\"\n [content]=\"'icon-text'\"\n [icon]=\"config.icon\"\n [text]=\"config.label\"\n [disabled]=\"config.disabled ?? false\"\n ></button>\n</nc-button-group>\n" }] }], ctorParameters: () => [{ type: i1.CornerstoneService }, { type: i0.ChangeDetectorRef }], propDecorators: { toolGroupId: [{ type: Input }], toolList: [{ type: Input }], activeViewportId: [{ type: Input }], toolbarInit: [{ type: Output }], toolbarDestroy: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbC1iYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctY29ybmVyc3RvbmUvc3JjL2xpYi90b29sL3Rvb2wtYmFyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWNvcm5lcnN0b25lL3NyYy9saWIvdG9vbC90b29sLWJhci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUlMLE1BQU0sR0FFUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLElBQUksWUFBWSxFQUFFLEtBQUssRUFBd0IsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7Ozs7O0FBVXJILE1BQU0sT0FBTyxnQkFBZ0I7SUF1QjNCLFlBQW9CLFNBQTZCLEVBQVUsR0FBc0I7UUFBN0QsY0FBUyxHQUFULFNBQVMsQ0FBb0I7UUFBVSxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQXRCekUsYUFBUSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7UUFNdkMsYUFBUSxHQUFlLEVBQUUsQ0FBQztRQUtoQixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDekMsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBTXRELG1CQUFjLEdBQWlCLEVBQUUsQ0FBQztRQUNsQyxlQUFVLEdBQWlCLEVBQUUsQ0FBQztJQUdzRCxDQUFDO0lBRXJGLFdBQVcsQ0FBQyxPQUFzQjtRQUNoQyxNQUFNLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLEdBQUcsT0FBTyxDQUFDO1FBQy9DLElBQUksUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUM7WUFDMUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3hCLENBQUM7UUFDRCxJQUFJLGdCQUFnQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQztZQUMxRCxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbkQsQ0FBQztJQUNILENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDckQsSUFBSSxDQUFDLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBRSxDQUFDO1FBQ3JFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRCxJQUFJLGlCQUFpQjtRQUNuQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUMvQyxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzdDLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxVQUFrQjtRQUNqQyxPQUFPLENBQUMsS0FBSyxDQUFDLDRCQUE0QixFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRUQsa0JBQWtCLENBQUMsVUFBa0I7UUFDbkMsT0FBTyxDQUFDLEtBQUssQ0FBQyw4QkFBOEIsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDckUsQ0FBQztJQUVELGNBQWM7UUFDWixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxjQUFjLEdBQWlCLEVBQUUsQ0FBQztRQUN4QyxNQUFNLFVBQVUsR0FBaUIsRUFBRSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7WUFDakMsTUFBTSxNQUFNLEdBQUcsZUFBZSxDQUFDLFFBQVEsQ0FBRSxDQUFDO1lBQzFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1lBQ3hCLElBQUksTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNoQixjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUM1QixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztnQkFDdEMsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLFNBQVMsQ0FBQztnQkFDN0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7b0JBQ3RCLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3ZCLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO29CQUN6QyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RDLENBQUM7WUFDSCxDQUFDO2lCQUFNLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUMzQixVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzFCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDL0MsTUFBTSxVQUFVLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLElBQUksVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakQsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUNyQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUMvQixDQUFDO0lBRUQsb0JBQW9CLENBQUMscUJBQThCO1FBQ2pELE1BQU0sZ0JBQWdCLEdBQUcscUJBQXFCLENBQUM7UUFDL0MsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDdEIsT0FBTztRQUNULENBQUM7UUFFRCx1QkFBdUI7UUFDdkIsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFFakQsd0JBQXdCO1FBQ3hCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxnQkFBZ0IsQ0FBQztRQUV6QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsZ0JBQWlCLENBQUMsQ0FBQztRQUMxRSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQztZQUNuQyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFO2dCQUN6QyxJQUFJLFVBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7b0JBQzVDLFVBQVUsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUM5QixDQUFDO3FCQUFNLENBQUM7b0JBQ04sVUFBVSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7Z0JBQzdCLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7Z0JBQ25DLElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztvQkFDOUMsWUFBWSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQ2hDLENBQUM7cUJBQU0sQ0FBQztvQkFDTixZQUFZLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztnQkFDL0IsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1lBRUgsNkJBQTZCO1lBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO2dCQUNyRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDL0MsQ0FBQztZQUVELDhCQUE4QjtZQUM5QixJQUFJLGtCQUFrQixLQUFLLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ3JFLCtCQUErQjtnQkFDL0IsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDbkUsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO29CQUN6QixJQUFJLElBQUksS0FBSyxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDO3dCQUNwQyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDdEMsQ0FBQztnQkFDSCxDQUFDLENBQUMsQ0FBQztnQkFFSCxXQUFXO2dCQUNYLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFO29CQUNsRCxRQUFRLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxZQUFZLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDO2lCQUNoRSxDQUFDLENBQUM7Z0JBRUgsb0JBQW9CO2dCQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckUsQ0FBQztZQUVELElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDM0IsQ0FBQztJQUNILENBQUM7SUFFRCxVQUFVLENBQUMsS0FBWTtRQUNyQixJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDakMsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakIsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNyQixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDckIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2RCxDQUFDO1lBQ0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7WUFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRTtnQkFDN0MsUUFBUSxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsWUFBWSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQzthQUNoRSxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsU0FBUyxDQUFDLDRCQUE0QixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRSxDQUFDO0lBQ0gsQ0FBQztJQUVELFlBQVksQ0FBQyxJQUFZO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUM7UUFDbEYsSUFBSSxVQUFVLEVBQUUsUUFBUSxFQUFFLENBQUM7WUFDekIsVUFBVSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGdCQUFpQixFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRixDQUFDO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxPQUFPLENBQUMsS0FBSyxDQUFDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDM0MsZ0JBQWdCLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDOytHQS9MVSxnQkFBZ0I7bUdBQWhCLGdCQUFnQixnUkN6QjdCLCtvQkF1QkE7OzRGREVhLGdCQUFnQjtrQkFONUIsU0FBUzsrQkFDRSxhQUFhLFlBQ2IsV0FBVyxtQkFFSix1QkFBdUIsQ0FBQyxNQUFNO3VIQU0vQyxXQUFXO3NCQURWLEtBQUs7Z0JBSU4sUUFBUTtzQkFEUCxLQUFLO2dCQUlOLGdCQUFnQjtzQkFEZixLQUFLO2dCQUdJLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0csY0FBYztzQkFBdkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVE9PTF9DT05GSUdfTUFQIH0gZnJvbSAnLi90b29sLmNvbmZpZyc7XG5pbXBvcnQgeyBhZGRUb29sLCBFbnVtcyBhcyBjc1Rvb2xzRW51bXMsIHN0YXRlLCBUeXBlcyBhcyBjc1Rvb2xUeXBlcywgVG9vbEdyb3VwTWFuYWdlciB9IGZyb20gJ0Bjb3JuZXJzdG9uZWpzL3Rvb2xzJztcbmltcG9ydCB7IFRvb2xDb25maWcsIFRvb2xFbnVtIH0gZnJvbSAnLi90b29sLnR5cGVzJztcbmltcG9ydCB7IENvcm5lcnN0b25lU2VydmljZSB9IGZyb20gJy4uL2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduYy10b29sLWJhcicsXG4gIGV4cG9ydEFzOiAnbmNUb29sQmFyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3Rvb2wtYmFyLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFRvb2xCYXJDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0IHtcbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgQElucHV0KClcbiAgdG9vbEdyb3VwSWQhOiBzdHJpbmc7XG5cbiAgQElucHV0KClcbiAgdG9vbExpc3Q6IFRvb2xFbnVtW10gPSBbXTtcblxuICBASW5wdXQoKVxuICBhY3RpdmVWaWV3cG9ydElkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgQE91dHB1dCgpIHRvb2xiYXJJbml0ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gIEBPdXRwdXQoKSB0b29sYmFyRGVzdHJveSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIHByaXZhdGUgdG9vbEdyb3VwITogY3NUb29sVHlwZXMuSVRvb2xHcm91cDtcblxuICBzZWdtZW50YXRpb25SZXByZXNlbnRhdGlvblVJRHM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuXG4gIHRvb2xDb25maWdMaXN0OiBUb29sQ29uZmlnW10gPSBbXTtcbiAgY2FtZXJhTGlzdDogVG9vbENvbmZpZ1tdID0gW107XG4gIGN1cnJlbnRUb29sPzogVG9vbENvbmZpZztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNzU2VydmljZTogQ29ybmVyc3RvbmVTZXJ2aWNlLCBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGNvbnN0IHsgdG9vbExpc3QsIGFjdGl2ZVZpZXdwb3J0SWQgfSA9IGNoYW5nZXM7XG4gICAgaWYgKHRvb2xMaXN0ICYmICF0b29sTGlzdC5pc0ZpcnN0Q2hhbmdlKCkpIHtcbiAgICAgIHRoaXMudXBkYXRlVG9vbExpc3QoKTtcbiAgICB9XG4gICAgaWYgKGFjdGl2ZVZpZXdwb3J0SWQgJiYgIWFjdGl2ZVZpZXdwb3J0SWQuaXNGaXJzdENoYW5nZSgpKSB7XG4gICAgICB0aGlzLnVwZGF0ZUFjdGl2ZVZpZXdwb3J0KHRoaXMuYWN0aXZlVmlld3BvcnRJZCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgY29uc29sZS5kZWJ1ZygnVG9vbGJhciByZWdpc3RlcjonLCB0aGlzLnRvb2xHcm91cElkKTtcbiAgICB0aGlzLnRvb2xHcm91cCA9IFRvb2xHcm91cE1hbmFnZXIuY3JlYXRlVG9vbEdyb3VwKHRoaXMudG9vbEdyb3VwSWQpITtcbiAgICB0aGlzLnVwZGF0ZVRvb2xMaXN0KCk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy50b29sYmFySW5pdC5lbWl0KCk7XG4gICAgdGhpcy5jc1NlcnZpY2Uuc2V0VG9vbEdyb3VwKHRoaXMudG9vbEdyb3VwKTtcbiAgfVxuXG4gIGdldCByZW5kZXJpbmdFbmdpbmVJZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jc1NlcnZpY2UuZ2V0UmVuZGVyaW5nRW5naW5lSWQoKTtcbiAgfVxuXG4gIGdldCByZW5kZXJpbmdFbmdpbmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3NTZXJ2aWNlLmdldFJlbmRlcmluZ0VuZ2luZSgpO1xuICB9XG5cbiAgcmVnaXN0ZXJWaWV3cG9ydCh2aWV3cG9ydElkOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmRlYnVnKCdUb29sYmFyIHJlZ2lzdGVyIHZpZXdwb3J0OicsIHZpZXdwb3J0SWQpO1xuICAgIHRoaXMudG9vbEdyb3VwLmFkZFZpZXdwb3J0KHZpZXdwb3J0SWQsIHRoaXMucmVuZGVyaW5nRW5naW5lSWQpO1xuICB9XG5cbiAgdW5yZWdpc3RlclZpZXdwb3J0KHZpZXdwb3J0SWQ6IHN0cmluZykge1xuICAgIGNvbnNvbGUuZGVidWcoJ1Rvb2xiYXIgdW5yZWdpc3RlciB2aWV3cG9ydDonLCB2aWV3cG9ydElkKTtcbiAgICB0aGlzLnRvb2xHcm91cC5yZW1vdmVWaWV3cG9ydHModGhpcy5yZW5kZXJpbmdFbmdpbmVJZCwgdmlld3BvcnRJZCk7XG4gIH1cblxuICB1cGRhdGVUb29sTGlzdCgpIHtcbiAgICBpZiAoIXRoaXMudG9vbEdyb3VwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHRvb2xDb25maWdMaXN0OiBUb29sQ29uZmlnW10gPSBbXTtcbiAgICBjb25zdCBjYW1lcmFMaXN0OiBUb29sQ29uZmlnW10gPSBbXTtcbiAgICB0aGlzLnRvb2xMaXN0LmZvckVhY2goKHRvb2xFbnVtKSA9PiB7XG4gICAgICBjb25zdCBjb25maWcgPSBUT09MX0NPTkZJR19NQVBbdG9vbEVudW1dITtcbiAgICAgIGNvbmZpZy5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgaWYgKGNvbmZpZy50b29sKSB7XG4gICAgICAgIHRvb2xDb25maWdMaXN0LnB1c2goY29uZmlnKTtcbiAgICAgICAgY29uc3QgdG9vbE5hbWUgPSBjb25maWcudG9vbC50b29sTmFtZTtcbiAgICAgICAgY29uc3QgdG9vbEFscmVhZHlBZGRlZCA9IHN0YXRlLnRvb2xzW3Rvb2xOYW1lXSAhPT0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIXRvb2xBbHJlYWR5QWRkZWQpIHtcbiAgICAgICAgICBhZGRUb29sKGNvbmZpZy50b29sKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMudG9vbEdyb3VwLmhhc1Rvb2woY29uZmlnLm5hbWUpKSB7XG4gICAgICAgICAgdGhpcy50b29sR3JvdXAuYWRkVG9vbChjb25maWcubmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY29uZmlnLmNhbGxiYWNrKSB7XG4gICAgICAgIGNhbWVyYUxpc3QucHVzaChjb25maWcpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdG9vbENvbmZpZ0xpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHRvb2xDb25maWcgPSB0b29sQ29uZmlnTGlzdFtpXTtcbiAgICAgIGlmICh0b29sQ29uZmlnLm5hbWUpIHtcbiAgICAgICAgdGhpcy50b29sR3JvdXAuc2V0VG9vbFBhc3NpdmUodG9vbENvbmZpZy5uYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy50b29sQ29uZmlnTGlzdCA9IHRvb2xDb25maWdMaXN0O1xuICAgIHRoaXMuY2FtZXJhTGlzdCA9IGNhbWVyYUxpc3Q7XG4gIH1cblxuICB1cGRhdGVBY3RpdmVWaWV3cG9ydChpbnB1dEFjdGl2ZVZpZXdwb3J0SWQ/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBhY3RpdmVWaWV3cG9ydElkID0gaW5wdXRBY3RpdmVWaWV3cG9ydElkO1xuICAgIGlmICghYWN0aXZlVmlld3BvcnRJZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIOS/neWtmOaXp+eahGFjdGl2ZVZpZXdwb3J0SWRcbiAgICBjb25zdCBwcmV2aW91c1ZpZXdwb3J0SWQgPSB0aGlzLmFjdGl2ZVZpZXdwb3J0SWQ7XG5cbiAgICAvLyDmm7TmlrDlvZPliY3nmoRhY3RpdmVWaWV3cG9ydElkXG4gICAgdGhpcy5hY3RpdmVWaWV3cG9ydElkID0gYWN0aXZlVmlld3BvcnRJZDtcblxuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy5yZW5kZXJpbmdFbmdpbmUuZ2V0Vmlld3BvcnQodGhpcy5hY3RpdmVWaWV3cG9ydElkISk7XG4gICAgaWYgKHZpZXdwb3J0KSB7XG4gICAgICBjb25zdCB2aWV3cG9ydFR5cGUgPSB2aWV3cG9ydC50eXBlO1xuICAgICAgdGhpcy50b29sQ29uZmlnTGlzdC5mb3JFYWNoKCh0b29sQ29uZmlnKSA9PiB7XG4gICAgICAgIGlmICh0b29sQ29uZmlnLnR5cGVzLmluY2x1ZGVzKHZpZXdwb3J0VHlwZSkpIHtcbiAgICAgICAgICB0b29sQ29uZmlnLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdG9vbENvbmZpZy5kaXNhYmxlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5jYW1lcmFMaXN0Lm1hcCgoY2FtZXJhQ29uZmlnKSA9PiB7XG4gICAgICAgIGlmIChjYW1lcmFDb25maWcudHlwZXMuaW5jbHVkZXModmlld3BvcnRUeXBlKSkge1xuICAgICAgICAgIGNhbWVyYUNvbmZpZy5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbWVyYUNvbmZpZy5kaXNhYmxlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyDnoa7kv53mlrDnmoR2aWV3cG9ydOW3sua3u+WKoOWIsHRvb2xHcm91cOS4rVxuICAgICAgaWYgKCF0aGlzLnRvb2xHcm91cC5nZXRWaWV3cG9ydElkcygpLmluY2x1ZGVzKHRoaXMuYWN0aXZlVmlld3BvcnRJZCkpIHtcbiAgICAgICAgdGhpcy5yZWdpc3RlclZpZXdwb3J0KHRoaXMuYWN0aXZlVmlld3BvcnRJZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIOmHjeaWsOa/gOa0u+W9k+WJjeW3peWFt++8jOehruS/neWug+iDveWcqOaWsOeahHZpZXdwb3J05LiK5pON5L2cXG4gICAgICBpZiAocHJldmlvdXNWaWV3cG9ydElkICE9PSB0aGlzLmFjdGl2ZVZpZXdwb3J0SWQgJiYgdGhpcy5jdXJyZW50VG9vbCkge1xuICAgICAgICAvLyDlhYjnp7vpmaTlhbbku5bnu5HlrprvvIzku6Xnoa7kv53lt6XlhbflubLlh4DlnLDlupTnlKjkuo7mlrB2aWV3cG9ydFxuICAgICAgICBjb25zdCB0b29sTmFtZXMgPSB0aGlzLnRvb2xDb25maWdMaXN0Lm1hcCgoY29uZmlnKSA9PiBjb25maWcubmFtZSk7XG4gICAgICAgIHRvb2xOYW1lcy5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgICAgaWYgKG5hbWUgIT09IHRoaXMuY3VycmVudFRvb2w/Lm5hbWUpIHtcbiAgICAgICAgICAgIHRoaXMudG9vbEdyb3VwLnNldFRvb2xQYXNzaXZlKG5hbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8g6YeN5paw5r+A5rS75b2T5YmN5bel5YW3XG4gICAgICAgIHRoaXMudG9vbEdyb3VwLnNldFRvb2xBY3RpdmUodGhpcy5jdXJyZW50VG9vbC5uYW1lLCB7XG4gICAgICAgICAgYmluZGluZ3M6IFt7IG1vdXNlQnV0dG9uOiBjc1Rvb2xzRW51bXMuTW91c2VCaW5kaW5ncy5QcmltYXJ5IH1dLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDnoa7kv53lt6XlhbflupTnlKjkuo7lvZPliY12aWV3cG9ydFxuICAgICAgICB0aGlzLnRvb2xHcm91cC5zZXRWaWV3cG9ydHNDdXJzb3JCeVRvb2xOYW1lKHRoaXMuY3VycmVudFRvb2wubmFtZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBhY3RpdmVUb29sKG5hbWVzOiBhbnlbXSkge1xuICAgIGlmICghbmFtZXMgfHwgbmFtZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHByZXNzZWRUb29sID0gdGhpcy50b29sQ29uZmlnTGlzdC5maW5kKCh0b29sQ29uZmlnKSA9PiB0b29sQ29uZmlnLm5hbWUgPT09IG5hbWVzWzBdKTtcbiAgICBpZiAoIXByZXNzZWRUb29sKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChwcmVzc2VkVG9vbC50b29sKSB7XG4gICAgICBpZiAodGhpcy5jdXJyZW50VG9vbCkge1xuICAgICAgICB0aGlzLnRvb2xHcm91cC5zZXRUb29sUGFzc2l2ZSh0aGlzLmN1cnJlbnRUb29sLm5hbWUpO1xuICAgICAgfVxuICAgICAgdGhpcy5jdXJyZW50VG9vbCA9IHByZXNzZWRUb29sO1xuICAgICAgdGhpcy50b29sR3JvdXAuc2V0VG9vbEFjdGl2ZShwcmVzc2VkVG9vbC5uYW1lLCB7XG4gICAgICAgIGJpbmRpbmdzOiBbeyBtb3VzZUJ1dHRvbjogY3NUb29sc0VudW1zLk1vdXNlQmluZGluZ3MuUHJpbWFyeSB9XSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy50b29sR3JvdXAuc2V0Vmlld3BvcnRzQ3Vyc29yQnlUb29sTmFtZShwcmVzc2VkVG9vbC5uYW1lKTtcbiAgICB9XG4gIH1cblxuICBjaGFuZ2VDYW1lcmEobmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCFuYW1lKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNhbWVyYVRvb2wgPSB0aGlzLmNhbWVyYUxpc3QuZmluZCgodG9vbENvbmZpZykgPT4gdG9vbENvbmZpZy5uYW1lID09PSBuYW1lKTtcbiAgICBpZiAoY2FtZXJhVG9vbD8uY2FsbGJhY2spIHtcbiAgICAgIGNhbWVyYVRvb2wuY2FsbGJhY2sodGhpcy5yZW5kZXJpbmdFbmdpbmVJZCwgdGhpcy5hY3RpdmVWaWV3cG9ydElkISwgY2FtZXJhVG9vbC5vcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBjb25zb2xlLmRlYnVnKCdUb29sYmFyIGRlc3Ryb3k6ICcsIHRoaXMudG9vbEdyb3VwSWQpO1xuICAgIHRoaXMudG9vbGJhckRlc3Ryb3kuZW1pdCh0aGlzLnRvb2xHcm91cElkKTtcbiAgICBUb29sR3JvdXBNYW5hZ2VyLmRlc3Ryb3lUb29sR3JvdXAodGhpcy50b29sR3JvdXBJZCk7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCI8bmMtYnV0dG9uLWdyb3VwICh2YWx1ZUNoYW5nZSk9XCJhY3RpdmVUb29sKCRldmVudClcIj5cbiAgPGJ1dHRvblxuICAgIG5jLWJ1dHRvblxuICAgICpuZ0Zvcj1cImxldCBjb25maWcgb2YgdG9vbENvbmZpZ0xpc3RcIlxuICAgIFtpc1RvZ2dsZV09XCIhIWNvbmZpZy50b29sXCJcbiAgICBbY29udGVudF09XCInaWNvbi10ZXh0J1wiXG4gICAgW2ljb25dPVwiY29uZmlnLmljb25cIlxuICAgIFt0ZXh0XT1cImNvbmZpZy5sYWJlbFwiXG4gICAgW3ZhbHVlXT1cImNvbmZpZy5uYW1lXCJcbiAgICBbZGlzYWJsZWRdPVwiY29uZmlnLmRpc2FibGVkID8/IGZhbHNlXCJcbiAgPjwvYnV0dG9uPlxuPC9uYy1idXR0b24tZ3JvdXA+XG48bmMtYnV0dG9uLWdyb3VwPlxuICA8YnV0dG9uXG4gICAgbmMtYnV0dG9uXG4gICAgKm5nRm9yPVwibGV0IGNvbmZpZyBvZiBjYW1lcmFMaXN0XCJcbiAgICAoY2xpY2spPVwiY2hhbmdlQ2FtZXJhKGNvbmZpZy5uYW1lKVwiXG4gICAgW2NvbnRlbnRdPVwiJ2ljb24tdGV4dCdcIlxuICAgIFtpY29uXT1cImNvbmZpZy5pY29uXCJcbiAgICBbdGV4dF09XCJjb25maWcubGFiZWxcIlxuICAgIFtkaXNhYmxlZF09XCJjb25maWcuZGlzYWJsZWQgPz8gZmFsc2VcIlxuICA+PC9idXR0b24+XG48L25jLWJ1dHRvbi1ncm91cD5cbiJdfQ==