ng-cw-v12
Version:
Angular UI Component Library
351 lines (337 loc) • 43.9 kB
JavaScript
import { Component, ViewChild, Input } from '@angular/core';
import * as THREE from 'three';
import * as i0 from "@angular/core";
// ─── 着色器代码 ─────────────────────────────────────────────────────────────
const vertex = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 1.0);
}
`;
const fragment = `
precision highp float;
uniform vec2 iResolution;
uniform float iTime;
uniform float uTimeSpeed;
uniform float uColorBalance;
uniform float uWarpStrength;
uniform float uWarpFrequency;
uniform float uWarpSpeed;
uniform float uWarpAmplitude;
uniform float uBlendAngle;
uniform float uBlendSoftness;
uniform float uRotationAmount;
uniform float uNoiseScale;
uniform float uGrainAmount;
uniform float uGrainScale;
uniform float uGrainAnimated;
uniform float uContrast;
uniform float uGamma;
uniform float uSaturation;
uniform vec2 uCenterOffset;
uniform float uZoom;
uniform vec3 uColor1;
uniform vec3 uColor2;
uniform vec3 uColor3;
#define S(a,b,t) smoothstep(a,b,t)
mat2 Rot(float a) {
float s = sin(a), c = cos(a);
return mat2(c, -s, s, c);
}
vec2 hash(vec2 p) {
p = vec2(dot(p, vec2(2127.1, 81.17)), dot(p, vec2(1269.5, 283.37)));
return fract(sin(p) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p), f = fract(p), u = f * f * (3.0 - 2.0 * f);
float n = mix(mix(dot(-1.0 + 2.0 * hash(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0)),
dot(-1.0 + 2.0 * hash(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0)), u.x),
mix(dot(-1.0 + 2.0 * hash(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0)),
dot(-1.0 + 2.0 * hash(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0)), u.x), u.y);
return 0.5 + 0.5 * n;
}
void mainImage(out vec4 o, vec2 C) {
float t = iTime * uTimeSpeed;
vec2 uv = C / iResolution.xy;
float ratio = iResolution.x / iResolution.y;
vec2 tuv = uv - 0.5 + uCenterOffset;
tuv /= max(uZoom, 0.001);
float degree = noise(vec2(t * 0.1, tuv.x * tuv.y) * uNoiseScale);
tuv.y *= 1.0 / ratio;
tuv *= Rot(radians((degree - 0.5) * uRotationAmount + 180.0));
tuv.y *= ratio;
float frequency = uWarpFrequency;
float ws = max(uWarpStrength, 0.001);
float amplitude = uWarpAmplitude / ws;
float warpTime = t * uWarpSpeed;
tuv.x += sin(tuv.y * frequency + warpTime) / amplitude;
tuv.y += sin(tuv.x * (frequency * 1.5) + warpTime) / (amplitude * 0.5);
vec3 colLav = uColor1;
vec3 colOrg = uColor2;
vec3 colDark = uColor3;
float b = uColorBalance;
float s = max(uBlendSoftness, 0.0);
mat2 blendRot = Rot(radians(uBlendAngle));
float blendX = (tuv * blendRot).x;
float edge0 = -0.3 - b - s;
float edge1 = 0.2 - b + s;
float v0 = 0.5 - b + s;
float v1 = -0.3 - b - s;
vec3 layer1 = mix(colDark, colOrg, S(edge0, edge1, blendX));
vec3 layer2 = mix(colOrg, colLav, S(edge0, edge1, blendX));
vec3 col = mix(layer1, layer2, S(v0, v1, tuv.y));
vec2 grainUv = uv * max(uGrainScale, 0.001);
if (uGrainAnimated > 0.5) {
grainUv += vec2(iTime * 0.05);
}
float grain = fract(sin(dot(grainUv, vec2(12.9898, 78.233))) * 43758.5453);
col += (grain - 0.5) * uGrainAmount;
col = (col - 0.5) * uContrast + 0.5;
float luma = dot(col, vec3(0.2126, 0.7152, 0.0722));
col = mix(vec3(luma), col, uSaturation);
col = pow(max(col, 0.0), vec3(1.0 / max(uGamma, 0.001)));
col = clamp(col, 0.0, 1.0);
o = vec4(col, 1.0);
}
void main() {
mainImage(gl_FragColor, gl_FragCoord.xy);
}
`;
export class GrainientBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 渐变混合中使用的主色(十六进制字符串) */
this.ncColor1 = '#FF9FFC';
/** 渐变混合中使用的辅助强调色(十六进制字符串) */
this.ncColor2 = '#5227FF';
/** 渐变混合中使用了深色底色(十六进制字符串) */
this.ncColor3 = '#B19EEF';
/** 渐变动画的速度倍增器(0-5) */
this.ncTimeSpeed = 0.25;
/** 将色调平衡向深色或浅色方向调整(-1.0 到 1.0) */
this.ncColorBalance = 0.0;
/** 波扭曲变形强度(0-4) */
this.ncWarpStrength = 1.0;
/** 波的弯曲频率(0-12) */
this.ncWarpFrequency = 5.0;
/** 弯曲动画的速度倍率(0-6)*/
this.ncWarpSpeed = 2.0;
/** 扭曲变形的基准振幅(5-80) */
this.ncWarpAmplitude = 50.0;
/** 颜色混合轴的旋转角度(deg -180-180) */
this.ncBlendAngle = 0.0;
/** 柔化颜色图层之间的过渡边缘(0-0.4) */
this.ncBlendSoftness = 0.05;
/** 旋转量受噪声驱动(0-1440) */
this.ncRotationAmount = 500.0;
/** 调整驱动旋转的噪声频率(0-4) */
this.ncNoiseScale = 2.0;
/** 颗粒感强度(0-0.4) */
this.ncGrainAmount = 0.1;
/** 颗粒感尺度(0.2-8) */
this.ncGrainScale = 2.0;
/** 让谷物随时间变化呈现动画效果 */
this._grainAnimated = false;
/** 对最终颜色进行整体对比度调整(0-2.5) */
this.ncContrast = 1.5;
/** 最终颜色的伽马校正(0.4-2.5) */
this.ncGamma = 1.0;
/** 最终颜色的饱和度(0-2.5) */
this.ncSaturation = 1.0;
/** 渐变中心的水平偏移量(-1-1) */
this.ncCenterX = 0.0;
/** 渐变中心垂直偏移量(-1-1) */
this.ncCenterY = 0.0;
/** 渐变场的缩放级别(0.3-3) */
this.ncZoom = 0.9;
this.time0 = performance.now();
this.rafId = null;
}
set ncGrainAnimated(val) {
this._grainAnimated = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncGrainAnimated() {
return this._grainAnimated;
}
ngOnInit() { }
ngAfterViewInit() {
this.ngZone.runOutsideAngular(() => {
this.initScene();
this.setupResizeObserver();
this.animate();
});
}
ngOnDestroy() {
if (this.rafId)
cancelAnimationFrame(this.rafId);
if (this.resizeObserver)
this.resizeObserver.disconnect();
if (this.renderer) {
this.renderer.dispose();
this.renderer.forceContextLoss();
this.renderer.domElement.remove();
}
}
ngOnChanges(changes) {
if (!this.material)
return;
this.updateUniforms();
}
initScene() {
const container = this.containerRef.nativeElement;
const { width, height } = container.getBoundingClientRect();
this.renderer = new THREE.WebGLRenderer({ antialias: false, alpha: true });
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
this.renderer.setSize(width || 1, height || 1);
container.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
const geometry = new THREE.PlaneGeometry(2, 2);
this.material = new THREE.ShaderMaterial({
vertexShader: vertex,
fragmentShader: fragment,
uniforms: {
iTime: { value: 0 },
iResolution: { value: new THREE.Vector2(width, height) },
uTimeSpeed: { value: this.ncTimeSpeed },
uColorBalance: { value: this.ncColorBalance },
uWarpStrength: { value: this.ncWarpStrength },
uWarpFrequency: { value: this.ncWarpFrequency },
uWarpSpeed: { value: this.ncWarpSpeed },
uWarpAmplitude: { value: this.ncWarpAmplitude },
uBlendAngle: { value: this.ncBlendAngle },
uBlendSoftness: { value: this.ncBlendSoftness },
uRotationAmount: { value: this.ncRotationAmount },
uNoiseScale: { value: this.ncNoiseScale },
uGrainAmount: { value: this.ncGrainAmount },
uGrainScale: { value: this.ncGrainScale },
uGrainAnimated: { value: this.ncGrainAnimated ? 1.0 : 0.0 },
uContrast: { value: this.ncContrast },
uGamma: { value: this.ncGamma },
uSaturation: { value: this.ncSaturation },
uCenterOffset: { value: new THREE.Vector2(this.ncCenterX, this.ncCenterY) },
uZoom: { value: this.ncZoom },
uColor1: { value: new Float32Array(this.hexToRgb(this.ncColor1)) },
uColor2: { value: new Float32Array(this.hexToRgb(this.ncColor2)) },
uColor3: { value: new Float32Array(this.hexToRgb(this.ncColor3)) }
}
});
this.mesh = new THREE.Mesh(geometry, this.material);
this.scene.add(this.mesh);
}
updateUniforms() {
const u = this.material.uniforms;
u['uTimeSpeed'].value = this.ncTimeSpeed;
u['uColorBalance'].value = this.ncColorBalance;
u['uWarpStrength'].value = this.ncWarpStrength;
u['uWarpFrequency'].value = this.ncWarpFrequency;
u['uWarpSpeed'].value = this.ncWarpSpeed;
u['uWarpAmplitude'].value = this.ncWarpAmplitude;
u['uBlendAngle'].value = this.ncBlendAngle;
u['uBlendSoftness'].value = this.ncBlendSoftness;
u['uRotationAmount'].value = this.ncRotationAmount;
u['uNoiseScale'].value = this.ncNoiseScale;
u['uGrainAmount'].value = this.ncGrainAmount;
u['uGrainScale'].value = this.ncGrainScale;
u['uGrainAnimated'].value = this.ncGrainAnimated ? 1.0 : 0.0;
u['uContrast'].value = this.ncContrast;
u['uGamma'].value = this.ncGamma;
u['uSaturation'].value = this.ncSaturation;
u['uCenterOffset'].value.set(this.ncCenterX, this.ncCenterY);
u['uZoom'].value = this.ncZoom;
u['uColor1'].value = new Float32Array(this.hexToRgb(this.ncColor1));
u['uColor2'].value = new Float32Array(this.hexToRgb(this.ncColor2));
u['uColor3'].value = new Float32Array(this.hexToRgb(this.ncColor3));
}
hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (!result)
return [1, 1, 1];
return [parseInt(result[1], 16) / 255, parseInt(result[2], 16) / 255, parseInt(result[3], 16) / 255];
}
setupResizeObserver() {
this.resizeObserver = new ResizeObserver(() => {
this.ngZone.runOutsideAngular(() => {
this.onResize();
});
});
this.resizeObserver.observe(this.containerRef.nativeElement);
}
onResize() {
const container = this.containerRef.nativeElement;
const { width, height } = container.getBoundingClientRect();
if (width === 0 || height === 0)
return;
this.renderer.setSize(width, height);
this.material.uniforms['iResolution'].value.set(width, height);
}
animate() {
this.rafId = requestAnimationFrame((t) => {
this.animate();
this.render(t);
});
}
render(t) {
this.material.uniforms['iTime'].value = (t - this.time0) * 0.001;
this.renderer.render(this.scene, this.camera);
}
}
GrainientBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: GrainientBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
GrainientBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: GrainientBackgroundComponent, selector: "nc-grainient-background", inputs: { ncColor1: "ncColor1", ncColor2: "ncColor2", ncColor3: "ncColor3", ncTimeSpeed: "ncTimeSpeed", ncColorBalance: "ncColorBalance", ncWarpStrength: "ncWarpStrength", ncWarpFrequency: "ncWarpFrequency", ncWarpSpeed: "ncWarpSpeed", ncWarpAmplitude: "ncWarpAmplitude", ncBlendAngle: "ncBlendAngle", ncBlendSoftness: "ncBlendSoftness", ncRotationAmount: "ncRotationAmount", ncNoiseScale: "ncNoiseScale", ncGrainAmount: "ncGrainAmount", ncGrainScale: "ncGrainScale", ncGrainAnimated: "ncGrainAnimated", ncContrast: "ncContrast", ncGamma: "ncGamma", ncSaturation: "ncSaturation", ncCenterX: "ncCenterX", ncCenterY: "ncCenterY", ncZoom: "ncZoom" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-grainient-canvas-container\"></div>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-grainient-canvas-container{position:absolute;inset:0;z-index:0}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: GrainientBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-grainient-background',
templateUrl: './grainient-background.component.html',
styleUrls: ['./grainient-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncColor1: [{
type: Input
}], ncColor2: [{
type: Input
}], ncColor3: [{
type: Input
}], ncTimeSpeed: [{
type: Input
}], ncColorBalance: [{
type: Input
}], ncWarpStrength: [{
type: Input
}], ncWarpFrequency: [{
type: Input
}], ncWarpSpeed: [{
type: Input
}], ncWarpAmplitude: [{
type: Input
}], ncBlendAngle: [{
type: Input
}], ncBlendSoftness: [{
type: Input
}], ncRotationAmount: [{
type: Input
}], ncNoiseScale: [{
type: Input
}], ncGrainAmount: [{
type: Input
}], ncGrainScale: [{
type: Input
}], ncGrainAnimated: [{
type: Input
}], ncContrast: [{
type: Input
}], ncGamma: [{
type: Input
}], ncSaturation: [{
type: Input
}], ncCenterX: [{
type: Input
}], ncCenterY: [{
type: Input
}], ncZoom: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JhaW5pZW50LWJhY2tncm91bmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29tcG9uZW50cy9ncmFpbmllbnQtYmFja2dyb3VuZC9ncmFpbmllbnQtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2dyYWluaWVudC1iYWNrZ3JvdW5kL2dyYWluaWVudC1iYWNrZ3JvdW5kLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBSVQsU0FBUyxFQUVULEtBQUssRUFJTixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQzs7QUFFL0IsMEVBQTBFO0FBRTFFLE1BQU0sTUFBTSxHQUFHOzs7Ozs7Q0FNZCxDQUFDO0FBRUYsTUFBTSxRQUFRLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXNHaEIsQ0FBQztBQU9GLE1BQU0sT0FBTyw0QkFBNEI7SUErRHZDLFlBQW9CLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBN0RsQywwQkFBMEI7UUFDakIsYUFBUSxHQUFHLFNBQVMsQ0FBQztRQUM5Qiw2QkFBNkI7UUFDcEIsYUFBUSxHQUFHLFNBQVMsQ0FBQztRQUM5Qiw0QkFBNEI7UUFDbkIsYUFBUSxHQUFHLFNBQVMsQ0FBQztRQUM5QixzQkFBc0I7UUFDYixnQkFBVyxHQUFHLElBQUksQ0FBQztRQUM1QixrQ0FBa0M7UUFDekIsbUJBQWMsR0FBRyxHQUFHLENBQUM7UUFDOUIsbUJBQW1CO1FBQ1YsbUJBQWMsR0FBRyxHQUFHLENBQUM7UUFDOUIsbUJBQW1CO1FBQ1Ysb0JBQWUsR0FBRyxHQUFH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QUFRO3NCQUFoQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsY0FBYztzQkFBdEIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUVHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxlQUFlO3NCQUF2QixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBRUcsWUFBWTtzQkFBcEIsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBSUYsZUFBZTtzQkFEbEIsS0FBSztnQkFRRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBPbkluaXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgVmlld0NoaWxkLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgSW5wdXQsXHJcbiAgT25DaGFuZ2VzLFxyXG4gIFNpbXBsZUNoYW5nZXMsXHJcbiAgTmdab25lXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcclxuXHJcbi8vIOKUgOKUgOKUgCDnnYDoibLlmajku6PnoIEg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG5jb25zdCB2ZXJ0ZXggPSBgXHJcbiAgdmFyeWluZyB2ZWMyIHZVdjtcclxuICB2b2lkIG1haW4oKSB7XHJcbiAgICB2VXYgPSB1djtcclxuICAgIGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiwgMS4wKTtcclxuICB9XHJcbmA7XHJcblxyXG5jb25zdCBmcmFnbWVudCA9IGBcclxuICBwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XHJcbiAgdW5pZm9ybSB2ZWMyIGlSZXNvbHV0aW9uO1xyXG4gIHVuaWZvcm0gZmxvYXQgaVRpbWU7XHJcbiAgdW5pZm9ybSBmbG9hdCB1VGltZVNwZWVkO1xyXG4gIHVuaWZvcm0gZmxvYXQgdUNvbG9yQmFsYW5jZTtcclxuICB1bmlmb3JtIGZsb2F0IHVXYXJwU3RyZW5ndGg7XHJcbiAgdW5pZm9ybSBmbG9hdCB1V2FycEZyZXF1ZW5jeTtcclxuICB1bmlmb3JtIGZsb2F0IHVXYXJwU3BlZWQ7XHJcbiAgdW5pZm9ybSBmbG9hdCB1V2FycEFtcGxpdHVkZTtcclxuICB1bmlmb3JtIGZsb2F0IHVCbGVuZEFuZ2xlO1xyXG4gIHVuaWZvcm0gZmxvYXQgdUJsZW5kU29mdG5lc3M7XHJcbiAgdW5pZm9ybSBmbG9hdCB1Um90YXRpb25BbW91bnQ7XHJcbiAgdW5pZm9ybSBmbG9hdCB1Tm9pc2VTY2FsZTtcclxuICB1bmlmb3JtIGZsb2F0IHVHcmFpbkFtb3VudDtcclxuICB1bmlmb3JtIGZsb2F0IHVHcmFpblNjYWxlO1xyXG4gIHVuaWZvcm0gZmxvYXQgdUdyYWluQW5pbWF0ZWQ7XHJcbiAgdW5pZm9ybSBmbG9hdCB1Q29udHJhc3Q7XHJcbiAgdW5pZm9ybSBmbG9hdCB1R2FtbWE7XHJcbiAgdW5pZm9ybSBmbG9hdCB1U2F0dXJhdGlvbjtcclxuICB1bmlmb3JtIHZlYzIgdUNlbnRlck9mZnNldDtcclxuICB1bmlmb3JtIGZsb2F0IHVab29tO1xyXG4gIHVuaWZvcm0gdmVjMyB1Q29sb3IxO1xyXG4gIHVuaWZvcm0gdmVjMyB1Q29sb3IyO1xyXG4gIHVuaWZvcm0gdmVjMyB1Q29sb3IzO1xyXG5cclxuICAjZGVmaW5lIFMoYSxiLHQpIHNtb290aHN0ZXAoYSxiLHQpXHJcblxyXG4gIG1hdDIgUm90KGZsb2F0IGEpIHtcclxuICAgIGZsb2F0IHMgPSBzaW4oYSksIGMgPSBjb3MoYSk7XHJcbiAgICByZXR1cm4gbWF0MihjLCAtcywgcywgYyk7XHJcbiAgfVxyXG5cclxuICB2ZWMyIGhhc2godmVjMiBwKSB7XHJcbiAgICBwID0gdmVjMihkb3QocCwgdmVjMigyMTI3LjEsIDgxLjE3KSksIGRvdChwLCB2ZWMyKDEyNjkuNSwgMjgzLjM3KSkpO1xyXG4gICAgcmV0dXJuIGZyYWN0KHNpbihwKSAqIDQzNzU4LjU0NTMpO1xyXG4gIH1cclxuXHJcbiAgZmxvYXQgbm9pc2UodmVjMiBwKSB7XHJcbiAgICB2ZWMyIGkgPSBmbG9vcihwKSwgZiA9IGZyYWN0KHApLCB1ID0gZiAqIGYgKiAoMy4wIC0gMi4wICogZik7XHJcbiAgICBmbG9hdCBuID0gbWl4KG1peChkb3QoLTEuMCArIDIuMCAqIGhhc2goaSArIHZlYzIoMC4wLCAwLjApKSwgZiAtIHZlYzIoMC4wLCAwLjApKSxcclxuICAgICAgICAgICAgICAgICBkb3QoLTEuMCArIDIuMCAqIGhhc2goaSArIHZlYzIoMS4wLCAwLjApKSwgZiAtIHZlYzIoMS4wLCAwLjApKSwgdS54KSxcclxuICAgICAgICAgICAgIG1peChkb3QoLTEuMCArIDIuMCAqIGhhc2goaSArIHZlYzIoMC4wLCAxLjApKSwgZiAtIHZlYzIoMC4wLCAxLjApKSxcclxuICAgICAgICAgICAgICAgICBkb3QoLTEuMCArIDIuMCAqIGhhc2goaSArIHZlYzIoMS4wLCAxLjApKSwgZiAtIHZlYzIoMS4wLCAxLjApKSwgdS54KSwgdS55KTtcclxuICAgIHJldHVybiAwLjUgKyAwLjUgKiBuO1xyXG4gIH1cclxuXHJcbiAgdm9pZCBtYWluSW1hZ2Uob3V0IHZlYzQgbywgdmVjMiBDKSB7XHJcbiAgICBmbG9hdCB0ID0gaVRpbWUgKiB1VGltZVNwZWVkO1xyXG4gICAgdmVjMiB1diA9IEMgLyBpUmVzb2x1dGlvbi54eTtcclxuICAgIGZsb2F0IHJhdGlvID0gaVJlc29sdXRpb24ueCAvIGlSZXNvbHV0aW9uLnk7XHJcbiAgICB2ZWMyIHR1diA9IHV2IC0gMC41ICsgdUNlbnRlck9mZnNldDtcclxuICAgIHR1diAvPSBtYXgodVpvb20sIDAuMDAxKTtcclxuXHJcbiAgICBmbG9hdCBkZWdyZWUgPSBub2lzZSh2ZWMyKHQgKiAwLjEsIHR1di54ICogdHV2LnkpICogdU5vaXNlU2NhbGUpO1xyXG4gICAgdHV2LnkgKj0gMS4wIC8gcmF0aW87XHJcbiAgICB0dXYgKj0gUm90KHJhZGlhbnMoKGRlZ3JlZSAtIDAuNSkgKiB1Um90YXRpb25BbW91bnQgKyAxODAuMCkpO1xyXG4gICAgdHV2LnkgKj0gcmF0aW87XHJcblxyXG4gICAgZmxvYXQgZnJlcXVlbmN5ID0gdVdhcnBGcmVxdWVuY3k7XHJcbiAgICBmbG9hdCB3cyA9IG1heCh1V2FycFN0cmVuZ3RoLCAwLjAwMSk7XHJcbiAgICBmbG9hdCBhbXBsaXR1ZGUgPSB1V2FycEFtcGxpdHVkZSAvIHdzO1xyXG4gICAgZmxvYXQgd2FycFRpbWUgPSB0ICogdVdhcnBTcGVlZDtcclxuICAgIHR1di54ICs9IHNpbih0dXYueSAqIGZyZXF1ZW5jeSArIHdhcnBUaW1lKSAvIGFtcGxpdHVkZTtcclxuICAgIHR1di55ICs9IHNpbih0dXYueCAqIChmcmVxdWVuY3kgKiAxLjUpICsgd2FycFRpbWUpIC8gKGFtcGxpdHVkZSAqIDAuNSk7XHJcblxyXG4gICAgdmVjMyBjb2xMYXYgPSB1Q29sb3IxO1xyXG4gICAgdmVjMyBjb2xPcmcgPSB1Q29sb3IyO1xyXG4gICAgdmVjMyBjb2xEYXJrID0gdUNvbG9yMztcclxuICAgIGZsb2F0IGIgPSB1Q29sb3JCYWxhbmNlO1xyXG4gICAgZmxvYXQgcyA9IG1heCh1QmxlbmRTb2Z0bmVzcywgMC4wKTtcclxuICAgIG1hdDIgYmxlbmRSb3QgPSBSb3QocmFkaWFucyh1QmxlbmRBbmdsZSkpO1xyXG4gICAgZmxvYXQgYmxlbmRYID0gKHR1diAqIGJsZW5kUm90KS54O1xyXG5cclxuICAgIGZsb2F0IGVkZ2UwID0gLTAuMyAtIGIgLSBzO1xyXG4gICAgZmxvYXQgZWRnZTEgPSAwLjIgLSBiICsgcztcclxuICAgIGZsb2F0IHYwID0gMC41IC0gYiArIHM7XHJcbiAgICBmbG9hdCB2MSA9IC0wLjMgLSBiIC0gcztcclxuXHJcbiAgICB2ZWMzIGxheWVyMSA9IG1peChjb2xEYXJrLCBjb2xPcmcsIFMoZWRnZTAsIGVkZ2UxLCBibGVuZFgpKTtcclxuICAgIHZlYzMgbGF5ZXIyID0gbWl4KGNvbE9yZywgY29sTGF2LCBTKGVkZ2UwLCBlZGdlMSwgYmxlbmRYKSk7XHJcbiAgICB2ZWMzIGNvbCA9IG1peChsYXllcjEsIGxheWVyMiwgUyh2MCwgdjEsIHR1di55KSk7XHJcblxyXG4gICAgdmVjMiBncmFpblV2ID0gdXYgKiBtYXgodUdyYWluU2NhbGUsIDAuMDAxKTtcclxuICAgIGlmICh1R3JhaW5BbmltYXRlZCA+IDAuNSkge1xyXG4gICAgICBncmFpblV2ICs9IHZlYzIoaVRpbWUgKiAwLjA1KTtcclxuICAgIH1cclxuICAgIGZsb2F0IGdyYWluID0gZnJhY3Qoc2luKGRvdChncmFpblV2LCB2ZWMyKDEyLjk4OTgsIDc4LjIzMykpKSAqIDQzNzU4LjU0NTMpO1xyXG4gICAgY29sICs9IChncmFpbiAtIDAuNSkgKiB1R3JhaW5BbW91bnQ7XHJcblxyXG4gICAgY29sID0gKGNvbCAtIDAuNSkgKiB1Q29udHJhc3QgKyAwLjU7XHJcbiAgICBmbG9hdCBsdW1hID0gZG90KGNvbCwgdmVjMygwLjIxMjYsIDAuNzE1MiwgMC4wNzIyKSk7XHJcbiAgICBjb2wgPSBtaXgodmVjMyhsdW1hKSwgY29sLCB1U2F0dXJhdGlvbik7XHJcbiAgICBjb2wgPSBwb3cobWF4KGNvbCwgMC4wKSwgdmVjMygxLjAgLyBtYXgodUdhbW1hLCAwLjAwMSkpKTtcclxuICAgIGNvbCA9IGNsYW1wKGNvbCwgMC4wLCAxLjApO1xyXG5cclxuICAgIG8gPSB2ZWM0KGNvbCwgMS4wKTtcclxuICB9XHJcblxyXG4gIHZvaWQgbWFpbigpIHtcclxuICAgIG1haW5JbWFnZShnbF9GcmFnQ29sb3IsIGdsX0ZyYWdDb29yZC54eSk7XHJcbiAgfVxyXG5gO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduYy1ncmFpbmllbnQtYmFja2dyb3VuZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2dyYWluaWVudC1iYWNrZ3JvdW5kLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9ncmFpbmllbnQtYmFja2dyb3VuZC5jb21wb25lbnQubGVzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBHcmFpbmllbnRCYWNrZ3JvdW5kQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XHJcbiAgQFZpZXdDaGlsZCgnY29udGFpbmVyJywgeyBzdGF0aWM6IHRydWUgfSkgY29udGFpbmVyUmVmITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XHJcbiAgLyoqIOa4kOWPmOa3t+WQiOS4reS9v+eUqOeahOS4u+iJsu+8iOWNgeWFrei/m+WItuWtl+espuS4su+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jQ29sb3IxID0gJyNGRjlGRkMnO1xyXG4gIC8qKiDmuJDlj5jmt7flkIjkuK3kvb/nlKjnmoTovoXliqnlvLrosIPoibLvvIjljYHlha3ov5vliLblrZfnrKbkuLLvvIkgKi9cclxuICBASW5wdXQoKSBuY0NvbG9yMiA9ICcjNTIyN0ZGJztcclxuICAvKiog5riQ5Y+Y5re35ZCI5Lit5L2/55So5LqG5rex6Imy5bqV6Imy77yI5Y2B5YWt6L+b5Yi25a2X56ym5Liy77yJICovXHJcbiAgQElucHV0KCkgbmNDb2xvcjMgPSAnI0IxOUVFRic7XHJcbiAgLyoqIOa4kOWPmOWKqOeUu+eahOmAn+W6puWAjeWinuWZqO+8iDAtNe+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jVGltZVNwZWVkID0gMC4yNTtcclxuICAvKiog5bCG6Imy6LCD5bmz6KGh5ZCR5rex6Imy5oiW5rWF6Imy5pa55ZCR6LCD5pW077yILTEuMCDliLAgMS4w77yJICovXHJcbiAgQElucHV0KCkgbmNDb2xvckJhbGFuY2UgPSAwLjA7XHJcbiAgLyoqIOazouaJreabsuWPmOW9ouW8uuW6pu+8iDAtNO+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jV2FycFN0cmVuZ3RoID0gMS4wO1xyXG4gIC8qKiDms6LnmoTlvK/mm7LpopHnjofvvIgwLTEy77yJICovXHJcbiAgQElucHV0KCkgbmNXYXJwRnJlcXVlbmN5ID0gNS4wO1xyXG4gIC8qKiDlvK/mm7LliqjnlLvnmoTpgJ/luqblgI3njofvvIgwLTbvvIkqL1xyXG4gIEBJbnB1dCgpIG5jV2FycFNwZWVkID0gMi4wO1xyXG4gIC8qKiDmia3mm7Llj5jlvaLnmoTln7rlh4bmjK/luYXvvIg1LTgw77yJICovXHJcbiAgQElucHV0KCkgbmNXYXJwQW1wbGl0dWRlID0gNTAuMDtcclxuICAvKiog6aKc6Imy5re35ZCI6L2055qE5peL6L2s6KeS5bqm77yIZGVnIC0xODAtMTgw77yJICovXHJcbiAgQElucHV0KCkgbmNCbGVuZEFuZ2xlID0gMC4wO1xyXG4gIC8qKiDmn5TljJbpopzoibLlm77lsYLkuYvpl7TnmoTov4fmuKHovrnnvJjvvIgwLTAuNO+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jQmxlbmRTb2Z0bmVzcyA9IDAuMDU7XHJcbiAgLyoqIOaXi+i9rOmHj+WPl+WZquWjsOmpseWKqO+8iDAtMTQ0MO+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jUm90YXRpb25BbW91bnQgPSA1MDAuMDtcclxuICAvKiog6LCD5pW06amx5Yqo5peL6L2s55qE5Zmq5aOw6aKR546H77yIMC0077yJICovXHJcbiAgQElucHV0KCkgbmNOb2lzZVNjYWxlID0gMi4wO1xyXG4gIC8qKiDpopfnspLmhJ/lvLrluqbvvIgwLTAuNO+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jR3JhaW5BbW91bnQgPSAwLjE7XHJcbiAgLyoqIOmil+eykuaEn+WwuuW6pu+8iDAuMi0477yJICovXHJcbiAgQElucHV0KCkgbmNHcmFpblNjYWxlID0gMi4wO1xyXG4gIC8qKiDorqnosLfnianpmo/ml7bpl7Tlj5jljJblkYjnjrDliqjnlLvmlYjmnpwgKi9cclxuICBwcml2YXRlIF9ncmFpbkFuaW1hdGVkOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KClcclxuICBzZXQgbmNHcmFpbkFuaW1hdGVkKHZhbDogYm9vbGVhbiB8IHN0cmluZykge1xyXG4gICAgdGhpcy5fZ3JhaW5BbmltYXRlZCA9IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09IGZhbHNlICYmIHZhbCAhPT0gJ2ZhbHNlJztcclxuICB9XHJcbiAgZ2V0IG5jR3JhaW5BbmltYXRlZCgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9ncmFpbkFuaW1hdGVkO1xyXG4gIH1cclxuICAvKiog5a+55pyA57uI6aKc6Imy6L+b6KGM5pW05L2T5a+55q+U5bqm6LCD5pW077yIMC0yLjXvvIkgKi9cclxuICBASW5wdXQoKSBuY0NvbnRyYXN0ID0gMS41O1xyXG4gIC8qKiDmnIDnu4jpopzoibLnmoTkvL3pqazmoKHmraPvvIgwLjQtMi4177yJICovXHJcbiAgQElucHV0KCkgbmNHYW1tYSA9IDEuMDtcclxuICAvKiog5pyA57uI6aKc6Imy55qE6aWx5ZKM5bqm77yIMC0yLjXvvIkgKi9cclxuICBASW5wdXQoKSBuY1NhdHVyYXRpb24gPSAxLjA7XHJcbiAgLyoqIOa4kOWPmOS4reW/g+eahOawtOW5s+WBj+enu+mHj++8iC0xLTHvvIkgKi9cclxuICBASW5wdXQoKSBuY0NlbnRlclggPSAwLjA7XHJcbiAgLyoqIOa4kOWPmOS4reW/g+WeguebtOWBj+enu+mHj++8iC0xLTHvvIkgKi9cclxuICBASW5wdXQoKSBuY0NlbnRlclkgPSAwLjA7XHJcbiAgLyoqIOa4kOWPmOWcuueahOe8qeaUvue6p+WIq++8iDAuMy0z77yJICovXHJcbiAgQElucHV0KCkgbmNab29tID0gMC45O1xyXG5cclxuICBwcml2YXRlIHJlbmRlcmVyITogVEhSRUUuV2ViR0xSZW5kZXJlcjtcclxuICBwcml2YXRlIHNjZW5lITogVEhSRUUuU2NlbmU7XHJcbiAgcHJpdmF0ZSBjYW1lcmEhOiBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmE7XHJcbiAgcHJpdmF0ZSBtZXNoITogVEhSRUUuTWVzaDtcclxuICBwcml2YXRlIG1hdGVyaWFsITogVEhSRUUuU2hhZGVyTWF0ZXJpYWw7XHJcbiAgcHJpdmF0ZSB0aW1lMCA9IHBlcmZvcm1hbmNlLm5vdygpO1xyXG4gIHByaXZhdGUgcmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVzaXplT2JzZXJ2ZXIhOiBSZXNpemVPYnNlcnZlcjtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSkgeyB9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQgeyB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgdGhpcy5pbml0U2NlbmUoKTtcclxuICAgICAgdGhpcy5zZXR1cFJlc2l6ZU9ic2VydmVyKCk7XHJcbiAgICAgIHRoaXMuYW5pbWF0ZSgpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnJhZklkKSBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJhZklkKTtcclxuICAgIGlmICh0aGlzLnJlc2l6ZU9ic2VydmVyKSB0aGlzLnJlc2l6ZU9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcclxuICAgIGlmICh0aGlzLnJlbmRlcmVyKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIuZGlzcG9zZSgpO1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLmZvcmNlQ29udGV4dExvc3MoKTtcclxuICAgICAgdGhpcy5yZW5kZXJlci5kb21FbGVtZW50LnJlbW92ZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm1hdGVyaWFsKSByZXR1cm47XHJcbiAgICB0aGlzLnVwZGF0ZVVuaWZvcm1zKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluaXRTY2VuZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoeyBhbnRpYWxpYXM6IGZhbHNlLCBhbHBoYTogdHJ1ZSB9KTtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyhNYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxLCAyKSk7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnNldFNpemUod2lkdGggfHwgMSwgaGVpZ2h0IHx8IDEpO1xyXG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG4gICAgdGhpcy5jYW1lcmEgPSBuZXcgVEhSRUUuT3J0aG9ncmFwaGljQ2FtZXJhKC0xLCAxLCAxLCAtMSwgMCwgMSk7XHJcblxyXG4gICAgY29uc3QgZ2VvbWV0cnkgPSBuZXcgVEhSRUUuUGxhbmVHZW9tZXRyeSgyLCAyKTtcclxuICAgIHRoaXMubWF0ZXJpYWwgPSBuZXcgVEhSRUUuU2hhZGVyTWF0ZXJpYWwoe1xyXG4gICAgICB2ZXJ0ZXhTaGFkZXI6IHZlcnRleCxcclxuICAgICAgZnJhZ21lbnRTaGFkZXI6IGZyYWdtZW50LFxyXG4gICAgICB1bmlmb3Jtczoge1xyXG4gICAgICAgIGlUaW1lOiB7IHZhbHVlOiAwIH0sXHJcbiAgICAgICAgaVJlc29sdXRpb246IHsgdmFsdWU6IG5ldyBUSFJFRS5WZWN0b3IyKHdpZHRoLCBoZWlnaHQpIH0sXHJcbiAgICAgICAgdVRpbWVTcGVlZDogeyB2YWx1ZTogdGhpcy5uY1RpbWVTcGVlZCB9LFxyXG4gICAgICAgIHVDb2xvckJhbGFuY2U6IHsgdmFsdWU6IHRoaXMubmNDb2xvckJhbGFuY2UgfSxcclxuICAgICAgICB1V2FycFN0cmVuZ3RoOiB7IHZhbHVlOiB0aGlzLm5jV2FycFN0cmVuZ3RoIH0sXHJcbiAgICAgICAgdVdhcnBGcmVxdWVuY3k6IHsgdmFsdWU6IHRoaXMubmNXYXJwRnJlcXVlbmN5IH0sXHJcbiAgICAgICAgdVdhcnBTcGVlZDogeyB2YWx1ZTogdGhpcy5uY1dhcnBTcGVlZCB9LFxyXG4gICAgICAgIHVXYXJwQW1wbGl0dWRlOiB7IHZhbHVlOiB0aGlzLm5jV2FycEFtcGxpdHVkZSB9LFxyXG4gICAgICAgIHVCbGVuZEFuZ2xlOiB7IHZhbHVlOiB0aGlzLm5jQmxlbmRBbmdsZSB9LFxyXG4gICAgICAgIHVCbGVuZFNvZnRuZXNzOiB7IHZhbHVlOiB0aGlzLm5jQmxlbmRTb2Z0bmVzcyB9LFxyXG4gICAgICAgIHVSb3RhdGlvbkFtb3VudDogeyB2YWx1ZTogdGhpcy5uY1JvdGF0aW9uQW1vdW50IH0sXHJcbiAgICAgICAgdU5vaXNlU2NhbGU6IHsgdmFsdWU6IHRoaXMubmNOb2lzZVNjYWxlIH0sXHJcbiAgICAgICAgdUdyYWluQW1vdW50OiB7IHZhbHVlOiB0aGlzLm5jR3JhaW5BbW91bnQgfSxcclxuICAgICAgICB1R3JhaW5TY2FsZTogeyB2YWx1ZTogdGhpcy5uY0dyYWluU2NhbGUgfSxcclxuICAgICAgICB1R3JhaW5BbmltYXRlZDogeyB2YWx1ZTogdGhpcy5uY0dyYWluQW5pbWF0ZWQgPyAxLjAgOiAwLjAgfSxcclxuICAgICAgICB1Q29udHJhc3Q6IHsgdmFsdWU6IHRoaXMubmNDb250cmFzdCB9LFxyXG4gICAgICAgIHVHYW1tYTogeyB2YWx1ZTogdGhpcy5uY0dhbW1hIH0sXHJcbiAgICAgICAgdVNhdHVyYXRpb246IHsgdmFsdWU6IHRoaXMubmNTYXR1cmF0aW9uIH0sXHJcbiAgICAgICAgdUNlbnRlck9mZnNldDogeyB2YWx1ZTogbmV3IFRIUkVFLlZlY3RvcjIodGhpcy5uY0NlbnRlclgsIHRoaXMubmNDZW50ZXJZKSB9LFxyXG4gICAgICAgIHVab29tOiB7IHZhbHVlOiB0aGlzLm5jWm9vbSB9LFxyXG4gICAgICAgIHVDb2xvcjE6IHsgdmFsdWU6IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5oZXhUb1JnYih0aGlzLm5jQ29sb3IxKSkgfSxcclxuICAgICAgICB1Q29sb3IyOiB7IHZhbHVlOiBuZXcgRmxvYXQzMkFycmF5KHRoaXMuaGV4VG9SZ2IodGhpcy5uY0NvbG9yMikpIH0sXHJcbiAgICAgICAgdUNvbG9yMzogeyB2YWx1ZTogbmV3IEZsb2F0MzJBcnJheSh0aGlzLmhleFRvUmdiKHRoaXMubmNDb2xvcjMpKSB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMubWVzaCA9IG5ldyBUSFJFRS5NZXNoKGdlb21ldHJ5LCB0aGlzLm1hdGVyaWFsKTtcclxuICAgIHRoaXMuc2NlbmUuYWRkKHRoaXMubWVzaCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVVuaWZvcm1zKCk6IHZvaWQge1xyXG4gICAgY29uc3QgdSA9IHRoaXMubWF0ZXJpYWwudW5pZm9ybXM7XHJcbiAgICB1Wyd1VGltZVNwZWVkJ10udmFsdWUgPSB0aGlzLm5jVGltZVNwZWVkO1xyXG4gICAgdVsndUNvbG9yQmFsYW5jZSddLnZhbHVlID0gdGhpcy5uY0NvbG9yQmFsYW5jZTtcclxuICAgIHVbJ3VXYXJwU3RyZW5ndGgnXS52YWx1ZSA9IHRoaXMubmNXYXJwU3RyZW5ndGg7XHJcbiAgICB1Wyd1V2FycEZyZXF1ZW5jeSddLnZhbHVlID0gdGhpcy5uY1dhcnBGcmVxdWVuY3k7XHJcbiAgICB1Wyd1V2FycFNwZWVkJ10udmFsdWUgPSB0aGlzLm5jV2FycFNwZWVkO1xyXG4gICAgdVsndVdhcnBBbXBsaXR1ZGUnXS52YWx1ZSA9IHRoaXMubmNXYXJwQW1wbGl0dWRlO1xyXG4gICAgdVsndUJsZW5kQW5nbGUnXS52YWx1ZSA9IHRoaXMubmNCbGVuZEFuZ2xlO1xyXG4gICAgdVsndUJsZW5kU29mdG5lc3MnXS52YWx1ZSA9IHRoaXMubmNCbGVuZFNvZnRuZXNzO1xyXG4gICAgdVsndVJvdGF0aW9uQW1vdW50J10udmFsdWUgPSB0aGlzLm5jUm90YXRpb25BbW91bnQ7XHJcbiAgICB1Wyd1Tm9pc2VTY2FsZSddLnZhbHVlID0gdGhpcy5uY05vaXNlU2NhbGU7XHJcbiAgICB1Wyd1R3JhaW5BbW91bnQnXS52YWx1ZSA9IHRoaXMubmNHcmFpbkFtb3VudDtcclxuICAgIHVbJ3VHcmFpblNjYWxlJ10udmFsdWUgPSB0aGlzLm5jR3JhaW5TY2FsZTtcclxuICAgIHVbJ3VHcmFpbkFuaW1hdGVkJ10udmFsdWUgPSB0aGlzLm5jR3JhaW5BbmltYXRlZCA/IDEuMCA6IDAuMDtcclxuICAgIHVbJ3VDb250cmFzdCddLnZhbHVlID0gdGhpcy5uY0NvbnRyYXN0O1xyXG4gICAgdVsndUdhbW1hJ10udmFsdWUgPSB0aGlzLm5jR2FtbWE7XHJcbiAgICB1Wyd1U2F0dXJhdGlvbiddLnZhbHVlID0gdGhpcy5uY1NhdHVyYXRpb247XHJcbiAgICB1Wyd1Q2VudGVyT2Zmc2V0J10udmFsdWUuc2V0KHRoaXMubmNDZW50ZXJYLCB0aGlzLm5jQ2VudGVyWSk7XHJcbiAgICB1Wyd1Wm9vbSddLnZhbHVlID0gdGhpcy5uY1pvb207XHJcbiAgICB1Wyd1Q29sb3IxJ10udmFsdWUgPSBuZXcgRmxvYXQzMkFycmF5KHRoaXMuaGV4VG9SZ2IodGhpcy5uY0NvbG9yMSkpO1xyXG4gICAgdVsndUNvbG9yMiddLnZhbHVlID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmhleFRvUmdiKHRoaXMubmNDb2xvcjIpKTtcclxuICAgIHVbJ3VDb2xvcjMnXS52YWx1ZSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5oZXhUb1JnYih0aGlzLm5jQ29sb3IzKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhleFRvUmdiKGhleDogc3RyaW5nKSB7XHJcbiAgICBjb25zdCByZXN1bHQgPSAvXiM/KFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkoW2EtZlxcZF17Mn0pJC9pLmV4ZWMoaGV4KTtcclxuICAgIGlmICghcmVzdWx0KSByZXR1cm4gWzEsIDEsIDFdO1xyXG4gICAgcmV0dXJuIFtwYXJzZUludChyZXN1bHRbMV0sIDE2KSAvIDI1NSwgcGFyc2VJbnQocmVzdWx0WzJdLCAxNikgLyAyNTUsIHBhcnNlSW50KHJlc3VsdFszXSwgMTYpIC8gMjU1XTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBSZXNpemVPYnNlcnZlcigpOiB2b2lkIHtcclxuICAgIHRoaXMucmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4ge1xyXG4gICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgICAgdGhpcy5vblJlc2l6ZSgpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvblJlc2l6ZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQgfSA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIGlmICh3aWR0aCA9PT0gMCB8fCBoZWlnaHQgPT09IDApIHJldHVybjtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyLnNldFNpemUod2lkdGgsIGhlaWdodCk7XHJcbiAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWydpUmVzb2x1dGlvbiddLnZhbHVlLnNldCh3aWR0aCwgaGVpZ2h0KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYW5pbWF0ZSgpOiB2b2lkIHtcclxuICAgIHRoaXMucmFmSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKHQpID0+IHtcclxuICAgICAgdGhpcy5hbmltYXRlKCk7XHJcbiAgICAgIHRoaXMucmVuZGVyKHQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlbmRlcih0OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ2lUaW1lJ10udmFsdWUgPSAodCAtIHRoaXMudGltZTApICogMC4wMDE7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnJlbmRlcih0aGlzLnNjZW5lLCB0aGlzLmNhbWVyYSk7XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgI2NvbnRhaW5lciBjbGFzcz1cIm5jLWdyYWluaWVudC1jYW52YXMtY29udGFpbmVyXCI+PC9kaXY+XHJcbjxkaXYgY2xhc3M9XCJuYy1jb250ZW50LXdyYXBwZXJcIj5cclxuICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcbjwvZGl2PiJdfQ==