UNPKG

js-angusj-clipper

Version:

Polygon and line clipping and offsetting library for Javascript / Typescript - a port of Angus Johnson's clipper to WebAssembly / Asm.JS

296 lines 36 kB
"use strict"; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.scalePaths = exports.scalePath = exports.simplifyPolygons = exports.simplifyPolygon = exports.reversePaths = exports.reversePath = exports.polyTreeToPaths = exports.pointInPolygon = exports.orientation = exports.openPathsFromPolyTree = exports.minkowskiSumPaths = exports.minkowskiSumPath = exports.minkowskiDiff = exports.closedPathsFromPolyTree = exports.cleanPolygons = exports.cleanPolygon = exports.area = void 0; var enums_1 = require("./enums"); var nativeEnumConversion_1 = require("./native/nativeEnumConversion"); var PathsToNativePaths_1 = require("./native/PathsToNativePaths"); var PathToNativePath_1 = require("./native/PathToNativePath"); function tryDelete() { var e_1, _a; var objs = []; for (var _i = 0; _i < arguments.length; _i++) { objs[_i] = arguments[_i]; } try { for (var objs_1 = __values(objs), objs_1_1 = objs_1.next(); !objs_1_1.done; objs_1_1 = objs_1.next()) { var obj = objs_1_1.value; if (!obj.isDeleted()) { obj.delete(); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (objs_1_1 && !objs_1_1.done && (_a = objs_1.return)) _a.call(objs_1); } finally { if (e_1) throw e_1.error; } } } function area(path) { // we use JS since copying structures is slower than actually doing it var cnt = path.length; if (cnt < 3) { return 0; } var a = 0; for (var i = 0, j = cnt - 1; i < cnt; ++i) { a += (path[j].x + path[i].x) * (path[j].y - path[i].y); j = i; } return -a * 0.5; } exports.area = area; function cleanPolygon(nativeLib, path, distance) { if (distance === void 0) { distance = 1.1415; } var nativePath = PathToNativePath_1.pathToNativePath(nativeLib, path); try { nativeLib.cleanPolygon(nativePath, distance); return PathToNativePath_1.nativePathToPath(nativeLib, nativePath, true); // frees nativePath } finally { tryDelete(nativePath); } } exports.cleanPolygon = cleanPolygon; function cleanPolygons(nativeLib, paths, distance) { if (distance === void 0) { distance = 1.1415; } var nativePaths = PathsToNativePaths_1.pathsToNativePaths(nativeLib, paths); try { nativeLib.cleanPolygons(nativePaths, distance); return PathsToNativePaths_1.nativePathsToPaths(nativeLib, nativePaths, true); // frees nativePath } finally { tryDelete(nativePaths); } } exports.cleanPolygons = cleanPolygons; function addPolyNodeToPaths(polynode, nt, paths) { var match = true; switch (nt) { case 1 /* Open */: return; case 2 /* Closed */: match = !polynode.isOpen; break; default: break; } if (polynode.contour.length > 0 && match) { paths.push(polynode.contour); } for (var ii = 0, max = polynode.childs.length; ii < max; ii++) { var pn = polynode.childs[ii]; addPolyNodeToPaths(pn, nt, paths); } } function closedPathsFromPolyTree(polyTree) { // we do this in JS since copying path is more expensive than just doing it var result = []; // result.Capacity = polytree.Total; addPolyNodeToPaths(polyTree, 2 /* Closed */, result); return result; } exports.closedPathsFromPolyTree = closedPathsFromPolyTree; function minkowskiDiff(nativeLib, poly1, poly2) { var nativePath1 = PathToNativePath_1.pathToNativePath(nativeLib, poly1); var nativePath2 = PathToNativePath_1.pathToNativePath(nativeLib, poly2); var outNativePaths = new nativeLib.Paths(); try { nativeLib.minkowskiDiff(nativePath1, nativePath2, outNativePaths); tryDelete(nativePath1, nativePath2); return PathsToNativePaths_1.nativePathsToPaths(nativeLib, outNativePaths, true); // frees outNativePaths } finally { tryDelete(nativePath1, nativePath2, outNativePaths); } } exports.minkowskiDiff = minkowskiDiff; function minkowskiSumPath(nativeLib, pattern, path, pathIsClosed) { var patternNativePath = PathToNativePath_1.pathToNativePath(nativeLib, pattern); var nativePath = PathToNativePath_1.pathToNativePath(nativeLib, path); var outNativePaths = new nativeLib.Paths(); try { nativeLib.minkowskiSumPath(patternNativePath, nativePath, outNativePaths, pathIsClosed); tryDelete(patternNativePath, nativePath); return PathsToNativePaths_1.nativePathsToPaths(nativeLib, outNativePaths, true); // frees outNativePaths } finally { tryDelete(patternNativePath, nativePath, outNativePaths); } } exports.minkowskiSumPath = minkowskiSumPath; function minkowskiSumPaths(nativeLib, pattern, paths, pathIsClosed) { // TODO: im not sure if for this method we can reuse the input/output path var patternNativePath = PathToNativePath_1.pathToNativePath(nativeLib, pattern); var nativePaths = PathsToNativePaths_1.pathsToNativePaths(nativeLib, paths); try { nativeLib.minkowskiSumPaths(patternNativePath, nativePaths, nativePaths, pathIsClosed); tryDelete(patternNativePath); return PathsToNativePaths_1.nativePathsToPaths(nativeLib, nativePaths, true); // frees nativePaths } finally { tryDelete(patternNativePath, nativePaths); } } exports.minkowskiSumPaths = minkowskiSumPaths; function openPathsFromPolyTree(polyTree) { // we do this in JS since copying path is more expensive than just doing it var result = []; var len = polyTree.childs.length; result.length = len; var resultLength = 0; for (var i = 0; i < len; i++) { if (polyTree.childs[i].isOpen) { result[resultLength++] = polyTree.childs[i].contour; } } result.length = resultLength; return result; } exports.openPathsFromPolyTree = openPathsFromPolyTree; function orientation(path) { return area(path) >= 0; } exports.orientation = orientation; function pointInPolygon(point, path) { // we do this in JS since copying path is more expensive than just doing it // returns 0 if false, +1 if true, -1 if pt ON polygon boundary // See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf var result = 0; var cnt = path.length; if (cnt < 3) { return 0; } var ip = path[0]; for (var i = 1; i <= cnt; ++i) { var ipNext = i === cnt ? path[0] : path[i]; if (ipNext.y === point.y) { if (ipNext.x === point.x || (ip.y === point.y && ipNext.x > point.x === ip.x < point.x)) { return -1; } } if (ip.y < point.y !== ipNext.y < point.y) { if (ip.x >= point.x) { if (ipNext.x > point.x) { result = 1 - result; } else { var d = (ip.x - point.x) * (ipNext.y - point.y) - (ipNext.x - point.x) * (ip.y - point.y); if (d === 0) { return -1; } else if (d > 0 === ipNext.y > ip.y) { result = 1 - result; } } } else { if (ipNext.x > point.x) { var d = (ip.x - point.x) * (ipNext.y - point.y) - (ipNext.x - point.x) * (ip.y - point.y); if (d === 0) { return -1; } else if (d > 0 === ipNext.y > ip.y) { result = 1 - result; } } } } ip = ipNext; } return result; } exports.pointInPolygon = pointInPolygon; function polyTreeToPaths(polyTree) { // we do this in JS since copying path is more expensive than just doing it var result = []; // result.Capacity = polytree.total; addPolyNodeToPaths(polyTree, 0 /* Any */, result); return result; } exports.polyTreeToPaths = polyTreeToPaths; function reversePath(path) { // we use JS since copying structures is slower than actually doing it path.reverse(); } exports.reversePath = reversePath; function reversePaths(paths) { // we use JS since copying structures is slower than actually doing it for (var i = 0, max = paths.length; i < max; i++) { reversePath(paths[i]); } } exports.reversePaths = reversePaths; function simplifyPolygon(nativeLib, path, fillType) { if (fillType === void 0) { fillType = enums_1.PolyFillType.EvenOdd; } var nativePath = PathToNativePath_1.pathToNativePath(nativeLib, path); var outNativePaths = new nativeLib.Paths(); try { nativeLib.simplifyPolygon(nativePath, outNativePaths, nativeEnumConversion_1.polyFillTypeToNative(nativeLib, fillType)); tryDelete(nativePath); return PathsToNativePaths_1.nativePathsToPaths(nativeLib, outNativePaths, true); // frees outNativePaths } finally { tryDelete(nativePath, outNativePaths); } } exports.simplifyPolygon = simplifyPolygon; function simplifyPolygons(nativeLib, paths, fillType) { if (fillType === void 0) { fillType = enums_1.PolyFillType.EvenOdd; } var nativePaths = PathsToNativePaths_1.pathsToNativePaths(nativeLib, paths); try { nativeLib.simplifyPolygonsOverwrite(nativePaths, nativeEnumConversion_1.polyFillTypeToNative(nativeLib, fillType)); return PathsToNativePaths_1.nativePathsToPaths(nativeLib, nativePaths, true); // frees nativePaths } finally { tryDelete(nativePaths); } } exports.simplifyPolygons = simplifyPolygons; function scalePath(path, scale) { var sol = []; var i = path.length; while (i--) { var p = path[i]; sol.push({ x: Math.round(p.x * scale), y: Math.round(p.y * scale) }); } return sol; } exports.scalePath = scalePath; /** * Scales all inner paths by multiplying all its coordinates by a number and then rounding them. * * @param paths - Paths to scale * @param scale - Scale multiplier * @return {Paths} - The scaled paths */ function scalePaths(paths, scale) { if (scale === 0) { return []; } var sol = []; var i = paths.length; while (i--) { var p = paths[i]; sol.push(scalePath(p, scale)); } return sol; } exports.scalePaths = scalePaths; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Z1bmN0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUFBLGlDQUE2RDtBQUk3RCxzRUFBcUU7QUFDckUsa0VBQXFGO0FBQ3JGLDhEQUErRTtBQU0vRSxTQUFTLFNBQVM7O0lBQUMsY0FBMEI7U0FBMUIsVUFBMEIsRUFBMUIscUJBQTBCLEVBQTFCLElBQTBCO1FBQTFCLHlCQUEwQjs7O1FBQzNDLEtBQWtCLElBQUEsU0FBQSxTQUFBLElBQUksQ0FBQSwwQkFBQSw0Q0FBRTtZQUFuQixJQUFNLEdBQUcsaUJBQUE7WUFDWixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxFQUFFO2dCQUNwQixHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7YUFDZDtTQUNGOzs7Ozs7Ozs7QUFDSCxDQUFDO0FBRUQsU0FBZ0IsSUFBSSxDQUFDLElBQWtCO0lBQ3JDLHNFQUFzRTtJQUN0RSxJQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3hCLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRTtRQUNYLE9BQU8sQ0FBQyxDQUFDO0tBQ1Y7SUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLEVBQUUsQ0FBQyxFQUFFO1FBQ3pDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkQsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUNQO0lBQ0QsT0FBTyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7QUFDbEIsQ0FBQztBQVpELG9CQVlDO0FBRUQsU0FBZ0IsWUFBWSxDQUMxQixTQUFtQyxFQUNuQyxJQUFrQixFQUNsQixRQUFpQjtJQUFqQix5QkFBQSxFQUFBLGlCQUFpQjtJQUVqQixJQUFNLFVBQVUsR0FBRyxtQ0FBZ0IsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDckQsSUFBSTtRQUNGLFNBQVMsQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzdDLE9BQU8sbUNBQWdCLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLG1CQUFtQjtLQUMxRTtZQUFTO1FBQ1IsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0tBQ3ZCO0FBQ0gsQ0FBQztBQVpELG9DQVlDO0FBRUQsU0FBZ0IsYUFBYSxDQUMzQixTQUFtQyxFQUNuQyxLQUFvQixFQUNwQixRQUFpQjtJQUFqQix5QkFBQSxFQUFBLGlCQUFpQjtJQUVqQixJQUFNLFdBQVcsR0FBRyx1Q0FBa0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDekQsSUFBSTtRQUNGLFNBQVMsQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQy9DLE9BQU8sdUNBQWtCLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLG1CQUFtQjtLQUM3RTtZQUFTO1FBQ1IsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0tBQ3hCO0FBQ0gsQ0FBQztBQVpELHNDQVlDO0FBUUQsU0FBUyxrQkFBa0IsQ0FBQyxRQUFrQixFQUFFLEVBQVksRUFBRSxLQUFxQjtJQUNqRixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUM7SUFDakIsUUFBUSxFQUFFLEVBQUU7UUFDVjtZQUNFLE9BQU87UUFDVDtZQUNFLEtBQUssR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7WUFDekIsTUFBTTtRQUNSO1lBQ0UsTUFBTTtLQUNUO0lBRUQsSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksS0FBSyxFQUFFO1FBQ3hDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0tBQzlCO0lBQ0QsS0FBSyxJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUU7UUFDN0QsSUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQixrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ25DO0FBQ0gsQ0FBQztBQUVELFNBQWdCLHVCQUF1QixDQUFDLFFBQWtCO0lBQ3hELDJFQUEyRTtJQUUzRSxJQUFNLE1BQU0sR0FBVSxFQUFFLENBQUM7SUFDekIsb0NBQW9DO0lBQ3BDLGtCQUFrQixDQUFDLFFBQVEsa0JBQW1CLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFQRCwwREFPQztBQUVELFNBQWdCLGFBQWEsQ0FDM0IsU0FBbUMsRUFDbkMsS0FBbUIsRUFDbkIsS0FBbUI7SUFFbkIsSUFBTSxXQUFXLEdBQUcsbUNBQWdCLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3ZELElBQU0sV0FBVyxHQUFHLG1DQUFnQixDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN2RCxJQUFNLGNBQWMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUU3QyxJQUFJO1FBQ0YsU0FBUyxDQUFDLGFBQWEsQ0FBQyxXQUFXLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ2xFLFNBQVMsQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDcEMsT0FBTyx1Q0FBa0IsQ0FBQyxTQUFTLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsdUJBQXVCO0tBQ3BGO1lBQVM7UUFDUixTQUFTLENBQUMsV0FBVyxFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQztLQUNyRDtBQUNILENBQUM7QUFoQkQsc0NBZ0JDO0FBRUQsU0FBZ0IsZ0JBQWdCLENBQzlCLFNBQW1DLEVBQ25DLE9BQXFCLEVBQ3JCLElBQWtCLEVBQ2xCLFlBQXFCO0lBRXJCLElBQU0saUJBQWlCLEdBQUcsbUNBQWdCLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQy9ELElBQU0sVUFBVSxHQUFHLG1DQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNyRCxJQUFNLGNBQWMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUU3QyxJQUFJO1FBQ0YsU0FBUyxDQUFDLGdCQUFnQixDQUFDLGlCQUFpQixFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDeEYsU0FBUyxDQUFDLGlCQUFpQixFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3pDLE9BQU8sdUNBQWtCLENBQUMsU0FBUyxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLHVCQUF1QjtLQUNwRjtZQUFTO1FBQ1IsU0FBUyxDQUFDLGlCQUFpQixFQUFFLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztLQUMxRDtBQUNILENBQUM7QUFqQkQsNENBaUJDO0FBRUQsU0FBZ0IsaUJBQWlCLENBQy9CLFNBQW1DLEVBQ25DLE9BQXFCLEVBQ3JCLEtBQW9CLEVBQ3BCLFlBQXFCO0lBRXJCLDBFQUEwRTtJQUUxRSxJQUFNLGlCQUFpQixHQUFHLG1DQUFnQixDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMvRCxJQUFNLFdBQVcsR0FBRyx1Q0FBa0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFFekQsSUFBSTtRQUNGLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQ3ZGLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzdCLE9BQU8sdUNBQWtCLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLG9CQUFvQjtLQUM5RTtZQUFTO1FBQ1IsU0FBUyxDQUFDLGlCQUFpQixFQUFFLFdBQVcsQ0FBQyxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQWxCRCw4Q0FrQkM7QUFFRCxTQUFnQixxQkFBcUIsQ0FBQyxRQUFrQjtJQUN0RCwyRUFBMkU7SUFFM0UsSUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLElBQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ25DLE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO0lBQ3BCLElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQztJQUNyQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQzVCLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUU7WUFDN0IsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7U0FDckQ7S0FDRjtJQUNELE1BQU0sQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFDO0lBQzdCLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFkRCxzREFjQztBQUVELFNBQWdCLFdBQVcsQ0FBQyxJQUFrQjtJQUM1QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDekIsQ0FBQztBQUZELGtDQUVDO0FBRUQsU0FBZ0IsY0FBYyxDQUM1QixLQUF5QixFQUN6QixJQUFrQjtJQUVsQiwyRUFBMkU7SUFFM0UsK0RBQStEO0lBQy9ELGlGQUFpRjtJQUNqRixxRkFBcUY7SUFDckYsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsSUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN4QixJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUU7UUFDWCxPQUFPLENBQUMsQ0FBQztLQUNWO0lBQ0QsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxHQUFHLEVBQUUsRUFBRSxDQUFDLEVBQUU7UUFDN0IsSUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0MsSUFBSSxNQUFNLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUU7WUFDeEIsSUFBSSxNQUFNLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUN2RixPQUFPLENBQUMsQ0FBQyxDQUFDO2FBQ1g7U0FDRjtRQUNELElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRTtZQUN6QyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDbkIsSUFBSSxNQUFNLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLEVBQUU7b0JBQ3RCLE1BQU0sR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDO2lCQUNyQjtxQkFBTTtvQkFDTCxJQUFNLENBQUMsR0FDTCxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNwRixJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7d0JBQ1gsT0FBTyxDQUFDLENBQUMsQ0FBQztxQkFDWDt5QkFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFO3dCQUNwQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQztxQkFDckI7aUJBQ0Y7YUFDRjtpQkFBTTtnQkFDTCxJQUFJLE1BQU0sQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsRUFBRTtvQkFDdEIsSUFBTSxDQUFDLEdBQ0wsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDcEYsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO3dCQUNYLE9BQU8sQ0FBQyxDQUFDLENBQUM7cUJBQ1g7eUJBQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRTt3QkFDcEMsTUFBTSxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUM7cUJBQ3JCO2lCQUNGO2FBQ0Y7U0FDRjtRQUNELEVBQUUsR0FBRyxNQUFNLENBQUM7S0FDYjtJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFsREQsd0NBa0RDO0FBRUQsU0FBZ0IsZUFBZSxDQUFDLFFBQWtCO0lBQ2hELDJFQUEyRTtJQUUzRSxJQUFNLE1BQU0sR0FBVSxFQUFFLENBQUM7SUFDekIsb0NBQW9DO0lBQ3BDLGtCQUFrQixDQUFDLFFBQVEsZUFBZ0IsTUFBTSxDQUFDLENBQUM7SUFDbkQsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQVBELDBDQU9DO0FBRUQsU0FBZ0IsV0FBVyxDQUFDLElBQVU7SUFDcEMsc0VBQXNFO0lBQ3RFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUNqQixDQUFDO0FBSEQsa0NBR0M7QUFFRCxTQUFnQixZQUFZLENBQUMsS0FBWTtJQUN2QyxzRUFBc0U7SUFDdEUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNoRCxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDdkI7QUFDSCxDQUFDO0FBTEQsb0NBS0M7QUFFRCxTQUFnQixlQUFlLENBQzdCLFNBQW1DLEVBQ25DLElBQWtCLEVBQ2xCLFFBQTZDO0lBQTdDLHlCQUFBLEVBQUEsV0FBeUIsb0JBQVksQ0FBQyxPQUFPO0lBRTdDLElBQU0sVUFBVSxHQUFHLG1DQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNyRCxJQUFNLGNBQWMsR0FBRyxJQUFJLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3QyxJQUFJO1FBQ0YsU0FBUyxDQUFDLGVBQWUsQ0FDdkIsVUFBVSxFQUNWLGNBQWMsRUFDZCwyQ0FBb0IsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQzFDLENBQUM7UUFDRixTQUFTLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdEIsT0FBTyx1Q0FBa0IsQ0FBQyxTQUFTLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsdUJBQXVCO0tBQ3BGO1lBQVM7UUFDUixTQUFTLENBQUMsVUFBVSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0tBQ3ZDO0FBQ0gsQ0FBQztBQWxCRCwwQ0FrQkM7QUFFRCxTQUFnQixnQkFBZ0IsQ0FDOUIsU0FBbUMsRUFDbkMsS0FBb0IsRUFDcEIsUUFBNkM7SUFBN0MseUJBQUEsRUFBQSxXQUF5QixvQkFBWSxDQUFDLE9BQU87SUFFN0MsSUFBTSxXQUFXLEdBQUcsdUNBQWtCLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3pELElBQUk7UUFDRixTQUFTLENBQUMseUJBQXlCLENBQUMsV0FBVyxFQUFFLDJDQUFvQixDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQzVGLE9BQU8sdUNBQWtCLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLG9CQUFvQjtLQUM5RTtZQUFTO1FBQ1IsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0tBQ3hCO0FBQ0gsQ0FBQztBQVpELDRDQVlDO0FBRUQsU0FBZ0IsU0FBUyxDQUFDLElBQWtCLEVBQUUsS0FBYTtJQUN6RCxJQUFNLEdBQUcsR0FBUyxFQUFFLENBQUM7SUFDckIsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNwQixPQUFPLENBQUMsRUFBRSxFQUFFO1FBQ1YsSUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLEdBQUcsQ0FBQyxJQUFJLENBQUM7WUFDUCxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUMxQixDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztTQUMzQixDQUFDLENBQUM7S0FDSjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQVhELDhCQVdDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLEtBQW9CLEVBQUUsS0FBYTtJQUM1RCxJQUFJLEtBQUssS0FBSyxDQUFDLEVBQUU7UUFDZixPQUFPLEVBQUUsQ0FBQztLQUNYO0lBRUQsSUFBTSxHQUFHLEdBQVUsRUFBRSxDQUFDO0lBQ3RCLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDckIsT0FBTyxDQUFDLEVBQUUsRUFBRTtRQUNWLElBQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQixHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztLQUMvQjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQVpELGdDQVlDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUG9pbnRJblBvbHlnb25SZXN1bHQsIFBvbHlGaWxsVHlwZSB9IGZyb20gXCIuL2VudW1zXCI7XHJcbmltcG9ydCB7IEludFBvaW50IH0gZnJvbSBcIi4vSW50UG9pbnRcIjtcclxuaW1wb3J0IHsgTmF0aXZlQ2xpcHBlckxpYkluc3RhbmNlIH0gZnJvbSBcIi4vbmF0aXZlL05hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZVwiO1xyXG5pbXBvcnQgeyBOYXRpdmVEZWxldGFibGUgfSBmcm9tIFwiLi9uYXRpdmUvTmF0aXZlRGVsZXRhYmxlXCI7XHJcbmltcG9ydCB7IHBvbHlGaWxsVHlwZVRvTmF0aXZlIH0gZnJvbSBcIi4vbmF0aXZlL25hdGl2ZUVudW1Db252ZXJzaW9uXCI7XHJcbmltcG9ydCB7IG5hdGl2ZVBhdGhzVG9QYXRocywgcGF0aHNUb05hdGl2ZVBhdGhzIH0gZnJvbSBcIi4vbmF0aXZlL1BhdGhzVG9OYXRpdmVQYXRoc1wiO1xyXG5pbXBvcnQgeyBuYXRpdmVQYXRoVG9QYXRoLCBwYXRoVG9OYXRpdmVQYXRoIH0gZnJvbSBcIi4vbmF0aXZlL1BhdGhUb05hdGl2ZVBhdGhcIjtcclxuaW1wb3J0IHsgUGF0aCwgUmVhZG9ubHlQYXRoIH0gZnJvbSBcIi4vUGF0aFwiO1xyXG5pbXBvcnQgeyBQYXRocywgUmVhZG9ubHlQYXRocyB9IGZyb20gXCIuL1BhdGhzXCI7XHJcbmltcG9ydCB7IFBvbHlOb2RlIH0gZnJvbSBcIi4vUG9seU5vZGVcIjtcclxuaW1wb3J0IHsgUG9seVRyZWUgfSBmcm9tIFwiLi9Qb2x5VHJlZVwiO1xyXG5cclxuZnVuY3Rpb24gdHJ5RGVsZXRlKC4uLm9ianM6IE5hdGl2ZURlbGV0YWJsZVtdKSB7XHJcbiAgZm9yIChjb25zdCBvYmogb2Ygb2Jqcykge1xyXG4gICAgaWYgKCFvYmouaXNEZWxldGVkKCkpIHtcclxuICAgICAgb2JqLmRlbGV0ZSgpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGFyZWEocGF0aDogUmVhZG9ubHlQYXRoKTogbnVtYmVyIHtcclxuICAvLyB3ZSB1c2UgSlMgc2luY2UgY29weWluZyBzdHJ1Y3R1cmVzIGlzIHNsb3dlciB0aGFuIGFjdHVhbGx5IGRvaW5nIGl0XHJcbiAgY29uc3QgY250ID0gcGF0aC5sZW5ndGg7XHJcbiAgaWYgKGNudCA8IDMpIHtcclxuICAgIHJldHVybiAwO1xyXG4gIH1cclxuICBsZXQgYSA9IDA7XHJcbiAgZm9yIChsZXQgaSA9IDAsIGogPSBjbnQgLSAxOyBpIDwgY250OyArK2kpIHtcclxuICAgIGEgKz0gKHBhdGhbal0ueCArIHBhdGhbaV0ueCkgKiAocGF0aFtqXS55IC0gcGF0aFtpXS55KTtcclxuICAgIGogPSBpO1xyXG4gIH1cclxuICByZXR1cm4gLWEgKiAwLjU7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjbGVhblBvbHlnb24oXHJcbiAgbmF0aXZlTGliOiBOYXRpdmVDbGlwcGVyTGliSW5zdGFuY2UsXHJcbiAgcGF0aDogUmVhZG9ubHlQYXRoLFxyXG4gIGRpc3RhbmNlID0gMS4xNDE1XHJcbik6IFBhdGgge1xyXG4gIGNvbnN0IG5hdGl2ZVBhdGggPSBwYXRoVG9OYXRpdmVQYXRoKG5hdGl2ZUxpYiwgcGF0aCk7XHJcbiAgdHJ5IHtcclxuICAgIG5hdGl2ZUxpYi5jbGVhblBvbHlnb24obmF0aXZlUGF0aCwgZGlzdGFuY2UpO1xyXG4gICAgcmV0dXJuIG5hdGl2ZVBhdGhUb1BhdGgobmF0aXZlTGliLCBuYXRpdmVQYXRoLCB0cnVlKTsgLy8gZnJlZXMgbmF0aXZlUGF0aFxyXG4gIH0gZmluYWxseSB7XHJcbiAgICB0cnlEZWxldGUobmF0aXZlUGF0aCk7XHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY2xlYW5Qb2x5Z29ucyhcclxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcclxuICBwYXRoczogUmVhZG9ubHlQYXRocyxcclxuICBkaXN0YW5jZSA9IDEuMTQxNVxyXG4pOiBQYXRocyB7XHJcbiAgY29uc3QgbmF0aXZlUGF0aHMgPSBwYXRoc1RvTmF0aXZlUGF0aHMobmF0aXZlTGliLCBwYXRocyk7XHJcbiAgdHJ5IHtcclxuICAgIG5hdGl2ZUxpYi5jbGVhblBvbHlnb25zKG5hdGl2ZVBhdGhzLCBkaXN0YW5jZSk7XHJcbiAgICByZXR1cm4gbmF0aXZlUGF0aHNUb1BhdGhzKG5hdGl2ZUxpYiwgbmF0aXZlUGF0aHMsIHRydWUpOyAvLyBmcmVlcyBuYXRpdmVQYXRoXHJcbiAgfSBmaW5hbGx5IHtcclxuICAgIHRyeURlbGV0ZShuYXRpdmVQYXRocyk7XHJcbiAgfVxyXG59XHJcblxyXG5jb25zdCBlbnVtIE5vZGVUeXBlIHtcclxuICBBbnksXHJcbiAgT3BlbixcclxuICBDbG9zZWRcclxufVxyXG5cclxuZnVuY3Rpb24gYWRkUG9seU5vZGVUb1BhdGhzKHBvbHlub2RlOiBQb2x5Tm9kZSwgbnQ6IE5vZGVUeXBlLCBwYXRoczogUmVhZG9ubHlQYXRoW10pOiB2b2lkIHtcclxuICBsZXQgbWF0Y2ggPSB0cnVlO1xyXG4gIHN3aXRjaCAobnQpIHtcclxuICAgIGNhc2UgTm9kZVR5cGUuT3BlbjpcclxuICAgICAgcmV0dXJuO1xyXG4gICAgY2FzZSBOb2RlVHlwZS5DbG9zZWQ6XHJcbiAgICAgIG1hdGNoID0gIXBvbHlub2RlLmlzT3BlbjtcclxuICAgICAgYnJlYWs7XHJcbiAgICBkZWZhdWx0OlxyXG4gICAgICBicmVhaztcclxuICB9XHJcblxyXG4gIGlmIChwb2x5bm9kZS5jb250b3VyLmxlbmd0aCA+IDAgJiYgbWF0Y2gpIHtcclxuICAgIHBhdGhzLnB1c2gocG9seW5vZGUuY29udG91cik7XHJcbiAgfVxyXG4gIGZvciAobGV0IGlpID0gMCwgbWF4ID0gcG9seW5vZGUuY2hpbGRzLmxlbmd0aDsgaWkgPCBtYXg7IGlpKyspIHtcclxuICAgIGNvbnN0IHBuID0gcG9seW5vZGUuY2hpbGRzW2lpXTtcclxuICAgIGFkZFBvbHlOb2RlVG9QYXRocyhwbiwgbnQsIHBhdGhzKTtcclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjbG9zZWRQYXRoc0Zyb21Qb2x5VHJlZShwb2x5VHJlZTogUG9seVRyZWUpOiBQYXRocyB7XHJcbiAgLy8gd2UgZG8gdGhpcyBpbiBKUyBzaW5jZSBjb3B5aW5nIHBhdGggaXMgbW9yZSBleHBlbnNpdmUgdGhhbiBqdXN0IGRvaW5nIGl0XHJcblxyXG4gIGNvbnN0IHJlc3VsdDogUGF0aHMgPSBbXTtcclxuICAvLyByZXN1bHQuQ2FwYWNpdHkgPSBwb2x5dHJlZS5Ub3RhbDtcclxuICBhZGRQb2x5Tm9kZVRvUGF0aHMocG9seVRyZWUsIE5vZGVUeXBlLkNsb3NlZCwgcmVzdWx0KTtcclxuICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbWlua293c2tpRGlmZihcclxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcclxuICBwb2x5MTogUmVhZG9ubHlQYXRoLFxyXG4gIHBvbHkyOiBSZWFkb25seVBhdGhcclxuKTogUGF0aHMge1xyXG4gIGNvbnN0IG5hdGl2ZVBhdGgxID0gcGF0aFRvTmF0aXZlUGF0aChuYXRpdmVMaWIsIHBvbHkxKTtcclxuICBjb25zdCBuYXRpdmVQYXRoMiA9IHBhdGhUb05hdGl2ZVBhdGgobmF0aXZlTGliLCBwb2x5Mik7XHJcbiAgY29uc3Qgb3V0TmF0aXZlUGF0aHMgPSBuZXcgbmF0aXZlTGliLlBhdGhzKCk7XHJcblxyXG4gIHRyeSB7XHJcbiAgICBuYXRpdmVMaWIubWlua293c2tpRGlmZihuYXRpdmVQYXRoMSwgbmF0aXZlUGF0aDIsIG91dE5hdGl2ZVBhdGhzKTtcclxuICAgIHRyeURlbGV0ZShuYXRpdmVQYXRoMSwgbmF0aXZlUGF0aDIpO1xyXG4gICAgcmV0dXJuIG5hdGl2ZVBhdGhzVG9QYXRocyhuYXRpdmVMaWIsIG91dE5hdGl2ZVBhdGhzLCB0cnVlKTsgLy8gZnJlZXMgb3V0TmF0aXZlUGF0aHNcclxuICB9IGZpbmFsbHkge1xyXG4gICAgdHJ5RGVsZXRlKG5hdGl2ZVBhdGgxLCBuYXRpdmVQYXRoMiwgb3V0TmF0aXZlUGF0aHMpO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIG1pbmtvd3NraVN1bVBhdGgoXHJcbiAgbmF0aXZlTGliOiBOYXRpdmVDbGlwcGVyTGliSW5zdGFuY2UsXHJcbiAgcGF0dGVybjogUmVhZG9ubHlQYXRoLFxyXG4gIHBhdGg6IFJlYWRvbmx5UGF0aCxcclxuICBwYXRoSXNDbG9zZWQ6IGJvb2xlYW5cclxuKTogUGF0aHMge1xyXG4gIGNvbnN0IHBhdHRlcm5OYXRpdmVQYXRoID0gcGF0aFRvTmF0aXZlUGF0aChuYXRpdmVMaWIsIHBhdHRlcm4pO1xyXG4gIGNvbnN0IG5hdGl2ZVBhdGggPSBwYXRoVG9OYXRpdmVQYXRoKG5hdGl2ZUxpYiwgcGF0aCk7XHJcbiAgY29uc3Qgb3V0TmF0aXZlUGF0aHMgPSBuZXcgbmF0aXZlTGliLlBhdGhzKCk7XHJcblxyXG4gIHRyeSB7XHJcbiAgICBuYXRpdmVMaWIubWlua293c2tpU3VtUGF0aChwYXR0ZXJuTmF0aXZlUGF0aCwgbmF0aXZlUGF0aCwgb3V0TmF0aXZlUGF0aHMsIHBhdGhJc0Nsb3NlZCk7XHJcbiAgICB0cnlEZWxldGUocGF0dGVybk5hdGl2ZVBhdGgsIG5hdGl2ZVBhdGgpO1xyXG4gICAgcmV0dXJuIG5hdGl2ZVBhdGhzVG9QYXRocyhuYXRpdmVMaWIsIG91dE5hdGl2ZVBhdGhzLCB0cnVlKTsgLy8gZnJlZXMgb3V0TmF0aXZlUGF0aHNcclxuICB9IGZpbmFsbHkge1xyXG4gICAgdHJ5RGVsZXRlKHBhdHRlcm5OYXRpdmVQYXRoLCBuYXRpdmVQYXRoLCBvdXROYXRpdmVQYXRocyk7XHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gbWlua293c2tpU3VtUGF0aHMoXHJcbiAgbmF0aXZlTGliOiBOYXRpdmVDbGlwcGVyTGliSW5zdGFuY2UsXHJcbiAgcGF0dGVybjogUmVhZG9ubHlQYXRoLFxyXG4gIHBhdGhzOiBSZWFkb25seVBhdGhzLFxyXG4gIHBhdGhJc0Nsb3NlZDogYm9vbGVhblxyXG4pOiBQYXRocyB7XHJcbiAgLy8gVE9ETzogaW0gbm90IHN1cmUgaWYgZm9yIHRoaXMgbWV0aG9kIHdlIGNhbiByZXVzZSB0aGUgaW5wdXQvb3V0cHV0IHBhdGhcclxuXHJcbiAgY29uc3QgcGF0dGVybk5hdGl2ZVBhdGggPSBwYXRoVG9OYXRpdmVQYXRoKG5hdGl2ZUxpYiwgcGF0dGVybik7XHJcbiAgY29uc3QgbmF0aXZlUGF0aHMgPSBwYXRoc1RvTmF0aXZlUGF0aHMobmF0aXZlTGliLCBwYXRocyk7XHJcblxyXG4gIHRyeSB7XHJcbiAgICBuYXRpdmVMaWIubWlua293c2tpU3VtUGF0aHMocGF0dGVybk5hdGl2ZVBhdGgsIG5hdGl2ZVBhdGhzLCBuYXRpdmVQYXRocywgcGF0aElzQ2xvc2VkKTtcclxuICAgIHRyeURlbGV0ZShwYXR0ZXJuTmF0aXZlUGF0aCk7XHJcbiAgICByZXR1cm4gbmF0aXZlUGF0aHNUb1BhdGhzKG5hdGl2ZUxpYiwgbmF0aXZlUGF0aHMsIHRydWUpOyAvLyBmcmVlcyBuYXRpdmVQYXRoc1xyXG4gIH0gZmluYWxseSB7XHJcbiAgICB0cnlEZWxldGUocGF0dGVybk5hdGl2ZVBhdGgsIG5hdGl2ZVBhdGhzKTtcclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBvcGVuUGF0aHNGcm9tUG9seVRyZWUocG9seVRyZWU6IFBvbHlUcmVlKTogUmVhZG9ubHlQYXRoW10ge1xyXG4gIC8vIHdlIGRvIHRoaXMgaW4gSlMgc2luY2UgY29weWluZyBwYXRoIGlzIG1vcmUgZXhwZW5zaXZlIHRoYW4ganVzdCBkb2luZyBpdFxyXG5cclxuICBjb25zdCByZXN1bHQgPSBbXTtcclxuICBjb25zdCBsZW4gPSBwb2x5VHJlZS5jaGlsZHMubGVuZ3RoO1xyXG4gIHJlc3VsdC5sZW5ndGggPSBsZW47XHJcbiAgbGV0IHJlc3VsdExlbmd0aCA9IDA7XHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgaWYgKHBvbHlUcmVlLmNoaWxkc1tpXS5pc09wZW4pIHtcclxuICAgICAgcmVzdWx0W3Jlc3VsdExlbmd0aCsrXSA9IHBvbHlUcmVlLmNoaWxkc1tpXS5jb250b3VyO1xyXG4gICAgfVxyXG4gIH1cclxuICByZXN1bHQubGVuZ3RoID0gcmVzdWx0TGVuZ3RoO1xyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBvcmllbnRhdGlvbihwYXRoOiBSZWFkb25seVBhdGgpOiBib29sZWFuIHtcclxuICByZXR1cm4gYXJlYShwYXRoKSA+PSAwO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gcG9pbnRJblBvbHlnb24oXHJcbiAgcG9pbnQ6IFJlYWRvbmx5PEludFBvaW50PixcclxuICBwYXRoOiBSZWFkb25seVBhdGhcclxuKTogUG9pbnRJblBvbHlnb25SZXN1bHQge1xyXG4gIC8vIHdlIGRvIHRoaXMgaW4gSlMgc2luY2UgY29weWluZyBwYXRoIGlzIG1vcmUgZXhwZW5zaXZlIHRoYW4ganVzdCBkb2luZyBpdFxyXG5cclxuICAvLyByZXR1cm5zIDAgaWYgZmFsc2UsICsxIGlmIHRydWUsIC0xIGlmIHB0IE9OIHBvbHlnb24gYm91bmRhcnlcclxuICAvLyBTZWUgXCJUaGUgUG9pbnQgaW4gUG9seWdvbiBQcm9ibGVtIGZvciBBcmJpdHJhcnkgUG9seWdvbnNcIiBieSBIb3JtYW5uICYgQWdhdGhvc1xyXG4gIC8vIGh0dHA6Ly9jaXRlc2VlcnguaXN0LnBzdS5lZHUvdmlld2RvYy9kb3dubG9hZD9kb2k9MTAuMS4xLjg4LjU0OTgmcmVwPXJlcDEmdHlwZT1wZGZcclxuICBsZXQgcmVzdWx0ID0gMDtcclxuICBjb25zdCBjbnQgPSBwYXRoLmxlbmd0aDtcclxuICBpZiAoY250IDwgMykge1xyXG4gICAgcmV0dXJuIDA7XHJcbiAgfVxyXG4gIGxldCBpcCA9IHBhdGhbMF07XHJcbiAgZm9yIChsZXQgaSA9IDE7IGkgPD0gY250OyArK2kpIHtcclxuICAgIGNvbnN0IGlwTmV4dCA9IGkgPT09IGNudCA/IHBhdGhbMF0gOiBwYXRoW2ldO1xyXG4gICAgaWYgKGlwTmV4dC55ID09PSBwb2ludC55KSB7XHJcbiAgICAgIGlmIChpcE5leHQueCA9PT0gcG9pbnQueCB8fCAoaXAueSA9PT0gcG9pbnQueSAmJiBpcE5leHQueCA+IHBvaW50LnggPT09IGlwLnggPCBwb2ludC54KSkge1xyXG4gICAgICAgIHJldHVybiAtMTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGlwLnkgPCBwb2ludC55ICE9PSBpcE5leHQueSA8IHBvaW50LnkpIHtcclxuICAgICAgaWYgKGlwLnggPj0gcG9pbnQueCkge1xyXG4gICAgICAgIGlmIChpcE5leHQueCA+IHBvaW50LngpIHtcclxuICAgICAgICAgIHJlc3VsdCA9IDEgLSByZXN1bHQ7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IGQgPVxyXG4gICAgICAgICAgICAoaXAueCAtIHBvaW50LngpICogKGlwTmV4dC55IC0gcG9pbnQueSkgLSAoaXBOZXh0LnggLSBwb2ludC54KSAqIChpcC55IC0gcG9pbnQueSk7XHJcbiAgICAgICAgICBpZiAoZCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gLTE7XHJcbiAgICAgICAgICB9IGVsc2UgaWYgKGQgPiAwID09PSBpcE5leHQueSA+IGlwLnkpIHtcclxuICAgICAgICAgICAgcmVzdWx0ID0gMSAtIHJlc3VsdDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKGlwTmV4dC54ID4gcG9pbnQueCkge1xyXG4gICAgICAgICAgY29uc3QgZCA9XHJcbiAgICAgICAgICAgIChpcC54IC0gcG9pbnQueCkgKiAoaXBOZXh0LnkgLSBwb2ludC55KSAtIChpcE5leHQueCAtIHBvaW50LngpICogKGlwLnkgLSBwb2ludC55KTtcclxuICAgICAgICAgIGlmIChkID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAtMTtcclxuICAgICAgICAgIH0gZWxzZSBpZiAoZCA+IDAgPT09IGlwTmV4dC55ID4gaXAueSkge1xyXG4gICAgICAgICAgICByZXN1bHQgPSAxIC0gcmVzdWx0O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaXAgPSBpcE5leHQ7XHJcbiAgfVxyXG4gIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBwb2x5VHJlZVRvUGF0aHMocG9seVRyZWU6IFBvbHlUcmVlKTogUGF0aHMge1xyXG4gIC8vIHdlIGRvIHRoaXMgaW4gSlMgc2luY2UgY29weWluZyBwYXRoIGlzIG1vcmUgZXhwZW5zaXZlIHRoYW4ganVzdCBkb2luZyBpdFxyXG5cclxuICBjb25zdCByZXN1bHQ6IFBhdGhzID0gW107XHJcbiAgLy8gcmVzdWx0LkNhcGFjaXR5ID0gcG9seXRyZWUudG90YWw7XHJcbiAgYWRkUG9seU5vZGVUb1BhdGhzKHBvbHlUcmVlLCBOb2RlVHlwZS5BbnksIHJlc3VsdCk7XHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2VQYXRoKHBhdGg6IFBhdGgpOiB2b2lkIHtcclxuICAvLyB3ZSB1c2UgSlMgc2luY2UgY29weWluZyBzdHJ1Y3R1cmVzIGlzIHNsb3dlciB0aGFuIGFjdHVhbGx5IGRvaW5nIGl0XHJcbiAgcGF0aC5yZXZlcnNlKCk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiByZXZlcnNlUGF0aHMocGF0aHM6IFBhdGhzKTogdm9pZCB7XHJcbiAgLy8gd2UgdXNlIEpTIHNpbmNlIGNvcHlpbmcgc3RydWN0dXJlcyBpcyBzbG93ZXIgdGhhbiBhY3R1YWxseSBkb2luZyBpdFxyXG4gIGZvciAobGV0IGkgPSAwLCBtYXggPSBwYXRocy5sZW5ndGg7IGkgPCBtYXg7IGkrKykge1xyXG4gICAgcmV2ZXJzZVBhdGgocGF0aHNbaV0pO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHNpbXBsaWZ5UG9seWdvbihcclxuICBuYXRpdmVMaWI6IE5hdGl2ZUNsaXBwZXJMaWJJbnN0YW5jZSxcclxuICBwYXRoOiBSZWFkb25seVBhdGgsXHJcbiAgZmlsbFR5cGU6IFBvbHlGaWxsVHlwZSA9IFBvbHlGaWxsVHlwZS5FdmVuT2RkXHJcbik6IFBhdGhzIHtcclxuICBjb25zdCBuYXRpdmVQYXRoID0gcGF0aFRvTmF0aXZlUGF0aChuYXRpdmVMaWIsIHBhdGgpO1xyXG4gIGNvbnN0IG91dE5hdGl2ZVBhdGhzID0gbmV3IG5hdGl2ZUxpYi5QYXRocygpO1xyXG4gIHRyeSB7XHJcbiAgICBuYXRpdmVMaWIuc2ltcGxpZnlQb2x5Z29uKFxyXG4gICAgICBuYXRpdmVQYXRoLFxyXG4gICAgICBvdXROYXRpdmVQYXRocyxcclxuICAgICAgcG9seUZpbGxUeXBlVG9OYXRpdmUobmF0aXZlTGliLCBmaWxsVHlwZSlcclxuICAgICk7XHJcbiAgICB0cnlEZWxldGUobmF0aXZlUGF0aCk7XHJcbiAgICByZXR1cm4gbmF0aXZlUGF0aHNUb1BhdGhzKG5hdGl2ZUxpYiwgb3V0TmF0aXZlUGF0aHMsIHRydWUpOyAvLyBmcmVlcyBvdXROYXRpdmVQYXRoc1xyXG4gIH0gZmluYWxseSB7XHJcbiAgICB0cnlEZWxldGUobmF0aXZlUGF0aCwgb3V0TmF0aXZlUGF0aHMpO1xyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHNpbXBsaWZ5UG9seWdvbnMoXHJcbiAgbmF0aXZlTGliOiBOYXRpdmVDbGlwcGVyTGliSW5zdGFuY2UsXHJcbiAgcGF0aHM6IFJlYWRvbmx5UGF0aHMsXHJcbiAgZmlsbFR5cGU6IFBvbHlGaWxsVHlwZSA9IFBvbHlGaWxsVHlwZS5FdmVuT2RkXHJcbik6IFBhdGhzIHtcclxuICBjb25zdCBuYXRpdmVQYXRocyA9IHBhdGhzVG9OYXRpdmVQYXRocyhuYXRpdmVMaWIsIHBhdGhzKTtcclxuICB0cnkge1xyXG4gICAgbmF0aXZlTGliLnNpbXBsaWZ5UG9seWdvbnNPdmVyd3JpdGUobmF0aXZlUGF0aHMsIHBvbHlGaWxsVHlwZVRvTmF0aXZlKG5hdGl2ZUxpYiwgZmlsbFR5cGUpKTtcclxuICAgIHJldHVybiBuYXRpdmVQYXRoc1RvUGF0aHMobmF0aXZlTGliLCBuYXRpdmVQYXRocywgdHJ1ZSk7IC8vIGZyZWVzIG5hdGl2ZVBhdGhzXHJcbiAgfSBmaW5hbGx5IHtcclxuICAgIHRyeURlbGV0ZShuYXRpdmVQYXRocyk7XHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gc2NhbGVQYXRoKHBhdGg6IFJlYWRvbmx5UGF0aCwgc2NhbGU6IG51bWJlcik6IFBhdGgge1xyXG4gIGNvbnN0IHNvbDogUGF0aCA9IFtdO1xyXG4gIGxldCBpID0gcGF0aC5sZW5ndGg7XHJcbiAgd2hpbGUgKGktLSkge1xyXG4gICAgY29uc3QgcCA9IHBhdGhbaV07XHJcbiAgICBzb2wucHVzaCh7XHJcbiAgICAgIHg6IE1hdGgucm91bmQocC54ICogc2NhbGUpLFxyXG4gICAgICB5OiBNYXRoLnJvdW5kKHAueSAqIHNjYWxlKVxyXG4gICAgfSk7XHJcbiAgfVxyXG4gIHJldHVybiBzb2w7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTY2FsZXMgYWxsIGlubmVyIHBhdGhzIGJ5IG11bHRpcGx5aW5nIGFsbCBpdHMgY29vcmRpbmF0ZXMgYnkgYSBudW1iZXIgYW5kIHRoZW4gcm91bmRpbmcgdGhlbS5cclxuICpcclxuICogQHBhcmFtIHBhdGhzIC0gUGF0aHMgdG8gc2NhbGVcclxuICogQHBhcmFtIHNjYWxlIC0gU2NhbGUgbXVsdGlwbGllclxyXG4gKiBAcmV0dXJuIHtQYXRoc30gLSBUaGUgc2NhbGVkIHBhdGhzXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gc2NhbGVQYXRocyhwYXRoczogUmVhZG9ubHlQYXRocywgc2NhbGU6IG51bWJlcik6IFBhdGhzIHtcclxuICBpZiAoc2NhbGUgPT09IDApIHtcclxuICAgIHJldHVybiBbXTtcclxuICB9XHJcblxyXG4gIGNvbnN0IHNvbDogUGF0aHMgPSBbXTtcclxuICBsZXQgaSA9IHBhdGhzLmxlbmd0aDtcclxuICB3aGlsZSAoaS0tKSB7XHJcbiAgICBjb25zdCBwID0gcGF0aHNbaV07XHJcbiAgICBzb2wucHVzaChzY2FsZVBhdGgocCwgc2NhbGUpKTtcclxuICB9XHJcbiAgcmV0dXJuIHNvbDtcclxufVxyXG4iXX0=