UNPKG

ngx-spine

Version:

[![Build Status](https://travis-ci.org/PoiScript/ngx-spine.svg?branch=master)](https://travis-ci.org/PoiScript/ngx-spine)

416 lines 44.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /****************************************************************************** * Spine Runtimes License Agreement * Last updated May 1, 2019. Replaces all prior versions. * * Copyright (c) 2013-2019, Esoteric Software LLC * * Integration of the Spine Runtimes into software or otherwise creating * derivative works of the Spine Runtimes is permitted under the terms and * conditions of Section 2 of the Spine Editor License Agreement: * http://esotericsoftware.com/spine-editor-license * * Otherwise, it is permitted to integrate the Spine Runtimes into software * or otherwise create derivative works of the Spine Runtimes (collectively, * "Products"), provided that each user of the Products must obtain their own * Spine Editor license and redistribution of the Products in any form must * include this license and copyright notice. * * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ import { Pool } from "./Utils"; export class Triangulator { constructor() { this.convexPolygons = new Array(); this.convexPolygonsIndices = new Array(); this.indicesArray = new Array(); this.isConcaveArray = new Array(); this.triangles = new Array(); this.polygonPool = new Pool((/** * @return {?} */ () => { return new Array(); })); this.polygonIndicesPool = new Pool((/** * @return {?} */ () => { return new Array(); })); } /** * @param {?} verticesArray * @return {?} */ triangulate(verticesArray) { /** @type {?} */ let vertices = verticesArray; /** @type {?} */ let vertexCount = verticesArray.length >> 1; /** @type {?} */ let indices = this.indicesArray; indices.length = 0; for (let i = 0; i < vertexCount; i++) indices[i] = i; /** @type {?} */ let isConcave = this.isConcaveArray; isConcave.length = 0; for (let i = 0, n = vertexCount; i < n; ++i) isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices); /** @type {?} */ let triangles = this.triangles; triangles.length = 0; while (vertexCount > 3) { // Find ear tip. /** @type {?} */ let previous = vertexCount - 1; /** @type {?} */ let i = 0; /** @type {?} */ let next = 1; while (true) { outer: if (!isConcave[i]) { /** @type {?} */ let p1 = indices[previous] << 1; /** @type {?} */ let p2 = indices[i] << 1; /** @type {?} */ let p3 = indices[next] << 1; /** @type {?} */ let p1x = vertices[p1]; /** @type {?} */ let p1y = vertices[p1 + 1]; /** @type {?} */ let p2x = vertices[p2]; /** @type {?} */ let p2y = vertices[p2 + 1]; /** @type {?} */ let p3x = vertices[p3]; /** @type {?} */ let p3y = vertices[p3 + 1]; for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { if (!isConcave[ii]) continue; /** @type {?} */ let v = indices[ii] << 1; /** @type {?} */ let vx = vertices[v]; /** @type {?} */ let vy = vertices[v + 1]; if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy)) break outer; } } } break; } if (next == 0) { do { if (!isConcave[i]) break; i--; } while (i > 0); break; } previous = i; i = next; next = (next + 1) % vertexCount; } // Cut ear tip. triangles.push(indices[(vertexCount + i - 1) % vertexCount]); triangles.push(indices[i]); triangles.push(indices[(i + 1) % vertexCount]); indices.splice(i, 1); isConcave.splice(i, 1); vertexCount--; /** @type {?} */ let previousIndex = (vertexCount + i - 1) % vertexCount; /** @type {?} */ let nextIndex = i == vertexCount ? 0 : i; isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices); isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices); } if (vertexCount == 3) { triangles.push(indices[2]); triangles.push(indices[0]); triangles.push(indices[1]); } return triangles; } /** * @param {?} verticesArray * @param {?} triangles * @return {?} */ decompose(verticesArray, triangles) { /** @type {?} */ let vertices = verticesArray; /** @type {?} */ let convexPolygons = this.convexPolygons; this.polygonPool.freeAll(convexPolygons); convexPolygons.length = 0; /** @type {?} */ let convexPolygonsIndices = this.convexPolygonsIndices; this.polygonIndicesPool.freeAll(convexPolygonsIndices); convexPolygonsIndices.length = 0; /** @type {?} */ let polygonIndices = this.polygonIndicesPool.obtain(); polygonIndices.length = 0; /** @type {?} */ let polygon = this.polygonPool.obtain(); polygon.length = 0; // Merge subsequent triangles if they form a triangle fan. /** @type {?} */ let fanBaseIndex = -1; /** @type {?} */ let lastWinding = 0; for (let i = 0, n = triangles.length; i < n; i += 3) { /** @type {?} */ let t1 = triangles[i] << 1; /** @type {?} */ let t2 = triangles[i + 1] << 1; /** @type {?} */ let t3 = triangles[i + 2] << 1; /** @type {?} */ let x1 = vertices[t1]; /** @type {?} */ let y1 = vertices[t1 + 1]; /** @type {?} */ let x2 = vertices[t2]; /** @type {?} */ let y2 = vertices[t2 + 1]; /** @type {?} */ let x3 = vertices[t3]; /** @type {?} */ let y3 = vertices[t3 + 1]; // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). /** @type {?} */ let merged = false; if (fanBaseIndex == t1) { /** @type {?} */ let o = polygon.length - 4; /** @type {?} */ let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3); /** @type {?} */ let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]); if (winding1 == lastWinding && winding2 == lastWinding) { polygon.push(x3); polygon.push(y3); polygonIndices.push(t3); merged = true; } } // Otherwise make this triangle the new base. if (!merged) { if (polygon.length > 0) { convexPolygons.push(polygon); convexPolygonsIndices.push(polygonIndices); } else { this.polygonPool.free(polygon); this.polygonIndicesPool.free(polygonIndices); } polygon = this.polygonPool.obtain(); polygon.length = 0; polygon.push(x1); polygon.push(y1); polygon.push(x2); polygon.push(y2); polygon.push(x3); polygon.push(y3); polygonIndices = this.polygonIndicesPool.obtain(); polygonIndices.length = 0; polygonIndices.push(t1); polygonIndices.push(t2); polygonIndices.push(t3); lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3); fanBaseIndex = t1; } } if (polygon.length > 0) { convexPolygons.push(polygon); convexPolygonsIndices.push(polygonIndices); } // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. for (let i = 0, n = convexPolygons.length; i < n; i++) { polygonIndices = convexPolygonsIndices[i]; if (polygonIndices.length == 0) continue; /** @type {?} */ let firstIndex = polygonIndices[0]; /** @type {?} */ let lastIndex = polygonIndices[polygonIndices.length - 1]; polygon = convexPolygons[i]; /** @type {?} */ let o = polygon.length - 4; /** @type {?} */ let prevPrevX = polygon[o]; /** @type {?} */ let prevPrevY = polygon[o + 1]; /** @type {?} */ let prevX = polygon[o + 2]; /** @type {?} */ let prevY = polygon[o + 3]; /** @type {?} */ let firstX = polygon[0]; /** @type {?} */ let firstY = polygon[1]; /** @type {?} */ let secondX = polygon[2]; /** @type {?} */ let secondY = polygon[3]; /** @type {?} */ let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); for (let ii = 0; ii < n; ii++) { if (ii == i) continue; /** @type {?} */ let otherIndices = convexPolygonsIndices[ii]; if (otherIndices.length != 3) continue; /** @type {?} */ let otherFirstIndex = otherIndices[0]; /** @type {?} */ let otherSecondIndex = otherIndices[1]; /** @type {?} */ let otherLastIndex = otherIndices[2]; /** @type {?} */ let otherPoly = convexPolygons[ii]; /** @type {?} */ let x3 = otherPoly[otherPoly.length - 2]; /** @type {?} */ let y3 = otherPoly[otherPoly.length - 1]; if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue; /** @type {?} */ let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); /** @type {?} */ let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY); if (winding1 == winding && winding2 == winding) { otherPoly.length = 0; otherIndices.length = 0; polygon.push(x3); polygon.push(y3); polygonIndices.push(otherLastIndex); prevPrevX = prevX; prevPrevY = prevY; prevX = x3; prevY = y3; ii = 0; } } } // Remove empty polygons that resulted from the merge step above. for (let i = convexPolygons.length - 1; i >= 0; i--) { polygon = convexPolygons[i]; if (polygon.length == 0) { convexPolygons.splice(i, 1); this.polygonPool.free(polygon); polygonIndices = convexPolygonsIndices[i]; convexPolygonsIndices.splice(i, 1); this.polygonIndicesPool.free(polygonIndices); } } return convexPolygons; } /** * @private * @param {?} index * @param {?} vertexCount * @param {?} vertices * @param {?} indices * @return {?} */ static isConcave(index, vertexCount, vertices, indices) { /** @type {?} */ let previous = indices[(vertexCount + index - 1) % vertexCount] << 1; /** @type {?} */ let current = indices[index] << 1; /** @type {?} */ let next = indices[(index + 1) % vertexCount] << 1; return !this.positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); } /** * @private * @param {?} p1x * @param {?} p1y * @param {?} p2x * @param {?} p2y * @param {?} p3x * @param {?} p3y * @return {?} */ static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) { return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; } /** * @private * @param {?} p1x * @param {?} p1y * @param {?} p2x * @param {?} p2y * @param {?} p3x * @param {?} p3y * @return {?} */ static winding(p1x, p1y, p2x, p2y, p3x, p3y) { /** @type {?} */ let px = p2x - p1x; /** @type {?} */ let py = p2y - p1y; return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; } } if (false) { /** * @type {?} * @private */ Triangulator.prototype.convexPolygons; /** * @type {?} * @private */ Triangulator.prototype.convexPolygonsIndices; /** * @type {?} * @private */ Triangulator.prototype.indicesArray; /** * @type {?} * @private */ Triangulator.prototype.isConcaveArray; /** * @type {?} * @private */ Triangulator.prototype.triangles; /** * @type {?} * @private */ Triangulator.prototype.polygonPool; /** * @type {?} * @private */ Triangulator.prototype.polygonIndicesPool; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJpYW5ndWxhdG9yLmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LXNwaW5lLyIsInNvdXJjZXMiOlsibGliL3NwaW5lLXRzL2NvcmUvVHJpYW5ndWxhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNkJBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFFL0IsTUFBTSxPQUFPLFlBQVk7SUFBekI7UUFDVSxtQkFBYyxHQUFHLElBQUksS0FBSyxFQUFpQixDQUFDO1FBQzVDLDBCQUFxQixHQUFHLElBQUksS0FBSyxFQUFpQixDQUFDO1FBRW5ELGlCQUFZLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztRQUNuQyxtQkFBYyxHQUFHLElBQUksS0FBSyxFQUFXLENBQUM7UUFDdEMsY0FBUyxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7UUFFaEMsZ0JBQVcsR0FBRyxJQUFJLElBQUk7OztRQUFnQixHQUFHLEVBQUU7WUFDakQsT0FBTyxJQUFJLEtBQUssRUFBVSxDQUFDO1FBQzdCLENBQUMsRUFBQyxDQUFDO1FBRUssdUJBQWtCLEdBQUcsSUFBSSxJQUFJOzs7UUFBZ0IsR0FBRyxFQUFFO1lBQ3hELE9BQU8sSUFBSSxLQUFLLEVBQVUsQ0FBQztRQUM3QixDQUFDLEVBQUMsQ0FBQztJQWdVTCxDQUFDOzs7OztJQTlUUSxXQUFXLENBQUMsYUFBZ0M7O1lBQzdDLFFBQVEsR0FBRyxhQUFhOztZQUN4QixXQUFXLEdBQUcsYUFBYSxDQUFDLE1BQU0sSUFBSSxDQUFDOztZQUV2QyxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVk7UUFDL0IsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDbkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFdBQVcsRUFBRSxDQUFDLEVBQUU7WUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztZQUVq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RyxHQUFHLEdBQUcsR0FBRyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakUsQ0FBQztDQUNGOzs7Ozs7SUE3VUMsc0NBQW9EOzs7OztJQUNwRCw2Q0FBMkQ7Ozs7O0lBRTNELG9DQUEyQzs7Ozs7SUFDM0Msc0NBQThDOzs7OztJQUM5QyxpQ0FBd0M7Ozs7O0lBRXhDLG1DQUVHOzs7OztJQUVILDBDQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBNYXkgMSwgMjAxOS4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDE5LCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZIEVYUFJFU1NcbiAqIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOXG4gKiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCxcbiAqIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsXG4gKiBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsIEJVU0lORVNTXG4gKiBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZXG4gKiBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkdcbiAqIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSxcbiAqIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB7IFBvb2wgfSBmcm9tIFwiLi9VdGlsc1wiO1xuXG5leHBvcnQgY2xhc3MgVHJpYW5ndWxhdG9yIHtcbiAgcHJpdmF0ZSBjb252ZXhQb2x5Z29ucyA9IG5ldyBBcnJheTxBcnJheTxudW1iZXI+PigpO1xuICBwcml2YXRlIGNvbnZleFBvbHlnb25zSW5kaWNlcyA9IG5ldyBBcnJheTxBcnJheTxudW1iZXI+PigpO1xuXG4gIHByaXZhdGUgaW5kaWNlc0FycmF5ID0gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgcHJpdmF0ZSBpc0NvbmNhdmVBcnJheSA9IG5ldyBBcnJheTxib29sZWFuPigpO1xuICBwcml2YXRlIHRyaWFuZ2xlcyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XG5cbiAgcHJpdmF0ZSBwb2x5Z29uUG9vbCA9IG5ldyBQb29sPEFycmF5PG51bWJlcj4+KCgpID0+IHtcbiAgICByZXR1cm4gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgfSk7XG5cbiAgcHJpdmF0ZSBwb2x5Z29uSW5kaWNlc1Bvb2wgPSBuZXcgUG9vbDxBcnJheTxudW1iZXI+PigoKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBBcnJheTxudW1iZXI+KCk7XG4gIH0pO1xuXG4gIHB1YmxpYyB0cmlhbmd1bGF0ZSh2ZXJ0aWNlc0FycmF5OiBBcnJheUxpa2U8bnVtYmVyPik6IEFycmF5PG51bWJlcj4ge1xuICAgIGxldCB2ZXJ0aWNlcyA9IHZlcnRpY2VzQXJyYXk7XG4gICAgbGV0IHZlcnRleENvdW50ID0gdmVydGljZXNBcnJheS5sZW5ndGggPj4gMTtcblxuICAgIGxldCBpbmRpY2VzID0gdGhpcy5pbmRpY2VzQXJyYXk7XG4gICAgaW5kaWNlcy5sZW5ndGggPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmVydGV4Q291bnQ7IGkrKykgaW5kaWNlc1tpXSA9IGk7XG5cbiAgICBsZXQgaXNDb25jYXZlID0gdGhpcy5pc0NvbmNhdmVBcnJheTtcbiAgICBpc0NvbmNhdmUubGVuZ3RoID0gMDtcbiAgICBmb3IgKGxldCBpID0gMCwgbiA9IHZlcnRleENvdW50OyBpIDwgbjsgKytpKVxuICAgICAgaXNDb25jYXZlW2ldID0gVHJpYW5ndWxhdG9yLmlzQ29uY2F2ZShpLCB2ZXJ0ZXhDb3VudCwgdmVydGljZXMsIGluZGljZXMpO1xuXG4gICAgbGV0IHRyaWFuZ2xlcyA9IHRoaXMudHJpYW5nbGVzO1xuICAgIHRyaWFuZ2xlcy5sZW5ndGggPSAwO1xuXG4gICAgd2hpbGUgKHZlcnRleENvdW50ID4gMykge1xuICAgICAgLy8gRmluZCBlYXIgdGlwLlxuICAgICAgbGV0IHByZXZpb3VzID0gdmVydGV4Q291bnQgLSAxLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbmV4dCA9IDE7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBvdXRlcjogaWYgKCFpc0NvbmNhdmVbaV0pIHtcbiAgICAgICAgICBsZXQgcDEgPSBpbmRpY2VzW3ByZXZpb3VzXSA8PCAxLFxuICAgICAgICAgICAgcDIgPSBpbmRpY2VzW2ldIDw8IDEsXG4gICAgICAgICAgICBwMyA9IGluZGljZXNbbmV4dF0gPDwgMTtcbiAgICAgICAgICBsZXQgcDF4ID0gdmVydGljZXNbcDFdLFxuICAgICAgICAgICAgcDF5ID0gdmVydGljZXNbcDEgKyAxXTtcbiAgICAgICAgICBsZXQgcDJ4ID0gdmVydGljZXNbcDJdLFxuICAgICAgICAgICAgcDJ5ID0gdmVydGljZXNbcDIgKyAxXTtcbiAgICAgICAgICBsZXQgcDN4ID0gdmVydGljZXNbcDNdLFxuICAgICAgICAgICAgcDN5ID0gdmVydGljZXNbcDMgKyAxXTtcbiAgICAgICAgICBmb3IgKFxuICAgICAgICAgICAgbGV0IGlpID0gKG5leHQgKyAxKSAlIHZlcnRleENvdW50O1xuICAgICAgICAgICAgaWkgIT0gcHJldmlvdXM7XG4gICAgICAgICAgICBpaSA9IChpaSArIDEpICUgdmVydGV4Q291bnRcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGlmICghaXNDb25jYXZlW2lpXSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgdiA9IGluZGljZXNbaWldIDw8IDE7XG4gICAgICAgICAgICBsZXQgdnggPSB2ZXJ0aWNlc1t2XSxcbiAgICAgICAgICAgICAgdnkgPSB2ZXJ0aWNlc1t2ICsgMV07XG4gICAgICAgICAgICBpZiAoVHJpYW5ndWxhdG9yLnBvc2l0aXZlQXJlYShwM3gsIHAzeSwgcDF4LCBwMXksIHZ4LCB2eSkpIHtcbiAgICAgICAgICAgICAgaWYgKFRyaWFuZ3VsYXRvci5wb3NpdGl2ZUFyZWEocDF4LCBwMXksIHAyeCwgcDJ5LCB2eCwgdnkpKSB7XG4gICAgICAgICAgICAgICAgaWYgKFRyaWFuZ3VsYXRvci5wb3NpdGl2ZUFyZWEocDJ4LCBwMnksIHAzeCwgcDN5LCB2eCwgdnkpKVxuICAgICAgICAgICAgICAgICAgYnJlYWsgb3V0ZXI7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmV4dCA9PSAwKSB7XG4gICAgICAgICAgZG8ge1xuICAgICAgICAgICAgaWYgKCFpc0NvbmNhdmVbaV0pIGJyZWFrO1xuICAgICAgICAgICAgaS0tO1xuICAgICAgICAgIH0gd2hpbGUgKGkgPiAwKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHByZXZpb3VzID0gaTtcbiAgICAgICAgaSA9IG5leHQ7XG4gICAgICAgIG5leHQgPSAobmV4dCArIDEpICUgdmVydGV4Q291bnQ7XG4gICAgICB9XG5cbiAgICAgIC8vIEN1dCBlYXIgdGlwLlxuICAgICAgdHJpYW5nbGVzLnB1c2goaW5kaWNlc1sodmVydGV4Q291bnQgKyBpIC0gMSkgJSB2ZXJ0ZXhDb3VudF0pO1xuICAgICAgdHJpYW5nbGVzLnB1c2goaW5kaWNlc1tpXSk7XG4gICAgICB0cmlhbmdsZXMucHVzaChpbmRpY2VzWyhpICsgMSkgJSB2ZXJ0ZXhDb3VudF0pO1xuICAgICAgaW5kaWNlcy5zcGxpY2UoaSwgMSk7XG4gICAgICBpc0NvbmNhdmUuc3BsaWNlKGksIDEpO1xuICAgICAgdmVydGV4Q291bnQtLTtcblxuICAgICAgbGV0IHByZXZpb3VzSW5kZXggPSAodmVydGV4Q291bnQgKyBpIC0gMSkgJSB2ZXJ0ZXhDb3VudDtcbiAgICAgIGxldCBuZXh0SW5kZXggPSBpID09IHZlcnRleENvdW50ID8gMCA6IGk7XG4gICAgICBpc0NvbmNhdmVbcHJldmlvdXNJbmRleF0gPSBUcmlhbmd1bGF0b3IuaXNDb25jYXZlKFxuICAgICAgICBwcmV2aW91c0luZGV4LFxuICAgICAgICB2ZXJ0ZXhDb3VudCxcbiAgICAgICAgdmVydGljZXMsXG4gICAgICAgIGluZGljZXNcbiAgICAgICk7XG4gICAgICBpc0NvbmNhdmVbbmV4dEluZGV4XSA9IFRyaWFuZ3VsYXRvci5pc0NvbmNhdmUoXG4gICAgICAgIG5leHRJbmRleCxcbiAgICAgICAgdmVydGV4Q291bnQsXG4gICAgICAgIHZlcnRpY2VzLFxuICAgICAgICBpbmRpY2VzXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh2ZXJ0ZXhDb3VudCA9PSAzKSB7XG4gICAgICB0cmlhbmdsZXMucHVzaChpbmRpY2VzWzJdKTtcbiAgICAgIHRyaWFuZ2xlcy5wdXNoKGluZGljZXNbMF0pO1xuICAgICAgdHJpYW5nbGVzLnB1c2goaW5kaWNlc1sxXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyaWFuZ2xlcztcbiAgfVxuXG4gIGRlY29tcG9zZShcbiAgICB2ZXJ0aWNlc0FycmF5OiBBcnJheTxudW1iZXI+LFxuICAgIHRyaWFuZ2xlczogQXJyYXk8bnVtYmVyPlxuICApOiBBcnJheTxBcnJheTxudW1iZXI+PiB7XG4gICAgbGV0IHZlcnRpY2VzID0gdmVydGljZXNBcnJheTtcbiAgICBsZXQgY29udmV4UG9seWdvbnMgPSB0aGlzLmNvbnZleFBvbHlnb25zO1xuICAgIHRoaXMucG9seWdvblBvb2wuZnJlZUFsbChjb252ZXhQb2x5Z29ucyk7XG4gICAgY29udmV4UG9seWdvbnMubGVuZ3RoID0gMDtcblxuICAgIGxldCBjb252ZXhQb2x5Z29uc0luZGljZXMgPSB0aGlzLmNvbnZleFBvbHlnb25zSW5kaWNlcztcbiAgICB0aGlzLnBvbHlnb25JbmRpY2VzUG9vbC5mcmVlQWxsKGNvbnZleFBvbHlnb25zSW5kaWNlcyk7XG4gICAgY29udmV4UG9seWdvbnNJbmRpY2VzLmxlbmd0aCA9IDA7XG5cbiAgICBsZXQgcG9seWdvbkluZGljZXMgPSB0aGlzLnBvbHlnb25JbmRpY2VzUG9vbC5vYnRhaW4oKTtcbiAgICBwb2x5Z29uSW5kaWNlcy5sZW5ndGggPSAwO1xuXG4gICAgbGV0IHBvbHlnb24gPSB0aGlzLnBvbHlnb25Qb29sLm9idGFpbigpO1xuICAgIHBvbHlnb24ubGVuZ3RoID0gMDtcblxuICAgIC8vIE1lcmdlIHN1YnNlcXVlbnQgdHJpYW5nbGVzIGlmIHRoZXkgZm9ybSBhIHRyaWFuZ2xlIGZhbi5cbiAgICBsZXQgZmFuQmFzZUluZGV4ID0gLTEsXG4gICAgICBsYXN0V2luZGluZyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDAsIG4gPSB0cmlhbmdsZXMubGVuZ3RoOyBpIDwgbjsgaSArPSAzKSB7XG4gICAgICBsZXQgdDEgPSB0cmlhbmdsZXNbaV0gPDwgMSxcbiAgICAgICAgdDIgPSB0cmlhbmdsZXNbaSArIDFdIDw8IDEsXG4gICAgICAgIHQzID0gdHJpYW5nbGVzW2kgKyAyXSA8PCAxO1xuICAgICAgbGV0IHgxID0gdmVydGljZXNbdDFdLFxuICAgICAgICB5MSA9IHZlcnRpY2VzW3QxICsgMV07XG4gICAgICBsZXQgeDIgPSB2ZXJ0aWNlc1t0Ml0sXG4gICAgICAgIHkyID0gdmVydGljZXNbdDIgKyAxXTtcbiAgICAgIGxldCB4MyA9IHZlcnRpY2VzW3QzXSxcbiAgICAgICAgeTMgPSB2ZXJ0aWNlc1t0MyArIDFdO1xuXG4gICAgICAvLyBJZiB0aGUgYmFzZSBvZiB0aGUgbGFzdCB0cmlhbmdsZSBpcyB0aGUgc2FtZSBhcyB0aGlzIHRyaWFuZ2xlLCBjaGVjayBpZiB0aGV5IGZvcm0gYSBjb252ZXggcG9seWdvbiAodHJpYW5nbGUgZmFuKS5cbiAgICAgIGxldCBtZXJnZWQgPSBmYWxzZTtcbiAgICAgIGlmIChmYW5CYXNlSW5kZXggPT0gdDEpIHtcbiAgICAgICAgbGV0IG8gPSBwb2x5Z29uLmxlbmd0aCAtIDQ7XG4gICAgICAgIGxldCB3aW5kaW5nMSA9IFRyaWFuZ3VsYXRvci53aW5kaW5nKFxuICAgICAgICAgIHBvbHlnb25bb10sXG4gICAgICAgICAgcG9seWdvbltvICsgMV0sXG4gICAgICAgICAgcG9seWdvbltvICsgMl0sXG4gICAgICAgICAgcG9seWdvbltvICsgM10sXG4gICAgICAgICAgeDMsXG4gICAgICAgICAgeTNcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IHdpbmRpbmcyID0gVHJpYW5ndWxhdG9yLndpbmRpbmcoXG4gICAgICAgICAgeDMsXG4gICAgICAgICAgeTMsXG4gICAgICAgICAgcG9seWdvblswXSxcbiAgICAgICAgICBwb2x5Z29uWzFdLFxuICAgICAgICAgIHBvbHlnb25bMl0sXG4gICAgICAgICAgcG9seWdvblszXVxuICAgICAgICApO1xuICAgICAgICBpZiAod2luZGluZzEgPT0gbGFzdFdpbmRpbmcgJiYgd2luZGluZzIgPT0gbGFzdFdpbmRpbmcpIHtcbiAgICAgICAgICBwb2x5Z29uLnB1c2goeDMpO1xuICAgICAgICAgIHBvbHlnb24ucHVzaCh5Myk7XG4gICAgICAgICAgcG9seWdvbkluZGljZXMucHVzaCh0Myk7XG4gICAgICAgICAgbWVyZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBPdGhlcndpc2UgbWFrZSB0aGlzIHRyaWFuZ2xlIHRoZSBuZXcgYmFzZS5cbiAgICAgIGlmICghbWVyZ2VkKSB7XG4gICAgICAgIGlmIChwb2x5Z29uLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb252ZXhQb2x5Z29ucy5wdXNoKHBvbHlnb24pO1xuICAgICAgICAgIGNvbnZleFBvbHlnb25zSW5kaWNlcy5wdXNoKHBvbHlnb25JbmRpY2VzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnBvbHlnb25Qb29sLmZyZWUocG9seWdvbik7XG4gICAgICAgICAgdGhpcy5wb2x5Z29uSW5kaWNlc1Bvb2wuZnJlZShwb2x5Z29uSW5kaWNlcyk7XG4gICAgICAgIH1cbiAgICAgICAgcG9seWdvbiA9IHRoaXMucG9seWdvblBvb2wub2J0YWluKCk7XG4gICAgICAgIHBvbHlnb24ubGVuZ3RoID0gMDtcbiAgICAgICAgcG9seWdvbi5wdXNoKHgxKTtcbiAgICAgICAgcG9seWdvbi5wdXNoKHkxKTtcbiAgICAgICAgcG9seWdvbi5wdXNoKHgyKTtcbiAgICAgICAgcG9seWdvbi5wdXNoKHkyKTtcbiAgICAgICAgcG9seWdvbi5wdXNoKHgzKTtcbiAgICAgICAgcG9seWdvbi5wdXNoKHkzKTtcbiAgICAgICAgcG9seWdvbkluZGljZXMgPSB0aGlzLnBvbHlnb25JbmRpY2VzUG9vbC5vYnRhaW4oKTtcbiAgICAgICAgcG9seWdvbkluZGljZXMubGVuZ3RoID0gMDtcbiAgICAgICAgcG9seWdvbkluZGljZXMucHVzaCh0MSk7XG4gICAgICAgIHBvbHlnb25JbmRpY2VzLnB1c2godDIpO1xuICAgICAgICBwb2x5Z29uSW5kaWNlcy5wdXNoKHQzKTtcbiAgICAgICAgbGFzdFdpbmRpbmcgPSBUcmlhbmd1bGF0b3Iud2luZGluZyh4MSwgeTEsIHgyLCB5MiwgeDMsIHkzKTtcbiAgICAgICAgZmFuQmFzZUluZGV4ID0gdDE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHBvbHlnb24ubGVuZ3RoID4gMCkge1xuICAgICAgY29udmV4UG9seWdvbnMucHVzaChwb2x5Z29uKTtcbiAgICAgIGNvbnZleFBvbHlnb25zSW5kaWNlcy5wdXNoKHBvbHlnb25JbmRpY2VzKTtcbiAgICB9XG5cbiAgICAvLyBHbyB0aHJvdWdoIHRoZSBsaXN0IG9mIHBvbHlnb25zIGFuZCB0cnkgdG8gbWVyZ2UgdGhlIHJlbWFpbmluZyB0cmlhbmdsZXMgd2l0aCB0aGUgZm91bmQgdHJpYW5nbGUgZmFucy5cbiAgICBmb3IgKGxldCBpID0gMCwgbiA9IGNvbnZleFBvbHlnb25zLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgcG9seWdvbkluZGljZXMgPSBjb252ZXhQb2x5Z29uc0luZGljZXNbaV07XG4gICAgICBpZiAocG9seWdvbkluZGljZXMubGVuZ3RoID09IDApIGNvbnRpbnVlO1xuICAgICAgbGV0IGZpcnN0SW5kZXggPSBwb2x5Z29uSW5kaWNlc1swXTtcbiAgICAgIGxldCBsYXN0SW5kZXggPSBwb2x5Z29uSW5kaWNlc1twb2x5Z29uSW5kaWNlcy5sZW5ndGggLSAxXTtcblxuICAgICAgcG9seWdvbiA9IGNvbnZleFBvbHlnb25zW2ldO1xuICAgICAgbGV0IG8gPSBwb2x5Z29uLmxlbmd0aCAtIDQ7XG4gICAgICBsZXQgcHJldlByZXZYID0gcG9seWdvbltvXSxcbiAgICAgICAgcHJldlByZXZZID0gcG9seWdvbltvICsgMV07XG4gICAgICBsZXQgcHJldlggPSBwb2x5Z29uW28gKyAyXSxcbiAgICAgICAgcHJldlkgPSBwb2x5Z29uW28gKyAzXTtcbiAgICAgIGxldCBmaXJzdFggPSBwb2x5Z29uWzBdLFxuICAgICAgICBmaXJzdFkgPSBwb2x5Z29uWzFdO1xuICAgICAgbGV0IHNlY29uZFggPSBwb2x5Z29uWzJdLFxuICAgICAgICBzZWNvbmRZID0gcG9seWdvblszXTtcbiAgICAgIGxldCB3aW5kaW5nID0gVHJpYW5ndWxhdG9yLndpbmRpbmcoXG4gICAgICAgIHByZXZQcmV2WCxcbiAgICAgICAgcHJldlByZXZZLFxuICAgICAgICBwcmV2WCxcbiAgICAgICAgcHJldlksXG4gICAgICAgIGZpcnN0WCxcbiAgICAgICAgZmlyc3RZXG4gICAgICApO1xuXG4gICAgICBmb3IgKGxldCBpaSA9IDA7IGlpIDwgbjsgaWkrKykge1xuICAgICAgICBpZiAoaWkgPT0gaSkgY29udGludWU7XG4gICAgICAgIGxldCBvdGhlckluZGljZXMgPSBjb252ZXhQb2x5Z29uc0luZGljZXNbaWldO1xuICAgICAgICBpZiAob3RoZXJJbmRpY2VzLmxlbmd0aCAhPSAzKSBjb250aW51ZTtcbiAgICAgICAgbGV0IG90aGVyRmlyc3RJbmRleCA9IG90aGVySW5kaWNlc1swXTtcbiAgICAgICAgbGV0IG90aGVyU2Vjb25kSW5kZXggPSBvdGhlckluZGljZXNbMV07XG4gICAgICAgIGxldCBvdGhlckxhc3RJbmRleCA9IG90aGVySW5kaWNlc1syXTtcblxuICAgICAgICBsZXQgb3RoZXJQb2x5ID0gY29udmV4UG9seWdvbnNbaWldO1xuICAgICAgICBsZXQgeDMgPSBvdGhlclBvbHlbb3RoZXJQb2x5Lmxlbmd0aCAtIDJdLFxuICAgICAgICAgIHkzID0gb3RoZXJQb2x5W290aGVyUG9seS5sZW5ndGggLSAxXTtcblxuICAgICAgICBpZiAob3RoZXJGaXJzdEluZGV4ICE9IGZpcnN0SW5kZXggfHwgb3RoZXJTZWNvbmRJbmRleCAhPSBsYXN0SW5kZXgpXG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIGxldCB3aW5kaW5nMSA9IFRyaWFuZ3VsYXRvci53aW5kaW5nKFxuICAgICAgICAgIHByZXZQcmV2WCxcbiAgICAgICAgICBwcmV2UHJldlksXG4gICAgICAgICAgcHJldlgsXG4gICAgICAgICAgcHJldlksXG4gICAgICAgICAgeDMsXG4gICAgICAgICAgeTNcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IHdpbmRpbmcyID0gVHJpYW5ndWxhdG9yLndpbmRpbmcoXG4gICAgICAgICAgeDMsXG4gICAgICAgICAgeTMsXG4gICAgICAgICAgZmlyc3RYLFxuICAgICAgICAgIGZpcnN0WSxcbiAgICAgICAgICBzZWNvbmRYLFxuICAgICAgICAgIHNlY29uZFlcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHdpbmRpbmcxID09IHdpbmRpbmcgJiYgd2luZGluZzIgPT0gd2luZGluZykge1xuICAgICAgICAgIG90aGVyUG9seS5sZW5ndGggPSAwO1xuICAgICAgICAgIG90aGVySW5kaWNlcy5sZW5ndGggPSAwO1xuICAgICAgICAgIHBvbHlnb24ucHVzaCh4Myk7XG4gICAgICAgICAgcG9seWdvbi5wdXNoKHkzKTtcbiAgICAgICAgICBwb2x5Z29uSW5kaWNlcy5wdXNoKG90aGVyTGFzdEluZGV4KTtcbiAgICAgICAgICBwcmV2UHJldlggPSBwcmV2WDtcbiAgICAgICAgICBwcmV2UHJldlkgPSBwcmV2WTtcbiAgICAgICAgICBwcmV2WCA9IHgzO1xuICAgICAgICAgIHByZXZZID0geTM7XG4gICAgICAgICAgaWkgPSAwO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGVtcHR5IHBvbHlnb25zIHRoYXQgcmVzdWx0ZWQgZnJvbSB0aGUgbWVyZ2Ugc3RlcCBhYm92ZS5cbiAgICBmb3IgKGxldCBpID0gY29udmV4UG9seWdvbnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHBvbHlnb24gPSBjb252ZXhQb2x5Z29uc1tpXTtcbiAgICAgIGlmIChwb2x5Z29uLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgIGNvbnZleFBvbHlnb25zLnNwbGljZShpLCAxKTtcbiAgICAgICAgdGhpcy5wb2x5Z29uUG9vbC5mcmVlKHBvbHlnb24pO1xuICAgICAgICBwb2x5Z29uSW5kaWNlcyA9IGNvbnZleFBvbHlnb25zSW5kaWNlc1tpXTtcbiAgICAgICAgY29udmV4UG9seWdvbnNJbmRpY2VzLnNwbGljZShpLCAxKTtcbiAgICAgICAgdGhpcy5wb2x5Z29uSW5kaWNlc1Bvb2wuZnJlZShwb2x5Z29uSW5kaWNlcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnZleFBvbHlnb25zO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgaXNDb25jYXZlKFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgdmVydGV4Q291bnQ6IG51bWJlcixcbiAgICB2ZXJ0aWNlczogQXJyYXlMaWtlPG51bWJlcj4sXG4gICAgaW5kaWNlczogQXJyYXlMaWtlPG51bWJlcj5cbiAgKTogYm9vbGVhbiB7XG4gICAgbGV0IHByZXZpb3VzID0gaW5kaWNlc1sodmVydGV4Q291bnQgKyBpbmRleCAtIDEpICUgdmVydGV4Q291bnRdIDw8IDE7XG4gICAgbGV0IGN1cnJlbnQgPSBpbmRpY2VzW2luZGV4XSA8PCAxO1xuICAgIGxldCBuZXh0ID0gaW5kaWNlc1soaW5kZXggKyAxKSAlIHZlcnRleENvdW50XSA8PCAxO1xuICAgIHJldHVybiAhdGhpcy5wb3NpdGl2ZUFyZWEoXG4gICAgICB2ZXJ0aWNlc1twcmV2aW91c10sXG4gICAgICB2ZXJ0aWNlc1twcmV2aW91cyArIDFdLFxuICAgICAgdmVydGljZXNbY3VycmVudF0sXG4gICAgICB2ZXJ0aWNlc1tjdXJyZW50ICsgMV0sXG4gICAgICB2ZXJ0aWNlc1tuZXh0XSxcbiAgICAgIHZlcnRpY2VzW25leHQgKyAxXVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwb3NpdGl2ZUFyZWEoXG4gICAgcDF4OiBudW1iZXIsXG4gICAgcDF5OiBudW1iZXIsXG4gICAgcDJ4OiBudW1iZXIsXG4gICAgcDJ5OiBudW1iZXIsXG4gICAgcDN4OiBudW1iZXIsXG4gICAgcDN5OiBudW1iZXJcbiAgKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHAxeCAqIChwM3kgLSBwMnkpICsgcDJ4ICogKHAxeSAtIHAzeSkgKyBwM3ggKiAocDJ5IC0gcDF5KSA+PSAwO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgd2luZGluZyhcbiAgICBwMXg6IG51bWJlcixcbiAgICBwMXk6IG51bWJlcixcbiAgICBwMng6IG51bWJlcixcbiAgICBwMnk6IG51bWJlcixcbiAgICBwM3g6IG51bWJlcixcbiAgICBwM3k6IG51bWJlclxuICApOiBudW1iZXIge1xuICAgIGxldCBweCA9IHAyeCAtIHAxeCxcbiAgICAgIHB5ID0gcDJ5IC0gcDF5O1xuICAgIHJldHVybiBwM3ggKiBweSAtIHAzeSAqIHB4ICsgcHggKiBwMXkgLSBwMXggKiBweSA+PSAwID8gMSA6IC0xO1xuICB9XG59XG4iXX0=