kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
399 lines (385 loc) • 52.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getDatasetContext = getDatasetContext;
exports.getGeometriesFromDataset = getGeometriesFromDataset;
exports.getValuesFromDataset = getValuesFromDataset;
exports.getValuesFromVectorTileLayer = getValuesFromVectorTileLayer;
exports.highlightRows = highlightRows;
exports.highlightRowsByColumnValues = highlightRowsByColumnValues;
exports.interpolateColor = interpolateColor;
exports.saveAsDataset = saveAsDataset;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _colorInterpolate = _interopRequireDefault(require("color-interpolate"));
var _constants = require("@kepler.gl/constants");
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
/**
* Interpolate the colors from the original colors with the given number of colors
* @param originalColors The original colors
* @param numberOfColors The number of colors
* @returns The interpolated colors
*/
function interpolateColor(originalColors, numberOfColors) {
if (originalColors.length === numberOfColors) {
return originalColors;
}
var interp = (0, _colorInterpolate["default"])(originalColors);
var colors = Array.from({
length: numberOfColors
}, function (_, j) {
return interp(j / (numberOfColors - 1));
});
// convert colors from 'rgb(255, 255, 255)' to '#ffffff'
var hexColors = colors.map(function (color) {
var rgb = color.match(/\d+/g);
return "#".concat(rgb === null || rgb === void 0 ? void 0 : rgb.map(function (c) {
return parseInt(c).toString(16).padStart(2, '0');
}).join(''));
});
return hexColors;
}
/**
* Get the values from a dataset for a variable
* @param datasets
* @param datasetName
* @param variableName
* @returns {number[]}
*/
function getValuesFromDataset(datasets, layers, datasetName, variableName) {
// find which dataset has the variableName
var datasetId = Object.keys(datasets).find(function (dataId) {
return datasets[dataId].label === datasetName;
});
if (!datasetId) {
throw new Error("Dataset ".concat(datasetName, " not found"));
}
var dataset = datasets[datasetId];
if (dataset) {
// check if field exists
var field = dataset.fields.find(function (field) {
return field.name === variableName;
});
if (!field) {
throw new Error("Field ".concat(variableName, " not found in dataset ").concat(datasetName));
}
// for vector-tile, getting values from layerData
if (dataset.type === 'vector-tile') {
// get field from dataset
var _field = dataset.fields.find(function (field) {
return field.name === variableName;
});
if (_field) {
return getValuesFromVectorTileLayer(datasetId, layers, _field);
}
}
return Array.from({
length: dataset.length
}, function (_, i) {
return dataset.getValue(variableName, i);
});
}
return [];
}
function isVectorTileLayer(layer) {
return layer.type === _constants.LAYER_TYPES.vectorTile;
}
function getValuesFromVectorTileLayer(datasetId, layers, field) {
// get the index of the layer
var layerIndex = layers.findIndex(function (layer) {
return layer.config.dataId === datasetId;
});
if (layerIndex === -1) return [];
var layer = layers[layerIndex];
if (!isVectorTileLayer(layer)) return [];
var accessor = layer.accessRowValue(field);
var values = [];
// @ts-expect-error TODO fix this later in the vector-tile layer
var _iterator = _createForOfIteratorHelper(layer.tileDataset.tileSet),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var row = _step.value;
var value = accessor(field, row);
if (value === null) break;
values.push(value);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return values;
}
/**
* Highlight the rows in a dataset
* @param datasets The kepler.gl datasets
* @param layers The kepler.gl layers
* @param datasetName The name of the dataset
* @param selectedRowIndices The indices of the rows to highlight
* @param layerSetIsValid The function to set the layer validity
*/
function highlightRows(datasets, layers, datasetName, selectedRowIndices, layerSetIsValid) {
// update the filteredIndex in the dataset
var datasetId = Object.keys(datasets).find(function (dataId) {
return datasets[dataId].label === datasetName;
});
if (!datasetId) return;
var dataset = datasets[datasetId];
if (dataset) {
dataset.filteredIndex = selectedRowIndices.length === 0 ? dataset.allIndexes : selectedRowIndices;
// get all layers that use this dataset
var selectLayers = layers.filter(function (layer) {
return layer.config.dataId === dataset.id;
});
selectLayers.forEach(function (layer) {
layer.formatLayerData(datasets);
// trigger a re-render using layerSetIsValid() to update the top layer
layerSetIsValid(layer, true);
});
}
}
/**
* Get the dataset context, which is used to provide the dataset information to the AI assistant
* @param datasets The kepler.gl datasets
* @param layers The kepler.gl layers
* @returns The dataset context
*/
function getDatasetContext(datasets, layers) {
if (!datasets || !layers) return '';
var context = 'Please ONLY use the following datasets and layers to answer the user question:';
var dataMeta = Object.values(datasets).map(function (dataset) {
return {
datasetName: dataset.label,
datasetId: dataset.id,
fields: dataset.fields.map(function (field) {
return (0, _defineProperty2["default"])({}, field.name, field.type);
}),
layers: layers.filter(function (layer) {
return layer.config.dataId === dataset.id;
}).map(function (layer) {
return {
id: layer.id,
label: layer.config.label,
type: layer.type,
geometryMode: layer.config.columnMode,
// get the valid geometry columns as string
geometryColumns: Object.fromEntries(Object.entries(layer.config.columns).filter(function (_ref2) {
var _ref3 = (0, _slicedToArray2["default"])(_ref2, 2),
value = _ref3[1];
return value !== null;
}).map(function (_ref4) {
var _ref5 = (0, _slicedToArray2["default"])(_ref4, 2),
key = _ref5[0],
value = _ref5[1];
return [key, (0, _typeof2["default"])(value) === 'object' && value !== null ? Object.fromEntries(Object.entries(value).filter(function (_ref6) {
var _ref7 = (0, _slicedToArray2["default"])(_ref6, 2),
v = _ref7[1];
return v !== null;
})) : value];
}))
};
})
};
});
return "".concat(context, "\n").concat(JSON.stringify(dataMeta));
}
/**
* Get the geometries from a dataset
* @param datasets The kepler.gl datasets
* @param layers The kepler.gl layers
* @param layerData The layer data
* @param datasetName The name of the dataset
* @returns The geometries
*/
function getGeometriesFromDataset(datasets, layers, layerData, datasetName) {
var datasetId = Object.keys(datasets).find(function (dataId) {
return datasets[dataId].label === datasetName;
});
if (!datasetId) {
return [];
}
var dataset = datasets[datasetId];
// if layer is vector-tile, get the geometries from the layer
if (dataset.type === 'vector-tile') {
// find the vector-tile layer
var selected = layers.filter(function (layer) {
return layer.config.dataId === dataset.id;
});
var layer = selected.find(function (layer) {
return layer.type === _constants.LAYER_TYPES.vectorTile;
});
if (!layer) return [];
var geometries = [];
// @ts-expect-error TODO fix this later in the vector-tile layer
var _iterator2 = _createForOfIteratorHelper(layer.tileDataset.tileSet),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var row = _step2.value;
geometries.push(row);
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return geometries;
}
// for non-vector-tile dataset, get the geometries from the possible layer
var selectedLayers = layers.filter(function (layer) {
return layer.config.dataId === dataset.id;
});
if (selectedLayers.length === 0) return [];
// find geojson layer, then point layer, then other layers
var geojsonLayer = selectedLayers.find(function (layer) {
return layer.type === _constants.LAYER_TYPES.geojson;
});
var pointLayer = selectedLayers.find(function (layer) {
return layer.type === _constants.LAYER_TYPES.point;
});
var otherLayers = selectedLayers.filter(function (layer) {
return layer.type !== _constants.LAYER_TYPES.geojson && layer.type !== _constants.LAYER_TYPES.point;
});
var validLayer = geojsonLayer || pointLayer || otherLayers[0];
if (validLayer) {
var layerIndex = layers.findIndex(function (layer) {
return layer.id === validLayer.id;
});
var _geometries = layerData[layerIndex];
return _geometries.data;
}
return [];
}
/**
* Save the data as a new dataset by joining it with the left dataset
* @param datasets The kepler.gl datasets
* @param datasetName The name of the left dataset
* @param data The data to save
* @param addDataToMap The function to add the data to the map
*/
function saveAsDataset(datasets, layers, datasetName, newDatasetName, data) {
// find datasetId from datasets
var datasetId = Object.keys(datasets).find(function (dataId) {
return datasets[dataId].label === datasetName;
});
if (!datasetId) return;
// check if newDatasetName already exists
if (Object.keys(datasets).includes(newDatasetName)) return;
// Save the data as a new dataset by joining it with the left dataset
var leftDataset = datasets[datasetId];
var numRows = leftDataset.length;
var geometries;
if (leftDataset.type === 'vector-tile') {
// we need to get geometries from the vector-tile layer
geometries = getFeaturesFromVectorTile(leftDataset, layers) || [];
numRows = geometries.length;
}
var fields = [].concat((0, _toConsumableArray2["default"])(Object.keys(data).map(function (fieldName, index) {
return {
name: fieldName,
id: "".concat(fieldName, "_").concat(index),
displayName: fieldName,
type: determineFieldType(data[fieldName][0])
};
})), (0, _toConsumableArray2["default"])(leftDataset.fields.map(function (field, index) {
return {
name: field.name,
id: field.id || "".concat(field.name, "_").concat(index),
displayName: field.displayName,
type: field.type
};
})), (0, _toConsumableArray2["default"])(leftDataset.type === 'vector-tile' ? [{
name: '_geojson',
id: '_geojson',
displayName: '_geojson',
type: 'geojson'
}] : []));
// Pre-calculate data values array
var dataValues = Object.values(data);
var rows = Array(numRows).fill(null).map(function (_, rowIdx) {
return [].concat((0, _toConsumableArray2["default"])(dataValues.map(function (col) {
return col[rowIdx];
})), (0, _toConsumableArray2["default"])(leftDataset.fields.map(function (field) {
var _geometries$rowIdx$pr;
return leftDataset.type === 'vector-tile' ? (_geometries$rowIdx$pr = geometries[rowIdx].properties) === null || _geometries$rowIdx$pr === void 0 ? void 0 : _geometries$rowIdx$pr[field.name] : leftDataset.getValue(field.name, rowIdx);
})), (0, _toConsumableArray2["default"])(leftDataset.type === 'vector-tile' ? [geometries[rowIdx]] : []));
});
// create new dataset
var newDataset = {
info: {
id: newDatasetName,
label: newDatasetName
},
data: {
fields: fields,
rows: rows
}
};
return newDataset;
}
/**
* Helper function to determine field type
* @param value The value to determine the field type
* @returns The field type
*/
function determineFieldType(value) {
return typeof value === 'number' ? Number.isInteger(value) ? _constants.ALL_FIELD_TYPES.integer : _constants.ALL_FIELD_TYPES.real : _constants.ALL_FIELD_TYPES.string;
}
function highlightRowsByColumnValues(datasets, layers, datasetName, columnName, selectedValues, layerSetIsValid) {
var datasetId = Object.keys(datasets).find(function (dataId) {
return datasets[dataId].label === datasetName;
});
if (!datasetId) return;
var dataset = datasets[datasetId];
if (dataset) {
// get the values of the column
var values = Array.from({
length: dataset.length
}, function (_, i) {
return dataset.getValue(columnName, i);
});
// create a dict using the values
var valueDict = values.reduce(function (acc, value, index) {
acc[value] = index;
return acc;
}, {});
// need to fix the type error of value here
var selectedIndices = selectedValues.map(function (value) {
return valueDict[value];
});
// highlight the rows
highlightRows(datasets, layers, datasetName, selectedIndices, layerSetIsValid);
}
}
function getFeaturesFromVectorTile(leftDataset, layers) {
var layerIndex = layers.findIndex(function (layer) {
return layer.config.dataId === leftDataset.id;
});
if (layerIndex === -1) return;
var layer = layers[layerIndex];
if (!isVectorTileLayer(layer)) return;
var features = [];
// @ts-expect-error TODO fix this later in the vector-tile layer
var _iterator3 = _createForOfIteratorHelper(layer.tileDataset.tileSet),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var row = _step3.value;
features.push(row);
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
return features;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29sb3JJbnRlcnBvbGF0ZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX2NvbnN0YW50cyIsIl9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyIiwiciIsImUiLCJ0IiwiU3ltYm9sIiwiaXRlcmF0b3IiLCJBcnJheSIsImlzQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJsZW5ndGgiLCJfbiIsIkYiLCJzIiwibiIsImRvbmUiLCJ2YWx1ZSIsImYiLCJUeXBlRXJyb3IiLCJvIiwiYSIsInUiLCJjYWxsIiwibmV4dCIsIl9hcnJheUxpa2VUb0FycmF5IiwidG9TdHJpbmciLCJzbGljZSIsImNvbnN0cnVjdG9yIiwibmFtZSIsImZyb20iLCJ0ZXN0IiwiaW50ZXJwb2xhdGVDb2xvciIsIm9yaWdpbmFsQ29sb3JzIiwibnVtYmVyT2ZDb2xvcnMiLCJpbnRlcnAiLCJpbnRlcnBvbGF0ZSIsImNvbG9ycyIsIl8iLCJqIiwiaGV4Q29sb3JzIiwibWFwIiwiY29sb3IiLCJyZ2IiLCJtYXRjaCIsImNvbmNhdCIsImMiLCJwYXJzZUludCIsInBhZFN0YXJ0Iiwiam9pbiIsImdldFZhbHVlc0Zyb21EYXRhc2V0IiwiZGF0YXNldHMiLCJsYXllcnMiLCJkYXRhc2V0TmFtZSIsInZhcmlhYmxlTmFtZSIsImRhdGFzZXRJZCIsIk9iamVjdCIsImtleXMiLCJmaW5kIiwiZGF0YUlkIiwibGFiZWwiLCJFcnJvciIsImRhdGFzZXQiLCJmaWVsZCIsImZpZWxkcyIsInR5cGUiLCJnZXRWYWx1ZXNGcm9tVmVjdG9yVGlsZUxheWVyIiwiaSIsImdldFZhbHVlIiwiaXNWZWN0b3JUaWxlTGF5ZXIiLCJsYXllciIsIkxBWUVSX1RZUEVTIiwidmVjdG9yVGlsZSIsImxheWVySW5kZXgiLCJmaW5kSW5kZXgiLCJjb25maWciLCJhY2Nlc3NvciIsImFjY2Vzc1Jvd1ZhbHVlIiwidmFsdWVzIiwiX2l0ZXJhdG9yIiwidGlsZURhdGFzZXQiLCJ0aWxlU2V0IiwiX3N0ZXAiLCJyb3ciLCJwdXNoIiwiZXJyIiwiaGlnaGxpZ2h0Um93cyIsInNlbGVjdGVkUm93SW5kaWNlcyIsImxheWVyU2V0SXNWYWxpZCIsImZpbHRlcmVkSW5kZXgiLCJhbGxJbmRleGVzIiwic2VsZWN0TGF5ZXJzIiwiZmlsdGVyIiwiaWQiLCJmb3JFYWNoIiwiZm9ybWF0TGF5ZXJEYXRhIiwiZ2V0RGF0YXNldENvbnRleHQiLCJjb250ZXh0IiwiZGF0YU1ldGEiLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2VvbWV0cnlNb2RlIiwiY29sdW1uTW9kZSIsImdlb21ldHJ5Q29sdW1ucyIsImZyb21FbnRyaWVzIiwiZW50cmllcyIsImNvbHVtbnMiLCJfcmVmMiIsIl9yZWYzIiwiX3NsaWNlZFRvQXJyYXkyIiwiX3JlZjQiLCJfcmVmNSIsImtleSIsIl90eXBlb2YyIiwiX3JlZjYiLCJfcmVmNyIsInYiLCJKU09OIiwic3RyaW5naWZ5IiwiZ2V0R2VvbWV0cmllc0Zyb21EYXRhc2V0IiwibGF5ZXJEYXRhIiwic2VsZWN0ZWQiLCJnZW9tZXRyaWVzIiwiX2l0ZXJhdG9yMiIsIl9zdGVwMiIsInNlbGVjdGVkTGF5ZXJzIiwiZ2VvanNvbkxheWVyIiwiZ2VvanNvbiIsInBvaW50TGF5ZXIiLCJwb2ludCIsIm90aGVyTGF5ZXJzIiwidmFsaWRMYXllciIsImRhdGEiLCJzYXZlQXNEYXRhc2V0IiwibmV3RGF0YXNldE5hbWUiLCJpbmNsdWRlcyIsImxlZnREYXRhc2V0IiwibnVtUm93cyIsImdldEZlYXR1cmVzRnJvbVZlY3RvclRpbGUiLCJfdG9Db25zdW1hYmxlQXJyYXkyIiwiZmllbGROYW1lIiwiaW5kZXgiLCJkaXNwbGF5TmFtZSIsImRldGVybWluZUZpZWxkVHlwZSIsImRhdGFWYWx1ZXMiLCJyb3dzIiwiZmlsbCIsInJvd0lkeCIsImNvbCIsIl9nZW9tZXRyaWVzJHJvd0lkeCRwciIsInByb3BlcnRpZXMiLCJuZXdEYXRhc2V0IiwiaW5mbyIsIk51bWJlciIsImlzSW50ZWdlciIsIkFMTF9GSUVMRF9UWVBFUyIsImludGVnZXIiLCJyZWFsIiwic3RyaW5nIiwiaGlnaGxpZ2h0Um93c0J5Q29sdW1uVmFsdWVzIiwiY29sdW1uTmFtZSIsInNlbGVjdGVkVmFsdWVzIiwidmFsdWVEaWN0IiwicmVkdWNlIiwiYWNjIiwic2VsZWN0ZWRJbmRpY2VzIiwiZmVhdHVyZXMiLCJfaXRlcmF0b3IzIiwiX3N0ZXAzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rvb2xzL3V0aWxzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVRcbi8vIENvcHlyaWdodCBjb250cmlidXRvcnMgdG8gdGhlIGtlcGxlci5nbCBwcm9qZWN0XG5cbmltcG9ydCBpbnRlcnBvbGF0ZSBmcm9tICdjb2xvci1pbnRlcnBvbGF0ZSc7XG5pbXBvcnQge0ZlYXR1cmV9IGZyb20gJ2dlb2pzb24nO1xuaW1wb3J0IHtMYXllciwgVmVjdG9yVGlsZUxheWVyfSBmcm9tICdAa2VwbGVyLmdsL2xheWVycyc7XG5pbXBvcnQge0RhdGFzZXRzLCBLZXBsZXJUYWJsZX0gZnJvbSAnQGtlcGxlci5nbC90YWJsZSc7XG5pbXBvcnQge1NwYXRpYWxKb2luR2VvbWV0cmllc30gZnJvbSAnQG9wZW5hc3Npc3RhbnQvZ2VvZGEnO1xuaW1wb3J0IHtBTExfRklFTERfVFlQRVMsIExBWUVSX1RZUEVTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5pbXBvcnQge0ZpZWxkLCBQcm90b0RhdGFzZXQsIFByb3RvRGF0YXNldEZpZWxkfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcblxuLyoqXG4gKiBJbnRlcnBvbGF0ZSB0aGUgY29sb3JzIGZyb20gdGhlIG9yaWdpbmFsIGNvbG9ycyB3aXRoIHRoZSBnaXZlbiBudW1iZXIgb2YgY29sb3JzXG4gKiBAcGFyYW0gb3JpZ2luYWxDb2xvcnMgVGhlIG9yaWdpbmFsIGNvbG9yc1xuICogQHBhcmFtIG51bWJlck9mQ29sb3JzIFRoZSBudW1iZXIgb2YgY29sb3JzXG4gKiBAcmV0dXJucyBUaGUgaW50ZXJwb2xhdGVkIGNvbG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJwb2xhdGVDb2xvcihvcmlnaW5hbENvbG9yczogc3RyaW5nW10sIG51bWJlck9mQ29sb3JzOiBudW1iZXIpIHtcbiAgaWYgKG9yaWdpbmFsQ29sb3JzLmxlbmd0aCA9PT0gbnVtYmVyT2ZDb2xvcnMpIHtcbiAgICByZXR1cm4gb3JpZ2luYWxDb2xvcnM7XG4gIH1cbiAgY29uc3QgaW50ZXJwID0gaW50ZXJwb2xhdGUob3JpZ2luYWxDb2xvcnMpO1xuICBjb25zdCBjb2xvcnMgPSBBcnJheS5mcm9tKHtsZW5ndGg6IG51bWJlck9mQ29sb3JzfSwgKF8sIGopID0+IGludGVycChqIC8gKG51bWJlck9mQ29sb3JzIC0gMSkpKTtcbiAgLy8gY29udmVydCBjb2xvcnMgZnJvbSAncmdiKDI1NSwgMjU1LCAyNTUpJyB0byAnI2ZmZmZmZidcbiAgY29uc3QgaGV4Q29sb3JzID0gY29sb3JzLm1hcChjb2xvciA9PiB7XG4gICAgY29uc3QgcmdiID0gY29sb3IubWF0Y2goL1xcZCsvZyk7XG4gICAgcmV0dXJuIGAjJHtyZ2I/Lm1hcChjID0+IHBhcnNlSW50KGMpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKS5qb2luKCcnKX1gO1xuICB9KTtcbiAgcmV0dXJuIGhleENvbG9ycztcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHZhbHVlcyBmcm9tIGEgZGF0YXNldCBmb3IgYSB2YXJpYWJsZVxuICogQHBhcmFtIGRhdGFzZXRzXG4gKiBAcGFyYW0gZGF0YXNldE5hbWVcbiAqIEBwYXJhbSB2YXJpYWJsZU5hbWVcbiAqIEByZXR1cm5zIHtudW1iZXJbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFZhbHVlc0Zyb21EYXRhc2V0KFxuICBkYXRhc2V0czogRGF0YXNldHMsXG4gIGxheWVyczogTGF5ZXJbXSxcbiAgZGF0YXNldE5hbWU6IHN0cmluZyxcbiAgdmFyaWFibGVOYW1lOiBzdHJpbmdcbik6IHVua25vd25bXSB7XG4gIC8vIGZpbmQgd2hpY2ggZGF0YXNldCBoYXMgdGhlIHZhcmlhYmxlTmFtZVxuICBjb25zdCBkYXRhc2V0SWQgPSBPYmplY3Qua2V5cyhkYXRhc2V0cykuZmluZChkYXRhSWQgPT4gZGF0YXNldHNbZGF0YUlkXS5sYWJlbCA9PT0gZGF0YXNldE5hbWUpO1xuICBpZiAoIWRhdGFzZXRJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRGF0YXNldCAke2RhdGFzZXROYW1lfSBub3QgZm91bmRgKTtcbiAgfVxuICBjb25zdCBkYXRhc2V0ID0gZGF0YXNldHNbZGF0YXNldElkXTtcbiAgaWYgKGRhdGFzZXQpIHtcbiAgICAvLyBjaGVjayBpZiBmaWVsZCBleGlzdHNcbiAgICBjb25zdCBmaWVsZCA9IGRhdGFzZXQuZmllbGRzLmZpbmQoZmllbGQgPT4gZmllbGQubmFtZSA9PT0gdmFyaWFibGVOYW1lKTtcbiAgICBpZiAoIWZpZWxkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZpZWxkICR7dmFyaWFibGVOYW1lfSBub3QgZm91bmQgaW4gZGF0YXNldCAke2RhdGFzZXROYW1lfWApO1xuICAgIH1cbiAgICAvLyBmb3IgdmVjdG9yLXRpbGUsIGdldHRpbmcgdmFsdWVzIGZyb20gbGF5ZXJEYXRhXG4gICAgaWYgKGRhdGFzZXQudHlwZSA9PT0gJ3ZlY3Rvci10aWxlJykge1xuICAgICAgLy8gZ2V0IGZpZWxkIGZyb20gZGF0YXNldFxuICAgICAgY29uc3QgZmllbGQgPSBkYXRhc2V0LmZpZWxkcy5maW5kKGZpZWxkID0+IGZpZWxkLm5hbWUgPT09IHZhcmlhYmxlTmFtZSk7XG4gICAgICBpZiAoZmllbGQpIHtcbiAgICAgICAgcmV0dXJuIGdldFZhbHVlc0Zyb21WZWN0b3JUaWxlTGF5ZXIoZGF0YXNldElkLCBsYXllcnMsIGZpZWxkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIEFycmF5LmZyb20oe2xlbmd0aDogZGF0YXNldC5sZW5ndGh9LCAoXywgaSkgPT4gZGF0YXNldC5nZXRWYWx1ZSh2YXJpYWJsZU5hbWUsIGkpKTtcbiAgfVxuICByZXR1cm4gW107XG59XG5cbmZ1bmN0aW9uIGlzVmVjdG9yVGlsZUxheWVyKGxheWVyOiBMYXllcik6IGxheWVyIGlzIFZlY3RvclRpbGVMYXllciB7XG4gIHJldHVybiBsYXllci50eXBlID09PSBMQVlFUl9UWVBFUy52ZWN0b3JUaWxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmFsdWVzRnJvbVZlY3RvclRpbGVMYXllcihkYXRhc2V0SWQ6IHN0cmluZywgbGF5ZXJzOiBMYXllcltdLCBmaWVsZDogRmllbGQpIHtcbiAgLy8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgbGF5ZXJcbiAgY29uc3QgbGF5ZXJJbmRleCA9IGxheWVycy5maW5kSW5kZXgobGF5ZXIgPT4gbGF5ZXIuY29uZmlnLmRhdGFJZCA9PT0gZGF0YXNldElkKTtcbiAgaWYgKGxheWVySW5kZXggPT09IC0xKSByZXR1cm4gW107XG4gIGNvbnN0IGxheWVyID0gbGF5ZXJzW2xheWVySW5kZXhdO1xuICBpZiAoIWlzVmVjdG9yVGlsZUxheWVyKGxheWVyKSkgcmV0dXJuIFtdO1xuICBjb25zdCBhY2Nlc3NvciA9IGxheWVyLmFjY2Vzc1Jvd1ZhbHVlKGZpZWxkKTtcbiAgY29uc3QgdmFsdWVzOiB1bmtub3duW10gPSBbXTtcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciBUT0RPIGZpeCB0aGlzIGxhdGVyIGluIHRoZSB2ZWN0b3ItdGlsZSBsYXllclxuICBmb3IgKGNvbnN0IHJvdyBvZiBsYXllci50aWxlRGF0YXNldC50aWxlU2V0KSB7XG4gICAgY29uc3QgdmFsdWUgPSBhY2Nlc3NvcihmaWVsZCwgcm93KTtcbiAgICBpZiAodmFsdWUgPT09IG51bGwpIGJyZWFrO1xuICAgIHZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgfVxuICByZXR1cm4gdmFsdWVzO1xufVxuXG4vKipcbiAqIEhpZ2hsaWdodCB0aGUgcm93cyBpbiBhIGRhdGFzZXRcbiAqIEBwYXJhbSBkYXRhc2V0cyBUaGUga2VwbGVyLmdsIGRhdGFzZXRzXG4gKiBAcGFyYW0gbGF5ZXJzIFRoZSBrZXBsZXIuZ2wgbGF5ZXJzXG4gKiBAcGFyYW0gZGF0YXNldE5hbWUgVGhlIG5hbWUgb2YgdGhlIGRhdGFzZXRcbiAqIEBwYXJhbSBzZWxlY3RlZFJvd0luZGljZXMgVGhlIGluZGljZXMgb2YgdGhlIHJvd3MgdG8gaGlnaGxpZ2h0XG4gKiBAcGFyYW0gbGF5ZXJTZXRJc1ZhbGlkIFRoZSBmdW5jdGlvbiB0byBzZXQgdGhlIGxheWVyIHZhbGlkaXR5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoaWdobGlnaHRSb3dzKFxuICBkYXRhc2V0czogRGF0YXNldHMsXG4gIGxheWVyczogTGF5ZXJbXSxcbiAgZGF0YXNldE5hbWU6IHN0cmluZyxcbiAgc2VsZWN0ZWRSb3dJbmRpY2VzOiBudW1iZXJbXSxcbiAgbGF5ZXJTZXRJc1ZhbGlkOiAobGF5ZXI6IExheWVyLCBpc1ZhbGlkOiBib29sZWFuKSA9PiB2b2lkXG4pIHtcbiAgLy8gdXBkYXRlIHRoZSBmaWx0ZXJlZEluZGV4IGluIHRoZSBkYXRhc2V0XG4gIGNvbnN0IGRhdGFzZXRJZCA9IE9iamVjdC5rZXlzKGRhdGFzZXRzKS5maW5kKGRhdGFJZCA9PiBkYXRhc2V0c1tkYXRhSWRdLmxhYmVsID09PSBkYXRhc2V0TmFtZSk7XG4gIGlmICghZGF0YXNldElkKSByZXR1cm47XG4gIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tkYXRhc2V0SWRdO1xuICBpZiAoZGF0YXNldCkge1xuICAgIGRhdGFzZXQuZmlsdGVyZWRJbmRleCA9XG4gICAgICBzZWxlY3RlZFJvd0luZGljZXMubGVuZ3RoID09PSAwID8gZGF0YXNldC5hbGxJbmRleGVzIDogc2VsZWN0ZWRSb3dJbmRpY2VzO1xuICAgIC8vIGdldCBhbGwgbGF5ZXJzIHRoYXQgdXNlIHRoaXMgZGF0YXNldFxuICAgIGNvbnN0IHNlbGVjdExheWVycyA9IGxheWVycy5maWx0ZXIobGF5ZXIgPT4gbGF5ZXIuY29uZmlnLmRhdGFJZCA9PT0gZGF0YXNldC5pZCk7XG4gICAgc2VsZWN0TGF5ZXJzLmZvckVhY2gobGF5ZXIgPT4ge1xuICAgICAgbGF5ZXIuZm9ybWF0TGF5ZXJEYXRhKGRhdGFzZXRzKTtcbiAgICAgIC8vIHRyaWdnZXIgYSByZS1yZW5kZXIgdXNpbmcgbGF5ZXJTZXRJc1ZhbGlkKCkgdG8gdXBkYXRlIHRoZSB0b3AgbGF5ZXJcbiAgICAgIGxheWVyU2V0SXNWYWxpZChsYXllciwgdHJ1ZSk7XG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXQgdGhlIGRhdGFzZXQgY29udGV4dCwgd2hpY2ggaXMgdXNlZCB0byBwcm92aWRlIHRoZSBkYXRhc2V0IGluZm9ybWF0aW9uIHRvIHRoZSBBSSBhc3Npc3RhbnRcbiAqIEBwYXJhbSBkYXRhc2V0cyBUaGUga2VwbGVyLmdsIGRhdGFzZXRzXG4gKiBAcGFyYW0gbGF5ZXJzIFRoZSBrZXBsZXIuZ2wgbGF5ZXJzXG4gKiBAcmV0dXJucyBUaGUgZGF0YXNldCBjb250ZXh0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREYXRhc2V0Q29udGV4dChkYXRhc2V0cz86IERhdGFzZXRzLCBsYXllcnM/OiBMYXllcltdKSB7XG4gIGlmICghZGF0YXNldHMgfHwgIWxheWVycykgcmV0dXJuICcnO1xuICBjb25zdCBjb250ZXh0ID0gJ1BsZWFzZSBPTkxZIHVzZSB0aGUgZm9sbG93aW5nIGRhdGFzZXRzIGFuZCBsYXllcnMgdG8gYW5zd2VyIHRoZSB1c2VyIHF1ZXN0aW9uOic7XG4gIGNvbnN0IGRhdGFNZXRhID0gT2JqZWN0LnZhbHVlcyhkYXRhc2V0cykubWFwKChkYXRhc2V0OiBLZXBsZXJUYWJsZSkgPT4gKHtcbiAgICBkYXRhc2V0TmFtZTogZGF0YXNldC5sYWJlbCxcbiAgICBkYXRhc2V0SWQ6IGRhdGFzZXQuaWQsXG4gICAgZmllbGRzOiBkYXRhc2V0LmZpZWxkcy5tYXAoZmllbGQgPT4gKHtbZmllbGQubmFtZV06IGZpZWxkLnR5cGV9KSksXG4gICAgbGF5ZXJzOiBsYXllcnNcbiAgICAgIC5maWx0ZXIobGF5ZXIgPT4gbGF5ZXIuY29uZmlnLmRhdGFJZCA9PT0gZGF0YXNldC5pZClcbiAgICAgIC5tYXAobGF5ZXIgPT4gKHtcbiAgICAgICAgaWQ6IGxheWVyLmlkLFxuICAgICAgICBsYWJlbDogbGF5ZXIuY29uZmlnLmxhYmVsLFxuICAgICAgICB0eXBlOiBsYXllci50eXBlLFxuICAgICAgICBnZW9tZXRyeU1vZGU6IGxheWVyLmNvbmZpZy5jb2x1bW5Nb2RlLFxuICAgICAgICAvLyBnZXQgdGhlIHZhbGlkIGdlb21ldHJ5IGNvbHVtbnMgYXMgc3RyaW5nXG4gICAgICAgIGdlb21ldHJ5Q29sdW1uczogT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGxheWVyLmNvbmZpZy5jb2x1bW5zKVxuICAgICAgICAgICAgLmZpbHRlcigoWywgdmFsdWVdKSA9PiB2YWx1ZSAhPT0gbnVsbClcbiAgICAgICAgICAgIC5tYXAoKFtrZXksIHZhbHVlXSkgPT4gW1xuICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGxcbiAgICAgICAgICAgICAgICA/IE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyh2YWx1ZSkuZmlsdGVyKChbLCB2XSkgPT4gdiAhPT0gbnVsbCkpXG4gICAgICAgICAgICAgICAgOiB2YWx1ZVxuICAgICAgICAgICAgXSlcbiAgICAgICAgKVxuICAgICAgfSkpXG4gIH0pKTtcbiAgcmV0dXJuIGAke2NvbnRleHR9XFxuJHtKU09OLnN0cmluZ2lmeShkYXRhTWV0YSl9YDtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGdlb21ldHJpZXMgZnJvbSBhIGRhdGFzZXRcbiAqIEBwYXJhbSBkYXRhc2V0cyBUaGUga2VwbGVyLmdsIGRhdGFzZXRzXG4gKiBAcGFyYW0gbGF5ZXJzIFRoZSBrZXBsZXIuZ2wgbGF5ZXJzXG4gKiBAcGFyYW0gbGF5ZXJEYXRhIFRoZSBsYXllciBkYXRhXG4gKiBAcGFyYW0gZGF0YXNldE5hbWUgVGhlIG5hbWUgb2YgdGhlIGRhdGFzZXRcbiAqIEByZXR1cm5zIFRoZSBnZW9tZXRyaWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRHZW9tZXRyaWVzRnJvbURhdGFzZXQoXG4gIGRhdGFzZXRzOiBEYXRhc2V0cyxcbiAgbGF5ZXJzOiBMYXllcltdLFxuICBsYXllckRhdGE6IGFueVtdLFxuICBkYXRhc2V0TmFtZTogc3RyaW5nXG4pOiBTcGF0aWFsSm9pbkdlb21ldHJpZXMge1xuICBjb25zdCBkYXRhc2V0SWQgPSBPYmplY3Qua2V5cyhkYXRhc2V0cykuZmluZChkYXRhSWQgPT4gZGF0YXNldHNbZGF0YUlkXS5sYWJlbCA9PT0gZGF0YXNldE5hbWUpO1xuICBpZiAoIWRhdGFzZXRJZCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICBjb25zdCBkYXRhc2V0ID0gZGF0YXNldHNbZGF0YXNldElkXTtcblxuICAvLyBpZiBsYXllciBpcyB2ZWN0b3ItdGlsZSwgZ2V0IHRoZSBnZW9tZXRyaWVzIGZyb20gdGhlIGxheWVyXG4gIGlmIChkYXRhc2V0LnR5cGUgPT09ICd2ZWN0b3ItdGlsZScpIHtcbiAgICAvLyBmaW5kIHRoZSB2ZWN0b3ItdGlsZSBsYXllclxuICAgIGNvbnN0IHNlbGVjdGVkID0gbGF5ZXJzLmZpbHRlcihsYXllciA9PiBsYXllci5jb25maWcuZGF0YUlkID09PSBkYXRhc2V0LmlkKTtcbiAgICBjb25zdCBsYXllciA9IHNlbGVjdGVkLmZpbmQobGF5ZXIgPT4gbGF5ZXIudHlwZSA9PT0gTEFZRVJfVFlQRVMudmVjdG9yVGlsZSk7XG4gICAgaWYgKCFsYXllcikgcmV0dXJuIFtdO1xuXG4gICAgY29uc3QgZ2VvbWV0cmllczogRmVhdHVyZVtdID0gW107XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUT0RPIGZpeCB0aGlzIGxhdGVyIGluIHRoZSB2ZWN0b3ItdGlsZSBsYXllclxuICAgIGZvciAoY29uc3Qgcm93IG9mIGxheWVyLnRpbGVEYXRhc2V0LnRpbGVTZXQpIHtcbiAgICAgIGdlb21ldHJpZXMucHVzaChyb3cpO1xuICAgIH1cbiAgICByZXR1cm4gZ2VvbWV0cmllcztcbiAgfVxuXG4gIC8vIGZvciBub24tdmVjdG9yLXRpbGUgZGF0YXNldCwgZ2V0IHRoZSBnZW9tZXRyaWVzIGZyb20gdGhlIHBvc3NpYmxlIGxheWVyXG4gIGNvbnN0IHNlbGVjdGVkTGF5ZXJzID0gbGF5ZXJzLmZpbHRlcihsYXllciA9PiBsYXllci5jb25maWcuZGF0YUlkID09PSBkYXRhc2V0LmlkKTtcbiAgaWYgKHNlbGVjdGVkTGF5ZXJzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuXG4gIC8vIGZpbmQgZ2VvanNvbiBsYXllciwgdGhlbiBwb2ludCBsYXllciwgdGhlbiBvdGhlciBsYXllcnNcbiAgY29uc3QgZ2VvanNvbkxheWVyID0gc2VsZWN0ZWRMYXllcnMuZmluZChsYXllciA9PiBsYXllci50eXBlID09PSBMQVlFUl9UWVBFUy5nZW9qc29uKTtcbiAgY29uc3QgcG9pbnRMYXllciA9IHNlbGVjdGVkTGF5ZXJzLmZpbmQobGF5ZXIgPT4gbGF5ZXIudHlwZSA9PT0gTEFZRVJfVFlQRVMucG9pbnQpO1xuICBjb25zdCBvdGhlckxheWVycyA9IHNlbGVjdGVkTGF5ZXJzLmZpbHRlcihcbiAgICBsYXllciA9PiBsYXllci50eXBlICE9PSBMQVlFUl9UWVBFUy5nZW9qc29uICYmIGxheWVyLnR5cGUgIT09IExBWUVSX1RZUEVTLnBvaW50XG4gICk7XG5cbiAgY29uc3QgdmFsaWRMYXllciA9IGdlb2pzb25MYXllciB8fCBwb2ludExheWVyIHx8IG90aGVyTGF5ZXJzWzBdO1xuICBpZiAodmFsaWRMYXllcikge1xuICAgIGNvbnN0IGxheWVySW5kZXggPSBsYXllcnMuZmluZEluZGV4KGxheWVyID0+IGxheWVyLmlkID09PSB2YWxpZExheWVyLmlkKTtcbiAgICBjb25zdCBnZW9tZXRyaWVzID0gbGF5ZXJEYXRhW2xheWVySW5kZXhdO1xuICAgIHJldHVybiBnZW9tZXRyaWVzLmRhdGE7XG4gIH1cblxuICByZXR1cm4gW107XG59XG5cbi8qKlxuICogU2F2ZSB0aGUgZGF0YSBhcyBhIG5ldyBkYXRhc2V0IGJ5IGpvaW5pbmcgaXQgd2l0aCB0aGUgbGVmdCBkYXRhc2V0XG4gKiBAcGFyYW0gZGF0YXNldHMgVGhlIGtlcGxlci5nbCBkYXRhc2V0c1xuICogQHBhcmFtIGRhdGFzZXROYW1lIFRoZSBuYW1lIG9mIHRoZSBsZWZ0IGRhdGFzZXRcbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIHNhdmVcbiAqIEBwYXJhbSBhZGREYXRhVG9NYXAgVGhlIGZ1bmN0aW9uIHRvIGFkZCB0aGUgZGF0YSB0byB0aGUgbWFwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYXZlQXNEYXRhc2V0KFxuICBkYXRhc2V0czogRGF0YXNldHMsXG4gIGxheWVyczogTGF5ZXJbXSxcbiAgZGF0YXNldE5hbWU6IHN0cmluZyxcbiAgbmV3RGF0YXNldE5hbWU6IHN0cmluZyxcbiAgZGF0YTogUmVjb3JkPHN0cmluZywgbnVtYmVyW10+XG4pIHtcbiAgLy8gZmluZCBkYXRhc2V0SWQgZnJvbSBkYXRhc2V0c1xuICBjb25zdCBkYXRhc2V0SWQgPSBPYmplY3Qua2V5cyhkYXRhc2V0cykuZmluZChkYXRhSWQgPT4gZGF0YXNldHNbZGF0YUlkXS5sYWJlbCA9PT0gZGF0YXNldE5hbWUpO1xuICBpZiAoIWRhdGFzZXRJZCkgcmV0dXJuO1xuXG4gIC8vIGNoZWNrIGlmIG5ld0RhdGFzZXROYW1lIGFscmVhZHkgZXhpc3RzXG4gIGlmIChPYmplY3Qua2V5cyhkYXRhc2V0cykuaW5jbHVkZXMobmV3RGF0YXNldE5hbWUpKSByZXR1cm47XG5cbiAgLy8gU2F2ZSB0aGUgZGF0YSBhcyBhIG5ldyBkYXRhc2V0IGJ5IGpvaW5pbmcgaXQgd2l0aCB0aGUgbGVmdCBkYXRhc2V0XG4gIGNvbnN0IGxlZnREYXRhc2V0ID0gZGF0YXNldHNbZGF0YXNldElkXTtcbiAgbGV0IG51bVJvd3MgPSBsZWZ0RGF0YXNldC5sZW5ndGg7XG4gIGxldCBnZW9tZXRyaWVzOiBGZWF0dXJlW107XG5cbiAgaWYgKGxlZnREYXRhc2V0LnR5cGUgPT09ICd2ZWN0b3ItdGlsZScpIHtcbiAgICAvLyB3ZSBuZWVkIHRvIGdldCBnZW9tZXRyaWVzIGZyb20gdGhlIHZlY3Rvci10aWxlIGxheWVyXG4gICAgZ2VvbWV0cmllcyA9IGdldEZlYXR1cmVzRnJvbVZlY3RvclRpbGUobGVmdERhdGFzZXQsIGxheWVycykgfHwgW107XG4gICAgbnVtUm93cyA9IGdlb21ldHJpZXMubGVuZ3RoO1xuICB9XG5cbiAgY29uc3QgZmllbGRzOiBQcm90b0RhdGFzZXRGaWVsZFtdID0gW1xuICAgIC8vIE5ldyBmaWVsZHMgZnJvbSBkYXRhXG4gICAgLi4uT2JqZWN0LmtleXMoZGF0YSkubWFwKChmaWVsZE5hbWUsIGluZGV4KSA9PiAoe1xuICAgICAgbmFtZTogZmllbGROYW1lLFxuICAgICAgaWQ6IGAke2ZpZWxkTmFtZX1fJHtpbmRleH1gLFxuICAgICAgZGlzcGxheU5hbWU6IGZpZWxkTmFtZSxcbiAgICAgIHR5cGU6IGRldGVybWluZUZpZWxkVHlwZShkYXRhW2ZpZWxkTmFtZV1bMF0pXG4gICAgfSkpLFxuICAgIC8vIEV4aXN0aW5nIGZpZWxkcyBmcm9tIGxlZnREYXRhc2V0XG4gICAgLi4ubGVmdERhdGFzZXQuZmllbGRzLm1hcCgoZmllbGQsIGluZGV4KSA9PiAoe1xuICAgICAgbmFtZTogZmllbGQubmFtZSxcbiAgICAgIGlkOiBmaWVsZC5pZCB8fCBgJHtmaWVsZC5uYW1lfV8ke2luZGV4fWAsXG4gICAgICBkaXNwbGF5TmFtZTogZmllbGQuZGlzcGxheU5hbWUsXG4gICAgICB0eXBlOiBmaWVsZC50eXBlXG4gICAgfSkpLFxuICAgIC8vIGFkZCBnZW9tZXRyeSBjb2x1bW4gZm9yIHZlY3Rvci10aWxlXG4gICAgLi4uKGxlZnREYXRhc2V0LnR5cGUgPT09ICd2ZWN0b3ItdGlsZSdcbiAgICAgID8gW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdfZ2VvanNvbicsXG4gICAgICAgICAgICBpZDogJ19nZW9qc29uJyxcbiAgICAgICAgICAgIGRpc3BsYXlOYW1lOiAnX2dlb2pzb24nLFxuICAgICAgICAgICAgdHlwZTogJ2dlb2pzb24nXG4gICAgICAgICAgfVxuICAgICAgICBdXG4gICAgICA6IFtdKVxuICBdO1xuXG4gIC8vIFByZS1jYWxjdWxhdGUgZGF0YSB2YWx1ZXMgYXJyYXlcbiAgY29uc3QgZGF0YVZhbHVlcyA9IE9iamVjdC52YWx1ZXMoZGF0YSk7XG5cbiAgY29uc3Qgcm93cyA9IEFycmF5KG51bVJvd3MpXG4gICAgLmZpbGwobnVsbClcbiAgICAubWFwKChfLCByb3dJZHgpID0+IFtcbiAgICAgIC8vIE5ldyBkYXRhIHZhbHVlc1xuICAgICAgLi4uZGF0YVZhbHVlcy5tYXAoY29sID0+IGNvbFtyb3dJZHhdKSxcbiAgICAgIC8vIEV4aXN0aW5nIGRhdGFzZXQgdmFsdWVzXG4gICAgICAuLi5sZWZ0RGF0YXNldC5maWVsZHMubWFwKGZpZWxkID0+XG4gICAgICAgIGxlZnREYXRhc2V0LnR5cGUgPT09ICd2ZWN0b3ItdGlsZSdcbiAgICAgICAgICA/IGdlb21ldHJpZXNbcm93SWR4XS5wcm9wZXJ0aWVzPy5bZmllbGQubmFtZV1cbiAgICAgICAgICA6IGxlZnREYXRhc2V0LmdldFZhbHVlKGZpZWxkLm5hbWUsIHJvd0lkeClcbiAgICAgICksXG4gICAgICAvLyBnZW9tZXRyeSBjb2x1bW4gZm9yIHZlY3Rvci10aWxlXG4gICAgICAuLi4obGVmdERhdGFzZXQudHlwZSA9PT0gJ3ZlY3Rvci10aWxlJyA/IFtnZW9tZXRyaWVzW3Jvd0lkeF1dIDogW10pXG4gICAgXSk7XG5cbiAgLy8gY3JlYXRlIG5ldyBkYXRhc2V0XG4gIGNvbnN0IG5ld0RhdGFzZXQ6IFByb3RvRGF0YXNldCA9IHtcbiAgICBpbmZvOiB7XG4gICAgICBpZDogbmV3RGF0YXNldE5hbWUsXG4gICAgICBsYWJlbDogbmV3RGF0YXNldE5hbWVcbiAgICB9LFxuICAgIGRhdGE6IHtcbiAgICAgIGZpZWxkcyxcbiAgICAgIHJvd3NcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIG5ld0RhdGFzZXQ7XG59XG5cbi8qKlxuICogSGVscGVyIGZ1bmN0aW9uIHRvIGRldGVybWluZSBmaWVsZCB0eXBlXG4gKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIGRldGVybWluZSB0aGUgZmllbGQgdHlwZVxuICogQHJldHVybnMgVGhlIGZpZWxkIHR5cGVcbiAqL1xuZnVuY3Rpb24gZGV0ZXJtaW5lRmllbGRUeXBlKHZhbHVlOiB1bmtub3duKToga2V5b2YgdHlwZW9mIEFMTF9GSUVMRF9UWVBFUyB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInXG4gICAgPyBOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKVxuICAgICAgPyBBTExfRklFTERfVFlQRVMuaW50ZWdlclxuICAgICAgOiBBTExfRklFTERfVFlQRVMucmVhbFxuICAgIDogQUxMX0ZJRUxEX1RZUEVTLnN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhpZ2hsaWdodFJvd3NCeUNvbHVtblZhbHVlcyhcbiAgZGF0YXNldHM6IERhdGFzZXRzLFxuICBsYXllcnM6IExheWVyW10sXG4gIGRhdGFzZXROYW1lOiBzdHJpbmcsXG4gIGNvbHVtbk5hbWU6IHN0cmluZyxcbiAgc2VsZWN0ZWRWYWx1ZXM6IHVua25vd25bXSxcbiAgbGF5ZXJTZXRJc1ZhbGlkOiAobGF5ZXI6IExheWVyLCBpc1ZhbGlkOiBib29sZWFuKSA9PiB2b2lkXG4pIHtcbiAgY29uc3QgZGF0YXNldElkID0gT2JqZWN0LmtleXMoZGF0YXNldHMpLmZpbmQoZGF0YUlkID0+IGRhdGFzZXRzW2RhdGFJZF0ubGFiZWwgPT09IGRhdGFzZXROYW1lKTtcbiAgaWYgKCFkYXRhc2V0SWQpIHJldHVybjtcbiAgY29uc3QgZGF0YXNldCA9IGRhdGFzZXRzW2RhdGFzZXRJZF07XG4gIGlmIChkYXRhc2V0KSB7XG4gICAgLy8gZ2V0IHRoZSB2YWx1ZXMgb2YgdGhlIGNvbHVtblxuICAgIGNvbnN0IHZhbHVlcyA9IEFycmF5LmZyb20oe2xlbmd0aDogZGF0YXNldC5sZW5ndGh9LCAoXywgaSkgPT4gZGF0YXNldC5nZXRWYWx1ZShjb2x1bW5OYW1lLCBpKSk7XG4gICAgLy8gY3JlYXRlIGEgZGljdCB1c2luZyB0aGUgdmFsdWVzXG4gICAgY29uc3QgdmFsdWVEaWN0ID0gdmFsdWVzLnJlZHVjZSgoYWNjLCB2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgIGFjY1t2YWx1ZV0gPSBpbmRleDtcbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwge30pO1xuICAgIC8vIG5lZWQgdG8gZml4IHRoZSB0eXBlIGVycm9yIG9mIHZhbHVlIGhlcmVcbiAgICBjb25zdCBzZWxlY3RlZEluZGljZXMgPSBzZWxlY3RlZFZhbHVlcy5tYXAodmFsdWUgPT4gdmFsdWVEaWN0W3ZhbHVlIGFzIGFueV0pO1xuICAgIC8vIGhpZ2hsaWdodCB0aGUgcm93c1xuICAgIGhpZ2hsaWdodFJvd3MoZGF0YXNldHMsIGxheWVycywgZGF0YXNldE5hbWUsIHNlbGVjdGVkSW5kaWNlcywgbGF5ZXJTZXRJc1ZhbGlkKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRGZWF0dXJlc0Zyb21WZWN0b3JUaWxlKGxlZnREYXRhc2V0OiBLZXBsZXJUYWJsZSwgbGF5ZXJzOiBMYXllcltdKSB7XG4gIGNvbnN0IGxheWVySW5kZXggPSBsYXllcnMuZmluZEluZGV4KGxheWVyID0+IGxheWVyLmNvbmZpZy5kYXRhSWQgPT09IGxlZnREYXRhc2V0LmlkKTtcbiAgaWYgKGxheWVySW5kZXggPT09IC0xKSByZXR1cm47XG5cbiAgY29uc3QgbGF5ZXIgPSBsYXllcnNbbGF5ZXJJbmRleF07XG4gIGlmICghaXNWZWN0b3JUaWxlTGF5ZXIobGF5ZXIpKSByZXR1cm47XG5cbiAgY29uc3QgZmVhdHVyZXM6IEZlYXR1cmVbXSA9IFtdO1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gZml4IHRoaXMgbGF0ZXIgaW4gdGhlIHZlY3Rvci10aWxlIGxheWVyXG4gIGZvciAoY29uc3Qgcm93IG9mIGxheWVyLnRpbGVEYXRhc2V0LnRpbGVTZXQpIHtcbiAgICBmZWF0dXJlcy5wdXNoKHJvdyk7XG4gIH1cblxuICByZXR1cm4gZmVhdHVyZXM7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdBLElBQUFBLGlCQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFLQSxJQUFBQyxVQUFBLEdBQUFELE9BQUE7QUFBa0UsU0FBQUUsMkJBQUFDLENBQUEsRUFBQUMsQ0FBQSxRQUFBQyxDQUFBLHlCQUFBQyxNQUFBLElBQUFILENBQUEsQ0FBQUcsTUFBQSxDQUFBQyxRQUFBLEtBQUFKLENBQUEscUJBQUFFLENBQUEsUUFBQUcsS0FBQSxDQUFBQyxPQUFBLENBQUFOLENBQUEsTUFBQUUsQ0FBQSxHQUFBSywyQkFBQSxDQUFBUCxDQUFBLE1BQUFDLENBQUEsSUFBQUQsQ0FBQSx1QkFBQUEsQ0FBQSxDQUFBUSxNQUFBLElBQUFOLENBQUEsS0FBQUYsQ0FBQSxHQUFBRSxDQUFBLE9BQUFPLEVBQUEsTUFBQUMsQ0FBQSxZQUFBQSxFQUFBLGVBQUFDLENBQUEsRUFBQUQsQ0FBQSxFQUFBRSxDQUFBLFdBQUFBLEVBQUEsV0FBQUgsRUFBQSxJQUFBVCxDQUFBLENBQUFRLE1BQUEsS0FBQUssSUFBQSxXQUFBQSxJQUFBLE1BQUFDLEtBQUEsRUFBQWQsQ0FBQSxDQUFBUyxFQUFBLFVBQUFSLENBQUEsV0FBQUEsRUFBQUQsQ0FBQSxVQUFBQSxDQUFBLEtBQUFlLENBQUEsRUFBQUwsQ0FBQSxnQkFBQU0sU0FBQSxpSkFBQUMsQ0FBQSxFQUFBQyxDQUFBLE9BQUFDLENBQUEsZ0JBQUFSLENBQUEsV0FBQUEsRUFBQSxJQUFBVCxDQUFBLEdBQUFBLENBQUEsQ0FBQWtCLElBQUEsQ0FBQXBCLENBQUEsTUFBQVksQ0FBQSxXQUFBQSxFQUFBLFFBQUFaLENBQUEsR0FBQUUsQ0FBQSxDQUFBbUIs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