UNPKG

@esotericsoftware/spine-core

Version:
310 lines 50 kB
/****************************************************************************** * Spine Runtimes License Agreement * Last updated April 5, 2025. Replaces all prior versions. * * Copyright (c) 2013-2025, 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. * * THE SPINE RUNTIMES ARE 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 * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ import { ClippingAttachment, MeshAttachment, RegionAttachment } from "./attachments/index.js"; import { SkeletonClipping } from "./SkeletonClipping.js"; import { BlendMode } from "./SlotData.js"; export class SkeletonRendererCore { commandPool = new CommandPool(); worldVertices = new Float32Array(12 * 1024); quadIndices = new Uint16Array([0, 1, 2, 2, 3, 0]); clipping = new SkeletonClipping(); renderCommands = []; render(skeleton, pma = false, inColor, stride = 2) { this.commandPool.reset(); this.renderCommands.length = 0; const clipper = this.clipping; const drawOrder = skeleton.drawOrder.appliedPose; for (let i = 0; i < skeleton.slots.length; i++) { const slot = drawOrder[i]; const attachment = slot.appliedPose.attachment; if (!attachment) { clipper.clipEnd(slot); continue; } const pose = slot.appliedPose; const slotColor = pose.color; const alpha = slotColor.a; if ((alpha === 0 || !slot.bone.active) && !(attachment instanceof ClippingAttachment)) { clipper.clipEnd(slot); continue; } let vertices; let verticesCount; let uvs; let indices; let indicesCount; let attachmentColor; // biome-ignore lint/suspicious/noExplicitAny: texture depends on the runtime let texture; if (attachment instanceof RegionAttachment) { attachmentColor = attachment.color; if (attachmentColor.a === 0) { clipper.clipEnd(slot); continue; } const sequence = attachment.sequence; const sequenceIndex = sequence.resolveIndex(pose); attachment.computeWorldVertices(slot, attachment.getOffsets(pose), this.worldVertices, 0, stride); vertices = this.worldVertices; verticesCount = 4; uvs = sequence.getUVs(sequenceIndex); indices = this.quadIndices; indicesCount = 6; texture = sequence.regions[sequenceIndex]?.texture; } else if (attachment instanceof MeshAttachment) { attachmentColor = attachment.color; if (attachmentColor.a === 0) { clipper.clipEnd(slot); continue; } if (this.worldVertices.length < attachment.worldVerticesLength) this.worldVertices = new Float32Array(attachment.worldVerticesLength); attachment.computeWorldVertices(skeleton, slot, 0, attachment.worldVerticesLength, this.worldVertices, 0, stride); vertices = this.worldVertices; verticesCount = attachment.worldVerticesLength >> 1; const sequence = attachment.sequence; const sequenceIndex = sequence.resolveIndex(pose); uvs = sequence.getUVs(sequenceIndex); indices = attachment.triangles; indicesCount = indices.length; texture = sequence.regions[sequenceIndex]?.texture; } else if (attachment instanceof ClippingAttachment) { clipper.clipStart(skeleton, slot, attachment); continue; } else { continue; } const skelColor = skeleton.color; let color, darkColor; if (pma) { let a; if (inColor) { a = Math.floor(inColor[3] * skelColor.a * slotColor.a * attachmentColor.a * 255); const r = Math.floor(a * inColor[0] * skelColor.r * slotColor.r * attachmentColor.r); const g = Math.floor(a * inColor[1] * skelColor.g * slotColor.g * attachmentColor.g); const b = Math.floor(a * inColor[2] * skelColor.b * slotColor.b * attachmentColor.b); color = (a << 24) | (r << 16) | (g << 8) | b; } else { a = Math.floor(skelColor.a * slotColor.a * attachmentColor.a * 255); const r = Math.floor(a * skelColor.r * slotColor.r * attachmentColor.r); const g = Math.floor(a * skelColor.g * slotColor.g * attachmentColor.g); const b = Math.floor(a * skelColor.b * slotColor.b * attachmentColor.b); color = (a << 24) | (r << 16) | (g << 8) | b; } darkColor = 0xff000000; if (pose.darkColor) { const { r, g, b } = pose.darkColor; darkColor = 0xff000000 | (Math.floor(r * a) << 16) | (Math.floor(g * a) << 8) | Math.floor(b * a); } } else { if (inColor) { const a = Math.floor(inColor[3] * skelColor.a * slotColor.a * attachmentColor.a * 255); const r = Math.floor(inColor[0] * skelColor.r * slotColor.r * attachmentColor.r * 255); const g = Math.floor(inColor[1] * skelColor.g * slotColor.g * attachmentColor.g * 255); const b = Math.floor(inColor[2] * skelColor.b * slotColor.b * attachmentColor.b * 255); color = (a << 24) | (r << 16) | (g << 8) | b; } else { const a = Math.floor(skelColor.a * slotColor.a * attachmentColor.a * 255); const r = Math.floor(skelColor.r * slotColor.r * attachmentColor.r * 255); const g = Math.floor(skelColor.g * slotColor.g * attachmentColor.g * 255); const b = Math.floor(skelColor.b * slotColor.b * attachmentColor.b * 255); color = (a << 24) | (r << 16) | (g << 8) | b; } darkColor = 0; if (pose.darkColor) { const { r, g, b } = pose.darkColor; darkColor = (Math.floor(r * 255) << 16) | (Math.floor(g * 255) << 8) | Math.floor(b * 255); } } if (clipper.isClipping()) { clipper.clipTrianglesUnpacked(vertices, 0, indices, indicesCount, uvs, stride); vertices = clipper.clippedVerticesTyped; verticesCount = clipper.clippedVerticesLength / stride; uvs = clipper.clippedUVsTyped; indices = clipper.clippedTrianglesTyped; indicesCount = clipper.clippedTrianglesLength; } const cmd = this.commandPool.getCommand(verticesCount, indicesCount, stride); cmd.blendMode = slot.data.blendMode; cmd.texture = texture; cmd.positions.set(vertices.subarray(0, verticesCount * stride)); cmd.uvs.set(uvs.subarray(0, verticesCount << 1)); for (let j = 0; j < verticesCount; j++) { cmd.colors[j] = color; cmd.darkColors[j] = darkColor; } if (indices instanceof Uint16Array) { cmd.indices.set(indices.subarray(0, indicesCount)); } else { cmd.indices.set(indices.slice(0, indicesCount)); } this.renderCommands.push(cmd); clipper.clipEnd(slot); } clipper.clipEnd(); return this.batchCommands(stride); } batchSubCommands(commands, first, last, numVertices, numIndices, stride) { const firstCmd = commands[first]; const batched = this.commandPool.getCommand(numVertices, numIndices, stride); batched.blendMode = firstCmd.blendMode; batched.texture = firstCmd.texture; let positionsOffset = 0; let uvsOffset = 0; let colorsOffset = 0; let indicesOffset = 0; let vertexOffset = 0; for (let i = first; i <= last; i++) { const cmd = commands[i]; batched.positions.set(cmd.positions, positionsOffset); positionsOffset += cmd.numVertices * stride; batched.uvs.set(cmd.uvs, uvsOffset); uvsOffset += cmd.numVertices << 1; batched.colors.set(cmd.colors, colorsOffset); batched.darkColors.set(cmd.darkColors, colorsOffset); colorsOffset += cmd.numVertices; // cannot fast copy - indices need vertex offset adjustment for (let j = 0; j < cmd.numIndices; j++) batched.indices[indicesOffset + j] = cmd.indices[j] + vertexOffset; indicesOffset += cmd.numIndices; vertexOffset += cmd.numVertices; } return batched; } batchCommands(stride) { if (this.renderCommands.length === 0) return undefined; let root; let last; let first = this.renderCommands[0]; let startIndex = 0; let i = 1; let numVertices = first.numVertices; let numIndices = first.numIndices; while (i <= this.renderCommands.length) { const cmd = i < this.renderCommands.length ? this.renderCommands[i] : null; if (cmd && cmd.numVertices === 0 && cmd.numIndices === 0) { i++; continue; } const canBatch = cmd !== null && cmd.texture === first.texture && cmd.blendMode === first.blendMode && cmd.colors[0] === first.colors[0] && cmd.darkColors[0] === first.darkColors[0] && numIndices + cmd.numIndices < 0xffff; if (canBatch) { numVertices += cmd.numVertices; numIndices += cmd.numIndices; } else { const batched = this.batchSubCommands(this.renderCommands, startIndex, i - 1, numVertices, numIndices, stride); if (!last) { root = last = batched; } else { last.next = batched; last = batched; } if (i === this.renderCommands.length) break; first = this.renderCommands[i]; startIndex = i; numVertices = first.numVertices; numIndices = first.numIndices; } i++; } return root; } } class CommandPool { pool = []; inUse = []; getCommand(numVertices, numIndices, stride) { let cmd; for (const c of this.pool) { if (c._positions.length >= numVertices * stride && c._indices.length >= numIndices) { cmd = c; break; } } if (!cmd) { const _positions = new Float32Array(numVertices * stride); const _uvs = new Float32Array(numVertices << 1); const _colors = new Uint32Array(numVertices); const _darkColors = new Uint32Array(numVertices); const _indices = new Uint16Array(numIndices); cmd = { positions: _positions, uvs: _uvs, colors: _colors, darkColors: _darkColors, indices: _indices, _positions, _uvs, _colors, _darkColors, _indices, numVertices, numIndices, blendMode: BlendMode.Normal, texture: null }; } else { this.pool.splice(this.pool.indexOf(cmd), 1); cmd.next = undefined; cmd.numVertices = numVertices; cmd.numIndices = numIndices; cmd.positions = cmd._positions.subarray(0, numVertices * stride); cmd.uvs = cmd._uvs.subarray(0, numVertices << 1); cmd.colors = cmd._colors.subarray(0, numVertices); cmd.darkColors = cmd._darkColors.subarray(0, numVertices); cmd.indices = cmd._indices.subarray(0, numIndices); } this.inUse.push(cmd); return cmd; } reset() { this.pool.push(...this.inUse); this.inUse.length = 0; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25SZW5kZXJlckNvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU2tlbGV0b25SZW5kZXJlckNvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRS9FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU5RixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRzFDLE1BQU0sT0FBTyxvQkFBb0I7SUFDeEIsV0FBVyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7SUFDaEMsYUFBYSxHQUFHLElBQUksWUFBWSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUM1QyxXQUFXLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEQsUUFBUSxHQUFHLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztJQUNsQyxjQUFjLEdBQW9CLEVBQUUsQ0FBQztJQUU3QyxNQUFNLENBQUUsUUFBa0IsRUFBRSxHQUFHLEdBQUcsS0FBSyxFQUFFLE9BQTBDLEVBQUUsTUFBTSxHQUFHLENBQUM7UUFDOUYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFFL0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUU5QixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQztRQUNqRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFD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SUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDckIsT0FBTyxHQUFHLENBQUM7SUFDWixDQUFDO0lBRUQsS0FBSztRQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN2QixDQUFDO0NBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIEFwcmlsIDUsIDIwMjUuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAyNSwgRXNvdGVyaWMgU29mdHdhcmUgTExDXG4gKlxuICogSW50ZWdyYXRpb24gb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3Igb3RoZXJ3aXNlIGNyZWF0aW5nXG4gKiBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpcyBwZXJtaXR0ZWQgdW5kZXIgdGhlIHRlcm1zIGFuZFxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcbiAqIGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1lZGl0b3ItbGljZW5zZVxuICpcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxuICogb3Igb3RoZXJ3aXNlIGNyZWF0ZSBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyAoY29sbGVjdGl2ZWx5LFxuICogXCJQcm9kdWN0c1wiKSwgcHJvdmlkZWQgdGhhdCBlYWNoIHVzZXIgb2YgdGhlIFByb2R1Y3RzIG11c3Qgb2J0YWluIHRoZWlyIG93blxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XG4gKiBpbmNsdWRlIHRoaXMgbGljZW5zZSBhbmQgY29weXJpZ2h0IG5vdGljZS5cbiAqXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMgQVJFIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZXG4gKiBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTLFxuICogQlVTSU5FU1MgSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EXG4gKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB7IENsaXBwaW5nQXR0YWNobWVudCwgTWVzaEF0dGFjaG1lbnQsIFJlZ2lvbkF0dGFjaG1lbnQgfSBmcm9tIFwiLi9hdHRhY2htZW50cy9pbmRleC5qc1wiO1xuaW1wb3J0IHR5cGUgeyBTa2VsZXRvbiB9IGZyb20gXCIuL1NrZWxldG9uLmpzXCI7XG5pbXBvcnQgeyBTa2VsZXRvbkNsaXBwaW5nIH0gZnJvbSBcIi4vU2tlbGV0b25DbGlwcGluZy5qc1wiO1xuaW1wb3J0IHsgQmxlbmRNb2RlIH0gZnJvbSBcIi4vU2xvdERhdGEuanNcIjtcbmltcG9ydCB0eXBlIHsgQ29sb3IsIE51bWJlckFycmF5TGlrZSB9IGZyb20gXCIuL1V0aWxzLmpzXCI7XG5cbmV4cG9ydCBjbGFzcyBTa2VsZXRvblJlbmRlcmVyQ29yZSB7XG5cdHByaXZhdGUgY29tbWFuZFBvb2wgPSBuZXcgQ29tbWFuZFBvb2woKTtcblx0cHJpdmF0ZSB3b3JsZFZlcnRpY2VzID0gbmV3IEZsb2F0MzJBcnJheSgxMiAqIDEwMjQpO1xuXHRwcml2YXRlIHF1YWRJbmRpY2VzID0gbmV3IFVpbnQxNkFycmF5KFswLCAxLCAyLCAyLCAzLCAwXSk7XG5cdHByaXZhdGUgY2xpcHBpbmcgPSBuZXcgU2tlbGV0b25DbGlwcGluZygpO1xuXHRwcml2YXRlIHJlbmRlckNvbW1hbmRzOiBSZW5kZXJDb21tYW5kW10gPSBbXTtcblxuXHRyZW5kZXIgKHNrZWxldG9uOiBTa2VsZXRvbiwgcG1hID0gZmFsc2UsIGluQ29sb3I/OiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgc3RyaWRlID0gMik6IFJlbmRlckNvbW1hbmQgfCB1bmRlZmluZWQge1xuXHRcdHRoaXMuY29tbWFuZFBvb2wucmVzZXQoKTtcblx0XHR0aGlzLnJlbmRlckNvbW1hbmRzLmxlbmd0aCA9IDA7XG5cblx0XHRjb25zdCBjbGlwcGVyID0gdGhpcy5jbGlwcGluZztcblxuXHRcdGNvbnN0IGRyYXdPcmRlciA9IHNrZWxldG9uLmRyYXdPcmRlci5hcHBsaWVkUG9zZTtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHNrZWxldG9uLnNsb3RzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRjb25zdCBzbG90ID0gZHJhd09yZGVyW2ldO1xuXHRcdFx0Y29uc3QgYXR0YWNobWVudCA9IHNsb3QuYXBwbGllZFBvc2UuYXR0YWNobWVudDtcblxuXHRcdFx0aWYgKCFhdHRhY2htZW50KSB7XG5cdFx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IHBvc2UgPSBzbG90LmFwcGxpZWRQb3NlO1xuXHRcdFx0Y29uc3Qgc2xvdENvbG9yID0gcG9zZS5jb2xvcjtcblx0XHRcdGNvbnN0IGFscGhhID0gc2xvdENvbG9yLmE7XG5cdFx0XHRpZiAoKGFscGhhID09PSAwIHx8ICFzbG90LmJvbmUuYWN0aXZlKSAmJiAhKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBDbGlwcGluZ0F0dGFjaG1lbnQpKSB7XG5cdFx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGxldCB2ZXJ0aWNlczogTnVtYmVyQXJyYXlMaWtlO1xuXHRcdFx0bGV0IHZlcnRpY2VzQ291bnQ6IG51bWJlcjtcblx0XHRcdGxldCB1dnM6IE51bWJlckFycmF5TGlrZTtcblx0XHRcdGxldCBpbmRpY2VzOiBudW1iZXJbXSB8IFVpbnQxNkFycmF5O1xuXHRcdFx0bGV0IGluZGljZXNDb3VudDogbnVtYmVyO1xuXHRcdFx0bGV0IGF0dGFjaG1lbnRDb2xvcjogQ29sb3I7XG5cdFx0XHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IHRleHR1cmUgZGVwZW5kcyBvbiB0aGUgcnVudGltZVxuXHRcdFx0bGV0IHRleHR1cmU6IGFueTtcblxuXHRcdFx0aWYgKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBSZWdpb25BdHRhY2htZW50KSB7XG5cdFx0XHRcdGF0dGFjaG1lbnRDb2xvciA9IGF0dGFjaG1lbnQuY29sb3I7XG5cblx0XHRcdFx0aWYgKGF0dGFjaG1lbnRDb2xvci5hID09PSAwKSB7XG5cdFx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uc3Qgc2VxdWVuY2UgPSBhdHRhY2htZW50LnNlcXVlbmNlO1xuXHRcdFx0XHRjb25zdCBzZXF1ZW5jZUluZGV4ID0gc2VxdWVuY2UucmVzb2x2ZUluZGV4KHBvc2UpO1xuXHRcdFx0XHRhdHRhY2htZW50LmNvbXB1dGVXb3JsZFZlcnRpY2VzKHNsb3QsIGF0dGFjaG1lbnQuZ2V0T2Zmc2V0cyhwb3NlKSwgdGhpcy53b3JsZFZlcnRpY2VzLCAwLCBzdHJpZGUpO1xuXG5cdFx0XHRcdHZlcnRpY2VzID0gdGhpcy53b3JsZFZlcnRpY2VzO1xuXHRcdFx0XHR2ZXJ0aWNlc0NvdW50ID0gNDtcblx0XHRcdFx0dXZzID0gc2VxdWVuY2UuZ2V0VVZzKHNlcXVlbmNlSW5kZXgpO1xuXHRcdFx0XHRpbmRpY2VzID0gdGhpcy5xdWFkSW5kaWNlcztcblx0XHRcdFx0aW5kaWNlc0NvdW50ID0gNjtcblx0XHRcdFx0dGV4dHVyZSA9IHNlcXVlbmNlLnJlZ2lvbnNbc2VxdWVuY2VJbmRleF0/LnRleHR1cmU7XG5cblx0XHRcdH0gZWxzZSBpZiAoYXR0YWNobWVudCBpbnN0YW5jZW9mIE1lc2hBdHRhY2htZW50KSB7XG5cdFx0XHRcdGF0dGFjaG1lbnRDb2xvciA9IGF0dGFjaG1lbnQuY29sb3I7XG5cblx0XHRcdFx0aWYgKGF0dGFjaG1lbnRDb2xvci5hID09PSAwKSB7XG5cdFx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHRoaXMud29ybGRWZXJ0aWNlcy5sZW5ndGggPCBhdHRhY2htZW50LndvcmxkVmVydGljZXNMZW5ndGgpXG5cdFx0XHRcdFx0dGhpcy53b3JsZFZlcnRpY2VzID0gbmV3IEZsb2F0MzJBcnJheShhdHRhY2htZW50LndvcmxkVmVydGljZXNMZW5ndGgpO1xuXG5cdFx0XHRcdGF0dGFjaG1lbnQuY29tcHV0ZVdvcmxkVmVydGljZXMoc2tlbGV0b24sIHNsb3QsIDAsIGF0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aCwgdGhpcy53b3JsZFZlcnRpY2VzLCAwLCBzdHJpZGUpO1xuXHRcdFx0XHR2ZXJ0aWNlcyA9IHRoaXMud29ybGRWZXJ0aWNlcztcblx0XHRcdFx0dmVydGljZXNDb3VudCA9IGF0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aCA+PiAxO1xuXG5cdFx0XHRcdGNvbnN0IHNlcXVlbmNlID0gYXR0YWNobWVudC5zZXF1ZW5jZTtcblx0XHRcdFx0Y29uc3Qgc2VxdWVuY2VJbmRleCA9IHNlcXVlbmNlLnJlc29sdmVJbmRleChwb3NlKTtcblxuXHRcdFx0XHR1dnMgPSBzZXF1ZW5jZS5nZXRVVnMoc2VxdWVuY2VJbmRleCk7XG5cdFx0XHRcdGluZGljZXMgPSBhdHRhY2htZW50LnRyaWFuZ2xlcztcblx0XHRcdFx0aW5kaWNlc0NvdW50ID0gaW5kaWNlcy5sZW5ndGg7XG5cdFx0XHRcdHRleHR1cmUgPSBzZXF1ZW5jZS5yZWdpb25zW3NlcXVlbmNlSW5kZXhdPy50ZXh0dXJlO1xuXG5cdFx0XHR9IGVsc2UgaWYgKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBDbGlwcGluZ0F0dGFjaG1lbnQpIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwU3RhcnQoc2tlbGV0b24sIHNsb3QsIGF0dGFjaG1lbnQpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBza2VsQ29sb3IgPSBza2VsZXRvbi5jb2xvcjtcblx0XHRcdGxldCBjb2xvcjogbnVtYmVyLCBkYXJrQ29sb3I6IG51bWJlcjtcblx0XHRcdGlmIChwbWEpIHtcblx0XHRcdFx0bGV0IGE6IG51bWJlcjtcblx0XHRcdFx0aWYgKGluQ29sb3IpIHtcblx0XHRcdFx0XHRhID0gTWF0aC5mbG9vcihpbkNvbG9yWzNdICogc2tlbENvbG9yLmEgKiBzbG90Q29sb3IuYSAqIGF0dGFjaG1lbnRDb2xvci5hICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCByID0gTWF0aC5mbG9vcihhICogaW5Db2xvclswXSAqIHNrZWxDb2xvci5yICogc2xvdENvbG9yLnIgKiBhdHRhY2htZW50Q29sb3Iucik7XG5cdFx0XHRcdFx0Y29uc3QgZyA9IE1hdGguZmxvb3IoYSAqIGluQ29sb3JbMV0gKiBza2VsQ29sb3IuZyAqIHNsb3RDb2xvci5nICogYXR0YWNobWVudENvbG9yLmcpO1xuXHRcdFx0XHRcdGNvbnN0IGIgPSBNYXRoLmZsb29yKGEgKiBpbkNvbG9yWzJdICogc2tlbENvbG9yLmIgKiBzbG90Q29sb3IuYiAqIGF0dGFjaG1lbnRDb2xvci5iKTtcblx0XHRcdFx0XHRjb2xvciA9IChhIDw8IDI0KSB8IChyIDw8IDE2KSB8IChnIDw8IDgpIHwgYjtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRhID0gTWF0aC5mbG9vcihza2VsQ29sb3IuYSAqIHNsb3RDb2xvci5hICogYXR0YWNobWVudENvbG9yLmEgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbnN0IHIgPSBNYXRoLmZsb29yKGEgKiBza2VsQ29sb3IuciAqIHNsb3RDb2xvci5yICogYXR0YWNobWVudENvbG9yLnIpO1xuXHRcdFx0XHRcdGNvbnN0IGcgPSBNYXRoLmZsb29yKGEgKiBza2VsQ29sb3IuZyAqIHNsb3RDb2xvci5nICogYXR0YWNobWVudENvbG9yLmcpO1xuXHRcdFx0XHRcdGNvbnN0IGIgPSBNYXRoLmZsb29yKGEgKiBza2VsQ29sb3IuYiAqIHNsb3RDb2xvci5iICogYXR0YWNobWVudENvbG9yLmIpO1xuXHRcdFx0XHRcdGNvbG9yID0gKGEgPDwgMjQpIHwgKHIgPDwgMTYpIHwgKGcgPDwgOCkgfCBiO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZGFya0NvbG9yID0gMHhmZjAwMDAwMDtcblx0XHRcdFx0aWYgKHBvc2UuZGFya0NvbG9yKSB7XG5cdFx0XHRcdFx0Y29uc3QgeyByLCBnLCBiIH0gPSBwb3NlLmRhcmtDb2xvcjtcblx0XHRcdFx0XHRkYXJrQ29sb3IgPSAweGZmMDAwMDAwIHxcblx0XHRcdFx0XHRcdChNYXRoLmZsb29yKHIgKiBhKSA8PCAxNikgfFxuXHRcdFx0XHRcdFx0KE1hdGguZmxvb3IoZyAqIGEpIDw8IDgpIHxcblx0XHRcdFx0XHRcdE1hdGguZmxvb3IoYiAqIGEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoaW5Db2xvcikge1xuXHRcdFx0XHRcdGNvbnN0IGEgPSBNYXRoLmZsb29yKGluQ29sb3JbM10gKiBza2VsQ29sb3IuYSAqIHNsb3RDb2xvci5hICogYXR0YWNobWVudENvbG9yLmEgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbnN0IHIgPSBNYXRoLmZsb29yKGluQ29sb3JbMF0gKiBza2VsQ29sb3IuciAqIHNsb3RDb2xvci5yICogYXR0YWNobWVudENvbG9yLnIgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbnN0IGcgPSBNYXRoLmZsb29yKGluQ29sb3JbMV0gKiBza2VsQ29sb3IuZyAqIHNsb3RDb2xvci5nICogYXR0YWNobWVudENvbG9yLmcgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbnN0IGIgPSBNYXRoLmZsb29yKGluQ29sb3JbMl0gKiBza2VsQ29sb3IuYiAqIHNsb3RDb2xvci5iICogYXR0YWNobWVudENvbG9yLmIgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbG9yID0gKGEgPDwgMjQpIHwgKHIgPDwgMTYpIHwgKGcgPDwgOCkgfCBiO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnN0IGEgPSBNYXRoLmZsb29yKHNrZWxDb2xvci5hICogc2xvdENvbG9yLmEgKiBhdHRhY2htZW50Q29sb3IuYSAqIDI1NSk7XG5cdFx0XHRcdFx0Y29uc3QgciA9IE1hdGguZmxvb3Ioc2tlbENvbG9yLnIgKiBzbG90Q29sb3IuciAqIGF0dGFjaG1lbnRDb2xvci5yICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCBnID0gTWF0aC5mbG9vcihza2VsQ29sb3IuZyAqIHNsb3RDb2xvci5nICogYXR0YWNobWVudENvbG9yLmcgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbnN0IGIgPSBNYXRoLmZsb29yKHNrZWxDb2xvci5iICogc2xvdENvbG9yLmIgKiBhdHRhY2htZW50Q29sb3IuYiAqIDI1NSk7XG5cdFx0XHRcdFx0Y29sb3IgPSAoYSA8PCAyNCkgfCAociA8PCAxNikgfCAoZyA8PCA4KSB8IGI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkYXJrQ29sb3IgPSAwO1xuXHRcdFx0XHRpZiAocG9zZS5kYXJrQ29sb3IpIHtcblx0XHRcdFx0XHRjb25zdCB7IHIsIGcsIGIgfSA9IHBvc2UuZGFya0NvbG9yO1xuXHRcdFx0XHRcdGRhcmtDb2xvciA9IChNYXRoLmZsb29yKHIgKiAyNTUpIDw8IDE2KSB8IChNYXRoLmZsb29yKGcgKiAyNTUpIDw8IDgpIHwgTWF0aC5mbG9vcihiICogMjU1KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoY2xpcHBlci5pc0NsaXBwaW5nKCkpIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwVHJpYW5nbGVzVW5wYWNrZWQodmVydGljZXMsIDAsIGluZGljZXMsIGluZGljZXNDb3VudCwgdXZzLCBzdHJpZGUpO1xuXHRcdFx0XHR2ZXJ0aWNlcyA9IGNsaXBwZXIuY2xpcHBlZFZlcnRpY2VzVHlwZWQ7XG5cdFx0XHRcdHZlcnRpY2VzQ291bnQgPSBjbGlwcGVyLmNsaXBwZWRWZXJ0aWNlc0xlbmd0aCAvIHN0cmlkZTtcblx0XHRcdFx0dXZzID0gY2xpcHBlci5jbGlwcGVkVVZzVHlwZWQ7XG5cdFx0XHRcdGluZGljZXMgPSBjbGlwcGVyLmNsaXBwZWRUcmlhbmdsZXNUeXBlZDtcblx0XHRcdFx0aW5kaWNlc0NvdW50ID0gY2xpcHBlci5jbGlwcGVkVHJpYW5nbGVzTGVuZ3RoO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBjbWQgPSB0aGlzLmNvbW1hbmRQb29sLmdldENvbW1hbmQodmVydGljZXNDb3VudCwgaW5kaWNlc0NvdW50LCBzdHJpZGUpO1xuXHRcdFx0Y21kLmJsZW5kTW9kZSA9IHNsb3QuZGF0YS5ibGVuZE1vZGU7XG5cdFx0XHRjbWQudGV4dHVyZSA9IHRleHR1cmU7XG5cblx0XHRcdGNtZC5wb3NpdGlvbnMuc2V0KHZlcnRpY2VzLnN1YmFycmF5KDAsIHZlcnRpY2VzQ291bnQgKiBzdHJpZGUpKTtcblx0XHRcdGNtZC51dnMuc2V0KHV2cy5zdWJhcnJheSgwLCB2ZXJ0aWNlc0NvdW50IDw8IDEpKTtcblxuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCB2ZXJ0aWNlc0NvdW50OyBqKyspIHtcblx0XHRcdFx0Y21kLmNvbG9yc1tqXSA9IGNvbG9yO1xuXHRcdFx0XHRjbWQuZGFya0NvbG9yc1tqXSA9IGRhcmtDb2xvcjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGluZGljZXMgaW5zdGFuY2VvZiBVaW50MTZBcnJheSkge1xuXHRcdFx0XHRjbWQuaW5kaWNlcy5zZXQoaW5kaWNlcy5zdWJhcnJheSgwLCBpbmRpY2VzQ291bnQpKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNtZC5pbmRpY2VzLnNldChpbmRpY2VzLnNsaWNlKDAsIGluZGljZXNDb3VudCkpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLnJlbmRlckNvbW1hbmRzLnB1c2goY21kKTtcblx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHR9XG5cblx0XHRjbGlwcGVyLmNsaXBFbmQoKTtcblx0XHRyZXR1cm4gdGhpcy5iYXRjaENvbW1hbmRzKHN0cmlkZSk7XG5cdH1cblxuXHRwcml2YXRlIGJhdGNoU3ViQ29tbWFuZHMgKGNvbW1hbmRzOiBSZW5kZXJDb21tYW5kW10sIGZpcnN0OiBudW1iZXIsIGxhc3Q6IG51bWJlcixcblx0XHRudW1WZXJ0aWNlczogbnVtYmVyLCBudW1JbmRpY2VzOiBudW1iZXIsIHN0cmlkZTogbnVtYmVyKTogUmVuZGVyQ29tbWFuZCB7XG5cblx0XHRjb25zdCBmaXJzdENtZCA9IGNvbW1hbmRzW2ZpcnN0XTtcblx0XHRjb25zdCBiYXRjaGVkID0gdGhpcy5jb21tYW5kUG9vbC5nZXRDb21tYW5kKG51bVZlcnRpY2VzLCBudW1JbmRpY2VzLCBzdHJpZGUpO1xuXG5cdFx0YmF0Y2hlZC5ibGVuZE1vZGUgPSBmaXJzdENtZC5ibGVuZE1vZGU7XG5cdFx0YmF0Y2hlZC50ZXh0dXJlID0gZmlyc3RDbWQudGV4dHVyZTtcblxuXHRcdGxldCBwb3NpdGlvbnNPZmZzZXQgPSAwO1xuXHRcdGxldCB1dnNPZmZzZXQgPSAwO1xuXHRcdGxldCBjb2xvcnNPZmZzZXQgPSAwO1xuXHRcdGxldCBpbmRpY2VzT2Zmc2V0ID0gMDtcblx0XHRsZXQgdmVydGV4T2Zmc2V0ID0gMDtcblxuXHRcdGZvciAobGV0IGkgPSBmaXJzdDsgaSA8PSBsYXN0OyBpKyspIHtcblx0XHRcdGNvbnN0IGNtZCA9IGNvbW1hbmRzW2ldO1xuXG5cdFx0XHRiYXRjaGVkLnBvc2l0aW9ucy5zZXQoY21kLnBvc2l0aW9ucywgcG9zaXRpb25zT2Zmc2V0KTtcblx0XHRcdHBvc2l0aW9uc09mZnNldCArPSBjbWQubnVtVmVydGljZXMgKiBzdHJpZGU7XG5cblx0XHRcdGJhdGNoZWQudXZzLnNldChjbWQudXZzLCB1dnNPZmZzZXQpO1xuXHRcdFx0dXZzT2Zmc2V0ICs9IGNtZC5udW1WZXJ0aWNlcyA8PCAxO1xuXG5cdFx0XHRiYXRjaGVkLmNvbG9ycy5zZXQoY21kLmNvbG9ycywgY29sb3JzT2Zmc2V0KTtcblx0XHRcdGJhdGNoZWQuZGFya0NvbG9ycy5zZXQoY21kLmRhcmtDb2xvcnMsIGNvbG9yc09mZnNldCk7XG5cdFx0XHRjb2xvcnNPZmZzZXQgKz0gY21kLm51bVZlcnRpY2VzO1xuXG5cdFx0XHQvLyBjYW5ub3QgZmFzdCBjb3B5IC0gaW5kaWNlcyBuZWVkIHZlcnRleCBvZmZzZXQgYWRqdXN0bWVudFxuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCBjbWQubnVtSW5kaWNlczsgaisrKVxuXHRcdFx0XHRiYXRjaGVkLmluZGljZXNbaW5kaWNlc09mZnNldCArIGpdID0gY21kLmluZGljZXNbal0gKyB2ZXJ0ZXhPZmZzZXQ7XG5cblx0XHRcdGluZGljZXNPZmZzZXQgKz0gY21kLm51bUluZGljZXM7XG5cdFx0XHR2ZXJ0ZXhPZmZzZXQgKz0gY21kLm51bVZlcnRpY2VzO1xuXHRcdH1cblxuXHRcdHJldHVybiBiYXRjaGVkO1xuXHR9XG5cblx0cHJpdmF0ZSBiYXRjaENvbW1hbmRzIChzdHJpZGU6IG51bWJlcik6IFJlbmRlckNvbW1hbmQgfCB1bmRlZmluZWQge1xuXHRcdGlmICh0aGlzLnJlbmRlckNvbW1hbmRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuXHRcdGxldCByb290OiBSZW5kZXJDb21tYW5kIHwgdW5kZWZpbmVkO1xuXHRcdGxldCBsYXN0OiBSZW5kZXJDb21tYW5kIHwgdW5kZWZpbmVkO1xuXG5cdFx0bGV0IGZpcnN0ID0gdGhpcy5yZW5kZXJDb21tYW5kc1swXTtcblx0XHRsZXQgc3RhcnRJbmRleCA9IDA7XG5cdFx0bGV0IGkgPSAxO1xuXHRcdGxldCBudW1WZXJ0aWNlcyA9IGZpcnN0Lm51bVZlcnRpY2VzO1xuXHRcdGxldCBudW1JbmRpY2VzID0gZmlyc3QubnVtSW5kaWNlcztcblxuXHRcdHdoaWxlIChpIDw9IHRoaXMucmVuZGVyQ29tbWFuZHMubGVuZ3RoKSB7XG5cdFx0XHRjb25zdCBjbWQgPSBpIDwgdGhpcy5yZW5kZXJDb21tYW5kcy5sZW5ndGggPyB0aGlzLnJlbmRlckNvbW1hbmRzW2ldIDogbnVsbDtcblxuXHRcdFx0aWYgKGNtZCAmJiBjbWQubnVtVmVydGljZXMgPT09IDAgJiYgY21kLm51bUluZGljZXMgPT09IDApIHtcblx0XHRcdFx0aSsrO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgY2FuQmF0Y2ggPSBjbWQgIT09IG51bGwgJiZcblx0XHRcdFx0Y21kLnRleHR1cmUgPT09IGZpcnN0LnRleHR1cmUgJiZcblx0XHRcdFx0Y21kLmJsZW5kTW9kZSA9PT0gZmlyc3QuYmxlbmRNb2RlICYmXG5cdFx0XHRcdGNtZC5jb2xvcnNbMF0gPT09IGZpcnN0LmNvbG9yc1swXSAmJlxuXHRcdFx0XHRjbWQuZGFya0NvbG9yc1swXSA9PT0gZmlyc3QuZGFya0NvbG9yc1swXSAmJlxuXHRcdFx0XHRudW1JbmRpY2VzICsgY21kLm51bUluZGljZXMgPCAweGZmZmY7XG5cdFx0XHRpZiAoY2FuQmF0Y2gpIHtcblx0XHRcdFx0bnVtVmVydGljZXMgKz0gY21kLm51bVZlcnRpY2VzO1xuXHRcdFx0XHRudW1JbmRpY2VzICs9IGNtZC5udW1JbmRpY2VzO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3QgYmF0Y2hlZCA9IHRoaXMuYmF0Y2hTdWJDb21tYW5kcyh0aGlzLnJlbmRlckNvbW1hbmRzLCBzdGFydEluZGV4LCBpIC0gMSxcblx0XHRcdFx0XHRudW1WZXJ0aWNlcywgbnVtSW5kaWNlcywgc3RyaWRlKTtcblxuXHRcdFx0XHRpZiAoIWxhc3QpIHtcblx0XHRcdFx0XHRyb290ID0gbGFzdCA9IGJhdGNoZWQ7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bGFzdC5uZXh0ID0gYmF0Y2hlZDtcblx0XHRcdFx0XHRsYXN0ID0gYmF0Y2hlZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChpID09PSB0aGlzLnJlbmRlckNvbW1hbmRzLmxlbmd0aCkgYnJlYWs7XG5cblx0XHRcdFx0Zmlyc3QgPSB0aGlzLnJlbmRlckNvbW1hbmRzW2ldO1xuXHRcdFx0XHRzdGFydEluZGV4ID0gaTtcblx0XHRcdFx0bnVtVmVydGljZXMgPSBmaXJzdC5udW1WZXJ0aWNlcztcblx0XHRcdFx0bnVtSW5kaWNlcyA9IGZpcnN0Lm51bUluZGljZXM7XG5cdFx0XHR9XG5cdFx0XHRpKys7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJvb3Q7XG5cdH1cbn1cblxuLy8gdmFsdWVzIHdpdGggdW5kZXIgc2NvcmUgaXMgdGhlIG9yaWdpbmFsIHNpemVkIGFycmF5LCBiaWdnZXIgdGhhbiBuZWNlc3Nhcnlcbi8vIHZhbHVlcyB3aXRob3V0IHVuZGVyIHNjb3JlIGlzIGEgdmlldyBvZiB0aGUgb3JpZ25hbCBhcnJheSwgc2l6ZWQgYXMgbmVlZGVkXG5pbnRlcmZhY2UgUmVuZGVyQ29tbWFuZCB7XG5cdHBvc2l0aW9uczogRmxvYXQzMkFycmF5O1xuXHR1dnM6IEZsb2F0MzJBcnJheTtcblx0Y29sb3JzOiBVaW50MzJBcnJheTtcblx0ZGFya0NvbG9yczogVWludDMyQXJyYXk7XG5cdGluZGljZXM6IFVpbnQxNkFycmF5O1xuXHRfcG9zaXRpb25zOiBGbG9hdDMyQXJyYXk7XG5cdF91dnM6IEZsb2F0MzJBcnJheTtcblx0X2NvbG9yczogVWludDMyQXJyYXk7XG5cdF9kYXJrQ29sb3JzOiBVaW50MzJBcnJheTtcblx0X2luZGljZXM6IFVpbnQxNkFycmF5O1xuXHRudW1WZXJ0aWNlczogbnVtYmVyO1xuXHRudW1JbmRpY2VzOiBudW1iZXI7XG5cdGJsZW5kTW9kZTogQmxlbmRNb2RlO1xuXHQvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vRXhwbGljaXRBbnk6IHRleHR1cmUgZGVwZW5kcyBvbiB0aGUgcnVudGltZVxuXHR0ZXh0dXJlOiBhbnk7XG5cdG5leHQ/OiBSZW5kZXJDb21tYW5kO1xufVxuXG5jbGFzcyBDb21tYW5kUG9vbCB7XG5cdHByaXZhdGUgcG9vbDogUmVuZGVyQ29tbWFuZFtdID0gW107XG5cdHByaXZhdGUgaW5Vc2U6IFJlbmRlckNvbW1hbmRbXSA9IFtdO1xuXG5cdGdldENvbW1hbmQgKG51bVZlcnRpY2VzOiBudW1iZXIsIG51bUluZGljZXM6IG51bWJlciwgc3RyaWRlOiBudW1iZXIpOiBSZW5kZXJDb21tYW5kIHtcblx0XHRsZXQgY21kOiBSZW5kZXJDb21tYW5kIHwgdW5kZWZpbmVkO1xuXHRcdGZvciAoY29uc3QgYyBvZiB0aGlzLnBvb2wpIHtcblx0XHRcdGlmIChjLl9wb3NpdGlvbnMubGVuZ3RoID49IG51bVZlcnRpY2VzICogc3RyaWRlICYmIGMuX2luZGljZXMubGVuZ3RoID49IG51bUluZGljZXMpIHtcblx0XHRcdFx0Y21kID0gYztcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCFjbWQpIHtcblx0XHRcdGNvbnN0IF9wb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KG51bVZlcnRpY2VzICogc3RyaWRlKTtcblx0XHRcdGNvbnN0IF91dnMgPSBuZXcgRmxvYXQzMkFycmF5KG51bVZlcnRpY2VzIDw8IDEpO1xuXHRcdFx0Y29uc3QgX2NvbG9ycyA9IG5ldyBVaW50MzJBcnJheShudW1WZXJ0aWNlcyk7XG5cdFx0XHRjb25zdCBfZGFya0NvbG9ycyA9IG5ldyBVaW50MzJBcnJheShudW1WZXJ0aWNlcyk7XG5cdFx0XHRjb25zdCBfaW5kaWNlcyA9IG5ldyBVaW50MTZBcnJheShudW1JbmRpY2VzKTtcblx0XHRcdGNtZCA9IHtcblx0XHRcdFx0cG9zaXRpb25zOiBfcG9zaXRpb25zLFxuXHRcdFx0XHR1dnM6IF91dnMsXG5cdFx0XHRcdGNvbG9yczogX2NvbG9ycyxcblx0XHRcdFx0ZGFya0NvbG9yczogX2RhcmtDb2xvcnMsXG5cdFx0XHRcdGluZGljZXM6IF9pbmRpY2VzLFxuXHRcdFx0XHRfcG9zaXRpb25zLFxuXHRcdFx0XHRfdXZzLFxuXHRcdFx0XHRfY29sb3JzLFxuXHRcdFx0XHRfZGFya0NvbG9ycyxcblx0XHRcdFx0X2luZGljZXMsXG5cdFx0XHRcdG51bVZlcnRpY2VzLFxuXHRcdFx0XHRudW1JbmRpY2VzLFxuXHRcdFx0XHRibGVuZE1vZGU6IEJsZW5kTW9kZS5Ob3JtYWwsXG5cdFx0XHRcdHRleHR1cmU6IG51bGxcblx0XHRcdH07XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMucG9vbC5zcGxpY2UodGhpcy5wb29sLmluZGV4T2YoY21kKSwgMSk7XG5cdFx0XHRjbWQubmV4dCA9IHVuZGVmaW5lZDtcblx0XHRcdGNtZC5udW1WZXJ0aWNlcyA9IG51bVZlcnRpY2VzO1xuXHRcdFx0Y21kLm51bUluZGljZXMgPSBudW1JbmRpY2VzO1xuXG5cdFx0XHRjbWQucG9zaXRpb25zID0gY21kLl9wb3NpdGlvbnMuc3ViYXJyYXkoMCwgbnVtVmVydGljZXMgKiBzdHJpZGUpO1xuXHRcdFx0Y21kLnV2cyA9IGNtZC5fdXZzLnN1YmFycmF5KDAsIG51bVZlcnRpY2VzIDw8IDEpO1xuXHRcdFx0Y21kLmNvbG9ycyA9IGNtZC5fY29sb3JzLnN1YmFycmF5KDAsIG51bVZlcnRpY2VzKTtcblx0XHRcdGNtZC5kYXJrQ29sb3JzID0gY21kLl9kYXJrQ29sb3JzLnN1YmFycmF5KDAsIG51bVZlcnRpY2VzKTtcblx0XHRcdGNtZC5pbmRpY2VzID0gY21kLl9pbmRpY2VzLnN1YmFycmF5KDAsIG51bUluZGljZXMpO1xuXHRcdH1cblxuXHRcdHRoaXMuaW5Vc2UucHVzaChjbWQpO1xuXHRcdHJldHVybiBjbWQ7XG5cdH1cblxuXHRyZXNldCAoKTogdm9pZCB7XG5cdFx0dGhpcy5wb29sLnB1c2goLi4udGhpcy5pblVzZSk7XG5cdFx0dGhpcy5pblVzZS5sZW5ndGggPSAwO1xuXHR9XG