UNPKG

@esotericsoftware/spine-core

Version:
327 lines 52 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, slotZOffset = 0) { this.commandPool.reset(); this.renderCommands.length = 0; const clipper = this.clipping; let z = 0; const drawOrder = skeleton.drawOrder.appliedPose; for (let i = 0, n = drawOrder.length; i < n; i++) { const slot = drawOrder[i]; if (!slot.bone.active) { clipper.clipEnd(slot); continue; } const pose = slot.appliedPose; const attachment = pose.attachment; if (!attachment) { clipper.clipEnd(slot); continue; } const slotColor = pose.color; const alpha = slotColor.a; if (alpha === 0 && !(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.clipEnd(slot); clipper.clipStart(skeleton, slot, attachment); continue; } else { clipper.clipEnd(slot); continue; } if (!texture) { clipper.clipEnd(slot); 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)); // Store slot depth before batching so renderers can separate overlapping attachments. if (stride >= 3) { for (let j = 2, n = verticesCount * stride; j < n; j += stride) cmd.positions[j] = z; } 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); z += slotZOffset; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2tlbGV0b25SZW5kZXJlckNvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvU2tlbGV0b25SZW5kZXJlckNvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrRUEyQitFO0FBRS9FLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU5RixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRzFDLE1BQU0sT0FBTyxvQkFBb0I7SUFDeEIsV0FBVyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7SUFDaEMsYUFBYSxHQUFHLElBQUksWUFBWSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUM1QyxXQUFXLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEQsUUFBUSxHQUFHLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztJQUNsQyxjQUFjLEdBQW9CLEVBQUUsQ0FBQztJQUU3QyxNQUFNLENBQUUsUUFBa0IsRUFBRSxHQUFHLEdBQUcsS0FBSyxFQUFFLE9BQTBDLEVBQUUsTUFBTSxHQUFHLENBQUMsRUFBRSxXQUFXLEdBQUcsQ0FBQztRQUMvRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUUvQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBRTlCLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNWLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMs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QyxJQUFJLEdBQUcsU0FBUyxDQUFDO1lBQ3JCLEdBQUcsQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1lBQzlCLEdBQUcsQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1lBRTVCLEdBQUcsQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLFdBQVcsR0FBRyxNQUFNLENBQUMsQ0FBQztZQUNqRSxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxXQUFXLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDakQsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDbEQsR0FBRyxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDMUQsR0FBRyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDcEQsQ0FBQztRQUVELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLE9BQU8sR0FBRyxDQUFDO0lBQ1osQ0FBQztJQUVELEtBQUs7UUFDSixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDdkIsQ0FBQztDQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICogU3BpbmUgUnVudGltZXMgTGljZW5zZSBBZ3JlZW1lbnRcbiAqIExhc3QgdXBkYXRlZCBBcHJpbCA1LCAyMDI1LiBSZXBsYWNlcyBhbGwgcHJpb3IgdmVyc2lvbnMuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzLTIwMjUsIEVzb3RlcmljIFNvZnR3YXJlIExMQ1xuICpcbiAqIEludGVncmF0aW9uIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlIG9yIG90aGVyd2lzZSBjcmVhdGluZ1xuICogZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgaXMgcGVybWl0dGVkIHVuZGVyIHRoZSB0ZXJtcyBhbmRcbiAqIGNvbmRpdGlvbnMgb2YgU2VjdGlvbiAyIG9mIHRoZSBTcGluZSBFZGl0b3IgTGljZW5zZSBBZ3JlZW1lbnQ6XG4gKiBodHRwOi8vZXNvdGVyaWNzb2Z0d2FyZS5jb20vc3BpbmUtZWRpdG9yLWxpY2Vuc2VcbiAqXG4gKiBPdGhlcndpc2UsIGl0IGlzIHBlcm1pdHRlZCB0byBpbnRlZ3JhdGUgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmVcbiAqIG9yIG90aGVyd2lzZSBjcmVhdGUgZGVyaXZhdGl2ZSB3b3JrcyBvZiB0aGUgU3BpbmUgUnVudGltZXMgKGNvbGxlY3RpdmVseSxcbiAqIFwiUHJvZHVjdHNcIiksIHByb3ZpZGVkIHRoYXQgZWFjaCB1c2VyIG9mIHRoZSBQcm9kdWN0cyBtdXN0IG9idGFpbiB0aGVpciBvd25cbiAqIFNwaW5lIEVkaXRvciBsaWNlbnNlIGFuZCByZWRpc3RyaWJ1dGlvbiBvZiB0aGUgUHJvZHVjdHMgaW4gYW55IGZvcm0gbXVzdFxuICogaW5jbHVkZSB0aGlzIGxpY2Vuc2UgYW5kIGNvcHlyaWdodCBub3RpY2UuXG4gKlxuICogVEhFIFNQSU5FIFJVTlRJTUVTIEFSRSBQUk9WSURFRCBCWSBFU09URVJJQyBTT0ZUV0FSRSBMTEMgXCJBUyBJU1wiIEFORCBBTllcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcbiAqIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIEVTT1RFUklDIFNPRlRXQVJFIExMQyBCRSBMSUFCTEUgRk9SIEFOWVxuICogRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAqIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUyxcbiAqIEJVU0lORVNTIElOVEVSUlVQVElPTiwgT1IgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFMpIEhPV0VWRVIgQ0FVU0VEIEFORFxuICogT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAqIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRlxuICogVEhFIFNQSU5FIFJVTlRJTUVTLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5pbXBvcnQgeyBDbGlwcGluZ0F0dGFjaG1lbnQsIE1lc2hBdHRhY2htZW50LCBSZWdpb25BdHRhY2htZW50IH0gZnJvbSBcIi4vYXR0YWNobWVudHMvaW5kZXguanNcIjtcbmltcG9ydCB0eXBlIHsgU2tlbGV0b24gfSBmcm9tIFwiLi9Ta2VsZXRvbi5qc1wiO1xuaW1wb3J0IHsgU2tlbGV0b25DbGlwcGluZyB9IGZyb20gXCIuL1NrZWxldG9uQ2xpcHBpbmcuanNcIjtcbmltcG9ydCB7IEJsZW5kTW9kZSB9IGZyb20gXCIuL1Nsb3REYXRhLmpzXCI7XG5pbXBvcnQgdHlwZSB7IENvbG9yLCBOdW1iZXJBcnJheUxpa2UgfSBmcm9tIFwiLi9VdGlscy5qc1wiO1xuXG5leHBvcnQgY2xhc3MgU2tlbGV0b25SZW5kZXJlckNvcmUge1xuXHRwcml2YXRlIGNvbW1hbmRQb29sID0gbmV3IENvbW1hbmRQb29sKCk7XG5cdHByaXZhdGUgd29ybGRWZXJ0aWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkoMTIgKiAxMDI0KTtcblx0cHJpdmF0ZSBxdWFkSW5kaWNlcyA9IG5ldyBVaW50MTZBcnJheShbMCwgMSwgMiwgMiwgMywgMF0pO1xuXHRwcml2YXRlIGNsaXBwaW5nID0gbmV3IFNrZWxldG9uQ2xpcHBpbmcoKTtcblx0cHJpdmF0ZSByZW5kZXJDb21tYW5kczogUmVuZGVyQ29tbWFuZFtdID0gW107XG5cblx0cmVuZGVyIChza2VsZXRvbjogU2tlbGV0b24sIHBtYSA9IGZhbHNlLCBpbkNvbG9yPzogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIHN0cmlkZSA9IDIsIHNsb3RaT2Zmc2V0ID0gMCk6IFJlbmRlckNvbW1hbmQgfCB1bmRlZmluZWQge1xuXHRcdHRoaXMuY29tbWFuZFBvb2wucmVzZXQoKTtcblx0XHR0aGlzLnJlbmRlckNvbW1hbmRzLmxlbmd0aCA9IDA7XG5cblx0XHRjb25zdCBjbGlwcGVyID0gdGhpcy5jbGlwcGluZztcblxuXHRcdGxldCB6ID0gMDtcblx0XHRjb25zdCBkcmF3T3JkZXIgPSBza2VsZXRvbi5kcmF3T3JkZXIuYXBwbGllZFBvc2U7XG5cdFx0Zm9yIChsZXQgaSA9IDAsIG4gPSBkcmF3T3JkZXIubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBzbG90ID0gZHJhd09yZGVyW2ldO1xuXHRcdFx0aWYgKCFzbG90LmJvbmUuYWN0aXZlKSB7XG5cdFx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IHBvc2UgPSBzbG90LmFwcGxpZWRQb3NlO1xuXHRcdFx0Y29uc3QgYXR0YWNobWVudCA9IHBvc2UuYXR0YWNobWVudDtcblxuXHRcdFx0aWYgKCFhdHRhY2htZW50KSB7XG5cdFx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IHNsb3RDb2xvciA9IHBvc2UuY29sb3I7XG5cdFx0XHRjb25zdCBhbHBoYSA9IHNsb3RDb2xvci5hO1xuXHRcdFx0aWYgKGFscGhhID09PSAwICYmICEoYXR0YWNobWVudCBpbnN0YW5jZW9mIENsaXBwaW5nQXR0YWNobWVudCkpIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IHZlcnRpY2VzOiBOdW1iZXJBcnJheUxpa2U7XG5cdFx0XHRsZXQgdmVydGljZXNDb3VudDogbnVtYmVyO1xuXHRcdFx0bGV0IHV2czogTnVtYmVyQXJyYXlMaWtlO1xuXHRcdFx0bGV0IGluZGljZXM6IG51bWJlcltdIHwgVWludDE2QXJyYXk7XG5cdFx0XHRsZXQgaW5kaWNlc0NvdW50OiBudW1iZXI7XG5cdFx0XHRsZXQgYXR0YWNobWVudENvbG9yOiBDb2xvcjtcblx0XHRcdC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9FeHBsaWNpdEFueTogdGV4dHVyZSBkZXBlbmRzIG9uIHRoZSBydW50aW1lXG5cdFx0XHRsZXQgdGV4dHVyZTogYW55O1xuXG5cdFx0XHRpZiAoYXR0YWNobWVudCBpbnN0YW5jZW9mIFJlZ2lvbkF0dGFjaG1lbnQpIHtcblx0XHRcdFx0YXR0YWNobWVudENvbG9yID0gYXR0YWNobWVudC5jb2xvcjtcblxuXHRcdFx0XHRpZiAoYXR0YWNobWVudENvbG9yLmEgPT09IDApIHtcblx0XHRcdFx0XHRjbGlwcGVyLmNsaXBFbmQoc2xvdCk7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBzZXF1ZW5jZSA9IGF0dGFjaG1lbnQuc2VxdWVuY2U7XG5cdFx0XHRcdGNvbnN0IHNlcXVlbmNlSW5kZXggPSBzZXF1ZW5jZS5yZXNvbHZlSW5kZXgocG9zZSk7XG5cdFx0XHRcdGF0dGFjaG1lbnQuY29tcHV0ZVdvcmxkVmVydGljZXMoc2xvdCwgYXR0YWNobWVudC5nZXRPZmZzZXRzKHBvc2UpLCB0aGlzLndvcmxkVmVydGljZXMsIDAsIHN0cmlkZSk7XG5cblx0XHRcdFx0dmVydGljZXMgPSB0aGlzLndvcmxkVmVydGljZXM7XG5cdFx0XHRcdHZlcnRpY2VzQ291bnQgPSA0O1xuXHRcdFx0XHR1dnMgPSBzZXF1ZW5jZS5nZXRVVnMoc2VxdWVuY2VJbmRleCk7XG5cdFx0XHRcdGluZGljZXMgPSB0aGlzLnF1YWRJbmRpY2VzO1xuXHRcdFx0XHRpbmRpY2VzQ291bnQgPSA2O1xuXHRcdFx0XHR0ZXh0dXJlID0gc2VxdWVuY2UucmVnaW9uc1tzZXF1ZW5jZUluZGV4XT8udGV4dHVyZTtcblxuXHRcdFx0fSBlbHNlIGlmIChhdHRhY2htZW50IGluc3RhbmNlb2YgTWVzaEF0dGFjaG1lbnQpIHtcblx0XHRcdFx0YXR0YWNobWVudENvbG9yID0gYXR0YWNobWVudC5jb2xvcjtcblxuXHRcdFx0XHRpZiAoYXR0YWNobWVudENvbG9yLmEgPT09IDApIHtcblx0XHRcdFx0XHRjbGlwcGVyLmNsaXBFbmQoc2xvdCk7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAodGhpcy53b3JsZFZlcnRpY2VzLmxlbmd0aCA8IGF0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aClcblx0XHRcdFx0XHR0aGlzLndvcmxkVmVydGljZXMgPSBuZXcgRmxvYXQzMkFycmF5KGF0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aCk7XG5cblx0XHRcdFx0YXR0YWNobWVudC5jb21wdXRlV29ybGRWZXJ0aWNlcyhza2VsZXRvbiwgc2xvdCwgMCwgYXR0YWNobWVudC53b3JsZFZlcnRpY2VzTGVuZ3RoLCB0aGlzLndvcmxkVmVydGljZXMsIDAsIHN0cmlkZSk7XG5cdFx0XHRcdHZlcnRpY2VzID0gdGhpcy53b3JsZFZlcnRpY2VzO1xuXHRcdFx0XHR2ZXJ0aWNlc0NvdW50ID0gYXR0YWNobWVudC53b3JsZFZlcnRpY2VzTGVuZ3RoID4+IDE7XG5cblx0XHRcdFx0Y29uc3Qgc2VxdWVuY2UgPSBhdHRhY2htZW50LnNlcXVlbmNlO1xuXHRcdFx0XHRjb25zdCBzZXF1ZW5jZUluZGV4ID0gc2VxdWVuY2UucmVzb2x2ZUluZGV4KHBvc2UpO1xuXG5cdFx0XHRcdHV2cyA9IHNlcXVlbmNlLmdldFVWcyhzZXF1ZW5jZUluZGV4KTtcblx0XHRcdFx0aW5kaWNlcyA9IGF0dGFjaG1lbnQudHJpYW5nbGVzO1xuXHRcdFx0XHRpbmRpY2VzQ291bnQgPSBpbmRpY2VzLmxlbmd0aDtcblx0XHRcdFx0dGV4dHVyZSA9IHNlcXVlbmNlLnJlZ2lvbnNbc2VxdWVuY2VJbmRleF0/LnRleHR1cmU7XG5cblx0XHRcdH0gZWxzZSBpZiAoYXR0YWNobWVudCBpbnN0YW5jZW9mIENsaXBwaW5nQXR0YWNobWVudCkge1xuXHRcdFx0XHRjbGlwcGVyLmNsaXBFbmQoc2xvdCk7XG5cdFx0XHRcdGNsaXBwZXIuY2xpcFN0YXJ0KHNrZWxldG9uLCBzbG90LCBhdHRhY2htZW50KTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjbGlwcGVyLmNsaXBFbmQoc2xvdCk7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIXRleHR1cmUpIHtcblx0XHRcdFx0Y2xpcHBlci5jbGlwRW5kKHNsb3QpO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3Qgc2tlbENvbG9yID0gc2tlbGV0b24uY29sb3I7XG5cdFx0XHRsZXQgY29sb3I6IG51bWJlciwgZGFya0NvbG9yOiBudW1iZXI7XG5cdFx0XHRpZiAocG1hKSB7XG5cdFx0XHRcdGxldCBhOiBudW1iZXI7XG5cdFx0XHRcdGlmIChpbkNvbG9yKSB7XG5cdFx0XHRcdFx0YSA9IE1hdGguZmxvb3IoaW5Db2xvclszXSAqIHNrZWxDb2xvci5hICogc2xvdENvbG9yLmEgKiBhdHRhY2htZW50Q29sb3IuYSAqIDI1NSk7XG5cdFx0XHRcdFx0Y29uc3QgciA9IE1hdGguZmxvb3IoYSAqIGluQ29sb3JbMF0gKiBza2VsQ29sb3IuciAqIHNsb3RDb2xvci5yICogYXR0YWNobWVudENvbG9yLnIpO1xuXHRcdFx0XHRcdGNvbnN0IGcgPSBNYXRoLmZsb29yKGEgKiBpbkNvbG9yWzFdICogc2tlbENvbG9yLmcgKiBzbG90Q29sb3IuZyAqIGF0dGFjaG1lbnRDb2xvci5nKTtcblx0XHRcdFx0XHRjb25zdCBiID0gTWF0aC5mbG9vcihhICogaW5Db2xvclsyXSAqIHNrZWxDb2xvci5iICogc2xvdENvbG9yLmIgKiBhdHRhY2htZW50Q29sb3IuYik7XG5cdFx0XHRcdFx0Y29sb3IgPSAoYSA8PCAyNCkgfCAociA8PCAxNikgfCAoZyA8PCA4KSB8IGI7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0YSA9IE1hdGguZmxvb3Ioc2tlbENvbG9yLmEgKiBzbG90Q29sb3IuYSAqIGF0dGFjaG1lbnRDb2xvci5hICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCByID0gTWF0aC5mbG9vcihhICogc2tlbENvbG9yLnIgKiBzbG90Q29sb3IuciAqIGF0dGFjaG1lbnRDb2xvci5yKTtcblx0XHRcdFx0XHRjb25zdCBnID0gTWF0aC5mbG9vcihhICogc2tlbENvbG9yLmcgKiBzbG90Q29sb3IuZyAqIGF0dGFjaG1lbnRDb2xvci5nKTtcblx0XHRcdFx0XHRjb25zdCBiID0gTWF0aC5mbG9vcihhICogc2tlbENvbG9yLmIgKiBzbG90Q29sb3IuYiAqIGF0dGFjaG1lbnRDb2xvci5iKTtcblx0XHRcdFx0XHRjb2xvciA9IChhIDw8IDI0KSB8IChyIDw8IDE2KSB8IChnIDw8IDgpIHwgYjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRhcmtDb2xvciA9IDB4ZmYwMDAwMDA7XG5cdFx0XHRcdGlmIChwb3NlLmRhcmtDb2xvcikge1xuXHRcdFx0XHRcdGNvbnN0IHsgciwgZywgYiB9ID0gcG9zZS5kYXJrQ29sb3I7XG5cdFx0XHRcdFx0ZGFya0NvbG9yID0gMHhmZjAwMDAwMCB8XG5cdFx0XHRcdFx0XHQoTWF0aC5mbG9vcihyICogYSkgPDwgMTYpIHxcblx0XHRcdFx0XHRcdChNYXRoLmZsb29yKGcgKiBhKSA8PCA4KSB8XG5cdFx0XHRcdFx0XHRNYXRoLmZsb29yKGIgKiBhKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKGluQ29sb3IpIHtcblx0XHRcdFx0XHRjb25zdCBhID0gTWF0aC5mbG9vcihpbkNvbG9yWzNdICogc2tlbENvbG9yLmEgKiBzbG90Q29sb3IuYSAqIGF0dGFjaG1lbnRDb2xvci5hICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCByID0gTWF0aC5mbG9vcihpbkNvbG9yWzBdICogc2tlbENvbG9yLnIgKiBzbG90Q29sb3IuciAqIGF0dGFjaG1lbnRDb2xvci5yICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCBnID0gTWF0aC5mbG9vcihpbkNvbG9yWzFdICogc2tlbENvbG9yLmcgKiBzbG90Q29sb3IuZyAqIGF0dGFjaG1lbnRDb2xvci5nICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCBiID0gTWF0aC5mbG9vcihpbkNvbG9yWzJdICogc2tlbENvbG9yLmIgKiBzbG90Q29sb3IuYiAqIGF0dGFjaG1lbnRDb2xvci5iICogMjU1KTtcblx0XHRcdFx0XHRjb2xvciA9IChhIDw8IDI0KSB8IChyIDw8IDE2KSB8IChnIDw8IDgpIHwgYjtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjb25zdCBhID0gTWF0aC5mbG9vcihza2VsQ29sb3IuYSAqIHNsb3RDb2xvci5hICogYXR0YWNobWVudENvbG9yLmEgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbnN0IHIgPSBNYXRoLmZsb29yKHNrZWxDb2xvci5yICogc2xvdENvbG9yLnIgKiBhdHRhY2htZW50Q29sb3IuciAqIDI1NSk7XG5cdFx0XHRcdFx0Y29uc3QgZyA9IE1hdGguZmxvb3Ioc2tlbENvbG9yLmcgKiBzbG90Q29sb3IuZyAqIGF0dGFjaG1lbnRDb2xvci5nICogMjU1KTtcblx0XHRcdFx0XHRjb25zdCBiID0gTWF0aC5mbG9vcihza2VsQ29sb3IuYiAqIHNsb3RDb2xvci5iICogYXR0YWNobWVudENvbG9yLmIgKiAyNTUpO1xuXHRcdFx0XHRcdGNvbG9yID0gKGEgPDwgMjQpIHwgKHIgPDwgMTYpIHwgKGcgPDwgOCkgfCBiO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZGFya0NvbG9yID0gMDtcblx0XHRcdFx0aWYgKHBvc2UuZGFya0NvbG9yKSB7XG5cdFx0XHRcdFx0Y29uc3QgeyByLCBnLCBiIH0gPSBwb3NlLmRhcmtDb2xvcjtcblx0XHRcdFx0XHRkYXJrQ29sb3IgPSAoTWF0aC5mbG9vcihyICogMjU1KSA8PCAxNikgfCAoTWF0aC5mbG9vcihnICogMjU1KSA8PCA4KSB8IE1hdGguZmxvb3IoYiAqIDI1NSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKGNsaXBwZXIuaXNDbGlwcGluZygpKSB7XG5cdFx0XHRcdGNsaXBwZXIuY2xpcFRyaWFuZ2xlc1VucGFja2VkKHZlcnRpY2VzLCAwLCBpbmRpY2VzLCBpbmRpY2VzQ291bnQsIHV2cywgc3RyaWRlKTtcblx0XHRcdFx0dmVydGljZXMgPSBjbGlwcGVyLmNsaXBwZWRWZXJ0aWNlc1R5cGVkO1xuXHRcdFx0XHR2ZXJ0aWNlc0NvdW50ID0gY2xpcHBlci5jbGlwcGVkVmVydGljZXNMZW5ndGggLyBzdHJpZGU7XG5cdFx0XHRcdHV2cyA9IGNsaXBwZXIuY2xpcHBlZFVWc1R5cGVkO1xuXHRcdFx0XHRpbmRpY2VzID0gY2xpcHBlci5jbGlwcGVkVHJpYW5nbGVzVHlwZWQ7XG5cdFx0XHRcdGluZGljZXNDb3VudCA9IGNsaXBwZXIuY2xpcHBlZFRyaWFuZ2xlc0xlbmd0aDtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgY21kID0gdGhpcy5jb21tYW5kUG9vbC5nZXRDb21tYW5kKHZlcnRpY2VzQ291bnQsIGluZGljZXNDb3VudCwgc3RyaWRlKTtcblx0XHRcdGNtZC5ibGVuZE1vZGUgPSBzbG90LmRhdGEuYmxlbmRNb2RlO1xuXHRcdFx0Y21kLnRleHR1cmUgPSB0ZXh0dXJlO1xuXG5cdFx0XHRjbWQucG9zaXRpb25zLnNldCh2ZXJ0aWNlcy5zdWJhcnJheSgwLCB2ZXJ0aWNlc0NvdW50ICogc3RyaWRlKSk7XG5cdFx0XHQvLyBTdG9yZSBzbG90IGRlcHRoIGJlZm9yZSBiYXRjaGluZyBzbyByZW5kZXJlcnMgY2FuIHNlcGFyYXRlIG92ZXJsYXBwaW5nIGF0dGFjaG1lbnRzLlxuXHRcdFx0aWYgKHN0cmlkZSA+PSAzKSB7XG5cdFx0XHRcdGZvciAobGV0IGogPSAyLCBuID0gdmVydGljZXNDb3VudCAqIHN0cmlkZTsgaiA8IG47IGogKz0gc3RyaWRlKVxuXHRcdFx0XHRcdGNtZC5wb3NpdGlvbnNbal0gPSB6O1xuXHRcdFx0fVxuXHRcdFx0Y21kLnV2cy5zZXQodXZzLnN1YmFycmF5KDAsIHZlcnRpY2VzQ291bnQgPDwgMSkpO1xuXG5cdFx0XHRmb3IgKGxldCBqID0gMDsgaiA8IHZlcnRpY2VzQ291bnQ7IGorKykge1xuXHRcdFx0XHRjbWQuY29sb3JzW2pdID0gY29sb3I7XG5cdFx0XHRcdGNtZC5kYXJrQ29sb3JzW2pdID0gZGFya0NvbG9yO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoaW5kaWNlcyBpbnN0YW5jZW9mIFVpbnQxNkFycmF5KSB7XG5cdFx0XHRcdGNtZC5pbmRpY2VzLnNldChpbmRpY2VzLnN1YmFycmF5KDAsIGluZGljZXNDb3VudCkpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y21kLmluZGljZXMuc2V0KGluZGljZXMuc2xpY2UoMCwgaW5kaWNlc0NvdW50KSk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMucmVuZGVyQ29tbWFuZHMucHVzaChjbWQpO1xuXHRcdFx0eiArPSBzbG90Wk9mZnNldDtcblx0XHRcdGNsaXBwZXIuY2xpcEVuZChzbG90KTtcblx0XHR9XG5cblx0XHRjbGlwcGVyLmNsaXBFbmQoKTtcblx0XHRyZXR1cm4gdGhpcy5iYXRjaENvbW1hbmRzKHN0cmlkZSk7XG5cdH1cblxuXHRwcml2YXRlIGJhdGNoU3ViQ29tbWFuZHMgKGNvbW1hbmRzOiBSZW5kZXJDb21tYW5kW10sIGZpcnN0OiBudW1iZXIsIGxhc3Q6IG51bWJlcixcblx0XHRudW1WZXJ0aWNlczogbnVtYmVyLCBudW1JbmRpY2VzOiBudW1iZXIsIHN0cmlkZTogbnVtYmVyKTogUmVuZGVyQ29tbWFuZCB7XG5cblx0XHRjb25zdCBmaXJzdENtZCA9IGNvbW1hbmRzW2ZpcnN0XTtcblx0XHRjb25zdCBiYXRjaGVkID0gdGhpcy5jb21tYW5kUG9vbC5nZXRDb21tYW5kKG51bVZlcnRpY2VzLCBudW1JbmRpY2VzLCBzdHJpZGUpO1xuXG5cdFx0YmF0Y2hlZC5ibGVuZE1vZGUgPSBmaXJzdENtZC5ibGVuZE1vZGU7XG5cdFx0YmF0Y2hlZC50ZXh0dXJlID0gZmlyc3RDbWQudGV4dHVyZTtcblxuXHRcdGxldCBwb3NpdGlvbnNPZmZzZXQgPSAwO1xuXHRcdGxldCB1dnNPZmZzZXQgPSAwO1xuXHRcdGxldCBjb2xvcnNPZmZzZXQgPSAwO1xuXHRcdGxldCBpbmRpY2VzT2Zmc2V0ID0gMDtcblx0XHRsZXQgdmVydGV4T2Zmc2V0ID0gMDtcblxuXHRcdGZvciAobGV0IGkgPSBmaXJzdDsgaSA8PSBsYXN0OyBpKyspIHtcblx0XHRcdGNvbnN0IGNtZCA9IGNvbW1hbmRzW2ldO1xuXG5cdFx0XHRiYXRjaGVkLnBvc2l0aW9ucy5zZXQoY21kLnBvc2l0aW9ucywgcG9zaXRpb25zT2Zmc2V0KTtcblx0XHRcdHBvc2l0aW9uc09mZnNldCArPSBjbWQubnVtVmVydGljZXMgKiBzdHJpZGU7XG5cblx0XHRcdGJhdGNoZWQudXZzLnNldChjbWQudXZzLCB1dnNPZmZzZXQpO1xuXHRcdFx0dXZzT2Zmc2V0ICs9IGNtZC5udW1WZXJ0aWNlcyA8PCAxO1xuXG5cdFx0XHRiYXRjaGVkLmNvbG9ycy5zZXQoY21kLmNvbG9ycywgY29sb3JzT2Zmc2V0KTtcblx0XHRcdGJhdGNoZWQuZGFya0NvbG9ycy5zZXQoY21kLmRhcmtDb2xvcnMsIGNvbG9yc09mZnNldCk7XG5cdFx0XHRjb2xvcnNPZmZzZXQgKz0gY21kLm51bVZlcnRpY2VzO1xuXG5cdFx0XHQvLyBjYW5ub3QgZmFzdCBjb3B5IC0gaW5kaWNlcyBuZWVkIHZlcnRleCBvZmZzZXQgYWRqdXN0bWVudFxuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCBjbWQubnVtSW5kaWNlczsgaisrKVxuXHRcdFx0XHRiYXRjaGVkLmluZGljZXNbaW5kaWNlc09mZnNldCArIGpdID0gY21kLmluZGljZXNbal0gKyB2ZXJ0ZXhPZmZzZXQ7XG5cblx0XHRcdGluZGljZXNPZmZzZXQgKz0gY21kLm51bUluZGljZXM7XG5cdFx0XHR2ZXJ0ZXhPZmZzZXQgKz0gY21kLm51bVZlcnRpY2VzO1xuXHRcdH1cblxuXHRcdHJldHVybiBiYXRjaGVkO1xuXHR9XG5cblx0cHJpdmF0ZSBiYXRjaENvbW1hbmRzIChzdHJpZGU6IG51bWJlcik6IFJlbmRlckNvbW1hbmQgfCB1bmRlZmluZWQge1xuXHRcdGlmICh0aGlzLnJlbmRlckNvbW1hbmRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuXHRcdGxldCByb290OiBSZW5kZXJDb21tYW5kIHwgdW5kZWZpbmVkO1xuXHRcdGxldCBsYXN0OiBSZW5kZXJDb21tYW5kIHwgdW5kZWZpbmVkO1xuXG5cdFx0bGV0IGZpcnN0ID0gdGhpcy5yZW5kZXJDb21tYW5kc1swXTtcblx0XHRsZXQgc3RhcnRJbmRleCA9IDA7XG5cdFx0bGV0IGkgPSAxO1xuXHRcdGxldCBudW1WZXJ0aWNlcyA9IGZpcnN0Lm51bVZlcnRpY2VzO1xuXHRcdGxldCBudW1JbmRpY2VzID0gZmlyc3QubnVtSW5kaWNlcztcblxuXHRcdHdoaWxlIChpIDw9IHRoaXMucmVuZGVyQ29tbWFuZHMubGVuZ3RoKSB7XG5cdFx0XHRjb25zdCBjbWQgPSBpIDwgdGhpcy5yZW5kZXJDb21tYW5kcy5sZW5ndGggPyB0aGlzLnJlbmRlckNvbW1hbmRzW2ldIDogbnVsbDtcblxuXHRcdFx0aWYgKGNtZCAmJiBjbWQubnVtVmVydGljZXMgPT09IDAgJiYgY21kLm51bUluZGljZXMgPT09IDApIHtcblx0XHRcdFx0aSsrO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgY2FuQmF0Y2ggPSBjbWQgIT09IG51bGwgJiZcblx0XHRcdFx0Y21kLnRleHR1cmUgPT09IGZpcnN0LnRleHR1cmUgJiZcblx0XHRcdFx0Y21kLmJsZW5kTW9kZSA9PT0gZmlyc3QuYmxlbmRNb2RlICYmXG5cdFx0XHRcdGNtZC5jb2xvcnNbMF0gPT09IGZpcnN0LmNvbG9yc1swXSAmJlxuXHRcdFx0XHRjbWQuZGFya0NvbG9yc1swXSA9PT0gZmlyc3QuZGFya0NvbG9yc1swXSAmJlxuXHRcdFx0XHRudW1JbmRpY2VzICsgY21kLm51bUluZGljZXMgPCAweGZmZmY7XG5cdFx0XHRpZiAoY2FuQmF0Y2gpIHtcblx0XHRcdFx0bnVtVmVydGljZXMgKz0gY21kLm51bVZlcnRpY2VzO1xuXHRcdFx0XHRudW1JbmRpY2VzICs9IGNtZC5udW1JbmRpY2VzO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3QgYmF0Y2hlZCA9IHRoaXMuYmF0Y2hTdWJDb21tYW5kcyh0aGlzLnJlbmRlckNvbW1hbmRzLCBzdGFydEluZGV4LCBpIC0gMSxcblx0XHRcdFx0XHRudW1WZXJ0aWNlcywgbnVtSW5kaWNlcywgc3RyaWRlKTtcblxuXHRcdFx0XHRpZiAoIWxhc3QpIHtcblx0XHRcdFx0XHRyb290ID0gbGFzdCA9IGJhdGNoZWQ7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bGFzdC5uZXh0ID0gYmF0Y2hlZDtcblx0XHRcdFx0XHRsYXN0ID0gYmF0Y2hlZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChpID09PSB0aGlzLnJlbmRlckNvbW1hbmRzLmxlbmd0aCkgYnJlYWs7XG5cblx0XHRcdFx0Zmlyc3QgPSB0aGlzLnJlbmRlckNvbW1hbmRzW2ldO1xuXHRcdFx0XHRzdGFydEluZGV4ID0gaTtcblx0XHRcdFx0bnVtVmVydGljZXMgPSBmaXJzdC5udW1WZXJ0aWNlcztcblx0XHRcdFx0bnVtSW5kaWNlcyA9IGZpcnN0Lm51bUluZGljZXM7XG5cdFx0XHR9XG5cdFx0XHRpKys7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJvb3Q7XG5cdH1cbn1cblxuLy8gdmFsdWVzIHdpdGggdW5kZXIgc2NvcmUgaXMgdGhlIG9yaWdpbmFsIHNpemVkIGFycmF5LCBiaWdnZXIgdGhhbiBuZWNlc3Nhcnlcbi8vIHZhbHVlcyB3aXRob3V0IHVuZGVyIHNjb3JlIGlzIGEgdmlldyBvZiB0aGUgb3JpZ25hbCBhcnJheSwgc2l6ZWQgYXMgbmVlZGVkXG5leHBvcnQgaW50ZXJmYWNlIFJlbmRlckNvbW1hbmQge1xuXHRwb3NpdGlvbnM6IEZsb2F0MzJBcnJheTtcblx0dXZzOiBGbG9hdDMyQXJyYXk7XG5cdGNvbG9yczogVWludDMyQXJyYXk7XG5cdGRhcmtDb2xvcnM6IFVpbnQzMkFycmF5O1xuXHRpbmRpY2VzOiBVaW50MTZBcnJheTtcblx0X3Bvc2l0aW9uczogRmxvYXQzMkFycmF5O1xuXHRfdXZzOiBGbG9hdDMyQXJyYXk7XG5cdF9jb2xvcnM6IFVpbnQzMkFycmF5O1xuXHRfZGFya0NvbG9yczogVWludDMyQXJyYXk7XG5cdF9pbmRpY2VzOiBVaW50MTZBcnJheTtcblx0bnVtVmVydGljZXM6IG51bWJlcjtcblx0bnVtSW5kaWNlczogbnVtYmVyO1xuXHRibGVuZE1vZGU6IEJsZW5kTW9kZTtcblx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiB0ZXh0dXJlIGRlcGVuZHMgb24gdGhlIHJ1bnRpbWVcblx0dGV4dHVyZTogYW55O1xuXHRuZXh0PzogUmVuZGVyQ29tbWFuZDtcbn1cblxuY2xhc3MgQ29tbWFuZFBvb2wge1xuXHRwcml2YXRlIHBvb2w6IFJlbmRlckNvbW1hbmRbXSA9IFtdO1xuXHRwcml2YXRlIGluVXNlOiBSZW5kZXJDb21tYW5kW10gPSBbXTtcblxuXHRnZXRDb21tYW5kIChudW1WZXJ0aWNlczogbnVtYmVyLCBudW1JbmRpY2VzOiBudW1iZXIsIHN0cmlkZTogbnVtYmVyKTogUmVuZGVyQ29tbWFuZCB7XG5cdFx0bGV0IGNtZDogUmVuZGVyQ29tbW