ng-cw-v12
Version:
Angular UI Component Library
356 lines (351 loc) • 48.2 kB
JavaScript
import { Component, ViewChild, Input, HostListener } from '@angular/core';
import * as THREE from 'three';
import * as i0 from "@angular/core";
const MAX_COLORS = 8;
const frag = `
#define MAX_COLORS ${MAX_COLORS}
uniform vec2 uCanvas;
uniform float uTime;
uniform float uSpeed;
uniform vec2 uRot;
uniform int uColorCount;
uniform vec3 uColors[MAX_COLORS];
uniform int uTransparent;
uniform float uScale;
uniform float uFrequency;
uniform float uWarpStrength;
uniform vec2 uPointer; // in NDC [-1,1]
uniform float uMouseInfluence;
uniform float uParallax;
uniform float uNoise;
varying vec2 vUv;
void main() {
float t = uTime * uSpeed;
vec2 p = vUv * 2.0 - 1.0;
p += uPointer * uParallax * 0.1;
vec2 rp = vec2(p.x * uRot.x - p.y * uRot.y, p.x * uRot.y + p.y * uRot.x);
vec2 q = vec2(rp.x * (uCanvas.x / uCanvas.y), rp.y);
q /= max(uScale, 0.0001);
q /= 0.5 + 0.2 * dot(q, q);
q += 0.2 * cos(t) - 7.56;
vec2 toward = (uPointer - rp);
q += toward * uMouseInfluence * 0.2;
vec3 col = vec3(0.0);
float a = 1.0;
if (uColorCount > 0) {
vec2 s = q;
vec3 sumCol = vec3(0.0);
float cover = 0.0;
for (int i = 0; i < MAX_COLORS; ++i) {
if (i >= uColorCount) break;
s -= 0.01;
// Use uWarpStrength to directly scale the inner phase distortion
vec2 r = sin(1.5 * (s.yx * uFrequency) + (2.0 * uWarpStrength) * cos(s * uFrequency));
float m = length(r + sin(5.0 * r.y * uFrequency - 3.0 * t + float(i)) / 4.0);
float w = 1.0 - exp(-6.0 / exp(6.0 * m));
sumCol += uColors[i] * w;
cover = max(cover, w);
}
col = clamp(sumCol, 0.0, 1.0);
a = uTransparent > 0 ? cover : 1.0;
} else {
vec2 s = q;
for (int k = 0; k < 3; ++k) {
s -= 0.01;
vec2 r = sin(1.5 * (s.yx * uFrequency) + (2.0 * uWarpStrength) * cos(s * uFrequency));
float m = length(r + sin(5.0 * r.y * uFrequency - 3.0 * t + float(k)) / 4.0);
col[k] = 1.0 - exp(-6.0 / exp(6.0 * m));
}
a = uTransparent > 0 ? max(max(col.r, col.g), col.b) : 1.0;
}
if (uNoise > 0.0001) {
float n = fract(sin(dot(gl_FragCoord.xy + vec2(uTime), vec2(12.9898, 78.233))) * 43758.5453123);
col += (n - 0.5) * uNoise;
col = clamp(col, 0.0, 1.0);
}
vec3 rgb = (uTransparent > 0) ? col * a : col;
gl_FragColor = vec4(rgb, a);
}
`;
const vert = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 1.0);
}
`;
export class ColorBendsBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 容器背景颜色 */
this.ncBgColor = 'black';
/** 旋转角度(deg -180 - 180) */
this.ncRotation = 0;
/** 动画速度(0-1)*/
this.ncSpeed = 0.2;
/** 用于混合弯曲部分的颜色(十六进制字符串数组,最大支持8个颜色) */
this.ncColors = [];
/** 是否开启透明背景 */
this._transparent = true;
/** 自动旋转速度(deg/s -5-5) */
this.ncAutoRotate = 0;
/** 缩放比例(0.2-5) */
this.ncScale = 1;
/** 频率(0-5) */
this.ncFrequency = 1;
/** 扭曲强度(0-1) */
this.ncWarpStrength = 1;
/** 鼠标影响力的强度(0-2) */
this.ncMouseInfluence = 1;
/** 视差效果强度,视差效果是指指针移动内容时产生的效果(0-2) */
this.ncParallax = 0.5;
/** 噪点强度(0-1) */
this.ncNoise = 0.1;
this.pointerTarget = new THREE.Vector2(0, 0);
this.pointerCurrent = new THREE.Vector2(0, 0);
this.pointerSmooth = 8;
this.isVisible = true;
this.rafId = null;
this.resizeRafId = null;
this.loop = () => {
this.rafId = requestAnimationFrame(this.loop);
// 只在可见窗口时渲染
if (!this.isVisible || document.hidden) {
if (this.clock)
this.clock.getDelta(); // 防止重新唤醒时时间突变
return;
}
if (!this.renderer || !this.scene || !this.camera)
return;
const dt = this.clock.getDelta();
const elapsed = this.clock.elapsedTime;
this.material.uniforms['uTime'].value = elapsed;
const deg = (Number(this.ncRotation) % 360) + Number(this.ncAutoRotate) * elapsed;
const rad = (deg * Math.PI) / 180;
const c = Math.cos(rad);
const s = Math.sin(rad);
this.material.uniforms['uRot'].value.set(c, s);
const amt = Math.min(1, dt * this.pointerSmooth);
this.pointerCurrent.lerp(this.pointerTarget, amt);
this.material.uniforms['uPointer'].value.copy(this.pointerCurrent);
this.renderer.render(this.scene, this.camera);
};
}
set ncTransparent(val) {
this._transparent = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncTransparent() {
return this._transparent;
}
ngOnInit() { }
ngAfterViewInit() {
this.ngZone.runOutsideAngular(() => {
this.initScene();
});
}
ngOnDestroy() {
this.cleanup();
}
ngOnChanges(changes) {
if (!this.material)
return;
this.updateUniforms();
}
initScene() {
const container = this.containerRef.nativeElement;
this.scene = new THREE.Scene();
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
this.geometry = new THREE.PlaneGeometry(2, 2);
const uColorsArray = Array.from({ length: MAX_COLORS }, () => new THREE.Vector3(0, 0, 0));
this.material = new THREE.ShaderMaterial({
vertexShader: vert,
fragmentShader: frag,
uniforms: {
uCanvas: { value: new THREE.Vector2(1, 1) },
uTime: { value: 0 },
uSpeed: { value: Number(this.ncSpeed) },
uRot: { value: new THREE.Vector2(1, 0) },
uColorCount: { value: 0 },
uColors: { value: uColorsArray },
uTransparent: { value: this.ncTransparent ? 1 : 0 },
uScale: { value: Number(this.ncScale) },
uFrequency: { value: Number(this.ncFrequency) },
uWarpStrength: { value: Number(this.ncWarpStrength) },
uPointer: { value: new THREE.Vector2(0, 0) },
uMouseInfluence: { value: Number(this.ncMouseInfluence) },
uParallax: { value: Number(this.ncParallax) },
uNoise: { value: Number(this.ncNoise) }
},
premultipliedAlpha: true,
transparent: true
});
const mesh = new THREE.Mesh(this.geometry, this.material);
this.scene.add(mesh);
this.renderer = new THREE.WebGLRenderer({
antialias: false,
powerPreference: 'high-performance',
alpha: true
});
this.renderer.outputColorSpace = THREE.SRGBColorSpace;
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
this.renderer.setClearColor(0x000000, this.ncTransparent ? 0 : 1);
this.renderer.domElement.style.width = '100%';
this.renderer.domElement.style.height = '100%';
this.renderer.domElement.style.display = 'block';
container.appendChild(this.renderer.domElement);
this.clock = new THREE.Clock();
this.updateUniforms();
this.setupResizeObserver(container);
this.setupIntersectionObserver(container);
this.loop();
}
updateUniforms() {
if (!this.material)
return;
this.material.uniforms['uSpeed'].value = Number(this.ncSpeed);
this.material.uniforms['uScale'].value = Number(this.ncScale);
this.material.uniforms['uFrequency'].value = Number(this.ncFrequency);
this.material.uniforms['uWarpStrength'].value = Number(this.ncWarpStrength);
this.material.uniforms['uMouseInfluence'].value = Number(this.ncMouseInfluence);
this.material.uniforms['uParallax'].value = Number(this.ncParallax);
this.material.uniforms['uNoise'].value = Number(this.ncNoise);
this.material.uniforms['uTransparent'].value = this.ncTransparent ? 1 : 0;
if (this.renderer) {
this.renderer.setClearColor(0x000000, this.ncTransparent ? 0 : 1);
}
const toVec3 = (hex) => {
const h = hex.replace('#', '').trim();
const v = h.length === 3
? [parseInt(h[0] + h[0], 16), parseInt(h[1] + h[1], 16), parseInt(h[2] + h[2], 16)]
: [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
return new THREE.Vector3(v[0] / 255, v[1] / 255, v[2] / 255);
};
const arr = (this.ncColors || []).filter(Boolean).slice(0, MAX_COLORS).map(toVec3);
for (let i = 0; i < MAX_COLORS; i++) {
const vec = this.material.uniforms['uColors'].value[i];
if (i < arr.length)
vec.copy(arr[i]);
else
vec.set(0, 0, 0);
}
this.material.uniforms['uColorCount'].value = arr.length;
}
onPointerMove(e) {
var _a;
if (!((_a = this.containerRef) === null || _a === void 0 ? void 0 : _a.nativeElement))
return;
const container = this.containerRef.nativeElement;
const rect = container.getBoundingClientRect();
const x = ((e.clientX - rect.left) / (rect.width || 1)) * 2 - 1;
const y = -(((e.clientY - rect.top) / (rect.height || 1)) * 2 - 1);
this.pointerTarget.set(x, y);
}
resize(container) {
if (!this.renderer || !this.material)
return;
const w = container.clientWidth || 1;
const h = container.clientHeight || 1;
this.renderer.setSize(w, h, false);
this.material.uniforms['uCanvas'].value.set(w, h);
}
setupResizeObserver(container) {
this.resize(container);
this.resizeObserver = new ResizeObserver(() => {
if (!this.renderer)
return;
if (this.resizeRafId !== null)
cancelAnimationFrame(this.resizeRafId);
this.ngZone.runOutsideAngular(() => {
this.resizeRafId = requestAnimationFrame(() => {
if (!this.renderer)
return;
this.resize(container);
this.resizeRafId = null;
});
});
});
this.resizeObserver.observe(container);
}
setupIntersectionObserver(container) {
this.intersectionObserver = new IntersectionObserver((entries) => {
const entry = entries[0];
this.isVisible = entry.isIntersecting && entry.intersectionRatio > 0;
}, { threshold: [0, 0.01, 0.1] });
this.intersectionObserver.observe(container);
}
cleanup() {
var _a, _b;
if (this.rafId !== null) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
if (this.resizeRafId !== null) {
cancelAnimationFrame(this.resizeRafId);
this.resizeRafId = null;
}
try {
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
}
catch (e) {
void 0;
}
try {
(_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
}
catch (e) {
void 0;
}
if (this.geometry)
this.geometry.dispose();
if (this.material)
this.material.dispose();
if (this.renderer) {
const dom = this.renderer.domElement;
if (dom && dom.parentNode) {
dom.parentNode.removeChild(dom);
}
this.renderer.dispose();
}
}
}
ColorBendsBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ColorBendsBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
ColorBendsBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: ColorBendsBackgroundComponent, selector: "nc-color-bends-background", inputs: { ncBgColor: "ncBgColor", ncRotation: "ncRotation", ncSpeed: "ncSpeed", ncColors: "ncColors", ncTransparent: "ncTransparent", ncAutoRotate: "ncAutoRotate", ncScale: "ncScale", ncFrequency: "ncFrequency", ncWarpStrength: "ncWarpStrength", ncMouseInfluence: "ncMouseInfluence", ncParallax: "ncParallax", ncNoise: "ncNoise" }, host: { listeners: { "pointermove": "onPointerMove($event)" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-color-bends-canvas-container\" [style.background-color]=\"ncBgColor\"></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-color-bends-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: ColorBendsBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-color-bends-background',
templateUrl: './color-bends-background.component.html',
styleUrls: ['./color-bends-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncBgColor: [{
type: Input
}], ncRotation: [{
type: Input
}], ncSpeed: [{
type: Input
}], ncColors: [{
type: Input
}], ncTransparent: [{
type: Input
}], ncAutoRotate: [{
type: Input
}], ncScale: [{
type: Input
}], ncFrequency: [{
type: Input
}], ncWarpStrength: [{
type: Input
}], ncMouseInfluence: [{
type: Input
}], ncParallax: [{
type: Input
}], ncNoise: [{
type: Input
}], onPointerMove: [{
type: HostListener,
args: ['pointermove', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sb3ItYmVuZHMtYmFja2dyb3VuZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2NvbG9yLWJlbmRzLWJhY2tncm91bmQvY29sb3ItYmVuZHMtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2NvbG9yLWJlbmRzLWJhY2tncm91bmQvY29sb3ItYmVuZHMtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUlULFNBQVMsRUFFVCxLQUFLLEVBR0wsWUFBWSxFQUViLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sS0FBSyxLQUFLLE1BQU0sT0FBTyxDQUFDOztBQUUvQixNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUM7QUFFckIsTUFBTSxJQUFJLEdBQUc7cUJBQ1EsVUFBVTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0FvRTlCLENBQUM7QUFFRixNQUFNLElBQUksR0FBRzs7Ozs7O0NBTVosQ0FBQztBQU9GLE1BQU0sT0FBTyw2QkFBNkI7SUFvRHhDLFlBQW9CLE1BQWM7UUFBZCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBakRsQyxhQUFhO1FBQ0osY0FBUyxHQUFXLE9BQU8sQ0FBQztRQUNyQywyQkFBMkI7UUFDbEIsZUFBVSxHQUFXLENBQUMsQ0FBQztRQUNoQyxlQUFlO1FBQ04sWUFBTyxHQUFXLEdBQUcsQ0FBQztRQUMvQixzQ0FBc0M7UUFDN0IsYUFBUSxHQUFhLEVBQUUsQ0FBQztRQUNqQyxlQUFlO1FBQ1AsaUJBQVksR0FBWSxJQUFJLENBQUM7UUFRckMseUJBQXlCO1FBQ2hCLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBQ2xDLGtCQUFrQjtRQUNULFlBQU8sR0FB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OzBIQWhRVSw2QkFBNkI7OEdBQTdCLDZCQUE2Qiw0bEJDckcxQywwTEFHTTsyRkRrR08sNkJBQTZCO2tCQUx6QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSwyQkFBMkI7b0JBQ3JDLFdBQVcsRUFBRSx5Q0FBeUM7b0JBQ3RELFNBQVMsRUFBRSxDQUFDLHlDQUF5QyxDQUFDO2lCQUN2RDs2RkFFMkMsWUFBWTtzQkFBckQsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUcvQixTQUFTO3NCQUFqQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBSUYsYUFBYTtzQkFEaEIsS0FBSztnQkFRRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQWtJTixhQUFhO3NCQURaLFlBQVk7dUJBQUMsYUFBYSxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgT25Jbml0LFxyXG4gIE9uRGVzdHJveSxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG4gIElucHV0LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIEhvc3RMaXN0ZW5lcixcclxuICBOZ1pvbmVcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xyXG5cclxuY29uc3QgTUFYX0NPTE9SUyA9IDg7XHJcblxyXG5jb25zdCBmcmFnID0gYFxyXG4jZGVmaW5lIE1BWF9DT0xPUlMgJHtNQVhfQ09MT1JTfVxyXG51bmlmb3JtIHZlYzIgdUNhbnZhcztcclxudW5pZm9ybSBmbG9hdCB1VGltZTtcclxudW5pZm9ybSBmbG9hdCB1U3BlZWQ7XHJcbnVuaWZvcm0gdmVjMiB1Um90O1xyXG51bmlmb3JtIGludCB1Q29sb3JDb3VudDtcclxudW5pZm9ybSB2ZWMzIHVDb2xvcnNbTUFYX0NPTE9SU107XHJcbnVuaWZvcm0gaW50IHVUcmFuc3BhcmVudDtcclxudW5pZm9ybSBmbG9hdCB1U2NhbGU7XHJcbnVuaWZvcm0gZmxvYXQgdUZyZXF1ZW5jeTtcclxudW5pZm9ybSBmbG9hdCB1V2FycFN0cmVuZ3RoO1xyXG51bmlmb3JtIHZlYzIgdVBvaW50ZXI7IC8vIGluIE5EQyBbLTEsMV1cclxudW5pZm9ybSBmbG9hdCB1TW91c2VJbmZsdWVuY2U7XHJcbnVuaWZvcm0gZmxvYXQgdVBhcmFsbGF4O1xyXG51bmlmb3JtIGZsb2F0IHVOb2lzZTtcclxudmFyeWluZyB2ZWMyIHZVdjtcclxuXHJcbnZvaWQgbWFpbigpIHtcclxuICBmbG9hdCB0ID0gdVRpbWUgKiB1U3BlZWQ7XHJcbiAgdmVjMiBwID0gdlV2ICogMi4wIC0gMS4wO1xyXG4gIHAgKz0gdVBvaW50ZXIgKiB1UGFyYWxsYXggKiAwLjE7XHJcbiAgdmVjMiBycCA9IHZlYzIocC54ICogdVJvdC54IC0gcC55ICogdVJvdC55LCBwLnggKiB1Um90LnkgKyBwLnkgKiB1Um90LngpO1xyXG4gIHZlYzIgcSA9IHZlYzIocnAueCAqICh1Q2FudmFzLnggLyB1Q2FudmFzLnkpLCBycC55KTtcclxuICBxIC89IG1heCh1U2NhbGUsIDAuMDAwMSk7XHJcbiAgcSAvPSAwLjUgKyAwLjIgKiBkb3QocSwgcSk7XHJcbiAgcSArPSAwLjIgKiBjb3ModCkgLSA3LjU2O1xyXG4gIHZlYzIgdG93YXJkID0gKHVQb2ludGVyIC0gcnApO1xyXG4gIHEgKz0gdG93YXJkICogdU1vdXNlSW5mbHVlbmNlICogMC4yO1xyXG5cclxuICAgIHZlYzMgY29sID0gdmVjMygwLjApO1xyXG4gICAgZmxvYXQgYSA9IDEuMDtcclxuXHJcbiAgICBpZiAodUNvbG9yQ291bnQgPiAwKSB7XHJcbiAgICAgIHZlYzIgcyA9IHE7XHJcbiAgICAgIHZlYzMgc3VtQ29sID0gdmVjMygwLjApO1xyXG4gICAgICBmbG9hdCBjb3ZlciA9IDAuMDtcclxuICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBNQVhfQ09MT1JTOyArK2kpIHtcclxuICAgICAgICAgICAgaWYgKGkgPj0gdUNvbG9yQ291bnQpIGJyZWFrO1xyXG4gICAgICAgICAgICBzIC09IDAuMDE7XHJcbiAgICAgICAgICAgIC8vIFVzZSB1V2FycFN0cmVuZ3RoIHRvIGRpcmVjdGx5IHNjYWxlIHRoZSBpbm5lciBwaGFzZSBkaXN0b3J0aW9uXHJcbiAgICAgICAgICAgIHZlYzIgciA9IHNpbigxLjUgKiAocy55eCAqIHVGcmVxdWVuY3kpICsgKDIuMCAqIHVXYXJwU3RyZW5ndGgpICogY29zKHMgKiB1RnJlcXVlbmN5KSk7XHJcbiAgICAgICAgICAgIGZsb2F0IG0gPSBsZW5ndGgociArIHNpbig1LjAgKiByLnkgKiB1RnJlcXVlbmN5IC0gMy4wICogdCArIGZsb2F0KGkpKSAvIDQuMCk7XHJcbiAgICAgICAgICAgIGZsb2F0IHcgPSAxLjAgLSBleHAoLTYuMCAvIGV4cCg2LjAgKiBtKSk7XHJcbiAgICAgICAgICAgIHN1bUNvbCArPSB1Q29sb3JzW2ldICogdztcclxuICAgICAgICAgICAgY292ZXIgPSBtYXgoY292ZXIsIHcpO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbCA9IGNsYW1wKHN1bUNvbCwgMC4wLCAxLjApO1xyXG4gICAgICBhID0gdVRyYW5zcGFyZW50ID4gMCA/IGNvdmVyIDogMS4wO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICB2ZWMyIHMgPSBxO1xyXG4gICAgICAgIGZvciAoaW50IGsgPSAwOyBrIDwgMzsgKytrKSB7XHJcbiAgICAgICAgICAgIHMgLT0gMC4wMTtcclxuICAgICAgICAgICAgdmVjMiByID0gc2luKDEuNSAqIChzLnl4ICogdUZyZXF1ZW5jeSkgKyAoMi4wICogdVdhcnBTdHJlbmd0aCkgKiBjb3MocyAqIHVGcmVxdWVuY3kpKTtcclxuICAgICAgICAgICAgZmxvYXQgbSA9IGxlbmd0aChyICsgc2luKDUuMCAqIHIueSAqIHVGcmVxdWVuY3kgLSAzLjAgKiB0ICsgZmxvYXQoaykpIC8gNC4wKTtcclxuICAgICAgICAgICAgY29sW2tdID0gMS4wIC0gZXhwKC02LjAgLyBleHAoNi4wICogbSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBhID0gdVRyYW5zcGFyZW50ID4gMCA/IG1heChtYXgoY29sLnIsIGNvbC5nKSwgY29sLmIpIDogMS4wO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh1Tm9pc2UgPiAwLjAwMDEpIHtcclxuICAgICAgZmxvYXQgbiA9IGZyYWN0KHNpbihkb3QoZ2xfRnJhZ0Nvb3JkLnh5ICsgdmVjMih1VGltZSksIHZlYzIoMTIuOTg5OCwgNzguMjMzKSkpICogNDM3NTguNTQ1MzEyMyk7XHJcbiAgICAgIGNvbCArPSAobiAtIDAuNSkgKiB1Tm9pc2U7XHJcbiAgICAgIGNvbCA9IGNsYW1wKGNvbCwgMC4wLCAxLjApO1xyXG4gICAgfVxyXG5cclxuICAgIHZlYzMgcmdiID0gKHVUcmFuc3BhcmVudCA+IDApID8gY29sICogYSA6IGNvbDtcclxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQocmdiLCBhKTtcclxufVxyXG5gO1xyXG5cclxuY29uc3QgdmVydCA9IGBcclxudmFyeWluZyB2ZWMyIHZVdjtcclxudm9pZCBtYWluKCkge1xyXG4gIHZVdiA9IHV2O1xyXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiwgMS4wKTtcclxufVxyXG5gO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduYy1jb2xvci1iZW5kcy1iYWNrZ3JvdW5kJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vY29sb3ItYmVuZHMtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vY29sb3ItYmVuZHMtYmFja2dyb3VuZC5jb21wb25lbnQubGVzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDb2xvckJlbmRzQmFja2dyb3VuZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMge1xyXG4gIEBWaWV3Q2hpbGQoJ2NvbnRhaW5lcicsIHsgc3RhdGljOiB0cnVlIH0pIGNvbnRhaW5lclJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xyXG5cclxuICAvKiog5a655Zmo6IOM5pmv6aKc6ImyICovXHJcbiAgQElucHV0KCkgbmNCZ0NvbG9yOiBzdHJpbmcgPSAnYmxhY2snO1xyXG4gIC8qKiDml4vovazop5LluqbvvIhkZWcgLTE4MCAtIDE4MO+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jUm90YXRpb246IG51bWJlciA9IDA7XHJcbiAgLyoqIOWKqOeUu+mAn+W6pu+8iDAtMe+8iSovXHJcbiAgQElucHV0KCkgbmNTcGVlZDogbnVtYmVyID0gMC4yO1xyXG4gIC8qKiDnlKjkuo7mt7flkIjlvK/mm7Lpg6jliIbnmoTpopzoibLvvIjljYHlha3ov5vliLblrZfnrKbkuLLmlbDnu4TvvIzmnIDlpKfmlK/mjIE45Liq6aKc6Imy77yJICovXHJcbiAgQElucHV0KCkgbmNDb2xvcnM6IHN0cmluZ1tdID0gW107XHJcbiAgLyoqIOaYr+WQpuW8gOWQr+mAj+aYjuiDjOaZryAqL1xyXG4gIHByaXZhdGUgX3RyYW5zcGFyZW50OiBib29sZWFuID0gdHJ1ZTtcclxuICBASW5wdXQoKVxyXG4gIHNldCBuY1RyYW5zcGFyZW50KHZhbDogYm9vbGVhbiB8IHN0cmluZykge1xyXG4gICAgdGhpcy5fdHJhbnNwYXJlbnQgPSB2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBmYWxzZSAmJiB2YWwgIT09ICdmYWxzZSc7XHJcbiAgfVxyXG4gIGdldCBuY1RyYW5zcGFyZW50KCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zcGFyZW50O1xyXG4gIH1cclxuICAvKiog6Ieq5Yqo5peL6L2s6YCf5bqm77yIZGVnL3MgLTUtNe+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jQXV0b1JvdGF0ZTogbnVtYmVyID0gMDtcclxuICAvKiog57yp5pS+5q+U5L6L77yIMC4yLTXvvIkgKi9cclxuICBASW5wdXQoKSBuY1NjYWxlOiBudW1iZXIgPSAxO1xyXG4gIC8qKiDpopHnjofvvIgwLTXvvIkgKi9cclxuICBASW5wdXQoKSBuY0ZyZXF1ZW5jeTogbnVtYmVyID0gMTtcclxuICAvKiog5omt5puy5by65bqm77yIMC0x77yJICovXHJcbiAgQElucHV0KCkgbmNXYXJwU3RyZW5ndGg6IG51bWJlciA9IDE7XHJcbiAgLyoqIOm8oOagh+W9seWTjeWKm+eahOW8uuW6pu+8iDAtMu+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jTW91c2VJbmZsdWVuY2U6IG51bWJlciA9IDE7XHJcbiAgLyoqIOinhuW3ruaViOaenOW8uuW6pu+8jOinhuW3ruaViOaenOaYr+aMh+aMh+mSiOenu+WKqOWGheWuueaXtuS6p+eUn+eahOaViOaenO+8iDAtMu+8iSAqL1xyXG4gIEBJbnB1dCgpIG5jUGFyYWxsYXg6IG51bWJlciA9IDAuNTtcclxuICAvKiog5Zmq54K55by65bqm77yIMC0x77yJICovXHJcbiAgQElucHV0KCkgbmNOb2lzZTogbnVtYmVyID0gMC4xO1xyXG5cclxuICBwcml2YXRlIHNjZW5lITogVEhSRUUuU2NlbmU7XHJcbiAgcHJpdmF0ZSBjYW1lcmEhOiBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmE7XHJcbiAgcHJpdmF0ZSByZW5kZXJlciE6IFRIUkVFLldlYkdMUmVuZGVyZXI7XHJcbiAgcHJpdmF0ZSBtYXRlcmlhbCE6IFRIUkVFLlNoYWRlck1hdGVyaWFsO1xyXG4gIHByaXZhdGUgY2xvY2shOiBUSFJFRS5DbG9jaztcclxuICBwcml2YXRlIGdlb21ldHJ5ITogVEhSRUUuUGxhbmVHZW9tZXRyeTtcclxuXHJcbiAgcHJpdmF0ZSBwb2ludGVyVGFyZ2V0ID0gbmV3IFRIUkVFLlZlY3RvcjIoMCwgMCk7XHJcbiAgcHJpdmF0ZSBwb2ludGVyQ3VycmVudCA9IG5ldyBUSFJFRS5WZWN0b3IyKDAsIDApO1xyXG4gIHByaXZhdGUgcG9pbnRlclNtb290aCA9IDg7XHJcblxyXG4gIHByaXZhdGUgcmVzaXplT2JzZXJ2ZXIhOiBSZXNpemVPYnNlcnZlcjtcclxuICBwcml2YXRlIGludGVyc2VjdGlvbk9ic2VydmVyITogSW50ZXJzZWN0aW9uT2JzZXJ2ZXI7XHJcbiAgcHJpdmF0ZSBpc1Zpc2libGUgPSB0cnVlO1xyXG4gIHByaXZhdGUgcmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVzaXplUmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5nWm9uZTogTmdab25lKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7IH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICB0aGlzLmluaXRTY2VuZSgpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xlYW51cCgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm1hdGVyaWFsKSByZXR1cm47XHJcbiAgICB0aGlzLnVwZGF0ZVVuaWZvcm1zKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluaXRTY2VuZSgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG4gICAgdGhpcy5jYW1lcmEgPSBuZXcgVEhSRUUuT3J0aG9ncmFwaGljQ2FtZXJhKC0xLCAxLCAxLCAtMSwgMCwgMSk7XHJcblxyXG4gICAgdGhpcy5nZW9tZXRyeSA9IG5ldyBUSFJFRS5QbGFuZUdlb21ldHJ5KDIsIDIpO1xyXG4gICAgY29uc3QgdUNvbG9yc0FycmF5ID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogTUFYX0NPTE9SUyB9LCAoKSA9PiBuZXcgVEhSRUUuVmVjdG9yMygwLCAwLCAwKSk7XHJcblxyXG4gICAgdGhpcy5tYXRlcmlhbCA9IG5ldyBUSFJFRS5TaGFkZXJNYXRlcmlhbCh7XHJcbiAgICAgIHZlcnRleFNoYWRlcjogdmVydCxcclxuICAgICAgZnJhZ21lbnRTaGFkZXI6IGZyYWcsXHJcbiAgICAgIHVuaWZvcm1zOiB7XHJcbiAgICAgICAgdUNhbnZhczogeyB2YWx1ZTogbmV3IFRIUkVFLlZlY3RvcjIoMSwgMSkgfSxcclxuICAgICAgICB1VGltZTogeyB2YWx1ZTogMCB9LFxyXG4gICAgICAgIHVTcGVlZDogeyB2YWx1ZTogTnVtYmVyKHRoaXMubmNTcGVlZCkgfSxcclxuICAgICAgICB1Um90OiB7IHZhbHVlOiBuZXcgVEhSRUUuVmVjdG9yMigxLCAwKSB9LFxyXG4gICAgICAgIHVDb2xvckNvdW50OiB7IHZhbHVlOiAwIH0sXHJcbiAgICAgICAgdUNvbG9yczogeyB2YWx1ZTogdUNvbG9yc0FycmF5IH0sXHJcbiAgICAgICAgdVRyYW5zcGFyZW50OiB7IHZhbHVlOiB0aGlzLm5jVHJhbnNwYXJlbnQgPyAxIDogMCB9LFxyXG4gICAgICAgIHVTY2FsZTogeyB2YWx1ZTogTnVtYmVyKHRoaXMubmNTY2FsZSkgfSxcclxuICAgICAgICB1RnJlcXVlbmN5OiB7IHZhbHVlOiBOdW1iZXIodGhpcy5uY0ZyZXF1ZW5jeSkgfSxcclxuICAgICAgICB1V2FycFN0cmVuZ3RoOiB7IHZhbHVlOiBOdW1iZXIodGhpcy5uY1dhcnBTdHJlbmd0aCkgfSxcclxuICAgICAgICB1UG9pbnRlcjogeyB2YWx1ZTogbmV3IFRIUkVFLlZlY3RvcjIoMCwgMCkgfSxcclxuICAgICAgICB1TW91c2VJbmZsdWVuY2U6IHsgdmFsdWU6IE51bWJlcih0aGlzLm5jTW91c2VJbmZsdWVuY2UpIH0sXHJcbiAgICAgICAgdVBhcmFsbGF4OiB7IHZhbHVlOiBOdW1iZXIodGhpcy5uY1BhcmFsbGF4KSB9LFxyXG4gICAgICAgIHVOb2lzZTogeyB2YWx1ZTogTnVtYmVyKHRoaXMubmNOb2lzZSkgfVxyXG4gICAgICB9LFxyXG4gICAgICBwcmVtdWx0aXBsaWVkQWxwaGE6IHRydWUsXHJcbiAgICAgIHRyYW5zcGFyZW50OiB0cnVlXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBtZXNoID0gbmV3IFRIUkVFLk1lc2godGhpcy5nZW9tZXRyeSwgdGhpcy5tYXRlcmlhbCk7XHJcbiAgICB0aGlzLnNjZW5lLmFkZChtZXNoKTtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoe1xyXG4gICAgICBhbnRpYWxpYXM6IGZhbHNlLFxyXG4gICAgICBwb3dlclByZWZlcmVuY2U6ICdoaWdoLXBlcmZvcm1hbmNlJyxcclxuICAgICAgYWxwaGE6IHRydWVcclxuICAgIH0pO1xyXG4gICAgdGhpcy5yZW5kZXJlci5vdXRwdXRDb2xvclNwYWNlID0gVEhSRUUuU1JHQkNvbG9yU3BhY2U7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnNldFBpeGVsUmF0aW8oTWF0aC5taW4od2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMSwgMikpO1xyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRDbGVhckNvbG9yKDB4MDAwMDAwLCB0aGlzLm5jVHJhbnNwYXJlbnQgPyAwIDogMSk7XHJcbiAgICB0aGlzLnJlbmRlcmVyLmRvbUVsZW1lbnQuc3R5bGUud2lkdGggPSAnMTAwJSc7XHJcbiAgICB0aGlzLnJlbmRlcmVyLmRvbUVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xyXG4gICAgdGhpcy5yZW5kZXJlci5kb21FbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG5cclxuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnJlbmRlcmVyLmRvbUVsZW1lbnQpO1xyXG5cclxuICAgIHRoaXMuY2xvY2sgPSBuZXcgVEhSRUUuQ2xvY2soKTtcclxuXHJcbiAgICB0aGlzLnVwZGF0ZVVuaWZvcm1zKCk7XHJcbiAgICB0aGlzLnNldHVwUmVzaXplT2JzZXJ2ZXIoY29udGFpbmVyKTtcclxuICAgIHRoaXMuc2V0dXBJbnRlcnNlY3Rpb25PYnNlcnZlcihjb250YWluZXIpO1xyXG5cclxuICAgIHRoaXMubG9vcCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVVbmlmb3JtcygpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5tYXRlcmlhbCkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VTcGVlZCddLnZhbHVlID0gTnVtYmVyKHRoaXMubmNTcGVlZCk7XHJcbiAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWyd1U2NhbGUnXS52YWx1ZSA9IE51bWJlcih0aGlzLm5jU2NhbGUpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndUZyZXF1ZW5jeSddLnZhbHVlID0gTnVtYmVyKHRoaXMubmNGcmVxdWVuY3kpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVdhcnBTdHJlbmd0aCddLnZhbHVlID0gTnVtYmVyKHRoaXMubmNXYXJwU3RyZW5ndGgpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndU1vdXNlSW5mbHVlbmNlJ10udmFsdWUgPSBOdW1iZXIodGhpcy5uY01vdXNlSW5mbHVlbmNlKTtcclxuICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VQYXJhbGxheCddLnZhbHVlID0gTnVtYmVyKHRoaXMubmNQYXJhbGxheCk7XHJcbiAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWyd1Tm9pc2UnXS52YWx1ZSA9IE51bWJlcih0aGlzLm5jTm9pc2UpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVRyYW5zcGFyZW50J10udmFsdWUgPSB0aGlzLm5jVHJhbnNwYXJlbnQgPyAxIDogMDtcclxuXHJcbiAgICBpZiAodGhpcy5yZW5kZXJlcikge1xyXG4gICAgICB0aGlzLnJlbmRlcmVyLnNldENsZWFyQ29sb3IoMHgwMDAwMDAsIHRoaXMubmNUcmFuc3BhcmVudCA/IDAgOiAxKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0b1ZlYzMgPSAoaGV4OiBzdHJpbmcpID0+IHtcclxuICAgICAgY29uc3QgaCA9IGhleC5yZXBsYWNlKCcjJywgJycpLnRyaW0oKTtcclxuICAgICAgY29uc3QgdiA9IGgubGVuZ3RoID09PSAzXHJcbiAgICAgICAgPyBbcGFyc2VJbnQoaFswXSArIGhbMF0sIDE2KSwgcGFyc2VJbnQoaFsxXSArIGhbMV0sIDE2KSwgcGFyc2VJbnQoaFsyXSArIGhbMl0sIDE2KV1cclxuICAgICAgICA6IFtwYXJzZUludChoLnNsaWNlKDAsIDIpLCAxNiksIHBhcnNlSW50KGguc2xpY2UoMiwgNCksIDE2KSwgcGFyc2VJbnQoaC5zbGljZSg0LCA2KSwgMTYpXTtcclxuICAgICAgcmV0dXJuIG5ldyBUSFJFRS5WZWN0b3IzKHZbMF0gLyAyNTUsIHZbMV0gLyAyNTUsIHZbMl0gLyAyNTUpO1xyXG4gICAgfTtcclxuXHJcbiAgICBjb25zdCBhcnIgPSAodGhpcy5uY0NvbG9ycyB8fCBbXSkuZmlsdGVyKEJvb2xlYW4pLnNsaWNlKDAsIE1BWF9DT0xPUlMpLm1hcCh0b1ZlYzMpO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBNQVhfQ09MT1JTOyBpKyspIHtcclxuICAgICAgY29uc3QgdmVjID0gdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndUNvbG9ycyddLnZhbHVlW2ldO1xyXG4gICAgICBpZiAoaSA8IGFyci5sZW5ndGgpIHZlYy5jb3B5KGFycltpXSk7XHJcbiAgICAgIGVsc2UgdmVjLnNldCgwLCAwLCAwKTtcclxuICAgIH1cclxuICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ3VDb2xvckNvdW50J10udmFsdWUgPSBhcnIubGVuZ3RoO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcigncG9pbnRlcm1vdmUnLCBbJyRldmVudCddKVxyXG4gIG9uUG9pbnRlck1vdmUoZTogUG9pbnRlckV2ZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY29udGFpbmVyUmVmPy5uYXRpdmVFbGVtZW50KSByZXR1cm47XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgY29uc3QgcmVjdCA9IGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIGNvbnN0IHggPSAoKGUuY2xpZW50WCAtIHJlY3QubGVmdCkgLyAocmVjdC53aWR0aCB8fCAxKSkgKiAyIC0gMTtcclxuICAgIGNvbnN0IHkgPSAtKCgoZS5jbGllbnRZIC0gcmVjdC50b3ApIC8gKHJlY3QuaGVpZ2h0IHx8IDEpKSAqIDIgLSAxKTtcclxuICAgIHRoaXMucG9pbnRlclRhcmdldC5zZXQoeCwgeSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc2l6ZShjb250YWluZXI6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMucmVuZGVyZXIgfHwgIXRoaXMubWF0ZXJpYWwpIHJldHVybjtcclxuICAgIGNvbnN0IHcgPSBjb250YWluZXIuY2xpZW50V2lkdGggfHwgMTtcclxuICAgIGNvbnN0IGggPSBjb250YWluZXIuY2xpZW50SGVpZ2h0IHx8IDE7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnNldFNpemUodywgaCwgZmFsc2UpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndUNhbnZhcyddLnZhbHVlLnNldCh3LCBoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBSZXNpemVPYnNlcnZlcihjb250YWluZXI6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcbiAgICB0aGlzLnJlc2l6ZShjb250YWluZXIpO1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XHJcbiAgICAgIGlmICghdGhpcy5yZW5kZXJlcikgcmV0dXJuO1xyXG4gICAgICBpZiAodGhpcy5yZXNpemVSYWZJZCAhPT0gbnVsbCkgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5yZXNpemVSYWZJZCk7XHJcbiAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgICB0aGlzLnJlc2l6ZVJhZklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcclxuICAgICAgICAgIGlmICghdGhpcy5yZW5kZXJlcikgcmV0dXJuO1xyXG4gICAgICAgICAgdGhpcy5yZXNpemUoY29udGFpbmVyKTtcclxuICAgICAgICAgIHRoaXMucmVzaXplUmFmSWQgPSBudWxsO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lcik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoY29udGFpbmVyOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlciA9IG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcigoZW50cmllcykgPT4ge1xyXG4gICAgICBjb25zdCBlbnRyeSA9IGVudHJpZXNbMF07XHJcbiAgICAgIHRoaXMuaXNWaXNpYmxlID0gZW50cnkuaXNJbnRlcnNlY3RpbmcgJiYgZW50cnkuaW50ZXJzZWN0aW9uUmF0aW8gPiAwO1xyXG4gICAgfSwgeyB0aHJlc2hvbGQ6IFswLCAwLjAxLCAwLjFdIH0pO1xyXG4gICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lcik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGxvb3AgPSAoKTogdm9pZCA9PiB7XHJcbiAgICB0aGlzLnJhZklkID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMubG9vcCk7XHJcblxyXG4gICAgLy8g5Y+q5Zyo5Y+v6KeB56qX5Y+j5pe25riy5p+TXHJcbiAgICBpZiAoIXRoaXMuaXNWaXNpYmxlIHx8IGRvY3VtZW50LmhpZGRlbikge1xyXG4gICAgICBpZiAodGhpcy5jbG9jaykgdGhpcy5jbG9jay5nZXREZWx0YSgpOyAvLyDpmLLmraLph43mlrDllKTphpLml7bml7bpl7TnqoHlj5hcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLnJlbmRlcmVyIHx8ICF0aGlzLnNjZW5lIHx8ICF0aGlzLmNhbWVyYSkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGR0ID0gdGhpcy5jbG9jay5nZXREZWx0YSgpO1xyXG4gICAgY29uc3QgZWxhcHNlZCA9IHRoaXMuY2xvY2suZWxhcHNlZFRpbWU7XHJcbiAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWyd1VGltZSddLnZhbHVlID0gZWxhcHNlZDtcclxuXHJcbiAgICBjb25zdCBkZWcgPSAoTnVtYmVyKHRoaXMubmNSb3RhdGlvbikgJSAzNjApICsgTnVtYmVyKHRoaXMubmNBdXRvUm90YXRlKSAqIGVsYXBzZWQ7XHJcbiAgICBjb25zdCByYWQgPSAoZGVnICogTWF0aC5QSSkgLyAxODA7XHJcbiAgICBjb25zdCBjID0gTWF0aC5jb3MocmFkKTtcclxuICAgIGNvbnN0IHMgPSBNYXRoLnNpbihyYWQpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVJvdCddLnZhbHVlLnNldChjLCBzKTtcclxuXHJcbiAgICBjb25zdCBhbXQgPSBNYXRoLm1pbigxLCBkdCAqIHRoaXMucG9pbnRlclNtb290aCk7XHJcbiAgICB0aGlzLnBvaW50ZXJDdXJyZW50LmxlcnAodGhpcy5wb2ludGVyVGFyZ2V0LCBhbXQpO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sndVBvaW50ZXInXS52YWx1ZS5jb3B5KHRoaXMucG9pbnRlckN1cnJlbnQpO1xyXG5cclxuICAgIHRoaXMucmVuZGVyZXIucmVuZGVyKHRoaXMuc2NlbmUsIHRoaXMuY2FtZXJhKTtcclxuICB9O1xyXG5cclxuICBwcml2YXRlIGNsZWFudXAoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5yYWZJZCAhPT0gbnVsbCkge1xyXG4gICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJhZklkKTtcclxuICAgICAgdGhpcy5yYWZJZCA9IG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5yZXNpemVSYWZJZCAhPT0gbnVsbCkge1xyXG4gICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJlc2l6ZVJhZklkKTtcclxuICAgICAgdGhpcy5yZXNpemVSYWZJZCA9IG51bGw7XHJcbiAgICB9XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLnJlc2l6ZU9ic2VydmVyPy5kaXNjb25uZWN0KCk7XHJcbiAgICB9IGNhdGNoIChlKSB7IHZvaWQgMDsgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlcj8uZGlzY29ubmVjdCgpO1xyXG4gICAgfSBjYXRjaCAoZSkgeyB2b2lkIDA7IH1cclxuXHJcbiAgICBpZiAodGhpcy5nZW9tZXRyeSkgdGhpcy5nZW9tZXRyeS5kaXNwb3NlKCk7XHJcbiAgICBpZiAodGhpcy5tYXRlcmlhbCkgdGhpcy5tYXRlcmlhbC5kaXNwb3NlKCk7XHJcbiAgICBpZiAodGhpcy5yZW5kZXJlcikge1xyXG4gICAgICBjb25zdCBkb20gPSB0aGlzLnJlbmRlcmVyLmRvbUVsZW1lbnQ7XHJcbiAgICAgIGlmIChkb20gJiYgZG9tLnBhcmVudE5vZGUpIHtcclxuICAgICAgICBkb20ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb20pO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMucmVuZGVyZXIuZGlzcG9zZSgpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCI8ZGl2ICNjb250YWluZXIgY2xhc3M9XCJuYy1jb2xvci1iZW5kcy1jYW52YXMtY29udGFpbmVyXCIgW3N0eWxlLmJhY2tncm91bmQtY29sb3JdPVwibmNCZ0NvbG9yXCI+PC9kaXY+XHJcbjxkaXYgY2xhc3M9XCJuYy1jb250ZW50LXdyYXBwZXJcIj5cclxuICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuPC9kaXY+Il19