ng-d3-graphs
Version:
<img src="./assets/ng-d3.png" alt="drawing" width="250" height="250"/>
192 lines • 27.2 kB
JavaScript
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';
var BarComponent = /** @class */ (function () {
function BarComponent(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();
}
BarComponent.prototype.onResize = function () {
this.onResize$.next();
};
BarComponent.prototype.ngOnInit = function () {
this.options = tslib_1.__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();
};
BarComponent.prototype.render = function () {
var currentWidth = parseInt(d3.select(this.container.nativeElement).select('div').style('width'), 10);
var currentHeight = parseInt(d3.select(this.container.nativeElement).select('div').style('height'), 10);
var width = this.options.width - this.options.margin.left -
this.options.margin.right;
var 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,
};
var 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');
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1).domain(this.labels);
var y = d3.scaleLinear().rangeRound([height, 0]).domain([
0,
Math.max.apply(Math, tslib_1.__spread(this.data.map(function (d) { return Number(d); })))
]);
var xAxis = function (g) { return g.call(d3.axisBottom(x))
.attr('transform', 'translate(0,' + height + ')'); };
var yAxis = function (g) { return 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', function (d) {
return x(d.x);
})
.attr('y', function (d) {
return y(Number(d.y));
})
.attr('width', x.bandwidth())
.attr('height', function (d) {
return height - y(Number(d.y));
});
var _xAxis = svg.append('g').call(xAxis);
// text label for the x axis
this.addLabelAxisX(svg, width, height);
var _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);
};
BarComponent.prototype.changeAxisColor = function (axis, config) {
this.d3Service.changeAxisColor(axis, config);
};
BarComponent.prototype.removeAxisTicks = function (axis) {
this.d3Service.removeAxisTicks(axis);
};
BarComponent.prototype.addLabelAxisY = function (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);
};
BarComponent.prototype.addLabelAxisX = function (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);
};
BarComponent.prototype.combineLabelsDataToOne = function () {
var result = [];
var N = this.data.length;
for (var index = 0; index < N; index++) {
result.push({ x: this.labels[index], y: this.data[index] });
}
return result;
};
// gridlines in x axis function
BarComponent.prototype.make_x_gridlines = function (x) {
return d3.axisBottom(x).ticks(this.options.gridTicks);
};
// gridlines in y axis function
BarComponent.prototype.make_y_gridlines = function (y) {
return d3.axisLeft(y).ticks(this.options.gridTicks);
};
BarComponent.prototype.onResizeEvent = function () {
var _this = this;
this.onResize$.pipe(debounceTime(200)).subscribe(function () {
var svgExist = d3.select(_this.container.nativeElement).select('svg');
if (svgExist) {
svgExist.remove();
}
_this.render();
});
};
BarComponent.ctorParameters = function () { return [
{ 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);
return BarComponent;
}());
export { BarComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLWQzLWdyYXBocy8iLCJzb3VyY2VzIjpbImJhci9iYXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxpQkFBaUIsR0FBRSxNQUFNLGVBQWUsQ0FBQztBQUM5SCxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFJeEQsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBNkN4RDtJQTZCRSxzQkFDWSxTQUFxQixFQUNyQixTQUFvQjtRQURwQixjQUFTLEdBQVQsU0FBUyxDQUFZO1FBQ3JCLGNBQVMsR0FBVCxTQUFTLENBQVc7UUE5QnZCLFNBQUksR0FBYyxFQUFFLENBQUM7UUFDckIsV0FBTSxHQUFVLEVBQUUsQ0FBQztRQUNuQixZQUFPLEdBQWdCLEVBQWdCLENBQUM7UUFDakQsVUFBSyxHQUFVO1lBQ2IsS0FBSyxFQUFFLEVBQUU7WUFDVCxLQUFLLEVBQUUsRUFBRTtZQUNULFNBQVMsRUFBRSxFQUFFO1lBQ2IsU0FBUyxFQUFFLEVBQUU7WUFDYixjQUFjLEVBQUUsRUFBRTtTQUNuQixDQUFDO1FBQ0Ysa0JBQWEsR0FBb0IsRUFBRSxDQUFDO1FBQ3BDLGNBQVMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRTdCLGFBQVEsR0FBZTtZQUM3QixLQUFLLEVBQUUsR0FBRztZQUNWLE1BQU0sRUFBRSxHQUFHO1lBQ1gsTUFBTSxFQUFFLEVBQUMsR0FBRyxF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ZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIFZpZXdFbmNhcHN1bGF0aW9uLH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBkMyBmcm9tICdkMyc7XG5pbXBvcnQge1N1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtkZWJvdW5jZVRpbWV9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHtheGlzQ29uZmlnfSBmcm9tICcuLi9zaGFyZWQvY29uZmlnL2F4aXMuY29uZmlnJztcbmltcG9ydCB7QXhpc30gZnJvbSAnLi4vc2hhcmVkL21vZGVscy9heGlzLmludGVyZmFjZSc7XG5pbXBvcnQge0dyYXBoT3B0aW9uc30gZnJvbSAnLi4vc2hhcmVkL21vZGVscy9ncmFwaC1vcHRpb25zLmludGVyZmFjZSc7XG5pbXBvcnQge1ZpZXdCb3h9IGZyb20gJy4uL3NoYXJlZC9tb2RlbHMvdmlld2JveC5pbnRlcmZhY2UnO1xuaW1wb3J0IHtEM1NlcnZpY2V9IGZyb20gJy4uL3NoYXJlZC9zZXJ2aWNlcy9kMy5zZXJ2aWNlJztcblxuaW1wb3J0IHtCYXJTZXJ2aWNlfSBmcm9tICcuL2Jhci5zZXJ2aWNlJztcblxuZXhwb3J0IGludGVyZmFjZSBCYXIge1xuICBsYWJlbHM6IGFueVtdO1xuICBkYXRhOiBhbnlbXTtcbiAgb3B0aW9ucz86IGFueTtcbn1cblxuaW50ZXJmYWNlIEJhckRhdGEge1xuICBsYWJlbDogc3RyaW5nO1xuICB2YWx1ZXM6IGFueVtdO1xufVxuZXhwb3J0IGludGVyZmFjZSBCYXJEMyB7XG4gIHhBeGlzOiBBeGlzW107XG4gIHlBeGlzOiBBeGlzW107XG4gIHhBeGlzUGF0aDogc3RyaW5nO1xuICB5QXhpc1BhdGg6IHN0cmluZztcbiAgcmVjdGFuZ2xlc0RhdGE6IFJlY3RhbmdsZVtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY3RhbmdsZSB7XG4gIHg6IG51bWJlcjtcbiAgeTogbnVtYmVyO1xuICBoZWlnaHQ6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIExhYmVsc0FuZERhdGEge1xuICB4OiBhbnk7XG4gIHk6IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCYXJPcHRpb25zIGV4dGVuZHMgR3JhcGhPcHRpb25zIHtcbiAgZ3JpZFRpY2tzPzogbnVtYmVyO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZy1iYXInLFxuICB0ZW1wbGF0ZVVybDogJy4vYmFyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vYmFyLmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBCYXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSBkYXRhOiBCYXJEYXRhW10gPSBbXTtcbiAgQElucHV0KCkgbGFiZWxzOiBhbnlbXSA9IFtdO1xuICBASW5wdXQoKSBvcHRpb25zPzogQmFyT3B0aW9ucyA9IHt9IGFzIEJhck9wdGlvbnM7XG4gIGdyYXBoOiBCYXJEMyA9IHtcbiAgICB4QXhpczogW10sXG4gICAgeUF4aXM6IFtdLFxuICAgIHhBeGlzUGF0aDogJycsXG4gICAgeUF4aXNQYXRoOiAnJyxcbiAgICByZWN0YW5nbGVzRGF0YTogW10sXG4gIH07XG4gIGxhYmVsc0FuZERhdGE6IExhYmVsc0FuZERhdGFbXSA9IFtdO1xuICBwYXJzZVRpbWUgPSBkMy50aW1lUGFyc2UoJyVkLSViLSV5Jyk7XG5cbiAgcHJpdmF0ZSBfb3B0aW9uczogQmFyT3B0aW9ucyA9IHtcbiAgICB3aWR0aDogODc5LFxuICAgIGhlaWdodDogODA0LFxuICAgIG1hcmdpbjoge3RvcDogNTAsIHJpZ2h0OiA1MCwgYm90dG9tOiA1MCwgbGVmdDogNTB9LFxuICAgIGdyaWRUaWNrczogMCxcbiAgfTtcblxuICB2aWV3Qm94OiBWaWV3Qm94ID0ge30gYXMgVmlld0JveDtcblxuICBvblJlc2l6ZSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJylcbiAgb25SZXNpemUoKTogdm9pZCB7XG4gICAgdGhpcy5vblJlc2l6ZSQubmV4dCgpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBwcml2YXRlIGNvbnRhaW5lcjogRWxlbWVudFJlZixcbiAgICAgIHByaXZhdGUgZDNTZXJ2aWNlOiBEM1NlcnZpY2UsXG4gICkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB7Li4udGhpcy5fb3B0aW9ucywgLi4udGhpcy5vcHRpb25zfTtcbiAgICB0aGlzLnZpZXdCb3ggPSB7XG4gICAgICBtaW5YOiAtdGhpcy5vcHRpb25zLm1hcmdpbi5sZWZ0LFxuICAgICAgbWluWTogLTEwLFxuICAgICAgd2lkdGg6IHRoaXMub3B0aW9ucy53aWR0aCArIHRoaXMub3B0aW9ucy5tYXJnaW4ubGVmdCArXG4gICAgICAgICAgdGhpcy5vcHRpb25zLm1hcmdpbi5yaWdodCxcbiAgICAgIGhlaWdodDogdGhpcy5vcHRpb25zLmhlaWdodCArIHRoaXMub3B0aW9ucy5tYXJnaW4udG9wLFxuICAgIH07XG4gICAgdGhpcy5sYWJlbHNBbmREYXRhID0gdGhpcy5jb21iaW5lTGFiZWxzRGF0YVRvT25lKCk7XG5cbiAgICB0aGlzLm9uUmVzaXplRXZlbnQoKTtcblxuICAgIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlcigpIHtcbiAgICBjb25zdCBjdXJyZW50V2lkdGggPSBwYXJzZUludChcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQpLnNlbGVjdCgnZGl2Jykuc3R5bGUoJ3dpZHRoJyksXG4gICAgICAgIDEwKTtcbiAgICBjb25zdCBjdXJyZW50SGVpZ2h0ID0gcGFyc2VJbnQoXG4gICAgICAgIGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KS5zZWxlY3QoJ2RpdicpLnN0eWxlKCdoZWlnaHQnKSxcbiAgICAgICAgMTApO1xuXG4gICAgY29uc3Qgd2lkdGggPSB0aGlzLm9wdGlvbnMud2lkdGggLSB0aGlzLm9wdGlvbnMubWFyZ2luLmxlZnQgLVxuICAgICAgICB0aGlzLm9wdGlvbnMubWFyZ2luLnJpZ2h0O1xuICAgIGNvbnN0IGhlaWdodCA9IHRoaXMub3B0aW9ucy5oZWlnaHQgLSB0aGlzLm9wdGlvbnMubWFyZ2luLnRvcCAtXG4gICAgICAgIHRoaXMub3B0aW9ucy5tYXJnaW4uYm90dG9tO1xuICAgIHRoaXMudmlld0JveCA9IHtcbiAgICAgIG1pblg6IC10aGlzLm9wdGlvbnMubWFyZ2luLmxlZnQsXG4gICAgICBtaW5ZOiAtMTAsXG4gICAgICB3aWR0aDogdGhpcy5vcHRpb25zLndpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLm9wdGlvbnMuaGVpZ2h0IC0gdGhpcy5vcHRpb25zLm1hcmdpbi50b3AsXG4gICAgfTtcblxuICAgIGNvbnN0IHN2ZyA9IGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICAuc2VsZWN0KCdkaXYnKVxuICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCdzdmcnKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cignd2lkdGgnLCBjdXJyZW50V2lkdGgpXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBjdXJyZW50SGVpZ2h0KVxuXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3ZpZXdCb3gnLFxuICAgICAgICAgICAgICAgICAgICAgICAgYCR7dGhpcy52aWV3Qm94Lm1pblh9ICR7dGhpcy52aWV3Qm94Lm1pbll9ICR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3Qm94LndpZHRofSAke3RoaXMudmlld0JveC5oZWlnaHR9YClcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3N2Zy1jb250ZW50JywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgnZycpO1xuXG4gICAgY29uc3QgeCA9XG4gICAgICAgIGQzLnNjYWxlQmFuZCgpLnJhbmdlUm91bmQoWzAsIHdpZHRoXSkucGFkZGluZygwLjEpLmRvbWFpbih0aGlzLmxhYmVscyk7XG5cbiAgICBjb25zdCB5ID0gZDMuc2NhbGVMaW5lYXIoKS5yYW5nZVJvdW5kKFtoZWlnaHQsIDBdKS5kb21haW4oW1xuICAgICAgMCwgTWF0aC5tYXgoLi4udGhpcy5kYXRhLm1hcCgoZCkgPT4gTnVtYmVyKGQpKSlcbiAgICBdKTtcblxuICAgIGNvbnN0IHhBeGlzID0gKGcpID0+IGcuY2FsbChkMy5heGlzQm90dG9tKHgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcgKyBoZWlnaHQgKyAnKScpO1xuXG4gICAgY29uc3QgeUF4aXMgPSAoZykgPT4gZy5jYWxsKGQzLmF4aXNMZWZ0KHkpKTtcblxuICAgIC8vIGFkZCB0aGUgWCBncmlkbGluZXNcbiAgICBzdmcuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dyaWQnKVxuICAgICAgICAuY2FsbChcbiAgICAgICAgICAgIHRoaXMubWFrZV94X2dyaWRsaW5lcyh4KS50aWNrU2l6ZShoZWlnaHQpXG4gICAgICAgICAgICAvLyAudGlja0Zvcm1hdCgnJylcbiAgICAgICAgKTtcblxuICAgIC8vIGFkZCB0aGUgWSBncmlkbGluZXNcbiAgICBzdmcuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dyaWQnKVxuICAgICAgICAuY2FsbChcbiAgICAgICAgICAgIHRoaXMubWFrZV95X2dyaWRsaW5lcyh5KS50aWNrU2l6ZSgtd2lkdGgpXG4gICAgICAgICAgICAvLyAudGlja0Zvcm1hdCgnJylcbiAgICAgICAgKTtcblxuICAgIHN2Zy5zZWxlY3RBbGwoJy5iYXInKVxuICAgICAgICAuZGF0YSh0aGlzLmxhYmVsc0FuZERhdGEpXG4gICAgICAgIC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnYmFyJylcbiAgICAgICAgLmF0dHIoXG4gICAgICAgICAgICAneCcsXG4gICAgICAgICAgICAoZCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4geChkLngpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoXG4gICAgICAgICAgICAneScsXG4gICAgICAgICAgICAoZCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4geShOdW1iZXIoZC55KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAuYXR0cignd2lkdGgnLCB4LmJhbmR3aWR0aCgpKVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgKGQpID0+IHtcbiAgICAgICAgICByZXR1cm4gaGVpZ2h0IC0geShOdW1iZXIoZC55KSk7XG4gICAgICAgIH0pO1xuXG4gICAgY29uc3QgX3hBeGlzID0gc3ZnLmFwcGVuZCgnZycpLmNhbGwoeEF4aXMpO1xuXG4gICAgLy8gdGV4dCBsYWJlbCBmb3IgdGhlIHggYXhpc1xuICAgIHRoaXMuYWRkTGFiZWxBeGlzWChzdmcsIHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgY29uc3QgX3lBeGlzID0gc3ZnLmFwcGVuZCgnZycpLmNhbGwoeUF4aXMpO1xuXG4gICAgLy8gdGV4dCBsYWJlbCBmb3IgdGhlIHkgYXhpc1xuICAgIHRoaXMuYWRkTGFiZWxBeGlzWShzdmcsIGhlaWdodCk7XG5cbiAgICB0aGlzLnJlbW92ZUF4aXNUaWNrcyhfeEF4aXMpO1xuICAgIHRoaXMucmVtb3ZlQXhpc1RpY2tzKF95QXhpcyk7XG5cbiAgICB0aGlzLmNoYW5nZUF4aXNDb2xvcihfeEF4aXMsIGF4aXNDb25maWcpO1xuICAgIHRoaXMuY2hhbmdlQXhpc0NvbG9yKF95QXhpcywgYXhpc0NvbmZpZyk7XG4gIH1cblxuICBwcml2YXRlIGNoYW5nZUF4aXNDb2xvcihcbiAgICAgIGF4aXM6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgbnVsbCwgdW5kZWZpbmVkPiwgY29uZmlnOiBhbnkpIHtcbiAgICB0aGlzLmQzU2VydmljZS5jaGFuZ2VBeGlzQ29sb3IoYXhpcywgY29uZmlnKTtcbiAgfVxuXG5cbiAgcHJpdmF0ZSByZW1vdmVBeGlzVGlja3MoXG4gICAgICBheGlzOiBkMy5TZWxlY3Rpb248U1ZHR0VsZW1lbnQsIHVua25vd24sIG51bGwsIHVuZGVmaW5lZD4pIHtcbiAgICB0aGlzLmQzU2VydmljZS5yZW1vdmVBeGlzVGlja3MoYXhpcyk7XG4gIH1cblxuICBwcml2YXRlIGFkZExhYmVsQXhpc1koXG4gICAgICBzdmc6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgbnVsbCwgdW5kZWZpbmVkPixcbiAgICAgIGhlaWdodDogbnVtYmVyKSB7XG4gICAgc3ZnLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAncm90YXRlKDApJylcbiAgICAgICAgLmF0dHIoJ3knLCAwIC0gdGhpcy5vcHRpb25zLm1hcmdpbi50b3AgLyAyKVxuICAgICAgICAuYXR0cigneCcsIDApXG4gICAgICAgIC5hdHRyKCdkeScsICcxZW0nKVxuICAgICAgICAuc3R5bGUoJ3RleHQtYW5jaG9yJywgJ3N0YXJ0JylcbiAgICAgICAgLnRleHQodGhpcy5vcHRpb25zLnlBeGlzTGFiZWwpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRMYWJlbEF4aXNYKFxuICAgICAgc3ZnOiBkMy5TZWxlY3Rpb248U1ZHR0VsZW1lbnQsIHVua25vd24sIG51bGwsIHVuZGVmaW5lZD4sIHdpZHRoOiBudW1iZXIsXG4gICAgICBoZWlnaHQ6IG51bWJlcikge1xuICAgIHN2Zy5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuYXR0cihcbiAgICAgICAgICAgICd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgd2lkdGggLyAyICsgJyAsJyArXG4gICAgICAgICAgICAgICAgKGhlaWdodCArIHRoaXMub3B0aW9ucy5tYXJnaW4udG9wIC0gMTUpICsgJyknKVxuICAgICAgICAuc3R5bGUoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgIC50ZXh0KHRoaXMub3B0aW9ucy54QXhpc0xhYmVsKTtcbiAgfVxuXG4gIHByaXZhdGUgY29tYmluZUxhYmVsc0RhdGFUb09uZSgpOiBMYWJlbHNBbmREYXRhW10ge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIGNvbnN0IE4gPSB0aGlzLmRhdGEubGVuZ3RoO1xuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBOOyBpbmRleCsrKSB7XG4gICAgICByZXN1bHQucHVzaCh7eDogdGhpcy5sYWJlbHNbaW5kZXhdLCB5OiB0aGlzLmRhdGFbaW5kZXhdfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgLy8gZ3JpZGxpbmVzIGluIHggYXhpcyBmdW5jdGlvblxuICBwcml2YXRlIG1ha2VfeF9ncmlkbGluZXMoeCkge1xuICAgIHJldHVybiBkMy5heGlzQm90dG9tKHgpLnRpY2tzKHRoaXMub3B0aW9ucy5ncmlkVGlja3MpO1xuICB9XG5cbiAgLy8gZ3JpZGxpbmVzIGluIHkgYXhpcyBmdW5jdGlvblxuICBwcml2YXRlIG1ha2VfeV9ncmlkbGluZXMoeSkge1xuICAgIHJldHVybiBkMy5heGlzTGVmdCh5KS50aWNrcyh0aGlzLm9wdGlvbnMuZ3JpZFRpY2tzKTtcbiAgfVxuXG4gIG9uUmVzaXplRXZlbnQoKTogdm9pZCB7XG4gICAgdGhpcy5vblJlc2l6ZSQucGlwZShkZWJvdW5jZVRpbWUoMjAwKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIGNvbnN0IHN2Z0V4aXN0ID0gZDMuc2VsZWN0KHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQpLnNlbGVjdCgnc3ZnJyk7XG4gICAgICBpZiAoc3ZnRXhpc3QpIHtcbiAgICAgICAgc3ZnRXhpc3QucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH0pO1xuICB9XG59XG4iXX0=