UNPKG

ng-cw-v12

Version:

Angular UI Component Library

385 lines (369 loc) 48.5 kB
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=