UNPKG

kepler.gl

Version:

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

232 lines (185 loc) 20.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.h3GetResolution = undefined; var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray'); var _slicedToArray3 = _interopRequireDefault(_slicedToArray2); exports.getVertices = getVertices; exports.getCentroid = getCentroid; exports.idToPolygonGeo = idToPolygonGeo; exports.getCenterHex = getCenterHex; exports.getH3VerticeTransform = getH3VerticeTransform; exports.distortCylinderPositions = distortCylinderPositions; exports.getRadius = getRadius; exports.getAngle = getAngle; var _h3Js = require('h3-js'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.h3GetResolution = _h3Js.h3GetResolution; // get vertices should return [lon, lat] // 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. function getVertices(_ref) { var id = _ref.id; // always reverse it return (0, _h3Js.h3ToGeoBoundary)(id, true); } // get centroid should return [lon, lat] function getCentroid(_ref2) { var id = _ref2.id; // always reverse it to [lng, lat] return (0, _h3Js.h3ToGeo)(id).reverse(); } function idToPolygonGeo(_ref3, properties) { var object = _ref3.object; if (!object || !object.id) { return null; } var vertices = getVertices(object); return { geometry: { coordinates: vertices, type: 'LineString' }, properties: properties }; } function getCenterHex(_ref4, resolution) { var latitude = _ref4.latitude, longitude = _ref4.longitude; return (0, _h3Js.geoToH3)(latitude, longitude, resolution); } // H3 hexagon are not perfect hexagon after projection, they are slightly distorted // Here we calculate the distortion from perfect hexagon to h3 hexagon // A mathematica proof can be found at // https://beta.observablehq.com/@heshan0131/h3-hexagon-shape-normalize function getH3VerticeTransform(rawVertices, centroid) { var vertices = revertVertices(rawVertices.map(function (vt) { return offset(vt, centroid); })); var radius = getRadius(vertices[0], vertices[3]); var angle = getAngle(vertices[0], vertices[3]); // rotate hexagon vertices, so that v0 - v3 axis parallel with xAxis // 2___1 // 3 / \ 0 // \___/ // 4 5 // var rotatedVertices = vertices.map(function (vt) { return rotate([0, 0], vt, angle); }); // vertices of a perfect hexagon var normalVertices = getHexagonVertices(radius); // calculate distortion return getDistortions(rotatedVertices, normalVertices); } // Vertices index based on // https://github.com/uber/luma.gl/blob/master/modules/core/src/geometry/truncated-cone-geometry.js function distortCylinderPositions(positions, distortions) { var primitives = distortions.map(function (_ref5, i) { var dr = _ref5.dr, da = _ref5.da; return getPtOnCircle(dr, da + Math.PI * i / 3); }); // close it primitives.push(primitives[0]); // starting from the 8th vertice, repeat 4 times, only replace x(0), y(1) return positions.map(function (v, i) { if (i > 20 && i < 21 * 5 && i % 3 < 2) { var row = Math.floor(i / 3); var col = i % 3; return primitives[row % 7][col]; } return v; }); } function offset(_ref6, _ref7) { var _ref9 = (0, _slicedToArray3.default)(_ref6, 2), px = _ref9[0], py = _ref9[1]; var _ref8 = (0, _slicedToArray3.default)(_ref7, 2), x0 = _ref8[0], y0 = _ref8[1]; return [[px - x0], [py - y0]]; } function rotate(_ref10, _ref11, radians) { var _ref13 = (0, _slicedToArray3.default)(_ref10, 2), cx = _ref13[0], cy = _ref13[1]; var _ref12 = (0, _slicedToArray3.default)(_ref11, 2), x = _ref12[0], y = _ref12[1]; var cos = Math.cos(radians); var sin = Math.sin(radians); var nx = cos * (x - cx) + sin * (y - cy) + cx; var ny = cos * (y - cy) - sin * (x - cx) + cy; return [nx, ny]; } function getDistance(pt0, pt1) { var dx = pt0[0] - pt1[0]; var dy = pt0[1] - pt1[1]; var dxy = Math.sqrt(dx * dx + dy * dy); return dxy; } function getRadius(pt0, pt3) { var dxy = getDistance(pt0, pt3); return dxy / 2; } function getAngle(pt0, pt3) { var dx = pt0[0] - pt3[0]; var dy = pt0[1] - pt3[1]; var dxy = Math.sqrt(dx * dx + dy * dy); // Calculate angle that the perpendicular hexagon vertex axis is tilted var angle = Math.acos(dx / dxy) * Math.sign(dy); return angle; } function getPtOnCircle(radius, angle) { return [radius * Math.cos(angle), radius * Math.sin(angle)]; } function getHexagonVertices(r) { var ang60 = Math.PI / 3; var pts = []; for (var i = 0; i < 6; i++) { pts.push(getPtOnCircle(r, ang60 * i)); } return pts; } function revertVertices(verts) { // reverting verts from clock (h3) to counter clock wise (luma cylinder) var seq = [0, 5, 4, 3, 2, 1]; return seq.map(function (s) { return verts[s]; }); } function getDistortions(vts, origs) { // 0 and 3 should be the guide var ct = [0, 0]; var distortions = []; for (var i = 0; i < 6; i++) { var vt = vts[i]; var org = origs[i]; var r = getRadius(org, ct); var dr = getRadius(vt, ct) / r; var da = Math.atan2(vt[1], vt[0]) - Math.atan2(org[1], org[0]); distortions.push({ dr: dr, da: da }); } return distortions; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvaDMtaGV4YWdvbi1sYXllci9oMy11dGlscy5qcyJdLCJuYW1lcyI6WyJnZXRWZXJ0aWNlcyIsImdldENlbnRyb2lkIiwiaWRUb1BvbHlnb25HZW8iLCJnZXRDZW50ZXJIZXgiLCJnZXRIM1ZlcnRpY2VUcmFuc2Zvcm0iLCJkaXN0b3J0Q3lsaW5kZXJQb3NpdGlvbnMiLCJnZXRSYWRpdXMiLCJnZXRBbmdsZSIsImgzR2V0UmVzb2x1dGlvbiIsImlkIiwicmV2ZXJzZSIsInByb3BlcnRpZXMiLCJvYmplY3QiLCJ2ZXJ0aWNlcyIsImdlb21ldHJ5IiwiY29vcmRpbmF0ZXMiLCJ0eXBlIiwicmVzb2x1dGlvbiIsImxhdGl0dWRlIiwibG9uZ2l0dWRlIiwicmF3VmVydGljZXMiLCJjZW50cm9pZCIsInJldmVydFZlcnRpY2VzIiwibWFwIiwib2Zmc2V0IiwidnQiLCJyYWRpdXMiLCJhbmdsZSIsInJvdGF0ZWRWZXJ0aWNlcyIsInJvdGF0ZSIsIm5vcm1hbFZlcnRpY2VzIiwiZ2V0SGV4YWdvblZlcnRpY2VzIiwiZ2V0RGlzdG9ydGlvbnMiLCJwb3NpdGlvbnMiLCJkaXN0b3J0aW9ucyIsInByaW1pdGl2ZXMiLCJpIiwiZHIiLCJkYSIsImdldFB0T25DaXJjbGUiLCJNYXRoIiwiUEkiLCJwdXNoIiwidiIsInJvdyIsImZsb29yIiwiY29sIiwicHgiLCJweSIsIngwIiwieTAiLCJyYWRpYW5zIiwiY3giLCJjeSIsIngiLCJ5IiwiY29zIiwic2luIiwibngiLCJueSIsImdldERpc3RhbmNlIiwicHQwIiwicHQxIiwiZHgiLCJkeSIsImR4eSIsInNxcnQiLCJwdDMiLCJhY29zIiwic2lnbiIsInIiLCJhbmc2MCIsInB0cyIsInZlcnRzIiwic2VxIiwicyIsInZ0cyIsIm9yaWdzIiwiY3QiLCJvcmciLCJhdGFuMiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7UUF3QmdCQSxXLEdBQUFBLFc7UUFNQUMsVyxHQUFBQSxXO1FBS0FDLGMs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IiwiZmlsZSI6ImgzLXV0aWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDE4IFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtoM0dldFJlc29sdXRpb24sIGgzVG9HZW8sIGgzVG9HZW9Cb3VuZGFyeSwgZ2VvVG9IM30gZnJvbSAnaDMtanMnO1xuZXhwb3J0IHtoM0dldFJlc29sdXRpb259O1xuXG4vLyBnZXQgdmVydGljZXMgc2hvdWxkIHJldHVybiBbbG9uLCBsYXRdXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmVydGljZXMoe2lkfSkge1xuICAvLyBhbHdheXMgcmV2ZXJzZSBpdFxuICByZXR1cm4gaDNUb0dlb0JvdW5kYXJ5KGlkLCB0cnVlKTtcbn1cblxuLy8gZ2V0IGNlbnRyb2lkIHNob3VsZCByZXR1cm4gW2xvbiwgbGF0XVxuZXhwb3J0IGZ1bmN0aW9uIGdldENlbnRyb2lkKHtpZH0pIHtcbiAgLy8gYWx3YXlzIHJldmVyc2UgaXQgdG8gW2xuZywgbGF0XVxuICByZXR1cm4gaDNUb0dlbyhpZCkucmV2ZXJzZSgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaWRUb1BvbHlnb25HZW8oe29iamVjdH0sIHByb3BlcnRpZXMpIHtcbiAgaWYgKCFvYmplY3QgfHwgIW9iamVjdC5pZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgdmVydGljZXMgPSBnZXRWZXJ0aWNlcyhvYmplY3QpO1xuXG4gIHJldHVybiB7XG4gICAgZ2VvbWV0cnk6IHtcbiAgICAgIGNvb3JkaW5hdGVzOiB2ZXJ0aWNlcyxcbiAgICAgIHR5cGU6ICdMaW5lU3RyaW5nJ1xuICAgIH0sXG4gICAgcHJvcGVydGllc1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q2VudGVySGV4KHtsYXRpdHVkZSwgbG9uZ2l0dWRlfSwgcmVzb2x1dGlvbikge1xuICByZXR1cm4gZ2VvVG9IMyhsYXRpdHVkZSwgbG9uZ2l0dWRlLCByZXNvbHV0aW9uKTtcbn1cblxuLy8gSDMgaGV4YWdvbiBhcmUgbm90IHBlcmZlY3QgaGV4YWdvbiBhZnRlciBwcm9qZWN0aW9uLCB0aGV5IGFyZSBzbGlnaHRseSBkaXN0b3J0ZWRcbi8vIEhlcmUgd2UgY2FsY3VsYXRlIHRoZSBkaXN0b3J0aW9uIGZyb20gcGVyZmVjdCBoZXhhZ29uIHRvIGgzIGhleGFnb25cbi8vIEEgbWF0aGVtYXRpY2EgcHJvb2YgY2FuIGJlIGZvdW5kIGF0XG4vLyBodHRwczovL2JldGEub2JzZXJ2YWJsZWhxLmNvbS9AaGVzaGFuMDEzMS9oMy1oZXhhZ29uLXNoYXBlLW5vcm1hbGl6ZVxuZXhwb3J0IGZ1bmN0aW9uIGdldEgzVmVydGljZVRyYW5zZm9ybShyYXdWZXJ0aWNlcywgY2VudHJvaWQpIHtcbiAgY29uc3QgdmVydGljZXMgPSByZXZlcnRWZXJ0aWNlcyhyYXdWZXJ0aWNlcy5tYXAodnQgPT4gb2Zmc2V0KHZ0LCBjZW50cm9pZCkpKTtcbiAgY29uc3QgcmFkaXVzID0gZ2V0UmFkaXVzKHZlcnRpY2VzWzBdLCB2ZXJ0aWNlc1szXSk7XG5cbiAgY29uc3QgYW5nbGUgPSBnZXRBbmdsZSh2ZXJ0aWNlc1swXSwgdmVydGljZXNbM10pXG5cbiAgLy8gcm90YXRlIGhleGFnb24gdmVydGljZXMsIHNvIHRoYXQgdjAgLSB2MyBheGlzIHBhcmFsbGVsIHdpdGggeEF4aXNcbiAgLy8gICAyX19fMVxuICAvLyAzIC8gICBcXCAwXG4gIC8vICAgXFxfX18vXG4gIC8vICAgNCAgIDVcbiAgLy9cbiAgY29uc3Qgcm90YXRlZFZlcnRpY2VzID0gdmVydGljZXMubWFwKHZ0ID0+IHJvdGF0ZShbMCwgMF0sIHZ0LCBhbmdsZSkpO1xuXG4gIC8vIHZlcnRpY2VzIG9mIGEgcGVyZmVjdCBoZXhhZ29uXG4gIGNvbnN0IG5vcm1hbFZlcnRpY2VzID0gZ2V0SGV4YWdvblZlcnRpY2VzKHJhZGl1cyk7XG5cbiAgLy8gY2FsY3VsYXRlIGRpc3RvcnRpb25cbiAgcmV0dXJuIGdldERpc3RvcnRpb25zKHJvdGF0ZWRWZXJ0aWNlcywgbm9ybWFsVmVydGljZXMpXG59XG5cbi8vIFZlcnRpY2VzIGluZGV4IGJhc2VkIG9uXG4vLyBodHRwczovL2dpdGh1Yi5jb20vdWJlci9sdW1hLmdsL2Jsb2IvbWFzdGVyL21vZHVsZXMvY29yZS9zcmMvZ2VvbWV0cnkvdHJ1bmNhdGVkLWNvbmUtZ2VvbWV0cnkuanNcbmV4cG9ydCBmdW5jdGlvbiBkaXN0b3J0Q3lsaW5kZXJQb3NpdGlvbnMocG9zaXRpb25zLCBkaXN0b3J0aW9ucykge1xuXG4gIGNvbnN0IHByaW1pdGl2ZXMgPSBkaXN0b3J0aW9ucy5tYXAoKHtkciwgZGF9LCBpKSA9PlxuICAgIGdldFB0T25DaXJjbGUoZHIsIGRhICsgTWF0aC5QSSAqIGkgLyAzKSk7XG4gIC8vIGNsb3NlIGl0XG4gIHByaW1pdGl2ZXMucHVzaChwcmltaXRpdmVzWzBdKTtcblxuICAvLyBzdGFydGluZyBmcm9tIHRoZSA4dGggdmVydGljZSwgcmVwZWF0IDQgdGltZXMsIG9ubHkgcmVwbGFjZSB4KDApLCB5KDEpXG4gIHJldHVybiBwb3NpdGlvbnMubWFwKCh2LCBpKSA9PiB7XG4gICAgaWYgKGkgPiAyMCAmJiBpIDwgMjEgKiA1ICYmIGkgJSAzIDwgMikge1xuICAgICAgY29uc3Qgcm93ID0gTWF0aC5mbG9vcihpIC8gMyk7XG4gICAgICBjb25zdCBjb2wgPSBpICUgMztcbiAgICAgIHJldHVybiBwcmltaXRpdmVzW3JvdyAlIDddW2NvbF07XG4gICAgfVxuICAgIHJldHVybiB2O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gb2Zmc2V0KFtweCwgcHldLCBbeDAsIHkwXSkge1xuICByZXR1cm4gW1tweCAtIHgwXSwgW3B5IC0geTBdXTtcbn1cblxuZnVuY3Rpb24gcm90YXRlKFtjeCwgY3ldLCBbeCwgeV0sIHJhZGlhbnMpIHtcbiAgY29uc3QgY29zID0gTWF0aC5jb3MocmFkaWFucyk7XG4gIGNvbnN0IHNpbiA9IE1hdGguc2luKHJhZGlhbnMpO1xuICBjb25zdCBueCA9IChjb3MgKiAoeCAtIGN4KSkgKyAoc2luICogKHkgLSBjeSkpICsgY3g7XG4gIGNvbnN0IG55ID0gKGNvcyAqICh5IC0gY3kpKSAtIChzaW4gKiAoeCAtIGN4KSkgKyBjeTtcblxuICByZXR1cm4gW254LCBueV07XG59XG5cbmZ1bmN0aW9uIGdldERpc3RhbmNlKHB0MCwgcHQxKSB7XG4gIGNvbnN0IGR4ID0gcHQwWzBdIC0gcHQxWzBdO1xuICBjb25zdCBkeSA9IHB0MFsxXSAtIHB0MVsxXTtcbiAgY29uc3QgZHh5ID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgcmV0dXJuIGR4eTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFJhZGl1cyhwdDAsIHB0Mykge1xuICBjb25zdCBkeHkgPSBnZXREaXN0YW5jZShwdDAsIHB0Myk7XG4gIHJldHVybiBkeHkgLyAyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QW5nbGUocHQwLCBwdDMpIHtcbiAgY29uc3QgZHggPSBwdDBbMF0gLSBwdDNbMF07XG4gIGNvbnN0IGR5ID0gcHQwWzFdIC0gcHQzWzFdO1xuICBjb25zdCBkeHkgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuXG4gIC8vIENhbGN1bGF0ZSBhbmdsZSB0aGF0IHRoZSBwZXJwZW5kaWN1bGFyIGhleGFnb24gdmVydGV4IGF4aXMgaXMgdGlsdGVkXG4gIGNvbnN0IGFuZ2xlID0gTWF0aC5hY29zKGR4IC8gZHh5KSAqIE1hdGguc2lnbihkeSk7XG4gIHJldHVybiBhbmdsZTtcbn1cblxuZnVuY3Rpb24gZ2V0UHRPbkNpcmNsZShyYWRpdXMsIGFuZ2xlKSB7XG4gIHJldHVybiBbcmFkaXVzICogIE1hdGguY29zKGFuZ2xlKSwgcmFkaXVzICogIE1hdGguc2luKGFuZ2xlKV07XG59XG5cbmZ1bmN0aW9uIGdldEhleGFnb25WZXJ0aWNlcyhyKSB7XG4gIGNvbnN0IGFuZzYwID0gTWF0aC5QSSAvIDM7XG4gIGNvbnN0IHB0cyA9IFtdXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgNjsgaSsrKSB7XG4gICAgcHRzLnB1c2goZ2V0UHRPbkNpcmNsZShyLCBhbmc2MCAqIGkpKVxuICB9XG5cbiAgcmV0dXJuIHB0cztcbn1cblxuZnVuY3Rpb24gcmV2ZXJ0VmVydGljZXModmVydHMpIHtcbiAgLy8gcmV2ZXJ0aW5nIHZlcnRzIGZyb20gY2xvY2sgKGgzKSB0byBjb3VudGVyIGNsb2NrIHdpc2UgKGx1bWEgY3lsaW5kZXIpXG4gIGNvbnN0IHNlcSA9IFswLCA1LCA0LCAzLCAyLCAxXTtcbiAgcmV0dXJuIHNlcS5tYXAocyA9PiB2ZXJ0c1tzXSk7XG59XG5cbmZ1bmN0aW9uIGdldERpc3RvcnRpb25zKHZ0cywgb3JpZ3MpIHtcbiAgLy8gMCBhbmQgMyBzaG91bGQgYmUgdGhlIGd1aWRlXG4gIGNvbnN0IGN0ID0gWzAsIDBdO1xuICBjb25zdCBkaXN0b3J0aW9ucyA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgNjsgaSsrKSB7XG4gICAgY29uc3QgdnQgPSB2dHNbaV07XG4gICAgY29uc3Qgb3JnID0gb3JpZ3NbaV07XG5cbiAgICBjb25zdCByID0gZ2V0UmFkaXVzKG9yZywgY3QpO1xuICAgIGNvbnN0IGRyID0gZ2V0UmFkaXVzKHZ0LCBjdCkgLyByXG5cbiAgICBjb25zdCBkYSA9IE1hdGguYXRhbjIodnRbMV0sIHZ0WzBdKSAtIE1hdGguYXRhbjIob3JnWzFdLCBvcmdbMF0pO1xuXG4gICAgZGlzdG9ydGlvbnMucHVzaCh7ZHIsIGRhfSk7XG4gIH1cblxuICByZXR1cm4gZGlzdG9ydGlvbnM7XG59XG4iXX0=