@swimlane/ngx-charts
Version:
Declarative Charting Framework for Angular
259 lines • 25.6 kB
JavaScript
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { max } from 'd3-array';
import { arc, pie } from 'd3-shape';
import { formatLabel, escapeLabel } from '../common/label.helper';
import { PlacementTypes } from '../common/tooltip/position';
import { StyleTypes } from '../common/tooltip/style.type';
import * as i0 from "@angular/core";
import * as i1 from "./pie-label.component";
import * as i2 from "./pie-arc.component";
import * as i3 from "@angular/common";
import * as i4 from "../common/tooltip/tooltip.directive";
export class PieSeriesComponent {
constructor() {
this.series = [];
this.innerRadius = 60;
this.outerRadius = 80;
this.trimLabels = true;
this.maxLabelLength = 10;
this.tooltipDisabled = false;
this.animations = true;
this.select = new EventEmitter();
this.activate = new EventEmitter();
this.deactivate = new EventEmitter();
this.dblclick = new EventEmitter();
this.placementTypes = PlacementTypes;
this.styleTypes = StyleTypes;
}
ngOnChanges(changes) {
this.update();
}
update() {
const pieGenerator = pie()
.value(d => d.value)
.sort(null);
const arcData = pieGenerator(this.series);
this.max = max(arcData, d => {
return d.value;
});
this.data = this.calculateLabelPositions(arcData);
this.tooltipText = this.tooltipText || this.defaultTooltipText;
}
midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
outerArc() {
const factor = 1.5;
return arc()
.innerRadius(this.outerRadius * factor)
.outerRadius(this.outerRadius * factor);
}
calculateLabelPositions(pieData) {
const factor = 1.5;
const minDistance = 10;
const labelPositions = pieData;
labelPositions.forEach(d => {
d.pos = this.outerArc().centroid(d);
d.pos[0] = factor * this.outerRadius * (this.midAngle(d) < Math.PI ? 1 : -1);
});
for (let i = 0; i < labelPositions.length - 1; i++) {
const a = labelPositions[i];
if (!this.labelVisible(a)) {
continue;
}
for (let j = i + 1; j < labelPositions.length; j++) {
const b = labelPositions[j];
if (!this.labelVisible(b)) {
continue;
}
// if they're on the same side
if (b.pos[0] * a.pos[0] > 0) {
// if they're overlapping
const o = minDistance - Math.abs(b.pos[1] - a.pos[1]);
if (o > 0) {
// push the second up or down
b.pos[1] += Math.sign(b.pos[0]) * o;
}
}
}
}
return labelPositions;
}
labelVisible(myArc) {
return this.showLabels && myArc.endAngle - myArc.startAngle > Math.PI / 30;
}
getTooltipTitle(a) {
return this.tooltipTemplate ? undefined : this.tooltipText(a);
}
labelText(myArc) {
if (this.labelFormatting) {
return this.labelFormatting(myArc.data.name);
}
return this.label(myArc);
}
label(myArc) {
return formatLabel(myArc.data.name);
}
defaultTooltipText(myArc) {
const label = this.label(myArc);
const val = formatLabel(myArc.data.value);
return `
<span class="tooltip-label">${escapeLabel(label)}</span>
<span class="tooltip-val">${val}</span>
`;
}
color(myArc) {
return this.colors.getColor(this.label(myArc));
}
trackBy(index, item) {
return item.data.name;
}
onClick(data) {
this.select.emit(data);
}
isActive(entry) {
if (!this.activeEntries)
return false;
const item = this.activeEntries.find(d => {
return entry.name === d.name && entry.series === d.series;
});
return item !== undefined;
}
}
PieSeriesComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieSeriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
PieSeriesComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: PieSeriesComponent, selector: "g[ngx-charts-pie-series]", inputs: { colors: "colors", series: "series", dims: "dims", innerRadius: "innerRadius", outerRadius: "outerRadius", explodeSlices: "explodeSlices", showLabels: "showLabels", gradient: "gradient", activeEntries: "activeEntries", labelFormatting: "labelFormatting", trimLabels: "trimLabels", maxLabelLength: "maxLabelLength", tooltipText: "tooltipText", tooltipDisabled: "tooltipDisabled", tooltipTemplate: "tooltipTemplate", animations: "animations" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate", dblclick: "dblclick" }, usesOnChanges: true, ngImport: i0, template: `
<svg:g *ngFor="let arc of data; trackBy: trackBy">
<svg:g
ngx-charts-pie-label
*ngIf="labelVisible(arc)"
[data]="arc"
[radius]="outerRadius"
[color]="color(arc)"
[label]="labelText(arc)"
[labelTrim]="trimLabels"
[labelTrimSize]="maxLabelLength"
[max]="max"
[value]="arc.value"
[explodeSlices]="explodeSlices"
[animations]="animations"
></svg:g>
<svg:g
ngx-charts-pie-arc
[startAngle]="arc.startAngle"
[endAngle]="arc.endAngle"
[innerRadius]="innerRadius"
[outerRadius]="outerRadius"
[fill]="color(arc)"
[value]="arc.data.value"
[gradient]="gradient"
[data]="arc.data"
[max]="max"
[explodeSlices]="explodeSlices"
[isActive]="isActive(arc.data)"
[animate]="animations"
(select)="onClick($event)"
(activate)="activate.emit($event)"
(deactivate)="deactivate.emit($event)"
(dblclick)="dblclick.emit($event)"
ngx-tooltip
[tooltipDisabled]="tooltipDisabled"
[tooltipPlacement]="placementTypes.Top"
[tooltipType]="styleTypes.tooltip"
[tooltipTitle]="getTooltipTitle(arc)"
[tooltipTemplate]="tooltipTemplate"
[tooltipContext]="arc.data"
></svg:g>
</svg:g>
`, isInline: true, components: [{ type: i1.PieLabelComponent, selector: "g[ngx-charts-pie-label]", inputs: ["data", "radius", "label", "color", "max", "value", "explodeSlices", "animations", "labelTrim", "labelTrimSize"] }, { type: i2.PieArcComponent, selector: "g[ngx-charts-pie-arc]", inputs: ["fill", "startAngle", "endAngle", "innerRadius", "outerRadius", "cornerRadius", "value", "max", "data", "explodeSlices", "gradient", "animate", "pointerEvents", "isActive"], outputs: ["select", "activate", "deactivate", "dblclick"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.TooltipDirective, selector: "[ngx-tooltip]", inputs: ["tooltipCssClass", "tooltipTitle", "tooltipAppendToBody", "tooltipSpacing", "tooltipDisabled", "tooltipShowCaret", "tooltipPlacement", "tooltipAlignment", "tooltipType", "tooltipCloseOnClickOutside", "tooltipCloseOnMouseLeave", "tooltipHideTimeout", "tooltipShowTimeout", "tooltipTemplate", "tooltipShowEvent", "tooltipContext", "tooltipImmediateExit"], outputs: ["show", "hide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: PieSeriesComponent, decorators: [{
type: Component,
args: [{
selector: 'g[ngx-charts-pie-series]',
template: `
<svg:g *ngFor="let arc of data; trackBy: trackBy">
<svg:g
ngx-charts-pie-label
*ngIf="labelVisible(arc)"
[data]="arc"
[radius]="outerRadius"
[color]="color(arc)"
[label]="labelText(arc)"
[labelTrim]="trimLabels"
[labelTrimSize]="maxLabelLength"
[max]="max"
[value]="arc.value"
[explodeSlices]="explodeSlices"
[animations]="animations"
></svg:g>
<svg:g
ngx-charts-pie-arc
[startAngle]="arc.startAngle"
[endAngle]="arc.endAngle"
[innerRadius]="innerRadius"
[outerRadius]="outerRadius"
[fill]="color(arc)"
[value]="arc.data.value"
[gradient]="gradient"
[data]="arc.data"
[max]="max"
[explodeSlices]="explodeSlices"
[isActive]="isActive(arc.data)"
[animate]="animations"
(select)="onClick($event)"
(activate)="activate.emit($event)"
(deactivate)="deactivate.emit($event)"
(dblclick)="dblclick.emit($event)"
ngx-tooltip
[tooltipDisabled]="tooltipDisabled"
[tooltipPlacement]="placementTypes.Top"
[tooltipType]="styleTypes.tooltip"
[tooltipTitle]="getTooltipTitle(arc)"
[tooltipTemplate]="tooltipTemplate"
[tooltipContext]="arc.data"
></svg:g>
</svg:g>
`,
changeDetection: ChangeDetectionStrategy.OnPush
}]
}], propDecorators: { colors: [{
type: Input
}], series: [{
type: Input
}], dims: [{
type: Input
}], innerRadius: [{
type: Input
}], outerRadius: [{
type: Input
}], explodeSlices: [{
type: Input
}], showLabels: [{
type: Input
}], gradient: [{
type: Input
}], activeEntries: [{
type: Input
}], labelFormatting: [{
type: Input
}], trimLabels: [{
type: Input
}], maxLabelLength: [{
type: Input
}], tooltipText: [{
type: Input
}], tooltipDisabled: [{
type: Input
}], tooltipTemplate: [{
type: Input
}], animations: [{
type: Input
}], select: [{
type: Output
}], activate: [{
type: Output
}], deactivate: [{
type: Output
}], dblclick: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGllLXNlcmllcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zd2ltbGFuZS9uZ3gtY2hhcnRzL3NyYy9saWIvcGllLWNoYXJ0L3BpZS1zZXJpZXMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBRVQsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBRVosdUJBQXVCLEVBRXhCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0IsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFHcEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUdsRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDOzs7Ozs7QUFtRDFELE1BQU0sT0FBTyxrQkFBa0I7SUFoRC9CO1FBa0RXLFdBQU0sR0FBZSxFQUFFLENBQUM7UUFFeEIsZ0JBQVcsR0FBVyxFQUFFLENBQUM7UUFDekIsZ0JBQVcsR0FBVyxFQUFFLENBQUM7UUFNekIsZUFBVSxHQUFZLElBQUksQ0FBQztRQUMzQixtQkFBYyxHQUFXLEVBQUUsQ0FBQztRQUU1QixvQkFBZSxHQUFZLEtBQUssQ0FBQztRQUVqQyxlQUFVLEdBQVksSUFBSSxDQUFDO1FBRTFCLFdBQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzVCLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzlCLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2hDLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBS3hDLG1CQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ2hD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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkNUO29CQUNELGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2lCQUNoRDs4QkFFVSxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVJLE1BQU07c0JBQWYsTUFBTTtnQkFDRyxRQUFRO3NCQUFqQixNQUFNO2dCQUNHLFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csUUFBUTtzQkFBakIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBPbkNoYW5nZXMsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBUZW1wbGF0ZVJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IG1heCB9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCB7IGFyYywgcGllIH0gZnJvbSAnZDMtc2hhcGUnO1xuaW1wb3J0IHsgQ29sb3JIZWxwZXIgfSBmcm9tICcuLi9jb21tb24vY29sb3IuaGVscGVyJztcblxuaW1wb3J0IHsgZm9ybWF0TGFiZWwsIGVzY2FwZUxhYmVsIH0gZnJvbSAnLi4vY29tbW9uL2xhYmVsLmhlbHBlcic7XG5pbXBvcnQgeyBEYXRhSXRlbSB9IGZyb20gJy4uL21vZGVscy9jaGFydC1kYXRhLm1vZGVsJztcbmltcG9ydCB7IFBpZURhdGEgfSBmcm9tICcuL3BpZS1sYWJlbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgUGxhY2VtZW50VHlwZXMgfSBmcm9tICcuLi9jb21tb24vdG9vbHRpcC9wb3NpdGlvbic7XG5pbXBvcnQgeyBTdHlsZVR5cGVzIH0gZnJvbSAnLi4vY29tbW9uL3Rvb2x0aXAvc3R5bGUudHlwZSc7XG5pbXBvcnQgeyBWaWV3RGltZW5zaW9ucyB9IGZyb20gJy4uL2NvbW1vbi90eXBlcy92aWV3LWRpbWVuc2lvbi5pbnRlcmZhY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdnW25neC1jaGFydHMtcGllLXNlcmllc10nLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxzdmc6ZyAqbmdGb3I9XCJsZXQgYXJjIG9mIGRhdGE7IHRyYWNrQnk6IHRyYWNrQnlcIj5cbiAgICAgIDxzdmc6Z1xuICAgICAgICBuZ3gtY2hhcnRzLXBpZS1sYWJlbFxuICAgICAgICAqbmdJZj1cImxhYmVsVmlzaWJsZShhcmMpXCJcbiAgICAgICAgW2RhdGFdPVwiYXJjXCJcbiAgICAgICAgW3JhZGl1c109XCJvdXRlclJhZGl1c1wiXG4gICAgICAgIFtjb2xvcl09XCJjb2xvcihhcmMpXCJcbiAgICAgICAgW2xhYmVsXT1cImxhYmVsVGV4dChhcmMpXCJcbiAgICAgICAgW2xhYmVsVHJpbV09XCJ0cmltTGFiZWxzXCJcbiAgICAgICAgW2xhYmVsVHJpbVNpemVdPVwibWF4TGFiZWxMZW5ndGhcIlxuICAgICAgICBbbWF4XT1cIm1heFwiXG4gICAgICAgIFt2YWx1ZV09XCJhcmMudmFsdWVcIlxuICAgICAgICBbZXhwbG9kZVNsaWNlc109XCJleHBsb2RlU2xpY2VzXCJcbiAgICAgICAgW2FuaW1hdGlvbnNdPVwiYW5pbWF0aW9uc1wiXG4gICAgICA+PC9zdmc6Zz5cbiAgICAgIDxzdmc6Z1xuICAgICAgICBuZ3gtY2hhcnRzLXBpZS1hcmNcbiAgICAgICAgW3N0YXJ0QW5nbGVdPVwiYXJjLnN0YXJ0QW5nbGVcIlxuICAgICAgICBbZW5kQW5nbGVdPVwiYXJjLmVuZEFuZ2xlXCJcbiAgICAgICAgW2lubmVyUmFkaXVzXT1cImlubmVyUmFkaXVzXCJcbiAgICAgICAgW291dGVyUmFkaXVzXT1cIm91dGVyUmFkaXVzXCJcbiAgICAgICAgW2ZpbGxdPVwiY29sb3IoYXJjKVwiXG4gICAgICAgIFt2YWx1ZV09XCJhcmMuZGF0YS52YWx1ZVwiXG4gICAgICAgIFtncmFkaWVudF09XCJncmFkaWVudFwiXG4gICAgICAgIFtkYXRhXT1cImFyYy5kYXRhXCJcbiAgICAgICAgW21heF09XCJtYXhcIlxuICAgICAgICBbZXhwbG9kZVNsaWNlc109XCJleHBsb2RlU2xpY2VzXCJcbiAgICAgICAgW2lzQWN0aXZlXT1cImlzQWN0aXZlKGFyYy5kYXRhKVwiXG4gICAgICAgIFthbmltYXRlXT1cImFuaW1hdGlvbnNcIlxuICAgICAgICAoc2VsZWN0KT1cIm9uQ2xpY2soJGV2ZW50KVwiXG4gICAgICAgIChhY3RpdmF0ZSk9XCJhY3RpdmF0ZS5lbWl0KCRldmVudClcIlxuICAgICAgICAoZGVhY3RpdmF0ZSk9XCJkZWFjdGl2YXRlLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgIChkYmxjbGljayk9XCJkYmxjbGljay5lbWl0KCRldmVudClcIlxuICAgICAgICBuZ3gtdG9vbHRpcFxuICAgICAgICBbdG9vbHRpcERpc2FibGVkXT1cInRvb2x0aXBEaXNhYmxlZFwiXG4gICAgICAgIFt0b29sdGlwUGxhY2VtZW50XT1cInBsYWNlbWVudFR5cGVzLlRvcFwiXG4gICAgICAgIFt0b29sdGlwVHlwZV09XCJzdHlsZVR5cGVzLnRvb2x0aXBcIlxuICAgICAgICBbdG9vbHRpcFRpdGxlXT1cImdldFRvb2x0aXBUaXRsZShhcmMpXCJcbiAgICAgICAgW3Rvb2x0aXBUZW1wbGF0ZV09XCJ0b29sdGlwVGVtcGxhdGVcIlxuICAgICAgICBbdG9vbHRpcENvbnRleHRdPVwiYXJjLmRhdGFcIlxuICAgICAgPjwvc3ZnOmc+XG4gICAgPC9zdmc6Zz5cbiAgYCxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgUGllU2VyaWVzQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgY29sb3JzOiBDb2xvckhlbHBlcjtcbiAgQElucHV0KCkgc2VyaWVzOiBEYXRhSXRlbVtdID0gW107XG4gIEBJbnB1dCgpIGRpbXM6IFZpZXdEaW1lbnNpb25zO1xuICBASW5wdXQoKSBpbm5lclJhZGl1czogbnVtYmVyID0gNjA7XG4gIEBJbnB1dCgpIG91dGVyUmFkaXVzOiBudW1iZXIgPSA4MDtcbiAgQElucHV0KCkgZXhwbG9kZVNsaWNlczogYm9vbGVhbjtcbiAgQElucHV0KCkgc2hvd0xhYmVsczogYm9vbGVhbjtcbiAgQElucHV0KCkgZ3JhZGllbnQ6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGFjdGl2ZUVudHJpZXM6IGFueVtdO1xuICBASW5wdXQoKSBsYWJlbEZvcm1hdHRpbmc6IGFueTtcbiAgQElucHV0KCkgdHJpbUxhYmVsczogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIG1heExhYmVsTGVuZ3RoOiBudW1iZXIgPSAxMDtcbiAgQElucHV0KCkgdG9vbHRpcFRleHQ6IChvOiBhbnkpID0+IGFueTtcbiAgQElucHV0KCkgdG9vbHRpcERpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIHRvb2x0aXBUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgQElucHV0KCkgYW5pbWF0aW9uczogYm9vbGVhbiA9IHRydWU7XG5cbiAgQE91dHB1dCgpIHNlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGFjdGl2YXRlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZGVhY3RpdmF0ZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGRibGNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIG1heDogbnVtYmVyO1xuICBkYXRhOiBQaWVEYXRhW107XG5cbiAgcGxhY2VtZW50VHlwZXMgPSBQbGFjZW1lbnRUeXBlcztcbiAgc3R5bGVUeXBlcyA9IFN0eWxlVHlwZXM7XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMudXBkYXRlKCk7XG4gIH1cblxuICB1cGRhdGUoKTogdm9pZCB7XG4gICAgY29uc3QgcGllR2VuZXJhdG9yID0gcGllPGFueSwgYW55PigpXG4gICAgICAudmFsdWUoZCA9PiBkLnZhbHVlKVxuICAgICAgLnNvcnQobnVsbCk7XG5cbiAgICBjb25zdCBhcmNEYXRhID0gcGllR2VuZXJhdG9yKHRoaXMuc2VyaWVzKTtcblxuICAgIHRoaXMubWF4ID0gbWF4KGFyY0RhdGEsIGQgPT4ge1xuICAgICAgcmV0dXJuIGQudmFsdWU7XG4gICAgfSk7XG5cbiAgICB0aGlzLmRhdGEgPSB0aGlzLmNhbGN1bGF0ZUxhYmVsUG9zaXRpb25zKGFyY0RhdGEpO1xuICAgIHRoaXMudG9vbHRpcFRleHQgPSB0aGlzLnRvb2x0aXBUZXh0IHx8IHRoaXMuZGVmYXVsdFRvb2x0aXBUZXh0O1xuICB9XG5cbiAgbWlkQW5nbGUoZCk6IG51bWJlciB7XG4gICAgcmV0dXJuIGQuc3RhcnRBbmdsZSArIChkLmVuZEFuZ2xlIC0gZC5zdGFydEFuZ2xlKSAvIDI7XG4gIH1cblxuICBvdXRlckFyYygpOiBhbnkge1xuICAgIGNvbnN0IGZhY3RvciA9IDEuNTtcblxuICAgIHJldHVybiBhcmMoKVxuICAgICAgLmlubmVyUmFkaXVzKHRoaXMub3V0ZXJSYWRpdXMgKiBmYWN0b3IpXG4gICAgICAub3V0ZXJSYWRpdXModGhpcy5vdXRlclJhZGl1cyAqIGZhY3Rvcik7XG4gIH1cblxuICBjYWxjdWxhdGVMYWJlbFBvc2l0aW9ucyhwaWVEYXRhKTogYW55IHtcbiAgICBjb25zdCBmYWN0b3IgPSAxLjU7XG4gICAgY29uc3QgbWluRGlzdGFuY2UgPSAxMDtcbiAgICBjb25zdCBsYWJlbFBvc2l0aW9ucyA9IHBpZURhdGE7XG5cbiAgICBsYWJlbFBvc2l0aW9ucy5mb3JFYWNoKGQgPT4ge1xuICAgICAgZC5wb3MgPSB0aGlzLm91dGVyQXJjKCkuY2VudHJvaWQoZCk7XG4gICAgICBkLnBvc1swXSA9IGZhY3RvciAqIHRoaXMub3V0ZXJSYWRpdXMgKiAodGhpcy5taWRBbmdsZShkKSA8IE1hdGguUEkgPyAxIDogLTEpO1xuICAgIH0pO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsYWJlbFBvc2l0aW9ucy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgIGNvbnN0IGEgPSBsYWJlbFBvc2l0aW9uc1tpXTtcbiAgICAgIGlmICghdGhpcy5sYWJlbFZpc2libGUoYSkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGogPSBpICsgMTsgaiA8IGxhYmVsUG9zaXRpb25zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGNvbnN0IGIgPSBsYWJlbFBvc2l0aW9uc1tqXTtcbiAgICAgICAgaWYgKCF0aGlzLmxhYmVsVmlzaWJsZShiKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHRoZXkncmUgb24gdGhlIHNhbWUgc2lkZVxuICAgICAgICBpZiAoYi5wb3NbMF0gKiBhLnBvc1swXSA+IDApIHtcbiAgICAgICAgICAvLyBpZiB0aGV5J3JlIG92ZXJsYXBwaW5nXG4gICAgICAgICAgY29uc3QgbyA9IG1pbkRpc3RhbmNlIC0gTWF0aC5hYnMoYi5wb3NbMV0gLSBhLnBvc1sxXSk7XG4gICAgICAgICAgaWYgKG8gPiAwKSB7XG4gICAgICAgICAgICAvLyBwdXNoIHRoZSBzZWNvbmQgdXAgb3IgZG93blxuICAgICAgICAgICAgYi5wb3NbMV0gKz0gTWF0aC5zaWduKGIucG9zWzBdKSAqIG87XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxhYmVsUG9zaXRpb25zO1xuICB9XG5cbiAgbGFiZWxWaXNpYmxlKG15QXJjKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2hvd0xhYmVscyAmJiBteUFyYy5lbmRBbmdsZSAtIG15QXJjLnN0YXJ0QW5nbGUgPiBNYXRoLlBJIC8gMzA7XG4gIH1cblxuICBnZXRUb29sdGlwVGl0bGUoYSkge1xuICAgIHJldHVybiB0aGlzLnRvb2x0aXBUZW1wbGF0ZSA/IHVuZGVmaW5lZCA6IHRoaXMudG9vbHRpcFRleHQoYSk7XG4gIH1cblxuICBsYWJlbFRleHQobXlBcmMpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmxhYmVsRm9ybWF0dGluZykge1xuICAgICAgcmV0dXJuIHRoaXMubGFiZWxGb3JtYXR0aW5nKG15QXJjLmRhdGEubmFtZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmxhYmVsKG15QXJjKTtcbiAgfVxuXG4gIGxhYmVsKG15QXJjKTogc3RyaW5nIHtcbiAgICByZXR1cm4gZm9ybWF0TGFiZWwobXlBcmMuZGF0YS5uYW1lKTtcbiAgfVxuXG4gIGRlZmF1bHRUb29sdGlwVGV4dChteUFyYyk6IHN0cmluZyB7XG4gICAgY29uc3QgbGFiZWwgPSB0aGlzLmxhYmVsKG15QXJjKTtcbiAgICBjb25zdCB2YWwgPSBmb3JtYXRMYWJlbChteUFyYy5kYXRhLnZhbHVlKTtcblxuICAgIHJldHVybiBgXG4gICAgICA8c3BhbiBjbGFzcz1cInRvb2x0aXAtbGFiZWxcIj4ke2VzY2FwZUxhYmVsKGxhYmVsKX08L3NwYW4+XG4gICAgICA8c3BhbiBjbGFzcz1cInRvb2x0aXAtdmFsXCI+JHt2YWx9PC9zcGFuPlxuICAgIGA7XG4gIH1cblxuICBjb2xvcihteUFyYyk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuY29sb3JzLmdldENvbG9yKHRoaXMubGFiZWwobXlBcmMpKTtcbiAgfVxuXG4gIHRyYWNrQnkoaW5kZXgsIGl0ZW0pOiBzdHJpbmcge1xuICAgIHJldHVybiBpdGVtLmRhdGEubmFtZTtcbiAgfVxuXG4gIG9uQ2xpY2soZGF0YSk6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0LmVtaXQoZGF0YSk7XG4gIH1cblxuICBpc0FjdGl2ZShlbnRyeSk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5hY3RpdmVFbnRyaWVzKSByZXR1cm4gZmFsc2U7XG4gICAgY29uc3QgaXRlbSA9IHRoaXMuYWN0aXZlRW50cmllcy5maW5kKGQgPT4ge1xuICAgICAgcmV0dXJuIGVudHJ5Lm5hbWUgPT09IGQubmFtZSAmJiBlbnRyeS5zZXJpZXMgPT09IGQuc2VyaWVzO1xuICAgIH0pO1xuICAgIHJldHVybiBpdGVtICE9PSB1bmRlZmluZWQ7XG4gIH1cbn1cbiJdfQ==