UNPKG

react-planner-viewer

Version:

react-planner-viewer is a React Component for view plans builded with react-planner in 2D mode

304 lines (241 loc) 35.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _slicedToArray = function () { function sliceIterator(arr, i) { 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"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /** @description Determines the distance between two points * @param {number} x0 Vertex 0 x * @param {number} y0 Vertex 0 y * @param {number} x1 Vertex 1 x * @param {number} y1 Vertex 1 y * @return {number} */ exports.compareVertices = compareVertices; exports.minVertex = minVertex; exports.maxVertex = maxVertex; exports.orderVertices = orderVertices; exports.pointsDistance = pointsDistance; exports.verticesDistance = verticesDistance; exports.horizontalLine = horizontalLine; exports.verticalLine = verticalLine; exports.linePassingThroughTwoPoints = linePassingThroughTwoPoints; exports.distancePointFromLine = distancePointFromLine; exports.closestPointFromLine = closestPointFromLine; exports.intersectionFromTwoLines = intersectionFromTwoLines; exports.intersectionFromTwoLineSegment = intersectionFromTwoLineSegment; exports.distancePointFromLineSegment = distancePointFromLineSegment; exports.isPointOnLineSegment = isPointOnLineSegment; exports.closestPointFromLineSegment = closestPointFromLineSegment; exports.pointPositionOnLineSegment = pointPositionOnLineSegment; exports.mapRange = mapRange; exports.angleBetweenTwoPointsAndOrigin = angleBetweenTwoPointsAndOrigin; exports.angleBetweenTwoPoints = angleBetweenTwoPoints; exports.samePoints = samePoints; exports.extendLine = extendLine; exports.roundVertex = roundVertex; var _math = require("./math.js"); var _constants = require("../constants"); function compareVertices(v0, v1) { return v0.x === v1.x ? v0.y - v1.y : v0.x - v1.x; } function minVertex(v0, v1) { return compareVertices(v0, v1) > 0 ? v1 : v0; } function maxVertex(v0, v1) { return compareVertices(v0, v1) > 0 ? v0 : v1; } function orderVertices(vertices) { return vertices.sort(compareVertices); } function pointsDistance(x0, y0, x1, y1) { var diff_x = x0 - x1; var diff_y = y0 - y1; return Math.sqrt(diff_x * diff_x + diff_y * diff_y); } function verticesDistance(v1, v2) { var x0 = v1.x, y0 = v1.y; var x1 = v2.x, y1 = v2.y; return pointsDistance(x0, y0, x1, y1); } function horizontalLine(y) { return { a: 0, b: 1, c: -y }; } function verticalLine(x) { return { a: 1, b: 0, c: -x }; } function linePassingThroughTwoPoints(x1, y1, x2, y2) { // (x2 - x1)(y - y1) = (y2 - y1)(x - x1) // (y1 - y2)x + (x2 - x1)y + (y2x1 - x2y1) = 0 if (x1 === x2 && y1 == y2) throw new Error("Geometry error"); if (x1 === x2) return verticalLine(x); if (y1 === y2) return horizontalLine(y1); return { a: y1 - y2, b: x2 - x1, c: y2 * x1 - x2 * y1 }; } function distancePointFromLine(a, b, c, x, y) { //https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line return (0, _math.fAbs)(a * x + b * y + c) / Math.sqrt(a * a + b * b); } function closestPointFromLine(a, b, c, x, y) { //https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line var denom = a * a + b * b; return { x: (b * (b * x - a * y) - a * c) / denom, y: (a * -b * x + a * y - b * c) / denom }; } function intersectionFromTwoLines(a, b, c, j, k, l) { var det = b * j - a * k; if (det === 0) return undefined; //no intersection var y = (a * l - c * j) / det; var x = (c * k - b * l) / det; return { x: x, y: y }; } function intersectionFromTwoLineSegment(p1, p2, p3, p4) { //https://github.com/psalaets/line-intersect/blob/master/lib/check-intersection.js var x1 = p1.x, y1 = p1.y; var x2 = p2.x, y2 = p2.y; var x3 = p3.x, y3 = p3.y; var x4 = p4.x, y4 = p4.y; var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); var numA = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); var numB = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3); if ((0, _math.fAbs)(denom) <= _constants.EPSILON) { if ((0, _math.fAbs)(numA) <= _constants.EPSILON && (0, _math.fAbs)(numB) <= _constants.EPSILON) { var comparator = function comparator(pa, pb) { return pa.x === pb.x ? pa.y - pb.y : pa.x - pb.x; }; var line0 = [p1, p2].sort(comparator); var line1 = [p3.toJS(), p4.toJS()].sort(comparator); var _sort = [line0, line1].sort(function (lineA, lineB) { return comparator(lineA[0], lineB[0]); }), _sort2 = _slicedToArray(_sort, 2), lineSX = _sort2[0], lineDX = _sort2[1]; if (lineSX[1].x === lineDX[0].x) { return { type: lineDX[0].y <= lineSX[1].y ? "colinear" : "none" }; } else { return { type: lineDX[0].x <= lineSX[1].x ? "colinear" : "none" }; } } return { type: "parallel" }; } var uA = numA / denom; var uB = numB / denom; if (uA >= 0 - _constants.EPSILON && uA <= 1 + _constants.EPSILON && uB >= 0 - _constants.EPSILON && uB <= 1 + _constants.EPSILON) { var point = { x: x1 + uA * (x2 - x1), y: y1 + uA * (y2 - y1) }; return { type: "intersecting", point: point }; } return { type: "none" }; } function distancePointFromLineSegment(x1, y1, x2, y2, xp, yp) { //http://stackoverflow.com/a/6853926/1398836 var A = xp - x1; var B = yp - y1; var C = x2 - x1; var D = y2 - y1; var dot = A * C + B * D; var len_sq = C * C + D * D; var param = -1; if (len_sq != 0) //in case of 0 length line param = dot / len_sq; var xx = void 0, yy = void 0; if (param < 0) { xx = x1; yy = y1; } else if (param > 1) { xx = x2; yy = y2; } else { xx = x1 + param * C; yy = y1 + param * D; } var dx = xp - xx; var dy = yp - yy; return Math.sqrt(dx * dx + dy * dy); } /** * * @param x1 {number} x for first vertex of the segment * @param y1 {number} y for first vertex of the segment * @param x2 {number} x for second vertex of the segment * @param y2 {number} y for second vertex of the segment * @param xp {number} x for point we want to verify * @param yp {number} y for point we want to verify * @param maxDistance {number} the epsilon value used for comparisons * @returns {boolean} true if the point lies on the line segment false otherwise */ function isPointOnLineSegment(x1, y1, x2, y2, xp, yp) { var maxDistance = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : _constants.EPSILON; return distancePointFromLineSegment(x1, y1, x2, y2, xp, yp) <= maxDistance; } function closestPointFromLineSegment(x1, y1, x2, y2, xp, yp) { if (x1 === x2) return { x: x1, y: yp }; if (y1 === y2) return { x: xp, y: y1 }; var m = (y2 - y1) / (x2 - x1); var q = y1 - m * x1; var mi = -1 / m; var qi = yp - mi * xp; var x = (qi - q) / (m - mi); var y = m * x + q; return { x: x, y: y }; } function pointPositionOnLineSegment(x1, y1, x2, y2, xp, yp) { var length = pointsDistance(x1, y1, x2, y2); var distance = pointsDistance(x1, y1, xp, yp); var offset = distance / length; if (x1 > x2) offset = mapRange(offset, 0, 1, 1, 0); return offset; } function mapRange(value, low1, high1, low2, high2) { return low2 + (high2 - low2) * (value - low1) / (high1 - low1); } function angleBetweenTwoPointsAndOrigin(x1, y1, x2, y2) { return -Math.atan2(y1 - y2, x2 - x1) * 180 / Math.PI; } function angleBetweenTwoPoints(x1, y1, x2, y2) { return Math.atan2(y2 - y1, x2 - x1); } function samePoints(_ref, _ref2) { var x1 = _ref.x, y1 = _ref.y; var x2 = _ref2.x, y2 = _ref2.y; return (0, _math.fAbs)(x1 - x2) <= _constants.EPSILON && (0, _math.fAbs)(y1 - y2) <= _constants.EPSILON; } /** @description Extend line based on coordinates and new line length * @param {number} x1 Vertex 1 x * @param {number} y1 Vertex 1 y * @param {number} x2 Vertex 2 x * @param {number} y2 Vertex 2 y * @param {number} newDistance New line length * @return {object} */ function extendLine(x1, y1, x2, y2, newDistance) { var precision = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 6; var rad = Math.atan2(y2 - y1, x2 - x1); return { x: (0, _math.toFixedFloat)(x1 + Math.cos(rad) * newDistance, precision), y: (0, _math.toFixedFloat)(y1 + Math.sin(rad) * newDistance, precision) }; } function roundVertex(vertex) { var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 6; vertex.set('x', (0, _math.toFixedFloat)(vertex.get('x'), precision)); vertex.set('y', (0, _math.toFixedFloat)(vertex.get('y'), precision)); return vertex; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9nZW9tZXRyeS5qcyJdLCJuYW1lcyI6WyJjb21wYXJlVmVydGljZXMiLCJtaW5WZXJ0ZXgiLCJtYXhWZXJ0ZXgiLCJvcmRlclZlcnRpY2VzIiwicG9pbnRzRGlzdGFuY2UiLCJ2ZXJ0aWNlc0Rpc3RhbmNlIiwiaG9yaXpvbnRhbExpbmUiLCJ2ZXJ0aWNhbExpbmUiLCJsaW5lUGFzc2luZ1Rocm91Z2hUd29Qb2ludHMiLCJkaXN0YW5jZVBvaW50RnJvbUxpbmUiLCJjbG9zZXN0UG9pbnRGcm9tTGluZSIsImludGVyc2VjdGlvbkZyb21Ud29MaW5lcyIsImludGVyc2VjdGlvbkZyb21Ud29MaW5lU2VnbWVudCIsImRpc3RhbmNlUG9pbnRGcm9tTGluZVNlZ21lbnQiLCJpc1BvaW50T25MaW5lU2VnbWVudCIsImNsb3Nlc3RQb2ludEZyb21MaW5lU2VnbWVudCIsInBvaW50UG9zaXRpb25PbkxpbmVTZWdtZW50IiwibWFwUmFuZ2UiLCJhbmdsZUJldHdlZW5Ud29Qb2ludHNBbmRPcmlnaW4iLCJhbmdsZUJldHdlZW5Ud29Qb2ludHMiLCJzYW1lUG9pbnRzIiwiZXh0ZW5kTGluZSIsInJvdW5kVmVydGV4IiwidjAiLCJ2MSIsIngiLCJ5IiwidmVydGljZXMiLCJzb3J0IiwieDAiLCJ5MCIsIngxIiwieTEiLCJkaWZmX3giLCJkaWZmX3kiLCJNYXRoIiwic3FydCIsInYyIiwiYSIsImIiLCJjIiwieDIiLCJ5MiIsIkVycm9yIiwiZGVub20iLCJqIiwiayIsImwiLCJkZXQiLCJ1bmRlZmluZWQiLCJwMSIsInAyIiwicDMiLCJwNCIsIngzIiwieTMiLCJ4NCIsInk0IiwibnVtQSIsIm51bUIiLCJjb21wYXJhdG9yIiwicGEiLCJwYiIsImxpbmUwIiwibGluZTEiLCJ0b0pTIiwibGluZUEiLCJsaW5lQiIsImxpbmVTWCIsImxpbmVEWCIsInR5cGUiLCJ1QSIsInVCIiwicG9pbnQiLCJ4cCIsInlwIiwiQSIsIkIiLCJDIiwiRCIsImRvdCIsImxlbl9zcSIsInBhcmFtIiwieHgiLCJ5eSIsImR4IiwiZHkiLCJtYXhEaXN0YW5jZSIsIm0iLCJxIiwibWkiLCJxaSIsImxlbmd0aCIsImRpc3RhbmNlIiwib2Zmc2V0IiwidmFsdWUiLCJsb3cxIiwiaGlnaDEiLCJsb3cyIiwiaGlnaDIiLCJhdGFuMiIsIlBJIiwibmV3RGlzdGFuY2UiLCJwcmVjaXNpb24iLCJyYWQiLCJjb3MiLCJzaW4iLCJ2ZXJ0ZXgiLCJzZXQiLCJnZXQiXSwibWFwcGluZ3MiOiI7Ozs7Ozt5cEJBQUE7Ozs7Ozs7OztRQVVnQkEsZSxHQUFBQSxlO1FBSUFDLFMsR0FBQUEsUztRQUlBQyxTLEdBQUFBLFM7UUFJQUMsYSxHQUFBQSxhO1FBSUFDLGMsR0FBQUEsYztRQU9BQyxnQixHQUFBQSxnQjtRQVFBQyxjLEdBQUFBLGM7UUFJQUMsWSxHQUFBQSxZO1FBSUFDLDJCLEdBQUFBLDJCO1FBZUFDLHFCLEdBQUFBLHFCO1FBS0FDLG9CLEdBQUFBLG9CO1FBU0FDLHdCLEdBQUFBLHdCO1FBVUFDLDhCLEdBQUFBLDhCO1FBNENBQyw0QixHQUFBQSw0QjtRQTZDQUMsb0IsR0FBQUEsb0I7UUFJQUMsMkIsR0FBQUEsMkI7UUFnQkFDLDBCLEdBQUFBLDBCO1FBVUFDLFEsR0FBQUEsUTtRQUlBQyw4QixHQUFBQSw4QjtRQUlBQyxxQixHQUFBQSxxQjtRQUlBQyxVLEdBQUFBLFU7UUFZQUMsVSxHQUFBQSxVO1FBU0FDLFcsR0FBQUEsVzs7QUF6T2hCOztBQUNBOztBQUVPLFNBQVN0QixlQUFULENBQXlCdUIsRUFBekIsRUFBNkJDLEVBQTdCLEVBQWlDO0FBQ3RDLFNBQU9ELEdBQUdFLENBQUgsS0FBU0QsR0FBR0MsQ0FBWixHQUFnQkYsR0FBR0csQ0FBSCxHQUFPRixHQUFHRSxDQUExQixHQUE4QkgsR0FBR0UsQ0FBSCxHQUFPRCxHQUFHQyxDQUEvQztBQUNEOztBQUVNLFNBQVN4QixTQUFULENBQW1Cc0IsRUFBbkIsRUFBdUJDLEVBQXZCLEVBQTJCO0FBQ2hDLFNBQU94QixnQkFBZ0J1QixF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RUFBd0JDLEVBQXhCLEVBQTRCUyxFQUE1QixFQUFnQ0MsRUFBaEMsRUFBb0M0RCxXQUFwQyxFQUFnRTtBQUFBLE1BQWZDLFNBQWUsdUVBQUgsQ0FBRzs7QUFDckUsTUFBSUMsTUFBTXJFLEtBQUtpRSxLQUFMLENBQVcxRCxLQUFLVixFQUFoQixFQUFvQlMsS0FBS1YsRUFBekIsQ0FBVjs7QUFFQSxTQUFPO0FBQ0xOLE9BQUcsd0JBQWFNLEtBQU1JLEtBQUtzRSxHQUFMLENBQVNELEdBQVQsSUFBZ0JGLFdBQW5DLEVBQWlEQyxTQUFqRCxDQURFO0FBRUw3RSxPQUFHLHdCQUFhTSxLQUFNRyxLQUFLdUUsR0FBTCxDQUFTRixHQUFULElBQWdCRixXQUFuQyxFQUFpREMsU0FBakQ7QUFGRSxHQUFQO0FBSUQ7O0FBRU0sU0FBU2pGLFdBQVQsQ0FBcUJxRixNQUFyQixFQUE0QztBQUFBLE1BQWZKLFNBQWUsdUVBQUgsQ0FBRzs7QUFDakRJLFNBQU9DLEdBQVAsQ0FBVyxHQUFYLEVBQWdCLHdCQUFhRCxPQUFPRSxHQUFQLENBQVcsR0FBWCxDQUFiLEVBQThCTixTQUE5QixDQUFoQjtBQUNBSSxTQUFPQyxHQUFQLENBQVcsR0FBWCxFQUFnQix3QkFBYUQsT0FBT0UsR0FBUCxDQUFXLEdBQVgsQ0FBYixFQUE4Qk4sU0FBOUIsQ0FBaEI7O0FBRUEsU0FBT0ksTUFBUDtBQUNEIiwiZmlsZSI6Imdlb21ldHJ5LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqIEBkZXNjcmlwdGlvbiBEZXRlcm1pbmVzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBwb2ludHNcbiAqICBAcGFyYW0ge251bWJlcn0geDAgVmVydGV4IDAgeFxuICogIEBwYXJhbSB7bnVtYmVyfSB5MCBWZXJ0ZXggMCB5XG4gKiAgQHBhcmFtIHtudW1iZXJ9IHgxIFZlcnRleCAxIHhcbiAqICBAcGFyYW0ge251bWJlcn0geTEgVmVydGV4IDEgeVxuICogIEByZXR1cm4ge251bWJlcn1cbiAqL1xuaW1wb3J0IHt0b0ZpeGVkRmxvYXQsIGZBYnN9IGZyb20gJy4vbWF0aC5qcyc7XG5pbXBvcnQge0VQU0lMT059IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmVWZXJ0aWNlcyh2MCwgdjEpIHtcbiAgcmV0dXJuIHYwLnggPT09IHYxLnggPyB2MC55IC0gdjEueSA6IHYwLnggLSB2MS54XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtaW5WZXJ0ZXgodjAsIHYxKSB7XG4gIHJldHVybiBjb21wYXJlVmVydGljZXModjAsIHYxKSA+IDAgPyB2MSA6IHYwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF4VmVydGV4KHYwLCB2MSkge1xuICByZXR1cm4gY29tcGFyZVZlcnRpY2VzKHYwLCB2MSkgPiAwID8gdjAgOiB2MTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9yZGVyVmVydGljZXModmVydGljZXMpIHtcbiAgcmV0dXJuIHZlcnRpY2VzLnNvcnQoY29tcGFyZVZlcnRpY2VzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBvaW50c0Rpc3RhbmNlKHgwLCB5MCwgeDEsIHkxKSB7XG4gIGxldCBkaWZmX3ggPSB4MCAtIHgxO1xuICBsZXQgZGlmZl95ID0geTAgLSB5MTtcblxuICByZXR1cm4gTWF0aC5zcXJ0KChkaWZmX3ggKiBkaWZmX3gpICsgKGRpZmZfeSAqIGRpZmZfeSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmVydGljZXNEaXN0YW5jZSh2MSwgdjIpIHtcblxuICBsZXQge3g6IHgwLCB5OiB5MH0gPSB2MTtcbiAgbGV0IHt4OiB4MSwgeTogeTF9ID0gdjI7XG5cbiAgcmV0dXJuIHBvaW50c0Rpc3RhbmNlKHgwLCB5MCwgeDEsIHkxKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhvcml6b250YWxMaW5lKHkpIHtcbiAgcmV0dXJuIHthOiAwLCBiOiAxLCBjOiAteX1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZlcnRpY2FsTGluZSh4KSB7XG4gIHJldHVybiB7YTogMSwgYjogMCwgYzogLXh9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsaW5lUGFzc2luZ1Rocm91Z2hUd29Qb2ludHMoeDEsIHkxLCB4MiwgeTIpIHtcbiAgLy8gKHgyIC0geDEpKHkgLSB5MSkgPSAoeTIgLSB5MSkoeCAtIHgxKVxuICAvLyAoeTEgLSB5Mil4ICsgKHgyIC0geDEpeSArICh5MngxIC0geDJ5MSkgPSAwXG5cbiAgaWYgKHgxID09PSB4MiAmJiB5MSA9PSB5MikgdGhyb3cgbmV3IEVycm9yKFwiR2VvbWV0cnkgZXJyb3JcIik7XG4gIGlmICh4MSA9PT0geDIpIHJldHVybiB2ZXJ0aWNhbExpbmUoeCk7XG4gIGlmICh5MSA9PT0geTIpIHJldHVybiBob3Jpem9udGFsTGluZSh5MSk7XG5cbiAgcmV0dXJuIHtcbiAgICBhOiB5MSAtIHkyLFxuICAgIGI6IHgyIC0geDEsXG4gICAgYzogeTIgKiB4MSAtIHgyICogeTFcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpc3RhbmNlUG9pbnRGcm9tTGluZShhLCBiLCBjLCB4LCB5KSB7XG4gIC8vaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGlzdGFuY2VfZnJvbV9hX3BvaW50X3RvX2FfbGluZVxuICByZXR1cm4gZkFicyhhICogeCArIGIgKiB5ICsgYykgLyBNYXRoLnNxcnQoYSAqIGEgKyBiICogYik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbG9zZXN0UG9pbnRGcm9tTGluZShhLCBiLCBjLCB4LCB5KSB7XG4gIC8vaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGlzdGFuY2VfZnJvbV9hX3BvaW50X3RvX2FfbGluZVxuICBsZXQgZGVub20gPSBhICogYSArIGIgKiBiO1xuICByZXR1cm4ge1xuICAgIHg6IChiICogKGIgKiB4IC0gYSAqIHkpIC0gYSAqIGMpIC8gZGVub20sXG4gICAgeTogKChhICogLWIgKiB4ICsgYSAqIHkpIC0gYiAqIGMpIC8gZGVub20sXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGludGVyc2VjdGlvbkZyb21Ud29MaW5lcyhhLCBiLCBjLCBqLCBrLCBsKSB7XG4gIGxldCBkZXQgPSAoYiAqIGogLSBhICogayk7XG5cbiAgaWYgKGRldCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDsgLy9ubyBpbnRlcnNlY3Rpb25cblxuICBsZXQgeSA9IChhICogbCAtIGMgKiBqKSAvIGRldDtcbiAgbGV0IHggPSAoYyAqIGsgLSBiICogbCkgLyBkZXQ7XG4gIHJldHVybiB7eCwgeX07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnNlY3Rpb25Gcm9tVHdvTGluZVNlZ21lbnQocDEsIHAyLCBwMywgcDQpIHtcbiAgLy9odHRwczovL2dpdGh1Yi5jb20vcHNhbGFldHMvbGluZS1pbnRlcnNlY3QvYmxvYi9tYXN0ZXIvbGliL2NoZWNrLWludGVyc2VjdGlvbi5qc1xuXG4gIGxldCB7eDogeDEsIHk6IHkxfSA9IHAxO1xuICBsZXQge3g6IHgyLCB5OiB5Mn0gPSBwMjtcbiAgbGV0IHt4OiB4MywgeTogeTN9ID0gcDM7XG4gIGxldCB7eDogeDQsIHk6IHk0fSA9IHA0O1xuXG4gIGxldCBkZW5vbSA9ICgoeTQgLSB5MykgKiAoeDIgLSB4MSkpIC0gKCh4NCAtIHgzKSAqICh5MiAtIHkxKSk7XG4gIGxldCBudW1BID0gKCh4NCAtIHgzKSAqICh5MSAtIHkzKSkgLSAoKHk0IC0geTMpICogKHgxIC0geDMpKTtcbiAgbGV0IG51bUIgPSAoKHgyIC0geDEpICogKHkxIC0geTMpKSAtICgoeTIgLSB5MSkgKiAoeDEgLSB4MykpO1xuXG4gIGlmIChmQWJzKGRlbm9tKSA8PSBFUFNJTE9OKSB7XG4gICAgaWYgKGZBYnMobnVtQSkgPD0gRVBTSUxPTiAmJiBmQWJzKG51bUIpIDw9IEVQU0lMT04pIHtcblxuICAgICAgbGV0IGNvbXBhcmF0b3IgPSAocGEsIHBiKSA9PiBwYS54ID09PSBwYi54ID8gcGEueSAtIHBiLnkgOiBwYS54IC0gcGIueDtcbiAgICAgIGxldCBsaW5lMCA9IFtwMSwgcDJdLnNvcnQoY29tcGFyYXRvcik7XG4gICAgICBsZXQgbGluZTEgPSBbcDMudG9KUygpLCBwNC50b0pTKCldLnNvcnQoY29tcGFyYXRvcik7XG5cbiAgICAgIGxldCBbbGluZVNYLCBsaW5lRFhdID0gW2xpbmUwLCBsaW5lMV0uc29ydCgobGluZUEsIGxpbmVCKSA9PiBjb21wYXJhdG9yKGxpbmVBWzBdLCBsaW5lQlswXSkpO1xuXG4gICAgICBpZiAobGluZVNYWzFdLnggPT09IGxpbmVEWFswXS54KSB7XG4gICAgICAgIHJldHVybiB7dHlwZTogKGxpbmVEWFswXS55IDw9IGxpbmVTWFsxXS55KSA/IFwiY29saW5lYXJcIiA6IFwibm9uZVwifTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7dHlwZTogKGxpbmVEWFswXS54IDw9IGxpbmVTWFsxXS54KSA/IFwiY29saW5lYXJcIiA6IFwibm9uZVwifTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHt0eXBlOiBcInBhcmFsbGVsXCJ9O1xuICB9XG5cbiAgdmFyIHVBID0gbnVtQSAvIGRlbm9tO1xuICB2YXIgdUIgPSBudW1CIC8gZGVub207XG5cbiAgaWYgKHVBID49ICgwIC0gRVBTSUxPTikgJiYgdUEgPD0gKDEgKyBFUFNJTE9OKSAmJiB1QiA+PSAoMCAtIEVQU0lMT04pICYmIHVCIDw9ICgxICsgRVBTSUxPTikpIHtcbiAgICBsZXQgcG9pbnQgPSB7XG4gICAgICB4OiB4MSArICh1QSAqICh4MiAtIHgxKSksXG4gICAgICB5OiB5MSArICh1QSAqICh5MiAtIHkxKSlcbiAgICB9O1xuICAgIHJldHVybiB7dHlwZTogXCJpbnRlcnNlY3RpbmdcIiwgcG9pbnR9O1xuICB9XG5cbiAgcmV0dXJuIHt0eXBlOiBcIm5vbmVcIn07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkaXN0YW5jZVBvaW50RnJvbUxpbmVTZWdtZW50KHgxLCB5MSwgeDIsIHkyLCB4cCwgeXApIHtcbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS82ODUzOTI2LzEzOTg4MzZcblxuICBsZXQgQSA9IHhwIC0geDE7XG4gIGxldCBCID0geXAgLSB5MTtcbiAgbGV0IEMgPSB4MiAtIHgxO1xuICBsZXQgRCA9IHkyIC0geTE7XG5cbiAgbGV0IGRvdCA9IEEgKiBDICsgQiAqIEQ7XG4gIGxldCBsZW5fc3EgPSBDICogQyArIEQgKiBEO1xuICBsZXQgcGFyYW0gPSAtMTtcbiAgaWYgKGxlbl9zcSAhPSAwKSAvL2luIGNhc2Ugb2YgMCBsZW5ndGggbGluZVxuICAgIHBhcmFtID0gZG90IC8gbGVuX3NxO1xuXG4gIGxldCB4eCwgeXk7XG5cbiAgaWYgKHBhcmFtIDwgMCkge1xuICAgIHh4ID0geDE7XG4gICAgeXkgPSB5MTtcbiAgfVxuICBlbHNlIGlmIChwYXJhbSA+IDEpIHtcbiAgICB4eCA9IHgyO1xuICAgIHl5ID0geTI7XG4gIH1cbiAgZWxzZSB7XG4gICAgeHggPSB4MSArIHBhcmFtICogQztcbiAgICB5eSA9IHkxICsgcGFyYW0gKiBEO1xuICB9XG5cbiAgbGV0IGR4ID0geHAgLSB4eDtcbiAgbGV0IGR5ID0geXAgLSB5eTtcbiAgcmV0dXJuIE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB4MSB7bnVtYmVyfSB4IGZvciBmaXJzdCB2ZXJ0ZXggb2YgdGhlIHNlZ21lbnRcbiAqIEBwYXJhbSB5MSB7bnVtYmVyfSB5IGZvciBmaXJzdCB2ZXJ0ZXggb2YgdGhlIHNlZ21lbnRcbiAqIEBwYXJhbSB4MiB7bnVtYmVyfSB4IGZvciBzZWNvbmQgdmVydGV4IG9mIHRoZSBzZWdtZW50XG4gKiBAcGFyYW0geTIge251bWJlcn0geSBmb3Igc2Vjb25kIHZlcnRleCBvZiB0aGUgc2VnbWVudFxuICogQHBhcmFtIHhwIHtudW1iZXJ9IHggZm9yIHBvaW50IHdlIHdhbnQgdG8gdmVyaWZ5XG4gKiBAcGFyYW0geXAge251bWJlcn0geSBmb3IgcG9pbnQgd2Ugd2FudCB0byB2ZXJpZnlcbiAqIEBwYXJhbSBtYXhEaXN0YW5jZSB7bnVtYmVyfSB0aGUgZXBzaWxvbiB2YWx1ZSB1c2VkIGZvciBjb21wYXJpc29uc1xuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgdGhlIHBvaW50IGxpZXMgb24gdGhlIGxpbmUgc2VnbWVudCBmYWxzZSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUG9pbnRPbkxpbmVTZWdtZW50KHgxLCB5MSwgeDIsIHkyLCB4cCwgeXAsIG1heERpc3RhbmNlID0gRVBTSUxPTikge1xuICByZXR1cm4gZGlzdGFuY2VQb2ludEZyb21MaW5lU2VnbWVudCh4MSwgeTEsIHgyLCB5MiwgeHAsIHlwKSA8PSBtYXhEaXN0YW5jZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsb3Nlc3RQb2ludEZyb21MaW5lU2VnbWVudCh4MSwgeTEsIHgyLCB5MiwgeHAsIHlwKSB7XG4gIGlmICh4MSA9PT0geDIpIHJldHVybiB7eDogeDEsIHk6IHlwfTtcbiAgaWYgKHkxID09PSB5MikgcmV0dXJuIHt4OiB4cCwgeTogeTF9O1xuXG4gIGxldCBtID0gKHkyIC0geTEpIC8gKHgyIC0geDEpO1xuICBsZXQgcSA9IHkxIC0gbSAqIHgxO1xuXG4gIGxldCBtaSA9IC0xIC8gbTtcbiAgbGV0IHFpID0geXAgLSBtaSAqIHhwO1xuXG4gIGxldCB4ID0gKHFpIC0gcSkgLyAobSAtIG1pKTtcbiAgbGV0IHkgPSAobSAqIHggKyBxKTtcblxuICByZXR1cm4ge3gsIHl9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcG9pbnRQb3NpdGlvbk9uTGluZVNlZ21lbnQoeDEsIHkxLCB4MiwgeTIsIHhwLCB5cCkge1xuICBsZXQgbGVuZ3RoID0gcG9pbnRzRGlzdGFuY2UoeDEsIHkxLCB4MiwgeTIpO1xuICBsZXQgZGlzdGFuY2UgPSBwb2ludHNEaXN0YW5jZSh4MSwgeTEsIHhwLCB5cCk7XG5cbiAgbGV0IG9mZnNldCA9IGRpc3RhbmNlIC8gbGVuZ3RoO1xuICBpZiAoeDEgPiB4Mikgb2Zmc2V0ID0gbWFwUmFuZ2Uob2Zmc2V0LCAwLCAxLCAxLCAwKTtcblxuICByZXR1cm4gb2Zmc2V0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFwUmFuZ2UodmFsdWUsIGxvdzEsIGhpZ2gxLCBsb3cyLCBoaWdoMikge1xuICByZXR1cm4gbG93MiArIChoaWdoMiAtIGxvdzIpICogKHZhbHVlIC0gbG93MSkgLyAoaGlnaDEgLSBsb3cxKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFuZ2xlQmV0d2VlblR3b1BvaW50c0FuZE9yaWdpbih4MSwgeTEsIHgyLCB5Mikge1xuICByZXR1cm4gLShNYXRoLmF0YW4yKHkxIC0geTIsIHgyIC0geDEpKSAqIDE4MCAvIE1hdGguUEk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhbmdsZUJldHdlZW5Ud29Qb2ludHMoeDEsIHkxLCB4MiwgeTIpIHtcbiAgcmV0dXJuIE1hdGguYXRhbjIoeTIgLSB5MSwgeDIgLSB4MSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzYW1lUG9pbnRzKHt4OiB4MSwgeTogeTF9LCB7eDogeDIsIHk6IHkyfSkge1xuICByZXR1cm4gZkFicyh4MSAtIHgyKSA8PSBFUFNJTE9OICYmIGZBYnMoeTEgLSB5MikgPD0gRVBTSUxPTjtcbn1cblxuLyoqIEBkZXNjcmlwdGlvbiBFeHRlbmQgbGluZSBiYXNlZCBvbiBjb29yZGluYXRlcyBhbmQgbmV3IGxpbmUgbGVuZ3RoXG4gKiAgQHBhcmFtIHtudW1iZXJ9IHgxIFZlcnRleCAxIHhcbiAqICBAcGFyYW0ge251bWJlcn0geTEgVmVydGV4IDEgeVxuICogIEBwYXJhbSB7bnVtYmVyfSB4MiBWZXJ0ZXggMiB4XG4gKiAgQHBhcmFtIHtudW1iZXJ9IHkyIFZlcnRleCAyIHlcbiAqICBAcGFyYW0ge251bWJlcn0gbmV3RGlzdGFuY2UgTmV3IGxpbmUgbGVuZ3RoXG4gKiAgQHJldHVybiB7b2JqZWN0fVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0ZW5kTGluZSh4MSwgeTEsIHgyLCB5MiwgbmV3RGlzdGFuY2UsIHByZWNpc2lvbiA9IDYpIHtcbiAgbGV0IHJhZCA9IE1hdGguYXRhbjIoeTIgLSB5MSwgeDIgLSB4MSk7XG5cbiAgcmV0dXJuIHtcbiAgICB4OiB0b0ZpeGVkRmxvYXQoeDEgKyAoTWF0aC5jb3MocmFkKSAqIG5ld0Rpc3RhbmNlKSwgcHJlY2lzaW9uKSxcbiAgICB5OiB0b0ZpeGVkRmxvYXQoeTEgKyAoTWF0aC5zaW4ocmFkKSAqIG5ld0Rpc3RhbmNlKSwgcHJlY2lzaW9uKSxcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcm91bmRWZXJ0ZXgodmVydGV4LCBwcmVjaXNpb24gPSA2KSB7XG4gIHZlcnRleC5zZXQoJ3gnLCB0b0ZpeGVkRmxvYXQodmVydGV4LmdldCgneCcpLCBwcmVjaXNpb24pKTtcbiAgdmVydGV4LnNldCgneScsIHRvRml4ZWRGbG9hdCh2ZXJ0ZXguZ2V0KCd5JyksIHByZWNpc2lvbikpO1xuXG4gIHJldHVybiB2ZXJ0ZXg7XG59XG4iXX0=