ng-d3-graphs
Version:
<img src="./assets/ng-d3.png" alt="drawing" width="250" height="250"/>
273 lines (265 loc) • 36.6 kB
JavaScript
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