kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
301 lines (250 loc) • 28.4 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"] = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
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 _getPrototypeOf3 = _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 _d3Scale = require("d3-scale");
var _moment = _interopRequireDefault(require("moment"));
var _d3Array = require("d3-array");
var _reselect = require("reselect");
var _reactVis = require("react-vis");
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _classnames = _interopRequireDefault(require("classnames"));
var _rangeBrush = _interopRequireDefault(require("./range-brush"));
var _filterUtils = require("../../utils/filter-utils");
function _templateObject3() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n background-color: #d3d8e0;\n border-radius: 2px;\n color: ", ";\n font-size: 9px;\n margin: 4px;\n padding: 3px 6px;\n pointer-events: none;\n user-select: none;\n"]);
_templateObject3 = function _templateObject3() {
return data;
};
return data;
}
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; }
function _templateObject2() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n .histogram-bars {\n rect {\n fill: ", ";\n }\n rect.in-range {\n fill: ", ";\n }\n }\n"]);
_templateObject2 = function _templateObject2() {
return data;
};
return data;
}
function _templateObject() {
var data = (0, _taggedTemplateLiteral2["default"])(["\n .rv-xy-plot__inner path {\n fill: none;\n stroke-width: 1.5;\n }\n"]);
_templateObject = function _templateObject() {
return data;
};
return data;
}
var chartMargin = {
top: 8,
bottom: 0,
left: 0,
right: 0
};
var chartH = 52;
var containerH = 68;
var histogramStyle = {
highlightW: 0.7,
unHighlightedW: 0.4
};
var RangePlot =
/*#__PURE__*/
function (_Component) {
(0, _inherits2["default"])(RangePlot, _Component);
function RangePlot() {
var _getPrototypeOf2;
var _this;
(0, _classCallCheck2["default"])(this, RangePlot);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = (0, _possibleConstructorReturn2["default"])(this, (_getPrototypeOf2 = (0, _getPrototypeOf3["default"])(RangePlot)).call.apply(_getPrototypeOf2, [this].concat(args)));
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "state", {
hoveredDP: null
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "domainSelector", function (props) {
return props.lineChart && props.lineChart.xDomain;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "hintFormatter", (0, _reselect.createSelector)(_this.domainSelector, function (domain) {
return (0, _filterUtils.getTimeWidgetHintFormatter)(domain);
}));
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onMouseMove", function (hoveredDP) {
_this.setState({
hoveredDP: hoveredDP
});
});
return _this;
}
(0, _createClass2["default"])(RangePlot, [{
key: "render",
value: function render() {
var _this$props = this.props,
onBrush = _this$props.onBrush,
range = _this$props.range,
value = _this$props.value,
width = _this$props.width,
plotType = _this$props.plotType,
lineChart = _this$props.lineChart,
histogram = _this$props.histogram;
var domain = [histogram[0].x0, histogram[histogram.length - 1].x1];
var brushComponent = _react["default"].createElement(_rangeBrush["default"], {
domain: domain,
onBrush: onBrush,
range: range,
value: value,
width: width
});
return _react["default"].createElement("div", {
style: {
height: "".concat(containerH, "px"),
position: 'relative'
}
}, plotType === 'lineChart' ? _react["default"].createElement(LineChart, {
hoveredDP: this.state.hoveredDP,
width: width,
height: containerH,
margin: chartMargin,
children: brushComponent,
onMouseMove: this.onMouseMove,
yDomain: lineChart.yDomain,
hintFormat: this.hintFormatter(this.props),
data: lineChart.series
}) : _react["default"].createElement(Histogram, {
width: width,
height: chartH,
value: value,
margin: chartMargin,
histogram: histogram,
brushComponent: brushComponent
}));
}
}]);
return RangePlot;
}(_react.Component);
exports["default"] = RangePlot;
(0, _defineProperty2["default"])(RangePlot, "propTypes", {
value: _propTypes["default"].arrayOf(_propTypes["default"].number).isRequired,
histogram: _propTypes["default"].arrayOf(_propTypes["default"].shape({
x0: _propTypes["default"].number,
x1: _propTypes["default"].number
})),
lineChart: _propTypes["default"].object,
plotType: _propTypes["default"].string,
isEnlarged: _propTypes["default"].bool,
onBlur: _propTypes["default"].func,
width: _propTypes["default"].number.isRequired
});
var Histogram = function Histogram(_ref) {
var width = _ref.width,
height = _ref.height,
margin = _ref.margin,
histogram = _ref.histogram,
value = _ref.value,
brushComponent = _ref.brushComponent;
var domain = [histogram[0].x0, histogram[histogram.length - 1].x1];
var barWidth = width / histogram.length;
var x = (0, _d3Scale.scaleLinear)().domain(domain).range([0, width]);
var y = (0, _d3Scale.scaleLinear)().domain([0, (0, _d3Array.max)(histogram, function (d) {
return d.count;
})]).range([0, height]);
return _react["default"].createElement(HistogramWrapper, {
width: width,
height: height,
style: {
marginTop: "".concat(margin.top, "px")
}
}, _react["default"].createElement("g", {
className: "histogram-bars"
}, histogram.map(function (bar) {
var inRange = bar.x0 >= value[0] && bar.x1 <= value[1];
var wRatio = inRange ? histogramStyle.highlightW : histogramStyle.unHighlightedW;
return _react["default"].createElement("rect", {
className: (0, _classnames["default"])({
'in-range': inRange
}),
key: bar.x0,
height: y(bar.count),
width: barWidth * wRatio,
x: x(bar.x0) + barWidth * (1 - wRatio) / 2,
rx: 1,
ry: 1,
y: height - y(bar.count)
});
})), brushComponent);
};
var LineChartWrapper = _styledComponents["default"].div(_templateObject());
var HistogramWrapper = _styledComponents["default"].svg(_templateObject2(), function (props) {
return props.theme.histogramFillOutRange;
}, function (props) {
return props.theme.histogramFillInRange;
});
var LineChart = function LineChart(_ref2) {
var width = _ref2.width,
height = _ref2.height,
yDomain = _ref2.yDomain,
hintFormat = _ref2.hintFormat,
hoveredDP = _ref2.hoveredDP,
margin = _ref2.margin,
color = _ref2.color,
data = _ref2.data,
onMouseMove = _ref2.onMouseMove,
children = _ref2.children;
var brushData = [{
x: data[0].x,
y: yDomain[1],
customComponent: function customComponent() {
return children;
}
}];
return _react["default"].createElement(LineChartWrapper, null, _react["default"].createElement(_reactVis.XYPlot, {
width: width,
height: height,
margin: _objectSpread({}, margin, {
bottom: 12
})
}, _react["default"].createElement(_reactVis.LineSeries, {
strokeWidth: 2,
color: color,
data: data,
onNearestX: onMouseMove
}), _react["default"].createElement(_reactVis.MarkSeries, {
data: hoveredDP ? [hoveredDP] : [],
color: color,
size: 3
}), _react["default"].createElement(_reactVis.CustomSVGSeries, {
data: brushData
}), hoveredDP ? _react["default"].createElement(_reactVis.Hint, {
value: hoveredDP
}, _react["default"].createElement(HintContent, (0, _extends2["default"])({}, hoveredDP, {
format: function format(val) {
return _moment["default"].utc(val).format(hintFormat);
}
}))) : null));
};
var StyledHint = _styledComponents["default"].div(_templateObject3(), function (props) {
return props.theme.textColorLT;
});
var HintContent = function HintContent(_ref3) {
var x = _ref3.x,
y = _ref3.y,
format = _ref3.format;
return _react["default"].createElement(StyledHint, null, _react["default"].createElement("div", {
className: "hint--x"
}, format(x)), _react["default"].createElement("div", {
className: "row"
}, y));
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2NvbW1vbi9yYW5nZS1wbG90LmpzIl0sIm5hbWVzIjpbImNoYXJ0TWFyZ2luIiwidG9wIiwiYm90dG9tIiwibGVmdCIsInJpZ2h0IiwiY2hhcnRIIiwiY29udGFpbmVySCIsImhpc3RvZ3JhbVN0eWxlIiwiaGlnaGxpZ2h0VyIsInVuSGlnaGxpZ2h0ZWRXIiwiUmFuZ2VQbG90IiwiaG92ZXJlZERQIiwicHJvcHMiLCJsaW5lQ2hhcnQiLCJ4RG9tYWluIiwiZG9tYWluU2VsZWN0b3IiLCJkb21haW4iLCJzZXRTdGF0ZSIsIm9uQnJ1c2giLCJyYW5nZSIsInZhbHVlIiwid2lkdGgiLCJwbG90VHlwZSIsImhpc3RvZ3JhbSIsIngwIiwibGVuZ3RoIiwieDEiLCJicnVzaENvbXBvbmVudCIsImhlaWdodCIsInBvc2l0aW9uIiwic3RhdGUiLCJvbk1vdXNlTW92ZSIsInlEb21haW4iLCJoaW50Rm9ybWF0dGVyIiwic2VyaWVzIiwiQ29tcG9uZW50IiwiUHJvcFR5cGVzIiwiYXJyYXlPZiIsIm51bWJlciIsImlzUmVxdWlyZWQiLCJzaGFwZSIsIm9iamVjdCIsInN0cmluZyIsImlzRW5sYXJnZWQiLCJib29sIiwib25CbHVyIiwiZnVuYyIsIkhpc3RvZ3JhbSIsIm1hcmdpbiIsImJhcldpZHRoIiwieCIsInkiLCJkIiwiY291bnQiLCJtYXJnaW5Ub3AiLCJtYXAiLCJiYXIiLCJpblJhbmdlIiwid1JhdGlvIiwiTGluZUNoYXJ0V3JhcHBlciIsInN0eWxlZCIsImRpdiIsIkhpc3RvZ3JhbVdyYXBwZXIiLCJzdmciLCJ0aGVtZSIsImhpc3RvZ3JhbUZpbGxPdXRSYW5nZSIsImhpc3RvZ3JhbUZpbGxJblJhbmdlIiwiTGluZUNoYXJ0IiwiaGludEZvcm1hdCIsImNvbG9yIiwiZGF0YSIsImNoaWxkcmVuIiwiYnJ1c2hEYXRhIiwiY3VzdG9tQ29tcG9uZW50IiwidmFsIiwibW9tZW50IiwidXRjIiwiZm9ybWF0IiwiU3R5bGVk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SU4sSUFSTixDQURGLENBREY7QUFjRCxDQTVCRDs7QUE4QkEsSUFBTVUsVUFBVSxHQUFHbEIsNkJBQU9DLEdBQVYscUJBR0wsVUFBQWpELEtBQUs7QUFBQSxTQUFJQSxLQUFLLENBQUNvRCxLQUFOLENBQVllLFdBQWhCO0FBQUEsQ0FIQSxDQUFoQjs7QUFVQSxJQUFNQyxXQUFXLEdBQUcsU0FBZEEsV0FBYztBQUFBLE1BQUU5QixDQUFGLFNBQUVBLENBQUY7QUFBQSxNQUFLQyxDQUFMLFNBQUtBLENBQUw7QUFBQSxNQUFRMEIsTUFBUixTQUFRQSxNQUFSO0FBQUEsU0FDbEIsZ0NBQUMsVUFBRCxRQUNFO0FBQUssSUFBQSxTQUFTLEVBQUM7QUFBZixLQUEwQkEsTUFBTSxDQUFDM0IsQ0FBRCxDQUFoQyxDQURGLEVBRUU7QUFBSyxJQUFBLFNBQVMsRUFBQztBQUFmLEtBQXNCQyxDQUF0QixDQUZGLENBRGtCO0FBQUEsQ0FBcEIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjAgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgUmVhY3QsIHtDb21wb25lbnR9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQge3NjYWxlTGluZWFyfSBmcm9tICdkMy1zY2FsZSc7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQge21heH0gZnJvbSAnZDMtYXJyYXknO1xuaW1wb3J0IHtjcmVhdGVTZWxlY3Rvcn0gZnJvbSAncmVzZWxlY3QnO1xuaW1wb3J0IHtMaW5lU2VyaWVzLCBYWVBsb3QsIEN1c3RvbVNWR1NlcmllcywgSGludCwgTWFya1Nlcmllc30gZnJvbSAncmVhY3QtdmlzJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnc3R5bGVkLWNvbXBvbmVudHMnO1xuaW1wb3J0IGNsYXNzbmFtZXMgZnJvbSAnY2xhc3NuYW1lcyc7XG5cbmltcG9ydCBSYW5nZUJydXNoIGZyb20gJy4vcmFuZ2UtYnJ1c2gnO1xuaW1wb3J0IHtnZXRUaW1lV2lkZ2V0SGludEZvcm1hdHRlcn0gZnJvbSAndXRpbHMvZmlsdGVyLXV0aWxzJztcblxuY29uc3QgY2hhcnRNYXJnaW4gPSB7dG9wOiA4LCBib3R0b206IDAsIGxlZnQ6IDAsIHJpZ2h0OiAwfTtcbmNvbnN0IGNoYXJ0SCA9IDUyO1xuY29uc3QgY29udGFpbmVySCA9IDY4O1xuY29uc3QgaGlzdG9ncmFtU3R5bGUgPSB7XG4gIGhpZ2hsaWdodFc6IDAuNyxcbiAgdW5IaWdobGlnaHRlZFc6IDAuNFxufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmFuZ2VQbG90IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICB2YWx1ZTogUHJvcFR5cGVzLmFycmF5T2YoUHJvcFR5cGVzLm51bWJlcikuaXNSZXF1aXJlZCxcbiAgICBoaXN0b2dyYW06IFByb3BUeXBlcy5hcnJheU9mKFxuICAgICAgUHJvcFR5cGVzLnNoYXBlKHtcbiAgICAgICAgeDA6IFByb3BUeXBlcy5udW1iZXIsXG4gICAgICAgIHgxOiBQcm9wVHlwZXMubnVtYmVyXG4gICAgICB9KVxuICAgICksXG4gICAgbGluZUNoYXJ0OiBQcm9wVHlwZXMub2JqZWN0LFxuICAgIHBsb3RUeXBlOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgIGlzRW5sYXJnZWQ6IFByb3BUeXBlcy5ib29sLFxuICAgIG9uQmx1cjogUHJvcFR5cGVzLmZ1bmMsXG4gICAgd2lkdGg6IFByb3BUeXBlcy5udW1iZXIuaXNSZXF1aXJlZFxuICB9O1xuXG4gIHN0YXRlID0ge1xuICAgIGhvdmVyZWREUDogbnVsbFxuICB9O1xuXG4gIGRvbWFpblNlbGVjdG9yID0gcHJvcHMgPT4gcHJvcHMubGluZUNoYXJ0ICYmIHByb3BzLmxpbmVDaGFydC54RG9tYWluO1xuICBoaW50Rm9ybWF0dGVyID0gY3JlYXRlU2VsZWN0b3IodGhpcy5kb21haW5TZWxlY3RvciwgZG9tYWluID0+IGdldFRpbWVXaWRnZXRIaW50Rm9ybWF0dGVyKGRvbWFpbikpO1xuXG4gIG9uTW91c2VNb3ZlID0gaG92ZXJlZERQID0+IHtcbiAgICB0aGlzLnNldFN0YXRlKHtob3ZlcmVkRFB9KTtcbiAgfTtcblxuICByZW5kZXIoKSB7XG4gICAgY29uc3Qge29uQnJ1c2gsIHJhbmdlLCB2YWx1ZSwgd2lkdGgsIHBsb3RUeXBlLCBsaW5lQ2hhcnQsIGhpc3RvZ3JhbX0gPSB0aGlzLnByb3BzO1xuICAgIGNvbnN0IGRvbWFpbiA9IFtoaXN0b2dyYW1bMF0ueDAsIGhpc3RvZ3JhbVtoaXN0b2dyYW0ubGVuZ3RoIC0gMV0ueDFdO1xuXG4gICAgY29uc3QgYnJ1c2hDb21wb25lbnQgPSAoXG4gICAgICA8UmFuZ2VCcnVzaCBkb21haW49e2RvbWFpbn0gb25CcnVzaD17b25CcnVzaH0gcmFuZ2U9e3JhbmdlfSB2YWx1ZT17dmFsdWV9IHdpZHRoPXt3aWR0aH0gLz5cbiAgICApO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXZcbiAgICAgICAgc3R5bGU9e3tcbiAgICAgICAgICBoZWlnaHQ6IGAke2NvbnRhaW5lckh9cHhgLFxuICAgICAgICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnXG4gICAgICAgIH19XG4gICAgICA+XG4gICAgICAgIHtwbG90VHlwZSA9PT0gJ2xpbmVDaGFydCcgPyAoXG4gICAgICAgICAgPExpbmVDaGFydFxuICAgICAgICAgICAgaG92ZXJlZERQPXt0aGlzLnN0YXRlLmhvdmVyZWREUH1cbiAgICAgICAgICAgIHdpZHRoPXt3aWR0aH1cbiAgICAgICAgICAgIGhlaWdodD17Y29udGFpbmVySH1cbiAgICAgICAgICAgIG1hcmdpbj17Y2hhcnRNYXJnaW59XG4gICAgICAgICAgICBjaGlsZHJlbj17YnJ1c2hDb21wb25lbnR9XG4gICAgICAgICAgICBvbk1vdXNlTW92ZT17dGhpcy5vbk1vdXNlTW92ZX1cbiAgICAgICAgICAgIHlEb21haW49e2xpbmVDaGFydC55RG9tYWlufVxuICAgICAgICAgICAgaGludEZvcm1hdD17dGhpcy5oaW50Rm9ybWF0dGVyKHRoaXMucHJvcHMpfVxuICAgICAgICAgICAgZGF0YT17bGluZUNoYXJ0LnNlcmllc31cbiAgICAgICAgICAvPlxuICAgICAgICApIDogKFxuICAgICAgICAgIDxIaXN0b2dyYW1cbiAgICAgICAgICAgIHdpZHRoPXt3aWR0aH1cbiAgICAgICAgICAgIGhlaWdodD17Y2hhcnRIfVxuICAgICAgICAgICAgdmFsdWU9e3ZhbHVlfVxuICAgICAgICAgICAgbWFyZ2luPXtjaGFydE1hcmdpbn1cbiAgICAgICAgICAgIGhpc3RvZ3JhbT17aGlzdG9ncmFtfVxuICAgICAgICAgICAgYnJ1c2hDb21wb25lbnQ9e2JydXNoQ29tcG9uZW50fVxuICAgICAgICAgIC8+XG4gICAgICAgICl9XG4gICAgICA8L2Rpdj5cbiAgICApO1xuICB9XG59XG5cbmNvbnN0IEhpc3RvZ3JhbSA9ICh7d2lkdGgsIGhlaWdodCwgbWFyZ2luLCBoaXN0b2dyYW0sIHZhbHVlLCBicnVzaENvbXBvbmVudH0pID0+IHtcbiAgY29uc3QgZG9tYWluID0gW2hpc3RvZ3JhbVswXS54MCwgaGlzdG9ncmFtW2hpc3RvZ3JhbS5sZW5ndGggLSAxXS54MV07XG4gIGNvbnN0IGJhcldpZHRoID0gd2lkdGggLyBoaXN0b2dyYW0ubGVuZ3RoO1xuXG4gIGNvbnN0IHggPSBzY2FsZUxpbmVhcigpXG4gICAgLmRvbWFpbihkb21haW4pXG4gICAgLnJhbmdlKFswLCB3aWR0aF0pO1xuXG4gIGNvbnN0IHkgPSBzY2FsZUxpbmVhcigpXG4gICAgLmRvbWFpbihbMCwgbWF4KGhpc3RvZ3JhbSwgZCA9PiBkLmNvdW50KV0pXG4gICAgLnJhbmdlKFswLCBoZWlnaHRdKTtcblxuICByZXR1cm4gKFxuICAgIDxIaXN0b2dyYW1XcmFwcGVyIHdpZHRoPXt3aWR0aH0gaGVpZ2h0PXtoZWlnaHR9IHN0eWxlPXt7bWFyZ2luVG9wOiBgJHttYXJnaW4udG9wfXB4YH19PlxuICAgICAgPGcgY2xhc3NOYW1lPVwiaGlzdG9ncmFtLWJhcnNcIj5cbiAgICAgICAge2hpc3RvZ3JhbS5tYXAoYmFyID0+IHtcbiAgICAgICAgICBjb25zdCBpblJhbmdlID0gYmFyLngwID49IHZhbHVlWzBdICYmIGJhci54MSA8PSB2YWx1ZVsxXTtcbiAgICAgICAgICBjb25zdCB3UmF0aW8gPSBpblJhbmdlID8gaGlzdG9ncmFtU3R5bGUuaGlnaGxpZ2h0VyA6IGhpc3RvZ3JhbVN0eWxlLnVuSGlnaGxpZ2h0ZWRXO1xuXG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxyZWN0XG4gICAgICAgICAgICAgIGNsYXNzTmFtZT17Y2xhc3NuYW1lcyh7J2luLXJhbmdlJzogaW5SYW5nZX0pfVxuICAgICAgICAgICAgICBrZXk9e2Jhci54MH1cbiAgICAgICAgICAgICAgaGVpZ2h0PXt5KGJhci5jb3VudCl9XG4gICAgICAgICAgICAgIHdpZHRoPXtiYXJXaWR0aCAqIHdSYXRpb31cbiAgICAgICAgICAgICAgeD17eChiYXIueDApICsgKGJhcldpZHRoICogKDEgLSB3UmF0aW8pKSAvIDJ9XG4gICAgICAgICAgICAgIHJ4PXsxfVxuICAgICAgICAgICAgICByeT17MX1cbiAgICAgICAgICAgICAgeT17aGVpZ2h0IC0geShiYXIuY291bnQpfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICApO1xuICAgICAgICB9KX1cbiAgICAgIDwvZz5cbiAgICAgIHticnVzaENvbXBvbmVudH1cbiAgICA8L0hpc3RvZ3JhbVdyYXBwZXI+XG4gICk7XG59O1xuXG5jb25zdCBMaW5lQ2hhcnRXcmFwcGVyID0gc3R5bGVkLmRpdmBcbiAgLnJ2LXh5LXBsb3RfX2lubmVyIHBhdGgge1xuICAgIGZpbGw6IG5vbmU7XG4gICAgc3Ryb2tlLXdpZHRoOiAxLjU7XG4gIH1cbmA7XG5cbmNvbnN0IEhpc3RvZ3JhbVdyYXBwZXIgPSBzdHlsZWQuc3ZnYFxuICAuaGlzdG9ncmFtLWJhcnMge1xuICAgIHJlY3Qge1xuICAgICAgZmlsbDogJHtwcm9wcyA9PiBwcm9wcy50aGVtZS5oaXN0b2dyYW1GaWxsT3V0UmFuZ2V9O1xuICAgIH1cbiAgICByZWN0LmluLXJhbmdlIHtcbiAgICAgIGZpbGw6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUuaGlzdG9ncmFtRmlsbEluUmFuZ2V9O1xuICAgIH1cbiAgfVxuYDtcbmNvbnN0IExpbmVDaGFydCA9ICh7XG4gIHdpZHRoLFxuICBoZWlnaHQsXG4gIHlEb21haW4sXG4gIGhpbnRGb3JtYXQsXG4gIGhvdmVyZWREUCxcbiAgbWFyZ2luLFxuICBjb2xvcixcbiAgZGF0YSxcbiAgb25Nb3VzZU1vdmUsXG4gIGNoaWxkcmVuXG59KSA9PiB7XG4gIGNvbnN0IGJydXNoRGF0YSA9IFt7eDogZGF0YVswXS54LCB5OiB5RG9tYWluWzFdLCBjdXN0b21Db21wb25lbnQ6ICgpID0+IGNoaWxkcmVufV07XG5cbiAgcmV0dXJuIChcbiAgICA8TGluZUNoYXJ0V3JhcHBlcj5cbiAgICAgIDxYWVBsb3Qgd2lkdGg9e3dpZHRofSBoZWlnaHQ9e2hlaWdodH0gbWFyZ2luPXt7Li4ubWFyZ2luLCBib3R0b206IDEyfX0+XG4gICAgICAgIDxMaW5lU2VyaWVzIHN0cm9rZVdpZHRoPXsyfSBjb2xvcj17Y29sb3J9IGRhdGE9e2RhdGF9IG9uTmVhcmVzdFg9e29uTW91c2VNb3ZlfSAvPlxuICAgICAgICA8TWFya1NlcmllcyBkYXRhPXtob3ZlcmVkRFAgPyBbaG92ZXJlZERQXSA6IFtdfSBjb2xvcj17Y29sb3J9IHNpemU9ezN9IC8+XG4gICAgICAgIDxDdXN0b21TVkdTZXJpZXMgZGF0YT17YnJ1c2hEYXRhfSAvPlxuICAgICAgICB7aG92ZXJlZERQID8gKFxuICAgICAgICAgIDxIaW50IHZhbHVlPXtob3ZlcmVkRFB9PlxuICAgICAgICAgICAgPEhpbnRDb250ZW50IHsuLi5ob3ZlcmVkRFB9IGZvcm1hdD17dmFsID0+IG1vbWVudC51dGModmFsKS5mb3JtYXQoaGludEZvcm1hdCl9IC8+XG4gICAgICAgICAgPC9IaW50PlxuICAgICAgICApIDogbnVsbH1cbiAgICAgIDwvWFlQbG90PlxuICAgIDwvTGluZUNoYXJ0V3JhcHBlcj5cbiAgKTtcbn07XG5cbmNvbnN0IFN0eWxlZEhpbnQgPSBzdHlsZWQuZGl2YFxuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZDNkOGUwO1xuICBib3JkZXItcmFkaXVzOiAycHg7XG4gIGNvbG9yOiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnRleHRDb2xvckxUfTtcbiAgZm9udC1zaXplOiA5cHg7XG4gIG1hcmdpbjogNHB4O1xuICBwYWRkaW5nOiAzcHggNnB4O1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbiAgdXNlci1zZWxlY3Q6IG5vbmU7XG5gO1xuY29uc3QgSGludENvbnRlbnQgPSAoe3gsIHksIGZvcm1hdH0pID0+IChcbiAgPFN0eWxlZEhpbnQ+XG4gICAgPGRpdiBjbGFzc05hbWU9XCJoaW50LS14XCI+e2Zvcm1hdCh4KX08L2Rpdj5cbiAgICA8ZGl2IGNsYXNzTmFtZT1cInJvd1wiPnt5fTwvZGl2PlxuICA8L1N0eWxlZEhpbnQ+XG4pO1xuIl19