kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
377 lines (319 loc) • 40.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.pointVisConfigs = exports.pointOptionalColumns = exports.pointRequiredColumns = exports.pointLabelResolver = exports.pointLabelAccessor = 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 _baseLayer = _interopRequireDefault(require("../base-layer"));
var _lodash = _interopRequireDefault(require("lodash.memoize"));
var _deck = require("deck.gl");
var _scatterplotBrushingLayer = _interopRequireDefault(require("../../deckgl-layers/scatterplot-brushing-layer/scatterplot-brushing-layer"));
var _lodash2 = _interopRequireDefault(require("lodash.uniq"));
var _colorUtils = require("../../utils/color-utils");
var _pointLayerIcon = _interopRequireDefault(require("./point-layer-icon"));
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,
altitude = _ref.altitude;
return function (d) {
return [d.data[lng.fieldIdx], d.data[lat.fieldIdx], altitude && altitude.fieldIdx > -1 ? d.data[altitude.fieldIdx] : 0];
};
};
exports.pointPosAccessor = pointPosAccessor;
var pointPosResolver = function pointPosResolver(_ref2) {
var lat = _ref2.lat,
lng = _ref2.lng,
altitude = _ref2.altitude;
return "".concat(lat.fieldIdx, "-").concat(lng.fieldIdx, "-").concat(altitude ? altitude.fieldIdx : 'z');
};
exports.pointPosResolver = pointPosResolver;
var pointLabelAccessor = function pointLabelAccessor(textLabel) {
return function (d) {
return String(d.data[textLabel.field.tableFieldIndex - 1]);
};
};
exports.pointLabelAccessor = pointLabelAccessor;
var pointLabelResolver = function pointLabelResolver(textLabel) {
return textLabel.field && textLabel.field.tableFieldIndex;
};
exports.pointLabelResolver = pointLabelResolver;
var pointRequiredColumns = ['lat', 'lng'];
exports.pointRequiredColumns = pointRequiredColumns;
var pointOptionalColumns = ['altitude'];
exports.pointOptionalColumns = pointOptionalColumns;
var pointVisConfigs = {
radius: 'radius',
fixedRadius: 'fixedRadius',
opacity: 'opacity',
outline: 'outline',
thickness: 'thickness',
colorRange: 'colorRange',
radiusRange: 'radiusRange',
'hi-precision': 'hi-precision'
};
exports.pointVisConfigs = pointVisConfigs;
var PointLayer =
/*#__PURE__*/
function (_Layer) {
(0, _inherits2["default"])(PointLayer, _Layer);
function PointLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, PointLayer);
_this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(PointLayer).call(this, props));
_this.registerVisConfig(pointVisConfigs);
_this.getPosition = (0, _lodash["default"])(pointPosAccessor, pointPosResolver);
_this.getText = (0, _lodash["default"])(pointLabelAccessor, pointLabelResolver);
return _this;
}
(0, _createClass2["default"])(PointLayer, [{
key: "formatLayerData",
// TODO: fix complexity
/* eslint-disable complexity */
value: function formatLayerData(_, allData, filteredIndex, oldLayerData) {
var _this2 = this;
var opt = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
var _this$config = this.config,
colorScale = _this$config.colorScale,
colorDomain = _this$config.colorDomain,
colorField = _this$config.colorField,
color = _this$config.color,
columns = _this$config.columns,
sizeField = _this$config.sizeField,
sizeScale = _this$config.sizeScale,
sizeDomain = _this$config.sizeDomain,
textLabel = _this$config.textLabel,
_this$config$visConfi = _this$config.visConfig,
radiusRange = _this$config$visConfi.radiusRange,
fixedRadius = _this$config$visConfi.fixedRadius,
colorRange = _this$config$visConfi.colorRange; // point color
var cScale = colorField && this.getVisChannelScale(colorScale, colorDomain, colorRange.colors.map(_colorUtils.hexToRgb)); // point radius
var rScale = sizeField && this.getVisChannelScale(sizeScale, sizeDomain, radiusRange, fixedRadius);
var getPosition = this.getPosition(columns);
if (!oldLayerData || oldLayerData.getPosition !== getPosition) {
this.updateLayerMeta(allData, getPosition);
}
var data;
if (oldLayerData && oldLayerData.data && opt.sameData && oldLayerData.getPosition === getPosition) {
data = oldLayerData.data;
} else {
data = filteredIndex.reduce(function (accu, index) {
var pos = getPosition({
data: allData[index]
}); // if doesn't have point lat or lng, do not add the point
// deck.gl can't handle position = null
if (!pos.every(Number.isFinite)) {
return accu;
}
accu.push({
data: allData[index]
});
return accu;
}, []);
} // get all distinct characters in the text labels
var getText = this.getText(textLabel);
var labelCharacterSet;
if (oldLayerData && oldLayerData.labelCharacterSet && opt.sameData && oldLayerData.getText === getText) {
labelCharacterSet = oldLayerData.labelCharacterSet;
} else {
var textLabels = textLabel.field ? data.map(getText) : [];
labelCharacterSet = (0, _lodash2["default"])(textLabels.join(''));
}
var getRadius = rScale ? function (d) {
return _this2.getEncodedChannelValue(rScale, d.data, sizeField);
} : 1;
var getColor = cScale ? function (d) {
return _this2.getEncodedChannelValue(cScale, d.data, colorField);
} : color;
return {
data: data,
labelCharacterSet: labelCharacterSet,
getPosition: getPosition,
getColor: getColor,
getRadius: getRadius,
getText: getText
};
}
/* eslint-enable complexity */
}, {
key: "updateLayerMeta",
value: function updateLayerMeta(allData, getPosition) {
var bounds = this.getPointsBounds(allData, function (d) {
return getPosition({
data: d
});
});
this.updateMeta({
bounds: bounds
});
}
}, {
key: "renderLayer",
value: function renderLayer(_ref3) {
var _this3 = this;
var data = _ref3.data,
idx = _ref3.idx,
layerInteraction = _ref3.layerInteraction,
objectHovered = _ref3.objectHovered,
mapState = _ref3.mapState,
interactionConfig = _ref3.interactionConfig;
var enableBrushing = interactionConfig.brush.enabled;
var layerProps = _objectSpread({
outline: this.config.visConfig.outline,
radiusMinPixels: 1,
fp64: this.config.visConfig['hi-precision'],
strokeWidth: this.config.visConfig.thickness,
radiusScale: this.getRadiusScaleByZoom(mapState)
}, this.config.visConfig.fixedRadius ? {} : {
radiusMaxPixels: 500
});
var interaction = {
autoHighlight: !enableBrushing,
enableBrushing: enableBrushing,
brushRadius: interactionConfig.brush.config.size * 1000,
highlightColor: this.config.highlightColor
};
return [new _scatterplotBrushingLayer["default"](_objectSpread({}, layerProps, {}, layerInteraction, {}, data, {}, interaction, {
idx: idx,
id: this.id,
opacity: this.config.visConfig.opacity,
pickable: true,
parameters: {
// circles will be flat on the map when the altitude column is not used
depthTest: this.config.columns.altitude.fieldIdx > -1
},
updateTriggers: {
getRadius: {
sizeField: this.config.sizeField,
radiusRange: this.config.visConfig.radiusRange,
fixedRadius: this.config.visConfig.fixedRadius,
sizeScale: this.config.sizeScale
},
getColor: {
color: this.config.color,
colorField: this.config.colorField,
colorRange: this.config.visConfig.colorRange,
colorScale: this.config.colorScale
}
}
}))].concat((0, _toConsumableArray2["default"])(this.config.textLabel.field ? [new _deck.TextLayer({
id: "".concat(this.id, "-label"),
data: data.data,
getPosition: data.getPosition,
getPixelOffset: this.config.textLabel.offset,
getSize: this.config.textLabel.size,
getTextAnchor: this.config.textLabel.anchor,
getText: data.getText,
getColor: function getColor(d) {
return _this3.config.textLabel.color;
},
fp64: this.config.visConfig['hi-precision'],
parameters: {
// text will always show on top of all layers
depthTest: false
},
characterSet: data.labelCharacterSet,
updateTriggers: {
getPosition: data.getPosition,
getPixelOffset: this.config.textLabel.offset,
getText: this.config.textLabel.field,
getTextAnchor: this.config.textLabel.anchor,
getSize: this.config.textLabel.size,
getColor: this.config.textLabel.color
}
})] : []));
}
}, {
key: "type",
get: function get() {
return 'point';
}
}, {
key: "isAggregated",
get: function get() {
return false;
}
}, {
key: "layerIcon",
get: function get() {
return _pointLayerIcon["default"];
}
}, {
key: "requiredLayerColumns",
get: function get() {
return pointRequiredColumns;
}
}, {
key: "optionalColumns",
get: function get() {
return pointOptionalColumns;
}
}, {
key: "columnPairs",
get: function get() {
return this.defaultPointColumnPairs;
}
}, {
key: "noneLayerDataAffectingProps",
get: function get() {
return [].concat((0, _toConsumableArray2["default"])((0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "noneLayerDataAffectingProps", this)), ['radius']);
}
}, {
key: "visualChannels",
get: function get() {
return _objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "visualChannels", this), {
size: _objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(PointLayer.prototype), "visualChannels", this).size, {
range: 'radiusRange',
property: 'radius',
channelScaleType: 'radius'
})
});
}
}], [{
key: "findDefaultLayerProps",
value: function findDefaultLayerProps(_ref4) {
var _ref4$fieldPairs = _ref4.fieldPairs,
fieldPairs = _ref4$fieldPairs === void 0 ? [] : _ref4$fieldPairs;
var props = []; // Make layer for each pair
fieldPairs.forEach(function (pair) {
// find fields for tableFieldIndex
var latField = pair.pair.lat;
var lngField = pair.pair.lng;
var layerName = pair.defaultName;
var prop = {
label: layerName.length ? layerName : 'Point'
}; // default layer color for begintrip and dropoff point
if (latField.value in _defaultSettings.DEFAULT_LAYER_COLOR) {
prop.color = (0, _colorUtils.hexToRgb)(_defaultSettings.DEFAULT_LAYER_COLOR[latField.value]);
} // set the first layer to be visible
if (props.length === 0) {
prop.isVisible = true;
} // const newLayer = new KeplerGlLayers.PointLayer(prop);
prop.columns = {
lat: latField,
lng: lngField,
altitude: {
value: null,
fieldIdx: -1,
optional: true
}
};
props.push(prop);
});
return props;
}
}]);
return PointLayer;
}(_baseLayer["default"]);
exports["default"] = PointLayer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvcG9pbnQtbGF5ZXIvcG9pbnQtbGF5ZXIuanMiXSwibmFtZXMiOlsicG9pbnRQb3NBY2Nlc3NvciIsImxhdCIsImxuZyIsImFsdGl0dWRlIiwiZCIsImRhdGEiLCJmaWVsZElkeCIsInBvaW50UG9zUmVzb2x2ZXIiLCJwb2ludExhYmVsQWNjZXNzb3IiLCJ0ZXh0TGFiZWwiLCJTdHJpbmciLCJmaWVsZCIsInRhYmxlRmllbGRJbmRleCIsInBvaW50TGFiZWxSZXNvbHZlciIsInBvaW50UmVxdWlyZWRDb2x1bW5zIiwicG9pbnRPcHRpb25hbENvbHVtbnMiLCJwb2ludFZpc0NvbmZpZ3MiLCJyYWRpdXMiLCJmaXhlZFJhZGl1cyIsIm9wYWNpdHkiLCJvdXRsaW5lIiwidGhpY2tuZXNzIiwiY29sb3JSYW5nZSIsInJhZGl1c1JhbmdlIiwiUG9pbnRMYXllciIsInByb3BzIiwicmVnaXN0ZXJWaXNDb25maWciLCJnZXRQb3NpdGlvbiIsImdldFRleHQiLCJfIiwiYWxsRGF0YSIsImZpbHRlcmVkSW5kZXgiLCJvbGRMYXllckRhdGEiLCJvcHQiLCJjb25maWciLCJjb2xvclNjYWxlIiwiY29sb3JEb21haW4iLCJjb2xvckZpZWxkIiwiY29sb3IiLCJjb2x1bW5zIiwic2l6ZUZpZWxkIiwic2l6ZVNjYWxlIiwic2l6ZURvbWFpbiIsInZpc0NvbmZpZyIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsImNvbG9ycyIsIm1hcCIsImhleFRvUmdiIiwiclNjYWxlIiwidXBkYXRlTGF5ZXJNZXRhIiwic2FtZURhdGEiLCJyZWR1Y2UiLCJhY2N1IiwiaW5kZXgiLCJwb3MiLCJldmVyeSIsIk51bWJlciIsImlzRmluaXRlIiwicHVzaCIsImxhYmVsQ2hhcmFjdGVyU2V0IiwidGV4dExhYmVscyIsImpvaW4iLCJnZXRSYWRpdXMiLCJnZXRFbmNvZGVkQ2hhbm5lbFZhbHVlIiwiZ2V0Q29sb3IiLCJib3VuZHMiLCJnZXRQb2ludHNCb3VuZHMiLCJ1cGRhdGVNZXRhIiwiaWR4IiwibGF5ZXJJbnRlcmFjdGlvbiIsIm9iamVjdEhvdmVyZWQiLCJtYXBTdGF0ZSIsImludGVyYWN0aW9uQ29uZmlnIiwiZW5hYmxlQnJ1c2hpbmciLCJicnVzaCIsImVuYWJsZWQiLCJsYXllclByb3BzIiwicmFkaXVzTWluUGl4ZWxzIiwiZnA2NCIsInN0cm9rZVdpZHRoIiwicmFkaXVzU2NhbGUiLCJnZXRSYWRpdXNTY2FsZUJ5Wm9vbSIsInJhZGl1c01heFBpeGVscyIsImludGVyYWN0aW9uIiwiYXV0b0hpZ2hsaWdodCIsImJydXNoUmFkaXVzIiwic2l6ZSIsImhpZ2hsaWdodENvbG9yIiwiU2NhdHRlcnBsb3RCcnVzaGluZ0xheWVyIiwiaWQiLCJwaWNrYWJsZSIsInBhcmFtZXRlcnMiLCJkZXB0aFRlc3QiLCJ1cGRhdGVUcmlnZ2VycyIsIlRleHRMYXllciIsImdldFBpeGVsT2Zmc2V0Iiwib2Zmc2V0IiwiZ2V0U2l6ZSIsImdldFRleHRBbmNob3IiLCJhbmNob3IiLCJjaGFyYWN0ZXJTZXQiLCJQb2ludExheWVySWNvbiIsImRlZmF1bHRQb2ludENvbHVtblBhaXJzIiwicmFuZ2UiLCJwcm9wZXJ0eSIsImNoYW5uZWxTY2FsZVR5cGUiLCJmaWVsZFBhaXJzIiwiZm9yRWFjaCIsInBhaXIiLCJsYXRGaWVsZCIsImxuZ0ZpZWxkIiwibGF5ZXJOYW1lIiwiZGVmYXVsdE5hbWUiLCJwcm9wIiwibGFiZWwiLCJsZW5ndGgiLCJ2YWx1ZSIsIkRFRkFVTFRfTEFZRVJfQ09MT1IiLCJpc1Zpc2libGUiLCJvcHRpb25hbCIsIkxheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7Ozs7QUFFTyxJQUFNQSxnQkFBZ0IsR0FBRyxTQUFuQkEsZ0JBQW1CO0FBQUEsTUFBRUMsR0FBRixRQUFFQSxHQUFGO0FBQUEsTUFBT0MsR0FBUCxRQUFPQSxHQUFQ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RixRQUFBQSxLQUFLLENBQUNrQyxJQUFOLENBQVd1RCxJQUFYO0FBQ0QsT0E1QkQ7QUE4QkEsYUFBT3pGLEtBQVA7QUFDRDs7O0VBbkZxQ2dHLHFCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDE5IFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IExheWVyIGZyb20gJy4uL2Jhc2UtbGF5ZXInO1xuaW1wb3J0IG1lbW9pemUgZnJvbSAnbG9kYXNoLm1lbW9pemUnO1xuaW1wb3J0IHtUZXh0TGF5ZXJ9IGZyb20gJ2RlY2suZ2wnO1xuaW1wb3J0IFNjYXR0ZXJwbG90QnJ1c2hpbmdMYXllciBmcm9tICdkZWNrZ2wtbGF5ZXJzL3NjYXR0ZXJwbG90LWJydXNoaW5nLWxheWVyL3NjYXR0ZXJwbG90LWJydXNoaW5nLWxheWVyJztcbmltcG9ydCB1bmlxIGZyb20gJ2xvZGFzaC51bmlxJztcbmltcG9ydCB7aGV4VG9SZ2J9IGZyb20gJ3V0aWxzL2NvbG9yLXV0aWxzJztcbmltcG9ydCBQb2ludExheWVySWNvbiBmcm9tICcuL3BvaW50LWxheWVyLWljb24nO1xuaW1wb3J0IHtERUZBVUxUX0xBWUVSX0NPTE9SfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5cbmV4cG9ydCBjb25zdCBwb2ludFBvc0FjY2Vzc29yID0gKHtsYXQsIGxuZywgYWx0aXR1ZGV9KSA9PiBkID0+IFtcbiAgZC5kYXRhW2xuZy5maWVsZElkeF0sXG4gIGQuZGF0YVtsYXQuZmllbGRJZHhdLFxuICBhbHRpdHVkZSAmJiBhbHRpdHVkZS5maWVsZElkeCA+IC0xID8gZC5kYXRhW2FsdGl0dWRlLmZpZWxkSWR4XSA6IDBcbl07XG5cbmV4cG9ydCBjb25zdCBwb2ludFBvc1Jlc29sdmVyID0gKHtsYXQsIGxuZywgYWx0aXR1ZGV9KSA9PlxuICBgJHtsYXQuZmllbGRJZHh9LSR7bG5nLmZpZWxkSWR4fS0ke2FsdGl0dWRlID8gYWx0aXR1ZGUuZmllbGRJZHggOiAneid9YDtcblxuZXhwb3J0IGNvbnN0IHBvaW50TGFiZWxBY2Nlc3NvciA9IHRleHRMYWJlbCA9PiBkID0+XG4gIFN0cmluZyhkLmRhdGFbdGV4dExhYmVsLmZpZWxkLnRhYmxlRmllbGRJbmRleCAtIDFdKTtcbmV4cG9ydCBjb25zdCBwb2ludExhYmVsUmVzb2x2ZXIgPSB0ZXh0TGFiZWwgPT5cbiAgdGV4dExhYmVsLmZpZWxkICYmIHRleHRMYWJlbC5maWVsZC50YWJsZUZpZWxkSW5kZXg7XG5cbmV4cG9ydCBjb25zdCBwb2ludFJlcXVpcmVkQ29sdW1ucyA9IFsnbGF0JywgJ2xuZyddO1xuZXhwb3J0IGNvbnN0IHBvaW50T3B0aW9uYWxDb2x1bW5zID0gWydhbHRpdHVkZSddO1xuXG5leHBvcnQgY29uc3QgcG9pbnRWaXNDb25maWdzID0ge1xuICByYWRpdXM6ICdyYWRpdXMnLFxuICBmaXhlZFJhZGl1czogJ2ZpeGVkUmFkaXVzJyxcbiAgb3BhY2l0eTogJ29wYWNpdHknLFxuICBvdXRsaW5lOiAnb3V0bGluZScsXG4gIHRoaWNrbmVzczogJ3RoaWNrbmVzcycsXG4gIGNvbG9yUmFuZ2U6ICdjb2xvclJhbmdlJyxcbiAgcmFkaXVzUmFuZ2U6ICdyYWRpdXNSYW5nZScsXG4gICdoaS1wcmVjaXNpb24nOiAnaGktcHJlY2lzaW9uJ1xufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUG9pbnRMYXllciBleHRlbmRzIExheWVyIHtcbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcyk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyVmlzQ29uZmlnKHBvaW50VmlzQ29uZmlncyk7XG4gICAgdGhpcy5nZXRQb3NpdGlvbiA9IG1lbW9pemUocG9pbnRQb3NBY2Nlc3NvciwgcG9pbnRQb3NSZXNvbHZlcik7XG4gICAgdGhpcy5nZXRUZXh0ID0gbWVtb2l6ZShwb2ludExhYmVsQWNjZXNzb3IsIHBvaW50TGFiZWxSZXNvbHZlcik7XG4gIH1cblxuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gJ3BvaW50JztcbiAgfVxuXG4gIGdldCBpc0FnZ3JlZ2F0ZWQoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZ2V0IGxheWVySWNvbigpIHtcbiAgICByZXR1cm4gUG9pbnRMYXllckljb247XG4gIH1cbiAgZ2V0IHJlcXVpcmVkTGF5ZXJDb2x1bW5zKCkge1xuICAgIHJldHVybiBwb2ludFJlcXVpcmVkQ29sdW1ucztcbiAgfVxuXG4gIGdldCBvcHRpb25hbENvbHVtbnMoKSB7XG4gICAgcmV0dXJuIHBvaW50T3B0aW9uYWxDb2x1bW5zO1xuICB9XG5cbiAgZ2V0IGNvbHVtblBhaXJzKCkge1xuICAgIHJldHVybiB0aGlzLmRlZmF1bHRQb2ludENvbHVtblBhaXJzO1xuICB9XG5cbiAgZ2V0IG5vbmVMYXllckRhdGFBZmZlY3RpbmdQcm9wcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm5vbmVMYXllckRhdGFBZmZlY3RpbmdQcm9wcywgJ3JhZGl1cyddO1xuICB9XG5cbiAgZ2V0IHZpc3VhbENoYW5uZWxzKCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscyxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgLi4uc3VwZXIudmlzdWFsQ2hhbm5lbHMuc2l6ZSxcbiAgICAgICAgcmFuZ2U6ICdyYWRpdXNSYW5nZScsXG4gICAgICAgIHByb3BlcnR5OiAncmFkaXVzJyxcbiAgICAgICAgY2hhbm5lbFNjYWxlVHlwZTogJ3JhZGl1cydcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgc3RhdGljIGZpbmREZWZhdWx0TGF5ZXJQcm9wcyh7ZmllbGRQYWlycyA9IFtdfSkge1xuICAgIGNvbnN0IHByb3BzID0gW107XG5cbiAgICAvLyBNYWtlIGxheWVyIGZvciBlYWNoIHBhaXJcbiAgICBmaWVsZFBhaXJzLmZvckVhY2gocGFpciA9PiB7XG4gICAgICAvLyBmaW5kIGZpZWxkcyBmb3IgdGFibGVGaWVsZEluZGV4XG4gICAgICBjb25zdCBsYXRGaWVsZCA9IHBhaXIucGFpci5sYXQ7XG4gICAgICBjb25zdCBsbmdGaWVsZCA9IHBhaXIucGFpci5sbmc7XG4gICAgICBjb25zdCBsYXllck5hbWUgPSBwYWlyLmRlZmF1bHROYW1lO1xuXG4gICAgICBjb25zdCBwcm9wID0ge1xuICAgICAgICBsYWJlbDogbGF5ZXJOYW1lLmxlbmd0aCA/IGxheWVyTmFtZSA6ICdQb2ludCdcbiAgICAgIH07XG5cbiAgICAgIC8vIGRlZmF1bHQgbGF5ZXIgY29sb3IgZm9yIGJlZ2ludHJpcCBhbmQgZHJvcG9mZiBwb2ludFxuICAgICAgaWYgKGxhdEZpZWxkLnZhbHVlIGluIERFRkFVTFRfTEFZRVJfQ09MT1IpIHtcbiAgICAgICAgcHJvcC5jb2xvciA9IGhleFRvUmdiKERFRkFVTFRfTEFZRVJfQ09MT1JbbGF0RmllbGQudmFsdWVdKTtcbiAgICAgIH1cblxuICAgICAgLy8gc2V0IHRoZSBmaXJzdCBsYXllciB0byBiZSB2aXNpYmxlXG4gICAgICBpZiAocHJvcHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHByb3AuaXNWaXNpYmxlID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gY29uc3QgbmV3TGF5ZXIgPSBuZXcgS2VwbGVyR2xMYXllcnMuUG9pbnRMYXllcihwcm9wKTtcbiAgICAgIHByb3AuY29sdW1ucyA9IHtcbiAgICAgICAgbGF0OiBsYXRGaWVsZCxcbiAgICAgICAgbG5nOiBsbmdGaWVsZCxcbiAgICAgICAgYWx0aXR1ZGU6IHt2YWx1ZTogbnVsbCwgZmllbGRJZHg6IC0xLCBvcHRpb25hbDogdHJ1ZX1cbiAgICAgIH07XG5cbiAgICAgIHByb3BzLnB1c2gocHJvcCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcHJvcHM7XG4gIH1cblxuICAvLyBUT0RPOiBmaXggY29tcGxleGl0eVxuICAvKiBlc2xpbnQtZGlzYWJsZSBjb21wbGV4aXR5ICovXG4gIGZvcm1hdExheWVyRGF0YShfLCBhbGxEYXRhLCBmaWx0ZXJlZEluZGV4LCBvbGRMYXllckRhdGEsIG9wdCA9IHt9KSB7XG4gICAgY29uc3Qge1xuICAgICAgY29sb3JTY2FsZSxcbiAgICAgIGNvbG9yRG9tYWluLFxuICAgICAgY29sb3JGaWVsZCxcbiAgICAgIGNvbG9yLFxuICAgICAgY29sdW1ucyxcbiAgICAgIHNpemVGaWVsZCxcbiAgICAgIHNpemVTY2FsZSxcbiAgICAgIHNpemVEb21haW4sXG4gICAgICB0ZXh0TGFiZWwsXG4gICAgICB2aXNDb25maWc6IHtyYWRpdXNSYW5nZSwgZml4ZWRSYWRpdXMsIGNvbG9yUmFuZ2V9XG4gICAgfSA9IHRoaXMuY29uZmlnO1xuXG4gICAgLy8gcG9pbnQgY29sb3JcbiAgICBjb25zdCBjU2NhbGUgPVxuICAgICAgY29sb3JGaWVsZCAmJlxuICAgICAgdGhpcy5nZXRWaXNDaGFubmVsU2NhbGUoXG4gICAgICAgIGNvbG9yU2NhbGUsXG4gICAgICAgIGNvbG9yRG9tYWluLFxuICAgICAgICBjb2xvclJhbmdlLmNvbG9ycy5tYXAoaGV4VG9SZ2IpXG4gICAgICApO1xuXG4gICAgLy8gcG9pbnQgcmFkaXVzXG4gICAgY29uc3QgclNjYWxlID1cbiAgICAgIHNpemVGaWVsZCAmJlxuICAgICAgdGhpcy5nZXRWaXNDaGFubmVsU2NhbGUoc2l6ZVNjYWxlLCBzaXplRG9tYWluLCByYWRpdXNSYW5nZSwgZml4ZWRSYWRpdXMpO1xuXG4gICAgY29uc3QgZ2V0UG9zaXRpb24gPSB0aGlzLmdldFBvc2l0aW9uKGNvbHVtbnMpO1xuICAgIGlmICghb2xkTGF5ZXJEYXRhIHx8IG9sZExheWVyRGF0YS5nZXRQb3NpdGlvbiAhPT0gZ2V0UG9zaXRpb24pIHtcbiAgICAgIHRoaXMudXBkYXRlTGF5ZXJNZXRhKGFsbERhdGEsIGdldFBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICBsZXQgZGF0YTtcbiAgICBpZiAoXG4gICAgICBvbGRMYXllckRhdGEgJiZcbiAgICAgIG9sZExheWVyRGF0YS5kYXRhICYmXG4gICAgICBvcHQuc2FtZURhdGEgJiZcbiAgICAgIG9sZExheWVyRGF0YS5nZXRQb3NpdGlvbiA9PT0gZ2V0UG9zaXRpb25cbiAgICApIHtcbiAgICAgIGRhdGEgPSBvbGRMYXllckRhdGEuZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGF0YSA9IGZpbHRlcmVkSW5kZXgucmVkdWNlKChhY2N1LCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBwb3MgPSBnZXRQb3NpdGlvbih7ZGF0YTogYWxsRGF0YVtpbmRleF19KTtcblxuICAgICAgICAvLyBpZiBkb2Vzbid0IGhhdmUgcG9pbnQgbGF0IG9yIGxuZywgZG8gbm90IGFkZCB0aGUgcG9pbnRcbiAgICAgICAgLy8gZGVjay5nbCBjYW4ndCBoYW5kbGUgcG9zaXRpb24gPSBudWxsXG4gICAgICAgIGlmICghcG9zLmV2ZXJ5KE51bWJlci5pc0Zpbml0ZSkpIHtcbiAgICAgICAgICByZXR1cm4gYWNjdTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFjY3UucHVzaCh7XG4gICAgICAgICAgZGF0YTogYWxsRGF0YVtpbmRleF1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGFjY3U7XG4gICAgICB9LCBbXSk7XG4gICAgfVxuXG4gICAgLy8gZ2V0IGFsbCBkaXN0aW5jdCBjaGFyYWN0ZXJzIGluIHRoZSB0ZXh0IGxhYmVsc1xuICAgIGNvbnN0IGdldFRleHQgPSB0aGlzLmdldFRleHQodGV4dExhYmVsKTtcbiAgICBsZXQgbGFiZWxDaGFyYWN0ZXJTZXQ7XG4gICAgaWYgKFxuICAgICAgb2xkTGF5ZXJEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEubGFiZWxDaGFyYWN0ZXJTZXQgJiZcbiAgICAgIG9wdC5zYW1lRGF0YSAmJlxuICAgICAgb2xkTGF5ZXJEYXRhLmdldFRleHQgPT09IGdldFRleHRcbiAgICApIHtcbiAgICAgIGxhYmVsQ2hhcmFjdGVyU2V0ID0gb2xkTGF5ZXJEYXRhLmxhYmVsQ2hhcmFjdGVyU2V0O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB0ZXh0TGFiZWxzID0gdGV4dExhYmVsLmZpZWxkID8gZGF0YS5tYXAoZ2V0VGV4dCkgOiBbXTtcbiAgICAgIGxhYmVsQ2hhcmFjdGVyU2V0ID0gdW5pcSh0ZXh0TGFiZWxzLmpvaW4oJycpKTtcbiAgICB9XG5cbiAgICBjb25zdCBnZXRSYWRpdXMgPSByU2NhbGVcbiAgICAgID8gZCA9PiB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoclNjYWxlLCBkLmRhdGEsIHNpemVGaWVsZClcbiAgICAgIDogMTtcblxuICAgIGNvbnN0IGdldENvbG9yID0gY1NjYWxlXG4gICAgICA/IGQgPT4gdGhpcy5nZXRFbmNvZGVkQ2hhbm5lbFZhbHVlKGNTY2FsZSwgZC5kYXRhLCBjb2xvckZpZWxkKVxuICAgICAgOiBjb2xvcjtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgbGFiZWxDaGFyYWN0ZXJTZXQsXG4gICAgICBnZXRQb3NpdGlvbixcbiAgICAgIGdldENvbG9yLFxuICAgICAgZ2V0UmFkaXVzLFxuICAgICAgZ2V0VGV4dFxuICAgIH07XG4gIH1cbiAgLyogZXNsaW50LWVuYWJsZSBjb21wbGV4aXR5ICovXG5cbiAgdXBkYXRlTGF5ZXJNZXRhKGFsbERhdGEsIGdldFBvc2l0aW9uKSB7XG4gICAgY29uc3QgYm91bmRzID0gdGhpcy5nZXRQb2ludHNCb3VuZHMoYWxsRGF0YSwgZCA9PiBnZXRQb3NpdGlvbih7ZGF0YTogZH0pKTtcbiAgICB0aGlzLnVwZGF0ZU1ldGEoe2JvdW5kc30pO1xuICB9XG5cbiAgcmVuZGVyTGF5ZXIoe1xuICAgIGRhdGEsXG4gICAgaWR4LFxuICAgIGxheWVySW50ZXJhY3Rpb24sXG4gICAgb2JqZWN0SG92ZXJlZCxcbiAgICBtYXBTdGF0ZSxcbiAgICBpbnRlcmFjdGlvbkNvbmZpZ1xuICB9KSB7XG4gICAgY29uc3QgZW5hYmxlQnJ1c2hpbmcgPSBpbnRlcmFjdGlvbkNvbmZpZy5icnVzaC5lbmFibGVkO1xuXG4gICAgY29uc3QgbGF5ZXJQcm9wcyA9IHtcbiAgICAgIG91dGxpbmU6IHRoaXMuY29uZmlnLnZpc0NvbmZpZy5vdXRsaW5lLFxuICAgICAgcmFkaXVzTWluUGl4ZWxzOiAxLFxuICAgICAgZnA2NDogdGhpcy5jb25maWcudmlzQ29uZmlnWydoaS1wcmVjaXNpb24nXSxcbiAgICAgIHN0cm9rZVdpZHRoOiB0aGlzLmNvbmZpZy52aXNDb25maWcudGhpY2tuZXNzLFxuICAgICAgcmFkaXVzU2NhbGU6IHRoaXMuZ2V0UmFkaXVzU2NhbGVCeVpvb20obWFwU3RhdGUpLFxuICAgICAgLi4uKHRoaXMuY29uZmlnLnZpc0NvbmZpZy5maXhlZFJhZGl1cyA/IHt9IDoge3JhZGl1c01heFBpeGVsczogNTAwfSlcbiAgICB9O1xuXG4gICAgY29uc3QgaW50ZXJhY3Rpb24gPSB7XG4gICAgICBhdXRvSGlnaGxpZ2h0OiAhZW5hYmxlQnJ1c2hpbmcsXG4gICAgICBlbmFibGVCcnVzaGluZyxcbiAgICAgIGJydXNoUmFkaXVzOiBpbnRlcmFjdGlvbkNvbmZpZy5icnVzaC5jb25maWcuc2l6ZSAqIDEwMDAsXG4gICAgICBoaWdobGlnaHRDb2xvcjogdGhpcy5jb25maWcuaGlnaGxpZ2h0Q29sb3JcbiAgICB9O1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIG5ldyBTY2F0dGVycGxvdEJydXNoaW5nTGF5ZXIoe1xuICAgICAgICAuLi5sYXllclByb3BzLFxuICAgICAgICAuLi5sYXllckludGVyYWN0aW9uLFxuICAgICAgICAuLi5kYXRhLFxuICAgICAgICAuLi5pbnRlcmFjdGlvbixcbiAgICAgICAgaWR4LFxuICAgICAgICBpZDogdGhpcy5pZCxcbiAgICAgICAgb3BhY2l0eTogdGhpcy5jb25maWcudmlzQ29uZmlnLm9wYWNpdHksXG4gICAgICAgIHBpY2thYmxlOiB0cnVlLFxuICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgLy8gY2lyY2xlcyB3aWxsIGJlIGZsYXQgb24gdGhlIG1hcCB3aGVuIHRoZSBhbHRpdHVkZSBjb2x1bW4gaXMgbm90IHVzZWRcbiAgICAgICAgICBkZXB0aFRlc3Q6IHRoaXMuY29uZmlnLmNvbHVtbnMuYWx0aXR1ZGUuZmllbGRJZHggPiAtMVxuICAgICAgICB9LFxuXG4gICAgICAgIHVwZGF0ZVRyaWdnZXJzOiB7XG4gICAgICAgICAgZ2V0UmFkaXVzOiB7XG4gICAgICAgICAgICBzaXplRmllbGQ6IHRoaXMuY29uZmlnLnNpemVGaWVsZCxcbiAgICAgICAgICAgIHJhZGl1c1JhbmdlOiB0aGlzLmNvbmZpZy52aXNDb25maWcucmFkaXVzUmFuZ2UsXG4gICAgICAgICAgICBmaXhlZFJhZGl1czogdGhpcy5jb25maWcudmlzQ29uZmlnLmZpeGVkUmFkaXVzLFxuICAgICAgICAgICAgc2l6ZVNjYWxlOiB0aGlzLmNvbmZpZy5zaXplU2NhbGVcbiAgICAgICAgICB9LFxuICAgICAgICAgIGdldENvbG9yOiB7XG4gICAgICAgICAgICBjb2xvcjogdGhpcy5jb25maWcuY29sb3IsXG4gICAgICAgICAgICBjb2xvckZpZWxkOiB0aGlzLmNvbmZpZy5jb2xvckZpZWxkLFxuICAgICAgICAgICAgY29sb3JSYW5nZTogdGhpcy5jb25maWcudmlzQ29uZmlnLmNvbG9yUmFuZ2UsXG4gICAgICAgICAgICBjb2xvclNjYWxlOiB0aGlzLmNvbmZpZy5jb2xvclNjYWxlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSxcbiAgICAgIC8vIHRleHQgbGFiZWwgbGF5ZXJcbiAgICAgIC4uLih0aGlzLmNvbmZpZy50ZXh0TGFiZWwuZmllbGRcbiAgICAgICAgPyBbXG4gICAgICAgICAgICBuZXcgVGV4dExheWVyKHtcbiAgICAgICAgICAgICAgaWQ6IGAke3RoaXMuaWR9LWxhYmVsYCxcbiAgICAgICAgICAgICAgZGF0YTogZGF0YS5kYXRhLFxuICAgICAgICAgICAgICBnZXRQb3NpdGlvbjogZGF0YS5nZXRQb3NpdGlvbixcbiAgICAgICAgICAgICAgZ2V0UGl4ZWxPZmZzZXQ6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5vZmZzZXQsXG4gICAgICAgICAgICAgIGdldFNpemU6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5zaXplLFxuICAgICAgICAgICAgICBnZXRUZXh0QW5jaG9yOiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwuYW5jaG9yLFxuICAgICAgICAgICAgICBnZXRUZXh0OiBkYXRhLmdldFRleHQsXG4gICAgICAgICAgICAgIGdldENvbG9yOiBkID0+IHRoaXMuY29uZmlnLnRleHRMYWJlbC5jb2xvcixcbiAgICAgICAgICAgICAgZnA2NDogdGhpcy5jb25maWcudmlzQ29uZmlnWydoaS1wcmVjaXNpb24nXSxcbiAgICAgICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgICAgIC8vIHRleHQgd2lsbCBhbHdheXMgc2hvdyBvbiB0b3Agb2YgYWxsIGxheWVyc1xuICAgICAgICAgICAgICAgIGRlcHRoVGVzdDogZmFsc2VcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgY2hhcmFjdGVyU2V0OiBkYXRhLmxhYmVsQ2hhcmFjdGVyU2V0LFxuICAgICAgICAgICAgICB1cGRhdGVUcmlnZ2Vyczoge1xuICAgICAgICAgICAgICAgIGdldFBvc2l0aW9uOiBkYXRhLmdldFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgIGdldFBpeGVsT2Zmc2V0OiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwub2Zmc2V0LFxuICAgICAgICAgICAgICAgIGdldFRleHQ6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5maWVsZCxcbiAgICAgICAgICAgICAgICBnZXRUZXh0QW5jaG9yOiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwuYW5jaG9yLFxuICAgICAgICAgICAgICAgIGdldFNpemU6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5zaXplLFxuICAgICAgICAgICAgICAgIGdldENvbG9yOiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwuY29sb3JcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICBdXG4gICAgICAgIDogW10pXG4gICAgXTtcbiAgfVxufVxuIl19