webglimpse
Version:
Webglimpse is a data visualization library for the web.
338 lines • 57.5 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 { 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