kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
246 lines (236 loc) • 30.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCursor = getCursor;
exports.getTooltip = getTooltip;
exports.isDrawingActive = isDrawingActive;
exports.onClick = onClick;
exports.onHover = onHover;
var _constants = require("@kepler.gl/constants");
// SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
/**
* Returns true if drawing is active.
* @param editorMenuActive Indicates whether the editor side menu is active.
* @param mode Current editing mode.
* @returs Returns true if drawing is active.
*/
function isDrawingActive(editorMenuActive, mode) {
return editorMenuActive && (mode === _constants.EDITOR_MODES.DRAW_POLYGON || mode === _constants.EDITOR_MODES.DRAW_RECTANGLE);
}
/**
* Handles click event for Editor layer.
* @param info Information about clicked object.
* @param event Event object.
* @param params
* @param params.editorMenuActive
* @param params.editor
* @param params.onLayerClick
* @param params.setSelectedFeature
* @param params.mapIndex
* @returns Returns true is the click is handled.
*/
// eslint-disable-next-line complexity
function onClick(info, event, _ref) {
var _info$layer;
var editorMenuActive = _ref.editorMenuActive,
editor = _ref.editor,
setSelectedFeature = _ref.setSelectedFeature,
onLayerClick = _ref.onLayerClick,
_ref$mapIndex = _ref.mapIndex,
mapIndex = _ref$mapIndex === void 0 ? 0 : _ref$mapIndex;
var drawingActive = isDrawingActive(editorMenuActive, editor.mode);
if ((info === null || info === void 0 || (_info$layer = info.layer) === null || _info$layer === void 0 ? void 0 : _info$layer.id) === _constants.EDITOR_LAYER_ID && info !== null && info !== void 0 && info.object) {
var _info$object$geometry;
var objectType = (_info$object$geometry = info.object.geometry) === null || _info$object$geometry === void 0 ? void 0 : _info$object$geometry.type;
if (drawingActive) {
if (editor.selectedFeature) {
setSelectedFeature(null);
}
} else if (objectType !== null && objectType !== void 0 && objectType.endsWith('Polygon') || objectType !== null && objectType !== void 0 && objectType.endsWith('Point')) {
var _event$srcEvent;
var clickContext;
if (event.rightButton && Array.isArray((_event$srcEvent = event.srcEvent) === null || _event$srcEvent === void 0 ? void 0 : _event$srcEvent.point)) {
var point = event.srcEvent.point;
clickContext = {
mapIndex: mapIndex,
rightClick: true,
position: {
x: point[0],
y: point[1]
}
};
}
if (objectType !== null && objectType !== void 0 && objectType.endsWith('Polygon')) {
setSelectedFeature(info.object, clickContext);
} else {
// don't select points
setSelectedFeature(editor.selectedFeature, clickContext);
}
}
// hide tooltips from regular data layers
onLayerClick(null, event);
} else if (drawingActive) {
// prevent interaction with other layers
onLayerClick(null, event);
} else {
if (editor.selectedFeature) {
if (event.rightButton) {
return true;
}
// click outside removes selection
setSelectedFeature(null);
}
return false;
}
return true;
}
/**
* Handles hover event for Editor layer.
* @param info Information about hovered object.
* @param params
* @param params.editorMenuActive
* @param params.editor
* @param params.hoverInfo
* @returns Returns true is hover is handled.
*/
function onHover(info, _ref2) {
var _info$layer2, _hoverInfo$layer;
var hoverInfo = _ref2.hoverInfo,
editor = _ref2.editor,
editorMenuActive = _ref2.editorMenuActive;
if (isDrawingActive(editorMenuActive, editor.mode)) {
return true;
}
return (info === null || info === void 0 || (_info$layer2 = info.layer) === null || _info$layer2 === void 0 ? void 0 : _info$layer2.id) === _constants.EDITOR_LAYER_ID && (hoverInfo === null || hoverInfo === void 0 || (_hoverInfo$layer = hoverInfo.layer) === null || _hoverInfo$layer === void 0 ? void 0 : _hoverInfo$layer.id) === _constants.EDITOR_LAYER_ID;
}
/**
* For small tooltips with short messages, e.g. "Drag to move the point",
* use the values below to decide when to position a tooltip to the left
* of the cursor or above the cursor, depending on proximity to the edge of
* the viewport to prevent the tooltip from being cut off.
*/
var MIN_DISTANCE_TO_LEFT_EDGE = 200;
var MIN_DISTANCE_TO_BOTTOM_EDGE = 100;
/**
* Returns tooltip based on interactions with Editor layer.
* @param info Information about hovered object.
* @param params
* @param params.editorMenuActive
* @param params.editor
* @param params.theme
* @raturns Returns a tooltip object compatible with Deck.getTooltip()
*/
// eslint-disable-next-line complexity
function getTooltip(
// TODO PickInfo type in deck typings doesn't include viewport and pixel
info, _ref3) {
var _editor$selectionCont;
var editor = _ref3.editor,
theme = _ref3.theme,
editorMenuActive = _ref3.editorMenuActive;
var object = info.object,
layer = info.layer,
_info$viewport = info.viewport,
viewport = _info$viewport === void 0 ? {} : _info$viewport,
_info$pixel = info.pixel,
pixel = _info$pixel === void 0 ? [] : _info$pixel;
var closeToLeftEdge = (viewport === null || viewport === void 0 ? void 0 : viewport.width) - pixel[0] < MIN_DISTANCE_TO_LEFT_EDGE;
var closeToBottomEdge = (viewport === null || viewport === void 0 ? void 0 : viewport.height) - pixel[1] < MIN_DISTANCE_TO_BOTTOM_EDGE;
// don't show the tooltip when the menu is visible
if ((_editor$selectionCont = editor.selectionContext) !== null && _editor$selectionCont !== void 0 && _editor$selectionCont.rightClick) {
return null;
}
if (isDrawingActive(editorMenuActive, editor.mode)) {
var _layer$state;
// TODO save interaction state in editor object
if (layer !== null && layer !== void 0 && (_layer$state = layer.state) !== null && _layer$state !== void 0 && (_layer$state = _layer$state.mode) !== null && _layer$state !== void 0 && (_layer$state = _layer$state._clickSequence) !== null && _layer$state !== void 0 && _layer$state.length) {
return null;
}
return getTooltipObject('Click to start new feature', theme, {
leftOfCursor: closeToLeftEdge,
aboveCursor: closeToBottomEdge
});
}
if ((layer === null || layer === void 0 ? void 0 : layer.id) === _constants.EDITOR_LAYER_ID) {
var _object$properties, _object$geometry, _object$properties2;
var selectedFeature = editor.selectedFeature;
if (selectedFeature) {
if (!object || object.id && object.id === selectedFeature.id) {
return getTooltipObject('Right click to view options\nDrag to move the feature', theme, {
leftOfCursor: closeToLeftEdge,
aboveCursor: closeToBottomEdge
});
}
}
if ((object === null || object === void 0 || (_object$properties = object.properties) === null || _object$properties === void 0 ? void 0 : _object$properties.editHandleType) === 'intermediate') {
return getTooltipObject('Click to insert a point', theme, {
leftOfCursor: closeToLeftEdge,
aboveCursor: closeToBottomEdge
});
}
if ((object === null || object === void 0 || (_object$geometry = object.geometry) === null || _object$geometry === void 0 ? void 0 : _object$geometry.type) === 'Point' || (object === null || object === void 0 || (_object$properties2 = object.properties) === null || _object$properties2 === void 0 ? void 0 : _object$properties2.guideType) === 'tentative') {
return getTooltipObject('Drag to move the point', theme, {
leftOfCursor: closeToLeftEdge,
aboveCursor: closeToBottomEdge
});
}
return getTooltipObject('Click to select the feature\nRight click to view options', theme, {
leftOfCursor: closeToLeftEdge,
aboveCursor: closeToBottomEdge
});
}
return null;
}
/**
* Returns cursor type based on interactions with Editor layer.
* @param params
* @param params.editorMenuActive
* @param params.editor
* @param params.hoverInfo
* @returns Returns cursor type.
*/
function getCursor(_ref4) {
var _hoverInfo$layer2;
var editorMenuActive = _ref4.editorMenuActive,
editor = _ref4.editor,
hoverInfo = _ref4.hoverInfo;
if (isDrawingActive(editorMenuActive, editor.mode)) {
return 'crosshair';
}
if ((hoverInfo === null || hoverInfo === void 0 || (_hoverInfo$layer2 = hoverInfo.layer) === null || _hoverInfo$layer2 === void 0 ? void 0 : _hoverInfo$layer2.id) === _constants.EDITOR_LAYER_ID && editor.selectedFeature) {
return 'move';
}
return null;
}
/**
* Returns a tooltip object that can be used as a Deck tooltip.
* Positioning can be modified if the cursor is close to the bottom or left edge of the viewport.
* @param text Text to show.
* @param theme Current theme.
* @param position.leftOfCursor Tooltip should display to the left of the cursor.
* @param position.aboveCursor Tooltip should display above cursor.
*/
function getTooltipObject(text, theme, position) {
var leftOfCursor = position.leftOfCursor,
aboveCursor = position.aboveCursor;
var marginTop = aboveCursor ? '-70px' : '15px';
var marginLeft = leftOfCursor ? '-200px' : '15px';
return {
text: text,
style: {
'margin-top': marginTop,
'margin-left': marginLeft,
'font-family': theme.fontFamily,
'font-size': theme.tooltipFontSize,
'font-weight': 400,
padding: '7px 18px',
'box-shadow': theme.tooltipBoxShadow,
'background-color': theme.tooltipBg,
color: theme.tooltipColor,
'border-radius': theme.primaryBtnRadius
}
};
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29uc3RhbnRzIiwicmVxdWlyZSIsImlzRHJhd2luZ0FjdGl2ZSIsImVkaXRvck1lbnVBY3RpdmUiLCJtb2RlIiwiRURJVE9SX01PREVTIiwiRFJBV19QT0xZR09OIiwiRFJBV19SRUNUQU5HTEUiLCJvbkNsaWNrIiwiaW5mbyIsImV2ZW50IiwiX3JlZiIsIl9pbmZvJGxheWVyIiwiZWRpdG9yIiwic2V0U2VsZWN0ZWRGZWF0dXJlIiwib25MYXllckNsaWNrIiwiX3JlZiRtYXBJbmRleCIsIm1hcEluZGV4IiwiZHJhd2luZ0FjdGl2ZSIsImxheWVyIiwiaWQiLCJFRElUT1JfTEFZRVJfSUQiLCJvYmplY3QiLCJfaW5mbyRvYmplY3QkZ2VvbWV0cnkiLCJvYmplY3RUeXBlIiwiZ2VvbWV0cnkiLCJ0eXBlIiwic2VsZWN0ZWRGZWF0dXJlIiwiZW5kc1dpdGgiLCJfZXZlbnQkc3JjRXZlbnQiLCJjbGlja0NvbnRleHQiLCJyaWdodEJ1dHRvbiIsIkFycmF5IiwiaXNBcnJheSIsInNyY0V2ZW50IiwicG9pbnQiLCJyaWdodENsaWNrIiwicG9zaXRpb24iLCJ4IiwieSIsIm9uSG92ZXIiLCJfcmVmMiIsIl9pbmZvJGxheWVyMiIsIl9ob3ZlckluZm8kbGF5ZXIiLCJob3ZlckluZm8iLCJNSU5fRElTVEFOQ0VfVE9fTEVGVF9FREdFIiwiTUlOX0RJU1RBTkNFX1RPX0JPVFRPTV9FREdFIiwiZ2V0VG9vbHRpcCIsIl9yZWYzIiwiX2VkaXRvciRzZWxlY3Rpb25Db250IiwidGhlbWUiLCJfaW5mbyR2aWV3cG9ydCIsInZpZXdwb3J0IiwiX2luZm8kcGl4ZWwiLCJwaXhlbCIsImNsb3NlVG9MZWZ0RWRnZSIsIndpZHRoIiwiY2xvc2VUb0JvdHRvbUVkZ2UiLCJoZWlnaHQiLCJzZWxlY3Rpb25Db250ZXh0IiwiX2xheWVyJHN0YXRlIiwic3RhdGUiLCJfY2xpY2tTZXF1ZW5jZSIsImxlbmd0aCIsImdldFRvb2x0aXBPYmplY3QiLCJsZWZ0T2ZDdXJzb3IiLCJhYm92ZUN1cnNvciIsIl9vYmplY3QkcHJvcGVydGllcyIsIl9vYmplY3QkZ2VvbWV0cnkiLCJfb2JqZWN0JHByb3BlcnRpZXMyIiwicHJvcGVydGllcyIsImVkaXRIYW5kbGVUeXBlIiwiZ3VpZGVUeXBlIiwiZ2V0Q3Vyc29yIiwiX3JlZjQiLCJfaG92ZXJJbmZvJGxheWVyMiIsInRleHQiLCJtYXJnaW5Ub3AiLCJtYXJnaW5MZWZ0Iiwic3R5bGUiLCJmb250RmFtaWx5IiwidG9vbHRpcEZvbnRTaXplIiwicGFkZGluZyIsInRvb2x0aXBCb3hTaGFkb3ciLCJ0b29sdGlwQmciLCJjb2xvciIsInRvb2x0aXBDb2xvciIsInByaW1hcnlCdG5SYWRpdXMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvZWRpdG9yLWxheWVyL2VkaXRvci1sYXllci11dGlscy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQge1BpY2tJbmZvfSBmcm9tICdAZGVjay5nbC9jb3JlL2xpYi9kZWNrJztcbmltcG9ydCB7RWRpdG9yLCBGZWF0dXJlLCBGZWF0dXJlU2VsZWN0aW9uQ29udGV4dH0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge0VESVRPUl9MQVlFUl9JRCwgRURJVE9SX01PREVTfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIGRyYXdpbmcgaXMgYWN0aXZlLlxuICogQHBhcmFtIGVkaXRvck1lbnVBY3RpdmUgSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGVkaXRvciBzaWRlIG1lbnUgaXMgYWN0aXZlLlxuICogQHBhcmFtIG1vZGUgQ3VycmVudCBlZGl0aW5nIG1vZGUuXG4gKiBAcmV0dXJzIFJldHVybnMgdHJ1ZSBpZiBkcmF3aW5nIGlzIGFjdGl2ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRHJhd2luZ0FjdGl2ZShlZGl0b3JNZW51QWN0aXZlOiBib29sZWFuLCBtb2RlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBlZGl0b3JNZW51QWN0aXZlICYmIChtb2RlID09PSBFRElUT1JfTU9ERVMuRFJBV19QT0xZR09OIHx8IG1vZGUgPT09IEVESVRPUl9NT0RFUy5EUkFXX1JFQ1RBTkdMRSlcbiAgKTtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIGNsaWNrIGV2ZW50IGZvciBFZGl0b3IgbGF5ZXIuXG4gKiBAcGFyYW0gaW5mbyBJbmZvcm1hdGlvbiBhYm91dCBjbGlja2VkIG9iamVjdC5cbiAqIEBwYXJhbSBldmVudCBFdmVudCBvYmplY3QuXG4gKiBAcGFyYW0gcGFyYW1zXG4gKiBAcGFyYW0gcGFyYW1zLmVkaXRvck1lbnVBY3RpdmVcbiAqIEBwYXJhbSBwYXJhbXMuZWRpdG9yXG4gKiBAcGFyYW0gcGFyYW1zLm9uTGF5ZXJDbGlja1xuICogQHBhcmFtIHBhcmFtcy5zZXRTZWxlY3RlZEZlYXR1cmVcbiAqIEBwYXJhbSBwYXJhbXMubWFwSW5kZXhcbiAqIEByZXR1cm5zIFJldHVybnMgdHJ1ZSBpcyB0aGUgY2xpY2sgaXMgaGFuZGxlZC5cbiAqL1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbmV4cG9ydCBmdW5jdGlvbiBvbkNsaWNrKFxuICBpbmZvOiBQaWNrSW5mbzxhbnk+LFxuICBldmVudDogYW55LFxuICB7XG4gICAgZWRpdG9yTWVudUFjdGl2ZSxcbiAgICBlZGl0b3IsXG4gICAgc2V0U2VsZWN0ZWRGZWF0dXJlLFxuICAgIG9uTGF5ZXJDbGljayxcbiAgICBtYXBJbmRleCA9IDBcbiAgfToge1xuICAgIGVkaXRvck1lbnVBY3RpdmU6IGJvb2xlYW47XG4gICAgZWRpdG9yOiBFZGl0b3I7XG4gICAgb25MYXllckNsaWNrOiAoZGF0YSwgY2xpY2tFdmVudCkgPT4gYW55O1xuICAgIHNldFNlbGVjdGVkRmVhdHVyZTogKFxuICAgICAgZmVhdHVyZTogRmVhdHVyZSB8IG51bGwsXG4gICAgICBzZWxlY3Rpb25Db250ZXh0PzogRmVhdHVyZVNlbGVjdGlvbkNvbnRleHRcbiAgICApID0+IGFueTtcbiAgICBtYXBJbmRleD86IG51bWJlcjtcbiAgfVxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGRyYXdpbmdBY3RpdmUgPSBpc0RyYXdpbmdBY3RpdmUoZWRpdG9yTWVudUFjdGl2ZSwgZWRpdG9yLm1vZGUpO1xuXG4gIGlmIChpbmZvPy5sYXllcj8uaWQgPT09IEVESVRPUl9MQVlFUl9JRCAmJiBpbmZvPy5vYmplY3QpIHtcbiAgICBjb25zdCBvYmplY3RUeXBlID0gaW5mby5vYmplY3QuZ2VvbWV0cnk/LnR5cGU7XG5cbiAgICBpZiAoZHJhd2luZ0FjdGl2ZSkge1xuICAgICAgaWYgKGVkaXRvci5zZWxlY3RlZEZlYXR1cmUpIHtcbiAgICAgICAgc2V0U2VsZWN0ZWRGZWF0dXJlKG51bGwpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAob2JqZWN0VHlwZT8uZW5kc1dpdGgoJ1BvbHlnb24nKSB8fCBvYmplY3RUeXBlPy5lbmRzV2l0aCgnUG9pbnQnKSkge1xuICAgICAgbGV0IGNsaWNrQ29udGV4dDtcbiAgICAgIGlmIChldmVudC5yaWdodEJ1dHRvbiAmJiBBcnJheS5pc0FycmF5KGV2ZW50LnNyY0V2ZW50Py5wb2ludCkpIHtcbiAgICAgICAgY29uc3Qge3BvaW50fSA9IGV2ZW50LnNyY0V2ZW50O1xuICAgICAgICBjbGlja0NvbnRleHQgPSB7XG4gICAgICAgICAgbWFwSW5kZXgsXG4gICAgICAgICAgcmlnaHRDbGljazogdHJ1ZSxcbiAgICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogcG9pbnRbMF0sXG4gICAgICAgICAgICB5OiBwb2ludFsxXVxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9iamVjdFR5cGU/LmVuZHNXaXRoKCdQb2x5Z29uJykpIHtcbiAgICAgICAgc2V0U2VsZWN0ZWRGZWF0dXJlKGluZm8ub2JqZWN0LCBjbGlja0NvbnRleHQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZG9uJ3Qgc2VsZWN0IHBvaW50c1xuICAgICAgICBzZXRTZWxlY3RlZEZlYXR1cmUoZWRpdG9yLnNlbGVjdGVkRmVhdHVyZSwgY2xpY2tDb250ZXh0KTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gaGlkZSB0b29sdGlwcyBmcm9tIHJlZ3VsYXIgZGF0YSBsYXllcnNcbiAgICBvbkxheWVyQ2xpY2sobnVsbCwgZXZlbnQpO1xuICB9IGVsc2UgaWYgKGRyYXdpbmdBY3RpdmUpIHtcbiAgICAvLyBwcmV2ZW50IGludGVyYWN0aW9uIHdpdGggb3RoZXIgbGF5ZXJzXG4gICAgb25MYXllckNsaWNrKG51bGwsIGV2ZW50KTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoZWRpdG9yLnNlbGVjdGVkRmVhdHVyZSkge1xuICAgICAgaWYgKGV2ZW50LnJpZ2h0QnV0dG9uKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBjbGljayBvdXRzaWRlIHJlbW92ZXMgc2VsZWN0aW9uXG4gICAgICBzZXRTZWxlY3RlZEZlYXR1cmUobnVsbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgaG92ZXIgZXZlbnQgZm9yIEVkaXRvciBsYXllci5cbiAqIEBwYXJhbSBpbmZvIEluZm9ybWF0aW9uIGFib3V0IGhvdmVyZWQgb2JqZWN0LlxuICogQHBhcmFtIHBhcmFtc1xuICogQHBhcmFtIHBhcmFtcy5lZGl0b3JNZW51QWN0aXZlXG4gKiBAcGFyYW0gcGFyYW1zLmVkaXRvclxuICogQHBhcmFtIHBhcmFtcy5ob3ZlckluZm9cbiAqIEByZXR1cm5zIFJldHVybnMgdHJ1ZSBpcyBob3ZlciBpcyBoYW5kbGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb25Ib3ZlcihcbiAgaW5mbzogUGlja0luZm88YW55PixcbiAge2hvdmVySW5mbywgZWRpdG9yLCBlZGl0b3JNZW51QWN0aXZlfToge2VkaXRvck1lbnVBY3RpdmU6IGJvb2xlYW47IGVkaXRvcjogRWRpdG9yOyBob3ZlckluZm99XG4pOiBib29sZWFuIHtcbiAgaWYgKGlzRHJhd2luZ0FjdGl2ZShlZGl0b3JNZW51QWN0aXZlLCBlZGl0b3IubW9kZSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBpbmZvPy5sYXllcj8uaWQgPT09IEVESVRPUl9MQVlFUl9JRCAmJiBob3ZlckluZm8/LmxheWVyPy5pZCA9PT0gRURJVE9SX0xBWUVSX0lEO1xufVxuXG4vKipcbiAqIEZvciBzbWFsbCB0b29sdGlwcyB3aXRoIHNob3J0IG1lc3NhZ2VzLCBlLmcuIFwiRHJhZyB0byBtb3ZlIHRoZSBwb2ludFwiLFxuICogdXNlIHRoZSB2YWx1ZXMgYmVsb3cgdG8gZGVjaWRlIHdoZW4gdG8gcG9zaXRpb24gYSB0b29sdGlwIHRvIHRoZSBsZWZ0XG4gKiBvZiB0aGUgY3Vyc29yIG9yIGFib3ZlIHRoZSBjdXJzb3IsIGRlcGVuZGluZyBvbiBwcm94aW1pdHkgdG8gdGhlIGVkZ2Ugb2ZcbiAqIHRoZSB2aWV3cG9ydCB0byBwcmV2ZW50IHRoZSB0b29sdGlwIGZyb20gYmVpbmcgY3V0IG9mZi5cbiAqL1xuY29uc3QgTUlOX0RJU1RBTkNFX1RPX0xFRlRfRURHRSA9IDIwMDtcbmNvbnN0IE1JTl9ESVNUQU5DRV9UT19CT1RUT01fRURHRSA9IDEwMDtcblxuLyoqXG4gKiBSZXR1cm5zIHRvb2x0aXAgYmFzZWQgb24gaW50ZXJhY3Rpb25zIHdpdGggRWRpdG9yIGxheWVyLlxuICogQHBhcmFtIGluZm8gSW5mb3JtYXRpb24gYWJvdXQgaG92ZXJlZCBvYmplY3QuXG4gKiBAcGFyYW0gcGFyYW1zXG4gKiBAcGFyYW0gcGFyYW1zLmVkaXRvck1lbnVBY3RpdmVcbiAqIEBwYXJhbSBwYXJhbXMuZWRpdG9yXG4gKiBAcGFyYW0gcGFyYW1zLnRoZW1lXG4gKiBAcmF0dXJucyBSZXR1cm5zIGEgdG9vbHRpcCBvYmplY3QgY29tcGF0aWJsZSB3aXRoIERlY2suZ2V0VG9vbHRpcCgpXG4gKi9cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5leHBvcnQgZnVuY3Rpb24gZ2V0VG9vbHRpcChcbiAgLy8gVE9ETyBQaWNrSW5mbyB0eXBlIGluIGRlY2sgdHlwaW5ncyBkb2Vzbid0IGluY2x1ZGUgdmlld3BvcnQgYW5kIHBpeGVsXG4gIGluZm86IFBpY2tJbmZvPGFueT4gJiB7dmlld3BvcnQ6IGFueTsgcGl4ZWw6IGFueVtdfSxcbiAge2VkaXRvciwgdGhlbWUsIGVkaXRvck1lbnVBY3RpdmV9OiB7ZWRpdG9yTWVudUFjdGl2ZTogYm9vbGVhbjsgZWRpdG9yOiBFZGl0b3I7IHRoZW1lOiBhbnl9XG4pOiBvYmplY3QgfCBudWxsIHtcbiAgY29uc3Qge29iamVjdCwgbGF5ZXIsIHZpZXdwb3J0ID0ge30sIHBpeGVsID0gW119ID0gaW5mbztcbiAgY29uc3QgY2xvc2VUb0xlZnRFZGdlID0gdmlld3BvcnQ/LndpZHRoIC0gcGl4ZWxbMF0gPCBNSU5fRElTVEFOQ0VfVE9fTEVGVF9FREdFO1xuICBjb25zdCBjbG9zZVRvQm90dG9tRWRnZSA9IHZpZXdwb3J0Py5oZWlnaHQgLSBwaXhlbFsxXSA8IE1JTl9ESVNUQU5DRV9UT19CT1RUT01fRURHRTtcblxuICAvLyBkb24ndCBzaG93IHRoZSB0b29sdGlwIHdoZW4gdGhlIG1lbnUgaXMgdmlzaWJsZVxuICBpZiAoZWRpdG9yLnNlbGVjdGlvbkNvbnRleHQ/LnJpZ2h0Q2xpY2spIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmIChpc0RyYXdpbmdBY3RpdmUoZWRpdG9yTWVudUFjdGl2ZSwgZWRpdG9yLm1vZGUpKSB7XG4gICAgLy8gVE9ETyBzYXZlIGludGVyYWN0aW9uIHN0YXRlIGluIGVkaXRvciBvYmplY3RcbiAgICBpZiAobGF5ZXI/LnN0YXRlPy5tb2RlPy5fY2xpY2tTZXF1ZW5jZT8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0VG9vbHRpcE9iamVjdCgnQ2xpY2sgdG8gc3RhcnQgbmV3IGZlYXR1cmUnLCB0aGVtZSwge1xuICAgICAgbGVmdE9mQ3Vyc29yOiBjbG9zZVRvTGVmdEVkZ2UsXG4gICAgICBhYm92ZUN1cnNvcjogY2xvc2VUb0JvdHRvbUVkZ2VcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChsYXllcj8uaWQgPT09IEVESVRPUl9MQVlFUl9JRCkge1xuICAgIGNvbnN0IHtzZWxlY3RlZEZlYXR1cmV9ID0gZWRpdG9yO1xuXG4gICAgaWYgKHNlbGVjdGVkRmVhdHVyZSkge1xuICAgICAgaWYgKCFvYmplY3QgfHwgKG9iamVjdC5pZCAmJiBvYmplY3QuaWQgPT09IHNlbGVjdGVkRmVhdHVyZS5pZCkpIHtcbiAgICAgICAgcmV0dXJuIGdldFRvb2x0aXBPYmplY3QoJ1JpZ2h0IGNsaWNrIHRvIHZpZXcgb3B0aW9uc1xcbkRyYWcgdG8gbW92ZSB0aGUgZmVhdHVyZScsIHRoZW1lLCB7XG4gICAgICAgICAgbGVmdE9mQ3Vyc29yOiBjbG9zZVRvTGVmdEVkZ2UsXG4gICAgICAgICAgYWJvdmVDdXJzb3I6IGNsb3NlVG9Cb3R0b21FZGdlXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChvYmplY3Q/LnByb3BlcnRpZXM/LmVkaXRIYW5kbGVUeXBlID09PSAnaW50ZXJtZWRpYXRlJykge1xuICAgICAgcmV0dXJuIGdldFRvb2x0aXBPYmplY3QoJ0NsaWNrIHRvIGluc2VydCBhIHBvaW50JywgdGhlbWUsIHtcbiAgICAgICAgbGVmdE9mQ3Vyc29yOiBjbG9zZVRvTGVmdEVkZ2UsXG4gICAgICAgIGFib3ZlQ3Vyc29yOiBjbG9zZVRvQm90dG9tRWRnZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKG9iamVjdD8uZ2VvbWV0cnk/LnR5cGUgPT09ICdQb2ludCcgfHwgb2JqZWN0Py5wcm9wZXJ0aWVzPy5ndWlkZVR5cGUgPT09ICd0ZW50YXRpdmUnKSB7XG4gICAgICByZXR1cm4gZ2V0VG9vbHRpcE9iamVjdCgnRHJhZyB0byBtb3ZlIHRoZSBwb2ludCcsIHRoZW1lLCB7XG4gICAgICAgIGxlZnRPZkN1cnNvcjogY2xvc2VUb0xlZnRFZGdlLFxuICAgICAgICBhYm92ZUN1cnNvcjogY2xvc2VUb0JvdHRvbUVkZ2VcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBnZXRUb29sdGlwT2JqZWN0KCdDbGljayB0byBzZWxlY3QgdGhlIGZlYXR1cmVcXG5SaWdodCBjbGljayB0byB2aWV3IG9wdGlvbnMnLCB0aGVtZSwge1xuICAgICAgbGVmdE9mQ3Vyc29yOiBjbG9zZVRvTGVmdEVkZ2UsXG4gICAgICBhYm92ZUN1cnNvcjogY2xvc2VUb0JvdHRvbUVkZ2VcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgY3Vyc29yIHR5cGUgYmFzZWQgb24gaW50ZXJhY3Rpb25zIHdpdGggRWRpdG9yIGxheWVyLlxuICogQHBhcmFtIHBhcmFtc1xuICogQHBhcmFtIHBhcmFtcy5lZGl0b3JNZW51QWN0aXZlXG4gKiBAcGFyYW0gcGFyYW1zLmVkaXRvclxuICogQHBhcmFtIHBhcmFtcy5ob3ZlckluZm9cbiAqIEByZXR1cm5zIFJldHVybnMgY3Vyc29yIHR5cGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDdXJzb3Ioe1xuICBlZGl0b3JNZW51QWN0aXZlLFxuICBlZGl0b3IsXG4gIGhvdmVySW5mb1xufToge1xuICBlZGl0b3JNZW51QWN0aXZlOiBib29sZWFuO1xuICBlZGl0b3I6IEVkaXRvcjtcbiAgaG92ZXJJbmZvOiBhbnk7XG59KTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmIChpc0RyYXdpbmdBY3RpdmUoZWRpdG9yTWVudUFjdGl2ZSwgZWRpdG9yLm1vZGUpKSB7XG4gICAgcmV0dXJuICdjcm9zc2hhaXInO1xuICB9XG5cbiAgaWYgKGhvdmVySW5mbz8ubGF5ZXI/LmlkID09PSBFRElUT1JfTEFZRVJfSUQgJiYgZWRpdG9yLnNlbGVjdGVkRmVhdHVyZSkge1xuICAgIHJldHVybiAnbW92ZSc7XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgdG9vbHRpcCBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCBhcyBhIERlY2sgdG9vbHRpcC5cbiAqIFBvc2l0aW9uaW5nIGNhbiBiZSBtb2RpZmllZCBpZiB0aGUgY3Vyc29yIGlzIGNsb3NlIHRvIHRoZSBib3R0b20gb3IgbGVmdCBlZGdlIG9mIHRoZSB2aWV3cG9ydC5cbiAqIEBwYXJhbSB0ZXh0IFRleHQgdG8gc2hvdy5cbiAqIEBwYXJhbSB0aGVtZSBDdXJyZW50IHRoZW1lLlxuICogQHBhcmFtIHBvc2l0aW9uLmxlZnRPZkN1cnNvciBUb29sdGlwIHNob3VsZCBkaXNwbGF5IHRvIHRoZSBsZWZ0IG9mIHRoZSBjdXJzb3IuXG4gKiBAcGFyYW0gcG9zaXRpb24uYWJvdmVDdXJzb3IgVG9vbHRpcCBzaG91bGQgZGlzcGxheSBhYm92ZSBjdXJzb3IuXG4gKi9cbmZ1bmN0aW9uIGdldFRvb2x0aXBPYmplY3QoXG4gIHRleHQ6IHN0cmluZyxcbiAgdGhlbWU6IGFueSxcbiAgcG9zaXRpb246IHtsZWZ0T2ZDdXJzb3I6IGJvb2xlYW47IGFib3ZlQ3Vyc29yOiBib29sZWFufVxuKToge3RleHQ6IHN0cmluZzsgc3R5bGU6IG9iamVjdH0ge1xuICBjb25zdCB7bGVmdE9mQ3Vyc29yLCBhYm92ZUN1cnNvcn0gPSBwb3NpdGlvbjtcbiAgY29uc3QgbWFyZ2luVG9wID0gYWJvdmVDdXJzb3IgPyAnLTcwcHgnIDogJzE1cHgnO1xuICBjb25zdCBtYXJnaW5MZWZ0ID0gbGVmdE9mQ3Vyc29yID8gJy0yMDBweCcgOiAnMTVweCc7XG4gIHJldHVybiB7XG4gICAgdGV4dCxcbiAgICBzdHlsZToge1xuICAgICAgJ21hcmdpbi10b3AnOiBtYXJnaW5Ub3AsXG4gICAgICAnbWFyZ2luLWxlZnQnOiBtYXJnaW5MZWZ0LFxuICAgICAgJ2ZvbnQtZmFtaWx5JzogdGhlbWUuZm9udEZhbWlseSxcbiAgICAgICdmb250LXNpemUnOiB0aGVtZS50b29sdGlwRm9udFNpemUsXG4gICAgICAnZm9udC13ZWlnaHQnOiA0MDAsXG4gICAgICBwYWRkaW5nOiAnN3B4IDE4cHgnLFxuICAgICAgJ2JveC1zaGFkb3cnOiB0aGVtZS50b29sdGlwQm94U2hhZG93LFxuICAgICAgJ2JhY2tncm91bmQtY29sb3InOiB0aGVtZS50b29sdGlwQmcsXG4gICAgICBjb2xvcjogdGhlbWUudG9vbHRpcENvbG9yLFxuICAgICAgJ2JvcmRlci1yYWRpdXMnOiB0aGVtZS5wcmltYXJ5QnRuUmFkaXVzXG4gICAgfVxuICB9O1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBS0EsSUFBQUEsVUFBQSxHQUFBQyxPQUFBO0FBTEE7QUFDQTs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTQyxlQUFlQSxDQUFDQyxnQkFBeUIsRUFBRUMsSUFBWSxFQUFXO0VBQ2hGLE9BQ0VELGdCQUFnQixLQUFLQyxJQUFJLEtBQUtDLHVCQUFZLENBQUNDLFlBQVksSUFBSUYsSUFBSSxLQUFLQyx1QkFBWSxDQUFDRSxjQUFjLENBQUM7QUFFcEc7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTQyxPQUFPQSxDQUNyQkMsSUFBbUIsRUFDbkJDLEtBQVUsRUFBQUMsSUFBQSxFQWlCRDtFQUFBLElBQUFDLFdBQUE7RUFBQSxJQWZQVCxnQkFBZ0IsR0FBQVEsSUFBQSxDQUFoQlIsZ0JBQWdCO0lBQ2hCVSxNQUFNLEdBQUFGLElBQUEsQ0FBTkUsTUFBTTtJQUNOQyxrQkFBa0IsR0FBQUgsSUFBQSxDQUFsQkcsa0JBQWtCO0lBQ2xCQyxZQUFZLEdBQUFKLElBQUEsQ0FBWkksWUFBWTtJQUFBQyxhQUFBLEdBQUFMLElBQUEsQ0FDWk0sUUFBUTtJQUFSQSxRQUFRLEdBQUFE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U2dCLFNBQVNBLENBQUFDLEtBQUEsRUFRUDtFQUFBLElBQUFDLGlCQUFBO0VBQUEsSUFQaEJ4RSxnQkFBZ0IsR0FBQXVFLEtBQUEsQ0FBaEJ2RSxnQkFBZ0I7SUFDaEJVLE1BQU0sR0FBQTZELEtBQUEsQ0FBTjdELE1BQU07SUFDTitCLFNBQVMsR0FBQThCLEtBQUEsQ0FBVDlCLFNBQVM7RUFNVCxJQUFJMUMsZUFBZSxDQUFDQyxnQkFBZ0IsRUFBRVUsTUFBTSxDQUFDVCxJQUFJLENBQUMsRUFBRTtJQUNsRCxPQUFPLFdBQVc7RUFDcEI7RUFFQSxJQUFJLENBQUF3QyxTQUFTLGFBQVRBLFNBQVMsZ0JBQUErQixpQkFBQSxHQUFUL0IsU0FBUyxDQUFFekIsS0FBSyxjQUFBd0QsaUJBQUEsdUJBQWhCQSxpQkFBQSxDQUFrQnZELEVBQUUsTUFBS0MsMEJBQWUsSUFBSVIsTUFBTSxDQUFDYyxlQUFlLEVBQUU7SUFDdEUsT0FBTyxNQUFNO0VBQ2Y7RUFFQSxPQUFPLElBQUk7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU3FDLGdCQUFnQkEsQ0FDdkJZLElBQVksRUFDWjFCLEtBQVUsRUFDVmIsUUFBdUQsRUFDeEI7RUFDL0IsSUFBTzRCLFlBQVksR0FBaUI1QixRQUFRLENBQXJDNEIsWUFBWTtJQUFFQyxXQUFXLEdBQUk3QixRQUFRLENBQXZCNkIsV0FBVztFQUNoQyxJQUFNVyxTQUFTLEdBQUdYLFdBQVcsR0FBRyxPQUFPLEdBQUcsTUFBTTtFQUNoRCxJQUFNWSxVQUFVLEdBQUdiLFlBQVksR0FBRyxRQUFRLEdBQUcsTUFBTTtFQUNuRCxPQUFPO0lBQ0xXLElBQUksRUFBSkEsSUFBSTtJQUNKRyxLQUFLLEVBQUU7TUFDTCxZQUFZLEVBQUVGLFNBQVM7TUFDdkIsYUFBYSxFQUFFQyxVQUFVO01BQ3pCLGFBQWEsRUFBRTVCLEtBQUssQ0FBQzhCLFVBQVU7TUFDL0IsV0FBVyxFQUFFOUIsS0FBSyxDQUFDK0IsZUFBZTtNQUNsQyxhQUFhLEVBQUUsR0FBRztNQUNsQkMsT0FBTyxFQUFFLFVBQVU7TUFDbkIsWUFBWSxFQUFFaEMsS0FBSyxDQUFDaUMsZ0JBQWdCO01BQ3BDLGtCQUFrQixFQUFFakMsS0FBSyxDQUFDa0MsU0FBUztNQUNuQ0MsS0FBSyxFQUFFbkMsS0FBSyxDQUFDb0MsWUFBWTtNQUN6QixlQUFlLEVBQUVwQyxLQUFLLENBQUNxQztJQUN6QjtFQUNGLENBQUM7QUFDSCIsImlnbm9yZUxpc3QiOltdfQ==