kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
419 lines (337 loc) • 41.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.keplerGlChildDeps = undefined;
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _taggedTemplateLiteral2 = require('babel-runtime/helpers/taggedTemplateLiteral');
var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2);
var _templateObject = (0, _taggedTemplateLiteral3.default)(['\n font-family: ff-clan-web-pro, \'Helvetica Neue\', Helvetica, sans-serif;\n font-weight: 400;\n font-size: 0.875em;\n line-height: 1.71429;\n\n *,\n *:before,\n *:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n }\n\n ul {\n margin: 0;\n padding: 0;\n }\n\n li {\n margin: 0;\n }\n\n a {\n text-decoration: none;\n color: ', ';\n }\n'], ['\n font-family: ff-clan-web-pro, \'Helvetica Neue\', Helvetica, sans-serif;\n font-weight: 400;\n font-size: 0.875em;\n line-height: 1.71429;\n\n *,\n *:before,\n *:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n }\n\n ul {\n margin: 0;\n padding: 0;\n }\n\n li {\n margin: 0;\n }\n\n a {\n text-decoration: none;\n color: ', ';\n }\n']); // Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _window = require('global/window');
var _redux = require('redux');
var _d3Request = require('d3-request');
var _styledComponents = require('styled-components');
var _styledComponents2 = _interopRequireDefault(_styledComponents);
var _keplerglConnect = require('../connect/keplergl-connect');
var _visStateActions = require('../actions/vis-state-actions');
var VisStateActions = _interopRequireWildcard(_visStateActions);
var _mapStateActions = require('../actions/map-state-actions');
var MapStateActions = _interopRequireWildcard(_mapStateActions);
var _mapStyleActions = require('../actions/map-style-actions');
var MapStyleActions = _interopRequireWildcard(_mapStyleActions);
var _uiStateActions = require('../actions/ui-state-actions');
var UIStateActions = _interopRequireWildcard(_uiStateActions);
var _defaultSettings = require('../constants/default-settings');
var _sidePanel = require('./side-panel');
var _sidePanel2 = _interopRequireDefault(_sidePanel);
var _mapContainer = require('./map-container');
var _mapContainer2 = _interopRequireDefault(_mapContainer);
var _bottomWidget = require('./bottom-widget');
var _bottomWidget2 = _interopRequireDefault(_bottomWidget);
var _modalContainer = require('./modal-container');
var _modalContainer2 = _interopRequireDefault(_modalContainer);
var _plotContainer = require('./plot-container');
var _plotContainer2 = _interopRequireDefault(_plotContainer);
var _utils = require('../utils/utils');
var _base = require('../styles/base');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var GlobalStyle = _styledComponents2.default.div(_templateObject, function (props) {
return props.theme.labelColor;
});
var keplerGlChildDeps = exports.keplerGlChildDeps = [].concat((0, _toConsumableArray3.default)(_bottomWidget2.default.deps), (0, _toConsumableArray3.default)(_sidePanel2.default.deps), (0, _toConsumableArray3.default)(_modalContainer2.default.deps), (0, _toConsumableArray3.default)(_mapContainer2.default.deps));
KeplerGlFactory.deps = [_bottomWidget2.default, _mapContainer2.default, _modalContainer2.default, _sidePanel2.default, _plotContainer2.default];
function KeplerGlFactory(BottomWidget, MapContainer, ModalWrapper, SidePanel, PlotContainer) {
var _class, _temp2;
var KeplerGL = (_temp2 = _class = function (_Component) {
(0, _inherits3.default)(KeplerGL, _Component);
function KeplerGL() {
var _ref;
var _temp, _this, _ret;
(0, _classCallCheck3.default)(this, KeplerGL);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = KeplerGL.__proto__ || Object.getPrototypeOf(KeplerGL)).call.apply(_ref, [this].concat(args))), _this), _this._loadMapStyle = function () {
var defaultStyles = Object.values(_this.props.mapStyle.mapStyles);
// add id to custom map styles if not given
var customeStyles = (_this.props.mapStyles || []).map(function (ms) {
return (0, _extends3.default)({}, ms, {
id: ms.id || (0, _utils.generateHashId)()
});
});
[].concat((0, _toConsumableArray3.default)(customeStyles), (0, _toConsumableArray3.default)(defaultStyles)).forEach(function (style) {
if (style.style) {
_this.props.mapStyleActions.loadMapStyles((0, _defineProperty3.default)({}, style.id, style));
} else {
_this._requestMapStyle(style);
}
});
}, _this._requestMapStyle = function (mapStyle) {
var url = mapStyle.url,
id = mapStyle.id;
(0, _d3Request.json)(url, function (error, result) {
if (error) {
_window.console.warn('Error loading map style ' + mapStyle.url);
} else {
_this.props.mapStyleActions.loadMapStyles((0, _defineProperty3.default)({}, id, (0, _extends3.default)({}, mapStyle, { style: result })));
}
});
}, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
}
(0, _createClass3.default)(KeplerGL, [{
key: 'componentWillMount',
value: function componentWillMount() {
this._loadMapStyle(this.props.mapStyles);
this._handleResize(this.props);
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
if (
// if dimension props has changed
this.props.height !== nextProps.height || this.props.width !== nextProps.width ||
// react-map-gl will dispatch updateViewport after this._handleResize is called
// here we check if this.props.mapState.height is sync with props.height
nextProps.height !== this.props.mapState.height) {
this._handleResize(nextProps);
}
}
}, {
key: '_handleResize',
value: function _handleResize(_ref2) {
var width = _ref2.width,
height = _ref2.height;
if (!Number.isFinite(width) || !Number.isFinite(height)) {
_window.console.warn('width and height is required');
return;
}
this.props.mapStateActions.updateMap({
width: width / (1 + Number(this.props.mapState.isSplit)),
height: height
});
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
var _props = this.props,
id = _props.id,
appName = _props.appName,
version = _props.version,
onSaveMap = _props.onSaveMap,
width = _props.width,
height = _props.height,
mapboxApiAccessToken = _props.mapboxApiAccessToken,
mapStyle = _props.mapStyle,
mapState = _props.mapState,
uiState = _props.uiState,
visState = _props.visState,
visStateActions = _props.visStateActions,
mapStateActions = _props.mapStateActions,
mapStyleActions = _props.mapStyleActions,
uiStateActions = _props.uiStateActions;
var filters = visState.filters,
layers = visState.layers,
splitMaps = visState.splitMaps,
layerOrder = visState.layerOrder,
layerBlending = visState.layerBlending,
layerClasses = visState.layerClasses,
interactionConfig = visState.interactionConfig,
datasets = visState.datasets,
layerData = visState.layerData,
hoverInfo = visState.hoverInfo,
clicked = visState.clicked;
var sideFields = {
appName: appName,
version: version,
datasets: datasets,
filters: filters,
layers: layers,
layerOrder: layerOrder,
layerClasses: layerClasses,
interactionConfig: interactionConfig,
mapStyle: mapStyle,
layerBlending: layerBlending,
onSaveMap: onSaveMap,
uiState: uiState,
mapStyleActions: mapStyleActions,
visStateActions: visStateActions,
uiStateActions: uiStateActions,
width: _defaultSettings.DIMENSIONS.sidePanel.width
};
var mapFields = {
datasets: datasets,
mapboxApiAccessToken: mapboxApiAccessToken,
mapState: mapState,
mapStyle: mapStyle,
mapControls: uiState.mapControls,
layers: layers,
layerOrder: layerOrder,
layerData: layerData,
layerBlending: layerBlending,
interactionConfig: interactionConfig,
hoverInfo: hoverInfo,
clicked: clicked,
toggleMapControl: uiStateActions.toggleMapControl,
uiStateActions: uiStateActions,
visStateActions: visStateActions,
mapStateActions: mapStateActions
};
var isSplit = splitMaps && splitMaps.length > 1;
var containerW = mapState.width * (Number(isSplit) + 1);
var mapContainers = !isSplit ? [_react2.default.createElement(MapContainer, (0, _extends3.default)({
key: 0,
index: 0
}, mapFields, {
mapLayers: isSplit ? splitMaps[0].layers : null
}))] : splitMaps.map(function (settings, index) {
return _react2.default.createElement(MapContainer, (0, _extends3.default)({
key: index,
index: index
}, mapFields, {
mapLayers: splitMaps[index].layers
}));
});
var isExporting = uiState.currentModal === _defaultSettings.EXPORT_IMAGE_ID;
return _react2.default.createElement(
_styledComponents.ThemeProvider,
{ theme: _base.theme },
_react2.default.createElement(
GlobalStyle,
{
style: {
position: 'relative',
width: width + 'px',
height: height + 'px'
},
className: 'kepler-gl',
id: 'kepler-gl__' + id,
innerRef: function innerRef(node) {
_this2.root = node;
}
},
!uiState.readOnly && _react2.default.createElement(SidePanel, sideFields),
_react2.default.createElement(
'div',
{ className: 'maps', style: { display: 'flex' } },
mapContainers
),
isExporting && _react2.default.createElement(PlotContainer, {
width: width,
height: height,
exportImageSetting: uiState.exportImage,
mapFields: mapFields,
startExportingImage: uiStateActions.startExportingImage,
setExportImageDataUri: uiStateActions.setExportImageDataUri
}),
_react2.default.createElement(BottomWidget, {
filters: filters,
datasets: datasets,
uiState: uiState,
visStateActions: visStateActions,
sidePanelWidth: _defaultSettings.DIMENSIONS.sidePanel.width + _defaultSettings.DIMENSIONS.sidePanel.margin.left,
containerW: containerW
}),
_react2.default.createElement(ModalWrapper, {
mapStyle: mapStyle,
visState: visState,
mapState: mapState,
uiState: uiState,
mapboxApiAccessToken: mapboxApiAccessToken,
visStateActions: visStateActions,
uiStateActions: uiStateActions,
mapStyleActions: mapStyleActions,
rootNode: this.root,
containerW: containerW,
containerH: mapState.height
})
)
);
}
}]);
return KeplerGL;
}(_react.Component), _class.defaultProps = {
mapStyles: [],
width: 800,
height: 800,
appName: _defaultSettings.KEPLER_GL_NAME,
version: _defaultSettings.KEPLER_GL_VERSION
}, _temp2);
return (0, _keplerglConnect.connect)(mapStateToProps, mapDispatchToProps)(KeplerGL);
}
function mapStateToProps(state, props) {
return (0, _extends3.default)({}, props, {
visState: state.visState,
mapStyle: state.mapStyle,
mapState: state.mapState,
uiState: state.uiState
});
}
function mapDispatchToProps(dispatch, ownProps) {
var userActions = ownProps.actions || {};
var _map = [VisStateActions, MapStateActions, MapStyleActions, UIStateActions].map(function (actions) {
return (0, _redux.bindActionCreators)(mergeActions(actions, userActions), dispatch);
}),
_map2 = (0, _slicedToArray3.default)(_map, 4),
visStateActions = _map2[0],
mapStateActions = _map2[1],
mapStyleActions = _map2[2],
uiStateActions = _map2[3];
return {
visStateActions: visStateActions,
mapStateActions: mapStateActions,
mapStyleActions: mapStyleActions,
uiStateActions: uiStateActions,
dispatch: dispatch
};
}
/**
* Override default maps-gl actions with user defined actions using the same key
*/
function mergeActions(actions, userActions) {
var overrides = {};
for (var key in userActions) {
if (userActions.hasOwnProperty(key) && actions.hasOwnProperty(key)) {
overrides[key] = userActions[key];
}
}
return (0, _extends3.default)({}, actions, overrides);
}
exports.default = KeplerGlFactory;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21wb25lbnRzL2tlcGxlci1nbC5qcyJdLCJuYW1lcyI6WyJWaXNTdGF0ZUFjdGlvbnMiLCJNYXBTdGF0ZUFjdGlvbnMiLCJNYXBTdHlsZUFjdGlvbnMiLCJVSVN0YXRlQWN0aW9ucyIsIkdsb2JhbFN0eWxlIiwic3R5bGVkIiwiZGl2IiwicHJvcHMiLCJ0aGVtZSIsImxhYmVsQ29sb3IiLCJrZXBsZXJHbENoaWxkRGVwcyIsIkJvdHRvbVdpZGdldEZhY3RvcnkiLCJkZXBzIiwiU2lkZVBhbmVsRmFjdG9yeSIsIk1vZGFsQ29udGFpbmVyRmFjdG9yeSIsIk1hcENvbnRhaW5lckZhY3RvcnkiLCJLZXBsZXJHbEZhY3RvcnkiLCJQbG90Q29udGFpbmVyRmFjdG9yeSIsIkJvdHRvbVdpZGdldCIsIk1hcENvbnRhaW5lciIsIk1vZGFsV3JhcHBlciIsIlNpZGVQYW5lbCIsIlBsb3RDb250YWluZXIiLCJLZXBsZXJHTCIsIl9sb2FkTWFwU3R5bGUiLCJkZWZhdWx0U3R5bGVzIiwiT2JqZWN0IiwidmFsdWVzIiwibWFwU3R5bGUiLCJtYXBTdHlsZXMiLCJjdXN0b21lU3R5bGVzIiwibWFwIiwibXMiLCJpZCIsImZvckVhY2giLCJzdHlsZSIsIm1hcFN0eWxlQWN0aW9ucyIsImxvYWRNYXBTdHlsZXMiLCJfcmVxdWVzdE1hcFN0eWxlIiwidXJsIiwiZXJyb3IiLCJyZXN1bHQiLCJDb25zb2xlIiwid2FybiIsIl9oYW5kbGVSZXNpemUiLCJuZXh0UHJvcHMiLCJoZWlnaHQiLCJ3aWR0aCIsIm1hcFN0YXRlIiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJtYXBTdGF0ZUFjdGlvbnMiLCJ1cGRhdGVNYXAiLCJpc1NwbGl0IiwiYXBwTmFtZSIsInZlcnNpb24iLCJvblNhdmVNYXAiLCJtYXBib3hBcGlBY2Nlc3NUb2tlbiIsInVpU3RhdGUiLCJ2aXNTdGF0ZSIsInZpc1N0YXRlQWN0aW9ucyIsInVpU3RhdGVBY3Rpb25zIiwiZmlsdGVycyIsImxheWVycyIsInNwbGl0TWFwcyIsImxheWVyT3JkZXIiLCJsYXllckJsZW5kaW5nIiwibGF5ZXJDbGFzc2VzIiwiaW50ZXJhY3Rpb25Db25maWciLCJkYXRhc2V0cyIsImxheWVyRGF0YSIsImhvdmVySW5mbyIsImNsaWNrZWQiLCJzaWRlRmllbGRzIiwiRElNRU5TSU9OUyIsInNpZGVQYW5lbCIsIm1hcEZpZWxkcyIsIm1hcENvbnRyb2xzIiwidG9nZ2xlTWFwQ29udHJvbCIsImxlbmd0aCIsImNvbnRhaW5lclciLCJtYXBDb250YWluZXJzIiwic2V0dGluZ3MiLCJpbmRleCIsImlzRXhwb3J0aW5nIiwiY3VycmVudE1vZGFsIiwiRVhQT1JUX0lNQUdFX0lEIiwicG9zaXRpb24iLCJyb290Iiwibm9kZSIsInJlYWRPbmx5IiwiZGlzcGxheSIsImV4cG9ydEltYWdlIiwic3RhcnRFeHBvcnRpbmdJbWFnZSIsInNldEV4cG9ydEltYWdlRGF0YVVyaSIsIm1hcmdpbiIsImxlZnQiLCJDb21wb25lbnQiLCJkZWZhdWx0UHJvcHMiLCJLRVBMRVJfR0xfTkFNRSIsIktFUExFUl9HTF9WRVJTSU9OIiwibWFwU3RhdGVUb1Byb3BzIiwibWFwRGlzcGF0Y2hUb1Byb3BzIiwic3RhdGUiLCJkaXNwYXRjaCIsIm93blByb3BzIiwidXNlckFjdGlvbnMiLCJhY3Rpb25zIiwibWVyZ2VBY3Rpb25zIiwib3ZlcnJpZGVzIiwia2V5IiwiaGFzT3duUHJvcGVydHkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7MDVCQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7QUFFQTs7SUFBWUEsZTs7QUFDWjs7SUFBWUMsZTs7QUFDWjs7SUFBWUMsZTs7QUFDWjs7SUFBWUMsYzs7QUFFWjs7QUFH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UUFGbEI7QUFHRS9CLGNBQVUyRSxNQUFNM0UsUUFIbEI7QUFJRW9CLGNBQVV1RCxNQUFNdkQsUUFKbEI7QUFLRVUsYUFBUzZDLE1BQU03QztBQUxqQjtBQU9EOztBQUVELFNBQVM0QyxrQkFBVCxDQUE0QkUsUUFBNUIsRUFBc0NDLFFBQXRDLEVBQWdEO0FBQzlDLE1BQU1DLGNBQWNELFNBQVNFLE9BQVQsSUFBb0IsRUFBeEM7O0FBRDhDLGFBUTFDLENBQ0YzRyxlQURFLEVBRUZDLGVBRkUsRUFHRkMsZUFIRSxFQUlGQyxjQUpFLEVBS0Y0QixHQUxFLENBS0U7QUFBQSxXQUNKLCtCQUFtQjZFLGFBQWFELE9BQWIsRUFBc0JELFdBQXRCLENBQW5CLEVBQXVERixRQUF2RCxDQURJO0FBQUEsR0FMRixDQVIwQztBQUFBO0FBQUEsTUFJNUM1QyxlQUo0QztBQUFBLE1BSzVDVCxlQUw0QztBQUFBLE1BTTVDZixlQU40QztBQUFBLE1BTzVDeUIsY0FQNEM7O0FBaUI5QyxTQUFPO0FBQ0xELG9DQURLO0FBRUxULG9DQUZLO0FBR0xmLG9DQUhLO0FBSUx5QixrQ0FKSztBQUtMMkM7QUFMSyxHQUFQO0FBT0Q7O0FBRUQ7OztBQUdBLFNBQVNJLFlBQVQsQ0FBc0JELE9BQXRCLEVBQStCRCxXQUEvQixFQUE0QztBQUMxQyxNQUFNRyxZQUFZLEVBQWxCO0FBQ0EsT0FBSyxJQUFNQyxHQUFYLElBQWtCSixXQUFsQixFQUErQjtBQUM3QixRQUFJQSxZQUFZSyxjQUFaLENBQTJCRCxHQUEzQixLQUFtQ0gsUUFBUUksY0FBUixDQUF1QkQsR0FBdkIsQ0FBdkMsRUFBb0U7QUFDbEVELGdCQUFVQyxHQUFWLElBQWlCSixZQUFZSSxHQUFaLENBQWpCO0FBQ0Q7QUFDRjs7QUFFRCxvQ0FBV0gsT0FBWCxFQUF1QkUsU0FBdkI7QUFDRDs7a0JBRWM3RixlIiwiZmlsZSI6ImtlcGxlci1nbC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAxOCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBSZWFjdCwge0NvbXBvbmVudH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHtjb25zb2xlIGFzIENvbnNvbGV9IGZyb20gJ2dsb2JhbC93aW5kb3cnO1xuaW1wb3J0IHtiaW5kQWN0aW9uQ3JlYXRvcnN9IGZyb20gJ3JlZHV4JztcbmltcG9ydCB7anNvbiBhcyByZXF1ZXN0SnNvbn0gZnJvbSAnZDMtcmVxdWVzdCc7XG5pbXBvcnQgc3R5bGVkLCB7VGhlbWVQcm92aWRlcn0gIGZyb20gJ3N0eWxlZC1jb21wb25lbnRzJztcbmltcG9ydCB7Y29ubmVjdCBhcyBrZXBsZXJHbENvbm5lY3R9IGZyb20gJy4uL2Nvbm5lY3Qva2VwbGVyZ2wtY29ubmVjdCc7XG5cbmltcG9ydCAqIGFzIFZpc1N0YXRlQWN0aW9ucyBmcm9tICdhY3Rpb25zL3Zpcy1zdGF0ZS1hY3Rpb25zJztcbmltcG9ydCAqIGFzIE1hcFN0YXRlQWN0aW9ucyBmcm9tICdhY3Rpb25zL21hcC1zdGF0ZS1hY3Rpb25zJztcbmltcG9ydCAqIGFzIE1hcFN0eWxlQWN0aW9ucyBmcm9tICdhY3Rpb25zL21hcC1zdHlsZS1hY3Rpb25zJztcbmltcG9ydCAqIGFzIFVJU3RhdGVBY3Rpb25zIGZyb20gJ2FjdGlvbnMvdWktc3RhdGUtYWN0aW9ucyc7XG5cbmltcG9ydCB7RVhQT1JUX0lNQUdFX0lELCBESU1FTlNJT05TLFxuICBLRVBMRVJfR0xfTkFNRSwgS0VQTEVSX0dMX1ZFUlNJT059IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcblxuaW1wb3J0IFNpZGVQYW5lbEZhY3RvcnkgZnJvbSAnLi9zaWRlLXBhbmVsJztcbmltcG9ydCBNYXBDb250YWluZXJGYWN0b3J5IGZyb20gJy4vbWFwLWNvbnRhaW5lcic7XG5pbXBvcnQgQm90dG9tV2lkZ2V0RmFjdG9yeSBmcm9tICcuL2JvdHRvbS13aWRnZXQnO1xuaW1wb3J0IE1vZGFsQ29udGFpbmVyRmFjdG9yeSBmcm9tICcuL21vZGFsLWNvbnRhaW5lcic7XG5pbXBvcnQgUGxvdENvbnRhaW5lckZhY3RvcnkgZnJvbSAnLi9wbG90LWNvbnRhaW5lcic7XG5cbmltcG9ydCB7Z2VuZXJhdGVIYXNoSWR9IGZyb20gJ3V0aWxzL3V0aWxzJztcblxuaW1wb3J0IHt0aGVtZX0gZnJvbSAnc3R5bGVzL2Jhc2UnO1xuXG5jb25zdCBHbG9iYWxTdHlsZSA9IHN0eWxlZC5kaXZgXG4gIGZvbnQtZmFtaWx5OiBmZi1jbGFuLXdlYi1wcm8sICdIZWx2ZXRpY2EgTmV1ZScsIEhlbHZldGljYSwgc2Fucy1zZXJpZjtcbiAgZm9udC13ZWlnaHQ6IDQwMDtcbiAgZm9udC1zaXplOiAwLjg3NWVtO1xuICBsaW5lLWhlaWdodDogMS43MTQyOTtcblxuICAqLFxuICAqOmJlZm9yZSxcbiAgKjphZnRlciB7XG4gICAgLXdlYmtpdC1ib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAgIC1tb3otYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICB9XG5cbiAgdWwge1xuICAgIG1hcmdpbjogMDtcbiAgICBwYWRkaW5nOiAwO1xuICB9XG5cbiAgbGkge1xuICAgIG1hcmdpbjogMDtcbiAgfVxuXG4gIGEge1xuICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbiAgICBjb2xvcjogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5sYWJlbENvbG9yfTtcbiAgfVxuYDtcblxuZXhwb3J0IGNvbnN0IGtlcGxlckdsQ2hpbGREZXBzID0gW1xuICAuLi5Cb3R0b21XaWRnZXRGYWN0b3J5LmRlcHMsXG4gIC4uLlNpZGVQYW5lbEZhY3RvcnkuZGVwcyxcbiAgLi4uTW9kYWxDb250YWluZXJGYWN0b3J5LmRlcHMsXG4gIC4uLk1hcENvbnRhaW5lckZhY3RvcnkuZGVwc1xuXTtcblxuS2VwbGVyR2xGYWN0b3J5LmRlcHMgPSBbXG4gIEJvdHRvbVdpZGdldEZhY3RvcnksXG4gIE1hcENvbnRhaW5lckZhY3RvcnksXG4gIE1vZGFsQ29udGFpbmVyRmFjdG9yeSxcbiAgU2lkZVBhbmVsRmFjdG9yeSxcbiAgUGxvdENvbnRhaW5lckZhY3Rvcnlcbl07XG5cbmZ1bmN0aW9uIEtlcGxlckdsRmFjdG9yeShcbiAgQm90dG9tV2lkZ2V0LFxuICBNYXBDb250YWluZXIsXG4gIE1vZGFsV3JhcHBlcixcbiAgU2lkZVBhbmVsLFxuICBQbG90Q29udGFpbmVyXG4pIHtcbiAgY2xhc3MgS2VwbGVyR0wgZXh0ZW5kcyBDb21wb25lbnQge1xuICAgIHN0YXRpYyBkZWZhdWx0UHJvcHMgPSB7XG4gICAgICBtYXBTdHlsZXM6IFtdLFxuICAgICAgd2lkdGg6IDgwMCxcbiAgICAgIGhlaWdodDogODAwLFxuICAgICAgYXBwTmFtZTogS0VQTEVSX0dMX05BTUUsXG4gICAgICB2ZXJzaW9uOiBLRVBMRVJfR0xfVkVSU0lPTlxuICAgIH07XG5cbiAgICBjb21wb25lbnRXaWxsTW91bnQoKSB7XG4gICAgICB0aGlzLl9sb2FkTWFwU3R5bGUodGhpcy5wcm9wcy5tYXBTdHlsZXMpO1xuICAgICAgdGhpcy5faGFuZGxlUmVzaXplKHRoaXMucHJvcHMpO1xuICAgIH1cblxuICAgIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHMobmV4dFByb3BzKSB7XG4gICAgICBpZiAoXG4gICAgICAgIC8vIGlmIGRpbWVuc2lvbiBwcm9wcyBoYXMgY2hhbmdlZFxuICAgICAgICB0aGlzLnByb3BzLmhlaWdodCAhPT0gbmV4dFByb3BzLmhlaWdodCB8fFxuICAgICAgICB0aGlzLnByb3BzLndpZHRoICE9PSBuZXh0UHJvcHMud2lkdGggfHxcbiAgICAgICAgLy8gcmVhY3QtbWFwLWdsIHdpbGwgZGlzcGF0Y2ggdXBkYXRlVmlld3BvcnQgYWZ0ZXIgdGhpcy5faGFuZGxlUmVzaXplIGlzIGNhbGxlZFxuICAgICAgICAvLyBoZXJlIHdlIGNoZWNrIGlmIHRoaXMucHJvcHMubWFwU3RhdGUuaGVpZ2h0IGlzIHN5bmMgd2l0aCBwcm9wcy5oZWlnaHRcbiAgICAgICAgbmV4dFByb3BzLmhlaWdodCAhPT0gdGhpcy5wcm9wcy5tYXBTdGF0ZS5oZWlnaHRcbiAgICAgICkge1xuICAgICAgICB0aGlzLl9oYW5kbGVSZXNpemUobmV4dFByb3BzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfaGFuZGxlUmVzaXplKHt3aWR0aCwgaGVpZ2h0fSkge1xuICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUod2lkdGgpIHx8ICFOdW1iZXIuaXNGaW5pdGUoaGVpZ2h0KSkge1xuICAgICAgICBDb25zb2xlLndhcm4oJ3dpZHRoIGFuZCBoZWlnaHQgaXMgcmVxdWlyZWQnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5wcm9wcy5tYXBTdGF0ZUFjdGlvbnMudXBkYXRlTWFwKHtcbiAgICAgICAgd2lkdGg6IHdpZHRoIC8gKDEgKyBOdW1iZXIodGhpcy5wcm9wcy5tYXBTdGF0ZS5pc1NwbGl0KSksXG4gICAgICAgIGhlaWdodFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2xvYWRNYXBTdHlsZSA9ICgpID0+IHtcbiAgICAgIGNvbnN0IGRlZmF1bHRTdHlsZXMgPSBPYmplY3QudmFsdWVzKHRoaXMucHJvcHMubWFwU3R5bGUubWFwU3R5bGVzKTtcbiAgICAgIC8vIGFkZCBpZCB0byBjdXN0b20gbWFwIHN0eWxlcyBpZiBub3QgZ2l2ZW5cbiAgICAgIGNvbnN0IGN1c3RvbWVTdHlsZXMgPSAodGhpcy5wcm9wcy5tYXBTdHlsZXMgfHwgW10pLm1hcChtcyA9PiAoe1xuICAgICAgICAuLi5tcyxcbiAgICAgICAgaWQ6IG1zLmlkIHx8IGdlbmVyYXRlSGFzaElkKClcbiAgICAgIH0pKTtcblxuICAgICAgWy4uLmN1c3RvbWVTdHlsZXMsIC4uLmRlZmF1bHRTdHlsZXNdLmZvckVhY2goXG4gICAgICAgIHN0eWxlID0+IHtcbiAgICAgICAgICBpZiAoc3R5bGUuc3R5bGUpIHtcbiAgICAgICAgICAgIHRoaXMucHJvcHMubWFwU3R5bGVBY3Rpb25zLmxvYWRNYXBTdHlsZXMoe1xuICAgICAgICAgICAgICBbc3R5bGUuaWRdOiBzdHlsZVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fcmVxdWVzdE1hcFN0eWxlKHN0eWxlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfTtcblxuICAgIF9yZXF1ZXN0TWFwU3R5bGUgPSAobWFwU3R5bGUpID0+IHtcbiAgICAgIGNvbnN0IHt1cmwsIGlkfSA9IG1hcFN0eWxlO1xuICAgICAgcmVxdWVzdEpzb24odXJsLCAoZXJyb3IsIHJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICBDb25zb2xlLndhcm4oYEVycm9yIGxvYWRpbmcgbWFwIHN0eWxlICR7bWFwU3R5bGUudXJsfWApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMucHJvcHMubWFwU3R5bGVBY3Rpb25zLmxvYWRNYXBTdHlsZXMoe1xuICAgICAgICAgICAgW2lkXTogey4uLm1hcFN0eWxlLCBzdHlsZTogcmVzdWx0fVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgcmVuZGVyKCkge1xuICAgICAgY29uc3Qge1xuICAgICAgICAvLyBwcm9wc1xuICAgICAgICBpZCxcbiAgICAgICAgYXBwTmFtZSxcbiAgICAgICAgdmVyc2lvbixcbiAgICAgICAgb25TYXZlTWFwLFxuICAgICAgICB3aWR0aCxcbiAgICAgICAgaGVpZ2h0LFxuICAgICAgICBtYXBib3hBcGlBY2Nlc3NUb2tlbixcblxuICAgICAgICAvLyByZWR1eCBzdGF0ZVxuICAgICAgICBtYXBTdHlsZSxcbiAgICAgICAgbWFwU3RhdGUsXG4gICAgICAgIHVpU3RhdGUsXG4gICAgICAgIHZpc1N0YXRlLFxuXG4gICAgICAgIC8vIGFjdGlvbnMsXG4gICAgICAgIHZpc1N0YXRlQWN0aW9ucyxcbiAgICAgICAgbWFwU3RhdGVBY3Rpb25zLFxuICAgICAgICBtYXBTdHlsZUFjdGlvbnMsXG4gICAgICAgIHVpU3RhdGVBY3Rpb25zXG4gICAgICB9ID0gdGhpcy5wcm9wcztcblxuICAgICAgY29uc3Qge1xuICAgICAgICBmaWx0ZXJzLFxuICAgICAgICBsYXllcnMsXG4gICAgICAgIHNwbGl0TWFwcywgLy8gdGhpcyB3aWxsIHN0b3JlIHN1cHBvcnQgZm9yIHNwbGl0IG1hcCB2aWV3IGlzIG5lY2Vzc2FyeVxuICAgICAgICBsYXllck9yZGVyLFxuICAgICAgICBsYXllckJsZW5kaW5nLFxuICAgICAgICBsYXllckNsYXNzZXMsXG4gICAgICAgIGludGVyYWN0aW9uQ29uZmlnLFxuICAgICAgICBkYXRhc2V0cyxcbiAgICAgICAgbGF5ZXJEYXRhLFxuICAgICAgICBob3ZlckluZm8sXG4gICAgICAgIGNsaWNrZWRcbiAgICAgIH0gPSB2aXNTdGF0ZTtcblxuICAgICAgY29uc3Qgc2lkZUZpZWxkcyA9IHtcbiAgICAgICAgYXBwTmFtZSxcbiAgICAgICAgdmVyc2lvbixcbiAgICAgICAgZGF0YXNldHMsXG4gICAgICAgIGZpbHRlcnMsXG4gICAgICAgIGxheWVycyxcbiAgICAgICAgbGF5ZXJPcmRlcixcbiAgICAgICAgbGF5ZXJDbGFzc2VzLFxuICAgICAgICBpbnRlcmFjdGlvbkNvbmZpZyxcbiAgICAgICAgbWFwU3R5bGUsXG4gICAgICAgIGxheWVyQmxlbmRpbmcsXG4gICAgICAgIG9uU2F2ZU1hcCxcbiAgICAgICAgdWlTdGF0ZSxcbiAgICAgICAgbWFwU3R5bGVBY3Rpb25zLFxuICAgICAgICB2aXNTdGF0ZUFjdGlvbnMsXG4gICAgICAgIHVpU3RhdGVBY3Rpb25zLFxuICAgICAgICB3aWR0aDogRElNRU5TSU9OUy5zaWRlUGFuZWwud2lkdGhcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG1hcEZpZWxkcyA9IHtcbiAgICAgICAgZGF0YXNldHMsXG4gICAgICAgIG1hcGJveEFwaUFjY2Vzc1Rva2VuLFxuICAgICAgICBtYXBTdGF0ZSxcbiAgICAgICAgbWFwU3R5bGUsXG4gICAgICAgIG1hcENvbnRyb2xzOiB1aVN0YXRlLm1hcENvbnRyb2xzLFxuICAgICAgICBsYXllcnMsXG4gICAgICAgIGxheWVyT3JkZXIsXG4gICAgICAgIGxheWVyRGF0YSxcbiAgICAgICAgbGF5ZXJCbGVuZGluZyxcbiAgICAgICAgaW50ZXJhY3Rpb25Db25maWcsXG4gICAgICAgIGhvdmVySW5mbyxcbiAgICAgICAgY2xpY2tlZCxcbiAgICAgICAgdG9nZ2xlTWFwQ29udHJvbDogdWlTdGF0ZUFjdGlvbnMudG9nZ2xlTWFwQ29udHJvbCxcbiAgICAgICAgdWlTdGF0ZUFjdGlvbnMsXG4gICAgICAgIHZpc1N0YXRlQWN0aW9ucyxcbiAgICAgICAgbWFwU3RhdGVBY3Rpb25zXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBpc1NwbGl0ID0gc3BsaXRNYXBzICYmIHNwbGl0TWFwcy5sZW5ndGggPiAxO1xuICAgICAgY29uc3QgY29udGFpbmVyVyA9IG1hcFN0YXRlLndpZHRoICogKE51bWJlcihpc1NwbGl0KSArIDEpO1xuXG4gICAgICBjb25zdCBtYXBDb250YWluZXJzID0gIWlzU3BsaXRcbiAgICAgICAgPyBbXG4gICAgICAgICAgICA8TWFwQ29udGFpbmVyXG4gICAgICAgICAgICAgIGtleT17MH1cbiAgICAgICAgICAgICAgaW5kZXg9ezB9XG4gICAgICAgICAgICAgIHsuLi5tYXBGaWVsZHN9XG4gICAgICAgICAgICAgIG1hcExheWVycz17aXNTcGxpdCA/IHNwbGl0TWFwc1swXS5sYXllcnMgOiBudWxsfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICBdXG4gICAgICAgIDogc3BsaXRNYXBzLm1hcCgoc2V0dGluZ3MsIGluZGV4KSA9PiAoXG4gICAgICAgICAgICA8TWFwQ29udGFpbmVyXG4gICAgICAgICAgICAgIGtleT17aW5kZXh9XG4gICAgICAgICAgICAgIGluZGV4PXtpbmRleH1cbiAgICAgICAgICAgICAgey4uLm1hcEZpZWxkc31cbiAgICAgICAgICAgICAgbWFwTGF5ZXJzPXtzcGxpdE1hcHNbaW5kZXhdLmxheWVyc31cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgKSk7XG5cbiAgICAgIGNvbnN0IGlzRXhwb3J0aW5nID0gdWlTdGF0ZS5jdXJyZW50TW9kYWwgPT09IEVYUE9SVF9JTUFHRV9JRDtcblxuICAgICAgcmV0dXJuIChcbiAgICAgICAgPFRoZW1lUHJvdmlkZXIgdGhlbWU9e3RoZW1lfT5cbiAgICAgICAgICA8R2xvYmFsU3R5bGVcbiAgICAgICAgICAgIHN0eWxlPXt7XG4gICAgICAgICAgICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgICAgICAgICAgICB3aWR0aDogYCR7d2lkdGh9cHhgLFxuICAgICAgICAgICAgICBoZWlnaHQ6IGAke2hlaWdodH1weGBcbiAgICAgICAgICAgIH19XG4gICAgICAgICAgICBjbGFzc05hbWU9XCJrZXBsZXItZ2xcIlxuICAgICAgICAgICAgaWQ9e2BrZXBsZXItZ2xfXyR7aWR9YH1cbiAgICAgICAgICAgIGlubmVyUmVmPXtub2RlID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5yb290ID0gbm9kZTtcbiAgICAgICAgICAgIH19XG4gICAgICAgICAgPlxuICAgICAgICAgICAgeyF1aVN0YXRlLnJlYWRPbmx5ICYmIDxTaWRlUGFuZWwgey4uLnNpZGVGaWVsZHN9IC8+fVxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJtYXBzXCIgc3R5bGU9e3tkaXNwbGF5OiAnZmxleCd9fT5cbiAgICAgICAgICAgICAge21hcENvbnRhaW5lcnN9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIHtpc0V4cG9ydGluZyAmJlxuICAgICAgICAgICAgICA8UGxvdENvbnRhaW5lclxuICAgICAgICAgICAgICAgIHdpZHRoPXt3aWR0aH1cbiAgICAgICAgICAgICAgICBoZWlnaHQ9e2hlaWdodH1cbiAgICAgICAgICAgICAgICBleHBvcnRJbWFnZVNldHRpbmc9e3VpU3RhdGUuZXhwb3J0SW1hZ2V9XG4gICAgICAgICAgICAgICAgbWFwRmllbGRzPXttYXBGaWVsZHN9XG4gICAgICAgICAgICAgICAgc3RhcnRFeHBvcnRpbmdJbWFnZT17dWlTdGF0ZUFjdGlvbnMuc3RhcnRFeHBvcnRpbmdJbWFnZX1cbiAgICAgICAgICAgICAgICBzZXRFeHBvcnRJbWFnZURhdGFVcmk9e3VpU3RhdGVBY3Rpb25zLnNldEV4cG9ydEltYWdlRGF0YVVyaX1cbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDxCb3R0b21XaWRnZXRcbiAgICAgICAgICAgICAgZmlsdGVycz17ZmlsdGVyc31cbiAgICAgICAgICAgICAgZGF0YXNldHM9e2RhdGFzZXRzfVxuICAgICAgICAgICAgICB1aVN0YXRlPXt1aVN0YXRlfVxuICAgICAgICAgICAgICB2aXNTdGF0ZUFjdGlvbnM9e3Zpc1N0YXRlQWN0aW9uc31cbiAgICAgICAgICAgICAgc2lkZVBhbmVsV2lkdGg9e1xuICAgICAgICAgICAgICAgIERJTUVOU0lPTlMuc2lkZVBhbmVsLndpZHRoICsgRElNRU5TSU9OUy5zaWRlUGFuZWwubWFyZ2luLmxlZnRcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb250YWluZXJXPXtjb250YWluZXJXfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxNb2RhbFdyYXBwZXJcbiAgICAgICAgICAgICAgbWFwU3R5bGU9e21hcFN0eWxlfVxuICAgICAgICAgICAgICB2aXNTdGF0ZT17dmlzU3RhdGV9XG4gICAgICAgICAgICAgIG1hcFN0YXRlPXttYXBTdGF0ZX1cbiAgICAgICAgICAgICAgdWlTdGF0ZT17dWlTdGF0ZX1cbiAgICAgICAgICAgICAgbWFwYm94QXBpQWNjZXNzVG9rZW49e21hcGJveEFwaUFjY2Vzc1Rva2VufVxuICAgICAgICAgICAgICB2aXNTdGF0ZUFjdGlvbnM9e3Zpc1N0YXRlQWN0aW9uc31cbiAgICAgICAgICAgICAgdWlTdGF0ZUFjdGlvbnM9e3VpU3RhdGVBY3Rpb25zfVxuICAgICAgICAgICAgICBtYXBTdHlsZUFjdGlvbnM9e21hcFN0eWxlQWN0aW9uc31cbiAgICAgICAgICAgICAgcm9vdE5vZGU9e3RoaXMucm9vdH1cbiAgICAgICAgICAgICAgY29udGFpbmVyVz17Y29udGFpbmVyV31cbiAgICAgICAgICAgICAgY29udGFpbmVySD17bWFwU3RhdGUuaGVpZ2h0fVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICA8L0dsb2JhbFN0eWxlPlxuICAgICAgICA8L1RoZW1lUHJvdmlkZXI+XG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBrZXBsZXJHbENvbm5lY3QobWFwU3RhdGVUb1Byb3BzLCBtYXBEaXNwYXRjaFRvUHJvcHMpKEtlcGxlckdMKTtcbn1cblxuZnVuY3Rpb24gbWFwU3RhdGVUb1Byb3BzKHN0YXRlLCBwcm9wcykge1xuICByZXR1cm4ge1xuICAgIC4uLnByb3BzLFxuICAgIHZpc1N0YXRlOiBzdGF0ZS52aXNTdGF0ZSxcbiAgICBtYXBTdHlsZTogc3RhdGUubWFwU3R5bGUsXG4gICAgbWFwU3RhdGU6IHN0YXRlLm1hcFN0YXRlLFxuICAgIHVpU3RhdGU6IHN0YXRlLnVpU3RhdGVcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWFwRGlzcGF0Y2hUb1Byb3BzKGRpc3BhdGNoLCBvd25Qcm9wcykge1xuICBjb25zdCB1c2VyQWN0aW9ucyA9IG93blByb3BzLmFjdGlvbnMgfHwge307XG5cbiAgY29uc3QgW1xuICAgIHZpc1N0YXRlQWN0aW9ucyxcbiAgICBtYXBTdGF0ZUFjdGlvbnMsXG4gICAgbWFwU3R5bGVBY3Rpb25zLFxuICAgIHVpU3RhdGVBY3Rpb25zXG4gIF0gPSBbXG4gICAgVmlzU3RhdGVBY3Rpb25zLFxuICAgIE1hcFN0YXRlQWN0aW9ucyxcbiAgICBNYXBTdHlsZUFjdGlvbnMsXG4gICAgVUlTdGF0ZUFjdGlvbnNcbiAgXS5tYXAoYWN0aW9ucyA9PlxuICAgIGJpbmRBY3Rpb25DcmVhdG9ycyhtZXJnZUFjdGlvbnMoYWN0aW9ucywgdXNlckFjdGlvbnMpLCBkaXNwYXRjaClcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHZpc1N0YXRlQWN0aW9ucyxcbiAgICBtYXBTdGF0ZUFjdGlvbnMsXG4gICAgbWFwU3R5bGVBY3Rpb25zLFxuICAgIHVpU3RhdGVBY3Rpb25zLFxuICAgIGRpc3BhdGNoXG4gIH07XG59XG5cbi8qKlxuICogT3ZlcnJpZGUgZGVmYXVsdCBtYXBzLWdsIGFjdGlvbnMgd2l0aCB1c2VyIGRlZmluZWQgYWN0aW9ucyB1c2luZyB0aGUgc2FtZSBrZXlcbiAqL1xuZnVuY3Rpb24gbWVyZ2VBY3Rpb25zKGFjdGlvbnMsIHVzZXJBY3Rpb25zKSB7XG4gIGNvbnN0IG92ZXJyaWRlcyA9IHt9O1xuICBmb3IgKGNvbnN0IGtleSBpbiB1c2VyQWN0aW9ucykge1xuICAgIGlmICh1c2VyQWN0aW9ucy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGFjdGlvbnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgb3ZlcnJpZGVzW2tleV0gPSB1c2VyQWN0aW9uc1trZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7Li4uYWN0aW9ucywgLi4ub3ZlcnJpZGVzfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgS2VwbGVyR2xGYWN0b3J5O1xuIl19