@nebula.gl/layers
Version:
A suite of 3D-enabled data editing layers, suitable for deck.gl
235 lines (183 loc) • 24.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toDeckColor = toDeckColor;
exports.recursivelyTraverseNestedArrays = recursivelyTraverseNestedArrays;
exports.generatePointsParallelToLinePoints = generatePointsParallelToLinePoints;
exports.distance2d = distance2d;
exports.mix = mix;
exports.nearestPointOnProjectedLine = nearestPointOnProjectedLine;
exports.insertBefore = insertBefore;
var _destination = _interopRequireDefault(require("@turf/destination"));
var _bearing = _interopRequireDefault(require("@turf/bearing"));
var _pointToLineDistance = _interopRequireDefault(require("@turf/point-to-line-distance"));
var _helpers = require("@turf/helpers");
var _viewportMercatorProject = _interopRequireDefault(require("viewport-mercator-project"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function toDeckColor(color) {
var defaultColor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [255, 0, 0, 255];
if (!Array.isArray(color)) {
return defaultColor;
}
return [color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255];
} //
// a GeoJSON helper function that calls the provided function with
// an argument that is the most deeply-nested array having elements
// that are arrays of primitives as an argument, e.g.
//
// {
// "type": "MultiPolygon",
// "coordinates": [
// [
// [[30, 20], [45, 40], [10, 40], [30, 20]]
// ],
// [
// [[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]]
// ]
// ]
// }
//
// the function would be called on:
//
// [[30, 20], [45, 40], [10, 40], [30, 20]]
//
// and
//
// [[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]]
//
function recursivelyTraverseNestedArrays(array, prefix, fn) {
if (!Array.isArray(array[0])) {
return true;
}
for (var i = 0; i < array.length; i++) {
if (recursivelyTraverseNestedArrays(array[i], [].concat(_toConsumableArray(prefix), [i]), fn)) {
fn(array, prefix);
break;
}
}
return false;
}
function generatePointsParallelToLinePoints(p1, p2, groundCoords) {
var lineString = {
type: 'LineString',
coordinates: [p1, p2]
};
var pt = (0, _helpers.point)(groundCoords);
var ddistance = (0, _pointToLineDistance["default"])(pt, lineString);
var lineBearing = (0, _bearing["default"])(p1, p2); // Check if current point is to the left or right of line
// Line from A=(x1,y1) to B=(x2,y2) a point P=(x,y)
// then (x−x1)(y2−y1)−(y−y1)(x2−x1)
var isPointToLeftOfLine = (groundCoords[0] - p1[0]) * (p2[1] - p1[1]) - (groundCoords[1] - p1[1]) * (p2[0] - p1[0]); // Bearing to draw perpendicular to the line string
var orthogonalBearing = isPointToLeftOfLine < 0 ? lineBearing - 90 : lineBearing - 270; // Get coordinates for the point p3 and p4 which are perpendicular to the lineString
// Add the distance as the current position moves away from the lineString
var p3 = (0, _destination["default"])(p2, ddistance, orthogonalBearing);
var p4 = (0, _destination["default"])(p1, ddistance, orthogonalBearing); //@ts-ignore
return [p3.geometry.coordinates, p4.geometry.coordinates];
}
function distance2d(x1, y1, x2, y2) {
var dx = x1 - x2;
var dy = y1 - y2;
return Math.sqrt(dx * dx + dy * dy);
}
function mix(a, b, ratio) {
return b * ratio + a * (1 - ratio);
}
function nearestPointOnProjectedLine(line, inPoint, viewport) {
var wmViewport = new _viewportMercatorProject["default"](viewport); // Project the line to viewport, then find the nearest point
var coordinates = line.geometry.coordinates;
var projectedCoords = coordinates.map(function (_ref) {
var _ref2 = _slicedToArray(_ref, 3),
x = _ref2[0],
y = _ref2[1],
_ref2$ = _ref2[2],
z = _ref2$ === void 0 ? 0 : _ref2$;
return wmViewport.project([x, y, z]);
}); //@ts-ignore
var _wmViewport$project = wmViewport.project(inPoint.geometry.coordinates),
_wmViewport$project2 = _slicedToArray(_wmViewport$project, 2),
x = _wmViewport$project2[0],
y = _wmViewport$project2[1]; // console.log('projectedCoords', JSON.stringify(projectedCoords));
var minDistance = Infinity;
var minPointInfo = {};
projectedCoords.forEach(function (_ref3, index) {
var _ref4 = _slicedToArray(_ref3, 2),
x2 = _ref4[0],
y2 = _ref4[1];
if (index === 0) {
return;
}
var _projectedCoords = _slicedToArray(projectedCoords[index - 1], 2),
x1 = _projectedCoords[0],
y1 = _projectedCoords[1]; // line from projectedCoords[index - 1] to projectedCoords[index]
// convert to Ax + By + C = 0
var A = y1 - y2;
var B = x2 - x1;
var C = x1 * y2 - x2 * y1; // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
var div = A * A + B * B;
var distance = Math.abs(A * x + B * y + C) / Math.sqrt(div); // TODO: Check if inside bounds
if (distance < minDistance) {
minDistance = distance;
minPointInfo = {
index: index,
x0: (B * (B * x - A * y) - A * C) / div,
y0: (A * (-B * x + A * y) - B * C) / div
};
}
}); //@ts-ignore
var _minPointInfo = minPointInfo,
index = _minPointInfo.index,
x0 = _minPointInfo.x0,
y0 = _minPointInfo.y0;
var _projectedCoords2 = _slicedToArray(projectedCoords[index - 1], 3),
x1 = _projectedCoords2[0],
y1 = _projectedCoords2[1],
_projectedCoords2$ = _projectedCoords2[2],
z1 = _projectedCoords2$ === void 0 ? 0 : _projectedCoords2$;
var _projectedCoords$inde = _slicedToArray(projectedCoords[index], 3),
x2 = _projectedCoords$inde[0],
y2 = _projectedCoords$inde[1],
_projectedCoords$inde2 = _projectedCoords$inde[2],
z2 = _projectedCoords$inde2 === void 0 ? 0 : _projectedCoords$inde2; // calculate what ratio of the line we are on to find the proper z
var lineLength = distance2d(x1, y1, x2, y2);
var startToPointLength = distance2d(x1, y1, x0, y0);
var ratio = startToPointLength / lineLength;
var z0 = mix(z1, z2, ratio);
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: wmViewport.unproject([x0, y0, z0])
},
properties: {
// TODO: calculate the distance in proper units
dist: minDistance,
index: index - 1
}
};
}
/**
* Inserts toInsert string into base string before insertBefore string.
* @param base A string to insert into.
* @param insertBefore A sub string in `base` string to insert before.
* @param toInsert A string to insert.
* @returns Combined string. `base` string if `insertBefore` string isn't found.
*/
function insertBefore(base, insertBefore, toInsert) {
var at = base.indexOf(insertBefore);
if (at < 0) {
return base;
}
return base.slice(0, at) + toInsert + base.slice(at);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlscy50cyJdLCJuYW1lcyI6WyJ0b0RlY2tDb2xvciIsImNvbG9yIiwiZGVmYXVsdENvbG9yIiwiQXJyYXkiLCJpc0FycmF5IiwicmVjdXJzaXZlbHlUcmF2ZXJzZU5lc3RlZEFycmF5cyIsImFycmF5IiwicHJlZml4IiwiZm4iLCJpIiwibGVuZ3RoIiwiZ2VuZXJhdGVQb2ludHNQYXJhbGxlbFRvTGluZVBvaW50cyIsInAxIiwicDIiLCJncm91bmRDb29yZHMiLCJsaW5lU3RyaW5nIiwidHlwZSIsImNvb3JkaW5hdGVzIiwicHQiLCJkZGlzdGFuY2UiLCJsaW5lQmVhcmluZyIsImlzUG9pbnRUb0xlZnRPZkxpbmUiLCJvcnRob2dvbmFsQmVhcmluZyIsInAzIiwicDQiLCJnZW9tZXRyeSIsImRpc3RhbmNlMmQiLCJ4MSIsInkxIiwieDIiLCJ5MiIsImR4IiwiZHkiLCJNYXRoIiwic3FydCIsIm1peCIsImEiLCJiIiwicmF0aW8iLCJuZWFyZXN0UG9pbnRPblByb2plY3RlZExpbmUiLCJsaW5lIiwiaW5Qb2ludCIsInZpZXdwb3J0Iiwid21WaWV3cG9ydCIsIldlYk1lcmNhdG9yVmlld3BvcnQiLCJwcm9qZWN0ZWRDb29yZHMiLCJtYXAiLCJ4IiwieSIsInoiLCJwcm9qZWN0IiwibWluRGlzdGFuY2UiLCJJbmZpbml0eSIsIm1pblBvaW50SW5mbyIsImZvckVhY2giLCJpbmRleCIsIkEiLCJCIiwiQyIsImRpdiIsImRpc3RhbmNlIiwiYWJzIiwieDAiLCJ5MCIsInoxIiwiejIiLCJsaW5lTGVuZ3RoIiwic3RhcnRUb1BvaW50TGVuZ3RoIiwiejAiLCJ1bnByb2plY3QiLCJwcm9wZXJ0aWVzIiwiZGlzdCIsImluc2VydEJlZm9yZSIsImJhc2UiLCJ0b0luc2VydCIsImF0IiwiaW5kZXhPZiIsInNsaWNlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBU0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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VUFBVSxDQUFDMEIsU0FBWCxDQUFxQixDQUFDUCxFQUFELEVBQUtDLEVBQUwsRUFBU0ssRUFBVCxDQUFyQjtBQUZMLEtBRkw7QUFNTEUsSUFBQUEsVUFBVSxFQUFFO0FBQ1Y7QUFDQUMsTUFBQUEsSUFBSSxFQUFFcEIsV0FGSTtBQUdWSSxNQUFBQSxLQUFLLEVBQUVBLEtBQUssR0FBRztBQUhMO0FBTlAsR0FBUDtBQVlEO0FBRUQ7Ozs7Ozs7OztBQU9PLFNBQVNpQixZQUFULENBQXNCQyxJQUF0QixFQUFvQ0QsWUFBcEMsRUFBMERFLFFBQTFELEVBQW9GO0FBQ3pGLE1BQU1DLEVBQUUsR0FBR0YsSUFBSSxDQUFDRyxPQUFMLENBQWFKLFlBQWIsQ0FBWDs7QUFDQSxNQUFJRyxFQUFFLEdBQUcsQ0FBVCxFQUFZO0FBQ1YsV0FBT0YsSUFBUDtBQUNEOztBQUNELFNBQU9BLElBQUksQ0FBQ0ksS0FBTCxDQUFXLENBQVgsRUFBY0YsRUFBZCxJQUFvQkQsUUFBcEIsR0FBK0JELElBQUksQ0FBQ0ksS0FBTCxDQUFXRixFQUFYLENBQXRDO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZGVzdGluYXRpb24gZnJvbSAnQHR1cmYvZGVzdGluYXRpb24nO1xuaW1wb3J0IGJlYXJpbmcgZnJvbSAnQHR1cmYvYmVhcmluZyc7XG5pbXBvcnQgcG9pbnRUb0xpbmVEaXN0YW5jZSBmcm9tICdAdHVyZi9wb2ludC10by1saW5lLWRpc3RhbmNlJztcbmltcG9ydCB7IHBvaW50IH0gZnJvbSAnQHR1cmYvaGVscGVycyc7XG5pbXBvcnQge1xuICBQb3NpdGlvbixcbiAgUG9pbnQsXG4gIExpbmVTdHJpbmcsXG4gIEZlYXR1cmVPZixcbiAgRmVhdHVyZVdpdGhQcm9wcyxcbiAgVmlld3BvcnQsXG59IGZyb20gJ0BuZWJ1bGEuZ2wvZWRpdC1tb2Rlcyc7XG5pbXBvcnQgV2ViTWVyY2F0b3JWaWV3cG9ydCBmcm9tICd2aWV3cG9ydC1tZXJjYXRvci1wcm9qZWN0JztcblxuLy8gVE9ETyBlZGl0LW1vZGVzOiBkZWxldGUgYW5kIHVzZSBlZGl0LW1vZGVzL3V0aWxzIGluc3RlYWRcblxuZXhwb3J0IHR5cGUgTmVhcmVzdFBvaW50VHlwZSA9IEZlYXR1cmVXaXRoUHJvcHM8UG9pbnQsIHsgZGlzdDogbnVtYmVyOyBpbmRleDogbnVtYmVyIH0+O1xuXG5leHBvcnQgZnVuY3Rpb24gdG9EZWNrQ29sb3IoXG4gIGNvbG9yPzogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfCBudW1iZXIsXG4gIGRlZmF1bHRDb2xvcjogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbMjU1LCAwLCAwLCAyNTVdXG4pOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShjb2xvcikpIHtcbiAgICByZXR1cm4gZGVmYXVsdENvbG9yO1xuICB9XG4gIHJldHVybiBbY29sb3JbMF0gKiAyNTUsIGNvbG9yWzFdICogMjU1LCBjb2xvclsyXSAqIDI1NSwgY29sb3JbM10gKiAyNTVdO1xufVxuXG4vL1xuLy8gYSBHZW9KU09OIGhlbHBlciBmdW5jdGlvbiB0aGF0IGNhbGxzIHRoZSBwcm92aWRlZCBmdW5jdGlvbiB3aXRoXG4vLyBhbiBhcmd1bWVudCB0aGF0IGlzIHRoZSBtb3N0IGRlZXBseS1uZXN0ZWQgYXJyYXkgaGF2aW5nIGVsZW1lbnRzXG4vLyB0aGF0IGFyZSBhcnJheXMgb2YgcHJpbWl0aXZlcyBhcyBhbiBhcmd1bWVudCwgZS5nLlxuLy9cbi8vIHtcbi8vICAgXCJ0eXBlXCI6IFwiTXVsdGlQb2x5Z29uXCIsXG4vLyAgIFwiY29vcmRpbmF0ZXNcIjogW1xuLy8gICAgICAgW1xuLy8gICAgICAgICAgIFtbMzAsIDIwXSwgWzQ1LCA0MF0sIFsxMCwgNDBdLCBbMzAsIDIwXV1cbi8vICAgICAgIF0sXG4vLyAgICAgICBbXG4vLyAgICAgICAgICAgW1sxNSwgNV0sIFs0MCwgMTBdLCBbMTAsIDIwXSwgWzUsIDEwXSwgWzE1LCA1XV1cbi8vICAgICAgIF1cbi8vICAgXVxuLy8gfVxuLy9cbi8vIHRoZSBmdW5jdGlvbiB3b3VsZCBiZSBjYWxsZWQgb246XG4vL1xuLy8gW1szMCwgMjBdLCBbNDUsIDQwXSwgWzEwLCA0MF0sIFszMCwgMjBdXVxuLy9cbi8vIGFuZFxuLy9cbi8vIFtbMTUsIDVdLCBbNDAsIDEwXSwgWzEwLCAyMF0sIFs1LCAxMF0sIFsxNSwgNV1dXG4vL1xuZXhwb3J0IGZ1bmN0aW9uIHJlY3Vyc2l2ZWx5VHJhdmVyc2VOZXN0ZWRBcnJheXMoXG4gIGFycmF5OiBBcnJheTxhbnk+LFxuICBwcmVmaXg6IEFycmF5PG51bWJlcj4sXG4gIGZuOiBGdW5jdGlvblxuKSB7XG4gIGlmICghQXJyYXkuaXNBcnJheShhcnJheVswXSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKHJlY3Vyc2l2ZWx5VHJhdmVyc2VOZXN0ZWRBcnJheXMoYXJyYXlbaV0sIFsuLi5wcmVmaXgsIGldLCBmbikpIHtcbiAgICAgIGZuKGFycmF5LCBwcmVmaXgpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlUG9pbnRzUGFyYWxsZWxUb0xpbmVQb2ludHMoXG4gIHAxOiBQb3NpdGlvbixcbiAgcDI6IFBvc2l0aW9uLFxuICBncm91bmRDb29yZHM6IFBvc2l0aW9uXG4pOiBQb3NpdGlvbltdIHtcbiAgY29uc3QgbGluZVN0cmluZzogTGluZVN0cmluZyA9IHtcbiAgICB0eXBlOiAnTGluZVN0cmluZycsXG4gICAgY29vcmRpbmF0ZXM6IFtwMSwgcDJdLFxuICB9O1xuICBjb25zdCBwdCA9IHBvaW50KGdyb3VuZENvb3Jkcyk7XG4gIGNvbnN0IGRkaXN0YW5jZSA9IHBvaW50VG9MaW5lRGlzdGFuY2UocHQsIGxpbmVTdHJpbmcpO1xuICBjb25zdCBsaW5lQmVhcmluZyA9IGJlYXJpbmcocDEsIHAyKTtcblxuICAvLyBDaGVjayBpZiBjdXJyZW50IHBvaW50IGlzIHRvIHRoZSBsZWZ0IG9yIHJpZ2h0IG9mIGxpbmVcbiAgLy8gTGluZSBmcm9tIEE9KHgxLHkxKSB0byBCPSh4Mix5MikgYSBwb2ludCBQPSh4LHkpXG4gIC8vIHRoZW4gKHjiiJJ4MSkoeTLiiJJ5MSniiJIoeeKIknkxKSh4MuKIkngxKVxuICBjb25zdCBpc1BvaW50VG9MZWZ0T2ZMaW5lID1cbiAgICAoZ3JvdW5kQ29vcmRzWzBdIC0gcDFbMF0pICogKHAyWzFdIC0gcDFbMV0pIC0gKGdyb3VuZENvb3Jkc1sxXSAtIHAxWzFdKSAqIChwMlswXSAtIHAxWzBdKTtcblxuICAvLyBCZWFyaW5nIHRvIGRyYXcgcGVycGVuZGljdWxhciB0byB0aGUgbGluZSBzdHJpbmdcbiAgY29uc3Qgb3J0aG9nb25hbEJlYXJpbmcgPSBpc1BvaW50VG9MZWZ0T2ZMaW5lIDwgMCA/IGxpbmVCZWFyaW5nIC0gOTAgOiBsaW5lQmVhcmluZyAtIDI3MDtcblxuICAvLyBHZXQgY29vcmRpbmF0ZXMgZm9yIHRoZSBwb2ludCBwMyBhbmQgcDQgd2hpY2ggYXJlIHBlcnBlbmRpY3VsYXIgdG8gdGhlIGxpbmVTdHJpbmdcbiAgLy8gQWRkIHRoZSBkaXN0YW5jZSBhcyB0aGUgY3VycmVudCBwb3NpdGlvbiBtb3ZlcyBhd2F5IGZyb20gdGhlIGxpbmVTdHJpbmdcbiAgY29uc3QgcDMgPSBkZXN0aW5hdGlvbihwMiwgZGRpc3RhbmNlLCBvcnRob2dvbmFsQmVhcmluZyk7XG4gIGNvbnN0IHA0ID0gZGVzdGluYXRpb24ocDEsIGRkaXN0YW5jZSwgb3J0aG9nb25hbEJlYXJpbmcpO1xuICAvL0B0cy1pZ25vcmVcbiAgcmV0dXJuIFtwMy5nZW9tZXRyeS5jb29yZGluYXRlcywgcDQuZ2VvbWV0cnkuY29vcmRpbmF0ZXNdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGlzdGFuY2UyZCh4MTogbnVtYmVyLCB5MTogbnVtYmVyLCB4MjogbnVtYmVyLCB5MjogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgZHggPSB4MSAtIHgyO1xuICBjb25zdCBkeSA9IHkxIC0geTI7XG4gIHJldHVybiBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWl4KGE6IG51bWJlciwgYjogbnVtYmVyLCByYXRpbzogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIGIgKiByYXRpbyArIGEgKiAoMSAtIHJhdGlvKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5lYXJlc3RQb2ludE9uUHJvamVjdGVkTGluZShcbiAgbGluZTogRmVhdHVyZU9mPExpbmVTdHJpbmc+LFxuICBpblBvaW50OiBGZWF0dXJlT2Y8UG9pbnQ+LFxuICB2aWV3cG9ydDogVmlld3BvcnRcbik6IE5lYXJlc3RQb2ludFR5cGUge1xuICBjb25zdCB3bVZpZXdwb3J0ID0gbmV3IFdlYk1lcmNhdG9yVmlld3BvcnQodmlld3BvcnQpO1xuICAvLyBQcm9qZWN0IHRoZSBsaW5lIHRvIHZpZXdwb3J0LCB0aGVuIGZpbmQgdGhlIG5lYXJlc3QgcG9pbnRcbiAgY29uc3QgY29vcmRpbmF0ZXM6IEFycmF5PEFycmF5PG51bWJlcj4+ID0gbGluZS5nZW9tZXRyeS5jb29yZGluYXRlcyBhcyBhbnk7XG4gIGNvbnN0IHByb2plY3RlZENvb3JkcyA9IGNvb3JkaW5hdGVzLm1hcCgoW3gsIHksIHogPSAwXSkgPT4gd21WaWV3cG9ydC5wcm9qZWN0KFt4LCB5LCB6XSkpO1xuICAvL0B0cy1pZ25vcmVcbiAgY29uc3QgW3gsIHldID0gd21WaWV3cG9ydC5wcm9qZWN0KGluUG9pbnQuZ2VvbWV0cnkuY29vcmRpbmF0ZXMpO1xuICAvLyBjb25zb2xlLmxvZygncHJvamVjdGVkQ29vcmRzJywgSlNPTi5zdHJpbmdpZnkocHJvamVjdGVkQ29vcmRzKSk7XG5cbiAgbGV0IG1pbkRpc3RhbmNlID0gSW5maW5pdHk7XG4gIGxldCBtaW5Qb2ludEluZm8gPSB7fTtcblxuICBwcm9qZWN0ZWRDb29yZHMuZm9yRWFjaCgoW3gyLCB5Ml0sIGluZGV4KSA9PiB7XG4gICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgW3gxLCB5MV0gPSBwcm9qZWN0ZWRDb29yZHNbaW5kZXggLSAxXTtcblxuICAgIC8vIGxpbmUgZnJvbSBwcm9qZWN0ZWRDb29yZHNbaW5kZXggLSAxXSB0byBwcm9qZWN0ZWRDb29yZHNbaW5kZXhdXG4gICAgLy8gY29udmVydCB0byBBeCArIEJ5ICsgQyA9IDBcbiAgICBjb25zdCBBID0geTEgLSB5MjtcbiAgICBjb25zdCBCID0geDIgLSB4MTtcbiAgICBjb25zdCBDID0geDEgKiB5MiAtIHgyICogeTE7XG5cbiAgICAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXN0YW5jZV9mcm9tX2FfcG9pbnRfdG9fYV9saW5lXG4gICAgY29uc3QgZGl2ID0gQSAqIEEgKyBCICogQjtcbiAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguYWJzKEEgKiB4ICsgQiAqIHkgKyBDKSAvIE1hdGguc3FydChkaXYpO1xuXG4gICAgLy8gVE9ETzogQ2hlY2sgaWYgaW5zaWRlIGJvdW5kc1xuXG4gICAgaWYgKGRpc3RhbmNlIDwgbWluRGlzdGFuY2UpIHtcbiAgICAgIG1pbkRpc3RhbmNlID0gZGlzdGFuY2U7XG4gICAgICBtaW5Qb2ludEluZm8gPSB7XG4gICAgICAgIGluZGV4LFxuICAgICAgICB4MDogKEIgKiAoQiAqIHggLSBBICogeSkgLSBBICogQykgLyBkaXYsXG4gICAgICAgIHkwOiAoQSAqICgtQiAqIHggKyBBICogeSkgLSBCICogQykgLyBkaXYsXG4gICAgICB9O1xuICAgIH1cbiAgfSk7XG4gIC8vQHRzLWlnbm9yZVxuICBjb25zdCB7IGluZGV4LCB4MCwgeTAgfSA9IG1pblBvaW50SW5mbztcbiAgY29uc3QgW3gxLCB5MSwgejEgPSAwXSA9IHByb2plY3RlZENvb3Jkc1tpbmRleCAtIDFdO1xuICBjb25zdCBbeDIsIHkyLCB6MiA9IDBdID0gcHJvamVjdGVkQ29vcmRzW2luZGV4XTtcblxuICAvLyBjYWxjdWxhdGUgd2hhdCByYXRpbyBvZiB0aGUgbGluZSB3ZSBhcmUgb24gdG8gZmluZCB0aGUgcHJvcGVyIHpcbiAgY29uc3QgbGluZUxlbmd0aCA9IGRpc3RhbmNlMmQoeDEsIHkxLCB4MiwgeTIpO1xuICBjb25zdCBzdGFydFRvUG9pbnRMZW5ndGggPSBkaXN0YW5jZTJkKHgxLCB5MSwgeDAsIHkwKTtcbiAgY29uc3QgcmF0aW8gPSBzdGFydFRvUG9pbnRMZW5ndGggLyBsaW5lTGVuZ3RoO1xuICBjb25zdCB6MCA9IG1peCh6MSwgejIsIHJhdGlvKTtcblxuICByZXR1cm4ge1xuICAgIHR5cGU6ICdGZWF0dXJlJyxcbiAgICBnZW9tZXRyeToge1xuICAgICAgdHlwZTogJ1BvaW50JyxcbiAgICAgIGNvb3JkaW5hdGVzOiB3bVZpZXdwb3J0LnVucHJvamVjdChbeDAsIHkwLCB6MF0pLFxuICAgIH0sXG4gICAgcHJvcGVydGllczoge1xuICAgICAgLy8gVE9ETzogY2FsY3VsYXRlIHRoZSBkaXN0YW5jZSBpbiBwcm9wZXIgdW5pdHNcbiAgICAgIGRpc3Q6IG1pbkRpc3RhbmNlLFxuICAgICAgaW5kZXg6IGluZGV4IC0gMSxcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIEluc2VydHMgdG9JbnNlcnQgc3RyaW5nIGludG8gYmFzZSBzdHJpbmcgYmVmb3JlIGluc2VydEJlZm9yZSBzdHJpbmcuXG4gKiBAcGFyYW0gYmFzZSBBIHN0cmluZyB0byBpbnNlcnQgaW50by5cbiAqIEBwYXJhbSBpbnNlcnRCZWZvcmUgQSBzdWIgc3RyaW5nIGluIGBiYXNlYCBzdHJpbmcgdG8gaW5zZXJ0IGJlZm9yZS5cbiAqIEBwYXJhbSB0b0luc2VydCBBIHN0cmluZyB0byBpbnNlcnQuXG4gKiBAcmV0dXJucyBDb21iaW5lZCBzdHJpbmcuIGBiYXNlYCBzdHJpbmcgaWYgYGluc2VydEJlZm9yZWAgc3RyaW5nIGlzbid0IGZvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5zZXJ0QmVmb3JlKGJhc2U6IHN0cmluZywgaW5zZXJ0QmVmb3JlOiBzdHJpbmcsIHRvSW5zZXJ0OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBhdCA9IGJhc2UuaW5kZXhPZihpbnNlcnRCZWZvcmUpO1xuICBpZiAoYXQgPCAwKSB7XG4gICAgcmV0dXJuIGJhc2U7XG4gIH1cbiAgcmV0dXJuIGJhc2Uuc2xpY2UoMCwgYXQpICsgdG9JbnNlcnQgKyBiYXNlLnNsaWNlKGF0KTtcbn1cbiJdfQ==
;