ng-cw-v12
Version:
Angular UI Component Library
449 lines (423 loc) • 52.4 kB
JavaScript
import { Component, ViewChild, Input, HostListener } from '@angular/core';
import * as THREE from 'three';
import * as i0 from "@angular/core";
const vert = `
precision highp float;
attribute vec3 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 1.0);
}
`;
const frag = `
precision highp float;
uniform float iTime;
uniform vec3 iResolution;
uniform float hue;
uniform float hover;
uniform float rot;
uniform float hoverIntensity;
uniform vec3 backgroundColor;
varying vec2 vUv;
vec3 rgb2yiq(vec3 c) {
float y = dot(c, vec3(0.299, 0.587, 0.114));
float i = dot(c, vec3(0.596, -0.274, -0.322));
float q = dot(c, vec3(0.211, -0.523, 0.312));
return vec3(y, i, q);
}
vec3 yiq2rgb(vec3 c) {
float r = c.x + 0.956 * c.y + 0.621 * c.z;
float g = c.x - 0.272 * c.y - 0.647 * c.z;
float b = c.x - 1.106 * c.y + 1.703 * c.z;
return vec3(r, g, b);
}
vec3 adjustHue(vec3 color, float hueDeg) {
float hueRad = hueDeg * 3.14159265 / 180.0;
vec3 yiq = rgb2yiq(color);
float cosA = cos(hueRad);
float sinA = sin(hueRad);
float i = yiq.y * cosA - yiq.z * sinA;
float q = yiq.y * sinA + yiq.z * cosA;
yiq.y = i;
yiq.z = q;
return yiq2rgb(yiq);
}
vec3 hash33(vec3 p3) {
p3 = fract(p3 * vec3(0.1031, 0.11369, 0.13787));
p3 += dot(p3, p3.yxz + 19.19);
return -1.0 + 2.0 * fract(vec3(
p3.x + p3.y,
p3.x + p3.z,
p3.y + p3.z
) * p3.zyx);
}
float snoise3(vec3 p) {
const float K1 = 0.333333333;
const float K2 = 0.166666667;
vec3 i = floor(p + (p.x + p.y + p.z) * K1);
vec3 d0 = p - (i - (i.x + i.y + i.z) * K2);
vec3 e = step(vec3(0.0), d0 - d0.yzx);
vec3 i1 = e * (1.0 - e.zxy);
vec3 i2 = 1.0 - e.zxy * (1.0 - e);
vec3 d1 = d0 - (i1 - K2);
vec3 d2 = d0 - (i2 - K1);
vec3 d3 = d0 - 0.5;
vec4 h = max(0.6 - vec4(
dot(d0, d0),
dot(d1, d1),
dot(d2, d2),
dot(d3, d3)
), 0.0);
vec4 n = h * h * h * h * vec4(
dot(d0, hash33(i)),
dot(d1, hash33(i + i1)),
dot(d2, hash33(i + i2)),
dot(d3, hash33(i + 1.0))
);
return dot(vec4(31.316), n);
}
vec4 extractAlpha(vec3 colorIn) {
float a = max(max(colorIn.r, colorIn.g), colorIn.b);
return vec4(colorIn.rgb / (a + 1e-5), a);
}
const vec3 baseColor1 = vec3(0.611765, 0.262745, 0.996078);
const vec3 baseColor2 = vec3(0.298039, 0.760784, 0.913725);
const vec3 baseColor3 = vec3(0.062745, 0.078431, 0.600000);
const float innerRadius = 0.6;
const float noiseScale = 0.65;
float light1(float intensity, float attenuation, float dist) {
return intensity / (1.0 + dist * attenuation);
}
float light2(float intensity, float attenuation, float dist) {
return intensity / (1.0 + dist * dist * attenuation);
}
vec4 draw(vec2 uv) {
vec3 color1 = adjustHue(baseColor1, hue);
vec3 color2 = adjustHue(baseColor2, hue);
vec3 color3 = adjustHue(baseColor3, hue);
float ang = atan(uv.y, uv.x);
float len = length(uv);
float invLen = len > 0.0 ? 1.0 / len : 0.0;
float bgLuminance = dot(backgroundColor, vec3(0.299, 0.587, 0.114));
float n0 = snoise3(vec3(uv * noiseScale, iTime * 0.5)) * 0.5 + 0.5;
float r0 = mix(mix(innerRadius, 1.0, 0.4), mix(innerRadius, 1.0, 0.6), n0);
float d0 = distance(uv, (r0 * invLen) * uv);
float v0 = light1(1.0, 10.0, d0);
v0 *= smoothstep(r0 * 1.05, r0, len);
float innerFade = smoothstep(r0 * 0.8, r0 * 0.95, len);
v0 *= mix(innerFade, 1.0, bgLuminance * 0.7);
float cl = cos(ang + iTime * 2.0) * 0.5 + 0.5;
float a = iTime * -1.0;
vec2 pos = vec2(cos(a), sin(a)) * r0;
float d = distance(uv, pos);
float v1 = light2(1.5, 5.0, d);
v1 *= light1(1.0, 50.0, d0);
float v2 = smoothstep(1.0, mix(innerRadius, 1.0, n0 * 0.5), len);
float v3 = smoothstep(innerRadius, mix(innerRadius, 1.0, 0.5), len);
vec3 colBase = mix(color1, color2, cl);
float fadeAmount = mix(1.0, 0.1, bgLuminance);
vec3 darkCol = mix(color3, colBase, v0);
darkCol = (darkCol + v1) * v2 * v3;
darkCol = clamp(darkCol, 0.0, 1.0);
vec3 lightCol = (colBase + v1) * mix(1.0, v2 * v3, fadeAmount);
lightCol = mix(backgroundColor, lightCol, v0);
lightCol = clamp(lightCol, 0.0, 1.0);
vec3 finalCol = mix(darkCol, lightCol, bgLuminance);
return extractAlpha(finalCol);
}
vec4 mainImage(vec2 fragCoord) {
vec2 center = iResolution.xy * 0.5;
float size = min(iResolution.x, iResolution.y);
vec2 uv = (fragCoord - center) / size * 2.0;
float angle = rot;
float s = sin(angle);
float c = cos(angle);
uv = vec2(c * uv.x - s * uv.y, s * uv.x + c * uv.y);
uv.x += hover * hoverIntensity * 0.1 * sin(uv.y * 10.0 + iTime);
uv.y += hover * hoverIntensity * 0.1 * sin(uv.x * 10.0 + iTime);
return draw(uv);
}
void main() {
vec2 fragCoord = vUv * iResolution.xy;
vec4 col = mainImage(fragCoord);
gl_FragColor = vec4(col.rgb * col.a, col.a);
}
`;
function hslToRgb(h, s, l) {
let r, g, b;
if (s === 0) {
r = g = b = l;
}
else {
const hue2rgb = (p, q, t) => {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1 / 6)
return p + (q - p) * 6 * t;
if (t < 1 / 2)
return q;
if (t < 2 / 3)
return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return new THREE.Vector3(r, g, b);
}
function hexToVec3(color) {
if (color.startsWith('#')) {
const r = parseInt(color.slice(1, 3), 16) / 255;
const g = parseInt(color.slice(3, 5), 16) / 255;
const b = parseInt(color.slice(5, 7), 16) / 255;
return new THREE.Vector3(r, g, b);
}
const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
if (rgbMatch) {
return new THREE.Vector3(parseInt(rgbMatch[1], 10) / 255, parseInt(rgbMatch[2], 10) / 255, parseInt(rgbMatch[3], 10) / 255);
}
const hslMatch = color.match(/hsla?\((\d+),\s*(\d+)%,\s*(\d+)%/);
if (hslMatch) {
const h = parseInt(hslMatch[1], 10) / 360;
const s = parseInt(hslMatch[2], 10) / 100;
const l = parseInt(hslMatch[3], 10) / 100;
return hslToRgb(h, s, l);
}
return new THREE.Vector3(0, 0, 0);
}
export class OrbBackgroundComponent {
constructor(ngZone) {
this.ngZone = ngZone;
/** 球体的基本色调(0-360)*/
this.ncHue = 0;
/** 控制悬停扭曲效果的强度(0-5)*/
this.ncHoverIntensity = 2;
/** 切换开关以启用或禁用鼠标悬停时的连续旋转 */
this._rotateOnHover = true;
/** 即使球体实际上并未悬停,也强制显示悬停动画 */
this._forceHoverState = false;
/** 容器的背景颜色,十六进制格式 */
this.ncBackgroundColor = '#000000';
this.rafId = null;
this.resizeRafId = null;
this.isVisible = true;
this.targetHover = 0;
this.lastTime = 0;
this.currentRot = 0;
this.rotationSpeed = 0.3;
}
set ncRotateOnHover(val) {
this._rotateOnHover = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncRotateOnHover() {
return this._rotateOnHover;
}
set ncForceHoverState(val) {
this._forceHoverState = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncForceHoverState() {
return this._forceHoverState;
}
ngOnInit() { }
ngAfterViewInit() {
this.initWebGL();
}
ngOnDestroy() {
this.cleanup();
}
ngOnChanges(changes) {
if (this.material) {
if (changes['ncHue']) {
this.material.uniforms['hue'].value = this.ncHue;
}
if (changes['ncHoverIntensity']) {
this.material.uniforms['hoverIntensity'].value = this.ncHoverIntensity;
}
if (changes['ncBackgroundColor']) {
this.material.uniforms['backgroundColor'].value = hexToVec3(this.ncBackgroundColor);
}
}
}
initWebGL() {
const container = this.containerRef.nativeElement;
this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true, premultipliedAlpha: false });
this.renderer.setClearColor(0x000000, 0); // Transparent background matching WebGL clearColor(0,0,0,0)
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.RawShaderMaterial({
vertexShader: vert,
fragmentShader: frag,
transparent: false,
blending: THREE.NoBlending,
uniforms: {
iTime: { value: 0 },
iResolution: { value: new THREE.Vector3(1, 1, 1) },
hue: { value: this.ncHue },
hover: { value: 0 },
rot: { value: 0 },
hoverIntensity: { value: this.ncHoverIntensity },
backgroundColor: { value: hexToVec3(this.ncBackgroundColor) }
}
});
this.plane = new THREE.Mesh(geometry, this.material);
this.scene.add(this.plane);
this.setupResizeObserver(container);
this.setupIntersectionObserver(container);
this.lastTime = performance.now();
this.ngZone.runOutsideAngular(() => {
const loop = (t) => {
this.rafId = requestAnimationFrame(loop);
if (this.isVisible) {
this.update(t);
}
};
loop(performance.now());
});
}
update(t) {
const dt = (t - this.lastTime) * 0.001;
this.lastTime = t;
this.material.uniforms['iTime'].value = t * 0.001;
const effectiveHover = this.ncForceHoverState ? 1 : this.targetHover;
this.material.uniforms['hover'].value += (effectiveHover - this.material.uniforms['hover'].value) * 0.1;
if (this.ncRotateOnHover && effectiveHover > 0.5) {
this.currentRot += dt * this.rotationSpeed;
}
this.material.uniforms['rot'].value = this.currentRot;
this.renderer.render(this.scene, this.camera);
}
handleResize() {
if (!this.containerRef || !this.renderer)
return;
const container = this.containerRef.nativeElement;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
const width = container.clientWidth || 1;
const height = container.clientHeight || 1;
this.renderer.setPixelRatio(dpr);
this.renderer.setSize(width, height, false);
const canvas = this.renderer.domElement;
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.style.display = 'block';
if (this.material) {
this.material.uniforms['iResolution'].value.set(canvas.width, canvas.height, canvas.width / canvas.height);
}
}
setupResizeObserver(container) {
this.resizeObserver = new ResizeObserver(() => {
if (this.resizeRafId !== null)
cancelAnimationFrame(this.resizeRafId);
this.ngZone.runOutsideAngular(() => {
this.resizeRafId = requestAnimationFrame(() => {
this.handleResize();
this.resizeRafId = null;
});
});
});
this.resizeObserver.observe(container);
}
setupIntersectionObserver(container) {
this.intersectionObserver = new IntersectionObserver(entries => {
const entry = entries[0];
this.isVisible = entry.isIntersecting && entry.intersectionRatio > 0;
}, { threshold: [0, 0.01, 0.1] });
this.intersectionObserver.observe(container);
}
cleanup() {
var _a, _b;
if (this.rafId !== null) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
if (this.resizeRafId !== null) {
cancelAnimationFrame(this.resizeRafId);
this.resizeRafId = null;
}
try {
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
}
catch (e) {
void 0;
}
try {
(_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
}
catch (e) {
void 0;
}
if (this.renderer) {
const canvas = this.renderer.domElement;
if (canvas && canvas.parentNode) {
canvas.parentNode.removeChild(canvas);
}
this.renderer.dispose();
}
}
// ─── HostListeners for Mouse Interaction ──────────────────────────
onMouseMove(event) {
if (!this.containerRef)
return;
const container = this.containerRef.nativeElement;
const rect = container.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const width = rect.width;
const height = rect.height;
// Prevent division by zero
if (width === 0 || height === 0)
return;
const size = Math.min(width, height);
const centerX = width / 2;
const centerY = height / 2;
const uvX = ((x - centerX) / size) * 2.0;
const uvY = ((y - centerY) / size) * 2.0;
if (Math.sqrt(uvX * uvX + uvY * uvY) < 0.8) {
this.targetHover = 1;
}
else {
this.targetHover = 0;
}
}
onMouseLeave() {
this.targetHover = 0;
}
}
OrbBackgroundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: OrbBackgroundComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
OrbBackgroundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: OrbBackgroundComponent, selector: "nc-orb-background", inputs: { ncHue: "ncHue", ncHoverIntensity: "ncHoverIntensity", ncRotateOnHover: "ncRotateOnHover", ncForceHoverState: "ncForceHoverState", ncBackgroundColor: "ncBackgroundColor" }, host: { listeners: { "mousemove": "onMouseMove($event)", "mouseleave": "onMouseLeave()" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #container class=\"nc-orb-canvas-container\"></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-orb-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: OrbBackgroundComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-orb-background',
templateUrl: './orb-background.component.html',
styleUrls: ['./orb-background.component.less']
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; }, propDecorators: { containerRef: [{
type: ViewChild,
args: ['container', { static: true }]
}], ncHue: [{
type: Input
}], ncHoverIntensity: [{
type: Input
}], ncRotateOnHover: [{
type: Input
}], ncForceHoverState: [{
type: Input
}], ncBackgroundColor: [{
type: Input
}], onMouseMove: [{
type: HostListener,
args: ['mousemove', ['$event']]
}], onMouseLeave: [{
type: HostListener,
args: ['mouseleave']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JiLWJhY2tncm91bmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29tcG9uZW50cy9vcmItYmFja2dyb3VuZC9vcmItYmFja2dyb3VuZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL29yYi1iYWNrZ3JvdW5kL29yYi1iYWNrZ3JvdW5kLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBSVQsU0FBUyxFQUVULEtBQUssRUFHTCxZQUFZLEVBRWIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxLQUFLLEtBQUssTUFBTSxPQUFPLENBQUM7O0FBRS9CLE1BQU0sSUFBSSxHQUFHOzs7Ozs7Ozs7Q0FTWixDQUFDO0FBRUYsTUFBTSxJQUFJLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQStKWixDQUFDO0FBRUYsU0FBUyxRQUFRLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFBRSxDQUFTO0lBQy9DLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFWixJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7UUFDWCxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDZjtTQUFNO1FBQ0wsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFTLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxFQUFFO1lBQ2xELElBQUksQ0FBQyxHQUFHLENBQUM7Z0JBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsQixJQUFJLENBQUMsR0FBRyxDQUFD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QUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDO1FBQ3pDLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDO1FBRXpDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUU7WUFDMUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDdEI7YUFBTTtZQUNMLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1NBQ3RCO0lBQ0gsQ0FBQztJQUdELFlBQVk7UUFDVixJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztJQUN2QixDQUFDOzttSEE3TlUsc0JBQXNCO3VHQUF0QixzQkFBc0IsMGRDalBuQywySUFHTTsyRkQ4T08sc0JBQXNCO2tCQUxsQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxtQkFBbUI7b0JBQzdCLFdBQVcsRUFBRSxpQ0FBaUM7b0JBQzlDLFNBQVMsRUFBRSxDQUFDLGlDQUFpQyxDQUFDO2lCQUMvQzs2RkFFMkMsWUFBWTtzQkFBckQsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUcvQixLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUlGLGVBQWU7c0JBRGxCLEtBQUs7Z0JBVUYsaUJBQWlCO3NCQURwQixLQUFLO2dCQVFHLGlCQUFpQjtzQkFBekIsS0FBSztnQkF1S04sV0FBVztzQkFEVixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkEyQnJDLFlBQVk7c0JBRFgsWUFBWTt1QkFBQyxZQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgT25Jbml0LFxyXG4gIE9uRGVzdHJveSxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIFZpZXdDaGlsZCxcclxuICBFbGVtZW50UmVmLFxyXG4gIElucHV0LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIEhvc3RMaXN0ZW5lcixcclxuICBOZ1pvbmVcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xyXG5cclxuY29uc3QgdmVydCA9IGBcclxuICBwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XHJcbiAgYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XHJcbiAgYXR0cmlidXRlIHZlYzIgdXY7XHJcbiAgdmFyeWluZyB2ZWMyIHZVdjtcclxuICB2b2lkIG1haW4oKSB7XHJcbiAgICB2VXYgPSB1djtcclxuICAgIGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiwgMS4wKTtcclxuICB9XHJcbmA7XHJcblxyXG5jb25zdCBmcmFnID0gYFxyXG4gIHByZWNpc2lvbiBoaWdocCBmbG9hdDtcclxuXHJcbiAgdW5pZm9ybSBmbG9hdCBpVGltZTtcclxuICB1bmlmb3JtIHZlYzMgaVJlc29sdXRpb247XHJcbiAgdW5pZm9ybSBmbG9hdCBodWU7XHJcbiAgdW5pZm9ybSBmbG9hdCBob3ZlcjtcclxuICB1bmlmb3JtIGZsb2F0IHJvdDtcclxuICB1bmlmb3JtIGZsb2F0IGhvdmVySW50ZW5zaXR5O1xyXG4gIHVuaWZvcm0gdmVjMyBiYWNrZ3JvdW5kQ29sb3I7XHJcbiAgdmFyeWluZyB2ZWMyIHZVdjtcclxuXHJcbiAgdmVjMyByZ2IyeWlxKHZlYzMgYykge1xyXG4gICAgZmxvYXQgeSA9IGRvdChjLCB2ZWMzKDAuMjk5LCAwLjU4NywgMC4xMTQpKTtcclxuICAgIGZsb2F0IGkgPSBkb3QoYywgdmVjMygwLjU5NiwgLTAuMjc0LCAtMC4zMjIpKTtcclxuICAgIGZsb2F0IHEgPSBkb3QoYywgdmVjMygwLjIxMSwgLTAuNTIzLCAwLjMxMikpO1xyXG4gICAgcmV0dXJuIHZlYzMoeSwgaSwgcSk7XHJcbiAgfVxyXG4gIFxyXG4gIHZlYzMgeWlxMnJnYih2ZWMzIGMpIHtcclxuICAgIGZsb2F0IHIgPSBjLnggKyAwLjk1NiAqIGMueSArIDAuNjIxICogYy56O1xyXG4gICAgZmxvYXQgZyA9IGMueCAtIDAuMjcyICogYy55IC0gMC42NDcgKiBjLno7XHJcbiAgICBmbG9hdCBiID0gYy54IC0gMS4xMDYgKiBjLnkgKyAxLjcwMyAqIGMuejtcclxuICAgIHJldHVybiB2ZWMzKHIsIGcsIGIpO1xyXG4gIH1cclxuICBcclxuICB2ZWMzIGFkanVzdEh1ZSh2ZWMzIGNvbG9yLCBmbG9hdCBodWVEZWcpIHtcclxuICAgIGZsb2F0IGh1ZVJhZCA9IGh1ZURlZyAqIDMuMTQxNTkyNjUgLyAxODAuMDtcclxuICAgIHZlYzMgeWlxID0gcmdiMnlpcShjb2xvcik7XHJcbiAgICBmbG9hdCBjb3NBID0gY29zKGh1ZVJhZCk7XHJcbiAgICBmbG9hdCBzaW5BID0gc2luKGh1ZVJhZCk7XHJcbiAgICBmbG9hdCBpID0geWlxLnkgKiBjb3NBIC0geWlxLnogKiBzaW5BO1xyXG4gICAgZmxvYXQgcSA9IHlpcS55ICogc2luQSArIHlpcS56ICogY29zQTtcclxuICAgIHlpcS55ID0gaTtcclxuICAgIHlpcS56ID0gcTtcclxuICAgIHJldHVybiB5aXEycmdiKHlpcSk7XHJcbiAgfVxyXG5cclxuICB2ZWMzIGhhc2gzMyh2ZWMzIHAzKSB7XHJcbiAgICBwMyA9IGZyYWN0KHAzICogdmVjMygwLjEwMzEsIDAuMTEzNjksIDAuMTM3ODcpKTtcclxuICAgIHAzICs9IGRvdChwMywgcDMueXh6ICsgMTkuMTkpO1xyXG4gICAgcmV0dXJuIC0xLjAgKyAyLjAgKiBmcmFjdCh2ZWMzKFxyXG4gICAgICBwMy54ICsgcDMueSxcclxuICAgICAgcDMueCArIHAzLnosXHJcbiAgICAgIHAzLnkgKyBwMy56XHJcbiAgICApICogcDMuenl4KTtcclxuICB9XHJcblxyXG4gIGZsb2F0IHNub2lzZTModmVjMyBwKSB7XHJcbiAgICBjb25zdCBmbG9hdCBLMSA9IDAuMzMzMzMzMzMzO1xyXG4gICAgY29uc3QgZmxvYXQgSzIgPSAwLjE2NjY2NjY2NztcclxuICAgIHZlYzMgaSA9IGZsb29yKHAgKyAocC54ICsgcC55ICsgcC56KSAqIEsxKTtcclxuICAgIHZlYzMgZDAgPSBwIC0gKGkgLSAoaS54ICsgaS55ICsgaS56KSAqIEsyKTtcclxuICAgIHZlYzMgZSA9IHN0ZXAodmVjMygwLjApLCBkMCAtIGQwLnl6eCk7XHJcbiAgICB2ZWMzIGkxID0gZSAqICgxLjAgLSBlLnp4eSk7XHJcbiAgICB2ZWMzIGkyID0gMS4wIC0gZS56eHkgKiAoMS4wIC0gZSk7XHJcbiAgICB2ZWMzIGQxID0gZDAgLSAoaTEgLSBLMik7XHJcbiAgICB2ZWMzIGQyID0gZDAgLSAoaTIgLSBLMSk7XHJcbiAgICB2ZWMzIGQzID0gZDAgLSAwLjU7XHJcbiAgICB2ZWM0IGggPSBtYXgoMC42IC0gdmVjNChcclxuICAgICAgZG90KGQwLCBkMCksXHJcbiAgICAgIGRvdChkMSwgZDEpLFxyXG4gICAgICBkb3QoZDIsIGQyKSxcclxuICAgICAgZG90KGQzLCBkMylcclxuICAgICksIDAuMCk7XHJcbiAgICB2ZWM0IG4gPSBoICogaCAqIGggKiBoICogdmVjNChcclxuICAgICAgZG90KGQwLCBoYXNoMzMoaSkpLFxyXG4gICAgICBkb3QoZDEsIGhhc2gzMyhpICsgaTEpKSxcclxuICAgICAgZG90KGQyLCBoYXNoMzMoaSArIGkyKSksXHJcbiAgICAgIGRvdChkMywgaGFzaDMzKGkgKyAxLjApKVxyXG4gICAgKTtcclxuICAgIHJldHVybiBkb3QodmVjNCgzMS4zMTYpLCBuKTtcclxuICB9XHJcblxyXG4gIHZlYzQgZXh0cmFjdEFscGhhKHZlYzMgY29sb3JJbikge1xyXG4gICAgZmxvYXQgYSA9IG1heChtYXgoY29sb3JJbi5yLCBjb2xvckluLmcpLCBjb2xvckluLmIpO1xyXG4gICAgcmV0dXJuIHZlYzQoY29sb3JJbi5yZ2IgLyAoYSArIDFlLTUpLCBhKTtcclxuICB9XHJcblxyXG4gIGNvbnN0IHZlYzMgYmFzZUNvbG9yMSA9IHZlYzMoMC42MTE3NjUsIDAuMjYyNzQ1LCAwLjk5NjA3OCk7XHJcbiAgY29uc3QgdmVjMyBiYXNlQ29sb3IyID0gdmVjMygwLjI5ODAzOSwgMC43NjA3ODQsIDAuOTEzNzI1KTtcclxuICBjb25zdCB2ZWMzIGJhc2VDb2xvcjMgPSB2ZWMzKDAuMDYyNzQ1LCAwLjA3ODQzMSwgMC42MDAwMDApO1xyXG4gIGNvbnN0IGZsb2F0IGlubmVyUmFkaXVzID0gMC42O1xyXG4gIGNvbnN0IGZsb2F0IG5vaXNlU2NhbGUgPSAwLjY1O1xyXG5cclxuICBmbG9hdCBsaWdodDEoZmxvYXQgaW50ZW5zaXR5LCBmbG9hdCBhdHRlbnVhdGlvbiwgZmxvYXQgZGlzdCkge1xyXG4gICAgcmV0dXJuIGludGVuc2l0eSAvICgxLjAgKyBkaXN0ICogYXR0ZW51YXRpb24pO1xyXG4gIH1cclxuICBmbG9hdCBsaWdodDIoZmxvYXQgaW50ZW5zaXR5LCBmbG9hdCBhdHRlbnVhdGlvbiwgZmxvYXQgZGlzdCkge1xyXG4gICAgcmV0dXJuIGludGVuc2l0eSAvICgxLjAgKyBkaXN0ICogZGlzdCAqIGF0dGVudWF0aW9uKTtcclxuICB9XHJcblxyXG4gIHZlYzQgZHJhdyh2ZWMyIHV2KSB7XHJcbiAgICB2ZWMzIGNvbG9yMSA9IGFkanVzdEh1ZShiYXNlQ29sb3IxLCBodWUpO1xyXG4gICAgdmVjMyBjb2xvcjIgPSBhZGp1c3RIdWUoYmFzZUNvbG9yMiwgaHVlKTtcclxuICAgIHZlYzMgY29sb3IzID0gYWRqdXN0SHVlKGJhc2VDb2xvcjMsIGh1ZSk7XHJcbiAgICBcclxuICAgIGZsb2F0IGFuZyA9IGF0YW4odXYueSwgdXYueCk7XHJcbiAgICBmbG9hdCBsZW4gPSBsZW5ndGgodXYpO1xyXG4gICAgZmxvYXQgaW52TGVuID0gbGVuID4gMC4wID8gMS4wIC8gbGVuIDogMC4wO1xyXG5cclxuICAgIGZsb2F0IGJnTHVtaW5hbmNlID0gZG90KGJhY2tncm91bmRDb2xvciwgdmVjMygwLjI5OSwgMC41ODcsIDAuMTE0KSk7XHJcbiAgICBcclxuICAgIGZsb2F0IG4wID0gc25vaXNlMyh2ZWMzKHV2ICogbm9pc2VTY2FsZSwgaVRpbWUgKiAwLjUpKSAqIDAuNSArIDAuNTtcclxuICAgIGZsb2F0IHIwID0gbWl4KG1peChpbm5lclJhZGl1cywgMS4wLCAwLjQpLCBtaXgoaW5uZXJSYWRpdXMsIDEuMCwgMC42KSwgbjApO1xyXG4gICAgZmxvYXQgZDAgPSBkaXN0YW5jZSh1diwgKHIwICogaW52TGVuKSAqIHV2KTtcclxuICAgIGZsb2F0IHYwID0gbGlnaHQxKDEuMCwgMTAuMCwgZDApO1xyXG5cclxuICAgIHYwICo9IHNtb290aHN0ZXAocjAgKiAxLjA1LCByMCwgbGVuKTtcclxuICAgIGZsb2F0IGlubmVyRmFkZSA9IHNtb290aHN0ZXAocjAgKiAwLjgsIHIwICogMC45NSwgbGVuKTtcclxuICAgIHYwICo9IG1peChpbm5lckZhZGUsIDEuMCwgYmdMdW1pbmFuY2UgKiAwLjcpO1xyXG4gICAgZmxvYXQgY2wgPSBjb3MoYW5nICsgaVRpbWUgKiAyLjApICogMC41ICsgMC41O1xyXG4gICAgXHJcbiAgICBmbG9hdCBhID0gaVRpbWUgKiAtMS4wO1xyXG4gICAgdmVjMiBwb3MgPSB2ZWMyKGNvcyhhKSwgc2luKGEpKSAqIHIwO1xyXG4gICAgZmxvYXQgZCA9IGRpc3RhbmNlKHV2LCBwb3MpO1xyXG4gICAgZmxvYXQgdjEgPSBsaWdodDIoMS41LCA1LjAsIGQpO1xyXG4gICAgdjEgKj0gbGlnaHQxKDEuMCwgNTAuMCwgZDApO1xyXG4gICAgXHJcbiAgICBmbG9hdCB2MiA9IHNtb290aHN0ZXAoMS4wLCBtaXgoaW5uZXJSYWRpdXMsIDEuMCwgbjAgKiAwLjUpLCBsZW4pO1xyXG4gICAgZmxvYXQgdjMgPSBzbW9vdGhzdGVwKGlubmVyUmFkaXVzLCBtaXgoaW5uZXJSYWRpdXMsIDEuMCwgMC41KSwgbGVuKTtcclxuICAgIFxyXG4gICAgdmVjMyBjb2xCYXNlID0gbWl4KGNvbG9yMSwgY29sb3IyLCBjbCk7XHJcbiAgICBmbG9hdCBmYWRlQW1vdW50ID0gbWl4KDEuMCwgMC4xLCBiZ0x1bWluYW5jZSk7XHJcbiAgICBcclxuICAgIHZlYzMgZGFya0NvbCA9IG1peChjb2xvcjMsIGNvbEJhc2UsIHYwKTtcclxuICAgIGRhcmtDb2wgPSAoZGFya0NvbCArIHYxKSAqIHYyICogdjM7XHJcbiAgICBkYXJrQ29sID0gY2xhbXAoZGFya0NvbCwgMC4wLCAxLjApO1xyXG4gICAgXHJcbiAgICB2ZWMzIGxpZ2h0Q29sID0gKGNvbEJhc2UgKyB2MSkgKiBtaXgoMS4wLCB2MiAqIHYzLCBmYWRlQW1vdW50KTtcclxuICAgIGxpZ2h0Q29sID0gbWl4KGJhY2tncm91bmRDb2xvciwgbGlnaHRDb2wsIHYwKTtcclxuICAgIGxpZ2h0Q29sID0gY2xhbXAobGlnaHRDb2wsIDAuMCwgMS4wKTtcclxuICAgIFxyXG4gICAgdmVjMyBmaW5hbENvbCA9IG1peChkYXJrQ29sLCBsaWdodENvbCwgYmdMdW1pbmFuY2UpO1xyXG4gICAgXHJcbiAgICByZXR1cm4gZXh0cmFjdEFscGhhKGZpbmFsQ29sKTtcclxuICB9XHJcblxyXG4gIHZlYzQgbWFpbkltYWdlKHZlYzIgZnJhZ0Nvb3JkKSB7XHJcbiAgICB2ZWMyIGNlbnRlciA9IGlSZXNvbHV0aW9uLnh5ICogMC41O1xyXG4gICAgZmxvYXQgc2l6ZSA9IG1pbihpUmVzb2x1dGlvbi54LCBpUmVzb2x1dGlvbi55KTtcclxuICAgIHZlYzIgdXYgPSAoZnJhZ0Nvb3JkIC0gY2VudGVyKSAvIHNpemUgKiAyLjA7XHJcbiAgICBcclxuICAgIGZsb2F0IGFuZ2xlID0gcm90O1xyXG4gICAgZmxvYXQgcyA9IHNpbihhbmdsZSk7XHJcbiAgICBmbG9hdCBjID0gY29zKGFuZ2xlKTtcclxuICAgIHV2ID0gdmVjMihjICogdXYueCAtIHMgKiB1di55LCBzICogdXYueCArIGMgKiB1di55KTtcclxuICAgIFxyXG4gICAgdXYueCArPSBob3ZlciAqIGhvdmVySW50ZW5zaXR5ICogMC4xICogc2luKHV2LnkgKiAxMC4wICsgaVRpbWUpO1xyXG4gICAgdXYueSArPSBob3ZlciAqIGhvdmVySW50ZW5zaXR5ICogMC4xICogc2luKHV2LnggKiAxMC4wICsgaVRpbWUpO1xyXG4gICAgXHJcbiAgICByZXR1cm4gZHJhdyh1dik7XHJcbiAgfVxyXG5cclxuICB2b2lkIG1haW4oKSB7XHJcbiAgICB2ZWMyIGZyYWdDb29yZCA9IHZVdiAqIGlSZXNvbHV0aW9uLnh5O1xyXG4gICAgdmVjNCBjb2wgPSBtYWluSW1hZ2UoZnJhZ0Nvb3JkKTtcclxuICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoY29sLnJnYiAqIGNvbC5hLCBjb2wuYSk7XHJcbiAgfVxyXG5gO1xyXG5cclxuZnVuY3Rpb24gaHNsVG9SZ2IoaDogbnVtYmVyLCBzOiBudW1iZXIsIGw6IG51bWJlcik6IFRIUkVFLlZlY3RvcjMge1xyXG4gIGxldCByLCBnLCBiO1xyXG5cclxuICBpZiAocyA9PT0gMCkge1xyXG4gICAgciA9IGcgPSBiID0gbDtcclxuICB9IGVsc2Uge1xyXG4gICAgY29uc3QgaHVlMnJnYiA9IChwOiBudW1iZXIsIHE6IG51bWJlciwgdDogbnVtYmVyKSA9PiB7XHJcbiAgICAgIGlmICh0IDwgMCkgdCArPSAxO1xyXG4gICAgICBpZiAodCA+IDEpIHQgLT0gMTtcclxuICAgICAgaWYgKHQgPCAxIC8gNikgcmV0dXJuIHAgKyAocSAtIHApICogNiAqIHQ7XHJcbiAgICAgIGlmICh0IDwgMSAvIDIpIHJldHVybiBxO1xyXG4gICAgICBpZiAodCA8IDIgLyAzKSByZXR1cm4gcCArIChxIC0gcCkgKiAoMiAvIDMgLSB0KSAqIDY7XHJcbiAgICAgIHJldHVybiBwO1xyXG4gICAgfTtcclxuXHJcbiAgICBjb25zdCBxID0gbCA8IDAuNSA/IGwgKiAoMSArIHMpIDogbCArIHMgLSBsICogcztcclxuICAgIGNvbnN0IHAgPSAyICogbCAtIHE7XHJcbiAgICByID0gaHVlMnJnYihwLCBxLCBoICsgMSAvIDMpO1xyXG4gICAgZyA9IGh1ZTJyZ2IocCwgcSwgaCk7XHJcbiAgICBiID0gaHVlMnJnYihwLCBxLCBoIC0gMSAvIDMpO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIG5ldyBUSFJFRS5WZWN0b3IzKHIsIGcsIGIpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBoZXhUb1ZlYzMoY29sb3I6IHN0cmluZyk6IFRIUkVFLlZlY3RvcjMge1xyXG4gIGlmIChjb2xvci5zdGFydHNXaXRoKCcjJykpIHtcclxuICAgIGNvbnN0IHIgPSBwYXJzZUludChjb2xvci5zbGljZSgxLCAzKSwgMTYpIC8gMjU1O1xyXG4gICAgY29uc3QgZyA9IHBhcnNlSW50KGNvbG9yLnNsaWNlKDMsIDUpLCAxNikgLyAyNTU7XHJcbiAgICBjb25zdCBiID0gcGFyc2VJbnQoY29sb3Iuc2xpY2UoNSwgNyksIDE2KSAvIDI1NTtcclxuICAgIHJldHVybiBuZXcgVEhSRUUuVmVjdG9yMyhyLCBnLCBiKTtcclxuICB9XHJcblxyXG4gIGNvbnN0IHJnYk1hdGNoID0gY29sb3IubWF0Y2goL3JnYmE/XFwoKFxcZCspLFxccyooXFxkKyksXFxzKihcXGQrKS8pO1xyXG4gIGlmIChyZ2JNYXRjaCkge1xyXG4gICAgcmV0dXJuIG5ldyBUSFJFRS5WZWN0b3IzKHBhcnNlSW50KHJnYk1hdGNoWzFdLCAxMCkgLyAyNTUsIHBhcnNlSW50KHJnYk1hdGNoWzJdLCAxMCkgLyAyNTUsIHBhcnNlSW50KHJnYk1hdGNoWzNdLCAxMCkgLyAyNTUpO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgaHNsTWF0Y2ggPSBjb2xvci5tYXRjaCgvaHNsYT9cXCgoXFxkKyksXFxzKihcXGQrKSUsXFxzKihcXGQrKSUvKTtcclxuICBpZiAoaHNsTWF0Y2gpIHtcclxuICAgIGNvbnN0IGggPSBwYXJzZUludChoc2xNYXRjaFsxXSwgMTApIC8gMzYwO1xyXG4gICAgY29uc3QgcyA9IHBhcnNlSW50KGhzbE1hdGNoWzJdLCAxMCkgLyAxMDA7XHJcbiAgICBjb25zdCBsID0gcGFyc2VJbnQoaHNsTWF0Y2hbM10sIDEwKSAvIDEwMDtcclxuICAgIHJldHVybiBoc2xUb1JnYihoLCBzLCBsKTtcclxuICB9XHJcblxyXG4gIHJldHVybiBuZXcgVEhSRUUuVmVjdG9yMygwLCAwLCAwKTtcclxufVxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduYy1vcmItYmFja2dyb3VuZCcsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL29yYi1iYWNrZ3JvdW5kLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9vcmItYmFja2dyb3VuZC5jb21wb25lbnQubGVzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBPcmJCYWNrZ3JvdW5kQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIE9uQ2hhbmdlcyB7XHJcbiAgQFZpZXdDaGlsZCgnY29udGFpbmVyJywgeyBzdGF0aWM6IHRydWUgfSkgY29udGFpbmVyUmVmITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XHJcblxyXG4gIC8qKiDnkIPkvZPnmoTln7rmnKzoibLosIPvvIgwLTM2MO+8iSovXHJcbiAgQElucHV0KCkgbmNIdWU6IG51bWJlciA9IDA7XHJcbiAgLyoqIOaOp+WItuaCrOWBnOaJreabsuaViOaenOeahOW8uuW6pu+8iDAtNe+8iSovXHJcbiAgQElucHV0KCkgbmNIb3ZlckludGVuc2l0eTogbnVtYmVyID0gMjtcclxuICAvKiog5YiH5o2i5byA5YWz5Lul5ZCv55So5oiW56aB55So6byg5qCH5oKs5YGc5pe255qE6L+e57ut5peL6L2sICovXHJcbiAgcHJpdmF0ZSBfcm90YXRlT25Ib3ZlcjogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KClcclxuICBzZXQgbmNSb3RhdGVPbkhvdmVyKHZhbDogYm9vbGVhbiB8IHN0cmluZykge1xyXG4gICAgdGhpcy5fcm90YXRlT25Ib3ZlciA9IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09IGZhbHNlICYmIHZhbCAhPT0gJ2ZhbHNlJztcclxuICB9XHJcbiAgZ2V0IG5jUm90YXRlT25Ib3ZlcigpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9yb3RhdGVPbkhvdmVyO1xyXG4gIH1cclxuICAvKiog5Y2z5L2/55CD5L2T5a6e6ZmF5LiK5bm25pyq5oKs5YGc77yM5Lmf5by65Yi25pi+56S65oKs5YGc5Yqo55S7ICovXHJcbiAgcHJpdmF0ZSBfZm9yY2VIb3ZlclN0YXRlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KClcclxuICBzZXQgbmNGb3JjZUhvdmVyU3RhdGUodmFsOiBib29sZWFuIHwgc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9mb3JjZUhvdmVyU3RhdGUgPSB2YWwgIT09IG51bGwgJiYgdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBmYWxzZSAmJiB2YWwgIT09ICdmYWxzZSc7XHJcbiAgfVxyXG4gIGdldCBuY0ZvcmNlSG92ZXJTdGF0ZSgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLl9mb3JjZUhvdmVyU3RhdGU7XHJcbiAgfVxyXG4gIC8qKiDlrrnlmajnmoTog4zmma/popzoibLvvIzljYHlha3ov5vliLbmoLzlvI8gKi9cclxuICBASW5wdXQoKSBuY0JhY2tncm91bmRDb2xvcjogc3RyaW5nID0gJyMwMDAwMDAnO1xyXG5cclxuICBwcml2YXRlIHJlbmRlcmVyITogVEhSRUUuV2ViR0xSZW5kZXJlcjtcclxuICBwcml2YXRlIHNjZW5lITogVEhSRUUuU2NlbmU7XHJcbiAgcHJpdmF0ZSBjYW1lcmEhOiBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmE7XHJcbiAgcHJpdmF0ZSBtYXRlcmlhbCE6IFRIUkVFLlJhd1NoYWRlck1hdGVyaWFsO1xyXG4gIHByaXZhdGUgcGxhbmUhOiBUSFJFRS5NZXNoO1xyXG5cclxuICBwcml2YXRlIHJlc2l6ZU9ic2VydmVyITogUmVzaXplT2JzZXJ2ZXI7XHJcbiAgcHJpdmF0ZSBpbnRlcnNlY3Rpb25PYnNlcnZlciE6IEludGVyc2VjdGlvbk9ic2VydmVyO1xyXG4gIHByaXZhdGUgcmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVzaXplUmFmSWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgaXNWaXNpYmxlID0gdHJ1ZTtcclxuXHJcbiAgcHJpdmF0ZSB0YXJnZXRIb3ZlciA9IDA7XHJcbiAgcHJpdmF0ZSBsYXN0VGltZSA9IDA7XHJcbiAgcHJpdmF0ZSBjdXJyZW50Um90ID0gMDtcclxuICBwcml2YXRlIHJvdGF0aW9uU3BlZWQgPSAwLjM7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgbmdab25lOiBOZ1pvbmUpIHsgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHsgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICB0aGlzLmluaXRXZWJHTCgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmNsZWFudXAoKTtcclxuICB9XHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm1hdGVyaWFsKSB7XHJcbiAgICAgIGlmIChjaGFuZ2VzWyduY0h1ZSddKSB7XHJcbiAgICAgICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1snaHVlJ10udmFsdWUgPSB0aGlzLm5jSHVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChjaGFuZ2VzWyduY0hvdmVySW50ZW5zaXR5J10pIHtcclxuICAgICAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWydob3ZlckludGVuc2l0eSddLnZhbHVlID0gdGhpcy5uY0hvdmVySW50ZW5zaXR5O1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChjaGFuZ2VzWyduY0JhY2tncm91bmRDb2xvciddKSB7XHJcbiAgICAgICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1snYmFja2dyb3VuZENvbG9yJ10udmFsdWUgPSBoZXhUb1ZlYzModGhpcy5uY0JhY2tncm91bmRDb2xvcik7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgaW5pdFdlYkdMKCk6IHZvaWQge1xyXG4gICAgY29uc3QgY29udGFpbmVyID0gdGhpcy5jb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoeyBhbHBoYTogdHJ1ZSwgYW50aWFsaWFzOiB0cnVlLCBwcmVtdWx0aXBsaWVkQWxwaGE6IGZhbHNlIH0pO1xyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRDbGVhckNvbG9yKDB4MDAwMDAwLCAwKTsgLy8gVHJhbnNwYXJlbnQgYmFja2dyb3VuZCBtYXRjaGluZyBXZWJHTCBjbGVhckNvbG9yKDAsMCwwLDApXHJcbiAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5yZW5kZXJlci5kb21FbGVtZW50KTtcclxuXHJcbiAgICB0aGlzLnNjZW5lID0gbmV3IFRIUkVFLlNjZW5lKCk7XHJcbiAgICB0aGlzLmNhbWVyYSA9IG5ldyBUSFJFRS5PcnRob2dyYXBoaWNDYW1lcmEoLTEsIDEsIDEsIC0xLCAwLCAxKTtcclxuXHJcbiAgICBjb25zdCBnZW9tZXRyeSA9IG5ldyBUSFJFRS5QbGFuZUdlb21ldHJ5KDIsIDIpO1xyXG5cclxuICAgIHRoaXMubWF0ZXJpYWwgPSBuZXcgVEhSRUUuUmF3U2hhZGVyTWF0ZXJpYWwoe1xyXG4gICAgICB2ZXJ0ZXhTaGFkZXI6IHZlcnQsXHJcbiAgICAgIGZyYWdtZW50U2hhZGVyOiBmcmFnLFxyXG4gICAgICB0cmFuc3BhcmVudDogZmFsc2UsXHJcbiAgICAgIGJsZW5kaW5nOiBUSFJFRS5Ob0JsZW5kaW5nLFxyXG4gICAgICB1bmlmb3Jtczoge1xyXG4gICAgICAgIGlUaW1lOiB7IHZhbHVlOiAwIH0sXHJcbiAgICAgICAgaVJlc29sdXRpb246IHsgdmFsdWU6IG5ldyBUSFJFRS5WZWN0b3IzKDEsIDEsIDEpIH0sXHJcbiAgICAgICAgaHVlOiB7IHZhbHVlOiB0aGlzLm5jSHVlIH0sXHJcbiAgICAgICAgaG92ZXI6IHsgdmFsdWU6IDAgfSxcclxuICAgICAgICByb3Q6IHsgdmFsdWU6IDAgfSxcclxuICAgICAgICBob3ZlckludGVuc2l0eTogeyB2YWx1ZTogdGhpcy5uY0hvdmVySW50ZW5zaXR5IH0sXHJcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB7IHZhbHVlOiBoZXhUb1ZlYzModGhpcy5uY0JhY2tncm91bmRDb2xvcikgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLnBsYW5lID0gbmV3IFRIUkVFLk1lc2goZ2VvbWV0cnksIHRoaXMubWF0ZXJpYWwpO1xyXG4gICAgdGhpcy5zY2VuZS5hZGQodGhpcy5wbGFuZSk7XHJcblxyXG4gICAgdGhpcy5zZXR1cFJlc2l6ZU9ic2VydmVyKGNvbnRhaW5lcik7XHJcbiAgICB0aGlzLnNldHVwSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoY29udGFpbmVyKTtcclxuXHJcbiAgICB0aGlzLmxhc3RUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XHJcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgIGNvbnN0IGxvb3AgPSAodDogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgdGhpcy5yYWZJZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShsb29wKTtcclxuICAgICAgICBpZiAodGhpcy5pc1Zpc2libGUpIHtcclxuICAgICAgICAgIHRoaXMudXBkYXRlKHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuICAgICAgbG9vcChwZXJmb3JtYW5jZS5ub3coKSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlKHQ6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3QgZHQgPSAodCAtIHRoaXMubGFzdFRpbWUpICogMC4wMDE7XHJcbiAgICB0aGlzLmxhc3RUaW1lID0gdDtcclxuXHJcbiAgICB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWydpVGltZSddLnZhbHVlID0gdCAqIDAuMDAxO1xyXG5cclxuICAgIGNvbnN0IGVmZmVjdGl2ZUhvdmVyID0gdGhpcy5uY0ZvcmNlSG92ZXJTdGF0ZSA/IDEgOiB0aGlzLnRhcmdldEhvdmVyO1xyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1snaG92ZXInXS52YWx1ZSArPSAoZWZmZWN0aXZlSG92ZXIgLSB0aGlzLm1hdGVyaWFsLnVuaWZvcm1zWydob3ZlciddLnZhbHVlKSAqIDAuMTtcclxuXHJcbiAgICBpZiAodGhpcy5uY1JvdGF0ZU9uSG92ZXIgJiYgZWZmZWN0aXZlSG92ZXIgPiAwLjUpIHtcclxuICAgICAgdGhpcy5jdXJyZW50Um90ICs9IGR0ICogdGhpcy5yb3RhdGlvblNwZWVkO1xyXG4gICAgfVxyXG4gICAgdGhpcy5tYXRlcmlhbC51bmlmb3Jtc1sncm90J10udmFsdWUgPSB0aGlzLmN1cnJlbnRSb3Q7XHJcblxyXG4gICAgdGhpcy5yZW5kZXJlci5yZW5kZXIodGhpcy5zY2VuZSwgdGhpcy5jYW1lcmEpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVSZXNpemUoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuY29udGFpbmVyUmVmIHx8ICF0aGlzLnJlbmRlcmVyKSByZXR1cm47XHJcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLmNvbnRhaW5lclJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgY29uc3QgZHByID0gTWF0aC5taW4od2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgMSwgMik7XHJcbiAgICBjb25zdCB3aWR0aCA9IGNvbnRhaW5lci5jbGllbnRXaWR0aCB8fCAxO1xyXG4gICAgY29uc3QgaGVpZ2h0ID0gY29udGFpbmVyLmNsaWVudEhlaWdodCB8fCAxO1xyXG5cclxuICAgIHRoaXMucmVuZGVyZXIuc2V0UGl4ZWxSYXRpbyhkcHIpO1xyXG4gICAgdGhpcy5yZW5kZXJlci5zZXRTaXplKHdpZHRoLCBoZWlnaHQsIGZhbHNlKTtcclxuXHJcbiAgICBjb25zdCBjYW52YXMgPSB0aGlzLnJlbmRlcmVyLmRvbUVsZW1lbnQ7XHJcbiAgICBjYW52YXMuc3R5bGUud2lkdGggPSAnMTAwJSc7XHJcbiAgICBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xyXG4gICAgY2FudmFzLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG5cclxuICAgIGlmICh0aGlzLm1hdGVyaWFsKSB7XHJcbiAgICAgIHRoaXMubWF0ZXJpYWwudW5pZm9ybXNbJ2lSZXNvbHV0aW9uJ10udmFsdWUuc2V0KGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCwgY2FudmFzLndpZHRoIC8gY2FudmFzLmhlaWdodCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwUmVzaXplT2JzZXJ2ZXIoY29udGFpbmVyOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLnJlc2l6ZVJhZklkICE9PSBudWxsKSBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJlc2l6ZVJhZklkKTtcclxuICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVzaXplUmFmSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5oYW5kbGVSZXNpemUoKTtcclxuICAgICAgICAgIHRoaXMucmVzaXplUmFmSWQgPSBudWxsO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKGNvbnRhaW5lcik7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoY29udGFpbmVyOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlciA9IG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcihlbnRyaWVzID0+IHtcclxuICAgICAgY29uc3QgZW50cnkgPSBlbnRyaWVzWzBdO1xyXG4gICAgICB0aGlzLmlzVmlzaWJsZSA9IGVudHJ5LmlzSW50ZXJzZWN0aW5nICYmIGVudHJ5LmludGVyc2VjdGlvblJhdGlvID4gMDtcclxuICAgIH0sIHsgdGhyZXNob2xkOiBbMCwgMC4wMSwgMC4xXSB9KTtcclxuICAgIHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIub2JzZXJ2ZShjb250YWluZXIpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbGVhbnVwKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMucmFmSWQgIT09IG51bGwpIHsgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5yYWZJZCk7IHRoaXMucmFmSWQgPSBudWxsOyB9XHJcbiAgICBpZiAodGhpcy5yZXNpemVSYWZJZCAhPT0gbnVsbCkgeyBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJlc2l6ZVJhZklkKTsgdGhpcy5yZXNpemVSYWZJZCA9IG51bGw7IH1cclxuICAgIHRyeSB7IHRoaXMucmVzaXplT2