UNPKG

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
"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