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
JavaScript
"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