UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

240 lines 43.7 kB
/* * Copyright (c) 2014, Metron, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import { 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==