UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

386 lines (315 loc) 35.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.HexagonIdVisConfigs = exports.hexIdResolver = exports.hexIdAccessor = exports.hexIdRequiredColumns = exports.HEXAGON_ID_FIELDS = 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 _lodash = require('lodash.memoize'); var _lodash2 = _interopRequireDefault(_lodash); var _baseLayer = require('../base-layer'); var _baseLayer2 = _interopRequireDefault(_baseLayer); var _deck = require('deck.gl'); var _h3HexagonCellLayer = require('../../deckgl-layers/h3-hexagon-cell-layer/h3-hexagon-cell-layer'); var _h3HexagonCellLayer2 = _interopRequireDefault(_h3HexagonCellLayer); var _h3Utils = require('./h3-utils'); var _h3HexagonLayerIcon = require('./h3-hexagon-layer-icon'); var _h3HexagonLayerIcon2 = _interopRequireDefault(_h3HexagonLayerIcon); var _defaultSettings = require('../../constants/default-settings'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var HEXAGON_ID_FIELDS = exports.HEXAGON_ID_FIELDS = { hex_id: ['hex_id', 'hexagon_id', 'h3_id'] }; // 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 hexIdRequiredColumns = exports.hexIdRequiredColumns = ['hex_id']; var hexIdAccessor = exports.hexIdAccessor = function hexIdAccessor(_ref) { var hex_id = _ref.hex_id; return function (d) { return d[hex_id.fieldIdx]; }; }; var hexIdResolver = exports.hexIdResolver = function hexIdResolver(_ref2) { var hex_id = _ref2.hex_id; return hex_id.fieldIdx; }; var HexagonIdVisConfigs = exports.HexagonIdVisConfigs = { opacity: 'opacity', colorRange: 'colorRange', coverage: 'coverage', sizeRange: 'elevationRange', coverageRange: 'coverageRange', elevationScale: 'elevationScale', 'hi-precision': 'hi-precision' }; function hexToRgb(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); var r = parseInt(result[1], 16); var g = parseInt(result[2], 16); var b = parseInt(result[3], 16); return [r, g, b]; } var HexagonIdLayer = function (_Layer) { (0, _inherits3.default)(HexagonIdLayer, _Layer); function HexagonIdLayer(props) { (0, _classCallCheck3.default)(this, HexagonIdLayer); var _this = (0, _possibleConstructorReturn3.default)(this, (HexagonIdLayer.__proto__ || Object.getPrototypeOf(HexagonIdLayer)).call(this, props)); _this.registerVisConfig(HexagonIdVisConfigs); _this.getHexId = (0, _lodash2.default)(hexIdAccessor, hexIdResolver); return _this; } (0, _createClass3.default)(HexagonIdLayer, [{ key: 'getDefaultLayerConfig', value: function getDefaultLayerConfig() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return (0, _extends3.default)({}, (0, _get3.default)(HexagonIdLayer.prototype.__proto__ || Object.getPrototypeOf(HexagonIdLayer.prototype), 'getDefaultLayerConfig', this).call(this, props), { // add height visual channel coverageField: null, coverageDomain: [0, 1], coverageScale: 'linear' }); } }, { 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, coverageField = _config.coverageField, coverageScale = _config.coverageScale, coverageDomain = _config.coverageDomain, _config$visConfig = _config.visConfig, sizeRange = _config$visConfig.sizeRange, colorRange = _config$visConfig.colorRange, coverageRange = _config$visConfig.coverageRange; // color var cScale = colorField && this.getVisChannelScale(colorScale, colorDomain, colorRange.colors.map(function (c) { return hexToRgb(c); })); // height var sScale = sizeField && this.getVisChannelScale(sizeScale, sizeDomain, sizeRange); // coverage var coScale = coverageField && this.getVisChannelScale(coverageScale, coverageDomain, coverageRange); var getHexId = this.getHexId(columns); if (!oldLayerData || oldLayerData.getHexId !== getHexId) { this.updateLayerMeta(allData, getHexId); } var data = void 0; if (oldLayerData && oldLayerData.data && opt.sameData && oldLayerData.getHexId === getHexId) { data = oldLayerData.data; } else { data = filteredIndex.reduce(function (accu, index, i) { var id = getHexId(allData[index]); var centroid = _this2.dataToFeature.centroids[index]; if (centroid) { accu.push({ // keep a reference to the original data index index: i, data: allData[index], id: id, centroid: centroid }); } return accu; }, []); } var getElevation = sScale ? function (d) { return _this2.getEncodedChannelValue(sScale, d.data, sizeField, 0); } : 0; var getColor = cScale ? function (d) { return _this2.getEncodedChannelValue(cScale, d.data, colorField); } : color; var getCoverage = coScale ? function (d) { return _this2.getEncodedChannelValue(coScale, d.data, coverageField, 0); } : 1; // const layerData = { return { data: data, getElevation: getElevation, getColor: getColor, getHexId: getHexId, getCoverage: getCoverage, hexagonVertices: this.dataToFeature.hexagonVertices, hexagonCenter: this.dataToFeature.hexagonCenter }; } }, { key: 'updateLayerMeta', value: function updateLayerMeta(allData, getHexId) { var hexagonVertices = void 0; var hexagonCenter = void 0; var centroids = {}; allData.forEach(function (d, index) { var id = getHexId(d); if (typeof id !== 'string' || !id.length) { return; } // find hexagonVertices // only need 1 instance of hexagonVertices if (!hexagonVertices) { hexagonVertices = id && (0, _h3Utils.getVertices)({ id: id }); hexagonCenter = id && (0, _h3Utils.getCentroid)({ id: id }); } // save a reference of centroids to dataToFeature // so we don't have to re calculate it again centroids[index] = (0, _h3Utils.getCentroid)({ id: id }); }); var bounds = this.getPointsBounds(Object.values(centroids), function (d) { return d; }); var lightSettings = this.getLightSettingsFromBounds(bounds); this.dataToFeature = { hexagonVertices: hexagonVertices, hexagonCenter: hexagonCenter, centroids: centroids }; this.updateMeta({ bounds: bounds, lightSettings: lightSettings }); } }, { key: 'renderLayer', value: function renderLayer(_ref3) { var data = _ref3.data, idx = _ref3.idx, layerInteraction = _ref3.layerInteraction, objectHovered = _ref3.objectHovered, mapState = _ref3.mapState, interactionConfig = _ref3.interactionConfig; var zoomFactor = this.getZoomFactor(mapState); var eleZoomFactor = this.getElevationZoomFactor(mapState); var config = this.config, meta = this.meta; var visConfig = config.visConfig; var updateTriggers = { getColor: { color: config.color, colorField: config.colorField, colorRange: config.visConfig.colorRange, colorScale: config.colorScale }, getElevation: { sizeField: config.sizeField, sizeRange: config.visConfig.sizeRange }, getCoverage: { coverageField: config.coverageField, coverageRange: config.visConfig.coverageRange } }; return [new _h3HexagonCellLayer2.default((0, _extends3.default)({}, layerInteraction, data, { id: this.id, idx: idx, pickable: true, // coverage coverage: config.coverageField ? 1 : visConfig.coverage, // parameters parameters: { depthTest: Boolean(config.sizeField || mapState.dragRotate) }, // highlight autoHighlight: Boolean(config.sizeField), // elevation extruded: Boolean(config.sizeField), elevationScale: visConfig.elevationScale * eleZoomFactor, // color opacity: visConfig.opacity, // render lightSettings: meta.lightSettings, updateTriggers: updateTriggers }))].concat((0, _toConsumableArray3.default)(this.isLayerHovered(objectHovered) && !config.sizeField ? [new _deck.GeoJsonLayer({ id: this.id + '-hovered', data: [(0, _h3Utils.idToPolygonGeo)(objectHovered, { lineColor: config.highlightColor })], lineWidthScale: 8 * zoomFactor })] : [])); } }, { key: 'type', get: function get() { return 'hexagonId'; } }, { key: 'name', get: function get() { return 'H3'; } }, { key: 'requiredLayerColumns', get: function get() { return hexIdRequiredColumns; } }, { key: 'layerIcon', get: function get() { // use hexagon layer icon for now return _h3HexagonLayerIcon2.default; } }, { key: 'visualChannels', get: function get() { return (0, _extends3.default)({}, (0, _get3.default)(HexagonIdLayer.prototype.__proto__ || Object.getPrototypeOf(HexagonIdLayer.prototype), 'visualChannels', this), { size: (0, _extends3.default)({}, (0, _get3.default)(HexagonIdLayer.prototype.__proto__ || Object.getPrototypeOf(HexagonIdLayer.prototype), 'visualChannels', this).size, { property: 'height' }), coverage: { property: 'coverage', field: 'coverageField', scale: 'coverageScale', domain: 'coverageDomain', range: 'coverageRange', key: 'coverage', channelScaleType: _defaultSettings.CHANNEL_SCALES.radius } }); } }], [{ key: 'findDefaultLayerProps', value: function findDefaultLayerProps(_ref4) { var fields = _ref4.fields; var foundColumns = this.findDefaultColumnField(HEXAGON_ID_FIELDS, fields); if (!foundColumns || !foundColumns.length) { return null; } return foundColumns.map(function (columns) { return { isVisible: true, label: 'H3 Hexagon', columns: columns }; }); } }]); return HexagonIdLayer; }(_baseLayer2.default); exports.default = HexagonIdLayer; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvaDMtaGV4YWdvbi1sYXllci9oMy1oZXhhZ29uLWxheWVyLmpzIl0sIm5hbWVzIjpbIkhFWEFHT05fSURfRklFTERTIiwiaGV4X2lkIiwiaGV4SWRSZXF1aXJlZENvbHVtbnMiLCJoZXhJZEFjY2Vzc29yIiwiZCIsImZpZWxkSWR4IiwiaGV4SWRSZXNvbHZlciIsIkhleGFnb25JZFZpc0NvbmZpZ3MiLCJvcGFjaXR5IiwiY29sb3JSYW5nZSIsImNvdmVyYWdlIiwic2l6ZVJhbmdlIiwiY292ZXJhZ2VSYW5nZSIsImVsZXZhdGlvblNjYWxlIiwiaGV4VG9SZ2IiLCJoZXgiLCJyZXN1bHQiLCJleGVjIiwiciIsInBhcnNlSW50IiwiZyIsImIiLCJIZXhhZ29uSWRMYXllciIsInByb3BzIiwicmVnaXN0ZXJWaXNDb25maWciLCJnZXRIZXhJZCIsImNvdmVyYWdlRmllbGQiLCJjb3ZlcmFnZURvbWFpbiIsImNvdmVyYWdlU2NhbGUiLCJfIiwiYWxsRGF0YSIsImZpbHRlcmVkSW5kZXgiLCJvbGRMYXllckRhdGEiLCJvcHQiLCJjb25maWciLCJjb2xvclNjYWxlIiwiY29sb3JEb21haW4iLCJjb2xvckZpZWxkIiwiY29sb3IiLCJjb2x1bW5zIiwic2l6ZUZpZWxkIiwic2l6ZVNjYWxlIiwic2l6ZURvbWFpbiIsInZpc0NvbmZpZyIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsImNvbG9ycyIsIm1hcCIsImMiLCJzU2NhbGUiLCJjb1NjYWxlIiwidXBkYXRlTGF5ZXJNZXRhIiwiZGF0YSIsInNhbWVEYXRhIiwicmVkdWNlIiwiYWNjdSIsImluZGV4IiwiaSIsImlkIiwiY2VudHJvaWQiLCJkYXRhVG9GZWF0dXJlIiwiY2VudHJvaWRzIiwicHVzaCIsImdldEVsZXZhdGlvbiIsImdldEVuY29kZWRDaGFubmVsVmFsdWUiLCJnZXRDb2xvciIsImdldENvdmVyYWdlIiwiaGV4YWdvblZlcnRpY2VzIiwiaGV4YWdvbkNlbnRlciIsImZvckVhY2giLCJsZW5ndGgiLCJib3VuZHMiLCJnZXRQb2ludHNCb3VuZHMiLCJPYmplY3QiLCJ2YWx1ZXMiLCJsaWdodFNldHRpbmdzIiwiZ2V0TGlnaHRTZXR0aW5nc0Zyb21Cb3VuZHMiLCJ1cGRhdGVNZXRhIiwiaWR4IiwibGF5ZXJJbnRlcmFjdGlvbiIsIm9iamVjdEhvdmVyZWQiLCJtYXBTdGF0ZSIsImludGVyYWN0aW9uQ29uZmlnIiwiem9vbUZhY3RvciIsImdldFpvb21GYWN0b3IiLCJlbGVab29tRmFjdG9yIiwiZ2V0RWxldmF0aW9uWm9vbUZhY3RvciIsIm1ldGEiLCJ1cGRhdGVUcmlnZ2VycyIsIkgzSGV4YWdvbkNlbGxMYXllciIsInBpY2thYmxlIiwicGFyYW1ldGVycyIsImRlcHRoVGVzdCIsIkJvb2xlYW4iLCJkcmFnUm90YXRlIiwiYXV0b0hpZ2hsaWdodCIsImV4dHJ1ZGVkIiwiaXNMYXllckhvdmVyZWQiLCJHZW9Kc29uTGF5ZXIiLCJsaW5lQ29sb3IiLCJoaWdobGlnaHRDb2xvciIsImxpbmVXaWR0aFNjYWxlIiwiSDNIZXhhZ29uTGF5ZXJJY29uIiwic2l6ZSIsInByb3BlcnR5IiwiZmllbGQiLCJzY2FsZSIsImRvbWFpbiIsInJhbmdlIiwia2V5IiwiY2hhbm5lbFNjYWxlVHlwZSIsIkNIQU5ORUxfU0NBTEVTIiwicmFkaXVzIiwiZmllbGRzIiwiZm91bmRDb2x1bW5zIiwiZmluZERlZmF1bHRDb2x1bW5GaWVsZCIsImlzVmlzaWJsZSIsImxhYmVsIiwiTGF5ZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOzs7O0FBRUE7Ozs7QUFDQTs7QUFDQTs7OztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFFTyxJQUFNQSxnREFBb0I7QUFDL0JDLFVBQVEsQ0FBQyxRQUFELEVBQVcsWUFBWCxFQUF5QixPQUF6QjtBQUR1QixDQUExQixDLENBN0JQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QkFFMEI7QUFDekIsYUFBT2pGLG9CQUFQO0FBQ0Q7Ozt3QkFFZTtBQUNkO0FBQ0EsYUFBT29HLDRCQUFQO0FBQ0Q7Ozt3QkFFb0I7QUFDbkI7QUFFRUMseUNBQ0ssa0lBQXFCQSxJQUQxQjtBQUVFQyxvQkFBVTtBQUZaLFVBRkY7QUFNRTlGLGtCQUFVO0FBQ1I4RixvQkFBVSxVQURGO0FBRVJDLGlCQUFPLGVBRkM7QUFHUkMsaUJBQU8sZUFIQztBQUlSQyxrQkFBUSxnQkFKQTtBQUtSQyxpQkFBTyxlQUxDO0FBTVJDLGVBQUssVUFORztBQU9SQyw0QkFBa0JDLGdDQUFlQztBQVB6QjtBQU5aO0FBZ0JEOzs7aURBRXNDO0FBQUEsVUFBVEMsTUFBUyxTQUFUQSxNQUFTOztBQUNyQyxVQUFNQyxlQUFlLEtBQUtDLHNCQUFMLENBQTRCbkgsaUJBQTVCLEVBQStDaUgsTUFBL0MsQ0FBckI7QUFDQSxVQUFJLENBQUNDLFlBQUQsSUFBaUIsQ0FBQ0EsYUFBYTVDLE1BQW5DLEVBQTJDO0FBQ3pDLGVBQU8sSUFBUDtBQUNEOztBQUVELGFBQU80QyxhQUFhbkUsR0FBYixDQUFpQjtBQUFBLGVBQVk7QUFDbENxRSxxQkFBVyxJQUR1QjtBQUVsQ0MsaUJBQU8sWUFGMkI7QUFHbEM5RTtBQUhrQyxTQUFaO0FBQUEsT0FBakIsQ0FBUDtBQUtEOzs7RUF0RHlDK0UsbUI7O2tCQUF2QmhHLGMiLCJmaWxlIjoiaDMtaGV4YWdvbi1sYXllci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAxOCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBtZW1vaXplIGZyb20gJ2xvZGFzaC5tZW1vaXplJztcblxuaW1wb3J0IExheWVyIGZyb20gJy4uL2Jhc2UtbGF5ZXInO1xuaW1wb3J0IHtHZW9Kc29uTGF5ZXJ9IGZyb20gJ2RlY2suZ2wnO1xuaW1wb3J0IEgzSGV4YWdvbkNlbGxMYXllciBmcm9tICdkZWNrZ2wtbGF5ZXJzL2gzLWhleGFnb24tY2VsbC1sYXllci9oMy1oZXhhZ29uLWNlbGwtbGF5ZXInO1xuaW1wb3J0IHtnZXRWZXJ0aWNlcywgZ2V0Q2VudHJvaWQsIGlkVG9Qb2x5Z29uR2VvfSBmcm9tICcuL2gzLXV0aWxzJztcbmltcG9ydCBIM0hleGFnb25MYXllckljb24gZnJvbSAnLi9oMy1oZXhhZ29uLWxheWVyLWljb24nO1xuaW1wb3J0IHtDSEFOTkVMX1NDQUxFU30gZnJvbSAnY29uc3RhbnRzL2RlZmF1bHQtc2V0dGluZ3MnO1xuXG5leHBvcnQgY29uc3QgSEVYQUdPTl9JRF9GSUVMRFMgPSB7XG4gIGhleF9pZDogWydoZXhfaWQnLCAnaGV4YWdvbl9pZCcsICdoM19pZCddXG59O1xuXG5leHBvcnQgY29uc3QgaGV4SWRSZXF1aXJlZENvbHVtbnMgPSBbJ2hleF9pZCddO1xuZXhwb3J0IGNvbnN0IGhleElkQWNjZXNzb3IgPSAoe2hleF9pZH0pID0+IGQgPT4gZFtoZXhfaWQuZmllbGRJZHhdO1xuZXhwb3J0IGNvbnN0IGhleElkUmVzb2x2ZXIgPSAoe2hleF9pZH0pID0+IGhleF9pZC5maWVsZElkeDtcblxuZXhwb3J0IGNvbnN0IEhleGFnb25JZFZpc0NvbmZpZ3MgPSB7XG4gIG9wYWNpdHk6ICdvcGFjaXR5JyxcbiAgY29sb3JSYW5nZTogJ2NvbG9yUmFuZ2UnLFxuICBjb3ZlcmFnZTogJ2NvdmVyYWdlJyxcbiAgc2l6ZVJhbmdlOiAnZWxldmF0aW9uUmFuZ2UnLFxuICBjb3ZlcmFnZVJhbmdlOiAnY292ZXJhZ2VSYW5nZScsXG4gIGVsZXZhdGlvblNjYWxlOiAnZWxldmF0aW9uU2NhbGUnLFxuICAnaGktcHJlY2lzaW9uJzogJ2hpLXByZWNpc2lvbidcbn07XG5cbmZ1bmN0aW9uIGhleFRvUmdiKGhleCkge1xuICBjb25zdCByZXN1bHQgPSAvXiM/KFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkoW2EtZlxcZF17Mn0pJC9pLmV4ZWMoaGV4KTtcblxuICBjb25zdCByID0gcGFyc2VJbnQocmVzdWx0WzFdLCAxNik7XG4gIGNvbnN0IGcgPSBwYXJzZUludChyZXN1bHRbMl0sIDE2KTtcbiAgY29uc3QgYiA9IHBhcnNlSW50KHJlc3VsdFszXSwgMTYpO1xuXG4gIHJldHVybiBbciwgZywgYl07XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEhleGFnb25JZExheWVyIGV4dGVuZHMgTGF5ZXIge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcbiAgICB0aGlzLnJlZ2lzdGVyVmlzQ29uZmlnKEhleGFnb25JZFZpc0NvbmZpZ3MpO1xuICAgIHRoaXMuZ2V0SGV4SWQgPSBtZW1vaXplKGhleElkQWNjZXNzb3IsIGhleElkUmVzb2x2ZXIpO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdoZXhhZ29uSWQnO1xuICB9XG5cbiAgZ2V0IG5hbWUoKSB7XG4gICAgcmV0dXJuICdIMyc7XG4gIH1cblxuICBnZXQgcmVxdWlyZWRMYXllckNvbHVtbnMoKSB7XG4gICAgcmV0dXJuIGhleElkUmVxdWlyZWRDb2x1bW5zO1xuICB9XG5cbiAgZ2V0IGxheWVySWNvbigpIHtcbiAgICAvLyB1c2UgaGV4YWdvbiBsYXllciBpY29uIGZvciBub3dcbiAgICByZXR1cm4gSDNIZXhhZ29uTGF5ZXJJY29uO1xuICB9XG5cbiAgZ2V0IHZpc3VhbENoYW5uZWxzKCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci52aXN1YWxDaGFubmVscyxcbiAgICAgIHNpemU6IHtcbiAgICAgICAgLi4uc3VwZXIudmlzdWFsQ2hhbm5lbHMuc2l6ZSxcbiAgICAgICAgcHJvcGVydHk6ICdoZWlnaHQnXG4gICAgICB9LFxuICAgICAgY292ZXJhZ2U6IHtcbiAgICAgICAgcHJvcGVydHk6ICdjb3ZlcmFnZScsXG4gICAgICAgIGZpZWxkOiAnY292ZXJhZ2VGaWVsZCcsXG4gICAgICAgIHNjYWxlOiAnY292ZXJhZ2VTY2FsZScsXG4gICAgICAgIGRvbWFpbjogJ2NvdmVyYWdlRG9tYWluJyxcbiAgICAgICAgcmFuZ2U6ICdjb3ZlcmFnZVJhbmdlJyxcbiAgICAgICAga2V5OiAnY292ZXJhZ2UnLFxuICAgICAgICBjaGFubmVsU2NhbGVUeXBlOiBDSEFOTkVMX1NDQUxFUy5yYWRpdXNcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgc3RhdGljIGZpbmREZWZhdWx0TGF5ZXJQcm9wcyh7ZmllbGRzfSkge1xuICAgIGNvbnN0IGZvdW5kQ29sdW1ucyA9IHRoaXMuZmluZERlZmF1bHRDb2x1bW5GaWVsZChIRVhBR09OX0lEX0ZJRUxEUywgZmllbGRzKTtcbiAgICBpZiAoIWZvdW5kQ29sdW1ucyB8fCAhZm91bmRDb2x1bW5zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kQ29sdW1ucy5tYXAoY29sdW1ucyA9PiAoe1xuICAgICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgICAgbGFiZWw6ICdIMyBIZXhhZ29uJyxcbiAgICAgIGNvbHVtbnNcbiAgICB9KSk7XG4gIH1cblxuICBnZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMgPSB7fSkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci5nZXREZWZhdWx0TGF5ZXJDb25maWcocHJvcHMpLFxuXG4gICAgICAvLyBhZGQgaGVpZ2h0IHZpc3VhbCBjaGFubmVsXG4gICAgICBjb3ZlcmFnZUZpZWxkOiBudWxsLFxuICAgICAgY292ZXJhZ2VEb21haW46IFswLCAxXSxcbiAgICAgIGNvdmVyYWdlU2NhbGU6ICdsaW5lYXInXG4gICAgfTtcbiAgfVxuXG4gIGZvcm1hdExheWVyRGF0YShfLCBhbGxEYXRhLCBmaWx0ZXJlZEluZGV4LCBvbGRMYXllckRhdGEsIG9wdCA9IHt9KSB7XG4gICAgY29uc3Qge1xuICAgICAgY29sb3JTY2FsZSxcbiAgICAgIGNvbG9yRG9tYWluLFxuICAgICAgY29sb3JGaWVsZCxcbiAgICAgIGNvbG9yLFxuICAgICAgY29sdW1ucyxcbiAgICAgIHNpemVGaWVsZCxcbiAgICAgIHNpemVTY2FsZSxcbiAgICAgIHNpemVEb21haW4sXG4gICAgICBjb3ZlcmFnZUZpZWxkLFxuICAgICAgY292ZXJhZ2VTY2FsZSxcbiAgICAgIGNvdmVyYWdlRG9tYWluLFxuICAgICAgdmlzQ29uZmlnOiB7c2l6ZVJhbmdlLCBjb2xvclJhbmdlLCBjb3ZlcmFnZVJhbmdlfVxuICAgIH0gPSB0aGlzLmNvbmZpZztcblxuICAgIC8vIGNvbG9yXG4gICAgY29uc3QgY1NjYWxlID1cbiAgICAgIGNvbG9yRmllbGQgJiZcbiAgICAgIHRoaXMuZ2V0VmlzQ2hhbm5lbFNjYWxlKFxuICAgICAgICBjb2xvclNjYWxlLFxuICAgICAgICBjb2xvckRvbWFpbixcbiAgICAgICAgY29sb3JSYW5nZS5jb2xvcnMubWFwKGMgPT4gaGV4VG9SZ2IoYykpXG4gICAgICApO1xuXG4gICAgLy8gaGVpZ2h0XG4gICAgY29uc3Qgc1NjYWxlID1cbiAgICAgIHNpemVGaWVsZCAmJiB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShzaXplU2NhbGUsIHNpemVEb21haW4sIHNpemVSYW5nZSk7XG5cbiAgICAvLyBjb3ZlcmFnZVxuICAgIGNvbnN0IGNvU2NhbGUgPVxuICAgICAgY292ZXJhZ2VGaWVsZCAmJiB0aGlzLmdldFZpc0NoYW5uZWxTY2FsZShjb3ZlcmFnZVNjYWxlLCBjb3ZlcmFnZURvbWFpbiwgY292ZXJhZ2VSYW5nZSk7XG5cbiAgICBjb25zdCBnZXRIZXhJZCA9IHRoaXMuZ2V0SGV4SWQoY29sdW1ucyk7XG5cbiAgICBpZiAoIW9sZExheWVyRGF0YSB8fCBvbGRMYXllckRhdGEuZ2V0SGV4SWQgIT09IGdldEhleElkKSB7XG4gICAgICB0aGlzLnVwZGF0ZUxheWVyTWV0YShhbGxEYXRhLCBnZXRIZXhJZCk7XG4gICAgfVxuXG4gICAgbGV0IGRhdGE7XG4gICAgaWYgKFxuICAgICAgb2xkTGF5ZXJEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZGF0YSAmJlxuICAgICAgb3B0LnNhbWVEYXRhICYmXG4gICAgICBvbGRMYXllckRhdGEuZ2V0SGV4SWQgPT09IGdldEhleElkXG4gICAgKSB7XG4gICAgICBkYXRhID0gb2xkTGF5ZXJEYXRhLmRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGEgPSBmaWx0ZXJlZEluZGV4LnJlZHVjZSgoYWNjdSwgaW5kZXgsIGkpID0+IHtcbiAgICAgICAgY29uc3QgaWQgPSBnZXRIZXhJZChhbGxEYXRhW2luZGV4XSk7XG4gICAgICAgIGNvbnN0IGNlbnRyb2lkID0gdGhpcy5kYXRhVG9GZWF0dXJlLmNlbnRyb2lkc1tpbmRleF07XG5cbiAgICAgICAgaWYgKGNlbnRyb2lkKSB7XG4gICAgICAgICAgYWNjdS5wdXNoKHtcbiAgICAgICAgICAgIC8vIGtlZXAgYSByZWZlcmVuY2UgdG8gdGhlIG9yaWdpbmFsIGRhdGEgaW5kZXhcbiAgICAgICAgICAgIGluZGV4OiBpLFxuICAgICAgICAgICAgZGF0YTogYWxsRGF0YVtpbmRleF0sXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGNlbnRyb2lkXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYWNjdTtcbiAgICAgIH0sIFtdKTtcbiAgICB9XG5cbiAgICBjb25zdCBnZXRFbGV2YXRpb24gPSBzU2NhbGUgPyBkID0+XG4gICAgICB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoc1NjYWxlLCBkLmRhdGEsIHNpemVGaWVsZCwgMCkgOiAwO1xuXG4gICAgY29uc3QgZ2V0Q29sb3IgPSBjU2NhbGUgPyBkID0+XG4gICAgICB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoY1NjYWxlLCBkLmRhdGEsIGNvbG9yRmllbGQpIDogY29sb3I7XG5cbiAgICBjb25zdCBnZXRDb3ZlcmFnZSA9IGNvU2NhbGUgPyBkID0+XG4gICAgICB0aGlzLmdldEVuY29kZWRDaGFubmVsVmFsdWUoY29TY2FsZSwgZC5kYXRhLCBjb3ZlcmFnZUZpZWxkLCAwKSA6IDE7XG5cbiAgICAvLyBjb25zdCBsYXllckRhdGEgPSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBnZXRFbGV2YXRpb24sXG4gICAgICBnZXRDb2xvcixcbiAgICAgIGdldEhleElkLFxuICAgICAgZ2V0Q292ZXJhZ2UsXG4gICAgICBoZXhhZ29uVmVydGljZXM6IHRoaXMuZGF0YVRvRmVhdHVyZS5oZXhhZ29uVmVydGljZXMsXG4gICAgICBoZXhhZ29uQ2VudGVyOiB0aGlzLmRhdGFUb0ZlYXR1cmUuaGV4YWdvbkNlbnRlclxuICAgIH07XG4gIH1cblxuICB1cGRhdGVMYXllck1ldGEoYWxsRGF0YSwgZ2V0SGV4SWQpIHtcbiAgICBsZXQgaGV4YWdvblZlcnRpY2VzO1xuICAgIGxldCBoZXhhZ29uQ2VudGVyO1xuICAgIGNvbnN0IGNlbnRyb2lkcyA9IHt9O1xuXG4gICAgYWxsRGF0YS5mb3JFYWNoKChkLCBpbmRleCkgPT4ge1xuICAgICAgY29uc3QgaWQgPSBnZXRIZXhJZChkKTtcbiAgICAgIGlmICh0eXBlb2YgaWQgIT09ICdzdHJpbmcnIHx8ICFpZC5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gZmluZCBoZXhhZ29uVmVydGljZXNcbiAgICAgIC8vIG9ubHkgbmVlZCAxIGluc3RhbmNlIG9mIGhleGFnb25WZXJ0aWNlc1xuICAgICAgaWYgKCFoZXhhZ29uVmVydGljZXMpIHtcbiAgICAgICAgaGV4YWdvblZlcnRpY2VzID0gaWQgJiYgZ2V0VmVydGljZXMoe2lkfSk7XG4gICAgICAgIGhleGFnb25DZW50ZXIgPSBpZCAmJiBnZXRDZW50cm9pZCh7aWR9KVxuICAgICAgfVxuXG4gICAgICAvLyBzYXZlIGEgcmVmZXJlbmNlIG9mIGNlbnRyb2lkcyB0byBkYXRhVG9GZWF0dXJlXG4gICAgICAvLyBzbyB3ZSBkb24ndCBoYXZlIHRvIHJlIGNhbGN1bGF0ZSBpdCBhZ2FpblxuICAgICAgY2VudHJvaWRzW2luZGV4XSA9IGdldENlbnRyb2lkKHtpZH0pO1xuICAgIH0pO1xuXG4gICAgY29uc3QgYm91bmRzID0gdGhpcy5nZXRQb2ludHNCb3VuZHMoT2JqZWN0LnZhbHVlcyhjZW50cm9pZHMpLCBkID0+IGQpO1xuICAgIGNvbnN0IGxpZ2h0U2V0dGluZ3MgPSB0aGlzLmdldExpZ2h0U2V0dGluZ3NGcm9tQm91bmRzKGJvdW5kcyk7XG5cbiAgICB0aGlzLmRhdGFUb0ZlYXR1cmUgPSB7aGV4YWdvblZlcnRpY2VzLCBoZXhhZ29uQ2VudGVyLCBjZW50cm9pZHN9O1xuICAgIHRoaXMudXBkYXRlTWV0YSh7Ym91bmRzLCBsaWdodFNldHRpbmdzfSk7XG4gIH1cblxuICByZW5kZXJMYXllcih7XG4gICAgZGF0YSxcbiAgICBpZHgsXG4gICAgbGF5ZXJJbnRlcmFjdGlvbixcbiAgICBvYmplY3RIb3ZlcmVkLFxuICAgIG1hcFN0YXRlLFxuICAgIGludGVyYWN0aW9uQ29uZmlnXG4gIH0pIHtcbiAgICBjb25zdCB6b29tRmFjdG9yID0gdGhpcy5nZXRab29tRmFjdG9yKG1hcFN0YXRlKTtcbiAgICBjb25zdCBlbGVab29tRmFjdG9yID0gdGhpcy5nZXRFbGV2YXRpb25ab29tRmFjdG9yKG1hcFN0YXRlKTtcbiAgICBjb25zdCB7Y29uZmlnLCBtZXRhfSA9IHRoaXM7XG4gICAgY29uc3Qge3Zpc0NvbmZpZ30gPSBjb25maWc7XG5cbiAgICBjb25zdCB1cGRhdGVUcmlnZ2VycyA9IHtcbiAgICAgIGdldENvbG9yOiB7XG4gICAgICAgIGNvbG9yOiBjb25maWcuY29sb3IsXG4gICAgICAgIGNvbG9yRmllbGQ6IGNvbmZpZy5jb2xvckZpZWxkLFxuICAgICAgICBjb2xvclJhbmdlOiBjb25maWcudmlzQ29uZmlnLmNvbG9yUmFuZ2UsXG4gICAgICAgIGNvbG9yU2NhbGU6IGNvbmZpZy5jb2xvclNjYWxlXG4gICAgICB9LFxuICAgICAgZ2V0RWxldmF0aW9uOiB7XG4gICAgICAgIHNpemVGaWVsZDogY29uZmlnLnNpemVGaWVsZCxcbiAgICAgICAgc2l6ZVJhbmdlOiBjb25maWcudmlzQ29uZmlnLnNpemVSYW5nZVxuICAgICAgfSxcbiAgICAgIGdldENvdmVyYWdlOiB7XG4gICAgICAgIGNvdmVyYWdlRmllbGQ6IGNvbmZpZy5jb3ZlcmFnZUZpZWxkLFxuICAgICAgICBjb3ZlcmFnZVJhbmdlOiBjb25maWcudmlzQ29uZmlnLmNvdmVyYWdlUmFuZ2VcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIFtcbiAgICAgIG5ldyBIM0hleGFnb25DZWxsTGF5ZXIoe1xuICAgICAgICAuLi5sYXllckludGVyYWN0aW9uLFxuICAgICAgICAuLi5kYXRhLFxuICAgICAgICBpZDogdGhpcy5pZCxcbiAgICAgICAgaWR4LFxuICAgICAgICBwaWNrYWJsZTogdHJ1ZSxcblxuICAgICAgICAvLyBjb3ZlcmFnZVxuICAgICAgICBjb3ZlcmFnZTogY29uZmlnLmNvdmVyYWdlRmllbGQgPyAxIDogdmlzQ29uZmlnLmNvdmVyYWdlLFxuXG4gICAgICAgIC8vIHBhcmFtZXRlcnNcbiAgICAgICAgcGFyYW1ldGVyczoge2RlcHRoVGVzdDogQm9vbGVhbihjb25maWcuc2l6ZUZpZWxkIHx8IG1hcFN0YXRlLmRyYWdSb3RhdGUpfSxcblxuICAgICAgICAvLyBoaWdobGlnaHRcbiAgICAgICAgYXV0b0hpZ2hsaWdodDogQm9vbGVhbihjb25maWcuc2l6ZUZpZWxkKSxcblxuICAgICAgICAvLyBlbGV2YXRpb25cbiAgICAgICAgZXh0cnVkZWQ6IEJvb2xlYW4oY29uZmlnLnNpemVGaWVsZCksXG4gICAgICAgIGVsZXZhdGlvblNjYWxlOiB2aXNDb25maWcuZWxldmF0aW9uU2NhbGUgKiBlbGVab29tRmFjdG9yLFxuXG4gICAgICAgIC8vIGNvbG9yXG4gICAgICAgIG9wYWNpdHk6IHZpc0NvbmZpZy5vcGFjaXR5LFxuXG4gICAgICAgIC8vIHJlbmRlclxuICAgICAgICBsaWdodFNldHRpbmdzOiBtZXRhLmxpZ2h0U2V0dGluZ3MsXG4gICAgICAgIHVwZGF0ZVRyaWdnZXJzXG4gICAgICB9KSxcbiAgICAgIC4uLih0aGlzLmlzTGF5ZXJIb3ZlcmVkKG9iamVjdEhvdmVyZWQpICYmICFjb25maWcuc2l6ZUZpZWxkXG4gICAgICAgID8gW1xuICAgICAgICAgICAgbmV3IEdlb0pzb25MYXllcih7XG4gICAgICAgICAgICAgIGlkOiBgJHt0aGlzLmlkfS1ob3ZlcmVkYCxcbiAgICAgICAgICAgICAgZGF0YTogW1xuICAgICAgICAgICAgICAgIGlkVG9Qb2x5Z29uR2VvKG9iamVjdEhvdmVyZWQsIHtcbiAgICAgICAgICAgICAgICAgIGxpbmVDb2xvcjogY29uZmlnLmhpZ2hsaWdodENvbG9yXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgbGluZVdpZHRoU2NhbGU6IDggKiB6b29tRmFjdG9yXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIF1cbiAgICAgICAgOiBbXSlcbiAgICBdO1xuICB9XG59XG4iXX0=