webglimpse
Version:
Webglimpse is a data visualization library for the web.
240 lines • 43.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 { Pane, yFrac, isLeftMouseDown } from './core';
import { gray } from './color';
import { newBackgroundPainter, xyFrac_VERTSHADER, solid_FRAGSHADER, putQuadXys } from './misc';
import { Program, UniformColor, Attribute } from './shader';
import { newDynamicBuffer } from './buffer';
import { GL, hasval } from './util/util';
export function newVerticalScrollLayout() {
const layout = {
updatePrefSize: function (parentPrefSize, children) {
if (children.length === 1) {
const childPrefSize = children[0].prefSize;
// XXX: Need some way to override the child's pref-height
if (!hasval(childPrefSize.h)) {
throw new Error('Vertical-scroll layout requires child to have a defined pref-height, but its pref-height is ' + childPrefSize.h);
}
parentPrefSize.w = childPrefSize.w;
parentPrefSize.h = childPrefSize.h;
}
else if (children.length > 1) {
throw new Error('Vertical-scroll layout only works with 1 child, but pane has ' + this.children.length + ' children');
}
},
jOffset: 0,
hContent: 0,
hVisible: 0,
updateChildViewports: function (children, parentViewport) {
if (children.length === 1) {
const child = children[0];
let j;
const h = child.prefSize.h;
if (h <= parentViewport.h) {
j = parentViewport.jEnd - h;
}
else {
j = Math.min(parentViewport.j, parentViewport.jEnd - h + Math.max(0, Math.round(layout.jOffset)));
}
child.viewport.setRect(parentViewport.i, j, parentViewport.w, h);
layout.jOffset = (j + h) - parentViewport.jEnd;
layout.hContent = h;
layout.hVisible = parentViewport.h;
}
else if (children.length > 1) {
throw new Error('Vertical-scroll layout only works with 1 child, but pane has ' + this.children.length + ' children');
}
}
};
return layout;
}
export function newVerticalScrollbar(scrollLayout, drawable, options) {
const bgColor = (hasval(options) && hasval(options.bgColor) ? options.bgColor : gray(0.9));
const scrollbar = new Pane(null);
scrollbar.addPainter(newBackgroundPainter(bgColor));
scrollbar.addPainter(newVerticalScrollbarPainter(scrollLayout, options));
attachVerticalScrollMouseListeners(scrollbar, scrollLayout, drawable);
return scrollbar;
}
export function newVerticalScrollbarPainter(scrollLayout, options) {
const fgColor = (hasval(options) && hasval(options.fgColor) ? options.fgColor : gray(0.56));
const borderColor = (hasval(options) && hasval(options.borderColor) ? options.borderColor : gray(0.42));
const borderThickness = (hasval(options) && hasval(options.borderThickness) ? options.borderThickness : 1);
const borderTop = (hasval(options) && hasval(options.borderTop) ? options.borderTop : true);
const borderLeft = (hasval(options) && hasval(options.borderLeft) ? options.borderLeft : false);
const borderRight = (hasval(options) && hasval(options.borderRight) ? options.borderRight : false);
const borderBottom = (hasval(options) && hasval(options.borderBottom) ? options.borderBottom : true);
const program = new Program(xyFrac_VERTSHADER, solid_FRAGSHADER);
const u_Color = new UniformColor(program, 'u_Color');
const a_XyFrac = new Attribute(program, 'a_XyFrac');
const numFillVertices = 6;
const numBorderVertices = (borderTop ? 6 : 0) + (borderLeft ? 6 : 0) + (borderRight ? 6 : 0) + (borderBottom ? 6 : 0);
const xyFrac = new Float32Array(2 * Math.max(numFillVertices, numBorderVertices));
const xyFracBuffer = newDynamicBuffer();
return function (gl, viewport) {
const hFrac = scrollLayout.hVisible / scrollLayout.hContent;
if (hFrac < 1) {
const yTop = Math.round(((scrollLayout.hContent - (scrollLayout.jOffset)) / scrollLayout.hContent) * viewport.h + 1e-4);
const yBottom = Math.round(((scrollLayout.hContent - (scrollLayout.jOffset + scrollLayout.hVisible)) / scrollLayout.hContent) * viewport.h + 1e-4);
const yFracTop = yTop / viewport.h;
const yFracBottom = yBottom / viewport.h;
const wBorderFrac = borderThickness / viewport.w;
const hBorderFrac = borderThickness / viewport.h;
gl.disable(GL.BLEND);
program.use(gl);
// Fill
//
putQuadXys(xyFrac, 0, 0 + (borderLeft ? wBorderFrac : 0), 1 - (borderRight ? wBorderFrac : 0), yFracTop - (borderTop ? hBorderFrac : 0), yFracBottom + (borderBottom ? hBorderFrac : 0));
xyFracBuffer.setData(xyFrac.subarray(0, 2 * numFillVertices));
a_XyFrac.setDataAndEnable(gl, xyFracBuffer, 2, GL.FLOAT);
u_Color.setData(gl, fgColor);
gl.drawArrays(GL.TRIANGLES, 0, numFillVertices);
// Border
//
let index = 0;
if (borderTop) {
index = putQuadXys(xyFrac, index, 0, 1 - (borderRight ? wBorderFrac : 0), yFracTop, yFracTop - hBorderFrac);
}
if (borderBottom) {
index = putQuadXys(xyFrac, index, 0 + (borderLeft ? wBorderFrac : 0), 1, yFracBottom + hBorderFrac, yFracBottom);
}
if (borderRight) {
index = putQuadXys(xyFrac, index, 1 - wBorderFrac, 1, yFracTop, yFracBottom + (borderBottom ? hBorderFrac : 0));
}
if (borderLeft) {
index = putQuadXys(xyFrac, index, 0, 0 + wBorderFrac, yFracTop - (borderTop ? hBorderFrac : 0), yFracBottom);
}
xyFracBuffer.setData(xyFrac.subarray(0, 2 * numBorderVertices));
a_XyFrac.setDataAndEnable(gl, xyFracBuffer, 2, GL.FLOAT);
u_Color.setData(gl, borderColor);
gl.drawArrays(GL.TRIANGLES, 0, numBorderVertices);
a_XyFrac.disable(gl);
program.endUse(gl);
}
};
}
// mouse listener for scrolling while panning on the timeline itself
export function attachTimelineVerticalScrollMouseListeners(pane, scrollLayout, drawable) {
// Used when dragging inside pane
let grab = null;
let jOffset = null;
pane.mouseDown.on(function (ev) {
if (isLeftMouseDown(ev.mouseEvent)) {
grab = ev.j;
jOffset = scrollLayout.jOffset;
}
});
pane.mouseMove.on(function (ev) {
if (hasval(grab)) {
scrollLayout.jOffset = jOffset - (grab - ev.j);
drawable.redraw();
}
});
pane.mouseUp.on(function (ev) {
grab = null;
});
}
// mouse listener for scrolling while interacting with the scrollbar
export function attachVerticalScrollMouseListeners(scrollbar, scrollLayout, drawable) {
// Used when dragging the handle
let grab = null;
// Used when scrollbar is pressed-and-held outside the handle
let pageScrollTimer = null;
let recentPointerFrac = null;
scrollbar.mouseDown.on(function (ev) {
if (isLeftMouseDown(ev.mouseEvent) && !hasval(grab)) {
const topFrac = (scrollLayout.hContent - scrollLayout.jOffset) / scrollLayout.hContent;
const fracExtent = scrollLayout.hVisible / scrollLayout.hContent;
const pointerFrac = yFrac(ev);
if (topFrac - fracExtent <= pointerFrac && pointerFrac <= topFrac) {
grab = (topFrac - pointerFrac) / fracExtent;
}
else {
// If the mouse is pressed on the scrollbar but outside the handle:
//
// 1. Immediately scroll one page toward the mouse
// 2. Wait 500ms
// 3. If the mouse-button is still down, scroll one page toward the mouse
// 4. Wait 50ms
// 5. Go to Step 3
//
// (A "page" is 7/8 of the viewport extent.)
//
let direction = 0;
if (pointerFrac < topFrac - fracExtent) {
direction = +1;
}
else if (pointerFrac > topFrac) {
direction = -1;
}
scrollLayout.jOffset += direction * Math.max(1, 0.875 * scrollLayout.hVisible);
drawable.redraw();
recentPointerFrac = pointerFrac;
const pageScroll = function () {
const pageTopFrac = (scrollLayout.hContent - scrollLayout.jOffset) / scrollLayout.hContent;
const pageFracExtent = scrollLayout.hVisible / scrollLayout.hContent;
const pagePointerFrac = recentPointerFrac;
let pageDirection = 0;
if (pagePointerFrac < pageTopFrac - pageFracExtent) {
pageDirection = +1;
}
else if (pagePointerFrac > pageTopFrac) {
pageDirection = -1;
}
scrollLayout.jOffset += pageDirection * Math.max(1, 0.875 * scrollLayout.hVisible);
drawable.redraw();
pageScrollTimer = setTimeout(pageScroll, 50);
};
pageScrollTimer = setTimeout(pageScroll, 500);
}
}
});
scrollbar.mouseMove.on(function (ev) {
const pointerFrac = yFrac(ev);
if (hasval(grab)) {
const fracExtent = scrollLayout.hVisible / scrollLayout.hContent;
const topFrac = pointerFrac + grab * fracExtent;
scrollLayout.jOffset = scrollLayout.hContent - topFrac * scrollLayout.hContent;
drawable.redraw();
}
if (hasval(pageScrollTimer)) {
recentPointerFrac = pointerFrac;
}
});
scrollbar.mouseUp.on(function (ev) {
grab = null;
if (hasval(pageScrollTimer)) {
clearTimeout(pageScrollTimer);
pageScrollTimer = null;
recentPointerFrac = null;
}
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dlYmdsaW1wc2Uvc2Nyb2xsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBQ0gsT0FBTyxFQUFnQyxJQUFJLEVBQXlCLEtBQUssRUFBRSxlQUFlLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFFMUcsT0FBTyxFQUFRLElBQUksRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUNwQyxPQUFPLEVBQUMsb0JBQW9CLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFDLE1BQU0sUUFBUSxDQUFDO0FBQzdGLE9BQU8sRUFBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUMxRCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDMUMsT0FBTyxFQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFTdkMsTUFBTSxVQUFVLHVCQUF1QjtJQUNuQyxNQUFNLE1BQU0sR0FBeUI7UUFFakMsY0FBYyxFQUFFLFVBQVUsY0FBb0IsRUFBRSxRQUF1QjtZQUNuRSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO2dCQUN2QixNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO2dCQUUzQyx5REFBeUQ7Z0JBQ3pELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLDhGQUE4RixHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDckk7Z0JBRUQsY0FBYyxDQUFDLENBQUMsR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDO2dCQUNuQyxjQUFjLENBQUMsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxDQUFDLENB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QUMsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sV0FBVyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hHLE1BQU0sZUFBZSxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNHLE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVGLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hHLE1BQU0sV0FBVyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25HLE1BQU0sWUFBWSxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXJHLE1BQU0sT0FBTyxHQUFHLElBQUks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QUVQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQsIE1ldHJvbiwgSW5jLlxyXG4gKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG4gKlxyXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxyXG4gKiBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XHJcbiAqXHJcbiAqIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xyXG4gKiAgICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cclxuICpcclxuICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxyXG4gKiAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXHJcbiAqICAgIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG4gKlxyXG4gKiAzLiBOZWl0aGVyIHRoZSBuYW1lIG9mIHRoZSBjb3B5cmlnaHQgaG9sZGVyIG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9yc1xyXG4gKiAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dFxyXG4gKiAgICBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uXHJcbiAqXHJcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiIEFORFxyXG4gKiBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxyXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXHJcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SXHJcbiAqIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xyXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7XHJcbiAqIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTlxyXG4gKiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxyXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJU1xyXG4gKiBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuICovXHJcbmltcG9ydCB7TGF5b3V0LCBMYXlvdXRFbnRyeSwgRHJhd2FibGUsIFBhbmUsIFBhaW50ZXIsIFBvaW50ZXJFdmVudCwgeUZyYWMsIGlzTGVmdE1vdXNlRG93bn0gZnJvbSAnLi9jb3JlJztcclxuaW1wb3J0IHtTaXplLCBCb3VuZHNVbm1vZGlmaWFibGV9IGZyb20gJy4vYm91bmRzJztcclxuaW1wb3J0IHtDb2xvciwgZ3JheX0gZnJvbSAnLi9jb2xvcic7XHJcbmltcG9ydCB7bmV3QmFja2dyb3VuZFBhaW50ZXIsIHh5RnJhY19WRVJUU0hBREVSLCBzb2xpZF9GUkFHU0hBREVSLCBwdXRRdWFkWHlzfSBmcm9tICcuL21pc2MnO1xyXG5pbXBvcnQge1Byb2dyYW0sIFVuaWZvcm1Db2xvciwgQXR0cmlidXRlfSBmcm9tICcuL3NoYWRlcic7XHJcbmltcG9ydCB7bmV3RHluYW1pY0J1ZmZlcn0gZnJvbSAnLi9idWZmZXInO1xyXG5pbXBvcnQge0dMLCBoYXN2YWx9IGZyb20gJy4vdXRpbC91dGlsJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgVmVydGljYWxTY3JvbGxMYXlvdXQgZXh0ZW5kcyBMYXlvdXQge1xyXG4gICAgak9mZnNldDogbnVtYmVyO1xyXG4gICAgaENvbnRlbnQ6IG51bWJlcjtcclxuICAgIGhWaXNpYmxlOiBudW1iZXI7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbmV3VmVydGljYWxTY3JvbGxMYXlvdXQoKTogVmVydGljYWxTY3JvbGxMYXlvdXQge1xyXG4gICAgY29uc3QgbGF5b3V0ID0gPFZlcnRpY2FsU2Nyb2xsTGF5b3V0PntcclxuXHJcbiAgICAgICAgdXBkYXRlUHJlZlNpemU6IGZ1bmN0aW9uIChwYXJlbnRQcmVmU2l6ZTogU2l6ZSwgY2hpbGRyZW46IExheW91dEVudHJ5W10pIHtcclxuICAgICAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgY2hpbGRQcmVmU2l6ZSA9IGNoaWxkcmVuWzBdLnByZWZTaXplO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFhYWDogTmVlZCBzb21lIHdheSB0byBvdmVycmlkZSB0aGUgY2hpbGQncyBwcmVmLWhlaWdodFxyXG4gICAgICAgICAgICAgICAgaWYgKCFoYXN2YWwoY2hpbGRQcmVmU2l6ZS5oKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVmVydGljYWwtc2Nyb2xsIGxheW91dCByZXF1aXJlcyBjaGlsZCB0byBoYXZlIGEgZGVmaW5lZCBwcmVmLWhlaWdodCwgYnV0IGl0cyBwcmVmLWhlaWdodCBpcyAnICsgY2hpbGRQcmVmU2l6ZS5oKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBwYXJlbnRQcmVmU2l6ZS53ID0gY2hpbGRQcmVmU2l6ZS53O1xyXG4gICAgICAgICAgICAgICAgcGFyZW50UHJlZlNpemUuaCA9IGNoaWxkUHJlZlNpemUuaDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChjaGlsZHJlbi5sZW5ndGggPiAxKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ZlcnRpY2FsLXNjcm9sbCBsYXlvdXQgb25seSB3b3JrcyB3aXRoIDEgY2hpbGQsIGJ1dCBwYW5lIGhhcyAnICsgdGhpcy5jaGlsZHJlbi5sZW5ndGggKyAnIGNoaWxkcmVuJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBqT2Zmc2V0OiAwLFxyXG4gICAgICAgIGhDb250ZW50OiAwLFxyXG4gICAgICAgIGhWaXNpYmxlOiAwLFxyXG5cclxuICAgICAgICB1cGRhdGVDaGlsZFZpZXdwb3J0czogZnVuY3Rpb24gKGNoaWxkcmVuOiBMYXlvdXRFbnRyeVtdLCBwYXJlbnRWaWV3cG9ydDogQm91bmRzVW5tb2RpZmlhYmxlKSB7XHJcbiAgICAgICAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5bMF07XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IGo7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBoID0gY2hpbGQucHJlZlNpemUuaDtcclxuICAgICAgICAgICAgICAgIGlmIChoIDw9IHBhcmVudFZpZXdwb3J0LmgpIHtcclxuICAgICAgICAgICAgICAgICAgICBqID0gcGFyZW50Vmlld3BvcnQuakVuZCAtIGg7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBqID0gTWF0aC5taW4ocGFyZW50Vmlld3BvcnQuaiwgcGFyZW50Vmlld3BvcnQuakVuZCAtIGggKyBNYXRoLm1heCgwLCBNYXRoLnJvdW5kKGxheW91dC5qT2Zmc2V0KSkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNoaWxkLnZpZXdwb3J0LnNldFJlY3QocGFyZW50Vmlld3BvcnQuaSwgaiwgcGFyZW50Vmlld3BvcnQudywgaCk7XHJcblxyXG4gICAgICAgICAgICAgICAgbGF5b3V0LmpPZmZzZXQgPSAoaiArIGgpIC0gcGFyZW50Vmlld3BvcnQuakVuZDtcclxuICAgICAgICAgICAgICAgIGxheW91dC5oQ29udGVudCA9IGg7XHJcbiAgICAgICAgICAgICAgICBsYXlvdXQuaFZpc2libGUgPSBwYXJlbnRWaWV3cG9ydC5oO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVmVydGljYWwtc2Nyb2xsIGxheW91dCBvbmx5IHdvcmtzIHdpdGggMSBjaGlsZCwgYnV0IHBhbmUgaGFzICcgKyB0aGlzLmNoaWxkcmVuLmxlbmd0aCArICcgY2hpbGRyZW4nKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIGxheW91dDtcclxufVxyXG5cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgU2Nyb2xsYmFyT3B0aW9ucyB7XHJcbiAgICBmZ0NvbG9yPzogQ29sb3I7XHJcbiAgICBiZ0NvbG9yPzogQ29sb3I7XHJcbiAgICBib3JkZXJDb2xvcj86IENvbG9yO1xyXG4gICAgYm9yZGVyVGhpY2tuZXNzPzogbnVtYmVyO1xyXG4gICAgYm9yZGVyVG9wPzogYm9vbGVhbjtcclxuICAgIGJvcmRlckxlZnQ/OiBib29sZWFuO1xyXG4gICAgYm9yZGVyUmlnaHQ/OiBib29sZWFuO1xyXG4gICAgYm9yZGVyQm90dG9tPzogYm9vbGVhbjtcclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdWZXJ0aWNhbFNjcm9sbGJhcihzY3JvbGxMYXlvdXQ6IFZlcnRpY2FsU2Nyb2xsTGF5b3V0LCBkcmF3YWJsZTogRHJhd2FibGUsIG9wdGlvbnM/OiBTY3JvbGxiYXJPcHRpb25zKTogUGFuZSB7XHJcbiAgICBjb25zdCBiZ0NvbG9yID0gKGhhc3ZhbChvcHRpb25zKSAmJiBoYXN2YWwob3B0aW9ucy5iZ0NvbG9yKSA/IG9wdGlvbnMuYmdDb2xvciA6IGdyYXkoMC45KSk7XHJcblxyXG4gICAgY29uc3Qgc2Nyb2xsYmFyID0gbmV3IFBhbmUobnVsbCk7XHJcbiAgICBzY3JvbGxiYXIuYWRkUGFpbnRlcihuZXdCYWNrZ3JvdW5kUGFpbnRlcihiZ0NvbG9yKSk7XHJcbiAgICBzY3JvbGxiYXIuYWRkUGFpbnRlcihuZXdWZXJ0aWNhbFNjcm9sbGJhclBhaW50ZXIoc2Nyb2xsTGF5b3V0LCBvcHRpb25zKSk7XHJcblxyXG4gICAgYXR0YWNoVmVydGljYWxTY3JvbGxNb3VzZUxpc3RlbmVycyhzY3JvbGxiYXIsIHNjcm9sbExheW91dCwgZHJhd2FibGUpO1xyXG5cclxuICAgIHJldHVybiBzY3JvbGxiYXI7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbmV3VmVydGljYWxTY3JvbGxiYXJQYWludGVyKHNjcm9sbExheW91dDogVmVydGljYWxTY3JvbGxMYXlvdXQsIG9wdGlvbnM/OiBTY3JvbGxiYXJPcHRpb25zKTogUGFpbnRlciB7XHJcbiAgICBjb25zdCBmZ0NvbG9yID0gKGhhc3ZhbChvcHRpb25zKSAmJiBoYXN2YWwob3B0aW9ucy5mZ0NvbG9yKSA/IG9wdGlvbnMuZmdDb2xvciA6IGdyYXkoMC41NikpO1xyXG4gICAgY29uc3QgYm9yZGVyQ29sb3IgPSAoaGFzdmFsKG9wdGlvbnMpICYmIGhhc3ZhbChvcHRpb25zLmJvcmRlckNvbG9yKSA/IG9wdGlvbnMuYm9yZGVyQ29sb3IgOiBncmF5KDAuNDIpKTtcclxuICAgIGNvbnN0IGJvcmRlclRoaWNrbmVzcyA9IChoYXN2YWwob3B0aW9ucykgJiYgaGFzdmFsKG9wdGlvbnMuYm9yZGVyVGhpY2tuZXNzKSA/IG9wdGlvbnMuYm9yZGVyVGhpY2tuZXNzIDogMSk7XHJcbiAgICBjb25zdCBib3JkZXJUb3AgPSAoaGFzdmFsKG9wdGlvbnMpICYmIGhhc3ZhbChvcHRpb25zLmJvcmRlclRvcCkgPyBvcHRpb25zLmJvcmRlclRvcCA6IHRydWUpO1xyXG4gICAgY29uc3QgYm9yZGVyTGVmdCA9IChoYXN2YWwob3B0aW9ucykgJiYgaGFzdmFsKG9wdGlvbnMuYm9yZGVyTGVmdCkgPyBvcHRpb25zLmJvcmRlckxlZnQgOiBmYWxzZSk7XHJcbiAgICBjb25zdCBib3JkZXJSaWdodCA9IChoYXN2YWwob3B0aW9ucykgJiYgaGFzdmFsKG9wdGlvbnMuYm9yZGVyUmlnaHQpID8gb3B0aW9ucy5ib3JkZXJSaWdodCA6IGZhbHNlKTtcclxuICAgIGNvbnN0IGJvcmRlckJvdHRvbSA9IChoYXN2YWwob3B0aW9ucykgJiYgaGFzdmFsKG9wdGlvbnMuYm9yZGVyQm90dG9tKSA/IG9wdGlvbnMuYm9yZGVyQm90dG9tIDogdHJ1ZSk7XHJcblxyXG4gICAgY29uc3QgcHJvZ3JhbSA9IG5ldyBQcm9ncmFtKHh5RnJhY19WRVJUU0hBREVSLCBzb2xpZF9GUkFHU0hBREVSKTtcclxuICAgIGNvbnN0IHVfQ29sb3IgPSBuZXcgVW5pZm9ybUNvbG9yKHByb2dyYW0sICd1X0NvbG9yJyk7XHJcbiAgICBjb25zdCBhX1h5RnJhYyA9IG5ldyBBdHRyaWJ1dGUocHJvZ3JhbSwgJ2FfWHlGcmFjJyk7XHJcblxyXG4gICAgY29uc3QgbnVtRmlsbFZlcnRpY2VzID0gNjtcclxuICAgIGNvbnN0IG51bUJvcmRlclZlcnRpY2VzID0gKGJvcmRlclRvcCA/IDYgOiAwKSArIChib3JkZXJMZWZ0ID8gNiA6IDApICsgKGJvcmRlclJpZ2h0ID8gNiA6IDApICsgKGJvcmRlckJvdHRvbSA/IDYgOiAwKTtcclxuICAgIGNvbnN0IHh5RnJhYyA9IG5ldyBGbG9hdDMyQXJyYXkoMiAqIE1hdGgubWF4KG51bUZpbGxWZXJ0aWNlcywgbnVtQm9yZGVyVmVydGljZXMpKTtcclxuICAgIGNvbnN0IHh5RnJhY0J1ZmZlciA9IG5ld0R5bmFtaWNCdWZmZXIoKTtcclxuXHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIHZpZXdwb3J0OiBCb3VuZHNVbm1vZGlmaWFibGUpIHtcclxuICAgICAgICBjb25zdCBoRnJhYyA9IHNjcm9sbExheW91dC5oVmlzaWJsZSAvIHNjcm9sbExheW91dC5oQ29udGVudDtcclxuICAgICAgICBpZiAoaEZyYWMgPCAxKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHlUb3AgPSBNYXRoLnJvdW5kKCgoc2Nyb2xsTGF5b3V0LmhDb250ZW50IC0gKHNjcm9sbExheW91dC5qT2Zmc2V0KSkgLyBzY3JvbGxMYXlvdXQuaENvbnRlbnQpICogdmlld3BvcnQuaCArIDFlLTQpO1xyXG4gICAgICAgICAgICBjb25zdCB5Qm90dG9tID0gTWF0aC5yb3VuZCgoKHNjcm9sbExheW91dC5oQ29udGVudCAtIChzY3JvbGxMYXlvdXQuak9mZnNldCArIHNjcm9sbExheW91dC5oVmlzaWJsZSkpIC8gc2Nyb2xsTGF5b3V0LmhDb250ZW50KSAqIHZpZXdwb3J0LmggKyAxZS00KTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHlGcmFjVG9wID0geVRvcCAvIHZpZXdwb3J0Lmg7XHJcbiAgICAgICAgICAgIGNvbnN0IHlGcmFjQm90dG9tID0geUJvdHRvbSAvIHZpZXdwb3J0Lmg7XHJcblxyXG4gICAgICAgICAgICBjb25zdCB3Qm9yZGVyRnJhYyA9IGJvcmRlclRoaWNrbmVzcyAvIHZpZXdwb3J0Lnc7XHJcbiAgICAgICAgICAgIGNvbnN0IGhCb3JkZXJGcmFjID0gYm9yZGVyVGhpY2tuZXNzIC8gdmlld3BvcnQuaDtcclxuXHJcbiAgICAgICAgICAgIGdsLmRpc2FibGUoR0wuQkxFTkQpO1xyXG5cclxuICAgICAgICAgICAgcHJvZ3JhbS51c2UoZ2wpO1xyXG5cclxuXHJcbiAgICAgICAgICAgIC8vIEZpbGxcclxuICAgICAgICAgICAgLy9cclxuXHJcbiAgICAgICAgICAgIHB1dFF1YWRYeXMoeHlGcmFjLCAwLCAwICsgKGJvcmRlckxlZnQgPyB3Qm9yZGVyRnJhYyA6IDApLCAxIC0gKGJvcmRlclJpZ2h0ID8gd0JvcmRlckZyYWMgOiAwKSwgeUZyYWNUb3AgLSAoYm9yZGVyVG9wID8gaEJvcmRlckZyYWMgOiAwKSwgeUZyYWNCb3R0b20gKyAoYm9yZGVyQm90dG9tID8gaEJvcmRlckZyYWMgOiAwKSk7XHJcbiAgICAgICAgICAgIHh5RnJhY0J1ZmZlci5zZXREYXRhKHh5RnJhYy5zdWJhcnJheSgwLCAyICogbnVtRmlsbFZlcnRpY2VzKSk7XHJcbiAgICAgICAgICAgIGFfWHlGcmFjLnNldERhdGFBbmRFbmFibGUoZ2wsIHh5RnJhY0J1ZmZlciwgMiwgR0wuRkxPQVQpO1xyXG4gICAgICAgICAgICB1X0NvbG9yLnNldERhdGEoZ2wsIGZnQ29sb3IpO1xyXG4gICAgICAgICAgICBnbC5kcmF3QXJyYXlzKEdMLlRSSUFOR0xFUywgMCwgbnVtRmlsbFZlcnRpY2VzKTtcclxuXHJcblxyXG4gICAgICAgICAgICAvLyBCb3JkZXJcclxuICAgICAgICAgICAgLy9cclxuXHJcbiAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XHJcbiAgICAgICAgICAgIGlmIChib3JkZXJUb3ApIHtcclxuICAgICAgICAgICAgICAgIGluZGV4ID0gcHV0UXVhZFh5cyh4eUZyYWMsIGluZGV4LCAwLCAxIC0gKGJvcmRlclJpZ2h0ID8gd0JvcmRlckZyYWMgOiAwKSwgeUZyYWNUb3AsIHlGcmFjVG9wIC0gaEJvcmRlckZyYWMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChib3JkZXJCb3R0b20pIHtcclxuICAgICAgICAgICAgICAgIGluZGV4ID0gcHV0UXVhZFh5cyh4eUZyYWMsIGluZGV4LCAwICsgKGJvcmRlckxlZnQgPyB3Qm9yZGVyRnJhYyA6IDApLCAxLCB5RnJhY0JvdHRvbSArIGhCb3JkZXJGcmFjLCB5RnJhY0JvdHRvbSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGJvcmRlclJpZ2h0KSB7XHJcbiAgICAgICAgICAgICAgICBpbmRleCA9IHB1dFF1YWRYeXMoeHlGcmFjLCBpbmRleCwgMSAtIHdCb3JkZXJGcmFjLCAxLCB5RnJhY1RvcCwgeUZyYWNCb3R0b20gKyAoYm9yZGVyQm90dG9tID8gaEJvcmRlckZyYWMgOiAwKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGJvcmRlckxlZnQpIHtcclxuICAgICAgICAgICAgICAgIGluZGV4ID0gcHV0UXVhZFh5cyh4eUZyYWMsIGluZGV4LCAwLCAwICsgd0JvcmRlckZyYWMsIHlGcmFjVG9wIC0gKGJvcmRlclRvcCA/IGhCb3JkZXJGcmFjIDogMCksIHlGcmFjQm90dG9tKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgeHlGcmFjQnVmZmVyLnNldERhdGEoeHlGcmFjLnN1YmFycmF5KDAsIDIgKiBudW1Cb3JkZXJWZXJ0aWNlcykpO1xyXG4gICAgICAgICAgICBhX1h5RnJhYy5zZXREYXRhQW5kRW5hYmxlKGdsLCB4eUZyYWNCdWZmZXIsIDIsIEdMLkZMT0FUKTtcclxuICAgICAgICAgICAgdV9Db2xvci5zZXREYXRhKGdsLCBib3JkZXJDb2xvcik7XHJcbiAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoR0wuVFJJQU5HTEVTLCAwLCBudW1Cb3JkZXJWZXJ0aWNlcyk7XHJcblxyXG5cclxuICAgICAgICAgICAgYV9YeUZyYWMuZGlzYWJsZShnbCk7XHJcbiAgICAgICAgICAgIHByb2dyYW0uZW5kVXNlKGdsKTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG4vLyBtb3VzZSBsaXN0ZW5lciBmb3Igc2Nyb2xsaW5nIHdoaWxlIHBhbm5pbmcgb24gdGhlIHRpbWVsaW5lIGl0c2VsZlxyXG5leHBvcnQgZnVuY3Rpb24gYXR0YWNoVGltZWxpbmVWZXJ0aWNhbFNjcm9sbE1vdXNlTGlzdGVuZXJzKHBhbmU6IFBhbmUsIHNjcm9sbExheW91dDogVmVydGljYWxTY3JvbGxMYXlvdXQsIGRyYXdhYmxlOiBEcmF3YWJsZSkge1xyXG5cclxuICAgIC8vIFVzZWQgd2hlbiBkcmFnZ2luZyBpbnNpZGUgcGFuZVxyXG4gICAgbGV0IGdyYWI6IG51bWJlciA9IG51bGw7XHJcbiAgICBsZXQgak9mZnNldDogbnVtYmVyID0gbnVsbDtcclxuXHJcbiAgICBwYW5lLm1vdXNlRG93bi5vbihmdW5jdGlvbiAoZXY6IFBvaW50ZXJFdmVudCkge1xyXG4gICAgICAgIGlmIChpc0xlZnRNb3VzZURvd24oZXYubW91c2VFdmVudCkpIHtcclxuICAgICAgICAgICAgZ3JhYiA9IGV2Lmo7XHJcbiAgICAgICAgICAgIGpPZmZzZXQgPSBzY3JvbGxMYXlvdXQuak9mZnNldDtcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBwYW5lLm1vdXNlTW92ZS5vbihmdW5jdGlvbiAoZXY6IFBvaW50ZXJFdmVudCkge1xyXG4gICAgICAgIGlmIChoYXN2YWwoZ3JhYikpIHtcclxuICAgICAgICAgICAgc2Nyb2xsTGF5b3V0LmpPZmZzZXQgPSBqT2Zmc2V0IC0gKGdyYWIgLSBldi5qKTtcclxuICAgICAgICAgICAgZHJhd2FibGUucmVkcmF3KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgcGFuZS5tb3VzZVVwLm9uKGZ1bmN0aW9uIChldjogUG9pbnRlckV2ZW50KSB7XHJcbiAgICAgICAgZ3JhYiA9IG51bGw7XHJcbiAgICB9KTtcclxufVxyXG5cclxuLy8gbW91c2UgbGlzdGVuZXIgZm9yIHNjcm9sbGluZyB3aGlsZSBpbnRlcmFjdGluZyB3aXRoIHRoZSBzY3JvbGxiYXJcclxuZXhwb3J0IGZ1bmN0aW9uIGF0dGFjaFZlcnRpY2FsU2Nyb2xsTW91c2VMaXN0ZW5lcnMoc2Nyb2xsYmFyOiBQYW5lLCBzY3JvbGxMYXlvdXQ6IFZlcnRpY2FsU2Nyb2xsTGF5b3V0LCBkcmF3YWJsZTogRHJhd2FibGUpIHtcclxuXHJcbiAgICAvLyBVc2VkIHdoZW4gZHJhZ2dpbmcgdGhlIGhhbmRsZVxyXG4gICAgbGV0IGdyYWI6IG51bWJlciA9IG51bGw7XHJcblxyXG4gICAgLy8gVXNlZCB3aGVuIHNjcm9sbGJhciBpcyBwcmVzc2VkLWFuZC1oZWxkIG91dHNpZGUgdGhlIGhhbmRsZVxyXG4gICAgbGV0IHBhZ2VTY3JvbGxUaW1lcjogYW55ID0gbnVsbDtcclxuICAgIGxldCByZWNlbnRQb2ludGVyRnJhYzogbnVtYmVyID0gbnVsbDtcclxuXHJcbiAgICBzY3JvbGxiYXIubW91c2VEb3duLm9uKGZ1bmN0aW9uIChldjogUG9pbnRlckV2ZW50KSB7XHJcbiAgICAgICAgaWYgKGlzTGVmdE1vdXNlRG93bihldi5tb3VzZUV2ZW50KSAmJiAhaGFzdmFsKGdyYWIpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHRvcEZyYWMgPSAoc2Nyb2xsTGF5b3V0LmhDb250ZW50IC0gc2Nyb2xsTGF5b3V0LmpPZmZzZXQpIC8gc2Nyb2xsTGF5b3V0LmhDb250ZW50O1xyXG4gICAgICAgICAgICBjb25zdCBmcmFjRXh0ZW50ID0gc2Nyb2xsTGF5b3V0LmhWaXNpYmxlIC8gc2Nyb2xsTGF5b3V0LmhDb250ZW50O1xyXG4gICAgICAgICAgICBjb25zdCBwb2ludGVyRnJhYyA9IHlGcmFjKGV2KTtcclxuICAgICAgICAgICAgaWYgKHRvcEZyYWMgLSBmcmFjRXh0ZW50IDw9IHBvaW50ZXJGcmFjICYmIHBvaW50ZXJGcmFjIDw9IHRvcEZyYWMpIHtcclxuICAgICAgICAgICAgICAgIGdyYWIgPSAodG9wRnJhYyAtIHBvaW50ZXJGcmFjKSAvIGZyYWNFeHRlbnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbW91c2UgaXMgcHJlc3NlZCBvbiB0aGUgc2Nyb2xsYmFyIGJ1dCBvdXRzaWRlIHRoZSBoYW5kbGU6XHJcbiAgICAgICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAgICAgLy8gIDEuIEltbWVkaWF0ZWx5IHNjcm9sbCBvbmUgcGFnZSB0b3dhcmQgdGhlIG1vdXNlXHJcbiAgICAgICAgICAgICAgICAvLyAgMi4gV2FpdCA1MDBtc1xyXG4gICAgICAgICAgICAgICAgLy8gIDMuIElmIHRoZSBtb3VzZS1idXR0b24gaXMgc3RpbGwgZG93biwgc2Nyb2xsIG9uZSBwYWdlIHRvd2FyZCB0aGUgbW91c2VcclxuICAgICAgICAgICAgICAgIC8vICA0LiBXYWl0IDUwbXNcclxuICAgICAgICAgICAgICAgIC8vICA1LiBHbyB0byBTdGVwIDNcclxuICAgICAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgICAgICAvLyAoQSBcInBhZ2VcIiBpcyA3Lzggb2YgdGhlIHZpZXdwb3J0IGV4dGVudC4pXHJcbiAgICAgICAgICAgICAgICAvL1xyXG5cclxuICAgICAgICAgICAgICAgIGxldCBkaXJlY3Rpb24gPSAwO1xyXG4gICAgICAgICAgICAgICAgaWYgKHBvaW50ZXJGcmFjIDwgdG9wRnJhYyAtIGZyYWNFeHRlbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSArMTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHBvaW50ZXJGcmFjID4gdG9wRnJhYykge1xyXG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IC0xO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgc2Nyb2xsTGF5b3V0LmpPZmZzZXQgKz0gZGlyZWN0aW9uICogTWF0aC5tYXgoMSwgMC44NzUgKiBzY3JvbGxMYXlvdXQuaFZpc2libGUpO1xyXG4gICAgICAgICAgICAgICAgZHJhd2FibGUucmVkcmF3KCk7XHJcblxyXG4gICAgICAgICAgICAgICAgcmVjZW50UG9pbnRlckZyYWMgPSBwb2ludGVyRnJhYztcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2VTY3JvbGwgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFnZVRvcEZyYWMgPSAoc2Nyb2xsTGF5b3V0LmhDb250ZW50IC0gc2Nyb2xsTGF5b3V0LmpPZmZzZXQpIC8gc2Nyb2xsTGF5b3V0LmhDb250ZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2VGcmFjRXh0ZW50ID0gc2Nyb2xsTGF5b3V0LmhWaXNpYmxlIC8gc2Nyb2xsTGF5b3V0LmhDb250ZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2VQb2ludGVyRnJhYyA9IHJlY2VudFBvaW50ZXJGcmFjO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgcGFnZURpcmVjdGlvbiA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhZ2VQb2ludGVyRnJhYyA8IHBhZ2VUb3BGcmFjIC0gcGFnZUZyYWNFeHRlbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGFnZURpcmVjdGlvbiA9ICsxO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChwYWdlUG9pbnRlckZyYWMgPiBwYWdlVG9wRnJhYykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwYWdlRGlyZWN0aW9uID0gLTE7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbExheW91dC5qT2Zmc2V0ICs9IHBhZ2VEaXJlY3Rpb24gKiBNYXRoLm1heCgxLCAwLjg3NSAqIHNjcm9sbExheW91dC5oVmlzaWJsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgZHJhd2FibGUucmVkcmF3KCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHBhZ2VTY3JvbGxUaW1lciA9IHNldFRpbWVvdXQocGFnZVNjcm9sbCwgNTApO1xyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIHBhZ2VTY3JvbGxUaW1lciA9IHNldFRpbWVvdXQocGFnZVNjcm9sbCwgNTAwKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHNjcm9sbGJhci5tb3VzZU1vdmUub24oZnVuY3Rpb24gKGV2OiBQb2ludGVyRXZlbnQpIHtcclxuICAgICAgICBjb25zdCBwb2ludGVyRnJhYyA9IHlGcmFjKGV2KTtcclxuICAgICAgICBpZiAoaGFzdmFsKGdyYWIpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZyYWNFeHRlbnQgPSBzY3JvbGxMYXlvdXQuaFZpc2libGUgLyBzY3JvbGxMYXlvdXQuaENvbnRlbnQ7XHJcbiAgICAgICAgICAgIGNvbnN0IHRvcEZyYWMgPSBwb2ludGVyRnJhYyArIGdyYWIgKiBmcmFjRXh0ZW50O1xyXG4gICAgICAgICAgICBzY3JvbGxMYXlvdXQuak9mZnNldCA9IHNjcm9sbExheW91dC5oQ29udGVudCAtIHRvcEZyYWMgKiBzY3JvbGxMYXlvdXQuaENvbnRlbnQ7XHJcbiAgICAgICAgICAgIGRyYXdhYmxlLnJlZHJhdygpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoaGFzdmFsKHBhZ2VTY3JvbGxUaW1lcikpIHtcclxuICAgICAgICAgICAgcmVjZW50UG9pbnRlckZyYWMgPSBwb2ludGVyRnJhYztcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBzY3JvbGxiYXIubW91c2VVcC5vbihmdW5jdGlvbiAoZXY6IFBvaW50ZXJFdmVudCkge1xyXG4gICAgICAgIGdyYWIgPSBudWxsO1xyXG4gICAgICAgIGlmIChoYXN2YWwocGFnZVNjcm9sbFRpbWVyKSkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQocGFnZVNjcm9sbFRpbWVyKTtcclxuICAgICAgICAgICAgcGFnZVNjcm9sbFRpbWVyID0gbnVsbDtcclxuICAgICAgICAgICAgcmVjZW50UG9pbnRlckZyYWMgPSBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG5cclxufVxyXG5cclxuXHJcbiJdfQ==