kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
240 lines (239 loc) • 39.3 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AddLayerToolComponent = AddLayerToolComponent;
exports.addLayer = void 0;
exports.guessDefaultLayer = guessDefaultLayer;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _lib = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/node_modules/react-redux/lib");
var _src = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/layers/src");
var _src2 = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/reducers/src");
var _src3 = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/src/actions/src");
var _utils = require("@openassistant/utils");
var _zod = require("zod");
var _react = require("/Users/ihordykhta/Desktop/unfolded/kepler.gl/node_modules/react");
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
var addLayer = exports.addLayer = (0, _utils.extendedTool)({
description: "Add a kepler.gl map layer from a dataset.\nYou can create basic map layer without color styling, or enhanced map layer with color visualization.\n\nFor basic maps:\n- Simply use datasetName, geometryColumn (if needed), latitudeColumn/longitudeColumn (for point maps), and mapType\n- Omit color-related parameters for simple visualization\n\nFor colored maps:\n- If user requests color visualization, use available columns in the dataset\n- Use dataClassify tool to classify data into bins or unique values when needed\n- If dataClassify tool returns a list of k breaks\n a. For a list of k break values, you must create k+1 entries in the colorMap, with the last value being null.\n b. For example: for breaks = [0, 3, 10], the colorMap could be [{value: 0, color: '##fff7bc', label: '< 0'}, {value: 3, color: '#fec44f', label: '[0-3)'}, {value: null, color: '#d95f0e', label: '>= 3'}]\n- If dataClassify tool returns a list of k unique values\n a. There should be k colors in the colorMap. For example: for uniqueValues = ['a', 'b', 'c'], the colorMap could be [{value: 'a', color: '#1b9e77'}, {value: 'b', color: '#d95f02'}, {value: 'c', color: '#7570b3'}]\n- Generate colorBrewer colors automatically if user doesn't specify colors\n\nFor geojson datasets:\n- Use geometryColumn: '_geojson' and mapType: 'geojson' even for point collections\n",
parameters: _zod.z.object({
datasetName: _zod.z.string().describe('The name of the dataset. Note: please do NOT use the datasetId.'),
latitudeColumn: _zod.z.string().optional(),
longitudeColumn: _zod.z.string().optional(),
layerName: _zod.z.string().optional().describe('If possible, generate a name for the layer based on the context.'),
layerType: _zod.z["enum"](['point', 'arc', 'line', 'grid', 'hexagon', 'geojson', 'cluster', 'heatmap', 'h3', 'trip', 's2']),
colorBy: _zod.z.string().optional(),
colorType: _zod.z["enum"](['breaks', 'unique']).optional(),
colorMap: _zod.z.array(_zod.z.object({
value: _zod.z.union([_zod.z.string(), _zod.z.number(), _zod.z["null"]()]),
color: _zod.z.string()
})).optional()
}),
execute: executeAddLayer,
component: AddLayerToolComponent
});
function isAddLayerArgs(args) {
return (0, _typeof2["default"])(args) === 'object' && args !== null && 'datasetName' in args && 'layerType' in args;
}
function isAddLayerFunctionContext(context) {
return context && typeof context.getDatasets === 'function';
}
function executeAddLayer(_x, _x2) {
return _executeAddLayer.apply(this, arguments);
}
function _executeAddLayer() {
_executeAddLayer = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(args, options) {
var _layer2, _layer3, datasetName, layerName, latitudeColumn, longitudeColumn, layerType, colorBy, colorType, colorMap, datasets, datasetId, dataset, layer, layerId, columns, newLayer, colorField, colorScale, colors, keplerColorMap, colorRange;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
if (isAddLayerArgs(args)) {
_context.next = 3;
break;
}
throw new Error('Invalid addLayer arguments');
case 3:
if (isAddLayerFunctionContext(options.context)) {
_context.next = 5;
break;
}
throw new Error('Invalid addLayer context');
case 5:
datasetName = args.datasetName, layerName = args.layerName, latitudeColumn = args.latitudeColumn, longitudeColumn = args.longitudeColumn, layerType = args.layerType, colorBy = args.colorBy, colorType = args.colorType, colorMap = args.colorMap;
datasets = options.context.getDatasets(); // check if dataset exists in kepler.gl
datasetId = Object.keys(datasets).find(function (dataId) {
return datasets[dataId].label === datasetName;
});
if (datasetId) {
_context.next = 10;
break;
}
throw new Error("Dataset ".concat(datasetName, " not found."));
case 10:
// check if field exists in the dataset
dataset = datasets[datasetId]; // check if layerType is valid
layer = guessDefaultLayer(dataset, layerType);
layerId = ((_layer2 = layer) === null || _layer2 === void 0 ? void 0 : _layer2.id) || "layer_".concat((0, _utils.generateId)());
if (!layer) {
// for point layer, try to creat a point layer manually if LLM sugggests Lat/Lng fields
if (layerType === 'point' && latitudeColumn && longitudeColumn) {
layer = {
id: layerId,
type: 'point',
config: {
dataId: datasetId,
label: layerName || "".concat(datasetName, "-").concat(layerType),
columns: {
lat: {
value: latitudeColumn,
fieldIdx: dataset.getColumnFieldIdx(latitudeColumn)
},
lng: {
value: longitudeColumn,
fieldIdx: dataset.getColumnFieldIdx(longitudeColumn)
}
}
},
visConfig: {
colorRange: {
name: 'Ice And Fire',
type: 'diverging',
category: 'Uber',
colors: ['#D50255', '#FEAD54', '#FEEDB1', '#E8FEB5', '#49E3CE', '#0198BD']
}
}
};
}
}
if (layer) {
_context.next = 16;
break;
}
throw new Error("Invalid layer type: ".concat(layerType, "."));
case 16:
columns = ((_layer3 = layer) === null || _layer3 === void 0 || (_layer3 = _layer3.config) === null || _layer3 === void 0 ? void 0 : _layer3.columns) || {}; // construct new layer config for addLayer() action
newLayer = {
id: layerId,
type: layer.type,
config: _objectSpread(_objectSpread({}, layer.config), {}, {
dataId: datasetId,
label: layerName || "".concat(datasetName, "-").concat(layerType),
columns: Object.keys(columns).reduce(function (acc, key) {
var column = columns[key];
if (column) {
acc[key] = column.value;
}
return acc;
}, {})
})
};
if (!colorBy) {
_context.next = 33;
break;
}
colorField = dataset.fields.find(function (f) {
return f.name === colorBy;
});
if (colorField) {
_context.next = 22;
break;
}
throw new Error("Field ".concat(colorBy, " not found."));
case 22:
// create kepler.gl's colorMap from uniqueValues and breaks
colorScale = colorType === 'breaks' ? 'custom' : 'customOrdinal';
colors = colorMap === null || colorMap === void 0 ? void 0 : colorMap.map(function (color) {
return color.color;
});
keplerColorMap = colorMap === null || colorMap === void 0 ? void 0 : colorMap.map(function (color) {
return [color.value, color.color];
});
colorRange = {
name: 'color.customPalette',
type: 'custom',
category: 'Custom',
colors: colors,
colorMap: keplerColorMap
};
newLayer.config['colorScale'] = colorScale;
newLayer.config['colorField'] = colorField;
newLayer.config['strokeColorScale'] = colorScale;
newLayer.config['strokeColorField'] = colorField;
newLayer.config.visConfig['colorRange'] = colorRange;
newLayer.config.visConfig['strokeColorRange'] = colorRange;
newLayer.config['visualChannels'] = {
colorField: {
name: colorBy,
type: colorField === null || colorField === void 0 ? void 0 : colorField.type
},
colorScale: colorScale
};
case 33:
return _context.abrupt("return", {
llmResult: {
success: true,
layer: JSON.stringify(newLayer),
details: "map layer ".concat(layerId, " will be added to the map.")
},
additionalData: {
layer: newLayer,
datasetId: datasetId
}
});
case 36:
_context.prev = 36;
_context.t0 = _context["catch"](0);
return _context.abrupt("return", {
llmResult: {
success: false,
error: _context.t0 instanceof Error ? _context.t0.message : 'Unknown error',
instruction: 'Try to fix the error. If the error persists, pause the execution and ask the user to try with different prompt and context.'
}
});
case 39:
case "end":
return _context.stop();
}
}, _callee, null, [[0, 36]]);
}));
return _executeAddLayer.apply(this, arguments);
}
function guessDefaultLayer(dataset, layerType) {
// special case for hexagon layer, which could be implemented as findDefaultLayerProps() in hexagon-layer.tsx
if (layerType === 'hexagon') {
if (dataset.fieldPairs && dataset.fieldPairs.length > 0) {
var props = dataset.fieldPairs.map(function (fieldPair) {
return {
isVisible: true,
label: 'Hexbin',
columns: fieldPair.pair
};
});
var _layer = new _src.LayerClasses.hexagon(props[0]);
return _layer;
}
}
var defaultLayers = (0, _src2.findDefaultLayer)(dataset, _src.LayerClasses);
var layer = defaultLayers.find(function (l) {
return l.type === layerType;
});
return layer || defaultLayers.length > 0 ? defaultLayers[0] : null;
}
function AddLayerToolComponent(_ref) {
var layer = _ref.layer,
datasetId = _ref.datasetId;
var dispatch = (0, _lib.useDispatch)();
(0, _react.useEffect)(function () {
dispatch((0, _src3.addLayer)(layer, datasetId));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return null;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbGliIiwicmVxdWlyZSIsIl9zcmMiLCJfc3JjMiIsIl9zcmMzIiwiX3V0aWxzIiwiX3pvZCIsIl9yZWFjdCIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwiYWRkTGF5ZXIiLCJleHBvcnRzIiwiZXh0ZW5kZWRUb29sIiwiZGVzY3JpcHRpb24iLCJwYXJhbWV0ZXJzIiwieiIsIm9iamVjdCIsImRhdGFzZXROYW1lIiwic3RyaW5nIiwiZGVzY3JpYmUiLCJsYXRpdHVkZUNvbHVtbiIsIm9wdGlvbmFsIiwibG9uZ2l0dWRlQ29sdW1uIiwibGF5ZXJOYW1lIiwibGF5ZXJUeXBlIiwiY29sb3JCeSIsImNvbG9yVHlwZSIsImNvbG9yTWFwIiwiYXJyYXkiLCJ2YWx1ZSIsInVuaW9uIiwibnVtYmVyIiwiY29sb3IiLCJleGVjdXRlIiwiZXhlY3V0ZUFkZExheWVyIiwiY29tcG9uZW50IiwiQWRkTGF5ZXJUb29sQ29tcG9uZW50IiwiaXNBZGRMYXllckFyZ3MiLCJhcmdzIiwiX3R5cGVvZjIiLCJpc0FkZExheWVyRnVuY3Rpb25Db250ZXh0IiwiY29udGV4dCIsImdldERhdGFzZXRzIiwiX3giLCJfeDIiLCJfZXhlY3V0ZUFkZExheWVyIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX3JlZ2VuZXJhdG9yIiwibWFyayIsIl9jYWxsZWUiLCJvcHRpb25zIiwiX2xheWVyMiIsIl9sYXllcjMiLCJkYXRhc2V0cyIsImRhdGFzZXRJZCIsImRhdGFzZXQiLCJsYXllciIsImxheWVySWQiLCJjb2x1bW5zIiwibmV3TGF5ZXIiLCJjb2xvckZpZWxkIiwiY29sb3JTY2FsZSIsImNvbG9ycyIsImtlcGxlckNvbG9yTWFwIiwiY29sb3JSYW5nZSIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0IiwicHJldiIsIm5leHQiLCJFcnJvciIsImZpbmQiLCJkYXRhSWQiLCJsYWJlbCIsImNvbmNhdCIsImd1ZXNzRGVmYXVsdExheWVyIiwiaWQiLCJnZW5lcmF0ZUlkIiwidHlwZSIsImNvbmZpZyIsImxhdCIsImZpZWxkSWR4IiwiZ2V0Q29sdW1uRmllbGRJZHgiLCJsbmciLCJ2aXNDb25maWciLCJuYW1lIiwiY2F0ZWdvcnkiLCJyZWR1Y2UiLCJhY2MiLCJrZXkiLCJjb2x1bW4iLCJmaWVsZHMiLCJmIiwibWFwIiwiYWJydXB0IiwibGxtUmVzdWx0Iiwic3VjY2VzcyIsIkpTT04iLCJzdHJpbmdpZnkiLCJkZXRhaWxzIiwiYWRkaXRpb25hbERhdGEiLCJ0MCIsImVycm9yIiwibWVzc2FnZSIsImluc3RydWN0aW9uIiwic3RvcCIsImZpZWxkUGFpcnMiLCJwcm9wcyIsImZpZWxkUGFpciIsImlzVmlzaWJsZSIsInBhaXIiLCJMYXllckNsYXNzZXMiLCJoZXhhZ29uIiwiZGVmYXVsdExheWVycyIsImZpbmREZWZhdWx0TGF5ZXIiLCJsIiwiX3JlZiIsImRpc3BhdGNoIiwidXNlRGlzcGF0Y2giLCJ1c2VFZmZlY3QiLCJhZGRMYXllckFjdGlvbiJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9haS1hc3Npc3RhbnQvc3JjL3Rvb2xzL2tlcGxlci10b29scy9sYXllci1jcmVhdGlvbi10b29sLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge3VzZURpc3BhdGNofSBmcm9tICdyZWFjdC1yZWR1eCc7XG5pbXBvcnQge0xheWVyQ2xhc3Nlc30gZnJvbSAnQGtlcGxlci5nbC9sYXllcnMnO1xuaW1wb3J0IEtlcGxlclRhYmxlLCB7RGF0YXNldHN9IGZyb20gJ0BrZXBsZXIuZ2wvdGFibGUnO1xuaW1wb3J0IHtmaW5kRGVmYXVsdExheWVyfSBmcm9tICdAa2VwbGVyLmdsL3JlZHVjZXJzJztcbmltcG9ydCB7YWRkTGF5ZXIgYXMgYWRkTGF5ZXJBY3Rpb259IGZyb20gJ0BrZXBsZXIuZ2wvYWN0aW9ucyc7XG5pbXBvcnQge2V4dGVuZGVkVG9vbCwgZ2VuZXJhdGVJZH0gZnJvbSAnQG9wZW5hc3Npc3RhbnQvdXRpbHMnO1xuaW1wb3J0IHt6fSBmcm9tICd6b2QnO1xuaW1wb3J0IHt1c2VFZmZlY3R9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGNvbnN0IGFkZExheWVyID0gZXh0ZW5kZWRUb29sPFxuICAvLyBwYXJhbWV0ZXJzXG4gIHouWm9kT2JqZWN0PHtcbiAgICBkYXRhc2V0TmFtZTogei5ab2RTdHJpbmc7XG4gICAgbGF0aXR1ZGVDb2x1bW46IHouWm9kT3B0aW9uYWw8ei5ab2RTdHJpbmc+O1xuICAgIGxvbmdpdHVkZUNvbHVtbjogei5ab2RPcHRpb25hbDx6LlpvZFN0cmluZz47XG4gICAgbGF5ZXJUeXBlOiB6LlpvZEVudW08XG4gICAgICBbXG4gICAgICAgICdwb2ludCcsXG4gICAgICAgICdhcmMnLFxuICAgICAgICAnbGluZScsXG4gICAgICAgICdncmlkJyxcbiAgICAgICAgJ2hleGFnb24nLFxuICAgICAgICAnZ2VvanNvbicsXG4gICAgICAgICdjbHVzdGVyJyxcbiAgICAgICAgJ2hlYXRtYXAnLFxuICAgICAgICAnaDMnLFxuICAgICAgICAndHJpcCcsXG4gICAgICAgICdzMidcbiAgICAgIF1cbiAgICA+O1xuICAgIGNvbG9yQnk6IHouWm9kT3B0aW9uYWw8ei5ab2RTdHJpbmc+O1xuICAgIGNvbG9yVHlwZTogei5ab2RPcHRpb25hbDx6LlpvZEVudW08WydicmVha3MnLCAndW5pcXVlJ10+PjtcbiAgICBjb2xvck1hcDogei5ab2RPcHRpb25hbDxcbiAgICAgIHouWm9kQXJyYXk8XG4gICAgICAgIHouWm9kT2JqZWN0PHtcbiAgICAgICAgICB2YWx1ZTogei5ab2RVbmlvbjxbei5ab2RTdHJpbmcsIHouWm9kTnVtYmVyLCB6LlpvZE51bGxdPjtcbiAgICAgICAgICBjb2xvcjogei5ab2RTdHJpbmc7XG4gICAgICAgIH0+XG4gICAgICA+XG4gICAgPjtcbiAgfT4sXG4gIC8vIHJldHVybiB0eXBlXG4gIEV4ZWN1dGVBZGRMYXllclJlc3VsdFsnbGxtUmVzdWx0J10sXG4gIC8vIGFkZGl0aW9uYWwgZGF0YVxuICBFeGVjdXRlQWRkTGF5ZXJSZXN1bHRbJ2FkZGl0aW9uYWxEYXRhJ10sXG4gIC8vIGNvbnRleHRcbiAgQWRkTGF5ZXJGdW5jdGlvbkNvbnRleHRcbj4oe1xuICBkZXNjcmlwdGlvbjogYEFkZCBhIGtlcGxlci5nbCBtYXAgbGF5ZXIgZnJvbSBhIGRhdGFzZXQuXG5Zb3UgY2FuIGNyZWF0ZSBiYXNpYyBtYXAgbGF5ZXIgd2l0aG91dCBjb2xvciBzdHlsaW5nLCBvciBlbmhhbmNlZCBtYXAgbGF5ZXIgd2l0aCBjb2xvciB2aXN1YWxpemF0aW9uLlxuXG5Gb3IgYmFzaWMgbWFwczpcbi0gU2ltcGx5IHVzZSBkYXRhc2V0TmFtZSwgZ2VvbWV0cnlDb2x1bW4gKGlmIG5lZWRlZCksIGxhdGl0dWRlQ29sdW1uL2xvbmdpdHVkZUNvbHVtbiAoZm9yIHBvaW50IG1hcHMpLCBhbmQgbWFwVHlwZVxuLSBPbWl0IGNvbG9yLXJlbGF0ZWQgcGFyYW1ldGVycyBmb3Igc2ltcGxlIHZpc3VhbGl6YXRpb25cblxuRm9yIGNvbG9yZWQgbWFwczpcbi0gSWYgdXNlciByZXF1ZXN0cyBjb2xvciB2aXN1YWxpemF0aW9uLCB1c2UgYXZhaWxhYmxlIGNvbHVtbnMgaW4gdGhlIGRhdGFzZXRcbi0gVXNlIGRhdGFDbGFzc2lmeSB0b29sIHRvIGNsYXNzaWZ5IGRhdGEgaW50byBiaW5zIG9yIHVuaXF1ZSB2YWx1ZXMgd2hlbiBuZWVkZWRcbi0gSWYgZGF0YUNsYXNzaWZ5IHRvb2wgcmV0dXJucyBhIGxpc3Qgb2YgayBicmVha3NcbiAgYS4gRm9yIGEgbGlzdCBvZiBrIGJyZWFrIHZhbHVlcywgeW91IG11c3QgY3JlYXRlIGsrMSBlbnRyaWVzIGluIHRoZSBjb2xvck1hcCwgd2l0aCB0aGUgbGFzdCB2YWx1ZSBiZWluZyBudWxsLlxuICBiLiBGb3IgZXhhbXBsZTogZm9yIGJyZWFrcyA9IFswLCAzLCAxMF0sIHRoZSBjb2xvck1hcCBjb3VsZCBiZSBbe3ZhbHVlOiAwLCBjb2xvcjogJyMjZmZmN2JjJywgbGFiZWw6ICc8IDAnfSwge3ZhbHVlOiAzLCBjb2xvcjogJyNmZWM0NGYnLCBsYWJlbDogJ1swLTMpJ30sIHt2YWx1ZTogbnVsbCwgY29sb3I6ICcjZDk1ZjBlJywgbGFiZWw6ICc+PSAzJ31dXG4tIElmIGRhdGFDbGFzc2lmeSB0b29sIHJldHVybnMgYSBsaXN0IG9mIGsgdW5pcXVlIHZhbHVlc1xuICBhLiBUaGVyZSBzaG91bGQgYmUgayBjb2xvcnMgaW4gdGhlIGNvbG9yTWFwLiBGb3IgZXhhbXBsZTogZm9yIHVuaXF1ZVZhbHVlcyA9IFsnYScsICdiJywgJ2MnXSwgdGhlIGNvbG9yTWFwIGNvdWxkIGJlIFt7dmFsdWU6ICdhJywgY29sb3I6ICcjMWI5ZTc3J30sIHt2YWx1ZTogJ2InLCBjb2xvcjogJyNkOTVmMDInfSwge3ZhbHVlOiAnYycsIGNvbG9yOiAnIzc1NzBiMyd9XVxuLSBHZW5lcmF0ZSBjb2xvckJyZXdlciBjb2xvcnMgYXV0b21hdGljYWxseSBpZiB1c2VyIGRvZXNuJ3Qgc3BlY2lmeSBjb2xvcnNcblxuRm9yIGdlb2pzb24gZGF0YXNldHM6XG4tIFVzZSBnZW9tZXRyeUNvbHVtbjogJ19nZW9qc29uJyBhbmQgbWFwVHlwZTogJ2dlb2pzb24nIGV2ZW4gZm9yIHBvaW50IGNvbGxlY3Rpb25zXG5gLFxuICBwYXJhbWV0ZXJzOiB6Lm9iamVjdCh7XG4gICAgZGF0YXNldE5hbWU6IHpcbiAgICAgIC5zdHJpbmcoKVxuICAgICAgLmRlc2NyaWJlKCdUaGUgbmFtZSBvZiB0aGUgZGF0YXNldC4gTm90ZTogcGxlYXNlIGRvIE5PVCB1c2UgdGhlIGRhdGFzZXRJZC4nKSxcbiAgICBsYXRpdHVkZUNvbHVtbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgIGxvbmdpdHVkZUNvbHVtbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICAgIGxheWVyTmFtZTogelxuICAgICAgLnN0cmluZygpXG4gICAgICAub3B0aW9uYWwoKVxuICAgICAgLmRlc2NyaWJlKCdJZiBwb3NzaWJsZSwgZ2VuZXJhdGUgYSBuYW1lIGZvciB0aGUgbGF5ZXIgYmFzZWQgb24gdGhlIGNvbnRleHQuJyksXG4gICAgbGF5ZXJUeXBlOiB6LmVudW0oW1xuICAgICAgJ3BvaW50JyxcbiAgICAgICdhcmMnLFxuICAgICAgJ2xpbmUnLFxuICAgICAgJ2dyaWQnLFxuICAgICAgJ2hleGFnb24nLFxuICAgICAgJ2dlb2pzb24nLFxuICAgICAgJ2NsdXN0ZXInLFxuICAgICAgJ2hlYXRtYXAnLFxuICAgICAgJ2gzJyxcbiAgICAgICd0cmlwJyxcbiAgICAgICdzMidcbiAgICBdKSxcbiAgICBjb2xvckJ5OiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gICAgY29sb3JUeXBlOiB6LmVudW0oWydicmVha3MnLCAndW5pcXVlJ10pLm9wdGlvbmFsKCksXG4gICAgY29sb3JNYXA6IHpcbiAgICAgIC5hcnJheShcbiAgICAgICAgei5vYmplY3Qoe1xuICAgICAgICAgIHZhbHVlOiB6LnVuaW9uKFt6LnN0cmluZygpLCB6Lm51bWJlcigpLCB6Lm51bGwoKV0pLFxuICAgICAgICAgIGNvbG9yOiB6LnN0cmluZygpXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAub3B0aW9uYWwoKVxuICB9KSxcbiAgZXhlY3V0ZTogZXhlY3V0ZUFkZExheWVyLFxuICBjb21wb25lbnQ6IEFkZExheWVyVG9vbENvbXBvbmVudFxufSk7XG5cbmV4cG9ydCB0eXBlIEFkZExheWVyVG9vbCA9IHR5cGVvZiBhZGRMYXllcjtcblxudHlwZSBBZGRMYXllckFyZ3MgPSB7XG4gIGRhdGFzZXROYW1lOiBzdHJpbmc7XG4gIGxheWVyTmFtZT86IHN0cmluZztcbiAgbGF5ZXJUeXBlOiBzdHJpbmc7XG4gIGxhdGl0dWRlQ29sdW1uPzogc3RyaW5nO1xuICBsb25naXR1ZGVDb2x1bW4/OiBzdHJpbmc7XG4gIGNvbG9yQnk/OiBzdHJpbmc7XG4gIGNvbG9yVHlwZT86IHN0cmluZztcbiAgY29sb3JNYXA/OiBBcnJheTx7dmFsdWU6IHN0cmluZyB8IG51bWJlciB8IG51bGw7IGNvbG9yOiBzdHJpbmc7IGxhYmVsPzogc3RyaW5nfT47XG59O1xuXG5mdW5jdGlvbiBpc0FkZExheWVyQXJncyhhcmdzOiBhbnkpOiBhcmdzIGlzIEFkZExheWVyQXJncyB7XG4gIHJldHVybiB0eXBlb2YgYXJncyA9PT0gJ29iamVjdCcgJiYgYXJncyAhPT0gbnVsbCAmJiAnZGF0YXNldE5hbWUnIGluIGFyZ3MgJiYgJ2xheWVyVHlwZScgaW4gYXJncztcbn1cblxudHlwZSBBZGRMYXllckZ1bmN0aW9uQ29udGV4dCA9IHtcbiAgZ2V0RGF0YXNldHM6ICgpID0+IERhdGFzZXRzO1xufTtcblxuZnVuY3Rpb24gaXNBZGRMYXllckZ1bmN0aW9uQ29udGV4dChjb250ZXh0OiBhbnkpOiBjb250ZXh0IGlzIEFkZExheWVyRnVuY3Rpb25Db250ZXh0IHtcbiAgcmV0dXJuIGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQuZ2V0RGF0YXNldHMgPT09ICdmdW5jdGlvbic7XG59XG5cbnR5cGUgRXhlY3V0ZUFkZExheWVyUmVzdWx0ID0ge1xuICBsbG1SZXN1bHQ6IHtcbiAgICBzdWNjZXNzOiBib29sZWFuO1xuICAgIGxheWVyPzogc3RyaW5nO1xuICAgIGRldGFpbHM/OiBzdHJpbmc7XG4gICAgZXJyb3I/OiBzdHJpbmc7XG4gICAgaW5zdHJ1Y3Rpb24/OiBzdHJpbmc7XG4gIH07XG4gIGFkZGl0aW9uYWxEYXRhPzoge1xuICAgIGxheWVyOiBvYmplY3Q7XG4gICAgZGF0YXNldElkOiBzdHJpbmc7XG4gIH07XG59O1xuXG5hc3luYyBmdW5jdGlvbiBleGVjdXRlQWRkTGF5ZXIoYXJncywgb3B0aW9ucyk6IFByb21pc2U8RXhlY3V0ZUFkZExheWVyUmVzdWx0PiB7XG4gIHRyeSB7XG4gICAgaWYgKCFpc0FkZExheWVyQXJncyhhcmdzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGFkZExheWVyIGFyZ3VtZW50cycpO1xuICAgIH1cblxuICAgIGlmICghaXNBZGRMYXllckZ1bmN0aW9uQ29udGV4dChvcHRpb25zLmNvbnRleHQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYWRkTGF5ZXIgY29udGV4dCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHtcbiAgICAgIGRhdGFzZXROYW1lLFxuICAgICAgbGF5ZXJOYW1lLFxuICAgICAgbGF0aXR1ZGVDb2x1bW4sXG4gICAgICBsb25naXR1ZGVDb2x1bW4sXG4gICAgICBsYXllclR5cGUsXG4gICAgICBjb2xvckJ5LFxuICAgICAgY29sb3JUeXBlLFxuICAgICAgY29sb3JNYXBcbiAgICB9ID0gYXJncztcblxuICAgIGNvbnN0IGRhdGFzZXRzID0gb3B0aW9ucy5jb250ZXh0LmdldERhdGFzZXRzKCk7XG5cbiAgICAvLyBjaGVjayBpZiBkYXRhc2V0IGV4aXN0cyBpbiBrZXBsZXIuZ2xcbiAgICBjb25zdCBkYXRhc2V0SWQgPSBPYmplY3Qua2V5cyhkYXRhc2V0cykuZmluZChkYXRhSWQgPT4gZGF0YXNldHNbZGF0YUlkXS5sYWJlbCA9PT0gZGF0YXNldE5hbWUpO1xuICAgIGlmICghZGF0YXNldElkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYERhdGFzZXQgJHtkYXRhc2V0TmFtZX0gbm90IGZvdW5kLmApO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGlmIGZpZWxkIGV4aXN0cyBpbiB0aGUgZGF0YXNldFxuICAgIGNvbnN0IGRhdGFzZXQgPSBkYXRhc2V0c1tkYXRhc2V0SWRdO1xuXG4gICAgLy8gY2hlY2sgaWYgbGF5ZXJUeXBlIGlzIHZhbGlkXG4gICAgbGV0IGxheWVyID0gZ3Vlc3NEZWZhdWx0TGF5ZXIoZGF0YXNldCwgbGF5ZXJUeXBlKTtcblxuICAgIGNvbnN0IGxheWVySWQgPSBsYXllcj8uaWQgfHwgYGxheWVyXyR7Z2VuZXJhdGVJZCgpfWA7XG5cbiAgICBpZiAoIWxheWVyKSB7XG4gICAgICAvLyBmb3IgcG9pbnQgbGF5ZXIsIHRyeSB0byBjcmVhdCBhIHBvaW50IGxheWVyIG1hbnVhbGx5IGlmIExMTSBzdWdnZ2VzdHMgTGF0L0xuZyBmaWVsZHNcbiAgICAgIGlmIChsYXllclR5cGUgPT09ICdwb2ludCcgJiYgbGF0aXR1ZGVDb2x1bW4gJiYgbG9uZ2l0dWRlQ29sdW1uKSB7XG4gICAgICAgIGxheWVyID0ge1xuICAgICAgICAgIGlkOiBsYXllcklkLFxuICAgICAgICAgIHR5cGU6ICdwb2ludCcsXG4gICAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgICBkYXRhSWQ6IGRhdGFzZXRJZCxcbiAgICAgICAgICAgIGxhYmVsOiBsYXllck5hbWUgfHwgYCR7ZGF0YXNldE5hbWV9LSR7bGF5ZXJUeXBlfWAsXG4gICAgICAgICAgICBjb2x1bW5zOiB7XG4gICAgICAgICAgICAgIGxhdDoge3ZhbHVlOiBsYXRpdHVkZUNvbHVtbiwgZmllbGRJZHg6IGRhdGFzZXQuZ2V0Q29sdW1uRmllbGRJZHgobGF0aXR1ZGVDb2x1bW4pfSxcbiAgICAgICAgICAgICAgbG5nOiB7dmFsdWU6IGxvbmdpdHVkZUNvbHVtbiwgZmllbGRJZHg6IGRhdGFzZXQuZ2V0Q29sdW1uRmllbGRJZHgobG9uZ2l0dWRlQ29sdW1uKX1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIHZpc0NvbmZpZzoge1xuICAgICAgICAgICAgY29sb3JSYW5nZToge1xuICAgICAgICAgICAgICBuYW1lOiAnSWNlIEFuZCBGaXJlJyxcbiAgICAgICAgICAgICAgdHlwZTogJ2RpdmVyZ2luZycsXG4gICAgICAgICAgICAgIGNhdGVnb3J5OiAnVWJlcicsXG4gICAgICAgICAgICAgIGNvbG9yczogWycjRDUwMjU1JywgJyNGRUFENTQnLCAnI0ZFRURCMScsICcjRThGRUI1JywgJyM0OUUzQ0UnLCAnIzAxOThCRCddXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGFzIGFueTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFsYXllcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGxheWVyIHR5cGU6ICR7bGF5ZXJUeXBlfS5gKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2x1bW5zID0gbGF5ZXI/LmNvbmZpZz8uY29sdW1ucyB8fCB7fTtcblxuICAgIC8vIGNvbnN0cnVjdCBuZXcgbGF5ZXIgY29uZmlnIGZvciBhZGRMYXllcigpIGFjdGlvblxuICAgIGNvbnN0IG5ld0xheWVyID0ge1xuICAgICAgaWQ6IGxheWVySWQsXG4gICAgICB0eXBlOiBsYXllci50eXBlLFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIC4uLmxheWVyLmNvbmZpZyxcbiAgICAgICAgZGF0YUlkOiBkYXRhc2V0SWQsXG4gICAgICAgIGxhYmVsOiBsYXllck5hbWUgfHwgYCR7ZGF0YXNldE5hbWV9LSR7bGF5ZXJUeXBlfWAsXG4gICAgICAgIGNvbHVtbnM6IE9iamVjdC5rZXlzKGNvbHVtbnMpLnJlZHVjZSgoYWNjLCBrZXkpID0+IHtcbiAgICAgICAgICBjb25zdCBjb2x1bW4gPSBjb2x1bW5zW2tleV07XG4gICAgICAgICAgaWYgKGNvbHVtbikge1xuICAgICAgICAgICAgYWNjW2tleV0gPSBjb2x1bW4udmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIH0sIHt9KVxuICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoY29sb3JCeSkge1xuICAgICAgY29uc3QgY29sb3JGaWVsZCA9IGRhdGFzZXQuZmllbGRzLmZpbmQoZiA9PiBmLm5hbWUgPT09IGNvbG9yQnkpO1xuICAgICAgaWYgKCFjb2xvckZpZWxkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgJHtjb2xvckJ5fSBub3QgZm91bmQuYCk7XG4gICAgICB9XG4gICAgICAvLyBjcmVhdGUga2VwbGVyLmdsJ3MgY29sb3JNYXAgZnJvbSB1bmlxdWVWYWx1ZXMgYW5kIGJyZWFrc1xuICAgICAgY29uc3QgY29sb3JTY2FsZSA9IGNvbG9yVHlwZSA9PT0gJ2JyZWFrcycgPyAnY3VzdG9tJyA6ICdjdXN0b21PcmRpbmFsJztcbiAgICAgIGNvbnN0IGNvbG9ycyA9IGNvbG9yTWFwPy5tYXAoY29sb3IgPT4gY29sb3IuY29sb3IpO1xuICAgICAgY29uc3Qga2VwbGVyQ29sb3JNYXAgPSBjb2xvck1hcD8ubWFwKGNvbG9yID0+IFtjb2xvci52YWx1ZSwgY29sb3IuY29sb3JdKTtcbiAgICAgIGNvbnN0IGNvbG9yUmFuZ2UgPSB7XG4gICAgICAgIG5hbWU6ICdjb2xvci5jdXN0b21QYWxldHRlJyxcbiAgICAgICAgdHlwZTogJ2N1c3RvbScsXG4gICAgICAgIGNhdGVnb3J5OiAnQ3VzdG9tJyxcbiAgICAgICAgY29sb3JzLFxuICAgICAgICBjb2xvck1hcDoga2VwbGVyQ29sb3JNYXBcbiAgICAgIH07XG5cbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snY29sb3JTY2FsZSddID0gY29sb3JTY2FsZTtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snY29sb3JGaWVsZCddID0gY29sb3JGaWVsZDtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snc3Ryb2tlQ29sb3JTY2FsZSddID0gY29sb3JTY2FsZTtcbiAgICAgIG5ld0xheWVyLmNvbmZpZ1snc3Ryb2tlQ29sb3JGaWVsZCddID0gY29sb3JGaWVsZDtcbiAgICAgIG5ld0xheWVyLmNvbmZpZy52aXNDb25maWdbJ2NvbG9yUmFuZ2UnXSA9IGNvbG9yUmFuZ2U7XG4gICAgICBuZXdMYXllci5jb25maWcudmlzQ29uZmlnWydzdHJva2VDb2xvclJhbmdlJ10gPSBjb2xvclJhbmdlO1xuICAgICAgbmV3TGF5ZXIuY29uZmlnWyd2aXN1YWxDaGFubmVscyddID0ge1xuICAgICAgICBjb2xvckZpZWxkOiB7XG4gICAgICAgICAgbmFtZTogY29sb3JCeSxcbiAgICAgICAgICB0eXBlOiBjb2xvckZpZWxkPy50eXBlXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yU2NhbGVcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxsbVJlc3VsdDoge1xuICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICBsYXllcjogSlNPTi5zdHJpbmdpZnkobmV3TGF5ZXIpLFxuICAgICAgICBkZXRhaWxzOiBgbWFwIGxheWVyICR7bGF5ZXJJZH0gd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwLmBcbiAgICAgIH0sXG4gICAgICBhZGRpdGlvbmFsRGF0YToge1xuICAgICAgICBsYXllcjogbmV3TGF5ZXIsXG4gICAgICAgIGRhdGFzZXRJZFxuICAgICAgfVxuICAgIH07XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxsbVJlc3VsdDoge1xuICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogJ1Vua25vd24gZXJyb3InLFxuICAgICAgICBpbnN0cnVjdGlvbjpcbiAgICAgICAgICAnVHJ5IHRvIGZpeCB0aGUgZXJyb3IuIElmIHRoZSBlcnJvciBwZXJzaXN0cywgcGF1c2UgdGhlIGV4ZWN1dGlvbiBhbmQgYXNrIHRoZSB1c2VyIHRvIHRyeSB3aXRoIGRpZmZlcmVudCBwcm9tcHQgYW5kIGNvbnRleHQuJ1xuICAgICAgfVxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGd1ZXNzRGVmYXVsdExheWVyKGRhdGFzZXQ6IEtlcGxlclRhYmxlLCBsYXllclR5cGU6IHN0cmluZykge1xuICAvLyBzcGVjaWFsIGNhc2UgZm9yIGhleGFnb24gbGF5ZXIsIHdoaWNoIGNvdWxkIGJlIGltcGxlbWVudGVkIGFzIGZpbmREZWZhdWx0TGF5ZXJQcm9wcygpIGluIGhleGFnb24tbGF5ZXIudHN4XG4gIGlmIChsYXllclR5cGUgPT09ICdoZXhhZ29uJykge1xuICAgIGlmIChkYXRhc2V0LmZpZWxkUGFpcnMgJiYgZGF0YXNldC5maWVsZFBhaXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHByb3BzID0gZGF0YXNldC5maWVsZFBhaXJzLm1hcChmaWVsZFBhaXIgPT4gKHtcbiAgICAgICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgICAgICBsYWJlbDogJ0hleGJpbicsXG4gICAgICAgIGNvbHVtbnM6IGZpZWxkUGFpci5wYWlyXG4gICAgICB9KSk7XG4gICAgICBjb25zdCBsYXllciA9IG5ldyBMYXllckNsYXNzZXMuaGV4YWdvbihwcm9wc1swXSk7XG4gICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuICB9XG4gIGNvbnN0IGRlZmF1bHRMYXllcnMgPSBmaW5kRGVmYXVsdExheWVyKGRhdGFzZXQsIExheWVyQ2xhc3Nlcyk7XG4gIGNvbnN0IGxheWVyID0gZGVmYXVsdExheWVycy5maW5kKGwgPT4gbC50eXBlID09PSBsYXllclR5cGUpO1xuICByZXR1cm4gbGF5ZXIgfHwgZGVmYXVsdExheWVycy5sZW5ndGggPiAwID8gZGVmYXVsdExheWVyc1swXSA6IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBBZGRMYXllclRvb2xDb21wb25lbnQoe2xheWVyLCBkYXRhc2V0SWR9KSB7XG4gIGNvbnN0IGRpc3BhdGNoID0gdXNlRGlzcGF0Y2goKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGRpc3BhdGNoKGFkZExheWVyQWN0aW9uKGxheWVyLCBkYXRhc2V0SWQpKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1k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
;