UNPKG

ngx-acuw

Version:

Angular components using WEBGL (threejs)

354 lines (344 loc) 35.5 kB
export class ImageTransitionShaders { constructor() { this.vertex = `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );}`; this.splitTransitionFrag = ` uniform float progress; uniform float intensity; uniform sampler2D texture1; uniform sampler2D texture2; uniform vec4 resolution1; uniform vec4 resolution2; varying vec2 vUv; mat2 rotate(float a) { float s = sin(a); float c = cos(a); return mat2(c, -s, s, c); } void main() { vec2 newUV1 = (vUv - vec2(0.5,0.5))*resolution1.zw + vec2(0.5,0.5); vec2 newUV2 = (vUv - vec2(0.5,0.5))*resolution2.zw + vec2(0.5,0.5); vec2 uvDivided1 = fract(newUV1*vec2(intensity,1.)); vec2 uvDivided2 = fract(newUV2*vec2(intensity,1.)); vec2 uvDisplaced1 = newUV1 + rotate(3.1415926/4.)*uvDivided1*progress*0.1; vec2 uvDisplaced2 = newUV2 + rotate(3.1415926/4.)*uvDivided2*(1. - progress)*0.1; vec4 t1 = texture2D(texture1,uvDisplaced1); vec4 t2 = texture2D(texture2,uvDisplaced2); // Use black background color // Top right vec2 tr1 = step(newUV1, vec2(1.0, 1.0)); vec2 tr2 = step(newUV2, vec2(1.0, 1.0)); float pct1 = tr1.x * tr1.y; float pct2 = tr2.x * tr2.y; // Bottom left vec2 bl1 = step(vec2(0.0, 0.0), newUV1); vec2 bl2 = step(vec2(0.0, 0.0), newUV2); pct1 *= bl1.x * bl1.y; pct2 *= bl2.x * bl2.y; vec4 t1wb = t1 * vec4(pct1,pct1,pct1,1.0); vec4 t2wb = t2 * vec4(pct2,pct2,pct2,1.0); gl_FragColor = mix(t1wb, t2wb, progress); } `; this.fadeFrag = ` uniform float progress; uniform sampler2D texture1; uniform sampler2D texture2; uniform vec4 resolution1; uniform vec4 resolution2; varying vec2 vUv; mat2 rotate(float a) { float s = sin(a); float c = cos(a); return mat2(c, -s, s, c); } void main() { vec2 newUV1 = (vUv - vec2(0.5,0.5))*resolution1.zw + vec2(0.5,0.5); vec2 newUV2 = (vUv - vec2(0.5,0.5))*resolution2.zw + vec2(0.5,0.5); vec2 uvDisplaced1 = newUV1 + vec2(1.0,0)*progress*0.1; vec2 uvDisplaced2 = newUV2 + vec2(1.0,0)*(1. - progress)*0.1; vec4 t1 = texture2D(texture1,uvDisplaced1); vec4 t2 = texture2D(texture2,uvDisplaced2); // Use black background color // Top right vec2 tr1 = step(newUV1, vec2(1.0, 1.0)); vec2 tr2 = step(newUV2, vec2(1.0, 1.0)); float pct1 = tr1.x * tr1.y; float pct2 = tr2.x * tr2.y; // Bottom left vec2 bl1 = step(vec2(0.0, 0.0), newUV1); vec2 bl2 = step(vec2(0.0, 0.0), newUV2); pct1 *= bl1.x * bl1.y; pct2 *= bl2.x * bl2.y; vec4 t1wb = t1 * vec4(pct1,pct1,pct1,1.0); vec4 t2wb = t2 * vec4(pct2,pct2,pct2,1.0); gl_FragColor = mix(t1wb, t2wb, progress); } `; this.noiseFrag = ` uniform float time; uniform float progress; uniform float width; uniform float scaleX; uniform float scaleY; uniform sampler2D texture1; uniform sampler2D texture2; uniform sampler2D displacement; uniform vec4 resolution1; uniform vec4 resolution2; varying vec2 vUv; varying vec4 vPosition; // Classic Perlin 3D Noise // by Stefan Gustavson // vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} vec4 fade(vec4 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);} float cnoise(vec4 P){ ; vec4 Pi0 = floor(P); // Integer part for indexing vec4 Pi1 = Pi0 + 1.0; // Integer part + 1 Pi0 = mod(Pi0, 289.0); Pi1 = mod(Pi1, 289.0); vec4 Pf0 = fract(P); // Fractional part for interpolation vec4 Pf1 = Pf0 - 1.0; // Fractional part - 1.0 vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); vec4 iy = vec4(Pi0.yy, Pi1.yy); vec4 iz0 = vec4(Pi0.zzzz); vec4 iz1 = vec4(Pi1.zzzz); vec4 iw0 = vec4(Pi0.wwww); vec4 iw1 = vec4(Pi1.wwww); vec4 ixy = permute(permute(ix) + iy); vec4 ixy0 = permute(ixy + iz0); vec4 ixy1 = permute(ixy + iz1); vec4 ixy00 = permute(ixy0 + iw0); vec4 ixy01 = permute(ixy0 + iw1); vec4 ixy10 = permute(ixy1 + iw0); vec4 ixy11 = permute(ixy1 + iw1); vec4 gx00 = ixy00 / 7.0; vec4 gy00 = floor(gx00) / 7.0; vec4 gz00 = floor(gy00) / 6.0; gx00 = fract(gx00) - 0.5; gy00 = fract(gy00) - 0.5; gz00 = fract(gz00) - 0.5; vec4 gw00 = vec4(0.75) - abs(gx00) - abs(gy00) - abs(gz00); vec4 sw00 = step(gw00, vec4(0.0)); gx00 -= sw00 * (step(0.0, gx00) - 0.5); gy00 -= sw00 * (step(0.0, gy00) - 0.5); vec4 gx01 = ixy01 / 7.0; vec4 gy01 = floor(gx01) / 7.0; vec4 gz01 = floor(gy01) / 6.0; gx01 = fract(gx01) - 0.5; gy01 = fract(gy01) - 0.5; gz01 = fract(gz01) - 0.5; vec4 gw01 = vec4(0.75) - abs(gx01) - abs(gy01) - abs(gz01); vec4 sw01 = step(gw01, vec4(0.0)); gx01 -= sw01 * (step(0.0, gx01) - 0.5); gy01 -= sw01 * (step(0.0, gy01) - 0.5); vec4 gx10 = ixy10 / 7.0; vec4 gy10 = floor(gx10) / 7.0; vec4 gz10 = floor(gy10) / 6.0; gx10 = fract(gx10) - 0.5; gy10 = fract(gy10) - 0.5; gz10 = fract(gz10) - 0.5; vec4 gw10 = vec4(0.75) - abs(gx10) - abs(gy10) - abs(gz10); vec4 sw10 = step(gw10, vec4(0.0)); gx10 -= sw10 * (step(0.0, gx10) - 0.5); gy10 -= sw10 * (step(0.0, gy10) - 0.5); vec4 gx11 = ixy11 / 7.0; vec4 gy11 = floor(gx11) / 7.0; vec4 gz11 = floor(gy11) / 6.0; gx11 = fract(gx11) - 0.5; gy11 = fract(gy11) - 0.5; gz11 = fract(gz11) - 0.5; vec4 gw11 = vec4(0.75) - abs(gx11) - abs(gy11) - abs(gz11); vec4 sw11 = step(gw11, vec4(0.0)); gx11 -= sw11 * (step(0.0, gx11) - 0.5); gy11 -= sw11 * (step(0.0, gy11) - 0.5); vec4 g0000 = vec4(gx00.x,gy00.x,gz00.x,gw00.x); vec4 g1000 = vec4(gx00.y,gy00.y,gz00.y,gw00.y); vec4 g0100 = vec4(gx00.z,gy00.z,gz00.z,gw00.z); vec4 g1100 = vec4(gx00.w,gy00.w,gz00.w,gw00.w); vec4 g0010 = vec4(gx10.x,gy10.x,gz10.x,gw10.x); vec4 g1010 = vec4(gx10.y,gy10.y,gz10.y,gw10.y); vec4 g0110 = vec4(gx10.z,gy10.z,gz10.z,gw10.z); vec4 g1110 = vec4(gx10.w,gy10.w,gz10.w,gw10.w); vec4 g0001 = vec4(gx01.x,gy01.x,gz01.x,gw01.x); vec4 g1001 = vec4(gx01.y,gy01.y,gz01.y,gw01.y); vec4 g0101 = vec4(gx01.z,gy01.z,gz01.z,gw01.z); vec4 g1101 = vec4(gx01.w,gy01.w,gz01.w,gw01.w); vec4 g0011 = vec4(gx11.x,gy11.x,gz11.x,gw11.x); vec4 g1011 = vec4(gx11.y,gy11.y,gz11.y,gw11.y); vec4 g0111 = vec4(gx11.z,gy11.z,gz11.z,gw11.z); vec4 g1111 = vec4(gx11.w,gy11.w,gz11.w,gw11.w); vec4 norm00 = taylorInvSqrt(vec4(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); g0000 *= norm00.x; g0100 *= norm00.y; g1000 *= norm00.z; g1100 *= norm00.w; vec4 norm01 = taylorInvSqrt(vec4(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); g0001 *= norm01.x; g0101 *= norm01.y; g1001 *= norm01.z; g1101 *= norm01.w; vec4 norm10 = taylorInvSqrt(vec4(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); g0010 *= norm10.x; g0110 *= norm10.y; g1010 *= norm10.z; g1110 *= norm10.w; vec4 norm11 = taylorInvSqrt(vec4(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); g0011 *= norm11.x; g0111 *= norm11.y; g1011 *= norm11.z; g1111 *= norm11.w; float n0000 = dot(g0000, Pf0); float n1000 = dot(g1000, vec4(Pf1.x, Pf0.yzw)); float n0100 = dot(g0100, vec4(Pf0.x, Pf1.y, Pf0.zw)); float n1100 = dot(g1100, vec4(Pf1.xy, Pf0.zw)); float n0010 = dot(g0010, vec4(Pf0.xy, Pf1.z, Pf0.w)); float n1010 = dot(g1010, vec4(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); float n0110 = dot(g0110, vec4(Pf0.x, Pf1.yz, Pf0.w)); float n1110 = dot(g1110, vec4(Pf1.xyz, Pf0.w)); float n0001 = dot(g0001, vec4(Pf0.xyz, Pf1.w)); float n1001 = dot(g1001, vec4(Pf1.x, Pf0.yz, Pf1.w)); float n0101 = dot(g0101, vec4(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); float n1101 = dot(g1101, vec4(Pf1.xy, Pf0.z, Pf1.w)); float n0011 = dot(g0011, vec4(Pf0.xy, Pf1.zw)); float n1011 = dot(g1011, vec4(Pf1.x, Pf0.y, Pf1.zw)); float n0111 = dot(g0111, vec4(Pf0.x, Pf1.yzw)); float n1111 = dot(g1111, Pf1); vec4 fade_xyzw = fade(Pf0); vec4 n_0w = mix(vec4(n0000, n1000, n0100, n1100), vec4(n0001, n1001, n0101, n1101), fade_xyzw.w); vec4 n_1w = mix(vec4(n0010, n1010, n0110, n1110), vec4(n0011, n1011, n0111, n1111), fade_xyzw.w); vec4 n_zw = mix(n_0w, n_1w, fade_xyzw.z); vec2 n_yzw = mix(n_zw.xy, n_zw.zw, fade_xyzw.y); float n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); return 2.2 * n_xyzw; } float map(float value, float min1, float max1, float min2, float max2) { return min2 + (value - min1) * (max2 - min2) / (max1 - min1); } float parabola( float x, float k ) { return pow( 4. * x * ( 1. - x ), k ); } void main() { float dt = parabola(progress,1.); float border = 1.; vec2 newUV1 = (vUv - vec2(0.5,0.5))*resolution1.zw + vec2(0.5,0.5); vec2 newUV2 = (vUv - vec2(0.5,0.5))*resolution2.zw + vec2(0.5,0.5); vec4 t1 = texture2D(texture1,newUV1); vec4 t2 = texture2D(texture2,newUV2); // Use black background color // Top right vec2 tr1 = step(newUV1, vec2(1.0, 1.0)); vec2 tr2 = step(newUV2, vec2(1.0, 1.0)); float pct1 = tr1.x * tr1.y; float pct2 = tr2.x * tr2.y; // Bottom left vec2 bl1 = step(vec2(0.0, 0.0), newUV1); vec2 bl2 = step(vec2(0.0, 0.0), newUV2); pct1 *= bl1.x * bl1.y; pct2 *= bl2.x * bl2.y; vec4 t1wb = t1 * vec4(pct1,pct1,pct1,1.0); vec4 t2wb = t2 * vec4(pct2,pct2,pct2,1.0); float realnoise = 0.5*(cnoise(vec4(newUV1.x*scaleX + 0.*time/3., newUV1.y*scaleY,0.*time/3.,0.)) +1.); float w = width*dt; float maskvalue = smoothstep(1. - w,1.,vUv.x + mix(-w/2., 1. - w/2., progress)); float mask = maskvalue + maskvalue*realnoise; float final = smoothstep(border,border+0.01,mask); gl_FragColor = mix(t1wb,t2wb,final); } `; this.blurFrag = ` // author: gre // license: MIT uniform float progress; uniform float intensity; uniform float ratio; uniform sampler2D texture1; uniform sampler2D texture2; uniform vec4 resolution1; uniform vec4 resolution2; varying vec2 vUv; const int passes = 6; void main() { vec2 newUV1 = (vUv - vec2(0.5,0.5))*resolution1.zw + vec2(0.5,0.5); vec2 newUV2 = (vUv - vec2(0.5,0.5))*resolution2.zw + vec2(0.5,0.5); vec4 t1 = vec4(0.0); vec4 t2 = vec4(0.0); float disp = intensity/100.0*(0.5-distance(0.5, progress)); for (int xi=0; xi<passes; xi++) { float x = float(xi) / float(passes) - 0.5; for (int yi=0; yi<passes; yi++) { float y = float(yi) / float(passes) - 0.5; vec2 v = vec2(x,y); float d = disp; t1 += texture2D(texture1,newUV1 + d*v); t2 += texture2D(texture2,newUV2 + d*v); } } t1 /= float(passes*passes); t2 /= float(passes*passes); // Use black background color // Top right vec2 tr1 = step(newUV1, vec2(1.0, 1.0)); vec2 tr2 = step(newUV2, vec2(1.0, 1.0)); float pct1 = tr1.x * tr1.y; float pct2 = tr2.x * tr2.y; // Bottom left vec2 bl1 = step(vec2(0.0, 0.0), newUV1); vec2 bl2 = step(vec2(0.0, 0.0), newUV2); pct1 *= bl1.x * bl1.y; pct2 *= bl2.x * bl2.y; vec4 t1wb = t1 * vec4(pct1,pct1,pct1,1.0); vec4 t2wb = t2 * vec4(pct2,pct2,pct2,1.0); gl_FragColor = mix(t1wb, t2wb, progress); } `; this.distortionFrag = ` uniform float progress; uniform sampler2D displacementTexture; uniform sampler2D texture1; uniform sampler2D texture2; uniform vec4 resolution1; uniform vec4 resolution2; uniform float angle1; uniform float angle2; uniform float intensity; varying vec2 vUv; mat2 getRotM(float angle) { float s = sin(angle); float c = cos(angle); return mat2(c, -s, s, c); } void main() { vec2 newUV1 = (vUv - vec2(0.5,0.5))*resolution1.zw + vec2(0.5,0.5); vec2 newUV2 = (vUv - vec2(0.5,0.5))*resolution2.zw + vec2(0.5,0.5); vec4 t1 = texture2D(texture1,newUV1); vec4 t2 = texture2D(texture2,newUV2); vec4 disp = texture2D(displacementTexture, newUV1); vec2 dispVec = vec2(disp.r, disp.g); vec2 distortedPosition1 = newUV1 + getRotM(angle1) * dispVec * intensity / 100.0 * progress; vec2 distortedPosition2 = newUV2 + getRotM(angle2) * dispVec * intensity / 100.0 * (1.0 - progress); vec4 t1d = texture2D(texture1, distortedPosition1); vec4 t2d = texture2D(texture2, distortedPosition2); // Use black background color // Top right vec2 tr1 = step(newUV1, vec2(1.0, 1.0)); vec2 tr2 = step(newUV2, vec2(1.0, 1.0)); float pct1 = tr1.x * tr1.y; float pct2 = tr2.x * tr2.y; // Bottom left vec2 bl1 = step(vec2(0.0, 0.0), newUV1); vec2 bl2 = step(vec2(0.0, 0.0), newUV2); pct1 *= bl1.x * bl1.y; pct2 *= bl2.x * bl2.y; vec4 t1wb = t1d * vec4(pct1,pct1,pct1,1.0); vec4 t2wb = t2d * vec4(pct2,pct2,pct2,1.0); gl_FragColor = mix(t1wb, t2wb, progress); } `; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2VUcmFuc2l0aW9uU2hhZGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1hY3V3L3NyYy9saWIvaW1hZ2UtdHJhbnNpdGlvbi9zaGFkZXJzL2ltYWdlVHJhbnNpdGlvblNoYWRlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxPQUFPLHNCQUFzQjtJQUFuQztRQUNJLFdBQU0sR0FBRyxtSEFBbUgsQ0FBQztRQUM3SCx3QkFBbUIsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztLQXFDckIsQ0FBQztRQUNGLGFBQVEsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztLQWtDVixDQUFDO1FBQ0YsY0FBUyxHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQTZLZCxDQUFDO1FBQ0MsYUFBUSxHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFtRGIsQ0FBQztRQUNGLG1CQUFjLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQWdEaEIsQ0FBQztJQUNILENBQUM7Q0FBQSIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBJbWFnZVRyYW5zaXRpb25TaGFkZXJze1xyXG4gICAgdmVydGV4ID0gYHZhcnlpbmcgdmVjMiB2VXY7dm9pZCBtYWluKCkge3ZVdiA9IHV2O2dsX1Bvc2l0aW9uID0gcHJvamVjdGlvbk1hdHJpeCAqIG1vZGVsVmlld01hdHJpeCAqIHZlYzQoIHBvc2l0aW9uLCAxLjAgKTt9YDtcclxuICAgIHNwbGl0VHJhbnNpdGlvbkZyYWcgPSBgXHJcbiAgICAgICAgICAgIHVuaWZvcm0gZmxvYXQgcHJvZ3Jlc3M7XHJcbiAgICAgICAgICAgIHVuaWZvcm0gZmxvYXQgaW50ZW5zaXR5O1xyXG4gICAgICAgICAgICB1bmlmb3JtIHNhbXBsZXIyRCB0ZXh0dXJlMTtcclxuICAgICAgICAgICAgdW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTI7XHJcbiAgICAgICAgICAgIHVuaWZvcm0gdmVjNCByZXNvbHV0aW9uMTtcclxuICAgICAgICAgICAgdW5pZm9ybSB2ZWM0IHJlc29sdXRpb24yO1xyXG4gICAgICAgICAgICB2YXJ5aW5nIHZlYzIgdlV2O1xyXG4gICAgICAgICAgICBtYXQyIHJvdGF0ZShmbG9hdCBhKSB7XHJcbiAgICAgICAgICAgICAgZmxvYXQgcyA9IHNpbihhKTtcclxuICAgICAgICAgICAgICBmbG9hdCBjID0gY29zKGEpO1xyXG4gICAgICAgICAgICAgIHJldHVybiBtYXQyKGMsIC1zLCBzLCBjKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB2b2lkIG1haW4oKVx0e1xyXG4gICAgICAgICAgICAgIHZlYzIgbmV3VVYxID0gKHZVdiAtIHZlYzIoMC41LDAuNSkpKnJlc29sdXRpb24xLnp3ICsgdmVjMigwLjUsMC41KTtcclxuICAgICAgICAgICAgICB2ZWMyIG5ld1VWMiA9ICh2VXYgLSB2ZWMyKDAuNSwwLjUpKSpyZXNvbHV0aW9uMi56dyArIHZlYzIoMC41LDAuNSk7XHJcbiAgICAgICAgICAgICAgdmVjMiB1dkRpdmlkZWQxID0gZnJhY3QobmV3VVYxKnZlYzIoaW50ZW5zaXR5LDEuKSk7XHJcbiAgICAgICAgICAgICAgdmVjMiB1dkRpdmlkZWQyID0gZnJhY3QobmV3VVYyKnZlYzIoaW50ZW5zaXR5LDEuKSk7XHJcbiAgICAgICAgICAgICAgdmVjMiB1dkRpc3BsYWNlZDEgPSBuZXdVVjEgKyByb3RhdGUoMy4xNDE1OTI2LzQuKSp1dkRpdmlkZWQxKnByb2dyZXNzKjAuMTtcclxuICAgICAgICAgICAgICB2ZWMyIHV2RGlzcGxhY2VkMiA9IG5ld1VWMiArIHJvdGF0ZSgzLjE0MTU5MjYvNC4pKnV2RGl2aWRlZDIqKDEuIC0gcHJvZ3Jlc3MpKjAuMTtcclxuICAgICAgICAgICAgICB2ZWM0IHQxID0gdGV4dHVyZTJEKHRleHR1cmUxLHV2RGlzcGxhY2VkMSk7XHJcbiAgICAgICAgICAgICAgdmVjNCB0MiA9IHRleHR1cmUyRCh0ZXh0dXJlMix1dkRpc3BsYWNlZDIpO1xyXG4gICAgICAgICAgICAgIC8vIFVzZSBibGFjayBiYWNrZ3JvdW5kIGNvbG9yXHJcbiAgICAgICAgICAgICAgLy8gVG9wIHJpZ2h0XHJcbiAgICAgICAgICAgICAgdmVjMiB0cjEgPSBzdGVwKG5ld1VWMSwgdmVjMigxLjAsIDEuMCkpO1xyXG4gICAgICAgICAgICAgIHZlYzIgdHIyID0gc3RlcChuZXdVVjIsIHZlYzIoMS4wLCAxLjApKTtcclxuICAgICAgICAgICAgICBmbG9hdCBwY3QxID0gdHIxLnggKiB0cjEueTtcclxuICAgICAgICAgICAgICBmbG9hdCBwY3QyID0gdHIyLnggKiB0cjIueTtcclxuICAgICAgICAgICAgICAvLyBCb3R0b20gbGVmdFxyXG4gICAgICAgICAgICAgIHZlYzIgYmwxID0gc3RlcCh2ZWMyKDAuMCwgMC4wKSwgbmV3VVYxKTtcclxuICAgICAgICAgICAgICB2ZWMyIGJsMiA9IHN0ZXAodmVjMigwLjAsIDAuMCksIG5ld1VWMik7XHJcbiAgICAgICAgICAgICAgcGN0MSAqPSBibDEueCAqIGJsMS55O1xyXG4gICAgICAgICAgICAgIHBjdDIgKj0gYmwyLnggKiBibDIueTtcclxuICAgICAgICAgICAgICB2ZWM0IHQxd2IgPSB0MSAqIHZlYzQocGN0MSxwY3QxLHBjdDEsMS4wKTtcclxuICAgICAgICAgICAgICB2ZWM0IHQyd2IgPSB0MiAqIHZlYzQocGN0MixwY3QyLHBjdDIsMS4wKTtcclxuICAgICAgICAgICAgICBnbF9GcmFnQ29sb3IgPSBtaXgodDF3YiwgdDJ3YiwgcHJvZ3Jlc3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICBgO1xyXG4gICAgZmFkZUZyYWcgPSBgXHJcbiAgICAgICAgICAgIHVuaWZvcm0gZmxvYXQgcHJvZ3Jlc3M7XHJcbiAgICAgICAgICAgIHVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmUxO1xyXG4gICAgICAgICAgICB1bmlmb3JtIHNhbXBsZXIyRCB0ZXh0dXJlMjtcclxuICAgICAgICAgICAgdW5pZm9ybSB2ZWM0IHJlc29sdXRpb24xO1xyXG4gICAgICAgICAgICB1bmlmb3JtIHZlYzQgcmVzb2x1dGlvbjI7XHJcbiAgICAgICAgICAgIHZhcnlpbmcgdmVjMiB2VXY7XHJcbiAgICAgICAgICAgIG1hdDIgcm90YXRlKGZsb2F0IGEpIHtcclxuICAgICAgICAgICAgICBmbG9hdCBzID0gc2luKGEpO1xyXG4gICAgICAgICAgICAgIGZsb2F0IGMgPSBjb3MoYSk7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIG1hdDIoYywgLXMsIHMsIGMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZvaWQgbWFpbigpXHR7XHJcbiAgICAgICAgICAgICAgdmVjMiBuZXdVVjEgPSAodlV2IC0gdmVjMigwLjUsMC41KSkqcmVzb2x1dGlvbjEuencgKyB2ZWMyKDAuNSwwLjUpO1xyXG4gICAgICAgICAgICAgIHZlYzIgbmV3VVYyID0gKHZVdiAtIHZlYzIoMC41LDAuNSkpKnJlc29sdXRpb24yLnp3ICsgdmVjMigwLjUsMC41KTtcclxuICAgICAgICAgICAgICB2ZWMyIHV2RGlzcGxhY2VkMSA9IG5ld1VWMSArIHZlYzIoMS4wLDApKnByb2dyZXNzKjAuMTtcclxuICAgICAgICAgICAgICB2ZWMyIHV2RGlzcGxhY2VkMiA9IG5ld1VWMiArIHZlYzIoMS4wLDApKigxLiAtIHByb2dyZXNzKSowLjE7XHJcbiAgICAgICAgICAgICAgdmVjNCB0MSA9IHRleHR1cmUyRCh0ZXh0dXJlMSx1dkRpc3BsYWNlZDEpO1xyXG4gICAgICAgICAgICAgIHZlYzQgdDIgPSB0ZXh0dXJlMkQodGV4dHVyZTIsdXZEaXNwbGFjZWQyKTtcclxuICAgICAgICAgICAgICAvLyBVc2UgYmxhY2sgYmFja2dyb3VuZCBjb2xvclxyXG4gICAgICAgICAgICAgIC8vIFRvcCByaWdodFxyXG4gICAgICAgICAgICAgIHZlYzIgdHIxID0gc3RlcChuZXdVVjEsIHZlYzIoMS4wLCAxLjApKTtcclxuICAgICAgICAgICAgICB2ZWMyIHRyMiA9IHN0ZXAobmV3VVYyLCB2ZWMyKDEuMCwgMS4wKSk7XHJcbiAgICAgICAgICAgICAgZmxvYXQgcGN0MSA9IHRyMS54ICogdHIxLnk7XHJcbiAgICAgICAgICAgICAgZmxvYXQgcGN0MiA9IHRyMi54ICogdHIyLnk7XHJcbiAgICAgICAgICAgICAgLy8gQm90dG9tIGxlZnRcclxuICAgICAgICAgICAgICB2ZWMyIGJsMSA9IHN0ZXAodmVjMigwLjAsIDAuMCksIG5ld1VWMSk7XHJcbiAgICAgICAgICAgICAgdmVjMiBibDIgPSBzdGVwKHZlYzIoMC4wLCAwLjApLCBuZXdVVjIpO1xyXG4gICAgICAgICAgICAgIHBjdDEgKj0gYmwxLnggKiBibDEueTtcclxuICAgICAgICAgICAgICBwY3QyICo9IGJsMi54ICogYmwyLnk7XHJcbiAgICAgICAgICAgICAgdmVjNCB0MXdiID0gdDEgKiB2ZWM0KHBjdDEscGN0MSxwY3QxLDEuMCk7XHJcbiAgICAgICAgICAgICAgdmVjNCB0MndiID0gdDIgKiB2ZWM0KHBjdDIscGN0MixwY3QyLDEuMCk7XHJcbiAgICAgICAgICAgICAgZ2xfRnJhZ0NvbG9yID0gbWl4KHQxd2IsIHQyd2IsIHByb2dyZXNzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgYDtcclxuICAgIG5vaXNlRnJhZyA9IGBcclxuXHRcdHVuaWZvcm0gZmxvYXQgdGltZTtcclxuXHRcdHVuaWZvcm0gZmxvYXQgcHJvZ3Jlc3M7XHJcblx0XHR1bmlmb3JtIGZsb2F0IHdpZHRoO1xyXG5cdFx0dW5pZm9ybSBmbG9hdCBzY2FsZVg7XHJcblx0XHR1bmlmb3JtIGZsb2F0IHNjYWxlWTtcclxuXHRcdHVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmUxO1xyXG5cdFx0dW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTI7XHJcblx0XHR1bmlmb3JtIHNhbXBsZXIyRCBkaXNwbGFjZW1lbnQ7XHJcblx0XHR1bmlmb3JtIHZlYzQgcmVzb2x1dGlvbjE7XHJcblx0XHR1bmlmb3JtIHZlYzQgcmVzb2x1dGlvbjI7XHJcblx0XHR2YXJ5aW5nIHZlYzIgdlV2O1xyXG5cdFx0dmFyeWluZyB2ZWM0IHZQb3NpdGlvbjtcclxuXHRcdC8vXHRDbGFzc2ljIFBlcmxpbiAzRCBOb2lzZVxyXG5cdFx0Ly9cdGJ5IFN0ZWZhbiBHdXN0YXZzb25cclxuXHRcdC8vXHJcblx0XHR2ZWM0IHBlcm11dGUodmVjNCB4KXtyZXR1cm4gbW9kKCgoeCozNC4wKSsxLjApKngsIDI4OS4wKTt9XHJcblx0XHR2ZWM0IHRheWxvckludlNxcnQodmVjNCByKXtyZXR1cm4gMS43OTI4NDI5MTQwMDE1OSAtIDAuODUzNzM0NzIwOTUzMTQgKiByO31cclxuXHRcdHZlYzQgZmFkZSh2ZWM0IHQpIHtyZXR1cm4gdCp0KnQqKHQqKHQqNi4wLTE1LjApKzEwLjApO31cclxuXHRcdGZsb2F0IGNub2lzZSh2ZWM0IFApe1xyXG5cdFx0ICA7XHJcblx0XHQgIHZlYzQgUGkwID0gZmxvb3IoUCk7IC8vIEludGVnZXIgcGFydCBmb3IgaW5kZXhpbmdcclxuXHRcdCAgdmVjNCBQaTEgPSBQaTAgKyAxLjA7IC8vIEludGVnZXIgcGFydCArIDFcclxuXHRcdCAgUGkwID0gbW9kKFBpMCwgMjg5LjApO1xyXG5cdFx0ICBQaTEgPSBtb2QoUGkxLCAyODkuMCk7XHJcblx0XHQgIHZlYzQgUGYwID0gZnJhY3QoUCk7IC8vIEZyYWN0aW9uYWwgcGFydCBmb3IgaW50ZXJwb2xhdGlvblxyXG5cdFx0ICB2ZWM0IFBmMSA9IFBmMCAtIDEuMDsgLy8gRnJhY3Rpb25hbCBwYXJ0IC0gMS4wXHJcblx0XHQgIHZlYzQgaXggPSB2ZWM0KFBpMC54LCBQaTEueCwgUGkwLngsIFBpMS54KTtcclxuXHRcdCAgdmVjNCBpeSA9IHZlYzQoUGkwLnl5LCBQaTEueXkpO1xyXG5cdFx0ICB2ZWM0IGl6MCA9IHZlYzQoUGkwLnp6enopO1xyXG5cdFx0ICB2ZWM0IGl6MSA9IHZlYzQoUGkxLnp6enopO1xyXG5cdFx0ICB2ZWM0IGl3MCA9IHZlYzQoUGkwLnd3d3cpO1xyXG5cdFx0ICB2ZWM0IGl3MSA9IHZlYzQoUGkxLnd3d3cpO1xyXG5cdFx0ICB2ZWM0IGl4eSA9IHBlcm11dGUocGVybXV0ZShpeCkgKyBpeSk7XHJcblx0XHQgIHZlYzQgaXh5MCA9IHBlcm11dGUoaXh5ICsgaXowKTtcclxuXHRcdCAgdmVjNCBpeHkxID0gcGVybXV0ZShpeHkgKyBpejEpO1xyXG5cdFx0ICB2ZWM0IGl4eTAwID0gcGVybXV0ZShpeHkwICsgaXcwKTtcclxuXHRcdCAgdmVjNCBpeHkwMSA9IHBlcm11dGUoaXh5MCArIGl3MSk7XHJcblx0XHQgIHZlYzQgaXh5MTAgPSBwZXJtdXRlKGl4eTEgKyBpdzApO1xyXG5cdFx0ICB2ZWM0IGl4eTExID0gcGVybXV0ZShpeHkxICsgaXcxKTtcclxuXHRcdCAgdmVjNCBneDAwID0gaXh5MDAgLyA3LjA7XHJcblx0XHQgIHZlYzQgZ3kwMCA9IGZsb29yKGd4MDApIC8gNy4wO1xyXG5cdFx0ICB2ZWM0IGd6MDAgPSBmbG9vcihneTAwKSAvIDYuMDtcclxuXHRcdCAgZ3gwMCA9IGZyYWN0KGd4MDApIC0gMC41O1xyXG5cdFx0ICBneTAwID0gZnJhY3QoZ3kwMCkgLSAwLjU7XHJcblx0XHQgIGd6MDAgPSBmcmFjdChnejAwKSAtIDAuNTtcclxuXHRcdCAgdmVjNCBndzAwID0gdmVjNCgwLjc1KSAtIGFicyhneDAwKSAtIGFicyhneTAwKSAtIGFicyhnejAwKTtcclxuXHRcdCAgdmVjNCBzdzAwID0gc3RlcChndzAwLCB2ZWM0KDAuMCkpO1xyXG5cdFx0ICBneDAwIC09IHN3MDAgKiAoc3RlcCgwLjAsIGd4MDApIC0gMC41KTtcclxuXHRcdCAgZ3kwMCAtPSBzdzAwICogKHN0ZXAoMC4wLCBneTAwKSAtIDAuNSk7XHJcblx0XHQgIHZlYzQgZ3gwMSA9IGl4eTAxIC8gNy4wO1xyXG5cdFx0ICB2ZWM0IGd5MDEgPSBmbG9vcihneDAxKSAvIDcuMDtcclxuXHRcdCAgdmVjNCBnejAxID0gZmxvb3IoZ3kwMSkgLyA2LjA7XHJcblx0XHQgIGd4MDEgPSBmcmFjdChneDAxKSAtIDAuNTtcclxuXHRcdCAgZ3kwMSA9IGZyYWN0KGd5MDEpIC0gMC41O1xyXG5cdFx0ICBnejAxID0gZnJhY3QoZ3owMSkgLSAwLjU7XHJcblx0XHQgIHZlYzQgZ3cwMSA9IHZlYzQoMC43NSkgLSBhYnMoZ3gwMSkgLSBhYnMoZ3kwMSkgLSBhYnMoZ3owMSk7XHJcblx0XHQgIHZlYzQgc3cwMSA9IHN0ZXAoZ3cwMSwgdmVjNCgwLjApKTtcclxuXHRcdCAgZ3gwMSAtPSBzdzAxICogKHN0ZXAoMC4wLCBneDAxKSAtIDAuNSk7XHJcblx0XHQgIGd5MDEgLT0gc3cwMSAqIChzdGVwKDAuMCwgZ3kwMSkgLSAwLjUpO1xyXG5cdFx0ICB2ZWM0IGd4MTAgPSBpeHkxMCAvIDcuMDtcclxuXHRcdCAgdmVjNCBneTEwID0gZmxvb3IoZ3gxMCkgLyA3LjA7XHJcblx0XHQgIHZlYzQgZ3oxMCA9IGZsb29yKGd5MTApIC8gNi4wO1xyXG5cdFx0ICBneDEwID0gZnJhY3QoZ3gxMCkgLSAwLjU7XHJcblx0XHQgIGd5MTAgPSBmcmFjdChneTEwKSAtIDAuNTtcclxuXHRcdCAgZ3oxMCA9IGZyYWN0KGd6MTApIC0gMC41O1xyXG5cdFx0ICB2ZWM0IGd3MTAgPSB2ZWM0KDAuNzUpIC0gYWJzKGd4MTApIC0gYWJzKGd5MTApIC0gYWJzKGd6MTApO1xyXG5cdFx0ICB2ZWM0IHN3MTAgPSBzdGVwKGd3MTAsIHZlYzQoMC4wKSk7XHJcblx0XHQgIGd4MTAgLT0gc3cxMCAqIChzdGVwKDAuMCwgZ3gxMCkgLSAwLjUpO1xyXG5cdFx0ICBneTEwIC09IHN3MTAgKiAoc3RlcCgwLjAsIGd5MTApIC0gMC41KTtcclxuXHRcdCAgdmVjNCBneDExID0gaXh5MTEgLyA3LjA7XHJcblx0XHQgIHZlYzQgZ3kxMSA9IGZsb29yKGd4MTEpIC8gNy4wO1xyXG5cdFx0ICB2ZWM0IGd6MTEgPSBmbG9vcihneTExKSAvIDYuMDtcclxuXHRcdCAgZ3gxMSA9IGZyYWN0KGd4MTEpIC0gMC41O1xyXG5cdFx0ICBneTExID0gZnJhY3QoZ3kxMSkgLSAwLjU7XHJcblx0XHQgIGd6MTEgPSBmcmFjdChnejExKSAtIDAuNTtcclxuXHRcdCAgdmVjNCBndzExID0gdmVjNCgwLjc1KSAtIGFicyhneDExKSAtIGFicyhneTExKSAtIGFicyhnejExKTtcclxuXHRcdCAgdmVjNCBzdzExID0gc3RlcChndzExLCB2ZWM0KDAuMCkpO1xyXG5cdFx0ICBneDExIC09IHN3MTEgKiAoc3RlcCgwLjAsIGd4MTEpIC0gMC41KTtcclxuXHRcdCAgZ3kxMSAtPSBzdzExICogKHN0ZXAoMC4wLCBneTExKSAtIDAuNSk7XHJcblx0XHQgIHZlYzQgZzAwMDAgPSB2ZWM0KGd4MDAueCxneTAwLngsZ3owMC54LGd3MDAueCk7XHJcblx0XHQgIHZlYzQgZzEwMDAgPSB2ZWM0KGd4MDAueSxneTAwLnksZ3owMC55LGd3MDAueSk7XHJcblx0XHQgIHZlYzQgZzAxMDAgPSB2ZWM0KGd4MDAueixneTAwLnosZ3owMC56LGd3MDAueik7XHJcblx0XHQgIHZlYzQgZzExMDAgPSB2ZWM0KGd4MDAudyxneTAwLncsZ3owMC53LGd3MDAudyk7XHJcblx0XHQgIHZlYzQgZzAwMTAgPSB2ZWM0KGd4MTAueCxneTEwLngsZ3oxMC54LGd3MTAueCk7XHJcblx0XHQgIHZlYzQgZzEwMTAgPSB2ZWM0KGd4MTAueSxneTEwLnksZ3oxMC55LGd3MTAueSk7XHJcblx0XHQgIHZlYzQgZzAxMTAgPSB2ZWM0KGd4MTAueixneTEwLnosZ3oxMC56LGd3MTAueik7XHJcblx0XHQgIHZlYzQgZzExMTAgPSB2ZWM0KGd4MTAudyxneTEwLncsZ3oxMC53LGd3MTAudyk7XHJcblx0XHQgIHZlYzQgZzAwMDEgPSB2ZWM0KGd4MDEueCxneTAxLngsZ3owMS54LGd3MDEueCk7XHJcblx0XHQgIHZlYzQgZzEwMDEgPSB2ZWM0KGd4MDEueSxneTAxLnksZ3owMS55LGd3MDEueSk7XHJcblx0XHQgIHZlYzQgZzAxMDEgPSB2ZWM0KGd4MDEueixneTAxLnosZ3owMS56LGd3MDEueik7XHJcblx0XHQgIHZlYzQgZzExMDEgPSB2ZWM0KGd4MDEudyxneTAxLncsZ3owMS53LGd3MDEudyk7XHJcblx0XHQgIHZlYzQgZzAwMTEgPSB2ZWM0KGd4MTEueCxneTExLngsZ3oxMS54LGd3MTEueCk7XHJcblx0XHQgIHZlYzQgZzEwMTEgPSB2ZWM0KGd4MTEueSxneTExLnksZ3oxMS55LGd3MTEueSk7XHJcblx0XHQgIHZlYzQgZzAxMTEgPSB2ZWM0KGd4MTEueixneTExLnosZ3oxMS56LGd3MTEueik7XHJcblx0XHQgIHZlYzQgZzExMTEgPSB2ZWM0KGd4MTEudyxneTExLncsZ3oxMS53LGd3MTEudyk7XHJcblx0XHQgIHZlYzQgbm9ybTAwID0gdGF5bG9ySW52U3FydCh2ZWM0KGRvdChnMDAwMCwgZzAwMDApLCBkb3QoZzAxMDAsIGcwMTAwKSwgZG90KGcxMDAwLCBnMTAwMCksIGRvdChnMTEwMCwgZzExMDApKSk7XHJcblx0XHQgIGcwMDAwICo9IG5vcm0wMC54O1xyXG5cdFx0ICBnMDEwMCAqPSBub3JtMDAueTtcclxuXHRcdCAgZzEwMDAgKj0gbm9ybTAwLno7XHJcblx0XHQgIGcxMTAwICo9IG5vcm0wMC53O1xyXG5cdFx0ICB2ZWM0IG5vcm0wMSA9IHRheWxvckludlNxcnQodmVjNChkb3QoZzAwMDEsIGcwMDAxKSwgZG90KGcwMTAxLCBnMDEwMSksIGRvdChnMTAwMSwgZzEwMDEpLCBkb3QoZzExMDEsIGcxMTAxKSkpO1xyXG5cdFx0ICBnMDAwMSAqPSBub3JtMDEueDtcclxuXHRcdCAgZzAxMDEgKj0gbm9ybTAxLnk7XHJcblx0XHQgIGcxMDAxICo9IG5vcm0wMS56O1xyXG5cdFx0ICBnMTEwMSAqPSBub3JtMDEudztcclxuXHRcdCAgdmVjNCBub3JtMTAgPSB0YXlsb3JJbnZTcXJ0KHZlYzQoZG90KGcwMDEwLCBnMDAxMCksIGRvdChnMDExMCwgZzAxMTApLCBkb3QoZzEwMTAsIGcxMDEwKSwgZG90KGcxMTEwLCBnMTExMCkpKTtcclxuXHRcdCAgZzAwMTAgKj0gbm9ybTEwLng7XHJcblx0XHQgIGcwMTEwICo9IG5vcm0xMC55O1xyXG5cdFx0ICBnMTAxMCAqPSBub3JtMTAuejtcclxuXHRcdCAgZzExMTAgKj0gbm9ybTEwLnc7XHJcblx0XHQgIHZlYzQgbm9ybTExID0gdGF5bG9ySW52U3FydCh2ZWM0KGRvdChnMDAxMSwgZzAwMTEpLCBkb3QoZzAxMTEsIGcwMTExKSwgZG90KGcxMDExLCBnMTAxMSksIGRvdChnMTExMSwgZzExMTEpKSk7XHJcblx0XHQgIGcwMDExICo9IG5vcm0xMS54O1xyXG5cdFx0ICBnMDExMSAqPSBub3JtMTEueTtcclxuXHRcdCAgZzEwMTEgKj0gbm9ybTExLno7XHJcblx0XHQgIGcxMTExICo9IG5vcm0xMS53O1xyXG5cdFx0ICBmbG9hdCBuMDAwMCA9IGRvdChnMDAwMCwgUGYwKTtcclxuXHRcdCAgZmxvYXQgbjEwMDAgPSBkb3QoZzEwMDAsIHZlYzQoUGYxLngsIFBmMC55encpKTtcclxuXHRcdCAgZmxvYXQgbjAxMDAgPSBkb3QoZzAxMDAsIHZlYzQoUGYwLngsIFBmMS55LCBQZjAuencpKTtcclxuXHRcdCAgZmxvYXQgbjExMDAgPSBkb3QoZzExMDAsIHZlYzQoUGYxLnh5LCBQZjAuencpKTtcclxuXHRcdCAgZmxvYXQgbjAwMTAgPSBkb3QoZzAwMTAsIHZlYzQoUGYwLnh5LCBQZjEueiwgUGYwLncpKTtcclxuXHRcdCAgZmxvYXQgbjEwMTAgPSBkb3QoZzEwMTAsIHZlYzQoUGYxLngsIFBmMC55LCBQZjEueiwgUGYwLncpKTtcclxuXHRcdCAgZmxvYXQgbjAxMTAgPSBkb3QoZzAxMTAsIHZlYzQoUGYwLngsIFBmMS55eiwgUGYwLncpKTtcclxuXHRcdCAgZmxvYXQgbjExMTAgPSBkb3QoZzExMTAsIHZlYzQoUGYxLnh5eiwgUGYwLncpKTtcclxuXHRcdCAgZmxvYXQgbjAwMDEgPSBkb3QoZzAwMDEsIHZlYzQoUGYwLnh5eiwgUGYxLncpKTtcclxuXHRcdCAgZmxvYXQgbjEwMDEgPSBkb3QoZzEwMDEsIHZlYzQoUGYxLngsIFBmMC55eiwgUGYxLncpKTtcclxuXHRcdCAgZmxvYXQgbjAxMDEgPSBkb3QoZzAxMDEsIHZlYzQoUGYwLngsIFBmMS55LCBQZjAueiwgUGYxLncpKTtcclxuXHRcdCAgZmxvYXQgbjExMDEgPSBkb3QoZzExMDEsIHZlYzQoUGYxLnh5LCBQZjAueiwgUGYxLncpKTtcclxuXHRcdCAgZmxvYXQgbjAwMTEgPSBkb3QoZzAwMTEsIHZlYzQoUGYwLnh5LCBQZjEuencpKTtcclxuXHRcdCAgZmxvYXQgbjEwMTEgPSBkb3QoZzEwMTEsIHZlYzQoUGYxLngsIFBmMC55LCBQZjEuencpKTtcclxuXHRcdCAgZmxvYXQgbjAxMTEgPSBkb3QoZzAxMTEsIHZlYzQoUGYwLngsIFBmMS55encpKTtcclxuXHRcdCAgZmxvYXQgbjExMTEgPSBkb3QoZzExMTEsIFBmMSk7XHJcblx0XHQgIHZlYzQgZmFkZV94eXp3ID0gZmFkZShQZjApO1xyXG5cdFx0ICB2ZWM0IG5fMHcgPSBtaXgodmVjNChuMDAwMCwgbjEwMDAsIG4wMTAwLCBuMTEwMCksIHZlYzQobjAwMDEsIG4xMDAxLCBuMDEwMSwgbjExMDEpLCBmYWRlX3h5encudyk7XHJcblx0XHQgIHZlYzQgbl8xdyA9IG1peCh2ZWM0KG4wMDEwLCBuMTAxMCwgbjAxMTAsIG4xMTEwKSwgdmVjNChuMDAxMSwgbjEwMTEsIG4wMTExLCBuMTExMSksIGZhZGVfeHl6dy53KTtcclxuXHRcdCAgdmVjNCBuX3p3ID0gbWl4KG5fMHcsIG5fMXcsIGZhZGVfeHl6dy56KTtcclxuXHRcdCAgdmVjMiBuX3l6dyA9IG1peChuX3p3Lnh5LCBuX3p3Lnp3LCBmYWRlX3h5encueSk7XHJcblx0XHQgIGZsb2F0IG5feHl6dyA9IG1peChuX3l6dy54LCBuX3l6dy55LCBmYWRlX3h5encueCk7XHJcblx0XHQgIHJldHVybiAyLjIgKiBuX3h5enc7XHJcblx0XHR9XHJcblx0XHRmbG9hdCBtYXAoZmxvYXQgdmFsdWUsIGZsb2F0IG1pbjEsIGZsb2F0IG1heDEsIGZsb2F0IG1pbjIsIGZsb2F0IG1heDIpIHtcclxuXHRcdCAgcmV0dXJuIG1pbjIgKyAodmFsdWUgLSBtaW4xKSAqIChtYXgyIC0gbWluMikgLyAobWF4MSAtIG1pbjEpO1xyXG5cdFx0fVxyXG5cdFx0ZmxvYXQgcGFyYWJvbGEoIGZsb2F0IHgsIGZsb2F0IGsgKSB7XHJcblx0XHQgIHJldHVybiBwb3coIDQuICogeCAqICggMS4gLSB4ICksIGsgKTtcclxuXHRcdH1cclxuXHRcdHZvaWQgbWFpbigpXHR7XHJcblx0XHRcdGZsb2F0IGR0ID0gcGFyYWJvbGEocHJvZ3Jlc3MsMS4pO1xyXG5cdFx0XHRmbG9hdCBib3JkZXIgPSAxLjtcclxuXHRcdFx0dmVjMiBuZXdVVjEgPSAodlV2IC0gdmVjMigwLjUsMC41KSkqcmVzb2x1dGlvbjEuencgKyB2ZWMyKDAuNSwwLjUpO1xyXG4gICAgICBcdFx0dmVjMiBuZXdVVjIgPSAodlV2IC0gdmVjMigwLjUsMC41KSkqcmVzb2x1dGlvbjIuencgKyB2ZWMyKDAuNSwwLjUpO1xyXG5cdFx0XHR2ZWM0IHQxID0gdGV4dHVyZTJEKHRleHR1cmUxLG5ld1VWMSk7XHJcbiAgICAgIFx0XHR2ZWM0IHQyID0gdGV4dHVyZTJEKHRleHR1cmUyLG5ld1VWMik7XHJcbiAgICAgIFx0XHQvLyBVc2UgYmxhY2sgYmFja2dyb3VuZCBjb2xvclxyXG4gICAgICBcdFx0Ly8gVG9wIHJpZ2h0XHJcbiAgICAgIFx0XHR2ZWMyIHRyMSA9IHN0ZXAobmV3VVYxLCB2ZWMyKDEuMCwgMS4wKSk7XHJcbiAgICAgIFx0XHR2ZWMyIHRyMiA9IHN0ZXAobmV3VVYyLCB2ZWMyKDEuMCwgMS4wKSk7XHJcbiAgICAgIFx0XHRmbG9hdCBwY3QxID0gdHIxLnggKiB0cjEueTtcclxuICAgICAgXHRcdGZsb2F0IHBjdDIgPSB0cjIueCAqIHRyMi55O1xyXG4gICAgICBcdFx0Ly8gQm90dG9tIGxlZnRcclxuICAgICAgXHRcdHZlYzIgYmwxID0gc3RlcCh2ZWMyKDAuMCwgMC4wKSwgbmV3VVYxKTtcclxuICAgICAgXHRcdHZlYzIgYmwyID0gc3RlcCh2ZWMyKDAuMCwgMC4wKSwgbmV3VVYyKTtcclxuICAgICAgXHRcdHBjdDEgKj0gYmwxLnggKiBibDEueTtcclxuICAgICAgXHRcdHBjdDIgKj0gYmwyLnggKiBibDIueTtcclxuICAgICAgXHRcdHZlYzQgdDF3YiA9IHQxICogdmVjNChwY3QxLHBjdDEscGN0MSwxLjApO1xyXG4gICAgICBcdFx0dmVjNCB0MndiID0gdDIgKiB2ZWM0KHBjdDIscGN0MixwY3QyLDEuMCk7XHJcblx0XHRcdGZsb2F0IHJlYWxub2lzZSA9IDAuNSooY25vaXNlKHZlYzQobmV3VVYxLngqc2NhbGVYICArIDAuKnRpbWUvMy4sIG5ld1VWMS55KnNjYWxlWSwwLip0aW1lLzMuLDAuKSkgKzEuKTtcclxuXHRcdFx0ZmxvYXQgdyA9IHdpZHRoKmR0O1xyXG5cdFx0XHRmbG9hdCBtYXNrdmFsdWUgPSBzbW9vdGhzdGVwKDEuIC0gdywxLix2VXYueCArIG1peCgtdy8yLiwgMS4gLSB3LzIuLCBwcm9ncmVzcykpO1xyXG5cdFx0XHRmbG9hdCBtYXNrID0gbWFza3ZhbHVlICsgbWFza3ZhbHVlKnJlYWxub2lzZTtcclxuXHRcdFx0ZmxvYXQgZmluYWwgPSBzbW9vdGhzdGVwKGJvcmRlcixib3JkZXIrMC4wMSxtYXNrKTtcclxuXHRcdFx0Z2xfRnJhZ0NvbG9yID0gbWl4KHQxd2IsdDJ3YixmaW5hbCk7XHJcblx0XHR9XHJcblx0YDtcclxuICAgIGJsdXJGcmFnID0gYFxyXG5cdFx0Ly8gYXV0aG9yOiBncmVcclxuXHRcdC8vIGxpY2Vuc2U6IE1JVFxyXG5cdFx0dW5pZm9ybSBmbG9hdCBwcm9ncmVzcztcclxuXHRcdHVuaWZvcm0gZmxvYXQgaW50ZW5zaXR5O1xyXG5cdFx0dW5pZm9ybSBmbG9hdCByYXRpbztcclxuXHRcdHVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmUxO1xyXG5cdFx0dW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTI7XHJcblx0XHR1bmlmb3JtIHZlYzQgcmVzb2x1dGlvbjE7XHJcblx0XHR1bmlmb3JtIHZlYzQgcmVzb2x1dGlvbjI7XHJcblx0XHR2YXJ5aW5nIHZlYzIgdlV2O1xyXG5cdFx0Y29uc3QgaW50IHBhc3NlcyA9IDY7XHJcblxyXG5cdFx0dm9pZCBtYWluKCkge1xyXG5cdFx0XHR2ZWMyIG5ld1VWMSA9ICh2VXYgLSB2ZWMyKDAuNSwwLjUpKSpyZXNvbHV0aW9uMS56dyArIHZlYzIoMC41LDAuNSk7XHJcblx0XHRcdHZlYzIgbmV3VVYyID0gKHZVdiAtIHZlYzIoMC41LDAuNSkpKnJlc29sdXRpb24yLnp3ICsgdmVjMigwLjUsMC41KTtcclxuXHJcblx0XHRcdHZlYzQgdDEgPSB2ZWM0KDAuMCk7XHJcblx0XHRcdHZlYzQgdDIgPSB2ZWM0KDAuMCk7XHJcblx0XHRcdGZsb2F0IGRpc3AgPSBpbnRlbnNpdHkvMTAwLjAqKDAuNS1kaXN0YW5jZSgwLjUsIHByb2dyZXNzKSk7XHJcblx0XHRcdGZvciAoaW50IHhpPTA7IHhpPHBhc3NlczsgeGkrKylcclxuXHRcdFx0e1xyXG5cdFx0XHRcdGZsb2F0IHggPSBmbG9hdCh4aSkgLyBmbG9hdChwYXNzZXMpIC0gMC41O1xyXG5cdFx0XHRcdGZvciAoaW50IHlpPTA7IHlpPHBhc3NlczsgeWkrKylcclxuXHRcdFx0XHR7XHJcblx0XHRcdFx0XHRmbG9hdCB5ID0gZmxvYXQoeWkpIC8gZmxvYXQocGFzc2VzKSAtIDAuNTtcclxuXHRcdFx0XHRcdHZlYzIgdiA9IHZlYzIoeCx5KTtcclxuXHRcdFx0XHRcdGZsb2F0IGQgPSBkaXNwO1xyXG5cdFx0XHRcdFx0dDEgKz0gdGV4dHVyZTJEKHRleHR1cmUxLG5ld1VWMSArIGQqdik7XHJcblx0XHRcdFx0XHR0MiArPSB0ZXh0dXJlMkQodGV4dHVyZTIsbmV3VVYyICsgZCp2KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHQxIC89IGZsb2F0KHBhc3NlcypwYXNzZXMpO1xyXG5cdFx0XHR0MiAvPSBmbG9hdChwYXNzZXMqcGFzc2VzKTtcclxuXHJcblx0XHRcdC8vIFVzZSBibGFjayBiYWNrZ3JvdW5kIGNvbG9yXHJcblx0XHRcdC8vIFRvcCByaWdodFxyXG5cdFx0XHR2ZWMyIHRyMSA9IHN0ZXAobmV3VVYxLCB2ZWMyKDEuMCwgMS4wKSk7XHJcblx0XHRcdHZlYzIgdHIyID0gc3RlcChuZXdVVjIsIHZlYzIoMS4wLCAxLjApKTtcclxuXHRcdFx0ZmxvYXQgcGN0MSA9IHRyMS54ICogdHIxLnk7XHJcblx0XHRcdGZsb2F0IHBjdDIgPSB0cjIueCAqIHRyMi55O1xyXG5cdFx0XHQvLyBCb3R0b20gbGVmdFxyXG5cdFx0XHR2ZWMyIGJsMSA9IHN0ZXAodmVjMigwLjAsIDAuMCksIG5ld1VWMSk7XHJcblx0XHRcdHZlYzIgYmwyID0gc3RlcCh2ZWMyKDAuMCwgMC4wKSwgbmV3VVYyKTtcclxuXHRcdFx0cGN0MSAqPSBibDEueCAqIGJsMS55O1xyXG5cdFx0XHRwY3QyICo9IGJsMi54ICogYmwyLnk7XHJcblx0XHRcdHZlYzQgdDF3YiA9IHQxICogdmVjNChwY3QxLHBjdDEscGN0MSwxLjApO1xyXG5cdFx0XHR2ZWM0IHQyd2IgPSB0MiAqIHZlYzQocGN0MixwY3QyLHBjdDIsMS4wKTtcclxuXHRcdFx0Z2xfRnJhZ0NvbG9yID0gbWl4KHQxd2IsIHQyd2IsIHByb2dyZXNzKTtcclxuXHRcdH1cclxuXHRgO1xyXG5cdGRpc3RvcnRpb25GcmFnID0gYFxyXG5cdHVuaWZvcm0gZmxvYXQgcHJvZ3Jlc3M7XHJcblx0dW5pZm9ybSBzYW1wbGVyMkQgZGlzcGxhY2VtZW50VGV4dHVyZTtcclxuXHR1bmlmb3JtIHNhbXBsZXIyRCB0ZXh0dXJlMTtcclxuICAgIHVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmUyO1xyXG4gICAgdW5pZm9ybSB2ZWM0IHJlc29sdXRpb24xO1xyXG4gICAgdW5pZm9ybSB2ZWM0IHJlc29sdXRpb24yO1xyXG5cdHVuaWZvcm0gZmxvYXQgYW5nbGUxO1xyXG5cdHVuaWZvcm0gZmxvYXQgYW5nbGUyO1xyXG5cdHVuaWZvcm0gZmxvYXQgaW50ZW5zaXR5O1xyXG5cclxuXHR2YXJ5aW5nIHZlYzIgdlV2O1xyXG5cclxuXHRtYXQyIGdldFJvdE0oZmxvYXQgYW5nbGUpIHtcclxuXHQgIGZsb2F0IHMgPSBzaW4oYW5nbGUpO1xyXG5cdCAgZmxvYXQgYyA9IGNvcyhhbmdsZSk7XHJcblx0ICByZXR1cm4gbWF0MihjLCAtcywgcywgYyk7XHJcblx0fVxyXG5cclxuXHR2b2lkIG1haW4oKSB7XHJcblx0ICB2ZWMyIG5ld1VWMSA9ICh2VXYgLSB2ZWMyKDAuNSwwLjUpKSpyZXNvbHV0aW9uMS56dyArIHZlYzIoMC41LDAuNSk7XHJcbiAgICAgIHZlYzIgbmV3VVYyID0gKHZVdiAtIHZlYzIoMC41LDAuNSkpKnJlc29sdXRpb24yLnp3ICsgdmVjMigwLjUsMC41KTtcclxuXHQgIHZlYzQgdDEgPSB0ZXh0dXJlMkQodGV4dHVyZTEsbmV3VVYxKTtcclxuICAgICAgdmVjNCB0MiA9IHRleHR1cmUyRCh0ZXh0dXJlMixuZXdVVjIpO1xyXG5cclxuXHQgIHZlYzQgZGlzcCA9IHRleHR1cmUyRChkaXNwbGFjZW1lbnRUZXh0dXJlLCBuZXdVVjEpO1xyXG5cdCAgdmVjMiBkaXNwVmVjID0gdmVjMihkaXNwLnIsIGRpc3AuZyk7XHJcblxyXG5cdCAgdmVjMiBkaXN0b3J0ZWRQb3NpdGlvbjEgPSBuZXdVVjEgKyBnZXRSb3RNKGFuZ2xlMSkgKiBkaXNwVmVjICogaW50ZW5zaXR5IC8gMTAwLjAgKiBwcm9ncmVzcztcclxuXHQgIHZlYzIgZGlzdG9ydGVkUG9zaXRpb24yID0gbmV3VVYyICsgZ2V0Um90TShhbmdsZTIpICogZGlzcFZlYyAqIGludGVuc2l0eSAvIDEwMC4wICogKDEuMCAtIHByb2dyZXNzKTtcclxuXHQgIHZlYzQgdDFkID0gdGV4dHVyZTJEKHRleHR1cmUxLCBkaXN0b3J0ZWRQb3NpdGlvbjEpO1xyXG5cdCAgdmVjNCB0MmQgPSB0ZXh0dXJlMkQodGV4dHVyZTIsIGRpc3RvcnRlZFBvc2l0aW9uMik7XHJcblxyXG5cdCAgLy8gVXNlIGJsYWNrIGJhY2tncm91bmQgY29sb3JcclxuXHQgIC8vIFRvcCByaWdodFxyXG5cdCAgdmVjMiB0cjEgPSBzdGVwKG5ld1VWMSwgdmVjMigxLjAsIDEuMCkpO1xyXG5cdCAgdmVjMiB0cjIgPSBzdGVwKG5ld1VWMiwgdmVjMigxLjAsIDEuMCkpO1xyXG5cdCAgZmxvYXQgcGN0MSA9IHRyMS54ICogdHIxLnk7XHJcblx0ICBmbG9hdCBwY3QyID0gdHIyLnggKiB0cjIueTtcclxuXHQgIC8vIEJvdHRvbSBsZWZ0XHJcblx0ICB2ZWMyIGJsMSA9IHN0ZXAodmVjMigwLjAsIDAuMCksIG5ld1VWMSk7XHJcblx0ICB2ZWMyIGJsMiA9IHN0ZXAodmVjMigwLjAsIDAuMCksIG5ld1VWMik7XHJcblx0ICBwY3QxICo9IGJsMS54ICogYmwxLnk7XHJcblx0ICBwY3QyICo9IGJsMi54ICogYmwyLnk7XHJcblx0ICB2ZWM0IHQxd2IgPSB0MWQgKiB2ZWM0KHBjdDEscGN0MSxwY3QxLDEuMCk7XHJcblx0ICB2ZWM0IHQyd2IgPSB0MmQgKiB2ZWM0KHBjdDIscGN0MixwY3QyLDEuMCk7XHJcblx0ICBnbF9GcmFnQ29sb3IgPSBtaXgodDF3YiwgdDJ3YiwgcHJvZ3Jlc3MpO1xyXG5cdH1cclxuXHRgO1xyXG59XHJcbiJdfQ==