UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

338 lines 57.5 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 { Pane } from './core'; import { sameColor } from './color'; import { Program, UniformColor, Attribute, Uniform1f } from './shader'; import { newDynamicBuffer } from './buffer'; import { GL, concatLines, hasval } from './util/util'; import { TextureRenderer } from './texture'; import { Notification } from './util/notification'; export function newGroupPainter(...painters) { return function (gl, viewport) { for (let n = 0; n < painters.length; n++) { painters[n](gl, viewport); } }; } export function newBlendingBackgroundPainter(color) { const program = new Program(xyNdc_VERTSHADER, solid_FRAGSHADER); const u_Color = new UniformColor(program, 'u_Color'); const a_XyNdc = new Attribute(program, 'a_XyNdc'); const numVertices = 4; const xy_NDC = new Float32Array(2 * numVertices); const xyBuffer_NDC = newDynamicBuffer(); return function (gl) { if (color.a >= 1) { gl.disable(GL.BLEND); } else { gl.blendFuncSeparate(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA); gl.enable(GL.BLEND); } program.use(gl); u_Color.setData(gl, color); xy_NDC[0] = -1; xy_NDC[1] = 1; xy_NDC[2] = -1; xy_NDC[3] = -1; xy_NDC[4] = 1; xy_NDC[5] = 1; xy_NDC[6] = 1; xy_NDC[7] = -1; xyBuffer_NDC.setData(xy_NDC); a_XyNdc.setDataAndEnable(gl, xyBuffer_NDC, 2, GL.FLOAT); gl.drawArrays(GL.TRIANGLE_STRIP, 0, numVertices); a_XyNdc.disable(gl); program.endUse(gl); }; } export class Highlight { constructor(color) { this._dashPattern = 0xFFFF; this._dashLength = 16; this.program = new Program(xyNdc_VERTSHADER, dash2_FRAGSHADER); this.u_Color = new UniformColor(this.program, 'u_Color'); this.a_XyNdc = new Attribute(this.program, 'a_XyNdc'); this.u_yOffset = new Uniform1f(this.program, 'u_yOffset'); this.u_DashPattern = new Uniform1f(this.program, 'u_DashPattern'); this.u_DashLength = new Uniform1f(this.program, 'u_DashLength'); this.numVertices = 4; this.xy_NDC = new Float32Array(2 * this.numVertices); this.xyBuffer_NDC = newDynamicBuffer(); this._color = color; } get color() { return this._color; } set color(color) { if (!sameColor(this._color, color)) { this._color = color; } } get dashPattern() { return this._dashPattern; } set dashPattern(pattern) { this._dashPattern = pattern; } get dashLength() { return this._dashLength; } set dashLength(length) { this._dashLength = length; } newPainter() { return (gl, viewport) => { if (this.color.a >= 1) { gl.disable(GL.BLEND); } else { 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_Color.setData(gl, this.color); this.u_DashPattern.setData(gl, this._dashPattern); this.u_DashLength.setData(gl, this._dashLength); this.u_yOffset.setData(gl, viewport.j + viewport.h); this.xy_NDC[0] = -1; this.xy_NDC[1] = 1; this.xy_NDC[2] = -1; this.xy_NDC[3] = -1; this.xy_NDC[4] = 1; this.xy_NDC[5] = 1; this.xy_NDC[6] = 1; this.xy_NDC[7] = -1; this.xyBuffer_NDC.setData(this.xy_NDC); this.a_XyNdc.setDataAndEnable(gl, this.xyBuffer_NDC, 2, GL.FLOAT); gl.drawArrays(GL.TRIANGLE_STRIP, 0, this.numVertices); this.a_XyNdc.disable(gl); this.program.endUse(gl); }; } } export class Background { constructor(color) { this._color = color; } get color() { return this._color; } set color(color) { if (!sameColor(this._color, color)) { this._color = color; } } newPainter() { const background = this; return function (gl, viewport) { if (hasval(background.color)) { gl.clearColor(background.color.r, background.color.g, background.color.b, background.color.a); gl.clear(GL.COLOR_BUFFER_BIT); } }; } } export function newBackgroundPainter(color) { return function (gl) { gl.clearColor(color.r, color.g, color.b, color.a); gl.clear(GL.COLOR_BUFFER_BIT); }; } export function newTexturePainter(texture, xFrac, yFrac, options) { const textureRenderer = new TextureRenderer(); return function (gl, viewport) { textureRenderer.begin(gl, viewport); textureRenderer.draw(gl, texture, xFrac, yFrac, options); textureRenderer.end(gl); }; } export function newSolidPane(color) { const pane = new Pane(null); pane.addPainter(newBackgroundPainter(color)); return pane; } export function fitToTexture(texture) { return function (parentPrefSize) { parentPrefSize.w = texture.w; parentPrefSize.h = texture.h; }; } export function fixedSize(w, h) { return function (parentPrefSize) { parentPrefSize.w = w; parentPrefSize.h = h; }; } /** * Takes (x,y) in NDC (Normalized Device Coords), in attribute a_XyNdc */ export let xyNdc_VERTSHADER = concatLines(' ', ' attribute vec2 a_XyNdc; ', ' ', ' void main( ) { ', ' gl_Position = vec4( a_XyNdc, 0.0, 1.0 ); ', ' } ', ' '); /** * Takes (x,y) as fractions of the viewport, in attribute a_XyFrac */ export let xyFrac_VERTSHADER = concatLines(' ', ' attribute vec2 a_XyFrac; ', ' ', ' void main( ) { ', ' gl_Position = vec4( ( -1.0 + 2.0*a_XyFrac ), 0.0, 1.0 ); ', ' } ', ' '); export let solid_FRAGSHADER = concatLines(' ', ' precision lowp float; ', ' uniform vec4 u_Color; ', ' ', ' void main( ) { ', ' gl_FragColor = u_Color; ', ' } ', ' '); export let dash_FRAGSHADER = concatLines(' precision highp float; ', ' uniform mat4 u_modelViewMatrix; ', ' varying float v_Distance; ', ' uniform float u_Dash; ', ' uniform vec4 u_Color; ', ' ', ' void main( ) { ', ' float v = floor(2.0 * fract(v_Distance * (u_Dash * (10.0 * u_modelViewMatrix[0][0])))); ', ' if(v > 0.5) ', ' discard; ', ' else ', ' gl_FragColor = u_Color; ', ' } ', ' '); export let dash2_FRAGSHADER = concatLines(' precision highp float; ', ' uniform float u_DashLength; ', ' uniform float u_DashPattern; ', ' uniform float u_yOffset; ', ' uniform vec4 u_Color; ', ' const float maskLength = 16.0; ', ' ', ' void main( ) { ', ' float dashPosition = fract((gl_FragCoord.y - u_yOffset) / u_DashLength); ', ' float maskIndex = floor(dashPosition * maskLength); ', ' float maskTest = floor(u_DashPattern / pow(2.0, maskIndex)); ', ' ', ' if(mod(maskTest, 2.0) < 1.0) ', ' discard; ', ' else ', ' gl_FragColor = u_Color; ', ' } ', ' '); export let varyingColor_FRAGSHADER = concatLines(' ', ' precision lowp float; ', ' varying vec4 v_Color; ', ' ', ' void main( ) { ', ' gl_FragColor = v_Color; ', ' } ', ' '); export let modelview_VERTSHADER = concatLines(' uniform mat4 u_modelViewMatrix; ', ' attribute vec4 a_Position; ', ' ', ' void main( ) { ', ' gl_Position = u_modelViewMatrix * a_Position ; ', ' } ', ' '); export let nearestPixelCenter_GLSLFUNC = concatLines(' ', ' float nearestPixelCenter( float frac, float pixelSize ) { ', ' return ( floor( frac*pixelSize + 1e-4 ) + 0.5 ) / pixelSize; ', ' } ', ' '); export var Side; (function (Side) { Side[Side["TOP"] = 0] = "TOP"; Side[Side["BOTTOM"] = 1] = "BOTTOM"; Side[Side["RIGHT"] = 2] = "RIGHT"; Side[Side["LEFT"] = 3] = "LEFT"; })(Side || (Side = {})); /** * Converts viewport-fraction to NDC (Normalized Device Coords) */ export function fracToNdc(frac) { return -1 + 2 * frac; } export function nearestPixel(viewportFrac, viewportSize, imageAnchor, imageSize) { const anchor = (imageAnchor * imageSize) % 1.0; return (Math.floor(viewportFrac * viewportSize - anchor + 0.5 + 1e-4) + anchor) / viewportSize; } export function putQuadXys(xys, index, xLeft, xRight, yTop, yBottom) { let n = index; n = putUpperLeftTriangleXys(xys, n, xLeft, xRight, yTop, yBottom); n = putLowerRightTriangleXys(xys, n, xLeft, xRight, yTop, yBottom); return n; } export function putUpperLeftTriangleXys(xys, index, xLeft, xRight, yTop, yBottom) { let n = index; xys[n++] = xLeft; xys[n++] = yTop; xys[n++] = xRight; xys[n++] = yTop; xys[n++] = xLeft; xys[n++] = yBottom; return n; } export function putLowerRightTriangleXys(xys, index, xLeft, xRight, yTop, yBottom) { let n = index; xys[n++] = xLeft; xys[n++] = yBottom; xys[n++] = xRight; xys[n++] = yTop; xys[n++] = xRight; xys[n++] = yBottom; return n; } export function putUpperRightTriangleXys(xys, index, xLeft, xRight, yTop, yBottom) { let n = index; xys[n++] = xLeft; xys[n++] = yTop; xys[n++] = xRight; xys[n++] = yTop; xys[n++] = xRight; xys[n++] = yBottom; return n; } export function putLowerLeftTriangleXys(xys, index, xLeft, xRight, yTop, yBottom) { let n = index; xys[n++] = xLeft; xys[n++] = yBottom; xys[n++] = xLeft; xys[n++] = yTop; xys[n++] = xRight; xys[n++] = yBottom; return n; } export function putQuadRgbas(rgbas, index, color) { return putRgbas(rgbas, index, color, 6); } export function putRgbas(rgbas, index, color, count) { let n = index; for (let v = 0; v < count; v++) { rgbas[n++] = color.r; rgbas[n++] = color.g; rgbas[n++] = color.b; rgbas[n++] = color.a; } return n; } export function clearSelection() { const selection = window.getSelection(); if (selection) { if (selection['removeAllRanges']) { selection['removeAllRanges'](); } else if (selection['empty']) { selection['empty'](); } } } export class SimpleModel { constructor(value = null) { this._value = value; this._changed = new Notification(); } get value() { return this._value; } get changed() { return this._changed; } set value(value) { if (value !== this._value) { this._value = value; this._changed.fire(); } } } export class XyModel { constructor(x, y) { this._x = x; this._y = y; this._changed = new Notification(); } get x() { return this._x; } get y() { return this._y; } get changed() { return this._changed; } set x(x) { if (x !== this._x) { this._x = x; this._changed.fire(); } } set y(y) { if (y !== this._y) { this._y = y; this._changed.fire(); } } setXy(x, y) { if (x !== this._x || y !== this._y) { this._x = x; this._y = y; this._changed.fire(); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlzYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93ZWJnbGltcHNlL21pc2MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxPQUFPLEVBQVcsSUFBSSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRXZDLE9BQU8sRUFBUyxTQUFTLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDM0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQWlCLE1BQU0sVUFBVSxDQUFDO0FBQzNELE9BQU8sRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN0RCxPQUFPLEVBQWlDLGVBQWUsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMzRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbkQsTUFBTSxVQUFVLGVBQWUsQ0FBQyxHQUFHLFFBQW1CO0lBQ2xELE9BQWdCLFVBQVUsRUFBeUIsRUFBRSxRQUE0QjtRQUM3RSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN0QyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1NBQzdCO0lBQ0wsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUdELE1BQU0sVUFBVSw0QkFBNEIsQ0FBQyxLQUFZO0lBRXJELE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDaEUsTUFBTSxPQUFPLEdBQUcsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3JELE1B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QUMsS0FBYSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25DLElBQUksQ0FBQyxLQUFhLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkMsSUFBSSxPQUFPLEtBQW1CLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFFckQsSUFBSSxDQUFDLENBQUMsQ0FBUztRQUNYLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDZixJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNaLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDO0lBRUQsSUFBSSxDQUFDLENBQUMsQ0FBUztRQUNYLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDZixJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNaLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLENBQVMsRUFBRSxDQUFTO1FBQ3RCLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDaEMsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDWixJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNaLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQsIE1ldHJvbiwgSW5jLlxyXG4gKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKlxyXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxyXG4gKiBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XHJcbiAqXHJcbiAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xyXG4gKiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cclxuICpcclxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxyXG4gKiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXHJcbiAqICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG4gKlxyXG4gKiAzLiBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBjb3B5cmlnaHQgaG9sZGVyIG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9yc1xyXG4gKiAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dFxyXG4gKiAgICBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uXHJcbiAqXHJcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxyXG4gKiBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxyXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXHJcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXHJcbiAqIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xyXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XHJcbiAqIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxyXG4gKiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxyXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xyXG4gKiBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuICovXHJcbmltcG9ydCB7IFBhaW50ZXIsIFBhbmUgfSBmcm9tICcuL2NvcmUnO1xyXG5pbXBvcnQgeyBCb3VuZHNVbm1vZGlmaWFibGUsIFNpemUgfSBmcm9tICcuL2JvdW5kcyc7XHJcbmltcG9ydCB7IENvbG9yLCBzYW1lQ29sb3IgfSBmcm9tICcuL2NvbG9yJztcclxuaW1wb3J0IHsgUHJvZ3JhbSwgVW5pZm9ybUNvbG9yLCBBdHRyaWJ1dGUsIFVuaWZvcm0xZiB9IGZyb20gJy4vc2hhZGVyJztcclxuaW1wb3J0IHsgbmV3RHluYW1pY0J1ZmZlciwgRHluYW1pY0J1ZmZlciB9IGZyb20gJy4vYnVmZmVyJztcclxuaW1wb3J0IHsgR0wsIGNvbmNhdExpbmVzLCBoYXN2YWwgfSBmcm9tICcuL3V0aWwvdXRpbCc7XHJcbmltcG9ydCB7IFRleHR1cmUyRCwgVGV4dHVyZURyYXdPcHRpb25zLCBUZXh0dXJlUmVuZGVyZXIgfSBmcm9tICcuL3RleHR1cmUnO1xyXG5pbXBvcnQgeyBOb3RpZmljYXRpb24gfSBmcm9tICcuL3V0aWwvbm90aWZpY2F0aW9uJztcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdHcm91cFBhaW50ZXIoLi4ucGFpbnRlcnM6IFBhaW50ZXJbXSk6IFBhaW50ZXIge1xyXG4gICAgcmV0dXJuIDxQYWludGVyPmZ1bmN0aW9uIChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB2aWV3cG9ydDogQm91bmRzVW5tb2RpZmlhYmxlKTogdm9pZCB7XHJcbiAgICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCBwYWludGVycy5sZW5ndGg7IG4rKykge1xyXG4gICAgICAgICAgICBwYWludGVyc1tuXShnbCwgdmlld3BvcnQpO1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbmV3QmxlbmRpbmdCYWNrZ3JvdW5kUGFpbnRlcihjb2xvcjogQ29sb3IpOiBQYWludGVyIHtcclxuXHJcbiAgICBjb25zdCBwcm9ncmFtID0gbmV3IFByb2dyYW0oeHlOZGNfVkVSVFNIQURFUiwgc29saWRfRlJBR1NIQURFUik7XHJcbiAgICBjb25zdCB1X0NvbG9yID0gbmV3IFVuaWZvcm1Db2xvcihwcm9ncmFtLCAndV9Db2xvcicpO1xyXG4gICAgY29uc3QgYV9YeU5kYyA9IG5ldyBBdHRyaWJ1dGUocHJvZ3JhbSwgJ2FfWHlOZGMnKTtcclxuXHJcbiAgICBjb25zdCBudW1WZXJ0aWNlcyA9IDQ7XHJcbiAgICBjb25zdCB4eV9OREMgPSBuZXcgRmxvYXQzMkFycmF5KDIgKiBudW1WZXJ0aWNlcyk7XHJcbiAgICBjb25zdCB4eUJ1ZmZlcl9OREMgPSBuZXdEeW5hbWljQnVmZmVyKCk7XHJcblxyXG4gICAgcmV0dXJuIDxQYWludGVyPmZ1bmN0aW9uIChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogdm9pZCB7XHJcbiAgICAgICAgaWYgKGNvbG9yLmEgPj0gMSkge1xyXG4gICAgICAgICAgICBnbC5kaXNhYmxlKEdMLkJMRU5EKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGdsLmJsZW5kRnVuY1NlcGFyYXRlKEdMLlNSQ19BTFBIQSwgR0wuT05FX01JTlVTX1NSQ19BTFBIQSwgR0wuT05FLCBHTC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcclxuICAgICAgICAgICAgZ2wuZW5hYmxlKEdMLkJMRU5EKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHByb2dyYW0udXNlKGdsKTtcclxuICAgICAgICB1X0NvbG9yLnNldERhdGEoZ2wsIGNvbG9yKTtcclxuXHJcbiAgICAgICAgeHlfTkRDWzBdID0gLTE7XHJcbiAgICAgICAgeHlfTkRDWzFdID0gMTtcclxuICAgICAgICB4eV9ORENbMl0gPSAtMTtcclxuICAgICAgICB4eV9ORENbM10gPSAtMTtcclxuICAgICAgICB4eV9ORENbNF0gPSAxO1xyXG4gICAgICAgIHh5X05EQ1s1XSA9IDE7XHJcbiAgICAgICAgeHlfTkRDWzZdID0gMTtcclxuICAgICAgICB4eV9ORENbN10gPSAtMTtcclxuXHJcbiAgICAgICAgeHlCdWZmZXJfTkRDLnNldERhdGEoeHlfTkRDKTtcclxuICAgICAgICBhX1h5TmRjLnNldERhdGFBbmRFbmFibGUoZ2wsIHh5QnVmZmVyX05EQywgMiwgR0wuRkxPQVQpO1xyXG5cclxuICAgICAgICBnbC5kcmF3QXJyYXlzKEdMLlRSSUFOR0xFX1NUUklQLCAwLCBudW1WZXJ0aWNlcyk7XHJcblxyXG4gICAgICAgIGFfWHlOZGMuZGlzYWJsZShnbCk7XHJcbiAgICAgICAgcHJvZ3JhbS5lbmRVc2UoZ2wpO1xyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIEhpZ2hsaWdodCB7XHJcblxyXG4gICAgcHJpdmF0ZSBfY29sb3I6IENvbG9yO1xyXG4gICAgcHJpdmF0ZSBfZGFzaFBhdHRlcm4gPSAweEZGRkY7XHJcbiAgICBwcml2YXRlIF9kYXNoTGVuZ3RoID0gMTY7XHJcblxyXG4gICAgcHJvZ3JhbSA9IG5ldyBQcm9ncmFtKHh5TmRjX1ZFUlRTSEFERVIsIGRhc2gyX0ZSQUdTSEFERVIpO1xyXG4gICAgdV9Db2xvciA9IG5ldyBVbmlmb3JtQ29sb3IodGhpcy5wcm9ncmFtLCAndV9Db2xvcicpO1xyXG4gICAgYV9YeU5kYyA9IG5ldyBBdHRyaWJ1dGUodGhpcy5wcm9ncmFtLCAnYV9YeU5kYycpO1xyXG4gICAgdV95T2Zmc2V0ID0gbmV3IFVuaWZvcm0xZih0aGlzLnByb2dyYW0sICd1X3lPZmZzZXQnKTtcclxuICAgIHVfRGFzaFBhdHRlcm4gPSBuZXcgVW5pZm9ybTFmKHRoaXMucHJvZ3JhbSwgJ3VfRGFzaFBhdHRlcm4nKTtcclxuICAgIHVfRGFzaExlbmd0aCA9IG5ldyBVbmlmb3JtMWYodGhpcy5wcm9ncmFtLCAndV9EYXNoTGVuZ3RoJyk7XHJcblxyXG4gICAgbnVtVmVydGljZXMgPSA0O1xyXG4gICAgeHlfTkRDID0gbmV3IEZsb2F0MzJBcnJheSgyICogdGhpcy5udW1WZXJ0aWNlcyk7XHJcbiAgICB4eUJ1ZmZlcl9OREM6IER5bmFtaWNCdWZmZXIgPSBuZXdEeW5hbWljQnVmZmVyKCk7XHJcblxyXG4gICAgY29uc3RydWN0b3IoY29sb3I/OiBDb2xvcikge1xyXG4gICAgICAgIHRoaXMuX2NvbG9yID0gY29sb3I7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGNvbG9yKCk6IENvbG9yIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fY29sb3I7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0IGNvbG9yKGNvbG9yOiBDb2xvcikge1xyXG4gICAgICAgIGlmICghc2FtZUNvbG9yKHRoaXMuX2NvbG9yLCBjb2xvcikpIHtcclxuICAgICAgICAgICAgdGhpcy5fY29sb3IgPSBjb2xvcjtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGRhc2hQYXR0ZXJuKCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Rhc2hQYXR0ZXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHNldCBkYXNoUGF0dGVybihwYXR0ZXJuOiBudW1iZXIpIHtcclxuICAgICAgICB0aGlzLl9kYXNoUGF0dGVybiA9IHBhdHRlcm47XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGRhc2hMZW5ndGgoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fZGFzaExlbmd0aDtcclxuICAgIH1cclxuXHJcbiAgICBzZXQgZGFzaExlbmd0aChsZW5ndGg6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMuX2Rhc2hMZW5ndGggPSBsZW5ndGg7XHJcbiAgICB9XHJcblxyXG4gICAgbmV3UGFpbnRlcigpIHtcclxuICAgICAgICByZXR1cm4gKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHZpZXdwb3J0OiBCb3VuZHNVbm1vZGlmaWFibGUpID0+IHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuY29sb3IuYSA+PSAxKSB7XHJcbiAgICAgICAgICAgICAgICBnbC5kaXNhYmxlKEdMLkJMRU5EKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGdsLmJsZW5kRnVuY1NlcGFyYXRlKEdMLlNSQ19BTFBIQSwgR0wuT05FX01JTlVTX1NSQ19BTFBIQSwgR0wuT05FLCBHTC5PTkVfTUlOVVNfU1JDX0FMUEhBKTtcclxuICAgICAgICAgICAgICAgIGdsLmVuYWJsZShHTC5CTEVORCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMucHJvZ3JhbS51c2UoZ2wpO1xyXG4gICAgICAgICAgICB0aGlzLnVfQ29sb3Iuc2V0RGF0YShnbCwgdGhpcy5jb2xvcik7XHJcbiAgICAgICAgICAgIHRoaXMudV9EYXNoUGF0dGVybi5zZXREYXRhKGdsLCB0aGlzLl9kYXNoUGF0dGVybik7XHJcbiAgICAgICAgICAgIHRoaXMudV9EYXNoTGVuZ3RoLnNldERhdGEoZ2wsIHRoaXMuX2Rhc2hMZW5ndGgpO1xyXG4gICAgICAgICAgICB0aGlzLnVfeU9mZnNldC5zZXREYXRhKGdsLCB2aWV3cG9ydC5qICsgdmlld3BvcnQuaCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnh5X05EQ1swXSA9IC0xO1xyXG4gICAgICAgICAgICB0aGlzLnh5X05EQ1sxXSA9IDE7XHJcbiAgICAgICAgICAgIHRoaXMueHlfTkRDWzJdID0gLTE7XHJcbiAgICAgICAgICAgIHRoaXMueHlfTkRDWzNdID0gLTE7XHJcbiAgICAgICAgICAgIHRoaXMueHlfTkRDWzRdID0gMTtcclxuICAgICAgICAgICAgdGhpcy54eV9ORENbNV0gPSAxO1xyXG4gICAgICAgICAgICB0aGlzLnh5X05EQ1s2XSA9IDE7XHJcbiAgICAgICAgICAgIHRoaXMueHlfTkRDWzddID0gLTE7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnh5QnVmZmVyX05EQy5zZXREYXRhKHRoaXMueHlfTkRDKTtcclxuICAgICAgICAgICAgdGhpcy5hX1h5TmRjLnNldERhdGFBbmRFbmFibGUoZ2wsIHRoaXMueHlCdWZmZXJfTkRDLCAyLCBHTC5GTE9BVCk7XHJcblxyXG4gICAgICAgICAgICBnbC5kcmF3QXJyYXlzKEdMLlRSSUFOR0xFX1NUUklQLCAwLCB0aGlzLm51bVZlcnRpY2VzKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuYV9YeU5kYy5kaXNhYmxlKGdsKTtcclxuICAgICAgICAgICAgdGhpcy5wcm9ncmFtLmVuZFVzZShnbCk7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIEJhY2tncm91bmQge1xyXG5cclxuICAgIHByaXZhdGUgX2NvbG9yOiBDb2xvcjtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihjb2xvcj86IENvbG9yKSB7XHJcbiAgICAgICAgdGhpcy5fY29sb3IgPSBjb2xvcjtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgY29sb3IoKTogQ29sb3Ige1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9jb2xvcjtcclxuICAgIH1cclxuXHJcbiAgICBzZXQgY29sb3IoY29sb3I6IENvbG9yKSB7XHJcbiAgICAgICAgaWYgKCFzYW1lQ29sb3IodGhpcy5fY29sb3IsIGNvbG9yKSkge1xyXG4gICAgICAgICAgICB0aGlzLl9jb2xvciA9IGNvbG9yO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBuZXdQYWludGVyKCkge1xyXG4gICAgICAgIGNvbnN0IGJhY2tncm91bmQ6IEJhY2tncm91bmQgPSB0aGlzO1xyXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgdmlld3BvcnQ6IEJvdW5kc1VubW9kaWZpYWJsZSkge1xyXG4gICAgICAgICAgICBpZiAoaGFzdmFsKGJhY2tncm91bmQuY29sb3IpKSB7XHJcbiAgICAgICAgICAgICAgICBnbC5jbGVhckNvbG9yKGJhY2tncm91bmQuY29sb3IuciwgYmFja2dyb3VuZC5jb2xvci5nLCBiYWNrZ3JvdW5kLmNvbG9yLmIsIGJhY2tncm91bmQuY29sb3IuYSk7XHJcbiAgICAgICAgICAgICAgICBnbC5jbGVhcihHTC5DT0xPUl9CVUZGRVJfQklUKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbmV3QmFja2dyb3VuZFBhaW50ZXIoY29sb3I6IENvbG9yKTogUGFpbnRlciB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpIHtcclxuICAgICAgICBnbC5jbGVhckNvbG9yKGNvbG9yLnIsIGNvbG9yLmcsIGNvbG9yLmIsIGNvbG9yLmEpO1xyXG4gICAgICAgIGdsLmNsZWFyKEdMLkNPTE9SX0JVRkZFUl9CSVQpO1xyXG4gICAgfTtcclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdUZXh0dXJlUGFpbnRlcih0ZXh0dXJlOiBUZXh0dXJlMkQsIHhGcmFjOiBudW1iZXIsIHlGcmFjOiBudW1iZXIsIG9wdGlvbnM6IFRleHR1cmVEcmF3T3B0aW9ucykge1xyXG4gICAgY29uc3QgdGV4dHVyZVJlbmRlcmVyID0gbmV3IFRleHR1cmVSZW5kZXJlcigpO1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB2aWV3cG9ydDogQm91bmRzVW5tb2RpZmlhYmxlKSB7XHJcbiAgICAgICAgdGV4dHVyZVJlbmRlcmVyLmJlZ2luKGdsLCB2aWV3cG9ydCk7XHJcbiAgICAgICAgdGV4dHVyZVJlbmRlcmVyLmRyYXcoZ2wsIHRleHR1cmUsIHhGcmFjLCB5RnJhYywgb3B0aW9ucyk7XHJcbiAgICAgICAgdGV4dHVyZVJlbmRlcmVyLmVuZChnbCk7XHJcbiAgICB9O1xyXG59XHJcblxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIG5ld1NvbGlkUGFuZShjb2xvcjogQ29sb3IpOiBQYW5lIHtcclxuICAgIGNvbnN0IHBhbmUgPSBuZXcgUGFuZShudWxsKTtcclxuICAgIHBhbmUuYWRkUGFpbnRlcihuZXdCYWNrZ3JvdW5kUGFpbnRlcihjb2xvcikpO1xyXG4gICAgcmV0dXJuIHBhbmU7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZml0VG9UZXh0dXJlKHRleHR1cmU6IFRleHR1cmUyRCkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChwYXJlbnRQcmVmU2l6ZTogU2l6ZSkge1xyXG4gICAgICAgIHBhcmVudFByZWZTaXplLncgPSB0ZXh0dXJlLnc7XHJcbiAgICAgICAgcGFyZW50UHJlZlNpemUuaCA9IHRleHR1cmUuaDtcclxuICAgIH07XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gZml4ZWRTaXplKHc6IG51bWJlciwgaDogbnVtYmVyKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHBhcmVudFByZWZTaXplOiBTaXplKSB7XHJcbiAgICAgICAgcGFyZW50UHJlZlNpemUudyA9IHc7XHJcbiAgICAgICAgcGFyZW50UHJlZlNpemUuaCA9IGg7XHJcbiAgICB9O1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIFRha2VzICh4LHkpIGluIE5EQyAoTm9ybWFsaXplZCBEZXZpY2UgQ29vcmRzKSwgaW4gYXR0cmlidXRlIGFfWHlOZGNcclxuICovXHJcbmV4cG9ydCBsZXQgeHlOZGNfVkVSVFNIQURFUiA9IGNvbmNhdExpbmVzKFxyXG4gICAgJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICBhdHRyaWJ1dGUgdmVjMiBhX1h5TmRjOyAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgdm9pZCBtYWluKCApIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgZ2xfUG9zaXRpb24gPSB2ZWM0KCBhX1h5TmRjLCAwLjAsIDEuMCApOyAgJyxcclxuICAgICcgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdcclxuKTtcclxuXHJcblxyXG4vKipcclxuICogVGFrZXMgKHgseSkgYXMgZnJhY3Rpb25zIG9mIHRoZSB2aWV3cG9ydCwgaW4gYXR0cmlidXRlIGFfWHlGcmFjXHJcbiAqL1xyXG5leHBvcnQgbGV0IHh5RnJhY19WRVJUU0hBREVSID0gY29uY2F0TGluZXMoXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICBhdHRyaWJ1dGUgdmVjMiBhX1h5RnJhYzsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICB2b2lkIG1haW4oICkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgZ2xfUG9zaXRpb24gPSB2ZWM0KCAoIC0xLjAgKyAyLjAqYV9YeUZyYWMgKSwgMC4wLCAxLjAgKTsgICcsXHJcbiAgICAnICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdcclxuKTtcclxuXHJcblxyXG5leHBvcnQgbGV0IHNvbGlkX0ZSQUdTSEFERVIgPSBjb25jYXRMaW5lcyhcclxuICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIHByZWNpc2lvbiBsb3dwIGZsb2F0OyAgICAgICAgJyxcclxuICAgICcgIHVuaWZvcm0gdmVjNCB1X0NvbG9yOyAgICAgICAgJyxcclxuICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIHZvaWQgbWFpbiggKSB7ICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICBnbF9GcmFnQ29sb3IgPSB1X0NvbG9yOyAgJyxcclxuICAgICcgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1xyXG4pO1xyXG5cclxuXHJcbmV4cG9ydCBsZXQgZGFzaF9GUkFHU0hBREVSID0gY29uY2F0TGluZXMoXHJcbiAgICAnICBwcmVjaXNpb24gaGlnaHAgZmxvYXQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4OyAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIHZhcnlpbmcgZmxvYXQgdl9EaXN0YW5jZTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICB1bmlmb3JtIGZsb2F0IHVfRGFzaDsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgdW5pZm9ybSB2ZWM0IHVfQ29sb3I7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICB2b2lkIG1haW4oICkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgICAgIGZsb2F0IHYgPSBmbG9vcigyLjAgKiBmcmFjdCh2X0Rpc3RhbmNlICogKHVfRGFzaCAqICgxMC4wICogdV9tb2RlbFZpZXdNYXRyaXhbMF1bMF0pKSkpOyAgICcsXHJcbiAgICAnICAgICAgaWYodiA+IDAuNSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgICAgICAgICBkaXNjYXJkOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICBlbHNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgICAgIGdsX0ZyYWdDb2xvciA9IHVfQ29sb3I7ICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdcclxuKTtcclxuXHJcbmV4cG9ydCBsZXQgZGFzaDJfRlJBR1NIQURFUiA9IGNvbmNhdExpbmVzKFxyXG4gICAgJyAgcHJlY2lzaW9uIGhpZ2hwIGZsb2F0OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIHVuaWZvcm0gZmxvYXQgdV9EYXNoTGVuZ3RoOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICB1bmlmb3JtIGZsb2F0IHVfRGFzaFBhdHRlcm47ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgdW5pZm9ybSBmbG9hdCB1X3lPZmZzZXQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIHVuaWZvcm0gdmVjNCB1X0NvbG9yOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICBjb25zdCBmbG9hdCBtYXNrTGVuZ3RoID0gMTYuMDsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIHZvaWQgbWFpbiggKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgZmxvYXQgZGFzaFBvc2l0aW9uID0gZnJhY3QoKGdsX0ZyYWdDb29yZC55IC0gdV95T2Zmc2V0KSAvIHVfRGFzaExlbmd0aCk7ICAnLFxyXG4gICAgJyAgICAgIGZsb2F0IG1hc2tJbmRleCA9IGZsb29yKGRhc2hQb3NpdGlvbiAqIG1hc2tMZW5ndGgpOyAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICBmbG9hdCBtYXNrVGVzdCA9IGZsb29yKHVfRGFzaFBhdHRlcm4gLyBwb3coMi4wLCBtYXNrSW5kZXgpKTsgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgICAgIGlmKG1vZChtYXNrVGVzdCwgMi4wKSA8IDEuMCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgICAgICAgICAgZGlzY2FyZDsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgZWxzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLFxyXG4gICAgJyAgICAgIGdsX0ZyYWdDb2xvciA9IHVfQ29sb3I7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyxcclxuICAgICcgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnXHJcbik7XHJcblxyXG5leHBvcnQgbGV0IHZhcnlpbmdDb2xvcl9GUkFHU0hBREVSID0gY29uY2F0TGluZXMoXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICBwcmVjaXNpb24gbG93cCBmbG9hdDsgICAgICAgICcsXHJcbiAgICAnICB2YXJ5aW5nIHZlYzQgdl9Db2xvcjsgICAgICAgICcsXHJcbiAgICAnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcsXHJcbiAgICAnICB2b2lkIG1haW4oICkgeyAgICAgICAgICAg