UNPKG

@esotericsoftware/spine-webgl

Version:
203 lines 27.9 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 { Shader } from "./Shader.js"; import { ManagedWebGLRenderingContext } from "./WebGL.js"; export class Mesh { attributes; context; vertices; verticesBuffer = null; verticesLength = 0; dirtyVertices = false; indices; indicesBuffer = null; indicesLength = 0; dirtyIndices = false; elementsPerVertex = 0; getAttributes() { return this.attributes; } maxVertices() { return this.vertices.length / this.elementsPerVertex; } numVertices() { return this.verticesLength / this.elementsPerVertex; } setVerticesLength(length) { this.dirtyVertices = true; this.verticesLength = length; } getVertices() { return this.vertices; } maxIndices() { return this.indices.length; } numIndices() { return this.indicesLength; } setIndicesLength(length) { this.dirtyIndices = true; this.indicesLength = length; } getIndices() { return this.indices; } ; getVertexSizeInFloats() { let size = 0; for (var i = 0; i < this.attributes.length; i++) { let attribute = this.attributes[i]; size += attribute.numElements; } return size; } constructor(context, attributes, maxVertices, maxIndices) { this.attributes = attributes; this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context); this.elementsPerVertex = 0; for (let i = 0; i < attributes.length; i++) { this.elementsPerVertex += attributes[i].numElements; } this.vertices = new Float32Array(maxVertices * this.elementsPerVertex); this.indices = new Uint16Array(maxIndices); this.context.addRestorable(this); } setVertices(vertices) { this.dirtyVertices = true; if (vertices.length > this.vertices.length) throw Error("Mesh can't store more than " + this.maxVertices() + " vertices"); this.vertices.set(vertices, 0); this.verticesLength = vertices.length; } setIndices(indices) { this.dirtyIndices = true; if (indices.length > this.indices.length) throw Error("Mesh can't store more than " + this.maxIndices() + " indices"); this.indices.set(indices, 0); this.indicesLength = indices.length; } draw(shader, primitiveType) { this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex); } drawWithOffset(shader, primitiveType, offset, count) { let gl = this.context.gl; if (this.dirtyVertices || this.dirtyIndices) this.update(); this.bind(shader); if (this.indicesLength > 0) { gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2); } else { gl.drawArrays(primitiveType, offset, count); } this.unbind(shader); } bind(shader) { let gl = this.context.gl; gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); let offset = 0; for (let i = 0; i < this.attributes.length; i++) { let attrib = this.attributes[i]; let location = shader.getAttributeLocation(attrib.name); gl.enableVertexAttribArray(location); gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4); offset += attrib.numElements; } if (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); } unbind(shader) { let gl = this.context.gl; for (let i = 0; i < this.attributes.length; i++) { let attrib = this.attributes[i]; let location = shader.getAttributeLocation(attrib.name); gl.disableVertexAttribArray(location); } gl.bindBuffer(gl.ARRAY_BUFFER, null); if (this.indicesLength > 0) gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); } update() { let gl = this.context.gl; if (this.dirtyVertices) { if (!this.verticesBuffer) { this.verticesBuffer = gl.createBuffer(); } gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW); this.dirtyVertices = false; } if (this.dirtyIndices) { if (!this.indicesBuffer) { this.indicesBuffer = gl.createBuffer(); } gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW); this.dirtyIndices = false; } } restore() { this.verticesBuffer = null; this.indicesBuffer = null; this.update(); } dispose() { this.context.removeRestorable(this); let gl = this.context.gl; gl.deleteBuffer(this.verticesBuffer); gl.deleteBuffer(this.indicesBuffer); } } export class VertexAttribute { name; type; numElements; constructor(name, type, numElements) { this.name = name; this.type = type; this.numElements = numElements; } } export class Position2Attribute extends VertexAttribute { constructor() { super(Shader.POSITION, VertexAttributeType.Float, 2); } } export class Position3Attribute extends VertexAttribute { constructor() { super(Shader.POSITION, VertexAttributeType.Float, 3); } } export class TexCoordAttribute extends VertexAttribute { constructor(unit = 0) { super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2); } } export class ColorAttribute extends VertexAttribute { constructor() { super(Shader.COLOR, VertexAttributeType.Float, 4); } } export class Color2Attribute extends VertexAttribute { constructor() { super(Shader.COLOR2, VertexAttributeType.Float, 4); } } export var VertexAttributeType; (function (VertexAttributeType) { VertexAttributeType[VertexAttributeType["Float"] = 0] = "Float"; })(VertexAttributeType || (VertexAttributeType = {})); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVzaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9NZXNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0VBMkIrRTtBQUcvRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUcxRCxNQUFNLE9BQU8sSUFBSTtJQXVDb0U7SUF0QzVFLE9BQU8sQ0FBK0I7SUFDdEMsUUFBUSxDQUFlO0lBQ3ZCLGNBQWMsR0FBdUIsSUFBSSxDQUFDO0lBQzFDLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUN0QixPQUFPLENBQWM7SUFDckIsYUFBYSxHQUF1QixJQUFJLENBQUM7SUFDekMsYUFBYSxHQUFHLENBQUMsQ0FBQztJQUNsQixZQUFZLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLGlCQUFpQixHQUFHLENBQUMsQ0FBQztJQUU5QixhQUFhLEtBQXlCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFFL0QsV0FBVyxLQUFjLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUNoRixXQUFXLEtBQWMsT0FBTyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7SUFDL0UsaUJBQWlCLENBQUUsTUFBYztRQUNoQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0sQ0FBQztJQUM5QixDQUFDO0lBQ0QsV0FBVyxLQUFvQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXRELFVBQVUsS0FBYyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNyRCxVQUFVLEtBQWMsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUNwRCxnQkFBZ0IsQ0FBRSxNQUFjO1FBQy9CLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO0lBQzdCLENBQUM7SUFDRCxVQUFVLEtBQW1CLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQSxDQUFDLENBQUM7SUFBQSxDQUFDO0lBRW5ELHFCQUFxQjtRQUNwQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7UUFDYixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNqRCxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLElBQUksSUFBSSxTQUFTLENBQUMsV0FBVyxDQUFDO1FBQy9CLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFRCxZQUFhLE9BQTZELEVBQVUsVUFBNkIsRUFBRSxXQUFtQixFQUFFLFVBQWtCO1FBQXRFLGVBQVUsR0FBVixVQUFVLENBQW1CO1FBQ2hILElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxZQUFZLDRCQUE0QixDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksNEJBQTRCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckgsSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsQ0FBQztRQUMzQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzVDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1FBQ3JELENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksWUFBWSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUN2RSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksV0FBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxXQUFXLENBQUUsUUFBdUI7UUFDbkMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDMUIsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTTtZQUFFLE1BQU0sS0FBSyxDQUFDLDZCQUE2QixHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsR0FBRyxXQUFXLENBQUMsQ0FBQztRQUMxSCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxVQUFVLENBQUUsT0FBc0I7UUFDakMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTTtZQUFFLE1BQU0sS0FBSyxDQUFDLDZCQUE2QixHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsR0FBRyxVQUFVLENBQUMsQ0FBQztRQUN0SCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQ3JDLENBQUM7SUFFRCxJQUFJLENBQUUsTUFBYyxFQUFFLGFBQXFCO1FBQzFDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLGFBQWEsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDM0ksQ0FBQztJQUVELGNBQWMsQ0FBRSxNQUFjLEVBQUUsYUFBcUIsRUFBRSxNQUFjLEVBQUUsS0FBYTtRQUNuRixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN6QixJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFlBQVk7WUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQixJQUFJLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsRUFBRSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7YUFBTSxDQUFDO1lBQ1AsRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFJLENBQUUsTUFBYztRQUNuQixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN6QixFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3BELElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNmLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pELElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEMsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN4RCxFQUFFLENBQUMsdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckMsRUFBRSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlHLE1BQU0sSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDO1FBQzlCLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQztZQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLG9CQUFvQixFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN4RixDQUFDO0lBRUQsTUFBTSxDQUFFLE1BQWM7UUFDckIsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDekIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDakQsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNoQyxJQUFJLFFBQVEsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3hELEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBQ0QsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDO1lBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDMUUsQ0FBQztJQUVPLE1BQU07UUFDYixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN6QixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLEVBQUUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN6QyxDQUFDO1lBQ0QsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNwRCxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDaEcsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3pCLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3hDLENBQUM7WUFDRCxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDM0QsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdEcsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDM0IsQ0FBQztJQUNGLENBQUM7SUFFRCxPQUFPO1FBQ04sSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFDM0IsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDMUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2YsQ0FBQztJQUVELE9BQU87UUFDTixJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3pCLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7Q0FDRDtBQUVELE1BQU0sT0FBTyxlQUFlO0lBQ1A7SUFBcUI7SUFBa0M7SUFBM0UsWUFBb0IsSUFBWSxFQUFTLElBQXlCLEVBQVMsV0FBbUI7UUFBMUUsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFTLFNBQUksR0FBSixJQUFJLENBQXFCO1FBQVMsZ0JBQVcsR0FBWCxXQUFXLENBQVE7SUFBSSxDQUFDO0NBQ25HO0FBRUQsTUFBTSxPQUFPLGtCQUFtQixTQUFRLGVBQWU7SUFDdEQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGtCQUFtQixTQUFRLGVBQWU7SUFDdEQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGlCQUFrQixTQUFRLGVBQWU7SUFDckQsWUFBYSxPQUFlLENBQUM7UUFDNUIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRixDQUFDO0NBQ0Q7QUFFRCxNQUFNLE9BQU8sY0FBZSxTQUFRLGVBQWU7SUFDbEQ7UUFDQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQztDQUNEO0FBRUQsTUFBTSxPQUFPLGVBQWdCLFNBQVEsZUFBZTtJQUNuRDtRQUNDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0NBQ0Q7QUFFRCxNQUFNLENBQU4sSUFBWSxtQkFFWDtBQUZELFdBQVksbUJBQW1CO0lBQzlCLCtEQUFLLENBQUE7QUFDTixDQUFDLEVBRlcsbUJBQW1CLEtBQW5CLG1CQUFtQixRQUU5QiIsInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIFNwaW5lIFJ1bnRpbWVzIExpY2Vuc2UgQWdyZWVtZW50XG4gKiBMYXN0IHVwZGF0ZWQgQXByaWwgNSwgMjAyNS4gUmVwbGFjZXMgYWxsIHByaW9yIHZlcnNpb25zLlxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMy0yMDI1LCBFc290ZXJpYyBTb2Z0d2FyZSBMTENcbiAqXG4gKiBJbnRlZ3JhdGlvbiBvZiB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZSBvciBvdGhlcndpc2UgY3JlYXRpbmdcbiAqIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGlzIHBlcm1pdHRlZCB1bmRlciB0aGUgdGVybXMgYW5kXG4gKiBjb25kaXRpb25zIG9mIFNlY3Rpb24gMiBvZiB0aGUgU3BpbmUgRWRpdG9yIExpY2Vuc2UgQWdyZWVtZW50OlxuICogaHR0cDovL2Vzb3Rlcmljc29mdHdhcmUuY29tL3NwaW5lLWVkaXRvci1saWNlbnNlXG4gKlxuICogT3RoZXJ3aXNlLCBpdCBpcyBwZXJtaXR0ZWQgdG8gaW50ZWdyYXRlIHRoZSBTcGluZSBSdW50aW1lcyBpbnRvIHNvZnR3YXJlXG4gKiBvciBvdGhlcndpc2UgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIChjb2xsZWN0aXZlbHksXG4gKiBcIlByb2R1Y3RzXCIpLCBwcm92aWRlZCB0aGF0IGVhY2ggdXNlciBvZiB0aGUgUHJvZHVjdHMgbXVzdCBvYnRhaW4gdGhlaXIgb3duXG4gKiBTcGluZSBFZGl0b3IgbGljZW5zZSBhbmQgcmVkaXN0cmlidXRpb24gb2YgdGhlIFByb2R1Y3RzIGluIGFueSBmb3JtIG11c3RcbiAqIGluY2x1ZGUgdGhpcyBsaWNlbnNlIGFuZCBjb3B5cmlnaHQgbm90aWNlLlxuICpcbiAqIFRIRSBTUElORSBSVU5USU1FUyBBUkUgUFJPVklERUQgQlkgRVNPVEVSSUMgU09GVFdBUkUgTExDIFwiQVMgSVNcIiBBTkQgQU5ZXG4gKiBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gKiBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBFU09URVJJQyBTT0ZUV0FSRSBMTEMgQkUgTElBQkxFIEZPUiBBTllcbiAqIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTXG4gKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVMsXG4gKiBCVVNJTkVTUyBJTlRFUlJVUFRJT04sIE9SIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTKSBIT1dFVkVSIENBVVNFRCBBTkRcbiAqIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUXG4gKiAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0ZcbiAqIFRIRSBTUElORSBSVU5USU1FUywgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuaW1wb3J0IHsgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB9IGZyb20gXCJAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jb3JlXCI7XG5pbXBvcnQgeyBTaGFkZXIgfSBmcm9tIFwiLi9TaGFkZXIuanNcIjtcbmltcG9ydCB7IE1hbmFnZWRXZWJHTFJlbmRlcmluZ0NvbnRleHQgfSBmcm9tIFwiLi9XZWJHTC5qc1wiO1xuXG5cbmV4cG9ydCBjbGFzcyBNZXNoIGltcGxlbWVudHMgRGlzcG9zYWJsZSwgUmVzdG9yYWJsZSB7XG5cdHByaXZhdGUgY29udGV4dDogTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcblx0cHJpdmF0ZSB2ZXJ0aWNlczogRmxvYXQzMkFycmF5O1xuXHRwcml2YXRlIHZlcnRpY2VzQnVmZmVyOiBXZWJHTEJ1ZmZlciB8IG51bGwgPSBudWxsO1xuXHRwcml2YXRlIHZlcnRpY2VzTGVuZ3RoID0gMDtcblx0cHJpdmF0ZSBkaXJ0eVZlcnRpY2VzID0gZmFsc2U7XG5cdHByaXZhdGUgaW5kaWNlczogVWludDE2QXJyYXk7XG5cdHByaXZhdGUgaW5kaWNlc0J1ZmZlcjogV2ViR0xCdWZmZXIgfCBudWxsID0gbnVsbDtcblx0cHJpdmF0ZSBpbmRpY2VzTGVuZ3RoID0gMDtcblx0cHJpdmF0ZSBkaXJ0eUluZGljZXMgPSBmYWxzZTtcblx0cHJpdmF0ZSBlbGVtZW50c1BlclZlcnRleCA9IDA7XG5cblx0Z2V0QXR0cmlidXRlcyAoKTogVmVydGV4QXR0cmlidXRlW10geyByZXR1cm4gdGhpcy5hdHRyaWJ1dGVzOyB9XG5cblx0bWF4VmVydGljZXMgKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnZlcnRpY2VzLmxlbmd0aCAvIHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXg7IH1cblx0bnVtVmVydGljZXMgKCk6IG51bWJlciB7IHJldHVybiB0aGlzLnZlcnRpY2VzTGVuZ3RoIC8gdGhpcy5lbGVtZW50c1BlclZlcnRleDsgfVxuXHRzZXRWZXJ0aWNlc0xlbmd0aCAobGVuZ3RoOiBudW1iZXIpIHtcblx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSB0cnVlO1xuXHRcdHRoaXMudmVydGljZXNMZW5ndGggPSBsZW5ndGg7XG5cdH1cblx0Z2V0VmVydGljZXMgKCk6IEZsb2F0MzJBcnJheSB7IHJldHVybiB0aGlzLnZlcnRpY2VzOyB9XG5cblx0bWF4SW5kaWNlcyAoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuaW5kaWNlcy5sZW5ndGg7IH1cblx0bnVtSW5kaWNlcyAoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuaW5kaWNlc0xlbmd0aDsgfVxuXHRzZXRJbmRpY2VzTGVuZ3RoIChsZW5ndGg6IG51bWJlcikge1xuXHRcdHRoaXMuZGlydHlJbmRpY2VzID0gdHJ1ZTtcblx0XHR0aGlzLmluZGljZXNMZW5ndGggPSBsZW5ndGg7XG5cdH1cblx0Z2V0SW5kaWNlcyAoKTogVWludDE2QXJyYXkgeyByZXR1cm4gdGhpcy5pbmRpY2VzIH07XG5cblx0Z2V0VmVydGV4U2l6ZUluRmxvYXRzICgpOiBudW1iZXIge1xuXHRcdGxldCBzaXplID0gMDtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bGV0IGF0dHJpYnV0ZSA9IHRoaXMuYXR0cmlidXRlc1tpXTtcblx0XHRcdHNpemUgKz0gYXR0cmlidXRlLm51bUVsZW1lbnRzO1xuXHRcdH1cblx0XHRyZXR1cm4gc2l6ZTtcblx0fVxuXG5cdGNvbnN0cnVjdG9yIChjb250ZXh0OiBNYW5hZ2VkV2ViR0xSZW5kZXJpbmdDb250ZXh0IHwgV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBwcml2YXRlIGF0dHJpYnV0ZXM6IFZlcnRleEF0dHJpYnV0ZVtdLCBtYXhWZXJ0aWNlczogbnVtYmVyLCBtYXhJbmRpY2VzOiBudW1iZXIpIHtcblx0XHR0aGlzLmNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dCA/IGNvbnRleHQgOiBuZXcgTWFuYWdlZFdlYkdMUmVuZGVyaW5nQ29udGV4dChjb250ZXh0KTtcblx0XHR0aGlzLmVsZW1lbnRzUGVyVmVydGV4ID0gMDtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXggKz0gYXR0cmlidXRlc1tpXS5udW1FbGVtZW50cztcblx0XHR9XG5cdFx0dGhpcy52ZXJ0aWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkobWF4VmVydGljZXMgKiB0aGlzLmVsZW1lbnRzUGVyVmVydGV4KTtcblx0XHR0aGlzLmluZGljZXMgPSBuZXcgVWludDE2QXJyYXkobWF4SW5kaWNlcyk7XG5cdFx0dGhpcy5jb250ZXh0LmFkZFJlc3RvcmFibGUodGhpcyk7XG5cdH1cblxuXHRzZXRWZXJ0aWNlcyAodmVydGljZXM6IEFycmF5PG51bWJlcj4pIHtcblx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSB0cnVlO1xuXHRcdGlmICh2ZXJ0aWNlcy5sZW5ndGggPiB0aGlzLnZlcnRpY2VzLmxlbmd0aCkgdGhyb3cgRXJyb3IoXCJNZXNoIGNhbid0IHN0b3JlIG1vcmUgdGhhbiBcIiArIHRoaXMubWF4VmVydGljZXMoKSArIFwiIHZlcnRpY2VzXCIpO1xuXHRcdHRoaXMudmVydGljZXMuc2V0KHZlcnRpY2VzLCAwKTtcblx0XHR0aGlzLnZlcnRpY2VzTGVuZ3RoID0gdmVydGljZXMubGVuZ3RoO1xuXHR9XG5cblx0c2V0SW5kaWNlcyAoaW5kaWNlczogQXJyYXk8bnVtYmVyPikge1xuXHRcdHRoaXMuZGlydHlJbmRpY2VzID0gdHJ1ZTtcblx0XHRpZiAoaW5kaWNlcy5sZW5ndGggPiB0aGlzLmluZGljZXMubGVuZ3RoKSB0aHJvdyBFcnJvcihcIk1lc2ggY2FuJ3Qgc3RvcmUgbW9yZSB0aGFuIFwiICsgdGhpcy5tYXhJbmRpY2VzKCkgKyBcIiBpbmRpY2VzXCIpO1xuXHRcdHRoaXMuaW5kaWNlcy5zZXQoaW5kaWNlcywgMCk7XG5cdFx0dGhpcy5pbmRpY2VzTGVuZ3RoID0gaW5kaWNlcy5sZW5ndGg7XG5cdH1cblxuXHRkcmF3IChzaGFkZXI6IFNoYWRlciwgcHJpbWl0aXZlVHlwZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5kcmF3V2l0aE9mZnNldChzaGFkZXIsIHByaW1pdGl2ZVR5cGUsIDAsIHRoaXMuaW5kaWNlc0xlbmd0aCA+IDAgPyB0aGlzLmluZGljZXNMZW5ndGggOiB0aGlzLnZlcnRpY2VzTGVuZ3RoIC8gdGhpcy5lbGVtZW50c1BlclZlcnRleCk7XG5cdH1cblxuXHRkcmF3V2l0aE9mZnNldCAoc2hhZGVyOiBTaGFkZXIsIHByaW1pdGl2ZVR5cGU6IG51bWJlciwgb2Zmc2V0OiBudW1iZXIsIGNvdW50OiBudW1iZXIpIHtcblx0XHRsZXQgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0aWYgKHRoaXMuZGlydHlWZXJ0aWNlcyB8fCB0aGlzLmRpcnR5SW5kaWNlcykgdGhpcy51cGRhdGUoKTtcblx0XHR0aGlzLmJpbmQoc2hhZGVyKTtcblx0XHRpZiAodGhpcy5pbmRpY2VzTGVuZ3RoID4gMCkge1xuXHRcdFx0Z2wuZHJhd0VsZW1lbnRzKHByaW1pdGl2ZVR5cGUsIGNvdW50LCBnbC5VTlNJR05FRF9TSE9SVCwgb2Zmc2V0ICogMik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGdsLmRyYXdBcnJheXMocHJpbWl0aXZlVHlwZSwgb2Zmc2V0LCBjb3VudCk7XG5cdFx0fVxuXHRcdHRoaXMudW5iaW5kKHNoYWRlcik7XG5cdH1cblxuXHRiaW5kIChzaGFkZXI6IFNoYWRlcikge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgdGhpcy52ZXJ0aWNlc0J1ZmZlcik7XG5cdFx0bGV0IG9mZnNldCA9IDA7XG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmF0dHJpYnV0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdGxldCBhdHRyaWIgPSB0aGlzLmF0dHJpYnV0ZXNbaV07XG5cdFx0XHRsZXQgbG9jYXRpb24gPSBzaGFkZXIuZ2V0QXR0cmlidXRlTG9jYXRpb24oYXR0cmliLm5hbWUpO1xuXHRcdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkobG9jYXRpb24pO1xuXHRcdFx0Z2wudmVydGV4QXR0cmliUG9pbnRlcihsb2NhdGlvbiwgYXR0cmliLm51bUVsZW1lbnRzLCBnbC5GTE9BVCwgZmFsc2UsIHRoaXMuZWxlbWVudHNQZXJWZXJ0ZXggKiA0LCBvZmZzZXQgKiA0KTtcblx0XHRcdG9mZnNldCArPSBhdHRyaWIubnVtRWxlbWVudHM7XG5cdFx0fVxuXHRcdGlmICh0aGlzLmluZGljZXNMZW5ndGggPiAwKSBnbC5iaW5kQnVmZmVyKGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSLCB0aGlzLmluZGljZXNCdWZmZXIpO1xuXHR9XG5cblx0dW5iaW5kIChzaGFkZXI6IFNoYWRlcikge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0bGV0IGF0dHJpYiA9IHRoaXMuYXR0cmlidXRlc1tpXTtcblx0XHRcdGxldCBsb2NhdGlvbiA9IHNoYWRlci5nZXRBdHRyaWJ1dGVMb2NhdGlvbihhdHRyaWIubmFtZSk7XG5cdFx0XHRnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkobG9jYXRpb24pO1xuXHRcdH1cblx0XHRnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgbnVsbCk7XG5cdFx0aWYgKHRoaXMuaW5kaWNlc0xlbmd0aCA+IDApIGdsLmJpbmRCdWZmZXIoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIG51bGwpO1xuXHR9XG5cblx0cHJpdmF0ZSB1cGRhdGUgKCkge1xuXHRcdGxldCBnbCA9IHRoaXMuY29udGV4dC5nbDtcblx0XHRpZiAodGhpcy5kaXJ0eVZlcnRpY2VzKSB7XG5cdFx0XHRpZiAoIXRoaXMudmVydGljZXNCdWZmZXIpIHtcblx0XHRcdFx0dGhpcy52ZXJ0aWNlc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuXHRcdFx0fVxuXHRcdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmVydGljZXNCdWZmZXIpO1xuXHRcdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHRoaXMudmVydGljZXMuc3ViYXJyYXkoMCwgdGhpcy52ZXJ0aWNlc0xlbmd0aCksIGdsLkRZTkFNSUNfRFJBVyk7XG5cdFx0XHR0aGlzLmRpcnR5VmVydGljZXMgPSBmYWxzZTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kaXJ0eUluZGljZXMpIHtcblx0XHRcdGlmICghdGhpcy5pbmRpY2VzQnVmZmVyKSB7XG5cdFx0XHRcdHRoaXMuaW5kaWNlc0J1ZmZlciA9IGdsLmNyZWF0ZUJ1ZmZlcigpO1xuXHRcdFx0fVxuXHRcdFx0Z2wuYmluZEJ1ZmZlcihnbC5FTEVNRU5UX0FSUkFZX0JVRkZFUiwgdGhpcy5pbmRpY2VzQnVmZmVyKTtcblx0XHRcdGdsLmJ1ZmZlckRhdGEoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIHRoaXMuaW5kaWNlcy5zdWJhcnJheSgwLCB0aGlzLmluZGljZXNMZW5ndGgpLCBnbC5EWU5BTUlDX0RSQVcpO1xuXHRcdFx0dGhpcy5kaXJ0eUluZGljZXMgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRyZXN0b3JlICgpIHtcblx0XHR0aGlzLnZlcnRpY2VzQnVmZmVyID0gbnVsbDtcblx0XHR0aGlzLmluZGljZXNCdWZmZXIgPSBudWxsO1xuXHRcdHRoaXMudXBkYXRlKCk7XG5cdH1cblxuXHRkaXNwb3NlICgpIHtcblx0XHR0aGlzLmNvbnRleHQucmVtb3ZlUmVzdG9yYWJsZSh0aGlzKTtcblx0XHRsZXQgZ2wgPSB0aGlzLmNvbnRleHQuZ2w7XG5cdFx0Z2wuZGVsZXRlQnVmZmVyKHRoaXMudmVydGljZXNCdWZmZXIpO1xuXHRcdGdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmluZGljZXNCdWZmZXIpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAocHVibGljIG5hbWU6IHN0cmluZywgcHVibGljIHR5cGU6IFZlcnRleEF0dHJpYnV0ZVR5cGUsIHB1YmxpYyBudW1FbGVtZW50czogbnVtYmVyKSB7IH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvc2l0aW9uMkF0dHJpYnV0ZSBleHRlbmRzIFZlcnRleEF0dHJpYnV0ZSB7XG5cdGNvbnN0cnVjdG9yICgpIHtcblx0XHRzdXBlcihTaGFkZXIuUE9TSVRJT04sIFZlcnRleEF0dHJpYnV0ZVR5cGUuRmxvYXQsIDIpO1xuXHR9XG59XG5cbmV4cG9ydCBjbGFzcyBQb3NpdGlvbjNBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAoKSB7XG5cdFx0c3VwZXIoU2hhZGVyLlBPU0lUSU9OLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCAzKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgVGV4Q29vcmRBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAodW5pdDogbnVtYmVyID0gMCkge1xuXHRcdHN1cGVyKFNoYWRlci5URVhDT09SRFMgKyAodW5pdCA9PSAwID8gXCJcIiA6IHVuaXQpLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCAyKTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQ29sb3JBdHRyaWJ1dGUgZXh0ZW5kcyBWZXJ0ZXhBdHRyaWJ1dGUge1xuXHRjb25zdHJ1Y3RvciAoKSB7XG5cdFx0c3VwZXIoU2hhZGVyLkNPTE9SLCBWZXJ0ZXhBdHRyaWJ1dGVUeXBlLkZsb2F0LCA0KTtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgQ29sb3IyQXR0cmlidXRlIGV4dGVuZHMgVmVydGV4QXR0cmlidXRlIHtcblx0Y29uc3RydWN0b3IgKCkge1xuXHRcdHN1cGVyKFNoYWRlci5DT0xPUjIsIFZlcnRleEF0dHJpYnV0ZVR5cGUuRmxvYXQsIDQpO1xuXHR9XG59XG5cbmV4cG9ydCBlbnVtIFZlcnRleEF0dHJpYnV0ZVR5cGUge1xuXHRGbG9hdFxufVxuIl19