UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

181 lines 41.7 kB
/* * 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