ng-cw-v12
Version:
Angular UI Component Library
517 lines (480 loc) • 68.4 kB
JavaScript
import { Component, ViewChild, Input, HostListener } from '@angular/core';
import { Scene, OrthographicCamera, WebGLRenderer, PlaneGeometry, Mesh, ShaderMaterial, Vector3, Vector2, Clock } from 'three';
import * as i0 from "@angular/core";
const vertexShader = `
precision highp float;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
precision highp float;
uniform float iTime;
uniform vec3 iResolution;
uniform float animationSpeed;
uniform bool enableTop;
uniform bool enableMiddle;
uniform bool enableBottom;
uniform int topLineCount;
uniform int middleLineCount;
uniform int bottomLineCount;
uniform float topLineDistance;
uniform float middleLineDistance;
uniform float bottomLineDistance;
uniform vec3 topWavePosition;
uniform vec3 middleWavePosition;
uniform vec3 bottomWavePosition;
uniform vec2 iMouse;
uniform bool interactive;
uniform float bendRadius;
uniform float bendStrength;
uniform float bendInfluence;
uniform bool parallax;
uniform float parallaxStrength;
uniform vec2 parallaxOffset;
uniform vec3 lineGradient[8];
uniform int lineGradientCount;
const vec3 BLACK = vec3(0.0);
const vec3 PINK = vec3(233.0, 71.0, 245.0) / 255.0;
const vec3 BLUE = vec3(47.0, 75.0, 162.0) / 255.0;
mat2 rotate(float r) {
return mat2(cos(r), sin(r), -sin(r), cos(r));
}
vec3 background_color(vec2 uv) {
vec3 col = vec3(0.0);
float y = sin(uv.x - 0.2) * 0.3 - 0.1;
float m = uv.y - y;
col += mix(BLUE, BLACK, smoothstep(0.0, 1.0, abs(m)));
col += mix(PINK, BLACK, smoothstep(0.0, 1.0, abs(m - 0.8)));
return col * 0.5;
}
vec3 getLineColor(float t, vec3 baseColor) {
if (lineGradientCount <= 0) {
return baseColor;
}
vec3 gradientColor;
if (lineGradientCount == 1) {
gradientColor = lineGradient[0];
} else {
float clampedT = clamp(t, 0.0, 0.9999);
float scaled = clampedT * float(lineGradientCount - 1);
int idx = int(floor(scaled));
float f = fract(scaled);
int idx2 = min(idx + 1, lineGradientCount - 1);
vec3 c1 = lineGradient[idx];
vec3 c2 = lineGradient[idx2];
gradientColor = mix(c1, c2, f);
}
return gradientColor * 0.5;
}
float wave(vec2 uv, float offset, vec2 screenUv, vec2 mouseUv, bool shouldBend) {
float time = iTime * animationSpeed;
float x_offset = offset;
float x_movement = time * 0.1;
float amp = sin(offset + time * 0.2) * 0.3;
float y = sin(uv.x + x_offset + x_movement) * amp;
if (shouldBend) {
vec2 d = screenUv - mouseUv;
float influence = exp(-dot(d, d) * bendRadius); // radial falloff around cursor
float bendOffset = (mouseUv.y - screenUv.y) * influence * bendStrength * bendInfluence;
y += bendOffset;
}
float m = uv.y - y;
return 0.0175 / max(abs(m) + 0.01, 1e-3) + 0.01;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 baseUv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;
baseUv.y *= -1.0;
if (parallax) {
baseUv += parallaxOffset;
}
vec3 col = vec3(0.0);
vec3 b = lineGradientCount > 0 ? vec3(0.0) : background_color(baseUv);
vec2 mouseUv = vec2(0.0);
if (interactive) {
mouseUv = (2.0 * iMouse - iResolution.xy) / iResolution.y;
mouseUv.y *= -1.0;
}
if (enableBottom) {
for (int i = 0; i < 20; ++i) { // Fixed limit for Loop
if(i >= bottomLineCount) break;
float fi = float(i);
float t = fi / max(float(bottomLineCount - 1), 1.0);
vec3 lineCol = getLineColor(t, b);
float angle = bottomWavePosition.z * log(length(baseUv) + 1.0);
vec2 ruv = baseUv * rotate(angle);
col += lineCol * wave(
ruv + vec2(bottomLineDistance * fi + bottomWavePosition.x, bottomWavePosition.y),
1.5 + 0.2 * fi,
baseUv,
mouseUv,
interactive
) * 0.2;
}
}
if (enableMiddle) {
for (int i = 0; i < 20; ++i) {
if(i >= middleLineCount) break;
float fi = float(i);
float t = fi / max(float(middleLineCount - 1), 1.0);
vec3 lineCol = getLineColor(t, b);
float angle = middleWavePosition.z * log(length(baseUv) + 1.0);
vec2 ruv = baseUv * rotate(angle);
col += lineCol * wave(
ruv + vec2(middleLineDistance * fi + middleWavePosition.x, middleWavePosition.y),
2.0 + 0.15 * fi,
baseUv,
mouseUv,
interactive
);
}
}
if (enableTop) {
for (int i = 0; i < 20; ++i) {
if(i >= topLineCount) break;
float fi = float(i);
float t = fi / max(float(topLineCount - 1), 1.0);
vec3 lineCol = getLineColor(t, b);
float angle = topWavePosition.z * log(length(baseUv) + 1.0);
vec2 ruv = baseUv * rotate(angle);
ruv.x *= -1.0;
col += lineCol * wave(
ruv + vec2(topLineDistance * fi + topWavePosition.x, topWavePosition.y),
1.0 + 0.2 * fi,
baseUv,
mouseUv,
interactive
) * 0.1;
}
}
fragColor = vec4(col, 1.0);
}
void main() {
vec4 color = vec4(0.0);
mainImage(color, gl_FragCoord.xy);
gl_FragColor = color;
}
`;
const MAX_GRADIENT_STOPS = 8;
function hexToVec3(hex) {
let value = hex.trim();
if (value.startsWith('#')) {
value = value.slice(1);
}
let r = 255;
let g = 255;
let b = 255;
if (value.length === 3) {
r = parseInt(value[0] + value[0], 16);
g = parseInt(value[1] + value[1], 16);
b = parseInt(value[2] + value[2], 16);
}
else if (value.length === 6) {
r = parseInt(value.slice(0, 2), 16);
g = parseInt(value.slice(2, 4), 16);
b = parseInt(value.slice(4, 6), 16);
}
return new Vector3(r / 255, g / 255, b / 255);
}
export class FloatingLinesBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 用于线条渐变着色的十六进制颜色字符串数组(最多 8 种颜色) */
this.ncLinesGradient = [];
/** 显示哪些波形层。可以单独切换显示/隐藏各个波形 */
this.ncEnabledWaves = ['top', 'middle', 'bottom'];
/** 每波形的线条数。单个数值适用于所有波形,也可以使用数组进行逐波形控制(1-20) */
this.ncLineCount = 6;
/** 行间距。单个数值适用于所有波形,或使用数组进行逐个波形的控制(1-100) */
this.ncLineDistance = 5;
/** 顶部波浪的位置和旋转参数 { x, y, rotate } */
this.ncTopWavePosition = { x: 10.0, y: 0.5, rotate: -0.4 };
/** 中部波浪的位置和旋转参数 { x, y, rotate } */
this.ncMiddleWavePosition = { x: 5.0, y: 0.0, rotate: 0.2 };
/** 底部波浪的位置和旋转参数 { x, y, rotate } */
this.ncBottomWavePosition = { x: 2.0, y: -0.7, rotate: -1 };
/** 波浪动画的速度倍增器 */
this.ncAnimationSpeed = 1;
/** 线条是否会对鼠标/指针移动做出反应 */
this._interactive = true;
/** 受鼠标交互影响区域的半径(1-30) */
this.ncBendRadius = 5.0;
/** 与鼠标交互时弯曲效应的强度(-15-15) */
this.ncBendStrength = -0.5;
/** 鼠标移动跟踪的平滑因子(0-1) */
this.ncMouseDamping = 0.05;
/** 启用鼠标移动时的视差效果 */
this._parallax = true;
/** 视差效应的强度 */
this.ncParallaxStrength = 0.2;
/** CSS mix-blend-mode 应用于canvas元素 */
this.ncMixBlendMode = 'unset';
this.clock = new Clock();
this.rafId = 0;
this.targetMouse = new Vector2(-1000, -1000);
this.currentMouse = new Vector2(-1000, -1000);
this.targetInfluence = 0;
this.currentInfluence = 0;
this.targetParallax = new Vector2(0, 0);
this.currentParallax = new Vector2(0, 0);
this.uniforms = {};
}
set ncInteractive(val) {
this._interactive = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncInteractive() {
return this._interactive;
}
set ncParallax(val) {
this._parallax = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncParallax() {
return this._parallax;
}
ngOnInit() { }
ngAfterViewInit() {
this.initThree();
this.setupResizeObserver();
this.ngZone.runOutsideAngular(() => {
this.animate();
});
}
ngOnDestroy() {
if (this.rafId)
cancelAnimationFrame(this.rafId);
if (this.resizeObserver)
this.resizeObserver.disconnect();
this.cleanupThree();
}
ngOnChanges(changes) {
if (this.material) {
this.updateUniforms();
}
}
initThree() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
const el = this.containerRef.nativeElement;
this.scene = new Scene();
this.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
this.camera.position.z = 1;
this.renderer = new WebGLRenderer({ antialias: true, alpha: false });
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
this.renderer.setSize(el.clientWidth || 1, el.clientHeight || 1, false);
el.appendChild(this.renderer.domElement);
this.uniforms = {
iTime: { value: 0 },
iResolution: { value: new Vector3(el.clientWidth, el.clientHeight, 1) },
animationSpeed: { value: this.ncAnimationSpeed },
enableTop: { value: this.ncEnabledWaves.includes('top') },
enableMiddle: { value: this.ncEnabledWaves.includes('middle') },
enableBottom: { value: this.ncEnabledWaves.includes('bottom') },
topLineCount: { value: this.getLineCount('top') },
middleLineCount: { value: this.getLineCount('middle') },
bottomLineCount: { value: this.getLineCount('bottom') },
topLineDistance: { value: this.getLineDistance('top') * 0.01 },
middleLineDistance: { value: this.getLineDistance('middle') * 0.01 },
bottomLineDistance: { value: this.getLineDistance('bottom') * 0.01 },
topWavePosition: {
value: new Vector3((_b = (_a = this.ncTopWavePosition) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 10.0, (_d = (_c = this.ncTopWavePosition) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0.5, (_f = (_e = this.ncTopWavePosition) === null || _e === void 0 ? void 0 : _e.rotate) !== null && _f !== void 0 ? _f : -0.4)
},
middleWavePosition: {
value: new Vector3((_h = (_g = this.ncMiddleWavePosition) === null || _g === void 0 ? void 0 : _g.x) !== null && _h !== void 0 ? _h : 5.0, (_k = (_j = this.ncMiddleWavePosition) === null || _j === void 0 ? void 0 : _j.y) !== null && _k !== void 0 ? _k : 0.0, (_m = (_l = this.ncMiddleWavePosition) === null || _l === void 0 ? void 0 : _l.rotate) !== null && _m !== void 0 ? _m : 0.2)
},
bottomWavePosition: {
value: new Vector3((_p = (_o = this.ncBottomWavePosition) === null || _o === void 0 ? void 0 : _o.x) !== null && _p !== void 0 ? _p : 2.0, (_r = (_q = this.ncBottomWavePosition) === null || _q === void 0 ? void 0 : _q.y) !== null && _r !== void 0 ? _r : -0.7, (_t = (_s = this.ncBottomWavePosition) === null || _s === void 0 ? void 0 : _s.rotate) !== null && _t !== void 0 ? _t : -1)
},
iMouse: { value: new Vector2(-1000, -1000) },
interactive: { value: this.ncInteractive },
bendRadius: { value: this.ncBendRadius },
bendStrength: { value: this.ncBendStrength },
bendInfluence: { value: 0 },
parallax: { value: this.ncParallax },
parallaxStrength: { value: this.ncParallaxStrength },
parallaxOffset: { value: new Vector2(0, 0) },
lineGradient: {
value: Array.from({ length: MAX_GRADIENT_STOPS }, () => new Vector3(1, 1, 1))
},
lineGradientCount: { value: 0 }
};
if (this.ncLinesGradient && this.ncLinesGradient.length > 0) {
const stops = this.ncLinesGradient.slice(0, MAX_GRADIENT_STOPS);
this.uniforms.lineGradientCount.value = stops.length;
stops.forEach((hex, i) => {
const color = hexToVec3(hex);
this.uniforms.lineGradient.value[i].copy(color);
});
}
this.material = new ShaderMaterial({
uniforms: this.uniforms,
vertexShader,
fragmentShader
});
this.geometry = new PlaneGeometry(2, 2);
this.mesh = new Mesh(this.geometry, this.material);
this.scene.add(this.mesh);
}
updateUniforms() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
this.uniforms.animationSpeed.value = this.ncAnimationSpeed;
this.uniforms.enableTop.value = this.ncEnabledWaves.includes('top');
this.uniforms.enableMiddle.value = this.ncEnabledWaves.includes('middle');
this.uniforms.enableBottom.value = this.ncEnabledWaves.includes('bottom');
this.uniforms.topLineCount.value = this.getLineCount('top');
this.uniforms.middleLineCount.value = this.getLineCount('middle');
this.uniforms.bottomLineCount.value = this.getLineCount('bottom');
this.uniforms.topLineDistance.value = this.getLineDistance('top') * 0.01;
this.uniforms.middleLineDistance.value = this.getLineDistance('middle') * 0.01;
this.uniforms.bottomLineDistance.value = this.getLineDistance('bottom') * 0.01;
this.uniforms.topWavePosition.value.set((_b = (_a = this.ncTopWavePosition) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 10.0, (_d = (_c = this.ncTopWavePosition) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0.5, (_f = (_e = this.ncTopWavePosition) === null || _e === void 0 ? void 0 : _e.rotate) !== null && _f !== void 0 ? _f : -0.4);
this.uniforms.middleWavePosition.value.set((_h = (_g = this.ncMiddleWavePosition) === null || _g === void 0 ? void 0 : _g.x) !== null && _h !== void 0 ? _h : 5.0, (_k = (_j = this.ncMiddleWavePosition) === null || _j === void 0 ? void 0 : _j.y) !== null && _k !== void 0 ? _k : 0.0, (_m = (_l = this.ncMiddleWavePosition) === null || _l === void 0 ? void 0 : _l.rotate) !== null && _m !== void 0 ? _m : 0.2);
this.uniforms.bottomWavePosition.value.set((_p = (_o = this.ncBottomWavePosition) === null || _o === void 0 ? void 0 : _o.x) !== null && _p !== void 0 ? _p : 2.0, (_r = (_q = this.ncBottomWavePosition) === null || _q === void 0 ? void 0 : _q.y) !== null && _r !== void 0 ? _r : -0.7, (_t = (_s = this.ncBottomWavePosition) === null || _s === void 0 ? void 0 : _s.rotate) !== null && _t !== void 0 ? _t : -1);
this.uniforms.interactive.value = this.ncInteractive;
this.uniforms.bendRadius.value = this.ncBendRadius;
this.uniforms.bendStrength.value = this.ncBendStrength;
this.uniforms.parallax.value = this.ncParallax;
this.uniforms.parallaxStrength.value = this.ncParallaxStrength;
if (this.ncLinesGradient && this.ncLinesGradient.length > 0) {
const stops = this.ncLinesGradient.slice(0, MAX_GRADIENT_STOPS);
this.uniforms.lineGradientCount.value = stops.length;
stops.forEach((hex, i) => {
const color = hexToVec3(hex);
this.uniforms.lineGradient.value[i].copy(color);
});
}
else {
this.uniforms.lineGradientCount.value = 0;
}
}
getLineCount(waveType) {
var _a;
if (typeof this.ncLineCount === 'number')
return this.ncLineCount;
if (!this.ncEnabledWaves.includes(waveType))
return 0;
const index = this.ncEnabledWaves.indexOf(waveType);
return (_a = this.ncLineCount[index]) !== null && _a !== void 0 ? _a : 0;
}
getLineDistance(waveType) {
var _a;
if (typeof this.ncLineDistance === 'number')
return this.ncLineDistance;
if (!this.ncEnabledWaves.includes(waveType))
return 0.1;
const index = this.ncEnabledWaves.indexOf(waveType);
return (_a = this.ncLineDistance[index]) !== null && _a !== void 0 ? _a : 0.1;
}
setupResizeObserver() {
this.resizeObserver = new ResizeObserver(() => {
const el = this.containerRef.nativeElement;
const width = el.clientWidth || 1;
const height = el.clientHeight || 1;
this.ngZone.runOutsideAngular(() => {
this.renderer.setSize(width, height, false);
const canvasWidth = this.renderer.domElement.width;
const canvasHeight = this.renderer.domElement.height;
this.uniforms.iResolution.value.set(canvasWidth, canvasHeight, 1);
});
});
this.resizeObserver.observe(this.containerRef.nativeElement);
}
onPointerMove(event) {
if (!this.ncInteractive && !this.ncParallax)
return;
const rect = this.renderer.domElement.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const dpr = this.renderer.getPixelRatio();
if (this.ncInteractive) {
this.targetMouse.set(x * dpr, (rect.height - y) * dpr);
this.targetInfluence = 1.0;
}
if (this.ncParallax) {
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const offsetX = (x - centerX) / rect.width;
const offsetY = -(y - centerY) / rect.height;
this.targetParallax.set(offsetX * this.ncParallaxStrength, offsetY * this.ncParallaxStrength);
}
}
onPointerLeave() {
this.targetInfluence = 0.0;
}
animate() {
this.rafId = requestAnimationFrame(() => this.animate());
this.render();
}
render() {
this.uniforms.iTime.value = this.clock.getElapsedTime();
if (this.ncInteractive) {
this.currentMouse.lerp(this.targetMouse, this.ncMouseDamping);
this.uniforms.iMouse.value.copy(this.currentMouse);
this.currentInfluence += (this.targetInfluence - this.currentInfluence) * this.ncMouseDamping;
this.uniforms.bendInfluence.value = this.currentInfluence;
}
if (this.ncParallax) {
this.currentParallax.lerp(this.targetParallax, this.ncMouseDamping);
this.uniforms.parallaxOffset.value.copy(this.currentParallax);
}
this.renderer.render(this.scene, this.camera);
}
cleanupThree() {
if (this.geometry)
this.geometry.dispose();
if (this.material)
this.material.dispose();
if (this.renderer) {
this.renderer.dispose();
this.renderer.domElement.remove();
}
}
}
FloatingLinesBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: FloatingLinesBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
FloatingLinesBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: FloatingLinesBackgroundComponent, selector: "nc-floating-lines-background", inputs: { ncLinesGradient: "ncLinesGradient", ncEnabledWaves: "ncEnabledWaves", ncLineCount: "ncLineCount", ncLineDistance: "ncLineDistance", ncTopWavePosition: "ncTopWavePosition", ncMiddleWavePosition: "ncMiddleWavePosition", ncBottomWavePosition: "ncBottomWavePosition", ncAnimationSpeed: "ncAnimationSpeed", ncInteractive: "ncInteractive", ncBendRadius: "ncBendRadius", ncBendStrength: "ncBendStrength", ncMouseDamping: "ncMouseDamping", ncParallax: "ncParallax", ncParallaxStrength: "ncParallaxStrength", ncMixBlendMode: "ncMixBlendMode" }, host: { listeners: { "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-floating-lines-canvas-container\" [style.mix-blend-mode]=\"ncMixBlendMode\"></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-floating-lines-canvas-container{position:absolute;inset:0;z-index:0}.nc-content-wrapper{position:relative;z-index:1;width:100%;height:100%}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: FloatingLinesBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-floating-lines-background',
templateUrl: './floating-lines-background.component.html',
styleUrls: ['./floating-lines-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncLinesGradient: [{
type: Input
}], ncEnabledWaves: [{
type: Input
}], ncLineCount: [{
type: Input
}], ncLineDistance: [{
type: Input
}], ncTopWavePosition: [{
type: Input
}], ncMiddleWavePosition: [{
type: Input
}], ncBottomWavePosition: [{
type: Input
}], ncAnimationSpeed: [{
type: Input
}], ncInteractive: [{
type: Input
}], ncBendRadius: [{
type: Input
}], ncBendStrength: [{
type: Input
}], ncMouseDamping: [{
type: Input
}], ncParallax: [{
type: Input
}], ncParallaxStrength: [{
type: Input
}], ncMixBlendMode: [{
type: Input
}], onPointerMove: [{
type: HostListener,
args: ['pointermove', ['$event']]
}], onPointerLeave: [{
type: HostListener,
args: ['pointerleave']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvYXRpbmctbGluZXMtYmFja2dyb3VuZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2Zsb2F0aW5nLWxpbmVzLWJhY2tncm91bmQvZmxvYXRpbmctbGluZXMtYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2Zsb2F0aW5nLWxpbmVzLWJhY2tncm91bmQvZmxvYXRpbmctbGluZXMtYmFja2dyb3VuZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUlULFNBQVMsRUFFVCxLQUFLLEVBR0wsWUFBWSxFQUViLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxLQUFLLEVBQ0wsa0JBQWtCLEVBQ2xCLGFBQWEsRUFDYixhQUFhLEVBQ2IsSUFBSSxFQUNKLGNBQWMsRUFDZCxPQUFPLEVBQ1AsT0FBTyxFQUNQLEtBQUssRUFDTixNQUFNLE9BQU8sQ0FBQzs7QUFTZixNQUFNLFlBQVksR0FBRzs7Ozs7O0NBTXBCLENBQUM7QUFFRixNQUFNLGNBQWMsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBdUx0QixDQUFDO0FBRUYsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUM7QUFFN0IsU0FBUyxTQUFTLENBQUMsR0FBVztJQUM1QixJQUFJLEtBQUssR0FBRyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkIsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FB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LFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDhCQUE4QjtvQkFDeEMsV0FBVyxFQUFFLDRDQUE0QztvQkFDekQsU0FBUyxFQUFFLENBQUMsNENBQTRDLENBQUM7aUJBQzFEOzZGQUUyQyxZQUFZO3NCQUFyRCxTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRy9CLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsY0FBYztzQkFBdEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFFRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUlGLGFBQWE7c0JBRGhCLEtBQUs7Z0JBUUcsWUFBWTtzQkFBcEIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBSUYsVUFBVTtzQkFEYixLQUFLO2dCQVFHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQTRNTixhQUFhO3NCQURaLFlBQVk7dUJBQUMsYUFBYSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQXdCdkMsY0FBYztzQkFEYixZQUFZO3VCQUFDLGNBQWMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBPbkluaXQsXHJcbiAgT25EZXN0cm95LFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgVmlld0NoaWxkLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgSW5wdXQsXHJcbiAgT25DaGFuZ2VzLFxyXG4gIFNpbXBsZUNoYW5nZXMsXHJcbiAgSG9zdExpc3RlbmVyLFxyXG4gIE5nWm9uZVxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIFNjZW5lLFxyXG4gIE9ydGhvZ3JhcGhpY0NhbWVyYSxcclxuICBXZWJHTFJlbmRlcmVyLFxyXG4gIFBsYW5lR2VvbWV0cnksXHJcbiAgTWVzaCxcclxuICBTaGFkZXJNYXRlcmlhbCxcclxuICBWZWN0b3IzLFxyXG4gIFZlY3RvcjIsXHJcbiAgQ2xvY2tcclxufSBmcm9tICd0aHJlZSc7XHJcblxyXG5leHBvcnQgdHlwZSBOY1dhdmVUeXBlID0gJ3RvcCcgfCAnbWlkZGxlJyB8ICdib3R0b20nO1xyXG5leHBvcnQgaW50ZXJmYWNlIE5jV2F2ZVBvc2l0aW9uIHtcclxuICB4PzogbnVtYmVyO1xyXG4gIHk/OiBudW1iZXI7XHJcbiAgcm90YXRlPzogbnVtYmVyO1xyXG59XHJcblxyXG5jb25zdCB2ZXJ0ZXhTaGFkZXIgPSBgXHJcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuXHJcbnZvaWQgbWFpbigpIHtcclxuICBnbF9Qb3NpdGlvbiA9IHByb2plY3Rpb25NYXRyaXggKiBtb2RlbFZpZXdNYXRyaXggKiB2ZWM0KHBvc2l0aW9uLCAxLjApO1xyXG59XHJcbmA7XHJcblxyXG5jb25zdCBmcmFnbWVudFNoYWRlciA9IGBcclxucHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xyXG5cclxudW5pZm9ybSBmbG9hdCBpVGltZTtcclxudW5pZm9ybSB2ZWMzICBpUmVzb2x1dGlvbjtcclxudW5pZm9ybSBmbG9hdCBhbmltYXRpb25TcGVlZDtcclxuXHJcbnVuaWZvcm0gYm9vbCBlbmFibGVUb3A7XHJcbnVuaWZvcm0gYm9vbCBlbmFibGVNaWRkbGU7XHJcbnVuaWZvcm0gYm9vbCBlbmFibGVCb3R0b207XHJcblxyXG51bmlmb3JtIGludCB0b3BMaW5lQ291bnQ7XHJcbnVuaWZvcm0gaW50IG1pZGRsZUxpbmVDb3VudDtcclxudW5pZm9ybSBpbnQgYm90dG9tTGluZUNvdW50O1xyXG5cclxudW5pZm9ybSBmbG9hdCB0b3BMaW5lRGlzdGFuY2U7XHJcbnVuaWZvcm0gZmxvYXQgbWlkZGxlTGluZURpc3RhbmNlO1xyXG51bmlmb3JtIGZsb2F0IGJvdHRvbUxpbmVEaXN0YW5jZTtcclxuXHJcbnVuaWZvcm0gdmVjMyB0b3BXYXZlUG9zaXRpb247XHJcbnVuaWZvcm0gdmVjMyBtaWRkbGVXYXZlUG9zaXRpb247XHJcbnVuaWZvcm0gdmVjMyBib3R0b21XYXZlUG9zaXRpb247XHJcblxyXG51bmlmb3JtIHZlYzIgaU1vdXNlO1xyXG51bmlmb3JtIGJvb2wgaW50ZXJhY3RpdmU7XHJcbnVuaWZvcm0gZmxvYXQgYmVuZFJhZGl1cztcclxudW5pZm9ybSBmbG9hdCBiZW5kU3RyZW5ndGg7XHJcbnVuaWZvcm0gZmxvYXQgYmVuZEluZmx1ZW5jZTtcclxuXHJcbnVuaWZvcm0gYm9vbCBwYXJhbGxheDtcclxudW5pZm9ybSBmbG9hdCBwYXJhbGxheFN0cmVuZ3RoO1xyXG51bmlmb3JtIHZlYzIgcGFyYWxsYXhPZmZzZXQ7XHJcblxyXG51bmlmb3JtIHZlYzMgbGluZUdyYWRpZW50WzhdO1xyXG51bmlmb3JtIGludCBsaW5lR3JhZGllbnRDb3VudDtcclxuXHJcbmNvbnN0IHZlYzMgQkxBQ0sgPSB2ZWMzKDAuMCk7XHJcbmNvbnN0IHZlYzMgUElOSyAgPSB2ZWMzKDIzMy4wLCA3MS4wLCAyNDUuMCkgLyAyNTUuMDtcclxuY29uc3QgdmVjMyBCTFVFICA9IHZlYzMoNDcuMCwgIDc1LjAsIDE2Mi4wKSAvIDI1NS4wO1xyXG5cclxubWF0MiByb3RhdGUoZmxvYXQgcikge1xyXG4gIHJldHVybiBtYXQyKGNvcyhyKSwgc2luKHIpLCAtc2luKHIpLCBjb3MocikpO1xyXG59XHJcblxyXG52ZWMzIGJhY2tncm91bmRfY29sb3IodmVjMiB1dikge1xyXG4gIHZlYzMgY29sID0gdmVjMygwLjApO1xyXG5cclxuICBmbG9hdCB5ID0gc2luKHV2LnggLSAwLjIpICogMC4zIC0gMC4xO1xyXG4gIGZsb2F0IG0gPSB1di55IC0geTtcclxuXHJcbiAgY29sICs9IG1peChCTFVFLCBCTEFDSywgc21vb3Roc3RlcCgwLjAsIDEuMCwgYWJzKG0pKSk7XHJcbiAgY29sICs9IG1peChQSU5LLCBCTEFDSywgc21vb3Roc3RlcCgwLjAsIDEuMCwgYWJzKG0gLSAwLjgpKSk7XHJcbiAgcmV0dXJuIGNvbCAqIDAuNTtcclxufVxyXG5cclxudmVjMyBnZXRMaW5lQ29sb3IoZmxvYXQgdCwgdmVjMyBiYXNlQ29sb3IpIHtcclxuICBpZiAobGluZUdyYWRpZW50Q291bnQgPD0gMCkge1xyXG4gICAgcmV0dXJuIGJhc2VDb2xvcjtcclxuICB9XHJcblxyXG4gIHZlYzMgZ3JhZGllbnRDb2xvcjtcclxuICBcclxuICBpZiAobGluZUdyYWRpZW50Q291bnQgPT0gMSkge1xyXG4gICAgZ3JhZGllbnRDb2xvciA9IGxpbmVHcmFkaWVudFswXTtcclxuICB9IGVsc2Uge1xyXG4gICAgZmxvYXQgY2xhbXBlZFQgPSBjbGFtcCh0LCAwLjAsIDAuOTk5OSk7XHJcbiAgICBmbG9hdCBzY2FsZWQgPSBjbGFtcGVkVCAqIGZsb2F0KGxpbmVHcmFkaWVudENvdW50IC0gMSk7XHJcbiAgICBpbnQgaWR4ID0gaW50KGZsb29yKHNjYWxlZCkpO1xyXG4gICAgZmxvYXQgZiA9IGZyYWN0KHNjYWxlZCk7XHJcbiAgICBpbnQgaWR4MiA9IG1pbihpZHggKyAxLCBsaW5lR3JhZGllbnRDb3VudCAtIDEpO1xyXG5cclxuICAgIHZlYzMgYzEgPSBsaW5lR3JhZGllbnRbaWR4XTtcclxuICAgIHZlYzMgYzIgPSBsaW5lR3JhZGllbnRbaWR4Ml07XHJcbiAgICBcclxuICAgIGdyYWRpZW50Q29sb3IgPSBtaXgoYzEsIGMyLCBmKTtcclxuICB9XHJcbiAgXHJcbiAgcmV0dXJuIGdyYWRpZW50Q29sb3IgKiAwLjU7XHJcbn1cclxuXHJcbmZsb2F0IHdhdmUodmVjMiB1diwgZmxvYXQgb2Zmc2V0LCB2ZWMyIHNjcmVlblV2LCB2ZWMyIG1vdXNlVXYsIGJvb2wgc2hvdWxkQmVuZCkge1xyXG4gIGZsb2F0IHRpbWUgPSBpVGltZSAqIGFuaW1hdGlvblNwZWVkO1xyXG5cclxuICBmbG9hdCB4X29mZnNldCAgID0gb2Zmc2V0O1xyXG4gIGZsb2F0IHhfbW92ZW1lbnQgPSB0aW1lICogMC4xO1xyXG4gIGZsb2F0IGFtcCAgICAgICAgPSBzaW4ob2Zmc2V0ICsgdGltZSAqIDAuMikgKiAwLjM7XHJcbiAgZmxvYXQgeSAgICAgICAgICA9IHNpbih1di54ICsgeF9vZmZzZXQgKyB4X21vdmVtZW50KSAqIGFtcDtcclxuXHJcbiAgaWYgKHNob3VsZEJlbmQpIHtcclxuICAgIHZlYzIgZCA9IHNjcmVlblV2IC0gbW91c2VVdjtcclxuICAgIGZsb2F0IGluZmx1ZW5jZSA9IGV4cCgtZG90KGQsIGQpICogYmVuZFJhZGl1cyk7IC8vIHJhZGlhbCBmYWxsb2ZmIGFyb3VuZCBjdXJzb3JcclxuICAgIGZsb2F0IGJlbmRPZmZzZXQgPSAobW91c2VVdi55IC0gc2NyZWVuVXYueSkgKiBpbmZsdWVuY2UgKiBiZW5kU3RyZW5ndGggKiBiZW5kSW5mbHVlbmNlO1xyXG4gICAgeSArPSBiZW5kT2Zmc2V0O1xyXG4gIH1cclxuXHJcbiAgZmxvYXQgbSA9IHV2LnkgLSB5O1xyXG4gIHJldHVybiAwLjAxNzUgLyBtYXgoYWJzKG0pICsgMC4wMSwgMWUtMykgKyAwLjAxO1xyXG59XHJcblxyXG52b2lkIG1haW5JbWFnZShvdXQgdmVjNCBmcmFnQ29sb3IsIGluIHZlYzIgZnJhZ0Nvb3JkKSB7XHJcbiAgdmVjMiBiYXNlVXYgPSAoMi4wICogZnJhZ0Nvb3JkIC0gaVJlc29sdXRpb24ueHkpIC8gaVJlc29sdXRpb24ueTtcclxuICBiYXNlVXYueSAqPSAtMS4wO1xyXG4gIFxyXG4gIGlmIChwYXJhbGxheCkge1xyXG4gICAgYmFzZVV2ICs9IHBhcmFsbGF4T2Zmc2V0O1xyXG4gIH1cclxuXHJcbiAgdmVjMyBjb2wgPSB2ZWMzKDAuMCk7XHJcblxyXG4gIHZlYzMgYiA9IGxpbmVHcmFkaWVudENvdW50ID4gMCA/IHZlYzMoMC4wKSA6IGJhY2tncm91bmRfY29sb3IoYmFzZVV2KTtcclxuXHJcbiAgdmVjMiBtb3VzZVV2ID0gdmVjMigwLjApO1xyXG4gIGlmIChpbnRlcmFjdGl2ZSkge1xyXG4gICAgbW91c2VVdiA9ICgyLjAgKiBpTW91c2UgLSBpUmVzb2x1dGlvbi54eSkgLyBpUmVzb2x1dGlvbi55O1xyXG4gICAgbW91c2VVdi55ICo9IC0xLjA7XHJcbiAgfVxyXG4gIFxyXG4gIGlmIChlbmFibGVCb3R0b20pIHtcclxuICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMjA7ICsraSkgeyAvLyBGaXhlZCBsaW1pdCBmb3IgTG9vcFxyXG4gICAgICBpZihpID49IGJvdHRvbUxpbmVDb3VudCkgYnJlYWs7XHJcbiAgICAgIGZsb2F0IGZpID0gZmxvYXQoaSk7XHJcbiAgICAgIGZsb2F0IHQgPSBmaSAvIG1heChmbG9hdChib3R0b21MaW5lQ291bnQgLSAxKSwgMS4wKTtcclxuICAgICAgdmVjMyBsaW5lQ29sID0gZ2V0TGluZUNvbG9yKHQsIGIpO1xyXG4gICAgICBcclxuICAgICAgZmxvYXQgYW5nbGUgPSBib3R0b21XYXZlUG9zaXRpb24ueiAqIGxvZyhsZW5ndGgoYmFzZVV2KSArIDEuMCk7XHJcbiAgICAgIHZlYzIgcnV2ID0gYmFzZVV2ICogcm90YXRlKGFuZ2xlKTtcclxuICAgICAgY29sICs9IGxpbmVDb2wgKiB3YXZlKFxyXG4gICAgICAgIHJ1diArIHZlYzIoYm90dG9tTGluZURpc3RhbmNlICogZmkgKyBib3R0b21XYXZlUG9zaXRpb24ueCwgYm90dG9tV2F2ZVBvc2l0aW9uLnkpLFxyXG4gICAgICAgIDEuNSArIDAuMiAqIGZpLFxyXG4gICAgICAgIGJhc2VVdixcclxuICAgICAgICBtb3VzZVV2LFxyXG4gICAgICAgIGludGVyYWN0aXZlXHJcbiAgICAgICkgKiAwLjI7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpZiAoZW5hYmxlTWlkZGxlKSB7XHJcbiAgICBmb3IgKGludCBpID0gMDsgaSA8IDIwOyArK2kpIHtcclxuICAgICAgaWYoaSA+PSBtaWRkbGVMaW5lQ291bnQpIGJyZWFrO1xyXG4gICAgICBmbG9hdCBmaSA9IGZsb2F0KGkpO1xyXG4gICAgICBmbG9hdCB0ID0gZmkgLyBtYXgoZmxvYXQobWlkZGxlTGluZUNvdW50IC0gMSksIDEuMCk7XHJcbiAgICAgIHZlYzMgbGluZUNvbCA9IGdldExpbmVDb2xvcih0LCBiKTtcclxuICAgICAgXHJcbiAgICAgIGZsb2F0IGFuZ2xlID0gbWlkZGxlV2F2ZVBvc2l0aW9uLnogKiBsb2cobGVuZ3RoKGJhc2VVdikgKyAxLjApO1xyXG4gICAgICB2ZWMyIHJ1diA9IGJhc2VVdiAqIHJvdGF0ZShhbmdsZSk7XHJcbiAgICAgIGNvbCArPSBsaW5lQ29sICogd2F2ZShcclxuICAgICAgICBydXYgKyB2ZWMyKG1pZGRsZUxpbmVEaXN0YW5jZSAqIGZpICsgbWlkZGxlV2F2ZVBvc2l0aW9uLngsIG1pZGRsZVdhdmVQb3NpdGlvbi55KSxcclxuICAgICAgICAyLjAgKyAwLjE1ICogZmksXHJcbiAgICAgICAgYmFzZVV2LFxyXG4gICAgICAgIG1vdXNlVXYsXHJcbiAgICAgICAgaW50ZXJhY3RpdmVcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGlmIChlbmFibGVUb3ApIHtcclxuICAgIGZvciAoaW50IGkgPSAwOyBpIDwgMjA7ICsraSkge1xyXG4gICAgICBpZihpID49IHRvcExpbmVDb3VudCkgYnJlYWs7XHJcbiAgICAgIGZsb2F0IGZpID0gZmxvYXQoaSk7XHJcbiAgICAgIGZsb2F0IHQgPSBmaSAvIG1heChmbG9hdCh0b3BMaW5lQ291bnQgLSAxKSwgMS4wKTtcclxuICAgICAgdmVjMyBsaW5lQ29sID0gZ2V0TGluZUNvbG9yKHQsIGIpO1xyXG4gICAgICBcclxuICAgICAgZmxvYXQgYW5nbGUgPSB0b3BXYXZlUG9zaXRpb24ueiAqIGxvZyhsZW5ndGgoYmFzZVV2KSArIDEuMCk7XHJcbiAgICAgIHZlYzIgcnV2ID0gYmFzZVV2ICogcm90YXRlKGFuZ2xlKTtcclxuICAgICAgcnV2LnggKj0gLTEuMDtcclxuICAgICAgY29sICs9IGxpbmVDb2wgKiB3YXZlKFxyXG4gICAgICAgIHJ1diArIHZlYzIodG9wTGluZURpc3RhbmNlICogZmkgKyB0b3BXYXZlUG9zaXRpb24ueCwgdG9wV2F2ZVBvc2l0aW9uLnkpLFxyXG4gICAgICAgIDEuMCArIDAuMiAqIGZpLFxyXG4gICAgICAgIGJhc2VVdixcclxuICAgICAgICBtb3VzZVV2LFxyXG4gICAgICAgIGludGVyYWN0aXZlXHJcbiAgICAgICkgKiAwLjE7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBmcmFnQ29sb3IgPSB2ZWM0KGNvbCwgMS4wKTtcclxufVxyXG5cclxudm9pZCBtYWluKCkge1xyXG4gIHZlYzQgY29sb3IgPSB2ZWM0KDAuMCk7XHJcbiAgbWFpbkltYWdlKGNvbG9yLCBnbF9GcmFnQ29vcmQueHkpO1xyXG4gIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xyXG59XHJcbmA7XHJcblxyXG5jb25zdCBNQVhfR1JBRElFTlRfU1RPUFMgPSA4O1xyXG5cclxuZnVuY3Rpb24gaGV4VG9WZWMzKGhleDogc3RyaW5nKSB7XHJcbiAgbGV0IHZhbHVlID0gaGV4LnRyaW0oKTtcclxuICBpZiAodmFsdWUuc3RhcnRzV2l0aCgnIycpKSB7XHJcbiAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDEpO1xyXG4gIH1cclxuICBsZXQgciA9IDI1NTtcclxuICBsZXQgZyA9IDI1NTtcclxuICBsZXQgYiA9IDI1NTtcclxuICBpZiAodmFsdWUubGVuZ3RoID09P