UNPKG

kepler.gl

Version:

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

428 lines (415 loc) 59.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.FeatureTypes = exports.COLUMN_MODE_GEOJSON = void 0; exports.applyFiltersToTableColumns = applyFiltersToTableColumns; exports.detectTableColumns = detectTableColumns; exports.featureToDeckGlGeoType = void 0; exports.fieldIsGeoArrow = fieldIsGeoArrow; exports.getGeojsonBounds = getGeojsonBounds; exports.getGeojsonDataMaps = getGeojsonDataMaps; exports.getGeojsonFeatureTypes = getGeojsonFeatureTypes; exports.getGeojsonLayerMeta = getGeojsonLayerMeta; exports.getGeojsonPointDataMaps = getGeojsonPointDataMaps; exports.groupColumnsAsGeoJson = groupColumnsAsGeoJson; exports.parseGeoJsonRawFeature = parseGeoJsonRawFeature; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _buffer = require("buffer"); var _geojsonNormalize = _interopRequireDefault(require("@mapbox/geojson-normalize")); var _bbox = _interopRequireDefault(require("@turf/bbox")); var _d3Array = require("d3-array"); var _center = _interopRequireDefault(require("@turf/center")); var _core = require("@loaders.gl/core"); var _wkt = require("@loaders.gl/wkt"); var _gis = require("@loaders.gl/gis"); var _utils = require("@kepler.gl/utils"); var _constants = require("@kepler.gl/constants"); var _layerUtils = require("../layer-utils"); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project var COLUMN_MODE_GEOJSON = exports.COLUMN_MODE_GEOJSON = 'geojson'; /* eslint-disable */ // TODO: Re-enable eslint when we upgrade to handle enums and type maps var FeatureTypes = exports.FeatureTypes = /*#__PURE__*/function (FeatureTypes) { FeatureTypes["Point"] = "Point"; FeatureTypes["MultiPoint"] = "MultiPoint"; FeatureTypes["LineString"] = "LineString"; FeatureTypes["MultiLineString"] = "MultiLineString"; FeatureTypes["Polygon"] = "Polygon"; FeatureTypes["MultiPolygon"] = "MultiPolygon"; return FeatureTypes; }({}); // @ts-expect-error return type of getGeojsonFeatureTypes ? /* eslint-enable */ /** * Returns true if the field has geoarrow extension. * @param geoField A field to test. * @returns */ function fieldIsGeoArrow(geoField) { var _geoField$metadata; return Boolean(geoField === null || geoField === void 0 || (_geoField$metadata = geoField.metadata) === null || _geoField$metadata === void 0 ? void 0 : _geoField$metadata.get('ARROW:extension:name')); } function parseGeoJsonRawFeature(rawFeature) { var properties = null; // help ensure that properties is present on the returned geojson feature if ((0, _typeof2["default"])(rawFeature) === 'object') { // Support GeoJson feature as object // probably need to normalize it as well var normalized = (0, _geojsonNormalize["default"])(rawFeature); if (!normalized || !Array.isArray(normalized.features)) { // fail to normalize GeoJson return null; } return _objectSpread({ properties: properties }, normalized.features[0]); } else if (typeof rawFeature === 'string') { var parsedGeometry = parseGeometryFromString(rawFeature); if (!parsedGeometry) return null; // @ts-expect-error verify whether parsedGeometry always contains properties return _objectSpread({ properties: properties }, parsedGeometry); } else if (Array.isArray(rawFeature)) { // Support GeoJson LineString as an array of points return { type: 'Feature', geometry: { // why do we need to flip it... coordinates: rawFeature.map(function (pts) { return [pts[1], pts[0]]; }), type: 'LineString' }, properties: properties }; } return null; } function getGeojsonLayerMeta(_ref) { var dataContainer = _ref.dataContainer, getFeature = _ref.getFeature, config = _ref.config; var dataToFeature = config.columnMode === COLUMN_MODE_GEOJSON ? getGeojsonDataMaps(dataContainer, getFeature) : // COLUMN_MODE_TABLE groupColumnsAsGeoJson(dataContainer, config.columns, 'sortBy'); // get bounds from features var bounds = getGeojsonBounds(dataToFeature); // if any of the feature has properties.radius set to be true var fixedRadius = Boolean(dataToFeature.find(function (d) { var _d$properties; return d && 'properties' in d && ((_d$properties = d.properties) === null || _d$properties === void 0 ? void 0 : _d$properties.radius); })); // keep a record of what type of geometry the collection has var featureTypes = getGeojsonFeatureTypes(dataToFeature); var meanCenters = []; for (var i = 0; i < dataToFeature.length; i++) { var feature = dataToFeature[i]; if (feature) { try { // TODO: use line interpolate to get center of line for LineString var cent = (0, _center["default"])(feature); meanCenters.push(cent.geometry.coordinates); } catch (e) { meanCenters.push(null); } } } return { dataToFeature: dataToFeature, bounds: bounds, fixedRadius: fixedRadius, featureTypes: featureTypes, centroids: meanCenters }; } /** * Parse raw data to GeoJson feature */ function getGeojsonDataMaps(dataContainer, getFeature) { var acceptableTypes = ['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon', 'GeometryCollection']; var dataToFeature = []; for (var index = 0; index < dataContainer.numRows(); index++) { var feature = parseGeoJsonRawFeature(getFeature({ index: index })); if (feature && feature.geometry && acceptableTypes.includes(feature.geometry.type)) { var cleaned = _objectSpread(_objectSpread({}, feature), {}, { // store index of the data in feature properties properties: _objectSpread(_objectSpread({}, feature.properties), {}, { index: index }) }); dataToFeature[index] = cleaned; } else { dataToFeature[index] = null; } } return dataToFeature; } /** * Parse raw data to GeoJson point feature coordinates */ function getGeojsonPointDataMaps(dataContainer, getFeature) { var acceptableTypes = ['Point', 'MultiPoint', 'GeometryCollection']; var dataToFeature = []; for (var index = 0; index < dataContainer.numRows(); index++) { var feature = parseGeoJsonRawFeature(getFeature(dataContainer.rowAsArray(index))); if (feature && feature.geometry && acceptableTypes.includes(feature.geometry.type)) { dataToFeature[index] = feature.geometry.type === 'Point' || feature.geometry.type === 'MultiPoint' ? feature.geometry.coordinates : // @ts-expect-error Property 'geometries' does not exist on type 'LineString' (feature.geometry.geometries || []).reduce(function (accu, f) { if (f.type === 'Point') { accu.push(f.coordinates); } else if (f.type === 'MultiPoint') { accu.push.apply(accu, (0, _toConsumableArray2["default"])(f.coordinates)); } return accu; }, []); } else { dataToFeature[index] = null; } } return dataToFeature; } /** * Parse geojson from string * @param {String} geoString * @returns {null | Object} geojson object or null if failed */ function parseGeometryFromString(geoString) { var parsedGeo; // try parse as geojson string // {"type":"Polygon","coordinates":[[[-74.158491,40.83594]]]} try { parsedGeo = JSON.parse(geoString); } catch (e) { // keep trying to parse } // try parse as wkt using loaders.gl WKTLoader if (!parsedGeo) { try { parsedGeo = (0, _core.parseSync)(geoString, _wkt.WKTLoader); } catch (e) { return null; } } // try parse as wkb using loaders.gl WKBLoader if (!parsedGeo) { try { var buffer = _buffer.Buffer.from(geoString, 'hex'); var binaryGeo = (0, _core.parseSync)(buffer, _wkt.WKBLoader); // @ts-expect-error parsedGeo = (0, _gis.binaryToGeometry)(binaryGeo); } catch (e) { return null; } } if (!parsedGeo) { return null; } var normalized = (0, _geojsonNormalize["default"])(parsedGeo); if (!normalized || !Array.isArray(normalized.features)) { // fail to normalize geojson return null; } return normalized.features[0]; } /** * Get geojson bounds */ function getGeojsonBounds() { var features = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; // 70 ms for 10,000 polygons // here we only pick couple var maxCount = 10000; var samples = features.length > maxCount ? (0, _utils.getSampleData)(features, maxCount) : features; var validSingleGeometry = function validSingleGeometry(geom) { return geom.coordinates && geom.coordinates.length; }; var validGeometryCollection = function validGeometryCollection(geom) { return geom.geometries && geom.geometries.length && geom.geometries.every(validSingleGeometry); }; var nonEmpty = samples.filter(function (d) { return d && d.geometry && (validSingleGeometry(d.geometry) || validGeometryCollection(d.geometry)); }); try { return (0, _bbox["default"])({ type: 'FeatureCollection', features: nonEmpty }); } catch (e) { return null; } } var featureToDeckGlGeoType = exports.featureToDeckGlGeoType = { Point: 'point', MultiPoint: 'point', LineString: 'line', MultiLineString: 'line', Polygon: 'polygon', MultiPolygon: 'polygon' }; /** * Parse geojson from string */ function getGeojsonFeatureTypes(allFeatures) { // @ts-expect-error some test cases only have 1 geotype var featureTypes = {}; for (var f = 0; f < allFeatures.length; f++) { var feature = allFeatures[f]; if (feature && 'geometry' in feature) { var geoType = featureToDeckGlGeoType[feature.geometry && feature.geometry.type]; if (geoType) { featureTypes[geoType] = true; } } } return featureTypes; } function groupColumnsAsGeoJson(dataContainer, columns) { var sortByColumn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'timestamp'; var groupedById = {}; var sortByFieldIdx = columns[sortByColumn].fieldIdx; var sortByRequired = !columns[sortByColumn].optional; for (var index = 0; index < dataContainer.numRows(); index++) { // note: can materialize the row var datum = dataContainer.rowAsArray(index); var id = datum[columns.id.fieldIdx]; var lat = datum[columns.lat.fieldIdx]; var lon = datum[columns.lng.fieldIdx]; var altitude = columns.altitude ? datum[columns.altitude.fieldIdx] : 0; var sortBy = sortByFieldIdx > -1 ? datum[sortByFieldIdx] : null; // @ts-expect-error var coords = [lon, lat, altitude, sortBy]; // Adding references to the original data to the coordinates array coords.datumIndex = index; coords.datum = datum; if (!groupedById[id]) groupedById[id] = []; if (Number.isFinite(lon) && Number.isFinite(lat) && (!sortByRequired || sortByRequired && sortBy)) { // only push points if lat,lng,and sortby exist groupedById[id].push(coords); } } var result = Object.entries(groupedById).map( // eslint-disable-next-line @typescript-eslint/no-unused-vars function (_ref2, index) { var _ref3 = (0, _slicedToArray2["default"])(_ref2, 2), _ = _ref3[0], items = _ref3[1]; return { type: 'Feature', geometry: { type: 'LineString', // Sort by columns if has sortByField // TODO: items are expected in Position[] format? coordinates: sortByFieldIdx > -1 ? items.sort(function (a, b) { return (0, _d3Array.ascending)(a[3], b[3]); }) : items }, properties: { index: index, // values are used for valueAccessor in TripLayer.formatLayerData() // Note: this can cause row materialization in case of non-row based containers values: items.map(function (item) { return dataContainer.rowAsArray(item.datumIndex); }) } }; }); return result; } /** * Find id / ts / lat / lng columns from a table and assign it to layer columns */ function detectTableColumns(dataset, layerColumns) { var sortBy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'timestamp'; var fields = dataset.fields, fieldPairs = dataset.fieldPairs; if (!fieldPairs.length || !fields.length) { return null; } // find sort by field var sortByFieldIdx = fields.findIndex(function (f) { return f.type === _constants.ALL_FIELD_TYPES.timestamp; }); // find id column var idFieldIdx = fields.findIndex(function (f) { var _f$name; return (_f$name = f.name) === null || _f$name === void 0 ? void 0 : _f$name.toLowerCase().match(/^(id|uuid)$/g); }); if (sortByFieldIdx > -1 && idFieldIdx > -1) { var pointColumns = (0, _layerUtils.assignPointPairToLayerColumn)(fieldPairs[0], true); return { columns: _objectSpread(_objectSpread({}, Object.keys(layerColumns).reduce(function (accu, col) { var _pointColumns$col; return _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, col, (_pointColumns$col = pointColumns[col]) !== null && _pointColumns$col !== void 0 ? _pointColumns$col : layerColumns[col])); }, {})), {}, (0, _defineProperty2["default"])({ geojson: { value: null, fieldIdx: -1 // optional: true }, id: { value: fields[idFieldIdx].name, fieldIdx: idFieldIdx // optional: false } }, sortBy, { value: fields[sortByFieldIdx].name, fieldIdx: sortByFieldIdx // optional: false })), label: fieldPairs[0].defaultName }; } return null; } function applyFiltersToTableColumns(dataset, dataToFeature) { var dataContainer = dataset.dataContainer, filteredIndex = dataset.filteredIndex; if (filteredIndex.length === dataContainer.numRows()) { // Only apply the filtering when something is to be filtered out return dataToFeature; } var filteredIndexSet = new Set(filteredIndex); var filteredFeatures = []; var _iterator = _createForOfIteratorHelper(dataToFeature), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var feature = _step.value; // @ts-expect-error geometry.coordinates not available for GeometryCollection var filteredCoords = feature.geometry.coordinates.filter(function (c) { return filteredIndexSet.has(c.datumIndex); }); if (filteredCoords.length > 0 && feature) { filteredFeatures.push(_objectSpread(_objectSpread({}, feature), {}, { geometry: _objectSpread(_objectSpread({}, feature.geometry), {}, { coordinates: filteredCoords }), properties: _objectSpread(_objectSpread({}, feature.properties), {}, { // @ts-expect-error BinaryFeatureCollection values: feature.geometry.coordinates.map(function (c) { return dataContainer.rowAsArray(c.datumIndex); }) }) })); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return filteredFeatures; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYnVmZmVyIiwicmVxdWlyZSIsIl9nZW9qc29uTm9ybWFsaXplIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9iYm94IiwiX2QzQXJyYXkiLCJfY2VudGVyIiwiX2NvcmUiLCJfd2t0IiwiX2dpcyIsIl91dGlscyIsIl9jb25zdGFudHMiLCJfbGF5ZXJVdGlscyIsIl9jcmVhdGVGb3JPZkl0ZXJhdG9ySGVscGVyIiwiciIsImUiLCJ0IiwiU3ltYm9sIiwiaXRlcmF0b3IiLCJBcnJheSIsImlzQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJsZW5ndGgiLCJfbiIsIkYiLCJzIiwibiIsImRvbmUiLCJ2YWx1ZSIsImYiLCJUeXBlRXJyb3IiLCJvIiwiYSIsInUiLCJjYWxsIiwibmV4dCIsIl9hcnJheUxpa2VUb0FycmF5IiwidG9TdHJpbmciLCJzbGljZSIsImNvbnN0cnVjdG9yIiwibmFtZSIsImZyb20iLCJ0ZXN0Iiwib3duS2V5cyIsIk9iamVjdCIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJmaWx0ZXIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJlbnVtZXJhYmxlIiwicHVzaCIsImFwcGx5IiwiX29iamVjdFNwcmVhZCIsImFyZ3VtZW50cyIsImZvckVhY2giLCJfZGVmaW5lUHJvcGVydHkyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyIsImRlZmluZVByb3BlcnRpZXMiLCJkZWZpbmVQcm9wZXJ0eSIsIkNPTFVNTl9NT0RFX0dFT0pTT04iLCJleHBvcnRzIiwiRmVhdHVyZVR5cGVzIiwiZmllbGRJc0dlb0Fycm93IiwiZ2VvRmllbGQiLCJfZ2VvRmllbGQkbWV0YWRhdGEiLCJCb29sZWFuIiwibWV0YWRhdGEiLCJnZXQiLCJwYXJzZUdlb0pzb25SYXdGZWF0dXJlIiwicmF3RmVhdHVyZSIsInByb3BlcnRpZXMiLCJfdHlwZW9mMiIsIm5vcm1hbGl6ZWQiLCJub3JtYWxpemUiLCJmZWF0dXJlcyIsInBhcnNlZEdlb21ldHJ5IiwicGFyc2VHZW9tZXRyeUZyb21TdHJpbmciLCJ0eXBlIiwiZ2VvbWV0cnkiLCJjb29yZGluYXRlcyIsIm1hcCIsInB0cyIsImdldEdlb2pzb25MYXllck1ldGEiLCJfcmVmIiwiZGF0YUNvbnRhaW5lciIsImdldEZlYXR1cmUiLCJjb25maWciLCJkYXRhVG9GZWF0dXJlIiwiY29sdW1uTW9kZSIsImdldEdlb2pzb25EYXRhTWFwcyIsImdyb3VwQ29sdW1uc0FzR2VvSnNvbiIsImNvbHVtbnMiLCJib3VuZHMiLCJnZXRHZW9qc29uQm91bmRzIiwiZml4ZWRSYWRpdXMiLCJmaW5kIiwiZCIsIl9kJHByb3BlcnRpZXMiLCJyYWRpdXMiLCJmZWF0dXJlVHlwZXMiLCJnZXRHZW9qc29uRmVhdHVyZVR5cGVzIiwibWVhbkNlbnRlcnMiLCJpIiwiZmVhdHVyZSIsImNlbnQiLCJjZW50ZXIiLCJjZW50cm9pZHMiLCJhY2NlcHRhYmxlVHlwZXMiLCJpbmRleCIsIm51bVJvd3MiLCJpbmNsdWRlcyIsImNsZWFuZWQiLCJnZXRHZW9qc29uUG9pbnREYXRhTWFwcyIsInJvd0FzQXJyYXkiLCJnZW9tZXRyaWVzIiwicmVkdWNlIiwiYWNjdSIsIl90b0NvbnN1bWFibGVBcnJheTIiLCJnZW9TdHJpbmciLCJwYXJzZWRHZW8iLCJKU09OIiwicGFyc2UiLCJwYXJzZVN5bmMiLCJXS1RMb2FkZXIiLCJidWZmZXIiLCJCdWZmZXIiLCJiaW5hcnlHZW8iLCJXS0JMb2FkZXIiLCJiaW5hcnlUb0dlb21ldHJ5IiwidW5kZWZpbmVkIiwibWF4Q291bnQiLCJzYW1wbGVzIiwiZ2V0U2FtcGxlRGF0YSIsInZhbGlkU2luZ2xlR2VvbWV0cnkiLCJnZW9tIiwidmFsaWRHZW9tZXRyeUNvbGxlY3Rpb24iLCJldmVyeSIsIm5vbkVtcHR5IiwiYmJveCIsImZlYXR1cmVUb0RlY2tHbEdlb1R5cGUiLCJQb2ludCIsIk11bHRpUG9pbnQiLCJMaW5lU3RyaW5nIiwiTXVsdGlMaW5lU3RyaW5nIiwiUG9seWdvbiIsIk11bHRpUG9seWdvbiIsImFsbEZlYXR1cmVzIiwiZ2VvVHlwZSIsInNvcnRCeUNvbHVtbiIsImdyb3VwZWRCeUlkIiwic29ydEJ5RmllbGRJZHgiLCJmaWVsZElkeCIsInNvcnRCeVJlcXVpcmVkIiwib3B0aW9uYWwiLCJkYXR1bSIsImlkIiwibGF0IiwibG9uIiwibG5nIiwiYWx0aXR1ZGUiLCJzb3J0QnkiLCJjb29yZHMiLCJkYXR1bUluZGV4IiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJyZXN1bHQiLCJlbnRyaWVzIiwiX3JlZjIiLCJfcmVmMyIsIl9zbGljZWRUb0FycmF5MiIsIl8iLCJpdGVtcyIsInNvcnQiLCJiIiwiYXNjZW5kaW5nIiwidmFsdWVzIiwiaXRlbSIsImRldGVjdFRhYmxlQ29sdW1ucyIsImRhdGFzZXQiLCJsYXllckNvbHVtbnMiLCJmaWVsZHMiLCJmaWVsZFBhaXJzIiwiZmluZEluZGV4IiwiQUxMX0ZJRUxEX1RZUEVTIiwidGltZXN0YW1wIiwiaWRGaWVsZElkeCIsIl9mJG5hbWUiLCJ0b0xvd2VyQ2FzZSIsIm1hdGNoIiwicG9pbnRDb2x1bW5zIiwiYXNzaWduUG9pbnRQYWlyVG9MYXllckNvbHVtbiIsImNvbCIsIl9wb2ludENvbHVtbnMkY29sIiwiZ2VvanNvbiIsImxhYmVsIiwiZGVmYXVsdE5hbWUiLCJhcHBseUZpbHRlcnNUb1RhYmxlQ29sdW1ucyIsImZpbHRlcmVkSW5kZXgiLCJmaWx0ZXJlZEluZGV4U2V0IiwiU2V0IiwiZmlsdGVyZWRGZWF0dXJlcyIsIl9pdGVyYXRvciIsIl9zdGVwIiwiZmlsdGVyZWRDb29yZHMiLCJjIiwiaGFzIiwiZXJyIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2dlb2pzb24tbGF5ZXIvZ2VvanNvbi11dGlscy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge0J1ZmZlcn0gZnJvbSAnYnVmZmVyJztcbmltcG9ydCB7RmVhdHVyZSwgUG9zaXRpb24sIEJCb3h9IGZyb20gJ2dlb2pzb24nO1xuaW1wb3J0IG5vcm1hbGl6ZSBmcm9tICdAbWFwYm94L2dlb2pzb24tbm9ybWFsaXplJztcbmltcG9ydCBiYm94IGZyb20gJ0B0dXJmL2Jib3gnO1xuaW1wb3J0IHthc2NlbmRpbmd9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCBjZW50ZXIgZnJvbSAnQHR1cmYvY2VudGVyJztcbmltcG9ydCB7QWxsR2VvSlNPTn0gZnJvbSAnQHR1cmYvaGVscGVycyc7XG5pbXBvcnQge3BhcnNlU3luY30gZnJvbSAnQGxvYWRlcnMuZ2wvY29yZSc7XG5pbXBvcnQge1dLQkxvYWRlciwgV0tUTG9hZGVyfSBmcm9tICdAbG9hZGVycy5nbC93a3QnO1xuaW1wb3J0IHtiaW5hcnlUb0dlb21ldHJ5fSBmcm9tICdAbG9hZGVycy5nbC9naXMnO1xuaW1wb3J0IHtCaW5hcnlGZWF0dXJlQ29sbGVjdGlvbn0gZnJvbSAnQGxvYWRlcnMuZ2wvc2NoZW1hJztcbmltcG9ydCB7RGF0YUNvbnRhaW5lckludGVyZmFjZSwgZ2V0U2FtcGxlRGF0YX0gZnJvbSAnQGtlcGxlci5nbC91dGlscyc7XG5pbXBvcnQge0FMTF9GSUVMRF9UWVBFU30gZnJvbSAnQGtlcGxlci5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtMYXllckNvbHVtbnMsIFByb3RvRGF0YXNldEZpZWxkfSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7S2VwbGVyVGFibGV9IGZyb20gJ0BrZXBsZXIuZ2wvdGFibGUnO1xuXG5pbXBvcnQge0dlb2pzb25MYXllck1ldGFQcm9wcywgYXNzaWduUG9pbnRQYWlyVG9MYXllckNvbHVtbn0gZnJvbSAnLi4vbGF5ZXItdXRpbHMnO1xuaW1wb3J0IHtMYXllckJhc2VDb25maWd9IGZyb20gJy4uL2Jhc2UtbGF5ZXInO1xuXG5leHBvcnQgdHlwZSBHZXRGZWF0dXJlID0gKGQ6IGFueSkgPT4gRmVhdHVyZTtcbmV4cG9ydCB0eXBlIEdlb2pzb25EYXRhTWFwcyA9IChGZWF0dXJlIHwgQmluYXJ5RmVhdHVyZUNvbGxlY3Rpb24gfCBudWxsKVtdO1xuZXhwb3J0IHR5cGUgR2VvanNvblBvaW50RGF0YU1hcHMgPSAobnVtYmVyW10gfCBudW1iZXJbXVtdIHwgbnVsbClbXTtcblxuZXhwb3J0IGNvbnN0IENPTFVNTl9NT0RFX0dFT0pTT04gPSAnZ2VvanNvbic7XG5cbi8qIGVzbGludC1kaXNhYmxlICovXG4vLyBUT0RPOiBSZS1lbmFibGUgZXNsaW50IHdoZW4gd2UgdXBncmFkZSB0byBoYW5kbGUgZW51bXMgYW5kIHR5cGUgbWFwc1xuZXhwb3J0IGVudW0gRmVhdHVyZVR5cGVzIHtcbiAgUG9pbnQgPSAnUG9pbnQnLFxuICBNdWx0aVBvaW50ID0gJ011bHRpUG9pbnQnLFxuICBMaW5lU3RyaW5nID0gJ0xpbmVTdHJpbmcnLFxuICBNdWx0aUxpbmVTdHJpbmcgPSAnTXVsdGlMaW5lU3RyaW5nJyxcbiAgUG9seWdvbiA9ICdQb2x5Z29uJyxcbiAgTXVsdGlQb2x5Z29uID0gJ011bHRpUG9seWdvbidcbn1cblxuLy8gQHRzLWV4cGVjdC1lcnJvciByZXR1cm4gdHlwZSBvZiBnZXRHZW9qc29uRmVhdHVyZVR5cGVzID9cbnR5cGUgRmVhdHVyZVR5cGVNYXAgPSB7XG4gIFtrZXkgaW4gRmVhdHVyZVR5cGVzXTogYm9vbGVhbjtcbn07XG5cbi8qIGVzbGludC1lbmFibGUgKi9cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIGZpZWxkIGhhcyBnZW9hcnJvdyBleHRlbnNpb24uXG4gKiBAcGFyYW0gZ2VvRmllbGQgQSBmaWVsZCB0byB0ZXN0LlxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpZWxkSXNHZW9BcnJvdyhnZW9GaWVsZD86IFByb3RvRGF0YXNldEZpZWxkIHwgbnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gQm9vbGVhbihnZW9GaWVsZD8ubWV0YWRhdGE/LmdldCgnQVJST1c6ZXh0ZW5zaW9uOm5hbWUnKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUdlb0pzb25SYXdGZWF0dXJlKHJhd0ZlYXR1cmU6IHVua25vd24pOiBGZWF0dXJlIHwgbnVsbCB7XG4gIGNvbnN0IHByb3BlcnRpZXMgPSBudWxsOyAvLyBoZWxwIGVuc3VyZSB0aGF0IHByb3BlcnRpZXMgaXMgcHJlc2VudCBvbiB0aGUgcmV0dXJuZWQgZ2VvanNvbiBmZWF0dXJlXG4gIGlmICh0eXBlb2YgcmF3RmVhdHVyZSA9PT0gJ29iamVjdCcpIHtcbiAgICAvLyBTdXBwb3J0IEdlb0pzb24gZmVhdHVyZSBhcyBvYmplY3RcbiAgICAvLyBwcm9iYWJseSBuZWVkIHRvIG5vcm1hbGl6ZSBpdCBhcyB3ZWxsXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZShyYXdGZWF0dXJlKTtcbiAgICBpZiAoIW5vcm1hbGl6ZWQgfHwgIUFycmF5LmlzQXJyYXkobm9ybWFsaXplZC5mZWF0dXJlcykpIHtcbiAgICAgIC8vIGZhaWwgdG8gbm9ybWFsaXplIEdlb0pzb25cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB7cHJvcGVydGllcywgLi4ubm9ybWFsaXplZC5mZWF0dXJlc1swXX07XG4gIH0gZWxzZSBpZiAodHlwZW9mIHJhd0ZlYXR1cmUgPT09ICdzdHJpbmcnKSB7XG4gICAgY29uc3QgcGFyc2VkR2VvbWV0cnkgPSBwYXJzZUdlb21ldHJ5RnJvbVN0cmluZyhyYXdGZWF0dXJlKTtcbiAgICBpZiAoIXBhcnNlZEdlb21ldHJ5KSByZXR1cm4gbnVsbDtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHZlcmlmeSB3aGV0aGVyIHBhcnNlZEdlb21ldHJ5IGFsd2F5cyBjb250YWlucyBwcm9wZXJ0aWVzXG4gICAgcmV0dXJuIHtwcm9wZXJ0aWVzLCAuLi5wYXJzZWRHZW9tZXRyeX07XG4gIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyYXdGZWF0dXJlKSkge1xuICAgIC8vIFN1cHBvcnQgR2VvSnNvbiAgTGluZVN0cmluZyBhcyBhbiBhcnJheSBvZiBwb2ludHNcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ0ZlYXR1cmUnLFxuICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgLy8gd2h5IGRvIHdlIG5lZWQgdG8gZmxpcCBpdC4uLlxuICAgICAgICBjb29yZGluYXRlczogcmF3RmVhdHVyZS5tYXAocHRzID0+IFtwdHNbMV0sIHB0c1swXV0pLFxuICAgICAgICB0eXBlOiAnTGluZVN0cmluZydcbiAgICAgIH0sXG4gICAgICBwcm9wZXJ0aWVzXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2VvanNvbkxheWVyTWV0YSh7XG4gIGRhdGFDb250YWluZXIsXG4gIGdldEZlYXR1cmUsXG4gIGNvbmZpZ1xufToge1xuICBkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlO1xuICBnZXRGZWF0dXJlOiBHZXRGZWF0dXJlO1xuICBjb25maWc6IExheWVyQmFzZUNvbmZpZztcbn0pOiBHZW9qc29uTGF5ZXJNZXRhUHJvcHMge1xuICBjb25zdCBkYXRhVG9GZWF0dXJlID1cbiAgICBjb25maWcuY29sdW1uTW9kZSA9PT0gQ09MVU1OX01PREVfR0VPSlNPTlxuICAgICAgPyBnZXRHZW9qc29uRGF0YU1hcHMoZGF0YUNvbnRhaW5lciwgZ2V0RmVhdHVyZSlcbiAgICAgIDogLy8gQ09MVU1OX01PREVfVEFCTEVcbiAgICAgICAgZ3JvdXBDb2x1bW5zQXNHZW9Kc29uKGRhdGFDb250YWluZXIsIGNvbmZpZy5jb2x1bW5zLCAnc29ydEJ5Jyk7XG5cbiAgLy8gZ2V0IGJvdW5kcyBmcm9tIGZlYXR1cmVzXG4gIGNvbnN0IGJvdW5kcyA9IGdldEdlb2pzb25Cb3VuZHMoZGF0YVRvRmVhdHVyZSk7XG4gIC8vIGlmIGFueSBvZiB0aGUgZmVhdHVyZSBoYXMgcHJvcGVydGllcy5yYWRpdXMgc2V0IHRvIGJlIHRydWVcbiAgY29uc3QgZml4ZWRSYWRpdXMgPSBCb29sZWFuKFxuICAgIGRhdGFUb0ZlYXR1cmUuZmluZChkID0+IGQgJiYgJ3Byb3BlcnRpZXMnIGluIGQgJiYgZC5wcm9wZXJ0aWVzPy5yYWRpdXMpXG4gICk7XG5cbiAgLy8ga2VlcCBhIHJlY29yZCBvZiB3aGF0IHR5cGUgb2YgZ2VvbWV0cnkgdGhlIGNvbGxlY3Rpb24gaGFzXG4gIGNvbnN0IGZlYXR1cmVUeXBlcyA9IGdldEdlb2pzb25GZWF0dXJlVHlwZXMoZGF0YVRvRmVhdHVyZSk7XG5cbiAgY29uc3QgbWVhbkNlbnRlcnM6IEFycmF5PG51bWJlcltdIHwgbnVsbD4gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhVG9GZWF0dXJlLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZmVhdHVyZSA9IGRhdGFUb0ZlYXR1cmVbaV07XG4gICAgaWYgKGZlYXR1cmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFRPRE86IHVzZSBsaW5lIGludGVycG9sYXRlIHRvIGdldCBjZW50ZXIgb2YgbGluZSBmb3IgTGluZVN0cmluZ1xuICAgICAgICBjb25zdCBjZW50ID0gY2VudGVyKGZlYXR1cmUgYXMgQWxsR2VvSlNPTik7XG4gICAgICAgIG1lYW5DZW50ZXJzLnB1c2goY2VudC5nZW9tZXRyeS5jb29yZGluYXRlcyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIG1lYW5DZW50ZXJzLnB1c2gobnVsbCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBkYXRhVG9GZWF0dXJlLFxuICAgIGJvdW5kcyxcbiAgICBmaXhlZFJhZGl1cyxcbiAgICBmZWF0dXJlVHlwZXMsXG4gICAgY2VudHJvaWRzOiBtZWFuQ2VudGVyc1xuICB9O1xufVxuXG4vKipcbiAqIFBhcnNlIHJhdyBkYXRhIHRvIEdlb0pzb24gZmVhdHVyZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2VvanNvbkRhdGFNYXBzKFxuICBkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlLFxuICBnZXRGZWF0dXJlOiBHZXRGZWF0dXJlXG4pOiBHZW9qc29uRGF0YU1hcHMge1xuICBjb25zdCBhY2NlcHRhYmxlVHlwZXMgPSBbXG4gICAgJ1BvaW50JyxcbiAgICAnTXVsdGlQb2ludCcsXG4gICAgJ0xpbmVTdHJpbmcnLFxuICAgICdNdWx0aUxpbmVTdHJpbmcnLFxuICAgICdQb2x5Z29uJyxcbiAgICAnTXVsdGlQb2x5Z29uJyxcbiAgICAnR2VvbWV0cnlDb2xsZWN0aW9uJ1xuICBdO1xuXG4gIGNvbnN0IGRhdGFUb0ZlYXR1cmU6IEdlb2pzb25EYXRhTWFwcyA9IFtdO1xuXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBkYXRhQ29udGFpbmVyLm51bVJvd3MoKTsgaW5kZXgrKykge1xuICAgIGNvbnN0IGZlYXR1cmUgPSBwYXJzZUdlb0pzb25SYXdGZWF0dXJlKGdldEZlYXR1cmUoe2luZGV4fSkpO1xuXG4gICAgaWYgKGZlYXR1cmUgJiYgZmVhdHVyZS5nZW9tZXRyeSAmJiBhY2NlcHRhYmxlVHlwZXMuaW5jbHVkZXMoZmVhdHVyZS5nZW9tZXRyeS50eXBlKSkge1xuICAgICAgY29uc3QgY2xlYW5lZCA9IHtcbiAgICAgICAgLi4uZmVhdHVyZSxcbiAgICAgICAgLy8gc3RvcmUgaW5kZXggb2YgdGhlIGRhdGEgaW4gZmVhdHVyZSBwcm9wZXJ0aWVzXG4gICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAuLi5mZWF0dXJlLnByb3BlcnRpZXMsXG4gICAgICAgICAgaW5kZXhcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgZGF0YVRvRmVhdHVyZVtpbmRleF0gPSBjbGVhbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRhVG9GZWF0dXJlW2luZGV4XSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRhdGFUb0ZlYXR1cmU7XG59XG5cbi8qKlxuICogUGFyc2UgcmF3IGRhdGEgdG8gR2VvSnNvbiBwb2ludCBmZWF0dXJlIGNvb3JkaW5hdGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRHZW9qc29uUG9pbnREYXRhTWFwcyhcbiAgZGF0YUNvbnRhaW5lcjogRGF0YUNvbnRhaW5lckludGVyZmFjZSxcbiAgZ2V0RmVhdHVyZTogR2V0RmVhdHVyZVxuKTogR2VvanNvblBvaW50RGF0YU1hcHMge1xuICBjb25zdCBhY2NlcHRhYmxlVHlwZXMgPSBbJ1BvaW50JywgJ011bHRpUG9pbnQnLCAnR2VvbWV0cnlDb2xsZWN0aW9uJ107XG5cbiAgY29uc3QgZGF0YVRvRmVhdHVyZTogR2VvanNvblBvaW50RGF0YU1hcHMgPSBbXTtcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZGF0YUNvbnRhaW5lci5udW1Sb3dzKCk7IGluZGV4KyspIHtcbiAgICBjb25zdCBmZWF0dXJlID0gcGFyc2VHZW9Kc29uUmF3RmVhdHVyZShnZXRGZWF0dXJlKGRhdGFDb250YWluZXIucm93QXNBcnJheShpbmRleCkpKTtcblxuICAgIGlmIChmZWF0dXJlICYmIGZlYXR1cmUuZ2VvbWV0cnkgJiYgYWNjZXB0YWJsZVR5cGVzLmluY2x1ZGVzKGZlYXR1cmUuZ2VvbWV0cnkudHlwZSkpIHtcbiAgICAgIGRhdGFUb0ZlYXR1cmVbaW5kZXhdID1cbiAgICAgICAgZmVhdHVyZS5nZW9tZXRyeS50eXBlID09PSAnUG9pbnQnIHx8IGZlYXR1cmUuZ2VvbWV0cnkudHlwZSA9PT0gJ011bHRpUG9pbnQnXG4gICAgICAgICAgPyBmZWF0dXJlLmdlb21ldHJ5LmNvb3JkaW5hdGVzXG4gICAgICAgICAgOiAvLyBAdHMtZXhwZWN0LWVycm9yIFByb3BlcnR5ICdnZW9tZXRyaWVzJyBkb2VzIG5vdCBleGlzdCBvbiB0eXBlICdMaW5lU3RyaW5nJ1xuICAgICAgICAgICAgKGZlYXR1cmUuZ2VvbWV0cnkuZ2VvbWV0cmllcyB8fCBbXSkucmVkdWNlKChhY2N1LCBmKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChmLnR5cGUgPT09ICdQb2ludCcpIHtcbiAgICAgICAgICAgICAgICBhY2N1LnB1c2goZi5jb29yZGluYXRlcyk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZi50eXBlID09PSAnTXVsdGlQb2ludCcpIHtcbiAgICAgICAgICAgICAgICBhY2N1LnB1c2goLi4uZi5jb29yZGluYXRlcyk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZXR1cm4gYWNjdTtcbiAgICAgICAgICAgIH0sIFtdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGF0YVRvRmVhdHVyZVtpbmRleF0gPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkYXRhVG9GZWF0dXJlO1xufVxuXG4vKipcbiAqIFBhcnNlIGdlb2pzb24gZnJvbSBzdHJpbmdcbiAqIEBwYXJhbSB7U3RyaW5nfSBnZW9TdHJpbmdcbiAqIEByZXR1cm5zIHtudWxsIHwgT2JqZWN0fSBnZW9qc29uIG9iamVjdCBvciBudWxsIGlmIGZhaWxlZFxuICovXG5mdW5jdGlvbiBwYXJzZUdlb21ldHJ5RnJvbVN0cmluZyhnZW9TdHJpbmc6IHN0cmluZyk6IEZlYXR1cmUgfCBudWxsIHtcbiAgbGV0IHBhcnNlZEdlbztcblxuICAvLyB0cnkgcGFyc2UgYXMgZ2VvanNvbiBzdHJpbmdcbiAgLy8ge1widHlwZVwiOlwiUG9seWdvblwiLFwiY29vcmRpbmF0ZXNcIjpbW1stNzQuMTU4NDkxLDQwLjgzNTk0XV1dfVxuICB0cnkge1xuICAgIHBhcnNlZEdlbyA9IEpTT04ucGFyc2UoZ2VvU3RyaW5nKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIGtlZXAgdHJ5aW5nIHRvIHBhcnNlXG4gIH1cblxuICAvLyB0cnkgcGFyc2UgYXMgd2t0IHVzaW5nIGxvYWRlcnMuZ2wgV0tUTG9hZGVyXG4gIGlmICghcGFyc2VkR2VvKSB7XG4gICAgdHJ5IHtcbiAgICAgIHBhcnNlZEdlbyA9IHBhcnNlU3luYyhnZW9TdHJpbmcsIFdLVExvYWRlcik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gdHJ5IHBhcnNlIGFzIHdrYiB1c2luZyBsb2FkZXJzLmdsIFdLQkxvYWRlclxuICBpZiAoIXBhcnNlZEdlbykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuZnJvbShnZW9TdHJpbmcsICdoZXgnKTtcbiAgICAgIGNvbnN0IGJpbmFyeUdlbyA9IHBhcnNlU3luYyhidWZmZXIsIFdLQkxvYWRlcik7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBwYXJzZWRHZW8gPSBiaW5hcnlUb0dlb21ldHJ5KGJpbmFyeUdlbyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFwYXJzZWRHZW8pIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemUocGFyc2VkR2VvKTtcblxuICBpZiAoIW5vcm1hbGl6ZWQgfHwgIUFycmF5LmlzQXJyYXkobm9ybWFsaXplZC5mZWF0dXJlcykpIHtcbiAgICAvLyBmYWlsIHRvIG5vcm1hbGl6ZSBnZW9qc29uXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gbm9ybWFsaXplZC5mZWF0dXJlc1swXTtcbn1cblxuLyoqXG4gKiBHZXQgZ2VvanNvbiBib3VuZHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdlb2pzb25Cb3VuZHMoZmVhdHVyZXM6IEdlb2pzb25EYXRhTWFwcyA9IFtdKTogQkJveCB8IG51bGwge1xuICAvLyA3MCBtcyBmb3IgMTAsMDAwIHBvbHlnb25zXG4gIC8vIGhlcmUgd2Ugb25seSBwaWNrIGNvdXBsZVxuICBjb25zdCBtYXhDb3VudCA9IDEwMDAwO1xuICBjb25zdCBzYW1wbGVzID0gZmVhdHVyZXMubGVuZ3RoID4gbWF4Q291bnQgPyBnZXRTYW1wbGVEYXRhKGZlYXR1cmVzLCBtYXhDb3VudCkgOiBmZWF0dXJlcztcblxuICBjb25zdCB2YWxpZFNpbmdsZUdlb21ldHJ5ID0gZ2VvbSA9PiBnZW9tLmNvb3JkaW5hdGVzICYmIGdlb20uY29vcmRpbmF0ZXMubGVuZ3RoO1xuICBjb25zdCB2YWxpZEdlb21ldHJ5Q29sbGVjdGlvbiA9IGdlb20gPT5cbiAgICBnZW9tLmdlb21ldHJpZXMgJiYgZ2VvbS5nZW9tZXRyaWVzLmxlbmd0aCAmJiBnZW9tLmdlb21ldHJpZXMuZXZlcnkodmFsaWRTaW5nbGVHZW9tZXRyeSk7XG4gIGNvbnN0IG5vbkVtcHR5ID0gc2FtcGxlcy5maWx0ZXIoXG4gICAgZCA9PiBkICYmIGQuZ2VvbWV0cnkgJiYgKHZhbGlkU2luZ2xlR2VvbWV0cnkoZC5nZW9tZXRyeSkgfHwgdmFsaWRHZW9tZXRyeUNvbGxlY3Rpb24oZC5nZW9tZXRyeSkpXG4gICk7XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gYmJveCh7XG4gICAgICB0eXBlOiAnRmVhdHVyZUNvbGxlY3Rpb24nLFxuICAgICAgZmVhdHVyZXM6IG5vbkVtcHR5XG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZmVhdHVyZVRvRGVja0dsR2VvVHlwZSA9IHtcbiAgUG9pbnQ6ICdwb2ludCcsXG4gIE11bHRpUG9pbnQ6ICdwb2ludCcsXG4gIExpbmVTdHJpbmc6ICdsaW5lJyxcbiAgTXVsdGlMaW5lU3RyaW5nOiAnbGluZScsXG4gIFBvbHlnb246ICdwb2x5Z29uJyxcbiAgTXVsdGlQb2x5Z29uOiAncG9seWdvbidcbn07XG5cbmV4cG9ydCB0eXBlIERlY2tHbEdlb1R5cGVzID0ge1xuICBwb2ludDogYm9vbGVhbjtcbiAgbGluZTogYm9vbGVhbjtcbiAgcG9seWdvbjogYm9vbGVhbjtcbn07XG5cbi8qKlxuICogUGFyc2UgZ2VvanNvbiBmcm9tIHN0cmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2VvanNvbkZlYXR1cmVUeXBlcyhhbGxGZWF0dXJlczogR2VvanNvbkRhdGFNYXBzKTogRGVja0dsR2VvVHlwZXMge1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIHNvbWUgdGVzdCBjYXNlcyBvbmx5IGhhdmUgMSBnZW90eXBlXG4gIGNvbnN0IGZlYXR1cmVUeXBlczogRGVja0dsR2VvVHlwZXMgPSB7fTtcbiAgZm9yIChsZXQgZiA9IDA7IGYgPCBhbGxGZWF0dXJlcy5sZW5ndGg7IGYrKykge1xuICAgIGNvbnN0IGZlYXR1cmUgPSBhbGxGZWF0dXJlc1tmXTtcbiAgICBpZiAoZmVhdHVyZSAmJiAnZ2VvbWV0cnknIGluIGZlYXR1cmUpIHtcbiAgICAgIGNvbnN0IGdlb1R5cGUgPSBmZWF0dXJlVG9EZWNrR2xHZW9UeXBlW2ZlYXR1cmUuZ2VvbWV0cnkgJiYgZmVhdHVyZS5nZW9tZXRyeS50eXBlXTtcbiAgICAgIGlmIChnZW9UeXBlKSB7XG4gICAgICAgIGZlYXR1cmVUeXBlc1tnZW9UeXBlXSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZlYXR1cmVUeXBlcztcbn1cblxudHlwZSBDb29yZHNUeXBlID0gW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciB8IG51bGxdICYge1xuICBkYXR1bUluZGV4OiBudW1iZXI7XG4gIGRhdHVtOiBudW1iZXJbXTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBncm91cENvbHVtbnNBc0dlb0pzb24oXG4gIGRhdGFDb250YWluZXI6IERhdGFDb250YWluZXJJbnRlcmZhY2UsXG4gIGNvbHVtbnM6IExheWVyQ29sdW1ucyxcbiAgc29ydEJ5Q29sdW1uID0gJ3RpbWVzdGFtcCdcbik6IEZlYXR1cmVbXSB7XG4gIGNvbnN0IGdyb3VwZWRCeUlkOiB7W2tleTogc3RyaW5nXTogQ29vcmRzVHlwZVtdfSA9IHt9O1xuICBjb25zdCBzb3J0QnlGaWVsZElkeCA9IGNvbHVtbnNbc29ydEJ5Q29sdW1uXS5maWVsZElkeDtcbiAgY29uc3Qgc29ydEJ5UmVxdWlyZWQgPSAhY29sdW1uc1tzb3J0QnlDb2x1bW5dLm9wdGlvbmFsO1xuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZGF0YUNvbnRhaW5lci5udW1Sb3dzKCk7IGluZGV4KyspIHtcbiAgICAvLyBub3RlOiBjYW4gbWF0ZXJpYWxpemUgdGhlIHJvd1xuICAgIGNvbnN0IGRhdHVtID0gZGF0YUNvbnRhaW5lci5yb3dBc0FycmF5KGluZGV4KTtcbiAgICBjb25zdCBpZCA9IGRhdHVtW2NvbHVtbnMuaWQuZmllbGRJZHhdO1xuICAgIGNvbnN0IGxhdCA9IGRhdHVtW2NvbHVtbnMubGF0LmZpZWxkSWR4XTtcbiAgICBjb25zdCBsb24gPSBkYXR1bVtjb2x1bW5zLmxuZy5maWVsZElkeF07XG4gICAgY29uc3QgYWx0aXR1ZGUgPSBjb2x1bW5zLmFsdGl0dWRlID8gZGF0dW1bY29sdW1ucy5hbHRpdHVkZS5maWVsZElkeF0gOiAwO1xuICAgIGNvbnN0IHNvcnRCeSA9IHNvcnRCeUZpZWxkSWR4ID4gLTEgPyBkYXR1bVtzb3J0QnlGaWVsZElkeF0gOiBudWxsO1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICBjb25zdCBjb29yZHM6IENvb3Jkc1R5cGUgPSBbbG9uLCBsYXQsIGFsdGl0dWRlLCBzb3J0QnldO1xuICAgIC8vIEFkZGluZyByZWZlcmVuY2VzIHRvIHRoZSBvcmlnaW5hbCBkYXRhIHRvIHRoZSBjb29yZGluYXRlcyBhcnJheVxuICAgIGNvb3Jkcy5kYXR1bUluZGV4ID0gaW5kZXg7XG4gICAgY29vcmRzLmRhdHVtID0gZGF0dW07XG4gICAgaWYgKCFncm91cGVkQnlJZFtpZF0pIGdyb3VwZWRCeUlkW2lkXSA9IFtdO1xuXG4gICAgaWYgKFxuICAgICAgTnVtYmVyLmlzRmluaXRlKGxvbikgJiZcbiAgICAgIE51bWJlci5pc0Zpbml0ZShsYXQpICYmXG4gICAgICAoIXNvcnRCeVJlcXVpcmVkIHx8IChzb3J0QnlSZXF1aXJlZCAmJiBzb3J0QnkpKVxuICAgICkge1xuICAgICAgLy8gb25seSBwdXNoIHBvaW50cyBpZiBsYXQsbG5nLGFuZCBzb3J0YnkgZXhpc3RcbiAgICAgIGdyb3VwZWRCeUlkW2lkXS5wdXNoKGNvb3Jkcyk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBGZWF0dXJlW10gPSBPYmplY3QuZW50cmllcyhncm91cGVkQnlJZCkubWFwKFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAoW18sIGl0ZW1zXTogW3N0cmluZywgQ29vcmRzVHlwZVtdXSwgaW5kZXgpID0+ICh7XG4gICAgICB0eXBlOiAnRmVhdHVyZScgYXMgY29uc3QsXG4gICAgICBnZW9tZXRyeToge1xuICAgICAgICB0eXBlOiAnTGluZVN0cmluZycgYXMgY29uc3QsXG4gICAgICAgIC8vIFNvcnQgYnkgY29sdW1ucyBpZiBoYXMgc29ydEJ5RmllbGRcbiAgICAgICAgLy8gVE9ETzogaXRlbXMgYXJlIGV4cGVjdGVkIGluIFBvc2l0aW9uW10gZm9ybWF0P1xuICAgICAgICBjb29yZGluYXRlczogKHNvcnRCeUZpZWxkSWR4ID4gLTFcbiAgICAgICAgICA/IGl0ZW1zLnNvcnQoKGEsIGIpID0+IGFzY2VuZGluZyhhWzNdIGFzIGFueSwgYlszXSBhcyBhbnkpKVxuICAgICAgICAgIDogaXRlbXMpIGFzIFBvc2l0aW9uW11cbiAgICAgIH0sXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGluZGV4LFxuICAgICAgICAvLyB2YWx1ZXMgYXJlIHVzZWQgZm9yIHZhbHVlQWNjZXNzb3IgaW4gVHJpcExheWVyLmZvcm1hdExheWVyRGF0YSgpXG4gICAgICAgIC8vIE5vdGU6IHRoaXMgY2FuIGNhdXNlIHJvdyBtYXRlcmlhbGl6YXRpb24gaW4gY2FzZSBvZiBub24tcm93IGJhc2VkIGNvbnRhaW5lcnNcbiAgICAgICAgdmFsdWVzOiBpdGVtcy5tYXAoaXRlbSA9PiBkYXRhQ29udGFpbmVyLnJvd0FzQXJyYXkoaXRlbS5kYXR1bUluZGV4KSlcbiAgICAgIH1cbiAgICB9KVxuICApO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIEZpbmQgaWQgLyB0cyAvIGxhdCAvIGxuZyBjb2x1bW5zIGZyb20gYSB0YWJsZSBhbmQgYXNzaWduIGl0IHRvIGxheWVyIGNvbHVtbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRldGVjdFRhYmxlQ29sdW1ucyhcbiAgZGF0YXNldDogS2VwbGVyVGFibGUsXG4gIGxheWVyQ29sdW1uczogTGF5ZXJDb2x1bW5zLFxuICBzb3J0QnkgPSAndGltZXN0YW1wJ1xuKSB7XG4gIGNvbnN0IHtmaWVsZHMsIGZpZWxkUGFpcnN9ID0gZGF0YXNldDtcbiAgaWYgKCFmaWVsZFBhaXJzLmxlbmd0aCB8fCAhZmllbGRzLmxlbmd0aCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIC8vIGZpbmQgc29ydCBieSBmaWVsZFxuICBjb25zdCBzb3J0QnlGaWVsZElkeCA9IGZpZWxkcy5maW5kSW5kZXgoZiA9PiBmLnR5cGUgPT09IEFMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXApO1xuICAvLyBmaW5kIGlkIGNvbHVtblxuICBjb25zdCBpZEZpZWxkSWR4ID0gZmllbGRzLmZpbmRJbmRleChmID0+IGYubmFtZT8udG9Mb3dlckNhc2UoKS5tYXRjaCgvXihpZHx1dWlkKSQvZykpO1xuXG4gIGlmIChzb3J0QnlGaWVsZElkeCA+IC0xICYmIGlkRmllbGRJZHggPiAtMSkge1xuICAgIGNvbnN0IHBvaW50Q29sdW1ucyA9IGFzc2lnblBvaW50UGFpclRvTGF5ZXJDb2x1bW4oZmllbGRQYWlyc1swXSwgdHJ1ZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbHVtbnM6IHtcbiAgICAgICAgLi4uT2JqZWN0LmtleXMobGF5ZXJDb2x1bW5zKS5yZWR1Y2UoXG4gICAgICAgICAgKGFjY3UsIGNvbCkgPT4gKHtcbiAgICAgICAgICAgIC4uLmFjY3UsXG4gICAgICAgICAgICBbY29sXTogcG9pbnRDb2x1bW5zW2NvbF0gPz8gbGF5ZXJDb2x1bW5zW2NvbF1cbiAgICAgICAgICB9KSxcbiAgICAgICAgICB7fVxuICAgICAgICApLFxuICAgICAgICBnZW9qc29uOiB7XG4gICAgICAgICAgdmFsdWU6IG51bGwsXG4gICAgICAgICAgZmllbGRJZHg6IC0xXG4gICAgICAgICAgLy8gb3B0aW9uYWw6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgaWQ6IHtcbiAgICAgICAgICB2YWx1ZTogZmllbGRzW2lkRmllbGRJZHhdLm5hbWUsXG4gICAgICAgICAgZmllbGRJZHg6IGlkRmllbGRJZHhcbiAgICAgICAgICAvLyBvcHRpb25hbDogZmFsc2VcbiAgICAgICAgfSxcbiAgICAgICAgW3NvcnRCeV06IHtcbiAgICAgICAgICB2YWx1ZTogZmllbGRzW3NvcnRCeUZpZWxkSWR4XS5uYW1lLFxuICAgICAgICAgIGZpZWxkSWR4OiBzb3J0QnlGaWVsZElkeFxuICAgICAgICAgIC8vIG9wdGlvbmFsOiBmYWxzZVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgbGFiZWw6IGZpZWxkUGFpcnNbMF0uZGVmYXVsdE5hbWVcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseUZpbHRlcnNUb1RhYmxlQ29sdW1ucyhcbiAgZGF0YXNldDogS2VwbGVyVGFibGUsXG4gIGRhdGFUb0ZlYXR1cmU6IEdlb2pzb25EYXRhTWFwc1xuKTogR2VvanNvbkRhdGFNYXBzIHtcbiAgY29uc3Qge2RhdGFDb250YWluZXIsIGZpbHRlcmVkSW5kZXh9ID0gZGF0YXNldDtcbiAgaWYgKGZpbHRlcmVkSW5kZXgubGVuZ3RoID09PSBkYXRhQ29udGFpbmVyLm51bVJvd3MoKSkge1xuICAgIC8vIE9ubHkgYXBwbHkgdGhlIGZpbHRlcmluZyB3aGVuIHNvbWV0aGluZyBpcyB0byBiZSBmaWx0ZXJlZCBvdXRcbiAgICByZXR1cm4gZGF0YVRvRmVhdHVyZTtcbiAgfVxuXG4gIGNvbnN0IGZpbHRlcmVkSW5kZXhTZXQgPSBuZXcgU2V0KGZpbHRlcmVkSW5kZXgpO1xuICBjb25zdCBmaWx0ZXJlZEZlYXR1cmVzOiBHZW9qc29uRGF0YU1hcHMgPSBbXTtcbiAgZm9yIChjb25zdCBmZWF0dXJlIG9mIGRhdGFUb0ZlYXR1cmUpIHtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGdlb21ldHJ5LmNvb3JkaW5hdGVzIG5vdCBhdmFpbGFibGUgZm9yIEdlb21ldHJ5Q29sbGVjdGlvblxuICAgIGNvbnN0IGZpbHRlcmVkQ29vcmRzID0gZmVhdHVyZS5nZW9tZXRyeS5jb29yZGluYXRlcy5maWx0ZXIoYyA9PlxuICAgICAgZmlsdGVyZWRJbmRleFNldC5oYXMoYy5kYXR1bUluZGV4KVxuICAgICk7XG4gICAgaWYgKGZpbHRlcmVkQ29vcmRzLmxlbmd0aCA+IDAgJiYgZmVhdHVyZSkge1xuICAgICAgZmlsdGVyZWRGZWF0dXJlcy5wdXNoKHtcbiAgICAgICAgLi4uZmVhdHVyZSxcbiAgICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIEJpbmFyeUZlYXR1cmVDb2xsZWN0aW9uXG4gICAgICAgICAgLi4uZmVhdHVyZS5nZW9tZXRyeSxcbiAgICAgICAgICBjb29yZGluYXRlczogZmlsdGVyZWRDb29yZHNcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgQmluYXJ5RmVhdHVyZUNvbGxlY3Rpb25cbiAgICAgICAgICAuLi5mZWF0dXJlLnByb3BlcnRpZXMsXG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBCaW5hcnlGZWF0dXJlQ29sbGVjdGlvblxuICAgICAgICAgIHZhbHVlczogZmVhdHVyZS5nZW9tZXRyeS5jb29yZGluYXRlcy5tYXAoYyA9PiBkYXRhQ29udGFpbmVyLnJvd0FzQXJyYXkoYy5kYXR1bUluZGV4KSlcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBmaWx0ZXJlZEZlYXR1cmVzO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0EsSUFBQUEs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