UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

462 lines (431 loc) 56.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.addCustomPaletteColor = addCustomPaletteColor; exports.addNewQuantativeColorBreakAtIndex = addNewQuantativeColorBreakAtIndex; exports.colorMaybeToHex = colorMaybeToHex; exports.colorMaybeToRGB = colorMaybeToRGB; exports.colorRangeBackwardCompatibility = colorRangeBackwardCompatibility; exports.createLinearGradient = createLinearGradient; exports.hasColorMap = hasColorMap; exports.hexToRgb = hexToRgb; exports.initializeCustomPalette = initializeCustomPalette; exports.interpolateHex = interpolateHex; exports.isHexColor = isHexColor; exports.isQuaPalette = isQuaPalette; exports.isRgbColor = isRgbColor; exports.normalizeColor = normalizeColor; exports.paletteIsColorBlindSafe = paletteIsColorBlindSafe; exports.paletteIsSteps = paletteIsSteps; exports.paletteIsType = paletteIsType; exports.removeCustomPaletteColor = removeCustomPaletteColor; exports.reverseColorRange = reverseColorRange; exports.rgbToHex = rgbToHex; exports.sortCustomPaletteColor = sortCustomPaletteColor; exports.updateColorRangeByMatchingPalette = updateColorRangeByMatchingPalette; exports.updateColorRangeBySelectedPalette = updateColorRangeBySelectedPalette; exports.updateCustomColorRangeByColorUI = updateCustomColorRangeByColorUI; exports.updateCustomPaletteColor = updateCustomPaletteColor; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _constants = require("@kepler.gl/constants"); var _commonUtils = require("@kepler.gl/common-utils"); var _d3Color = require("d3-color"); var _d3Interpolate = require("d3-interpolate"); var _utils = require("./utils"); var _console = _interopRequireDefault(require("global/console")); var _excluded = ["colors"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project /** * get r g b from hex code * * @param hex * @returns array of r g bs */ function hexToRgb(hex) { var result = isHexColor(hex); if (!result) { return [0, 0, 0]; } var r = parseInt(result[1], 16); var g = parseInt(result[2], 16); var b = parseInt(result[3], 16); return [r, g, b]; } function isHexColor(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result; } function PadNum(c) { var hex = c.toString(16); return hex.length === 1 ? "0".concat(hex) : hex; } /** * get hex from r g b * * @param rgb * @returns hex string */ function rgbToHex(_ref) { var _ref2 = (0, _slicedToArray2["default"])(_ref, 3), r = _ref2[0], g = _ref2[1], b = _ref2[2]; return "#".concat([r, g, b].map(function (n) { return PadNum(n); }).join('')).toUpperCase(); } /** * Whether color range has custom color map */ function hasColorMap(colorRange) { return Array.isArray(colorRange.colorMap) && Boolean(colorRange.colorMap.length); } /** * given a list of rgb arrays it will generate a linear gradient css rule * @param direction * @param colors * @return */ function createLinearGradient(direction, colors) { var step = parseFloat((100.0 / colors.length).toFixed(2)); var bands = colors.map(function (rgb, index) { return "rgba(".concat(rgb.join(','), ", 1) ").concat(step * index, "%, rgba(").concat(rgb.join(','), ", 1) ").concat(step * (index + 1), "%"); }); return "linear-gradient(to ".concat(direction, ", ").concat(bands.join(','), ")"); } /** * Convert color to RGB */ function colorMaybeToRGB(color) { if (isRgbColor(color)) { return color; } if (typeof color === 'string') { var rgbObj = (0, _d3Color.rgb)(color); if (Number.isFinite(rgbObj === null || rgbObj === void 0 ? void 0 : rgbObj.r) && Number.isFinite(rgbObj === null || rgbObj === void 0 ? void 0 : rgbObj.g) && Number.isFinite(rgbObj === null || rgbObj === void 0 ? void 0 : rgbObj.b)) { return [rgbObj.r, rgbObj.g, rgbObj.b]; } } return null; } /** * Whether color is rgb * @returns */ function isRgbColor(color) { return Boolean(color && Array.isArray(color) && color.length === 3 && color.every(function (n) { return Number.isFinite(n) && n <= 255 && n >= 0; })); } /** * Take color values in 0-255 range and map to [0, 1] */ function normalizeColor(color) { return color.map(function (component) { return component / 255.0; }); } /** * Convert color to Hex */ function colorMaybeToHex(color) { var rgbColor = colorMaybeToRGB(color); if (rgbColor) return rgbToHex(rgbColor); return '#000000'; } /** * Convert color to Hex */ function interpolateHex(hex1, hex2) { return (0, _d3Color.rgb)((0, _d3Interpolate.interpolate)(hex1, hex2)(0.5)).hex().toUpperCase(); } function addNewCategoricalStepAtIndex(colorMap, index, newColor) { if (!Array.isArray(colorMap) || !colorMap.length) { return colorMap; } var newColorMap = colorMap.map(function (_ref3) { var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2), val = _ref4[0], c = _ref4[1]; return [Array.isArray(val) ? (0, _toConsumableArray2["default"])(val) : val, c]; }); newColorMap = (0, _utils.arrayInsert)(newColorMap, index + 1, [null, newColor]); return newColorMap; } function addNewQuantativeColorBreakAtIndex(colorMap, index, newColors) { if (!Array.isArray(colorMap) || !colorMap.length) { return colorMap; } if (colorMap.length < 2) { // less then 2, add 1 at end // however shouldn't allow delete when there are 2 return newColors.map(function (c, i) { return i === 0 ? colorMap[i] : [null, c]; }); } // breaks should be 1 less than colors var breaks = colorMap.map(function (cm) { return cm[0]; }).slice(0, colorMap.length - 1); // insert new break var newValue = index >= breaks.length - 1 ? breaks[breaks.length - 1] + (breaks.length > 1 ? breaks[breaks.length - 1] - breaks[breaks.length - 2] : 0) : (breaks[index] + breaks[index + 1]) / 2; var newBreaks = (0, _utils.arrayInsert)(breaks, index + 1, newValue); // asign breaks to color return newColors.map(function (c, i) { return i === newColors.length - 1 ? [null, c] : [newBreaks[i] === undefined ? null : newBreaks[i], c]; }); } /** * Add a new color to custom palette */ function addCustomPaletteColor(customPalette, index) { var colors = customPalette.colors, colorMap = customPalette.colorMap; var update = {}; var newColor = index === colors.length - 1 ? colors[index] : interpolateHex(colors[index], colors[index + 1]); update.colors = (0, _utils.arrayInsert)(colors, index + 1, newColor); // add color to colorMap if (colorMap) { update.colorMap = customPalette.type === 'customOrdinal' ? addNewCategoricalStepAtIndex(colorMap, index, newColor) : addNewQuantativeColorBreakAtIndex(colorMap, index, update.colors); } return _objectSpread(_objectSpread({}, customPalette), update); } function replaceColorsInColorRange(colorRange, newColors) { var oldColors = colorRange.colors; var updated = _objectSpread(_objectSpread({}, colorRange), {}, { colors: newColors }); // update color map // keep value, replace color if (Array.isArray(updated.colorMap)) { updated.colorMap = updated.colorMap.map(function (cm, i) { return [cm[0], newColors[i]]; }); } // update colorlegends // keep value, replace color if (updated.colorLegends) { updated.colorLegends = Object.keys(updated.colorLegends).reduce(function (accu, key) { var colorIdx = oldColors.findIndex(function (c) { return c === key; }); var newColor = newColors[colorIdx]; return newColor ? _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, newColor, updated.colorLegends[key])) : accu; }, {}); } return updated; } /** * Sort custom palette */ function sortCustomPaletteColor(customPalette, oldIndex, newIndex) { var colors = customPalette.colors; var newColors = (0, _commonUtils.arrayMove)(colors, oldIndex, newIndex); var update = replaceColorsInColorRange(customPalette, newColors); // @ts-ignore return _objectSpread(_objectSpread({}, customPalette), update); } /** * remove a color in custom palette at index */ function removeCustomPaletteColor(customPalette, index) { var colors = customPalette.colors, colorMap = customPalette.colorMap, colorLegends = customPalette.colorLegends; var oldValue = colors[index]; var update = {}; update.colors = (0, _toConsumableArray2["default"])(colors); if (update.colors.length > 1) { update.colors.splice(index, 1); } // update color map if (Array.isArray(colorMap)) { // find colorMap index var colorMapIndex = colorMap.findIndex(function (cm) { return cm[1] === oldValue; }); if (colorMapIndex >= 0) { update.colorMap = (0, _toConsumableArray2["default"])(colorMap); update.colorMap.splice(colorMapIndex, 1); } } // update color legend if (colorLegends !== null && colorLegends !== void 0 && colorLegends[oldValue]) { update.colorLegends = _objectSpread({}, colorLegends); delete update.colorLegends[oldValue]; } return _objectSpread(_objectSpread({}, customPalette), update); } /** * Update a color in custom palette at index */ function updateCustomPaletteColor(customPalette, index, newValue) { var colors = customPalette.colors; var hex = newValue.toUpperCase(); var newColors = (0, _toConsumableArray2["default"])(colors); newColors[index] = hex; var update = replaceColorsInColorRange(customPalette, newColors); // @ts-ignore return _objectSpread(_objectSpread({}, customPalette), update); } /** * Get a reversed colorRange */ function reverseColorRange(reversed, colorRange) { var newColors = colorRange === null || colorRange === void 0 ? void 0 : colorRange.colors.slice().reverse(); var updated = replaceColorsInColorRange(colorRange, newColors); updated.reversed = reversed; return updated; } /** * Whether palette matches current ColorBlindSafe config */ function paletteIsColorBlindSafe(palette, colorBlindSafe) { return !colorBlindSafe || colorBlindSafe && palette.colorBlindSafe; } /** * Whether palette matches current steps config */ function isQuaPalette(palette) { return palette.type === _constants.PALETTE_TYPES.QUA; } /** * Whether palette matches current steps config */ function paletteIsSteps(palette, steps) { return !isQuaPalette(palette) || palette.maxStep >= steps; } /** * Whether palette matches current type config */ function paletteIsType(palette, type) { return type === 'all' || type === palette.type; } /** * Find best match palette based on config, update color range by it */ function updateColorRangeByMatchingPalette(currentColorRange, config) { var steps = config.steps, colorBlindSafe = config.colorBlindSafe, type = config.type; var matchingPalette = _constants.KEPLER_COLOR_PALETTES.filter(function (palette) { return ( // palette match type paletteIsType(palette, type) && // palette has same step paletteIsSteps(palette, steps) && // palette is colorBlindSafe paletteIsColorBlindSafe(palette, colorBlindSafe) ); }); var bestMatch = matchingPalette.length ? matchingPalette.find(function (p) { return p.name === currentColorRange.name; }) || matchingPalette[0] : null; if (bestMatch) { return updateColorRangeBySelectedPalette(currentColorRange, bestMatch, config); } // we do nothing _console["default"].warn("we cant find any preset palette matches requirments: steps=".concat(steps, " && colorBlindSafe=").concat(colorBlindSafe)); return currentColorRange; } /** * Update custom palette when reverse the colors in custom palette, since changing 'steps', * 'colorBindSafe', 'type' should fall back to predefined palette. */ function updateCustomColorRangeByColorUI(oldColorRange, colorConfig) { var reversed = colorConfig.reversed; var colors = oldColorRange.colors; // for custom palette, one can only 'reverse' the colors in custom palette. colors.reverse(); var colorRange = _objectSpread(_objectSpread(_objectSpread({ name: oldColorRange.name, type: oldColorRange.type, category: oldColorRange.category, colors: colors }, reversed ? { reversed: reversed } : {}), oldColorRange.colorMap ? { colorMap: oldColorRange.colorMap } : {}), oldColorRange.colorLegends ? { colorLegends: oldColorRange.colorLegends } : {}); return replaceColorsInColorRange(colorRange, colorRange.colors); } /** * Update color range after selecting a palette from color range selectoer * Copy over colorMap and colorLegends */ function updateColorRangeBySelectedPalette(oldColorRange, colorPalette, colorConfig) { var _colorPaletteToColorR = (0, _constants.colorPaletteToColorRange)(colorPalette, colorConfig), newColors = _colorPaletteToColorR.colors, newColorRange = (0, _objectWithoutProperties2["default"])(_colorPaletteToColorR, _excluded); var colorRange = _objectSpread(_objectSpread(_objectSpread({ colors: oldColorRange.colors }, newColorRange), oldColorRange.colorMap ? { colorMap: oldColorRange.colorMap } : {}), oldColorRange.colorLegends ? { colorLegends: oldColorRange.colorLegends } : {}); return replaceColorsInColorRange(colorRange, newColors); } var UberNameRegex = new RegExp(/^([A-Za-z ])+/g); var ColorBrewerRegex = new RegExp(/^ColorBrewer ([A-Za-z1-9])+/g); /** * convert saved colorRange to colorPalette objevt type/name/category/isColorBlind */ function colorRangeBackwardCompatibility(colorRange) { if (!colorRange || colorRange.type === 'custom' || colorRange.colorMap) { // don't do anything to custom color palette, or palette with custom breaks return colorRange; } var trimName; if (colorRange.category === 'Uber') { var _colorRange$name; var matchName = ((_colorRange$name = colorRange.name) !== null && _colorRange$name !== void 0 ? _colorRange$name : '').match(UberNameRegex); trimName = matchName ? matchName[0].trim() : null; // match Uber Viz Qualitative 1.4 -> Uber Viz Qualitative } else if (colorRange.category === 'ColorBrewer') { var _colorRange$name2; var _matchName = ((_colorRange$name2 = colorRange.name) !== null && _colorRange$name2 !== void 0 ? _colorRange$name2 : '').match(ColorBrewerRegex); trimName = _matchName ? _matchName[0].replace('ColorBrewer ', '').trim() : null; } if (trimName) { var matchingPalette = _constants.KEPLER_COLOR_PALETTES.find(function (p) { return p.name === trimName; }); if (matchingPalette) { return _objectSpread(_objectSpread({}, colorRange), {}, { name: trimName, type: matchingPalette === null || matchingPalette === void 0 ? void 0 : matchingPalette.type, category: matchingPalette.category }); } } return colorRange; } /** * Initialize custom palette from current standard color range object */ function initializeCustomPalette(colorRange, colorMap) { // TODO: check on `isReversed` key, whether we can remove it here var customPalette = _objectSpread(_objectSpread({}, colorRange), {}, { name: _constants.DEFAULT_CUSTOM_PALETTE.name, type: _constants.DEFAULT_CUSTOM_PALETTE.type, category: _constants.DEFAULT_CUSTOM_PALETTE.category }, colorMap ? { colorMap: colorMap } : {}); // only customPalette.colors are needed for custom palette editor with custom ordinal scale if (!colorMap && colorRange.type === _constants.SCALE_TYPES.customOrdinal) { delete customPalette.colorMap; } return customPalette; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29uc3RhbnRzIiwicmVxdWlyZSIsIl9jb21tb25VdGlscyIsIl9kM0NvbG9yIiwiX2QzSW50ZXJwb2xhdGUiLCJfdXRpbHMiLCJfY29uc29sZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfZXhjbHVkZWQiLCJvd25LZXlzIiwiZSIsInIiLCJ0IiwiT2JqZWN0Iiwia2V5cyIsImdldE93blByb3BlcnR5U3ltYm9scyIsIm8iLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImxlbmd0aCIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsImhleFRvUmdiIiwiaGV4IiwicmVzdWx0IiwiaXNIZXhDb2xvciIsInBhcnNlSW50IiwiZyIsImIiLCJleGVjIiwiUGFkTnVtIiwiYyIsInRvU3RyaW5nIiwiY29uY2F0IiwicmdiVG9IZXgiLCJfcmVmIiwiX3JlZjIiLCJfc2xpY2VkVG9BcnJheTIiLCJtYXAiLCJuIiwiam9pbiIsInRvVXBwZXJDYXNlIiwiaGFzQ29sb3JNYXAiLCJjb2xvclJhbmdlIiwiQXJyYXkiLCJpc0FycmF5IiwiY29sb3JNYXAiLCJCb29sZWFuIiwiY3JlYXRlTGluZWFyR3JhZGllbnQiLCJkaXJlY3Rpb24iLCJjb2xvcnMiLCJzdGVwIiwicGFyc2VGbG9hdCIsInRvRml4ZWQiLCJiYW5kcyIsInJnYiIsImluZGV4IiwiY29sb3JNYXliZVRvUkdCIiwiY29sb3IiLCJpc1JnYkNvbG9yIiwicmdiT2JqIiwiZDNSZ2IiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsImV2ZXJ5Iiwibm9ybWFsaXplQ29sb3IiLCJjb21wb25lbnQiLCJjb2xvck1heWJlVG9IZXgiLCJyZ2JDb2xvciIsImludGVycG9sYXRlSGV4IiwiaGV4MSIsImhleDIiLCJpbnRlcnBvbGF0ZSIsImFkZE5ld0NhdGVnb3JpY2FsU3RlcEF0SW5kZXgiLCJuZXdDb2xvciIsIm5ld0NvbG9yTWFwIiwiX3JlZjMiLCJfcmVmNCIsInZhbCIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJhcnJheUluc2VydCIsImFkZE5ld1F1YW50YXRpdmVDb2xvckJyZWFrQXRJbmRleCIsIm5ld0NvbG9ycyIsImkiLCJicmVha3MiLCJjbSIsInNsaWNlIiwibmV3VmFsdWUiLCJuZXdCcmVha3MiLCJ1bmRlZmluZWQiLCJhZGRDdXN0b21QYWxldHRlQ29sb3IiLCJjdXN0b21QYWxldHRlIiwidXBkYXRlIiwidHlwZSIsInJlcGxhY2VDb2xvcnNJbkNvbG9yUmFuZ2UiLCJvbGRDb2xvcnMiLCJ1cGRhdGVkIiwiY29sb3JMZWdlbmRzIiwicmVkdWNlIiwiYWNjdSIsImtleSIsImNvbG9ySWR4IiwiZmluZEluZGV4Iiwic29ydEN1c3RvbVBhbGV0dGVDb2xvciIsIm9sZEluZGV4IiwibmV3SW5kZXgiLCJhcnJheU1vdmUiLCJyZW1vdmVDdXN0b21QYWxldHRlQ29sb3IiLCJvbGRWYWx1ZSIsInNwbGljZSIsImNvbG9yTWFwSW5kZXgiLCJ1cGRhdGVDdXN0b21QYWxldHRlQ29sb3IiLCJyZXZlcnNlQ29sb3JSYW5nZSIsInJldmVyc2VkIiwicmV2ZXJzZSIsInBhbGV0dGVJc0NvbG9yQmxpbmRTYWZlIiwicGFsZXR0ZSIsImNvbG9yQmxpbmRTYWZlIiwiaXNRdWFQYWxldHRlIiwiUEFMRVRURV9UWVBFUyIsIlFVQSIsInBhbGV0dGVJc1N0ZXBzIiwic3RlcHMiLCJtYXhTdGVwIiwicGFsZXR0ZUlzVHlwZSIsInVwZGF0ZUNvbG9yUmFuZ2VCeU1hdGNoaW5nUGFsZXR0ZSIsImN1cnJlbnRDb2xvclJhbmdlIiwiY29uZmlnIiwibWF0Y2hpbmdQYWxldHRlIiwiS0VQTEVSX0NPTE9SX1BBTEVUVEVTIiwiYmVzdE1hdGNoIiwiZmluZCIsInAiLCJuYW1lIiwidXBkYXRlQ29sb3JSYW5nZUJ5U2VsZWN0ZWRQYWxldHRlIiwiQ29uc29sZSIsIndhcm4iLCJ1cGRhdGVDdXN0b21Db2xvclJhbmdlQnlDb2xvclVJIiwib2xkQ29sb3JSYW5nZSIsImNvbG9yQ29uZmlnIiwiY2F0ZWdvcnkiLCJjb2xvclBhbGV0dGUiLCJfY29sb3JQYWxldHRlVG9Db2xvclIiLCJjb2xvclBhbGV0dGVUb0NvbG9yUmFuZ2UiLCJuZXdDb2xvclJhbmdlIiwiX29iamVjdFdpdGhvdXRQcm9wZXJ0aWVzMiIsIlViZXJOYW1lUmVnZXgiLCJSZWdFeHAiLCJDb2xvckJyZXdlclJlZ2V4IiwiY29sb3JSYW5nZUJhY2t3YXJkQ29tcGF0aWJpbGl0eSIsInRyaW1OYW1lIiwiX2NvbG9yUmFuZ2UkbmFtZSIsIm1hdGNoTmFtZSIsIm1hdGNoIiwidHJpbSIsIl9jb2xvclJhbmdlJG5hbWUyIiwicmVwbGFjZSIsImluaXRpYWxpemVDdXN0b21QYWxldHRlIiwiREVGQVVMVF9DVVNUT01fUEFMRVRURSIsIlNDQUxFX1RZUEVTIiwiY3VzdG9tT3JkaW5hbCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9jb2xvci11dGlscy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge1xuICBDYXRlZ29yaWNhbFBhbGV0dGUsXG4gIENvbG9yUGFsZXR0ZSxcbiAgREVGQVVMVF9DVVNUT01fUEFMRVRURSxcbiAgY29sb3JQYWxldHRlVG9Db2xvclJhbmdlXG59IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcbmltcG9ydCB7YXJyYXlNb3ZlfSBmcm9tICdAa2VwbGVyLmdsL2NvbW1vbi11dGlscyc7XG5pbXBvcnQge1xuICBDb2xvck1hcCxcbiAgQ29sb3JSYW5nZSxcbiAgQ29sb3JSYW5nZUNvbmZpZyxcbiAgSGV4Q29sb3IsXG4gIFJHQkFDb2xvcixcbiAgUkdCQ29sb3Jcbn0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge3JnYiBhcyBkM1JnYn0gZnJvbSAnZDMtY29sb3InO1xuaW1wb3J0IHtpbnRlcnBvbGF0ZX0gZnJvbSAnZDMtaW50ZXJwb2xhdGUnO1xuaW1wb3J0IHthcnJheUluc2VydH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgQ29uc29sZSBmcm9tICdnbG9iYWwvY29uc29sZSc7XG5pbXBvcnQge0tFUExFUl9DT0xPUl9QQUxFVFRFUywgUEFMRVRURV9UWVBFUywgU0NBTEVfVFlQRVN9IGZyb20gJ0BrZXBsZXIuZ2wvY29uc3RhbnRzJztcblxuLyoqXG4gKiBnZXQgciBnIGIgZnJvbSBoZXggY29kZVxuICpcbiAqIEBwYXJhbSBoZXhcbiAqIEByZXR1cm5zIGFycmF5IG9mIHIgZyBic1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGV4VG9SZ2IoaGV4OiBzdHJpbmcpOiBSR0JDb2xvciB7XG4gIGNvbnN0IHJlc3VsdCA9IGlzSGV4Q29sb3IoaGV4KTtcblxuICBpZiAoIXJlc3VsdCkge1xuICAgIHJldHVybiBbMCwgMCwgMF07XG4gIH1cblxuICBjb25zdCByID0gcGFyc2VJbnQocmVzdWx0WzFdLCAxNik7XG4gIGNvbnN0IGcgPSBwYXJzZUludChyZXN1bHRbMl0sIDE2KTtcbiAgY29uc3QgYiA9IHBhcnNlSW50KHJlc3VsdFszXSwgMTYpO1xuXG4gIHJldHVybiBbciwgZywgYl07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0hleENvbG9yKGhleDogc3RyaW5nKTogUmVnRXhwRXhlY0FycmF5IHwgbnVsbCB7XG4gIGNvbnN0IHJlc3VsdCA9IC9eIz8oW2EtZlxcZF17Mn0pKFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkkL2kuZXhlYyhoZXgpO1xuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIFBhZE51bShjKSB7XG4gIGNvbnN0IGhleCA9IGMudG9TdHJpbmcoMTYpO1xuICByZXR1cm4gaGV4Lmxlbmd0aCA9PT0gMSA/IGAwJHtoZXh9YCA6IGhleDtcbn1cblxuLyoqXG4gKiBnZXQgaGV4IGZyb20gciBnIGJcbiAqXG4gKiBAcGFyYW0gcmdiXG4gKiBAcmV0dXJucyBoZXggc3RyaW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZ2JUb0hleChbciwgZywgYl06IFJHQkNvbG9yIHwgUkdCQUNvbG9yKTogSGV4Q29sb3Ige1xuICByZXR1cm4gYCMke1tyLCBnLCBiXS5tYXAobiA9PiBQYWROdW0obikpLmpvaW4oJycpfWAudG9VcHBlckNhc2UoKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGNvbG9yIHJhbmdlIGhhcyBjdXN0b20gY29sb3IgbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNDb2xvck1hcChjb2xvclJhbmdlOiBDb2xvclJhbmdlKTogYm9vbGVhbiB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGNvbG9yUmFuZ2UuY29sb3JNYXApICYmIEJvb2xlYW4oY29sb3JSYW5nZS5jb2xvck1hcC5sZW5ndGgpO1xufVxuXG4vKipcbiAqIGdpdmVuIGEgbGlzdCBvZiByZ2IgYXJyYXlzIGl0IHdpbGwgZ2VuZXJhdGUgYSBsaW5lYXIgZ3JhZGllbnQgY3NzIHJ1bGVcbiAqIEBwYXJhbSBkaXJlY3Rpb25cbiAqIEBwYXJhbSBjb2xvcnNcbiAqIEByZXR1cm5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUxpbmVhckdyYWRpZW50KGRpcmVjdGlvbjogc3RyaW5nLCBjb2xvcnM6IFJHQkNvbG9yW10pOiBzdHJpbmcge1xuICBjb25zdCBzdGVwID0gcGFyc2VGbG9hdCgoMTAwLjAgLyBjb2xvcnMubGVuZ3RoKS50b0ZpeGVkKDIpKTtcbiAgY29uc3QgYmFuZHMgPSBjb2xvcnMubWFwKChyZ2IsIGluZGV4KSA9PiB7XG4gICAgcmV0dXJuIGByZ2JhKCR7cmdiLmpvaW4oJywnKX0sIDEpICR7c3RlcCAqIGluZGV4fSUsIHJnYmEoJHtyZ2Iuam9pbignLCcpfSwgMSkgJHtcbiAgICAgIHN0ZXAgKiAoaW5kZXggKyAxKVxuICAgIH0lYDtcbiAgfSk7XG5cbiAgcmV0dXJuIGBsaW5lYXItZ3JhZGllbnQodG8gJHtkaXJlY3Rpb259LCAke2JhbmRzLmpvaW4oJywnKX0pYDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGNvbG9yIHRvIFJHQlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb3JNYXliZVRvUkdCKGNvbG9yOiB1bmtub3duKTogUkdCQ29sb3IgfCBudWxsIHtcbiAgaWYgKGlzUmdiQ29sb3IoY29sb3IpKSB7XG4gICAgcmV0dXJuIGNvbG9yIGFzIFJHQkNvbG9yO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjb2xvciA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCByZ2JPYmogPSBkM1JnYihjb2xvcik7XG4gICAgaWYgKE51bWJlci5pc0Zpbml0ZShyZ2JPYmo/LnIpICYmIE51bWJlci5pc0Zpbml0ZShyZ2JPYmo/LmcpICYmIE51bWJlci5pc0Zpbml0ZShyZ2JPYmo/LmIpKSB7XG4gICAgICByZXR1cm4gW3JnYk9iai5yLCByZ2JPYmouZywgcmdiT2JqLmJdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgY29sb3IgaXMgcmdiXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZ2JDb2xvcihjb2xvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gQm9vbGVhbihcbiAgICBjb2xvciAmJlxuICAgICAgQXJyYXkuaXNBcnJheShjb2xvcikgJiZcbiAgICAgIGNvbG9yLmxlbmd0aCA9PT0gMyAmJlxuICAgICAgY29sb3IuZXZlcnkobiA9PiBOdW1iZXIuaXNGaW5pdGUobikgJiYgbiA8PSAyNTUgJiYgbiA+PSAwKVxuICApO1xufVxuXG4vKipcbiAqIFRha2UgY29sb3IgdmFsdWVzIGluIDAtMjU1IHJhbmdlIGFuZCBtYXAgdG8gWzAsIDFdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVDb2xvcihjb2xvcjogbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gIHJldHVybiBjb2xvci5tYXAoY29tcG9uZW50ID0+IGNvbXBvbmVudCAvIDI1NS4wKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGNvbG9yIHRvIEhleFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb3JNYXliZVRvSGV4KGNvbG9yOiB1bmtub3duKTogSGV4Q29sb3Ige1xuICBjb25zdCByZ2JDb2xvciA9IGNvbG9yTWF5YmVUb1JHQihjb2xvcik7XG4gIGlmIChyZ2JDb2xvcikgcmV0dXJuIHJnYlRvSGV4KHJnYkNvbG9yKTtcbiAgcmV0dXJuICcjMDAwMDAwJztcbn1cblxuLyoqXG4gKiBDb252ZXJ0IGNvbG9yIHRvIEhleFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnBvbGF0ZUhleChoZXgxOiBIZXhDb2xvciwgaGV4MjogSGV4Q29sb3IpOiBIZXhDb2xvciB7XG4gIHJldHVybiBkM1JnYihpbnRlcnBvbGF0ZShoZXgxLCBoZXgyKSgwLjUpKS5oZXgoKS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhZGROZXdDYXRlZ29yaWNhbFN0ZXBBdEluZGV4KGNvbG9yTWFwLCBpbmRleCwgbmV3Q29sb3IpIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KGNvbG9yTWFwKSB8fCAhY29sb3JNYXAubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGNvbG9yTWFwO1xuICB9XG5cbiAgbGV0IG5ld0NvbG9yTWFwID0gY29sb3JNYXAubWFwKChbdmFsLCBjXSkgPT4gW0FycmF5LmlzQXJyYXkodmFsKSA/IFsuLi52YWxdIDogdmFsLCBjXSk7XG4gIG5ld0NvbG9yTWFwID0gYXJyYXlJbnNlcnQobmV3Q29sb3JNYXAsIGluZGV4ICsgMSwgW251bGwsIG5ld0NvbG9yXSk7XG5cbiAgcmV0dXJuIG5ld0NvbG9yTWFwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkTmV3UXVhbnRhdGl2ZUNvbG9yQnJlYWtBdEluZGV4KGNvbG9yTWFwLCBpbmRleCwgbmV3Q29sb3JzKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShjb2xvck1hcCkgfHwgIWNvbG9yTWFwLmxlbmd0aCkge1xuICAgIHJldHVybiBjb2xvck1hcDtcbiAgfVxuXG4gIGlmIChjb2xvck1hcC5sZW5ndGggPCAyKSB7XG4gICAgLy8gbGVzcyB0aGVuIDIsIGFkZCAxIGF0IGVuZFxuICAgIC8vIGhvd2V2ZXIgc2hvdWxkbid0IGFsbG93IGRlbGV0ZSB3aGVuIHRoZXJlIGFyZSAyXG4gICAgcmV0dXJuIG5ld0NvbG9ycy5tYXAoKGMsIGkpID0+IChpID09PSAwID8gY29sb3JNYXBbaV0gOiBbbnVsbCwgY10pKTtcbiAgfVxuXG4gIC8vIGJyZWFrcyBzaG91bGQgYmUgMSBsZXNzIHRoYW4gY29sb3JzXG4gIGNvbnN0IGJyZWFrcyA9IGNvbG9yTWFwLm1hcChjbSA9PiBjbVswXSkuc2xpY2UoMCwgY29sb3JNYXAubGVuZ3RoIC0gMSk7XG5cbiAgLy8gaW5zZXJ0IG5ldyBicmVha1xuICBjb25zdCBuZXdWYWx1ZSA9XG4gICAgaW5kZXggPj0gYnJlYWtzLmxlbmd0aCAtIDFcbiAgICAgID8gYnJlYWtzW2JyZWFrcy5sZW5ndGggLSAxXSArXG4gICAgICAgIChicmVha3MubGVuZ3RoID4gMSA/IGJyZWFrc1ticmVha3MubGVuZ3RoIC0gMV0gLSBicmVha3NbYnJlYWtzLmxlbmd0aCAtIDJdIDogMClcbiAgICAgIDogKGJyZWFrc1tpbmRleF0gKyBicmVha3NbaW5kZXggKyAxXSkgLyAyO1xuXG4gIGNvbnN0IG5ld0JyZWFrcyA9IGFycmF5SW5zZXJ0KGJyZWFrcywgaW5kZXggKyAxLCBuZXdWYWx1ZSk7XG5cbiAgLy8gYXNpZ24gYnJlYWtzIHRvIGNvbG9yXG4gIHJldHVybiBuZXdDb2xvcnMubWFwKChjLCBpKSA9PlxuICAgIGkgPT09IG5ld0NvbG9ycy5sZW5ndGggLSAxID8gW251bGwsIGNdIDogW25ld0JyZWFrc1tpXSA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IG5ld0JyZWFrc1tpXSwgY11cbiAgKTtcbn1cblxuLyoqXG4gKiBBZGQgYSBuZXcgY29sb3IgdG8gY3VzdG9tIHBhbGV0dGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZEN1c3RvbVBhbGV0dGVDb2xvcihjdXN0b21QYWxldHRlOiBDb2xvclJhbmdlLCBpbmRleDogbnVtYmVyKTogQ29sb3JSYW5nZSB7XG4gIGNvbnN0IHtjb2xvcnMsIGNvbG9yTWFwfSA9IGN1c3RvbVBhbGV0dGU7XG4gIGNvbnN0IHVwZGF0ZTogUGFydGlhbDxDb2xvclJhbmdlPiA9IHt9O1xuXG4gIGNvbnN0IG5ld0NvbG9yID1cbiAgICBpbmRleCA9PT0gY29sb3JzLmxlbmd0aCAtIDEgPyBjb2xvcnNbaW5kZXhdIDogaW50ZXJwb2xhdGVIZXgoY29sb3JzW2luZGV4XSwgY29sb3JzW2luZGV4ICsgMV0pO1xuXG4gIHVwZGF0ZS5jb2xvcnMgPSBhcnJheUluc2VydChjb2xvcnMsIGluZGV4ICsgMSwgbmV3Q29sb3IpO1xuXG4gIC8vIGFkZCBjb2xvciB0byBjb2xvck1hcFxuICBpZiAoY29sb3JNYXApIHtcbiAgICB1cGRhdGUuY29sb3JNYXAgPVxuICAgICAgY3VzdG9tUGFsZXR0ZS50eXBlID09PSAnY3VzdG9tT3JkaW5hbCdcbiAgICAgICAgPyBhZGROZXdDYXRlZ29yaWNhbFN0ZXBBdEluZGV4KGNvbG9yTWFwLCBpbmRleCwgbmV3Q29sb3IpXG4gICAgICAgIDogYWRkTmV3UXVhbnRhdGl2ZUNvbG9yQnJlYWtBdEluZGV4KGNvbG9yTWFwLCBpbmRleCwgdXBkYXRlLmNvbG9ycyk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLmN1c3RvbVBhbGV0dGUsXG4gICAgLi4udXBkYXRlXG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlcGxhY2VDb2xvcnNJbkNvbG9yUmFuZ2UoY29sb3JSYW5nZSwgbmV3Q29sb3JzKSB7XG4gIGNvbnN0IG9sZENvbG9ycyA9IGNvbG9yUmFuZ2UuY29sb3JzO1xuICBjb25zdCB1cGRhdGVkID0ge1xuICAgIC4uLmNvbG9yUmFuZ2UsXG4gICAgY29sb3JzOiBuZXdDb2xvcnNcbiAgfTtcblxuICAvLyB1cGRhdGUgY29sb3IgbWFwXG4gIC8vIGtlZXAgdmFsdWUsIHJlcGxhY2UgY29sb3JcbiAgaWYgKEFycmF5LmlzQXJyYXkodXBkYXRlZC5jb2xvck1hcCkpIHtcbiAgICB1cGRhdGVkLmNvbG9yTWFwID0gdXBkYXRlZC5jb2xvck1hcC5tYXAoKGNtLCBpKSA9PiBbY21bMF0sIG5ld0NvbG9yc1tpXV0pO1xuICB9XG4gIC8vIHVwZGF0ZSBjb2xvcmxlZ2VuZHNcbiAgLy8ga2VlcCB2YWx1ZSwgcmVwbGFjZSBjb2xvclxuICBpZiAodXBkYXRlZC5jb2xvckxlZ2VuZHMpIHtcbiAgICB1cGRhdGVkLmNvbG9yTGVnZW5kcyA9IE9iamVjdC5rZXlzKHVwZGF0ZWQuY29sb3JMZWdlbmRzKS5yZWR1Y2UoKGFjY3UsIGtleSkgPT4ge1xuICAgICAgY29uc3QgY29sb3JJZHggPSBvbGRDb2xvcnMuZmluZEluZGV4KGMgPT4gYyA9PT0ga2V5KTtcbiAgICAgIGNvbnN0IG5ld0NvbG9yID0gbmV3Q29sb3JzW2NvbG9ySWR4XTtcblxuICAgICAgcmV0dXJuIG5ld0NvbG9yXG4gICAgICAgID8ge1xuICAgICAgICAgICAgLi4uYWNjdSxcbiAgICAgICAgICAgIFtuZXdDb2xvcl06IHVwZGF0ZWQuY29sb3JMZWdlbmRzW2tleV1cbiAgICAgICAgICB9XG4gICAgICAgIDogYWNjdTtcbiAgICB9LCB7fSk7XG4gIH1cblxuICByZXR1cm4gdXBkYXRlZDtcbn1cblxuLyoqXG4gKiBTb3J0IGN1c3RvbSBwYWxldHRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb3J0Q3VzdG9tUGFsZXR0ZUNvbG9yKFxuICBjdXN0b21QYWxldHRlOiBDb2xvclJhbmdlLFxuICBvbGRJbmRleDogbnVtYmVyLFxuICBuZXdJbmRleDogbnVtYmVyXG4pOiBDb2xvclJhbmdlIHtcbiAgY29uc3Qge2NvbG9yc30gPSBjdXN0b21QYWxldHRlO1xuXG4gIGNvbnN0IG5ld0NvbG9ycyA9IGFycmF5TW92ZShjb2xvcnMsIG9sZEluZGV4LCBuZXdJbmRleCk7XG4gIGNvbnN0IHVwZGF0ZSA9IHJlcGxhY2VDb2xvcnNJbkNvbG9yUmFuZ2UoY3VzdG9tUGFsZXR0ZSwgbmV3Q29sb3JzKTtcblxuICAvLyBAdHMtaWdub3JlXG4gIHJldHVybiB7XG4gICAgLi4uY3VzdG9tUGFsZXR0ZSxcbiAgICAuLi51cGRhdGVcbiAgfTtcbn1cblxuLyoqXG4gKiByZW1vdmUgYSBjb2xvciBpbiBjdXN0b20gcGFsZXR0ZSBhdCBpbmRleFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlQ3VzdG9tUGFsZXR0ZUNvbG9yKGN1c3RvbVBhbGV0dGU6IENvbG9yUmFuZ2UsIGluZGV4OiBudW1iZXIpOiBDb2xvclJhbmdlIHtcbiAgY29uc3Qge2NvbG9ycywgY29sb3JNYXAsIGNvbG9yTGVnZW5kc30gPSBjdXN0b21QYWxldHRlO1xuICBjb25zdCBvbGRWYWx1ZSA9IGNvbG9yc1tpbmRleF07XG4gIGNvbnN0IHVwZGF0ZTogUGFydGlhbDxDb2xvclJhbmdlPiA9IHt9O1xuICB1cGRhdGUuY29sb3JzID0gWy4uLmNvbG9yc107XG5cbiAgaWYgKHVwZGF0ZS5jb2xvcnMubGVuZ3RoID4gMSkge1xuICAgIHVwZGF0ZS5jb2xvcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxuICAvLyB1cGRhdGUgY29sb3IgbWFwXG4gIGlmIChBcnJheS5pc0FycmF5KGNvbG9yTWFwKSkge1xuICAgIC8vIGZpbmQgY29sb3JNYXAgaW5kZXhcbiAgICBjb25zdCBjb2xvck1hcEluZGV4ID0gY29sb3JNYXAuZmluZEluZGV4KGNtID0+IGNtWzFdID09PSBvbGRWYWx1ZSk7XG4gICAgaWYgKGNvbG9yTWFwSW5kZXggPj0gMCkge1xuICAgICAgdXBkYXRlLmNvbG9yTWFwID0gWy4uLmNvbG9yTWFwXTtcbiAgICAgIHVwZGF0ZS5jb2xvck1hcC5zcGxpY2UoY29sb3JNYXBJbmRleCwgMSk7XG4gICAgfVxuICB9XG4gIC8vIHVwZGF0ZSBjb2xvciBsZWdlbmRcbiAgaWYgKGNvbG9yTGVnZW5kcz8uW29sZFZhbHVlXSkge1xuICAgIHVwZGF0ZS5jb2xvckxlZ2VuZHMgPSB7Li4uY29sb3JMZWdlbmRzfTtcbiAgICBkZWxldGUgdXBkYXRlLmNvbG9yTGVnZW5kc1tvbGRWYWx1ZV07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLmN1c3RvbVBhbGV0dGUsXG4gICAgLi4udXBkYXRlXG4gIH07XG59XG5cbi8qKlxuICogVXBkYXRlIGEgY29sb3IgaW4gY3VzdG9tIHBhbGV0dGUgYXQgaW5kZXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUN1c3RvbVBhbGV0dGVDb2xvcihcbiAgY3VzdG9tUGFsZXR0ZTogQ29sb3JSYW5nZSxcbiAgaW5kZXg6IG51bWJlcixcbiAgbmV3VmFsdWU6IEhleENvbG9yXG4pOiBDb2xvclJhbmdlIHtcbiAgY29uc3Qge2NvbG9yc30gPSBjdXN0b21QYWxldHRlO1xuICBjb25zdCBoZXggPSBuZXdWYWx1ZS50b1VwcGVyQ2FzZSgpO1xuICBjb25zdCBuZXdDb2xvcnMgPSBbLi4uY29sb3JzXTtcbiAgbmV3Q29sb3JzW2luZGV4XSA9IGhleDtcblxuICBjb25zdCB1cGRhdGUgPSByZXBsYWNlQ29sb3JzSW5Db2xvclJhbmdlKGN1c3RvbVBhbGV0dGUsIG5ld0NvbG9ycyk7XG5cbiAgLy8gQHRzLWlnbm9yZVxuICByZXR1cm4ge1xuICAgIC4uLmN1c3RvbVBhbGV0dGUsXG4gICAgLi4udXBkYXRlXG4gIH07XG59XG5cbi8qKlxuICogR2V0IGEgcmV2ZXJzZWQgY29sb3JSYW5nZVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmV2ZXJzZUNvbG9yUmFuZ2UocmV2ZXJzZWQ6IGJvb2xlYW4sIGNvbG9yUmFuZ2U6IENvbG9yUmFuZ2UpOiBDb2xvclJhbmdlIHtcbiAgY29uc3QgbmV3Q29sb3JzID0gY29sb3JSYW5nZT8uY29sb3JzLnNsaWNlKCkucmV2ZXJzZSgpO1xuICBjb25zdCB1cGRhdGVkID0gcmVwbGFjZUNvbG9yc0luQ29sb3JSYW5nZShjb2xvclJhbmdlLCBuZXdDb2xvcnMpO1xuICB1cGRhdGVkLnJldmVyc2VkID0gcmV2ZXJzZWQ7XG5cbiAgcmV0dXJuIHVwZGF0ZWQ7XG59XG5cbi8qKlxuICogV2hldGhlciBwYWxldHRlIG1hdGNoZXMgY3VycmVudCBDb2xvckJsaW5kU2FmZSBjb25maWdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhbGV0dGVJc0NvbG9yQmxpbmRTYWZlKHBhbGV0dGU6IENvbG9yUGFsZXR0ZSwgY29sb3JCbGluZFNhZmU6IGJvb2xlYW4pIHtcbiAgcmV0dXJuICFjb2xvckJsaW5kU2FmZSB8fCAoY29sb3JCbGluZFNhZmUgJiYgcGFsZXR0ZS5jb2xvckJsaW5kU2FmZSk7XG59XG5cbi8qKlxuICogV2hldGhlciBwYWxldHRlIG1hdGNoZXMgY3VycmVudCBzdGVwcyBjb25maWdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUXVhUGFsZXR0ZShwYWxldHRlOiBDb2xvclBhbGV0dGUpOiBwYWxldHRlIGlzIENhdGVnb3JpY2FsUGFsZXR0ZSB7XG4gIHJldHVybiBwYWxldHRlLnR5cGUgPT09IFBBTEVUVEVfVFlQRVMuUVVBO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgcGFsZXR0ZSBtYXRjaGVzIGN1cnJlbnQgc3RlcHMgY29uZmlnXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYWxldHRlSXNTdGVwcyhwYWxldHRlOiBDb2xvclBhbGV0dGUsIHN0ZXBzOiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuICFpc1F1YVBhbGV0dGUocGFsZXR0ZSkgfHwgcGFsZXR0ZS5tYXhTdGVwID49IHN0ZXBzO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgcGFsZXR0ZSBtYXRjaGVzIGN1cnJlbnQgdHlwZSBjb25maWdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhbGV0dGVJc1R5cGUocGFsZXR0ZTogQ29sb3JQYWxldHRlLCB0eXBlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGUgPT09ICdhbGwnIHx8IHR5cGUgPT09IHBhbGV0dGUudHlwZTtcbn1cbi8qKlxuICogRmluZCBiZXN0IG1hdGNoIHBhbGV0dGUgYmFzZWQgb24gY29uZmlnLCB1cGRhdGUgY29sb3IgcmFuZ2UgYnkgaXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUNvbG9yUmFuZ2VCeU1hdGNoaW5nUGFsZXR0ZShcbiAgY3VycmVudENvbG9yUmFuZ2U6IENvbG9yUmFuZ2UsXG4gIGNvbmZpZzogQ29sb3JSYW5nZUNvbmZpZ1xuKTogQ29sb3JSYW5nZSB7XG4gIGNvbnN0IHtzdGVwcywgY29sb3JCbGluZFNhZmUsIHR5cGV9ID0gY29uZmlnO1xuXG4gIGNvbnN0IG1hdGNoaW5nUGFsZXR0ZSA9IEtFUExFUl9DT0xPUl9QQUxFVFRFUy5maWx0ZXIoXG4gICAgcGFsZXR0ZSA9PlxuICAgICAgLy8gcGFsZXR0ZSBtYXRjaCB0eXBlXG4gICAgICBwYWxldHRlSXNUeXBlKHBhbGV0dGUsIHR5cGUpICYmXG4gICAgICAvLyBwYWxldHRlIGhhcyBzYW1lIHN0ZXBcbiAgICAgIHBhbGV0dGVJc1N0ZXBzKHBhbGV0dGUsIHN0ZXBzKSAmJlxuICAgICAgLy8gcGFsZXR0ZSBpcyBjb2xvckJsaW5kU2FmZVxuICAgICAgcGFsZXR0ZUlzQ29sb3JCbGluZFNhZmUocGFsZXR0ZSwgY29sb3JCbGluZFNhZmUpXG4gICk7XG5cbiAgY29uc3QgYmVzdE1hdGNoID0gbWF0Y2hpbmdQYWxldHRlLmxlbmd0aFxuICAgID8gbWF0Y2hpbmdQYWxldHRlLmZpbmQocCA9PiBwLm5hbWUgPT09IGN1cnJlbnRDb2xvclJhbmdlLm5hbWUpIHx8IG1hdGNoaW5nUGFsZXR0ZVswXVxuICAgIDogbnVsbDtcblxuICBpZiAoYmVzdE1hdGNoKSB7XG4gICAgcmV0dXJuIHVwZGF0ZUNvbG9yUmFuZ2VCeVNlbGVjdGVkUGFsZXR0ZShjdXJyZW50Q29sb3JSYW5nZSwgYmVzdE1hdGNoLCBjb25maWcpO1xuICB9XG4gIC8vIHdlIGRvIG5vdGhpbmdcbiAgQ29uc29sZS53YXJuKFxuICAgIGB3ZSBjYW50IGZpbmQgYW55IHByZXNldCBwYWxldHRlIG1hdGNoZXMgcmVxdWlybWVudHM6IHN0ZXBzPSR7c3RlcHN9ICYmIGNvbG9yQmxpbmRTYWZlPSR7Y29sb3JCbGluZFNhZmV9YFxuICApO1xuXG4gIHJldHVybiBjdXJyZW50Q29sb3JSYW5nZTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgY3VzdG9tIHBhbGV0dGUgd2hlbiByZXZlcnNlIHRoZSBjb2xvcnMgaW4gY3VzdG9tIHBhbGV0dGUsIHNpbmNlIGNoYW5naW5nICdzdGVwcycsXG4gKiAnY29sb3JCaW5kU2FmZScsICd0eXBlJyBzaG91bGQgZmFsbCBiYWNrIHRvIHByZWRlZmluZWQgcGFsZXR0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUN1c3RvbUNvbG9yUmFuZ2VCeUNvbG9yVUkoXG4gIG9sZENvbG9yUmFuZ2U6IENvbG9yUmFuZ2UsXG4gIGNvbG9yQ29uZmlnOiBDb2xvclJhbmdlQ29uZmlnXG4pOiBDb2xvclJhbmdlIHtcbiAgY29uc3Qge3JldmVyc2VkfSA9IGNvbG9yQ29uZmlnO1xuICBjb25zdCBjb2xvcnMgPSBvbGRDb2xvclJhbmdlLmNvbG9ycztcbiAgLy8gZm9yIGN1c3RvbSBwYWxldHRlLCBvbmUgY2FuIG9ubHkgJ3JldmVyc2UnIHRoZSBjb2xvcnMgaW4gY3VzdG9tIHBhbGV0dGUuXG4gIGNvbG9ycy5yZXZlcnNlKCk7XG5cbiAgY29uc3QgY29sb3JSYW5nZSA9IHtcbiAgICBuYW1lOiBvbGRDb2xvclJhbmdlLm5hbWUsXG4gICAgdHlwZTogb2xkQ29sb3JSYW5nZS50eXBlLFxuICAgIGNhdGVnb3J5OiBvbGRDb2xvclJhbmdlLmNhdGVnb3J5LFxuICAgIGNvbG9ycyxcbiAgICAuLi4ocmV2ZXJzZWQgPyB7cmV2ZXJzZWR9IDoge30pLFxuICAgIC4uLihvbGRDb2xvclJhbmdlLmNvbG9yTWFwID8ge2NvbG9yTWFwOiBvbGRDb2xvclJhbmdlLmNvbG9yTWFwfSA6IHt9KSxcbiAgICAuLi4ob2xkQ29sb3JSYW5nZS5jb2xvckxlZ2VuZHMgPyB7Y29sb3JMZWdlbmRzOiBvbGRDb2xvclJhbmdlLmNvbG9yTGVnZW5kc30gOiB7fSlcbiAgfTtcblxuICByZXR1cm4gcmVwbGFjZUNvbG9yc0luQ29sb3JSYW5nZShjb2xvclJhbmdlLCBjb2xvclJhbmdlLmNvbG9ycyk7XG59XG5cbi8qKlxuICogVXBkYXRlIGNvbG9yIHJhbmdlIGFmdGVyIHNlbGVjdGluZyBhIHBhbGV0dGUgZnJvbSBjb2xvciByYW5nZSBzZWxlY3RvZXJcbiAqIENvcHkgb3ZlciBjb2xvck1hcCBhbmQgY29sb3JMZWdlbmRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVDb2xvclJhbmdlQnlTZWxlY3RlZFBhbGV0dGUob2xkQ29sb3JSYW5nZSwgY29sb3JQYWxldHRlLCBjb2xvckNvbmZpZykge1xuICBjb25zdCB7Y29sb3JzOiBuZXdDb2xvcnMsIC4uLm5ld0NvbG9yUmFuZ2V9ID0gY29sb3JQYWxldHRlVG9Db2xvclJhbmdlKGNvbG9yUGFsZXR0ZSwgY29sb3JDb25maWcpO1xuXG4gIGNvbnN0IGNvbG9yUmFuZ2UgPSB7XG4gICAgY29sb3JzOiBvbGRDb2xvclJhbmdlLmNvbG9ycyxcbiAgICAuLi5uZXdDb2xvclJhbmdlLFxuICAgIC4uLihvbGRDb2xvclJhbmdlLmNvbG9yTWFwID8ge2NvbG9yTWFwOiBvbGRDb2xvclJhbmdlLmNvbG9yTWFwfSA6IHt9KSxcbiAgICAuLi4ob2xkQ29sb3JSYW5nZS5jb2xvckxlZ2VuZHMgPyB7Y29sb3JMZWdlbmRzOiBvbGRDb2xvclJhbmdlLmNvbG9yTGVnZW5kc30gOiB7fSlcbiAgfTtcblxuICByZXR1cm4gcmVwbGFjZUNvbG9yc0luQ29sb3JSYW5nZShjb2xvclJhbmdlLCBuZXdDb2xvcnMpO1xufVxuXG5jb25zdCBVYmVyTmFtZVJlZ2V4ID0gbmV3IFJlZ0V4cCgvXihbQS1aYS16IF0pKy9nKTtcbmNvbnN0IENvbG9yQnJld2VyUmVnZXggPSBuZXcgUmVnRXhwKC9eQ29sb3JCcmV3ZXIgKFtBLVphLXoxLTldKSsvZyk7XG5cbi8qKlxuICogY29udmVydCBzYXZlZCBjb2xvclJhbmdlIHRvIGNvbG9yUGFsZXR0ZSBvYmpldnQgdHlwZS9uYW1lL2NhdGVnb3J5L2lzQ29sb3JCbGluZFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb3JSYW5nZUJhY2t3YXJkQ29tcGF0aWJpbGl0eShjb2xvclJhbmdlOiBDb2xvclJhbmdlKTogQ29sb3JSYW5nZSB7XG4gIGlmICghY29sb3JSYW5nZSB8fCBjb2xvclJhbmdlLnR5cGUgPT09ICdjdXN0b20nIHx8IGNvbG9yUmFuZ2UuY29sb3JNYXApIHtcbiAgICAvLyBkb24ndCBkbyBhbnl0aGluZyB0byBjdXN0b20gY29sb3IgcGFsZXR0ZSwgb3IgcGFsZXR0ZSB3aXRoIGN1c3RvbSBicmVha3NcbiAgICByZXR1cm4gY29sb3JSYW5nZTtcbiAgfVxuICBsZXQgdHJpbU5hbWU7XG4gIGlmIChjb2xvclJhbmdlLmNhdGVnb3J5ID09PSAnVWJlcicpIHtcbiAgICBjb25zdCBtYXRjaE5hbWUgPSAoY29sb3JSYW5nZS5uYW1lID8/ICcnKS5tYXRjaChVYmVyTmFtZVJlZ2V4KTtcbiAgICB0cmltTmFtZSA9IG1hdGNoTmFtZSA/IG1hdGNoTmFtZVswXS50cmltKCkgOiBudWxsO1xuICAgIC8vIG1hdGNoIFViZXIgVml6IFF1YWxpdGF0aXZlIDEuNCAtPiBVYmVyIFZpeiBRdWFsaXRhdGl2ZVxuICB9IGVsc2UgaWYgKGNvbG9yUmFuZ2UuY2F0ZWdvcnkgPT09ICdDb2xvckJyZXdlcicpIHtcbiAgICBjb25zdCBtYXRjaE5hbWUgPSAoY29sb3JSYW5nZS5uYW1lID8/ICcnKS5tYXRjaChDb2xvckJyZXdlclJlZ2V4KTtcbiAgICB0cmltTmFtZSA9IG1hdGNoTmFtZSA/IG1hdGNoTmFtZVswXS5yZXBsYWNlKCdDb2xvckJyZXdlciAnLCAnJykudHJpbSgpIDogbnVsbDtcbiAgfVxuXG4gIGlmICh0cmltTmFtZSkge1xuICAgIGNvbnN0IG1hdGNoaW5nUGFsZXR0ZSA9IEtFUExFUl9DT0xPUl9QQUxFVFRFUy5maW5kKHAgPT4gcC5uYW1lID09PSB0cmltTmFtZSk7XG4gICAgaWYgKG1hdGNoaW5nUGFsZXR0ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uY29sb3JSYW5nZSxcbiAgICAgICAgbmFtZTogdHJpbU5hbWUsXG4gICAgICAgIHR5cGU6IG1hdGNoaW5nUGFsZXR0ZT8udHlwZSxcbiAgICAgICAgY2F0ZWdvcnk6IG1hdGNoaW5nUGFsZXR0ZS5jYXRlZ29yeVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY29sb3JSYW5nZTtcbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIGN1c3RvbSBwYWxldHRlIGZyb20gY3VycmVudCBzdGFuZGFyZCBjb2xvciByYW5nZSBvYmplY3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVDdXN0b21QYWxldHRlKGNvbG9yUmFuZ2U6IENvbG9yUmFuZ2UsIGNvbG9yTWFwPzogQ29sb3JNYXApOiBDb2xvclJhbmdlIHtcbiAgLy8gVE9ETzogY2hlY2sgb24gYGlzUmV2ZXJzZWRgIGtleSwgd2hldGhlciB3ZSBjYW4gcmVtb3ZlIGl0IGhlcmVcbiAgY29uc3QgY3VzdG9tUGFsZXR0ZSA9IHtcbiAgICAuLi5jb2xvclJhbmdlLFxuICAgIG5hbWU6IERFRkFVTFRfQ1VTVE9NX1BBTEVUVEUubmFtZSxcbiAgICB0eXBlOiBERUZBVUxUX0NVU1RPTV9QQUxFVFRFLnR5cGUsXG4gICAgY2F0ZWdvcnk6IERFRkFVTFRfQ1VTVE9NX1BBTEVUVEUuY2F0ZWdvcnksXG4gICAgLi4uKGNvbG9yTWFwID8ge2NvbG9yTWFwfSA6IHt9KVxuICB9O1xuXG4gIC8vIG9ubHkgY3VzdG9tUGFsZXR0ZS5jb2xvcnMgYXJlIG5lZWRlZCBmb3IgY3VzdG9tIHBhbGV0dGUgZWRpdG9yIHdpdGggY3VzdG9tIG9yZGluYWwgc2NhbGVcbiAgaWYgKCFjb2xvck1hcCAmJiBjb2xvclJhbmdlLnR5cGUgPT09IFNDQUxFX1RZUEVTLmN1c3RvbU9yZGluYWwpIHtcbiAgICBkZWxldGUgY3VzdG9tUGFsZXR0ZS5jb2xv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