kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
308 lines (262 loc) • 32.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.aggregateRequiredColumns = exports.getValueAggr = exports.pointPosResolver = exports.pointPosAccessor = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _lodash = _interopRequireDefault(require("lodash.memoize"));
var _baseLayer = _interopRequireDefault(require("./base-layer"));
var _colorUtils = require("../utils/color-utils");
var _aggregateUtils = require("../utils/aggregate-utils");
var _defaultSettings = require("../constants/default-settings");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var pointPosAccessor = function pointPosAccessor(_ref) {
var lat = _ref.lat,
lng = _ref.lng;
return function (d) {
return [d[lng.fieldIdx], d[lat.fieldIdx]];
};
};
exports.pointPosAccessor = pointPosAccessor;
var pointPosResolver = function pointPosResolver(_ref2) {
var lat = _ref2.lat,
lng = _ref2.lng;
return "".concat(lat.fieldIdx, "-").concat(lng.fieldIdx);
};
exports.pointPosResolver = pointPosResolver;
var getValueAggr = function getValueAggr(field, aggregation) {
return function (points) {
return (0, _aggregateUtils.aggregate)(points.map(function (p) {
return p[field.tableFieldIndex - 1];
}), aggregation);
};
};
exports.getValueAggr = getValueAggr;
var aggrResolver = function aggrResolver(field, aggregation) {
return "".concat(field.name, "-").concat(aggregation);
};
var getLayerColorRange = function getLayerColorRange(colorRange) {
return colorRange.colors.map(_colorUtils.hexToRgb);
};
var aggregateRequiredColumns = ['lat', 'lng'];
exports.aggregateRequiredColumns = aggregateRequiredColumns;
var AggregationLayer =
/*#__PURE__*/
function (_Layer) {
(0, _inherits2["default"])(AggregationLayer, _Layer);
function AggregationLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, AggregationLayer);
_this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(AggregationLayer).call(this, props));
_this.getPosition = (0, _lodash["default"])(pointPosAccessor, pointPosResolver);
_this.getColorValue = (0, _lodash["default"])(getValueAggr, aggrResolver);
_this.getColorRange = (0, _lodash["default"])(getLayerColorRange);
_this.getElevationValue = (0, _lodash["default"])(getValueAggr, aggrResolver);
return _this;
}
(0, _createClass2["default"])(AggregationLayer, [{
key: "getVisualChannelDescription",
/**
* Get the description of a visualChannel config
* @param key
* @returns {{label: string, measure: (string|string)}}
*/
value: function getVisualChannelDescription(key) {
// e.g. label: Color, measure: Average of ETA
// console.log('inside getVisualChannelDescription', key);
var _this$visualChannels$ = this.visualChannels[key],
range = _this$visualChannels$.range,
field = _this$visualChannels$.field,
defaultMeasure = _this$visualChannels$.defaultMeasure,
aggregation = _this$visualChannels$.aggregation;
return {
label: this.visConfigSettings[range].label,
measure: this.config[field] ? "".concat(this.config.visConfig[aggregation], " of ").concat(this.config[field].name) : defaultMeasure
};
}
}, {
key: "getHoverData",
value: function getHoverData(object) {
// return aggregated object
return object;
}
/**
* Aggregation layer handles visual channel aggregation inside deck.gl layer
*/
}, {
key: "updateLayerVisualChannel",
value: function updateLayerVisualChannel(_ref3, channel) {
var data = _ref3.data,
allData = _ref3.allData;
this.validateVisualChannel(channel);
}
/**
* Validate aggregation type on top of basic layer visual channel validation
* @param channel
*/
}, {
key: "validateVisualChannel",
value: function validateVisualChannel(channel) {
// field type decides aggregation type decides scale type
this.validateFieldType(channel);
this.validateAggregationType(channel);
this.validateScale(channel);
}
/**
* Validate aggregation type based on selected field
*/
}, {
key: "validateAggregationType",
value: function validateAggregationType(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
aggregation = visualChannel.aggregation;
var aggregationOptions = this.getAggregationOptions(channel);
if (!aggregation) {
return;
}
if (!aggregationOptions.length) {
// if field cannot be aggregated, set field to null
this.updateLayerConfig((0, _defineProperty2["default"])({}, field, null));
} else if (!aggregationOptions.includes(this.config.visConfig[aggregation])) {
// current aggregation type is not supported by this field
// set aggregation to the first supported option
this.updateLayerVisConfig((0, _defineProperty2["default"])({}, aggregation, aggregationOptions[0]));
}
}
}, {
key: "getAggregationOptions",
value: function getAggregationOptions(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
channelScaleType = visualChannel.channelScaleType; // console.log("field and channelScaleType",field, channelScaleType )
return Object.keys(this.config[field] ? _defaultSettings.FIELD_OPTS[this.config[field].type].scale[channelScaleType] : _defaultSettings.DEFAULT_AGGREGATION[channelScaleType]);
}
/**
* Get scale options based on current field and aggregation type
* @param {string} channel
* @returns {string[]}
*/
}, {
key: "getScaleOptions",
value: function getScaleOptions(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
aggregation = visualChannel.aggregation,
channelScaleType = visualChannel.channelScaleType;
var aggregationType = this.config.visConfig[aggregation];
return this.config[field] ? // scale options based on aggregation
_defaultSettings.FIELD_OPTS[this.config[field].type].scale[channelScaleType][aggregationType] : // default scale options for point count
_defaultSettings.DEFAULT_AGGREGATION[channelScaleType][aggregationType];
}
/**
* Aggregation layer handles visual channel aggregation inside deck.gl layer
*/
}, {
key: "updateLayerDomain",
value: function updateLayerDomain(dataset, newFilter) {
return this;
}
}, {
key: "updateLayerMeta",
value: function updateLayerMeta(allData, getPosition) {
// get bounds from points
var bounds = this.getPointsBounds(allData, getPosition); // get lightSettings from points
var lightSettings = this.getLightSettingsFromBounds(bounds);
this.updateMeta({
bounds: bounds,
lightSettings: lightSettings
});
}
}, {
key: "formatLayerData",
value: function formatLayerData(_, allData, filteredIndex, oldLayerData) {
var opt = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
var getPosition = this.getPosition(this.config.columns);
if (!oldLayerData || oldLayerData.getPosition !== getPosition) {
this.updateLayerMeta(allData, getPosition);
}
var getColorValue = this.config.colorField ? this.getColorValue(this.config.colorField, this.config.visConfig.colorAggregation) : undefined; // console.log('getColorValue inside aggregation Layer', getColorValue);
var getElevationValue = this.config.sizeField ? this.getElevationValue(this.config.sizeField, this.config.visConfig.sizeAggregation) : undefined;
var data;
if (oldLayerData && oldLayerData.data && opt.sameData && oldLayerData.getPosition === getPosition) {
data = oldLayerData.data;
} else {
data = filteredIndex.map(function (i) {
return allData[i];
});
}
return _objectSpread({
data: data,
getPosition: getPosition
}, getColorValue ? {
getColorValue: getColorValue
} : {}, {}, getElevationValue ? {
getElevationValue: getElevationValue
} : {});
}
}, {
key: "isAggregated",
get: function get() {
return true;
}
}, {
key: "requiredLayerColumns",
get: function get() {
return aggregateRequiredColumns;
}
}, {
key: "columnPairs",
get: function get() {
return this.defaultPointColumnPairs;
}
}, {
key: "noneLayerDataAffectingProps",
get: function get() {
return [].concat((0, _toConsumableArray2["default"])((0, _get2["default"])((0, _getPrototypeOf2["default"])(AggregationLayer.prototype), "noneLayerDataAffectingProps", this)), ['enable3d', 'colorRange', 'colorScale', 'colorDomain', 'sizeRange', 'sizeScale', 'sizeDomain', 'percentile', 'coverage', 'elevationPercentile', 'elevationScale']);
}
}, {
key: "visualChannels",
get: function get() {
return {
color: {
aggregation: 'colorAggregation',
channelScaleType: _defaultSettings.CHANNEL_SCALES.colorAggr,
defaultMeasure: 'Point Count',
domain: 'colorDomain',
field: 'colorField',
key: 'color',
property: 'color',
range: 'colorRange',
scale: 'colorScale'
},
size: {
aggregation: 'sizeAggregation',
channelScaleType: _defaultSettings.CHANNEL_SCALES.sizeAggr,
condition: function condition(config) {
return config.visConfig.enable3d;
},
defaultMeasure: 'Point Count',
domain: 'sizeDomain',
field: 'sizeField',
key: 'size',
property: 'height',
range: 'sizeRange',
scale: 'sizeScale'
}
};
}
}]);
return AggregationLayer;
}(_baseLayer["default"]);
exports["default"] = AggregationLayer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sYXllcnMvYWdncmVnYXRpb24tbGF5ZXIuanMiXSwibmFtZXMiOlsicG9pbnRQb3NBY2Nlc3NvciIsImxhdCIsImxuZyIsImQiLCJmaWVsZElkeCIsInBvaW50UG9zUmVzb2x2ZXIiLCJnZXRWYWx1ZUFnZ3IiLCJmaWVsZCIsImFnZ3JlZ2F0aW9uIiwicG9pbnRzIiwibWFwIiwicCIsInRhYmxlRmllbGRJbmRleCIsImFnZ3JSZXNvbHZlciIsIm5hbWUiLCJnZXRMYXllckNvbG9yUmFuZ2UiLCJjb2xvclJhbmdlIiwiY29sb3JzIiwiaGV4VG9SZ2IiLCJhZ2dyZWdhdGVSZXF1aXJlZENvbHVtbnMiLCJBZ2dyZWdhdGlvbkxheWVyIiwicHJvcHMiLCJnZXRQb3NpdGlvbiIsImdldENvbG9yVmFsdWUiLCJnZXRDb2xvclJhbmdlIiwiZ2V0RWxldmF0aW9uVmFsdWUiLCJrZXkiLCJ2aXN1YWxDaGFubmVscyIsInJhbmdlIiwiZGVmYXVsdE1lYXN1cmUiLCJsYWJlbCIsInZpc0NvbmZpZ1NldHRpbmdzIiwibWVhc3VyZSIsImNvbmZpZyIsInZpc0NvbmZpZyIsIm9iamVjdCIsImNoYW5uZWwiLCJkYXRhIiwiYWxsRGF0YSIsInZhbGlkYXRlVmlzdWFsQ2hhbm5lbCIsInZhbGlkYXRlRmllbGRUeXBlIiwidmFsaWRhdGVBZ2dyZWdhdGlvblR5cGUiLCJ2YWxpZGF0ZVNjYWxlIiwidmlzdWFsQ2hhbm5lbCIsImFnZ3JlZ2F0aW9uT3B0aW9ucyIsImdldEFnZ3JlZ2F0aW9uT3B0aW9ucyIsImxlbmd0aCIsInVwZGF0ZUxheWVyQ29uZmlnIiwiaW5jbHVkZXMiLCJ1cGRhdGVMYXllclZpc0NvbmZpZyIsImNoYW5uZWxTY2FsZVR5cGUiLCJPYmplY3QiLCJrZXlzIiwiRklFTERfT1BUUyIsInR5cGUiLCJzY2FsZSIsIkRFRkFVTFRfQUdHUkVHQVRJT04iLCJhZ2dyZWdhdGlvblR5cGUiLCJkYXRhc2V0IiwibmV3RmlsdGVyIiwiYm91bmRzIiwiZ2V0UG9pbnRzQm91bmRzIiwibGlnaHRTZXR0aW5ncyIsImdldExpZ2h0U2V0dGluZ3NGcm9tQm91bmRzIiwidXBkYXRlTWV0YSIsIl8iLCJmaWx0ZXJlZEluZGV4Iiwib2xkTGF5ZXJEYXRhIiwib3B0IiwiY29sdW1ucyIsInVwZGF0ZUxheWVyTWV0YSIsImNvbG9yRmllbGQiLCJjb2xvckFnZ3JlZ2F0aW9uIiwidW5kZWZpbmVkIiwic2l6ZUZpZWxkIiwic2l6ZUFnZ3JlZ2F0aW9uIiwic2FtZURhdGEiLCJpIiwiZGVmYXVsdFBvaW50Q29sdW1uUGFpcnMiLCJjb2xvciIsIkNIQU5ORUxfU0NBTEVTIiwiY29sb3JBZ2dyIiwiZG9tYWluIiwicHJvcGVydHkiLCJzaXplIiwic2l6ZUFnZ3IiLCJjb25kaXRpb24iLCJlbmFibGUzZCIsIkxheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7QUFNTyxJQUFNQSxnQkFBZ0IsR0FBRyxTQUFuQkEsZ0JBQW1CO0FBQUEsTUFBRUMsR0FBRixRQUFFQSxHQUFGO0FBQUEsTUFBT0MsR0FBUCxRQUFPQSxHQUFQO0FBQUEsU0FBZ0IsVUFBQUMsQ0FBQztBQUFBLFdBQUksQ0FDbkRBLENBQUMsQ0FBQ0QsR0FBRyxDQUFDRSxRQUFMLENBRGtELEVBRW5ERCxDQUFDLENBQUNGLEdBQUcsQ0FBQ0csUUFBTCxDQUZrRCxDQUFKO0FBQUEsR0FBakI7QUFBQSxDQUF6Qjs7OztBQUtBLElBQU1DLGdCQUFnQixHQUFHLFNBQW5CQSxnQkFBbUI7QUFBQSxNQUFFSixHQUFGLFNBQUVBLEdBQUY7QUFBQSxNQUFPQyxHQUFQLFNBQU9BLEdBQVA7QUFBQSxtQkFDM0JELEdBQUcsQ0FBQ0csUUFEdUIsY0FDWEYsR0FBRyxDQUFDRSxRQURPO0FBQUEsQ0FBekI7Ozs7QUFHQSxJQUFNRSxZQUFZLEdBQUcsU0FBZkEsWUFBZSxDQUFDQyxLQUFELEVBQVFDLFdBQVI7QUFBQSxTQUF3QixVQUFBQyxNQUFN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OEIsZ0NBQWVDLFNBRjVCO0FBR0xwRCxVQUFBQSxjQUFjLEVBQUUsYUFIWDtBQUlMcUQsVUFBQUEsTUFBTSxFQUFFLGFBSkg7QUFLTDNFLFVBQUFBLEtBQUssRUFBRSxZQUxGO0FBTUxtQixVQUFBQSxHQUFHLEVBQUUsT0FOQTtBQU9MeUQsVUFBQUEsUUFBUSxFQUFFLE9BUEw7QUFRTHZELFVBQUFBLEtBQUssRUFBRSxZQVJGO0FBU0wyQixVQUFBQSxLQUFLLEVBQUU7QUFURixTQURGO0FBWUw2QixRQUFBQSxJQUFJLEVBQUU7QUFDSjVFLFVBQUFBLFdBQVcsRUFBRSxpQkFEVDtBQUVKMEMsVUFBQUEsZ0JBQWdCLEVBQUU4QixnQ0FBZUssUUFGN0I7QUFHSkMsVUFBQUEsU0FBUyxFQUFFLG1CQUFBckQsTUFBTTtBQUFBLG1CQUFJQSxNQUFNLENBQUNDLFNBQVAsQ0FBaUJxRCxRQUFyQjtBQUFBLFdBSGI7QUFJSjFELFVBQUFBLGNBQWMsRUFBRSxhQUpaO0FBS0pxRCxVQUFBQSxNQUFNLEVBQUUsWUFMSjtBQU1KM0UsVUFBQUEsS0FBSyxFQUFFLFdBTkg7QUFPSm1CLFVBQUFBLEdBQUcsRUFBRSxNQVBEO0FBUUp5RCxVQUFBQSxRQUFRLEVBQUUsUUFSTjtBQVNKdkQsVUFBQUEsS0FBSyxFQUFFLFdBVEg7QUFVSjJCLFVBQUFBLEtBQUssRUFBRTtBQVZIO0FBWkQsT0FBUDtBQXlCRDs7O0VBakUyQ2lDLHFCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDE5IFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IG1lbW9pemUgZnJvbSAnbG9kYXNoLm1lbW9pemUnO1xuaW1wb3J0IExheWVyIGZyb20gJy4vYmFzZS1sYXllcic7XG5pbXBvcnQge2hleFRvUmdifSBmcm9tICd1dGlscy9jb2xvci11dGlscyc7XG5pbXBvcnQge2FnZ3JlZ2F0ZX0gZnJvbSAndXRpbHMvYWdncmVnYXRlLXV0aWxzJztcbmltcG9ydCB7XG4gIENIQU5ORUxfU0NBTEVTLFxuICBGSUVMRF9PUFRTLFxuICBERUZBVUxUX0FHR1JFR0FUSU9OXG59IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcblxuZXhwb3J0IGNvbnN0IHBvaW50UG9zQWNjZXNzb3IgPSAoe2xhdCwgbG5nfSkgPT4gZCA9PiBbXG4gIGRbbG5nLmZpZWxkSWR4XSxcbiAgZFtsYXQuZmllbGRJZHhdXG5dO1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NSZXNvbHZlciA9ICh7bGF0LCBsbmd9KSA9PlxuICBgJHtsYXQuZmllbGRJZHh9LSR7bG5nLmZpZWxkSWR4fWA7XG5cbmV4cG9ydCBjb25zdCBnZXRWYWx1ZUFnZ3IgPSAoZmllbGQsIGFnZ3JlZ2F0aW9uKSA9PiBwb2ludHMgPT5cbiAgYWdncmVnYXRlKHBvaW50cy5tYXAocCA9PiBwW2ZpZWxkLnRhYmxlRmllbGRJbmRleCAtIDFdKSwgYWdncmVnYXRpb24pO1xuXG5jb25zdCBhZ2dyUmVzb2x2ZXIgPSAoZmllbGQsIGFnZ3JlZ2F0aW9uKSA9PiBgJHtmaWVsZC5uYW1lfS0ke2FnZ3JlZ2F0aW9ufWA7XG5cbmNvbnN0IGdldExheWVyQ29sb3JSYW5nZSA9IGNvbG9yUmFuZ2UgPT4gY29sb3JSYW5nZS5jb2xvcnMubWFwKGhleFRvUmdiKTtcblxuZXhwb3J0IGNvbnN0IGFnZ3JlZ2F0ZVJlcXVpcmVkQ29sdW1ucyA9IFsnbGF0JywgJ2xuZyddO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBZ2dyZWdhdGlvbkxheWVyIGV4dGVuZHMgTGF5ZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcblxuICAgIHRoaXMuZ2V0UG9zaXRpb24gPSBtZW1vaXplKHBvaW50UG9zQWNjZXNzb3IsIHBvaW50UG9zUmVzb2x2ZXIpO1xuICAgIHRoaXMuZ2V0Q29sb3JWYWx1ZSA9IG1lbW9pemUoZ2V0VmFsdWVBZ2dyLCBhZ2dyUmVzb2x2ZXIpO1xuICAgIHRoaXMuZ2V0Q29sb3JSYW5nZSA9IG1lbW9pemUoZ2V0TGF5ZXJDb2xvclJhbmdlKTtcbiAgICB0aGlzLmdldEVsZXZhdGlvblZhbHVlID0gbWVtb2l6ZShnZXRWYWx1ZUFnZ3IsIGFnZ3JSZXNvbHZlcik7XG4gIH1cblxuICBnZXQgaXNBZ2dyZWdhdGVkKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZ2V0IHJlcXVpcmVkTGF5ZXJDb2x1bW5zKCkge1xuICAgIHJldHVybiBhZ2dyZWdhdGVSZXF1aXJlZENvbHVtbnM7XG4gIH1cblxuICBnZXQgY29sdW1uUGFpcnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGVmYXVsdFBvaW50Q29sdW1uUGFpcnM7XG4gIH1cblxuICBnZXQgbm9uZUxheWVyRGF0YUFmZmVjdGluZ1Byb3BzKCkge1xuICAgIHJldHVybiBbXG4gICAgICAuLi5zdXBlci5ub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMsXG4gICAgICAnZW5hYmxlM2QnLFxuICAgICAgJ2NvbG9yUmFuZ2UnLFxuICAgICAgJ2NvbG9yU2NhbGUnLFxuICAgICAgJ2NvbG9yRG9tYWluJyxcbiAgICAgICdzaXplUmFuZ2UnLFxuICAgICAgJ3NpemVTY2FsZScsXG4gICAgICAnc2l6ZURvbWFpbicsXG4gICAgICAncGVyY2VudGlsZScsXG4gICAgICAnY292ZXJhZ2UnLFxuICAgICAgJ2VsZXZhdGlvblBlcmNlbnRpbGUnLFxuICAgICAgJ2VsZXZhdGlvblNjYWxlJ1xuICAgIF07XG4gIH1cblxuICBnZXQgdmlzdWFsQ2hhbm5lbHMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbG9yOiB7XG4gICAgICAgIGFnZ3JlZ2F0aW9uOiAnY29sb3JBZ2dyZWdhdGlvbicsXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6IENIQU5ORUxfU0NBTEVTLmNvbG9yQWdncixcbiAgICAgICAgZGVmYXVsdE1lYXN1cmU6ICdQb2ludCBDb3VudCcsXG4gICAgICAgIGRvbWFpbjogJ2NvbG9yRG9tYWluJyxcbiAgICAgICAgZmllbGQ6ICdjb2xvckZpZWxkJyxcbiAgICAgICAga2V5OiAnY29sb3InLFxuICAgICAgICBwcm9wZXJ0eTogJ2NvbG9yJyxcbiAgICAgICAgcmFuZ2U6ICdjb2xvclJhbmdlJyxcbiAgICAgICAgc2NhbGU6ICdjb2xvclNjYWxlJ1xuICAgICAgfSxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgYWdncmVnYXRpb246ICdzaXplQWdncmVnYXRpb24nLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5zaXplQWdncixcbiAgICAgICAgY29uZGl0aW9uOiBjb25maWcgPT4gY29uZmlnLnZpc0NvbmZpZy5lbmFibGUzZCxcbiAgICAgICAgZGVmYXVsdE1lYXN1cmU6ICdQb2ludCBDb3VudCcsXG4gICAgICAgIGRvbWFpbjogJ3NpemVEb21haW4nLFxuICAgICAgICBmaWVsZDogJ3NpemVGaWVsZCcsXG4gICAgICAgIGtleTogJ3NpemUnLFxuICAgICAgICBwcm9wZXJ0eTogJ2hlaWdodCcsXG4gICAgICAgIHJhbmdlOiAnc2l6ZVJhbmdlJyxcbiAgICAgICAgc2NhbGU6ICdzaXplU2NhbGUnXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRlc2NyaXB0aW9uIG9mIGEgdmlzdWFsQ2hhbm5lbCBjb25maWdcbiAgICogQHBhcmFtIGtleVxuICAgKiBAcmV0dXJucyB7e2xhYmVsOiBzdHJpbmcsIG1lYXN1cmU6IChzdHJpbmd8c3RyaW5nKX19XG4gICAqL1xuICBnZXRWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24oa2V5KSB7XG4gICAgLy8gZS5nLiBsYWJlbDogQ29sb3IsIG1lYXN1cmU6IEF2ZXJhZ2Ugb2YgRVRBXG4gICAgLy8gY29uc29sZS5sb2coJ2luc2lkZSBnZXRWaXN1YWxDaGFubmVsRGVzY3JpcHRpb24nLCBrZXkpO1xuICAgIGNvbnN0IHtyYW5nZSwgZmllbGQsIGRlZmF1bHRNZWFzdXJlLCBhZ2dyZWdhdGlvbn0gPSB0aGlzLnZpc3VhbENoYW5uZWxzW1xuICAgICAga2V5XG4gICAgXTtcbiAgICByZXR1cm4ge1xuICAgICAgbGFiZWw6IHRoaXMudmlzQ29uZmlnU2V0dGluZ3NbcmFuZ2VdLmxhYmVsLFxuICAgICAgbWVhc3VyZTogdGhpcy5jb25maWdbZmllbGRdXG4gICAgICAgID8gYCR7dGhpcy5jb25maWcudmlzQ29uZmlnW2FnZ3JlZ2F0aW9uXX0gb2YgJHt0aGlzLmNvbmZpZ1tmaWVsZF0ubmFtZX1gXG4gICAgICAgIDogZGVmYXVsdE1lYXN1cmVcbiAgICB9O1xuICB9XG5cbiAgZ2V0SG92ZXJEYXRhKG9iamVjdCkge1xuICAgIC8vIHJldHVybiBhZ2dyZWdhdGVkIG9iamVjdFxuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cblxuICAvKipcbiAgICogQWdncmVnYXRpb24gbGF5ZXIgaGFuZGxlcyB2aXN1YWwgY2hhbm5lbCBhZ2dyZWdhdGlvbiBpbnNpZGUgZGVjay5nbCBsYXllclxuICAgKi9cbiAgdXBkYXRlTGF5ZXJWaXN1YWxDaGFubmVsKHtkYXRhLCBhbGxEYXRhfSwgY2hhbm5lbCkge1xuICAgIHRoaXMudmFsaWRhdGVWaXN1YWxDaGFubmVsKGNoYW5uZWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGFnZ3JlZ2F0aW9uIHR5cGUgb24gdG9wIG9mIGJhc2ljIGxheWVyIHZpc3VhbCBjaGFubmVsIHZhbGlkYXRpb25cbiAgICogQHBhcmFtIGNoYW5uZWxcbiAgICovXG4gIHZhbGlkYXRlVmlzdWFsQ2hhbm5lbChjaGFubmVsKSB7XG4gICAgLy8gZmllbGQgdHlwZSBkZWNpZGVzIGFnZ3JlZ2F0aW9uIHR5cGUgZGVjaWRlcyBzY2FsZSB0eXBlXG4gICAgdGhpcy52YWxpZGF0ZUZpZWxkVHlwZShjaGFubmVsKTtcbiAgICB0aGlzLnZhbGlkYXRlQWdncmVnYXRpb25UeXBlKGNoYW5uZWwpO1xuICAgIHRoaXMudmFsaWRhdGVTY2FsZShjaGFubmVsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBhZ2dyZWdhdGlvbiB0eXBlIGJhc2VkIG9uIHNlbGVjdGVkIGZpZWxkXG4gICAqL1xuICB2YWxpZGF0ZUFnZ3JlZ2F0aW9uVHlwZShjaGFubmVsKSB7XG4gICAgY29uc3QgdmlzdWFsQ2hhbm5lbCA9IHRoaXMudmlzdWFsQ2hhbm5lbHNbY2hhbm5lbF07XG4gICAgY29uc3Qge2ZpZWxkLCBhZ2dyZWdhdGlvbn0gPSB2aXN1YWxDaGFubmVsO1xuICAgIGNvbnN0IGFnZ3JlZ2F0aW9uT3B0aW9ucyA9IHRoaXMuZ2V0QWdncmVnYXRpb25PcHRpb25zKGNoYW5uZWwpO1xuXG4gICAgaWYgKCFhZ2dyZWdhdGlvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghYWdncmVnYXRpb25PcHRpb25zLmxlbmd0aCkge1xuICAgICAgLy8gaWYgZmllbGQgY2Fubm90IGJlIGFnZ3JlZ2F0ZWQsIHNldCBmaWVsZCB0byBudWxsXG4gICAgICB0aGlzLnVwZGF0ZUxheWVyQ29uZmlnKHtbZmllbGRdOiBudWxsfSk7XG4gICAgfSBlbHNlIGlmIChcbiAgICAgICFhZ2dyZWdhdGlvbk9wdGlvbnMuaW5jbHVkZXModGhpcy5jb25maWcudmlzQ29uZmlnW2FnZ3JlZ2F0aW9uXSlcbiAgICApIHtcbiAgICAgIC8vIGN1cnJlbnQgYWdncmVnYXRpb24gdHlwZSBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgZmllbGRcbiAgICAgIC8vIHNldCBhZ2dyZWdhdGlvbiB0byB0aGUgZmlyc3Qgc3VwcG9ydGVkIG9wdGlvblxuICAgICAgdGhpcy51cGRhdGVMYXllclZpc0NvbmZpZyh7W2FnZ3JlZ2F0aW9uXTogYWdncmVnYXRpb25PcHRpb25zWzBdfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0QWdncmVnYXRpb25PcHRpb25zKGNoYW5uZWwpIHtcbiAgICBjb25zdCB2aXN1YWxDaGFubmVsID0gdGhpcy52aXN1YWxDaGFubmVsc1tjaGFubmVsXTtcbiAgICBjb25zdCB7ZmllbGQsIGNoYW5uZWxTY2FsZVR5cGV9ID0gdmlzdWFsQ2hhbm5lbDtcbiAgICAvLyBjb25zb2xlLmxvZyhcImZpZWxkIGFuZCBjaGFubmVsU2NhbGVUeXBlXCIsZmllbGQsIGNoYW5uZWxTY2FsZVR5cGUgKVxuICAgIHJldHVybiBPYmplY3Qua2V5cyhcbiAgICAgIHRoaXMuY29uZmlnW2ZpZWxkXVxuICAgICAgICA/IEZJRUxEX09QVFNbdGhpcy5jb25maWdbZmllbGRdLnR5cGVdLnNjYWxlW2NoYW5uZWxTY2FsZVR5cGVdXG4gICAgICAgIDogREVGQVVMVF9BR0dSRUdBVElPTltjaGFubmVsU2NhbGVUeXBlXVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNjYWxlIG9wdGlvbnMgYmFzZWQgb24gY3VycmVudCBmaWVsZCBhbmQgYWdncmVnYXRpb24gdHlwZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbFxuICAgKiBAcmV0dXJucyB7c3RyaW5nW119XG4gICAqL1xuICBnZXRTY2FsZU9wdGlvbnMoY2hhbm5lbCkge1xuICAgIGNvbnN0IHZpc3VhbENoYW5uZWwgPSB0aGlzLnZpc3VhbENoYW5uZWxzW2NoYW5uZWxdO1xuICAgIGNvbnN0IHtmaWVsZCwgYWdncmVnYXRpb24sIGNoYW5uZWxTY2FsZVR5cGV9ID0gdmlzdWFsQ2hhbm5lbDtcbiAgICBjb25zdCBhZ2dyZWdhdGlvblR5cGUgPSB0aGlzLmNvbmZpZy52aXNDb25maWdbYWdncmVnYXRpb25dO1xuICAgIHJldHVybiB0aGlzLmNvbmZpZ1tmaWVsZF1cbiAgICAgID8gLy8gc2NhbGUgb3B0aW9ucyBiYXNlZCBvbiBhZ2dyZWdhdGlvblxuICAgICAgICBGSUVMRF9PUFRTW3RoaXMuY29uZmlnW2ZpZWxkXS50eXBlXS5zY2FsZVtjaGFubmVsU2NhbGVUeXBlXVtcbiAgICAgICAgICBhZ2dyZWdhdGlvblR5cGVcbiAgICAgICAgXVxuICAgICAgOiAvLyBkZWZhdWx0IHNjYWxlIG9wdGlvbnMgZm9yIHBvaW50IGNvdW50XG4gICAgICAgIERFRkFVTFRfQUdHUkVHQVRJT05bY2hhbm5lbFNjYWxlVHlwZV1bYWdncmVnYXRpb25UeXBlXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZ2dyZWdhdGlvbiBsYXllciBoYW5kbGVzIHZpc3VhbCBjaGFubmVsIGFnZ3JlZ2F0aW9uIGluc2lkZSBkZWNrLmdsIGxheWVyXG4gICAqL1xuICB1cGRhdGVMYXllckRvbWFpbihkYXRhc2V0LCBuZXdGaWx0ZXIpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHVwZGF0ZUxheWVyTWV0YShhbGxEYXRhLCBnZXRQb3NpdGlvbikge1xuICAgIC8vIGdldCBib3VuZHMgZnJvbSBwb2ludHNcbiAgICBjb25zdCBib3VuZHMgPSB0aGlzLmdldFBvaW50c0JvdW5kcyhhbGxEYXRhLCBnZXRQb3NpdGlvbik7XG5cbiAgICAvLyBnZXQgbGlnaHRTZXR0aW5ncyBmcm9tIHBvaW50c1xuICAgIGNvbnN0IGxpZ2h0U2V0dGluZ3MgPSB0aGlzLmdldExpZ2h0U2V0dGluZ3NGcm9tQm91bmRzKGJvdW5kcyk7XG5cbiAgICB0aGlzLnVwZGF0ZU1ldGEoe2JvdW5kcywgbGlnaHRTZXR0aW5nc30pO1xuICB9XG5cbiAgZm9ybWF0TGF5ZXJEYXRhKF8sIGFsbERhdGEsIGZpbHRlcmVkSW5kZXgsIG9sZExheWVyRGF0YSwgb3B0ID0ge30pIHtcbiAgICBjb25zdCBnZXRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24odGhpcy5jb25maWcuY29sdW1ucyk7XG5cbiAgICBpZiAoIW9sZExheWVyRGF0YSB8fCBvbGRMYXllckRhdGEuZ2V0UG9zaXRpb24gIT09IGdldFBvc2l0aW9uKSB7XG4gICAgICB0aGlzLnVwZGF0ZUxheWVyTWV0YShhbGxEYXRhLCBnZXRQb3NpdGlvbik7XG4gICAgfVxuXG4gICAgY29uc3QgZ2V0Q29sb3JWYWx1ZSA9IHRoaXMuY29uZmlnLmNvbG9yRmllbGRcbiAgICAgID8gdGhpcy5nZXRDb2xvclZhbHVlKFxuICAgICAgICAgIHRoaXMuY29uZmlnLmNvbG9yRmllbGQsXG4gICAgICAgICAgdGhpcy5jb25maWcudmlzQ29uZmlnLmNvbG9yQWdncmVnYXRpb25cbiAgICAgICAgKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgLy8gY29uc29sZS5sb2coJ2dldENvbG9yVmFsdWUgaW5zaWRlIGFnZ3JlZ2F0aW9uIExheWVyJywgZ2V0Q29sb3JWYWx1ZSk7XG5cbiAgICBjb25zdCBnZXRFbGV2YXRpb25WYWx1ZSA9IHRoaXMuY29uZmlnLnNpemVGaWVsZFxuICAgICAgPyB0aGlzLmdldEVsZXZhdGlvblZhbHVlKFxuICAgICAgICAgIHRoaXMuY29uZmlnLnNpemVGaWVsZCxcbiAgICAgICAgICB0aGlzLmNvbmZpZy52aXNDb25maWcuc2l6ZUFnZ3JlZ2F0aW9uXG4gICAgICAgIClcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgbGV0IGRhdGE7XG4gICAgaWYgKFxuICAgICAgb2xkTGF5ZXJEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZGF0YSAmJlxuICAgICAgb3B0LnNhbWVEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZ2V0UG9zaXRpb24gPT09IGdldFBvc2l0aW9uXG4gICAgKSB7XG4gICAgICBkYXRhID0gb2xkTGF5ZXJEYXRhLmRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGEgPSBmaWx0ZXJlZEluZGV4Lm1hcChpID0+IGFsbERhdGFbaV0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgZ2V0UG9zaXRpb24sXG4gICAgICAuLi4oZ2V0Q29sb3JWYWx1ZSA/IHtnZXRDb2xvclZhbHVlfSA6IHt9KSxcbiAgICAgIC4uLihnZXRFbGV2YXRpb25WYWx1ZSA/IHtnZXRFbGV2YXRpb25WYWx1ZX0gOiB7fSlcbiAgICB9O1xuICB9XG59XG4iXX0=