ng-cw-v12
Version:
Angular UI Component Library
385 lines (369 loc) • 48.5 kB
JavaScript
import { Component, ViewChild, Input, HostListener } from '@angular/core';
import * as THREE from 'three';
import * as i0 from "@angular/core";
const vert = `
attribute vec3 position;
varying vec2 vUv;
void main() {
vUv = position.xy * 0.5 + 0.5;
gl_Position = vec4(position, 1.0);
}
`;
const frag = `
precision highp float;
uniform float iTime;
uniform vec2 iResolution;
uniform bool enableRainbow;
uniform vec3 gridColor;
uniform float rippleIntensity;
uniform float gridSize;
uniform float gridThickness;
uniform float fadeDistance;
uniform float vignetteStrength;
uniform float glowIntensity;
uniform float opacity;
uniform float gridRotation;
uniform bool mouseInteraction;
uniform vec2 mousePosition;
uniform float mouseInfluence;
uniform float mouseInteractionRadius;
varying vec2 vUv;
float pi = 3.141592;
mat2 rotate(float angle) {
float s = sin(angle);
float c = cos(angle);
return mat2(c, -s, s, c);
}
void main() {
vec2 uv = vUv * 2.0 - 1.0;
uv.x *= iResolution.x / iResolution.y;
if (gridRotation != 0.0) {
uv = rotate(gridRotation * pi / 180.0) * uv;
}
float dist = length(uv);
float func = sin(pi * (iTime - dist));
vec2 rippleUv = uv + uv * func * rippleIntensity;
if (mouseInteraction && mouseInfluence > 0.0) {
vec2 mouseUv = (mousePosition * 2.0 - 1.0);
mouseUv.x *= iResolution.x / iResolution.y;
float mouseDist = length(uv - mouseUv);
float influence = mouseInfluence * exp(-mouseDist * mouseDist / (mouseInteractionRadius * mouseInteractionRadius));
float mouseWave = sin(pi * (iTime * 2.0 - mouseDist * 3.0)) * influence;
rippleUv += normalize(uv - mouseUv) * mouseWave * rippleIntensity * 0.3;
}
vec2 a = sin(gridSize * 0.5 * pi * rippleUv - pi / 2.0);
vec2 b = abs(a);
float aaWidth = 0.5;
vec2 smoothB = vec2(
smoothstep(0.0, aaWidth, b.x),
smoothstep(0.0, aaWidth, b.y)
);
vec3 color = vec3(0.0);
color += exp(-gridThickness * smoothB.x * (0.8 + 0.5 * sin(pi * iTime)));
color += exp(-gridThickness * smoothB.y);
color += 0.5 * exp(-(gridThickness / 4.0) * sin(smoothB.x));
color += 0.5 * exp(-(gridThickness / 3.0) * smoothB.y);
if (glowIntensity > 0.0) {
color += glowIntensity * exp(-gridThickness * 0.5 * smoothB.x);
color += glowIntensity * exp(-gridThickness * 0.5 * smoothB.y);
}
float ddd = exp(-2.0 * clamp(pow(dist, fadeDistance), 0.0, 1.0));
vec2 vignetteCoords = vUv - 0.5;
float vignetteDistance = length(vignetteCoords);
float vignette = 1.0 - pow(vignetteDistance * 2.0, vignetteStrength);
vignette = clamp(vignette, 0.0, 1.0);
vec3 t;
if (enableRainbow) {
t = vec3(
uv.x * 0.5 + 0.5 * sin(iTime),
uv.y * 0.5 + 0.5 * cos(iTime),
pow(cos(iTime), 4.0)
) + 0.5;
} else {
t = gridColor;
}
float finalFade = ddd * vignette;
float alpha = length(color) * finalFade * opacity;
gl_FragColor = vec4(color * t * finalFade * opacity, alpha);
}
`;
export class RippleGridBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 彩虹模式关闭时网格的颜色 */
this.ncGridColor = '#5227ff';
/** 控制中心波纹效应的强度(0-0.3)*/
this.ncRippleIntensity = 0.05;
/** 控制网格图案的密度/大小(5-30)*/
this.ncGridSize = 10.0;
/** 控制网格线的粗细(5-50)*/
this.ncGridThickness = 15.0;
/** 控制淡入淡出效果从中心向外延伸的距离(0.5-3)*/
this.ncFadeDistance = 1.5;
/** 控制暗角(边缘变暗)效果的强度(0.5-5)*/
this.ncVignetteStrength = 2.0;
/** 为网格线添加发光效果(0-1)*/
this.ncGlowIntensity = 0.1;
/** 整体效果的不透明度(0-1)*/
this.ncOpacity = 1.0;
/** 将整个网格图案旋转一定角度(0-360)*/
this.ncGridRotation = 0;
/** 启用鼠标/触摸交互以产生涟漪效 */
this._mouseInteraction = true;
/** 控制鼠标交互效果的半径(0.2-2)*/
this.ncMouseInteractionRadius = 1;
/** 为网格启用彩虹色循环动画 */
this._enableRainbow = false;
this.rafId = null;
this.resizeRafId = null;
this.isVisible = true;
this.isDestroyed = false;
this.clock = new THREE.Clock();
this.mousePosition = new THREE.Vector2(0.5, 0.5);
this.targetMouse = new THREE.Vector2(0.5, 0.5);
this.targetInfluence = 0;
}
set ncMouseInteraction(val) {
this._mouseInteraction = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncMouseInteraction() {
return this._mouseInteraction;
}
set ncEnableRainbow(val) {
this._enableRainbow = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncEnableRainbow() {
return this._enableRainbow;
}
ngOnInit() { }
ngAfterViewInit() {
this.initWebGL();
this.setupResizeObserver();
this.setupIntersectionObserver();
this.ngZone.runOutsideAngular(() => {
this.startAnimation();
});
}
ngOnDestroy() {
this.isDestroyed = true;
this.cleanup();
}
ngOnChanges(changes) {
if (!this.material)
return;
this.updateUniforms();
}
hexToRgb(hex) {
let cleanHex = hex;
if (cleanHex.startsWith('#')) {
cleanHex = cleanHex.slice(1);
}
const result = /^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(cleanHex);
return result
? new THREE.Vector3(parseInt(result[1], 16) / 255, parseInt(result[2], 16) / 255, parseInt(result[3], 16) / 255)
: new THREE.Vector3(1, 1, 1);
}
updateUniforms() {
if (!this.material)
return;
const u = this.material.uniforms;
u.enableRainbow.value = this.ncEnableRainbow;
u.gridColor.value.copy(this.hexToRgb(this.ncGridColor));
u.rippleIntensity.value = this.ncRippleIntensity;
u.gridSize.value = this.ncGridSize;
u.gridThickness.value = this.ncGridThickness;
u.fadeDistance.value = this.ncFadeDistance;
u.vignetteStrength.value = this.ncVignetteStrength;
u.glowIntensity.value = this.ncGlowIntensity;
u.opacity.value = this.ncOpacity;
u.gridRotation.value = this.ncGridRotation;
u.mouseInteraction.value = this.ncMouseInteraction;
u.mouseInteractionRadius.value = this.ncMouseInteractionRadius;
}
initWebGL() {
const el = this.containerRef.nativeElement;
this.renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
powerPreference: 'high-performance'
});
const dpr = Math.min(window.devicePixelRatio, 2);
this.renderer.setPixelRatio(dpr);
this.renderer.setSize(el.offsetWidth, el.offsetHeight);
el.appendChild(this.renderer.domElement);
this.scene = new THREE.Scene();
// The camera doesn't matter much as we use RawShaderMaterial that sets gl_Position directly
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
this.camera.position.z = 1;
const geometry = new THREE.PlaneGeometry(2, 2);
this.material = new THREE.RawShaderMaterial({
vertexShader: vert,
fragmentShader: frag,
uniforms: {
iTime: { value: 0 },
iResolution: { value: new THREE.Vector2(el.offsetWidth, el.offsetHeight) },
enableRainbow: { value: this.ncEnableRainbow },
gridColor: { value: this.hexToRgb(this.ncGridColor) },
rippleIntensity: { value: this.ncRippleIntensity },
gridSize: { value: this.ncGridSize },
gridThickness: { value: this.ncGridThickness },
fadeDistance: { value: this.ncFadeDistance },
vignetteStrength: { value: this.ncVignetteStrength },
glowIntensity: { value: this.ncGlowIntensity },
opacity: { value: this.ncOpacity },
gridRotation: { value: this.ncGridRotation },
mouseInteraction: { value: this.ncMouseInteraction },
mousePosition: { value: new THREE.Vector2(0.5, 0.5) },
mouseInfluence: { value: 0 },
mouseInteractionRadius: { value: this.ncMouseInteractionRadius }
},
blending: THREE.NormalBlending,
transparent: true,
depthTest: false,
depthWrite: false
});
this.mesh = new THREE.Mesh(geometry, this.material);
this.scene.add(this.mesh);
this.clock.start();
}
onMouseMove(e) {
if (!this.ncMouseInteraction || !this.containerRef)
return;
const rect = this.containerRef.nativeElement.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = 1.0 - (e.clientY - rect.top) / rect.height; // Flip Y coordinate
this.targetMouse.set(x, y);
}
onMouseEnter() {
if (!this.ncMouseInteraction)
return;
this.targetInfluence = 1.0;
}
onMouseLeave() {
if (!this.ncMouseInteraction)
return;
this.targetInfluence = 0.0;
}
setupResizeObserver() {
const el = this.containerRef.nativeElement;
this.resizeObserver = new ResizeObserver(() => {
if (this.resizeRafId !== null)
cancelAnimationFrame(this.resizeRafId);
this.ngZone.runOutsideAngular(() => {
this.resizeRafId = requestAnimationFrame(() => {
if (!this.renderer || !el)
return;
const w = el.offsetWidth || 1;
const h = el.offsetHeight || 1;
this.renderer.setSize(w, h);
if (this.material) {
this.material.uniforms.iResolution.value.set(w, h);
}
this.resizeRafId = null;
});
});
});
this.resizeObserver.observe(el);
}
setupIntersectionObserver() {
const el = this.containerRef.nativeElement;
this.intersectionObserver = new IntersectionObserver((entries) => {
this.isVisible = entries[0].isIntersecting;
if (this.isVisible) {
if (this.rafId === null) {
this.ngZone.runOutsideAngular(() => {
this.startAnimation();
});
}
}
}, { threshold: [0, 0.01, 0.1] });
this.intersectionObserver.observe(el);
}
startAnimation() {
if (this.isDestroyed)
return;
const render = () => {
if (!this.isVisible) {
this.rafId = null;
return;
}
this.rafId = requestAnimationFrame(render);
const t = this.clock.getElapsedTime();
if (this.material) {
this.material.uniforms.iTime.value = t;
// Mouse smoothing
const lerpFactor = 0.1;
this.mousePosition.x += (this.targetMouse.x - this.mousePosition.x) * lerpFactor;
this.mousePosition.y += (this.targetMouse.y - this.mousePosition.y) * lerpFactor;
const currentInfluence = this.material.uniforms.mouseInfluence.value;
this.material.uniforms.mouseInfluence.value += (this.targetInfluence - currentInfluence) * 0.05;
this.material.uniforms.mousePosition.value.copy(this.mousePosition);
}
this.renderer.render(this.scene, this.camera);
};
render();
}
cleanup() {
var _a, _b, _c;
if (this.rafId !== null)
cancelAnimationFrame(this.rafId);
if (this.resizeRafId !== null)
cancelAnimationFrame(this.resizeRafId);
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
(_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
if (this.renderer) {
const el = (_c = this.containerRef) === null || _c === void 0 ? void 0 : _c.nativeElement;
if (el && this.renderer.domElement.parentNode === el) {
el.removeChild(this.renderer.domElement);
}
this.renderer.dispose();
}
}
}
RippleGridBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: RippleGridBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
RippleGridBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: RippleGridBackgroundComponent, selector: "nc-ripple-grid-background", inputs: { ncGridColor: "ncGridColor", ncRippleIntensity: "ncRippleIntensity", ncGridSize: "ncGridSize", ncGridThickness: "ncGridThickness", ncFadeDistance: "ncFadeDistance", ncVignetteStrength: "ncVignetteStrength", ncGlowIntensity: "ncGlowIntensity", ncOpacity: "ncOpacity", ncGridRotation: "ncGridRotation", ncMouseInteraction: "ncMouseInteraction", ncMouseInteractionRadius: "ncMouseInteractionRadius", ncEnableRainbow: "ncEnableRainbow" }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-ripple-grid-canvas-container\"></div>\r\n<div class=\"nc-content-wrapper\">\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}.nc-ripple-grid-canvas-container{position:absolute;inset:0;z-index:0;background-color:#000}.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: RippleGridBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-ripple-grid-background',
templateUrl: './ripple-grid-background.component.html',
styleUrls: ['./ripple-grid-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncGridColor: [{
type: Input
}], ncRippleIntensity: [{
type: Input
}], ncGridSize: [{
type: Input
}], ncGridThickness: [{
type: Input
}], ncFadeDistance: [{
type: Input
}], ncVignetteStrength: [{
type: Input
}], ncGlowIntensity: [{
type: Input
}], ncOpacity: [{
type: Input
}], ncGridRotation: [{
type: Input
}], ncMouseInteraction: [{
type: Input
}], ncMouseInteractionRadius: [{
type: Input
}], ncEnableRainbow: [{
type: Input
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], onMouseEnter: [{
type: HostListener,
args: ['mouseenter']
}], onMouseLeave: [{
type: HostListener,
args: ['mouseleave']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmlwcGxlLWdyaWQtYmFja2dyb3VuZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3JpcHBsZS1ncmlkLWJhY2tncm91bmQvcmlwcGxlLWdyaWQtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3JpcHBsZS1ncmlkLWJhY2tncm91bmQvcmlwcGxlLWdyaWQtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUlULFNBQVMsRUFFVCxLQUFLLEVBR0wsWUFBWSxFQUViLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sS0FBSyxLQUFLLE1BQU0sT0FBTyxDQUFDOztBQUUvQixNQUFNLElBQUksR0FBRzs7Ozs7OztDQU9aLENBQUM7QUFFRixNQUFNLElBQUksR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBNkZaLENBQUM7QUFPRixNQUFNLE9BQU8sNkJBQTZCO0lBNkR4QyxZQUFvQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQTFEbEMsbUJBQW1CO1FBQ1YsZ0JBQVcsR0FBVyxTQUFTLENBQUM7UUFDekMsd0JBQXdCO1FBQ2Ysc0JBQWlCLEdBQVcsSUFBSSxDQUFDO1FBQzFDLHdCQUF3QjtRQUNmLGVBQVUsR0FBVyxJQUFJLENBQUM7UUFDbkMsb0JBQW9CO1FBQ1gsb0JBQWUsR0FBVyxJQUFJLENBQUM7UUFDeEMsK0JBQStCO1FBQ3RCLG1CQUFjLEdBQVcsR0FBRyxDQUFDO1FBQ3RDLDRCQUE0QjtRQUNuQix1QkFBa0IsR0FBVyxHQUFHLENBQUM7UUFDMUMscUJBQXFCO1FBQ1osb0JBQWUsR0FBVyxHQUFH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QUFRLENBQUM7Z0JBVXJDLFlBQVk7c0JBRFgsWUFBWTt1QkFBQyxZQUFZO2dCQU8xQixZQUFZO3NCQURYLFlBQVk7dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uSW5pdCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBWaWV3Q2hpbGQsXHJcbiAgRWxlbWVudFJlZixcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgU2ltcGxlQ2hhbmdlcyxcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgTmdab25lXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcclxuXHJcbmNvbnN0IHZlcnQgPSBgXHJcbiAgYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XHJcbiAgdmFyeWluZyB2ZWMyIHZVdjtcclxuICB2b2lkIG1haW4oKSB7XHJcbiAgICB2VXYgPSBwb3NpdGlvbi54eSAqIDAuNSArIDAuNTtcclxuICAgIGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiwgMS4wKTtcclxuICB9XHJcbmA7XHJcblxyXG5jb25zdCBmcmFnID0gYFxyXG4gIHByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuICB1bmlmb3JtIGZsb2F0IGlUaW1lO1xyXG4gIHVuaWZvcm0gdmVjMiBpUmVzb2x1dGlvbjtcclxuICB1bmlmb3JtIGJvb2wgZW5hYmxlUmFpbmJvdztcclxuICB1bmlmb3JtIHZlYzMgZ3JpZENvbG9yO1xyXG4gIHVuaWZvcm0gZmxvYXQgcmlwcGxlSW50ZW5zaXR5O1xyXG4gIHVuaWZvcm0gZmxvYXQgZ3JpZFNpemU7XHJcbiAgdW5pZm9ybSBmbG9hdCBncmlkVGhpY2tuZXNzO1xyXG4gIHVuaWZvcm0gZmxvYXQgZmFkZURpc3RhbmNlO1xyXG4gIHVuaWZvcm0gZmxvYXQgdmlnbmV0dGVTdHJlbmd0aDtcclxuICB1bmlmb3JtIGZsb2F0IGdsb3dJbnRlbnNpdHk7XHJcbiAgdW5pZm9ybSBmbG9hdCBvcGFjaXR5O1xyXG4gIHVuaWZvcm0gZmxvYXQgZ3JpZFJvdGF0aW9uO1xyXG4gIHVuaWZvcm0gYm9vbCBtb3VzZUludGVyYWN0aW9uO1xyXG4gIHVuaWZvcm0gdmVjMiBtb3VzZVBvc2l0aW9uO1xyXG4gIHVuaWZvcm0gZmxvYXQgbW91c2VJbmZsdWVuY2U7XHJcbiAgdW5pZm9ybSBmbG9hdCBtb3VzZUludGVyYWN0aW9uUmFkaXVzO1xyXG4gIHZhcnlpbmcgdmVjMiB2VXY7XHJcblxyXG4gIGZsb2F0IHBpID0gMy4xNDE1OTI7XHJcblxyXG4gIG1hdDIgcm90YXRlKGZsb2F0IGFuZ2xlKSB7XHJcbiAgICBmbG9hdCBzID0gc2luKGFuZ2xlKTtcclxuICAgIGZsb2F0IGMgPSBjb3MoYW5nbGUpO1xyXG4gICAgcmV0dXJuIG1hdDIoYywgLXMsIHMsIGMpO1xyXG4gIH1cclxuXHJcbiAgdm9pZCBtYWluKCkge1xyXG4gICAgdmVjMiB1diA9IHZVdiAqIDIuMCAtIDEuMDtcclxuICAgIHV2LnggKj0gaVJlc29sdXRpb24ueCAvIGlSZXNvbHV0aW9uLnk7XHJcblxyXG4gICAgaWYgKGdyaWRSb3RhdGlvbiAhPSAwLjApIHtcclxuICAgICAgdXYgPSByb3RhdGUoZ3JpZFJvdGF0aW9uICogcGkgLyAxODAuMCkgKiB1djtcclxuICAgIH1cclxuXHJcbiAgICBmbG9hdCBkaXN0ID0gbGVuZ3RoKHV2KTtcclxuICAgIGZsb2F0IGZ1bmMgPSBzaW4ocGkgKiAoaVRpbWUgLSBkaXN0KSk7XHJcbiAgICB2ZWMyIHJpcHBsZVV2ID0gdXYgKyB1diAqIGZ1bmMgKiByaXBwbGVJbnRlbnNpdHk7XHJcblxyXG4gICAgaWYgKG1vdXNlSW50ZXJhY3Rpb24gJiYgbW91c2VJbmZsdWVuY2UgPiAwLjApIHtcclxuICAgICAgdmVjMiBtb3VzZVV2ID0gKG1vdXNlUG9zaXRpb24gKiAyLjAgLSAxLjApO1xyXG4gICAgICBtb3VzZVV2LnggKj0gaVJlc29sdXRpb24ueCAvIGlSZXNvbHV0aW9uLnk7XHJcbiAgICAgIGZsb2F0IG1vdXNlRGlzdCA9IGxlbmd0aCh1diAtIG1vdXNlVXYpO1xyXG4gICAgICBcclxuICAgICAgZmxvYXQgaW5mbHVlbmNlID0gbW91c2VJbmZsdWVuY2UgKiBleHAoLW1vdXNlRGlzdCAqIG1vdXNlRGlzdCAvIChtb3VzZUludGVyYWN0aW9uUmFkaXVzICogbW91c2VJbnRlcmFjdGlvblJhZGl1cykpO1xyXG4gICAgICBcclxuICAgICAgZmxvYXQgbW91c2VXYXZlID0gc2luKHBpICogKGlUaW1lICogMi4wIC0gbW91c2VEaXN0ICogMy4wKSkgKiBpbmZsdWVuY2U7XHJcbiAgICAgIHJpcHBsZVV2ICs9IG5vcm1hbGl6ZSh1diAtIG1vdXNlVXYpICogbW91c2VXYXZlICogcmlwcGxlSW50ZW5zaXR5ICogMC4zO1xyXG4gICAgfVxyXG5cclxuICAgIHZlYzIgYSA9IHNpbihncmlkU2l6ZSAqIDAuNSAqIHBpICogcmlwcGxlVXYgLSBwaSAvIDIuMCk7XHJcbiAgICB2ZWMyIGIgPSBhYnMoYSk7XHJcblxyXG4gICAgZmxvYXQgYWFXaWR0aCA9IDAuNTtcclxuICAgIHZlYzIgc21vb3RoQiA9IHZlYzIoXHJcbiAgICAgIHNtb290aHN0ZXAoMC4wLCBhYVdpZHRoLCBiLngpLFxyXG4gICAgICBzbW9vdGhzdGVwKDAuMCwgYWFXaWR0aCwgYi55KVxyXG4gICAgKTtcclxuXHJcbiAgICB2ZWMzIGNvbG9yID0gdmVjMygwLjApO1xyXG4gICAgY29sb3IgKz0gZXhwKC1ncmlkVGhpY2tuZXNzICogc21vb3RoQi54ICogKDAuOCArIDAuNSAqIHNpbihwaSAqIGlUaW1lKSkpO1xyXG4gICAgY29sb3IgKz0gZXhwKC1ncmlkVGhpY2tuZXNzICogc21vb3RoQi55KTtcclxuICAgIGNvbG9yICs9IDAuNSAqIGV4cCgtKGdyaWRUaGlja25lc3MgLyA0LjApICogc2luKHNtb290aEIueCkpO1xyXG4gICAgY29sb3IgKz0gMC41ICogZXhwKC0oZ3JpZFRoaWNrbmVzcyAvIDMuMCkgKiBzbW9vdGhCLnkpO1xyXG5cclxuICAgIGlmIChnbG93SW50ZW5zaXR5ID4gMC4wKSB7XHJcbiAgICAgIGNvbG9yICs9IGdsb3dJbnRlbnNpdHkgKiBleHAoLWdyaWRUaGlja25lc3MgKiAwLjUgKiBzbW9vdGhCLngpO1xyXG4gICAgICBjb2xvciArPSBnbG93SW50ZW5zaXR5ICogZXhwKC1ncmlkVGhpY2tuZXNzICogMC41ICogc21vb3RoQi55KTtcclxuICAgIH1cclxuXHJcbiAgICBmbG9hdCBkZGQgPSBleHAoLTIuMCAqIGNsYW1wKHBvdyhkaXN0LCBmYWRlRGlzdGFuY2UpLCAwLjAsIDEuMCkpO1xyXG4gICAgXHJcbiAgICB2ZWMyIHZpZ25ldHRlQ29vcmRzID0gdlV2IC0gMC41O1xyXG4gICAgZmxvYXQgdmlnbmV0dGVEaXN0YW5jZSA9IGxlbmd0aCh2aWduZXR0ZUNvb3Jkcyk7XHJcbiAgICBmbG9hdCB2aWduZXR0ZSA9IDEuMCAtIHBvdyh2aWduZXR0ZURpc3RhbmNlICogMi4wLCB2aWduZXR0ZVN0cmVuZ3RoKTtcclxuICAgIHZpZ25ldHRlID0gY2xhbXAodmlnbmV0dGUsIDAuMCwgMS4wKTtcclxuICAgIFxyXG4gICAgdmVjMyB0O1xyXG4gICAgaWYgKGVuYWJsZVJhaW5ib3cpIHtcclxuICAgICAgdCA9IHZlYzMoXHJcbiAgICAgICAgdXYueCAqIDAuNSArIDAuNSAqIHNpbihpVGltZSksXHJcbiAgICAgICAgdXYueSAqIDAuNSArIDAuNSAqIGNvcyhpVGltZSksXHJcbiAgICAgICAgcG93KGNvcyhpVGltZSksIDQuMClcclxuICAgICAgKSArIDAuNTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHQgPSBncmlkQ29sb3I7XHJcbiAgICB9XHJcblxyXG4gICAgZmxvYXQgZmluYWxGYWRlID0gZGRkICogdmlnbmV0dGU7XHJcbiAgICBmbG9hdCBhbHBoYSA9IGxlbmd0aChjb2xvcikgKiBmaW5hbEZhZGUgKiBvcGFjaXR5O1xyXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNChjb2xvciAqIHQgKiBmaW5hbEZhZGUgKiBvcGFjaXR5LCBhbHBoYSk7XHJcbiAgfVxyXG5gO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduYy1yaXBwbGUtZ3JpZC1iYWNrZ3JvdW5kJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vcmlwcGxlLWdyaWQtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vcmlwcGxlLWdyaWQtYmFja2dyb3VuZC5jb21wb25lbnQubGVzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBSaXBwbGVHcmlkQmFja2dyb3VuZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMge1xyXG4gIEBWaWV3Q2hpbGQoJ2NvbnRhaW5lcicsIHsgc3RhdGljOiB0cnVlIH0pIGNvbnRhaW5lclJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xyXG5cclxuICAvKiog5b2p6Jm55qih5byP5YWz6Zet5pe2572R5qC855qE6aKc6ImyICovXHJcbiAgQElucHV0KCkgbmNHcmlkQ29sb3I6IHN0cmluZyA9ICcjNTIyN2ZmJztcclxuICAvKiog5o6n5Yi25Lit5b+D5rOi57q55pWI5bqU55qE5by65bqm77yIMC0wLjPvvIkqL1xyXG4gIEBJbnB1dCgpIG5jUmlwcGxlSW50ZW5zaXR5OiBudW1iZXIgPSAwLjA1O1xyXG4gIC8qKiDmjqfliLbnvZHmoLzlm77moYjnmoTlr4bluqYv5aSn5bCP77yINS0zMO+8iSovXHJcbiAgQElucHV0KCkgbmNHcmlkU2l6ZTogbnVtYmVyID0gMTAuMDtcclxuICAvKiog5o6n5Yi2572R5qC857q/55qE57KX57uG77yINS01MO+8iSovXHJcbiAgQElucHV0KCkgbmNHcmlkVGhpY2tuZXNzOiBudW1iZXIgPSAxNS4wO1xyXG4gIC8qKiDmjqfliLbmt6HlhaXmt6Hlh7rmlYjmnpzku47kuK3lv4PlkJHlpJblu7bkvLjnmoTot53nprvvvIgwLjUtM++8iSovXHJcbiAgQElucHV0KCkgbmNGYWRlRGlzdGFuY2U6IG51bWJlciA9IDEuNTtcclxuICAvKiog5o6n5Yi25pqX6KeS77yI6L6557yY5Y+Y5pqX77yJ5pWI5p6c55qE5by65bqm77yIMC41LTXvvIkqL1xyXG4gIEBJbnB1dCgpIG5jVmlnbmV0dGVTdHJlbmd0aDogbnVtYmVyID0gMi4wO1xyXG4gIC8qKiDkuLrnvZHmoLznur/mt7vliqDlj5HlhYnmlYjmnpzvvIgwLTHvvIkqL1xyXG4gIEBJbnB1dCgpIG5jR2xvd0ludGVuc2l0eTogbnVtYmVyID0gMC4xO1xyXG4gIC8qKiDmlbTkvZPmlYjmnpznmoTkuI3pgI/mmI7luqbvvIgwLTHvvIkqL1xyXG4gIEBJbnB1dCgpIG5jT3BhY2l0eTogbnVtYmVyID0gMS4wO1xyXG4gIC8qKiDlsIbmlbTkuKrnvZHmoLzlm77moYjml4vovazkuIDlrprop5LluqbvvIgwLTM2MO+8iSovXHJcbiAgQElucHV0KCkgbmNHcmlkUm90YXRpb246IG51bWJlciA9IDA7XHJcbiAgLyoqIOWQr+eUqOm8oOaghy/op6bmkbjkuqTkupLku6XkuqfnlJ/mtp/mvKrmlYggKi9cclxuICBwcml2YXRlIF9tb3VzZUludGVyYWN0aW9uOiBib29sZWFuID0gdHJ1ZTtcclxuICBASW5wdXQoKVxyXG4gIHNldCBuY01vdXNlSW50ZXJhY3Rpb24odmFsOiBib29sZWFuIHwgc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9tb3VzZUludGVyYWN0aW9uID0gdmFsICE9PSBudWxsICYmIHZhbCAhPT0gdW5kZWZpbmVkICYmIHZhbCAhPT0gZmFsc2UgJiYgdmFsICE9PSAnZmFsc2UnO1xyXG4gIH1cclxuICBnZXQgbmNNb3VzZUludGVyYWN0aW9uKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuX21vdXNlSW50ZXJhY3Rpb247XHJcbiAgfVxyXG4gIC8qKiDmjqfliLbpvKDmoIfkuqTkupLmlYjmnpznmoTljYrlvoTvvIgwLjItMu+8iSovXHJcbiAgQElucHV0KCkgbmNNb3VzZUludGVyYWN0aW9uUmFkaXVzOiBudW1iZXIgPSAxO1xyXG4gIC8qKiDkuLrnvZHmoLzlkK/nlKjlvanombnoibLlvqrnjq/liqjnlLsgKi9cclxuICBwcml2YXRlIF9lbmFibGVSYWluYm93OiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KClcclxuICBzZXQgbmNFbmFibGVSYWluYm93KHZhbDogYm9vbGVhbiB8IHN0cmluZykge1xyXG4gICAgdGhpcy5fZW5hYmxlUmFpbmJvdyA9IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09IGZhbHNlICYmIHZhbCAhPT0gJ2ZhbHNlJztcclxuICB9XHJcbiAgZ2V0IG5jRW5hYmxlUmFpbmJvdygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9lbmFibGVSYWluYm93O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZW5kZXJlciE6IFRIUkVFLldlYkdMUmVuZGVyZXI7XHJcbiAgcHJpdmF0ZSBzY2VuZSE6IFRIUkVFLlNjZW5lO1xyXG4gIHByaXZhdGUgY2FtZXJhITogVEhSRUUuT3J0aG9ncmFwaGljQ2FtZXJhO1xyXG4gIHByaXZhdGUgbWF0ZXJpYWwhOiBUSFJFRS5SYXdTaGFkZXJNYXRlcmlhbDtcclxuICBwcml2YXRlIG1lc2ghOiBUSFJFRS5NZXNoO1xyXG5cclxuICBwcml2YXRlIHJlc2l6ZU9ic2VydmVyITogUmVzaXplT2JzZXJ2ZXI7XHJcbiAgcHJpdmF0ZSBpbnRlcnNlY3Rpb25PYnNlcnZlciE6IEludGVyc2VjdGlvbk9ic2VydmVyO1xyXG4gIHByaXZhdGUgcmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVzaXplUmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgaXNWaXNpYmxlOiBib29sZWFuID0gdHJ1ZTtcclxuICBwcml2YXRlIGlzRGVzdHJveWVkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIHByaXZhdGUgY2xvY2sgPSBuZXcgVEhSRUUuQ2xvY2soKTtcclxuXHJcbiAgcHJpdmF0ZSBtb3VzZVBvc2l0aW9uID0gbmV3IFRIUkVFLlZlY3RvcjIoMC41LCAwLjUpO1xyXG4gIHByaXZhdGUgdGFyZ2V0TW91c2UgPSBuZXcgVEhSRUUuVmVjdG9yMigwLjUsIDAuNSk7XHJcbiAgcHJpdmF0ZSB0YXJnZXRJbmZsdWVuY2UgPSAwO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5nWm9uZTogTmdab25lKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7IH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbml0V2ViR0woKTtcclxuICAgIHRoaXMuc2V0dXBSZXNpemVPYnNlcnZlcigpO1xyXG4gICAgdGhpcy5zZXR1cEludGVyc2VjdGlvbk9ic2VydmVyKCk7XHJcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzRGVzdHJveWVkID0gdHJ1ZTtcclxuICAgIHRoaXMuY2xlYW51cCgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm1hdGVyaWFsKSByZXR1cm47XHJcbiAgICB0aGlzLnVwZGF0ZVVuaWZvcm1zKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhleFRvUmdiKGhleDogc3RyaW5nKTogVEhSRUUuVmVjdG9yMyB7XHJcbiAgICBsZXQgY2xlYW5IZXggPSBoZXg7XHJcbiAgICBpZiAoY2xlYW5IZXguc3RhcnRzV2l0aCgnIycpKSB7XHJcbiAgICAgIGNsZWFuSGV4ID0gY2xlYW5IZXguc2xpY2UoMSk7XHJcbiAgICB9XHJcbiAgICBjb25zdCByZXN1bHQgPSAvXihbYS1mXFxkXXsyfSkoW2EtZlxcZF17Mn0pKFthLWZcXGRdezJ9KSQvaS5leGVjKGNsZWFuSGV4KTtcclxuICAgIHJldHVybiByZXN1bHRcclxuICAgICAgPyBuZXcgVEhSRUUuVmVjdG9yMyhcclxuICAgICAgICBwYXJzZUludChyZXN1bHRbMV0sIDE2KSAvIDI1NSxcclxuICAgICAgICBwYXJzZUludChyZXN1bHRbMl0sIDE2KSAvIDI1NSxcclxuICAgICAgICBwYXJzZUludChyZXN1bHRbM10sIDE2KSAvIDI1NVxyXG4gICAgICApXHJcbiAgICAgIDogbmV3IFRIUkVFLlZlY3RvcjMoMSwgMSwgMSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVVuaWZvcm1zKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm1hdGVyaWFsKSByZXR1cm47XHJcbiAgICBjb25zdCB1ID0gdGhpcy5tYXRlcmlhbC51bmlmb3JtcztcclxuICAgIHUuZW5hYmxlUmFpbmJvdy52YWx1ZSA9IHRoaXMubmNFbmFibGVSYWluYm93O1xyXG4gICAgdS5ncmlkQ29sb3IudmFsdWUuY29weSh0aGlzLmhleFRvUmdiKHRoaXMubmNHcmlkQ29sb3IpKTtcclxuICAgIHUucmlwcGxlSW50ZW5zaXR5LnZhbHVlID0gdGhpcy5uY1JpcHBsZUludGVuc2l0eTtcclxuICAgIHUuZ3JpZFNpemUudmFsdWUgPSB0aGlzLm5jR3JpZFNpemU7XHJcbiAgICB1LmdyaWRUaGlja25lc3MudmFsdWUgPSB0aGlzLm5jR3JpZFRoaWNrbmVzcztcclxuICAgIHUuZmFkZURpc3RhbmNlLnZhbHVlID0gdGhpcy5uY0ZhZGVEaXN0YW5jZTtcclxuICAgIHUudmlnbmV0dGVTdHJlbmd0aC52YWx1ZSA9IHRoaXMubmNWaWduZXR0ZVN0cmVuZ3RoO1xyXG4gICAgdS5nbG93SW50ZW5zaXR5LnZhbHVlID0gdGhpcy5uY0dsb3dJbnRlbnNpdHk7XHJcbiAgICB1Lm9wYWNpdHkudmFsdWUgPSB0aGlzLm5jT3BhY2l0eTtcclxuICAgIHUuZ3JpZFJvdGF0aW9uLnZhbHVlID0gdGhpcy5uY0dyaWRSb3RhdGlvbjtcclxuICAgIHUubW91c2VJbnRlcmFjdGlvbi52YWx1ZSA9IHRoaXMubmNNb3VzZUludGVyYWN0aW9uO1xyXG4gICAgdS5tb3VzZUludGVyYWN0aW9uUmFkaXVzLnZhbHVlID0gdGhpcy5uY01vdXNlSW50ZXJhY3Rpb25SYWRpdXM7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGluaXRXZWJHTCgpOiB2b2lkIHtcclxuICAgIGNvbnN0IGVsID0gdGhpcy5jb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoe1xyXG4gICAgICBhbHBoYTogdHJ1ZSxcclxuICAgICAgYW50aWFsaWFzOiB0cnVlLFxyXG4gICAgICBwb3dlclByZWZlcmVuY2U6ICdoaWdoLXBlcmZvcm1hbmNlJ1xyXG4gICAgfSk7XHJcbiAgICBjb25zdCBkcHIgPSBNYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywgMik7XHJcbiAgICB0aGlzLnJlbmRlcmVyLnNldFBpeGVsUmF0aW8oZHByKTtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0U2l6ZShlbC5vZmZzZXRXaWR0aCwgZWwub2Zmc2V0SGVpZ2h0KTtcclxuICAgIGVsLmFwcGVuZENoaWxkKHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudCk7XHJcblxyXG4gICAgdGhpcy5zY2VuZSA9IG5ldyBUSFJFRS5TY2VuZSgpO1xyXG5cclxuICAgIC8vIFRoZSBjYW1lcmEgZG9lc24ndCBtYXR0ZXIgbXVjaCBhcyB3ZSB1c2UgUmF3U2hhZGVyTWF0ZXJpYWwgdGhhdCBzZXRzIGdsX1Bvc2l0aW9uIGRpcmVjdGx5XHJcbiAgICB0aGlzLmNhbWVyYSA9IG5ldyBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmEoLTEsIDEsIDEsIC0xLCAwLjEsIDEwKTtcclxuICAgIHRoaXMuY2FtZXJhLnBvc2l0aW9uLnogPSAxO1xyXG5cclxuICAgIGNvbnN0IGdlb21ldHJ5ID0gbmV3IFRIUkVFLlBsYW5lR2VvbWV0cnkoMiwgMik7XHJcblxyXG4gICAgdGhpcy5tYXRlcmlhbCA9IG5ldyBUSFJFRS5SYXdTaGFkZXJNYXRlcmlhbCh7XHJcbiAgICAgIHZlcnRleFNoYWRlcjogdmVydCxcclxuICAgICAgZnJhZ21lbnRTaGFkZXI6IGZyYWcsXHJcbiAgICAgIHVuaWZvcm1zOiB7XHJcbiAgICAgICAgaVRpbWU6IHsgdmFsdWU6IDAgfSxcclxuICAgICAgICBpUmVzb2x1dGlvbjogeyB2YWx1ZTogbmV3IFRIUkVFLlZlY3RvcjIoZWwub2Zmc2V0V2lkdGgsIGVsLm9mZnNldEhlaWdodCkgfSxcclxuICAgICAgICBlbmFibGVSYWluYm93OiB7IHZhbHVlOiB0aGlzLm5jRW5hYmxlUmFpbmJvdyB9LFxyXG4gICAgICAgIGdyaWRDb2xvcjogeyB2YWx1ZTogdGhpcy5oZXhUb1JnYih0aGlzLm5jR3JpZENvbG9yKSB9LFxyXG4gICAgICAgIHJpcHBsZUludGVuc2l0eTogeyB2YWx1ZTogdGhpcy5uY1JpcHBsZUludGVuc2l0eSB9LFxyXG4gICAgICAgIGdyaWRTaXplOiB7IHZhbHVlOiB0aGlzLm5jR3JpZFNpemUgfSxcclxuICAgICAgICBncmlkVGhpY2tuZXNzOiB7IHZhbHVlOiB0aGlzLm5jR3JpZFRoaWNrbmVzcyB9LFxyXG4gICAgICAgIGZhZGVEaXN0YW5jZTogeyB2YWx1ZTogdGhpcy5uY0ZhZGVEaXN0YW5jZSB9LFxyXG4gICAgICAgIHZpZ25ldHRlU3RyZW5ndGg6IHsgdmFsdWU6IHRoaXMubmNWaWduZXR0ZVN0cmVuZ3RoIH0sXHJcbiAgICAgICAgZ2xvd0ludGVuc2l0eTogeyB2YWx1ZTogdGhpcy5uY0dsb3dJbnRlbnNpdHkgfSxcclxuICAgICAgICBvcGFjaXR5OiB7IHZhbHVlOiB0aGlzLm5jT3BhY2l0eSB9LFxyXG4gICAgICAgIGdyaWRSb3RhdGlvbjogeyB2YWx1ZTogdGhpcy5uY0dyaWRSb3RhdGlvbiB9LFxyXG4gICAgICAgIG1vdXNlSW50ZXJhY3Rpb246IHsgdmFsdWU6IHRoaXMubmNNb3VzZUludGVyYWN0aW9uIH0sXHJcbiAgICAgICAgbW91c2VQb3NpdGlvbjogeyB2YWx1ZTogbmV3IFRIUkVFLlZlY3RvcjIoMC41LCAwLjUpIH0sXHJcbiAgICAgICAgbW91c2VJbmZsdWVuY2U6IHsgdmFsdWU6IDAgfSxcclxuICAgICAgICBtb3VzZUludGVyYWN0aW9uUmFkaXVzOiB7IHZhbHVlOiB0aGlzLm5jTW91c2VJbnRlcmFjdGlvblJhZGl1cyB9XHJcbiAgICAgIH0sXHJcbiAgICAgIGJsZW5kaW5nOiBUSFJFRS5Ob3JtYWxCbGVuZGluZyxcclxuICAgICAgdHJhbnNwYXJlbnQ6IHRydWUsXHJcbiAgICAgIGRlcHRoVGVzdDogZmFsc2UsXHJcbiAgICAgIGRlcHRoV3JpdGU6IGZhbHNlXHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLm1lc2ggPSBuZXcgVEhSRUUuTWVzaChnZW9tZXRyeSwgdGhpcy5tYXRlcmlhbCk7XHJcbiAgICB0aGlzLnNjZW5lLmFkZCh0aGlzLm1lc2gpO1xyXG5cclxuICAgIHRoaXMuY2xvY2suc3RhcnQoKTtcclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbW92ZScsIFsnJGV2ZW50J10pXHJcbiAgb25Nb3VzZU1vdmUoZTogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm5jTW91c2VJbnRlcmFjdGlvbiB8fCAhdGhpcy5jb250YWluZXJSZWYpIHJldHVybjtcclxuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgY29uc3QgeCA9IChlLmNsaWVudFggLSByZWN0LmxlZnQpIC8gcmVjdC53aWR0aDtcclxuICAgIGNvbnN0IHkgPSAxLjAgLSAoZS5jbGllbnRZIC0gcmVjdC50b3ApIC8gcmVjdC5oZWlnaHQ7IC8vIEZsaXAgWSBjb29yZGluYXRlXHJcbiAgICB0aGlzLnRhcmdldE1vdXNlLnNldCh4LCB5KTtcclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlZW50ZXInKVxyXG4gIG9uTW91c2VFbnRlcigpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5uY01vdXNlSW50ZXJhY3Rpb24pIHJldHVybjtcclxuICAgIHRoaXMudGFyZ2V0SW5mbHVlbmNlID0gMS4wO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXHJcbiAgb25Nb3VzZUxlYXZlKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm5jTW91c2VJbnRlcmFjdGlvbikgcmV0dXJuO1xyXG4gICAgdGhpcy50YXJnZXRJbmZsdWVuY2UgPSAwLjA7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwUmVzaXplT2JzZXJ2ZXIoKTogdm9pZCB7XHJcbiAgICBjb25zdCBlbCA9IHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICB0aGlzLnJlc2l6ZU9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKCgpID0+IHtcclxuICAgICAgaWYgKHRoaXMucmVzaXplUmFmSWQgIT09IG51bGwpIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmVzaXplUmFmSWQpO1xyXG4gICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgICAgdGhpcy5yZXNpemVSYWZJZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XHJcbiAgICAgICAgICBpZiAoIXRoaXMucmVuZGVyZXIgfHwgIWVsKSByZXR1cm47XHJcbiAgICAgICAgICBjb25zdCB3ID0gZWwub2Zmc2V0V2lkdGggfHwgMTtcclxuICAgICAgICAgIGNvbnN0IGggPSBlbC5vZmZzZXRIZWlnaHQgfHwgMTtcclxuICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U2l6ZSh3LCBoKTtcclxuICAgICAgICAgIGlmICh0aGlzLm1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXMuaVJlc29sdXRpb24udmFsdWUuc2V0KHcsIGgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdGhpcy5yZXNpemVSYWZJZCA9IG51bGw7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLnJlc2l6ZU9ic2VydmVyLm9ic2VydmUoZWwpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzZXR1cEludGVyc2VjdGlvbk9ic2VydmVyKCk6IHZvaWQge1xyXG4gICAgY29uc3QgZWwgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlciA9IG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcigoZW50cmllcykgPT4ge1xyXG4gICAgICB0aGlzLmlzVmlzaWJsZSA9IGVudHJpZXNbMF0uaXNJbnRlcnNlY3Rpbmc7XHJcbiAgICAgIGlmICh0aGlzLmlzVmlzaWJsZSkge1xyXG4gICAgICAgIGlmICh0aGlzLnJhZklkID09PSBudWxsKSB7XHJcbiAgICAgICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSwgeyB0aHJlc2hvbGQ6IFswLCAwLjAxLCAwLjFdIH0pO1xyXG4gICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlci5vYnNlcnZlKGVsKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc3RhcnRBbmltYXRpb24oKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5pc0Rlc3Ryb3llZCkgcmV0dXJuO1xyXG4gICAgY29uc3QgcmVuZGVyID0gKCkgPT4ge1xyXG4gICAgICBpZiAoIXRoaXMuaXNWaXNpYmxlKSB7XHJcbiAgICAgICAgdGhpcy5yYWZJZCA9IG51bGw7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMucmFmSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVuZGVyKTtcclxuXHJcbiAgICAgIGNvbnN0IHQgPSB0aGlzLmNsb2NrLmdldEVsYXBzZWRUaW1lKCk7XHJcblxyXG4gICAgICBpZiAodGhpcy5tYXRlcmlhbCkge1xyXG4gICAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXMuaVRpbWUudmFsdWUgPSB0O1xyXG5cclxuICAgICAgICAvLyBNb3VzZSBzbW9vdGhpbmdcclxuICAgICAgICBjb25zdCBsZXJwRmFjdG9yID0gMC4xO1xyXG4gICAgICAgIHRoaXMubW91c2VQb3NpdGlvbi54ICs9ICh0aGlzLnRhcmdldE1vdXNlLnggLSB0aGlzLm1vdXNlUG9zaXRpb24ueCkgKiBsZXJwRmFjdG9yO1xyXG4gICAgICAgIHRoaXMubW91c2VQb3NpdGlvbi55ICs9ICh0aGlzLnRhcmdldE1vdXNlLnkgLSB0aGlzLm1vdXNlUG9zaXRpb24ueSkgKiBsZXJwRmFjdG9yO1xyXG5cclxuICAgICAgICBjb25zdCBjdXJyZW50SW5mbHVlbmNlID0gdGhpcy5tYXRlcmlhbC51bmlmb3Jtcy5tb3VzZUluZmx1ZW5jZS52YWx1ZTtcclxuICAgICAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zLm1vdXNlSW5mbHVlbmNlLnZhbHVlICs9ICh0aGlzLnRhcmdldEluZmx1ZW5jZSAtIGN1cnJlbnRJbmZsdWVuY2UpICogMC4wNTtcclxuXHJcbiAgICAgICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtcy5tb3VzZVBvc2l0aW9uLnZhbHVlLmNvcHkodGhpcy5tb3VzZVBvc2l0aW9uKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5yZW5kZXJlci5yZW5kZXIodGhpcy5zY2VuZSwgdGhpcy5jYW1lcmEpO1xyXG4gICAgfTtcclxuICAgIHJlbmRlcigpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhbnVwKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMucmFmSWQgIT09IG51bGwpIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmFmSWQpO1xyXG4gICAgaWYgKHRoaXMucmVzaXplUmFmSWQgIT09IG51bGwpIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMucmVzaXplUmFmSWQpO1xyXG5cclxuICAgIHRoaXMucmVzaXplT2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTtcclxuICAgIHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTtcclxuXHJcbiAgICBpZiAodGhpcy5yZW5kZXJlcikge1xyXG4gICAgICBjb25zdCBlbCA9IHRoaXMuY29udGFpbmVyUmVmPy5uYXRpdmVFbGVtZW50O1xyXG4gICAgICBpZiAoZWwgJiYgdGhpcy5yZW5kZXJlci5kb21FbGVtZW50LnBhcmVudE5vZGUgPT09IGVsKSB7XHJcbiAgICAgICAgZWwucmVtb3ZlQ2hpbGQodGhpcy5yZW5kZXJlci5kb21FbGVtZW50KTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnJlbmRlcmVyLmRpc3Bvc2UoKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiPGRpdiAjY29udGFpbmVyIGNsYXNzPVwibmMtcmlwcGxlLWdyaWQtY2FudmFzLWNvbnRhaW5lclwiPjwvZGl2PlxyXG48ZGl2IGNsYXNzPVwibmMtY29udGVudC13cmFwcGVyXCI+XHJcbiAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcbjwvZGl2PlxyXG4iXX0=