ngx-beautiful-charts
Version:
A library to create charts in Angular
311 lines • 32.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, Input, ElementRef } from '@angular/core';
import { colorSchemes } from '../../constants/color-schemes';
import { TimelineChartService } from './timeline-chart.service';
import { GlobalParametersService } from '../../global/global-parameters.service';
export class TimelineChartComponent {
/**
* @param {?} timelineChartService
* @param {?} globalParametersService
* @param {?} currentElement
*/
constructor(timelineChartService, globalParametersService, currentElement) {
this.timelineChartService = timelineChartService;
this.globalParametersService = globalParametersService;
this.currentElement = currentElement;
this.colorScheme = 'colorful';
this.customColorScheme = [];
this.xPadding = 60;
this.yPadding = this.xPadding / 2;
this.timeData = [];
}
/**
* @return {?}
*/
computeBarDimensions() {
this.barWidth = this.timelineChartService.rectHeight * .05;
this.barStartY = this.yPadding + this.timelineChartService.rectHeight / 2 - this.barWidth / 2;
this.barEndY = this.yPadding + this.timelineChartService.rectHeight / 2 + this.barWidth / 2;
}
/**
* @return {?}
*/
setColors() {
/** @type {?} */
let cnt = 0;
for (const oneTimeData of this.data) {
if (!oneTimeData.color) {
if (this.customColorScheme.length > 0) {
oneTimeData.color = this.customColorScheme[cnt % this.customColorScheme.length];
}
else {
oneTimeData.color = colorSchemes[this.colorScheme][cnt % 10];
}
cnt++;
}
}
}
/**
* @return {?}
*/
setDimensions() {
if (this.width && !this.height)
this.height = this.width / 2;
else if (!this.width && this.height)
this.width = this.height * 2;
else if (!this.width && !this.height) {
/** @type {?} */
const host = this.currentElement.nativeElement;
if (host.parentNode != null) {
/** @type {?} */
const dims = host.parentNode.getBoundingClientRect();
this.width = dims.width;
this.height = dims.width / 2;
}
}
// console.log('---set dimensions---');
// console.log('width: ' + this.width);
// console.log('height: ' + this.height);
// console.log('--------------------');
}
/**
* @param {?} text
* @param {?} width
* @return {?}
*/
textWrap(text, width) {
/** @type {?} */
const noOfCharactersPerLine = width / 10;
/** @type {?} */
const newLineStr = '\n';
/** @type {?} */
let done = false;
/** @type {?} */
const res = [];
do {
/** @type {?} */
let found = false;
for (let i = noOfCharactersPerLine - 1; i >= 0; i--) {
if ((text.charAt(i) === ' ')) {
res.push([text.slice(0, i), newLineStr].join(''));
text = text.slice(i + 1);
found = true;
break;
}
}
if (!found) {
res.push([text.slice(0, noOfCharactersPerLine), newLineStr].join(''));
text = text.slice(noOfCharactersPerLine);
}
if (text.length < noOfCharactersPerLine)
done = true;
} while (!done);
res.push(text);
return res;
}
/**
* @return {?}
*/
computeTimeData() {
// const distanceBetweenTimeBubbles = this.width * .8 / (this.data.length - 1);
/** @type {?} */
const minTime = Math.min(...this.data.map((/**
* @param {?} timeData
* @return {?}
*/
timeData => timeData.time)));
/** @type {?} */
const maxTime = Math.max(...this.data.map((/**
* @param {?} timeData
* @return {?}
*/
timeData => timeData.time)));
/** @type {?} */
const perTimeWidth = this.timelineChartService.rectWidth * .8 / (maxTime - minTime);
this.data.sort((/**
* @param {?} a
* @param {?} b
* @return {?}
*/
(a, b) => a.time < b.time ? -1 : a.time > b.time ? 1 : 0));
/** @type {?} */
const diffs = [];
for (let i = 1; i < this.data.length; i++) {
diffs.push(this.data[i].time - this.data[i - 1].time);
}
/** @type {?} */
const minDiff = Math.min(...diffs);
this.timeBubbleRadius = Math.min(minDiff * perTimeWidth * .4);
/** @type {?} */
const maxRadius = this.timelineChartService.rectWidth * .8 / (this.data.length - 1) * .25;
/** @type {?} */
const minRadius = this.timelineChartService.rectWidth * .8 * .04;
// console.log('max: ' + maxRadius);
// console.log('min: ' + minRadius);
if (this.timeBubbleRadius > maxRadius)
this.timeBubbleRadius = maxRadius;
if (this.timeBubbleRadius < minRadius)
this.timeBubbleRadius = minRadius;
this.textBlockHeight = this.timelineChartService.rectHeight * 2 / 16;
this.timeData = [];
/** @type {?} */
let cnt = 0;
/** @type {?} */
let up = 1;
for (const oneTimeData of this.data) {
/** @type {?} */
const color = oneTimeData.color;
/** @type {?} */
const x = (oneTimeData.time - minTime) * perTimeWidth;
/** @type {?} */
const timeBubble = {
centre: {
x,
y: this.barStartY + this.barWidth / 2
},
text: oneTimeData.displayTime ? oneTimeData.displayTime : oneTimeData.time
// oneTimeData.displayTime ?
// this.textWrap(oneTimeData.displayTime, this.timeBubbleRadius * 2) :
// [oneTimeData.time]
};
/** @type {?} */
const start = {
x,
y: (up === 1) ? this.barStartY : this.barEndY
};
/** @type {?} */
const end = {
x,
y: (up === 1) ? this.barStartY - this.timelineChartService.rectHeight / 4 : this.barEndY + this.timelineChartService.rectHeight / 4
};
/** @type {?} */
const line = 'M ' + start.x + ' ' + start.y + ' ' + end.x + ' ' + end.y;
/** @type {?} */
const textBlock = {
position: {
x,
y: (up === 1) ?
this.barStartY - this.timelineChartService.rectHeight * 7 / 16 :
this.barEndY + this.timelineChartService.rectHeight * 4 / 16
},
text: this.textWrap(oneTimeData.text, this.timeBubbleRadius * 4)
};
this.timeData.push({
timeBubble,
line,
textBlock,
color
});
up = up * -1;
cnt++;
}
}
/**
* @return {?}
*/
ngOnInit() {
this.componentID = this.globalParametersService.addNewComponent();
this.computeBarDimensions();
this.setColors();
this.timelineChartService.setValues({
componentID: this.componentID,
width: this.width,
height: this.height,
xPadding: this.xPadding,
yPadding: this.yPadding
});
/** @type {?} */
const transX = this.xPadding + this.timelineChartService.rectWidth * .1;
this.gTranslate = 'translate(' + transX + 'px, ' + this.yPadding + 'px)';
this.computeBarDimensions();
this.computeTimeData();
}
/**
* @return {?}
*/
ngOnChanges() {
this.computeBarDimensions();
this.setColors();
this.timelineChartService.setValues({
componentID: this.componentID,
width: this.width,
height: this.height,
xPadding: this.xPadding,
yPadding: this.yPadding
});
/** @type {?} */
const transX = this.xPadding + this.timelineChartService.rectWidth * .1;
this.gTranslate = 'translate(' + transX + 'px, ' + this.yPadding + 'px)';
this.computeBarDimensions();
this.computeTimeData();
}
}
TimelineChartComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-timeline-chart',
template: "<svg [attr.width]=\"width\" [attr.height]=\"height\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n <g [ngStyle]=\"{'transform': gTranslate}\">\n <rect x=\"0\" \n [attr.y]=\"barStartY\" \n [attr.width]=\"timelineChartService.rectWidth * .8\" \n [attr.height]=\"barWidth\" \n fill=\"grey\" />\n\n <g *ngFor=\"let timeDataInst of timeData\">\n <circle class=\"time-bubble\" [attr.cx]=\"timeDataInst.timeBubble.centre.x\" \n [attr.cy]=\"timeDataInst.timeBubble.centre.y\" \n [attr.r]=\"timeBubbleRadius\" [attr.fill]=\"timeDataInst.color\">\n </circle>\n\n <text class=\"time-bubble-text\" [attr.x]=\"timeDataInst.timeBubble.centre.x\"\n [attr.y]=\"timeDataInst.timeBubble.centre.y\"\n text-anchor=\"middle\" dominant-baseline=\"middle\">\n {{ timeDataInst.timeBubble.text }}\n <!-- <tspan *ngFor=\"let line of timeDataInst.timeBubble.text\" \n [attr.x]=\"timeDataInst.timeBubble.centre.x\"\n [attr.dx]=\"0\"\n [attr.dy]=\"14\">\n {{ line }}\n </tspan> -->\n </text>\n \n <path class=\"line-path\"\n [attr.d]=\"timeDataInst.line\" fill=\"none\" [attr.stroke]=\"timeDataInst.color\" />\n\n <text class=\"time-block-text\" [attr.x]=\"timeDataInst.textBlock.position.x\"\n [attr.y]=\"timeDataInst.textBlock.position.y\"\n [attr.height]=\"textBlockHeight\"\n text-anchor=\"middle\" dominant-baseline=\"middle\">\n <tspan *ngFor=\"let line of timeDataInst.textBlock.text\" \n [attr.x]=\"timeDataInst.textBlock.position.x\"\n [attr.dx]=\"0\"\n [attr.dy]=\"14\">\n {{ line }}\n </tspan>\n </text>\n\n </g>\n </g>\n</svg>\n\n",
providers: [TimelineChartService],
styles: [".time-bubble-text{font-size:12px}"]
}] }
];
/** @nocollapse */
TimelineChartComponent.ctorParameters = () => [
{ type: TimelineChartService },
{ type: GlobalParametersService },
{ type: ElementRef }
];
TimelineChartComponent.propDecorators = {
data: [{ type: Input }],
width: [{ type: Input }],
height: [{ type: Input }],
colorScheme: [{ type: Input }],
customColorScheme: [{ type: Input }]
};
if (false) {
/** @type {?} */
TimelineChartComponent.prototype.data;
/** @type {?} */
TimelineChartComponent.prototype.width;
/** @type {?} */
TimelineChartComponent.prototype.height;
/** @type {?} */
TimelineChartComponent.prototype.colorScheme;
/** @type {?} */
TimelineChartComponent.prototype.customColorScheme;
/** @type {?} */
TimelineChartComponent.prototype.componentID;
/** @type {?} */
TimelineChartComponent.prototype.xPadding;
/** @type {?} */
TimelineChartComponent.prototype.yPadding;
/** @type {?} */
TimelineChartComponent.prototype.gTranslate;
/** @type {?} */
TimelineChartComponent.prototype.barWidth;
/** @type {?} */
TimelineChartComponent.prototype.barStartY;
/** @type {?} */
TimelineChartComponent.prototype.barEndY;
/** @type {?} */
TimelineChartComponent.prototype.timeBubbleRadius;
/** @type {?} */
TimelineChartComponent.prototype.textBlockHeight;
/** @type {?} */
TimelineChartComponent.prototype.timeData;
/** @type {?} */
TimelineChartComponent.prototype.timelineChartService;
/**
* @type {?}
* @private
*/
TimelineChartComponent.prototype.globalParametersService;
/**
* @type {?}
* @private
*/
TimelineChartComponent.prototype.currentElement;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZWxpbmUtY2hhcnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWJlYXV0aWZ1bC1jaGFydHMvIiwic291cmNlcyI6WyJsaWIvdGltZWxpbmUtY2hhcnQvdGltZWxpbmUtY2hhcnQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLEtBQUssRUFBYSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBUWpGLE1BQU0sT0FBTyxzQkFBc0I7Ozs7OztJQTBKakMsWUFBbUIsb0JBQTBDLEVBQ3pDLHVCQUFnRCxFQUNoRCxjQUEwQjtRQUYzQix5QkFBb0IsR0FBcEIsb0JBQW9CLENBQXNCO1FBQ3pDLDRCQUF1QixHQUF2Qix1QkFBdUIsQ0FBeUI7UUFDaEQsbUJBQWMsR0FBZCxjQUFjLENBQVk7UUF2SnJDLGdCQUFXLEdBQUcsVUFBVSxDQUFDO1FBQ3pCLHNCQUFpQixHQUFhLEVBQUUsQ0FBQztRQUkxQyxhQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2QsYUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBUzdCLGFBQVEsR0FBRyxFQUFFLENBQUM7SUF5SWQsQ0FBQzs7OztJQXJJRCxvQkFBb0I7UUFDbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQztRQUMzRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENB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Q0FBWTs7SUFDWiwwQ0FBYzs7SUFDZCwwQ0FBNkI7O0lBQzdCLDRDQUFtQjs7SUFFbkIsMENBQWlCOztJQUNqQiwyQ0FBa0I7O0lBQ2xCLHlDQUFnQjs7SUFFaEIsa0RBQXlCOztJQUN6QixpREFBd0I7O0lBQ3hCLDBDQUFjOztJQXNJRixzREFBaUQ7Ozs7O0lBQ2pELHlEQUF3RDs7Ozs7SUFDeEQsZ0RBQWtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPbkNoYW5nZXMsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGNvbG9yU2NoZW1lcyB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy9jb2xvci1zY2hlbWVzJztcbmltcG9ydCB7IFRpbWVsaW5lQ2hhcnRTZXJ2aWNlIH0gZnJvbSAnLi90aW1lbGluZS1jaGFydC5zZXJ2aWNlJztcbmltcG9ydCB7IEdsb2JhbFBhcmFtZXRlcnNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vZ2xvYmFsL2dsb2JhbC1wYXJhbWV0ZXJzLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtdGltZWxpbmUtY2hhcnQnLFxuICB0ZW1wbGF0ZVVybDogJy4vdGltZWxpbmUtY2hhcnQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90aW1lbGluZS1jaGFydC5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtUaW1lbGluZUNoYXJ0U2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgVGltZWxpbmVDaGFydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcblxuICBASW5wdXQoKSBkYXRhOiBhbnk7XG4gIEBJbnB1dCgpIHdpZHRoOiBudW1iZXI7XG4gIEBJbnB1dCgpIGhlaWdodDogbnVtYmVyO1xuICBASW5wdXQoKSBjb2xvclNjaGVtZSA9ICdjb2xvcmZ1bCc7XG4gIEBJbnB1dCgpIGN1c3RvbUNvbG9yU2NoZW1lOiBzdHJpbmdbXSA9IFtdO1xuXG5cbiAgY29tcG9uZW50SUQ7XG4gIHhQYWRkaW5nID0gNjA7XG4gIHlQYWRkaW5nID0gdGhpcy54UGFkZGluZyAvIDI7XG4gIGdUcmFuc2xhdGU6IHN0cmluZztcblxuICBiYXJXaWR0aDogbnVtYmVyO1xuICBiYXJTdGFydFk6IG51bWJlcjtcbiAgYmFyRW5kWTogbnVtYmVyO1xuXG4gIHRpbWVCdWJibGVSYWRpdXM6IG51bWJlcjtcbiAgdGV4dEJsb2NrSGVpZ2h0OiBudW1iZXI7XG4gIHRpbWVEYXRhID0gW107XG5cblxuXG4gIGNvbXB1dGVCYXJEaW1lbnNpb25zKCkge1xuICAgIHRoaXMuYmFyV2lkdGggPSB0aGlzLnRpbWVsaW5lQ2hhcnRTZXJ2aWNlLnJlY3RIZWlnaHQgKiAuMDU7XG4gICAgdGhpcy5iYXJTdGFydFkgPSB0aGlzLnlQYWRkaW5nICsgdGhpcy50aW1lbGluZUNoYXJ0U2VydmljZS5yZWN0SGVpZ2h0IC8gMiAtIHRoaXMuYmFyV2lkdGggLyAyO1xuICAgIHRoaXMuYmFyRW5kWSA9IHRoaXMueVBhZGRpbmcgKyB0aGlzLnRpbWVsaW5lQ2hhcnRTZXJ2aWNlLnJlY3RIZWlnaHQgLyAyICsgdGhpcy5iYXJXaWR0aCAvIDI7XG4gIH1cblxuICBzZXRDb2xvcnMoKSB7XG4gICAgbGV0IGNudCA9IDA7XG4gICAgZm9yIChjb25zdCBvbmVUaW1lRGF0YSBvZiB0aGlzLmRhdGEpIHtcbiAgICAgIGlmICghb25lVGltZURhdGEuY29sb3IpIHtcbiAgICAgICAgaWYgKHRoaXMuY3VzdG9tQ29sb3JTY2hlbWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgIG9uZVRpbWVEYXRhLmNvbG9yID0gdGhpcy5jdXN0b21Db2xvclNjaGVtZVtjbnQgJSB0aGlzLmN1c3RvbUNvbG9yU2NoZW1lLmxlbmd0aF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb25lVGltZURhdGEuY29sb3IgPSBjb2xvclNjaGVtZXNbdGhpcy5jb2xvclNjaGVtZV1bY250ICUgMTBdO1xuICAgICAgICB9XG4gICAgICAgIGNudCsrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldERpbWVuc2lvbnMoKSB7XG4gICAgaWYgKHRoaXMud2lkdGggJiYgIXRoaXMuaGVpZ2h0KSB0aGlzLmhlaWdodCA9IHRoaXMud2lkdGggLyAyO1xuICAgIGVsc2UgaWYgKCF0aGlzLndpZHRoICYmIHRoaXMuaGVpZ2h0KSB0aGlzLndpZHRoID0gdGhpcy5oZWlnaHQgKiAyO1xuICAgIGVsc2UgaWYgKCF0aGlzLndpZHRoICYmICF0aGlzLmhlaWdodCkge1xuICAgICAgY29uc3QgaG9zdCA9IHRoaXMuY3VycmVudEVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgIGlmIChob3N0LnBhcmVudE5vZGUgIT0gbnVsbCkge1xuICAgICAgICBjb25zdCBkaW1zID0gaG9zdC5wYXJlbnROb2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLndpZHRoID0gZGltcy53aWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSBkaW1zLndpZHRoIC8gMjtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gY29uc29sZS5sb2coJy0tLXNldCBkaW1lbnNpb25zLS0tJyk7XG4gICAgLy8gY29uc29sZS5sb2coJ3dpZHRoOiAnICsgdGhpcy53aWR0aCk7XG4gICAgLy8gY29uc29sZS5sb2coJ2hlaWdodDogJyArIHRoaXMuaGVpZ2h0KTtcbiAgICAvLyBjb25zb2xlLmxvZygnLS0tLS0tLS0tLS0tLS0tLS0tLS0nKTtcbiAgfVxuXG4gIHRleHRXcmFwKHRleHQsIHdpZHRoKSB7XG4gICAgY29uc3Qgbm9PZkNoYXJhY3RlcnNQZXJMaW5lID0gd2lkdGggLyAxMDtcbiAgICBjb25zdCBuZXdMaW5lU3RyID0gJ1xcbic7XG4gICAgbGV0IGRvbmUgPSBmYWxzZTtcbiAgICBjb25zdCByZXMgPSBbXTtcbiAgICBkbyB7XG4gICAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICAgIGZvciAobGV0IGkgPSBub09mQ2hhcmFjdGVyc1BlckxpbmUgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIGlmICgodGV4dC5jaGFyQXQoaSkgID09PSAnICcpKSB7XG4gICAgICAgICAgICAgIHJlcy5wdXNoKFt0ZXh0LnNsaWNlKDAsIGkpLCBuZXdMaW5lU3RyXS5qb2luKCcnKSk7XG4gICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKGkgKyAxKTtcbiAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIWZvdW5kKSB7XG4gICAgICAgICAgcmVzLnB1c2goW3RleHQuc2xpY2UoMCwgbm9PZkNoYXJhY3RlcnNQZXJMaW5lKSwgbmV3TGluZVN0cl0uam9pbignJykpO1xuICAgICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKG5vT2ZDaGFyYWN0ZXJzUGVyTGluZSk7XG4gICAgICB9XG4gICAgICBpZiAodGV4dC5sZW5ndGggPCBub09mQ2hhcmFjdGVyc1BlckxpbmUpIGRvbmUgPSB0cnVlO1xuICAgIH0gd2hpbGUgKCFkb25lKTtcbiAgICByZXMucHVzaCh0ZXh0KTtcbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgY29tcHV0ZVRpbWVEYXRhKCkge1xuICAgIC8vIGNvbnN0IGRpc3RhbmNlQmV0d2VlblRpbWVCdWJibGVzID0gdGhpcy53aWR0aCAqIC44IC8gKHRoaXMuZGF0YS5sZW5ndGggLSAxKTtcbiAgICBjb25zdCBtaW5UaW1lID0gTWF0aC5taW4oLi4udGhpcy5kYXRhLm1hcCh0aW1lRGF0YSA9PiB0aW1lRGF0YS50aW1lKSk7XG4gICAgY29uc3QgbWF4VGltZSA9IE1hdGgubWF4KC4uLnRoaXMuZGF0YS5tYXAodGltZURhdGEgPT4gdGltZURhdGEudGltZSkpO1xuICAgIGNvbnN0IHBlclRpbWVXaWR0aCA9IHRoaXMudGltZWxpbmVDaGFydFNlcnZpY2UucmVjdFdpZHRoICogLjggLyAobWF4VGltZSAtIG1pblRpbWUpO1xuICAgIHRoaXMuZGF0YS5zb3J0KChhLCBiKSA9PiBhLnRpbWUgPCBiLnRpbWUgPyAtMSA6IGEudGltZSA+IGIudGltZSA/IDEgOiAwKTtcbiAgICBjb25zdCBkaWZmcyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgdGhpcy5kYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBkaWZmcy5wdXNoKHRoaXMuZGF0YVtpXS50aW1lIC0gdGhpcy5kYXRhW2kgLSAxXS50aW1lKTtcbiAgICB9XG4gICAgY29uc3QgbWluRGlmZiA9IE1hdGgubWluKC4uLmRpZmZzKTtcbiAgICB0aGlzLnRpbWVCdWJibGVSYWRpdXMgPSBNYXRoLm1pbihtaW5EaWZmICogcGVyVGltZVdpZHRoICogLjQpO1xuICAgIGNvbnN0IG1heFJhZGl1cyA9IHRoaXMudGltZWxpbmVDaGFydFNlcnZpY2UucmVjdFdpZHRoICogLjggLyAodGhpcy5kYXRhLmxlbmd0aCAtIDEpICogLjI1O1xuICAgIGNvbnN0IG1pblJhZGl1cyA9IHRoaXMudGltZWxpbmVDaGFydFNlcnZpY2UucmVjdFdpZHRoICogLjggKiAuMDQ7XG5cbiAgICAvLyBjb25zb2xlLmxvZygnbWF4OiAnICsgbWF4UmFkaXVzKTtcbiAgICAvLyBjb25zb2xlLmxvZygnbWluOiAnICsgbWluUmFkaXVzKTtcblxuXG4gICAgaWYgKHRoaXMudGltZUJ1YmJsZVJhZGl1cyA+IG1heFJhZGl1cykgdGhpcy50aW1lQnViYmxlUmFkaXVzID0gbWF4UmFkaXVzO1xuICAgIGlmICh0aGlzLnRpbWVCdWJibGVSYWRpdXMgPCBtaW5SYWRpdXMpIHRoaXMudGltZUJ1YmJsZVJhZGl1cyA9IG1pblJhZGl1cztcbiAgICB0aGlzLnRleHRCbG9ja0hlaWdodCA9IHRoaXMudGltZWxpbmVDaGFydFNlcnZpY2UucmVjdEhlaWdodCAqIDIgLyAxNjtcbiAgICB0aGlzLnRpbWVEYXRhID0gW107XG4gICAgbGV0IGNudCA9IDA7XG4gICAgbGV0IHVwID0gMTtcbiAgICBmb3IgKGNvbnN0IG9uZVRpbWVEYXRhIG9mIHRoaXMuZGF0YSkge1xuICAgICAgY29uc3QgY29sb3IgPSBvbmVUaW1lRGF0YS5jb2xvcjtcbiAgICAgIGNvbnN0IHggPSAob25lVGltZURhdGEudGltZSAtIG1pblRpbWUpICogcGVyVGltZVdpZHRoO1xuICAgICAgY29uc3QgdGltZUJ1YmJsZSA9IHtcbiAgICAgICAgY2VudHJlOiB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5OiB0aGlzLmJhclN0YXJ0WSArIHRoaXMuYmFyV2lkdGggLyAyXG4gICAgICAgIH0sXG4gICAgICAgIHRleHQ6IG9uZVRpbWVEYXRhLmRpc3BsYXlUaW1lID8gb25lVGltZURhdGEuZGlzcGxheVRpbWUgOiBvbmVUaW1lRGF0YS50aW1lXG4gICAgICAgIC8vIG9uZVRpbWVEYXRhLmRpc3BsYXlUaW1lID9cbiAgICAgICAgLy8gdGhpcy50ZXh0V3JhcChvbmVUaW1lRGF0YS5kaXNwbGF5VGltZSwgdGhpcy50aW1lQnViYmxlUmFkaXVzICogMikgOlxuICAgICAgICAvLyBbb25lVGltZURhdGEudGltZV1cbiAgICAgIH07XG4gICAgICBjb25zdCBzdGFydCA9IHtcbiAgICAgICAgeCxcbiAgICAgICAgeTogKHVwID09PSAxKSA/IHRoaXMuYmFyU3RhcnRZIDogdGhpcy5iYXJFbmRZXG4gICAgICB9O1xuICAgICAgY29uc3QgZW5kID0ge1xuICAgICAgICB4LFxuICAgICAgICB5OiAodXAgPT09IDEpID8gdGhpcy5iYXJTdGFydFkgLSB0aGlzLnRpbWVsaW5lQ2hhcnRTZXJ2aWNlLnJlY3RIZWlnaHQgLyA0IDogdGhpcy5iYXJFbmRZICsgdGhpcy50aW1lbGluZUNoYXJ0U2VydmljZS5yZWN0SGVpZ2h0IC8gNFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGxpbmUgPSAnTSAnICsgc3RhcnQueCArICcgJyArIHN0YXJ0LnkgKyAnICcgKyBlbmQueCArICcgJyArIGVuZC55O1xuXG4gICAgICBjb25zdCB0ZXh0QmxvY2sgPSB7XG4gICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgeCxcbiAgICAgICAgICB5OiAodXAgPT09IDEpID9cbiAgICAgICAgICB0aGlzLmJhclN0YXJ0WSAtIHRoaXMudGltZWxpbmVDaGFydFNlcnZpY2UucmVjdEhlaWdodCAqIDcgLyAxNiA6XG4gICAgICAgICAgdGhpcy5iYXJFbmRZICsgdGhpcy50aW1lbGluZUNoYXJ0U2VydmljZS5yZWN0SGVpZ2h0ICogNCAvIDE2XG4gICAgICAgIH0sXG4gICAgICAgIHRleHQ6IHRoaXMudGV4dFdyYXAob25lVGltZURhdGEudGV4dCwgdGhpcy50aW1lQnViYmxlUmFkaXVzICogNClcbiAgICAgIH07XG4gICAgICB0aGlzLnRpbWVEYXRhLnB1c2goe1xuICAgICAgICB0aW1lQnViYmxlLFxuICAgICAgICBsaW5lLFxuICAgICAgICB0ZXh0QmxvY2ssXG4gICAgICAgIGNvbG9yXG4gICAgICB9KTtcbiAgICAgIHVwID0gdXAgKiAtMTtcbiAgICAgIGNudCsrO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyB0aW1lbGluZUNoYXJ0U2VydmljZTogVGltZWxpbmVDaGFydFNlcnZpY2UsXG4gICAgICAgICAgICAgIHByaXZhdGUgZ2xvYmFsUGFyYW1ldGVyc1NlcnZpY2U6IEdsb2JhbFBhcmFtZXRlcnNTZXJ2aWNlLFxuICAgICAgICAgICAgICBwcml2YXRlIGN1cnJlbnRFbGVtZW50OiBFbGVtZW50UmVmKSB7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmNvbXBvbmVudElEID0gdGhpcy5nbG9iYWxQYXJhbWV0ZXJzU2VydmljZS5hZGROZXdDb21wb25lbnQoKTtcbiAgICB0aGlzLmNvbXB1dGVCYXJEaW1lbnNpb25zKCk7XG4gICAgdGhpcy5zZXRDb2xvcnMoKTtcbiAgICB0aGlzLnRpbWVsaW5lQ2hhcnRTZXJ2aWNlLnNldFZhbHVlcyh7XG4gICAgICBjb21wb25lbnRJRDogdGhpcy5jb21wb25lbnRJRCxcbiAgICAgIHdpZHRoOiB0aGlzLndpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLmhlaWdodCxcbiAgICAgIHhQYWRkaW5nOiB0aGlzLnhQYWRkaW5nLFxuICAgICAgeVBhZGRpbmc6IHRoaXMueVBhZGRpbmdcbiAgICB9KTtcbiAgICBjb25zdCB0cmFuc1ggPSB0aGlzLnhQYWRkaW5nICsgdGhpcy50aW1lbGluZUNoYXJ0U2VydmljZS5yZWN0V2lkdGggKiAuMTtcbiAgICB0aGlzLmdUcmFuc2xhdGUgPSAndHJhbnNsYXRlKCcgKyB0cmFuc1ggKyAncHgsICcgKyB0aGlzLnlQYWRkaW5nICsgJ3B4KSc7XG4gICAgdGhpcy5jb21wdXRlQmFyRGltZW5zaW9ucygpO1xuICAgIHRoaXMuY29tcHV0ZVRpbWVEYXRhKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcygpIHtcbiAgICB0aGlzLmNvbXB1dGVCYXJEaW1lbnNpb25zKCk7XG4gICAgdGhpcy5zZXRDb2xvcnMoKTtcbiAgICB0aGlzLnRpbWVsaW5lQ2hhcnRTZXJ2aWNlLnNldFZhbHVlcyh7XG4gICAgICBjb21wb25lbnRJRDogdGhpcy5jb21wb25lbnRJRCxcbiAgICAgIHdpZHRoOiB0aGlzLndpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLmhlaWdodCxcbiAgICAgIHhQYWRkaW5nOiB0aGlzLnhQYWRkaW5nLFxuICAgICAgeVBhZGRpbmc6IHRoaXMueVBhZGRpbmdcbiAgICB9KTtcbiAgICBjb25zdCB0cmFuc1ggPSB0aGlzLnhQYWRkaW5nICsgdGhpcy50aW1lbGluZUNoYXJ0U2VydmljZS5yZWN0V2lkdGggKiAuMTtcbiAgICB0aGlzLmdUcmFuc2xhdGUgPSAndHJhbnNsYXRlKCcgKyB0cmFuc1ggKyAncHgsICcgKyB0aGlzLnlQYWRkaW5nICsgJ3B4KSc7XG4gICAgdGhpcy5jb21wdXRlQmFyRGltZW5zaW9ucygpO1xuICAgIHRoaXMuY29tcHV0ZVRpbWVEYXRhKCk7XG4gIH1cbn1cbiJdfQ==