UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

176 lines 40.9 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 { white } from '../color'; import { Program, UniformColor, Attribute } from '../shader'; import { xyFrac_VERTSHADER, solid_FRAGSHADER, putQuadXys } from '../misc'; import { ensureCapacityFloat32, GL, hasval } from '../util/util'; import { newDynamicBuffer } from '../buffer'; import { newTextTextureCache2 } from '../text'; import { TextureRenderer } from '../texture'; import { indexAtOrBefore, indexAtOrAfter } from '../util/sorted_arrays'; export function newTimeseriesCursorPainterFactory(cursorOptions) { // Painter Factory return function (drawable, timeAxis, dataAxis, model, rowModel, ui, options) { let textColor = (hasval(cursorOptions) && hasval(cursorOptions.textColor) ? cursorOptions.textColor : white); let lineColor = (hasval(cursorOptions) && hasval(cursorOptions.lineColor) ? cursorOptions.lineColor : white); const font = (hasval(cursorOptions) && hasval(cursorOptions.font) ? cursorOptions.font : options.timelineFont); const buffer_px = (hasval(cursorOptions) && hasval(cursorOptions.buffer_px) ? cursorOptions.buffer_px : 4); const textDecimals = (hasval(cursorOptions) && hasval(cursorOptions.textDecimals) ? cursorOptions.textDecimals : 2); const boxSize_px = (hasval(cursorOptions) && hasval(cursorOptions.boxSize_px) ? cursorOptions.boxSize_px : 8); const crosshairThickness_px = (hasval(cursorOptions) && hasval(cursorOptions.crosshairThickness_px) ? cursorOptions.boxSize_px : 2); const boxThickness_px = (hasval(cursorOptions) && hasval(cursorOptions.boxThickness_px) ? cursorOptions.boxSize_px : 2); const program = new Program(xyFrac_VERTSHADER, solid_FRAGSHADER); const u_Color = new UniformColor(program, 'u_Color'); const a_Position = new Attribute(program, 'a_XyFrac'); let xys = new Float32Array(0); xys = ensureCapacityFloat32(xys, 4); const xysBuffer = newDynamicBuffer(); const textTextures = newTextTextureCache2(font); const textureRenderer = new TextureRenderer(); // Painter return function (gl, viewport) { // only draw a cursor if we are the current hovered row const hoveredRow = ui.selection.hoveredRow.value; if (!hasval(hoveredRow) || hoveredRow.rowGuid !== rowModel.rowGuid) { return; } gl.blendFuncSeparate(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA); gl.enable(GL.BLEND); let indexXys = 0; textTextures.resetTouches(); const time = ui.selection.hoveredTime_PMILLIS.value; const y = ui.selection.hoveredY.value; if (!hasval(time) || !hasval(y)) { return; } const wLine = crosshairThickness_px / viewport.w; const hLine = crosshairThickness_px / viewport.h; const wBoxLine = boxThickness_px / viewport.w; const hBoxLine = boxThickness_px / viewport.h; const wBox = boxSize_px / viewport.w; const hBox = boxSize_px / viewport.h; if (hasval(time)) { const cursorModel = model.cursor(rowModel.cursorGuid); if (hasval(cursorModel)) { if (hasval(cursorModel.lineColor)) { lineColor = cursorModel.lineColor; } if (hasval(cursorModel.textColor)) { textColor = cursorModel.textColor; } textureRenderer.begin(gl, viewport); const timeseriesCount = cursorModel.labeledTimeseriesGuids.length; // 36 vertices for crosshairs, 48 vertices per timeseries intersection marker xys = ensureCapacityFloat32(xys, 2 * (36 + timeseriesCount * 48)); for (let i = 0; i < cursorModel.labeledTimeseriesGuids.length; i++) { const timeseriesGuid = cursorModel.labeledTimeseriesGuids.valueAt(i); const timeseries = model.timeseries(timeseriesGuid); // if the row doesn't contain the timeseries, don't show cursor intersections if (!rowModel.timeseriesGuids.hasValue(timeseriesGuid)) { continue; } for (let j = 0; j < timeseries.fragmentGuids.length; j++) { const fragmentGuid = timeseries.fragmentGuids.valueAt(j); const fragment = model.timeseriesFragment(fragmentGuid); // fragments should not overlap if (fragment.start_PMILLIS < time && fragment.end_PMILLIS > time) { let value; // bars are drawn starting at the point and continuing to the next point, so we don't interpolate them if (timeseries.uiHint === 'bars') { const index = indexAtOrBefore(fragment.times_PMILLIS, time); value = fragment.data[index]; } else { const index0 = indexAtOrBefore(fragment.times_PMILLIS, time); const index1 = indexAtOrAfter(fragment.times_PMILLIS, time); const value0 = fragment.data[index0]; const time0 = fragment.times_PMILLIS[index0]; const value1 = fragment.data[index1]; const time1 = fragment.times_PMILLIS[index1]; const diff = time1 - time0; const diff0 = (time - time0) / diff; const diff1 = 1 - diff0; value = value0 * diff1 + value1 * diff0; } const textTexture = textTextures.value(textColor.rgbaString, value.toFixed(textDecimals)); const valueFracY = dataAxis.vFrac(value); const valueFracX = timeAxis.tFrac(time); const boxLeft = valueFracX - wBox / 2; const boxRight = valueFracX + wBox / 2; const boxTop = valueFracY + hBox / 2; const boxBottom = valueFracY - hBox / 2; // draw box at value location // left edge indexXys = putQuadXys(xys, indexXys, boxLeft - wBoxLine / 2, boxLeft + wBoxLine / 2, boxTop + hBoxLine / 2, boxBottom - hBoxLine / 2); // right edge indexXys = putQuadXys(xys, indexXys, boxRight - wBoxLine / 2, boxRight + wBoxLine / 2, boxTop + hBoxLine / 2, boxBottom - hBoxLine / 2); // top edge indexXys = putQuadXys(xys, indexXys, boxLeft + wBoxLine / 2, boxRight - wBoxLine / 2, boxTop - hBoxLine / 2, boxTop + hBoxLine / 2); // bottom edge indexXys = putQuadXys(xys, indexXys, boxLeft + wBoxLine / 2, boxRight - wBoxLine / 2, boxBottom - hBoxLine / 2, boxBottom + hBoxLine / 2); // draw text // XXX 0.6 looks more centered to the eye than 0.5 for numeric text textureRenderer.draw(gl, textTexture, boxRight + wBoxLine / 2 + buffer_px / viewport.w, valueFracY, { xAnchor: 0, yAnchor: .6 }); } } } if (hasval(cursorModel.showCursorText) ? cursorModel.showCursorText : true) { const textTexture = textTextures.value(textColor.rgbaString, y.toFixed(textDecimals)); textureRenderer.draw(gl, textTexture, 1, dataAxis.vFrac(y) + buffer_px / viewport.h, { xAnchor: 1, yAnchor: 0 }); } textureRenderer.end(gl); textTextures.retainTouched(); const xLeft = 0; const xRight = 1; const yMid = dataAxis.vFrac(y); const xMid = timeAxis.tFrac(time); // draw horizontal line if (hasval(cursorModel.showHorizontalLine) ? cursorModel.showHorizontalLine : true) { indexXys = putQuadXys(xys, indexXys, xLeft, xRight, yMid - hLine / 2, yMid + hLine / 2); } // draw vertical lines (split in two to avoid overlap with horizontal) if (hasval(cursorModel.showVerticalLine) ? cursorModel.showVerticalLine : true) { indexXys = putQuadXys(xys, indexXys, xMid - wLine / 2, xMid + wLine / 2, 0, yMid - hLine / 2); indexXys = putQuadXys(xys, indexXys, xMid - wLine / 2, xMid + wLine / 2, yMid + hLine / 2, 1); } // draw lines program.use(gl); xysBuffer.setData(xys.subarray(0, indexXys)); a_Position.setDataAndEnable(gl, xysBuffer, 2, GL.FLOAT); u_Color.setData(gl, lineColor); gl.drawArrays(GL.TRIANGLES, 0, Math.floor(indexXys / 2)); a_Position.disable(gl); program.endUse(gl); } } }; }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZWxpbmVfY3Vyc29yX3BhaW50ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvd2ViZ2xpbXBzZS90aW1lbGluZS90aW1lbGluZV9jdXJzb3JfcGFpbnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUNILE9BQU8sRUFBUyxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFPeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzdELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDMUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDakUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFzQnhFLE1BQU0sVUFBVSxpQ0FBaUMsQ0FBQyxhQUE4QztJQUU1RixrQkFBa0I7SUFDbEIsT0FBTyxVQUFVLFFBQWtCLEVBQUUsUUFBb0IsRUFBRSxRQUFnQixFQUFFLEtBQW9CLEVBQUUsUUFBMEIsRUFBRSxFQUFjLEVBQUUsT0FBeUM7UUFFcEwsSUFBSSxTQUFTLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0csSUFBSSxTQUFTLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0csTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQy9HLE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNHLE1BQU0sWUFBWSxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BILE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlHLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksTUFBTSxDQUFDLGFBQWEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwSSxNQUFNLGVBQWUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsSUFBSSxN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S0FBSyxDQUFDLENBQUM7b0JBQ3hELE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO29CQUMvQixFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBRXpELFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQ3ZCLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7aUJBQ3RCO2FBQ0o7UUFDTCxDQUFDLENBQUM7SUFDTixDQUFDLENBQUM7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogQ29weXJpZ2h0IChjKSAyMDE0LCBNZXRyb24sIEluYy5cclxuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICpcclxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcclxuICogYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxyXG4gKlxyXG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuICogICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXHJcbiAqXHJcbiAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuICogICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxyXG4gKiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cclxuICpcclxuICogMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cyBjb250cmlidXRvcnNcclxuICogICAgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXRcclxuICogICAgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxyXG4gKlxyXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcclxuICogQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcclxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxyXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxyXG4gKiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcclxuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xyXG4gKiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cclxuICogQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcclxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcclxuICogU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXHJcbiAqL1xyXG5pbXBvcnQgeyBDb2xvciwgd2hpdGUgfSBmcm9tICcuLi9jb2xvcic7XHJcbmltcG9ydCB7IFRpbWVsaW5lVGltZXNlcmllc1BhaW50ZXJGYWN0b3J5LCBUaW1lbGluZVRpbWVzZXJpZXNQYWludGVyT3B0aW9ucyB9IGZyb20gJy4vdGltZWxpbmVfdGltZXNlcmllc19yb3cnO1xyXG5pbXBvcnQgeyBEcmF3YWJsZSwgUGFpbnRlciB9IGZyb20gJy4uL2NvcmUnO1xyXG5pbXBvcnQgeyBUaW1lQXhpczFEIH0gZnJvbSAnLi90aW1lX2F4aXMnO1xyXG5pbXBvcnQgeyBBeGlzMUQgfSBmcm9tICcuLi9wbG90L2F4aXMnO1xyXG5pbXBvcnQgeyBUaW1lbGluZU1vZGVsLCBUaW1lbGluZVJvd01vZGVsLCBUaW1lbGluZVRpbWVzZXJpZXNGcmFnbWVudE1vZGVsIH0gZnJvbSAnLi90aW1lbGluZV9tb2RlbCc7XHJcbmltcG9ydCB7IFRpbWVsaW5lVWkgfSBmcm9tICcuL3RpbWVsaW5lX3VpJztcclxuaW1wb3J0IHsgUHJvZ3JhbSwgVW5pZm9ybUNvbG9yLCBBdHRyaWJ1dGUgfSBmcm9tICcuLi9zaGFkZXInO1xyXG5pbXBvcnQgeyB4eUZyYWNfVkVSVFNIQURFUiwgc29saWRfRlJBR1NIQURFUiwgcHV0UXVhZFh5cyB9IGZyb20gJy4uL21pc2MnO1xyXG5pbXBvcnQgeyBlbnN1cmVDYXBhY2l0eUZsb2F0MzIsIEdMLCBoYXN2YWwgfSBmcm9tICcuLi91dGlsL3V0aWwnO1xyXG5pbXBvcnQgeyBuZXdEeW5hbWljQnVmZmVyIH0gZnJvbSAnLi4vYnVmZmVyJztcclxuaW1wb3J0IHsgbmV3VGV4dFRleHR1cmVDYWNoZTIgfSBmcm9tICcuLi90ZXh0JztcclxuaW1wb3J0IHsgVGV4dHVyZVJlbmRlcmVyIH0gZnJvbSAnLi4vdGV4dHVyZSc7XHJcbmltcG9ydCB7IEJvdW5kc1VubW9kaWZpYWJsZSB9IGZyb20gJy4uL2JvdW5kcyc7XHJcbmltcG9ydCB7IGluZGV4QXRPckJlZm9yZSwgaW5kZXhBdE9yQWZ0ZXIgfSBmcm9tICcuLi91dGlsL3NvcnRlZF9hcnJheXMnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBUaW1lc2VyaWVzQ3Vyc29yUGFpbnRlck9wdGlvbnMge1xyXG4gICAgZm9udD86IHN0cmluZztcclxuICAgIHRleHRDb2xvcj86IENvbG9yO1xyXG4gICAgLy8gbnVtYmVyIG9mIHBpeGVscyBiZXR3ZWVuIGJveCBhbmQgbGFiZWwgdGV4dFxyXG4gICAgYnVmZmVyX3B4PzogbnVtYmVyO1xyXG4gICAgLy8gbnVtYmVyIG9mIHNpZ25pZmljYW50IGRpZ2l0cyBpbiB0ZXh0IGxhYmVsc1xyXG4gICAgdGV4dERlY2ltYWxzPzogbnVtYmVyO1xyXG5cclxuICAgIC8vIGNvbG9yIG9mIHNlbGVjdGlvbiBib3ggYW5kIGNyb3NzaGFpciBsaW5lc1xyXG4gICAgbGluZUNvbG9yPzogQ29sb3I7XHJcblxyXG4gICAgLy8gdGhpY2tuZXNzIG9mIGN1cnNvciBjcm9zc2hhaXIgbGluZXMgaW4gcGl4ZWxzXHJcbiAgICBjcm9zc2hhaXJUaGlja25lc3NfcHg/OiBudW1iZXI7XHJcblxyXG4gICAgLy8gd2lkdGgvaGVpZ2h0IG9mIHNlbGVjdGlvbiBib3ggKHNob3duIGF0IGludGVyc2VjdGlvbiBiZXdlZW4gY3Jvc3NoYWlycyBhbmQgdGltZXNlcmllcykgaW4gcGl4ZWxzXHJcbiAgICBib3hTaXplX3B4PzogbnVtYmVyO1xyXG4gICAgLy8gdGhpY2tuZXNzIG9mIHNlbGVjdGlvbiBib3ggbGluZXMgaW4gcGl4ZWxzXHJcbiAgICBib3hUaGlja25lc3NfcHg/OiBudW1iZXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdUaW1lc2VyaWVzQ3Vyc29yUGFpbnRlckZhY3RvcnkoY3Vyc29yT3B0aW9ucz86IFRpbWVzZXJpZXNDdXJzb3JQYWludGVyT3B0aW9ucyk6IFRpbWVsaW5lVGltZXNlcmllc1BhaW50ZXJGYWN0b3J5IHtcclxuXHJcbiAgICAvLyBQYWludGVyIEZhY3RvcnlcclxuICAgIHJldHVybiBmdW5jdGlvbiAoZHJhd2FibGU6IERyYXdhYmxlLCB0aW1lQXhpczogVGltZUF4aXMxRCwgZGF0YUF4aXM6IEF4aXMxRCwgbW9kZWw6IFRpbWVsaW5lTW9kZWwsIHJvd01vZGVsOiBUaW1lbGluZVJvd01vZGVsLCB1aTogVGltZWxpbmVVaSwgb3B0aW9uczogVGltZWxpbmVUaW1lc2VyaWVzUGFpbnRlck9wdGlvbnMpOiBQYWludGVyIHtcclxuXHJcbiAgICAgICAgbGV0IHRleHRDb2xvciA9IChoYXN2YWwoY3Vyc29yT3B0aW9ucykgJiYgaGFzdmFsKGN1cnNvck9wdGlvbnMudGV4dENvbG9yKSA/IGN1cnNvck9wdGlvbnMudGV4dENvbG9yIDogd2hpdGUpO1xyXG4gICAgICAgIGxldCBsaW5lQ29sb3IgPSAoaGFzdmFsKGN1cnNvck9wdGlvbnMpICYmIGhhc3ZhbChjdXJzb3JPcHRpb25zLmxpbmVDb2xvcikgPyBjdXJzb3JPcHRpb25zLmxpbmVDb2xvciA6IHdoaXRlKTtcclxuICAgICAgICBjb25zdCBmb250ID0gKGhhc3ZhbChjdXJzb3JPcHRpb25zKSAmJiBoYXN2YWwoY3Vyc29yT3B0aW9ucy5mb250KSA/IGN1cnNvck9wdGlvbnMuZm9udCA6IG9wdGlvbnMudGltZWxpbmVGb250KTtcclxuICAgICAgICBjb25zdCBidWZmZXJfcHggPSAoaGFzdmFsKGN1cnNvck9wdGlvbnMpICYmIGhhc3ZhbChjdXJzb3JPcHRpb25zLmJ1ZmZlcl9weCkgPyBjdXJzb3JPcHRpb25zLmJ1ZmZlcl9weCA6IDQpO1xyXG4gICAgICAgIGNvbnN0IHRleHREZWNpbWFscyA9IChoYXN2YWwoY3Vyc29yT3B0aW9ucykgJiYgaGFzdmFsKGN1cnNvck9wdGlvbnMudGV4dERlY2ltYWxzKSA/IGN1cnNvck9wdGlvbnMudGV4dERlY2ltYWxzIDogMik7XHJcbiAgICAgICAgY29uc3QgYm94U2l6ZV9weCA9IChoYXN2YWwoY3Vyc29yT3B0aW9ucykgJiYgaGFzdmFsKGN1cnNvck9wdGlvbnMuYm94U2l6ZV9weCkgPyBjdXJzb3JPcHRpb25zLmJveFNpemVfcHggOiA4KTtcclxuICAgICAgICBjb25zdCBjcm9zc2hhaXJUaGlja25lc3NfcHggPSAoaGFzdmFsKGN1cnNvck9wdGlvbnMpICYmIGhhc3ZhbChjdXJzb3JPcHRpb25zLmNyb3NzaGFpclRoaWNrbmVzc19weCkgPyBjdXJzb3JPcHRpb25zLmJveFNpemVfcHggOiAyKTtcclxuICAgICAgICBjb25zdCBib3hUaGlja25lc3NfcHggPSAoaGFzdmFsKGN1cnNvck9wdGlvbnMpICYmIGhhc3ZhbChjdXJzb3JPcHRpb25zLmJveFRoaWNrbmVzc19weCkgPyBjdXJzb3JPcHRpb25zLmJveFNpemVfcHggOiAyKTtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvZ3JhbSA9IG5ldyBQcm9ncmFtKHh5RnJhY19WRVJUU0hBREVSLCBzb2xpZF9GUkFHU0hBREVSKTtcclxuICAgICAgICBjb25zdCB1X0NvbG9yID0gbmV3IFVuaWZvcm1Db2xvcihwcm9ncmFtLCAndV9Db2xvcicpO1xyXG4gICAgICAgIGNvbnN0IGFfUG9zaXRpb24gPSBuZXcgQXR0cmlidXRlKHByb2dyYW0sICdhX1h5RnJhYycpO1xyXG5cclxuICAgICAgICBsZXQgeHlzID0gbmV3IEZsb2F0MzJBcnJheSgwKTtcclxuICAgICAgICB4eXMgPSBlbnN1cmVDYXBhY2l0eUZsb2F0MzIoeHlzLCA0KTtcclxuICAgICAgICBjb25zdCB4eXNCdWZmZXIgPSBuZXdEeW5hbWljQnVmZmVyKCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHRleHRUZXh0dXJlcyA9IG5ld1RleHRUZXh0dXJlQ2FjaGUyKGZvbnQpO1xyXG4gICAgICAgIGNvbnN0IHRleHR1cmVSZW5kZXJlciA9IG5ldyBUZXh0dXJlUmVuZGVyZXIoKTtcclxuXHJcbiAgICAgICAgLy8gUGFpbnRlclxyXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgdmlld3BvcnQ6IEJvdW5kc1VubW9kaWZpYWJsZSkge1xyXG5cclxuICAgICAgICAgICAgLy8gb25seSBkcmF3IGEgY3Vyc29yIGlmIHdlIGFyZSB0aGUgY3VycmVudCBob3ZlcmVkIHJvd1xyXG4gICAgICAgICAgICBjb25zdCBob3ZlcmVkUm93OiBUaW1lbGluZVJvd01vZGVsID0gdWkuc2VsZWN0aW9uLmhvdmVyZWRSb3cudmFsdWU7XHJcbiAgICAgICAgICAgIGlmICghaGFzdmFsKGhvdmVyZWRSb3cpIHx8IGhvdmVyZWRSb3cucm93R3VpZCAhPT0gcm93TW9kZWwucm93R3VpZCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBnbC5ibGVuZEZ1bmNTZXBhcmF0ZShHTC5TUkNfQUxQSEEsIEdMLk9ORV9NSU5VU19TUkNfQUxQSEEsIEdMLk9ORSwgR0wuT05FX01JTlVTX1NSQ19BTFBIQSk7XHJcbiAgICAgICAgICAgIGdsLmVuYWJsZShHTC5CTEVORCk7XHJcblxyXG4gICAgICAgICAgICBsZXQgaW5kZXhYeXMgPSAwO1xyXG4gICAgICAgICAgICB0ZXh0VGV4dHVyZXMucmVzZXRUb3VjaGVzKCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCB0aW1lID0gdWkuc2VsZWN0aW9uLmhvdmVyZWRUaW1lX1BNSUxMSVMudmFsdWU7XHJcbiAgICAgICAgICAgIGNvbnN0IHkgPSB1aS5zZWxlY3Rpb24uaG92ZXJlZFkudmFsdWU7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWhhc3ZhbCh0aW1lKSB8fCAhaGFzdmFsKHkpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHdMaW5lID0gY3Jvc3NoYWlyVGhpY2tuZXNzX3B4IC8gdmlld3BvcnQudztcclxuICAgICAgICAgICAgY29uc3QgaExpbmUgPSBjcm9zc2hhaXJUaGlja25lc3NfcHggLyB2aWV3cG9ydC5oO1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgd0JveExpbmUgPSBib3hUaGlja25lc3NfcHggLyB2aWV3cG9ydC53O1xyXG4gICAgICAgICAgICBjb25zdCBoQm94TGluZSA9IGJveFRoaWNrbmVzc19weCAvIHZpZXdwb3J0Lmg7XHJcblxyXG4gICAgICAgICAgICBjb25zdCB3Qm94ID0gYm94U2l6ZV9weCAvIHZpZXdwb3J0Lnc7XHJcbiAgICAgICAgICAgIGNvbnN0IGhCb3ggPSBib3hTaXplX3B4IC8gdmlld3BvcnQuaDtcclxuXHJcbiAgICAgICAgICAgIGlmIChoYXN2YWwodGltZSkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBjdXJzb3JNb2RlbCA9IG1vZGVsLmN1cnNvcihyb3dNb2RlbC5jdXJzb3JHdWlkKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaGFzdmFsKGN1cnNvck1vZGVsKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXN2YWwoY3Vyc29yTW9kZWwubGluZUNvbG9yKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lQ29sb3IgPSBjdXJzb3JNb2RlbC5saW5lQ29sb3I7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoaGFzdmFsKGN1cnNvck1vZGVsLnRleHRDb2xvcikpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dENvbG9yID0gY3Vyc29yTW9kZWwudGV4dENvbG9yO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dHVyZVJlbmRlcmVyLmJlZ2luKGdsLCB2aWV3cG9ydCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVzZXJpZXNDb3VudCA9IGN1cnNvck1vZGVsLmxhYmVsZWRUaW1lc2VyaWVzR3VpZHMubGVuZ3RoO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyAzNiB2ZXJ0aWNlcyBmb3IgY3Jvc3NoYWlycywgNDggdmVydGljZXMgcGVyIHRpbWVzZXJpZXMgaW50ZXJzZWN0aW9uIG1hcmtlclxyXG4gICAgICAgICAgICAgICAgICAgIHh5cyA9IGVuc3VyZUNhcGFjaXR5RmxvYXQzMih4eXMsIDIgKiAoMzYgKyB0aW1lc2VyaWVzQ291bnQgKiA0OCkpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGN1cnNvck1vZGVsLmxhYmVsZWRUaW1lc2VyaWVzR3VpZHMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVzZXJpZXNHdWlkID0gY3Vyc29yTW9kZWwubGFiZWxlZFRpbWVzZXJpZXNHdWlkcy52YWx1ZUF0KGkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lc2VyaWVzID0gbW9kZWwudGltZXNlcmllcyh0aW1lc2VyaWVzR3VpZCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcm93IGRvZXNuJ3QgY29udGFpbiB0aGUgdGltZXNlcmllcywgZG9uJ3Qgc2hvdyBjdXJzb3IgaW50ZXJzZWN0aW9uc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXJvd01vZGVsLnRpbWVzZXJpZXNHdWlkcy5oYXNWYWx1ZSh0aW1lc2VyaWVzR3VpZCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRpbWVzZXJpZXMuZnJhZ21lbnRHdWlkcy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZnJhZ21lbnRHdWlkOiBzdHJpbmcgPSB0aW1lc2VyaWVzLmZyYWdtZW50R3VpZHMudmFsdWVBdChqKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZyYWdtZW50OiBUaW1lbGluZVRpbWVzZXJpZXNGcmFnbWVudE1vZGVsID0gbW9kZWwudGltZXNlcmllc0ZyYWdtZW50KGZyYWdtZW50R3VpZCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZnJhZ21lbnRzIHNob3VsZCBub3Qgb3ZlcmxhcFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyYWdtZW50LnN0YXJ0X1BNSUxMSVMgPCB0aW1lICYmIGZyYWdtZW50LmVuZF9QTUlMTElTID4gdGltZSkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWU6IG51bWJlcjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYmFycyBhcmUgZHJhd24gc3RhcnRpbmcgYXQgdGhlIHBvaW50IGFuZCBjb250aW51aW5nIHRvIHRoZSBuZXh0IHBvaW50LCBzbyB3ZSBkb24ndCBpbnRlcnBvbGF0ZSB0aGVtXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRpbWVzZXJpZXMudWlIaW50ID09PSAnYmFycycpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXg6IG51bWJlciA9IGluZGV4QXRPckJlZm9yZShmcmFnbWVudC50aW1lc19QTUlMTElTLCB0aW1lKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBmcmFnbWVudC5kYXRhW2luZGV4XTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4MDogbnVtYmVyID0gaW5kZXhBdE9yQmVmb3JlKGZyYWdtZW50LnRpbWVzX1BNSUxMSVMsIHRpbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleDE6IG51bWJlciA9IGluZGV4QXRPckFmdGVyKGZyYWdtZW50LnRpbWVzX1BNSUxMSVMsIHRpbWUpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUwID0gZnJhZ21lbnQuZGF0YVtpbmRleDBdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lMCA9IGZyYWdtZW50LnRpbWVzX1BNSUxMSVNbaW5kZXgwXTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlMSA9IGZyYWdtZW50LmRhdGFbaW5kZXgxXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZTEgPSBmcmFnbWVudC50aW1lc19QTUlMTElTW2luZGV4MV07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaWZmID0gdGltZTEgLSB0aW1lMDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGlmZjAgPSAodGltZSAtIHRpbWUwKSAvIGRpZmY7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpZmYxID0gMSAtIGRpZmYwO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZTAgKiBkaWZmMSArIHZhbHVlMSAqIGRpZmYwO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dFRleHR1cmUgPSB0ZXh0VGV4dHVyZXMudmFsdWUodGV4dENvbG9yLnJnYmFTdHJpbmcsIHZhbHVlLnRvRml4ZWQodGV4dERlY2ltYWxzKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlRnJhY1kgPSBkYXRhQXhpcy52RnJhYyh2YWx1ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVGcmFjWCA9IHRpbWVBeGlzLnRGcmFjKHRpbWUpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBib3hMZWZ0ID0gdmFsdWVGcmFjWCAtIHdCb3ggLyAyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJveFJpZ2h0ID0gdmFsdWVGcmFjWCArIHdCb3ggLyAyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJveFRvcCA9IHZhbHVlRnJhY1kgKyBoQm94IC8gMjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBib3hCb3R0b20gPSB2YWx1ZUZyYWNZIC0gaEJveCAvIDI7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRyYXcgYm94IGF0IHZhbHVlIGxvY2F0aW9uXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxlZnQgZWRnZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4WHlzID0gcHV0UXVhZFh5cyh4eXMsIGluZGV4WHlzLCBib3hMZWZ0IC0gd0JveExpbmUgLyAyLCBib3hMZWZ0ICsgd0JveExpbmUgLyAyLCBib3hUb3AgKyBoQm94TGluZSAvIDIsIGJveEJvdHRvbSAtIGhCb3hMaW5lIC8gMik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmlnaHQgZWRnZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4WHlzID0gcHV0UXVhZFh5cyh4eXMsIGluZGV4WHlzLCBib3hSaWdodCAtIHdCb3hMaW5lIC8gMiwgYm94UmlnaHQgKyB3Qm94TGluZSAvIDIsIGJveFRvcCArIGhCb3hMaW5lIC8gMiwgYm94Qm90dG9tIC0gaEJveExpbmUgLyAyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0b3AgZWRnZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4WHlzID0gcHV0UXVhZFh5cyh4eXMsIGluZGV4WHlzLCBib3hMZWZ0ICsgd0JveExpbmUgLyAyLCBib3hSaWdodCAtIHdCb3hMaW5lIC8gMiwgYm94VG9wIC0gaEJveExpbmUgLyAyLCBib3hUb3AgKyBoQm94TGluZSAvIDIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJvdHRvbSBlZGdlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhYeXMgPSBwdXRRdWFkWHlzKHh5cywgaW5kZXhYeXMsIGJveExlZnQgKyB3Qm94TGluZSAvIDIsIGJveFJpZ2h0IC0gd0JveExpbmUgLyAyLCBib3hCb3R0b20gLSBoQm94TGluZSAvIDIsIGJveEJvdHRvbSArIGhCb3hMaW5lIC8gMik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRyYXcgdGV4dFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFhYWCAwLjYgbG9va3MgbW9yZSBjZW50ZXJlZCB0byB0aGUgZXllIHRoYW4gMC41IGZvciBudW1lcmljIHRleHRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0dXJlUmVuZGVyZXIuZHJhdyhnbCwgdGV4dFRleHR1cmUsIGJveFJpZ2h0ICsgd0JveExpbmUgLyAyICsgYnVmZmVyX3B4IC8gdmlld3BvcnQudywgdmFsdWVGcmFjWSwgeyB4QW5jaG9yOiAwLCB5QW5jaG9yOiAuNiB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXN2YWwoY3Vyc29yTW9kZWwuc2hvd0N1cnNvclRleHQpID8gY3Vyc29yTW9kZWwuc2hvd0N1cnNvclRleHQgOiB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHRUZXh0dXJlID0gdGV4dFRleHR1cmVzLnZhbHVlKHRleHRDb2xvci5yZ2JhU3RyaW5nLCB5LnRvRml4ZWQodGV4dERlY2ltYWxzKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHR1cmVSZW5kZXJlci5kcmF3KGdsLCB0ZXh0VGV4dHVyZSwgMSwgZGF0YUF4aXMudkZyYWMoeSkgKyBidWZmZXJfcHggLyB2aWV3cG9ydC5oLCB7IHhBbmNob3I6IDEsIHlBbmNob3I6IDAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0ZXh0dXJlUmVuZGVyZXIuZW5kKGdsKTtcclxuICAgICAgICAgICAgICAgICAgICB0ZXh0VGV4dHVyZXMucmV0YWluVG91Y2hlZCgpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB4TGVmdCA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeFJpZ2h0ID0gMTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB5TWlkID0gZGF0YUF4aXMudkZyYWMoeSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeE1pZCA9IHRpbWVBeGlzLnRGcmFjKHRpbWUpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBkcmF3IGhvcml6b250YWwgbGluZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXN2YWwoY3Vyc29yTW9kZWwuc2hvd0hvcml6b250YWxMaW5lKSA/IGN1cnNvck1vZGVsLnNob3dIb3Jpem9udGFsTGluZSA6IHRydWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXhYeXMgPSBwdXRRdWFkWHlzKHh5cywgaW5kZXhYeXMsIHhMZWZ0LCB4UmlnaHQsIHlNaWQgLSBoTGluZSAvIDIsIHlNaWQgKyBoTGluZSAvIDIpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gZHJhdyB2ZXJ0aWNhbCBsaW5lcyAoc3BsaXQgaW4gdHdvIHRvIGF2b2lkIG92ZXJsYXAgd2l0aCBob3Jpem9udGFsKVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXN2YWwoY3Vyc29yTW9kZWwuc2hvd1ZlcnRpY2FsTGluZSkgPyBjdXJzb3JNb2RlbC5zaG93VmVydGljYWxMaW5lIDogdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleFh5cyA9IHB1dFF1YWRYeXMoeHlzLCBpbmRleFh5cywgeE1pZCAtIHdMaW5lIC8gMiwgeE1pZCArIHdMaW5lIC8gMiwgMCwgeU1pZCAtIGhMaW5lIC8gMik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4WHlzID0gcHV0UXVhZFh5cyh4eXMsIGluZGV4WHlzLCB4TWlkIC0gd0xpbmUgLyAyLCB4TWlkICsgd0xpbmUgLyAyLCB5TWlkICsgaExpbmUgLyAyLCAxKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIGRyYXcgbGluZXNcclxuICAgICAgICAgICAgICAgICAgICBwcm9ncmFtLnVzZShnbCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHh5c0J1ZmZlci5zZXREYXRhKHh5cy5zdWJhcnJheSgwLCBpbmRleFh5cykpO1xyXG4gICAgICAgICAgICAgICAgICAgIGFfUG9zaXRpb24uc2V0RGF0YUFuZEVuYWJsZShnbCwgeHlzQnVmZmVyLCAyLCBHTC5GTE9BVCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdV9Db2xvci5zZXREYXRhKGdsLCBsaW5lQ29sb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIGdsLmRyYXdBcnJheXMoR0wuVFJJQU5HTEVTLCAwLCBNYXRoLmZsb29yKGluZGV4WHlzIC8gMikpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBhX1Bvc2l0aW9uLmRpc2FibGUoZ2wpO1xyXG4gICAgICAgICAgICAgICAgICAgIHByb2dyYW0uZW5kVXNlKGdsKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICB9O1xyXG59XHJcbiJdfQ==