kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
365 lines (302 loc) • 34.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.pointVisConfigs = exports.pointOptionalColumns = exports.pointRequiredColumns = exports.pointPosResolver = exports.pointPosAccessor = undefined;
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _get2 = require('babel-runtime/helpers/get');
var _get3 = _interopRequireDefault(_get2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _baseLayer = require('../base-layer');
var _baseLayer2 = _interopRequireDefault(_baseLayer);
var _lodash = require('lodash.memoize');
var _lodash2 = _interopRequireDefault(_lodash);
var _deck = require('deck.gl');
var _scatterplotBrushingLayer = require('../../deckgl-layers/scatterplot-brushing-layer/scatterplot-brushing-layer');
var _scatterplotBrushingLayer2 = _interopRequireDefault(_scatterplotBrushingLayer);
var _colorUtils = require('../../utils/color-utils');
var _pointLayerIcon = require('./point-layer-icon');
var _pointLayerIcon2 = _interopRequireDefault(_pointLayerIcon);
var _defaultSettings = require('../../constants/default-settings');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var pointPosAccessor = exports.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];
};
}; // Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
var pointPosResolver = exports.pointPosResolver = function pointPosResolver(_ref2) {
var lat = _ref2.lat,
lng = _ref2.lng,
altitude = _ref2.altitude;
return lat.fieldIdx + '-' + lng.fieldIdx + '-' + (altitude ? altitude.fieldIdx : 'z');
};
var pointRequiredColumns = exports.pointRequiredColumns = ['lat', 'lng'];
var pointOptionalColumns = exports.pointOptionalColumns = ['altitude'];
var pointVisConfigs = exports.pointVisConfigs = {
radius: 'radius',
fixedRadius: 'fixedRadius',
opacity: 'opacity',
outline: 'outline',
thickness: 'thickness',
colorRange: 'colorRange',
radiusRange: 'radiusRange',
'hi-precision': 'hi-precision'
};
var PointLayer = function (_Layer) {
(0, _inherits3.default)(PointLayer, _Layer);
function PointLayer(props) {
(0, _classCallCheck3.default)(this, PointLayer);
var _this = (0, _possibleConstructorReturn3.default)(this, (PointLayer.__proto__ || Object.getPrototypeOf(PointLayer)).call(this, props));
_this.registerVisConfig(pointVisConfigs);
_this.getPosition = (0, _lodash2.default)(pointPosAccessor, pointPosResolver);
return _this;
}
(0, _createClass3.default)(PointLayer, [{
key: 'formatLayerData',
value: function formatLayerData(_, allData, filteredIndex, oldLayerData) {
var _this2 = this;
var opt = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
var _config = this.config,
colorScale = _config.colorScale,
colorDomain = _config.colorDomain,
colorField = _config.colorField,
color = _config.color,
columns = _config.columns,
sizeField = _config.sizeField,
sizeScale = _config.sizeScale,
sizeDomain = _config.sizeDomain,
_config$visConfig = _config.visConfig,
radiusRange = _config$visConfig.radiusRange,
fixedRadius = _config$visConfig.fixedRadius,
colorRange = _config$visConfig.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 = void 0;
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;
}, []);
}
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,
getPosition: getPosition,
getColor: getColor,
getRadius: getRadius
};
}
}, {
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 = (0, _extends3.default)({
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 _scatterplotBrushingLayer2.default((0, _extends3.default)({}, layerProps, layerInteraction, data, interaction, {
idx: idx,
id: this.id,
opacity: this.config.visConfig.opacity,
pickable: true,
// parameters
parameters: {
depthTest: mapState.dragRotate
},
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, _toConsumableArray3.default)(this.config.textLabel.field ? [new _deck.TextLayer({
id: 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: function getText(d) {
return String(d.data[_this3.config.textLabel.field.tableFieldIndex - 1]);
},
getColor: function getColor(d) {
return _this3.config.textLabel.color;
},
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 _pointLayerIcon2.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, _toConsumableArray3.default)((0, _get3.default)(PointLayer.prototype.__proto__ || Object.getPrototypeOf(PointLayer.prototype), 'noneLayerDataAffectingProps', this)), ['radius']);
}
}, {
key: 'visualChannels',
get: function get() {
return (0, _extends3.default)({}, (0, _get3.default)(PointLayer.prototype.__proto__ || Object.getPrototypeOf(PointLayer.prototype), 'visualChannels', this), {
size: (0, _extends3.default)({}, (0, _get3.default)(PointLayer.prototype.__proto__ || Object.getPrototypeOf(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 === undefined ? [] : _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;
}(_baseLayer2.default);
exports.default = PointLayer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvcG9pbnQtbGF5ZXIvcG9pbnQtbGF5ZXIuanMiXSwibmFtZXMiOlsicG9pbnRQb3NBY2Nlc3NvciIsImxhdCIsImxuZyIsImFsdGl0dWRlIiwiZCIsImRhdGEiLCJmaWVsZElkeCIsInBvaW50UG9zUmVzb2x2ZXIiLCJwb2ludFJlcXVpcmVkQ29sdW1ucyIsInBvaW50T3B0aW9uYWxDb2x1bW5zIiwicG9pbnRWaXNDb25maWdzIiwicmFkaXVzIiwiZml4ZWRSYWRpdXMiLCJvcGFjaXR5Iiwib3V0bGluZSIsInRoaWNrbmVzcyIsImNvbG9yUmFuZ2UiLCJyYWRpdXNSYW5nZSIsIlBvaW50TGF5ZXIiLCJwcm9wcyIsInJlZ2lzdGVyVmlzQ29uZmlnIiwiZ2V0UG9zaXRpb24iLCJfIiwiYWxsRGF0YSIsImZpbHRlcmVkSW5kZXgiLCJvbGRMYXllckRhdGEiLCJvcHQiLCJjb25maWciLCJjb2xvclNjYWxlIiwiY29sb3JEb21haW4iLCJjb2xvckZpZWxkIiwiY29sb3IiLCJjb2x1bW5zIiwic2l6ZUZpZWxkIiwic2l6ZVNjYWxlIiwic2l6ZURvbWFpbiIsInZpc0NvbmZpZyIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsImNvbG9ycyIsIm1hcCIsImhleFRvUmdiIiwiclNjYWxlIiwidXBkYXRlTGF5ZXJNZXRhIiwic2FtZURhdGEiLCJyZWR1Y2UiLCJhY2N1IiwiaW5kZXgiLCJwb3MiLCJldmVyeSIsIk51bWJlciIsImlzRmluaXRlIiwicHVzaCIsImdldFJhZGl1cyIsImdldEVuY29kZWRDaGFubmVsVmFsdWUiLCJnZXRDb2xvciIsImJvdW5kcyIsImdldFBvaW50c0JvdW5kcyIsInVwZGF0ZU1ldGEiLCJpZHgiLCJsYXllckludGVyYWN0aW9uIiwib2JqZWN0SG92ZXJlZCIsIm1hcFN0YXRlIiwiaW50ZXJhY3Rpb25Db25maWciLCJlbmFibGVCcnVzaGluZyIsImJydXNoIiwiZW5hYmxlZCIsImxheWVyUHJvcHMiLCJyYWRpdXNNaW5QaXhlbHMiLCJmcDY0Iiwic3Ryb2tlV2lkdGgiLCJyYWRpdXNTY2FsZSIsImdldFJhZGl1c1NjYWxlQnlab29tIiwicmFkaXVzTWF4UGl4ZWxzIiwiaW50ZXJhY3Rpb24iLCJhdXRvSGlnaGxpZ2h0IiwiYnJ1c2hSYWRpdXMiLCJzaXplIiwiaGlnaGxpZ2h0Q29sb3IiLCJTY2F0dGVycGxvdEJydXNoaW5nTGF5ZXIiLCJpZCIsInBpY2thYmxlIiwicGFyYW1ldGVycyIsImRlcHRoVGVzdCIsImRyYWdSb3RhdGUiLCJ1cGRhdGVUcmlnZ2VycyIsInRleHRMYWJlbCIsImZpZWxkIiwiVGV4dExheWVyIiwiZ2V0UGl4ZWxPZmZzZXQiLCJvZmZzZXQiLCJnZXRTaXplIiwiZ2V0VGV4dEFuY2hvciIsImFuY2hvciIsImdldFRleHQiLCJTdHJpbmciLCJ0YWJsZUZpZWxkSW5kZXgiLCJQb2ludExheWVySWNvbiIsImRlZmF1bHRQb2ludENvbHVtblBhaXJzIiwicmFuZ2UiLCJwcm9wZXJ0eSIsImNoYW5uZWxTY2FsZVR5cGUiLCJmaWVsZFBhaXJzIiwiZm9yRWFjaCIsImxhdEZpZWxkIiwicGFpciIsImxuZ0ZpZWxkIiwibGF5ZXJOYW1lIiwiZGVmYXVsdE5hbWUiLCJwcm9wIiwibGFiZWwiLCJsZW5ndGgiLCJ2YWx1ZSIsIkRFRkFVTFRfTEFZRVJfQ09MT1IiLCJpc1Zpc2libGUiLCJvcHRpb25hbCIsIkxheWVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7OztBQUNBOzs7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7QUFDQTs7OztBQUNBOzs7O0FBRU8sSUFBTUEsOENBQW1CLFNBQW5CQSxnQkFBbUI7QUFBQSxNQUFFQyxHQUFGLFFBQUVBLEdBQUY7QUFBQSxNQUFPQyxHQUFQLFFBQU9BLEdBQVA7QUFBQSxNQUFZQyxRQUFaLFFBQVlBLFFBQVo7QUFBQSxTQUEwQjtBQUFBLFdBQUssQ0FDN0RDLEVBQUVDLElBQUYsQ0FBT0gsSUFBSUks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LE9BQU87QUFDWEMsaUJBQU9ILFVBQVVJLE1BQVYsR0FBbUJKLFNBQW5CLEdBQStCO0FBRDNCLFNBQWI7O0FBSUE7QUFDQSxZQUFJSCxTQUFTUSxLQUFULElBQWtCQyxvQ0FBdEIsRUFBMkM7QUFDekNKLGVBQUs5RSxLQUFMLEdBQWEsMEJBQVNrRixxQ0FBb0JULFNBQVNRLEtBQTdCLENBQVQsQ0FBYjtBQUNEOztBQUVEO0FBQ0EsWUFBSTdGLE1BQU00RixNQUFOLEtBQWlCLENBQXJCLEVBQXdCO0FBQ3RCRixlQUFLSyxTQUFMLEdBQWlCLElBQWpCO0FBQ0Q7O0FBRUQ7QUFDQUwsYUFBSzdFLE9BQUwsR0FBZTtBQUNiL0IsZUFBS3VHLFFBRFE7QUFFYnRHLGVBQUt3RyxRQUZRO0FBR2J2RyxvQkFBVSxFQUFDNkcsT0FBTyxJQUFSLEVBQWMxRyxVQUFVLENBQUMsQ0FBekIsRUFBNEI2RyxVQUFVLElBQXRDO0FBSEcsU0FBZjs7QUFNQWhHLGNBQU1pQyxJQUFOLENBQVd5RCxJQUFYO0FBQ0QsT0E1QkQ7O0FBOEJBLGFBQU8xRixLQUFQO0FBQ0Q7OztFQWxGcUNpRyxtQjs7a0JBQW5CbEcsVSIsImZpbGUiOiJwb2ludC1sYXllci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAxOCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBMYXllciBmcm9tICcuLi9iYXNlLWxheWVyJztcbmltcG9ydCBtZW1vaXplIGZyb20gJ2xvZGFzaC5tZW1vaXplJztcbmltcG9ydCB7VGV4dExheWVyfSBmcm9tICdkZWNrLmdsJztcbmltcG9ydCBTY2F0dGVycGxvdEJydXNoaW5nTGF5ZXIgZnJvbSAnZGVja2dsLWxheWVycy9zY2F0dGVycGxvdC1icnVzaGluZy1sYXllci9zY2F0dGVycGxvdC1icnVzaGluZy1sYXllcic7XG5pbXBvcnQge2hleFRvUmdifSBmcm9tICd1dGlscy9jb2xvci11dGlscyc7XG5pbXBvcnQgUG9pbnRMYXllckljb24gZnJvbSAnLi9wb2ludC1sYXllci1pY29uJztcbmltcG9ydCB7REVGQVVMVF9MQVlFUl9DT0xPUn0gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NBY2Nlc3NvciA9ICh7bGF0LCBsbmcsIGFsdGl0dWRlfSkgPT4gZCA9PiBbXG4gIGQuZGF0YVtsbmcuZmllbGRJZHhdLFxuICBkLmRhdGFbbGF0LmZpZWxkSWR4XSxcbiAgYWx0aXR1ZGUgJiYgYWx0aXR1ZGUuZmllbGRJZHggPiAtMSA/IGQuZGF0YVthbHRpdHVkZS5maWVsZElkeF0gOiAwXG5dO1xuXG5leHBvcnQgY29uc3QgcG9pbnRQb3NSZXNvbHZlciA9ICh7bGF0LCBsbmcsIGFsdGl0dWRlfSkgPT5cbiAgYCR7bGF0LmZpZWxkSWR4fS0ke2xuZy5maWVsZElkeH0tJHthbHRpdHVkZSA/IGFsdGl0dWRlLmZpZWxkSWR4IDogJ3onfWA7XG5leHBvcnQgY29uc3QgcG9pbnRSZXF1aXJlZENvbHVtbnMgPSBbJ2xhdCcsICdsbmcnXTtcbmV4cG9ydCBjb25zdCBwb2ludE9wdGlvbmFsQ29sdW1ucyA9IFsnYWx0aXR1ZGUnXTtcblxuZXhwb3J0IGNvbnN0IHBvaW50VmlzQ29uZmlncyA9IHtcbiAgcmFkaXVzOiAncmFkaXVzJyxcbiAgZml4ZWRSYWRpdXM6ICdmaXhlZFJhZGl1cycsXG4gIG9wYWNpdHk6ICdvcGFjaXR5JyxcbiAgb3V0bGluZTogJ291dGxpbmUnLFxuICB0aGlja25lc3M6ICd0aGlja25lc3MnLFxuICBjb2xvclJhbmdlOiAnY29sb3JSYW5nZScsXG4gIHJhZGl1c1JhbmdlOiAncmFkaXVzUmFuZ2UnLFxuICAnaGktcHJlY2lzaW9uJzogJ2hpLXByZWNpc2lvbidcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvaW50TGF5ZXIgZXh0ZW5kcyBMYXllciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuXG4gICAgdGhpcy5yZWdpc3RlclZpc0NvbmZpZyhwb2ludFZpc0NvbmZpZ3MpO1xuICAgIHRoaXMuZ2V0UG9zaXRpb24gPSBtZW1vaXplKHBvaW50UG9zQWNjZXNzb3IsIHBvaW50UG9zUmVzb2x2ZXIpO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdwb2ludCc7XG4gIH1cblxuICBnZXQgaXNBZ2dyZWdhdGVkKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGdldCBsYXllckljb24oKSB7XG4gICAgcmV0dXJuIFBvaW50TGF5ZXJJY29uO1xuICB9XG4gIGdldCByZXF1aXJlZExheWVyQ29sdW1ucygpIHtcbiAgICByZXR1cm4gcG9pbnRSZXF1aXJlZENvbHVtbnM7XG4gIH1cblxuICBnZXQgb3B0aW9uYWxDb2x1bW5zKCkge1xuICAgIHJldHVybiBwb2ludE9wdGlvbmFsQ29sdW1ucztcbiAgfVxuXG4gIGdldCBjb2x1bW5QYWlycygpIHtcbiAgICByZXR1cm4gdGhpcy5kZWZhdWx0UG9pbnRDb2x1bW5QYWlycztcbiAgfVxuXG4gIGdldCBub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMoKSB7XG4gICAgcmV0dXJuIFsuLi5zdXBlci5ub25lTGF5ZXJEYXRhQWZmZWN0aW5nUHJvcHMsICdyYWRpdXMnXTtcbiAgfVxuXG4gIGdldCB2aXN1YWxDaGFubmVscygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uc3VwZXIudmlzdWFsQ2hhbm5lbHMsXG4gICAgICBzaXplOiB7XG4gICAgICAgIC4uLnN1cGVyLnZpc3VhbENoYW5uZWxzLnNpemUsXG4gICAgICAgIHJhbmdlOiAncmFkaXVzUmFuZ2UnLFxuICAgICAgICBwcm9wZXJ0eTogJ3JhZGl1cycsXG4gICAgICAgIGNoYW5uZWxTY2FsZVR5cGU6ICdyYWRpdXMnXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBmaW5kRGVmYXVsdExheWVyUHJvcHMoe2ZpZWxkUGFpcnMgPSBbXX0pIHtcbiAgICBjb25zdCBwcm9wcyA9IFtdO1xuXG4gICAgLy8gTWFrZSBsYXllciBmb3IgZWFjaCBwYWlyXG4gICAgZmllbGRQYWlycy5mb3JFYWNoKHBhaXIgPT4ge1xuICAgICAgLy8gZmluZCBmaWVsZHMgZm9yIHRhYmxlRmllbGRJbmRleFxuICAgICAgY29uc3QgbGF0RmllbGQgPSBwYWlyLnBhaXIubGF0O1xuICAgICAgY29uc3QgbG5nRmllbGQgPSBwYWlyLnBhaXIubG5nO1xuICAgICAgY29uc3QgbGF5ZXJOYW1lID0gcGFpci5kZWZhdWx0TmFtZTtcblxuICAgICAgY29uc3QgcHJvcCA9IHtcbiAgICAgICAgbGFiZWw6IGxheWVyTmFtZS5sZW5ndGggPyBsYXllck5hbWUgOiAnUG9pbnQnXG4gICAgICB9O1xuXG4gICAgICAvLyBkZWZhdWx0IGxheWVyIGNvbG9yIGZvciBiZWdpbnRyaXAgYW5kIGRyb3BvZmYgcG9pbnRcbiAgICAgIGlmIChsYXRGaWVsZC52YWx1ZSBpbiBERUZBVUxUX0xBWUVSX0NPTE9SKSB7XG4gICAgICAgIHByb3AuY29sb3IgPSBoZXhUb1JnYihERUZBVUxUX0xBWUVSX0NPTE9SW2xhdEZpZWxkLnZhbHVlXSk7XG4gICAgICB9XG5cbiAgICAgIC8vIHNldCB0aGUgZmlyc3QgbGF5ZXIgdG8gYmUgdmlzaWJsZVxuICAgICAgaWYgKHByb3BzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBwcm9wLmlzVmlzaWJsZSA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIC8vIGNvbnN0IG5ld0xheWVyID0gbmV3IEtlcGxlckdsTGF5ZXJzLlBvaW50TGF5ZXIocHJvcCk7XG4gICAgICBwcm9wLmNvbHVtbnMgPSB7XG4gICAgICAgIGxhdDogbGF0RmllbGQsXG4gICAgICAgIGxuZzogbG5nRmllbGQsXG4gICAgICAgIGFsdGl0dWRlOiB7dmFsdWU6IG51bGwsIGZpZWxkSWR4OiAtMSwgb3B0aW9uYWw6IHRydWV9XG4gICAgICB9O1xuXG4gICAgICBwcm9wcy5wdXNoKHByb3ApO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHByb3BzO1xuICB9XG5cbiAgZm9ybWF0TGF5ZXJEYXRhKF8sIGFsbERhdGEsIGZpbHRlcmVkSW5kZXgsIG9sZExheWVyRGF0YSwgb3B0ID0ge30pIHtcbiAgICBjb25zdCB7XG4gICAgICBjb2xvclNjYWxlLFxuICAgICAgY29sb3JEb21haW4sXG4gICAgICBjb2xvckZpZWxkLFxuICAgICAgY29sb3IsXG4gICAgICBjb2x1bW5zLFxuICAgICAgc2l6ZUZpZWxkLFxuICAgICAgc2l6ZVNjYWxlLFxuICAgICAgc2l6ZURvbWFpbixcbiAgICAgIHZpc0NvbmZpZzoge3JhZGl1c1JhbmdlLCBmaXhlZFJhZGl1cywgY29sb3JSYW5nZX1cbiAgICB9ID0gdGhpcy5jb25maWc7XG5cbiAgICAvLyBwb2ludCBjb2xvclxuICAgIGNvbnN0IGNTY2FsZSA9XG4gICAgICBjb2xvckZpZWxkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShcbiAgICAgICAgY29sb3JTY2FsZSxcbiAgICAgICAgY29sb3JEb21haW4sXG4gICAgICAgIGNvbG9yUmFuZ2UuY29sb3JzLm1hcChoZXhUb1JnYilcbiAgICAgICk7XG5cbiAgICAvLyBwb2ludCByYWRpdXNcbiAgICBjb25zdCByU2NhbGUgPVxuICAgICAgc2l6ZUZpZWxkICYmXG4gICAgICB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShzaXplU2NhbGUsIHNpemVEb21haW4sIHJhZGl1c1JhbmdlLCBmaXhlZFJhZGl1cyk7XG5cbiAgICBjb25zdCBnZXRQb3NpdGlvbiA9IHRoaXMuZ2V0UG9zaXRpb24oY29sdW1ucyk7XG5cbiAgICBpZiAoIW9sZExheWVyRGF0YSB8fCBvbGRMYXllckRhdGEuZ2V0UG9zaXRpb24gIT09IGdldFBvc2l0aW9uKSB7XG4gICAgICB0aGlzLnVwZGF0ZUxheWVyTWV0YShhbGxEYXRhLCBnZXRQb3NpdGlvbik7XG4gICAgfVxuXG4gICAgbGV0IGRhdGE7XG4gICAgaWYgKFxuICAgICAgb2xkTGF5ZXJEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZGF0YSAmJlxuICAgICAgb3B0LnNhbWVEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZ2V0UG9zaXRpb24gPT09IGdldFBvc2l0aW9uXG4gICAgKSB7XG4gICAgICBkYXRhID0gb2xkTGF5ZXJEYXRhLmRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGEgPSBmaWx0ZXJlZEluZGV4LnJlZHVjZSgoYWNjdSwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgcG9zID0gZ2V0UG9zaXRpb24oe2RhdGE6IGFsbERhdGFbaW5kZXhdfSk7XG5cbiAgICAgICAgLy8gaWYgZG9lc24ndCBoYXZlIHBvaW50IGxhdCBvciBsbmcsIGRvIG5vdCBhZGQgdGhlIHBvaW50XG4gICAgICAgIC8vIGRlY2suZ2wgY2FuJ3QgaGFuZGxlIHBvc2l0aW9uID0gbnVsbFxuICAgICAgICBpZiAoIXBvcy5ldmVyeShOdW1iZXIuaXNGaW5pdGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGFjY3U7XG4gICAgICAgIH1cblxuICAgICAgICBhY2N1LnB1c2goe1xuICAgICAgICAgIGRhdGE6IGFsbERhdGFbaW5kZXhdXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBhY2N1O1xuICAgICAgfSwgW10pO1xuICAgIH1cblxuICAgIGNvbnN0IGdldFJhZGl1cyA9IHJTY2FsZSA/IGQgPT5cbiAgICAgIHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShyU2NhbGUsIGQuZGF0YSwgc2l6ZUZpZWxkKSA6IDE7XG5cbiAgICBjb25zdCBnZXRDb2xvciA9IGNTY2FsZSA/IGQgPT5cbiAgICAgIHRoaXMuZ2V0RW5jb2RlZENoYW5uZWxWYWx1ZShjU2NhbGUsIGQuZGF0YSwgY29sb3JGaWVsZCkgOiBjb2xvcjtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhLFxuICAgICAgZ2V0UG9zaXRpb24sXG4gICAgICBnZXRDb2xvcixcbiAgICAgIGdldFJhZGl1c1xuICAgIH07XG4gIH1cblxuICB1cGRhdGVMYXllck1ldGEoYWxsRGF0YSwgZ2V0UG9zaXRpb24pIHtcbiAgICBjb25zdCBib3VuZHMgPSB0aGlzLmdldFBvaW50c0JvdW5kcyhhbGxEYXRhLCBkID0+IGdldFBvc2l0aW9uKHtkYXRhOiBkfSkpO1xuICAgIHRoaXMudXBkYXRlTWV0YSh7Ym91bmRzfSk7XG4gIH1cblxuICByZW5kZXJMYXllcih7XG4gICAgZGF0YSxcbiAgICBpZHgsXG4gICAgbGF5ZXJJbnRlcmFjdGlvbixcbiAgICBvYmplY3RIb3ZlcmVkLFxuICAgIG1hcFN0YXRlLFxuICAgIGludGVyYWN0aW9uQ29uZmlnXG4gIH0pIHtcbiAgICBjb25zdCBlbmFibGVCcnVzaGluZyA9IGludGVyYWN0aW9uQ29uZmlnLmJydXNoLmVuYWJsZWQ7XG5cbiAgICBjb25zdCBsYXllclByb3BzID0ge1xuICAgICAgb3V0bGluZTogdGhpcy5jb25maWcudmlzQ29uZmlnLm91dGxpbmUsXG4gICAgICByYWRpdXNNaW5QaXhlbHM6IDEsXG4gICAgICBmcDY0OiB0aGlzLmNvbmZpZy52aXNDb25maWdbJ2hpLXByZWNpc2lvbiddLFxuICAgICAgc3Ryb2tlV2lkdGg6IHRoaXMuY29uZmlnLnZpc0NvbmZpZy50aGlja25lc3MsXG4gICAgICByYWRpdXNTY2FsZTogdGhpcy5nZXRSYWRpdXNTY2FsZUJ5Wm9vbShtYXBTdGF0ZSksXG4gICAgICAuLi4odGhpcy5jb25maWcudmlzQ29uZmlnLmZpeGVkUmFkaXVzID8ge30gOiB7cmFkaXVzTWF4UGl4ZWxzOiA1MDB9KVxuICAgIH07XG5cbiAgICBjb25zdCBpbnRlcmFjdGlvbiA9IHtcbiAgICAgIGF1dG9IaWdobGlnaHQ6ICFlbmFibGVCcnVzaGluZyxcbiAgICAgIGVuYWJsZUJydXNoaW5nLFxuICAgICAgYnJ1c2hSYWRpdXM6IGludGVyYWN0aW9uQ29uZmlnLmJydXNoLmNvbmZpZy5zaXplICogMTAwMCxcbiAgICAgIGhpZ2hsaWdodENvbG9yOiB0aGlzLmNvbmZpZy5oaWdobGlnaHRDb2xvclxuICAgIH07XG5cbiAgICByZXR1cm4gW1xuICAgICAgbmV3IFNjYXR0ZXJwbG90QnJ1c2hpbmdMYXllcih7XG4gICAgICAgIC4uLmxheWVyUHJvcHMsXG4gICAgICAgIC4uLmxheWVySW50ZXJhY3Rpb24sXG4gICAgICAgIC4uLmRhdGEsXG4gICAgICAgIC4uLmludGVyYWN0aW9uLFxuICAgICAgICBpZHgsXG4gICAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgICBvcGFjaXR5OiB0aGlzLmNvbmZpZy52aXNDb25maWcub3BhY2l0eSxcbiAgICAgICAgcGlja2FibGU6IHRydWUsXG4gICAgICAgIC8vIHBhcmFtZXRlcnNcbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgIGRlcHRoVGVzdDogbWFwU3RhdGUuZHJhZ1JvdGF0ZVxuICAgICAgICB9LFxuXG4gICAgICAgIHVwZGF0ZVRyaWdnZXJzOiB7XG4gICAgICAgICAgZ2V0UmFkaXVzOiB7XG4gICAgICAgICAgICBzaXplRmllbGQ6IHRoaXMuY29uZmlnLnNpemVGaWVsZCxcbiAgICAgICAgICAgIHJhZGl1c1JhbmdlOiB0aGlzLmNvbmZpZy52aXNDb25maWcucmFkaXVzUmFuZ2UsXG4gICAgICAgICAgICBmaXhlZFJhZGl1czogdGhpcy5jb25maWcudmlzQ29uZmlnLmZpeGVkUmFkaXVzLFxuICAgICAgICAgICAgc2l6ZVNjYWxlOiB0aGlzLmNvbmZpZy5zaXplU2NhbGVcbiAgICAgICAgICB9LFxuICAgICAgICAgIGdldENvbG9yOiB7XG4gICAgICAgICAgICBjb2xvcjogdGhpcy5jb25maWcuY29sb3IsXG4gICAgICAgICAgICBjb2xvckZpZWxkOiB0aGlzLmNvbmZpZy5jb2xvckZpZWxkLFxuICAgICAgICAgICAgY29sb3JSYW5nZTogdGhpcy5jb25maWcudmlzQ29uZmlnLmNvbG9yUmFuZ2UsXG4gICAgICAgICAgICBjb2xvclNjYWxlOiB0aGlzLmNvbmZpZy5jb2xvclNjYWxlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KSxcbiAgICAgIC8vIHRleHQgbGFiZWwgbGF5ZXJcbiAgICAgIC4uLih0aGlzLmNvbmZpZy50ZXh0TGFiZWwuZmllbGRcbiAgICAgICAgPyBbXG4gICAgICAgICAgICBuZXcgVGV4dExheWVyKHtcbiAgICAgICAgICAgICAgaWQ6IGAke3RoaXMuaWR9LWxhYmVsYCxcbiAgICAgICAgICAgICAgZGF0YTogZGF0YS5kYXRhLFxuICAgICAgICAgICAgICBnZXRQb3NpdGlvbjogZGF0YS5nZXRQb3NpdGlvbixcbiAgICAgICAgICAgICAgZ2V0UGl4ZWxPZmZzZXQ6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5vZmZzZXQsXG4gICAgICAgICAgICAgIGdldFNpemU6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5zaXplLFxuICAgICAgICAgICAgICBnZXRUZXh0QW5jaG9yOiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwuYW5jaG9yLFxuICAgICAgICAgICAgICBnZXRUZXh0OiBkID0+IFN0cmluZyhkLmRhdGFbdGhpcy5jb25maWcudGV4dExhYmVsLmZpZWxkLnRhYmxlRmllbGRJbmRleCAtIDFdKSxcbiAgICAgICAgICAgICAgZ2V0Q29sb3I6IGQgPT4gdGhpcy5jb25maWcudGV4dExhYmVsLmNvbG9yLFxuICAgICAgICAgICAgICB1cGRhdGVUcmlnZ2Vyczoge1xuICAgICAgICAgICAgICAgIGdldFBvc2l0aW9uOiBkYXRhLmdldFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgIGdldFBpeGVsT2Zmc2V0OiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwub2Zmc2V0LFxuICAgICAgICAgICAgICAgIGdldFRleHQ6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5maWVsZCxcbiAgICAgICAgICAgICAgICBnZXRUZXh0QW5jaG9yOiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwuYW5jaG9yLFxuICAgICAgICAgICAgICAgIGdldFNpemU6IHRoaXMuY29uZmlnLnRleHRMYWJlbC5zaXplLFxuICAgICAgICAgICAgICAgIGdldENvbG9yOiB0aGlzLmNvbmZpZy50ZXh0TGFiZWwuY29sb3JcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICBdXG4gICAgICAgIDogW10pXG4gICAgXTtcbiAgfVxufVxuIl19