UNPKG

ng-zorro-antd

Version:

An enterprise-class UI components based on Ant Design and Angular

426 lines (424 loc) 55.2 kB
/** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ import { __decorate } from "tslib"; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Host, Input, Optional, Output, TemplateRef, ViewChildren, ViewEncapsulation } from '@angular/core'; import { forkJoin, ReplaySubject, Subject } from 'rxjs'; import { finalize, take, takeUntil } from 'rxjs/operators'; import { buildGraph } from 'dagre-compound'; import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation'; import { cancelRequestAnimationFrame } from 'ng-zorro-antd/core/polyfill'; import { InputBoolean } from 'ng-zorro-antd/core/util'; import { calculateTransform } from './core/utils'; import { NzGraphEdgeDirective } from './graph-edge.directive'; import { NzGraphGroupNodeDirective } from './graph-group-node.directive'; import { NzGraphNodeComponent } from './graph-node.component'; import { NzGraphNodeDirective } from './graph-node.directive'; import { NzGraphZoomDirective } from './graph-zoom.directive'; import { nzTypeDefinition, NZ_GRAPH_LAYOUT_SETTING } from './interface'; /** Checks whether an object is a data source. */ export function isDataSource(value) { // Check if the value is a DataSource by observing if it has a connect function. Cannot // be checked as an `instanceof DataSource` since people could create their own sources // that match the interface, but don't extend DataSource. return value && typeof value.connect === 'function'; } export class NzGraphComponent { constructor(cdr, elementRef, noAnimation, nzGraphZoom) { this.cdr = cdr; this.elementRef = elementRef; this.noAnimation = noAnimation; this.nzGraphZoom = nzGraphZoom; this.nzRankDirection = 'LR'; this.nzAutoSize = false; this.nzGraphInitialized = new EventEmitter(); this.nzGraphRendered = new EventEmitter(); this.nzNodeClick = new EventEmitter(); this.requestId = -1; this.transformStyle = ''; this.graphRenderedSubject$ = new ReplaySubject(1); this.renderInfo = { labelHeight: 0 }; this.mapOfNodeAttr = {}; this.mapOfEdgeAttr = {}; this.zoom = 1; this.typedNodes = nzTypeDefinition(); this.layoutSetting = NZ_GRAPH_LAYOUT_SETTING; this.destroy$ = new Subject(); this.nodeTrackByFun = (_, node) => node.name; this.edgeTrackByFun = (_, edge) => `${edge.v}-${edge.w}`; this.subGraphTransform = (node) => { const x = node.x - node.coreBox.width / 2.0; const y = node.y - node.height / 2.0 + node.paddingTop; return `translate(${x}, ${y})`; }; this.$asNzGraphEdges = (data) => data; this.coreTransform = (node) => `translate(0, ${node.parentNodeName ? node.labelHeight : 0})`; } ngOnInit() { this.graphRenderedSubject$.pipe(take(1), takeUntil(this.destroy$)).subscribe(() => { // Only zooming is not set, move graph to center if (!this.nzGraphZoom) { this.fitCenter(); } this.nzGraphInitialized.emit(this); }); } ngOnChanges(changes) { const { nzAutoFit, nzRankDirection, nzGraphData, nzGraphLayoutConfig } = changes; if (nzGraphLayoutConfig) { this.layoutSetting = this.mergeConfig(nzGraphLayoutConfig.currentValue); } if (nzGraphData) { if (this.dataSource !== this.nzGraphData) { this._switchDataSource(this.nzGraphData); } } if ((nzAutoFit && !nzAutoFit.firstChange) || (nzRankDirection && !nzRankDirection.firstChange)) { // Render graph if (this.dataSource.dataSource) { this.drawGraph(this.dataSource.dataSource, { rankDirection: this.nzRankDirection, expanded: this.dataSource.expansionModel.selected || [] }).then(() => { this.cdr.markForCheck(); }); } } this.cdr.markForCheck(); } ngAfterContentChecked() { if (this.dataSource && !this._dataSubscription) { this.observeRenderChanges(); } } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); if (this.dataSource && typeof this.dataSource.disconnect === 'function') { this.dataSource.disconnect(); } if (this._dataSubscription) { this._dataSubscription.unsubscribe(); this._dataSubscription = null; } cancelRequestAnimationFrame(this.requestId); } /** * Emit event */ clickNode(node) { this.nzNodeClick.emit(node); } /** * Move graph to center and scale automatically */ fitCenter() { const { x, y, k } = calculateTransform(this.elementRef.nativeElement.querySelector('svg'), this.elementRef.nativeElement.querySelector('svg > g')); if (k) { this.zoom = k; this.transformStyle = `translate(${x}, ${y})scale(${k})`; } this.cdr.markForCheck(); } /** * re-Draw graph * * @param data * @param options * @param needResize */ drawGraph(data, options, needResize = false) { return new Promise(resolve => { this.requestId = requestAnimationFrame(() => { const renderInfo = this.buildGraphInfo(data, options); // TODO // Need better performance this.renderInfo = renderInfo; this.cdr.markForCheck(); this.requestId = requestAnimationFrame(() => { var _a; this.drawNodes(!((_a = this.noAnimation) === null || _a === void 0 ? void 0 : _a.nzNoAnimation)).then(() => { // Update element this.cdr.markForCheck(); if (needResize) { this.resizeNodeSize().then(() => { const dataSource = this.dataSource.dataSource; this.drawGraph(dataSource, options, false).then(() => resolve()); }); } else { this.graphRenderedSubject$.next(); this.nzGraphRendered.emit(this); resolve(); } }); }); }); this.cdr.markForCheck(); }); } /** * Redraw all nodes * * @param animate */ drawNodes(animate = true) { return new Promise(resolve => { if (animate) { this.makeNodesAnimation().subscribe(() => { resolve(); }); } else { this.listOfNodeComponent.map(node => { node.makeNoAnimation(); }); resolve(); } }); } resizeNodeSize() { return new Promise(resolve => { var _a; const dataSource = this.dataSource.dataSource; let scale = ((_a = this.nzGraphZoom) === null || _a === void 0 ? void 0 : _a.nzZoom) || this.zoom || 1; this.listOfNodeElement.forEach(nodeEle => { var _a; const contentEle = nodeEle.nativeElement; if (contentEle) { let width; let height; // Check if foreignObject is set const clientRect = (_a = contentEle.querySelector('foreignObject > :first-child')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect(); if (clientRect) { width = clientRect.width; height = clientRect.height; } else { const bBoxRect = contentEle.getBBox(); width = bBoxRect.width; height = bBoxRect.height; // getBBox will return actual value scale = 1; } // Element id type is string const node = dataSource.nodes.find(n => `${n.id}` === nodeEle.nativeElement.id); if (node && width && height) { node.height = height / scale; node.width = width / scale; } } }); resolve(); }); } /** * Switch to the provided data source by resetting the data and unsubscribing from the current * render change subscription if one exists. If the data source is null, interpret this by * clearing the node outlet. Otherwise start listening for new data. */ _switchDataSource(dataSource) { if (this.dataSource && typeof this.dataSource.disconnect === 'function') { this.nzGraphData.disconnect(); } if (this._dataSubscription) { this._dataSubscription.unsubscribe(); this._dataSubscription = null; } this.dataSource = dataSource; this.observeRenderChanges(); } /** Set up a subscription for the data provided by the data source. */ observeRenderChanges() { let dataStream; let graphOptions = { rankDirection: this.nzRankDirection }; if (isDataSource(this.dataSource)) { dataStream = this.dataSource.connect(); } if (dataStream) { this._dataSubscription = dataStream.pipe(takeUntil(this.destroy$)).subscribe(data => { graphOptions = { rankDirection: this.nzRankDirection, expanded: this.nzGraphData.expansionModel.selected }; this.drawGraph(data, graphOptions, this.nzAutoSize).then(() => { this.cdr.detectChanges(); }); }); } else { throw Error(`A valid data source must be provided.`); } } /** * Get renderInfo and prepare some data * * @param data * @param options * @private */ buildGraphInfo(data, options) { this.parseInfo(data); const renderInfo = buildGraph(data, options, this.layoutSetting); const dig = (nodes) => { nodes.forEach(node => { const { x, y } = node; node.xOffset = x; node.yOffset = y; if (node.type === 1 && this.mapOfNodeAttr.hasOwnProperty(node.name)) { Object.assign(node, this.mapOfNodeAttr[node.name]); } else if (node.type === 0) { node.edges.forEach(edge => { if (this.mapOfEdgeAttr.hasOwnProperty(`${edge.v}-${edge.w}`)) { Object.assign(edge, this.mapOfEdgeAttr[`${edge.v}-${edge.w}`]); } }); dig(node.nodes); } }); }; dig(renderInfo.nodes); // Assign data to edges of root graph renderInfo.edges.forEach(edge => { if (this.mapOfEdgeAttr.hasOwnProperty(`${edge.v}-${edge.w}`)) { Object.assign(edge, this.mapOfEdgeAttr[`${edge.v}-${edge.w}`]); } }); return renderInfo; } /** * Play with animation * * @private */ makeNodesAnimation() { return forkJoin(...this.listOfNodeComponent.map(node => node.makeAnimation())).pipe(finalize(() => { this.cdr.detectChanges(); })); } parseInfo(data) { data.nodes.forEach(n => { this.mapOfNodeAttr[n.id] = n; }); data.edges.forEach(e => { this.mapOfEdgeAttr[`${e.v}-${e.w}`] = e; }); } /** * Merge config with user inputs * * @param config * @private */ mergeConfig(config) { const graphMeta = (config === null || config === void 0 ? void 0 : config.layout) || {}; const subSceneMeta = (config === null || config === void 0 ? void 0 : config.subScene) || {}; const defaultNodeMeta = (config === null || config === void 0 ? void 0 : config.defaultNode) || {}; const defaultCompoundNodeMeta = (config === null || config === void 0 ? void 0 : config.defaultCompoundNode) || {}; const bridge = NZ_GRAPH_LAYOUT_SETTING.nodeSize.bridge; const graph = { meta: Object.assign(Object.assign({}, NZ_GRAPH_LAYOUT_SETTING.graph.meta), graphMeta) }; const subScene = { meta: Object.assign(Object.assign({}, NZ_GRAPH_LAYOUT_SETTING.subScene.meta), subSceneMeta) }; const nodeSize = { meta: Object.assign(Object.assign({}, NZ_GRAPH_LAYOUT_SETTING.nodeSize.meta), defaultCompoundNodeMeta), node: Object.assign(Object.assign({}, NZ_GRAPH_LAYOUT_SETTING.nodeSize.node), defaultNodeMeta), bridge }; return { graph, subScene, nodeSize }; } } NzGraphComponent.decorators = [ { type: Component, args: [{ changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, selector: 'nz-graph', exportAs: 'nzGraph', template: ` <ng-content></ng-content> <svg width="100%" height="100%"> <svg:defs nz-graph-defs></svg:defs> <svg:g [attr.transform]="transformStyle"> <ng-container [ngTemplateOutlet]="groupTemplate" [ngTemplateOutletContext]="{ renderNode: renderInfo, type: 'root' }" ></ng-container> </svg:g> </svg> <ng-template #groupTemplate let-renderNode="renderNode" let-type="type"> <svg:g [attr.transform]="type === 'sub' ? subGraphTransform(renderNode) : null"> <svg:g class="core" [attr.transform]="coreTransform(renderNode)"> <svg:g class="nz-graph-edges"> <ng-container *ngFor="let edge of $asNzGraphEdges(renderNode.edges); trackBy: edgeTrackByFun"> <g class="nz-graph-edge" nz-graph-edge [edge]="edge" [edgeType]="nzGraphLayoutConfig?.defaultEdge?.type" [customTemplate]="customGraphEdgeTemplate" ></g> </ng-container> </svg:g> <svg:g class="nz-graph-nodes"> <ng-container *ngFor="let node of typedNodes(renderNode.nodes); trackBy: nodeTrackByFun"> <g *ngIf="node.type === 1" class="nz-graph-node" nz-graph-node [node]="node" [customTemplate]="nodeTemplate" (nodeClick)="clickNode($event)" ></g> <g *ngIf="node.type === 0" class="nz-graph-node" nz-graph-node [node]="node" [customTemplate]="groupNodeTemplate" (nodeClick)="clickNode($event)" ></g> <ng-container *ngIf="node.expanded" [ngTemplateOutlet]="groupTemplate" [ngTemplateOutletContext]="{ renderNode: node, type: 'sub' }" ></ng-container> </ng-container> </svg:g> </svg:g> </svg:g> </ng-template> `, host: { '[class.nz-graph]': 'true', '[class.nz-graph-auto-size]': 'nzAutoSize' } },] } ]; NzGraphComponent.ctorParameters = () => [ { type: ChangeDetectorRef }, { type: ElementRef }, { type: NzNoAnimationDirective, decorators: [{ type: Host }, { type: Optional }] }, { type: NzGraphZoomDirective, decorators: [{ type: Optional }] } ]; NzGraphComponent.propDecorators = { listOfNodeElement: [{ type: ViewChildren, args: [NzGraphNodeComponent, { read: ElementRef },] }], listOfNodeComponent: [{ type: ViewChildren, args: [NzGraphNodeComponent,] }], nodeTemplate: [{ type: ContentChild, args: [NzGraphNodeDirective, { static: true, read: TemplateRef },] }], groupNodeTemplate: [{ type: ContentChild, args: [NzGraphGroupNodeDirective, { static: true, read: TemplateRef },] }], customGraphEdgeTemplate: [{ type: ContentChild, args: [NzGraphEdgeDirective, { static: true, read: TemplateRef },] }], nzGraphData: [{ type: Input }], nzRankDirection: [{ type: Input }], nzGraphLayoutConfig: [{ type: Input }], nzAutoSize: [{ type: Input }], nzGraphInitialized: [{ type: Output }], nzGraphRendered: [{ type: Output }], nzNodeClick: [{ type: Output }] }; __decorate([ InputBoolean() ], NzGraphComponent.prototype, "nzAutoSize", void 0); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JhcGguY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vY29tcG9uZW50cy9ncmFwaC9ncmFwaC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHOztBQUVILE9BQU8sRUFFTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLFlBQVksRUFDWixJQUFJLEVBQ0osS0FBSyxFQUlMLFFBQVEsRUFDUixNQUFNLEVBR04sV0FBVyxFQUNYLFlBQVksRUFDWixpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFFBQVEsRUFBYyxhQUFhLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUNsRixPQUFPLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFNUMsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDekUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFMUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXZELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUVsRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFP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Ozs7WUF6YUYsU0FBUyxTQUFDO2dCQUNULGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2dCQUMvQyxhQUFhLEVBQUUsaUJBQWlCLENBQUMsSUFBSTtnQkFDckMsUUFBUSxFQUFFLFVBQVU7Z0JBQ3BCLFFBQVEsRUFBRSxTQUFTO2dCQUNuQixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1RFQ7Z0JBQ0QsSUFBSSxFQUFFO29CQUNKLGtCQUFrQixFQUFFLE1BQU07b0JBQzFCLDRCQUE0QixFQUFFLFlBQVk7aUJBQzNDO2FBQ0Y7OztZQTNIQyxpQkFBaUI7WUFHakIsVUFBVTtZQW9CSCxzQkFBc0IsdUJBZ0sxQixJQUFJLFlBQUksUUFBUTtZQXJKWixvQkFBb0IsdUJBc0p4QixRQUFROzs7Z0NBekRWLFlBQVksU0FBQyxvQkFBb0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7a0NBQ3ZELFlBQVksU0FBQyxvQkFBb0I7MkJBRWpDLFlBQVksU0FBQyxvQkFBb0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRTtnQ0FHdEUsWUFBWSxTQUFDLHlCQUF5QixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFO3NDQUczRSxZQUFZLFNBQUMsb0JBQW9CLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7MEJBT3RFLEtBQUs7OEJBQ0wsS0FBSztrQ0FDTCxLQUFLO3lCQUNMLEtBQUs7aUNBRUwsTUFBTTs4QkFDTixNQUFNOzBCQUNOLE1BQU07O0FBSmtCO0lBQWYsWUFBWSxFQUFFO29EQUFvQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9naXRodWIuY29tL05HLVpPUlJPL25nLXpvcnJvLWFudGQvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICovXG5cbmltcG9ydCB7XG4gIEFmdGVyQ29udGVudENoZWNrZWQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDaGlsZHJlbixcbiAgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBmb3JrSm9pbiwgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaW5hbGl6ZSwgdGFrZSwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBidWlsZEdyYXBoIH0gZnJvbSAnZGFncmUtY29tcG91bmQnO1xuXG5pbXBvcnQgeyBOek5vQW5pbWF0aW9uRGlyZWN0aXZlIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL25vLWFuaW1hdGlvbic7XG5pbXBvcnQgeyBjYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvcG9seWZpbGwnO1xuaW1wb3J0IHsgQm9vbGVhbklucHV0LCBOelNhZmVBbnkgfSBmcm9tICduZy16b3Jyby1hbnRkL2NvcmUvdHlwZXMnO1xuaW1wb3J0IHsgSW5wdXRCb29sZWFuIH0gZnJvbSAnbmctem9ycm8tYW50ZC9jb3JlL3V0aWwnO1xuXG5pbXBvcnQgeyBjYWxjdWxhdGVUcmFuc2Zvcm0gfSBmcm9tICcuL2NvcmUvdXRpbHMnO1xuaW1wb3J0IHsgTnpHcmFwaERhdGEgfSBmcm9tICcuL2RhdGEtc291cmNlL2dyYXBoLWRhdGEtc291cmNlJztcbmltcG9ydCB7IE56R3JhcGhFZGdlRGlyZWN0aXZlIH0gZnJvbSAnLi9ncmFwaC1lZGdlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBOekdyYXBoR3JvdXBOb2RlRGlyZWN0aXZlIH0gZnJvbSAnLi9ncmFwaC1ncm91cC1ub2RlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBOekdyYXBoTm9kZUNvbXBvbmVudCB9IGZyb20gJy4vZ3JhcGgtbm9kZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgTnpHcmFwaE5vZGVEaXJlY3RpdmUgfSBmcm9tICcuL2dyYXBoLW5vZGUuZGlyZWN0aXZlJztcbmltcG9ydCB7IE56R3JhcGhab29tRGlyZWN0aXZlIH0gZnJvbSAnLi9ncmFwaC16b29tLmRpcmVjdGl2ZSc7XG5pbXBvcnQge1xuICBOekdyYXBoRGF0YURlZixcbiAgTnpHcmFwaEVkZ2UsXG4gIE56R3JhcGhFZGdlRGVmLFxuICBOekdyYXBoR3JvdXBOb2RlLFxuICBOekdyYXBoTGF5b3V0Q29uZmlnLFxuICBOekdyYXBoTm9kZSxcbiAgTnpHcmFwaE5vZGVEZWYsXG4gIE56R3JhcGhPcHRpb24sXG4gIE56TGF5b3V0U2V0dGluZyxcbiAgTnpSYW5rRGlyZWN0aW9uLFxuICBuelR5cGVEZWZpbml0aW9uLFxuICBOWl9HUkFQSF9MQVlPVVRfU0VUVElOR1xufSBmcm9tICcuL2ludGVyZmFjZSc7XG5cbi8qKiBDaGVja3Mgd2hldGhlciBhbiBvYmplY3QgaXMgYSBkYXRhIHNvdXJjZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RhdGFTb3VyY2UodmFsdWU6IE56U2FmZUFueSk6IHZhbHVlIGlzIE56R3JhcGhEYXRhIHtcbiAgLy8gQ2hlY2sgaWYgdGhlIHZhbHVlIGlzIGEgRGF0YVNvdXJjZSBieSBvYnNlcnZpbmcgaWYgaXQgaGFzIGEgY29ubmVjdCBmdW5jdGlvbi4gQ2Fubm90XG4gIC8vIGJlIGNoZWNrZWQgYXMgYW4gYGluc3RhbmNlb2YgRGF0YVNvdXJjZWAgc2luY2UgcGVvcGxlIGNvdWxkIGNyZWF0ZSB0aGVpciBvd24gc291cmNlc1xuICAvLyB0aGF0IG1hdGNoIHRoZSBpbnRlcmZhY2UsIGJ1dCBkb24ndCBleHRlbmQgRGF0YVNvdXJjZS5cbiAgcmV0dXJuIHZhbHVlICYmIHR5cGVvZiB2YWx1ZS5jb25uZWN0ID09PSAnZnVuY3Rpb24nO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHNlbGVjdG9yOiAnbnotZ3JhcGgnLFxuICBleHBvcnRBczogJ256R3JhcGgnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICA8c3ZnIHdpZHRoPVwiMTAwJVwiIGhlaWdodD1cIjEwMCVcIj5cbiAgICAgIDxzdmc6ZGVmcyBuei1ncmFwaC1kZWZzPjwvc3ZnOmRlZnM+XG4gICAgICA8c3ZnOmcgW2F0dHIudHJhbnNmb3JtXT1cInRyYW5zZm9ybVN0eWxlXCI+XG4gICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJncm91cFRlbXBsYXRlXCJcbiAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyByZW5kZXJOb2RlOiByZW5kZXJJbmZvLCB0eXBlOiAncm9vdCcgfVwiXG4gICAgICAgID48L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvc3ZnOmc+XG4gICAgPC9zdmc+XG5cbiAgICA8bmctdGVtcGxhdGUgI2dyb3VwVGVtcGxhdGUgbGV0LXJlbmRlck5vZGU9XCJyZW5kZXJOb2RlXCIgbGV0LXR5cGU9XCJ0eXBlXCI+XG4gICAgICA8c3ZnOmcgW2F0dHIudHJhbnNmb3JtXT1cInR5cGUgPT09ICdzdWInID8gc3ViR3JhcGhUcmFuc2Zvcm0ocmVuZGVyTm9kZSkgOiBudWxsXCI+XG4gICAgICAgIDxzdmc6ZyBjbGFzcz1cImNvcmVcIiBbYXR0ci50cmFuc2Zvcm1dPVwiY29yZVRyYW5zZm9ybShyZW5kZXJOb2RlKVwiPlxuICAgICAgICAgIDxzdmc6ZyBjbGFzcz1cIm56LWdyYXBoLWVkZ2VzXCI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBlZGdlIG9mICRhc056R3JhcGhFZGdlcyhyZW5kZXJOb2RlLmVkZ2VzKTsgdHJhY2tCeTogZWRnZVRyYWNrQnlGdW5cIj5cbiAgICAgICAgICAgICAgPGdcbiAgICAgICAgICAgICAgICBjbGFzcz1cIm56LWdyYXBoLWVkZ2VcIlxuICAgICAgICAgICAgICAgIG56LWdyYXBoLWVkZ2VcbiAgICAgICAgICAgICAgICBbZWRnZV09XCJlZGdlXCJcbiAgICAgICAgICAgICAgICBbZWRnZVR5cGVdPVwibnpHcmFwaExheW91dENvbmZpZz8uZGVmYXVsdEVkZ2U/LnR5cGVcIlxuICAgICAgICAgICAgICAgIFtjdXN0b21UZW1wbGF0ZV09XCJjdXN0b21HcmFwaEVkZ2VUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgID48L2c+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8L3N2ZzpnPlxuXG4gICAgICAgICAgPHN2ZzpnIGNsYXNzPVwibnotZ3JhcGgtbm9kZXNcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG5vZGUgb2YgdHlwZWROb2RlcyhyZW5kZXJOb2RlLm5vZGVzKTsgdHJhY2tCeTogbm9kZVRyYWNrQnlGdW5cIj5cbiAgICAgICAgICAgICAgPGdcbiAgICAgICAgICAgICAgICAqbmdJZj1cIm5vZGUudHlwZSA9PT0gMVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJuei1ncmFwaC1ub2RlXCJcbiAgICAgICAgICAgICAgICBuei1ncmFwaC1ub2RlXG4gICAgICAgICAgICAgICAgW25vZGVdPVwibm9kZVwiXG4gICAgICAgICAgICAgICAgW2N1c3RvbVRlbXBsYXRlXT1cIm5vZGVUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgKG5vZGVDbGljayk9XCJjbGlja05vZGUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgID48L2c+XG4gICAgICAgICAgICAgIDxnXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJub2RlLnR5cGUgPT09IDBcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwibnotZ3JhcGgtbm9kZVwiXG4gICAgICAgICAgICAgICAgbnotZ3JhcGgtbm9kZVxuICAgICAgICAgICAgICAgIFtub2RlXT1cIm5vZGVcIlxuICAgICAgICAgICAgICAgIFtjdXN0b21UZW1wbGF0ZV09XCJncm91cE5vZGVUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgKG5vZGVDbGljayk9XCJjbGlja05vZGUoJGV2ZW50KVwiXG4gICAgICAgICAgICAgID48L2c+XG4gICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAqbmdJZj1cIm5vZGUuZXhwYW5kZWRcIlxuICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImdyb3VwVGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHJlbmRlck5vZGU6IG5vZGUsIHR5cGU6ICdzdWInIH1cIlxuICAgICAgICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8L3N2ZzpnPlxuICAgICAgICA8L3N2ZzpnPlxuICAgICAgPC9zdmc6Zz5cbiAgICA8L25nLXRlbXBsYXRlPlxuICBgLFxuICBob3N0OiB7XG4gICAgJ1tjbGFzcy5uei1ncmFwaF0nOiAndHJ1ZScsXG4gICAgJ1tjbGFzcy5uei1ncmFwaC1hdXRvLXNpemVdJzogJ256QXV0b1NpemUnXG4gIH1cbn0pXG5leHBvcnQgY2xhc3MgTnpHcmFwaENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlckNvbnRlbnRDaGVja2VkLCBPbkRlc3Ryb3kge1xuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfbnpBdXRvU2l6ZTogQm9vbGVhbklucHV0O1xuXG4gIEBWaWV3Q2hpbGRyZW4oTnpHcmFwaE5vZGVDb21wb25lbnQsIHsgcmVhZDogRWxlbWVudFJlZiB9KSBsaXN0T2ZOb2RlRWxlbWVudCE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPjtcbiAgQFZpZXdDaGlsZHJlbihOekdyYXBoTm9kZUNvbXBvbmVudCkgbGlzdE9mTm9kZUNvbXBvbmVudCE6IFF1ZXJ5TGlzdDxOekdyYXBoTm9kZUNvbXBvbmVudD47XG5cbiAgQENvbnRlbnRDaGlsZChOekdyYXBoTm9kZURpcmVjdGl2ZSwgeyBzdGF0aWM6IHRydWUsIHJlYWQ6IFRlbXBsYXRlUmVmIH0pIG5vZGVUZW1wbGF0ZT86IFRlbXBsYXRlUmVmPHtcbiAgICAkaW1wbGljaXQ6IE56R3JhcGhOb2RlO1xuICB9PjtcbiAgQENvbnRlbnRDaGlsZChOekdyYXBoR3JvdXBOb2RlRGlyZWN0aXZlLCB7IHN0YXRpYzogdHJ1ZSwgcmVhZDogVGVtcGxhdGVSZWYgfSkgZ3JvdXBOb2RlVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjx7XG4gICAgJGltcGxpY2l0OiBOekdyYXBoR3JvdXBOb2RlO1xuICB9PjtcbiAgQENvbnRlbnRDaGlsZChOekdyYXBoRWRnZURpcmVjdGl2ZSwgeyBzdGF0aWM6IHRydWUsIHJlYWQ6IFRlbXBsYXRlUmVmIH0pIGN1c3RvbUdyYXBoRWRnZVRlbXBsYXRlPzogVGVtcGxhdGVSZWY8e1xuICAgICRpbXBsaWNpdDogTnpHcmFwaEVkZ2U7XG4gIH0+O1xuICAvKipcbiAgICogUHJvdmlkZXMgYSBzdHJlYW0gY29udGFpbmluZyB0aGUgbGF0ZXN0IGRhdGEgYXJyYXkgdG8gcmVuZGVyLlxuICAgKiBEYXRhIHNvdXJjZSBjYW4gYmUgYW4gb2JzZXJ2YWJsZSBvZiBOekdyYXBoRGF0YSwgb3IgYSBOekdyYXBoRGF0YSB0byByZW5kZXIuXG4gICAqL1xuICBASW5wdXQoKSBuekdyYXBoRGF0YSE6IE56R3JhcGhEYXRhO1xuICBASW5wdXQoKSBuelJhbmtEaXJlY3Rpb246IE56UmFua0RpcmVjdGlvbiA9ICdMUic7XG4gIEBJbnB1dCgpIG56R3JhcGhMYXlvdXRDb25maWc/OiBOekdyYXBoTGF5b3V0Q29uZmlnO1xuICBASW5wdXQoKSBASW5wdXRCb29sZWFuKCkgbnpBdXRvU2l6ZSA9IGZhbHNlO1xuXG4gIEBPdXRwdXQoKSByZWFkb25seSBuekdyYXBoSW5pdGlhbGl6ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPE56R3JhcGhDb21wb25lbnQ+KCk7XG4gIEBPdXRwdXQoKSByZWFkb25seSBuekdyYXBoUmVuZGVyZWQgPSBuZXcgRXZlbnRFbWl0dGVyPE56R3JhcGhDb21wb25lbnQ+KCk7XG4gIEBPdXRwdXQoKSByZWFkb25seSBuek5vZGVDbGljazogRXZlbnRFbWl0dGVyPE56R3JhcGhOb2RlIHwgTnpHcmFwaEdyb3VwTm9kZT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcmVxdWVzdElkOiBudW1iZXIgPSAtMTtcbiAgdHJhbnNmb3JtU3R5bGUgPSAnJztcbiAgZ3JhcGhSZW5kZXJlZFN1YmplY3QkID0gbmV3IFJlcGxheVN1YmplY3Q8dm9pZD4oMSk7XG4gIHJlbmRlckluZm86IE56R3JhcGhHcm91cE5vZGUgPSB7IGxhYmVsSGVpZ2h0OiAwIH0gYXMgTnpHcmFwaEdyb3VwTm9kZTtcbiAgbWFwT2ZOb2RlQXR0cjogeyBba2V5OiBzdHJpbmddOiBOekdyYXBoTm9kZURlZiB9ID0ge307XG4gIG1hcE9mRWRnZUF0dHI6IHsgW2tleTogc3RyaW5nXTogTnpHcmFwaEVkZ2VEZWYgfSA9IHt9O1xuICB6b29tID0gMTtcblxuICBwdWJsaWMgcmVhZG9ubHkgdHlwZWROb2RlcyA9IG56VHlwZURlZmluaXRpb248QXJyYXk8TnpHcmFwaE5vZGUgfCBOekdyYXBoR3JvdXBOb2RlPj4oKTtcbiAgcHJpdmF0ZSBkYXRhU291cmNlPzogTnpHcmFwaERhdGE7XG4gIHByaXZhdGUgbGF5b3V0U2V0dGluZzogTnpMYXlvdXRTZXR0aW5nID0gTlpfR1JBUEhfTEFZT1VUX1NFVFRJTkc7XG4gIC8qKiBEYXRhIHN1YnNjcmlwdGlvbiAqL1xuICBwcml2YXRlIF9kYXRhU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uIHwgbnVsbDtcbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgbm9kZVRyYWNrQnlGdW4gPSAoXzogbnVtYmVyLCBub2RlOiBOekdyYXBoTm9kZSB8IE56R3JhcGhHcm91cE5vZGUpID0+IG5vZGUubmFtZTtcbiAgZWRnZVRyYWNrQnlGdW4gPSAoXzogbnVtYmVyLCBlZGdlOiBOekdyYXBoRWRnZSkgPT4gYCR7ZWRnZS52fS0ke2VkZ2Uud31gO1xuXG4gIHN1YkdyYXBoVHJhbnNmb3JtID0gKG5vZGU6IE56R3JhcGhHcm91cE5vZGUpID0+IHtcbiAgICBjb25zdCB4ID0gbm9kZS54IC0gbm9kZS5jb3JlQm94LndpZHRoIC8gMi4wO1xuICAgIGNvbnN0IHkgPSBub2RlLnkgLSBub2RlLmhlaWdodCAvIDIuMCArIG5vZGUucGFkZGluZ1RvcDtcbiAgICByZXR1cm4gYHRyYW5zbGF0ZSgke3h9LCAke3l9KWA7XG4gIH07XG5cbiAgJGFzTnpHcmFwaEVkZ2VzID0gKGRhdGE6IHVua25vd24pID0+IGRhdGEgYXMgTnpHcmFwaEVkZ2VbXTtcblxuICBjb3JlVHJhbnNmb3JtID0gKG5vZGU6IE56R3JhcGhHcm91cE5vZGUpID0+IGB0cmFuc2xhdGUoMCwgJHtub2RlLnBhcmVudE5vZGVOYW1lID8gbm9kZS5sYWJlbEhlaWdodCA6IDB9KWA7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBASG9zdCgpIEBPcHRpb25hbCgpIHB1YmxpYyBub0FuaW1hdGlvbj86IE56Tm9BbmltYXRpb25EaXJlY3RpdmUsXG4gICAgQE9wdGlvbmFsKCkgcHVibGljIG56R3JhcGhab29tPzogTnpHcmFwaFpvb21EaXJlY3RpdmVcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZ3JhcGhSZW5kZXJlZFN1YmplY3QkLnBpcGUodGFrZSgxKSwgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgLy8gT25seSB6b29taW5nIGlzIG5vdCBzZXQsIG1vdmUgZ3JhcGggdG8gY2VudGVyXG4gICAgICBpZiAoIXRoaXMubnpHcmFwaFpvb20pIHtcbiAgICAgICAgdGhpcy5maXRDZW50ZXIoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubnpHcmFwaEluaXRpYWxpemVkLmVtaXQodGhpcyk7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgY29uc3QgeyBuekF1dG9GaXQsIG56UmFua0RpcmVjdGlvbiwgbnpHcmFwaERhdGEsIG56R3JhcGhMYXlvdXRDb25maWcgfSA9IGNoYW5nZXM7XG4gICAgaWYgKG56R3JhcGhMYXlvdXRDb25maWcpIHtcbiAgICAgIHRoaXMubGF5b3V0U2V0dGluZyA9IHRoaXMubWVyZ2VDb25maWcobnpHcmFwaExheW91dENvbmZpZy5jdXJyZW50VmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChuekdyYXBoRGF0YSkge1xuICAgICAgaWYgKHRoaXMuZGF0YVNvdXJjZSAhPT0gdGhpcy5uekdyYXBoRGF0YSkge1xuICAgICAgICB0aGlzLl9zd2l0Y2hEYXRhU291cmNlKHRoaXMubnpHcmFwaERhdGEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICgobnpBdXRvRml0ICYmICFuekF1dG9GaXQuZmlyc3RDaGFuZ2UpIHx8IChuelJhbmtEaXJlY3Rpb24gJiYgIW56UmFua0RpcmVjdGlvbi5maXJzdENoYW5nZSkpIHtcbiAgICAgIC8vIFJlbmRlciBncmFwaFxuICAgICAgaWYgKHRoaXMuZGF0YVNvdXJjZSEuZGF0YVNvdXJjZSkge1xuICAgICAgICB0aGlzLmRyYXdHcmFwaCh0aGlzLmRhdGFTb3VyY2UhLmRhdGFTb3VyY2UsIHtcbiAgICAgICAgICByYW5rRGlyZWN0aW9uOiB0aGlzLm56UmFua0RpcmVjdGlvbixcbiAgICAgICAgICBleHBhbmRlZDogdGhpcy5kYXRhU291cmNlIS5leHBhbnNpb25Nb2RlbC5zZWxlY3RlZCB8fCBbXVxuICAgICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudENoZWNrZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSAmJiAhdGhpcy5fZGF0YVN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5vYnNlcnZlUmVuZGVyQ2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcblxuICAgIGlmICh0aGlzLmRhdGFTb3VyY2UgJiYgdHlwZW9mIHRoaXMuZGF0YVNvdXJjZS5kaXNjb25uZWN0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzLmRhdGFTb3VyY2UuZGlzY29ubmVjdCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9kYXRhU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICB9XG4gICAgY2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMucmVxdWVzdElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbWl0IGV2ZW50XG4gICAqL1xuICBjbGlja05vZGUobm9kZTogTnpHcmFwaE5vZGUgfCBOekdyYXBoR3JvdXBOb2RlKTogdm9pZCB7XG4gICAgdGhpcy5uek5vZGVDbGljay5lbWl0KG5vZGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vdmUgZ3JhcGggdG8gY2VudGVyIGFuZCBzY2FsZSBhdXRvbWF0aWNhbGx5XG4gICAqL1xuICBmaXRDZW50ZXIoKTogdm9pZCB7XG4gICAgY29uc3QgeyB4LCB5LCBrIH0gPSBjYWxjdWxhdGVUcmFuc2Zvcm0oXG4gICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdzdmcnKSxcbiAgICAgIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N2ZyA+IGcnKVxuICAgICkhO1xuICAgIGlmIChrKSB7XG4gICAgICB0aGlzLnpvb20gPSBrO1xuICAgICAgdGhpcy50cmFuc2Zvcm1TdHlsZSA9IGB0cmFuc2xhdGUoJHt4fSwgJHt5fSlzY2FsZSgke2t9KWA7XG4gICAgfVxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyoqXG4gICAqIHJlLURyYXcgZ3JhcGhcbiAgICpcbiAgICogQHBhcmFtIGRhdGFcbiAgICogQHBhcmFtIG9wdGlvbnNcbiAgICogQHBhcmFtIG5lZWRSZXNpemVcbiAgICovXG4gIGRyYXdHcmFwaChkYXRhOiBOekdyYXBoRGF0YURlZiwgb3B0aW9uczogTnpHcmFwaE9wdGlvbiwgbmVlZFJlc2l6ZTogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5yZXF1ZXN0SWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICBjb25zdCByZW5kZXJJbmZvID0gdGhpcy5idWlsZEdyYXBoSW5mbyhkYXRhLCBvcHRpb25zKTtcbiAgICAgICAgLy8gVE9ET1xuICAgICAgICAvLyBOZWVkIGJldHRlciBwZXJmb3JtYW5jZVxuICAgICAgICB0aGlzLnJlbmRlckluZm8gPSByZW5kZXJJbmZvO1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgdGhpcy5yZXF1ZXN0SWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuZHJhd05vZGVzKCF0aGlzLm5vQW5pbWF0aW9uPy5uek5vQW5pbWF0aW9uKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBlbGVtZW50XG4gICAgICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICAgIGlmIChuZWVkUmVzaXplKSB7XG4gICAgICAgICAgICAgIHRoaXMucmVzaXplTm9kZVNpemUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhU291cmNlOiBOekdyYXBoRGF0YURlZiA9IHRoaXMuZGF0YVNvdXJjZSEuZGF0YVNvdXJjZSE7XG4gICAgICAgICAgICAgICAgdGhpcy5kcmF3R3JhcGgoZGF0YVNvdXJjZSwgb3B0aW9ucywgZmFsc2UpLnRoZW4oKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLmdyYXBoUmVuZGVyZWRTdWJqZWN0JC5uZXh0KCk7XG4gICAgICAgICAgICAgIHRoaXMubnpHcmFwaFJlbmRlcmVkLmVtaXQodGhpcyk7XG4gICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZHJhdyBhbGwgbm9kZXNcbiAgICpcbiAgICogQHBhcmFtIGFuaW1hdGVcbiAgICovXG4gIGRyYXdOb2RlcyhhbmltYXRlOiBib29sZWFuID0gdHJ1ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIGlmIChhbmltYXRlKSB7XG4gICAgICAgIHRoaXMubWFrZU5vZGVzQW5pbWF0aW9uKCkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5saXN0T2ZOb2RlQ29tcG9uZW50Lm1hcChub2RlID0+IHtcbiAgICAgICAgICBub2RlLm1ha2VOb0FuaW1hdGlvbigpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNpemVOb2RlU2l6ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBjb25zdCBkYXRhU291cmNlOiBOekdyYXBoRGF0YURlZiA9IHRoaXMuZGF0YVNvdXJjZSEuZGF0YVNvdXJjZSE7XG4gICAgICBsZXQgc2NhbGUgPSB0aGlzLm56R3JhcGhab29tPy5uelpvb20gfHwgdGhpcy56b29tIHx8IDE7XG4gICAgICB0aGlzLmxpc3RPZk5vZGVFbGVtZW50LmZvckVhY2gobm9kZUVsZSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnRFbGUgPSBub2RlRWxlLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIGlmIChjb250ZW50RWxlKSB7XG4gICAgICAgICAgbGV0IHdpZHRoOiBudW1iZXI7XG4gICAgICAgICAgbGV0IGhlaWdodDogbnVtYmVyO1xuICAgICAgICAgIC8vIENoZWNrIGlmIGZvcmVpZ25PYmplY3QgaXMgc2V0XG4gICAgICAgICAgY29uc3QgY2xpZW50UmVjdCA9IGNvbnRlbnRFbGUucXVlcnlTZWxlY3RvcignZm9yZWlnbk9iamVjdCA+IDpmaXJzdC1jaGlsZCcpPy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICBpZiAoY2xpZW50UmVjdCkge1xuICAgICAgICAgICAgd2lkdGggPSBjbGllbnRSZWN0LndpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0ID0gY2xpZW50UmVjdC5oZWlnaHQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGJCb3hSZWN0ID0gY29udGVudEVsZS5nZXRCQm94KCk7XG4gICAgICAgICAgICB3aWR0aCA9IGJCb3hSZWN0LndpZHRoO1xuICAgICAgICAgICAgaGVpZ2h0ID0gYkJveFJlY3QuaGVpZ2h0O1xuICAgICAgICAgICAgLy8gZ2V0QkJveCB3aWxsIHJldHVybiBhY3R1YWwgdmFsdWVcbiAgICAgICAgICAgIHNjYWxlID0gMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gRWxlbWVudCBpZCB0eXBlIGlzIHN0cmluZ1xuICAgICAgICAgIGNvbnN0IG5vZGUgPSBkYXRhU291cmNlLm5vZGVzLmZpbmQobiA9PiBgJHtuLmlkfWAgPT09IG5vZGVFbGUubmF0aXZlRWxlbWVudC5pZCk7XG4gICAgICAgICAgaWYgKG5vZGUgJiYgd2lkdGggJiYgaGVpZ2h0KSB7XG4gICAgICAgICAgICBub2RlLmhlaWdodCA9IGhlaWdodCAvIHNjYWxlO1xuICAgICAgICAgICAgbm9kZS53aWR0aCA9IHdpZHRoIC8gc2NhbGU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTd2l0Y2ggdG8gdGhlIHByb3ZpZGVkIGRhdGEgc291cmNlIGJ5IHJlc2V0dGluZyB0aGUgZGF0YSBhbmQgdW5zdWJzY3JpYmluZyBmcm9tIHRoZSBjdXJyZW50XG4gICAqIHJlbmRlciBjaGFuZ2Ugc3Vic2NyaXB0aW9uIGlmIG9uZSBleGlzdHMuIElmIHRoZSBkYXRhIHNvdXJjZSBpcyBudWxsLCBpbnRlcnByZXQgdGhpcyBieVxuICAgKiBjbGVhcmluZyB0aGUgbm9kZSBvdXRsZXQuIE90aGVyd2lzZSBzdGFydCBsaXN0ZW5pbmcgZm9yIG5ldyBkYXRhLlxuICAgKi9cbiAgcHJpdmF0ZSBfc3dpdGNoRGF0YVNvdXJjZShkYXRhU291cmNlOiBOekdyYXBoRGF0YSk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRhdGFTb3VyY2UgJiYgdHlwZW9mIHRoaXMuZGF0YVNvdXJjZS5kaXNjb25uZWN0ID09PSAnZnVuY3Rpb24nKSB7XG4gICA