UNPKG

kepler.gl

Version:

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

352 lines (288 loc) 32.9 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = undefined; 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 _taggedTemplateLiteral2 = require('babel-runtime/helpers/taggedTemplateLiteral'); var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2); var _class, _temp, _initialiseProps; var _templateObject = (0, _taggedTemplateLiteral3.default)(['\n margin-top: ', ';\n align-items: flex-end;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n'], ['\n margin-top: ', ';\n align-items: flex-end;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n']), _templateObject2 = (0, _taggedTemplateLiteral3.default)(['\n display: flex;\n height: ', ';\n align-items: center;\n font-size: 11px;\n justify-content: ', ';\n color: ', ';\n\n .horizontal-bar {\n padding: 0 12px;\n }\n\n .time-value {\n display: flex;\n flex-direction: ', ';\n align-items: flex-start;\n }\n\n .time-value:last-child {\n align-items: flex-end;\n }\n'], ['\n display: flex;\n height: ', ';\n align-items: center;\n font-size: 11px;\n justify-content: ', ';\n color: ', ';\n\n .horizontal-bar {\n padding: 0 12px;\n }\n\n .time-value {\n display: flex;\n flex-direction: ', ';\n align-items: flex-start;\n }\n\n .time-value:last-child {\n align-items: flex-end;\n }\n']), _templateObject3 = (0, _taggedTemplateLiteral3.default)(['\n margin-bottom: 12px;\n margin-right: 42px;\n\n &.disabled {\n opacity: 0.4;\n pointer-events: none;\n }\n'], ['\n margin-bottom: 12px;\n margin-right: 42px;\n\n &.disabled {\n opacity: 0.4;\n pointer-events: none;\n }\n']), _templateObject4 = (0, _taggedTemplateLiteral3.default)(['\n svg {\n margin: 0 6px;\n }\n'], ['\n svg {\n margin: 0 6px;\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 _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _moment = require('moment'); var _moment2 = _interopRequireDefault(_moment); var _window = require('global/window'); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _lodash = require('lodash.throttle'); var _lodash2 = _interopRequireDefault(_lodash); var _styledComponents = require('styled-components'); var _styledComponents2 = _interopRequireDefault(_styledComponents); var _reselect = require('reselect'); var _icons = require('./icons'); var _styledComponents3 = require('./styled-components'); var _filterUtils = require('../../utils/filter-utils'); var _rangeSlider = require('./range-slider'); var _rangeSlider2 = _interopRequireDefault(_rangeSlider); var _timeSliderMarker = require('./time-slider-marker'); var _timeSliderMarker2 = _interopRequireDefault(_timeSliderMarker); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var defaultTimeFormat = function defaultTimeFormat(val) { return _moment2.default.utc(val).format('MM/DD/YY hh:mma'); }; var animationControlWidth = 140; var StyledSliderContainer = _styledComponents2.default.div(_templateObject, function (props) { return props.isEnlarged ? '12px' : '0px'; }); var TimeRangeSlider = (_temp = _class = function (_Component) { (0, _inherits3.default)(TimeRangeSlider, _Component); function TimeRangeSlider(props) { (0, _classCallCheck3.default)(this, TimeRangeSlider); var _this = (0, _possibleConstructorReturn3.default)(this, (TimeRangeSlider.__proto__ || Object.getPrototypeOf(TimeRangeSlider)).call(this, props)); _initialiseProps.call(_this); _this.state = { isAnimating: false, width: 288 }; _this._animation = null; _this._sliderThrottle = (0, _lodash2.default)(function () { var _this$props; return (_this$props = _this.props).onChange.apply(_this$props, arguments); }, 20); return _this; } (0, _createClass3.default)(TimeRangeSlider, [{ key: 'componentDidUpdate', value: function componentDidUpdate() { if (!this._animation && this.state.isAnimating) { this._animation = (0, _window.requestAnimationFrame)(this._nextFrame); } } }, { key: 'render', value: function render() { var _props = this.props, domain = _props.domain, value = _props.value, isEnlarged = _props.isEnlarged; var isAnimating = this.state.isAnimating; return _react2.default.createElement( 'div', { className: 'time-range-slider' }, _react2.default.createElement(TimeTitle, { timeFormat: this.titleFormatter(this.props), value: value, isEnlarged: isEnlarged }), _react2.default.createElement( StyledSliderContainer, { className: 'time-range-slider__container', isEnlarged: isEnlarged }, isEnlarged ? _react2.default.createElement(AnimationControls, { isAnimatable: this.props.isAnimatable, isEnlarged: isEnlarged, isAnimating: isAnimating, pauseAnimation: this._pauseAnimation, resetAnimation: this._resetAnimation, startAnimation: this._startAnimation }) : null, _react2.default.createElement( 'div', { style: { width: isEnlarged ? 'calc(100% - ' + animationControlWidth + 'px)' : '100%' } }, _react2.default.createElement(_rangeSlider2.default, { range: domain, value0: value[0], value1: value[1], histogram: this.props.histogram, lineChart: this.props.lineChart, plotType: this.props.plotType, isEnlarged: isEnlarged, showInput: false, step: this.props.step, onChange: this._sliderUpdate, xAxis: _timeSliderMarker2.default }) ) ) ); } }]); return TimeRangeSlider; }(_react.Component), _class.propTypes = { onChange: _propTypes2.default.func.isRequired, domain: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired, value: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired, step: _propTypes2.default.number.isRequired, plotType: _propTypes2.default.string, histogram: _propTypes2.default.arrayOf(_propTypes2.default.any), lineChart: _propTypes2.default.object, toggleAnimation: _propTypes2.default.func.isRequired, isAnimatable: _propTypes2.default.bool, isEnlarged: _propTypes2.default.bool, speed: _propTypes2.default.number }, _initialiseProps = function _initialiseProps() { var _this2 = this; this.domainSelector = function (props) { return props.domain; }; this.titleFormatter = (0, _reselect.createSelector)(this.domainSelector, function (domain) { return (0, _filterUtils.getTimeWidgetTitleFormatter)(domain); }); this._sliderUpdate = function (args) { _this2._sliderThrottle.cancel(); _this2._sliderThrottle(args); }; this._resetAnimation = function () { var _props2 = _this2.props, domain = _props2.domain, value = _props2.value; var value0 = domain[0]; var value1 = value0 + value[1] - value[0]; _this2.props.onChange([value0, value1]); }; this._startAnimation = function () { _this2._pauseAnimation(); _this2.props.toggleAnimation(); _this2.setState({ isAnimating: true }); }; this._pauseAnimation = function () { if (_this2._animation) { (0, _window.cancelAnimationFrame)(_this2._animation); _this2.props.toggleAnimation(); _this2._animation = null; } _this2.setState({ isAnimating: false }); }; this._nextFrame = function () { _this2._animation = null; var _props3 = _this2.props, domain = _props3.domain, value = _props3.value; var speed = (domain[1] - domain[0]) / _filterUtils.BASE_SPEED * _this2.props.speed; // loop when reaches the end var value0 = value[1] + speed > domain[1] ? domain[0] : value[0] + speed; var value1 = value0 + value[1] - value[0]; _this2.props.onChange([value0, value1]); }; }, _temp); exports.default = TimeRangeSlider; var TimeValueWrapper = _styledComponents2.default.div(_templateObject2, function (props) { return props.theme.secondaryInputHeight; }, function (props) { return props.isEnlarged ? 'center' : 'space-between'; }, function (props) { return props.theme.labelColor; }, function (props) { return props.isEnlarged ? 'row' : 'column'; }); var TimeTitle = function TimeTitle(_ref) { var value = _ref.value, isEnlarged = _ref.isEnlarged, _ref$timeFormat = _ref.timeFormat, timeFormat = _ref$timeFormat === undefined ? defaultTimeFormat : _ref$timeFormat; return _react2.default.createElement( TimeValueWrapper, { isEnlarged: isEnlarged }, _react2.default.createElement(TimeValue, { key: 0, value: _moment2.default.utc(value[0]).format(timeFormat), split: !isEnlarged }), isEnlarged ? _react2.default.createElement( 'div', { className: 'horizontal-bar' }, _react2.default.createElement(_icons.Minus, { height: '12px' }) ) : null, _react2.default.createElement(TimeValue, { key: 1, value: _moment2.default.utc(value[1]).format(timeFormat), split: !isEnlarged }) ); }; var TimeValue = function TimeValue(_ref2) { var value = _ref2.value, split = _ref2.split; return ( // render two lines if not enlarged _react2.default.createElement( 'div', { className: 'time-value' }, split ? value.split(' ').map(function (v, i) { return _react2.default.createElement( 'div', { key: i }, i === 0 ? _react2.default.createElement( _styledComponents3.SelectText, null, v ) : _react2.default.createElement( _styledComponents3.SelectTextBold, null, v ) ); }) : _react2.default.createElement( _styledComponents3.SelectTextBold, null, value ) ) ); }; var StyledAnimationControls = _styledComponents2.default.div(_templateObject3); var IconButton = _styledComponents3.Button.extend(_templateObject4); var AnimationControls = function AnimationControls(_ref3) { var isAnimatable = _ref3.isAnimatable, isAnimating = _ref3.isAnimating, pauseAnimation = _ref3.pauseAnimation, resetAnimation = _ref3.resetAnimation, startAnimation = _ref3.startAnimation; return _react2.default.createElement( StyledAnimationControls, { className: (0, _classnames2.default)('time-range-slider__control', { disabled: !isAnimatable }) }, _react2.default.createElement( _styledComponents3.ButtonGroup, null, _react2.default.createElement( IconButton, { className: 'playback-control-button', onClick: resetAnimation, secondary: true }, _react2.default.createElement(_icons.Reset, { height: '12px' }) ), _react2.default.createElement( IconButton, { className: (0, _classnames2.default)('playback-control-button', { active: isAnimating }), onClick: isAnimating ? pauseAnimation : startAnimation, secondary: true }, isAnimating ? _react2.default.createElement(_icons.Pause, { height: '12px' }) : _react2.default.createElement(_icons.Play, { height: '12px' }) ) ) ); }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2NvbW1vbi90aW1lLXJhbmdlLXNsaWRlci5qcyJdLCJuYW1lcyI6WyJkZWZhdWx0VGltZUZvcm1hdCIsIm1vbWVudCIsInV0YyIsInZhbCIsImZvcm1hdCIsImFuaW1hdGlvbkNvbnRyb2xXaWR0aCIsIlN0eWxlZFNsaWRlckNvbnRhaW5lciIsInN0eWxlZCIsImRpdiIsInByb3BzIiwiaXNFbmxhcmdlZCIsIlRpbWVSYW5nZVNsaWRlciIsInN0YXRlIiwiaXNBbmltYXRpbmciLCJ3aWR0aCIsIl9hbmltYXRpb24iLCJfc2xpZGVyVGhyb3R0bGUiLCJvbkNoYW5nZSIsIl9uZXh0RnJhbWUiLCJkb21haW4iLCJ2YWx1ZSIsInRpdGxlRm9ybWF0dGVyIiwiaXNBbmltYXRhYmxlIiwiX3BhdXNlQW5pbWF0aW9uIiwiX3Jlc2V0QW5pbWF0aW9uIiwiX3N0YXJ0QW5pbWF0aW9uIiwiaGlzdG9ncmFtIiwibGluZUNoYXJ0IiwicGxvdFR5cGUiLCJzdGVwIiwiX3NsaWRlclVwZGF0ZSIsIlRpbWVTbGlkZXJNYXJrZXIiLCJDb21wb25lbnQiLCJwcm9wVHlwZXMiLCJQcm9wVHlwZXMiLCJmdW5jIiwiaXNSZXF1aXJlZCIsImFycmF5T2YiLCJudW1iZXIiLCJzdHJpbmciLCJhbnkiLCJvYmplY3QiLCJ0b2dnbGVBbmltYXRpb24iLCJib29sIiwic3BlZWQiLCJkb21haW5TZWxlY3RvciIsImNhbmNlbCIsImFyZ3MiLCJ2YWx1ZTAiLCJ2YWx1ZTEiLCJzZXRTdGF0ZSIsIkJBU0VfU1BFRUQiLCJUaW1lVmFsdWVXcmFwcGVyIiwidGhlbWUiLCJzZWNvbmRhcnlJbnB1dEhlaWdodCIsImxhYmVsQ29sb3IiLCJUaW1lVGl0bGUiLCJ0aW1lRm9ybWF0IiwiVGltZVZhbHVlIiwic3BsaXQiLCJtYXAiLCJ2IiwiaSIsIlN0eWxlZEFuaW1hdGlvbkNvbnRyb2xzIiwiSWNvbkJ1dHRvbiIsIkJ1dHRvbiIsImV4dGVuZCIsIkFuaW1hdGlvbkNvbnRyb2xzIiwicGF1c2VBbmltYXRpb24iLCJyZXNldEFuaW1hdGlvbiIsInN0YXJ0QW5pbWF0aW9uIiwiZGlzYWJsZWQiLCJhY3RpdmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2lKQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBLElBQU1BLG9CQUFvQixTQUFwQkEsaUJBQW9CO0FBQUEsU0FBT0MsaUJBQU9DLEdBQVAsQ0FBV0MsR0FBWCxFQUFnQkMsTUFBaEIsQ0FBdUIsaUJBQXZCLENBQVA7QUFBQSxDQUExQjtBQUNBLElBQU1DLHdCQUF3QixHQUE5Qjs7QUFFQSxJQUFNQyx3QkFBd0JDLDJCQUFPQyxHQUEvQixrQkFDVTtBQUFBLFNBQVNDLE1BQU1DLFVBQU4sR0FBbUIsTUFBbkIsR0FBNEIsS0FBckM7QUFBQSxDQURWLENBQU47O0lBUXFCQyxlOzs7QUFlbkIsMkJBQVlGLEtBQVosRUFBbUI7QUFBQTs7QUFBQSxnSkFDWEEsS0FEVzs7QUFBQTs7QUFFakIsVUFBS0csS0FBTCxHQUFhO0FBQ1hDLG1CQUFhLEtBREY7QUFFWEMsYUFBTztBQUZJLEtBQWI7QUFJQSxVQUFLQyxVQUFMLEdBQWtCLElBQWxCO0FBQ0EsVUFBS0MsZUFBTCxHQUF1QixzQkFBUztBQUFBOztBQUFBLGFBQWMscUJBQUtQLEtBQUwsRUFBV1EsUUFBWCw4QkFBZDtBQUFBLEtBQVQsRUFBc0QsRUFBdEQsQ0FBdkI7QUFQaUI7QUFRbEI7Ozs7eUNBRW9CO0FBQ25CLFVBQUksQ0FBQyxLQUFLRixVQUFOLElBQW9CLEtBQUtILEtBQUwsQ0FBV0MsV0FBbkMsRUFBZ0Q7QUFDOUMsYUFB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QVEzRCxXQUFULEVBQXRDLENBQXZCO0FBQ0UsbUJBQVNBLGNBQWN1RCxjQUFkLEdBQStCRSxjQUQxQyxFQUMwRCxlQUQxRDtBQUVHekQsc0JBQWMsOEJBQUMsWUFBRCxJQUFPLFFBQU8sTUFBZCxHQUFkLEdBQXVDLDhCQUFDLFdBQUQsSUFBTSxRQUFPLE1BQWI7QUFGMUM7QUFMRjtBQUhGLEdBUHdCO0FBQUEsQ0FBMUIiLCJmaWxlIjoidGltZS1yYW5nZS1zbGlkZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMTggVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgUmVhY3QsIHtDb21wb25lbnR9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBQcm9wVHlwZXMgZnJvbSAncHJvcC10eXBlcyc7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQge3JlcXVlc3RBbmltYXRpb25GcmFtZSwgY2FuY2VsQW5pbWF0aW9uRnJhbWV9IGZyb20gJ2dsb2JhbC93aW5kb3cnO1xuaW1wb3J0IGNsYXNzbmFtZXMgZnJvbSAnY2xhc3NuYW1lcyc7XG5pbXBvcnQgdGhyb3R0bGUgZnJvbSAnbG9kYXNoLnRocm90dGxlJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnc3R5bGVkLWNvbXBvbmVudHMnO1xuaW1wb3J0IHtjcmVhdGVTZWxlY3Rvcn0gZnJvbSAncmVzZWxlY3QnO1xuaW1wb3J0IHtQbGF5LCBSZXNldCwgUGF1c2UsIE1pbnVzfSBmcm9tICdjb21wb25lbnRzL2NvbW1vbi9pY29ucyc7XG5pbXBvcnQge1NlbGVjdFRleHRCb2xkLCBTZWxlY3RUZXh0LCBCdXR0b24sIEJ1dHRvbkdyb3VwfSBmcm9tICdjb21wb25lbnRzL2NvbW1vbi9zdHlsZWQtY29tcG9uZW50cyc7XG5pbXBvcnQge2dldFRpbWVXaWRnZXRUaXRsZUZvcm1hdHRlciwgQkFTRV9TUEVFRH0gZnJvbSAndXRpbHMvZmlsdGVyLXV0aWxzJztcbmltcG9ydCBSYW5nZVNsaWRlciBmcm9tICcuL3JhbmdlLXNsaWRlcic7XG5pbXBvcnQgVGltZVNsaWRlck1hcmtlciBmcm9tICcuL3RpbWUtc2xpZGVyLW1hcmtlcic7XG5cbmNvbnN0IGRlZmF1bHRUaW1lRm9ybWF0ID0gdmFsID0+IG1vbWVudC51dGModmFsKS5mb3JtYXQoJ01NL0REL1lZIGhoOm1tYScpO1xuY29uc3QgYW5pbWF0aW9uQ29udHJvbFdpZHRoID0gMTQwO1xuXG5jb25zdCBTdHlsZWRTbGlkZXJDb250YWluZXIgPSBzdHlsZWQuZGl2YFxuICBtYXJnaW4tdG9wOiAke3Byb3BzID0+IHByb3BzLmlzRW5sYXJnZWQgPyAnMTJweCcgOiAnMHB4J307XG4gIGFsaWduLWl0ZW1zOiBmbGV4LWVuZDtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuYDtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGltZVJhbmdlU2xpZGVyIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICBvbkNoYW5nZTogUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcbiAgICBkb21haW46IFByb3BUeXBlcy5hcnJheU9mKFByb3BUeXBlcy5udW1iZXIpLmlzUmVxdWlyZWQsXG4gICAgdmFsdWU6IFByb3BUeXBlcy5hcnJheU9mKFByb3BUeXBlcy5udW1iZXIpLmlzUmVxdWlyZWQsXG4gICAgc3RlcDogUHJvcFR5cGVzLm51bWJlci5pc1JlcXVpcmVkLFxuICAgIHBsb3RUeXBlOiBQcm9wVHlwZXMuc3RyaW5nLFxuICAgIGhpc3RvZ3JhbTogUHJvcFR5cGVzLmFycmF5T2YoUHJvcFR5cGVzLmFueSksXG4gICAgbGluZUNoYXJ0OiBQcm9wVHlwZXMub2JqZWN0LFxuICAgIHRvZ2dsZUFuaW1hdGlvbjogUHJvcFR5cGVzLmZ1bmMuaXNSZXF1aXJlZCxcbiAgICBpc0FuaW1hdGFibGU6IFByb3BUeXBlcy5ib29sLFxuICAgIGlzRW5sYXJnZWQ6IFByb3BUeXBlcy5ib29sLFxuICAgIHNwZWVkOiBQcm9wVHlwZXMubnVtYmVyXG4gIH07XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcyk7XG4gICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgIGlzQW5pbWF0aW5nOiBmYWxzZSxcbiAgICAgIHdpZHRoOiAyODhcbiAgICB9O1xuICAgIHRoaXMuX2FuaW1hdGlvbiA9IG51bGw7XG4gICAgdGhpcy5fc2xpZGVyVGhyb3R0bGUgPSB0aHJvdHRsZSgoLi4udmFsdWUpID0+IHRoaXMucHJvcHMub25DaGFuZ2UoLi4udmFsdWUpLCAyMCk7XG4gIH1cblxuICBjb21wb25lbnREaWRVcGRhdGUoKSB7XG4gICAgaWYgKCF0aGlzLl9hbmltYXRpb24gJiYgdGhpcy5zdGF0ZS5pc0FuaW1hdGluZykge1xuICAgICAgdGhpcy5fYW5pbWF0aW9uID0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMuX25leHRGcmFtZSk7XG4gICAgfVxuICB9XG5cbiAgZG9tYWluU2VsZWN0b3IgPSBwcm9wcyA9PiBwcm9wcy5kb21haW47XG4gIHRpdGxlRm9ybWF0dGVyID0gY3JlYXRlU2VsZWN0b3IodGhpcy5kb21haW5TZWxlY3RvciwgZG9tYWluID0+XG4gICAgZ2V0VGltZVdpZGdldFRpdGxlRm9ybWF0dGVyKGRvbWFpbilcbiAgKTtcblxuICBfc2xpZGVyVXBkYXRlID0gYXJncyA9PiB7XG4gICAgdGhpcy5fc2xpZGVyVGhyb3R0bGUuY2FuY2VsKCk7XG4gICAgdGhpcy5fc2xpZGVyVGhyb3R0bGUoYXJncyk7XG4gIH07XG5cbiAgX3Jlc2V0QW5pbWF0aW9uID0gKCkgPT4ge1xuICAgIGNvbnN0IHtkb21haW4sIHZhbHVlfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3QgdmFsdWUwID0gZG9tYWluWzBdO1xuICAgIGNvbnN0IHZhbHVlMSA9IHZhbHVlMCArIHZhbHVlWzFdIC0gdmFsdWVbMF07XG4gICAgdGhpcy5wcm9wcy5vbkNoYW5nZShbdmFsdWUwLCB2YWx1ZTFdKTtcbiAgfTtcblxuICBfc3RhcnRBbmltYXRpb24gPSAoKSA9PiB7XG4gICAgdGhpcy5fcGF1c2VBbmltYXRpb24oKTtcbiAgICB0aGlzLnByb3BzLnRvZ2dsZUFuaW1hdGlvbigpO1xuICAgIHRoaXMuc2V0U3RhdGUoe2lzQW5pbWF0aW5nOiB0cnVlfSk7XG4gIH07XG5cbiAgX3BhdXNlQW5pbWF0aW9uID0gKCkgPT4ge1xuICAgIGlmICh0aGlzLl9hbmltYXRpb24pIHtcbiAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuX2FuaW1hdGlvbik7XG4gICAgICB0aGlzLnByb3BzLnRvZ2dsZUFuaW1hdGlvbigpO1xuICAgICAgdGhpcy5fYW5pbWF0aW9uID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5zZXRTdGF0ZSh7aXNBbmltYXRpbmc6IGZhbHNlfSk7XG4gIH07XG5cbiAgX25leHRGcmFtZSA9ICgpID0+IHtcbiAgICB0aGlzLl9hbmltYXRpb24gPSBudWxsO1xuXG4gICAgY29uc3Qge2RvbWFpbiwgdmFsdWV9ID0gdGhpcy5wcm9wcztcbiAgICBjb25zdCBzcGVlZCA9ICgoZG9tYWluWzFdIC0gZG9tYWluWzBdKSAvIEJBU0VfU1BFRUQpICogdGhpcy5wcm9wcy5zcGVlZDtcblxuICAgIC8vIGxvb3Agd2hlbiByZWFjaGVzIHRoZSBlbmRcbiAgICBjb25zdCB2YWx1ZTAgPSB2YWx1ZVsxXSArIHNwZWVkID4gZG9tYWluWzFdID8gZG9tYWluWzBdIDogdmFsdWVbMF0gKyBzcGVlZDtcbiAgICBjb25zdCB2YWx1ZTEgPSB2YWx1ZTAgKyB2YWx1ZVsxXSAtIHZhbHVlWzBdO1xuICAgIHRoaXMucHJvcHMub25DaGFuZ2UoW3ZhbHVlMCwgdmFsdWUxXSk7XG4gIH07XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IHtkb21haW4sIHZhbHVlLCBpc0VubGFyZ2VkfSA9IHRoaXMucHJvcHM7XG4gICAgY29uc3Qge2lzQW5pbWF0aW5nfSA9IHRoaXMuc3RhdGU7XG5cbiAgICByZXR1cm4gKFxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJ0aW1lLXJhbmdlLXNsaWRlclwiPlxuICAgICAgICA8VGltZVRpdGxlXG4gICAgICAgICAgdGltZUZvcm1hdD17dGhpcy50aXRsZUZvcm1hdHRlcih0aGlzLnByb3BzKX1cbiAgICAgICAgICB2YWx1ZT17dmFsdWV9XG4gICAgICAgICAgaXNFbmxhcmdlZD17aXNFbmxhcmdlZH1cbiAgICAgICAgLz5cbiAgICAgICAgPFN0eWxlZFNsaWRlckNvbnRhaW5lclxuICAgICAgICAgIGNsYXNzTmFtZT1cInRpbWUtcmFuZ2Utc2xpZGVyX19jb250YWluZXJcIlxuICAgICAgICAgIGlzRW5sYXJnZWQ9e2lzRW5sYXJnZWR9PlxuICAgICAgICAgIHtpc0VubGFyZ2VkID8gPEFuaW1hdGlvbkNvbnRyb2xzXG4gICAgICAgICAgICBpc0FuaW1hdGFibGU9e3RoaXMucHJvcHMuaXNBbmltYXRhYmxlfVxuICAgICAgICAgICAgaXNFbmxhcmdlZD17aXNFbmxhcmdlZH1cbiAgICAgICAgICAgIGlzQW5pbWF0aW5nPXtpc0FuaW1hdGluZ31cbiAgICAgICAgICAgIHBhdXNlQW5pbWF0aW9uPXt0aGlzLl9wYXVzZUFuaW1hdGlvbn1cbiAgICAgICAgICAgIHJlc2V0QW5pbWF0aW9uPXt0aGlzLl9yZXNldEFuaW1hdGlvbn1cbiAgICAgICAgICAgIHN0YXJ0QW5pbWF0aW9uPXt0aGlzLl9zdGFydEFuaW1hdGlvbn1cbiAgICAgICAgICAvPiA6IG51bGx9XG4gICAgICAgICAgPGRpdiBzdHlsZT17e3dpZHRoOiBpc0VubGFyZ2VkID8gYGNhbGMoMTAwJSAtICR7YW5pbWF0aW9uQ29udHJvbFdpZHRofXB4KWAgOiAnMTAwJSd9fT5cbiAgICAgICAgICAgIDxSYW5nZVNsaWRlclxuICAgICAgICAgICAgICByYW5nZT17ZG9tYWlufVxuICAgICAgICAgICAgICB2YWx1ZTA9e3ZhbHVlWzBdfVxuICAgICAgICAgICAgICB2YWx1ZTE9e3ZhbHVlWzFdfVxuICAgICAgICAgICAgICBoaXN0b2dyYW09e3RoaXMucHJvcHMuaGlzdG9ncmFtfVxuICAgICAgICAgICAgICBsaW5lQ2hhcnQ9e3RoaXMucHJvcHMubGluZUNoYXJ0fVxuICAgICAgICAgICAgICBwbG90VHlwZT17dGhpcy5wcm9wcy5wbG90VHlwZX1cbiAgICAgICAgICAgICAgaXNFbmxhcmdlZD17aXNFbmxhcmdlZH1cbiAgICAgICAgICAgICAgc2hvd0lucHV0PXtmYWxzZX1cbiAgICAgICAgICAgICAgc3RlcD17dGhpcy5wcm9wcy5zdGVwfVxuICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5fc2xpZGVyVXBkYXRlfVxuICAgICAgICAgICAgICB4QXhpcz17VGltZVNsaWRlck1hcmtlcn1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvU3R5bGVkU2xpZGVyQ29udGFpbmVyPlxuICAgICAgPC9kaXY+XG4gICAgKTtcbiAgfVxufVxuXG5jb25zdCBUaW1lVmFsdWVXcmFwcGVyID0gc3R5bGVkLmRpdmBcbiAgZGlzcGxheTogZmxleDtcbiAgaGVpZ2h0OiAke3Byb3BzID0+IHByb3BzLnRoZW1lLnNlY29uZGFyeUlucHV0SGVpZ2h0fTtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZm9udC1zaXplOiAxMXB4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6ICR7cHJvcHMgPT4gcHJvcHMuaXNFbmxhcmdlZCA/ICdjZW50ZXInIDogJ3NwYWNlLWJldHdlZW4nfTtcbiAgY29sb3I6ICR7cHJvcHMgPT4gcHJvcHMudGhlbWUubGFiZWxDb2xvcn07XG5cbiAgLmhvcml6b250YWwtYmFyIHtcbiAgICBwYWRkaW5nOiAwIDEycHg7XG4gIH1cblxuICAudGltZS12YWx1ZSB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogJHtwcm9wcyA9PiBwcm9wcy5pc0VubGFyZ2VkID8gJ3JvdycgOiAnY29sdW1uJ307XG4gICAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XG4gIH1cblxuICAudGltZS12YWx1ZTpsYXN0LWNoaWxkIHtcbiAgICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XG4gIH1cbmA7XG5cbmNvbnN0IFRpbWVUaXRsZSA9ICh7dmFsdWUsIGlzRW5sYXJnZWQsIHRpbWVGb3JtYXQgPSBkZWZhdWx0VGltZUZvcm1hdH0pID0+IChcbiAgPFRpbWVWYWx1ZVdyYXBwZXIgaXNFbmxhcmdlZD17aXNFbmxhcmdlZH0+XG4gICAgPFRpbWVWYWx1ZSBrZXk9ezB9IHZhbHVlPXttb21lbnQudXRjKHZhbHVlWzBdKS5mb3JtYXQodGltZUZvcm1hdCl9IHNwbGl0PXshaXNFbmxhcmdlZH0vPlxuICAgIHtpc0VubGFyZ2VkID8gKFxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJob3Jpem9udGFsLWJhclwiPlxuICAgICAgICA8TWludXMgaGVpZ2h0PVwiMTJweFwiLz5cbiAgICAgIDwvZGl2PlxuICAgICkgOiBudWxsfVxuICAgIDxUaW1lVmFsdWUga2V5PXsxfSB2YWx1ZT17bW9tZW50LnV0Yyh2YWx1ZVsxXSkuZm9ybWF0KHRpbWVGb3JtYXQpfSBzcGxpdD17IWlzRW5sYXJnZWR9Lz5cbiAgPC9UaW1lVmFsdWVXcmFwcGVyPlxuKTtcblxuY29uc3QgVGltZVZhbHVlID0gKHt2YWx1ZSwgc3BsaXR9KSA9PiAoXG4gIC8vIHJlbmRlciB0d28gbGluZXMgaWYgbm90IGVubGFyZ2VkXG4gIDxkaXYgY2xhc3NOYW1lPVwidGltZS12YWx1ZVwiPlxuICAgIHtzcGxpdCA/IHZhbHVlLnNwbGl0KCcgJykubWFwKCh2LCBpKSA9PiAoXG4gICAgICA8ZGl2IGtleT17aX0+XG4gICAgICAgIHtpID09PSAwID8gPFNlbGVjdFRleHQ+e3Z9PC9TZWxlY3RUZXh0PiA6XG4gICAgICAgIDxTZWxlY3RUZXh0Qm9sZD57dn08L1NlbGVjdFRleHRCb2xkPn1cbiAgICAgIDwvZGl2PlxuICAgICkpIDogPFNlbGVjdFRleHRCb2xkPnt2YWx1ZX08L1NlbGVjdFRleHRCb2xkPn1cbiAgPC9kaXY+XG4pO1xuXG5jb25zdCBTdHlsZWRBbmltYXRpb25Db250cm9scyA9IHN0eWxlZC5kaXZgXG4gIG1hcmdpbi1ib3R0b206IDEycHg7XG4gIG1hcmdpbi1yaWdodDogNDJweDtcblxuICAmLmRpc2FibGVkIHtcbiAgICBvcGFjaXR5OiAwLjQ7XG4gICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gIH1cbmA7XG5cbmNvbnN0IEljb25CdXR0b24gPSBCdXR0b24uZXh0ZW5kYFxuICBzdmcge1xuICAgIG1hcmdpbjogMCA2cHg7XG4gIH1cbmA7XG5cbmNvbnN0IEFuaW1hdGlvbkNvbnRyb2xzID0gKHtcbiAgaXNBbmltYXRhYmxlLFxuICBpc0FuaW1hdGluZyxcbiAgcGF1c2VBbmltYXRpb24sXG4gIHJlc2V0QW5pbWF0aW9uLFxuICBzdGFydEFuaW1hdGlvblxufSkgPT4gKFxuICA8U3R5bGVkQW5pbWF0aW9uQ29udHJvbHNcbiAgICBjbGFzc05hbWU9e2NsYXNzbmFtZXMoJ3RpbWUtcmFuZ2Utc2xpZGVyX19jb250cm9sJywge2Rpc2FibGVkOiAhaXNBbmltYXRhYmxlfSl9XG4gID5cbiAgICA8QnV0dG9uR3JvdXA+XG4gICAgICA8SWNvbkJ1dHRvbiBjbGFzc05hbWU9XCJwbGF5YmFjay1jb250cm9sLWJ1dHRvblwiXG4gICAgICAgIG9uQ2xpY2s9e3Jlc2V0QW5pbWF0aW9ufSBzZWNvbmRhcnk+XG4gICAgICAgIDxSZXNldCBoZWlnaHQ9XCIxMnB4XCIvPlxuICAgICAgPC9JY29uQnV0dG9uPlxuICAgICAgPEljb25CdXR0b24gY2xhc3NOYW1lPXtjbGFzc25hbWVzKCdwbGF5YmFjay1jb250cm9sLWJ1dHRvbicsIHthY3RpdmU6IGlzQW5pbWF0aW5nfSl9XG4gICAgICAgIG9uQ2xpY2s9e2lzQW5pbWF0aW5nID8gcGF1c2VBbmltYXRpb24gOiBzdGFydEFuaW1hdGlvbn0gc2Vjb25kYXJ5PlxuICAgICAgICB7aXNBbmltYXRpbmcgPyA8UGF1c2UgaGVpZ2h0PVwiMTJweFwiLz4gOiA8UGxheSBoZWlnaHQ9XCIxMnB4XCIvPn1cbiAgICAgIDwvSWNvbkJ1dHRvbj5cbiAgICA8L0J1dHRvbkdyb3VwPlxuICA8L1N0eWxlZEFuaW1hdGlvbkNvbnRyb2xzPlxuKTtcbiJdfQ==