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+IGQgJiYgJ3Byb3BlcnRpZXMnIGluIGQgJiYgZC5wcm9wZXJ0aWVzPy5yYWRpdXMpXG4gICk7XG5cbiAgLy8ga2VlcCBhIHJlY29yZCBvZiB3aGF0IHR5cGUgb2YgZ2VvbWV0cnkgdGhlIGNvbGxlY3Rpb24gaGFzXG4gIGNvbnN0IGZlYXR1cmVUeXBlcyA9IGdldEdlb2pzb25GZWF0dXJlVHlwZXMoZGF0YVRvRmVhdHVyZSk7XG5cbiAgY29uc3QgbWVhbkNlbnRlcnM6IEFycmF5PG51bWJlcltdIHwgbnVsbD4gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhVG9GZWF0dXJlLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZmVhdHVyZSA9IGRhdGFUb0ZlYXR1cmVbaV07XG4gICAgaWYgKGZlYXR1cmUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFRPRE86IHVzZSBsaW5lIGludGVycG9sYXRlIHRvIGdldCBjZW50ZXIgb2YgbGluZSBmb3IgTGluZVN0cmluZ1xuICAgICAgICBjb25zdCBjZW50ID0gY2VudGVyKGZlYXR1cmUgYXMgQWxsR2VvSlNPTik7XG4gICAgICAgIG1lYW5DZW50ZXJzLnB1c2goY2VudC5nZW9tZXRyeS5jb29yZGluYXRlcyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIG1lYW5DZW50ZXJzLnB1c2gobnVsbCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBkYXRhVG9GZWF0dXJlLFxuICAgIGJvdW5kcyxcbiAgICBmaXhlZFJhZGl1cyxcbiAgICBmZWF0dXJlVHlwZXMsXG4gICAgY2VudHJvaWRzOiBtZWFuQ2VudGVyc1xuICB9O1xufVxuXG4vKipcbiAqIFBhcnNlIHJhdyBkYXRhIHRvIEdlb0pzb24gZmVhdHVyZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2VvanNvbkRhdGFNYXBzKFxuICBkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlLFxuICBnZXRGZWF0dXJlOiBHZXRGZWF0dXJlXG4pOiBHZW9qc29uRGF0YU1hcHMge1xuICBjb25zdCBhY2NlcHRhYmxlVHlwZXMgPSBbXG4gICAgJ1BvaW50JyxcbiAgICAnTXVsdGlQb2ludCcsXG4gICAgJ0xpbmVTdHJpbmcnLFxuICAgICdNdWx0aUxpbmVTdHJpbmcnLFxuICAgICdQb2x5Z29uJyxcbiAgICAnTXVsdGlQb2x5Z29uJyxcbiAgICAnR2VvbWV0cnlDb2xsZWN0aW9uJ1xuICBdO1xuXG4gIGNvbnN0IGRhdGFUb0ZlYXR1cmU6IEdlb2pzb25EYXRhTWFwcyA9IFtdO1xuXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBkYXRhQ29udGFpbmVyLm51bVJvd3MoKTsgaW5kZXgrKykge1xuICAgIGNvbnN0IGZlYXR1cmUgPSBwYXJzZUdlb0pzb25SYXdGZWF0dXJlKGdldEZlYXR1cmUoe2luZGV4fSkpO1xuXG4gICAgaWYgKGZlYXR1cmUgJiYgZmVhdHVyZS5nZW9tZXRyeSAmJiBhY2NlcHRhYmxlVHlwZXMuaW5jbHVkZXMoZmVhdHVyZS5nZW9tZXRyeS50eXBlKSkge1xuICAgICAgY29uc3QgY2xlYW5lZCA9IHtcbiAgICAgICAgLi4uZmVhdHVyZSxcbiAgICAgICAgLy8gc3RvcmUgaW5kZXggb2YgdGhlIGRhdGEgaW4gZmVhdHVyZSBwcm9wZXJ0aWVzXG4gICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAuLi5mZWF0dXJlLnByb3BlcnRpZXMsXG4gICAgICAgICAgaW5kZXhcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgZGF0YVRvRmVhdHVyZVtpbmRleF0gPSBjbGVhbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRhVG9GZWF0dXJlW2luZGV4XSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRhdGFUb0ZlYXR1cmU7XG59XG5cbi8qKlxuICogUGFyc2UgcmF3IGRhdGEgdG8gR2VvSnNvbiBwb2ludCBmZWF0dXJlIGNvb3JkaW5hdGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRHZW9qc29uUG9pbnREYXRhTWFwcyhcbiAgZGF0YUNvbnRhaW5lcjogRGF0YUNvbnRhaW5lckludGVyZmFjZSxcbiAgZ2V0RmVhdHVyZTogR2V0RmVhdHVyZVxuKTogR2VvanNvblBvaW50RGF0YU1hcHMge1xuICBjb25zdCBhY2NlcHRhYmxlVHlwZXMgPSBbJ1BvaW50JywgJ011bHRpUG9pbnQnLCAnR2VvbWV0cnlDb2xsZWN0aW9uJ107XG5cbiAgY29uc3QgZGF0YVRvRmVhdHVyZTogR2VvanNvblBvaW50RGF0YU1hcHMgPSBbXTtcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZGF0YUNvbnRhaW5lci5udW1Sb3dzKCk7IGluZGV4KyspIHtcbiAgICBjb25zdCBmZWF0dXJlID0gcGFyc2VHZW9Kc29uUmF3RmVhdHVyZShnZXRGZWF0dXJlKGRhdGFDb250YWluZXIucm93QXNBcnJheShpbmRleCkpKTtcblxuICAgIGlmIChmZWF0dXJlICYmIGZlYXR1cmUuZ2VvbWV0cnkgJiYgYWNjZXB0YWJsZVR5cGVzLmluY2x1ZGVzKGZlYXR1cmUuZ2VvbWV0cnkudHlwZSkpIHtcbiAgICAgIGRhdGFUb0ZlYXR1cmVbaW5kZXhdID1cbiAgICAgICAgZmVhdHVyZS5nZW9tZXRyeS50eXBlID09PSAnUG9pbnQnIHx8IGZlYXR1cmUuZ2VvbWV0cnkudHlwZSA9PT0gJ011bHRpUG9pbnQnXG4gICAgICAgICAgPyBmZWF0dXJlLmdlb21ldHJ5LmNvb3JkaW5hdGVzXG4gICAgICAgICAgOiAvLyBAdHMtZXhwZWN0LWVycm9yIFByb3BlcnR5ICdnZW9tZXRyaWVzJyBkb2VzIG5vdCBleGlzdCBvbiB0eXBlICdMaW5lU3RyaW5nJ1xuICAgICAgICAgICAgKGZlYXR1cmUuZ2VvbWV0cnkuZ2VvbWV0cmllcyB8fCBbXSkucmVkdWNlKChhY2N1LCBmKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChmLnR5cGUgPT09ICdQb2ludCcpIHtcbiAgICAgICAgICAgICAgICBhY2N1LnB1c2goZi5jb29yZGluYXRlcyk7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAoZi50eXBlID09PSAnTXVsdGlQb2ludCcpIHtcbiAgICAgICAgICAgICAgICBhY2N1LnB1c2goLi4uZi5jb29yZGluYXRlcyk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICByZXR1cm4gYWNjdTtcbiAgICAgICAgICAgIH0sIFtdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGF0YVRvRmVhdHVyZVtpbmRleF0gPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkYXRhVG9GZWF0dXJlO1xufVxuXG4vKipcbiAqIFBhcnNlIGdlb2pzb24gZnJvbSBzdHJpbmdcbiAqIEBwYXJhbSB7U3RyaW5nfSBnZW9TdHJpbmdcbiAqIEByZXR1cm5zIHtudWxsIHwgT2JqZWN0fSBnZW9qc29uIG9iamVjdCBvciBudWxsIGlmIGZhaWxlZFxuICovXG5mdW5jdGlvbiBwYXJzZUdlb21ldHJ5RnJvbVN0cmluZyhnZW9TdHJpbmc6IHN0cmluZyk6IEZlYXR1cmUgfCBudWxsIHtcbiAgbGV0IHBhcnNlZEdlbztcblxuICAvLyB0cnkgcGFyc2UgYXMgZ2VvanNvbiBzdHJpbmdcbiAgLy8ge1widHlwZVwiOlwiUG9seWdvblwiLFwiY29vcmRpbmF0ZXNcIjpbW1stNzQuMTU4NDkxLDQwLjgzNTk0XV1dfVxuICB0cnkge1xuICAgIHBhcnNlZEdlbyA9IEpTT04ucGFyc2UoZ2VvU3RyaW5nKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIGtlZXAgdHJ5aW5nIHRvIHBhcnNlXG4gIH1cblxuICAvLyB0cnkgcGFyc2UgYXMgd2t0IHVzaW5nIGxvYWRlcnMuZ2wgV0tUTG9hZGVyXG4gIGlmICghcGFyc2VkR2VvKSB7XG4gICAgdHJ5IHtcbiAgICAgIHBhcnNlZEdlbyA9IHBhcnNlU3luYyhnZW9TdHJpbmcsIFdLVExvYWRlcik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLy8gdHJ5IHBhcnNlIGFzIHdrYiB1c2luZyBsb2FkZXJzLmdsIFdLQkxvYWRlclxuICBpZiAoIXBhcnNlZEdlbykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuZnJvbShnZW9TdHJpbmcsICdoZXgnKTtcbiAgICAgIGNvbnN0IGJpbmFyeUdlbyA9IHBhcnNlU3luYyhidWZmZXIsIFdLQkxvYWRlcik7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBwYXJzZWRHZW8gPSBiaW5hcnlUb0dlb21ldHJ5KGJpbmFyeUdlbyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFwYXJzZWRHZW8pIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemUocGFyc2VkR2VvKTtcblxuICBpZiAoIW5vcm1hbGl6ZWQgfHwgIUFycmF5LmlzQXJyYXkobm9ybWFsaXplZC5mZWF0dXJlcykpIHtcbiAgICAvLyBmYWlsIHRvIG5vcm1hbGl6ZSBnZW9qc29uXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gbm9ybWFsaXplZC5mZWF0dXJlc1swXTtcbn1cblxuLyoqXG4gKiBHZXQgZ2VvanNvbiBib3VuZHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdlb2pzb25Cb3VuZHMoZmVhdHVyZXM6IEdlb2pzb25EYXRhTWFwcyA9IFtdKTogQkJveCB8IG51bGwge1xuICAvLyA3MCBtcyBmb3IgMTAsMDAwIHBvbHlnb25zXG4gIC8vIGhlcmUgd2Ugb25seSBwaWNrIGNvdXBsZVxuICBjb25zdCBtYXhDb3VudCA9IDEwMDAwO1xuICBjb25zdCBzYW1wbGVzID0gZmVhdHVyZXMubGVuZ3RoID4gbWF4Q291bnQgPyBnZXRTYW1wbGVEYXRhKGZlYXR1cmVzLCBtYXhDb3VudCkgOiBmZWF0dXJlcztcblxuICBjb25zdCB2YWxpZFNpbmdsZUdlb21ldHJ5ID0gZ2VvbSA9PiBnZW9tLmNvb3JkaW5hdGVzICYmIGdlb20uY29vcmRpbmF0ZXMubGVuZ3RoO1xuICBjb25zdCB2YWxpZEdlb21ldHJ5Q29sbGVjdGlvbiA9IGdlb20gPT4gZ2VvbS5nZW9tZXRyaWVzICYmIGdlb20uZ2VvbWV0cmllcy5sZW5ndGggJiYgZ2VvbS5nZW9tZXRyaWVzLmV2ZXJ5KHZhbGlkU2luZ2xlR2VvbWV0cnkpO1xuICBjb25zdCBub25FbXB0eSA9IHNhbXBsZXMuZmlsdGVyKFxuICAgIGQgPT4gZCAmJiBkLmdlb21ldHJ5ICYmICh2YWxpZFNpbmdsZUdlb21ldHJ5KGQuZ2VvbWV0cnkpIHx8IHZhbGlkR2VvbWV0cnlDb2xsZWN0aW9uKGQuZ2VvbWV0cnkpKVxuICApO1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGJib3goe1xuICAgICAgdHlwZTogJ0ZlYXR1cmVDb2xsZWN0aW9uJyxcbiAgICAgIGZlYXR1cmVzOiBub25FbXB0eVxuICAgIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGZlYXR1cmVUb0RlY2tHbEdlb1R5cGUgPSB7XG4gIFBvaW50OiAncG9pbnQnLFxuICBNdWx0aVBvaW50OiAncG9pbnQnLFxuICBMaW5lU3RyaW5nOiAnbGluZScsXG4gIE11bHRpTGluZVN0cmluZzogJ2xpbmUnLFxuICBQb2x5Z29uOiAncG9seWdvbicsXG4gIE11bHRpUG9seWdvbjogJ3BvbHlnb24nXG59O1xuXG5leHBvcnQgdHlwZSBEZWNrR2xHZW9UeXBlcyA9IHtcbiAgcG9pbnQ6IGJvb2xlYW47XG4gIGxpbmU6IGJvb2xlYW47XG4gIHBvbHlnb246IGJvb2xlYW47XG59O1xuXG4vKipcbiAqIFBhcnNlIGdlb2pzb24gZnJvbSBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEdlb2pzb25GZWF0dXJlVHlwZXMoYWxsRmVhdHVyZXM6IEdlb2pzb25EYXRhTWFwcyk6IERlY2tHbEdlb1R5cGVzIHtcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciBzb21lIHRlc3QgY2FzZXMgb25seSBoYXZlIDEgZ2VvdHlwZVxuICBjb25zdCBmZWF0dXJlVHlwZXM6IERlY2tHbEdlb1R5cGVzID0ge307XG4gIGZvciAobGV0IGYgPSAwOyBmIDwgYWxsRmVhdHVyZXMubGVuZ3RoOyBmKyspIHtcbiAgICBjb25zdCBmZWF0dXJlID0gYWxsRmVhdHVyZXNbZl07XG4gICAgaWYgKGZlYXR1cmUgJiYgJ2dlb21ldHJ5JyBpbiBmZWF0dXJlKSB7XG4gICAgICBjb25zdCBnZW9UeXBlID0gZmVhdHVyZVRvRGVja0dsR2VvVHlwZVtmZWF0dXJlLmdlb21ldHJ5ICYmIGZlYXR1cmUuZ2VvbWV0cnkudHlwZV07XG4gICAgICBpZiAoZ2VvVHlwZSkge1xuICAgICAgICBmZWF0dXJlVHlwZXNbZ2VvVHlwZV0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmZWF0dXJlVHlwZXM7XG59XG5cbnR5cGUgQ29vcmRzVHlwZSA9IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIgfCBudWxsXSAmIHtcbiAgZGF0dW1JbmRleDogbnVtYmVyO1xuICBkYXR1bTogbnVtYmVyW107XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBDb2x1bW5zQXNHZW9Kc29uKFxuICBkYXRhQ29udGFpbmVyOiBEYXRhQ29udGFpbmVySW50ZXJmYWNlLFxuICBjb2x1bW5zOiBMYXllckNvbHVtbnMsXG4gIHNvcnRCeUNvbHVtbiA9ICd0aW1lc3RhbXAnXG4pOiBGZWF0dXJlW10ge1xuICBjb25zdCBncm91cGVkQnlJZDoge1trZXk6IHN0cmluZ106IENvb3Jkc1R5cGVbXX0gPSB7fTtcbiAgY29uc3Qgc29ydEJ5RmllbGRJZHggPSBjb2x1bW5zW3NvcnRCeUNvbHVtbl0uZmllbGRJZHg7XG4gIGNvbnN0IHNvcnRCeVJlcXVpcmVkID0gIWNvbHVtbnNbc29ydEJ5Q29sdW1uXS5vcHRpb25hbDtcbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGRhdGFDb250YWluZXIubnVtUm93cygpOyBpbmRleCsrKSB7XG4gICAgLy8gbm90ZTogY2FuIG1hdGVyaWFsaXplIHRoZSByb3dcbiAgICBjb25zdCBkYXR1bSA9IGRhdGFDb250YWluZXIucm93QXNBcnJheShpbmRleCk7XG4gICAgY29uc3QgaWQgPSBkYXR1bVtjb2x1bW5zLmlkLmZpZWxkSWR4XTtcbiAgICBjb25zdCBsYXQgPSBkYXR1bVtjb2x1bW5zLmxhdC5maWVsZElkeF07XG4gICAgY29uc3QgbG9uID0gZGF0dW1bY29sdW1ucy5sbmcuZmllbGRJZHhdO1xuICAgIGNvbnN0IGFsdGl0dWRlID0gY29sdW1ucy5hbHRpdHVkZSA/IGRhdHVtW2NvbHVtbnMuYWx0aXR1ZGUuZmllbGRJZHhdIDogMDtcbiAgICBjb25zdCBzb3J0QnkgPSBzb3J0QnlGaWVsZElkeCA+IC0xID8gZGF0dW1bc29ydEJ5RmllbGRJZHhdIDogbnVsbDtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgY29uc3QgY29vcmRzOiBDb29yZHNUeXBlID0gW2xvbiwgbGF0LCBhbHRpdHVkZSwgc29ydEJ5XTtcbiAgICAvLyBBZGRpbmcgcmVmZXJlbmNlcyB0byB0aGUgb3JpZ2luYWwgZGF0YSB0byB0aGUgY29vcmRpbmF0ZXMgYXJyYXlcbiAgICBjb29yZHMuZGF0dW1JbmRleCA9IGluZGV4O1xuICAgIGNvb3Jkcy5kYXR1bSA9IGRhdHVtO1xuICAgIGlmICghZ3JvdXBlZEJ5SWRbaWRdKSBncm91cGVkQnlJZFtpZF0gPSBbXTtcblxuICAgIGlmIChcbiAgICAgIE51bWJlci5pc0Zpbml0ZShsb24pICYmXG4gICAgICBOdW1iZXIuaXNGaW5pdGUobGF0KSAmJlxuICAgICAgKCFzb3J0QnlSZXF1aXJlZCB8fCAoc29ydEJ5UmVxdWlyZWQgJiYgc29ydEJ5KSlcbiAgICApIHtcbiAgICAgIC8vIG9ubHkgcHVzaCBwb2ludHMgaWYgbGF0LGxuZyxhbmQgc29ydGJ5IGV4aXN0XG4gICAgICBncm91cGVkQnlJZFtpZF0ucHVzaChjb29yZHMpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHJlc3VsdDogRmVhdHVyZVtdID0gT2JqZWN0LmVudHJpZXMoZ3JvdXBlZEJ5SWQpLm1hcChcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgKFtfLCBpdGVtc106IFtzdHJpbmcsIENvb3Jkc1R5cGVbXV0sIGluZGV4KSA9PiAoe1xuICAgICAgdHlwZTogJ0ZlYXR1cmUnIGFzIGNvbnN0LFxuICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgdHlwZTogJ0xpbmVTdHJpbmcnIGFzIGNvbnN0LFxuICAgICAgICAvLyBTb3J0IGJ5IGNvbHVtbnMgaWYgaGFzIHNvcnRCeUZpZWxkXG4gICAgICAgIC8vIFRPRE86IGl0ZW1zIGFyZSBleHBlY3RlZCBpbiBQb3NpdGlvbltdIGZvcm1hdD9cbiAgICAgICAgY29vcmRpbmF0ZXM6IChzb3J0QnlGaWVsZElkeCA+IC0xXG4gICAgICAgICAgPyBpdGVtcy5zb3J0KChhLCBiKSA9PiBhc2NlbmRpbmcoYVszXSBhcyBhbnksIGJbM10gYXMgYW55KSlcbiAgICAgICAgICA6IGl0ZW1zKSBhcyBQb3NpdGlvbltdXG4gICAgICB9LFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICBpbmRleCxcbiAgICAgICAgLy8gdmFsdWVzIGFyZSB1c2VkIGZvciB2YWx1ZUFjY2Vzc29yIGluIFRyaXBMYXllci5mb3JtYXRMYXllckRhdGEoKVxuICAgICAgICAvLyBOb3RlOiB0aGlzIGNhbiBjYXVzZSByb3cgbWF0ZXJpYWxpemF0aW9uIGluIGNhc2Ugb2Ygbm9uLXJvdyBiYXNlZCBjb250YWluZXJzXG4gICAgICAgIHZhbHVlczogaXRlbXMubWFwKGl0ZW0gPT4gZGF0YUNvbnRhaW5lci5yb3dBc0FycmF5KGl0ZW0uZGF0dW1JbmRleCkpXG4gICAgICB9XG4gICAgfSlcbiAgKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBGaW5kIGlkIC8gdHMgLyBsYXQgLyBsbmcgY29sdW1ucyBmcm9tIGEgdGFibGUgYW5kIGFzc2lnbiBpdCB0byBsYXllciBjb2x1bW5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RUYWJsZUNvbHVtbnMoXG4gIGRhdGFzZXQ6IEtlcGxlclRhYmxlLFxuICBsYXllckNvbHVtbnM6IExheWVyQ29sdW1ucyxcbiAgc29ydEJ5ID0gJ3RpbWVzdGFtcCdcbikge1xuICBjb25zdCB7ZmllbGRzLCBmaWVsZFBhaXJzfSA9IGRhdGFzZXQ7XG4gIGlmICghZmllbGRQYWlycy5sZW5ndGggfHwgIWZpZWxkcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICAvLyBmaW5kIHNvcnQgYnkgZmllbGRcbiAgY29uc3Qgc29ydEJ5RmllbGRJZHggPSBmaWVsZHMuZmluZEluZGV4KGYgPT4gZi50eXBlID09PSBBTExfRklFTERfVFlQRVMudGltZXN0YW1wKTtcbiAgLy8gZmluZCBpZCBjb2x1bW5cbiAgY29uc3QgaWRGaWVsZElkeCA9IGZpZWxkcy5maW5kSW5kZXgoZiA9PiBmLm5hbWU/LnRvTG93ZXJDYXNlKCkubWF0Y2goL14oaWR8dXVpZCkkL2cpKTtcblxuICBpZiAoc29ydEJ5RmllbGRJZHggPiAtMSAmJiBpZEZpZWxkSWR4ID4gLTEpIHtcbiAgICBjb25zdCBwb2ludENvbHVtbnMgPSBhc3NpZ25Qb2ludFBhaXJUb0xheWVyQ29sdW1uKGZpZWxkUGFpcnNbMF0sIHRydWUpO1xuICAgIHJldHVybiB7XG4gICAgICBjb2x1bW5zOiB7XG4gICAgICAgIC4uLk9iamVjdC5rZXlzKGxheWVyQ29sdW1ucykucmVkdWNlKFxuICAgICAgICAgIChhY2N1LCBjb2wpID0+ICh7XG4gICAgICAgICAgICAuLi5hY2N1LFxuICAgICAgICAgICAgW2NvbF06IHBvaW50Q29sdW1uc1tjb2xdID8/IGxheWVyQ29sdW1uc1tjb2xdXG4gICAgICAgICAgfSksXG4gICAgICAgICAge31cbiAgICAgICAgKSxcbiAgICAgICAgZ2VvanNvbjoge1xuICAgICAgICAgIHZhbHVlOiBudWxsLFxuICAgICAgICAgIGZpZWxkSWR4OiAtMVxuICAgICAgICAgIC8vIG9wdGlvbmFsOiB0cnVlXG4gICAgICAgIH0sXG4gICAgICAgIGlkOiB7XG4gICAgICAgICAgdmFsdWU6IGZpZWxkc1tpZEZpZWxkSWR4XS5uYW1lLFxuICAgICAgICAgIGZpZWxkSWR4OiBpZEZpZWxkSWR4XG4gICAgICAgICAgLy8gb3B0aW9uYWw6IGZhbHNlXG4gICAgICAgIH0sXG4gICAgICAgIFtzb3J0QnldOiB7XG4gICAgICAgICAgdmFsdWU6IGZpZWxkc1tzb3J0QnlGaWVsZElkeF0ubmFtZSxcbiAgICAgICAgICBmaWVsZElkeDogc29ydEJ5RmllbGRJZHhcbiAgICAgICAgICAvLyBvcHRpb25hbDogZmFsc2VcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGxhYmVsOiBmaWVsZFBhaXJzWzBdLmRlZmF1bHROYW1lXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlGaWx0ZXJzVG9UYWJsZUNvbHVtbnMoXG4gIGRhdGFzZXQ6IEtlcGxlclRhYmxlLFxuICBkYXRhVG9GZWF0dXJlOiBHZW9qc29uRGF0YU1hcHNcbik6IEdlb2pzb25EYXRhTWFwcyB7XG4gIGNvbnN0IHtkYXRhQ29udGFpbmVyLCBmaWx0ZXJlZEluZGV4fSA9IGRhdGFzZXQ7XG4gIGlmIChmaWx0ZXJlZEluZGV4Lmxlbmd0aCA9PT0gZGF0YUNvbnRhaW5lci5udW1Sb3dzKCkpIHtcbiAgICAvLyBPbmx5IGFwcGx5IHRoZSBmaWx0ZXJpbmcgd2hlbiBzb21ldGhpbmcgaXMgdG8gYmUgZmlsdGVyZWQgb3V0XG4gICAgcmV0dXJuIGRhdGFUb0ZlYXR1cmU7XG4gIH1cblxuICBjb25zdCBmaWx0ZXJlZEluZGV4U2V0ID0gbmV3IFNldChmaWx0ZXJlZEluZGV4KTtcbiAgY29uc3QgZmlsdGVyZWRGZWF0dXJlczogR2VvanNvbkRhdGFNYXBzID0gW107XG4gIGZvciAoY29uc3QgZmVhdHVyZSBvZiBkYXRhVG9GZWF0dXJlKSB7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBnZW9tZXRyeS5jb29yZGluYXRlcyBub3QgYXZhaWxhYmxlIGZvciBHZW9tZXRyeUNvbGxlY3Rpb25cbiAgICBjb25zdCBmaWx0ZXJlZENvb3JkcyA9IGZlYXR1cmUuZ2VvbWV0cnkuY29vcmRpbmF0ZXMuZmlsdGVyKGMgPT5cbiAgICAgIGZpbHRlcmVkSW5kZXhTZXQuaGFzKGMuZGF0dW1JbmRleClcbiAgICApO1xuICAgIGlmIChmaWx0ZXJlZENvb3Jkcy5sZW5ndGggPiAwICYmIGZlYXR1cmUpIHtcbiAgICAgIGZpbHRlcmVkRmVhdHVyZXMucHVzaCh7XG4gICAgICAgIC4uLmZlYXR1cmUsXG4gICAgICAgIGdlb21ldHJ5OiB7XG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBCaW5hcnlGZWF0dXJlQ29sbGVjdGlvblxuICAgICAgICAgIC4uLmZlYXR1cmUuZ2VvbWV0cnksXG4gICAgICAgICAgY29vcmRpbmF0ZXM6IGZpbHRlcmVkQ29vcmRzXG4gICAgICAgIH0sXG4gICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIEJpbmFyeUZlYXR1cmVDb2xsZWN0aW9uXG4gICAgICAgICAgLi4uZmVhdHVyZS5wcm9wZXJ0aWVzLFxuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgQmluYXJ5RmVhdHVyZUNvbGxlY3Rpb25cbiAgICAgICAgICB2YWx1ZXM6IGZlYXR1cmUuZ2VvbWV0cnkuY29vcmRpbmF0ZXMubWFwKGMgPT4gZGF0YUNvbnRhaW5lci5yb3dBc0FycmF5KGMuZGF0dW1JbmRleCkpXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmlsdGVyZWRGZWF0dXJlcztcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdBLElBQUFBLE9BQUEsR0FBQUMsT0FBQTtBQUVBLElBQUFDLGlCQUFBLEdBQUFDLHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBRyxLQUFBLEdBQUFELHNCQUFBLENBQUFGLE9BQUE7QUFDQSxJQUFBSSxRQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxPQUFBLEdBQUFILHNCQUFBLENBQUFGLE9BQUE7QUFFQSxJQUFBTSxLQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxJQUFBLEdBQUFQLE9BQUE7QUFDQSxJQUFBUSxJQUFBLEdBQUFSLE9BQUE7QUFFQSxJQUFBUyxNQUFBLEdBQUFULE9BQUE7QUFDQSxJQUFBVSxVQUFBLEdBQUFWLE9BQUE7QUFJQSxJQUFBVyxXQUFBLEdBQUFYLE9BQUE7QUFBbUYsU0FBQVksMkJBQUFDLENBQUEsRUFBQUMsQ0FBQSxRQUFBQyxDQUFBLHlCQUFBQyxNQUFBLElBQUFILENBQUEsQ0FBQUcsTUFBQSxDQUFBQyxRQUFBLEtBQUFKLENBQUEscUJBQUFFLENBQUEsUUFBQUcsS0FBQSxDQUFBQyxPQUFBLENBQUFOLENBQUEsTUFBQUUsQ0FBQSxHQUFBSywyQkFBQSxDQUFBUCxDQUFBLE1BQUFDLENBQUEsSUFBQUQsQ0FBQSx1QkFBQUEsQ0FBQSxDQUFBUSxNQUFBLElBQUFOLENBQUEsS0FBQUYsQ0FBQSxHQUFBRSxDQUFBLE9BQUFPLEVBQUEsTUFBQUMsQ0FBQSxZQUFBQSxFQUFBLGVBQUFDLENBQUEsRUFBQUQsQ0FBQSxFQUFBRSxDQUFBLFdBQUFBLEVBQUEsV0FBQUgsRUFBQSxJQUFBVCxDQUFBLENBQUFRLE1BQUEsS0FBQUssSUFBQSxXQUFBQSxJQUFBLE1BQUFDLEtBQUEsRUFBQWQsQ0FBQSxDQUFBUyxFQUFBLFVBQUFSLENBQUEsV0FBQUEsRUFBQUQsQ0FBQSxVQUFBQSxDQUFBLEtBQUFlLENBQUEsRUFBQUwsQ0FBQSxnQkFBQU0sU0FBQSxpSkFBQUMsQ0FBQSxFQUFBQyxDQUFBLE9BQUFDLENBQUEsZ0JBQUFSLENBQUEsV0FBQUEsRUFBQSxJQUFBVCxDQUFBLEdBQUFBLENBQUEsQ0FBQWtCLElBQUEsQ0FBQXBCLENBQUEsTUFBQVksQ0FBQSxXQUFBQSxFQUFBLFFBQUFaLENBQUEsR0FBQUUsQ0FBQSxDQUFBbUIsSUFBQSxXQUFBSCxDQUFBLEdBQUFsQixDQUFBLENBQUFhLElBQUEsRUFBQWIsQ0FBQSxLQUFBQyxDQUFBLFdBQUFBLEVBQUFELENBQUEsSUFBQW1CLENBQUEsT0FBQUYsQ0FBQSxHQUFBakIsQ0FBQSxLQUFBZSxDQUFBLFdBQUFBLEVBQUEsVUFBQUcsQ0FBQSxZQUFBaEIsQ0FBQSxjQUFBQSxDQUFBLDhCQUFBaUIsQ0FBQSxRQUFBRixDQUFBO0FBQUEsU0FBQVYsNEJBQUFQLENBQUEsRUFBQWtCLENBQUEsUUFBQWxCLENBQUEsMkJBQUFBLENBQUEsU0FBQXNCLGlCQUFBLENBQUF0QixDQUFBLEVBQUFrQixDQUFBLE9BQUFoQixDQUFBLE1BQUFxQixRQUFBLENBQUFILElBQUEsQ0FBQXBCLENBQUEsRUFBQXdCLEtBQUEsNkJBQUF0QixDQUFBLElBQUFGLENBQUEsQ0FBQXlCLFdBQUEsS0FBQXZCLENBQUEsR0FBQUYsQ0FBQSxDQUFBeUIsV0FBQSxDQUFBQyxJQUFBLGFBQUF4QixDQUFBLGNBQUFBLENBQUEsR0FBQUcsS0FBQSxDQUFBc0IsSUFBQSxDQUFBM0IsQ0FBQSxvQkFBQUUsQ0FBQSwrQ0FBQTBCLElBQUEsQ0FBQTFCLENBQUEsSUFBQW9CLGlCQUFBLENBQUF0QixDQUFBLEVBQUFrQixDQUFBO0FBQUEsU0FBQUksa0JBQUF0QixDQUFBLEVBQUFrQixDQUFBLGFBQUFBLENBQUEsSUFBQUEsQ0FBQSxHQUFBbEIsQ0FBQSxDQUFBUSxNQUFBLE1BQUFVLENBQUEsR0FBQWxCLENBQUEsQ0FBQVEsTUFBQSxZQUFBUCxDQUFBLE1BQUFXLENBQUEsR0FBQVAsS0FBQSxDQUFBYSxDQUFBLEdBQUFqQixDQUFBLEdBQUFpQixDQUFBLEVBQUFqQixDQUFBLElBQUFXLENBQUEsQ0FBQVgsQ0FBQSxJQUFBRCxDQUFBLENBQUFDLENBQUEsVUFBQVcsQ0FBQTtBQUFBLFNBQUFpQixRQUFBNUIsQ0FBQSxFQUFBRCxDQUFBLFFBQUFFLENBQUEsR0FBQTRCLE1BQUEsQ0FBQUMsSUFBQSxDQUFBOUIsQ0FBQSxPQUFBNkIsTUFBQSxDQUFBRSxxQkFBQSxRQUFBZixDQUFBLEdBQUFhLE1BQUEsQ0FBQUUscUJBQUEsQ0FBQS9CLENBQUEsR0FBQUQsQ0FBQSxLQUFBaUIsQ0FBQSxHQUFBQSxDQUFBLENBQUFnQixNQUFBLFdBQUFqQyxDQUFBLFdBQUE4QixNQUFBLENBQUFJLHdCQUFBLENBQUFqQyxDQUFBLEVBQUFELENBQUEsRUFBQW1DLFVBQUEsT0FBQWpDLENBQUEsQ0FBQWtDLElBQUEsQ0FBQUMsS0FBQSxDQUFBbkMsQ0FBQSxFQUFBZSxDQUFBLFlBQUFmLENBQUE7QUFBQSxTQUFBb0MsY0FBQXJDLENBQUEsYUFBQUQsQ0FBQSxNQUFBQSxDQUFBLEdBQUF1QyxTQUFBLENBQUEvQixNQUFBLEVBQUFSLENBQUEsVUFBQUUsQ0FBQSxXQUFBcUMsU0FBQSxDQUFBdkMsQ0FBQSxJQUFBdUMsU0FBQSxDQUFBdkMsQ0FBQSxRQUFBQSxDQUFBLE9BQUE2QixPQUFBLENBQUFDLE1BQUEsQ0FBQTVCLENBQUEsT0FBQXNDLE9BQUEsV0FBQXhDLENBQUEsUUFBQXlDLGdCQUFBLGFBQUF4QyxDQUFBLEVBQUFELENBQUEsRUFBQUUsQ0FBQSxDQUFBRixDQUFBLFNBQUE4QixNQUFBLENBQUFZLHlCQUFBLEdBQUFaLE1BQUEsQ0FBQWEsZ0JBQUEsQ0FBQTFDLENBQUEsRUFBQTZCLE1BQUEsQ0FBQVkseUJBQUEsQ0FBQXhDLENBQUEsS0FBQTJCLE9BQUEsQ0FBQUMsTUFBQSxDQUFBNUIsQ0FBQSxHQUFBc0MsT0FBQSxXQUFBeEMsQ0FBQSxJQUFBOEIsTUFBQSxDQUFBYyxjQUFBLENBQUEzQyxDQUFBLEVBQUFELENBQUEsRUFBQThCLE1BQUEsQ0FBQUksd0JBQUEsQ0FBQWhDLENBQUEsRUFBQUYsQ0FBQSxpQkFBQUMsQ0FBQSxJQW5CbkY7QUFDQTtBQXlCTyxJQUFNNEMsbUJBQW1CLEdBQUFDLE9BQUEsQ0FBQUQsbUJBQUEsR0FBRyxTQUFTOztBQUU1QztBQUNBO0FBQUEsSUFDWUUsWUFBWSxHQUFBRCxPQUFBLENBQUFDLFlBQUEsMEJBQVpBLFlBQVk7RUFBWkEsWUFBWTtFQUFaQSxZQUFZO0VBQVpBLFlBQVk7RUFBWkEsWUFBWTtFQUFaQSxZQUFZO0VBQVpBLFlBQVk7RUFBQSxPQUFaQSxZQUFZO0FBQUEsT0FTeEI7QUFLQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ08sU0FBU0MsZUFBZUEsQ0FBQ0MsUUFBbUMsRUFBVztFQUFBLElBQUFDLGtCQUFBO0VBQzVFLE9BQU9DLE9BQU8sQ0FBQ0YsUUFBUSxhQUFSQSxRQUFRLGdCQUFBQyxrQkFBQSxHQUFSRCxRQUFRLENBQUVHLFFBQVEsY0FBQUYsa0JBQUEsdUJBQWxCQSxrQkFBQSxDQUFvQkcsR0FBRyxDQUFDLHNCQUFzQixDQUFDLENBQUM7QUFDakU7QUFFTyxTQUFTQyxzQkFBc0JBLENBQUNDLFVBQW1CLEVBQWtCO0VBQzFFLElBQU1DLFVBQVUsR0FBRyxJQUFJLENBQUMsQ0FBQztFQUN6QixJQUFJLElBQUFDLFFBQUEsYUFBT0YsVUFBVSxNQUFLLFFBQVEsRUFBRTtJQUNsQztJQUNBO0lBQ0EsSUFBTUcsVUFBVSxHQUFHLElBQUFDLDRCQUFTLEVBQUNKLFVBQVUsQ0FBQztJQUN4QyxJQUFJLENBQUNHLFVBQVUsSUFBSSxDQUFDckQsS0FBSyxDQUFDQyxPQUFPLENBQUNvRCxVQUFVLENBQUNFLFFBQVEsQ0FBQyxFQUFFO01BQ3REO01BQ0EsT0FBTyxJQUFJO0lBQ2I7SUFFQSxPQUFBdEIsYUFBQTtNQUFRa0IsVUFBVSxFQUFWQTtJQUFVLEdBQUtFLFVBQVUsQ0FBQ0UsUUFBUSxDQUFDLENBQUMsQ0FBQztFQUMvQyxDQUFDLE1BQU0sSUFBSSxPQUFPTCxVQUFVLEtBQUssUUFBUSxFQUFFO0lBQ3pDLElBQU1NLGNBQWMsR0FBR0MsdUJBQXVCLENBQUNQLFVBQVUsQ0FBQztJQUMxRCxJQUFJLENBQUNNLGNBQWMsRUFBRSxPQUFPLElBQUk7SUFDaEM7SUFDQSxPQUFBdkIsYUFBQTtNQUFRa0IsVUFBVSxFQUFWQTtJQUFVLEdBQUtLLGNBQWM7RUFDdkMsQ0FBQyxNQUFNLElBQUl4RCxLQUFLLENBQUNDLE9BQU8sQ0FBQ2lELFVBQVUsQ0FBQyxFQUFFO0lBQ3BDO0lBQ0EsT0FBTztNQUNMUSxJQUFJLEVBQUUsU0FBUztNQUNmQyxRQUFRLEVBQUU7UUFDUjtRQUNBQyxXQUFXLEVBQUVWLFVBQVUsQ0FBQ1csR0FBRyxDQUFDLFVBQUFDLEdBQUc7VUFBQSxPQUFJLENBQUNBLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRUEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQUEsRUFBQztRQUNwREosSUFBSSxFQUFFO01BQ1IsQ0FBQztNQUNEUCxVQUFVLEVBQVZBO0lBQ0YsQ0FBQztFQUNIO0VBRUEsT0FBTyxJQUFJO0FBQ2I7QUFFTyxTQUFTWSxtQkFBbUJBLENBQUFDLElBQUEsRUFRVDtFQUFBLElBUHhCQyxhQUFhLEdBQUFELElBQUEsQ0FBYkMsYUFBYTtJQUNiQyxVQUFVLEdBQUFGLElBQUEsQ0FBVkUsVUFBVTtJQUNWQyxNQUFNLEdBQUFILElBQUEsQ0FBTkcsTUFBTTtFQU1OLElBQU1DLGFBQWEsR0FDakJELE1BQU0sQ0FBQ0UsVUFBVSxLQUFLN0IsbUJBQW1CLEdBQ3JDOEIsa0JBQWtCLENBQUNMLGFBQWEsRUFBRUMsVUFBVSxDQUFDO0VBQzdDO0VBQ0FLLHFCQUFxQixDQUFDTixhQUFhLEVBQUVFLE1BQU0sQ0FBQ0ssT0FBTyxFQUFFLFFBQVEsQ0FBQzs7RUFFcEU7RUFDQSxJQUFNQyxNQUFNLEdBQUdDLGdCQUFnQixDQUFDTixhQUFhLENBQUM7RUFDOUM7RUFDQSxJQUFNTyxXQUFXLEdBQUc3QixPQUFPLENBQ3pCc0IsYUFBYSxDQUFDUSxJQUFJLENBQUMsVUFBQUMsQ0FBQztJQUFBLElBQUFDLGFBQUE7SUFBQSxPQUFJRCxDQUFDLElBQUksWUFBWSxJQUFJQSxDQUFDLE1BQUFDLGFBQUEsR0FBSUQsQ0FBQyxDQUFDMUIsVUFBVSxjQUFBMkIsYUFBQSx1QkFBWkEsYUFBQSxDQUFjQyxNQUFNO0VBQUEsRUFDeEUsQ0FBQzs7RUFFRDtFQUNBLElBQU1DLFlBQVksR0FBR0Msc0JBQXNCLENBQUNiLGFBQWEsQ0FBQztFQUUxRCxJQUFNYyxXQUFtQyxHQUFHLEVBQUU7RUFDOUMsS0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBQyxFQUFFQSxDQUFDLEdBQUdmLGFBQWEsQ0FBQ2pFLE1BQU0sRUFBRWdGLENBQUMsRUFBRSxFQUFFO0lBQzdDLElBQU1DLE9BQU8sR0FBR2hCLGFBQWEsQ0FBQ2UsQ0FBQyxDQUFDO0lBQ2hDLElBQUlDLE9BQU8sRUFBRTtNQUNYLElBQUk7UUFDRjtRQUNBLElBQU1DLElBQUksR0FBRyxJQUFBQyxrQkFBTSxFQUFDRixPQUFxQixDQUFDO1FBQzFDRixXQUFXLENBQUNuRCxJQUFJLENBQUNzRCxJQUFJLENBQUMxQixRQUFRLENBQUNDLFdBQVcsQ0FBQztNQUM3QyxDQUFDLENBQUMsT0FBT2hFLENBQUMsRUFBRTtRQUNWc0YsV0FBVyxDQUFDbkQsSUFBSSxDQUFDLElBQUksQ0FBQztNQUN4QjtJQUNGO0VBQ0Y7RUFFQSxPQUFPO0lBQ0xxQyxhQUFhLEVBQWJBLGFBQWE7SUFDYkssTUFBTSxFQUFOQSxNQUFNO0lBQ05FLFdBQVcsRUFBWEEsV0FBVztJQUNYSyxZQUFZLEVBQVpBLFlBQVk7SUFDWk8sU0FBUyxFQUFFTDtFQUNiLENBQUM7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDTyxTQUFTWixrQkFBa0JBLENBQ2hDTCxhQUFxQyxFQUNyQ0MsVUFBc0IsRUFDTDtFQUNqQixJQUFNc0IsZUFBZSxHQUFHLENBQ3RCLE9BQU8sRUFDUCxZQUFZLEVBQ1osWUFBWSxFQUNaLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsY0FBYyxFQUNkLG9CQUFvQixDQUNyQjtFQUVELElBQU1wQixhQUE4QixHQUFHLEVBQUU7RUFFekMsS0FBSyxJQUFJcUIsS0FBSyxHQUFHLENBQUMsRUFBRUEsS0FBSyxHQUFHeEIsYUFBYSxDQUFDeUIsT0FBTyxDQUFDLENBQUMsRUFBRUQsS0FBSyxFQUFFLEVBQUU7SUFDNUQsSUFBTUwsT0FBTyxHQUFHbkMsc0JBQXNCLENBQUNpQixVQUFVLENBQUM7TUFBQ3VCLEtBQUssRUFBTEE7SUFBSyxDQUFDLENBQUMsQ0FBQztJQUUzRCxJQUFJTCxPQUFPLElBQUlBLE9BQU8sQ0FBQ3pCLFFBQVEsSUFBSTZCLGVBQWUsQ0FBQ0csUUFBUSxDQUFDUCxPQUFPLENBQUN6QixRQUFRLENBQUNELElBQUksQ0FBQyxFQUFFO01BQ2xGLElBQU1rQyxPQUFPLEdBQUEzRCxhQUFBLENBQUFBLGFBQUEsS0FDUm1ELE9BQU87UUFDVjtRQUNBakMsVUFBVSxFQUFBbEIsYUFBQSxDQUFBQSxhQUFBLEtBQ0xtRCxPQUFPLENBQUNqQyxVQUFVO1VBQ3JCc0MsS0FBSyxFQUFMQTtRQUFLO01BQ04sRUFDRjtNQUVEckIsYUFBYSxDQUFDcUIsS0FBSyxDQUFDLEdBQUdHLE9BQU87SUFDaEMsQ0FBQyxNQUFNO01BQ0x4QixhQUFhLENBQUNxQixLQUFLLENBQUMsR0FBRyxJQUFJO0lBQzdCO0VBQ0Y7RUFFQSxPQUFPckIsYUFBYTtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDTyxTQUFTeUIsdUJBQXVCQSxDQUNyQzVCLGFBQXFDLEVBQ3JDQyxVQUFzQixFQUNBO0VBQ3RCLElBQU1zQixlQUFlLEdBQUcsQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixDQUFDO0VBRXJFLElBQU1wQixhQUFtQyxHQUFHLEVBQUU7RUFFOUMsS0FBSyxJQUFJcUIsS0FBSyxHQUFHLENBQUMsRUFBRUEsS0FBSyxHQUFHeEIsYUFBYSxDQUFDeUIsT0FBTyxDQUFDLENBQUMsRUFBRUQsS0FBSyxFQUFFLEVBQUU7SUFDNUQsSUFBTUwsT0FBTyxHQUFHbkMsc0JBQXNCLENBQUNpQixVQUFVLENBQUNELGFBQWEsQ0FBQzZCLFVBQVUsQ0FBQ0wsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUVuRixJQUFJTCxPQUFPLElBQUlBLE9BQU8sQ0FBQ3pCLFFBQVEsSUFBSTZCLGVBQWUsQ0FBQ0csUUFBUSxDQUFDUCxPQUFPLENBQUN6QixRQUFRLENBQUNELElBQUksQ0FBQyxFQUFFO01BQ2xGVSxhQUFhLENBQUNxQixLQUFLLENBQUMsR0FDbEJMLE9BQU8sQ0FBQ3pCLFFBQVEsQ0FBQ0QsSUFBSSxLQUFLLE9BQU8sSUFBSTBCLE9BQU8sQ0FBQ3pCLFFBQVEsQ0FBQ0QsSUFBSSxLQUFLLFlBQVksR0FDdkUwQixPQUFPLENBQUN6QixRQUFRLENBQUNDLFdBQVc7TUFDNUI7TUFDQSxDQUFDd0IsT0FBTyxDQUFDekIsUUFBUSxDQUFDb0MsVUFBVSxJQUFJLEVBQUUsRUFBRUMsTUFBTSxDQUFDLFVBQUNDLElBQUksRUFBRXZGLENBQUMsRUFBSztRQUN0RCxJQUFJQSxDQUFDLENBQUNnRCxJQUFJLEtBQUssT0FBTyxFQUFFO1VBQ3RCdUMsSUFBSSxDQUFDbEUsSUFBSSxDQUFDckIsQ0FBQyxDQUFDa0QsV0FBVyxDQUFDO1FBQzFCLENBQUMsTUFBTSxJQUFJbEQsQ0FBQyxDQUFDZ0QsSUFBSSxLQUFLLFlBQVksRUFBRTtVQUNsQ3VDLElBQUksQ0FBQ2xFLElBQUksQ0FBQUMsS0FBQSxDQUFUaUUsSUFBSSxNQUFBQyxtQkFBQSxhQUFTeEYsQ0FBQyxDQUFDa0QsV0FBVyxFQUFDO1FBQzdCO1FBRUEsT0FBT3FDLElBQUk7TUFDYixDQUFDLEVBQUUsRUFBRSxDQUFDO0lBQ2QsQ0FBQyxNQUFNO01BQ0w3QixhQUFhLENBQUNxQixLQUFLLENBQUMsR0FBRyxJQUFJO0lBQzdCO0VBQ0Y7RUFFQSxPQUFPckIsYUFBYTtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU1gsdUJBQXVCQSxDQUFDMEMsU0FBaUIsRUFBa0I7RUFDbEUsSUFBSUMsU0FBUzs7RUFFYjtFQUNBO0VBQ0EsSUFBSTtJQUNGQSxTQUFTLEdBQUdDLElBQUksQ0FBQ0MsS0FBSyxDQUFDSCxTQUFTLENBQUM7RUFDbkMsQ0FBQyxDQUFDLE9BQ