UNPKG

kepler.gl.geoiq

Version:

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

456 lines (388 loc) 55.7 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = MapContainerFactory; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactMapGl = _interopRequireDefault(require("react-map-gl")); var _deck = _interopRequireDefault(require("deck.gl")); var _constants = _interopRequireDefault(require("luma.gl/constants")); var _luma = require("luma.gl"); var _pickingModule = _interopRequireDefault(require("../shaderlib/picking-module")); var _brushingModule = _interopRequireDefault(require("../shaderlib/brushing-module")); var _mapPopover = _interopRequireDefault(require("./map/map-popover")); var _mapControl = _interopRequireDefault(require("./map/map-control")); var _styledComponents = require("./common/styled-components"); var _mapboxUtils = require("../layers/mapbox-utils"); var _mapboxUtils2 = require("../utils/map-style-utils/mapbox-utils"); var _defaultSettings = require("../constants/default-settings"); var _dBuildingLayer = _interopRequireDefault(require("../deckgl-layers/3d-building-layer/3d-building-layer")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var MAP_STYLE = { container: { display: 'inline-block', position: 'relative' }, top: { position: 'absolute', top: '0px', pointerEvents: 'none' } }; var getGlConst = function getGlConst(d) { return _constants["default"][d]; }; var MAPBOXGL_STYLE_UPDATE = 'style.load'; var TRANSITION_DURATION = 0; MapContainerFactory.deps = [_mapPopover["default"], _mapControl["default"]]; function MapContainerFactory(MapPopover, MapControl) { var MapContainer = /*#__PURE__*/ function (_Component) { (0, _inherits2["default"])(MapContainer, _Component); function MapContainer(props) { var _this; (0, _classCallCheck2["default"])(this, MapContainer); _this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(MapContainer).call(this, props)); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onCloseMapPopover", function () { _this.props.visStateActions.onLayerClick(null); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onLayerSetDomain", function (idx, colorDomain) { _this.props.visStateActions.layerConfigChange(_this.props.layers[idx], { colorDomain: colorDomain }); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onWebGLInitialized", function (gl) { (0, _luma.registerShaderModules)([_pickingModule["default"], _brushingModule["default"]], { ignoreMultipleRegistrations: true }); // allow Uint32 indices in building layer // gl.getExtension('OES_element_index_uint'); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onMouseMove", function (evt) { var brush = _this.props.interactionConfig.brush; if (evt.nativeEvent && brush.enabled) { _this.setState({ mousePosition: [evt.nativeEvent.offsetX, evt.nativeEvent.offsetY] }); } }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_handleMapToggleLayer", function (layerId) { var _this$props = _this.props, _this$props$index = _this$props.index, mapIndex = _this$props$index === void 0 ? 0 : _this$props$index, visStateActions = _this$props.visStateActions; visStateActions.toggleLayerForMap(mapIndex, layerId); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_setMapboxMap", function (mapbox) { if (!_this._map && mapbox) { _this._map = mapbox.getMap(); // bind mapboxgl event listener _this._map.on(MAPBOXGL_STYLE_UPDATE, function () { // force refresh mapboxgl layers (0, _mapboxUtils.updateMapboxLayers)(_this._map, _this._renderMapboxLayers(), _this.previousLayers, _this.props.mapLayers, { force: true }); if (typeof _this.props.onMapStyleLoaded === 'function') { _this.props.onMapStyleLoaded(_this._map); } }); _this._map.on('render', function () { if (typeof _this.props.onMapRender === 'function') { _this.props.onMapRender(_this._map); } }); } }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onBeforeRender", function (_ref) { var gl = _ref.gl; _this._setlayerBlending(gl); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_setlayerBlending", function (gl) { var blending = _defaultSettings.LAYER_BLENDINGS[_this.props.layerBlending]; var blendFunc = blending.blendFunc, blendEquation = blending.blendEquation; (0, _luma.setParameters)(gl, _objectSpread((0, _defineProperty2["default"])({}, _constants["default"].BLEND, true), blendFunc ? { blendFunc: blendFunc.map(getGlConst), blendEquation: Array.isArray(blendEquation) ? blendEquation.map(getGlConst) : getGlConst(blendEquation) } : {})); }); (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_renderLayer", function (overlays, idx) { var _this$props2 = _this.props, layers = _this$props2.layers, layerData = _this$props2.layerData, hoverInfo = _this$props2.hoverInfo, clicked = _this$props2.clicked, mapLayers = _this$props2.mapLayers, mapState = _this$props2.mapState, interactionConfig = _this$props2.interactionConfig; var mousePosition = _this.state.mousePosition; var layer = layers[idx]; var data = layerData[idx]; var layerInteraction = { mousePosition: mousePosition }; var objectHovered = clicked || hoverInfo; var layerCallbacks = { onSetLayerDomain: function onSetLayerDomain(val) { return _this._onLayerSetDomain(idx, val); } }; if (!_this._shouldRenderLayer(layer, data, mapLayers)) { return overlays; } var layerOverlay = []; // Layer is Layer class if (typeof layer.renderLayer === 'function') { layerOverlay = layer.renderLayer({ data: data, idx: idx, layerInteraction: layerInteraction, objectHovered: objectHovered, mapState: mapState, interactionConfig: interactionConfig, layerCallbacks: layerCallbacks }); } if (layerOverlay.length) { overlays = overlays.concat(layerOverlay); } return overlays; }); _this.state = { mousePosition: [0, 0] }; _this.previousLayers = {// [layers.id]: mapboxLayerConfig }; return _this; } (0, _createClass2["default"])(MapContainer, [{ key: "componentWillUnmount", value: function componentWillUnmount() { // unbind mapboxgl event listener if (this._map) { this._map.off(MAPBOXGL_STYLE_UPDATE); } } /* component private functions */ }, { key: "_renderObjectLayerPopover", /* component render functions */ /* eslint-disable complexity */ value: function _renderObjectLayerPopover() { // TODO: move this into reducer so it can be tested var _this$props3 = this.props, mapState = _this$props3.mapState, hoverInfo = _this$props3.hoverInfo, clicked = _this$props3.clicked, datasets = _this$props3.datasets, interactionConfig = _this$props3.interactionConfig, layers = _this$props3.layers, mapLayers = _this$props3.mapLayers; // if clicked something, ignore hover behavior var objectInfo = clicked || hoverInfo; if (!interactionConfig.tooltip.enabled || !objectInfo || !objectInfo.picked) { // nothing hovered return null; } var lngLat = objectInfo.lngLat, object = objectInfo.object, overlay = objectInfo.layer; // deckgl layer to kepler-gl layer var layer = layers[overlay.props.idx]; if (!layer || !layer.config.isVisible || !object || !layer.getHoverData || mapLayers && !mapLayers[layer.id].isVisible) { // layer is not visible return null; } var dataId = layer.config.dataId; var _datasets$dataId = datasets[dataId], allData = _datasets$dataId.allData, fields = _datasets$dataId.fields; var data = layer.getHoverData(object, allData); // project lnglat to screen so that tooltip follows the object on zoom var viewport = overlay.context.viewport; var _ref2 = this._getHoverXY(viewport, lngLat) || objectInfo, x = _ref2.x, y = _ref2.y; var popoverProps = { data: data, fields: fields, fieldsToShow: interactionConfig.tooltip.config.fieldsToShow[dataId], layer: layer, isVisible: true, x: x, y: y, freezed: Boolean(clicked), onClose: this._onCloseMapPopover, mapState: mapState }; // console.log('PopoverProps', popoverProps); return _react["default"].createElement("div", null, _react["default"].createElement(MapPopover, popoverProps)); } /* eslint-enable complexity */ }, { key: "_getHoverXY", value: function _getHoverXY(viewport, lngLat) { var screenCoord = !viewport || !lngLat ? null : viewport.project(lngLat); return screenCoord && { x: screenCoord[0], y: screenCoord[1] }; } }, { key: "_shouldRenderLayer", value: function _shouldRenderLayer(layer, data, mapLayers) { var isAvailableAndVisible = !(mapLayers && mapLayers[layer.id]) || mapLayers[layer.id].isVisible; return layer.shouldRenderLayer(data) && isAvailableAndVisible; } }, { key: "_renderOverlay", value: function _renderOverlay() { var _this$props4 = this.props, mapState = _this$props4.mapState, mapStyle = _this$props4.mapStyle, layerData = _this$props4.layerData, layerOrder = _this$props4.layerOrder, visStateActions = _this$props4.visStateActions; var deckGlLayers = []; // wait until data is ready before render data layers if (layerData && layerData.length) { // last layer render first deckGlLayers = layerOrder.slice().reverse().reduce(this._renderLayer, []); } var threeDBuildingLayerId = '_keplergl_3d-building'; if (mapStyle.visibleLayerGroups['3d building']) { deckGlLayers.push(new _dBuildingLayer["default"]({ id: threeDBuildingLayerId, threeDBuildingColor: mapStyle.threeDBuildingColor })); } return _react["default"].createElement(_deck["default"], { viewState: mapState, id: "default-deckgl-overlay", layers: deckGlLayers, onWebGLInitialized: this._onWebGLInitialized, onBeforeRender: this._onBeforeRender, onLayerHover: visStateActions.onLayerHover, onLayerClick: visStateActions.onLayerClick }); } }, { key: "_renderMapboxLayers", value: function _renderMapboxLayers() { var _this$props5 = this.props, layers = _this$props5.layers, layerData = _this$props5.layerData, layerOrder = _this$props5.layerOrder; return (0, _mapboxUtils.generateMapboxLayers)(layers, layerData, layerOrder); } }, { key: "_renderMapboxOverlays", value: function _renderMapboxOverlays() { if (this._map && this._map.isStyleLoaded()) { var mapboxLayers = this._renderMapboxLayers(); (0, _mapboxUtils.updateMapboxLayers)(this._map, mapboxLayers, this.previousLayers, this.props.mapLayers); this.previousLayers = mapboxLayers.reduce(function (_final, layer) { return _objectSpread({}, _final, (0, _defineProperty2["default"])({}, layer.id, layer.config)); }, {}); } } }, { key: "render", value: function render() { var _this$props6 = this.props, mapState = _this$props6.mapState, mapStyle = _this$props6.mapStyle, mapStateActions = _this$props6.mapStateActions, mapLayers = _this$props6.mapLayers, layers = _this$props6.layers, MapComponent = _this$props6.MapComponent, datasets = _this$props6.datasets, mapboxApiAccessToken = _this$props6.mapboxApiAccessToken, mapControls = _this$props6.mapControls, toggleMapControl = _this$props6.toggleMapControl; var updateMap = mapStateActions.updateMap, onMapClick = mapStateActions.onMapClick; if (!mapStyle.bottomMapStyle) { // style not yet loaded return _react["default"].createElement("div", null); } var mapProps = _objectSpread({}, mapState, { preserveDrawingBuffer: true, mapboxApiAccessToken: mapboxApiAccessToken, onViewportChange: updateMap, transformRequest: _mapboxUtils2.transformRequest }); return _react["default"].createElement(_styledComponents.StyledMapContainer, { style: MAP_STYLE.container, onMouseMove: this._onMouseMove }, _react["default"].createElement(MapControl, { datasets: datasets, dragRotate: mapState.dragRotate, isSplit: mapState.isSplit, isExport: this.props.isExport, layers: layers, mapIndex: this.props.index, mapLayers: mapLayers, mapControls: mapControls, scale: mapState.scale || 1, top: 0, onTogglePerspective: mapStateActions.togglePerspective, onToggleSplitMap: mapStateActions.toggleSplitMap, onMapToggleLayer: this._handleMapToggleLayer, onToggleFullScreen: mapStateActions.toggleFullScreen, fitBounds: mapStateActions.fitBounds, onToggleMapControl: toggleMapControl }), _react["default"].createElement(MapComponent, (0, _extends2["default"])({}, mapProps, { key: "bottom", ref: this._setMapboxMap, mapStyle: mapStyle.bottomMapStyle, onClick: onMapClick, getCursor: this.props.hoverInfo ? function () { return 'pointer'; } : undefined, transitionDuration: TRANSITION_DURATION }), this._renderOverlay(), this._renderMapboxOverlays()), mapStyle.topMapStyle && _react["default"].createElement("div", { style: MAP_STYLE.top }, _react["default"].createElement(MapComponent, (0, _extends2["default"])({}, mapProps, { key: "top", mapStyle: mapStyle.topMapStyle }))), this._renderObjectLayerPopover()); } }]); return MapContainer; }(_react.Component); (0, _defineProperty2["default"])(MapContainer, "propTypes", { // required datasets: _propTypes["default"].object, interactionConfig: _propTypes["default"].object.isRequired, layerBlending: _propTypes["default"].string.isRequired, layerOrder: _propTypes["default"].arrayOf(_propTypes["default"].any).isRequired, layerData: _propTypes["default"].arrayOf(_propTypes["default"].any).isRequired, layers: _propTypes["default"].arrayOf(_propTypes["default"].any).isRequired, mapState: _propTypes["default"].object.isRequired, mapStyle: _propTypes["default"].object.isRequired, mapControls: _propTypes["default"].object.isRequired, mapboxApiAccessToken: _propTypes["default"].string.isRequired, toggleMapControl: _propTypes["default"].func.isRequired, visStateActions: _propTypes["default"].object.isRequired, mapStateActions: _propTypes["default"].object.isRequired, // optional isExport: _propTypes["default"].bool, clicked: _propTypes["default"].object, hoverInfo: _propTypes["default"].object, mapLayers: _propTypes["default"].object, onMapToggleLayer: _propTypes["default"].func, onMapStyleLoaded: _propTypes["default"].func, onMapRender: _propTypes["default"].func }); (0, _defineProperty2["default"])(MapContainer, "defaultProps", { MapComponent: _reactMapGl["default"] }); return MapContainer; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL21hcC1jb250YWluZXIuanMiXSwibmFtZXMiOlsiTUFQX1NUWUxFIiwiY29udGFpbmVyIiwiZGlzcGxheSIsInBvc2l0aW9uIiwidG9wIiwicG9pbnRlckV2ZW50cyIsImdldEdsQ29uc3QiLCJkIiwiR0wiLCJNQVBCT1hHTF9TVFlMRV9VUERBVEUiLCJUUkFOU0lUSU9OX0RVUkFUSU9OIiwiTWFwQ29udGFpbmVyRmFjdG9yeSIsImRlcHMiLCJNYXBQb3BvdmVyRmFjdG9yeSIsIk1hcENvbnRyb2xGYWN0b3J5IiwiTWFwUG9wb3ZlciIsIk1hcENvbnRyb2wiLCJNYXBDb250YWluZXIiLCJwcm9wcyIsInZpc1N0YXRlQWN0aW9ucyIsIm9uTGF5ZXJDbGljayIsImlkeCIsImNvbG9yRG9tYWluIiwibGF5ZXJDb25maWdDaGFuZ2UiLCJsYXllcnMiLCJnbCIsInBpY2tpbmdNb2R1bGUiLCJicnVzaGluZ01vZHVsZSIsImlnbm9yZU11bHRpcGxlUmVnaXN0cmF0aW9ucyIsImV2dCIsImJydXNoIiwiaW50ZXJhY3Rpb25Db25maWciLCJuYXRpdmVFdmVudCIsImVuYWJsZWQiLCJzZXRTdGF0ZSIsIm1vdXNlUG9zaXRpb24iLCJvZmZzZXRYIiwib2Zmc2V0WSIsImxheWVySWQiLCJpbmRleCIsIm1hcEluZGV4IiwidG9nZ2xlTGF5ZXJGb3JNYXAiLCJtYXBib3giLCJfbWFwIiwiZ2V0TWFwIiwib24iLCJfcmVuZGVyTWFwYm94TGF5ZXJzIiwicHJldmlvdXNMYXllcnMiLCJtYXBMYXllcnMiLCJmb3JjZSIsIm9uTWFwU3R5bGVMb2FkZWQiLCJvbk1hcFJlbmRlciIsIl9zZXRsYXllckJsZW5kaW5nIiwiYmxlbmRpbmciLCJMQVlFUl9CTEVORElOR1MiLCJsYXllckJsZW5kaW5nIiwiYmxlbmRGdW5jIiwiYmxlbmRFcXVhdGlvbiIsIkJMRU5EIiwibWFwIiwiQXJyYXkiLCJpc0FycmF5Iiwib3ZlcmxheXMiLCJsYXllckRhdGEiLCJob3ZlckluZm8iLCJjbGlja2VkIiwibWFwU3RhdGUiLCJzdGF0ZSIsImxheWVyIiwiZGF0YSIsImxheWVySW50ZXJhY3Rpb24iLCJvYmplY3RIb3ZlcmVkIiwibGF5ZXJDYWxsYmFja3MiLCJvblNldExheWVyRG9tYWluIiwidmFsIiwiX29uTGF5ZXJTZXREb21haW4iLCJfc2hvdWxkUmVuZGVyTGF5ZXIiLCJsYXllck92ZXJsYXkiLCJyZW5kZXJMYXllciIsImxlbmd0aCIsImNvbmNhdCIsIm9mZiIsImRhdGFzZXRzIiwib2JqZWN0SW5mbyIsInRvb2x0aXAiLCJwaWNrZWQiLCJsbmdMYXQiLCJvYmplY3QiLCJvdmVybGF5IiwiY29uZmlnIiwiaXNWaXNpYmxlIiwiZ2V0SG92ZXJEYXRhIiwiaWQiLCJkYXRhSWQiLCJhbGxEYXRhIiwiZmllbGRzIiwidmlld3BvcnQiLCJjb250ZXh0IiwiX2dldEhvdmVyWFkiLCJ4IiwieSIsInBvcG92ZXJQcm9wcyIsImZpZWxkc1RvU2hvdyIsImZyZWV6ZWQiLCJCb29sZWFuIiwib25DbG9zZSIsIl9vbkNsb3NlTWFwUG9wb3ZlciIsInNjcmVlbkNvb3JkIiwicHJvamVjdCIsImlzQXZhaWxhYmxlQW5kVmlzaWJsZSIsInNob3VsZFJlbmRlckxheWVyIiwibWFwU3R5bGUiLCJsYXllck9yZGVyIiwiZGVja0dsTGF5ZXJzIiwic2xpY2UiLCJyZXZlcnNlIiwicmVkdWNlIiwiX3JlbmRlckxheWVyIiwidGhyZWVEQnVpbGRpbmdMYXllcklkIiwidmlzaWJsZUxheWVyR3JvdXBzIiwicHVzaCIsIlRocmVlREJ1aWxkaW5nTGF5ZXIiLCJ0aHJlZURCdWlsZGluZ0NvbG9yIiwiX29uV2ViR0xJbml0aWFsaXplZCIsIl9vbkJlZm9yZVJlbmRlciIsIm9uTGF5ZXJIb3ZlciIsImlzU3R5bGVMb2FkZWQiLCJtYXBib3hMYXllcnMiLCJmaW5hbCIsIm1hcFN0YXRlQWN0aW9ucyIsIk1hcENvbXBvbmVudCIsIm1hcGJveEFwaUFjY2Vzc1Rva2VuIiwibWFwQ29udHJvbHMiLCJ0b2dnbGVNYXBDb250cm9sIiwidXBkYXRlTWFwIiwib25NYXBDbGljayIsImJvdHRvbU1hcFN0eWxlIiwibWFwUHJvcHMiLCJwcmVzZXJ2ZURyYXdpbmdCdWZmZXIiLCJvblZpZXdwb3J0Q2hhbmdlIiwidHJhbnNmb3JtUmVxdWVzdCIsIl9vbk1vdXNlTW92ZSIsImRyYWdSb3RhdGUiLCJpc1NwbGl0IiwiaXNFeHBvcnQiLCJzY2FsZSIsInRvZ2dsZVBlcnNwZWN0aXZlIiwidG9nZ2xlU3BsaXRNYXAiLCJfaGFuZGxlTWFwVG9nZ2xlTGF5ZXIiLCJ0b2dnbGVGdWxsU2NyZWVuIiwiZml0Qm91bmRzIiwiX3NldE1hcGJveE1hcCIsInVuZGVmaW5lZCIsIl9yZW5kZXJPdmVybGF5IiwiX3JlbmRlck1hcGJveE92ZXJsYXlzIiwidG9wTWFwU3R5bGUiLCJfcmVuZGVyT2JqZWN0TGF5ZXJQb3BvdmVyIiwiQ29tcG9uZW50IiwiUHJvcFR5cGVzIiwiaXNSZXF1aXJlZCIsInN0cmluZyIsImFycmF5T2YiLCJhbnkiLCJmdW5jIiwiYm9vbCIsIm9uTWFwVG9nZ2xlTGF5ZXIiLCJNYXBib3hHTE1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUJBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBOztBQUNBOztBQUNBOztBQUdBOztBQUVBOztBQUdBOztBQUNBOzs7Ozs7QUFFQSxJQUFNQSxTQUFTLEdBQUc7QUFDaEJDLEVBQUFBLFNBQVMsRUFBRTtBQUNUQyxJQUFBQSxPQUFPLEVBQUUsY0FEQTtBQUVUQyxJQUFBQSxRQUFRLEVBQUU7QUFGRCxHQURLO0FBS2hCQyxFQUFBQSxHQUFHLEVBQUU7QUFDSEQsSUFBQUEsUUFBUSxFQUFFLFVBRFA7QUFFSEMsSUFBQUEsR0FBRyxFQUFFLEtBRkY7QUFHSEMsSUFBQUEsYUFBYSxFQUFFO0FBSFo7QUFMVyxDQUFsQjs7QUFZQSxJQUFNQyxVQUFVLEdBQUcsU0FBYkEsVUFBYSxDQUFBQyxDQUFD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bnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDE5IFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuLy8gbGlicmFyaWVzXG5pbXBvcnQgUmVhY3QsIHtDb21wb25lbnR9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQgTWFwYm94R0xNYXAgZnJvbSAncmVhY3QtbWFwLWdsJztcbmltcG9ydCBEZWNrR0wgZnJvbSAnZGVjay5nbCc7XG5pbXBvcnQgR0wgZnJvbSAnbHVtYS5nbC9jb25zdGFudHMnO1xuaW1wb3J0IHtyZWdpc3RlclNoYWRlck1vZHVsZXMsIHNldFBhcmFtZXRlcnN9IGZyb20gJ2x1bWEuZ2wnO1xuaW1wb3J0IHBpY2tpbmdNb2R1bGUgZnJvbSAnc2hhZGVybGliL3BpY2tpbmctbW9kdWxlJztcbmltcG9ydCBicnVzaGluZ01vZHVsZSBmcm9tICdzaGFkZXJsaWIvYnJ1c2hpbmctbW9kdWxlJztcblxuLy8gY29tcG9uZW50c1xuaW1wb3J0IE1hcFBvcG92ZXJGYWN0b3J5IGZyb20gJ2NvbXBvbmVudHMvbWFwL21hcC1wb3BvdmVyJztcbmltcG9ydCBNYXBDb250cm9sRmFjdG9yeSBmcm9tICdjb21wb25lbnRzL21hcC9tYXAtY29udHJvbCc7XG5pbXBvcnQge1N0eWxlZE1hcENvbnRhaW5lcn0gZnJvbSAnY29tcG9uZW50cy9jb21tb24vc3R5bGVkLWNvbXBvbmVudHMnO1xuXG4vLyBPdmVybGF5IHR5cGVcbmltcG9ydCB7Z2VuZXJhdGVNYXBib3hMYXllcnMsIHVwZGF0ZU1hcGJveExheWVyc30gZnJvbSAnLi4vbGF5ZXJzL21hcGJveC11dGlscyc7XG5cbmltcG9ydCB7dHJhbnNmb3JtUmVxdWVzdH0gZnJvbSAndXRpbHMvbWFwLXN0eWxlLXV0aWxzL21hcGJveC11dGlscyc7XG5cbi8vIGRlZmF1bHQtc2V0dGluZ3NcbmltcG9ydCB7TEFZRVJfQkxFTkRJTkdTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5pbXBvcnQgVGhyZWVEQnVpbGRpbmdMYXllciBmcm9tICcuLi9kZWNrZ2wtbGF5ZXJzLzNkLWJ1aWxkaW5nLWxheWVyLzNkLWJ1aWxkaW5nLWxheWVyJztcblxuY29uc3QgTUFQX1NUWUxFID0ge1xuICBjb250YWluZXI6IHtcbiAgICBkaXNwbGF5OiAnaW5saW5lLWJsb2NrJyxcbiAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJ1xuICB9LFxuICB0b3A6IHtcbiAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICB0b3A6ICcwcHgnLFxuICAgIHBvaW50ZXJFdmVudHM6ICdub25lJ1xuICB9XG59O1xuXG5jb25zdCBnZXRHbENvbnN0ID0gZCA9PiBHTFtkXTtcblxuY29uc3QgTUFQQk9YR0xfU1RZTEVfVVBEQVRFID0gJ3N0eWxlLmxvYWQnO1xuY29uc3QgVFJBTlNJVElPTl9EVVJBVElPTiA9IDA7XG5cbk1hcENvbnRhaW5lckZhY3RvcnkuZGVwcyA9IFtNYXBQb3BvdmVyRmFjdG9yeSwgTWFwQ29udHJvbEZhY3RvcnldO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBNYXBDb250YWluZXJGYWN0b3J5KE1hcFBvcG92ZXIsIE1hcENvbnRyb2wpIHtcbiAgY2xhc3MgTWFwQ29udGFpbmVyIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgICBzdGF0aWMgcHJvcFR5cGVzID0ge1xuICAgICAgLy8gcmVxdWlyZWRcbiAgICAgIGRhdGFzZXRzOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgaW50ZXJhY3Rpb25Db25maWc6IFByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbiAgICAgIGxheWVyQmxlbmRpbmc6IFByb3BUeXBlcy5zdHJpbmcuaXNSZXF1aXJlZCxcbiAgICAgIGxheWVyT3JkZXI6IFByb3BUeXBlcy5hcnJheU9mKFByb3BUeXBlcy5hbnkpLmlzUmVxdWlyZWQsXG4gICAgICBsYXllckRhdGE6IFByb3BUeXBlcy5hcnJheU9mKFByb3BUeXBlcy5hbnkpLmlzUmVxdWlyZWQsXG4gICAgICBsYXllcnM6IFByb3BUeXBlcy5hcnJheU9mKFByb3BUeXBlcy5hbnkpLmlzUmVxdWlyZWQsXG4gICAgICBtYXBTdGF0ZTogUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuICAgICAgbWFwU3R5bGU6IFByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbiAgICAgIG1hcENvbnRyb2xzOiBQcm9wVHlwZXMub2JqZWN0LmlzUmVxdWlyZWQsXG4gICAgICBtYXBib3hBcGlBY2Nlc3NUb2tlbjogUHJvcFR5cGVzLnN0cmluZy5pc1JlcXVpcmVkLFxuICAgICAgdG9nZ2xlTWFwQ29udHJvbDogUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcbiAgICAgIHZpc1N0YXRlQWN0aW9uczogUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuICAgICAgbWFwU3RhdGVBY3Rpb25zOiBQcm9wVHlwZXMub2JqZWN0LmlzUmVxdWlyZWQsXG5cbiAgICAgIC8vIG9wdGlvbmFsXG4gICAgICBpc0V4cG9ydDogUHJvcFR5cGVzLmJvb2wsXG4gICAgICBjbGlja2VkOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgaG92ZXJJbmZvOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgbWFwTGF5ZXJzOiBQcm9wVHlwZXMub2JqZWN0LFxuICAgICAgb25NYXBUb2dnbGVMYXllcjogUHJvcFR5cGVzLmZ1bmMsXG4gICAgICBvbk1hcFN0eWxlTG9hZGVkOiBQcm9wVHlwZXMuZnVuYyxcbiAgICAgIG9uTWFwUmVuZGVyOiBQcm9wVHlwZXMuZnVuY1xuICAgIH07XG5cbiAgICBzdGF0aWMgZGVmYXVsdFByb3BzID0ge1xuICAgICAgTWFwQ29tcG9uZW50OiBNYXBib3hHTE1hcFxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgICAgc3VwZXIocHJvcHMpO1xuICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgbW91c2VQb3NpdGlvbjogWzAsIDBdXG4gICAgICB9O1xuICAgICAgdGhpcy5wcmV2aW91c0xheWVycyA9IHtcbiAgICAgICAgLy8gW2xheWVycy5pZF06IG1hcGJveExheWVyQ29uZmlnXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgLy8gdW5iaW5kIG1hcGJveGdsIGV2ZW50IGxpc3RlbmVyXG4gICAgICBpZiAodGhpcy5fbWFwKSB7XG4gICAgICAgIHRoaXMuX21hcC5vZmYoTUFQQk9YR0xfU1RZTEVfVVBEQVRFKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBjb21wb25lbnQgcHJpdmF0ZSBmdW5jdGlvbnMgKi9cbiAgICBfb25DbG9zZU1hcFBvcG92ZXIgPSAoKSA9PiB7XG4gICAgICB0aGlzLnByb3BzLnZpc1N0YXRlQWN0aW9ucy5vbkxheWVyQ2xpY2sobnVsbCk7XG4gICAgfTtcblxuICAgIF9vbkxheWVyU2V0RG9tYWluID0gKGlkeCwgY29sb3JEb21haW4pID0+IHtcbiAgICAgIHRoaXMucHJvcHMudmlzU3RhdGVBY3Rpb25zLmxheWVyQ29uZmlnQ2hhbmdlKHRoaXMucHJvcHMubGF5ZXJzW2lkeF0sIHtcbiAgICAgICAgY29sb3JEb21haW5cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfb25XZWJHTEluaXRpYWxpemVkID0gZ2wgPT4ge1xuICAgICAgcmVnaXN0ZXJTaGFkZXJNb2R1bGVzKFtwaWNraW5nTW9kdWxlLCBicnVzaGluZ01vZHVsZV0sIHtcbiAgICAgICAgaWdub3JlTXVsdGlwbGVSZWdpc3RyYXRpb25zOiB0cnVlXG4gICAgICB9KTtcblxuICAgICAgLy8gYWxsb3cgVWludDMyIGluZGljZXMgaW4gYnVpbGRpbmcgbGF5ZXJcbiAgICAgIC8vIGdsLmdldEV4dGVuc2lvbignT0VTX2VsZW1lbnRfaW5kZXhfdWludCcpO1xuICAgIH07XG5cbiAgICBfb25Nb3VzZU1vdmUgPSBldnQgPT4ge1xuICAgICAgY29uc3Qge1xuICAgICAgICBpbnRlcmFjdGlvbkNvbmZpZzoge2JydXNofVxuICAgICAgfSA9IHRoaXMucHJvcHM7XG5cbiAgICAgIGlmIChldnQubmF0aXZlRXZlbnQgJiYgYnJ1c2guZW5hYmxlZCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICBtb3VzZVBvc2l0aW9uOiBbZXZ0Lm5hdGl2ZUV2ZW50Lm9mZnNldFgsIGV2dC5uYXRpdmVFdmVudC5vZmZzZXRZXVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX2hhbmRsZU1hcFRvZ2dsZUxheWVyID0gbGF5ZXJJZCA9PiB7XG4gICAgICBjb25zdCB7aW5kZXg6IG1hcEluZGV4ID0gMCwgdmlzU3RhdGVBY3Rpb25zfSA9IHRoaXMucHJvcHM7XG4gICAgICB2aXNTdGF0ZUFjdGlvbnMudG9nZ2xlTGF5ZXJGb3JNYXAobWFwSW5kZXgsIGxheWVySWQpO1xuICAgIH07XG5cbiAgICBfc2V0TWFwYm94TWFwID0gbWFwYm94ID0+IHtcbiAgICAgIGlmICghdGhpcy5fbWFwICYmIG1hcGJveCkge1xuICAgICAgICB0aGlzLl9tYXAgPSBtYXBib3guZ2V0TWFwKCk7XG4gICAgICAgIC8vIGJpbmQgbWFwYm94Z2wgZXZlbnQgbGlzdGVuZXJcbiAgICAgICAgdGhpcy5fbWFwLm9uKE1BUEJPWEdMX1NUWUxFX1VQREFURSwgKCkgPT4ge1xuICAgICAgICAgIC8vIGZvcmNlIHJlZnJlc2ggbWFwYm94Z2wgbGF5ZXJzXG5cbiAgICAgICAgICB1cGRhdGVNYXBib3hMYXllcnMoXG4gICAgICAgICAgICB0aGlzLl9tYXAsXG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJNYXBib3hMYXllcnMoKSxcbiAgICAgICAgICAgIHRoaXMucHJldmlvdXNMYXllcnMsXG4gICAgICAgICAgICB0aGlzLnByb3BzLm1hcExheWVycyxcbiAgICAgICAgICAgIHtmb3JjZTogdHJ1ZX1cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnByb3BzLm9uTWFwU3R5bGVMb2FkZWQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRoaXMucHJvcHMub25NYXBTdHlsZUxvYWRlZCh0aGlzLl9tYXApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5fbWFwLm9uKCdyZW5kZXInLCAoKSA9PiB7XG4gICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnByb3BzLm9uTWFwUmVuZGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLm9uTWFwUmVuZGVyKHRoaXMuX21hcCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX29uQmVmb3JlUmVuZGVyID0gKHtnbH0pID0+IHtcbiAgICAgIHRoaXMuX3NldGxheWVyQmxlbmRpbmcoZ2wpO1xuICAgIH07XG5cbiAgICBfc2V0bGF5ZXJCbGVuZGluZyA9IGdsID0+IHtcbiAgICAgIGNvbnN0IGJsZW5kaW5nID0gTEFZRVJfQkxFTkRJTkdTW3RoaXMucHJvcHMubGF5ZXJCbGVuZGluZ107XG4gICAgICBjb25zdCB7YmxlbmRGdW5jLCBibGVuZEVxdWF0aW9ufSA9IGJsZW5kaW5nO1xuXG4gICAgICBzZXRQYXJhbWV0ZXJzKGdsLCB7XG4gICAgICAgIFtHTC5CTEVORF06IHRydWUsXG4gICAgICAgIC4uLihibGVuZEZ1bmNcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgYmxlbmRGdW5jOiBibGVuZEZ1bmMubWFwKGdldEdsQ29uc3QpLFxuICAgICAgICAgICAgICBibGVuZEVxdWF0aW9uOiBBcnJheS5pc0FycmF5KGJsZW5kRXF1YXRpb24pXG4gICAgICAgICAgICAgICAgPyBibGVuZEVxdWF0aW9uLm1hcChnZXRHbENvbnN0KVxuICAgICAgICAgICAgICAgIDogZ2V0R2xDb25zdChibGVuZEVxdWF0aW9uKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIDoge30pXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyogY29tcG9uZW50IHJlbmRlciBmdW5jdGlvbnMgKi9cbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBjb21wbGV4aXR5ICovXG4gICAgX3JlbmRlck9iamVjdExheWVyUG9wb3ZlcigpIHtcbiAgICAgIC8vIFRPRE86IG1vdmUgdGhpcyBpbnRvIHJlZHVjZXIgc28gaXQgY2FuIGJlIHRlc3RlZFxuICAgICAgY29uc3Qge1xuICAgICAgICBtYXBTdGF0ZSxcbiAgICAgICAgaG92ZXJJbmZvLFxuICAgICAgICBjbGlja2VkLFxuICAgICAgICBkYXRhc2V0cyxcbiAgICAgICAgaW50ZXJhY3Rpb25Db25maWcsXG4gICAgICAgIGxheWVycyxcbiAgICAgICAgbWFwTGF5ZXJzXG4gICAgICB9ID0gdGhpcy5wcm9wcztcblxuICAgICAgLy8gaWYgY2xpY2tlZCBzb21ldGhpbmcsIGlnbm9yZSBob3ZlciBiZWhhdmlvclxuICAgICAgY29uc3Qgb2JqZWN0SW5mbyA9IGNsaWNrZWQgfHwgaG92ZXJJbmZvO1xuICAgICAgaWYgKFxuICAgICAgICAhaW50ZXJhY3Rpb25Db25maWcudG9vbHRpcC5lbmFibGVkIHx8XG4gICAgICAgICFvYmplY3RJbmZvIHx8XG4gICAgICAgICFvYmplY3RJbmZvLnBpY2tlZFxuICAgICAgKSB7XG4gICAgICAgIC8vIG5vdGhpbmcgaG92ZXJlZFxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qge2xuZ0xhdCwgb2JqZWN0LCBsYXllcjogb3ZlcmxheX0gPSBvYmplY3RJbmZvO1xuXG4gICAgICAvLyBkZWNrZ2wgbGF5ZXIgdG8ga2VwbGVyLWdsIGxheWVyXG4gICAgICBjb25zdCBsYXllciA9IGxheWVyc1tvdmVybGF5LnByb3BzLmlkeF07XG5cbiAgICAgIGlmIChcbiAgICAgICAgIWxheWVyIHx8XG4gICAgICAgICFsYXllci5jb25maWcuaXNWaXNpYmxlIHx8XG4gICAgICAgICFvYmplY3QgfHxcbiAgICAgICAgIWxheWVyLmdldEhvdmVyRGF0YSB8fFxuICAgICAgICAobWFwTGF5ZXJzICYmICFtYXBMYXllcnNbbGF5ZXIuaWRdLmlzVmlzaWJsZSlcbiAgICAgICkge1xuICAgICAgICAvLyBsYXllciBpcyBub3QgdmlzaWJsZVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qge1xuICAgICAgICBjb25maWc6IHtkYXRhSWR9XG4gICAgICB9ID0gbGF5ZXI7XG4gICAgICBjb25zdCB7YWxsRGF0YSwgZmllbGRzfSA9IGRhdGFzZXRzW2RhdGFJZF07XG4gICAgICBjb25zdCBkYXRhID0gbGF5ZXIuZ2V0SG92ZXJEYXRhKG9iamVjdCwgYWxsRGF0YSk7XG5cbiAgICAgIC8vIHByb2plY3QgbG5nbGF0IHRvIHNjcmVlbiBzbyB0aGF0IHRvb2x0aXAgZm9sbG93cyB0aGUgb2JqZWN0IG9uIHpvb21cbiAgICAgIGNvbnN0IHt2aWV3cG9ydH0gPSBvdmVybGF5LmNvbnRleHQ7XG4gICAgICBjb25zdCB7eCwgeX0gPSB0aGlzLl9nZXRIb3ZlclhZKHZpZXdwb3J0LCBsbmdMYXQpIHx8IG9iamVjdEluZm87XG5cbiAgICAgIGNvbnN0IHBvcG92ZXJQcm9wcyA9IHtcbiAgICAgICAgZGF0YSxcbiAgICAgICAgZmllbGRzLFxuICAgICAgICBmaWVsZHNUb1Nob3c6IGludGVyYWN0aW9uQ29uZmlnLnRvb2x0aXAuY29uZmlnLmZpZWxkc1RvU2hvd1tkYXRhSWRdLFxuICAgICAgICBsYXllcixcbiAgICAgICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgICAgICB4LFxuICAgICAgICB5LFxuICAgICAgICBmcmVlemVkOiBCb29sZWFuKGNsaWNrZWQpLFxuICAgICAgICBvbkNsb3NlOiB0aGlzLl9vbkNsb3NlTWFwUG9wb3ZlcixcbiAgICAgICAgbWFwU3RhdGVcbiAgICAgIH07XG4gICAgICAvLyBjb25zb2xlLmxvZygnUG9wb3ZlclByb3BzJywgcG9wb3ZlclByb3BzKTtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIDxkaXY+XG4gICAgICAgICAgPE1hcFBvcG92ZXIgey4uLnBvcG92ZXJQcm9wc30gLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICApO1xuICAgIH1cblxuICAgIC8qIGVzbGludC1lbmFibGUgY29tcGxleGl0eSAqL1xuXG4gICAgX2dldEhvdmVyWFkodmlld3BvcnQsIGxuZ0xhdCkge1xuICAgICAgY29uc3Qgc2NyZWVuQ29vcmQgPVxuICAgICAgICAhdmlld3BvcnQgfHwgIWxuZ0xhdCA/IG51bGwgOiB2aWV3cG9ydC5wcm9qZWN0KGxuZ0xhdCk7XG5cbiAgICAgIHJldHVybiBzY3JlZW5Db29yZCAmJiB7eDogc2NyZWVuQ29vcmRbMF0sIHk6IHNjcmVlbkNvb3JkWzFdfTtcbiAgICB9XG5cbiAgICBfc2hvdWxkUmVuZGVyTGF5ZXIobGF5ZXIsIGRhdGEsIG1hcExheWVycykge1xuICAgICAgY29uc3QgaXNBdmFpbGFibGVBbmRWaXNpYmxlID1cbiAgICAgICAgIShtYXBMYXllcnMgJiYgbWFwTGF5ZXJzW2xheWVyLmlkXSkgfHwgbWFwTGF5ZXJzW2xheWVyLmlkXS5pc1Zpc2libGU7XG4gICAgICByZXR1cm4gbGF5ZXIuc2hvdWxkUmVuZGVyTGF5ZXIoZGF0YSkgJiYgaXNBdmFpbGFibGVBbmRWaXNpYmxlO1xuICAgIH1cblxuICAgIF9yZW5kZXJMYXllciA9IChvdmVybGF5cywgaWR4KSA9PiB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGxheWVycyxcbiAgICAgICAgbGF5ZXJEYXRhLFxuICAgICAgICBob3ZlckluZm8sXG4gICAgICAgIGNsaWNrZWQsXG4gICAgICAgIG1hcExheWVycyxcbiAgICAgICAgbWFwU3RhdGUsXG4gICAgICAgIGludGVyYWN0aW9uQ29uZmlnXG4gICAgICB9ID0gdGhpcy5wcm9wcztcbiAgICAgIGNvbnN0IHttb3VzZVBvc2l0aW9ufSA9IHRoaXMuc3RhdGU7XG4gICAgICBjb25zdCBsYXllciA9IGxheWVyc1tpZHhdO1xuICAgICAgY29uc3QgZGF0YSA9IGxheWVyRGF0YVtpZHhdO1xuXG4gICAgICBjb25zdCBsYXllckludGVyYWN0aW9uID0ge1xuICAgICAgICBtb3VzZVBvc2l0aW9uXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBvYmplY3RIb3ZlcmVkID0gY2xpY2tlZCB8fCBob3ZlckluZm87XG4gICAgICBjb25zdCBsYXllckNhbGxiYWNrcyA9IHtcbiAgICAgICAgb25TZXRMYXllckRvbWFpbjogdmFsID0+IHRoaXMuX29uTGF5ZXJTZXREb21haW4oaWR4LCB2YWwpXG4gICAgICB9O1xuXG4gICAgICBpZiAoIXRoaXMuX3Nob3VsZFJlbmRlckxheWVyKGxheWVyLCBkYXRhLCBtYXBMYXllcnMpKSB7XG4gICAgICAgIHJldHVybiBvdmVybGF5cztcbiAgICAgIH1cblxuICAgICAgbGV0IGxheWVyT3ZlcmxheSA9IFtdO1xuXG4gICAgICAvLyBMYXllciBpcyBMYXllciBjbGFzc1xuICAgICAgaWYgKHR5cGVvZiBsYXllci5yZW5kZXJMYXllciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBsYXllck92ZXJsYXkgPSBsYXllci5yZW5kZXJMYXllcih7XG4gICAgICAgICAgZGF0YSxcbiAgICAgICAgICBpZHgsXG4gICAgICAgICAgbGF5ZXJJbnRlcmFjdGlvbixcbiAgICAgICAgICBvYmplY3RIb3ZlcmVkLFxuICAgICAgICAgIG1hcFN0YXRlLFxuICAgICAgICAgIGludGVyYWN0aW9uQ29uZmlnLFxuICAgICAgICAgIGxheWVyQ2FsbGJhY2tzXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAobGF5ZXJPdmVybGF5Lmxlbmd0aCkge1xuICAgICAgICBvdmVybGF5cyA9IG92ZXJsYXlzLmNvbmNhdChsYXllck92ZX