ngx-beautiful-charts
Version:
A library to create charts in Angular
378 lines • 40.5 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 { SunburstChartService } from './sunburst-chart.service';
import { GlobalParametersService } from '../../global/global-parameters.service';
export class SunburstChartComponent {
/**
* @param {?} sunburstChartService
* @param {?} globalParametersService
* @param {?} currentElement
*/
constructor(sunburstChartService, globalParametersService, currentElement) {
this.sunburstChartService = sunburstChartService;
this.globalParametersService = globalParametersService;
this.currentElement = currentElement;
this.colorScheme = 'colorful';
this.customColorScheme = [];
this.xPadding = 60;
this.yPadding = this.xPadding / 2;
this.sunDepth = 0;
}
/**
* @param {?} data
* @param {?} i
* @param {?=} color
* @return {?}
*/
getRefinedData(data, i, color = null) {
for (const sbData of data) {
sbData.level = i;
if (color && !sbData.color)
sbData.color = color;
if (sbData.level > this.sunDepth)
this.sunDepth = sbData.level;
if (sbData.children) {
if (sbData.children.length > 0) {
sbData.children = this.getRefinedData(sbData.children, i + 1, sbData.color);
sbData.value = sbData.children.map((/**
* @param {?} child
* @return {?}
*/
child => child.value)).reduce((/**
* @param {?} sum
* @param {?} curr
* @return {?}
*/
(sum, curr) => sum + curr));
}
else {
if (!sbData.value)
sbData.value = 0;
}
}
else if (!sbData.value)
sbData.value = 0;
}
return data;
}
/**
* @return {?}
*/
setDimensions() {
if (this.width)
this.height = this.width - this.xPadding;
else {
/** @type {?} */
const host = this.currentElement.nativeElement;
if (host.parentNode != null) {
/** @type {?} */
const dims = host.parentNode.getBoundingClientRect();
this.width = dims.width;
this.height = this.width - this.xPadding;
}
}
// console.log('---set dimensions---');
// console.log('width: ' + this.width);
// console.log('height: ' + this.height);
// console.log('--------------------');
}
/**
* @param {?} data
* @param {?} sum
* @param {?} angleRange
* @param {?} rotation
* @return {?}
*/
generateSlice(data, sum, angleRange, rotation) {
/** @type {?} */
const perc = data.value / sum;
/** @type {?} */
const angle = angleRange * perc;
// const angleMod = (angle > 180 ) ? 360 - angle : angle;
/** @type {?} */
const angleRad = angle * Math.PI / 180;
/** @type {?} */
const largeArc = (angle > 180) ? 1 : 0;
/** @type {?} */
const textRotation = (270 + angle / 2) % 360;
/** @type {?} */
const textX = (data.level - 1) * this.sunSliceWidth + this.sunSliceWidth / 2;
/** @type {?} */
let textRotationString = 'rotate(' + textRotation + 'deg)';
if (rotation > 180) {
/** @type {?} */
const x = textX * 2;
textRotationString = textRotationString + ' scale(-1,-1) translateX(' + -x + 'px)';
}
/** @type {?} */
let path;
/** @type {?} */
let hoverPath;
if (data.level === 1) {
path = 'M 0 0 0 ' + -this.sunSliceWidth + ' A '
+ this.sunSliceWidth + ' ' + this.sunSliceWidth
+ ' 0 ' + largeArc + ' 1 ' + this.sunSliceWidth * Math.sin(angleRad) + ' '
+ -this.sunSliceWidth * Math.cos(angleRad) + ' z';
/** @type {?} */
const hoverRadius = this.sunSliceWidth * 1.1;
hoverPath = 'M 0 0 0 ' + -hoverRadius + ' A '
+ hoverRadius + ' ' + hoverRadius
+ ' 0 ' + largeArc + ' 1 ' + hoverRadius * Math.sin(angleRad) + ' '
+ -hoverRadius * Math.cos(angleRad) + ' z';
}
else if (data.level > 1) {
/** @type {?} */
const sunSliceInnerRadius = this.sunRadius / (this.sunDepth) * (data.level - 1);
/** @type {?} */
const sunSliceOuterRadius = this.sunRadius / (this.sunDepth) * data.level;
path = 'M 0 ' + -sunSliceInnerRadius + ' 0 ' + -sunSliceOuterRadius
+ ' A ' + sunSliceOuterRadius + ' ' + sunSliceOuterRadius
+ ' 0 ' + largeArc + ' 1 ' + sunSliceOuterRadius * Math.sin(angleRad) + ' '
+ -sunSliceOuterRadius * Math.cos(angleRad)
+ ' L ' + sunSliceInnerRadius * Math.sin(angleRad) + ' '
+ -sunSliceInnerRadius * Math.cos(angleRad) + ' A '
+ sunSliceInnerRadius + ' ' + sunSliceInnerRadius
+ ' 0 ' + largeArc + ' 0 0 ' + -sunSliceInnerRadius + ' z';
/** @type {?} */
const hoverSliceOuterRadius = sunSliceOuterRadius + this.sunSliceWidth * 0.1;
hoverPath = 'M 0 ' + -sunSliceInnerRadius + ' 0 ' + -hoverSliceOuterRadius
+ ' A ' + hoverSliceOuterRadius + ' ' + hoverSliceOuterRadius
+ ' 0 ' + largeArc + ' 1 ' + hoverSliceOuterRadius * Math.sin(angleRad) + ' '
+ -hoverSliceOuterRadius * Math.cos(angleRad)
+ ' L ' + sunSliceInnerRadius * Math.sin(angleRad) + ' '
+ -sunSliceInnerRadius * Math.cos(angleRad) + ' A '
+ sunSliceInnerRadius + ' ' + sunSliceInnerRadius
+ ' 0 ' + largeArc + ' 0 0 ' + -sunSliceInnerRadius + ' z';
}
// console.log(hoverPath);
/** @type {?} */
const sunSlice = {
perc,
name: data.name,
color: data.color,
hoverD: hoverPath,
rotation: 'rotate(' + rotation + 'deg)',
textRotation: textRotationString,
textX,
d: path,
angle,
hover: false,
children: null
};
this.levelSunSlices[data.level - 1].push(sunSlice);
return sunSlice;
}
/**
* @param {?} data
* @param {?} angleRange
* @param {?} rotation
* @return {?}
*/
generateSunSlicesForAngle(data, angleRange, rotation) {
/** @type {?} */
const sunSlices = [];
/** @type {?} */
let sum = 0;
for (const val of data) {
sum = sum + val.value;
}
for (const val of data) {
/** @type {?} */
const sunSlice = this.generateSlice(val, sum, angleRange, rotation);
if (val.children && val.children.length > 0) {
sunSlice.children = this.generateSunSlicesForAngle(val.children, sunSlice.angle, rotation);
}
// console.log(val);
// console.log(sunSlice);
sunSlices.push(sunSlice);
rotation += sunSlice.angle;
}
return sunSlices;
}
/**
* @param {?} data
* @return {?}
*/
generateSunSlices(data) {
return this.generateSunSlicesForAngle(data, 360, 0);
}
/**
* @return {?}
*/
initiateLevelSunSlices() {
this.levelSunSlices = [];
for (let level = 1; level <= this.sunDepth; level++) {
this.levelSunSlices.push([]);
}
}
/**
* @return {?}
*/
setColors() {
/** @type {?} */
let cnt = 0;
for (const slice of this.data) {
if (!slice.color) {
if (this.customColorScheme.length > 0) {
slice.color = this.customColorScheme[cnt % this.customColorScheme.length];
}
else {
slice.color = colorSchemes[this.colorScheme][cnt % 10];
}
cnt++;
}
}
}
/**
* @return {?}
*/
ngOnInit() {
this.componentID = this.globalParametersService.addNewComponent();
// console.log('service (oninitsun) color scheme: ' + this.sunburstChartService.colorScheme);
this.setColors();
this.setDimensions();
this.sunburstChartService.setValues({
componentID: this.componentID,
width: this.width,
height: this.height,
xPadding: this.xPadding,
yPadding: this.yPadding,
data: this.data
});
this.sunRadius = this.sunburstChartService.sunRadius;
this.dataRefined = this.getRefinedData(this.data, 1);
// console.log('data refined: ');
// console.log(this.dataRefined);
this.initiateLevelSunSlices();
// console.log(this.sunDepth);
// console.log('level sun slices: ');
// console.log(this.levelSunSlices);
// this.hoverPieRadius = this.sunburstChartService.sunRadius / this.sunDepth * 1.05;
this.sunSliceWidth = this.sunRadius / this.sunDepth;
this.sunSlices = this.generateSunSlices(this.dataRefined);
// console.log(this.hoverPieRadius);
this.cX = this.xPadding + this.sunRadius;
this.cY = this.yPadding + this.sunRadius;
/** @type {?} */
const translateX = this.xPadding + this.sunRadius;
/** @type {?} */
const translateY = this.yPadding + this.sunRadius;
this.gTranslate = 'translate(' + translateX + 'px, ' + translateY + 'px)';
/** @type {?} */
const hoverTranslateXY = this.sunRadius * 0.08;
this.hoverTranslate = 'translate(' + hoverTranslateXY + 'px, ' + -hoverTranslateXY + 'px)';
}
/**
* @return {?}
*/
ngOnChanges() {
// console.log('service (onchangessun) color scheme: ' + this.sunburstChartService.colorScheme);
this.setColors();
this.setDimensions();
this.sunburstChartService.setValues({
componentID: this.componentID,
width: this.width,
height: this.height,
xPadding: this.xPadding,
yPadding: this.yPadding,
data: this.data
});
this.sunRadius = this.sunburstChartService.sunRadius;
this.dataRefined = this.getRefinedData(this.data, 1);
// console.log('data refined: ');
// console.log(this.dataRefined);
this.initiateLevelSunSlices();
// console.log(this.sunDepth);
// console.log('level sun slices: ');
// console.log(this.levelSunSlices);
// this.hoverPieRadius = this.sunburstChartService.sunRadius / this.sunDepth * 1.05;
this.sunSliceWidth = this.sunRadius / this.sunDepth;
this.sunSlices = this.generateSunSlices(this.dataRefined);
// console.log(this.hoverPieRadius);
this.cX = this.xPadding + this.sunRadius;
this.cY = this.yPadding + this.sunRadius;
/** @type {?} */
const translateX = this.xPadding + this.sunRadius;
/** @type {?} */
const translateY = this.yPadding + this.sunRadius;
this.gTranslate = 'translate(' + translateX + 'px, ' + translateY + 'px)';
/** @type {?} */
const hoverTranslateXY = this.sunRadius * 0.08;
this.hoverTranslate = 'translate(' + hoverTranslateXY + 'px, ' + -hoverTranslateXY + 'px)';
}
}
SunburstChartComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-sunburst-chart',
template: "<svg [attr.width]=\"width\" [attr.height]=\"height\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n\n <g *ngFor=\"let level of levelSunSlices\">\n <g *ngFor=\"let slice of level\">\n <g [ngStyle]=\"{'transform': gTranslate + ' ' + slice.rotation}\">\n <path class=\"sun-slice\" (mouseover)=\"slice.hover=true\" (mouseout)=\"slice.hover=false\"\n [ngStyle]=\"{'opacity': slice.hover ? 0.7 : 1.0}\"\n [attr.d]=\"slice.hover ? slice.hoverD : slice.d\" [attr.fill]=\"slice.color\" />\n <text class=\"slice-text\" [attr.x]=\"slice.textX\" \n [attr.y]=\"0\" dominant-baseline=\"middle\" text-anchor=\"middle\" [ngStyle]=\"{'transform': slice.textRotation}\"> \n {{ slice.name }} \n </text>\n </g>\n </g>\n </g>\n</svg>\n",
providers: [SunburstChartService],
styles: [".sun-slice{transition:.3s ease-in;stroke:#fff;stroke-width:.5}.slice-text{color:#fff}"]
}] }
];
/** @nocollapse */
SunburstChartComponent.ctorParameters = () => [
{ type: SunburstChartService },
{ type: GlobalParametersService },
{ type: ElementRef }
];
SunburstChartComponent.propDecorators = {
data: [{ type: Input }],
width: [{ type: Input }],
colorScheme: [{ type: Input }],
customColorScheme: [{ type: Input }]
};
if (false) {
/** @type {?} */
SunburstChartComponent.prototype.data;
/** @type {?} */
SunburstChartComponent.prototype.width;
/** @type {?} */
SunburstChartComponent.prototype.colorScheme;
/** @type {?} */
SunburstChartComponent.prototype.customColorScheme;
/** @type {?} */
SunburstChartComponent.prototype.componentID;
/** @type {?} */
SunburstChartComponent.prototype.height;
/** @type {?} */
SunburstChartComponent.prototype.xPadding;
/** @type {?} */
SunburstChartComponent.prototype.yPadding;
/** @type {?} */
SunburstChartComponent.prototype.dataRefined;
/** @type {?} */
SunburstChartComponent.prototype.sunSlices;
/** @type {?} */
SunburstChartComponent.prototype.sunSliceWidth;
/** @type {?} */
SunburstChartComponent.prototype.levelSunSlices;
/** @type {?} */
SunburstChartComponent.prototype.sunRadius;
/** @type {?} */
SunburstChartComponent.prototype.sunDepth;
/** @type {?} */
SunburstChartComponent.prototype.cX;
/** @type {?} */
SunburstChartComponent.prototype.cY;
/** @type {?} */
SunburstChartComponent.prototype.gTranslate;
/** @type {?} */
SunburstChartComponent.prototype.hoverTranslate;
/** @type {?} */
SunburstChartComponent.prototype.sunburstChartService;
/**
* @type {?}
* @private
*/
SunburstChartComponent.prototype.globalParametersService;
/**
* @type {?}
* @private
*/
SunburstChartComponent.prototype.currentElement;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VuYnVyc3QtY2hhcnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWJlYXV0aWZ1bC1jaGFydHMvIiwic291cmNlcyI6WyJsaWIvc3VuYnVyc3QtY2hhcnQvc3VuYnVyc3QtY2hhcnQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFxQixLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM3RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQVFqRixNQUFNLE9BQU8sc0JBQXNCOzs7Ozs7SUF1QmpDLFlBQW1CLG9CQUEwQyxFQUN6Qyx1QkFBZ0QsRUFDaEQsY0FBMEI7UUFGM0IseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUN6Qyw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQXlCO1FBQ2hELG1CQUFjLEdBQWQsY0FBYyxDQUFZO1FBckJyQyxnQkFBVyxHQUFHLFVBQVUsQ0FBQztRQUN6QixzQkFBaUIsR0FBYSxFQUFFLENBQUM7UUFJMUMsYUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNkLGFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztRQU03QixhQUFRLEdBQUcsQ0FBQyxDQUFDO0lBVWIsQ0FBQzs7Ozs7OztJQUVELGNBQWMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssR0FBRyxJQUFJO1FBQ2xDLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxFQUFFO1lBQ3pCLE1BQU0sQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLElBQUksS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUs7Z0JBQUUsTUFBTSxDQUFDLEtBQUssR0FBRyxLQUFL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YixvQ0FBVzs7SUFDWCxvQ0FBVzs7SUFDWCw0Q0FBbUI7O0lBQ25CLGdEQUF1Qjs7SUFFWCxzREFBaUQ7Ozs7O0lBQ2pELHlEQUF3RDs7Ozs7SUFDeEQsZ0RBQWtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE9uQ2hhbmdlcywgSW5wdXQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGNvbG9yU2NoZW1lcyB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy9jb2xvci1zY2hlbWVzJztcbmltcG9ydCB7IFN1bmJ1cnN0Q2hhcnRTZXJ2aWNlIH0gZnJvbSAnLi9zdW5idXJzdC1jaGFydC5zZXJ2aWNlJztcbmltcG9ydCB7IEdsb2JhbFBhcmFtZXRlcnNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vZ2xvYmFsL2dsb2JhbC1wYXJhbWV0ZXJzLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtc3VuYnVyc3QtY2hhcnQnLFxuICB0ZW1wbGF0ZVVybDogJy4vc3VuYnVyc3QtY2hhcnQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9zdW5idXJzdC1jaGFydC5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtTdW5idXJzdENoYXJ0U2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgU3VuYnVyc3RDaGFydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCAsIE9uQ2hhbmdlcyB7XG5cbiAgQElucHV0KCkgZGF0YTogYW55O1xuICBASW5wdXQoKSB3aWR0aDogbnVtYmVyO1xuICBASW5wdXQoKSBjb2xvclNjaGVtZSA9ICdjb2xvcmZ1bCc7XG4gIEBJbnB1dCgpIGN1c3RvbUNvbG9yU2NoZW1lOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGNvbXBvbmVudElEO1xuICBoZWlnaHQ6IG51bWJlcjtcbiAgeFBhZGRpbmcgPSA2MDtcbiAgeVBhZGRpbmcgPSB0aGlzLnhQYWRkaW5nIC8gMjtcbiAgZGF0YVJlZmluZWQ6IGFueTtcbiAgc3VuU2xpY2VzOiBhbnk7XG4gIHN1blNsaWNlV2lkdGg6IG51bWJlcjtcbiAgbGV2ZWxTdW5TbGljZXM6IGFueTtcbiAgc3VuUmFkaXVzOiBudW1iZXI7XG4gIHN1bkRlcHRoID0gMDtcbiAgLy8gaG92ZXJQaWVSYWRpdXM6IG51bWJlcjtcbiAgY1g6IG51bWJlcjtcbiAgY1k6IG51bWJlcjtcbiAgZ1RyYW5zbGF0ZTogc3RyaW5nO1xuICBob3ZlclRyYW5zbGF0ZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBzdW5idXJzdENoYXJ0U2VydmljZTogU3VuYnVyc3RDaGFydFNlcnZpY2UsXG4gICAgICAgICAgICAgIHByaXZhdGUgZ2xvYmFsUGFyYW1ldGVyc1NlcnZpY2U6IEdsb2JhbFBhcmFtZXRlcnNTZXJ2aWNlLFxuICAgICAgICAgICAgICBwcml2YXRlIGN1cnJlbnRFbGVtZW50OiBFbGVtZW50UmVmKSB7XG4gIH1cblxuICBnZXRSZWZpbmVkRGF0YShkYXRhLCBpLCBjb2xvciA9IG51bGwpIHtcbiAgICBmb3IgKGNvbnN0IHNiRGF0YSBvZiBkYXRhKSB7XG4gICAgICBzYkRhdGEubGV2ZWwgPSBpO1xuICAgICAgaWYgKGNvbG9yICYmICFzYkRhdGEuY29sb3IpIHNiRGF0YS5jb2xvciA9IGNvbG9yO1xuICAgICAgaWYgKHNiRGF0YS5sZXZlbCA+IHRoaXMuc3VuRGVwdGgpIHRoaXMuc3VuRGVwdGggPSBzYkRhdGEubGV2ZWw7XG4gICAgICBpZiAoc2JEYXRhLmNoaWxkcmVuKSB7XG4gICAgICAgIGlmIChzYkRhdGEuY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHNiRGF0YS5jaGlsZHJlbiA9IHRoaXMuZ2V0UmVmaW5lZERhdGEoc2JEYXRhLmNoaWxkcmVuLCBpICsgMSwgc2JEYXRhLmNvbG9yKTtcbiAgICAgICAgICBzYkRhdGEudmFsdWUgPSBzYkRhdGEuY2hpbGRyZW4ubWFwKGNoaWxkID0+IGNoaWxkLnZhbHVlKS5yZWR1Y2UoKHN1bSwgY3VycikgPT4gc3VtICsgY3Vycik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKCFzYkRhdGEudmFsdWUpIHNiRGF0YS52YWx1ZSA9IDA7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIXNiRGF0YS52YWx1ZSkgc2JEYXRhLnZhbHVlID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICBzZXREaW1lbnNpb25zKCkge1xuICAgIGlmICh0aGlzLndpZHRoKSB0aGlzLmhlaWdodCA9IHRoaXMud2lkdGggLSB0aGlzLnhQYWRkaW5nO1xuICAgIGVsc2Uge1xuICAgICAgY29uc3QgaG9zdCA9IHRoaXMuY3VycmVudEVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICAgIGlmIChob3N0LnBhcmVudE5vZGUgIT0gbnVsbCkge1xuICAgICAgICBjb25zdCBkaW1zID0gaG9zdC5wYXJlbnROb2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLndpZHRoID0gZGltcy53aWR0aDtcbiAgICAgICAgdGhpcy5oZWlnaHQgPSB0aGlzLndpZHRoIC0gdGhpcy54UGFkZGluZztcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gY29uc29sZS5sb2coJy0tLXNldCBkaW1lbnNpb25zLS0tJyk7XG4gICAgLy8gY29uc29sZS5sb2coJ3dpZHRoOiAnICsgdGhpcy53aWR0aCk7XG4gICAgLy8gY29uc29sZS5sb2coJ2hlaWdodDogJyArIHRoaXMuaGVpZ2h0KTtcbiAgICAvLyBjb25zb2xlLmxvZygnLS0tLS0tLS0tLS0tLS0tLS0tLS0nKTtcbiAgfVxuXG4gIGdlbmVyYXRlU2xpY2UoZGF0YSwgc3VtLCBhbmdsZVJhbmdlLCByb3RhdGlvbikge1xuICAgIGNvbnN0IHBlcmMgPSBkYXRhLnZhbHVlIC8gc3VtO1xuICAgIGNvbnN0IGFuZ2xlID0gYW5nbGVSYW5nZSAqIHBlcmM7XG4gICAgLy8gY29uc3QgYW5nbGVNb2QgPSAoYW5nbGUgPiAxODAgKSA/IDM2MCAtIGFuZ2xlIDogYW5nbGU7XG4gICAgY29uc3QgYW5nbGVSYWQgPSBhbmdsZSAqIE1hdGguUEkgLyAxODA7XG4gICAgY29uc3QgbGFyZ2VBcmMgPSAoYW5nbGUgPiAxODApID8gMSA6IDA7XG4gICAgY29uc3QgdGV4dFJvdGF0aW9uID0gKDI3MCArIGFuZ2xlIC8gMikgJSAzNjA7XG4gICAgY29uc3QgdGV4dFggPSAoZGF0YS5sZXZlbCAtIDEpICogdGhpcy5zdW5TbGljZVdpZHRoICsgdGhpcy5zdW5TbGljZVdpZHRoIC8gMjtcbiAgICBsZXQgdGV4dFJvdGF0aW9uU3RyaW5nID0gJ3JvdGF0ZSgnICsgdGV4dFJvdGF0aW9uICsgJ2RlZyknO1xuICAgIGlmIChyb3RhdGlvbiA+IDE4MCkge1xuICAgICAgY29uc3QgeCA9IHRleHRYICogMjtcbiAgICAgIHRleHRSb3RhdGlvblN0cmluZyA9IHRleHRSb3RhdGlvblN0cmluZyArICcgc2NhbGUoLTEsLTEpIHRyYW5zbGF0ZVgoJyArIC14ICsgJ3B4KSc7XG4gICAgfVxuICAgIGxldCBwYXRoO1xuICAgIGxldCBob3ZlclBhdGg7XG4gICAgaWYgKGRhdGEubGV2ZWwgPT09IDEpIHtcbiAgICAgIHBhdGggPSAnTSAwIDAgMCAnICsgLXRoaXMuc3VuU2xpY2VXaWR0aCArICcgQSAnXG4gICAgICArIHRoaXMuc3VuU2xpY2VXaWR0aCArICcgJyArIHRoaXMuc3VuU2xpY2VXaWR0aFxuICAgICAgKyAnIDAgJyArIGxhcmdlQXJjICsgJyAxICcgKyB0aGlzLnN1blNsaWNlV2lkdGggKiBNYXRoLnNpbihhbmdsZVJhZCkgKyAnICdcbiAgICAgICsgLXRoaXMuc3VuU2xpY2VXaWR0aCAqIE1hdGguY29zKGFuZ2xlUmFkKSArICcgeic7XG5cbiAgICAgIGNvbnN0IGhvdmVyUmFkaXVzID0gdGhpcy5zdW5TbGljZVdpZHRoICogMS4xO1xuICAgICAgaG92ZXJQYXRoID0gJ00gMCAwIDAgJyArIC1ob3ZlclJhZGl1cyArICcgQSAnXG4gICAgICArIGhvdmVyUmFkaXVzICsgJyAnICsgaG92ZXJSYWRpdXNcbiAgICAgICsgJyAwICcgKyBsYXJnZUFyYyArICcgMSAnICsgaG92ZXJSYWRpdXMgKiBNYXRoLnNpbihhbmdsZVJhZCkgKyAnICdcbiAgICAgICsgLWhvdmVyUmFkaXVzICogTWF0aC5jb3MoYW5nbGVSYWQpICsgJyB6JztcbiAgICB9IGVsc2UgaWYgKGRhdGEubGV2ZWwgPiAxKSB7XG4gICAgICBjb25zdCBzdW5TbGljZUlubmVyUmFkaXVzID0gdGhpcy5zdW5SYWRpdXMgLyAodGhpcy5zdW5EZXB0aCkgKiAoZGF0YS5sZXZlbCAtIDEpO1xuICAgICAgY29uc3Qgc3VuU2xpY2VPdXRlclJhZGl1cyA9IHRoaXMuc3VuUmFkaXVzIC8gKHRoaXMuc3VuRGVwdGgpICogZGF0YS5sZXZlbDtcblxuICAgICAgcGF0aCA9ICdNIDAgJyArIC1zdW5TbGljZUlubmVyUmFkaXVzICsgJyAwICcgKyAtc3VuU2xpY2VPdXRlclJhZGl1c1xuICAgICAgKyAnIEEgJyArIHN1blNsaWNlT3V0ZXJSYWRpdXMgKyAnICcgKyBzdW5TbGljZU91dGVyUmFkaXVzXG4gICAgICArICcgMCAnICsgbGFyZ2VBcmMgKyAnIDEgJyArIHN1blNsaWNlT3V0ZXJSYWRpdXMgKiBNYXRoLnNpbihhbmdsZVJhZCkgKyAnICdcbiAgICAgICsgLXN1blNsaWNlT3V0ZXJSYWRpdXMgKiBNYXRoLmNvcyhhbmdsZVJhZClcbiAgICAgICsgJyBMICcgKyBzdW5TbGljZUlubmVyUmFkaXVzICogTWF0aC5zaW4oYW5nbGVSYWQpICsgJyAnXG4gICAgICArIC1zdW5TbGljZUlubmVyUmFkaXVzICogTWF0aC5jb3MoYW5nbGVSYWQpICsgJyBBICdcbiAgICAgICsgc3VuU2xpY2VJbm5lclJhZGl1cyArICcgJyArIHN1blNsaWNlSW5uZXJSYWRpdXNcbiAgICAgICsgJyAwICcgKyBsYXJnZUFyYyArICcgMCAwICcgKyAtc3VuU2xpY2VJbm5lclJhZGl1cyArICcgeic7XG5cbiAgICAgIGNvbnN0IGhvdmVyU2xpY2VPdXRlclJhZGl1cyA9IHN1blNsaWNlT3V0ZXJSYWRpdXMgKyB0aGlzLnN1blNsaWNlV2lkdGggKiAwLjE7XG5cbiAgICAgIGhvdmVyUGF0aCA9ICdNIDAgJyArIC1zdW5TbGljZUlubmVyUmFkaXVzICsgJyAwICcgKyAtaG92ZXJTbGljZU91dGVyUmFkaXVzXG4gICAgICArICcgQSAnICsgaG92ZXJTbGljZU91dGVyUmFkaXVzICsgJyAnICsgaG92ZXJTbGljZU91dGVyUmFkaXVzXG4gICAgICArICcgMCAnICsgbGFyZ2VBcmMgKyAnIDEgJyArIGhvdmVyU2xpY2VPdXRlclJhZGl1cyAqIE1hdGguc2luKGFuZ2xlUmFkKSArICcgJ1xuICAgICAgKyAtaG92ZXJTbGljZU91dGVyUmFkaXVzICogTWF0aC5jb3MoYW5nbGVSYWQpXG4gICAgICArICcgTCAnICsgc3VuU2xpY2VJbm5lclJhZGl1cyAqIE1hdGguc2luKGFuZ2xlUmFkKSArICcgJ1xuICAgICAgKyAtc3VuU2xpY2VJbm5lclJhZGl1cyAqIE1hdGguY29zKGFuZ2xlUmFkKSArICcgQSAnXG4gICAgICArIHN1blNsaWNlSW5uZXJSYWRpdXMgKyAnICcgKyBzdW5TbGljZUlubmVyUmFkaXVzXG4gICAgICArICcgMCAnICsgbGFyZ2VBcmMgKyAnIDAgMCAnICsgLXN1blNsaWNlSW5uZXJSYWRpdXMgKyAnIHonO1xuICAgIH1cbiAgICAvLyBjb25zb2xlLmxvZyhob3ZlclBhdGgpO1xuXG4gICAgY29uc3Qgc3VuU2xpY2UgPSB7XG4gICAgICBwZXJjLFxuICAgICAgbmFtZTogZGF0YS5uYW1lLFxuICAgICAgY29sb3I6IGRhdGEuY29sb3IsXG4gICAgICBob3ZlckQ6IGhvdmVyUGF0aCxcbiAgICAgIHJvdGF0aW9uOiAncm90YXRlKCcgKyByb3RhdGlvbiArICdkZWcpJyxcbiAgICAgIHRleHRSb3RhdGlvbjogdGV4dFJvdGF0aW9uU3RyaW5nLFxuICAgICAgdGV4dFgsXG4gICAgICBkOiBwYXRoLFxuICAgICAgYW5nbGUsXG4gICAgICBob3ZlcjogZmFsc2UsXG4gICAgICBjaGlsZHJlbjogbnVsbFxuICAgIH07XG5cbiAgICB0aGlzLmxldmVsU3VuU2xpY2VzW2RhdGEubGV2ZWwgLSAxXS5wdXNoKHN1blNsaWNlKTtcblxuICAgIHJldHVybiBzdW5TbGljZTtcbiAgfVxuXG4gIGdlbmVyYXRlU3VuU2xpY2VzRm9yQW5nbGUoZGF0YSwgYW5nbGVSYW5nZSwgcm90YXRpb24pIHtcbiAgICBjb25zdCBzdW5TbGljZXMgPSBbXTtcblxuICAgIGxldCBzdW0gPSAwO1xuICAgIGZvciAoY29uc3QgdmFsIG9mIGRhdGEpIHtcbiAgICAgIHN1bSA9IHN1bSArIHZhbC52YWx1ZTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHZhbCBvZiBkYXRhKSB7XG5cbiAgICAgIGNvbnN0IHN1blNsaWNlID0gdGhpcy5nZW5lcmF0ZVNsaWNlKHZhbCwgc3VtLCBhbmdsZVJhbmdlLCByb3RhdGlvbik7XG4gICAgICBpZiAodmFsLmNoaWxkcmVuICYmIHZhbC5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XG4gICAgICAgIHN1blNsaWNlLmNoaWxkcmVuID0gdGhpcy5nZW5lcmF0ZVN1blNsaWNlc0ZvckFuZ2xlKHZhbC5jaGlsZHJlbiwgc3VuU2xpY2UuYW5nbGUsIHJvdGF0aW9uKTtcbiAgICAgIH1cbiAgICAgIC8vIGNvbnNvbGUubG9nKHZhbCk7XG5cbiAgICAgIC8vIGNvbnNvbGUubG9nKHN1blNsaWNlKTtcbiAgICAgIHN1blNsaWNlcy5wdXNoKHN1blNsaWNlKTtcbiAgICAgIHJvdGF0aW9uICs9IHN1blNsaWNlLmFuZ2xlO1xuICAgIH1cbiAgICByZXR1cm4gc3VuU2xpY2VzO1xuICB9XG5cbiAgZ2VuZXJhdGVTdW5TbGljZXMoZGF0YSkge1xuICAgIHJldHVybiB0aGlzLmdlbmVyYXRlU3VuU2xpY2VzRm9yQW5nbGUoZGF0YSwgMzYwLCAwKTtcbiAgfVxuXG4gIGluaXRpYXRlTGV2ZWxTdW5TbGljZXMoKSB7XG4gICAgdGhpcy5sZXZlbFN1blNsaWNlcyA9IFtdO1xuICAgIGZvciAobGV0IGxldmVsID0gMTsgbGV2ZWwgPD0gdGhpcy5zdW5EZXB0aDsgbGV2ZWwrKykge1xuICAgICAgdGhpcy5sZXZlbFN1blNsaWNlcy5wdXNoKFtdKTtcbiAgICB9XG4gIH1cblxuICBzZXRDb2xvcnMoKSB7XG4gICAgbGV0IGNudCA9IDA7XG4gICAgZm9yIChjb25zdCBzbGljZSBvZiB0aGlzLmRhdGEpIHtcbiAgICAgIGlmICghc2xpY2UuY29sb3IpIHtcbiAgICAgICAgaWYgKHRoaXMuY3VzdG9tQ29sb3JTY2hlbWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHNsaWNlLmNvbG9yID0gdGhpcy5jdXN0b21Db2xvclNjaGVtZVtjbnQgJSB0aGlzLmN1c3RvbUNvbG9yU2NoZW1lLmxlbmd0aF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2xpY2UuY29sb3IgPSBjb2xvclNjaGVtZXNbdGhpcy5jb2xvclNjaGVtZV1bY250ICUgMTBdO1xuICAgICAgICB9XG4gICAgICAgIGNudCsrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuY29tcG9uZW50SUQgPSB0aGlzLmdsb2JhbFBhcmFtZXRlcnNTZXJ2aWNlLmFkZE5ld0NvbXBvbmVudCgpO1xuICAgIC8vIGNvbnNvbGUubG9nKCdzZXJ2aWNlIChvbmluaXRzdW4pIGNvbG9yIHNjaGVtZTogJyArIHRoaXMuc3VuYnVyc3RDaGFydFNlcnZpY2UuY29sb3JTY2hlbWUpO1xuICAgIHRoaXMuc2V0Q29sb3JzKCk7XG4gICAgdGhpcy5zZXREaW1lbnNpb25zKCk7XG4gICAgdGhpcy5zdW5idXJzdENoYXJ0U2VydmljZS5zZXRWYWx1ZXMoe1xuICAgICAgY29tcG9uZW50SUQ6IHRoaXMuY29tcG9uZW50SUQsXG4gICAgICB3aWR0aDogdGhpcy53aWR0aCxcbiAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQsXG4gICAgICB4UGFkZGluZzogdGhpcy54UGFkZGluZyxcbiAgICAgIHlQYWRkaW5nOiB0aGlzLnlQYWRkaW5nLFxuICAgICAgZGF0YTogdGhpcy5kYXRhXG4gICAgfSk7XG4gICAgdGhpcy5zdW5SYWRpdXMgPSB0aGlzLnN1bmJ1cnN0Q2hhcnRTZXJ2aWNlLnN1blJhZGl1cztcbiAgICB0aGlzLmRhdGFSZWZpbmVkID0gdGhpcy5nZXRSZWZpbmVkRGF0YSh0aGlzLmRhdGEsIDEpO1xuICAgIC8vIGNvbnNvbGUubG9nKCdkYXRhIHJlZmluZWQ6ICcpO1xuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuZGF0YVJlZmluZWQpO1xuICAgIHRoaXMuaW5pdGlhdGVMZXZlbFN1blNsaWNlcygpO1xuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuc3VuRGVwdGgpO1xuICAgIC8vIGNvbnNvbGUubG9nKCdsZXZlbCBzdW4gc2xpY2VzOiAnKTtcbiAgICAvLyBjb25zb2xlLmxvZyh0aGlzLmxldmVsU3VuU2xpY2VzKTtcbiAgICAvLyB0aGlzLmhvdmVyUGllUmFkaXVzID0gdGhpcy5zdW5idXJzdENoYXJ0U2VydmljZS5zdW5SYWRpdXMgLyB0aGlzLnN1bkRlcHRoICogMS4wNTtcblxuICAgIHRoaXMuc3VuU2xpY2VXaWR0aCA9IHRoaXMuc3VuUmFkaXVzIC8gdGhpcy5zdW5EZXB0aDtcbiAgICB0aGlzLnN1blNsaWNlcyA9IHRoaXMuZ2VuZXJhdGVTdW5TbGljZXModGhpcy5kYXRhUmVmaW5lZCk7XG4gICAgLy8gY29uc29sZS5sb2codGhpcy5ob3ZlclBpZVJhZGl1cyk7XG4gICAgdGhpcy5jWCA9IHRoaXMueFBhZGRpbmcgKyB0aGlzLnN1blJhZGl1cztcbiAgICB0aGlzLmNZID0gdGhpcy55UGFkZGluZyArIHRoaXMuc3VuUmFkaXVzO1xuICAgIGNvbnN0IHRyYW5zbGF0ZVggPSB0aGlzLnhQYWRkaW5nICsgdGhpcy5zdW5SYWRpdXM7XG4gICAgY29uc3QgdHJhbnNsYXRlWSA9IHRoaXMueVBhZGRpbmcgKyB0aGlzLnN1blJhZGl1cztcbiAgICB0aGlzLmdUcmFuc2xhdGUgPSAndHJhbnNsYXRlKCcgKyB0cmFuc2xhdGVYICsgJ3B4LCAnICsgdHJhbnNsYXRlWSArICdweCknO1xuICAgIGNvbnN0IGhvdmVyVHJhbnNsYXRlWFkgPSB0aGlzLnN1blJhZGl1cyAqIDAuMDg7XG4gICAgdGhpcy5ob3ZlclRyYW5zbGF0ZSA9ICd0cmFuc2xhdGUoJyArIGhvdmVyVHJhbnNsYXRlWFkgKyAncHgsICcgKyAtaG92ZXJUcmFuc2xhdGVYWSArICdweCknO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoKSB7XG4gICAgLy8gY29uc29sZS5sb2coJ3NlcnZpY2UgKG9uY2hhbmdlc3N1bikgY29sb3Igc2NoZW1lOiAnICsgdGhpcy5zdW5idXJzdENoYXJ0U2VydmljZS5jb2xvclNjaGVtZSk7XG4gICAgdGhpcy5zZXRDb2xvcnMoKTtcbiAgICB0aGlzLnNldERpbWVuc2lvbnMoKTtcbiAgICB0aGlzLnN1bmJ1cnN0Q2hhcnRTZXJ2aWNlLnNldFZhbHVlcyh7XG4gICAgICBjb21wb25lbnRJRDogdGhpcy5jb21wb25lbnRJRCxcbiAgICAgIHdpZHRoOiB0aGlzLndpZHRoLFxuICAgICAgaGVpZ2h0OiB0aGlzLmhlaWdodCxcbiAgICAgIHhQYWRkaW5nOiB0aGlzLnhQYWRkaW5nLFxuICAgICAgeVBhZGRpbmc6IHRoaXMueVBhZGRpbmcsXG4gICAgICBkYXRhOiB0aGlzLmRhdGFcbiAgICB9KTtcbiAgICB0aGlzLnN1blJhZGl1cyA9IHRoaXMuc3VuYnVyc3RDaGFydFNlcnZpY2Uuc3VuUmFkaXVzO1xuICAgIHRoaXMuZGF0YVJlZmluZWQgPSB0aGlzLmdldFJlZmluZWREYXRhKHRoaXMuZGF0YSwgMSk7XG4gICAgLy8gY29uc29sZS5sb2coJ2RhdGEgcmVmaW5lZDogJyk7XG4gICAgLy8gY29uc29sZS5sb2codGhpcy5kYXRhUmVmaW5lZCk7XG4gICAgdGhpcy5pbml0aWF0ZUxldmVsU3VuU2xpY2VzKCk7XG4gICAgLy8gY29uc29sZS5sb2codGhpcy5zdW5EZXB0aCk7XG4gICAgLy8gY29uc29sZS5sb2coJ2xldmVsIHN1biBzbGljZXM6ICcpO1xuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMubGV2ZWxTdW5TbGljZXMpO1xuICAgIC8vIHRoaXMuaG92ZXJQaWVSYWRpdXMgPSB0aGlzLnN1bmJ1cnN0Q2hhcnRTZXJ2aWNlLnN1blJhZGl1cyAvIHRoaXMuc3VuRGVwdGggKiAxLjA1O1xuXG4gICAgdGhpcy5zdW5TbGljZVdpZHRoID0gdGhpcy5zdW5SYWRpdXMgLyB0aGlzLnN1bkRlcHRoO1xuICAgIHRoaXMuc3VuU2xpY2VzID0gdGhpcy5nZW5lcmF0ZVN1blNsaWNlcyh0aGlzLmRhdGFSZWZpbmVkKTtcbiAgICAvLyBjb25zb2xlLmxvZyh0aGlzLmhvdmVyUGllUmFkaXVzKTtcbiAgICB0aGlzLmNYID0gdGhpcy54UGFkZGluZyArIHRoaXMuc3VuUmFkaXVzO1xuICAgIHRoaXMuY1kgPSB0aGlzLnlQYWRkaW5nICsgdGhpcy5zdW5SYWRpdXM7XG4gICAgY29uc3QgdHJhbnNsYXRlWCA9IHRoaXMueFBhZGRpbmcgKyB0aGlzLnN1blJhZGl1cztcbiAgICBjb25zdCB0cmFuc2xhdGVZID0gdGhpcy55UGFkZGluZyArIHRoaXMuc3VuUmFkaXVzO1xuICAgIHRoaXMuZ1RyYW5zbGF0ZSA9ICd0cmFuc2xhdGUoJyArIHRyYW5zbGF0ZVggKyAncHgsICcgKyB0cmFuc2xhdGVZICsgJ3B4KSc7XG4gICAgY29uc3QgaG92ZXJUcmFuc2xhdGVYWSA9IHRoaXMuc3VuUmFkaXVzICogMC4wODtcbiAgICB0aGlzLmhvdmVyVHJhbnNsYXRlID0gJ3RyYW5zbGF0ZSgnICsgaG92ZXJUcmFuc2xhdGVYWSArICdweCwgJyArIC1ob3ZlclRyYW5zbGF0ZVhZICsgJ3B4KSc7XG4gIH1cblxufVxuIl19