UNPKG

ng-cw-v12

Version:

Angular UI Component Library

446 lines (426 loc) 57 kB
import { Component, ViewChild, Input, HostListener } from '@angular/core'; import * as THREE from 'three'; import * as i0 from "@angular/core"; // ─── 顶点着色器 ─────────────────────────────────────────────────────── const vert = ` varying vec2 vUv; void main() { vUv = uv; gl_Position = vec4(position, 1.0); } `; // ─── 片元着色器 ─────────────────────────────────────────────────────── const frag = `precision highp float; uniform float iTime; uniform vec2 iResolution; uniform vec2 rayPos; uniform vec2 rayDir; uniform vec3 raysColor; uniform float raysSpeed; uniform float lightSpread; uniform float rayLength; uniform float pulsating; uniform float fadeDistance; uniform float saturation; uniform vec2 mousePos; uniform float mouseInfluence; uniform float noiseAmount; uniform float distortion; varying vec2 vUv; float noise(vec2 st) { return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123); } float rayStrength(vec2 raySource, vec2 rayRefDirection, vec2 coord, float seedA, float seedB, float speed) { vec2 sourceToCoord = coord - raySource; vec2 dirNorm = normalize(sourceToCoord); float cosAngle = dot(dirNorm, rayRefDirection); float distortedAngle = cosAngle + distortion * sin(iTime * 2.0 + length(sourceToCoord) * 0.01) * 0.2; float spreadFactor = pow(max(distortedAngle, 0.0), 1.0 / max(lightSpread, 0.001)); float distance = length(sourceToCoord); float maxDistance = iResolution.x * rayLength; float lengthFalloff = clamp((maxDistance - distance) / maxDistance, 0.0, 1.0); float fadeFalloff = clamp((iResolution.x * fadeDistance - distance) / (iResolution.x * fadeDistance), 0.5, 1.0); float pulse = pulsating > 0.5 ? (0.8 + 0.2 * sin(iTime * speed * 3.0)) : 1.0; float baseStrength = clamp( (0.45 + 0.15 * sin(distortedAngle * seedA + iTime * speed)) + (0.3 + 0.2 * cos(-distortedAngle * seedB + iTime * speed)), 0.0, 1.0 ); return baseStrength * lengthFalloff * fadeFalloff * spreadFactor * pulse; } void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 coord = vec2(fragCoord.x, iResolution.y - fragCoord.y); vec2 finalRayDir = rayDir; if (mouseInfluence > 0.0) { vec2 mouseScreenPos = mousePos * iResolution.xy; vec2 mouseDirection = normalize(mouseScreenPos - rayPos); finalRayDir = normalize(mix(rayDir, mouseDirection, mouseInfluence)); } vec4 rays1 = vec4(1.0) * rayStrength(rayPos, finalRayDir, coord, 36.2214, 21.11349, 1.5 * raysSpeed); vec4 rays2 = vec4(1.0) * rayStrength(rayPos, finalRayDir, coord, 22.3991, 18.0234, 1.1 * raysSpeed); fragColor = rays1 * 0.5 + rays2 * 0.4; if (noiseAmount > 0.0) { float n = noise(coord * 0.01 + iTime * 0.1); fragColor.rgb *= (1.0 - noiseAmount + noiseAmount * n); } float brightness = 1.0 - (coord.y / iResolution.y); fragColor.x *= 0.1 + brightness * 0.8; fragColor.y *= 0.3 + brightness * 0.6; fragColor.z *= 0.5 + brightness * 0.5; if (saturation != 1.0) { float gray = dot(fragColor.rgb, vec3(0.299, 0.587, 0.114)); fragColor.rgb = mix(vec3(gray), fragColor.rgb, saturation); } fragColor.rgb *= raysColor; } void main() { vec4 color; mainImage(color, gl_FragCoord.xy); gl_FragColor = color; } `; const getAnchorAndDir = (origin, w, h) => { const outside = 0.2; switch (origin) { case 'top-left': return { anchor: [0, -outside * h], dir: [0, 1] }; case 'top-right': return { anchor: [w, -outside * h], dir: [0, 1] }; case 'left': return { anchor: [-outside * w, 0.5 * h], dir: [1, 0] }; case 'right': return { anchor: [(1 + outside) * w, 0.5 * h], dir: [-1, 0] }; case 'bottom-left': return { anchor: [0, (1 + outside) * h], dir: [0, -1] }; case 'bottom-center': return { anchor: [0.5 * w, (1 + outside) * h], dir: [0, -1] }; case 'bottom-right': return { anchor: [w, (1 + outside) * h], dir: [0, -1] }; default: // "top-center" return { anchor: [0.5 * w, -outside * h], dir: [0, 1] }; } }; export class LightRaysBackgroundComponent { constructor(ngZone) { this.ngZone = ngZone; /** 光线发射源位置。可选项: 'top-center', 'top-left', 'top-right', 'right', 'left', 'bottom-center', 'bottom-right', 'bottom-left' */ this.ncRaysOrigin = 'top-center'; /** 射线颜色,十六进制格式 */ this.ncRaysColor = '#ffffff'; /** 射线动画速度(0.1-3) */ this.ncRaysSpeed = 1; /** 光线扩散宽度(0.1-2) */ this.ncLightSpread = 1; /** 光线的最大长度/范围(0.5-3)*/ this.ncRayLength = 2; /** 启用脉动(闪烁)动画效果 */ this._pulsating = false; /** 射线从源头开始淡出的距离(0.5-2)*/ this.ncFadeDistance = 1.0; /** 颜色饱和度(0-1)*/ this.ncSaturation = 1.0; /** 让光线向鼠标光标方向旋转 */ this._followMouse = true; /** 鼠标对光线的影响程度(0-1)*/ this.ncMouseInfluence = 0.1; /** 给光线添加噪点/颗粒感(0-1)*/ this.ncNoiseAmount = 0.0; /** 对光线应用波形扭曲(0-1)*/ this.ncDistortion = 0.0; /** 背景颜色 */ this.ncBgColor = 'black'; this.renderer = null; this.material = null; this.scene = null; this.camera = null; this.rafId = null; this.resizeRafId = null; this.isVisible = true; this.running = false; this.mouse = { x: 0.5, y: 0.5 }; this.smoothMouse = { x: 0.5, y: 0.5 }; this._onVisibility = () => { if (document.hidden) { this.pause(); } else if (this.isVisible) { this.ngZone.runOutsideAngular(() => { this.start(); }); } }; this.loop = (t) => { if (!this.running) return; if (this.material && this.renderer && this.scene && this.camera) { this.material.uniforms['iTime'].value = t * 0.001; if (this.ncFollowMouse && this.ncMouseInfluence > 0.0) { const smoothing = 0.92; this.smoothMouse.x = this.smoothMouse.x * smoothing + this.mouse.x * (1 - smoothing); this.smoothMouse.y = this.smoothMouse.y * smoothing + this.mouse.y * (1 - smoothing); this.material.uniforms['mousePos'].value.set(this.smoothMouse.x, this.smoothMouse.y); } try { this.renderer.render(this.scene, this.camera); } catch (error) { console.warn('WebGL rendering error:', error); return; } } this.rafId = requestAnimationFrame(this.loop); }; } set ncPulsating(val) { this._pulsating = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncPulsating() { return this._pulsating; } set ncFollowMouse(val) { this._followMouse = val !== null && val !== undefined && val !== false && val !== 'false'; } get ncFollowMouse() { return this._followMouse; } ngOnInit() { } ngAfterViewInit() { this.ngZone.runOutsideAngular(() => { this.initWebGL(); }); } ngOnDestroy() { this.cleanup(); } ngOnChanges(changes) { if (!this.material) return; const u = this.material.uniforms; if (changes['ncRaysColor']) { u['raysColor'].value.set(this.ncRaysColor); } if (changes['ncRaysSpeed']) u['raysSpeed'].value = this.ncRaysSpeed; if (changes['ncLightSpread']) u['lightSpread'].value = this.ncLightSpread; if (changes['ncRayLength']) u['rayLength'].value = this.ncRayLength; if (changes['ncPulsating']) u['pulsating'].value = this.ncPulsating ? 1.0 : 0.0; if (changes['ncFadeDistance']) u['fadeDistance'].value = this.ncFadeDistance; if (changes['ncSaturation']) u['saturation'].value = this.ncSaturation; if (changes['ncMouseInfluence']) u['mouseInfluence'].value = this.ncMouseInfluence; if (changes['ncNoiseAmount']) u['noiseAmount'].value = this.ncNoiseAmount; if (changes['ncDistortion']) u['distortion'].value = this.ncDistortion; if (changes['ncRaysOrigin']) { this.ngZone.runOutsideAngular(() => { this.updatePlacement(); }); } } initWebGL() { const container = this.containerRef.nativeElement; this.renderer = new THREE.WebGLRenderer({ alpha: true }); this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2)); this.renderer.domElement.style.width = '100%'; this.renderer.domElement.style.height = '100%'; this.renderer.domElement.style.display = 'block'; container.appendChild(this.renderer.domElement); this.scene = new THREE.Scene(); this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); const geometry = new THREE.PlaneGeometry(2, 2); this.material = new THREE.ShaderMaterial({ vertexShader: vert, fragmentShader: frag, uniforms: { iTime: { value: 0 }, iResolution: { value: new THREE.Vector2(1, 1) }, rayPos: { value: new THREE.Vector2(0, 0) }, rayDir: { value: new THREE.Vector2(0, 1) }, raysColor: { value: new THREE.Color(this.ncRaysColor) }, raysSpeed: { value: this.ncRaysSpeed }, lightSpread: { value: this.ncLightSpread }, rayLength: { value: this.ncRayLength }, pulsating: { value: this.ncPulsating ? 1.0 : 0.0 }, fadeDistance: { value: this.ncFadeDistance }, saturation: { value: this.ncSaturation }, mousePos: { value: new THREE.Vector2(0.5, 0.5) }, mouseInfluence: { value: this.ncMouseInfluence }, noiseAmount: { value: this.ncNoiseAmount }, distortion: { value: this.ncDistortion } }, transparent: true, depthWrite: false }); const mesh = new THREE.Mesh(geometry, this.material); this.scene.add(mesh); this.setupResizeObserver(container); this.setupIntersectionObserver(container); // 初始化一次配置 this.updatePlacement(); document.addEventListener('visibilitychange', this._onVisibility); } updatePlacement() { var _a; if (!((_a = this.containerRef) === null || _a === void 0 ? void 0 : _a.nativeElement) || !this.renderer || !this.material) return; const container = this.containerRef.nativeElement; const wCSS = container.clientWidth; const hCSS = container.clientHeight; if (wCSS === 0 || hCSS === 0) return; this.renderer.setSize(wCSS, hCSS, false); // false 因为我们使用 CSS 100% 缩放 const dpr = this.renderer.getPixelRatio(); const w = wCSS * dpr; const h = hCSS * dpr; this.material.uniforms['iResolution'].value.set(w, h); const { anchor, dir } = getAnchorAndDir(this.ncRaysOrigin, w, h); this.material.uniforms['rayPos'].value.set(anchor[0], anchor[1]); this.material.uniforms['rayDir'].value.set(dir[0], dir[1]); } start() { if (this.running) return; this.running = true; this.rafId = requestAnimationFrame(this.loop); } pause() { this.running = false; if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; } } setupResizeObserver(container) { this.resizeObserver = new ResizeObserver(() => { if (!this.renderer) return; if (this.resizeRafId !== null) cancelAnimationFrame(this.resizeRafId); this.ngZone.runOutsideAngular(() => { this.resizeRafId = requestAnimationFrame(() => { this.updatePlacement(); 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; if (this.isVisible && !document.hidden) { this.ngZone.runOutsideAngular(() => { this.start(); }); } else { this.pause(); } }, { threshold: [0, 0.01, 0.1] }); this.intersectionObserver.observe(container); } cleanup() { var _a, _b; this.pause(); if (this.resizeRafId !== null) { cancelAnimationFrame(this.resizeRafId); this.resizeRafId = null; } document.removeEventListener('visibilitychange', this._onVisibility); 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.renderer) { try { const canvas = this.renderer.domElement; this.renderer.dispose(); if (canvas && canvas.parentNode) { canvas.parentNode.removeChild(canvas); } } catch (error) { console.warn('Error during WebGL cleanup:', error); } this.renderer = null; } if (this.material) { this.material.dispose(); this.material = null; } this.scene = null; this.camera = null; } onMouseMove(event) { var _a; if (!this.ncFollowMouse || !((_a = this.containerRef) === null || _a === void 0 ? void 0 : _a.nativeElement)) return; const rect = this.containerRef.nativeElement.getBoundingClientRect(); const x = (event.clientX - rect.left) / rect.width; const y = (event.clientY - rect.top) / rect.height; this.mouse = { x, y }; } } LightRaysBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: LightRaysBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); LightRaysBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: LightRaysBackgroundComponent, selector: "nc-light-rays-background", inputs: { ncRaysOrigin: "ncRaysOrigin", ncRaysColor: "ncRaysColor", ncRaysSpeed: "ncRaysSpeed", ncLightSpread: "ncLightSpread", ncRayLength: "ncRayLength", ncPulsating: "ncPulsating", ncFadeDistance: "ncFadeDistance", ncSaturation: "ncSaturation", ncFollowMouse: "ncFollowMouse", ncMouseInfluence: "ncMouseInfluence", ncNoiseAmount: "ncNoiseAmount", ncDistortion: "ncDistortion", ncBgColor: "ncBgColor" }, host: { listeners: { "mousemove": "onMouseMove($event)" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-light-rays-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-light-rays-canvas-container{position:absolute;inset:0;z-index:0;pointer-events:none}.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: LightRaysBackgroundComponent, decorators: [{ type: Component, args: [{ selector: 'nc-light-rays-background', templateUrl: './light-rays-background.component.html', styleUrls: ['./light-rays-background.component.less'] }] }], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{ type: ViewChild, args: ['container', { static: true }] }], ncRaysOrigin: [{ type: Input }], ncRaysColor: [{ type: Input }], ncRaysSpeed: [{ type: Input }], ncLightSpread: [{ type: Input }], ncRayLength: [{ type: Input }], ncPulsating: [{ type: Input }], ncFadeDistance: [{ type: Input }], ncSaturation: [{ type: Input }], ncFollowMouse: [{ type: Input }], ncMouseInfluence: [{ type: Input }], ncNoiseAmount: [{ type: Input }], ncDistortion: [{ type: Input }], ncBgColor: [{ type: Input }], onMouseMove: [{ type: HostListener, args: ['mousemove', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlnaHQtcmF5cy1iYWNrZ3JvdW5kLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvbGlnaHQtcmF5cy1iYWNrZ3JvdW5kL2xpZ2h0LXJheXMtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2xpZ2h0LXJheXMtYmFja2dyb3VuZC9saWdodC1yYXlzLWJhY2tncm91bmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFJVCxTQUFTLEVBRVQsS0FBSyxFQUdMLFlBQVksRUFFYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQzs7QUFJL0Isb0VBQW9FO0FBQ3BFLE1BQU0sSUFBSSxHQUFHOzs7Ozs7Q0FNWixDQUFDO0FBRUYsb0VBQW9FO0FBQ3BFLE1BQU0sSUFBSSxHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0E2RlosQ0FBQztBQUVGLE1BQU0sZUFBZSxHQUFHLENBQUMsTUFBYyxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsRUFBRTtJQUMvRCxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUM7SUFDcEIsUUFBUSxNQUFNLEVBQUU7UUFDZCxLQUFLLFVBQVU7WUFDYixPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3BELEtBQUssV0FBVztZQUNkLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDcEQsS0FBSyxNQUFNO1lBQ1QsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDMUQsS0FBSyxPQUFPO1lBQ1YsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNoRSxLQUFLLGFBQWE7WUFDaEIsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFELEtBQUssZUFBZTtZQUNsQixPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2hFLEtBQUssY0FBYztZQUNqQixPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDMUQsU0FBUyxlQUFlO1lBQ3RCLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQzNEO0FBQ0gsQ0FBQyxDQUFDO0FBT0YsTUFBTSxPQUFPLDRCQUE0QjtJQTJEdkMsWUFBb0IsTUFBYztRQUFkLFdBQU0sR0FBTixNQUFNLENBQVE7UUF4RGxDLDBIQUEwSDtRQUNqSCxpQkFBWSxHQUEwQixZQUFZLENBQUM7UUFDNUQsa0JBQWtCO1FBQ1QsZ0JBQVcsR0FBVyxTQUFTLENBQUM7UUFDekMsb0JBQW9CO1FBQ1gsZ0JBQVcsR0FBVyxDQUFDLENBQUM7UUFDakMsb0JBQW9CO1FBQ1gsa0JBQWEsR0FBVyxDQUFDLENBQUM7UUFDbkMsdUJBQXVCO1FBQ2QsZ0JBQVcsR0FBVyxDQUFDLENBQUM7UUFDakMsbUJBQW1CO1FBQ1gsZUFBVSxHQUFZLEtBQUssQ0FBQztRQVFwQyx5QkFBeUI7UUFDaEIsbUJBQWMsR0FBVyxHQUFHLENBQUM7UUFDdEMsZ0JBQWdCO1FBQ1AsaUJBQVksR0FBVyxHQUFHLENBQUM7UUFDcEMsbUJBQW1CO1FBQ1gsaUJBQVksR0FBWSxJQUFJLENBQUM7UUFRckMscUJBQXFCO1FBQ1oscUJBQWdCLEdBQVcsR0FBRyxDQUFDO1FBQ3hDLHNCQUFzQjtRQUNiLGtCQUFhLEdBQVcsR0FBRyxDQUFDO1FBQ3JDLG9CQUFvQjtRQUNYLGlCQUFZLEdBQVcsR0FBRyxDQUFDO1FBQ3BDLFdBQVc7UUFDRixjQUFTLEdBQVcsT0FBTyxDQUFDO1FBRTdCLGFBQVEsR0FBK0IsSUFBSSxDQUFDO1FBQzVDLGFBQVEsR0FBZ0MsSUFBSSxDQUFDO1FBQzdDLFVBQUssR0FBdUIsSUFBSSxDQUFDO1FBQ2pDLFdBQU0sR0FBb0MsSUFBSSxDQUFDO1FBSS9DLFVBQUssR0FBa0IsSUFBSSxDQUFDO1FBQzVCLGdCQUFXLEdBQWtCLElBQUksQ0FBQztRQUNsQyxjQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFFaEIsVUFBSyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDM0IsZ0JBQVcsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBNkZqQyxrQkFBYSxHQUFHLEdBQUcsRUFBRTtZQUMzQixJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUU7Z0JBQ25CLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNkO2lCQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRTtnQkFDekIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUU7b0JBQ2pDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDZixDQUFDLENBQUMsQ0FBQzthQUNKO1FBQ0gsQ0FBQyxDQUFDO1FBd0JNLFNBQUksR0FBRyxDQUFDLENBQVMsRUFBRSxFQUFFO1lBQzNCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTztnQkFBRSxPQUFPO1lBRTFCLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDL0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7Z0JBRWxELElBQUksSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsR0FBRyxFQUFFO29CQUNyRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUM7b0JBQ3ZCLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQztvQkFDckYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDO29CQUNyRixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ3RGO2dCQUVELElBQUk7b0JBQ0YsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7aUJBQy9DO2dCQUFDLE9BQU8sS0FBSyxFQUFFO29CQUNkLE9BQU8sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQzlDLE9BQU87aUJBQ1I7YUFDRjtZQUVELElBQUksQ0FBQyxLQUFLLEdBQUcscUJBQXFCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELENBQUMsQ0FBQztJQWpKb0MsQ0FBQztJQTVDdkMsSUFDSSxXQUFXLENBQUMsR0FBcUI7UUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLEtBQUssSUFBSSxHQUFHLEtBQUssT0FBTyxDQUFDO0lBQzFGLENBQUM7SUFDRCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDekIsQ0FBQztJQU9ELElBQ0ksYUFBYSxDQUFDLEdBQXFCO1FBQ3JDLElBQUksQ0FBQyxZQUFZLEdBQUcsR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsS0FBSyxLQUFLLElBQUksR0FBRyxLQUFLLE9BQU8sQ0FBQztJQUM1RixDQUFDO0lBQ0QsSUFBSSxhQUFhO1FBQ2YsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUEyQkQsUUFBUSxLQUFXLENBQUM7SUFFcEIsZUFBZTtRQUNiLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTztRQUUzQixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUNqQyxJQUFJLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRTtZQUMxQixDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDNUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxhQUFhLENBQUM7WUFBRSxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDcEUsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDO1lBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQzFFLElBQUksT0FBTyxDQUFDLGFBQWEsQ0FBQztZQUFFLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNwRSxJQUFJLE9BQU8sQ0FBQyxhQUFhLENBQUM7WUFBRSxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ2hGLElBQUksT0FBTyxDQUFDLGdCQUFnQixDQUFDO1lBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQzdFLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FBQztZQUFFLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUN2RSxJQUFJLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztZQUFFLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDbkYsSUFBSSxPQUFPLENBQUMsZUFBZSxDQUFDO1lBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQzFFLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FBQztZQUFFLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUV2RSxJQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsRUFBRTtZQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtnQkFDakMsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3pCLENBQUMsQ0FBQyxDQUFDO1NBQ0o7SUFDSCxDQUFDO0lBRU8sU0FBUztRQUNmLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDO1FBRWxELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFdkUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUM7UUFDOUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDL0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFFakQsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRWhELElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUUvRCxNQUFNLFFBQVEsR0FBRyxJQUFJLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRS9DLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxLQUFLLENBQUMsY0FBYyxDQUFDO1lBQ3ZDLFlBQVksRUFBRSxJQUFJO1lBQ2xCLGNBQWMsRUFBRSxJQUFJO1lBQ3BCLFFBQVEsRUFBRTtnQkFDUixLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFO2dCQUNuQixXQUFXLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtnQkFDL0MsTUFBTSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUU7Z0JBQzFDLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO2dCQUMxQyxTQUFTLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRTtnQkFDdkQsU0FBUyxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUU7Z0JBQ3RDLFdBQVcsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUMxQyxTQUFTLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRTtnQkFDdEMsU0FBUyxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFO2dCQUNsRCxZQUFZLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLGNBQWMsRUFBRTtnQkFDNUMsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQ3hDLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFO2dCQUNoRCxjQUFjLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixFQUFFO2dCQUNoRCxXQUFXLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDMUMsVUFBVSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUU7YUFDekM7WUFDRCxXQUFXLEVBQUUsSUFBSTtZQUNqQixVQUFVLEVBQUUsS0FBSztTQUNsQixDQUFDLENBQUM7UUFFSCxNQUFNLElBQUksR0FBRyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyQixJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRTFDLFVBQVU7UUFDVixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFFdkIsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBWU8sZUFBZTs7UUFDckIsSUFBSSxDQUFDLENBQUEsTUFBQSxJQUFJLENBQUMsWUFBWSwwQ0FBRSxhQUFhLENBQUEsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFFbEYsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUM7UUFDbEQsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLFdBQVcsQ0FBQztRQUNuQyxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDO1FBRXBDLElBQUksSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQztZQUFFLE9BQU87UUFFckMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLDJCQUEyQjtRQUVyRSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzFDLE1BQU0sQ0FBQyxHQUFHLElBQUksR0FBRyxHQUFHLENBQUM7UUFDckIsTUFBTSxDQUFDLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUVyQixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUV0RCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNqRSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBMEJPLEtBQUs7UUFDWCxJQUFJLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTztRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsS0FBSyxHQUFHLHFCQUFxQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRU8sS0FBSztRQUNYLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQ3JCLElBQUksSUFBSSxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUU7WUFDdkIsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1NBQ25CO0lBQ0gsQ0FBQztJQUVPLG1CQUFtQixDQUFDLFNBQXNCO1FBQ2hELElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQUMsR0FBRyxFQUFFO1lBQzVDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPO1lBQzNCLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxJQUFJO2dCQUFFLG9CQUFvQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN0RSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtnQkFDakMsSUFBSSxDQUFDLFdBQVcsR0FBRyxxQkFBcUIsQ0FBQyxHQUFHLEVBQUU7b0JBQzVDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQkFDdkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7Z0JBQzFCLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFTyx5QkFBeUIsQ0FBQyxTQUFzQjtRQUN0RCxJQUFJLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUM3RCxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDekIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsY0FBYyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7WUFFckUsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRTtnQkFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUU7b0JBQ2pDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDZixDQUFDLENBQUMsQ0FBQzthQUNKO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNkO1FBQ0gsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRU8sT0FBTzs7UUFDYixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDYixJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssSUFBSSxFQUFFO1lBQzdCLG9CQUFvQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN2QyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztTQUN6QjtRQUVELFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxrQkFBa0IsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFckUsSUFBSTtZQUFFLE1BQUEsSUFBSSxDQUFDLGNBQWMsMENBQUUsVUFBVSxFQUFFLENBQUM7U0FBRTtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQUUsS0FBSyxDQUFDLENBQUM7U0FBRTtRQUNoRSxJQUFJO1lBQUUsTUFBQSxJQUFJLENBQUMsb0JBQW9CLDBDQUFFLFVBQVUsRUFBRSxDQUFDO1NBQUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUFFLEtBQUssQ0FBQyxDQUFDO1NBQUU7UUFFdEUsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLElBQUk7Z0JBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBRXhCLElBQUksTUFBTSxJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUU7b0JBQy9CLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2lCQUN2QzthQUNGO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsT0FBTyxDQUFDLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUNwRDtZQUNELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1NBQ3RCO1FBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2pCLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7U0FDdEI7UUFDRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztRQUNsQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztJQUNyQixDQUFDO0lBR0QsV0FBVyxDQUFDLEtBQWlCOztRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxDQUFDLENBQUEsTUFBQSxJQUFJLENBQUMsWUFBWSwwQ0FBRSxhQUFhLENBQUE7WUFBRSxPQUFPO1FBQ3JFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDckUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ25ELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNuRCxJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7O3lIQW5TVSw0QkFBNEI7NkdBQTVCLDRCQUE0QixpcUJDckp6Qyx5TEFHTTsyRkRrSk8sNEJBQTRCO2tCQUx4QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSwwQkFBMEI7b0JBQ3BDLFdBQVcsRUFBRSx3Q0FBd0M7b0JBQ3JELFNBQVMsRUFBRSxDQUFDLHdDQUF3QyxDQUFDO2lCQUN0RDs2RkFFMkMsWUFBWTtzQkFBckQsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUcvQixZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBSUYsV0FBVztzQkFEZCxLQUFLO2dCQVFHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsWUFBWTtzQkFBcEIsS0FBSztnQkFJRixhQUFhO3NCQURoQixLQUFLO2dCQVFHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFtUE4sV0FBVztzQkFEVixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uSW5pdCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBWaWV3Q2hpbGQsXHJcbiAgRWxlbWVudFJlZixcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgU2ltcGxlQ2hhbmdlcyxcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgTmdab25lXHJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcclxuXHJcbmV4cG9ydCB0eXBlIE5jTGlnaHRSYXlzT3JpZ2luVHlwZSA9ICd0b3AtbGVmdCcgfCAndG9wLWNlbnRlcicgfCAndG9wLXJpZ2h0JyB8ICdsZWZ0JyB8ICdyaWdodCcgfCAnYm90dG9tLWxlZnQnIHwgJ2JvdHRvbS1jZW50ZXInIHwgJ2JvdHRvbS1yaWdodCc7XHJcblxyXG4vLyDilIDilIDilIAg6aG254K5552A6Imy5ZmoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5jb25zdCB2ZXJ0ID0gYFxyXG52YXJ5aW5nIHZlYzIgdlV2O1xyXG52b2lkIG1haW4oKSB7XHJcbiAgdlV2ID0gdXY7XHJcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uLCAxLjApO1xyXG59XHJcbmA7XHJcblxyXG4vLyDilIDilIDilIAg54mH5YWD552A6Imy5ZmoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5jb25zdCBmcmFnID0gYHByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuXHJcbnVuaWZvcm0gZmxvYXQgaVRpbWU7XHJcbnVuaWZvcm0gdmVjMiAgaVJlc29sdXRpb247XHJcblxyXG51bmlmb3JtIHZlYzIgIHJheVBvcztcclxudW5pZm9ybSB2ZWMyICByYXlEaXI7XHJcbnVuaWZvcm0gdmVjMyAgcmF5c0NvbG9yO1xyXG51bmlmb3JtIGZsb2F0IHJheXNTcGVlZDtcclxudW5pZm9ybSBmbG9hdCBsaWdodFNwcmVhZDtcclxudW5pZm9ybSBmbG9hdCByYXlMZW5ndGg7XHJcbnVuaWZvcm0gZmxvYXQgcHVsc2F0aW5nO1xyXG51bmlmb3JtIGZsb2F0IGZhZGVEaXN0YW5jZTtcclxudW5pZm9ybSBmbG9hdCBzYXR1cmF0aW9uO1xyXG51bmlmb3JtIHZlYzIgIG1vdXNlUG9zO1xyXG51bmlmb3JtIGZsb2F0IG1vdXNlSW5mbHVlbmNlO1xyXG51bmlmb3JtIGZsb2F0IG5vaXNlQW1vdW50O1xyXG51bmlmb3JtIGZsb2F0IGRpc3RvcnRpb247XHJcblxyXG52YXJ5aW5nIHZlYzIgdlV2O1xyXG5cclxuZmxvYXQgbm9pc2UodmVjMiBzdCkge1xyXG4gIHJldHVybiBmcmFjdChzaW4oZG90KHN0Lnh5LCB2ZWMyKDEyLjk4OTgsNzguMjMzKSkpICogNDM3NTguNTQ1MzEyMyk7XHJcbn1cclxuXHJcbmZsb2F0IHJheVN0cmVuZ3RoKHZlYzIgcmF5U291cmNlLCB2ZWMyIHJheVJlZkRpcmVjdGlvbiwgdmVjMiBjb29yZCxcclxuICAgICAgICAgICAgICAgICAgZmxvYXQgc2VlZEEsIGZsb2F0IHNlZWRCLCBmbG9hdCBzcGVlZCkge1xyXG4gIHZlYzIgc291cmNlVG9Db29yZCA9IGNvb3JkIC0gcmF5U291cmNlO1xyXG4gIHZlYzIgZGlyTm9ybSA9IG5vcm1hbGl6ZShzb3VyY2VUb0Nvb3JkKTtcclxuICBmbG9hdCBjb3NBbmdsZSA9IGRvdChkaXJOb3JtLCByYXlSZWZEaXJlY3Rpb24pO1xyXG5cclxuICBmbG9hdCBkaXN0b3J0ZWRBbmdsZSA9IGNvc0FuZ2xlICsgZGlzdG9ydGlvbiAqIHNpbihpVGltZSAqIDIuMCArIGxlbmd0aChzb3VyY2VUb0Nvb3JkKSAqIDAuMDEpICogMC4yO1xyXG4gIFxyXG4gIGZsb2F0IHNwcmVhZEZhY3RvciA9IHBvdyhtYXgoZGlzdG9ydGVkQW5nbGUsIDAuMCksIDEuMCAvIG1heChsaWdodFNwcmVhZCwgMC4wMDEpKTtcclxuXHJcbiAgZmxvYXQgZGlzdGFuY2UgPSBsZW5ndGgoc291cmNlVG9Db29yZCk7XHJcbiAgZmxvYXQgbWF4RGlzdGFuY2UgPSBpUmVzb2x1dGlvbi54ICogcmF5TGVuZ3RoO1xyXG4gIGZsb2F0IGxlbmd0aEZhbGxvZmYgPSBjbGFtcCgobWF4RGlzdGFuY2UgLSBkaXN0YW5jZSkgLyBtYXhEaXN0YW5jZSwgMC4wLCAxLjApO1xyXG4gIFxyXG4gIGZsb2F0IGZhZGVGYWxsb2ZmID0gY2xhbXAoKGlSZXNvbHV0aW9uLnggKiBmYWRlRGlzdGFuY2UgLSBkaXN0YW5jZSkgLyAoaVJlc29sdXRpb24ueCAqIGZhZGVEaXN0YW5jZSksIDAuNSwgMS4wKTtcclxuICBmbG9hdCBwdWxzZSA9IHB1bHNhdGluZyA+IDAuNSA/ICgwLjggKyAwLjIgKiBzaW4oaVRpbWUgKiBzcGVlZCAqIDMuMCkpIDogMS4wO1xyXG5cclxuICBmbG9hdCBiYXNlU3RyZW5ndGggPSBjbGFtcChcclxuICAgICgwLjQ1ICsgMC4xNSAqIHNpbihkaXN0b3J0ZWRBbmdsZSAqIHNlZWRBICsgaVRpbWUgKiBzcGVlZCkpICtcclxuICAgICgwLjMgKyAwLjIgKiBjb3MoLWRpc3RvcnRlZEFuZ2xlICogc2VlZEIgKyBpVGltZSAqIHNwZWVkKSksXHJcbiAgICAwLjAsIDEuMFxyXG4gICk7XHJcblxyXG4gIHJldHVybiBiYXNlU3RyZW5ndGggKiBsZW5ndGhGYWxsb2ZmICogZmFkZUZhbGxvZmYgKiBzcHJlYWRGYWN0b3IgKiBwdWxzZTtcclxufVxyXG5cclxudm9pZCBtYWluSW1hZ2Uob3V0IHZlYzQgZnJhZ0NvbG9yLCBpbiB2ZWMyIGZyYWdDb29yZCkge1xyXG4gIHZlYzIgY29vcmQgPSB2ZWMyKGZyYWdDb29yZC54LCBpUmVzb2x1dGlvbi55IC0gZnJhZ0Nvb3JkLnkpO1xyXG4gIFxyXG4gIHZlYzIgZmluYWxSYXlEaXIgPSByYXlEaXI7XHJcbiAgaWYgKG1vdXNlSW5mbHVlbmNlID4gMC4wKSB7XHJcbiAgICB2ZWMyIG1vdXNlU2NyZWVuUG9zID0gbW91c2VQb3MgKiBpUmVzb2x1dGlvbi54eTtcclxuICAgIHZlYzIgbW91c2VEaXJlY3Rpb24gPSBub3JtYWxpemUobW91c2VTY3JlZW5Qb3MgLSByYXlQb3MpO1xyXG4gICAgZmluYWxSYXlEaXIgPSBub3JtYWxpemUobWl4KHJheURpciwgbW91c2VEaXJlY3Rpb24sIG1vdXNlSW5mbHVlbmNlKSk7XHJcbiAgfVxyXG5cclxuICB2ZWM0IHJheXMxID0gdmVjNCgxLjApICpcclxuICAgICAgICAgICAgICAgcmF5U3RyZW5ndGgocmF5UG9zLCBmaW5hbFJheURpciwgY29vcmQsIDM2LjIyMTQsIDIxLjExMzQ5LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAxLjUgKiByYXlzU3BlZWQpO1xyXG4gIHZlYzQgcmF5czIgPSB2ZWM0KDEuMCkgKlxyXG4gICAgICAgICAgICAgICByYXlTdHJlbmd0aChyYXlQb3MsIGZpbmFsUmF5RGlyLCBjb29yZCwgMjIuMzk5MSwgMTguMDIzNCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgMS4xICogcmF5c1NwZWVkKTtcclxuXHJcbiAgZnJhZ0NvbG9yID0gcmF5czEgKiAwLjUgKyByYXlzMiAqIDAuNDtcclxuXHJcbiAgaWYgKG5vaXNlQW1vdW50ID4gMC4wKSB7XHJcbiAgICBmbG9hdCBuID0gbm9pc2UoY29vcmQgKiAwLjAxICsgaVRpbWUgKiAwLjEpO1xyXG4gICAgZnJhZ0NvbG9yLnJnYiAqPSAoMS4wIC0gbm9pc2VBbW91bnQgKyBub2lzZUFtb3VudCAqIG4pO1xyXG4gIH1cclxuXHJcbiAgZmxvYXQgYnJpZ2h0bmVzcyA9IDEuMCAtIChjb29yZC55IC8gaVJlc29sdXRpb24ueSk7XHJcbiAgZnJhZ0NvbG9yLnggKj0gMC4xICsgYnJpZ2h0bmVzcyAqIDAuODtcclxuICBmcmFnQ29sb3IueSAqPSAwLjMgKyBicmlnaHRuZXNzICogMC42O1xyXG4gIGZyYWdDb2xvci56ICo9IDAuNSArIGJyaWdodG5lc3MgKiAwLjU7XHJcblxyXG4gIGlmIChzYXR1cmF0aW9uICE9IDEuMCkge1xyXG4gICAgZmxvYXQgZ3JheSA9IGRvdChmcmFnQ29sb3IucmdiLCB2ZWMzKDAuMjk5LCAwLjU4NywgMC4xMTQpKTtcclxuICAgIGZyYWdDb2xvci5yZ2IgPSBtaXgodmVjMyhncmF5KSwgZnJhZ0NvbG9yLnJnYiwgc2F0dXJhdGlvbik7XHJcbiAgfVxyXG5cclxuICBmcmFnQ29sb3IucmdiICo9IHJheXNDb2xvcjtcclxufVxyXG5cclxudm9pZCBtYWluKCkge1xyXG4gIHZlYzQgY29sb3I7XHJcbiAgbWFpbkltYWdlKGNvbG9yLCBnbF9GcmFnQ29vcmQueHkpO1xyXG4gIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xyXG59XHJcbmA7XHJcblxyXG5jb25zdCBnZXRBbmNob3JBbmREaXIgPSAob3JpZ2luOiBzdHJpbmcsIHc6IG51bWJlciwgaDogbnVtYmVyKSA9PiB7XHJcbiAgY29uc3Qgb3V0c2lkZSA9IDAuMjtcclxuICBzd2l0Y2ggKG9yaWdpbikge1xyXG4gICAgY2FzZSAndG9wLWxlZnQnOlxyXG4gICAgICByZXR1cm4geyBhbmNob3I6IFswLCAtb3V0c2lkZSAqIGhdLCBkaXI6IFswLCAxXSB9O1xyXG4gICAgY2FzZSAndG9wLXJpZ2h0JzpcclxuICAgICAgcmV0dXJuIHsgYW5jaG9yOiBbdywgLW91dHNpZGUgKiBoXSwgZGlyOiBbMCwgMV0gfTtcclxuICAgIGNhc2UgJ2xlZnQnOlxyXG4gICAgICByZXR1cm4geyBhbmNob3I6IFstb3V0c2lkZSAqIHcsIDAuNSAqIGhdLCBkaXI6IFsxLCAwXSB9O1xyXG4gICAgY2FzZSAncmlnaHQnOlxyXG4gICAgICByZXR1cm4geyBhbmNob3I6IFsoMSArIG91dHNpZGUpICogdywgMC41ICogaF0sIGRpcjogWy0xLCAwXSB9O1xyXG4gICAgY2FzZSAnYm90dG9tLWxlZnQnOlxyXG4gICAgICByZXR1cm4geyBhbmNob3I6IFswLCAoMSArIG91dHNpZGUpICogaF0sIGRpcjogWzAsIC0xXSB9O1xyXG4gICAgY2FzZSAnYm90dG9tLWNlbnRlcic6XHJcbiAgICAgIHJldHVybiB7IGFuY2hvcjogWzAuNSAqIHcsICgxICsgb3V0c2lkZSkgKiBoXSwgZGlyOiBbMCwgLTFdIH07XHJcbiAgICBjYXNlICdib3R0b20tcmlnaHQnOlxyXG4gICAgICByZXR1cm4geyBhbmNob3I6IFt3LCAoMSArIG91dHNpZGUpICogaF0sIGRpcjogWzAsIC0xXSB9O1xyXG4gICAgZGVmYXVsdDogLy8gXCJ0b3AtY2VudGVyXCJcclxuICAgICAgcmV0dXJuIHsgYW5jaG9yOiBbMC41ICogdywgLW91dHNpZGUgKiBoXSwgZGlyOiBbMCwgMV0gfTtcclxuICB9XHJcbn07XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25jLWxpZ2h0LXJheXMtYmFja2dyb3VuZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2xpZ2h0LXJheXMtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vbGlnaHQtcmF5cy1iYWNrZ3JvdW5kLmNvbXBvbmVudC5sZXNzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIExpZ2h0UmF5c0JhY2tncm91bmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzIHtcclxuICBAVmlld0NoaWxkKCdjb250YWluZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSBjb250YWluZXJSZWYhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcclxuXHJcbiAgLyoqIOWFiee6v+WPkeWwhOa6kOS9jee9ruOAguWPr+mAiemhuTogJ3RvcC1jZW50ZXInLCAndG9wLWxlZnQnLCAndG9wLXJpZ2h0JywgJ3JpZ2h0JywgJ2xlZnQnLCAnYm90dG9tLWNlbnRlcicsICdib3R0b20tcmlnaHQnLCAnYm90dG9tLWxlZnQnICovXHJcbiAgQElucHV0KCkgbmNSYXlzT3JpZ2luOiBOY0xpZ2h0UmF5c09yaWdpblR5cGUgPSAndG9wLWNlbnRlcic7XHJcbiAgLyoqIOWwhOe6v+minOiJsu+8jOWNgeWFrei/m+WItuagvOW8jyAqL1xyXG4gIEBJbnB1dCgpIG5jUmF5c0NvbG9yOiBzdHJpbmcgPSAnI2ZmZmZmZic7XHJcbiAgLyoqIOWwhOe6v+WKqOeUu+mAn+W6pu+8iDAuMS0z77yJICovXHJcbiAgQElucHV0KCkgbmNSYXlzU3BlZWQ6IG51bWJlciA9IDE7XHJcbiAgLyoqIOWFiee6v+aJqeaVo+WuveW6pu+8iDAuMS0y77yJICovXHJcbiAgQElucHV0KCkgbmNMaWdodFNwcmVhZDogbnVtYmVyID0gMTtcclxuICAvKiog5YWJ57q/55qE5pyA5aSn6ZW/5bqmL+iMg+WbtO+8iDAuNS0z77yJKi9cclxuICBASW5wdXQoKSBuY1JheUxlbmd0aDogbnVtYmVyID0gMjtcclxuICAvKiog5ZCv55So6ISJ5Yqo77yI6Zeq54OB77yJ5Yqo55S75pWI5p6cICovXHJcbiAgcHJpdmF0ZSBfcHVsc2F0aW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KClcclxuICBzZXQgbmNQdWxzYXRpbmcodmFsOiBib29sZWFuIHwgc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9wdWxzYXRpbmcgPSB2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBmYWxzZSAmJiB2YWwgIT09ICdmYWxzZSc7XHJcbiAgfVxyXG4gIGdldCBuY1B1bHNhdGluZygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9wdWxzYXRpbmc7XHJcbiAgfVxyXG4gIC8qKiDlsITnur/ku47mupDlpLTlvIDlp4vmt6Hlh7rnmoTot53nprvvvIgwLjUtMu+8iSovXHJcbiAgQElucHV0KCkgbmNGYWRlRGlzdGFuY2U6IG51bWJlciA9IDEuMDtcclxuICAvKiog6aKc6Imy6aWx5ZKM5bqm77yIMC0x77yJKi9cclxuICBASW5wdXQoKSBuY1NhdHVyYXRpb246IG51bWJlciA9IDEuMDtcclxuICAvKiog6K6p5YWJ57q/5ZCR6byg5qCH5YWJ5qCH5pa55ZCR5peL6L2sICovXHJcbiAgcHJpdmF0ZSBfZm9sbG93TW91c2U6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IG5jRm9sbG93TW91c2UodmFsOiBib29sZWFuIHwgc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9mb2xsb3dNb3VzZSA9IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09IGZhbHNlICYmIHZhbCAhPT0gJ2ZhbHNlJztcclxuICB9XHJcbiAgZ2V0IG5jRm9sbG93TW91c2UoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5fZm9sbG93TW91c2U7XHJcbiAgfVxyXG4gIC8qKiDpvKDmoIflr7nlhYnnur/nmoTlvbHlk43nqIvluqbvvIgwLTHvvIkqL1xyXG4gIEBJbnB1dCgpIG5jTW91c2VJbmZsdWVuY2U6IG51bWJlciA9IDAuMTtcclxuICAvKiog57uZ5YWJ57q/5re75Yqg5Zmq54K5L+mil+eykuaEn++8iDAtMe+8iSovXHJcbiAgQElucHV0KCkgbmNOb2lzZUFtb3VudDogbnVtYmVyID0gMC4wO1xyXG4gIC8qKiDlr7nlhYnnur/lupTnlKjms6LlvaLmia3mm7LvvIgwLTHvvIkqL1xyXG4gIEBJbnB1dCgpIG5jRGlzdG9ydGlvbjogbnVtYmVyID0gMC4wO1xyXG4gIC8qKiDog4zmma/popzoibIgKi9cclxuICBASW5wdXQoKSBuY0JnQ29sb3I6IHN0cmluZyA9ICdibGFjayc7XHJcblxyXG4gIHByaXZhdGUgcmVuZGVyZXI6IFRIUkVFLldlYkdMUmVuZGVyZXIgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIG1hdGVyaWFsOiBUSFJFRS5TaGFkZXJNYXRlcmlhbCB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgc2NlbmU6IFRIUkVFLlNjZW5lIHwgbnVsbCA9IG51bGw7XHJcbiAgcHJpdmF0ZSBjYW1lcmE6IFRIUkVFLk9ydGhvZ3JhcGhpY0NhbWVyYSB8IG51bGwgPSBudWxsO1xyXG5cclxuICBwcml2YXRlIHJlc2l6ZU9ic2VydmVyITogUmVzaXplT2JzZXJ2ZXI7XHJcbiAgcHJpdmF0ZSBpbnRlcnNlY3Rpb25PYnNlcnZlciE6IEludGVyc2VjdGlvbk9ic2VydmVyO1xyXG4gIHByaXZhdGUgcmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVzaXplUmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgaXNWaXNpYmxlID0gdHJ1ZTtcclxuICBwcml2YXRlIHJ1bm5pbmcgPSBmYWxzZTtcclxuXHJcbiAgcHJpdmF0ZSBtb3VzZSA9IHsgeDogMC41LCB5OiAwLjUgfTtcclxuICBwcml2YXRlIHNtb290aE1vdXNlID0geyB4OiAwLjUsIHk6IDAuNSB9O1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5nWm9uZTogTmdab25lKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7IH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICB0aGlzLmluaXRXZWJHTCgpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xlYW51cCgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLm1hdGVyaWFsKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgdSA9IHRoaXMubWF0ZXJpYWwudW5pZm9ybXM7XHJcbiAgICBpZiAoY2hhbmdlc1snbmNSYXlzQ29sb3InXSkge1xyXG4gICAgICB1WydyYXlzQ29sb3InXS52YWx1ZS5zZXQodGhpcy5uY1JheXNDb2xvcik7XHJcbiAgICB9XHJcbiAgICBpZiAoY2hhbmdlc1snbmNSYXlzU3BlZWQnXSkgdVsncmF5c1NwZWVkJ10udmFsdWUgPSB0aGlzLm5jUmF5c1NwZWVkO1xyXG4gICAgaWYgKGNoYW5nZXNbJ25jTGlnaHRTcHJlYWQnXSkgdVsnbGlnaHRTcHJlYWQnXS52YWx1ZSA9IHRoaXMubmNMaWdodFNwcmVhZDtcclxuICAgIGlmIChjaGFuZ2VzWyduY1JheUxlbmd0aCddKSB1WydyYXlMZW5ndGgnXS52YWx1ZSA9IHRoaXMubmNSYXlMZW5ndGg7XHJcbiAgICBpZiAoY2hhbmdlc1snbmNQdWxzYXRpbmcnXSkgdVsncHVsc2F0aW5nJ10udmFsdWUgPSB0aGlzLm5jUHVsc2F0aW5nID8gMS4wIDogMC4wO1xyXG4gICAgaWYgKGNoYW5nZXNbJ25jRmFkZURpc3RhbmNlJ10pIHVbJ2ZhZGVEaXN0YW5jZSddLnZhbHVlID0gdGhpcy5uY0ZhZGVEaXN0YW5jZTtcclxuICAgIGlmIChjaGFuZ2VzWyduY1NhdHVyYXRpb24nXSkgdVsnc2F0dXJhdGlvbiddLnZhbHVlID0gdGhpcy5uY1NhdHVyYXRpb247XHJcbiAgICBpZiAoY2hhbmdlc1snbmNNb3VzZUluZmx1ZW5jZSddKSB1Wydtb3VzZUluZmx1ZW5jZSddLnZhbHVlID0gdGhpcy5uY01vdXNlSW5mbHVlbmNlO1xyXG4gICAgaWYgKGNoYW5nZXNbJ25jTm9pc2VBbW91bnQnXSkgdVsnbm9pc2VBbW91bnQnXS52YWx1ZSA9IHRoaXMubmNOb2lzZUFtb3VudDtcclxuICAgIGlmIChjaGFuZ2VzWyduY0Rpc3RvcnRpb24nXSkgdVsnZGlzdG9ydGlvbiddLnZhbHVlID0gdGhpcy5uY0Rpc3RvcnRpb247XHJcblxyXG4gICAgaWYgKGNoYW5nZXNbJ25jUmF5c09yaWdpbiddKSB7XHJcbiAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgICB0aGlzLnVwZGF0ZVBsYWNlbWVudCgpO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgaW5pdFdlYkdMKCk6IHZvaWQge1xyXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoeyBhbHBoYTogdHJ1ZSB9KTtcclxuICAgIHRoaXMucmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyhNYXRoLm1pbih3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxLCAyKSk7XHJcblxyXG4gICAgdGhpcy5yZW5kZXJlci5kb21FbGVtZW50LnN0eWxlLndpZHRoID0gJzEwMCUnO1xyXG4gICAgdGhpcy5yZW5kZXJlci5kb21FbGVtZW50LnN0eWxlLmhlaWdodCA9ICcxMDAlJztcclxuICAgIHRoaXMucmVuZGVyZXIuZG9tRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcclxuXHJcbiAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5yZW5kZXJlci5kb21FbGVtZW50KTtcclxuXHJcbiAgICB0aGlzLnNjZW5lID0gbmV3IFRIUkVFLlNjZW5lKCk7XHJcbiAgICB0aGlzLmNhbWVyYSA9IG5ldyBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmEoLTEsIDEsIDEsIC0xLCAwLCAxKTtcclxuXHJcbiAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBUSFJFRS5QbGFuZUdlb21ldHJ5KDIsIDIpO1xyXG5cclxuICAgIHRoaXMubWF0ZXJpYWwgPSBuZXcgVEhSRUUuU2hhZGVyTWF0ZXJpYWwoe1xyXG4gICAgICB2ZXJ0ZXhTaGFkZXI6IHZlcnQsXHJcbiAgICAgIGZyYWdtZW50U2hhZGVyOiBmcmFnLFxyXG4gICAgICB1bmlmb3Jtczoge1xyXG4gICAgICAgIGlUaW1lOiB7IHZhbHVlOiAwIH0sXHJcbiAgICAgICAgaVJlc29sdXRpb246IHsgdmFsdWU6IG5ldyBUSFJFRS5WZWN0b3IyKDEsIDEpIH0sXHJcbiAgICAgICAgcmF5UG9zOiB7IHZhbHVlOiBuZXcgVEhSRUUuVmVjdG9yMigwLCAwKSB9LFxyXG4gICAgICAgIHJheURpcjogeyB2YWx1ZTogbmV3IFRIUkVFLlZlY3RvcjIoMCwgMSkgfSxcclxuICAgICAgICByYXlzQ29sb3I6IHsgdmFsdWU6IG5ldyBUSFJFRS5Db2xvcih0aGlzLm5jUmF5c0NvbG9yKSB9LFxyXG4gICAgICAgIHJheXNTcGVlZDogeyB2YWx1ZTogdGhpcy5uY1JheXNTcGVlZCB9LFxyXG4gICAgICAgIGxpZ2h0U3ByZWFkOiB7IHZhbHVlOiB0aGlzLm5jTGlnaHRTcHJlYWQgfSxcclxuICAgICAgICByYXlMZW5ndGg6IHsgdmFsdWU6IHRoaXMubmNSYXlMZW5ndGggfSxcclxuICAgICAgICBwdWxzYXRpbmc6IHsgdmFsdWU6IHRoaXMubmNQdWxzYXRpbmcgPyAxLjAgOiAwLjAgfSxcclxuICAgICAgICBmYWRlRGlzdGFuY2U6IHsgdmFsdWU6IHRoaXMubmNGYWRlRGlzdGFuY2UgfSxcclxuICAgICAgICBzYXR1cmF0aW9uOiB7IHZhbHVlOiB0aGlzLm5jU2F0dXJhdGlvbiB9LFxyXG4gICAgICAgIG1vdXNlUG9zOiB7IHZhbHVlOiBuZXcgVEhSRUUuVmVjdG9yMigwLjUsIDAuNSkgfSxcclxuICAgICAgICBtb3VzZUluZmx1ZW5jZTogeyB2YWx1ZTogdGhpcy5uY01vdXNlSW5mbHVlbmNlIH0sXHJcbiAgICAgICAgbm9pc2VBbW91bnQ6IHsgdmFsdWU6IHRoaXMubmNOb2lzZUFtb3VudCB9LFxyXG4gICAgICAgIGRpc3RvcnRpb246IHsgdmFsdWU6IHRoaXMubmNEaXN0b3J0aW9uIH1cclxuICAgICAgfSxcclxuICAgICAgdHJhbnNwYXJlbnQ6IHRydWUsXHJcbiAgICAgIGRlcHRoV3JpdGU6IGZhbHNlXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBtZXNoID0gbmV3IFRIUkVFLk1lc2goZ2VvbWV0cnksIHRoaXMubWF0ZXJpYWwpO1xyXG4gICAgdGhpcy5zY2VuZS5hZGQobWVzaCk7XHJcblxyXG4gICAgdGhpcy5zZXR1cFJlc2l6ZU9ic2VydmVyKGNvbnRhaW5lcik7XHJcbiAgICB0aGlzLnNldHVwSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoY29udGFpbmVyKTtcclxuXHJcbiAgICAvLyDliJ3lp4vljJbkuIDmrKHphY3nva5cclxuICAgIHRoaXMudXBkYXRlUGxhY2VtZW50KCk7XHJcblxyXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndmlzaWJpbGl0eWNoYW5nZScsIHRoaXMuX29uVmlzaWJpbGl0eSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9vblZpc2liaWxpdHkgPSAoKSA9PiB7XHJcbiAgICBpZiAoZG9jdW1lbnQuaGlkZGVuKSB7XHJcbiAgICAgIHRoaXMucGF1c2UoKTtcc