UNPKG

@qogni/dygraphs

Version:

dygraphs is a fast, flexible open source JavaScript charting library.

373 lines (356 loc) 52.3 kB
/** * @license * Copyright 2012 Dan Vanderkam (danvdk@gmail.com) * MIT-licenced: https://opensource.org/licenses/MIT */ /*global Dygraph:false */ /* Current bits of jankiness: - Uses two private APIs: 1. Dygraph.optionsViewForAxis_ 2. dygraph.plotter_.area - Registers for a "predraw" event, which should be renamed. - I call calculateEmWidthInDiv more often than needed. */ /*global Dygraph:false */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var utils = _interopRequireWildcard(require("../dygraph-utils")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } /** * Creates the legend, which appears when the user hovers over the chart. * The legend can be either a user-specified or generated div. * * @constructor */ var Legend = function Legend() { this.legend_div_ = null; this.is_generated_div_ = false; // do we own this div, or was it user-specified? }; Legend.prototype.toString = function () { return "Legend Plugin"; }; /** * This is called during the dygraph constructor, after options have been set * but before the data is available. * * Proper tasks to do here include: * - Reading your own options * - DOM manipulation * - Registering event listeners * * @param {Dygraph} g Graph instance. * @return {object.<string, function(ev)>} Mapping of event names to callbacks. */ Legend.prototype.activate = function (g) { var div; var userLabelsDiv = g.getOption('labelsDiv'); if (userLabelsDiv && null !== userLabelsDiv) { if (typeof userLabelsDiv == "string" || userLabelsDiv instanceof String) { div = document.getElementById(userLabelsDiv); } else { div = userLabelsDiv; } } else { div = document.createElement("div"); div.className = "dygraph-legend"; // TODO(danvk): come up with a cleaner way to expose this. g.graphDiv.appendChild(div); this.is_generated_div_ = true; } this.legend_div_ = div; this.one_em_width_ = 10; // just a guess, will be updated. return { select: this.select, deselect: this.deselect, // TODO(danvk): rethink the name "predraw" before we commit to it in any API. predraw: this.predraw, didDrawChart: this.didDrawChart }; }; // Needed for dashed lines. var calculateEmWidthInDiv = function calculateEmWidthInDiv(div) { var sizeSpan = document.createElement('span'); sizeSpan.setAttribute('style', 'margin: 0; padding: 0 0 0 1em; border: 0;'); div.appendChild(sizeSpan); var oneEmWidth = sizeSpan.offsetWidth; div.removeChild(sizeSpan); return oneEmWidth; }; var escapeHTML = function escapeHTML(str) { return str.replace(/&/g, "&amp;").replace(/"/g, "&#34;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }; Legend.prototype.select = function (e) { var xValue = e.selectedX; var points = e.selectedPoints; var row = e.selectedRow; var legendMode = e.dygraph.getOption('legend'); if (legendMode === 'never') { this.legend_div_.style.display = 'none'; return; } var html = Legend.generateLegendHTML(e.dygraph, xValue, points, this.one_em_width_, row); if (html instanceof Node && html.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { this.legend_div_.innerHTML = ''; this.legend_div_.appendChild(html); } else this.legend_div_.innerHTML = html; // must be done now so offsetWidth isn’t 0… this.legend_div_.style.display = ''; if (legendMode === 'follow') { // create floating legend div var area = e.dygraph.plotter_.area; var labelsDivWidth = this.legend_div_.offsetWidth; var yAxisLabelWidth = e.dygraph.getOptionForAxis('axisLabelWidth', 'y'); // find the closest data point by checking the currently highlighted series, // or fall back to using the first data point available var highlightSeries = e.dygraph.getHighlightSeries(); var point; if (highlightSeries) { point = points.find(function (p) { return p.name === highlightSeries; }); if (!point) point = points[0]; } else point = points[0]; // determine floating [left, top] coordinates of the legend div // within the plotter_ area // offset 50 px to the right and down from the first selection point // 50 px is guess based on mouse cursor size var followOffsetX = e.dygraph.getNumericOption('legendFollowOffsetX'); var followOffsetY = e.dygraph.getNumericOption('legendFollowOffsetY'); var leftLegend = point.x * area.w + followOffsetX; var topLegend = point.y * area.h + followOffsetY; // if legend floats to end of the chart area, it flips to the other // side of the selection point if (leftLegend + labelsDivWidth + 1 > area.w) { leftLegend = leftLegend - 2 * followOffsetX - labelsDivWidth - (yAxisLabelWidth - area.x); } this.legend_div_.style.left = yAxisLabelWidth + leftLegend + "px"; this.legend_div_.style.top = topLegend + "px"; } else if (legendMode === 'onmouseover' && this.is_generated_div_) { // synchronise this with Legend.prototype.predraw below var area = e.dygraph.plotter_.area; var labelsDivWidth = this.legend_div_.offsetWidth; this.legend_div_.style.left = area.x + area.w - labelsDivWidth - 1 + "px"; this.legend_div_.style.top = area.y + "px"; } }; Legend.prototype.deselect = function (e) { var legendMode = e.dygraph.getOption('legend'); if (legendMode !== 'always') { this.legend_div_.style.display = "none"; } // Have to do this every time, since styles might have changed. var oneEmWidth = calculateEmWidthInDiv(this.legend_div_); this.one_em_width_ = oneEmWidth; var html = Legend.generateLegendHTML(e.dygraph, undefined, undefined, oneEmWidth, null); if (html instanceof Node && html.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { this.legend_div_.innerHTML = ''; this.legend_div_.appendChild(html); } else this.legend_div_.innerHTML = html; }; Legend.prototype.didDrawChart = function (e) { this.deselect(e); }; // Right edge should be flush with the right edge of the charting area (which // may not be the same as the right edge of the div, if we have two y-axes). // TODO(danvk): is any of this really necessary? Could just set "right" in "activate". /** * Position the labels div so that: * - its right edge is flush with the right edge of the charting area * - its top edge is flush with the top edge of the charting area * @private */ Legend.prototype.predraw = function (e) { // Don't touch a user-specified labelsDiv. if (!this.is_generated_div_) return; // TODO(danvk): only use real APIs for this. e.dygraph.graphDiv.appendChild(this.legend_div_); // synchronise this with Legend.prototype.select above var area = e.dygraph.plotter_.area; var labelsDivWidth = this.legend_div_.offsetWidth; this.legend_div_.style.left = area.x + area.w - labelsDivWidth - 1 + "px"; this.legend_div_.style.top = area.y + "px"; }; /** * Called when dygraph.destroy() is called. * You should null out any references and detach any DOM elements. */ Legend.prototype.destroy = function () { this.legend_div_ = null; }; /** * Generates HTML for the legend which is displayed when hovering over the * chart. If no selected points are specified, a default legend is returned * (this may just be the empty string). * @param {number} x The x-value of the selected points. * @param {Object} sel_points List of selected points for the given * x-value. Should have properties like 'name', 'yval' and 'canvasy'. * @param {number} oneEmWidth The pixel width for 1em in the legend. Only * relevant when displaying a legend with no selection (i.e. {legend: * 'always'}) and with dashed lines. * @param {number} row The selected row index. * @private */ Legend.generateLegendHTML = function (g, x, sel_points, oneEmWidth, row) { // Data about the selection to pass to legendFormatter var data = { dygraph: g, x: x, i: row, series: [] }; var labelToSeries = {}; var labels = g.getLabels(); if (labels) { for (var i = 1; i < labels.length; i++) { var series = g.getPropertiesForSeries(labels[i]); var strokePattern = g.getOption('strokePattern', labels[i]); var seriesData = { dashHTML: generateLegendDashHTML(strokePattern, series.color, oneEmWidth), label: labels[i], labelHTML: escapeHTML(labels[i]), isVisible: series.visible, color: series.color }; data.series.push(seriesData); labelToSeries[labels[i]] = seriesData; } } if (typeof x !== 'undefined') { var xOptView = g.optionsViewForAxis_('x'); var xvf = xOptView('valueFormatter'); data.xHTML = xvf.call(g, x, xOptView, labels[0], g, row, 0); var yOptViews = []; var num_axes = g.numAxes(); for (var i = 0; i < num_axes; i++) { // TODO(danvk): remove this use of a private API yOptViews[i] = g.optionsViewForAxis_('y' + (i ? 1 + i : '')); } var showZeros = g.getOption('labelsShowZeroValues'); var highlightSeries = g.getHighlightSeries(); for (i = 0; i < sel_points.length; i++) { var pt = sel_points[i]; var seriesData = labelToSeries[pt.name]; seriesData.y = pt.yval; if (pt.yval === 0 && !showZeros || isNaN(pt.canvasy)) { seriesData.isVisible = false; continue; } var series = g.getPropertiesForSeries(pt.name); var yOptView = yOptViews[series.axis - 1]; var fmtFunc = yOptView('valueFormatter'); var yHTML = fmtFunc.call(g, pt.yval, yOptView, pt.name, g, row, labels.indexOf(pt.name)); utils.update(seriesData, { yHTML: yHTML }); if (pt.name == highlightSeries) { seriesData.isHighlighted = true; } } } var formatter = g.getOption('legendFormatter') || Legend.defaultFormatter; return formatter.call(g, data); }; Legend.defaultFormatter = function (data) { var g = data.dygraph; // TODO(danvk): deprecate this option in place of {legend: 'never'} // XXX should this logic be in the formatter? if (g.getOption('showLabelsOnHighlight') !== true) return ''; var sepLines = g.getOption('labelsSeparateLines'); var html; if (typeof data.x === 'undefined') { // TODO: this check is duplicated in generateLegendHTML. Put it in one place. if (g.getOption('legend') != 'always') { return ''; } html = ''; for (var i = 0; i < data.series.length; i++) { var series = data.series[i]; if (!series.isVisible) continue; if (html !== '') html += sepLines ? '<br />' : ' '; html += "<span style='font-weight: bold; color: ".concat(series.color, ";'>").concat(series.dashHTML, " ").concat(series.labelHTML, "</span>"); } return html; } html = data.xHTML + ':'; for (var i = 0; i < data.series.length; i++) { var series = data.series[i]; if (!series.y && !series.yHTML) continue; if (!series.isVisible) continue; if (sepLines) html += '<br>'; var cls = series.isHighlighted ? ' class="highlight"' : ''; html += "<span".concat(cls, "> <b><span style='color: ").concat(series.color, ";'>").concat(series.labelHTML, "</span></b>:&#160;").concat(series.yHTML, "</span>"); } return html; }; /** * Generates html for the "dash" displayed on the legend when using "legend: always". * In particular, this works for dashed lines with any stroke pattern. It will * try to scale the pattern to fit in 1em width. Or if small enough repeat the * pattern for 1em width. * * @param strokePattern The pattern * @param color The color of the series. * @param oneEmWidth The width in pixels of 1em in the legend. * @private */ // TODO(danvk): cache the results of this function generateLegendDashHTML(strokePattern, color, oneEmWidth) { // Easy, common case: a solid line if (!strokePattern || strokePattern.length <= 1) { return "<div class=\"dygraph-legend-line\" style=\"border-bottom-color: ".concat(color, ";\"></div>"); } var i, j, paddingLeft, marginRight; var strokePixelLength = 0, segmentLoop = 0; var normalizedPattern = []; var loop; // Compute the length of the pixels including the first segment twice, // since we repeat it. for (i = 0; i <= strokePattern.length; i++) { strokePixelLength += strokePattern[i % strokePattern.length]; } // See if we can loop the pattern by itself at least twice. loop = Math.floor(oneEmWidth / (strokePixelLength - strokePattern[0])); if (loop > 1) { // This pattern fits at least two times, no scaling just convert to em; for (i = 0; i < strokePattern.length; i++) { normalizedPattern[i] = strokePattern[i] / oneEmWidth; } // Since we are repeating the pattern, we don't worry about repeating the // first segment in one draw. segmentLoop = normalizedPattern.length; } else { // If the pattern doesn't fit in the legend we scale it to fit. loop = 1; for (i = 0; i < strokePattern.length; i++) { normalizedPattern[i] = strokePattern[i] / strokePixelLength; } // For the scaled patterns we do redraw the first segment. segmentLoop = normalizedPattern.length + 1; } // Now make the pattern. var dash = ""; for (j = 0; j < loop; j++) { for (i = 0; i < segmentLoop; i += 2) { // The padding is the drawn segment. paddingLeft = normalizedPattern[i % normalizedPattern.length]; if (i < strokePattern.length) { // The margin is the space segment. marginRight = normalizedPattern[(i + 1) % normalizedPattern.length]; } else { // The repeated first segment has no right margin. marginRight = 0; } dash += "<div class=\"dygraph-legend-dash\" style=\"margin-right: ".concat(marginRight, "em; padding-left: ").concat(paddingLeft, "em;\"></div>"); } } return dash; } var _default = exports["default"] = Legend; module.exports = exports.default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImV4cG9ydHMiLCJ2YWx1ZSIsInV0aWxzIiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJyZXF1aXJlIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiTGVnZW5kIiwibGVnZW5kX2Rpdl8iLCJpc19nZW5lcmF0ZWRfZGl2XyIsInByb3RvdHlwZSIsInRvU3RyaW5nIiwiYWN0aXZhdGUiLCJnIiwiZGl2IiwidXNlckxhYmVsc0RpdiIsImdldE9wdGlvbiIsIlN0cmluZyIsImRvY3VtZW50IiwiZ2V0RWxlbWVudEJ5SWQiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwiZ3JhcGhEaXYiLCJhcHBlbmRDaGlsZCIsIm9uZV9lbV93aWR0aF8iLCJzZWxlY3QiLCJkZXNlbGVjdCIsInByZWRyYXciLCJkaWREcmF3Q2hhcnQiLCJjYWxjdWxhdGVFbVdpZHRoSW5EaXYiLCJzaXplU3BhbiIsInNldEF0dHJpYnV0ZSIsIm9uZUVtV2lkdGgiLCJvZmZzZXRXaWR0aCIsInJlbW92ZUNoaWxkIiwiZXNjYXBlSFRNTCIsInN0ciIsInJlcGxhY2UiLCJ4VmFsdWUiLCJzZWxlY3RlZFgiLCJwb2ludHMiLCJzZWxlY3RlZFBvaW50cyIsInJvdyIsInNlbGVjdGVkUm93IiwibGVnZW5kTW9kZSIsImR5Z3JhcGgiLCJzdHlsZSIsImRpc3BsYXkiLCJodG1sIiwiZ2VuZXJhdGVMZWdlbmRIVE1MIiwiTm9kZSIsIm5vZGVUeXBlIiwiRE9DVU1FTlRfRlJBR01FTlRfTk9ERSIsImlubmVySFRNTCIsImFyZWEiLCJwbG90dGVyXyIsImxhYmVsc0RpdldpZHRoIiwieUF4aXNMYWJlbFdpZHRoIiwiZ2V0T3B0aW9uRm9yQXhpcyIsImhpZ2hsaWdodFNlcmllcyIsImdldEhpZ2hsaWdodFNlcmllcyIsInBvaW50IiwiZmluZCIsInAiLCJuYW1lIiwiZm9sbG93T2Zmc2V0WCIsImdldE51bWVyaWNPcHRpb24iLCJmb2xsb3dPZmZzZXRZIiwibGVmdExlZ2VuZCIsIngiLCJ3IiwidG9wTGVnZW5kIiwieSIsImgiLCJsZWZ0IiwidG9wIiwidW5kZWZpbmVkIiwiZGVzdHJveSIsInNlbF9wb2ludHMiLCJkYXRhIiwic2VyaWVzIiwibGFiZWxUb1NlcmllcyIsImxhYmVscyIsImdldExhYmVscyIsImxlbmd0aCIsImdldFByb3BlcnRpZXNGb3JTZXJpZXMiLCJzdHJva2VQYXR0ZXJuIiwic2VyaWVzRGF0YSIsImRhc2hIVE1MIiwiZ2VuZXJhdGVMZWdlbmREYXNoSFRNTCIsImNvbG9yIiwibGFiZWwiLCJsYWJlbEhUTUwiLCJpc1Zpc2libGUiLCJ2aXNpYmxlIiwicHVzaCIsInhPcHRWaWV3Iiwib3B0aW9uc1ZpZXdGb3JBeGlzXyIsInh2ZiIsInhIVE1MIiwieU9wdFZpZXdzIiwibnVtX2F4ZXMiLCJudW1BeGVzIiwic2hvd1plcm9zIiwicHQiLCJ5dmFsIiwiaXNOYU4iLCJjYW52YXN5IiwieU9wdFZpZXciLCJheGlzIiwiZm10RnVuYyIsInlIVE1MIiwiaW5kZXhPZiIsInVwZGF0ZSIsImlzSGlnaGxpZ2h0ZWQiLCJmb3JtYXR0ZXIiLCJkZWZhdWx0Rm9ybWF0dGVyIiwic2VwTGluZXMiLCJjb25jYXQiLCJjbHMiLCJqIiwicGFkZGluZ0xlZnQiLCJtYXJnaW5SaWdodCIsInN0cm9rZVBpeGVsTGVuZ3RoIiwic2VnbWVudExvb3AiLCJub3JtYWxpemVkUGF0dGVybiIsImxvb3AiLCJNYXRoIiwiZmxvb3IiLCJkYXNoIiwiX2RlZmF1bHQiLCJtb2R1bGUiLCJkZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbnMvbGVnZW5kLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDEyIERhbiBWYW5kZXJrYW0gKGRhbnZka0BnbWFpbC5jb20pXG4gKiBNSVQtbGljZW5jZWQ6IGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlUXG4gKi9cbi8qZ2xvYmFsIER5Z3JhcGg6ZmFsc2UgKi9cblxuLypcbkN1cnJlbnQgYml0cyBvZiBqYW5raW5lc3M6XG4tIFVzZXMgdHdvIHByaXZhdGUgQVBJczpcbiAgICAxLiBEeWdyYXBoLm9wdGlvbnNWaWV3Rm9yQXhpc19cbiAgICAyLiBkeWdyYXBoLnBsb3R0ZXJfLmFyZWFcbi0gUmVnaXN0ZXJzIGZvciBhIFwicHJlZHJhd1wiIGV2ZW50LCB3aGljaCBzaG91bGQgYmUgcmVuYW1lZC5cbi0gSSBjYWxsIGNhbGN1bGF0ZUVtV2lkdGhJbkRpdiBtb3JlIG9mdGVuIHRoYW4gbmVlZGVkLlxuKi9cblxuLypnbG9iYWwgRHlncmFwaDpmYWxzZSAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJy4uL2R5Z3JhcGgtdXRpbHMnO1xuXG4vKipcbiAqIENyZWF0ZXMgdGhlIGxlZ2VuZCwgd2hpY2ggYXBwZWFycyB3aGVuIHRoZSB1c2VyIGhvdmVycyBvdmVyIHRoZSBjaGFydC5cbiAqIFRoZSBsZWdlbmQgY2FuIGJlIGVpdGhlciBhIHVzZXItc3BlY2lmaWVkIG9yIGdlbmVyYXRlZCBkaXYuXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbnZhciBMZWdlbmQgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5sZWdlbmRfZGl2XyA9IG51bGw7XG4gIHRoaXMuaXNfZ2VuZXJhdGVkX2Rpdl8gPSBmYWxzZTsgIC8vIGRvIHdlIG93biB0aGlzIGRpdiwgb3Igd2FzIGl0IHVzZXItc3BlY2lmaWVkP1xufTtcblxuTGVnZW5kLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gXCJMZWdlbmQgUGx1Z2luXCI7XG59O1xuXG4vKipcbiAqIFRoaXMgaXMgY2FsbGVkIGR1cmluZyB0aGUgZHlncmFwaCBjb25zdHJ1Y3RvciwgYWZ0ZXIgb3B0aW9ucyBoYXZlIGJlZW4gc2V0XG4gKiBidXQgYmVmb3JlIHRoZSBkYXRhIGlzIGF2YWlsYWJsZS5cbiAqXG4gKiBQcm9wZXIgdGFza3MgdG8gZG8gaGVyZSBpbmNsdWRlOlxuICogLSBSZWFkaW5nIHlvdXIgb3duIG9wdGlvbnNcbiAqIC0gRE9NIG1hbmlwdWxhdGlvblxuICogLSBSZWdpc3RlcmluZyBldmVudCBsaXN0ZW5lcnNcbiAqXG4gKiBAcGFyYW0ge0R5Z3JhcGh9IGcgR3JhcGggaW5zdGFuY2UuXG4gKiBAcmV0dXJuIHtvYmplY3QuPHN0cmluZywgZnVuY3Rpb24oZXYpPn0gTWFwcGluZyBvZiBldmVudCBuYW1lcyB0byBjYWxsYmFja3MuXG4gKi9cbkxlZ2VuZC5wcm90b3R5cGUuYWN0aXZhdGUgPSBmdW5jdGlvbihnKSB7XG4gIHZhciBkaXY7XG5cbiAgdmFyIHVzZXJMYWJlbHNEaXYgPSBnLmdldE9wdGlvbignbGFiZWxzRGl2Jyk7XG4gIGlmICh1c2VyTGFiZWxzRGl2ICYmIG51bGwgIT09IHVzZXJMYWJlbHNEaXYpIHtcbiAgICBpZiAodHlwZW9mKHVzZXJMYWJlbHNEaXYpID09IFwic3RyaW5nXCIgfHwgdXNlckxhYmVsc0RpdiBpbnN0YW5jZW9mIFN0cmluZykge1xuICAgICAgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodXNlckxhYmVsc0Rpdik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpdiA9IHVzZXJMYWJlbHNEaXY7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgZGl2LmNsYXNzTmFtZSA9IFwiZHlncmFwaC1sZWdlbmRcIjtcbiAgICAvLyBUT0RPKGRhbnZrKTogY29tZSB1cCB3aXRoIGEgY2xlYW5lciB3YXkgdG8gZXhwb3NlIHRoaXMuXG4gICAgZy5ncmFwaERpdi5hcHBlbmRDaGlsZChkaXYpO1xuICAgIHRoaXMuaXNfZ2VuZXJhdGVkX2Rpdl8gPSB0cnVlO1xuICB9XG5cbiAgdGhpcy5sZWdlbmRfZGl2XyA9IGRpdjtcbiAgdGhpcy5vbmVfZW1fd2lkdGhfID0gMTA7ICAvLyBqdXN0IGEgZ3Vlc3MsIHdpbGwgYmUgdXBkYXRlZC5cblxuICByZXR1cm4ge1xuICAgIHNlbGVjdDogdGhpcy5zZWxlY3QsXG4gICAgZGVzZWxlY3Q6IHRoaXMuZGVzZWxlY3QsXG4gICAgLy8gVE9ETyhkYW52ayk6IHJldGhpbmsgdGhlIG5hbWUgXCJwcmVkcmF3XCIgYmVmb3JlIHdlIGNvbW1pdCB0byBpdCBpbiBhbnkgQVBJLlxuICAgIHByZWRyYXc6IHRoaXMucHJlZHJhdyxcbiAgICBkaWREcmF3Q2hhcnQ6IHRoaXMuZGlkRHJhd0NoYXJ0XG4gIH07XG59O1xuXG4vLyBOZWVkZWQgZm9yIGRhc2hlZCBsaW5lcy5cbnZhciBjYWxjdWxhdGVFbVdpZHRoSW5EaXYgPSBmdW5jdGlvbihkaXYpIHtcbiAgdmFyIHNpemVTcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICBzaXplU3Bhbi5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgJ21hcmdpbjogMDsgcGFkZGluZzogMCAwIDAgMWVtOyBib3JkZXI6IDA7Jyk7XG4gIGRpdi5hcHBlbmRDaGlsZChzaXplU3Bhbik7XG4gIHZhciBvbmVFbVdpZHRoPXNpemVTcGFuLm9mZnNldFdpZHRoO1xuICBkaXYucmVtb3ZlQ2hpbGQoc2l6ZVNwYW4pO1xuICByZXR1cm4gb25lRW1XaWR0aDtcbn07XG5cbnZhciBlc2NhcGVIVE1MID0gZnVuY3Rpb24oc3RyKSB7XG4gIHJldHVybiBzdHIucmVwbGFjZSgvJi9nLCBcIiZhbXA7XCIpLnJlcGxhY2UoL1wiL2csIFwiJiMzNDtcIikucmVwbGFjZSgvPC9nLCBcIiZsdDtcIikucmVwbGFjZSgvPi9nLCBcIiZndDtcIik7XG59O1xuXG5MZWdlbmQucHJvdG90eXBlLnNlbGVjdCA9IGZ1bmN0aW9uKGUpIHtcbiAgdmFyIHhWYWx1ZSA9IGUuc2VsZWN0ZWRYO1xuICB2YXIgcG9pbnRzID0gZS5zZWxlY3RlZFBvaW50cztcbiAgdmFyIHJvdyA9IGUuc2VsZWN0ZWRSb3c7XG5cbiAgdmFyIGxlZ2VuZE1vZGUgPSBlLmR5Z3JhcGguZ2V0T3B0aW9uKCdsZWdlbmQnKTtcbiAgaWYgKGxlZ2VuZE1vZGUgPT09ICduZXZlcicpIHtcbiAgICB0aGlzLmxlZ2VuZF9kaXZfLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGh0bWwgPSBMZWdlbmQuZ2VuZXJhdGVMZWdlbmRIVE1MKGUuZHlncmFwaCwgeFZhbHVlLCBwb2ludHMsIHRoaXMub25lX2VtX3dpZHRoXywgcm93KTtcbiAgaWYgKGh0bWwgaW5zdGFuY2VvZiBOb2RlICYmIGh0bWwubm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfRlJBR01FTlRfTk9ERSkge1xuICAgIHRoaXMubGVnZW5kX2Rpdl8uaW5uZXJIVE1MID0gJyc7XG4gICAgdGhpcy5sZWdlbmRfZGl2Xy5hcHBlbmRDaGlsZChodG1sKTtcbiAgfSBlbHNlXG4gICAgdGhpcy5sZWdlbmRfZGl2Xy5pbm5lckhUTUwgPSBodG1sO1xuICAvLyBtdXN0IGJlIGRvbmUgbm93IHNvIG9mZnNldFdpZHRoIGlzbuKAmXQgMOKAplxuICB0aGlzLmxlZ2VuZF9kaXZfLnN0eWxlLmRpc3BsYXkgPSAnJztcblxuICBpZiAobGVnZW5kTW9kZSA9PT0gJ2ZvbGxvdycpIHtcbiAgICAvLyBjcmVhdGUgZmxvYXRpbmcgbGVnZW5kIGRpdlxuICAgIHZhciBhcmVhID0gZS5keWdyYXBoLnBsb3R0ZXJfLmFyZWE7XG4gICAgdmFyIGxhYmVsc0RpdldpZHRoID0gdGhpcy5sZWdlbmRfZGl2Xy5vZmZzZXRXaWR0aDtcbiAgICB2YXIgeUF4aXNMYWJlbFdpZHRoID0gZS5keWdyYXBoLmdldE9wdGlvbkZvckF4aXMoJ2F4aXNMYWJlbFdpZHRoJywgJ3knKTtcbiAgICAvLyBmaW5kIHRoZSBjbG9zZXN0IGRhdGEgcG9pbnQgYnkgY2hlY2tpbmcgdGhlIGN1cnJlbnRseSBoaWdobGlnaHRlZCBzZXJpZXMsXG4gICAgLy8gb3IgZmFsbCBiYWNrIHRvIHVzaW5nIHRoZSBmaXJzdCBkYXRhIHBvaW50IGF2YWlsYWJsZVxuICAgIHZhciBoaWdobGlnaHRTZXJpZXMgPSBlLmR5Z3JhcGguZ2V0SGlnaGxpZ2h0U2VyaWVzKClcbiAgICB2YXIgcG9pbnQ7XG4gICAgaWYgKGhpZ2hsaWdodFNlcmllcykge1xuICAgICAgcG9pbnQgPSBwb2ludHMuZmluZChwID0+IHAubmFtZSA9PT0gaGlnaGxpZ2h0U2VyaWVzKTtcbiAgICAgIGlmICghcG9pbnQpXG4gICAgICAgIHBvaW50ID0gcG9pbnRzWzBdO1xuICAgIH0gZWxzZVxuICAgICAgcG9pbnQgPSBwb2ludHNbMF07XG4gICAgLy8gZGV0ZXJtaW5lIGZsb2F0aW5nIFtsZWZ0LCB0b3BdIGNvb3JkaW5hdGVzIG9mIHRoZSBsZWdlbmQgZGl2XG4gICAgLy8gd2l0aGluIHRoZSBwbG90dGVyXyBhcmVhXG4gICAgLy8gb2Zmc2V0IDUwIHB4IHRvIHRoZSByaWdodCBhbmQgZG93biBmcm9tIHRoZSBmaXJzdCBzZWxlY3Rpb24gcG9pbnRcbiAgICAvLyA1MCBweCBpcyBndWVzcyBiYXNlZCBvbiBtb3VzZSBjdXJzb3Igc2l6ZVxuICAgIGNvbnN0IGZvbGxvd09mZnNldFggPSBlLmR5Z3JhcGguZ2V0TnVtZXJpY09wdGlvbignbGVnZW5kRm9sbG93T2Zmc2V0WCcpO1xuICAgIGNvbnN0IGZvbGxvd09mZnNldFkgPSBlLmR5Z3JhcGguZ2V0TnVtZXJpY09wdGlvbignbGVnZW5kRm9sbG93T2Zmc2V0WScpO1xuICAgIHZhciBsZWZ0TGVnZW5kID0gcG9pbnQueCAqIGFyZWEudyArIGZvbGxvd09mZnNldFg7XG4gICAgdmFyIHRvcExlZ2VuZCAgPSBwb2ludC55ICogYXJlYS5oICsgZm9sbG93T2Zmc2V0WTtcblxuICAgIC8vIGlmIGxlZ2VuZCBmbG9hdHMgdG8gZW5kIG9mIHRoZSBjaGFydCBhcmVhLCBpdCBmbGlwcyB0byB0aGUgb3RoZXJcbiAgICAvLyBzaWRlIG9mIHRoZSBzZWxlY3Rpb24gcG9pbnRcbiAgICBpZiAoKGxlZnRMZWdlbmQgKyBsYWJlbHNEaXZXaWR0aCArIDEpID4gYXJlYS53KSB7XG4gICAgICBsZWZ0TGVnZW5kID0gbGVmdExlZ2VuZCAtIDIgKiBmb2xsb3dPZmZzZXRYIC0gbGFiZWxzRGl2V2lkdGggLSAoeUF4aXNMYWJlbFdpZHRoIC0gYXJlYS54KTtcbiAgICB9XG5cbiAgICB0aGlzLmxlZ2VuZF9kaXZfLnN0eWxlLmxlZnQgPSB5QXhpc0xhYmVsV2lkdGggKyBsZWZ0TGVnZW5kICsgXCJweFwiO1xuICAgIHRoaXMubGVnZW5kX2Rpdl8uc3R5bGUudG9wID0gdG9wTGVnZW5kICsgXCJweFwiO1xuICB9IGVsc2UgaWYgKGxlZ2VuZE1vZGUgPT09ICdvbm1vdXNlb3ZlcicgJiYgdGhpcy5pc19nZW5lcmF0ZWRfZGl2Xykge1xuICAgIC8vIHN5bmNocm9uaXNlIHRoaXMgd2l0aCBMZWdlbmQucHJvdG90eXBlLnByZWRyYXcgYmVsb3dcbiAgICB2YXIgYXJlYSA9IGUuZHlncmFwaC5wbG90dGVyXy5hcmVhO1xuICAgIHZhciBsYWJlbHNEaXZXaWR0aCA9IHRoaXMubGVnZW5kX2Rpdl8ub2Zmc2V0V2lkdGg7XG4gICAgdGhpcy5sZWdlbmRfZGl2Xy5zdHlsZS5sZWZ0ID0gYXJlYS54ICsgYXJlYS53IC0gbGFiZWxzRGl2V2lkdGggLSAxICsgXCJweFwiO1xuICAgIHRoaXMubGVnZW5kX2Rpdl8uc3R5bGUudG9wID0gYXJlYS55ICsgXCJweFwiO1xuICB9XG59O1xuXG5MZWdlbmQucHJvdG90eXBlLmRlc2VsZWN0ID0gZnVuY3Rpb24oZSkge1xuICB2YXIgbGVnZW5kTW9kZSA9IGUuZHlncmFwaC5nZXRPcHRpb24oJ2xlZ2VuZCcpO1xuICBpZiAobGVnZW5kTW9kZSAhPT0gJ2Fsd2F5cycpIHtcbiAgICB0aGlzLmxlZ2VuZF9kaXZfLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgfVxuXG4gIC8vIEhhdmUgdG8gZG8gdGhpcyBldmVyeSB0aW1lLCBzaW5jZSBzdHlsZXMgbWlnaHQgaGF2ZSBjaGFuZ2VkLlxuICB2YXIgb25lRW1XaWR0aCA9IGNhbGN1bGF0ZUVtV2lkdGhJbkRpdih0aGlzLmxlZ2VuZF9kaXZfKTtcbiAgdGhpcy5vbmVfZW1fd2lkdGhfID0gb25lRW1XaWR0aDtcblxuICB2YXIgaHRtbCA9IExlZ2VuZC5nZW5lcmF0ZUxlZ2VuZEhUTUwoZS5keWdyYXBoLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgb25lRW1XaWR0aCwgbnVsbCk7XG4gIGlmIChodG1sIGluc3RhbmNlb2YgTm9kZSAmJiBodG1sLm5vZGVUeXBlID09PSBOb2RlLkRPQ1VNRU5UX0ZSQUdNRU5UX05PREUpIHtcbiAgICB0aGlzLmxlZ2VuZF9kaXZfLmlubmVySFRNTCA9ICcnO1xuICAgIHRoaXMubGVnZW5kX2Rpdl8uYXBwZW5kQ2hpbGQoaHRtbCk7XG4gIH0gZWxzZVxuICAgIHRoaXMubGVnZW5kX2Rpdl8uaW5uZXJIVE1MID0gaHRtbDtcbn07XG5cbkxlZ2VuZC5wcm90b3R5cGUuZGlkRHJhd0NoYXJ0ID0gZnVuY3Rpb24oZSkge1xuICB0aGlzLmRlc2VsZWN0KGUpO1xufTtcblxuLy8gUmlnaHQgZWRnZSBzaG91bGQgYmUgZmx1c2ggd2l0aCB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgY2hhcnRpbmcgYXJlYSAod2hpY2hcbi8vIG1heSBub3QgYmUgdGhlIHNhbWUgYXMgdGhlIHJpZ2h0IGVkZ2Ugb2YgdGhlIGRpdiwgaWYgd2UgaGF2ZSB0d28geS1heGVzKS5cbi8vIFRPRE8oZGFudmspOiBpcyBhbnkgb2YgdGhpcyByZWFsbHkgbmVjZXNzYXJ5PyBDb3VsZCBqdXN0IHNldCBcInJpZ2h0XCIgaW4gXCJhY3RpdmF0ZVwiLlxuLyoqXG4gKiBQb3NpdGlvbiB0aGUgbGFiZWxzIGRpdiBzbyB0aGF0OlxuICogLSBpdHMgcmlnaHQgZWRnZSBpcyBmbHVzaCB3aXRoIHRoZSByaWdodCBlZGdlIG9mIHRoZSBjaGFydGluZyBhcmVhXG4gKiAtIGl0cyB0b3AgZWRnZSBpcyBmbHVzaCB3aXRoIHRoZSB0b3AgZWRnZSBvZiB0aGUgY2hhcnRpbmcgYXJlYVxuICogQHByaXZhdGVcbiAqL1xuTGVnZW5kLnByb3RvdHlwZS5wcmVkcmF3ID0gZnVuY3Rpb24oZSkge1xuICAvLyBEb24ndCB0b3VjaCBhIHVzZXItc3BlY2lmaWVkIGxhYmVsc0Rpdi5cbiAgaWYgKCF0aGlzLmlzX2dlbmVyYXRlZF9kaXZfKSByZXR1cm47XG5cbiAgLy8gVE9ETyhkYW52ayk6IG9ubHkgdXNlIHJlYWwgQVBJcyBmb3IgdGhpcy5cbiAgZS5keWdyYXBoLmdyYXBoRGl2LmFwcGVuZENoaWxkKHRoaXMubGVnZW5kX2Rpdl8pO1xuICAvLyBzeW5jaHJvbmlzZSB0aGlzIHdpdGggTGVnZW5kLnByb3RvdHlwZS5zZWxlY3QgYWJvdmVcbiAgdmFyIGFyZWEgPSBlLmR5Z3JhcGgucGxvdHRlcl8uYXJlYTtcbiAgdmFyIGxhYmVsc0RpdldpZHRoID0gdGhpcy5sZWdlbmRfZGl2Xy5vZmZzZXRXaWR0aDtcbiAgdGhpcy5sZWdlbmRfZGl2Xy5zdHlsZS5sZWZ0ID0gYXJlYS54ICsgYXJlYS53IC0gbGFiZWxzRGl2V2lkdGggLSAxICsgXCJweFwiO1xuICB0aGlzLmxlZ2VuZF9kaXZfLnN0eWxlLnRvcCA9IGFyZWEueSArIFwicHhcIjtcbn07XG5cbi8qKlxuICogQ2FsbGVkIHdoZW4gZHlncmFwaC5kZXN0cm95KCkgaXMgY2FsbGVkLlxuICogWW91IHNob3VsZCBudWxsIG91dCBhbnkgcmVmZXJlbmNlcyBhbmQgZGV0YWNoIGFueSBET00gZWxlbWVudHMuXG4gKi9cbkxlZ2VuZC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmxlZ2VuZF9kaXZfID0gbnVsbDtcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIEhUTUwgZm9yIHRoZSBsZWdlbmQgd2hpY2ggaXMgZGlzcGxheWVkIHdoZW4gaG92ZXJpbmcgb3ZlciB0aGVcbiAqIGNoYXJ0LiBJZiBubyBzZWxlY3RlZCBwb2ludHMgYXJlIHNwZWNpZmllZCwgYSBkZWZhdWx0IGxlZ2VuZCBpcyByZXR1cm5lZFxuICogKHRoaXMgbWF5IGp1c3QgYmUgdGhlIGVtcHR5IHN0cmluZykuXG4gKiBAcGFyYW0ge251bWJlcn0geCBUaGUgeC12YWx1ZSBvZiB0aGUgc2VsZWN0ZWQgcG9pbnRzLlxuICogQHBhcmFtIHtPYmplY3R9IHNlbF9wb2ludHMgTGlzdCBvZiBzZWxlY3RlZCBwb2ludHMgZm9yIHRoZSBnaXZlblxuICogICB4LXZhbHVlLiBTaG91bGQgaGF2ZSBwcm9wZXJ0aWVzIGxpa2UgJ25hbWUnLCAneXZhbCcgYW5kICdjYW52YXN5Jy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvbmVFbVdpZHRoIFRoZSBwaXhlbCB3aWR0aCBmb3IgMWVtIGluIHRoZSBsZWdlbmQuIE9ubHlcbiAqICAgcmVsZXZhbnQgd2hlbiBkaXNwbGF5aW5nIGEgbGVnZW5kIHdpdGggbm8gc2VsZWN0aW9uIChpLmUuIHtsZWdlbmQ6XG4gKiAgICdhbHdheXMnfSkgYW5kIHdpdGggZGFzaGVkIGxpbmVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHJvdyBUaGUgc2VsZWN0ZWQgcm93IGluZGV4LlxuICogQHByaXZhdGVcbiAqL1xuTGVnZW5kLmdlbmVyYXRlTGVnZW5kSFRNTCA9IGZ1bmN0aW9uKGcsIHgsIHNlbF9wb2ludHMsIG9uZUVtV2lkdGgsIHJvdykge1xuICAvLyBEYXRhIGFib3V0IHRoZSBzZWxlY3Rpb24gdG8gcGFzcyB0byBsZWdlbmRGb3JtYXR0ZXJcbiAgdmFyIGRhdGEgPSB7XG4gICAgZHlncmFwaDogZyxcbiAgICB4OiB4LFxuICAgIGk6IHJvdyxcbiAgICBzZXJpZXM6IFtdXG4gIH07XG5cbiAgdmFyIGxhYmVsVG9TZXJpZXMgPSB7fTtcbiAgdmFyIGxhYmVscyA9IGcuZ2V0TGFiZWxzKCk7XG4gIGlmIChsYWJlbHMpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGxhYmVscy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNlcmllcyA9IGcuZ2V0UHJvcGVydGllc0ZvclNlcmllcyhsYWJlbHNbaV0pO1xuICAgICAgdmFyIHN0cm9rZVBhdHRlcm4gPSBnLmdldE9wdGlvbignc3Ryb2tlUGF0dGVybicsIGxhYmVsc1tpXSk7XG4gICAgICB2YXIgc2VyaWVzRGF0YSA9IHtcbiAgICAgICAgZGFzaEhUTUw6IGdlbmVyYXRlTGVnZW5kRGFzaEhUTUwoc3Ryb2tlUGF0dGVybiwgc2VyaWVzLmNvbG9yLCBvbmVFbVdpZHRoKSxcbiAgICAgICAgbGFiZWw6IGxhYmVsc1tpXSxcbiAgICAgICAgbGFiZWxIVE1MOiBlc2NhcGVIVE1MKGxhYmVsc1tpXSksXG4gICAgICAgIGlzVmlzaWJsZTogc2VyaWVzLnZpc2libGUsXG4gICAgICAgIGNvbG9yOiBzZXJpZXMuY29sb3JcbiAgICAgIH07XG5cbiAgICAgIGRhdGEuc2VyaWVzLnB1c2goc2VyaWVzRGF0YSk7XG4gICAgICBsYWJlbFRvU2VyaWVzW2xhYmVsc1tpXV0gPSBzZXJpZXNEYXRhO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0eXBlb2YoeCkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgdmFyIHhPcHRWaWV3ID0gZy5vcHRpb25zVmlld0ZvckF4aXNfKCd4Jyk7XG4gICAgdmFyIHh2ZiA9IHhPcHRWaWV3KCd2YWx1ZUZvcm1hdHRlcicpO1xuICAgIGRhdGEueEhUTUwgPSB4dmYuY2FsbChnLCB4LCB4T3B0VmlldywgbGFiZWxzWzBdLCBnLCByb3csIDApO1xuXG4gICAgdmFyIHlPcHRWaWV3cyA9IFtdO1xuICAgIHZhciBudW1fYXhlcyA9IGcubnVtQXhlcygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtX2F4ZXM7IGkrKykge1xuICAgICAgLy8gVE9ETyhkYW52ayk6IHJlbW92ZSB0aGlzIHVzZSBvZiBhIHByaXZhdGUgQVBJXG4gICAgICB5T3B0Vmlld3NbaV0gPSBnLm9wdGlvbnNWaWV3Rm9yQXhpc18oJ3knICsgKGkgPyAxICsgaSA6ICcnKSk7XG4gICAgfVxuXG4gICAgdmFyIHNob3daZXJvcyA9IGcuZ2V0T3B0aW9uKCdsYWJlbHNTaG93WmVyb1ZhbHVlcycpO1xuICAgIHZhciBoaWdobGlnaHRTZXJpZXMgPSBnLmdldEhpZ2hsaWdodFNlcmllcygpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBzZWxfcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcHQgPSBzZWxfcG9pbnRzW2ldO1xuICAgICAgdmFyIHNlcmllc0RhdGEgPSBsYWJlbFRvU2VyaWVzW3B0Lm5hbWVdO1xuICAgICAgc2VyaWVzRGF0YS55ID0gcHQueXZhbDtcblxuICAgICAgaWYgKChwdC55dmFsID09PSAwICYmICFzaG93WmVyb3MpIHx8IGlzTmFOKHB0LmNhbnZhc3kpKSB7XG4gICAgICAgIHNlcmllc0RhdGEuaXNWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2VyaWVzID0gZy5nZXRQcm9wZXJ0aWVzRm9yU2VyaWVzKHB0Lm5hbWUpO1xuICAgICAgdmFyIHlPcHRWaWV3ID0geU9wdFZpZXdzW3Nlcmllcy5heGlzIC0gMV07XG4gICAgICB2YXIgZm10RnVuYyA9IHlPcHRWaWV3KCd2YWx1ZUZvcm1hdHRlcicpO1xuICAgICAgdmFyIHlIVE1MID0gZm10RnVuYy5jYWxsKGcsIHB0Lnl2YWwsIHlPcHRWaWV3LCBwdC5uYW1lLCBnLCByb3csIGxhYmVscy5pbmRleE9mKHB0Lm5hbWUpKTtcblxuICAgICAgdXRpbHMudXBkYXRlKHNlcmllc0RhdGEsIHt5SFRNTH0pO1xuXG4gICAgICBpZiAocHQubmFtZSA9PSBoaWdobGlnaHRTZXJpZXMpIHtcbiAgICAgICAgc2VyaWVzRGF0YS5pc0hpZ2hsaWdodGVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgZm9ybWF0dGVyID0gKGcuZ2V0T3B0aW9uKCdsZWdlbmRGb3JtYXR0ZXInKSB8fCBMZWdlbmQuZGVmYXVsdEZvcm1hdHRlcik7XG4gIHJldHVybiBmb3JtYXR0ZXIuY2FsbChnLCBkYXRhKTtcbn1cblxuTGVnZW5kLmRlZmF1bHRGb3JtYXR0ZXIgPSBmdW5jdGlvbihkYXRhKSB7XG4gIHZhciBnID0gZGF0YS5keWdyYXBoO1xuXG4gIC8vIFRPRE8oZGFudmspOiBkZXByZWNhdGUgdGhpcyBvcHRpb24gaW4gcGxhY2Ugb2Yge2xlZ2VuZDogJ25ldmVyJ31cbiAgLy8gWFhYIHNob3VsZCB0aGlzIGxvZ2ljIGJlIGluIHRoZSBmb3JtYXR0ZXI/XG4gIGlmIChnLmdldE9wdGlvbignc2hvd0xhYmVsc09uSGlnaGxpZ2h0JykgIT09IHRydWUpIHJldHVybiAnJztcblxuICB2YXIgc2VwTGluZXMgPSBnLmdldE9wdGlvbignbGFiZWxzU2VwYXJhdGVMaW5lcycpO1xuICB2YXIgaHRtbDtcblxuICBpZiAodHlwZW9mKGRhdGEueCkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gVE9ETzogdGhpcyBjaGVjayBpcyBkdXBsaWNhdGVkIGluIGdlbmVyYXRlTGVnZW5kSFRNTC4gUHV0IGl0IGluIG9uZSBwbGFjZS5cbiAgICBpZiAoZy5nZXRPcHRpb24oJ2xlZ2VuZCcpICE9ICdhbHdheXMnKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgaHRtbCA9ICcnO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGF0YS5zZXJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBzZXJpZXMgPSBkYXRhLnNlcmllc1tpXTtcbiAgICAgIGlmICghc2VyaWVzLmlzVmlzaWJsZSkgY29udGludWU7XG5cbiAgICAgIGlmIChodG1sICE9PSAnJykgaHRtbCArPSAoc2VwTGluZXMgPyAnPGJyIC8+JyA6ICcgJyk7XG4gICAgICBodG1sICs9IGA8c3BhbiBzdHlsZT0nZm9udC13ZWlnaHQ6IGJvbGQ7IGNvbG9yOiAke3Nlcmllcy5jb2xvcn07Jz4ke3Nlcmllcy5kYXNoSFRNTH0gJHtzZXJpZXMubGFiZWxIVE1MfTwvc3Bhbj5gO1xuICAgIH1cbiAgICByZXR1cm4gaHRtbDtcbiAgfVxuXG4gIGh0bWwgPSBkYXRhLnhIVE1MICsgJzonO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEuc2VyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHNlcmllcyA9IGRhdGEuc2VyaWVzW2ldO1xuICAgIGlmICghc2VyaWVzLnkgJiYgIXNlcmllcy55SFRNTCkgY29udGludWU7XG4gICAgaWYgKCFzZXJpZXMuaXNWaXNpYmxlKSBjb250aW51ZTtcbiAgICBpZiAoc2VwTGluZXMpIGh0bWwgKz0gJzxicj4nO1xuICAgIHZhciBjbHMgPSBzZXJpZXMuaXNIaWdobGlnaHRlZCA/ICcgY2xhc3M9XCJoaWdobGlnaHRcIicgOiAnJztcbiAgICBodG1sICs9IGA8c3BhbiR7Y2xzfT4gPGI+PHNwYW4gc3R5bGU9J2NvbG9yOiAke3Nlcmllcy5jb2xvcn07Jz4ke3Nlcmllcy5sYWJlbEhUTUx9PC9zcGFuPjwvYj46JiMxNjA7JHtzZXJpZXMueUhUTUx9PC9zcGFuPmA7XG4gIH1cbiAgcmV0dXJuIGh0bWw7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBodG1sIGZvciB0aGUgXCJkYXNoXCIgZGlzcGxheWVkIG9uIHRoZSBsZWdlbmQgd2hlbiB1c2luZyBcImxlZ2VuZDogYWx3YXlzXCIuXG4gKiBJbiBwYXJ0aWN1bGFyLCB0aGlzIHdvcmtzIGZvciBkYXNoZWQgbGluZXMgd2l0aCBhbnkgc3Ryb2tlIHBhdHRlcm4uIEl0IHdpbGxcbiAqIHRyeSB0byBzY2FsZSB0aGUgcGF0dGVybiB0byBmaXQgaW4gMWVtIHdpZHRoLiBPciBpZiBzbWFsbCBlbm91Z2ggcmVwZWF0IHRoZVxuICogcGF0dGVybiBmb3IgMWVtIHdpZHRoLlxuICpcbiAqIEBwYXJhbSBzdHJva2VQYXR0ZXJuIFRoZSBwYXR0ZXJuXG4gKiBAcGFyYW0gY29sb3IgVGhlIGNvbG9yIG9mIHRoZSBzZXJpZXMuXG4gKiBAcGFyYW0gb25lRW1XaWR0aCBUaGUgd2lkdGggaW4gcGl4ZWxzIG9mIDFlbSBpbiB0aGUgbGVnZW5kLlxuICogQHByaXZhdGVcbiAqL1xuLy8gVE9ETyhkYW52ayk6IGNhY2hlIHRoZSByZXN1bHRzIG9mIHRoaXNcbmZ1bmN0aW9uIGdlbmVyYXRlTGVnZW5kRGFzaEhUTUwoc3Ryb2tlUGF0dGVybiwgY29sb3IsIG9uZUVtV2lkdGgpIHtcbiAgLy8gRWFzeSwgY29tbW9uIGNhc2U6IGEgc29saWQgbGluZVxuICBpZiAoIXN0cm9rZVBhdHRlcm4gfHwgc3Ryb2tlUGF0dGVybi5sZW5ndGggPD0gMSkge1xuICAgIHJldHVybiBgPGRpdiBjbGFzcz1cImR5Z3JhcGgtbGVnZW5kLWxpbmVcIiBzdHlsZT1cImJvcmRlci1ib3R0b20tY29sb3I6ICR7Y29sb3J9O1wiPjwvZGl2PmA7XG4gIH1cblxuICB2YXIgaSwgaiwgcGFkZGluZ0xlZnQsIG1hcmdpblJpZ2h0O1xuICB2YXIgc3Ryb2tlUGl4ZWxMZW5ndGggPSAwLCBzZWdtZW50TG9vcCA9IDA7XG4gIHZhciBub3JtYWxpemVkUGF0dGVybiA9IFtdO1xuICB2YXIgbG9vcDtcblxuICAvLyBDb21wdXRlIHRoZSBsZW5ndGggb2YgdGhlIHBpeGVscyBpbmNsdWRpbmcgdGhlIGZpcnN0IHNlZ21lbnQgdHdpY2UsXG4gIC8vIHNpbmNlIHdlIHJlcGVhdCBpdC5cbiAgZm9yIChpID0gMDsgaSA8PSBzdHJva2VQYXR0ZXJuLmxlbmd0aDsgaSsrKSB7XG4gICAgc3Ryb2tlUGl4ZWxMZW5ndGggKz0gc3Ryb2tlUGF0dGVybltpJXN0cm9rZVBhdHRlcm4ubGVuZ3RoXTtcbiAgfVxuXG4gIC8vIFNlZSBpZiB3ZSBjYW4gbG9vcCB0aGUgcGF0dGVybiBieSBpdHNlbGYgYXQgbGVhc3QgdHdpY2UuXG4gIGxvb3AgPSBNYXRoLmZsb29yKG9uZUVtV2lkdGgvKHN0cm9rZVBpeGVsTGVuZ3RoLXN0cm9rZVBhdHRlcm5bMF0pKTtcbiAgaWYgKGxvb3AgPiAxKSB7XG4gICAgLy8gVGhpcyBwYXR0ZXJuIGZpdHMgYXQgbGVhc3QgdHdvIHRpbWVzLCBubyBzY2FsaW5nIGp1c3QgY29udmVydCB0byBlbTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgc3Ryb2tlUGF0dGVybi5sZW5ndGg7IGkrKykge1xuICAgICAgbm9ybWFsaXplZFBhdHRlcm5baV0gPSBzdHJva2VQYXR0ZXJuW2ldL29uZUVtV2lkdGg7XG4gICAgfVxuICAgIC8vIFNpbmNlIHdlIGFyZSByZXBlYXRpbmcgdGhlIHBhdHRlcm4sIHdlIGRvbid0IHdvcnJ5IGFib3V0IHJlcGVhdGluZyB0aGVcbiAgICAvLyBmaXJzdCBzZWdtZW50IGluIG9uZSBkcmF3LlxuICAgIHNlZ21lbnRMb29wID0gbm9ybWFsaXplZFBhdHRlcm4ubGVuZ3RoO1xuICB9IGVsc2Uge1xuICAgIC8vIElmIHRoZSBwYXR0ZXJuIGRvZXNuJ3QgZml0IGluIHRoZSBsZWdlbmQgd2Ugc2NhbGUgaXQgdG8gZml0LlxuICAgIGxvb3AgPSAxO1xuICAgIGZvciAoaSA9IDA7IGkgPCBzdHJva2VQYXR0ZXJuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBub3JtYWxpemVkUGF0dGVybltpXSA9IHN0cm9rZVBhdHRlcm5baV0vc3Ryb2tlUGl4ZWxMZW5ndGg7XG4gICAgfVxuICAgIC8vIEZvciB0aGUgc2NhbGVkIHBhdHRlcm5zIHdlIGRvIHJlZHJhdyB0aGUgZmlyc3Qgc2VnbWVudC5cbiAgICBzZWdtZW50TG9vcCA9IG5vcm1hbGl6ZWRQYXR0ZXJuLmxlbmd0aCsxO1xuICB9XG5cbiAgLy8gTm93IG1ha2UgdGhlIHBhdHRlcm4uXG4gIHZhciBkYXNoID0gXCJcIjtcbiAgZm9yIChqID0gMDsgaiA8IGxvb3A7IGorKykge1xuICAgIGZvciAoaSA9IDA7IGkgPCBzZWdtZW50TG9vcDsgaSs9Mikge1xuICAgICAgLy8gVGhlIHBhZGRpbmcgaXMgdGhlIGRyYXduIHNlZ21lbnQuXG4gICAgICBwYWRkaW5nTGVmdCA9IG5vcm1hbGl6ZWRQYXR0ZXJuW2klbm9ybWFsaXplZFBhdHRlcm4ubGVuZ3RoXTtcbiAgICAgIGlmIChpIDwgc3Ryb2tlUGF0dGVybi5sZW5ndGgpIHtcbiAgICAgICAgLy8gVGhlIG1hcmdpbiBpcyB0aGUgc3BhY2Ugc2VnbWVudC5cbiAgICAgICAgbWFyZ2luUmlnaHQgPSBub3JtYWxpemVkUGF0dGVyblsoaSsxKSVub3JtYWxpemVkUGF0dGVybi5sZW5ndGhdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVGhlIHJlcGVhdGVkIGZpcnN0IHNlZ21lbnQgaGFzIG5vIHJpZ2h0IG1hcmdpbi5cbiAgICAgICAgbWFyZ2luUmlnaHQgPSAwO1xuICAgICAgfVxuICAgICAgZGFzaCArPSBgPGRpdiBjbGFzcz1cImR5Z3JhcGgtbGVnZW5kLWRhc2hcIiBzdHlsZT1cIm1hcmdpbi1yaWdodDogJHttYXJnaW5SaWdodH1lbTsgcGFkZGluZy1sZWZ0OiAke3BhZGRpbmdMZWZ0fWVtO1wiPjwvZGl2PmA7XG4gICAgfVxuICB9XG4gIHJldHVybiBkYXNoO1xufVxuXG5leHBvcnQgZGVmYXVsdCBMZWdlbmQ7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsWUFBWTs7QUFBQ0EsTUFBQSxDQUFBQyxjQUFBLENBQUFDLE9BQUE7RUFBQUMsS0FBQTtBQUFBO0FBQUFELE9BQUE7QUFFYixJQUFBRSxLQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFBMEMsU0FBQUMseUJBQUFDLENBQUEsNkJBQUFDLE9BQUEsbUJBQUFDLENBQUEsT0FBQUQsT0FBQSxJQUFBRSxDQUFBLE9BQUFGLE9BQUEsWUFBQUYsd0JBQUEsWUFBQUEseUJBQUFDLENBQUEsV0FBQUEsQ0FBQSxHQUFBRyxDQUFBLEdBQUFELENBQUEsS0FBQUYsQ0FBQTtBQUFBLFNBQUFILHdCQUFBRyxDQUFBLEVBQUFFLENBQUEsU0FBQUEsQ0FBQSxJQUFBRixDQUFBLElBQUFBLENBQUEsQ0FBQUksVUFBQSxTQUFBSixDQUFBLGVBQUFBLENBQUEsdUJBQUFBLENBQUEs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