webglimpse
Version:
Webglimpse is a data visualization library for the web.
181 lines • 41.7 kB
JavaScript
/*
* Copyright (c) 2014, Metron, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { GL, concatLines, getObjectId, hasval } from './util/util';
import { Program, Uniform2f, Uniform1f, UniformSampler2D, Attribute } from './shader';
import { newStaticBuffer } from './buffer';
import { nearestPixel } from './misc';
class TextureEntry {
constructor(gl, target, texture) {
this.gl = gl;
this.target = target;
this.texture = texture;
this.textureUnit = -1;
}
}
export class Texture {
constructor(helper) {
this.helper = helper;
this.textures = {};
}
bind(gl, textureUnit) {
const glId = getObjectId(gl);
if (hasval(this.textures[glId])) {
const en = this.textures[glId];
gl.activeTexture(GL.TEXTURE0 + textureUnit);
gl.bindTexture(en.target, en.texture);
en.textureUnit = textureUnit;
}
else {
const target = this.helper.target(gl);
const texture = gl.createTexture();
if (!hasval(texture)) {
throw new Error('Failed to create texture');
}
this.textures[glId] = new TextureEntry(gl, target, texture);
const en = this.textures[glId];
gl.activeTexture(GL.TEXTURE0 + textureUnit);
gl.bindTexture(en.target, en.texture);
en.textureUnit = textureUnit;
this.helper.init(gl, target);
}
}
unbind(gl) {
const glId = getObjectId(gl);
if (hasval(this.textures[glId])) {
const en = this.textures[glId];
gl.activeTexture(GL.TEXTURE0 + en.textureUnit);
gl.bindTexture(en.target, null);
en.textureUnit = -1;
}
}
dispose() {
// XXX: Not sure this actually works ... may have to make each gl current or something
for (const glid in this.textures) {
if (this.textures.hasOwnProperty(glid)) {
const en = this.textures[glid];
en.gl.deleteTexture(en.texture);
}
}
this.textures = {};
}
}
export class FloatDataTexture2D extends Texture {
constructor(w, h, array) {
super({
target: function (gl) {
return GL.TEXTURE_2D;
},
init: function (gl, target) {
if (!gl.getExtension('OES_texture_float')) {
throw new Error('OES_texture_float extension is required');
}
gl.texParameteri(target, GL.TEXTURE_MAG_FILTER, GL.NEAREST);
gl.texParameteri(target, GL.TEXTURE_MIN_FILTER, GL.NEAREST);
gl.texParameteri(target, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
gl.texParameteri(target, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
// GL.LUMINANCE isn't supported with GL.FLOAT
gl.texImage2D(target, 0, GL.RGBA, w, h, 0, GL.RGBA, GL.FLOAT, array);
}
});
this._w = w;
this._h = h;
}
get w() { return this._w; }
get h() { return this._h; }
}
export class Texture2D extends Texture {
constructor(w, h, minFilter, magFilter, draw) {
const canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
draw(canvas.getContext('2d'));
super({
target: function (gl) {
return GL.TEXTURE_2D;
},
init: function (gl, target) {
gl.texParameteri(target, GL.TEXTURE_MAG_FILTER, magFilter);
gl.texParameteri(target, GL.TEXTURE_MIN_FILTER, minFilter);
gl.texParameteri(target, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE);
gl.texParameteri(target, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE);
gl.texImage2D(target, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, canvas);
}
});
this._w = w;
this._h = h;
}
get w() { return this._w; }
get h() { return this._h; }
}
export class TextureRenderer {
constructor() {
this.textureRenderer_VERTSHADER = concatLines(' ', ' uniform vec2 u_XyFrac; ', ' uniform vec2 u_Anchor; ', ' uniform float u_Rotation_CCWRAD; ', ' uniform vec2 u_ImageSize; ', ' uniform vec2 u_ViewportSize; ', ' ', ' attribute vec2 a_ImageFrac; ', ' ', ' varying vec2 v_StCoord; ', ' ', ' void main( ) { ', ' float cosRot = cos( u_Rotation_CCWRAD ); ', ' float sinRot = sin( u_Rotation_CCWRAD ); ', ' ', ' // Column major ', ' mat2 rotation = mat2( cosRot, sinRot, ', ' -sinRot, cosRot ); ', ' ', ' vec2 xy = -1.0 + 2.0*( u_XyFrac + rotation*( u_ImageSize*( a_ImageFrac - u_Anchor ) ) / u_ViewportSize ); ', ' gl_Position = vec4( xy, 0.0, 1.0 ); ', ' ', ' v_StCoord = vec2( a_ImageFrac.x, 1.0 - a_ImageFrac.y ); ', ' } ', ' ');
this.textureRenderer_FRAGSHADER = concatLines(' ', ' precision mediump float; ', ' ', ' uniform sampler2D u_Sampler; ', ' ', ' varying vec2 v_StCoord; ', ' ', ' void main( ) { ', ' gl_FragColor = texture2D( u_Sampler, v_StCoord ); ', ' } ', ' ');
this.program = new Program(this.textureRenderer_VERTSHADER, this.textureRenderer_FRAGSHADER);
this.u_XyFrac = new Uniform2f(this.program, 'u_XyFrac');
this.u_Anchor = new Uniform2f(this.program, 'u_Anchor');
this.u_Rotation_CCWRAD = new Uniform1f(this.program, 'u_Rotation_CCWRAD');
this.u_ImageSize = new Uniform2f(this.program, 'u_ImageSize');
this.u_ViewportSize = new Uniform2f(this.program, 'u_ViewportSize');
this.u_Sampler = new UniformSampler2D(this.program, 'u_Sampler');
this.a_ImageFrac = new Attribute(this.program, 'a_ImageFrac');
this.imageFracData = newStaticBuffer(new Float32Array([0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]));
this.wViewport = 0;
this.hViewport = 0;
}
begin(gl, viewport) {
gl.blendFuncSeparate(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA);
gl.enable(GL.BLEND);
this.program.use(gl);
this.u_ViewportSize.setData(gl, viewport.w, viewport.h);
this.a_ImageFrac.setDataAndEnable(gl, this.imageFracData, 2, GL.FLOAT);
this.wViewport = viewport.w;
this.hViewport = viewport.h;
}
draw(gl, texture, xFrac, yFrac, options) {
const xAnchor = (hasval(options) && hasval(options.xAnchor) ? options.xAnchor : 0.5);
const yAnchor = (hasval(options) && hasval(options.yAnchor) ? options.yAnchor : 0.5);
const rotation_CCWRAD = (hasval(options) && hasval(options.rotation_CCWRAD) ? options.rotation_CCWRAD : 0);
const width = (hasval(options) && hasval(options.width) ? options.width : texture.w);
const height = (hasval(options) && hasval(options.height) ? options.height : texture.h);
this.u_XyFrac.setData(gl, nearestPixel(xFrac, this.wViewport, xAnchor, texture.w), nearestPixel(yFrac, this.hViewport, yAnchor, texture.h));
this.u_Anchor.setData(gl, xAnchor, yAnchor);
this.u_Rotation_CCWRAD.setData(gl, rotation_CCWRAD);
this.u_ImageSize.setData(gl, width, height);
this.u_Sampler.setDataAndBind(gl, 0, texture);
gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4);
}
end(gl) {
this.a_ImageFrac.disable(gl);
this.u_Sampler.unbind(gl);
this.program.endUse(gl);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dHVyZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93ZWJnbGltcHNlL3RleHR1cmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxPQUFPLEVBQWEsRUFBRSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzlFLE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxTQUFTLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDdEYsT0FBTyxFQUFVLGVBQWUsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVuRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRXRDLE1BQU0sWUFBWTtJQU1kLFlBQVksRUFBeUIsRUFBRSxNQUFjLEVBQUUsT0FBcUI7UUFDeEUsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDYixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzFCLENBQUM7Q0FDSjtBQVNELE1BQU0sT0FBTyxPQUFPO0lBSWhCLFlBQVksTUFBcUI7UUFDN0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVELElBQUksQ0FBQyxFQUF5QixFQUFFLFdBQW1CO1FBQy9DLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUU7WUFDN0IsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFD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Q0FBQyxDQUFDO1FBRXhGLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxZQUFZLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxZQUFZLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVJLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLGNBQWMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELEdBQUcsQ0FBQyxFQUF5QjtRQUN6QixJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1QixDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQsIE1ldHJvbiwgSW5jLlxyXG4gKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKlxyXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxyXG4gKiBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XHJcbiAqXHJcbiAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xyXG4gKiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cclxuICpcclxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxyXG4gKiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXHJcbiAqICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG4gKlxyXG4gKiAzLiBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBjb3B5cmlnaHQgaG9sZGVyIG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9yc1xyXG4gKiAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dFxyXG4gKiAgICBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uXHJcbiAqXHJcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxyXG4gKiBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxyXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXHJcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXHJcbiAqIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xyXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XHJcbiAqIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxyXG4gKiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxyXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xyXG4gKiBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuICovXHJcbmltcG9ydCB7IFN0cmluZ01hcCwgR0wsIGNvbmNhdExpbmVzLCBnZXRPYmplY3RJZCwgaGFzdmFsIH0gZnJvbSAnLi91dGlsL3V0aWwnO1xyXG5pbXBvcnQgeyBQcm9ncmFtLCBVbmlmb3JtMmYsIFVuaWZvcm0xZiwgVW5pZm9ybVNhbXBsZXIyRCwgQXR0cmlidXRlIH0gZnJvbSAnLi9zaGFkZXInO1xyXG5pbXBvcnQgeyBCdWZmZXIsIG5ld1N0YXRpY0J1ZmZlciB9IGZyb20gJy4vYnVmZmVyJztcclxuaW1wb3J0IHsgQm91bmRzVW5tb2RpZmlhYmxlIH0gZnJvbSAnLi9ib3VuZHMnO1xyXG5pbXBvcnQgeyBuZWFyZXN0UGl4ZWwgfSBmcm9tICcuL21pc2MnO1xyXG5cclxuY2xhc3MgVGV4dHVyZUVudHJ5IHtcclxuICAgIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XHJcbiAgICB0YXJnZXQ6IG51bWJlcjtcclxuICAgIHRleHR1cmU6IFdlYkdMVGV4dHVyZTtcclxuICAgIHRleHR1cmVVbml0OiBudW1iZXI7XHJcblxyXG4gICAgY29uc3RydWN0b3IoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgdGFyZ2V0OiBudW1iZXIsIHRleHR1cmU6IFdlYkdMVGV4dHVyZSkge1xyXG4gICAgICAgIHRoaXMuZ2wgPSBnbDtcclxuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcclxuICAgICAgICB0aGlzLnRleHR1cmUgPSB0ZXh0dXJlO1xyXG4gICAgICAgIHRoaXMudGV4dHVyZVVuaXQgPSAtMTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVGV4dHVyZUhlbHBlciB7XHJcbiAgICB0YXJnZXQoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IG51bWJlcjtcclxuICAgIGluaXQoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgdGFyZ2V0OiBudW1iZXIpOiB2b2lkO1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIFRleHR1cmUge1xyXG4gICAgcHJpdmF0ZSBoZWxwZXI6IFRleHR1cmVIZWxwZXI7XHJcbiAgICBwcml2YXRlIHRleHR1cmVzOiBTdHJpbmdNYXA8VGV4dHVyZUVudHJ5PjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihoZWxwZXI6IFRleHR1cmVIZWxwZXIpIHtcclxuICAgICAgICB0aGlzLmhlbHBlciA9IGhlbHBlcjtcclxuICAgICAgICB0aGlzLnRleHR1cmVzID0ge307XHJcbiAgICB9XHJcblxyXG4gICAgYmluZChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB0ZXh0dXJlVW5pdDogbnVtYmVyKSB7XHJcbiAgICAgICAgY29uc3QgZ2xJZCA9IGdldE9iamVjdElkKGdsKTtcclxuICAgICAgICBpZiAoaGFzdmFsKHRoaXMudGV4dHVyZXNbZ2xJZF0pKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGVuID0gdGhpcy50ZXh0dXJlc1tnbElkXTtcclxuICAgICAgICAgICAgZ2wuYWN0aXZlVGV4dHVyZShHTC5URVhUVVJFMCArIHRleHR1cmVVbml0KTtcclxuICAgICAgICAgICAgZ2wuYmluZFRleHR1cmUoZW4udGFyZ2V0LCBlbi50ZXh0dXJlKTtcclxuICAgICAgICAgICAgZW4udGV4dHVyZVVuaXQgPSB0ZXh0dXJlVW5pdDtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IHRoaXMuaGVscGVyLnRhcmdldChnbCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XHJcbiAgICAgICAgICAgIGlmICghaGFzdmFsKHRleHR1cmUpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBjcmVhdGUgdGV4dHVyZScpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMudGV4dHVyZXNbZ2xJZF0gPSBuZXcgVGV4dHVyZUVudHJ5KGdsLCB0YXJnZXQsIHRleHR1cmUpO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgZW4gPSB0aGlzLnRleHR1cmVzW2dsSWRdO1xyXG4gICAgICAgICAgICBnbC5hY3RpdmVUZXh0dXJlKEdMLlRFWFRVUkUwICsgdGV4dHVyZVVuaXQpO1xyXG4gICAgICAgICAgICBnbC5iaW5kVGV4dHVyZShlbi50YXJnZXQsIGVuLnRleHR1cmUpO1xyXG4gICAgICAgICAgICBlbi50ZXh0dXJlVW5pdCA9IHRleHR1cmVVbml0O1xyXG5cclxuICAgICAgICAgICAgdGhpcy5oZWxwZXIuaW5pdChnbCwgdGFyZ2V0KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdW5iaW5kKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpIHtcclxuICAgICAgICBjb25zdCBnbElkID0gZ2V0T2JqZWN0SWQoZ2wpO1xyXG4gICAgICAgIGlmIChoYXN2YWwodGhpcy50ZXh0dXJlc1tnbElkXSkpIHtcclxuICAgICAgICAgICAgY29uc3QgZW4gPSB0aGlzLnRleHR1cmVzW2dsSWRdO1xyXG4gICAgICAgICAgICBnbC5hY3RpdmVUZXh0dXJlKEdMLlRFWFRVUkUwICsgZW4udGV4dHVyZVVuaXQpO1xyXG4gICAgICAgICAgICBnbC5iaW5kVGV4dHVyZShlbi50YXJnZXQsIG51bGwpO1xyXG4gICAgICAgICAgICBlbi50ZXh0dXJlVW5pdCA9IC0xO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBkaXNwb3NlKCkge1xyXG4gICAgICAgIC8vIFhYWDogTm90IHN1cmUgdGhpcyBhY3R1YWxseSB3b3JrcyAuLi4gbWF5IGhhdmUgdG8gbWFrZSBlYWNoIGdsIGN1cnJlbnQgb3Igc29tZXRoaW5nXHJcbiAgICAgICAgZm9yIChjb25zdCBnbGlkIGluIHRoaXMudGV4dHVyZXMpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMudGV4dHVyZXMuaGFzT3duUHJvcGVydHkoZ2xpZCkpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGVuID0gdGhpcy50ZXh0dXJlc1tnbGlkXTtcclxuICAgICAgICAgICAgICAgIGVuLmdsLmRlbGV0ZVRleHR1cmUoZW4udGV4dHVyZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy50ZXh0dXJlcyA9IHt9O1xyXG4gICAgfVxyXG59XHJcblxyXG5cclxuZXhwb3J0IHR5cGUgSW1hZ2VEcmF3ZXIgPSAoY29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKSA9PiB2b2lkO1xyXG5cclxuZXhwb3J0IGNsYXNzIEZsb2F0RGF0YVRleHR1cmUyRCBleHRlbmRzIFRleHR1cmUge1xyXG4gICAgcHJpdmF0ZSBfdzogbnVtYmVyO1xyXG4gICAgcHJpdmF0ZSBfaDogbnVtYmVyO1xyXG5cclxuICAgIGdldCB3KCk6IG51bWJlciB7IHJldHVybiB0aGlzLl93OyB9XHJcbiAgICBnZXQgaCgpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5faDsgfVxyXG5cclxuICAgIGNvbnN0cnVjdG9yKHc6IG51bWJlciwgaDogbnVtYmVyLCBhcnJheTogRmxvYXQzMkFycmF5KSB7XHJcbiAgICAgICAgc3VwZXIoe1xyXG4gICAgICAgICAgICB0YXJnZXQ6IGZ1bmN0aW9uIChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogbnVtYmVyIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBHTC5URVhUVVJFXzJEO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBpbml0OiBmdW5jdGlvbiAoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgdGFyZ2V0OiBudW1iZXIpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWdsLmdldEV4dGVuc2lvbignT0VTX3RleHR1cmVfZmxvYXQnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignT0VTX3RleHR1cmVfZmxvYXQgZXh0ZW5zaW9uIGlzIHJlcXVpcmVkJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaSh0YXJnZXQsIEdMLlRFWFRVUkVfTUFHX0ZJTFRFUiwgR0wuTkVBUkVTVCk7XHJcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0wuVEVYVFVSRV9NSU5fRklMVEVSLCBHTC5ORUFSRVNUKTtcclxuICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTC5URVhUVVJFX1dSQVBfUywgR0wuQ0xBTVBfVE9fRURHRSk7XHJcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0wuVEVYVFVSRV9XUkFQX1QsIEdMLkNMQU1QX1RPX0VER0UpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIEdMLkxVTUlOQU5DRSBpc24ndCBzdXBwb3J0ZWQgd2l0aCBHTC5GTE9BVFxyXG4gICAgICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRCh0YXJnZXQsIDAsIEdMLlJHQkEsIHcsIGgsIDAsIEdMLlJHQkEsIEdMLkZMT0FULCBhcnJheSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5fdyA9IHc7XHJcbiAgICAgICAgdGhpcy5faCA9IGg7XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBUZXh0dXJlMkQgZXh0ZW5kcyBUZXh0dXJlIHtcclxuICAgIHByaXZhdGUgX3c6IG51bWJlcjtcclxuICAgIHByaXZhdGUgX2g6IG51bWJlcjtcclxuXHJcbiAgICBnZXQgdygpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5fdzsgfVxyXG4gICAgZ2V0IGgoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuX2g7IH1cclxuXHJcbiAgICBjb25zdHJ1Y3Rvcih3OiBudW1iZXIsIGg6IG51bWJlciwgbWluRmlsdGVyOiBudW1iZXIsIG1hZ0ZpbHRlcjogbnVtYmVyLCBkcmF3OiBJbWFnZURyYXdlcikge1xyXG4gICAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xyXG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHc7XHJcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGg7XHJcbiAgICAgICAgZHJhdyhjYW52YXMuZ2V0Q29udGV4dCgnMmQnKSk7XHJcblxyXG4gICAgICAgIHN1cGVyKHtcclxuICAgICAgICAgICAgdGFyZ2V0OiBmdW5jdGlvbiAoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IG51bWJlciB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gR0wuVEVYVFVSRV8yRDtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgaW5pdDogZnVuY3Rpb24gKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHRhcmdldDogbnVtYmVyKSB7XHJcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0wuVEVYVFVSRV9NQUdfRklMVEVSLCBtYWdGaWx0ZXIpO1xyXG4gICAgICAgICAgICAgICAgZ2wudGV4UGFyYW1ldGVyaSh0YXJnZXQsIEdMLlRFWFRVUkVfTUlOX0ZJTFRFUiwgbWluRmlsdGVyKTtcclxuICAgICAgICAgICAgICAgIGdsLnRleFBhcmFtZXRlcmkodGFyZ2V0LCBHTC5URVhUVVJFX1dSQVBfUywgR0wuQ0xBTVBfVE9fRURHRSk7XHJcbiAgICAgICAgICAgICAgICBnbC50ZXhQYXJhbWV0ZXJpKHRhcmdldCwgR0wuVEVYVFVSRV9XUkFQX1QsIEdMLkNMQU1QX1RPX0VER0UpO1xyXG4gICAgICAgICAgICAgICAgZ2wudGV4SW1hZ2UyRCh0YXJnZXQsIDAsIEdMLlJHQkEsIEdMLlJHQkEsIEdMLlVOU0lHTkVEX0JZVEUsIGNhbnZhcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5fdyA9IHc7XHJcbiAgICAgICAgdGhpcy5faCA9IGg7XHJcbiAgICB9XHJcbn1cclxuXHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFRleHR1cmVEcmF3T3B0aW9ucyB7XHJcbiAgICB4QW5jaG9yPzogbnVtYmVyO1xyXG4gICAgeUFuY2hvcj86IG51bWJlcjtcclxuICAgIHJvdGF0aW9uX0NDV1JBRD86IG51bWJlcjtcclxuICAgIHdpZHRoPzogbnVtYmVyO1xyXG4gICAgaGVpZ2h0PzogbnVtYmVyO1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIFRleHR1cmVSZW5kZXJlciB7XHJcblxyXG4gICAgcHJpdmF0ZSB0ZXh0dXJlUmVuZGVyZXJfVkVSVFNIQURFUiA9IGNvbmNhdExpbmVzKFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgdW5pZm9ybSB2ZWMyIHVfWHlGcmFjOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICB1bmlmb3JtIHZlYzIgdV9BbmNob3I7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgIHVuaWZvcm0gZmxvYXQgdV9Sb3RhdGlvbl9DQ1dSQUQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgdW5pZm9ybSB2ZWMyIHVfSW1hZ2VTaXplOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICB1bmlmb3JtIHZlYzIgdV9WaWV3cG9ydFNpemU7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgYXR0cmlidXRlIHZlYzIgYV9JbWFnZUZyYWM7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgIHZhcnlpbmcgdmVjMiB2X1N0Q29vcmQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICB2b2lkIG1haW4oICkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICBmbG9hdCBjb3NSb3QgPSBjb3MoIHVfUm90YXRpb25fQ0NXUkFEICk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgICAgIGZsb2F0IHNpblJvdCA9IHNpbiggdV9Sb3RhdGlvbl9DQ1dSQUQgKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAvLyBDb2x1bW4gbWFqb3IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgICAgIG1hdDIgcm90YXRpb24gPSBtYXQyKCBjb3NSb3QsIHNpblJvdCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgLXNpblJvdCwgY29zUm90ICk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgICAgIHZlYzIgeHkgPSAtMS4wICsgMi4wKiggdV9YeUZyYWMgKyByb3RhdGlvbiooIHVfSW1hZ2VTaXplKiggYV9JbWFnZUZyYWMgLSB1X0FuY2hvciApICkgLyB1X1ZpZXdwb3J0U2l6ZSApOyAgJyxcclxuICAgICAgICAnICAgICAgZ2xfUG9zaXRpb24gPSB2ZWM0KCB4eSwgMC4wLCAxLjAgKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAgICAgJyAgICAgIHZfU3RDb29yZCA9IHZlYzIoIGFfSW1hZ2VGcmFjLngsIDEuMCAtIGFfSW1hZ2VGcmFjLnkgKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICAgICAnICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdcclxuICAgICk7XHJcblxyXG4gICAgcHJpdmF0ZSB0ZXh0dXJlUmVuZGVyZXJfRlJBR1NIQURFUiA9IGNvbmNhdExpbmVzKFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgIHByZWNpc2lvbiBtZWRpdW1wIGZsb2F0OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgIHVuaWZvcm0gc2FtcGxlcjJEIHVfU2FtcGxlcjsgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgIHZhcnlpbmcgdmVjMiB2X1N0Q29vcmQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgIHZvaWQgbWFpbiggKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQoIHVfU2FtcGxlciwgdl9TdENvb3JkICk7ICAnLFxyXG4gICAgICAgICcgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnXHJcbiAgICApO1xyXG5cclxuXHJcbiAgICBwcml2YXRlIHByb2dyYW06IFByb2dyYW07XHJcbiAgICBwcml2YXRlIHVfWHlGcmFjOiBVbmlmb3JtMmY7XHJcbiAgICBwcml2YXRlIHVfQW5jaG9yOiBVbmlmb3JtMmY7XHJcbiAgICBwcml2YXRlIHVfUm90YXRpb25fQ0NXUkFEOiBVbmlmb3JtMWY7XHJcbiAgICBwcml2YXRlIHVfSW1hZ2VTaXplOiBVbmlmb3JtMmY7XHJcbiAgICBwcml2YXRlIHVfVmlld3BvcnRTaXplOiBVbmlmb3JtMmY7XHJcbiAgICBwcml2YXRlIHVfU2FtcGxlcjogVW5pZm9ybVNhbXBsZXIyRDtcclxuXHJcbiAgICBwcml2YXRlIGFfSW1hZ2VGcmFjOiBBdHRyaWJ1dGU7XHJcblxyXG4gICAgcHJpdmF0ZSBpbWFnZUZyYWNEYXRhOiBCdWZmZXI7XHJcblxyXG4gICAgcHJpdmF0ZSB3Vmlld3BvcnQ6IG51bWJlcjtcclxuICAgIHByaXZhdGUgaFZpZXdwb3J0OiBudW1iZXI7XHJcblxyXG5cclxuICAgIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgICAgIHRoaXMucHJvZ3JhbSA9IG5ldyBQcm9ncmFtKHRoaXMudGV4dHVyZVJlbmRlcmVyX1ZFUlRTSEFERVIsIHRoaXMudGV4dHVyZVJlbmRlcmVyX0ZSQUdTSEFERVIpO1xyXG4gICAgICAgIHRoaXMudV9YeUZyYWMgPSBuZXcgVW5pZm9ybTJmKHRoaXMucHJvZ3JhbSwgJ3VfWHlGcmFjJyk7XHJcbiAgICAgICAgdGhpcy51X0FuY2hvciA9IG5ldyBVbmlmb3JtMmYodGhpcy5wcm9ncmFtLCAndV9BbmNob3InKTtcclxuICAgICAgICB0aGlzLnVfUm90YXRpb25fQ0NXUkFEID0gbmV3IFVuaWZvcm0xZih0aGlzLnByb2dyYW0sICd1X1JvdGF0aW9uX0NDV1JBRCcpO1xyXG4gICAgICAgIHRoaXMudV9JbWFnZVNpemUgPSBuZXcgVW5pZm9ybTJmKHRoaXMucHJvZ3JhbSwgJ3VfSW1hZ2VTaXplJyk7XHJcbiAgICAgICAgdGhpcy51X1ZpZXdwb3J0U2l6ZSA9IG5ldyBVbmlmb3JtMmYodGhpcy5wcm9ncmFtLCAndV9WaWV3cG9ydFNpemUnKTtcclxuICAgICAgICB0aGlzLnVfU2FtcGxlciA9IG5ldyBVbmlmb3JtU2FtcGxlcjJEKHRoaXMucHJvZ3JhbSwgJ3VfU2FtcGxlcicpO1xyXG5cclxuICAgICAgICB0aGlzLmFfSW1hZ2VGcmFjID0gbmV3IEF0dHJpYnV0ZSh0aGlzLnByb2dyYW0sICdhX0ltYWdlRnJhYycpO1xyXG4gICAgICAgIHRoaXMuaW1hZ2VGcmFjRGF0YSA9IG5ld1N0YXRpY0J1ZmZlcihuZXcgRmxvYXQzMkFycmF5KFswLjAsIDAuMCwgMC4wLCAxLjAsIDEuMCwgMC4wLCAxLjAsIDEuMF0pKTtcclxuXHJcbiAgICAgICAgdGhpcy53Vmlld3BvcnQgPSAwO1xyXG4gICAgICAgIHRoaXMuaFZpZXdwb3J0ID0gMDtcclxuICAgIH1cclxuXHJcbiAgICBiZWdpbihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB2aWV3cG9ydDogQm91bmRzVW5tb2RpZmlhYmxlKSB7XHJcbiAgICAgICAgZ2wuYmxlbmRGdW5jU2VwYXJhdGUoR0wuU1JDX0FMUEhBLCBHTC5PTkVfTUlOVVNfU1JDX0FMUEhBLCBHTC5PTkUsIEdMLk9ORV9NSU5VU19TUkNfQUxQSEEpO1xyXG4gICAgICAgIGdsLmVuYWJsZShHTC5CTEVORCk7XHJcblxyXG4gICAgICAgIHRoaXMucHJvZ3JhbS51c2UoZ2wpO1xyXG4gICAgICAgIHRoaXMudV9WaWV3cG9ydFNpemUuc2V0RGF0YShnbCwgdmlld3BvcnQudywgdmlld3BvcnQuaCk7XHJcbiAgICAgICAgdGhpcy5hX0ltYWdlRnJhYy5zZXREYXRhQW5kRW5hYmxlKGdsLCB0aGlzLmltYWdlRnJhY0RhdGEsIDIsIEdMLkZMT0FUKTtcclxuXHJcbiAgICAgICAgdGhpcy53Vmlld3BvcnQgPSB2aWV3cG9ydC53O1xyXG4gICAgICAgIHRoaXMuaFZpZXdwb3J0ID0gdmlld3BvcnQuaDtcclxuICAgIH1cclxuXHJcbiAgICBkcmF3KGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHRleHR1cmU6IFRleHR1cmUyRCwgeEZyYWM6IG51bWJlciwgeUZyYWM6IG51bWJlciwgb3B0aW9ucz86IFRleHR1cmVEcmF3T3B0aW9ucykge1xyXG4gICAgICAgIGNvbnN0IHhBbmNob3IgPSAoaGFzdmFsKG9wdGlvbnMpICYmIGhhc3ZhbChvcHRpb25zLnhBbmNob3IpID8gb3B0aW9ucy54QW5jaG9yIDogMC41KTtcclxuICAgICAgICBjb25zdCB5QW5jaG9yID0gKGhhc3ZhbChvcHRpb25zKSAmJiBoYXN2YWwob3B0aW9ucy55QW5jaG9yKSA/IG9wdGlvbnMueUFuY2hvciA6IDAuNSk7XHJcbiAgICAgICAgY29uc3Qgcm90YXRpb25fQ0NXUkFEID0gKGhhc3ZhbChvcHRpb25zKSAmJiBoYXN2YWwob3B0aW9ucy5yb3RhdGlvbl9DQ1dSQUQpID8gb3B0aW9ucy5yb3RhdGlvbl9DQ1dSQUQgOiAwKTtcclxuICAgICAgICBjb25zdCB3aWR0aCA9IChoYXN2YWwob3B0aW9ucykgJiYgaGFzdmFsKG9wdGlvbnMud2lkdGgpID8gb3B0aW9ucy53aWR0aCA6IHRleHR1cmUudyk7XHJcbiAgICAgICAgY29uc3QgaGVpZ2h0ID0gKGhhc3ZhbChvcHRpb25zKSAmJiBoYXN2YWwob3B0aW9ucy5oZWlnaHQpID8gb3B0aW9ucy5oZWlnaHQgOiB0ZXh0dXJlLmgpO1xyXG5cclxuICAgICAgICB0aGlzLnVfWHlGcmFjLnNldERhdGEoZ2wsIG5lYXJlc3RQaXhlbCh4RnJhYywgdGhpcy53Vmlld3BvcnQsIHhBbmNob3IsIHRleHR1cmUudyksIG5lYXJlc3RQaXhlbCh5RnJhYywgdGhpcy5oVmlld3BvcnQsIHlBbmNob3IsIHRleHR1cmUuaCkpO1xyXG4gICAgICAgIHRoaXMudV9BbmNob3Iuc2V0RGF0YShnbCwgeEFuY2hvciwgeUFuY2hvcik7XHJcbiAgICAgICAgdGhpcy51X1JvdGF0aW9uX0NDV1JBRC5zZXREYXRhKGdsLCByb3RhdGlvbl9DQ1dSQUQpO1xyXG4gICAgICAgIHRoaXMudV9JbWFnZVNpemUuc2V0RGF0YShnbCwgd2lkdGgsIGhlaWdodCk7XHJcbiAgICAgICAgdGhpcy51X1NhbXBsZXIuc2V0RGF0YUFuZEJpbmQoZ2wsIDAsIHRleHR1cmUpO1xyXG4gICAgICAgIGdsLmRyYXdBcnJheXMoR0wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpO1xyXG4gICAgfVxyXG5cclxuICAgIGVuZChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KSB7XHJcbiAgICAgICAgdGhpcy5hX0ltYWdlRnJhYy5kaXNhYmxlKGdsKTtcclxuICAgICAgICB0aGlzLnVfU2FtcGxlci51bmJpbmQoZ2wpO1xyXG4gICAgICAgIHRoaXMucHJvZ3JhbS5lbmRVc2UoZ2wpO1xyXG4gICAgfVxyXG59XHJcblxyXG5cclxuIl19