UNPKG

ng-d3-graphs

Version:

<img src="./assets/ng-d3.png" alt="drawing" width="250" height="250"/>

189 lines 26.4 kB
import * as tslib_1 from "tslib"; import { ChangeDetectionStrategy, Component, ElementRef, HostListener, Input, OnInit, ViewEncapsulation, } from '@angular/core'; import * as d3 from 'd3'; import { Subject } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import { axisConfig } from '../shared/config/axis.config'; import { D3Service } from '../shared/services/d3.service'; let BarComponent = class BarComponent { constructor(container, d3Service) { this.container = container; this.d3Service = d3Service; this.data = []; this.labels = []; this.options = {}; this.graph = { xAxis: [], yAxis: [], xAxisPath: '', yAxisPath: '', rectanglesData: [], }; this.labelsAndData = []; this.parseTime = d3.timeParse('%d-%b-%y'); this._options = { width: 879, height: 804, margin: { top: 50, right: 50, bottom: 50, left: 50 }, gridTicks: 0, }; this.viewBox = {}; this.onResize$ = new Subject(); } onResize() { this.onResize$.next(); } ngOnInit() { this.options = Object.assign({}, this._options, this.options); this.viewBox = { minX: -this.options.margin.left, minY: -10, width: this.options.width + this.options.margin.left + this.options.margin.right, height: this.options.height + this.options.margin.top, }; this.labelsAndData = this.combineLabelsDataToOne(); this.onResizeEvent(); this.render(); } render() { const currentWidth = parseInt(d3.select(this.container.nativeElement).select('div').style('width'), 10); const currentHeight = parseInt(d3.select(this.container.nativeElement).select('div').style('height'), 10); const width = this.options.width - this.options.margin.left - this.options.margin.right; const height = this.options.height - this.options.margin.top - this.options.margin.bottom; this.viewBox = { minX: -this.options.margin.left, minY: -10, width: this.options.width, height: this.options.height - this.options.margin.top, }; const svg = d3.select(this.container.nativeElement) .select('div') .append('svg') .attr('width', currentWidth) .attr('height', currentHeight) .attr('viewBox', `${this.viewBox.minX} ${this.viewBox.minY} ${this.viewBox.width} ${this.viewBox.height}`) .classed('svg-content', true) .append('g'); const x = d3.scaleBand().rangeRound([0, width]).padding(0.1).domain(this.labels); const y = d3.scaleLinear().rangeRound([height, 0]).domain([ 0, Math.max(...this.data.map((d) => Number(d))) ]); const xAxis = (g) => g.call(d3.axisBottom(x)) .attr('transform', 'translate(0,' + height + ')'); const yAxis = (g) => g.call(d3.axisLeft(y)); // add the X gridlines svg.append('g') .attr('class', 'grid') .call(this.make_x_gridlines(x).tickSize(height) // .tickFormat('') ); // add the Y gridlines svg.append('g') .attr('class', 'grid') .call(this.make_y_gridlines(y).tickSize(-width) // .tickFormat('') ); svg.selectAll('.bar') .data(this.labelsAndData) .enter() .append('rect') .attr('class', 'bar') .attr('x', (d) => { return x(d.x); }) .attr('y', (d) => { return y(Number(d.y)); }) .attr('width', x.bandwidth()) .attr('height', (d) => { return height - y(Number(d.y)); }); const _xAxis = svg.append('g').call(xAxis); // text label for the x axis this.addLabelAxisX(svg, width, height); const _yAxis = svg.append('g').call(yAxis); // text label for the y axis this.addLabelAxisY(svg, height); this.removeAxisTicks(_xAxis); this.removeAxisTicks(_yAxis); this.changeAxisColor(_xAxis, axisConfig); this.changeAxisColor(_yAxis, axisConfig); } changeAxisColor(axis, config) { this.d3Service.changeAxisColor(axis, config); } removeAxisTicks(axis) { this.d3Service.removeAxisTicks(axis); } addLabelAxisY(svg, height) { svg.append('text') .attr('transform', 'rotate(0)') .attr('y', 0 - this.options.margin.top / 2) .attr('x', 0) .attr('dy', '1em') .style('text-anchor', 'start') .text(this.options.yAxisLabel); } addLabelAxisX(svg, width, height) { svg.append('text') .attr('transform', 'translate(' + width / 2 + ' ,' + (height + this.options.margin.top - 15) + ')') .style('text-anchor', 'middle') .text(this.options.xAxisLabel); } combineLabelsDataToOne() { const result = []; const N = this.data.length; for (let index = 0; index < N; index++) { result.push({ x: this.labels[index], y: this.data[index] }); } return result; } // gridlines in x axis function make_x_gridlines(x) { return d3.axisBottom(x).ticks(this.options.gridTicks); } // gridlines in y axis function make_y_gridlines(y) { return d3.axisLeft(y).ticks(this.options.gridTicks); } onResizeEvent() { this.onResize$.pipe(debounceTime(200)).subscribe(() => { const svgExist = d3.select(this.container.nativeElement).select('svg'); if (svgExist) { svgExist.remove(); } this.render(); }); } }; BarComponent.ctorParameters = () => [ { type: ElementRef }, { type: D3Service } ]; tslib_1.__decorate([ Input() ], BarComponent.prototype, "data", void 0); tslib_1.__decorate([ Input() ], BarComponent.prototype, "labels", void 0); tslib_1.__decorate([ Input() ], BarComponent.prototype, "options", void 0); tslib_1.__decorate([ HostListener('window:resize') ], BarComponent.prototype, "onResize", null); BarComponent = tslib_1.__decorate([ Component({ selector: 'ng-bar', template: "\n<div class=\"svg-container\"></div>\n", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".svg-container{display:inline-block;position:relative;width:100%;height:100%;padding-bottom:100%;vertical-align:top;overflow:hidden}.svg-content{display:inline-block;position:absolute;top:0;left:0}.grid line{stroke:#d3d3d3;stroke-opacity:.4;shape-rendering:crispEdges}.grid path{stroke-width:0}.grid text{display:none}.bar{fill:#4682b4}.bar:hover{fill:brown}"] }) ], BarComponent); export { BarComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLWQzLWdyYXBocy8iLCJzb3VyY2VzIjpbImJhci9iYXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxpQkFBaUIsR0FBRSxNQUFNLGVBQWUsQ0FBQztBQUM5SCxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFJeEQsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBNkN4RCxJQUFhLFlBQVksR0FBekIsTUFBYSxZQUFZO0lBNkJ2QixZQUNZLFNBQXFCLEVBQ3JCLFNBQW9CO1FBRHBCLGNBQVMsR0FBVCxTQUFTLENBQVk7UUFDckIsY0FBUyxHQUFULFNBQVMsQ0FBVztRQTlCdkIsU0FBSSxHQUFjLEVBQUUsQ0FBQztRQUNyQixXQUFNLEdBQVUsRUFBRSxDQUFDO1FBQ25CLFlBQU8sR0FBZ0IsRUFBZ0IsQ0FBQztRQUNqRCxVQUFLLEdBQVU7WUFDYixLQUFLLEVBQUUsRUFBRTtZQUNULEtBQUssRUFBRSxFQUFFO1lBQ1QsU0FBUyxFQUFFLEVBQUU7WUFDYixTQUFTLEVBQUUsRUFBRTtZQUNiLGNBQWMsRUFBRSxFQUFFO1NBQ25CLENBQUM7UUFDRixrQkFBYSxHQUFvQixFQUFFLENBQUM7UUFDcEMsY0FBUyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFN0IsYUFBUSxHQUFlO1lBQzdCLEtBQUssRUFBRSxHQUFHO1lBQ1YsTUFBTSxFQUFFLEdBQUc7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LElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELCtCQUErQjtJQUN2QixnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3hCLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQsYUFBYTtRQUNYLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDcEQsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2RSxJQUFJLFFBQVEsRUFBRTtnQkFDWixRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7YUFDbkI7WUFDRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0YsQ0FBQTs7WUFuTHdCLFVBQVU7WUFDVixTQUFTOztBQTlCdkI7SUFBUixLQUFLLEVBQUU7MENBQXNCO0FBQ3JCO0lBQVIsS0FBSyxFQUFFOzRDQUFvQjtBQUNuQjtJQUFSLEtBQUssRUFBRTs2Q0FBeUM7QUFzQmpEO0lBREMsWUFBWSxDQUFDLGVBQWUsQ0FBQzs0Q0FHN0I7QUEzQlUsWUFBWTtJQVB4QixTQUFTLENBQUM7UUFDVCxRQUFRLEVBQUUsUUFBUTtRQUNsQixtREFBbUM7UUFFbkMsYUFBYSxFQUFFLGlCQUFpQixDQUFDLElBQUk7UUFDckMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07O0tBQ2hELENBQUM7R0FDVyxZQUFZLENBaU54QjtTQWpOWSxZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIFZpZXdFbmNhcHN1bGF0aW9uLH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBkMyBmcm9tICdkMyc7XG5pbXBvcnQge1N1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtkZWJvdW5jZVRpbWV9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHtheGlzQ29uZmlnfSBmcm9tICcuLi9zaGFyZWQvY29uZmlnL2F4aXMuY29uZmlnJztcbmltcG9ydCB7QXhpc30gZnJvbSAnLi4vc2hhcmVkL21vZGVscy9heGlzLmludGVyZmFjZSc7XG5pbXBvcnQge0dyYXBoT3B0aW9uc30gZnJvbSAnLi4vc2hhcmVkL21vZGVscy9ncmFwaC1vcHRpb25zLmludGVyZmFjZSc7XG5pbXBvcnQge1ZpZXdCb3h9IGZyb20gJy4uL3NoYXJlZC9tb2RlbHMvdmlld2JveC5pbnRlcmZhY2UnO1xuaW1wb3J0IHtEM1NlcnZpY2V9IGZyb20gJy4uL3NoYXJlZC9zZXJ2aWNlcy9kMy5zZXJ2aWNlJztcblxuaW1wb3J0IHtCYXJTZXJ2aWNlfSBmcm9tICcuL2Jhci5zZXJ2aWNlJztcblxuZXhwb3J0IGludGVyZmFjZSBCYXIge1xuICBsYWJlbHM6IGFueVtdO1xuICBkYXRhOiBhbnlbXTtcbiAgb3B0aW9ucz86IGFueTtcbn1cblxuaW50ZXJmYWNlIEJhckRhdGEge1xuICBsYWJlbDogc3RyaW5nO1xuICB2YWx1ZXM6IGFueVtdO1xufVxuZXhwb3J0IGludGVyZmFjZSBCYXJEMyB7XG4gIHhBeGlzOiBBeGlzW107XG4gIHlBeGlzOiBBeGlzW107XG4gIHhBeGlzUGF0aDogc3RyaW5nO1xuICB5QXhpc1BhdGg6IHN0cmluZztcbiAgcmVjdGFuZ2xlc0RhdGE6IFJlY3RhbmdsZVtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY3RhbmdsZSB7XG4gIHg6IG51bWJlcjtcbiAgeTogbnVtYmVyO1xuICBoZWlnaHQ6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIExhYmVsc0FuZERhdGEge1xuICB4OiBhbnk7XG4gIHk6IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCYXJPcHRpb25zIGV4dGVuZHMgR3JhcGhPcHRpb25zIHtcbiAgZ3JpZFRpY2tzPzogbnVtYmVyO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZy1iYXInLFxuICB0ZW1wbGF0ZVVybDogJy4vYmFyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vYmFyLmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBCYXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSBkYXRhOiBCYXJEYXRhW10gPSBbXTtcbiAgQElucHV0KCkgbGFiZWxzOiBhbnlbXSA9IFtdO1xuICBASW5wdXQoKSBvcHRpb25zPzogQmFyT3B0aW9ucyA9IHt9IGFzIEJhck9wdGlvbnM7XG4gIGdyYXBoOiBCYXJEMyA9IHtcbiAgICB4QXhpczogW10sXG4gICAgeUF4aXM6IFtdLFxuICAgIHhBeGlzUGF0aDogJycsXG4gICAgeUF4aXNQYXRoOiAnJyxcbiAgICByZWN0YW5nbGVzRGF0YTogW10sXG4gIH07XG4gIGxhYmVsc0FuZERhdGE6IExhYmVsc0FuZERhdGFbXSA9IFtdO1xuICBwYXJzZVRpbWUgPSBkMy50aW1lUGFyc2UoJyVkLSViLSV5Jyk7XG5cbiAgcHJpdmF0ZSBfb3B0aW9uczogQmFyT3B0aW9ucyA9IHtcbiAgICB3aWR0aDogODc5LFxuICAgIGhlaWdodDogODA0LFxuICAgIG1hcmdpbjoge3RvcDogNTAsIHJpZ2h0OiA1MCwgYm90dG9tOiA1MCwgbGVmdDogNTB9LFxuICAgIGdyaWRUaWNrczogMCxcbiAgfTtcblxuICB2aWV3Qm94OiBWaWV3Qm94ID0ge30gYXMgVmlld0JveDtcblxuICBvblJlc2l6ZSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJylcbiAgb25SZXNpemUoKTogdm9pZCB7XG4gICAgdGhpcy5vblJlc2l6ZSQubmV4dCgpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBwcml2YXRlIGNvbnRhaW5lcjogRWxlbWVudFJlZixcbiAgICAgIHByaXZhdGUgZDNTZXJ2aWNlOiBEM1NlcnZpY2UsXG4gICkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB7Li4udGhpcy5fb3B0aW9ucywgLi4udGhpcy5vcHRpb25zfTtcbiAgICB0aGlzLnZpZXdCb3ggPSB7XG4gICAgICBtaW5YOiAtdGhpcy5vcHRpb25zLm1hcmdpbi5sZWZ0LFxuICAgICAgbWluWTogLTEwLFxuICAgICAgd2lkdGg6IHRoaXMub3B0aW9ucy53aWR0aCArIHRoaXMub3B0aW9ucy5tYXJnaW4ubGVmdCArXG4gICAgICAgICAgdGhpcy5vcHRpb25zLm1hcmdpbi5yaWdodCxcbiAgICAgIGhlaWdodDogdGhpcy5vcHRpb25zLmhlaWdodCArIHRoaXMub3B0aW9ucy5tYXJnaW4udG9wLFxuICAgIH07XG4gICAgdGhpcy5sYWJlbHNBbmREYXRhID0gdGhpcy5jb21iaW5lTGFiZWxzRGF0YVRvT25lKCk7XG5cbiAgICB0aGlzLm9uUmVzaXplRXZlbnQoKTtcblxuICAgIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlcigpIHtcbiAgICBjb25zdCBjdXJyZW50V2lkdGggPSBwYXJzZUludChcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQpLnNlbGVjdCgnZGl2Jykuc3R5bGUoJ3dpZHRoJyksXG4gICAgICAgIDEwKTtcbiAgICBjb25zdCBjdXJyZW50SGVpZ2h0ID0gcGFyc2VJbnQoXG4gICAgICAgIGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KS5zZWxlY3QoJ2RpdicpLnN0eWxlKCdoZWlnaHQnKSxcbiAgICAgICAgMTApO1xuXG4gICAgY29uc3Qgd2lkdGggPSB0aGlzLm9wdGlvbnMud2lkdGggLSB0aGlzLm9wdGlvbnMubWFyZ2luLmxlZnQgLVxuICAgICAgICB0aGlzLm9wdGlvbnMubWFyZ2luLnJpZ2h0O1xuICAgIGNvbnN0IGhlaWdodCA9IHRoaXMub3B0aW9ucy5oZWlnaHQgLSB0aGlzLm9wdGlvbnMubWFyZ2luLnRvcCAtXG4gICAgICAgIHRoaXMub3B0aW9ucy5tYXJnaW4uYm90dG9tO1xuICAgIHRoaXMudmlld0JveCA9IHtcbiAgICAgIG1pblg6IC10aGlzLm9wdGlvbnMubWFyZ2luLmxlZnQsXG4gICAgICBtaW5ZOiAtMTAsXG4gICAgICB3aWR0aDogdGhpcy5vcHRpb25zLndpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLm9wdGlvbnMuaGVpZ2h0IC0gdGhpcy5vcHRpb25zLm1hcmdpbi50b3AsXG4gICAgfTtcblxuICAgIGNvbnN0IHN2ZyA9IGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICAuc2VsZWN0KCdkaXYnKVxuICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCdzdmcnKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cignd2lkdGgnLCBjdXJyZW50V2lkdGgpXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBjdXJyZW50SGVpZ2h0KVxuXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3ZpZXdCb3gnLFxuICAgICAgICAgICAgICAgICAgICAgICAgYCR7dGhpcy52aWV3Qm94Lm1pblh9ICR7dGhpcy52aWV3Qm94Lm1pbll9ICR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3Qm94LndpZHRofSAke3RoaXMudmlld0JveC5oZWlnaHR9YClcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3N2Zy1jb250ZW50JywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgnZycpO1xuXG4gICAgY29uc3QgeCA9XG4gICAgICAgIGQzLnNjYWxlQmFuZCgpLnJhbmdlUm91bmQoWzAsIHdpZHRoXSkucGFkZGluZygwLjEpLmRvbWFpbih0aGlzLmxhYmVscyk7XG5cbiAgICBjb25zdCB5ID0gZDMuc2NhbGVMaW5lYXIoKS5yYW5nZVJvdW5kKFtoZWlnaHQsIDBdKS5kb21haW4oW1xuICAgICAgMCwgTWF0aC5tYXgoLi4udGhpcy5kYXRhLm1hcCgoZCkgPT4gTnVtYmVyKGQpKSlcbiAgICBdKTtcblxuICAgIGNvbnN0IHhBeGlzID0gKGcpID0+IGcuY2FsbChkMy5heGlzQm90dG9tKHgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcgKyBoZWlnaHQgKyAnKScpO1xuXG4gICAgY29uc3QgeUF4aXMgPSAoZykgPT4gZy5jYWxsKGQzLmF4aXNMZWZ0KHkpKTtcblxuICAgIC8vIGFkZCB0aGUgWCBncmlkbGluZXNcbiAgICBzdmcuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dyaWQnKVxuICAgICAgICAuY2FsbChcbiAgICAgICAgICAgIHRoaXMubWFrZV94X2dyaWRsaW5lcyh4KS50aWNrU2l6ZShoZWlnaHQpXG4gICAgICAgICAgICAvLyAudGlja0Zvcm1hdCgnJylcbiAgICAgICAgKTtcblxuICAgIC8vIGFkZCB0aGUgWSBncmlkbGluZXNcbiAgICBzdmcuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dyaWQnKVxuICAgICAgICAuY2FsbChcbiAgICAgICAgICAgIHRoaXMubWFrZV95X2dyaWRsaW5lcyh5KS50aWNrU2l6ZSgtd2lkdGgpXG4gICAgICAgICAgICAvLyAudGlja0Zvcm1hdCgnJylcbiAgICAgICAgKTtcblxuICAgIHN2Zy5zZWxlY3RBbGwoJy5iYXInKVxuICAgICAgICAuZGF0YSh0aGlzLmxhYmVsc0FuZERhdGEpXG4gICAgICAgIC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnYmFyJylcbiAgICAgICAgLmF0dHIoXG4gICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAoZCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4geChkLngpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoXG4gICAgICAgICAgICAneScsXG4gICAgICAgICAgICAoZCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4geShOdW1iZXIoZC55KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAuYXR0cignd2lkdGgnLCB4LmJhbmR3aWR0aCgpKVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgKGQpID0+IHtcbiAgICAgICAgICByZXR1cm4gaGVpZ2h0IC0geShOdW1iZXIoZC55KSk7XG4gICAgICAgIH0pO1xuXG4gICAgY29uc3QgX3hBeGlzID0gc3ZnLmFwcGVuZCgnZycpLmNhbGwoeEF4aXMpO1xuXG4gICAgLy8gdGV4dCBsYWJlbCBmb3IgdGhlIHggYXhpc1xuICAgIHRoaXMuYWRkTGFiZWxBeGlzWChzdmcsIHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgY29uc3QgX3lBeGlzID0gc3ZnLmFwcGVuZCgnZycpLmNhbGwoeUF4aXMpO1xuXG4gICAgLy8gdGV4dCBsYWJlbCBmb3IgdGhlIHkgYXhpc1xuICAgIHRoaXMuYWRkTGFiZWxBeGlzWShzdmcsIGhlaWdodCk7XG5cbiAgICB0aGlzLnJlbW92ZUF4aXNUaWNrcyhfeEF4aXMpO1xuICAgIHRoaXMucmVtb3ZlQXhpc1RpY2tzKF95QXhpcyk7XG5cbiAgICB0aGlzLmNoYW5nZUF4aXNDb2xvcihfeEF4aXMsIGF4aXNDb25maWcpO1xuICAgIHRoaXMuY2hhbmdlQXhpc0NvbG9yKF95QXhpcywgYXhpc0NvbmZpZyk7XG4gIH1cblxuICBwcml2YXRlIGNoYW5nZUF4aXNDb2xvcihcbiAgICAgIGF4aXM6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgbnVsbCwgdW5kZWZpbmVkPiwgY29uZmlnOiBhbnkpIHtcbiAgICB0aGlzLmQzU2VydmljZS5jaGFuZ2VBeGlzQ29sb3IoYXhpcywgY29uZmlnKTtcbiAgfVxuXG5cbiAgcHJpdmF0ZSByZW1vdmVBeGlzVGlja3MoXG4gICAgICBheGlzOiBkMy5TZWxlY3Rpb248U1ZHR0VsZW1lbnQsIHVua25vd24sIG51bGwsIHVuZGVmaW5lZD4pIHtcbiAgICB0aGlzLmQzU2VydmljZS5yZW1vdmVBeGlzVGlja3MoYXhpcyk7XG4gIH1cblxuICBwcml2YXRlIGFkZExhYmVsQXhpc1koXG4gICAgICBzdmc6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgbnVsbCwgdW5kZWZpbmVkPixcbiAgICAgIGhlaWdodDogbnVtYmVyKSB7XG4gICAgc3ZnLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAncm90YXRlKDApJylcbiAgICAgICAgLmF0dHIoJ3knLCAwIC0gdGhpcy5vcHRpb25zLm1hcmdpbi50b3AgLyAyKVxuICAgICAgICAuYXR0cigneCcsIDApXG4gICAgICAgIC5hdHRyKCdkeScsICcxZW0nKVxuICAgICAgICAuc3R5bGUoJ3RleHQtYW5jaG9yJywgJ3N0YXJ0JylcbiAgICAgICAgLnRleHQodGhpcy5vcHRpb25zLnlBeGlzTGFiZWwpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRMYWJlbEF4aXNYKFxuICAgICAgc3ZnOiBkMy5TZWxlY3Rpb248U1ZHR0VsZW1lbnQsIHVua25vd24sIG51bGwsIHVuZGVmaW5lZD4sIHdpZHRoOiBudW1iZXIsXG4gICAgICBoZWlnaHQ6IG51bWJlcikge1xuICAgIHN2Zy5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuYXR0cihcbiAgICAgICAgICAgICd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgd2lkdGggLyAyICsgJyAsJyArXG4gICAgICAgICAgICAgICAgKGhlaWdodCArIHRoaXMub3B0aW9ucy5tYXJnaW4udG9wIC0gMTUpICsgJyknKVxuICAgICAgICAuc3R5bGUoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgIC50ZXh0KHRoaXMub3B0aW9ucy54QXhpc0xhYmVsKTtcbiAgfVxuXG4gIHByaXZhdGUgY29tYmluZUxhYmVsc0RhdGFUb09uZSgpOiBMYWJlbHNBbmREYXRhW10ge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IE4gPSB0aGlzLmRhdGEubGVuZ3RoO1xuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBOOyBpbmRleCsrKSB7XG4gICAgICByZXN1bHQucHVzaCh7eDogdGhpcy5sYWJlbHNbaW5kZXhdLCB5OiB0aGlzLmRhdGFbaW5kZXhdfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgLy8gZ3JpZGxpbmVzIGluIHggYXhpcyBmdW5jdGlvblxuICBwcml2YXRlIG1ha2VfeF9ncmlkbGluZXMoeCkge1xuICAgIHJldHVybiBkMy5heGlzQm90dG9tKHgpLnRpY2tzKHRoaXMub3B0aW9ucy5ncmlkVGlja3MpO1xuICB9XG5cbiAgLy8gZ3JpZGxpbmVzIGluIHkgYXhpcyBmdW5jdGlvblxuICBwcml2YXRlIG1ha2VfeV9ncmlkbGluZXMoeSkge1xuICAgIHJldHVybiBkMy5heGlzTGVmdCh5KS50aWNrcyh0aGlzLm9wdGlvbnMuZ3JpZFRpY2tzKTtcbiAgfVxuXG4gIG9uUmVzaXplRXZlbnQoKTogdm9pZCB7XG4gICAgdGhpcy5vblJlc2l6ZSQucGlwZShkZWJvdW5jZVRpbWUoMjAwKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGNvbnN0IHN2Z0V4aXN0ID0gZDMuc2VsZWN0KHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQpLnNlbGVjdCgnc3ZnJyk7XG4gICAgICBpZiAoc3ZnRXhpc3QpIHtcbiAgICAgICAgc3ZnRXhpc3QucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH0pO1xuICB9XG59XG4iXX0=