UNPKG

ng-d3-graphs

Version:

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

273 lines (265 loc) 36.6 kB
import * as tslib_1 from "tslib"; import { 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 MultilineComponent = /** @class */ (function () { function MultilineComponent(container, d3Service) { this.container = container; this.d3Service = d3Service; this.data = []; this.labels = []; this.options = {}; this.labelsAndData = []; this.utcParse = d3.utcParse('%Y-%m'); this.viewBox = {}; this._options = { width: 879, height: 804, yAxisLabel: '', xAxisLabel: '', margin: { top: 50, right: 50, bottom: 50, left: 50 }, timeParser: axisConfig.xAxisTimeParser, timeFormat: axisConfig.xAxisTimeFormat, xAxisTicks: axisConfig.xAxisTicks, }; this.parseTime = d3.timeParse(this.options.timeParser); this.formatTime = d3.timeFormat(this.options.timeFormat); this.onResize$ = new Subject(); } MultilineComponent.prototype.onResize = function () { this.onResize$.next(); }; MultilineComponent.prototype.ngOnInit = function () { this.options = tslib_1.__assign({}, this._options, this.options); this.viewBox = { minX: -this.options.margin.left, minY: -25, width: this.options.width + this.options.margin.left + this.options.margin.right, height: this.options.height + this.options.margin.top, }; this.parseTime = d3.timeParse(this.options.timeParser); this.formatTime = d3.timeFormat(this.options.timeFormat); this.labels = this.formatData(); this.labelsAndData = this.combineLabelsDataToOne(); this.onResizeEvent(); this.render(); }; MultilineComponent.prototype.formatData = function () { var _this = this; return this.labels.map(function (d) { return _this.parseTime(d); }); }; MultilineComponent.prototype.combineLabelsDataToOne = function () { var result = []; var N = this.data.length; for (var index = 0; index < N; index++) { result.push({ x: this.labels, y: this.data[index] }); } return result; }; MultilineComponent.prototype.render = function () { var _this = this; 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 xDomain = this.getXdomain(); var x = d3.scaleTime().domain(xDomain).range([0, width]); var y = d3.scaleLinear() .domain([0, d3.max(this.data, function (d) { return d3.max(d.values); })]) .range([height, 0]) .nice(); // const xAxis = (g) => // g.attr('transform', `translate(0,${height})`).call(d3.axisBottom(x)); var xAxis = this.d3Service.getXaxisTime(svg, height, x, this.options.timeFormat, this.options.xAxisTicks); var yAxis = function (g) { return g.call(d3.axisLeft(y)); }; var line = d3.line() .defined(function (d) { return !isNaN(d); }) .x(function (d, i) { return x(_this.labels[i]); }) .y(function (d) { return y(d); }); // 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('') ); var _yAxis = svg.append('g').call(yAxis); // text label for the x axis this.addLabelAxisX(svg, width, height); // text label for the y axis this.addLabelAxisY(svg, height); var path = svg.append('g') .attr('fill', 'none') .attr('stroke', 'steelblue') .attr('stroke-width', 1.5) .attr('stroke-linejoin', 'round') .attr('stroke-linecap', 'round') .selectAll('path') .data(this.data) .join('path') .style('mix-blend-mode', 'multiply') .attr('d', function (d) { return line(d.values); }) .text('this is '); this.removeAxisTicks(xAxis); this.removeAxisTicks(_yAxis); this.changeAxisColor(xAxis, axisConfig); this.changeAxisColor(_yAxis, axisConfig); // TODO: comment in when issue #61 is fixed /* svg.call(hover, path, this); function hover(svg, path, _this) { if ('ontouchstart' in document) { svg.style('-webkit-tap-highlight-color', 'transparent') .on('touchmove', moved) .on('touchstart', entered) .on('touchend', left); } else { svg.on('mousemove', moved) .on('mouseenter', entered) .on('mouseleave', left); } const dot = svg.append('g').attr('display', 'none'); dot.append('circle').attr('r', 2.5); dot.append('text') .attr('font-family', 'sans-serif') .attr('font-size', 10) .attr('text-anchor', 'middle') .attr('y', -8); function moved() { d3.event.preventDefault(); const ym = y.invert(d3.event.layerY) as any; const xm = x.invert(d3.event.layerX) as any; const i1 = d3.bisectLeft(_this.labels, xm, 1); const i0 = i1 - 1; const i = xm - _this.labels[i0] > _this.labels[i1] - xm ? i1 : i0; // const s = d3.least(_this.data, d => Math.abs(d.values[i] - ym)); const s = _this.least(_this.data, d => Math.abs(d.values[i] - ym), i, ym); path.attr('stroke', d => d === s ? null : '#ddd') .filter(d => d === s) .raise(); dot.attr( 'transform', `translate(${x(_this.labels[i])},${y(s.values[i])})`); dot.select('text').text(s.name); } function entered() { path.style('mix-blend-mode', null).attr('stroke', '#ddd'); dot.attr('display', null); } function left() { path.style('mix-blend-mode', 'multiply').attr('stroke', null); dot.attr('display', 'none'); } } */ }; MultilineComponent.prototype.changeAxisColor = function (axis, config) { this.d3Service.changeAxisColor(axis, config); }; MultilineComponent.prototype.removeAxisTicks = function (axis) { this.d3Service.removeAxisTicks(axis); }; MultilineComponent.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); }; MultilineComponent.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); }; MultilineComponent.prototype.getXdomain = function () { var domainExtent = d3.extent(this.labels, function (d) { return d; }); return domainExtent.map(function (d) { return new Date(d); }); }; MultilineComponent.prototype.least = function (arr, filterFun, pos, ym) { var tempValues = arr.map(function (d) { return filterFun(d); }); var minNum = Math.min.apply(Math, tslib_1.__spread(tempValues)); var graphHovered; var minimax = tempValues[0]; var minPos = 0; for (var i = 1; i < tempValues.length; i++) { var element = tempValues[i]; if (element >= minimax) { minPos = i; minimax = element; } } graphHovered = arr[minPos]; return graphHovered; }; // gridlines in x axis function MultilineComponent.prototype.make_x_gridlines = function (x) { return d3.axisBottom(x).ticks(this.options.gridTicks); }; // gridlines in y axis function MultilineComponent.prototype.make_y_gridlines = function (y) { return d3.axisLeft(y).ticks(this.options.gridTicks); }; MultilineComponent.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(); }); }; MultilineComponent.ctorParameters = function () { return [ { type: ElementRef }, { type: D3Service } ]; }; tslib_1.__decorate([ Input() ], MultilineComponent.prototype, "data", void 0); tslib_1.__decorate([ Input() ], MultilineComponent.prototype, "labels", void 0); tslib_1.__decorate([ Input() ], MultilineComponent.prototype, "options", void 0); tslib_1.__decorate([ HostListener('window:resize') ], MultilineComponent.prototype, "onResize", null); MultilineComponent = tslib_1.__decorate([ Component({ selector: 'ng-multiline', template: "<div class=\"svg-container\"></div>\n", encapsulation: ViewEncapsulation.None, 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}"] }) ], MultilineComponent); return MultilineComponent; }()); export { MultilineComponent }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGlsaW5lLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLWQzLWdyYXBocy8iLCJzb3VyY2VzIjpbIm11bHRpbGluZS9tdWx0aWxpbmUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxpQkFBaUIsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNwRyxPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFHeEQsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLCtCQUErQixDQUFDO0FBc0J4RDtJQThCRSw0QkFDWSxTQUFxQixFQUNyQixTQUFvQjtRQURwQixjQUFTLEdBQVQsU0FBUyxDQUFZO1FBQ3JCLGNBQVMsR0FBVCxTQUFTLENBQVc7UUEvQnZCLFNBQUksR0FBb0IsRUFBRSxDQUFDO1FBQzNCLFdBQU0sR0FBVSxFQUFFLENBQUM7UUFDbkIsWUFBTyxHQUFzQixFQUFzQixDQUFDO1FBQzdELGtCQUFhLEdBQW9CLEVBQUUsQ0FBQztRQUNwQyxhQUFRLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUdoQyxZQUFPLEdBQVksRUFBYSxDQUFDO1FBRWpDLGFBQVEsR0FBcUI7WUFDM0IsS0FBSyxFQUFFLEdBQUc7WUFDVixNQUFNLEVBQUUsR0FBRztZQUNYLFVBQVUsRUFBRSxFQUFFO1lBQ2QsVUFBVSxFQUFFLEVBQUU7WUFDZCxNQUFNLEVBQUUsRUFBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFB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QUM7SUFDdEQsQ0FBQztJQUVELDBDQUFhLEdBQWI7UUFBQSxpQkFRQztRQVBDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUMvQyxJQUFNLFFBQVEsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZFLElBQUksUUFBUSxFQUFFO2dCQUNaLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQzthQUNuQjtZQUNELEtBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7O2dCQTFRc0IsVUFBVTtnQkFDVixTQUFTOztJQS9CdkI7UUFBUixLQUFLLEVBQUU7b0RBQTRCO0lBQzNCO1FBQVIsS0FBSyxFQUFFO3NEQUFvQjtJQUNuQjtRQUFSLEtBQUssRUFBRTt1REFBcUQ7SUF1QjdEO1FBREMsWUFBWSxDQUFDLGVBQWUsQ0FBQztzREFHN0I7SUE1QlUsa0JBQWtCO1FBTjlCLFNBQVMsQ0FBQztZQUNULFFBQVEsRUFBRSxjQUFjO1lBQ3hCLGlEQUF5QztZQUV6QyxhQUFhLEVBQUUsaUJBQWlCLENBQUMsSUFBSTs7U0FDdEMsQ0FBQztPQUNXLGtCQUFrQixDQTBTOUI7SUFBRCx5QkFBQztDQUFBLEFBMVNELElBMFNDO1NBMVNZLGtCQUFrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIFZpZXdFbmNhcHN1bGF0aW9ufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCAqIGFzIGQzIGZyb20gJ2QzJztcbmltcG9ydCB7U3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2RlYm91bmNlVGltZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge2F4aXNDb25maWd9IGZyb20gJy4uL3NoYXJlZC9jb25maWcvYXhpcy5jb25maWcnO1xuaW1wb3J0IHtHcmFwaE9wdGlvbnN9IGZyb20gJy4uL3NoYXJlZC9tb2RlbHMvZ3JhcGgtb3B0aW9ucy5pbnRlcmZhY2UnO1xuaW1wb3J0IHtWaWV3Qm94fSBmcm9tICcuLi9zaGFyZWQvbW9kZWxzL3ZpZXdib3guaW50ZXJmYWNlJztcbmltcG9ydCB7RDNTZXJ2aWNlfSBmcm9tICcuLi9zaGFyZWQvc2VydmljZXMvZDMuc2VydmljZSc7XG5cbmludGVyZmFjZSBMYWJlbHNBbmREYXRhIHtcbiAgeDogYW55O1xuICB5OiBhbnk7XG59XG5cbmludGVyZmFjZSBNdWx0aWxpbmVEYXRhIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgdmFsdWVzOiBhbnlbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNdWx0aWxpbmVPcHRpb25zIGV4dGVuZHMgR3JhcGhPcHRpb25zIHtcbiAgZ3JpZFRpY2tzPzogbnVtYmVyO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZy1tdWx0aWxpbmUnLFxuICB0ZW1wbGF0ZVVybDogJy4vbXVsdGlsaW5lLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vbXVsdGlsaW5lLmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG59KVxuZXhwb3J0IGNsYXNzIE11bHRpbGluZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpIGRhdGE6IE11bHRpbGluZURhdGFbXSA9IFtdO1xuICBASW5wdXQoKSBsYWJlbHM6IGFueVtdID0gW107XG4gIEBJbnB1dCgpIG9wdGlvbnM/OiBNdWx0aWxpbmVPcHRpb25zID0ge30gYXMgTXVsdGlsaW5lT3B0aW9ucztcbiAgbGFiZWxzQW5kRGF0YTogTGFiZWxzQW5kRGF0YVtdID0gW107XG4gIHV0Y1BhcnNlID0gZDMudXRjUGFyc2UoJyVZLSVtJyk7XG4gIHg6IGFueTtcbiAgeTogYW55O1xuICB2aWV3Qm94OiBWaWV3Qm94ID0ge30gYXMgVmlld0JveDtcblxuICBfb3B0aW9uczogTXVsdGlsaW5lT3B0aW9ucyA9IHtcbiAgICB3aWR0aDogODc5LFxuICAgIGhlaWdodDogODA0LFxuICAgIHlBeGlzTGFiZWw6ICcnLFxuICAgIHhBeGlzTGFiZWw6ICcnLFxuICAgIG1hcmdpbjoge3RvcDogNTAsIHJpZ2h0OiA1MCwgYm90dG9tOiA1MCwgbGVmdDogNTB9LFxuICAgIHRpbWVQYXJzZXI6IGF4aXNDb25maWcueEF4aXNUaW1lUGFyc2VyLFxuICAgIHRpbWVGb3JtYXQ6IGF4aXNDb25maWcueEF4aXNUaW1lRm9ybWF0LFxuICAgIHhBeGlzVGlja3M6IGF4aXNDb25maWcueEF4aXNUaWNrcyxcbiAgfTtcblxuICBwYXJzZVRpbWUgPSBkMy50aW1lUGFyc2UodGhpcy5vcHRpb25zLnRpbWVQYXJzZXIpO1xuICBmb3JtYXRUaW1lID0gZDMudGltZUZvcm1hdCh0aGlzLm9wdGlvbnMudGltZUZvcm1hdCk7XG5cbiAgb25SZXNpemUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OnJlc2l6ZScpXG4gIG9uUmVzaXplKCk6IHZvaWQge1xuICAgIHRoaXMub25SZXNpemUkLm5leHQoKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSBjb250YWluZXI6IEVsZW1lbnRSZWYsXG4gICAgICBwcml2YXRlIGQzU2VydmljZTogRDNTZXJ2aWNlLFxuICApIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5vcHRpb25zID0gey4uLnRoaXMuX29wdGlvbnMsIC4uLnRoaXMub3B0aW9uc307XG4gICAgdGhpcy52aWV3Qm94ID0ge1xuICAgICAgbWluWDogLXRoaXMub3B0aW9ucy5tYXJnaW4ubGVmdCxcbiAgICAgIG1pblk6IC0yNSxcbiAgICAgIHdpZHRoOiB0aGlzLm9wdGlvbnMud2lkdGggKyB0aGlzLm9wdGlvbnMubWFyZ2luLmxlZnQgK1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5tYXJnaW4ucmlnaHQsXG4gICAgICBoZWlnaHQ6IHRoaXMub3B0aW9ucy5oZWlnaHQgKyB0aGlzLm9wdGlvbnMubWFyZ2luLnRvcCxcbiAgICB9O1xuXG4gICAgdGhpcy5wYXJzZVRpbWUgPSBkMy50aW1lUGFyc2UodGhpcy5vcHRpb25zLnRpbWVQYXJzZXIpO1xuICAgIHRoaXMuZm9ybWF0VGltZSA9IGQzLnRpbWVGb3JtYXQodGhpcy5vcHRpb25zLnRpbWVGb3JtYXQpO1xuXG5cbiAgICB0aGlzLmxhYmVscyA9IHRoaXMuZm9ybWF0RGF0YSgpO1xuICAgIHRoaXMubGFiZWxzQW5kRGF0YSA9IHRoaXMuY29tYmluZUxhYmVsc0RhdGFUb09uZSgpO1xuXG4gICAgdGhpcy5vblJlc2l6ZUV2ZW50KCk7XG5cbiAgICB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JtYXREYXRhKCkge1xuICAgIHJldHVybiB0aGlzLmxhYmVscy5tYXAoZCA9PiB0aGlzLnBhcnNlVGltZShkKSk7XG4gIH1cblxuICBwcml2YXRlIGNvbWJpbmVMYWJlbHNEYXRhVG9PbmUoKTogTGFiZWxzQW5kRGF0YVtdIHtcbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBjb25zdCBOID0gdGhpcy5kYXRhLmxlbmd0aDtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgTjsgaW5kZXgrKykge1xuICAgICAgcmVzdWx0LnB1c2goe3g6IHRoaXMubGFiZWxzLCB5OiB0aGlzLmRhdGFbaW5kZXhdfSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICByZW5kZXIoKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFdpZHRoID0gcGFyc2VJbnQoXG4gICAgICAgIGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KS5zZWxlY3QoJ2RpdicpLnN0eWxlKCd3aWR0aCcpLFxuICAgICAgICAxMCk7XG4gICAgY29uc3QgY3VycmVudEhlaWdodCA9IHBhcnNlSW50KFxuICAgICAgICBkMy5zZWxlY3QodGhpcy5jb250YWluZXIubmF0aXZlRWxlbWVudCkuc2VsZWN0KCdkaXYnKS5zdHlsZSgnaGVpZ2h0JyksXG4gICAgICAgIDEwKTtcblxuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5vcHRpb25zLndpZHRoIC0gdGhpcy5vcHRpb25zLm1hcmdpbi5sZWZ0IC1cbiAgICAgICAgdGhpcy5vcHRpb25zLm1hcmdpbi5yaWdodDtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLm9wdGlvbnMuaGVpZ2h0IC0gdGhpcy5vcHRpb25zLm1hcmdpbi50b3AgLVxuICAgICAgICB0aGlzLm9wdGlvbnMubWFyZ2luLmJvdHRvbTtcblxuICAgIHRoaXMudmlld0JveCA9IHtcbiAgICAgIG1pblg6IC10aGlzLm9wdGlvbnMubWFyZ2luLmxlZnQsXG4gICAgICBtaW5ZOiAtMTAsXG4gICAgICB3aWR0aDogdGhpcy5vcHRpb25zLndpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLm9wdGlvbnMuaGVpZ2h0IC0gdGhpcy5vcHRpb25zLm1hcmdpbi50b3AsXG4gICAgfTtcblxuICAgIGNvbnN0IHN2ZyA9IGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICAuc2VsZWN0KCdkaXYnKVxuICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCdzdmcnKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cignd2lkdGgnLCBjdXJyZW50V2lkdGgpXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBjdXJyZW50SGVpZ2h0KVxuICAgICAgICAgICAgICAgICAgICAuYXR0cihcbiAgICAgICAgICAgICAgICAgICAgICAgICd2aWV3Qm94JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGAke3RoaXMudmlld0JveC5taW5YfSAke3RoaXMudmlld0JveC5taW5ZfSAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlld0JveC53aWR0aH0gJHt0aGlzLnZpZXdCb3guaGVpZ2h0fWApXG4gICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzdmctY29udGVudCcsIHRydWUpXG4gICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJ2cnKTtcblxuICAgIGNvbnN0IHhEb21haW4gPSB0aGlzLmdldFhkb21haW4oKTtcbiAgICBjb25zdCB4ID0gZDMuc2NhbGVUaW1lKCkuZG9tYWluKHhEb21haW4pLnJhbmdlKFswLCB3aWR0aF0pO1xuXG4gICAgY29uc3QgeSA9IGQzLnNjYWxlTGluZWFyKClcbiAgICAgICAgICAgICAgICAgIC5kb21haW4oWzAsIGQzLm1heCh0aGlzLmRhdGEsIChkKSA9PiBkMy5tYXgoZC52YWx1ZXMpKV0pXG4gICAgICAgICAgICAgICAgICAucmFuZ2UoW2hlaWdodCwgMF0pXG4gICAgICAgICAgICAgICAgICAubmljZSgpO1xuXG4gICAgLy8gY29uc3QgeEF4aXMgPSAoZykgPT5cbiAgICAvLyAgICAgZy5hdHRyKCd0cmFuc2Zvcm0nLCBgdHJhbnNsYXRlKDAsJHtoZWlnaHR9KWApLmNhbGwoZDMuYXhpc0JvdHRvbSh4KSk7XG5cbiAgICBjb25zdCB4QXhpcyA9IHRoaXMuZDNTZXJ2aWNlLmdldFhheGlzVGltZShcbiAgICAgICAgc3ZnLCBoZWlnaHQsIHgsIHRoaXMub3B0aW9ucy50aW1lRm9ybWF0LCB0aGlzLm9wdGlvbnMueEF4aXNUaWNrcyk7XG5cblxuICAgIGNvbnN0IHlBeGlzID0gKGcpID0+IGcuY2FsbChkMy5heGlzTGVmdCh5KSk7XG5cbiAgICBjb25zdCBsaW5lID0gZDMubGluZTxhbnk+KClcbiAgICAgICAgICAgICAgICAgICAgIC5kZWZpbmVkKChkKSA9PiAhaXNOYU4oZCkpXG4gICAgICAgICAgICAgICAgICAgICAueCgoZCwgaSkgPT4geCh0aGlzLmxhYmVsc1tpXSkpXG4gICAgICAgICAgICAgICAgICAgICAueSgoZCkgPT4geShkKSk7XG5cbiAgICAvLyBhZGQgdGhlIFggZ3JpZGxpbmVzXG4gICAgc3ZnLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdncmlkJylcbiAgICAgICAgLmNhbGwoXG4gICAgICAgICAgICB0aGlzLm1ha2VfeF9ncmlkbGluZXMoeCkudGlja1NpemUoaGVpZ2h0KVxuICAgICAgICAgICAgLy8gLnRpY2tGb3JtYXQoJycpXG4gICAgICAgICk7XG5cbiAgICAvLyBhZGQgdGhlIFkgZ3JpZGxpbmVzXG4gICAgc3ZnLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdncmlkJylcbiAgICAgICAgLmNhbGwoXG4gICAgICAgICAgICB0aGlzLm1ha2VfeV9ncmlkbGluZXMoeSkudGlja1NpemUoLXdpZHRoKVxuICAgICAgICAgICAgLy8gLnRpY2tGb3JtYXQoJycpXG4gICAgICAgICk7XG5cbiAgICBjb25zdCBfeUF4aXMgPSBzdmcuYXBwZW5kKCdnJykuY2FsbCh5QXhpcyk7XG5cbiAgICAvLyB0ZXh0IGxhYmVsIGZvciB0aGUgeCBheGlzXG4gICAgdGhpcy5hZGRMYWJlbEF4aXNYKHN2Zywgd2lkdGgsIGhlaWdodCk7XG4gICAgLy8gdGV4dCBsYWJlbCBmb3IgdGhlIHkgYXhpc1xuICAgIHRoaXMuYWRkTGFiZWxBeGlzWShzdmcsIGhlaWdodCk7XG5cbiAgICBjb25zdCBwYXRoID0gc3ZnLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAgICAgICAgICAuYXR0cignZmlsbCcsICdub25lJylcbiAgICAgICAgICAgICAgICAgICAgIC5hdHRyKCdzdHJva2UnLCAnc3RlZWxibHVlJylcbiAgICAgICAgICAgICAgICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCAxLjUpXG4gICAgICAgICAgICAgICAgICAgICAuYXR0cignc3Ryb2tlLWxpbmVqb2luJywgJ3JvdW5kJylcbiAgICAgICAgICAgICAgICAgICAgIC5hdHRyKCdzdHJva2UtbGluZWNhcCcsICdyb3VuZCcpXG4gICAgICAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgIC5kYXRhKHRoaXMuZGF0YSlcbiAgICAgICAgICAgICAgICAgICAgIC5qb2luKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgIC5zdHlsZSgnbWl4LWJsZW5kLW1vZGUnLCAnbXVsdGlwbHknKVxuICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCAoZCkgPT4gbGluZShkLnZhbHVlcykpXG4gICAgICAgICAgICAgICAgICAgICAudGV4dCgndGhpcyBpcyAnKTtcblxuICAgIHRoaXMucmVtb3ZlQXhpc1RpY2tzKHhBeGlzKTtcbiAgICB0aGlzLnJlbW92ZUF4aXNUaWNrcyhfeUF4aXMpO1xuXG4gICAgdGhpcy5jaGFuZ2VBeGlzQ29sb3IoeEF4aXMsIGF4aXNDb25maWcpO1xuICAgIHRoaXMuY2hhbmdlQXhpc0NvbG9yKF95QXhpcywgYXhpc0NvbmZpZyk7XG5cbiAgICAvLyBUT0RPOiBjb21tZW50IGluIHdoZW4gaXNzdWUgIzYxIGlzIGZpeGVkXG4gICAgLyogc3ZnLmNhbGwoaG92ZXIsIHBhdGgsIHRoaXMpO1xuXG4gICAgZnVuY3Rpb24gaG92ZXIoc3ZnLCBwYXRoLCBfdGhpcykge1xuXG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQpIHtcbiAgICAgICAgc3ZnLnN0eWxlKCctd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3InLCAndHJhbnNwYXJlbnQnKVxuICAgICAgICAgIC5vbigndG91Y2htb3ZlJywgbW92ZWQpXG4gICAgICAgICAgLm9uKCd0b3VjaHN0YXJ0JywgZW50ZXJlZClcbiAgICAgICAgICAub24oJ3RvdWNoZW5kJywgbGVmdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdmcub24oJ21vdXNlbW92ZScsIG1vdmVkKVxuICAgICAgICAgIC5vbignbW91c2VlbnRlcicsIGVudGVyZWQpXG4gICAgICAgICAgLm9uKCdtb3VzZWxlYXZlJywgbGVmdCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRvdCA9IHN2Zy5hcHBlbmQoJ2cnKS5hdHRyKCdkaXNwbGF5JywgJ25vbmUnKTtcblxuICAgICAgZG90LmFwcGVuZCgnY2lyY2xlJykuYXR0cigncicsIDIuNSk7XG5cbiAgICAgIGRvdC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuYXR0cignZm9udC1mYW1pbHknLCAnc2Fucy1zZXJpZicpXG4gICAgICAgIC5hdHRyKCdmb250LXNpemUnLCAxMClcbiAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgIC5hdHRyKCd5JywgLTgpO1xuXG4gICAgICBmdW5jdGlvbiBtb3ZlZCgpIHtcbiAgICAgICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc3QgeW0gPSB5LmludmVydChkMy5ldmVudC5sYXllclkpIGFzIGFueTtcbiAgICAgICAgY29uc3QgeG0gPSB4LmludmVydChkMy5ldmVudC5sYXllclgpIGFzIGFueTtcbiAgICAgICAgY29uc3QgaTEgPSBkMy5iaXNlY3RMZWZ0KF90aGlzLmxhYmVscywgeG0sIDEpO1xuICAgICAgICBjb25zdCBpMCA9IGkxIC0gMTtcbiAgICAgICAgY29uc3QgaSA9IHhtIC0gX3RoaXMubGFiZWxzW2kwXSA+IF90aGlzLmxhYmVsc1tpMV0gLSB4bSA/IGkxIDogaTA7XG4gICAgICAgIC8vIGNvbnN0IHMgPSBkMy5sZWFzdChfdGhpcy5kYXRhLCBkID0+IE1hdGguYWJzKGQudmFsdWVzW2ldIC0geW0pKTtcbiAgICAgICAgY29uc3QgcyA9IF90aGlzLmxlYXN0KF90aGlzLmRhdGEsIGQgPT4gTWF0aC5hYnMoZC52YWx1ZXNbaV0gLSB5bSksIGksXG4gICAgeW0pOyBwYXRoLmF0dHIoJ3N0cm9rZScsIGQgPT4gZCA9PT0gcyA/IG51bGwgOiAnI2RkZCcpIC5maWx0ZXIoZCA9PiBkID09PSBzKVxuICAgICAgICAgIC5yYWlzZSgpO1xuICAgICAgICBkb3QuYXR0cihcbiAgICAgICAgICAndHJhbnNmb3JtJywgYHRyYW5zbGF0ZSgke3goX3RoaXMubGFiZWxzW2ldKX0sJHt5KHMudmFsdWVzW2ldKX0pYCk7XG4gICAgICAgIGRvdC5zZWxlY3QoJ3RleHQnKS50ZXh0KHMubmFtZSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGVudGVyZWQoKSB7XG4gICAgICAgIHBhdGguc3R5bGUoJ21peC1ibGVuZC1tb2RlJywgbnVsbCkuYXR0cignc3Ryb2tlJywgJyNkZGQnKTtcbiAgICAgICAgZG90LmF0dHIoJ2Rpc3BsYXknLCBudWxsKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gbGVmdCgpIHtcbiAgICAgICAgcGF0aC5zdHlsZSgnbWl4LWJsZW5kLW1vZGUnLCAnbXVsdGlwbHknKS5hdHRyKCdzdHJva2UnLCBudWxsKTtcbiAgICAgICAgZG90LmF0dHIoJ2Rpc3BsYXknLCAnbm9uZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAqL1xuICB9XG5cbiAgcHJpdmF0ZSBjaGFuZ2VBeGlzQ29sb3IoXG4gICAgICBheGlzOiBkMy5TZWxlY3Rpb248U1ZHR0VsZW1lbnQsIHVua25vd24sIG51bGwsIHVuZGVmaW5lZD4sIGNvbmZpZzogYW55KSB7XG4gICAgdGhpcy5kM1NlcnZpY2UuY2hhbmdlQXhpc0NvbG9yKGF4aXMsIGNvbmZpZyk7XG4gIH1cblxuICBwcml2YXRlIHJlbW92ZUF4aXNUaWNrcyhcbiAgICAgIGF4aXM6IGQzLlNlbGVjdGlvbjxTVkdHRWxlbWVudCwgdW5rbm93biwgbnVsbCwgdW5kZWZpbmVkPikge1xuICAgIHRoaXMuZDNTZXJ2aWNlLnJlbW92ZUF4aXNUaWNrcyhheGlzKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkTGFiZWxBeGlzWShcbiAgICAgIHN2ZzogZDMuU2VsZWN0aW9uPFNWR0dFbGVtZW50LCB1bmtub3duLCBudWxsLCB1bmRlZmluZWQ+LFxuICAgICAgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICBzdmcuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICdyb3RhdGUoMCknKVxuICAgICAgICAuYXR0cigneScsIDAgLSB0aGlzLm9wdGlvbnMubWFyZ2luLnRvcCAvIDIpXG4gICAgICAgIC5hdHRyKCd4JywgMClcbiAgICAgICAgLmF0dHIoJ2R5JywgJzFlbScpXG4gICAgICAgIC5zdHlsZSgndGV4dC1hbmNob3InLCAnc3RhcnQnKVxuXG4gICAgICAgIC50ZXh0KHRoaXMub3B0aW9ucy55QXhpc0xhYmVsKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkTGFiZWxBeGlzWChcbiAgICAgIHN2ZzogZDMuU2VsZWN0aW9uPFNWR0dFbGVtZW50LCB1bmtub3duLCBudWxsLCB1bmRlZmluZWQ+LCB3aWR0aDogbnVtYmVyLFxuICAgICAgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICBzdmcuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmF0dHIoXG4gICAgICAgICAgICAndHJhbnNmb3JtJyxcbiAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIHdpZHRoIC8gMiArICcgLCcgK1xuICAgICAgICAgICAgICAgIChoZWlnaHQgKyB0aGlzLm9wdGlvbnMubWFyZ2luLnRvcCAtIDE1KSArICcpJylcbiAgICAgICAgLnN0eWxlKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAudGV4dCh0aGlzLm9wdGlvbnMueEF4aXNMYWJlbCk7XG4gIH1cblxuICBwcml2YXRlIGdldFhkb21haW4oKTogRGF0ZVtdIHtcbiAgICBjb25zdCBkb21haW5FeHRlbnQgPSBkMy5leHRlbnQodGhpcy5sYWJlbHMsIChkKSA9PiBkKSBhcyBhbnlbXTtcbiAgICByZXR1cm4gZG9tYWluRXh0ZW50Lm1hcCgoZCkgPT4gbmV3IERhdGUoZCkpO1xuICB9XG5cbiAgbGVhc3QoYXJyOiBhbnlbXSwgZmlsdGVyRnVuOiBhbnksIHBvczogYW55LCB5bTogYW55KSB7XG4gICAgY29uc3QgdGVtcFZhbHVlcyA9IGFyci5tYXAoKGQpID0+IGZpbHRlckZ1bihkKSk7XG4gICAgY29uc3QgbWluTnVtID0gTWF0aC5taW4oLi4udGVtcFZhbHVlcyk7XG4gICAgbGV0IGdyYXBoSG92ZXJlZDtcbiAgICBsZXQgbWluaW1heCA9IHRlbXBWYWx1ZXNbMF07XG4gICAgbGV0IG1pblBvcyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCB0ZW1wVmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGVtcFZhbHVlc1tpXTtcbiAgICAgIGlmIChlbGVtZW50ID49IG1pbmltYXgpIHtcbiAgICAgICAgbWluUG9zID0gaTtcbiAgICAgICAgbWluaW1heCA9IGVsZW1lbnQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZ3JhcGhIb3ZlcmVkID0gYXJyW21pblBvc107XG4gICAgcmV0dXJuIGdyYXBoSG92ZXJlZDtcbiAgfVxuXG4gIC8vIGdyaWRsaW5lcyBpbiB4IGF4aXMgZnVuY3Rpb25cbiAgcHJpdmF0ZSBtYWtlX3hfZ3JpZGxpbmVzKHgpIHtcbiAgICByZXR1cm4gZDMuYXhpc0JvdHRvbSh4KS50aWNrcyh0aGlzLm9wdGlvbnMuZ3JpZFRpY2tzKTtcbiAgfVxuXG4gIC8vIGdyaWRsaW5lcyBpbiB5IGF4aXMgZnVuY3Rpb25cbiAgcHJpdmF0ZSBtYWtlX3lfZ3JpZGxpbmVzKHkpIHtcbiAgICByZXR1cm4gZDMuYXhpc0xlZnQoeSkudGlja3ModGhpcy5vcHRpb25zLmdyaWRUaWNrcyk7XG4gIH1cblxuICBvblJlc2l6ZUV2ZW50KCk6IHZvaWQge1xuICAgIHRoaXMub25SZXNpemUkLnBpcGUoZGVib3VuY2VUaW1lKDIwMCkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBjb25zdCBzdmdFeGlzdCA9IGQzLnNlbGVjdCh0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50KS5zZWxlY3QoJ3N2ZycpO1xuICAgICAgaWYgKHN2Z0V4aXN0KSB7XG4gICAgICAgIHN2Z0V4aXN0LnJlbW92ZSgpO1xuICAgICAgfVxuICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICB9KTtcbiAgfVxufVxuIl19