@swimlane/ngx-charts
Version:
Declarative Charting Framework for Angular
362 lines • 39.5 kB
JavaScript
import { Component, Input, Output, EventEmitter, HostListener, ChangeDetectionStrategy } from '@angular/core';
import { select } from 'd3-selection';
import { interpolate } from 'd3-interpolate';
import { easeSinInOut } from 'd3-ease';
import cloneDeep from 'clone-deep';
import { roundedRect } from '../common/shape.helper';
import { id } from '../utils/id';
import { BarOrientation } from '../common/types/bar-orientation.enum';
import * as i0 from "@angular/core";
import * as i1 from "../common/svg-linear-gradient.component";
import * as i2 from "@angular/common";
export class BoxComponent {
constructor(element, cd) {
this.cd = cd;
this.roundEdges = true;
this.gradient = false;
this.offset = 0;
this.isActive = false;
this.animations = true;
this.noBarWhenZero = true;
this.select = new EventEmitter();
this.activate = new EventEmitter();
this.deactivate = new EventEmitter();
this.BarOrientation = BarOrientation;
this.initialized = false;
this.hasGradient = false;
this.hideBar = false;
this.nativeElm = element.nativeElement;
}
ngOnChanges(changes) {
if (!this.initialized) {
this.loadAnimation();
this.initialized = true;
}
else {
this.update();
}
}
update() {
this.boxStrokeWidth = Math.max(this.strokeWidth, 1);
this.whiskerStrokeWidth = Math.max(this.strokeWidth / 2, 1);
this.medianLineWidth = 1.5 * this.strokeWidth;
this.gradientId = 'grad' + id().toString();
this.gradientFill = `url(#${this.gradientId})`;
if (this.gradient) {
this.gradientStops = this.getGradient();
this.hasGradient = true;
}
else {
this.hasGradient = false;
}
this.updateLineEl();
this.updatePathEl();
this.checkToHideBar();
this.maskLineId = 'mask' + id().toString();
this.maskLine = `url(#${this.maskLineId})`;
if (this.cd) {
this.cd.markForCheck();
}
}
loadAnimation() {
this.boxPath = this.oldPath = this.getStartingPath();
this.oldLineCoordinates = this.getStartingLineCoordinates();
setTimeout(this.update.bind(this), 100);
}
updatePathEl() {
const nodeBar = select(this.nativeElm).selectAll('.bar');
const path = this.getPath();
if (this.animations) {
nodeBar
.attr('d', this.oldPath)
.transition()
.ease(easeSinInOut)
.duration(500)
.attrTween('d', this.pathTween(path, 4));
}
else {
nodeBar.attr('d', path);
}
this.oldPath = path;
}
updateLineEl() {
const lineEl = select(this.nativeElm).selectAll('.bar-line');
const lineCoordinates = this.lineCoordinates;
const oldLineCoordinates = this.oldLineCoordinates;
if (this.animations) {
lineEl
.attr('x1', (_, index) => oldLineCoordinates[index].v1.x)
.attr('y1', (_, index) => oldLineCoordinates[index].v1.y)
.attr('x2', (_, index) => oldLineCoordinates[index].v2.x)
.attr('y2', (_, index) => oldLineCoordinates[index].v2.y)
.transition()
.ease(easeSinInOut)
.duration(500)
.attr('x1', (_, index) => lineCoordinates[index].v1.x)
.attr('y1', (_, index) => lineCoordinates[index].v1.y)
.attr('x2', (_, index) => lineCoordinates[index].v2.x)
.attr('y2', (_, index) => lineCoordinates[index].v2.y);
}
else {
lineEl
.attr('x1', (_, index) => lineCoordinates[index].v1.x)
.attr('y1', (_, index) => lineCoordinates[index].v1.y)
.attr('x2', (_, index) => lineCoordinates[index].v2.x)
.attr('y2', (_, index) => lineCoordinates[index].v2.y);
}
this.oldLineCoordinates = [...lineCoordinates];
}
/**
* See [D3 Selections](https://www.d3indepth.com/selections/)
* @param d The joined data.
* @param index The index of the element within the selection
* @param node The node element (Line).
*/
lineTween(attr, d, index, node) {
const nodeLineEl = node[index];
return nodeLineEl[attr].baseVal.value;
}
// TODO: Refactor into another .ts file if https://github.com/swimlane/ngx-charts/pull/1179 gets merged.
pathTween(d1, precision) {
return function () {
// tslint:disable-next-line: no-this-assignment
const path0 = this;
const path1 = this.cloneNode();
path1.setAttribute('d', d1);
const n0 = path0?.getTotalLength();
const n1 = path1?.getTotalLength();
// Uniform sampling of distance based on specified precision.
const distances = [0];
let i = 0;
const dt = precision / Math.max(n0, n1);
while (i < 1) {
distances.push(i);
i += dt;
}
distances.push(1);
// Compute point-interpolators at each distance.
const points = distances.map((t) => {
const p0 = path0.getPointAtLength(t * n0);
const p1 = path1.getPointAtLength(t * n1);
return interpolate([p0.x, p0.y], [p1.x, p1.y]);
});
// 't': T is the fraction of time (between 0 and 1) since the transition began.
return (t) => {
return t < 1 ? 'M' + points.map((p) => p(t)).join('L') : d1;
};
};
}
getStartingPath() {
if (!this.animations) {
return this.getPath();
}
const radius = this.roundEdges ? 1 : 0;
const { x, y } = this.lineCoordinates[2].v1;
return roundedRect(x - this.width, y - 1, this.width, 2, radius, this.edges);
}
getPath() {
const radius = this.getRadius();
let path = '';
path = roundedRect(this.x, this.y, this.width, this.height, Math.min(this.height, radius), this.edges);
return path;
}
getStartingLineCoordinates() {
if (!this.animations) {
return [...this.lineCoordinates];
}
const lineCoordinates = cloneDeep(this.lineCoordinates);
lineCoordinates[1].v1.y = lineCoordinates[1].v2.y = lineCoordinates[3].v1.y = lineCoordinates[3].v2.y = lineCoordinates[0].v1.y = lineCoordinates[0].v2.y =
lineCoordinates[2].v1.y;
return lineCoordinates;
}
getRadius() {
let radius = 0;
if (this.roundEdges && this.height > 5 && this.width > 5) {
radius = Math.floor(Math.min(5, this.height / 2, this.width / 2));
}
return radius;
}
getGradient() {
return [
{
offset: 0,
color: this.fill,
opacity: this.getStartOpacity()
},
{
offset: 100,
color: this.fill,
opacity: 1
}
];
}
getStartOpacity() {
if (this.roundEdges) {
return 0.2;
}
else {
return 0.5;
}
}
get edges() {
let edges = [false, false, false, false];
if (this.roundEdges) {
edges = [true, true, true, true];
}
return edges;
}
onMouseEnter() {
this.activate.emit(this.data);
}
onMouseLeave() {
this.deactivate.emit(this.data);
}
checkToHideBar() {
this.hideBar = this.noBarWhenZero && this.height === 0;
}
}
BoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
BoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.0", type: BoxComponent, selector: "g[ngx-charts-box]", inputs: { strokeColor: "strokeColor", strokeWidth: "strokeWidth", fill: "fill", data: "data", width: "width", height: "height", x: "x", y: "y", lineCoordinates: "lineCoordinates", roundEdges: "roundEdges", gradient: "gradient", gradientStops: "gradientStops", offset: "offset", isActive: "isActive", animations: "animations", ariaLabel: "ariaLabel", noBarWhenZero: "noBarWhenZero" }, outputs: { select: "select", activate: "activate", deactivate: "deactivate" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, usesOnChanges: true, ngImport: i0, template: `
<svg:defs>
<svg:g
*ngIf="hasGradient"
ngx-charts-svg-linear-gradient
[orientation]="BarOrientation.Vertical"
[name]="gradientId"
[stops]="gradientStops"
/>
<svg:mask [attr.id]="maskLineId">
<svg:g>
<rect height="100%" width="100%" fill="white" fill-opacity="1" />
<path class="bar" [attr.d]="boxPath" fill="black" fill-opacity="1" />
</svg:g>
</svg:mask>
</svg:defs>
<svg:g>
<svg:path
class="bar"
role="img"
tabIndex="-1"
[class.active]="isActive"
[class.hidden]="hideBar"
[attr.d]="boxPath"
[attr.stroke]="strokeColor"
[attr.stroke-width]="boxStrokeWidth"
[attr.aria-label]="ariaLabel"
[attr.fill]="hasGradient ? gradientFill : fill"
(click)="select.emit(data)"
/>
<svg:line
*ngFor="let line of lineCoordinates; let i = index"
class="bar-line"
[class.hidden]="hideBar"
[attr.x1]="line.v1.x"
[attr.y1]="line.v1.y"
[attr.x2]="line.v2.x"
[attr.y2]="line.v2.y"
[attr.stroke]="strokeColor"
[attr.stroke-width]="i === 2 ? medianLineWidth : whiskerStrokeWidth"
[attr.mask]="i ? undefined : maskLine"
fill="none"
/>
</svg:g>
`, isInline: true, components: [{ type: i1.SvgLinearGradientComponent, selector: "g[ngx-charts-svg-linear-gradient]", inputs: ["orientation", "name", "stops"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.0", ngImport: i0, type: BoxComponent, decorators: [{
type: Component,
args: [{
selector: 'g[ngx-charts-box]',
template: `
<svg:defs>
<svg:g
*ngIf="hasGradient"
ngx-charts-svg-linear-gradient
[orientation]="BarOrientation.Vertical"
[name]="gradientId"
[stops]="gradientStops"
/>
<svg:mask [attr.id]="maskLineId">
<svg:g>
<rect height="100%" width="100%" fill="white" fill-opacity="1" />
<path class="bar" [attr.d]="boxPath" fill="black" fill-opacity="1" />
</svg:g>
</svg:mask>
</svg:defs>
<svg:g>
<svg:path
class="bar"
role="img"
tabIndex="-1"
[class.active]="isActive"
[class.hidden]="hideBar"
[attr.d]="boxPath"
[attr.stroke]="strokeColor"
[attr.stroke-width]="boxStrokeWidth"
[attr.aria-label]="ariaLabel"
[attr.fill]="hasGradient ? gradientFill : fill"
(click)="select.emit(data)"
/>
<svg:line
*ngFor="let line of lineCoordinates; let i = index"
class="bar-line"
[class.hidden]="hideBar"
[attr.x1]="line.v1.x"
[attr.y1]="line.v1.y"
[attr.x2]="line.v2.x"
[attr.y2]="line.v2.y"
[attr.stroke]="strokeColor"
[attr.stroke-width]="i === 2 ? medianLineWidth : whiskerStrokeWidth"
[attr.mask]="i ? undefined : maskLine"
fill="none"
/>
</svg:g>
`,
changeDetection: ChangeDetectionStrategy.OnPush
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { strokeColor: [{
type: Input
}], strokeWidth: [{
type: Input
}], fill: [{
type: Input
}], data: [{
type: Input
}], width: [{
type: Input
}], height: [{
type: Input
}], x: [{
type: Input
}], y: [{
type: Input
}], lineCoordinates: [{
type: Input
}], roundEdges: [{
type: Input
}], gradient: [{
type: Input
}], gradientStops: [{
type: Input
}], offset: [{
type: Input
}], isActive: [{
type: Input
}], animations: [{
type: Input
}], ariaLabel: [{
type: Input
}], noBarWhenZero: [{
type: Input
}], select: [{
type: Output
}], activate: [{
type: Output
}], deactivate: [{
type: Output
}], onMouseEnter: [{
type: HostListener,
args: ['mouseenter']
}], onMouseLeave: [{
type: HostListener,
args: ['mouseleave']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm94LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N3aW1sYW5lL25neC1jaGFydHMvc3JjL2xpYi9ib3gtY2hhcnQvYm94LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUNaLFlBQVksRUFJWix1QkFBdUIsRUFFeEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLE1BQU0sRUFBWSxNQUFNLGNBQWMsQ0FBQztBQUNoRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUV2QyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFFbkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHakMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNDQUFzQyxDQUFDOzs7O0FBc0R0RSxNQUFNLE9BQU8sWUFBWTtJQWdEdkIsWUFBWSxPQUFtQixFQUFZLEVBQXFCO1FBQXJCLE9BQUUsR0FBRixFQUFFLENBQW1CO1FBdEN2RCxlQUFVLEdBQVksSUFBSSxDQUFDO1FBQzNCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFFMUIsV0FBTSxHQUFXLENBQUMsQ0FBQztRQUNuQixhQUFRLEdBQVksS0FBSyxDQUFDO1FBQzFCLGVBQVUsR0FBWSxJQUFJLENBQUM7UUFFM0Isa0JBQWEsR0FBWSxJQUFJLENBQUM7UUFFN0IsV0FBTSxHQUE0QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3JELGFBQVEsR0FBNEIsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN2RCxlQUFVLEdBQTRCLElBQUksWUFBWSxFQUFFLENBQUM7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Q0FBQyxDQUFDO2lCQUNyRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7aUJBQ3JELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztpQkFDckQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDMUQ7YUFBTTtZQUNMLE1BQU07aUJBQ0gsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2lCQUNyRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7aUJBQ3JELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztpQkFDckQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDMUQ7UUFDRCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILFNBQVMsQ0FBQyxJQUFZLEVBQUUsQ0FB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TyxHQUFHLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7SUFDekQsQ0FBQzs7eUdBMVFVLFlBQVk7NkZBQVosWUFBWSxzbkJBL0NiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRDVDsyRkFHVSxZQUFZO2tCQWpEeEIsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsbUJBQW1CO29CQUM3QixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNENUO29CQUNELGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2lCQUNoRDtpSUFFVSxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLENBQUM7c0JBQVQsS0FBSztnQkFDRyxDQUFDO3NCQUFULEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFFSSxNQUFNO3NCQUFmLE1BQU07Z0JBQ0csUUFBUTtzQkFBakIsTUFBTTtnQkFDRyxVQUFVO3NCQUFuQixNQUFNO2dCQTBPUCxZQUFZO3NCQURYLFlBQVk7dUJBQUMsWUFBWTtnQkFNMUIsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdExpc3RlbmVyLFxuICBFbGVtZW50UmVmLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBPbkNoYW5nZXMsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHNlbGVjdCwgQmFzZVR5cGUgfSBmcm9tICdkMy1zZWxlY3Rpb24nO1xuaW1wb3J0IHsgaW50ZXJwb2xhdGUgfSBmcm9tICdkMy1pbnRlcnBvbGF0ZSc7XG5pbXBvcnQgeyBlYXNlU2luSW5PdXQgfSBmcm9tICdkMy1lYXNlJztcblxuaW1wb3J0IGNsb25lRGVlcCBmcm9tICdjbG9uZS1kZWVwJztcblxuaW1wb3J0IHsgcm91bmRlZFJlY3QgfSBmcm9tICcuLi9jb21tb24vc2hhcGUuaGVscGVyJztcbmltcG9ydCB7IGlkIH0gZnJvbSAnLi4vdXRpbHMvaWQnO1xuaW1wb3J0IHsgSUJveE1vZGVsIH0gZnJvbSAnLi4vbW9kZWxzL2NoYXJ0LWRhdGEubW9kZWwnO1xuaW1wb3J0IHsgSVZlY3RvcjJEIH0gZnJvbSAnLi4vbW9kZWxzL2Nvb3JkaW5hdGVzLm1vZGVsJztcbmltcG9ydCB7IEJhck9yaWVudGF0aW9uIH0gZnJvbSAnLi4vY29tbW9uL3R5cGVzL2Jhci1vcmllbnRhdGlvbi5lbnVtJztcbmltcG9ydCB7IEdyYWRpZW50IH0gZnJvbSAnLi4vY29tbW9uL3R5cGVzL2dyYWRpZW50LmludGVyZmFjZSc7XG5cbnR5cGUgTGluZUNvb3JkaW5hdGVzID0gW0lWZWN0b3IyRCwgSVZlY3RvcjJELCBJVmVjdG9yMkQsIElWZWN0b3IyRF07XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dbbmd4LWNoYXJ0cy1ib3hdJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8c3ZnOmRlZnM+XG4gICAgICA8c3ZnOmdcbiAgICAgICAgKm5nSWY9XCJoYXNHcmFkaWVudFwiXG4gICAgICAgIG5neC1jaGFydHMtc3ZnLWxpbmVhci1ncmFkaWVudFxuICAgICAgICBbb3JpZW50YXRpb25dPVwiQmFyT3JpZW50YXRpb24uVmVydGljYWxcIlxuICAgICAgICBbbmFtZV09XCJncmFkaWVudElkXCJcbiAgICAgICAgW3N0b3BzXT1cImdyYWRpZW50U3RvcHNcIlxuICAgICAgLz5cbiAgICAgIDxzdmc6bWFzayBbYXR0ci5pZF09XCJtYXNrTGluZUlkXCI+XG4gICAgICAgIDxzdmc6Zz5cbiAgICAgICAgICA8cmVjdCBoZWlnaHQ9XCIxMDAlXCIgd2lkdGg9XCIxMDAlXCIgZmlsbD1cIndoaXRlXCIgZmlsbC1vcGFjaXR5PVwiMVwiIC8+XG4gICAgICAgICAgPHBhdGggY2xhc3M9XCJiYXJcIiBbYXR0ci5kXT1cImJveFBhdGhcIiBmaWxsPVwiYmxhY2tcIiBmaWxsLW9wYWNpdHk9XCIxXCIgLz5cbiAgICAgICAgPC9zdmc6Zz5cbiAgICAgIDwvc3ZnOm1hc2s+XG4gICAgPC9zdmc6ZGVmcz5cbiAgICA8c3ZnOmc+XG4gICAgICA8c3ZnOnBhdGhcbiAgICAgICAgY2xhc3M9XCJiYXJcIlxuICAgICAgICByb2xlPVwiaW1nXCJcbiAgICAgICAgdGFiSW5kZXg9XCItMVwiXG4gICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiaXNBY3RpdmVcIlxuICAgICAgICBbY2xhc3MuaGlkZGVuXT1cImhpZGVCYXJcIlxuICAgICAgICBbYXR0ci5kXT1cImJveFBhdGhcIlxuICAgICAgICBbYXR0ci5zdHJva2VdPVwic3Ryb2tlQ29sb3JcIlxuICAgICAgICBbYXR0ci5zdHJva2Utd2lkdGhdPVwiYm94U3Ryb2tlV2lkdGhcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiXG4gICAgICAgIFthdHRyLmZpbGxdPVwiaGFzR3JhZGllbnQgPyBncmFkaWVudEZpbGwgOiBmaWxsXCJcbiAgICAgICAgKGNsaWNrKT1cInNlbGVjdC5lbWl0KGRhdGEpXCJcbiAgICAgIC8+XG4gICAgICA8c3ZnOmxpbmVcbiAgICAgICAgKm5nRm9yPVwibGV0IGxpbmUgb2YgbGluZUNvb3JkaW5hdGVzOyBsZXQgaSA9IGluZGV4XCJcbiAgICAgICAgY2xhc3M9XCJiYXItbGluZVwiXG4gICAgICAgIFtjbGFzcy5oaWRkZW5dPVwiaGlkZUJhclwiXG4gICAgICAgIFthdHRyLngxXT1cImxpbmUudjEueFwiXG4gICAgICAgIFthdHRyLnkxXT1cImxpbmUudjEueVwiXG4gICAgICAgIFthdHRyLngyXT1cImxpbmUudjIueFwiXG4gICAgICAgIFthdHRyLnkyXT1cImxpbmUudjIueVwiXG4gICAgICAgIFthdHRyLnN0cm9rZV09XCJzdHJva2VDb2xvclwiXG4gICAgICAgIFthdHRyLnN0cm9rZS13aWR0aF09XCJpID09PSAyID8gbWVkaWFuTGluZVdpZHRoIDogd2hpc2tlclN0cm9rZVdpZHRoXCJcbiAgICAgICAgW2F0dHIubWFza109XCJpID8gdW5kZWZpbmVkIDogbWFza0xpbmVcIlxuICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAvPlxuICAgIDwvc3ZnOmc+XG4gIGAsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEJveENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIEBJbnB1dCgpIHN0cm9rZUNvbG9yOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHN0cm9rZVdpZHRoOiBudW1iZXI7XG4gIEBJbnB1dCgpIGZpbGw6IHN0cmluZztcbiAgQElucHV0KCkgZGF0YTogSUJveE1vZGVsO1xuICBASW5wdXQoKSB3aWR0aDogbnVtYmVyO1xuICBASW5wdXQoKSBoZWlnaHQ6IG51bWJlcjtcbiAgQElucHV0KCkgeDogbnVtYmVyO1xuICBASW5wdXQoKSB5OiBudW1iZXI7XG4gIEBJbnB1dCgpIGxpbmVDb29yZGluYXRlczogTGluZUNvb3JkaW5hdGVzO1xuICBASW5wdXQoKSByb3VuZEVkZ2VzOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgZ3JhZGllbnQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgZ3JhZGllbnRTdG9wczogR3JhZGllbnRbXTtcbiAgQElucHV0KCkgb2Zmc2V0OiBudW1iZXIgPSAwO1xuICBASW5wdXQoKSBpc0FjdGl2ZTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBhbmltYXRpb25zOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgYXJpYUxhYmVsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIG5vQmFyV2hlblplcm86IGJvb2xlYW4gPSB0cnVlO1xuXG4gIEBPdXRwdXQoKSBzZWxlY3Q6IEV2ZW50RW1pdHRlcjxJQm94TW9kZWw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgYWN0aXZhdGU6IEV2ZW50RW1pdHRlcjxJQm94TW9kZWw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZGVhY3RpdmF0ZTogRXZlbnRFbWl0dGVyPElCb3hNb2RlbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQmFyT3JpZW50YXRpb24gPSBCYXJPcmllbnRhdGlvbjtcblxuICBuYXRpdmVFbG06IGFueTtcblxuICAvLyBQYXRoIHJlbGF0ZWQgcHJvcGVydGllcy5cbiAgb2xkUGF0aDogc3RyaW5nO1xuICBib3hQYXRoOiBzdHJpbmc7XG4gIG9sZExpbmVDb29yZGluYXRlczogTGluZUNvb3JkaW5hdGVzO1xuXG4gIC8vIENvbG9yIHJlbGF0ZWQgcHJvcGVydGllcy5cbiAgZ3JhZGllbnRJZDogc3RyaW5nO1xuICBncmFkaWVudEZpbGw6IHN0cmluZztcbiAgaW5pdGlhbGl6ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgaGFzR3JhZGllbnQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgaGlkZUJhcjogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBNYXNrIFBhdGggdG8gY3V0IHRoZSBsaW5lIG9uIHRoZSBib3ggcGFydC4gKi9cbiAgbWFza0xpbmU6IHN0cmluZztcbiAgLyoqIE1hc2sgUGF0aCBJZCB0byBrZWVwIHRyYWNrIG9mIHRoZSBtYXNrIGVsZW1lbnQgKi9cbiAgbWFza0xpbmVJZDogc3RyaW5nO1xuXG4gIGJveFN0cm9rZVdpZHRoOiBudW1iZXI7XG4gIHdoaXNrZXJTdHJva2VXaWR0aDogbnVtYmVyO1xuICBtZWRpYW5MaW5lV2lkdGg6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihlbGVtZW50OiBFbGVtZW50UmVmLCBwcm90ZWN0ZWQgY2Q6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgdGhpcy5uYXRpdmVFbG0gPSBlbGVtZW50Lm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLmxvYWRBbmltYXRpb24oKTtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLmJveFN0cm9rZVdpZHRoID0gTWF0aC5tYXgodGhpcy5zdHJva2VXaWR0aCwgMSk7XG4gICAgdGhpcy53aGlza2VyU3Ryb2tlV2lkdGggPSBNYXRoLm1heCh0aGlzLnN0cm9rZVdpZHRoIC8gMiwgMSk7XG4gICAgdGhpcy5tZWRpYW5MaW5lV2lkdGggPSAxLjUgKiB0aGlzLnN0cm9rZVdpZHRoO1xuXG4gICAgdGhpcy5ncmFkaWVudElkID0gJ2dyYWQnICsgaWQoKS50b1N0cmluZygpO1xuICAgIHRoaXMuZ3JhZGllbnRGaWxsID0gYHVybCgjJHt0aGlzLmdyYWRpZW50SWR9KWA7XG5cbiAgICBpZiAodGhpcy5ncmFkaWVudCkge1xuICAgICAgdGhpcy5ncmFkaWVudFN0b3BzID0gdGhpcy5nZXRHcmFkaWVudCgpO1xuICAgICAgdGhpcy5oYXNHcmFkaWVudCA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGFzR3JhZGllbnQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZUxpbmVFbCgpO1xuICAgIHRoaXMudXBkYXRlUGF0aEVsKCk7XG4gICAgdGhpcy5jaGVja1RvSGlkZUJhcigpO1xuICAgIHRoaXMubWFza0xpbmVJZCA9ICdtYXNrJyArIGlkKCkudG9TdHJpbmcoKTtcbiAgICB0aGlzLm1hc2tMaW5lID0gYHVybCgjJHt0aGlzLm1hc2tMaW5lSWR9KWA7XG5cbiAgICBpZiAodGhpcy5jZCkge1xuICAgICAgdGhpcy5jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICBsb2FkQW5pbWF0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuYm94UGF0aCA9IHRoaXMub2xkUGF0aCA9IHRoaXMuZ2V0U3RhcnRpbmdQYXRoKCk7XG4gICAgdGhpcy5vbGRMaW5lQ29vcmRpbmF0ZXMgPSB0aGlzLmdldFN0YXJ0aW5nTGluZUNvb3JkaW5hdGVzKCk7XG4gICAgc2V0VGltZW91dCh0aGlzLnVwZGF0ZS5iaW5kKHRoaXMpLCAxMDApO1xuICB9XG5cbiAgdXBkYXRlUGF0aEVsKCk6IHZvaWQge1xuICAgIGNvbnN0IG5vZGVCYXIgPSBzZWxlY3QodGhpcy5uYXRpdmVFbG0pLnNlbGVjdEFsbCgnLmJhcicpO1xuICAgIGNvbnN0IHBhdGggPSB0aGlzLmdldFBhdGgoKTtcbiAgICBpZiAodGhpcy5hbmltYXRpb25zKSB7XG4gICAgICBub2RlQmFyXG4gICAgICAgIC5hdHRyKCdkJywgdGhpcy5vbGRQYXRoKVxuICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGVhc2VTaW5Jbk91dClcbiAgICAgICAgLmR1cmF0aW9uKDUwMClcbiAgICAgICAgLmF0dHJUd2VlbignZCcsIHRoaXMucGF0aFR3ZWVuKHBhdGgsIDQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbm9kZUJhci5hdHRyKCdkJywgcGF0aCk7XG4gICAgfVxuICAgIHRoaXMub2xkUGF0aCA9IHBhdGg7XG4gIH1cblxuICB1cGRhdGVMaW5lRWwoKTogdm9pZCB7XG4gICAgY29uc3QgbGluZUVsID0gc2VsZWN0KHRoaXMubmF0aXZlRWxtKS5zZWxlY3RBbGwoJy5iYXItbGluZScpO1xuICAgIGNvbnN0IGxpbmVDb29yZGluYXRlcyA9IHRoaXMubGluZUNvb3JkaW5hdGVzO1xuICAgIGNvbnN0IG9sZExpbmVDb29yZGluYXRlcyA9IHRoaXMub2xkTGluZUNvb3JkaW5hdGVzO1xuICAgIGlmICh0aGlzLmFuaW1hdGlvbnMpIHtcbiAgICAgIGxpbmVFbFxuICAgICAgICAuYXR0cigneDEnLCAoXywgaW5kZXgpID0+IG9sZExpbmVDb29yZGluYXRlc1tpbmRleF0udjEueClcbiAgICAgICAgLmF0dHIoJ3kxJywgKF8sIGluZGV4KSA9PiBvbGRMaW5lQ29vcmRpbmF0ZXNbaW5kZXhdLnYxLnkpXG4gICAgICAgIC5hdHRyKCd4MicsIChfLCBpbmRleCkgPT4gb2xkTGluZUNvb3JkaW5hdGVzW2luZGV4XS52Mi54KVxuICAgICAgICAuYXR0cigneTInLCAoXywgaW5kZXgpID0+IG9sZExpbmVDb29yZGluYXRlc1tpbmRleF0udjIueSlcbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShlYXNlU2luSW5PdXQpXG4gICAgICAgIC5kdXJhdGlvbig1MDApXG4gICAgICAgIC5hdHRyKCd4MScsIChfLCBpbmRleCkgPT4gbGluZUNvb3JkaW5hdGVzW2luZGV4XS52MS54KVxuICAgICAgICAuYXR0cigneTEnLCAoXywgaW5kZXgpID0+IGxpbmVDb29yZGluYXRlc1tpbmRleF0udjEueSlcbiAgICAgICAgLmF0dHIoJ3gyJywgKF8sIGluZGV4KSA9PiBsaW5lQ29vcmRpbmF0ZXNbaW5kZXhdLnYyLngpXG4gICAgICAgIC5hdHRyKCd5MicsIChfLCBpbmRleCkgPT4gbGluZUNvb3JkaW5hdGVzW2luZGV4XS52Mi55KTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGluZUVsXG4gICAgICAgIC5hdHRyKCd4MScsIChfLCBpbmRleCkgPT4gbGluZUNvb3JkaW5hdGVzW2luZGV4XS52MS54KVxuICAgICAgICAuYXR0cigneTEnLCAoXywgaW5kZXgpID0+IGxpbmVDb29yZGluYXRlc1tpbmRleF0udjEueSlcbiAgICAgICAgLmF0dHIoJ3gyJywgKF8sIGluZGV4KSA9PiBsaW5lQ29vcmRpbmF0ZXNbaW5kZXhdLnYyLngpXG4gICAgICAgIC5hdHRyKCd5MicsIChfLCBpbmRleCkgPT4gbGluZUNvb3JkaW5hdGVzW2luZGV4XS52Mi55KTtcbiAgICB9XG4gICAgdGhpcy5vbGRMaW5lQ29vcmRpbmF0ZXMgPSBbLi4ubGluZUNvb3JkaW5hdGVzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZWUgW0QzIFNlbGVjdGlvbnNdKGh0dHBzOi8vd3d3LmQzaW5kZXB0aC5jb20vc2VsZWN0aW9ucy8pXG4gICAqIEBwYXJhbSBkIFRoZSBqb2luZWQgZGF0YS5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCB3aXRoaW4gdGhlIHNlbGVjdGlvblxuICAgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSBlbGVtZW50IChMaW5lKS5cbiAgICovXG4gIGxpbmVUd2VlbihhdHRyOiBzdHJpbmcsIGQ6IGFueSwgaW5kZXg6IG51bWJlciwgbm9kZTogQmFzZVR5cGVbXSB8IEFycmF5TGlrZTxCYXNlVHlwZT4pIHtcbiAgICBjb25zdCBub2RlTGluZUVsID0gbm9kZVtpbmRleF0gYXMgU1ZHTGluZUVsZW1lbnQ7XG4gICAgcmV0dXJuIG5vZGVMaW5lRWxbYXR0cl0uYmFzZVZhbC52YWx1ZTtcbiAgfVxuXG4gIC8vIFRPRE86IFJlZmFjdG9yIGludG8gYW5vdGhlciAudHMgZmlsZSBpZiBodHRwczovL2dpdGh1Yi5jb20vc3dpbWxhbmUvbmd4LWNoYXJ0cy9wdWxsLzExNzkgZ2V0cyBtZXJnZWQuXG4gIHBhdGhUd2VlbihkMTogc3RyaW5nLCBwcmVjaXNpb246IG51bWJlcikge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG5vLXRoaXMtYXNzaWdubWVudFxuICAgICAgY29uc3QgcGF0aDAgPSB0aGlzO1xuICAgICAgY29uc3QgcGF0aDEgPSB0aGlzLmNsb25lTm9kZSgpO1xuICAgICAgcGF0aDEuc2V0QXR0cmlidXRlKCdkJywgZDEpO1xuICAgICAgY29uc3QgbjAgPSBwYXRoMD8uZ2V0VG90YWxMZW5ndGgoKTtcbiAgICAgIGNvbnN0IG4xID0gcGF0aDE/LmdldFRvdGFsTGVuZ3RoKCk7XG4gICAgICAvLyBVbmlmb3JtIHNhbXBsaW5nIG9mIGRpc3RhbmNlIGJhc2VkIG9uIHNwZWNpZmllZCBwcmVjaXNpb24uXG4gICAgICBjb25zdCBkaXN0YW5jZXMgPSBbMF07XG4gICAgICBsZXQgaSA9IDA7XG4gICAgICBjb25zdCBkdCA9IHByZWNpc2lvbiAvIE1hdGgubWF4KG4wLCBuMSk7XG4gICAgICB3aGlsZSAoaSA8IDEpIHtcbiAgICAgICAgZGlzdGFuY2VzLnB1c2goaSk7XG4gICAgICAgIGkgKz0gZHQ7XG4gICAgICB9XG4gICAgICBkaXN0YW5jZXMucHVzaCgxKTtcblxuICAgICAgLy8gQ29tcHV0ZSBwb2ludC1pbnRlcnBvbGF0b3JzIGF0IGVhY2ggZGlzdGFuY2UuXG4gICAgICBjb25zdCBwb2ludHMgPSBkaXN0YW5jZXMubWFwKCh0OiBudW1iZXIpID0+IHtcbiAgICAgICAgY29uc3QgcDAgPSBwYXRoMC5nZXRQb2ludEF0TGVuZ3RoKHQgKiBuMCk7XG4gICAgICAgIGNvbnN0IHAxID0gcGF0aDEuZ2V0UG9pbnRBdExlbmd0aCh0ICogbjEpO1xuICAgICAgICByZXR1cm4gaW50ZXJwb2xhdGUoW3AwLngsIHAwLnldLCBbcDEueCwgcDEueV0pO1xuICAgICAgfSk7XG5cbiAgICAgIC8vICd0JzogVCBpcyB0aGUgZnJhY3Rpb24gb2YgdGltZSAoYmV0d2VlbiAwIGFuZCAxKSBzaW5jZSB0aGUgdHJhbnNpdGlvbiBiZWdhbi5cbiAgICAgIHJldHVybiAodDogYW55KSA9PiB7XG4gICAgICAgIHJldHVybiB0IDwgMSA/ICdNJyArIHBvaW50cy5tYXAoKHA6ICh0OiBudW1iZXIpID0+IGFueVtdKSA9PiBwKHQpKS5qb2luKCdMJykgOiBkMTtcbiAgICAgIH07XG4gICAgfTtcbiAgfVxuXG4gIGdldFN0YXJ0aW5nUGF0aCgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5hbmltYXRpb25zKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRQYXRoKCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmFkaXVzID0gdGhpcy5yb3VuZEVkZ2VzID8gMSA6IDA7XG4gICAgY29uc3QgeyB4LCB5IH0gPSB0aGlzLmxpbmVDb29yZGluYXRlc1syXS52MTtcblxuICAgIHJldHVybiByb3VuZGVkUmVjdCh4IC0gdGhpcy53aWR0aCwgeSAtIDEsIHRoaXMud2lkdGgsIDIsIHJhZGl1cywgdGhpcy5lZGdlcyk7XG4gIH1cblxuICBnZXRQYXRoKCk6IHN0cmluZyB7XG4gICAgY29uc3QgcmFkaXVzID0gdGhpcy5nZXRSYWRpdXMoKTtcbiAgICBsZXQgcGF0aCA9ICcnO1xuXG4gICAgcGF0aCA9IHJvdW5kZWRSZWN0KHRoaXMueCwgdGhpcy55LCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCwgTWF0aC5taW4odGhpcy5oZWlnaHQsIHJhZGl1cyksIHRoaXMuZWRnZXMpO1xuXG4gICAgcmV0dXJuIHBhdGg7XG4gIH1cblxuICBnZXRTdGFydGluZ0xpbmVDb29yZGluYXRlcygpOiBMaW5lQ29vcmRpbmF0ZXMge1xuICAgIGlmICghdGhpcy5hbmltYXRpb25zKSB7XG4gICAgICByZXR1cm4gWy4uLnRoaXMubGluZUNvb3JkaW5hdGVzXTtcbiAgICB9XG5cbiAgICBjb25zdCBsaW5lQ29vcmRpbmF0ZXM6IExpbmVDb29yZGluYXRlcyA9IGNsb25lRGVlcCh0aGlzLmxpbmVDb29yZGluYXRlcyk7XG5cbiAgICBsaW5lQ29vcmRpbmF0ZXNbMV0udjEueSA9IGxpbmVDb29yZGluYXRlc1sxXS52Mi55ID0gbGluZUNvb3JkaW5hdGVzWzNdLnYxLnkgPSBsaW5lQ29vcmRpbmF0ZXNbM10udjIueSA9IGxpbmVDb29yZGluYXRlc1swXS52MS55ID0gbGluZUNvb3JkaW5hdGVzWzBdLnYyLnkgPVxuICAgICAgbGluZUNvb3JkaW5hdGVzWzJdLnYxLnk7XG5cbiAgICByZXR1cm4gbGluZUNvb3JkaW5hdGVzO1xuICB9XG5cbiAgZ2V0UmFkaXVzKCk6IG51bWJlciB7XG4gICAgbGV0IHJhZGl1cyA9IDA7XG5cbiAgICBpZiAodGhpcy5yb3VuZEVkZ2VzICYmIHRoaXMuaGVpZ2h0ID4gNSAmJiB0aGlzLndpZHRoID4gNSkge1xuICAgICAgcmFkaXVzID0gTWF0aC5mbG9vcihNYXRoLm1pbig1LCB0aGlzLmhlaWdodCAvIDIsIHRoaXMud2lkdGggLyAyKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJhZGl1cztcbiAgfVxuXG4gIGdldEdyYWRpZW50KCk6IEdyYWRpZW50W10ge1xuICAgIHJldHVybiBbXG4gICAgICB7XG4gICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgY29sb3I6IHRoaXMuZmlsbCxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5nZXRTdGFydE9wYWNpdHkoKVxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgb2Zmc2V0OiAxMDAsXG4gICAgICAgIGNvbG9yOiB0aGlzLmZpbGwsXG4gICAgICAgIG9wYWNpdHk6IDFcbiAgICAgIH1cbiAgICBdO1xuICB9XG5cbiAgZ2V0U3RhcnRPcGFjaXR5KCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMucm91bmRFZGdlcykge1xuICAgICAgcmV0dXJuIDAuMjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIDAuNTtcbiAgICB9XG4gIH1cblxuICBnZXQgZWRnZXMoKTogYm9vbGVhbltdIHtcbiAgICBsZXQgZWRnZXM6IFtib29sZWFuLCBib29sZWFuLCBib29sZWFuLCBib29sZWFuXSA9IFtmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZV07XG4gICAgaWYgKHRoaXMucm91bmRFZGdlcykge1xuICAgICAgZWRnZXMgPSBbdHJ1ZSwgdHJ1ZSwgdHJ1ZSwgdHJ1ZV07XG4gICAgfVxuICAgIHJldHVybiBlZGdlcztcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlZW50ZXInKVxuICBvbk1vdXNlRW50ZXIoKTogdm9pZCB7XG4gICAgdGhpcy5hY3RpdmF0ZS5lbWl0KHRoaXMuZGF0YSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdtb3VzZWxlYXZlJylcbiAgb25Nb3VzZUxlYXZlKCk6IHZvaWQge1xuICAgIHRoaXMuZGVhY3RpdmF0ZS5lbWl0KHRoaXMuZGF0YSk7XG4gIH1cblxuICBwcml2YXRlIGNoZWNrVG9IaWRlQmFyKCk6IHZvaWQge1xuICAgIHRoaXMuaGlkZUJhciA9IHRoaXMubm9CYXJXaGVuWmVybyAmJiB0aGlzLmhlaWdodCA9PT0gMDtcbiAgfVxufVxuIl19