@esotericsoftware/spine-core
Version:
The official Spine Runtimes for the web.
327 lines • 52 kB
JavaScript
/******************************************************************************
* 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