Files
SpineParticlesWeb/vendor/spine/spine-pixi-v7-4.3/dist/SpineDebugRenderer.js
T
2026-09-02 13:53:12 +08:00

451 lines
74 KiB
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, PathAttachment, RegionAttachment, SkeletonBounds } from "@spine-particle/spine-core-4.3";
import { Container } from "@pixi/display";
import { Graphics } from "@pixi/graphics";
import { Text } from "@pixi/text";
/**
* This is a debug renderer that uses PixiJS Graphics under the hood.
* @public
*/
export class SpineDebugRenderer {
registeredSpines = new Map();
drawMeshHull = true;
drawMeshTriangles = true;
drawBones = true;
drawPaths = true;
drawBoundingBoxes = true;
drawClipping = true;
drawRegionAttachments = true;
drawEvents = true;
lineWidth = 1;
regionAttachmentsColor = 0x0078ff;
meshHullColor = 0x0078ff;
meshTrianglesColor = 0xffcc00;
clippingPolygonColor = 0xff00ff;
boundingBoxesRectColor = 0x00ff00;
boundingBoxesPolygonColor = 0x00ff00;
boundingBoxesCircleColor = 0x00ff00;
pathsCurveColor = 0xff0000;
pathsLineColor = 0xff00ff;
skeletonXYColor = 0xff0000;
bonesColor = 0x00eecc;
eventFontSize = 24;
eventFontColor = 0x0;
/**
* The debug is attached by force to each spine object. So we need to create it inside the spine when we get the first update
*/
registerSpine(spine) {
if (this.registeredSpines.has(spine)) {
console.warn("SpineDebugRenderer.registerSpine() - this spine is already registered!", spine);
return;
}
const debugDisplayObjects = {
parentDebugContainer: new Container(),
bones: new Container(),
skeletonXY: new Graphics(),
regionAttachmentsShape: new Graphics(),
meshTrianglesLine: new Graphics(),
meshHullLine: new Graphics(),
clippingPolygon: new Graphics(),
boundingBoxesRect: new Graphics(),
boundingBoxesCircle: new Graphics(),
boundingBoxesPolygon: new Graphics(),
pathsCurve: new Graphics(),
pathsLine: new Graphics(),
eventText: new Container(),
eventCallback: {
event: (_, event) => {
if (this.drawEvents) {
const scale = Math.abs(spine.scale.x || spine.scale.y || 1);
const text = new Text(event.data.name, { fontSize: this.eventFontSize / scale, fill: this.eventFontColor, fontFamily: "monospace" });
text.scale.x = Math.sign(spine.scale.x);
text.anchor.set(0.5);
debugDisplayObjects.eventText.addChild(text);
setTimeout(() => {
if (!text.destroyed) {
text.destroy();
}
}, 250);
}
},
},
};
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.bones);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.skeletonXY);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.regionAttachmentsShape);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.meshTrianglesLine);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.meshHullLine);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.clippingPolygon);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.boundingBoxesRect);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.boundingBoxesCircle);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.boundingBoxesPolygon);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.pathsCurve);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.pathsLine);
debugDisplayObjects.parentDebugContainer.addChild(debugDisplayObjects.eventText);
debugDisplayObjects.parentDebugContainer.zIndex = 9999999;
// Disable screen reader and mouse input on debug objects.
// biome-ignore lint/suspicious/noExplicitAny: this prop is available in later versions
debugDisplayObjects.parentDebugContainer.accessibleChildren = false;
(debugDisplayObjects.parentDebugContainer).eventMode = "none";
(debugDisplayObjects.parentDebugContainer).interactiveChildren = false;
spine.addChild(debugDisplayObjects.parentDebugContainer);
spine.state.addListener(debugDisplayObjects.eventCallback);
this.registeredSpines.set(spine, debugDisplayObjects);
}
renderDebug(spine) {
if (!this.registeredSpines.has(spine)) {
// This should never happen. Spines are registered when you assign spine.debug
this.registerSpine(spine);
}
const debugDisplayObjects = this.registeredSpines.get(spine);
if (!debugDisplayObjects) {
return;
}
spine.addChild(debugDisplayObjects.parentDebugContainer);
debugDisplayObjects.skeletonXY.clear();
debugDisplayObjects.regionAttachmentsShape.clear();
debugDisplayObjects.meshTrianglesLine.clear();
debugDisplayObjects.meshHullLine.clear();
debugDisplayObjects.clippingPolygon.clear();
debugDisplayObjects.boundingBoxesRect.clear();
debugDisplayObjects.boundingBoxesCircle.clear();
debugDisplayObjects.boundingBoxesPolygon.clear();
debugDisplayObjects.pathsCurve.clear();
debugDisplayObjects.pathsLine.clear();
for (let len = debugDisplayObjects.bones.children.length; len > 0; len--) {
debugDisplayObjects.bones.children[len - 1].destroy({ children: true, texture: true, baseTexture: true });
}
const scale = Math.abs(spine.scale.x || spine.scale.y || 1);
const lineWidth = this.lineWidth / scale;
if (this.drawBones) {
this.drawBonesFunc(spine, debugDisplayObjects, lineWidth, scale);
}
if (this.drawPaths) {
this.drawPathsFunc(spine, debugDisplayObjects, lineWidth);
}
if (this.drawBoundingBoxes) {
this.drawBoundingBoxesFunc(spine, debugDisplayObjects, lineWidth);
}
if (this.drawClipping) {
this.drawClippingFunc(spine, debugDisplayObjects, lineWidth);
}
if (this.drawMeshHull || this.drawMeshTriangles) {
this.drawMeshHullAndMeshTriangles(spine, debugDisplayObjects, lineWidth);
}
if (this.drawRegionAttachments) {
this.drawRegionAttachmentsFunc(spine, debugDisplayObjects, lineWidth);
}
if (this.drawEvents) {
for (const child of debugDisplayObjects.eventText.children) {
child.alpha -= 0.05;
child.y -= 2;
}
}
}
drawBonesFunc(spine, debugDisplayObjects, lineWidth, scale) {
const skeleton = spine.skeleton;
const skeletonX = skeleton.x;
const skeletonY = skeleton.y;
const bones = skeleton.bones;
debugDisplayObjects.skeletonXY.lineStyle(lineWidth, this.skeletonXYColor, 1);
for (let i = 0, len = bones.length; i < len; i++) {
const bone = bones[i];
const boneLen = bone.data.length;
const applied = bone.appliedPose;
const starX = skeletonX + applied.worldX;
const starY = skeletonY + applied.worldY;
const endX = skeletonX + boneLen * applied.a + applied.worldX;
const endY = skeletonY + boneLen * applied.b + applied.worldY;
if (bone.data.name === "root" || bone.data.parent === null) {
continue;
}
const w = Math.abs(starX - endX);
const h = Math.abs(starY - endY);
// a = w, // side length a
const a2 = Math.pow(w, 2); // square root of side length a
const b = h; // side length b
const b2 = Math.pow(h, 2); // square root of side length b
const c = Math.sqrt(a2 + b2); // side length c
const c2 = Math.pow(c, 2); // square root of side length c
const rad = Math.PI / 180;
// A = Math.acos([a2 + c2 - b2] / [2 * a * c]) || 0, // Angle A
// C = Math.acos([a2 + b2 - c2] / [2 * a * b]) || 0, // C angle
const B = Math.acos((c2 + b2 - a2) / (2 * b * c)) || 0; // angle of corner B
if (c === 0) {
continue;
}
const gp = new Graphics();
debugDisplayObjects.bones.addChild(gp);
// draw bone
const refRation = c / 50 / scale;
gp.beginFill(this.bonesColor, 1);
gp.drawPolygon(0, 0, 0 - refRation, c - refRation * 3, 0, c - refRation, 0 + refRation, c - refRation * 3);
gp.endFill();
gp.x = starX;
gp.y = starY;
gp.pivot.y = c;
// Calculate bone rotation angle
let rotation = 0;
if (starX < endX && starY < endY) {
// bottom right
rotation = -B + 180 * rad;
}
else if (starX > endX && starY < endY) {
// bottom left
rotation = 180 * rad + B;
}
else if (starX > endX && starY > endY) {
// top left
rotation = -B;
}
else if (starX < endX && starY > endY) {
// bottom left
rotation = B;
}
else if (starY === endY && starX < endX) {
// To the right
rotation = 90 * rad;
}
else if (starY === endY && starX > endX) {
// go left
rotation = -90 * rad;
}
else if (starX === endX && starY < endY) {
// down
rotation = 180 * rad;
}
else if (starX === endX && starY > endY) {
// up
rotation = 0;
}
gp.rotation = rotation;
// Draw the starting rotation point of the bone
gp.lineStyle(lineWidth + refRation / 2.4, this.bonesColor, 1);
gp.beginFill(0x000000, 0.6);
gp.drawCircle(0, c, refRation * 1.2);
gp.endFill();
}
// Draw the skeleton starting point "X" form
const startDotSize = lineWidth * 3;
debugDisplayObjects.skeletonXY.moveTo(skeletonX - startDotSize, skeletonY - startDotSize);
debugDisplayObjects.skeletonXY.lineTo(skeletonX + startDotSize, skeletonY + startDotSize);
debugDisplayObjects.skeletonXY.moveTo(skeletonX + startDotSize, skeletonY - startDotSize);
debugDisplayObjects.skeletonXY.lineTo(skeletonX - startDotSize, skeletonY + startDotSize);
}
drawRegionAttachmentsFunc(spine, debugDisplayObjects, lineWidth) {
const skeleton = spine.skeleton;
const slots = skeleton.slots;
debugDisplayObjects.regionAttachmentsShape.lineStyle(lineWidth, this.regionAttachmentsColor, 1);
for (let i = 0, len = slots.length; i < len; i++) {
const slot = slots[i];
const attachment = slot.appliedPose.attachment;
if (attachment == null || !(attachment instanceof RegionAttachment)) {
continue;
}
const vertices = new Float32Array(8);
attachment.computeWorldVertices(slot, attachment.getOffsets(slot.appliedPose), vertices, 0, 2);
debugDisplayObjects.regionAttachmentsShape.drawPolygon(Array.from(vertices.slice(0, 8)));
}
}
drawMeshHullAndMeshTriangles(spine, debugDisplayObjects, lineWidth) {
const skeleton = spine.skeleton;
const slots = skeleton.slots;
debugDisplayObjects.meshHullLine.lineStyle(lineWidth, this.meshHullColor, 1);
debugDisplayObjects.meshTrianglesLine.lineStyle(lineWidth, this.meshTrianglesColor, 1);
for (let i = 0, len = slots.length; i < len; i++) {
const slot = slots[i];
if (!slot.bone.active) {
continue;
}
const attachment = slot.appliedPose.attachment;
if (attachment == null || !(attachment instanceof MeshAttachment)) {
continue;
}
const meshAttachment = attachment;
const vertices = new Float32Array(meshAttachment.worldVerticesLength);
const triangles = meshAttachment.triangles;
let hullLength = meshAttachment.hullLength;
meshAttachment.computeWorldVertices(skeleton, slot, 0, meshAttachment.worldVerticesLength, vertices, 0, 2);
// draw the skinned mesh (triangle)
if (this.drawMeshTriangles) {
for (let i = 0, len = triangles.length; i < len; i += 3) {
const v1 = triangles[i] * 2;
const v2 = triangles[i + 1] * 2;
const v3 = triangles[i + 2] * 2;
debugDisplayObjects.meshTrianglesLine.moveTo(vertices[v1], vertices[v1 + 1]);
debugDisplayObjects.meshTrianglesLine.lineTo(vertices[v2], vertices[v2 + 1]);
debugDisplayObjects.meshTrianglesLine.lineTo(vertices[v3], vertices[v3 + 1]);
}
}
// draw skin border
if (this.drawMeshHull && hullLength > 0) {
hullLength = (hullLength >> 1) * 2;
let lastX = vertices[hullLength - 2];
let lastY = vertices[hullLength - 1];
for (let i = 0, len = hullLength; i < len; i += 2) {
const x = vertices[i];
const y = vertices[i + 1];
debugDisplayObjects.meshHullLine.moveTo(x, y);
debugDisplayObjects.meshHullLine.lineTo(lastX, lastY);
lastX = x;
lastY = y;
}
}
}
}
drawClippingFunc(spine, debugDisplayObjects, lineWidth) {
const skeleton = spine.skeleton;
const slots = skeleton.slots;
debugDisplayObjects.clippingPolygon.lineStyle(lineWidth, this.clippingPolygonColor, 1);
for (let i = 0, len = slots.length; i < len; i++) {
const slot = slots[i];
if (!slot.bone.active) {
continue;
}
const attachment = slot.appliedPose.attachment;
if (attachment == null || !(attachment instanceof ClippingAttachment)) {
continue;
}
const clippingAttachment = attachment;
const nn = clippingAttachment.worldVerticesLength;
const world = new Float32Array(nn);
clippingAttachment.computeWorldVertices(skeleton, slot, 0, nn, world, 0, 2);
debugDisplayObjects.clippingPolygon.drawPolygon(Array.from(world));
}
}
drawBoundingBoxesFunc(spine, debugDisplayObjects, lineWidth) {
// draw the total outline of the bounding box
debugDisplayObjects.boundingBoxesRect.lineStyle(lineWidth, this.boundingBoxesRectColor, 5);
const bounds = new SkeletonBounds();
bounds.update(spine.skeleton, true);
if (bounds.minX !== Infinity) {
debugDisplayObjects.boundingBoxesRect.drawRect(bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight());
}
const polygons = bounds.polygons;
const drawPolygon = (polygonVertices, _offset, count) => {
debugDisplayObjects.boundingBoxesPolygon.lineStyle(lineWidth, this.boundingBoxesPolygonColor, 1);
debugDisplayObjects.boundingBoxesPolygon.beginFill(this.boundingBoxesPolygonColor, 0.1);
if (count < 3) {
throw new Error("Polygon must contain at least 3 vertices");
}
const paths = [];
const dotSize = lineWidth * 2;
for (let i = 0, len = polygonVertices.length; i < len; i += 2) {
const x1 = polygonVertices[i];
const y1 = polygonVertices[i + 1];
// draw the bounding box node
debugDisplayObjects.boundingBoxesCircle.lineStyle(0);
debugDisplayObjects.boundingBoxesCircle.beginFill(this.boundingBoxesCircleColor);
debugDisplayObjects.boundingBoxesCircle.drawCircle(x1, y1, dotSize);
debugDisplayObjects.boundingBoxesCircle.endFill();
paths.push(x1, y1);
}
// draw the bounding box area
debugDisplayObjects.boundingBoxesPolygon.drawPolygon(paths);
debugDisplayObjects.boundingBoxesPolygon.endFill();
};
for (let i = 0, len = polygons.length; i < len; i++) {
const polygon = polygons[i];
drawPolygon(polygon, 0, polygon.length);
}
}
drawPathsFunc(spine, debugDisplayObjects, lineWidth) {
const skeleton = spine.skeleton;
const slots = skeleton.slots;
debugDisplayObjects.pathsCurve.lineStyle(lineWidth, this.pathsCurveColor, 1);
debugDisplayObjects.pathsLine.lineStyle(lineWidth, this.pathsLineColor, 1);
for (let i = 0, len = slots.length; i < len; i++) {
const slot = slots[i];
if (!slot.bone.active) {
continue;
}
const attachment = slot.appliedPose.attachment;
if (attachment == null || !(attachment instanceof PathAttachment)) {
continue;
}
const pathAttachment = attachment;
let nn = pathAttachment.worldVerticesLength;
const world = new Float32Array(nn);
pathAttachment.computeWorldVertices(skeleton, slot, 0, nn, world, 0, 2);
let x1 = world[2];
let y1 = world[3];
let x2 = 0;
let y2 = 0;
if (pathAttachment.closed) {
const cx1 = world[0];
const cy1 = world[1];
const cx2 = world[nn - 2];
const cy2 = world[nn - 1];
x2 = world[nn - 4];
y2 = world[nn - 3];
// curve
debugDisplayObjects.pathsCurve.moveTo(x1, y1);
debugDisplayObjects.pathsCurve.bezierCurveTo(cx1, cy1, cx2, cy2, x2, y2);
// handle
debugDisplayObjects.pathsLine.moveTo(x1, y1);
debugDisplayObjects.pathsLine.lineTo(cx1, cy1);
debugDisplayObjects.pathsLine.moveTo(x2, y2);
debugDisplayObjects.pathsLine.lineTo(cx2, cy2);
}
nn -= 4;
for (let ii = 4; ii < nn; ii += 6) {
const cx1 = world[ii];
const cy1 = world[ii + 1];
const cx2 = world[ii + 2];
const cy2 = world[ii + 3];
x2 = world[ii + 4];
y2 = world[ii + 5];
// curve
debugDisplayObjects.pathsCurve.moveTo(x1, y1);
debugDisplayObjects.pathsCurve.bezierCurveTo(cx1, cy1, cx2, cy2, x2, y2);
// handle
debugDisplayObjects.pathsLine.moveTo(x1, y1);
debugDisplayObjects.pathsLine.lineTo(cx1, cy1);
debugDisplayObjects.pathsLine.moveTo(x2, y2);
debugDisplayObjects.pathsLine.lineTo(cx2, cy2);
x1 = x2;
y1 = y2;
}
}
}
unregisterSpine(spine) {
if (!this.registeredSpines.has(spine)) {
console.warn("SpineDebugRenderer.unregisterSpine() - spine is not registered, can't unregister!", spine);
}
const debugDisplayObjects = this.registeredSpines.get(spine);
if (!debugDisplayObjects) {
return;
}
spine.state.removeListener(debugDisplayObjects.eventCallback);
debugDisplayObjects.parentDebugContainer.destroy({ baseTexture: true, children: true, texture: true });
this.registeredSpines.delete(spine);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3BpbmVEZWJ1Z1JlbmRlcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NwaW5lRGVidWdSZW5kZXJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OytFQTJCK0U7QUFHL0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDcEksT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFlBQVksQ0FBQztBQXlDbEM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGtCQUFrQjtJQUN0QixnQkFBZ0IsR0FBb0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUUvRCxZQUFZLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUN6QixTQUFTLEdBQUcsSUFBSSxDQUFDO0lBQ2pCLFNBQVMsR0FBRyxJQUFJLENBQUM7SUFDakIsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO0lBQ3pCLFlBQVksR0FBRyxJQUFJLENBQUM7SUFDcEIscUJBQXFCLEdBQUcsSUFBSSxDQUFDO0lBQzdCLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFFbEIsU0FBUyxHQUFHLENBQUMsQ0FBQztJQUNkLHNCQUFzQixHQUFHLFFBQVEsQ0FBQztJQUNsQyxhQUFhLEdBQUcsUUFBUSxDQUFDO0lBQ3pCLGtCQUFrQixHQUFHLFFBQVEsQ0FBQztJQUM5QixvQkFBb0IsR0FBRyxRQUFRLENBQUM7SUFDaEMsc0JBQXNCLEdBQUcsUUFBUSxDQUFDO0lBQ2xDLHlCQUF5QixHQUFHLFFBQVEsQ0FBQztJQUNyQyx3QkFBd0IsR0FBRyxRQUFRLENBQUM7SUFDcEMsZUFBZSxHQUFH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QUUsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDN0MsbUJBQW1CLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQy9DLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUM3QyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDL0MsRUFBRSxHQUFHLEVBQUUsQ0FBQztnQkFDUixFQUFFLEdBQUcsRUFBRSxDQUFDO1lBQ1QsQ0FBQztRQUNGLENBQUM7SUFDRixDQUFDO0lBRU0sZUFBZSxDQUFFLEtBQVk7UUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN2QyxPQUFPLENBQUMsSUFBSSxDQUFDLG1GQUFtRixFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzFHLENBQUM7UUFDRCxNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFN0QsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDMUIsT0FBTztRQUNSLENBQUM7UUFFRCxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUU5RCxtQkFBbUIsQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDdkcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0NBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gKiBTcGluZSBSdW50aW1lcyBMaWNlbnNlIEFncmVlbWVudFxuICogTGFzdCB1cGRhdGVkIEFwcmlsIDUsIDIwMjUuIFJlcGxhY2VzIGFsbCBwcmlvciB2ZXJzaW9ucy5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMtMjAyNSwgRXNvdGVyaWMgU29mdHdhcmUgTExDXG4gKlxuICogSW50ZWdyYXRpb24gb2YgdGhlIFNwaW5lIFJ1bnRpbWVzIGludG8gc29mdHdhcmUgb3Igb3RoZXJ3aXNlIGNyZWF0aW5nXG4gKiBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyBpcyBwZXJtaXR0ZWQgdW5kZXIgdGhlIHRlcm1zIGFuZFxuICogY29uZGl0aW9ucyBvZiBTZWN0aW9uIDIgb2YgdGhlIFNwaW5lIEVkaXRvciBMaWNlbnNlIEFncmVlbWVudDpcbiAqIGh0dHA6Ly9lc290ZXJpY3NvZnR3YXJlLmNvbS9zcGluZS1lZGl0b3ItbGljZW5zZVxuICpcbiAqIE90aGVyd2lzZSwgaXQgaXMgcGVybWl0dGVkIHRvIGludGVncmF0ZSB0aGUgU3BpbmUgUnVudGltZXMgaW50byBzb2Z0d2FyZVxuICogb3Igb3RoZXJ3aXNlIGNyZWF0ZSBkZXJpdmF0aXZlIHdvcmtzIG9mIHRoZSBTcGluZSBSdW50aW1lcyAoY29sbGVjdGl2ZWx5LFxuICogXCJQcm9kdWN0c1wiKSwgcHJvdmlkZWQgdGhhdCBlYWNoIHVzZXIgb2YgdGhlIFByb2R1Y3RzIG11c3Qgb2J0YWluIHRoZWlyIG93blxuICogU3BpbmUgRWRpdG9yIGxpY2Vuc2UgYW5kIHJlZGlzdHJpYnV0aW9uIG9mIHRoZSBQcm9kdWN0cyBpbiBhbnkgZm9ybSBtdXN0XG4gKiBpbmNsdWRlIHRoaXMgbGljZW5zZSBhbmQgY29weXJpZ2h0IG5vdGljZS5cbiAqXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMgQVJFIFBST1ZJREVEIEJZIEVTT1RFUklDIFNPRlRXQVJFIExMQyBcIkFTIElTXCIgQU5EIEFOWVxuICogRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRFxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgRVNPVEVSSUMgU09GVFdBUkUgTExDIEJFIExJQUJMRSBGT1IgQU5ZXG4gKiBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFU1xuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTLFxuICogQlVTSU5FU1MgSU5URVJSVVBUSU9OLCBPUiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUykgSE9XRVZFUiBDQVVTRUQgQU5EXG4gKiBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVFxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GXG4gKiBUSEUgU1BJTkUgUlVOVElNRVMsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbmltcG9ydCB0eXBlIHsgQW5pbWF0aW9uU3RhdGVMaXN0ZW5lciB9IGZyb20gXCJAZXNvdGVyaWNzb2Z0d2FyZS9zcGluZS1jb3JlXCI7XG5pbXBvcnQgeyBDbGlwcGluZ0F0dGFjaG1lbnQsIE1lc2hBdHRhY2htZW50LCBQYXRoQXR0YWNobWVudCwgUmVnaW9uQXR0YWNobWVudCwgU2tlbGV0b25Cb3VuZHMgfSBmcm9tIFwiQGVzb3Rlcmljc29mdHdhcmUvc3BpbmUtY29yZVwiO1xuaW1wb3J0IHsgQ29udGFpbmVyIH0gZnJvbSBcIkBwaXhpL2Rpc3BsYXlcIjtcbmltcG9ydCB7IEdyYXBoaWNzIH0gZnJvbSBcIkBwaXhpL2dyYXBoaWNzXCI7XG5pbXBvcnQgeyBUZXh0IH0gZnJvbSBcIkBwaXhpL3RleHRcIjtcbmltcG9ydCB0eXBlIHsgU3BpbmUgfSBmcm9tIFwiLi9TcGluZS5qc1wiO1xuXG4vKipcbiAqIE1ha2UgYSBjbGFzcyB0aGF0IGV4dGVuZHMgZnJvbSB0aGlzIGludGVyZmFjZSB0byBjcmVhdGUgeW91ciBvd24gZGVidWcgcmVuZGVyZXIuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSVNwaW5lRGVidWdSZW5kZXJlciB7XG5cdC8qKlxuXHQgKiBUaGlzIHdpbGwgYmUgY2FsbGVkIGV2ZXJ5IGZyYW1lLCBhZnRlciB0aGUgc3BpbmUgaGFzIGJlZW4gdXBkYXRlZC5cblx0ICovXG5cdHJlbmRlckRlYnVnIChzcGluZTogU3BpbmUpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiAgVGhpcyBpcyBjYWxsZWQgd2hlbiB0aGUgYHNwaW5lLmRlYnVnYCBvYmplY3QgaXMgc2V0IHRvIG51bGwgb3Igd2hlbiB0aGUgc3BpbmUgaXMgZGVzdHJveWVkLlxuXHQgKi9cblx0dW5yZWdpc3RlclNwaW5lIChzcGluZTogU3BpbmUpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBUaGlzIGlzIGNhbGxlZCB3aGVuIHRoZSBgc3BpbmUuZGVidWdgIG9iamVjdCBpcyBzZXQgdG8gYSBuZXcgaW5zdGFuY2Ugb2YgYSBkZWJ1ZyByZW5kZXJlci5cblx0ICovXG5cdHJlZ2lzdGVyU3BpbmUgKHNwaW5lOiBTcGluZSk6IHZvaWQ7XG59XG5cbnR5cGUgRGVidWdEaXNwbGF5T2JqZWN0cyA9IHtcblx0Ym9uZXM6IENvbnRhaW5lcjtcblx0c2tlbGV0b25YWTogR3JhcGhpY3M7XG5cdHJlZ2lvbkF0dGFjaG1lbnRzU2hhcGU6IEdyYXBoaWNzO1xuXHRtZXNoVHJpYW5nbGVzTGluZTogR3JhcGhpY3M7XG5cdG1lc2hIdWxsTGluZTogR3JhcGhpY3M7XG5cdGNsaXBwaW5nUG9seWdvbjogR3JhcGhpY3M7XG5cdGJvdW5kaW5nQm94ZXNSZWN0OiBHcmFwaGljcztcblx0Ym91bmRpbmdCb3hlc0NpcmNsZTogR3JhcGhpY3M7XG5cdGJvdW5kaW5nQm94ZXNQb2x5Z29uOiBHcmFwaGljcztcblx0cGF0aHNDdXJ2ZTogR3JhcGhpY3M7XG5cdHBhdGhzTGluZTogR3JhcGhpY3M7XG5cdHBhcmVudERlYnVnQ29udGFpbmVyOiBDb250YWluZXI7XG5cdGV2ZW50VGV4dDogQ29udGFpbmVyO1xuXHRldmVudENhbGxiYWNrOiBBbmltYXRpb25TdGF0ZUxpc3RlbmVyO1xufTtcblxuLyoqXG4gKiBUaGlzIGlzIGEgZGVidWcgcmVuZGVyZXIgdGhhdCB1c2VzIFBpeGlKUyBHcmFwaGljcyB1bmRlciB0aGUgaG9vZC5cbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNsYXNzIFNwaW5lRGVidWdSZW5kZXJlciBpbXBsZW1lbnRzIElTcGluZURlYnVnUmVuZGVyZXIge1xuXHRwcml2YXRlIHJlZ2lzdGVyZWRTcGluZXM6IE1hcDxTcGluZSwgRGVidWdEaXNwbGF5T2JqZWN0cz4gPSBuZXcgTWFwKCk7XG5cblx0cHVibGljIGRyYXdNZXNoSHVsbCA9IHRydWU7XG5cdHB1YmxpYyBkcmF3TWVzaFRyaWFuZ2xlcyA9IHRydWU7XG5cdHB1YmxpYyBkcmF3Qm9uZXMgPSB0cnVlO1xuXHRwdWJsaWMgZHJhd1BhdGhzID0gdHJ1ZTtcblx0cHVibGljIGRyYXdCb3VuZGluZ0JveGVzID0gdHJ1ZTtcblx0cHVibGljIGRyYXdDbGlwcGluZyA9IHRydWU7XG5cdHB1YmxpYyBkcmF3UmVnaW9uQXR0YWNobWVudHMgPSB0cnVlO1xuXHRwdWJsaWMgZHJhd0V2ZW50cyA9IHRydWU7XG5cblx0cHVibGljIGxpbmVXaWR0aCA9IDE7XG5cdHB1YmxpYyByZWdpb25BdHRhY2htZW50c0NvbG9yID0gMHgwMDc4ZmY7XG5cdHB1YmxpYyBtZXNoSHVsbENvbG9yID0gMHgwMDc4ZmY7XG5cdHB1YmxpYyBtZXNoVHJpYW5nbGVzQ29sb3IgPSAweGZmY2MwMDtcblx0cHVibGljIGNsaXBwaW5nUG9seWdvbkNvbG9yID0gMHhmZjAwZmY7XG5cdHB1YmxpYyBib3VuZGluZ0JveGVzUmVjdENvbG9yID0gMHgwMGZmMDA7XG5cdHB1YmxpYyBib3VuZGluZ0JveGVzUG9seWdvbkNvbG9yID0gMHgwMGZmMDA7XG5cdHB1YmxpYyBib3VuZGluZ0JveGVzQ2lyY2xlQ29sb3IgPSAweDAwZmYwMDtcblx0cHVibGljIHBhdGhzQ3VydmVDb2xvciA9IDB4ZmYwMDAwO1xuXHRwdWJsaWMgcGF0aHNMaW5lQ29sb3IgPSAweGZmMDBmZjtcblx0cHVibGljIHNrZWxldG9uWFlDb2xvciA9IDB4ZmYwMDAwO1xuXHRwdWJsaWMgYm9uZXNDb2xvciA9IDB4MDBlZWNjO1xuXHRwdWJsaWMgZXZlbnRGb250U2l6ZTogbnVtYmVyID0gMjQ7XG5cdHB1YmxpYyBldmVudEZvbnRDb2xvcjogbnVtYmVyID0gMHgwO1xuXG5cdC8qKlxuXHQgKiBUaGUgZGVidWcgaXMgYXR0YWNoZWQgYnkgZm9yY2UgdG8gZWFjaCBzcGluZSBvYmplY3QuIFNvIHdlIG5lZWQgdG8gY3JlYXRlIGl0IGluc2lkZSB0aGUgc3BpbmUgd2hlbiB3ZSBnZXQgdGhlIGZpcnN0IHVwZGF0ZVxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVyU3BpbmUgKHNwaW5lOiBTcGluZSk6IHZvaWQge1xuXHRcdGlmICh0aGlzLnJlZ2lzdGVyZWRTcGluZXMuaGFzKHNwaW5lKSkge1xuXHRcdFx0Y29uc29sZS53YXJuKFwiU3BpbmVEZWJ1Z1JlbmRlcmVyLnJlZ2lzdGVyU3BpbmUoKSAtIHRoaXMgc3BpbmUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIVwiLCBzcGluZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGNvbnN0IGRlYnVnRGlzcGxheU9iamVjdHM6IERlYnVnRGlzcGxheU9iamVjdHMgPSB7XG5cdFx0XHRwYXJlbnREZWJ1Z0NvbnRhaW5lcjogbmV3IENvbnRhaW5lcigpLFxuXHRcdFx0Ym9uZXM6IG5ldyBDb250YWluZXIoKSxcblx0XHRcdHNrZWxldG9uWFk6IG5ldyBHcmFwaGljcygpLFxuXHRcdFx0cmVnaW9uQXR0YWNobWVudHNTaGFwZTogbmV3IEdyYXBoaWNzKCksXG5cdFx0XHRtZXNoVHJpYW5nbGVzTGluZTogbmV3IEdyYXBoaWNzKCksXG5cdFx0XHRtZXNoSHVsbExpbmU6IG5ldyBHcmFwaGljcygpLFxuXHRcdFx0Y2xpcHBpbmdQb2x5Z29uOiBuZXcgR3JhcGhpY3MoKSxcblx0XHRcdGJvdW5kaW5nQm94ZXNSZWN0OiBuZXcgR3JhcGhpY3MoKSxcblx0XHRcdGJvdW5kaW5nQm94ZXNDaXJjbGU6IG5ldyBHcmFwaGljcygpLFxuXHRcdFx0Ym91bmRpbmdCb3hlc1BvbHlnb246IG5ldyBHcmFwaGljcygpLFxuXHRcdFx0cGF0aHNDdXJ2ZTogbmV3IEdyYXBoaWNzKCksXG5cdFx0XHRwYXRoc0xpbmU6IG5ldyBHcmFwaGljcygpLFxuXHRcdFx0ZXZlbnRUZXh0OiBuZXcgQ29udGFpbmVyKCksXG5cdFx0XHRldmVudENhbGxiYWNrOiB7XG5cdFx0XHRcdGV2ZW50OiAoXywgZXZlbnQpID0+IHtcblx0XHRcdFx0XHRpZiAodGhpcy5kcmF3RXZlbnRzKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBzY2FsZSA9IE1hdGguYWJzKHNwaW5lLnNjYWxlLnggfHwgc3BpbmUuc2NhbGUueSB8fCAxKTtcblx0XHRcdFx0XHRcdGNvbnN0IHRleHQgPSBuZXcgVGV4dChldmVudC5kYXRhLm5hbWUsIHsgZm9udFNpemU6IHRoaXMuZXZlbnRGb250U2l6ZSAvIHNjYWxlLCBmaWxsOiB0aGlzLmV2ZW50Rm9udENvbG9yLCBmb250RmFtaWx5OiBcIm1vbm9zcGFjZVwiIH0pO1xuXHRcdFx0XHRcdFx0dGV4dC5zY2FsZS54ID0gTWF0aC5zaWduKHNwaW5lLnNjYWxlLngpO1xuXHRcdFx0XHRcdFx0dGV4dC5hbmNob3Iuc2V0KDAuNSk7XG5cdFx0XHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmV2ZW50VGV4dC5hZGRDaGlsZCh0ZXh0KTtcblx0XHRcdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAoIXRleHQuZGVzdHJveWVkKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGV4dC5kZXN0cm95KCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0sIDI1MCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0fSxcblx0XHR9O1xuXG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvbmVzKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhcmVudERlYnVnQ29udGFpbmVyLmFkZENoaWxkKGRlYnVnRGlzcGxheU9iamVjdHMuc2tlbGV0b25YWSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLnJlZ2lvbkF0dGFjaG1lbnRzU2hhcGUpO1xuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGFyZW50RGVidWdDb250YWluZXIuYWRkQ2hpbGQoZGVidWdEaXNwbGF5T2JqZWN0cy5tZXNoVHJpYW5nbGVzTGluZSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLm1lc2hIdWxsTGluZSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLmNsaXBwaW5nUG9seWdvbik7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvdW5kaW5nQm94ZXNSZWN0KTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhcmVudERlYnVnQ29udGFpbmVyLmFkZENoaWxkKGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc0NpcmNsZSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvdW5kaW5nQm94ZXNQb2x5Z29uKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhcmVudERlYnVnQ29udGFpbmVyLmFkZENoaWxkKGRlYnVnRGlzcGxheU9iamVjdHMucGF0aHNDdXJ2ZSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzTGluZSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lci5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLmV2ZW50VGV4dCk7XG5cblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhcmVudERlYnVnQ29udGFpbmVyLnpJbmRleCA9IDk5OTk5OTk7XG5cblx0XHQvLyBEaXNhYmxlIHNjcmVlbiByZWFkZXIgYW5kIG1vdXNlIGlucHV0IG9uIGRlYnVnIG9iamVjdHMuXG5cdFx0Ly8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0V4cGxpY2l0QW55OiB0aGlzIHByb3AgaXMgYXZhaWxhYmxlIGluIGxhdGVyIHZlcnNpb25zXG5cdFx0KGRlYnVnRGlzcGxheU9iamVjdHMucGFyZW50RGVidWdDb250YWluZXIgYXMgYW55KS5hY2Nlc3NpYmxlQ2hpbGRyZW4gPSBmYWxzZTtcblx0XHQoZGVidWdEaXNwbGF5T2JqZWN0cy5wYXJlbnREZWJ1Z0NvbnRhaW5lcikuZXZlbnRNb2RlID0gXCJub25lXCI7XG5cdFx0KGRlYnVnRGlzcGxheU9iamVjdHMucGFyZW50RGVidWdDb250YWluZXIpLmludGVyYWN0aXZlQ2hpbGRyZW4gPSBmYWxzZTtcblxuXHRcdHNwaW5lLmFkZENoaWxkKGRlYnVnRGlzcGxheU9iamVjdHMucGFyZW50RGVidWdDb250YWluZXIpO1xuXG5cdFx0c3BpbmUuc3RhdGUuYWRkTGlzdGVuZXIoZGVidWdEaXNwbGF5T2JqZWN0cy5ldmVudENhbGxiYWNrKTtcblxuXHRcdHRoaXMucmVnaXN0ZXJlZFNwaW5lcy5zZXQoc3BpbmUsIGRlYnVnRGlzcGxheU9iamVjdHMpO1xuXHR9XG5cdHB1YmxpYyByZW5kZXJEZWJ1ZyAoc3BpbmU6IFNwaW5lKTogdm9pZCB7XG5cdFx0aWYgKCF0aGlzLnJlZ2lzdGVyZWRTcGluZXMuaGFzKHNwaW5lKSkge1xuXHRcdFx0Ly8gVGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLiBTcGluZXMgYXJlIHJlZ2lzdGVyZWQgd2hlbiB5b3UgYXNzaWduIHNwaW5lLmRlYnVnXG5cdFx0XHR0aGlzLnJlZ2lzdGVyU3BpbmUoc3BpbmUpO1xuXHRcdH1cblxuXHRcdGNvbnN0IGRlYnVnRGlzcGxheU9iamVjdHMgPSB0aGlzLnJlZ2lzdGVyZWRTcGluZXMuZ2V0KHNwaW5lKTtcblxuXHRcdGlmICghZGVidWdEaXNwbGF5T2JqZWN0cykge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRzcGluZS5hZGRDaGlsZChkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhcmVudERlYnVnQ29udGFpbmVyKTtcblxuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMuc2tlbGV0b25YWS5jbGVhcigpO1xuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMucmVnaW9uQXR0YWNobWVudHNTaGFwZS5jbGVhcigpO1xuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMubWVzaFRyaWFuZ2xlc0xpbmUuY2xlYXIoKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLm1lc2hIdWxsTGluZS5jbGVhcigpO1xuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMuY2xpcHBpbmdQb2x5Z29uLmNsZWFyKCk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5ib3VuZGluZ0JveGVzUmVjdC5jbGVhcigpO1xuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc0NpcmNsZS5jbGVhcigpO1xuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc1BvbHlnb24uY2xlYXIoKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzQ3VydmUuY2xlYXIoKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzTGluZS5jbGVhcigpO1xuXG5cdFx0Zm9yIChsZXQgbGVuID0gZGVidWdEaXNwbGF5T2JqZWN0cy5ib25lcy5jaGlsZHJlbi5sZW5ndGg7IGxlbiA+IDA7IGxlbi0tKSB7XG5cdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvbmVzLmNoaWxkcmVuW2xlbiAtIDFdLmRlc3Ryb3koeyBjaGlsZHJlbjogdHJ1ZSwgdGV4dHVyZTogdHJ1ZSwgYmFzZVRleHR1cmU6IHRydWUgfSk7XG5cdFx0fVxuXG5cdFx0Y29uc3Qgc2NhbGUgPSBNYXRoLmFicyhzcGluZS5zY2FsZS54IHx8IHNwaW5lLnNjYWxlLnkgfHwgMSk7XG5cdFx0Y29uc3QgbGluZVdpZHRoID0gdGhpcy5saW5lV2lkdGggLyBzY2FsZTtcblxuXHRcdGlmICh0aGlzLmRyYXdCb25lcykge1xuXHRcdFx0dGhpcy5kcmF3Qm9uZXNGdW5jKHNwaW5lLCBkZWJ1Z0Rpc3BsYXlPYmplY3RzLCBsaW5lV2lkdGgsIHNjYWxlKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kcmF3UGF0aHMpIHtcblx0XHRcdHRoaXMuZHJhd1BhdGhzRnVuYyhzcGluZSwgZGVidWdEaXNwbGF5T2JqZWN0cywgbGluZVdpZHRoKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kcmF3Qm91bmRpbmdCb3hlcykge1xuXHRcdFx0dGhpcy5kcmF3Qm91bmRpbmdCb3hlc0Z1bmMoc3BpbmUsIGRlYnVnRGlzcGxheU9iamVjdHMsIGxpbmVXaWR0aCk7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuZHJhd0NsaXBwaW5nKSB7XG5cdFx0XHR0aGlzLmRyYXdDbGlwcGluZ0Z1bmMoc3BpbmUsIGRlYnVnRGlzcGxheU9iamVjdHMsIGxpbmVXaWR0aCk7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuZHJhd01lc2hIdWxsIHx8IHRoaXMuZHJhd01lc2hUcmlhbmdsZXMpIHtcblx0XHRcdHRoaXMuZHJhd01lc2hIdWxsQW5kTWVzaFRyaWFuZ2xlcyhzcGluZSwgZGVidWdEaXNwbGF5T2JqZWN0cywgbGluZVdpZHRoKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kcmF3UmVnaW9uQXR0YWNobWVudHMpIHtcblx0XHRcdHRoaXMuZHJhd1JlZ2lvbkF0dGFjaG1lbnRzRnVuYyhzcGluZSwgZGVidWdEaXNwbGF5T2JqZWN0cywgbGluZVdpZHRoKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5kcmF3RXZlbnRzKSB7XG5cdFx0XHRmb3IgKGNvbnN0IGNoaWxkIG9mIGRlYnVnRGlzcGxheU9iamVjdHMuZXZlbnRUZXh0LmNoaWxkcmVuKSB7XG5cdFx0XHRcdGNoaWxkLmFscGhhIC09IDAuMDU7XG5cdFx0XHRcdGNoaWxkLnkgLT0gMjtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGRyYXdCb25lc0Z1bmMgKHNwaW5lOiBTcGluZSwgZGVidWdEaXNwbGF5T2JqZWN0czogRGVidWdEaXNwbGF5T2JqZWN0cywgbGluZVdpZHRoOiBudW1iZXIsIHNjYWxlOiBudW1iZXIpOiB2b2lkIHtcblx0XHRjb25zdCBza2VsZXRvbiA9IHNwaW5lLnNrZWxldG9uO1xuXHRcdGNvbnN0IHNrZWxldG9uWCA9IHNrZWxldG9uLng7XG5cdFx0Y29uc3Qgc2tlbGV0b25ZID0gc2tlbGV0b24ueTtcblx0XHRjb25zdCBib25lcyA9IHNrZWxldG9uLmJvbmVzO1xuXG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5za2VsZXRvblhZLmxpbmVTdHlsZShsaW5lV2lkdGgsIHRoaXMuc2tlbGV0b25YWUNvbG9yLCAxKTtcblxuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSBib25lcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0Y29uc3QgYm9uZSA9IGJvbmVzW2ldO1xuXHRcdFx0Y29uc3QgYm9uZUxlbiA9IGJvbmUuZGF0YS5sZW5ndGg7XG5cdFx0XHRjb25zdCBhcHBsaWVkID0gYm9uZS5hcHBsaWVkUG9zZTtcblx0XHRcdGNvbnN0IHN0YXJYID0gc2tlbGV0b25YICsgYXBwbGllZC53b3JsZFg7XG5cdFx0XHRjb25zdCBzdGFyWSA9IHNrZWxldG9uWSArIGFwcGxpZWQud29ybGRZO1xuXHRcdFx0Y29uc3QgZW5kWCA9IHNrZWxldG9uWCArIGJvbmVMZW4gKiBhcHBsaWVkLmEgKyBhcHBsaWVkLndvcmxkWDtcblx0XHRcdGNvbnN0IGVuZFkgPSBza2VsZXRvblkgKyBib25lTGVuICogYXBwbGllZC5iICsgYXBwbGllZC53b3JsZFk7XG5cblx0XHRcdGlmIChib25lLmRhdGEubmFtZSA9PT0gXCJyb290XCIgfHwgYm9uZS5kYXRhLnBhcmVudCA9PT0gbnVsbCkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgdyA9IE1hdGguYWJzKHN0YXJYIC0gZW5kWCk7XG5cdFx0XHRjb25zdCBoID0gTWF0aC5hYnMoc3RhclkgLSBlbmRZKTtcblx0XHRcdC8vIGEgPSB3LCAvLyBzaWRlIGxlbmd0aCBhXG5cdFx0XHRjb25zdCBhMiA9IE1hdGgucG93KHcsIDIpOyAvLyBzcXVhcmUgcm9vdCBvZiBzaWRlIGxlbmd0aCBhXG5cdFx0XHRjb25zdCBiID0gaDsgLy8gc2lkZSBsZW5ndGggYlxuXHRcdFx0Y29uc3QgYjIgPSBNYXRoLnBvdyhoLCAyKTsgLy8gc3F1YXJlIHJvb3Qgb2Ygc2lkZSBsZW5ndGggYlxuXHRcdFx0Y29uc3QgYyA9IE1hdGguc3FydChhMiArIGIyKTsgLy8gc2lkZSBsZW5ndGggY1xuXHRcdFx0Y29uc3QgYzIgPSBNYXRoLnBvdyhjLCAyKTsgLy8gc3F1YXJlIHJvb3Qgb2Ygc2lkZSBsZW5ndGggY1xuXHRcdFx0Y29uc3QgcmFkID0gTWF0aC5QSSAvIDE4MDtcblx0XHRcdC8vIEEgPSBNYXRoLmFjb3MoW2EyICsgYzIgLSBiMl0gLyBbMiAqIGEgKiBjXSkgfHwgMCwgLy8gQW5nbGUgQVxuXHRcdFx0Ly8gQyA9IE1hdGguYWNvcyhbYTIgKyBiMiAtIGMyXSAvIFsyICogYSAqIGJdKSB8fCAwLCAvLyBDIGFuZ2xlXG5cdFx0XHRjb25zdCBCID0gTWF0aC5hY29zKChjMiArIGIyIC0gYTIpIC8gKDIgKiBiICogYykpIHx8IDA7IC8vIGFuZ2xlIG9mIGNvcm5lciBCXG5cblx0XHRcdGlmIChjID09PSAwKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBncCA9IG5ldyBHcmFwaGljcygpO1xuXG5cdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvbmVzLmFkZENoaWxkKGdwKTtcblxuXHRcdFx0Ly8gZHJhdyBib25lXG5cdFx0XHRjb25zdCByZWZSYXRpb24gPSBjIC8gNTAgLyBzY2FsZTtcblxuXHRcdFx0Z3AuYmVnaW5GaWxsKHRoaXMuYm9uZXNDb2xvciwgMSk7XG5cdFx0XHRncC5kcmF3UG9seWdvbigwLCAwLCAwIC0gcmVmUmF0aW9uLCBjIC0gcmVmUmF0aW9uICogMywgMCwgYyAtIHJlZlJhdGlvbiwgMCArIHJlZlJhdGlvbiwgYyAtIHJlZlJhdGlvbiAqIDMpO1xuXHRcdFx0Z3AuZW5kRmlsbCgpO1xuXHRcdFx0Z3AueCA9IHN0YXJYO1xuXHRcdFx0Z3AueSA9IHN0YXJZO1xuXHRcdFx0Z3AucGl2b3QueSA9IGM7XG5cblx0XHRcdC8vIENhbGN1bGF0ZSBib25lIHJvdGF0aW9uIGFuZ2xlXG5cdFx0XHRsZXQgcm90YXRpb24gPSAwO1xuXG5cdFx0XHRpZiAoc3RhclggPCBlbmRYICYmIHN0YXJZIDwgZW5kWSkge1xuXHRcdFx0XHQvLyBib3R0b20gcmlnaHRcblx0XHRcdFx0cm90YXRpb24gPSAtQiArIDE4MCAqIHJhZDtcblx0XHRcdH0gZWxzZSBpZiAoc3RhclggPiBlbmRYICYmIHN0YXJZIDwgZW5kWSkge1xuXHRcdFx0XHQvLyBib3R0b20gbGVmdFxuXHRcdFx0XHRyb3RhdGlvbiA9IDE4MCAqIHJhZCArIEI7XG5cdFx0XHR9IGVsc2UgaWYgKHN0YXJYID4gZW5kWCAmJiBzdGFyWSA+IGVuZFkpIHtcblx0XHRcdFx0Ly8gdG9wIGxlZnRcblx0XHRcdFx0cm90YXRpb24gPSAtQjtcblx0XHRcdH0gZWxzZSBpZiAoc3RhclggPCBlbmRYICYmIHN0YXJZID4gZW5kWSkge1xuXHRcdFx0XHQvLyBib3R0b20gbGVmdFxuXHRcdFx0XHRyb3RhdGlvbiA9IEI7XG5cdFx0XHR9IGVsc2UgaWYgKHN0YXJZID09PSBlbmRZICYmIHN0YXJYIDwgZW5kWCkge1xuXHRcdFx0XHQvLyBUbyB0aGUgcmlnaHRcblx0XHRcdFx0cm90YXRpb24gPSA5MCAqIHJhZDtcblx0XHRcdH0gZWxzZSBpZiAoc3RhclkgPT09IGVuZFkgJiYgc3RhclggPiBlbmRYKSB7XG5cdFx0XHRcdC8vIGdvIGxlZnRcblx0XHRcdFx0cm90YXRpb24gPSAtOTAgKiByYWQ7XG5cdFx0XHR9IGVsc2UgaWYgKHN0YXJYID09PSBlbmRYICYmIHN0YXJZIDwgZW5kWSkge1xuXHRcdFx0XHQvLyBkb3duXG5cdFx0XHRcdHJvdGF0aW9uID0gMTgwICogcmFkO1xuXHRcdFx0fSBlbHNlIGlmIChzdGFyWCA9PT0gZW5kWCAmJiBzdGFyWSA+IGVuZFkpIHtcblx0XHRcdFx0Ly8gdXBcblx0XHRcdFx0cm90YXRpb24gPSAwO1xuXHRcdFx0fVxuXHRcdFx0Z3Aucm90YXRpb24gPSByb3RhdGlvbjtcblxuXHRcdFx0Ly8gRHJhdyB0aGUgc3RhcnRpbmcgcm90YXRpb24gcG9pbnQgb2YgdGhlIGJvbmVcblx0XHRcdGdwLmxpbmVTdHlsZShsaW5lV2lkdGggKyByZWZSYXRpb24gLyAyLjQsIHRoaXMuYm9uZXNDb2xvciwgMSk7XG5cdFx0XHRncC5iZWdpbkZpbGwoMHgwMDAwMDAsIDAuNik7XG5cdFx0XHRncC5kcmF3Q2lyY2xlKDAsIGMsIHJlZlJhdGlvbiAqIDEuMik7XG5cdFx0XHRncC5lbmRGaWxsKCk7XG5cdFx0fVxuXG5cdFx0Ly8gRHJhdyB0aGUgc2tlbGV0b24gc3RhcnRpbmcgcG9pbnQgXCJYXCIgZm9ybVxuXHRcdGNvbnN0IHN0YXJ0RG90U2l6ZSA9IGxpbmVXaWR0aCAqIDM7XG5cblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnNrZWxldG9uWFkubW92ZVRvKHNrZWxldG9uWCAtIHN0YXJ0RG90U2l6ZSwgc2tlbGV0b25ZIC0gc3RhcnREb3RTaXplKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnNrZWxldG9uWFkubGluZVRvKHNrZWxldG9uWCArIHN0YXJ0RG90U2l6ZSwgc2tlbGV0b25ZICsgc3RhcnREb3RTaXplKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnNrZWxldG9uWFkubW92ZVRvKHNrZWxldG9uWCArIHN0YXJ0RG90U2l6ZSwgc2tlbGV0b25ZIC0gc3RhcnREb3RTaXplKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnNrZWxldG9uWFkubGluZVRvKHNrZWxldG9uWCAtIHN0YXJ0RG90U2l6ZSwgc2tlbGV0b25ZICsgc3RhcnREb3RTaXplKTtcblx0fVxuXG5cdHByaXZhdGUgZHJhd1JlZ2lvbkF0dGFjaG1lbnRzRnVuYyAoc3BpbmU6IFNwaW5lLCBkZWJ1Z0Rpc3BsYXlPYmplY3RzOiBEZWJ1Z0Rpc3BsYXlPYmplY3RzLCBsaW5lV2lkdGg6IG51bWJlcik6IHZvaWQge1xuXHRcdGNvbnN0IHNrZWxldG9uID0gc3BpbmUuc2tlbGV0b247XG5cdFx0Y29uc3Qgc2xvdHMgPSBza2VsZXRvbi5zbG90cztcblxuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMucmVnaW9uQXR0YWNobWVudHNTaGFwZS5saW5lU3R5bGUobGluZVdpZHRoLCB0aGlzLnJlZ2lvbkF0dGFjaG1lbnRzQ29sb3IsIDEpO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDAsIGxlbiA9IHNsb3RzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBzbG90ID0gc2xvdHNbaV07XG5cdFx0XHRjb25zdCBhdHRhY2htZW50ID0gc2xvdC5hcHBsaWVkUG9zZS5hdHRhY2htZW50O1xuXG5cdFx0XHRpZiAoYXR0YWNobWVudCA9PSBudWxsIHx8ICEoYXR0YWNobWVudCBpbnN0YW5jZW9mIFJlZ2lvbkF0dGFjaG1lbnQpKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCB2ZXJ0aWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkoOCk7XG5cblx0XHRcdGF0dGFjaG1lbnQuY29tcHV0ZVdvcmxkVmVydGljZXMoc2xvdCwgYXR0YWNobWVudC5nZXRPZmZzZXRzKHNsb3QuYXBwbGllZFBvc2UpLCB2ZXJ0aWNlcywgMCwgMik7XG5cdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnJlZ2lvbkF0dGFjaG1lbnRzU2hhcGUuZHJhd1BvbHlnb24oQXJyYXkuZnJvbSh2ZXJ0aWNlcy5zbGljZSgwLCA4KSkpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgZHJhd01lc2hIdWxsQW5kTWVzaFRyaWFuZ2xlcyAoc3BpbmU6IFNwaW5lLCBkZWJ1Z0Rpc3BsYXlPYmplY3RzOiBEZWJ1Z0Rpc3BsYXlPYmplY3RzLCBsaW5lV2lkdGg6IG51bWJlcik6IHZvaWQge1xuXHRcdGNvbnN0IHNrZWxldG9uID0gc3BpbmUuc2tlbGV0b247XG5cdFx0Y29uc3Qgc2xvdHMgPSBza2VsZXRvbi5zbG90cztcblxuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMubWVzaEh1bGxMaW5lLmxpbmVTdHlsZShsaW5lV2lkdGgsIHRoaXMubWVzaEh1bGxDb2xvciwgMSk7XG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5tZXNoVHJpYW5nbGVzTGluZS5saW5lU3R5bGUobGluZVdpZHRoLCB0aGlzLm1lc2hUcmlhbmdsZXNDb2xvciwgMSk7XG5cblx0XHRmb3IgKGxldCBpID0gMCwgbGVuID0gc2xvdHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGNvbnN0IHNsb3QgPSBzbG90c1tpXTtcblxuXHRcdFx0aWYgKCFzbG90LmJvbmUuYWN0aXZlKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgYXR0YWNobWVudCA9IHNsb3QuYXBwbGllZFBvc2UuYXR0YWNobWVudDtcblxuXHRcdFx0aWYgKGF0dGFjaG1lbnQgPT0gbnVsbCB8fCAhKGF0dGFjaG1lbnQgaW5zdGFuY2VvZiBNZXNoQXR0YWNobWVudCkpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IG1lc2hBdHRhY2htZW50ID0gYXR0YWNobWVudDtcblxuXHRcdFx0Y29uc3QgdmVydGljZXMgPSBuZXcgRmxvYXQzMkFycmF5KG1lc2hBdHRhY2htZW50LndvcmxkVmVydGljZXNMZW5ndGgpO1xuXHRcdFx0Y29uc3QgdHJpYW5nbGVzID0gbWVzaEF0dGFjaG1lbnQudHJpYW5nbGVzO1xuXHRcdFx0bGV0IGh1bGxMZW5ndGggPSBtZXNoQXR0YWNobWVudC5odWxsTGVuZ3RoO1xuXG5cdFx0XHRtZXNoQXR0YWNobWVudC5jb21wdXRlV29ybGRWZXJ0aWNlcyhza2VsZXRvbiwgc2xvdCwgMCwgbWVzaEF0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aCwgdmVydGljZXMsIDAsIDIpO1xuXHRcdFx0Ly8gZHJhdyB0aGUgc2tpbm5lZCBtZXNoICh0cmlhbmdsZSlcblx0XHRcdGlmICh0aGlzLmRyYXdNZXNoVHJpYW5nbGVzKSB7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB0cmlhbmdsZXMubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDMpIHtcblx0XHRcdFx0XHRjb25zdCB2MSA9IHRyaWFuZ2xlc1tpXSAqIDI7XG5cdFx0XHRcdFx0Y29uc3QgdjIgPSB0cmlhbmdsZXNbaSArIDFdICogMjtcblx0XHRcdFx0XHRjb25zdCB2MyA9IHRyaWFuZ2xlc1tpICsgMl0gKiAyO1xuXG5cdFx0XHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5tZXNoVHJpYW5nbGVzTGluZS5tb3ZlVG8odmVydGljZXNbdjFdLCB2ZXJ0aWNlc1t2MSArIDFdKTtcblx0XHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLm1lc2hUcmlhbmdsZXNMaW5lLmxpbmVUbyh2ZXJ0aWNlc1t2Ml0sIHZlcnRpY2VzW3YyICsgMV0pO1xuXHRcdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMubWVzaFRyaWFuZ2xlc0xpbmUubGluZVRvKHZlcnRpY2VzW3YzXSwgdmVydGljZXNbdjMgKyAxXSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gZHJhdyBza2luIGJvcmRlclxuXHRcdFx0aWYgKHRoaXMuZHJhd01lc2hIdWxsICYmIGh1bGxMZW5ndGggPiAwKSB7XG5cdFx0XHRcdGh1bGxMZW5ndGggPSAoaHVsbExlbmd0aCA+PiAxKSAqIDI7XG5cdFx0XHRcdGxldCBsYXN0WCA9IHZlcnRpY2VzW2h1bGxMZW5ndGggLSAyXTtcblx0XHRcdFx0bGV0IGxhc3RZID0gdmVydGljZXNbaHVsbExlbmd0aCAtIDFdO1xuXG5cdFx0XHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSBodWxsTGVuZ3RoOyBpIDwgbGVuOyBpICs9IDIpIHtcblx0XHRcdFx0XHRjb25zdCB4ID0gdmVydGljZXNbaV07XG5cdFx0XHRcdFx0Y29uc3QgeSA9IHZlcnRpY2VzW2kgKyAxXTtcblxuXHRcdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMubWVzaEh1bGxMaW5lLm1vdmVUbyh4LCB5KTtcblx0XHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLm1lc2hIdWxsTGluZS5saW5lVG8obGFzdFgsIGxhc3RZKTtcblx0XHRcdFx0XHRsYXN0WCA9IHg7XG5cdFx0XHRcdFx0bGFzdFkgPSB5O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBkcmF3Q2xpcHBpbmdGdW5jIChzcGluZTogU3BpbmUsIGRlYnVnRGlzcGxheU9iamVjdHM6IERlYnVnRGlzcGxheU9iamVjdHMsIGxpbmVXaWR0aDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Y29uc3Qgc2tlbGV0b24gPSBzcGluZS5za2VsZXRvbjtcblx0XHRjb25zdCBzbG90cyA9IHNrZWxldG9uLnNsb3RzO1xuXG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5jbGlwcGluZ1BvbHlnb24ubGluZVN0eWxlKGxpbmVXaWR0aCwgdGhpcy5jbGlwcGluZ1BvbHlnb25Db2xvciwgMSk7XG5cdFx0Zm9yIChsZXQgaSA9IDAsIGxlbiA9IHNsb3RzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRjb25zdCBzbG90ID0gc2xvdHNbaV07XG5cblx0XHRcdGlmICghc2xvdC5ib25lLmFjdGl2ZSkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IGF0dGFjaG1lbnQgPSBzbG90LmFwcGxpZWRQb3NlLmF0dGFjaG1lbnQ7XG5cblx0XHRcdGlmIChhdHRhY2htZW50ID09IG51bGwgfHwgIShhdHRhY2htZW50IGluc3RhbmNlb2YgQ2xpcHBpbmdBdHRhY2htZW50KSkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgY2xpcHBpbmdBdHRhY2htZW50ID0gYXR0YWNobWVudDtcblxuXHRcdFx0Y29uc3Qgbm4gPSBjbGlwcGluZ0F0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aDtcblx0XHRcdGNvbnN0IHdvcmxkID0gbmV3IEZsb2F0MzJBcnJheShubik7XG5cblx0XHRcdGNsaXBwaW5nQXR0YWNobWVudC5jb21wdXRlV29ybGRWZXJ0aWNlcyhza2VsZXRvbiwgc2xvdCwgMCwgbm4sIHdvcmxkLCAwLCAyKTtcblx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMuY2xpcHBpbmdQb2x5Z29uLmRyYXdQb2x5Z29uKEFycmF5LmZyb20od29ybGQpKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGRyYXdCb3VuZGluZ0JveGVzRnVuYyAoc3BpbmU6IFNwaW5lLCBkZWJ1Z0Rpc3BsYXlPYmplY3RzOiBEZWJ1Z0Rpc3BsYXlPYmplY3RzLCBsaW5lV2lkdGg6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIGRyYXcgdGhlIHRvdGFsIG91dGxpbmUgb2YgdGhlIGJvdW5kaW5nIGJveFxuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc1JlY3QubGluZVN0eWxlKGxpbmVXaWR0aCwgdGhpcy5ib3VuZGluZ0JveGVzUmVjdENvbG9yLCA1KTtcblxuXHRcdGNvbnN0IGJvdW5kcyA9IG5ldyBTa2VsZXRvbkJvdW5kcygpO1xuXG5cdFx0Ym91bmRzLnVwZGF0ZShzcGluZS5za2VsZXRvbiwgdHJ1ZSk7XG5cdFx0aWYgKGJvdW5kcy5taW5YICE9PSBJbmZpbml0eSkge1xuXHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5ib3VuZGluZ0JveGVzUmVjdC5kcmF3UmVjdChib3VuZHMubWluWCwgYm91bmRzLm1pblksIGJvdW5kcy5nZXRXaWR0aCgpLCBib3VuZHMuZ2V0SGVpZ2h0KCkpO1xuXHRcdH1cblx0XHRjb25zdCBwb2x5Z29ucyA9IGJvdW5kcy5wb2x5Z29ucztcblx0XHRjb25zdCBkcmF3UG9seWdvbiA9IChwb2x5Z29uVmVydGljZXM6IEFycmF5TGlrZTxudW1iZXI+LCBfb2Zmc2V0OiB1bmtub3duLCBjb3VudDogbnVtYmVyKTogdm9pZCA9PiB7XG5cdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvdW5kaW5nQm94ZXNQb2x5Z29uLmxpbmVTdHlsZShsaW5lV2lkdGgsIHRoaXMuYm91bmRpbmdCb3hlc1BvbHlnb25Db2xvciwgMSk7XG5cdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvdW5kaW5nQm94ZXNQb2x5Z29uLmJlZ2luRmlsbCh0aGlzLmJvdW5kaW5nQm94ZXNQb2x5Z29uQ29sb3IsIDAuMSk7XG5cblx0XHRcdGlmIChjb3VudCA8IDMpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiUG9seWdvbiBtdXN0IGNvbnRhaW4gYXQgbGVhc3QgMyB2ZXJ0aWNlc1wiKTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHBhdGhzID0gW107XG5cdFx0XHRjb25zdCBkb3RTaXplID0gbGluZVdpZHRoICogMjtcblxuXHRcdFx0Zm9yIChsZXQgaSA9IDAsIGxlbiA9IHBvbHlnb25WZXJ0aWNlcy5sZW5ndGg7IGkgPCBsZW47IGkgKz0gMikge1xuXHRcdFx0XHRjb25zdCB4MSA9IHBvbHlnb25WZXJ0aWNlc1tpXTtcblx0XHRcdFx0Y29uc3QgeTEgPSBwb2x5Z29uVmVydGljZXNbaSArIDFdO1xuXG5cdFx0XHRcdC8vIGRyYXcgdGhlIGJvdW5kaW5nIGJveCBub2RlXG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc0NpcmNsZS5saW5lU3R5bGUoMCk7XG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc0NpcmNsZS5iZWdpbkZpbGwodGhpcy5ib3VuZGluZ0JveGVzQ2lyY2xlQ29sb3IpO1xuXHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvdW5kaW5nQm94ZXNDaXJjbGUuZHJhd0NpcmNsZSh4MSwgeTEsIGRvdFNpemUpO1xuXHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLmJvdW5kaW5nQm94ZXNDaXJjbGUuZW5kRmlsbCgpO1xuXG5cdFx0XHRcdHBhdGhzLnB1c2goeDEsIHkxKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gZHJhdyB0aGUgYm91bmRpbmcgYm94IGFyZWFcblx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMuYm91bmRpbmdCb3hlc1BvbHlnb24uZHJhd1BvbHlnb24ocGF0aHMpO1xuXHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5ib3VuZGluZ0JveGVzUG9seWdvbi5lbmRGaWxsKCk7XG5cdFx0fTtcblxuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSBwb2x5Z29ucy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0Y29uc3QgcG9seWdvbiA9IHBvbHlnb25zW2ldO1xuXG5cdFx0XHRkcmF3UG9seWdvbihwb2x5Z29uLCAwLCBwb2x5Z29uLmxlbmd0aCk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBkcmF3UGF0aHNGdW5jIChzcGluZTogU3BpbmUsIGRlYnVnRGlzcGxheU9iamVjdHM6IERlYnVnRGlzcGxheU9iamVjdHMsIGxpbmVXaWR0aDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Y29uc3Qgc2tlbGV0b24gPSBzcGluZS5za2VsZXRvbjtcblx0XHRjb25zdCBzbG90cyA9IHNrZWxldG9uLnNsb3RzO1xuXG5cdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXRoc0N1cnZlLmxpbmVTdHlsZShsaW5lV2lkdGgsIHRoaXMucGF0aHNDdXJ2ZUNvbG9yLCAxKTtcblx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzTGluZS5saW5lU3R5bGUobGluZVdpZHRoLCB0aGlzLnBhdGhzTGluZUNvbG9yLCAxKTtcblxuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSBzbG90cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0Y29uc3Qgc2xvdCA9IHNsb3RzW2ldO1xuXG5cdFx0XHRpZiAoIXNsb3QuYm9uZS5hY3RpdmUpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHRjb25zdCBhdHRhY2htZW50ID0gc2xvdC5hcHBsaWVkUG9zZS5hdHRhY2htZW50O1xuXG5cdFx0XHRpZiAoYXR0YWNobWVudCA9PSBudWxsIHx8ICEoYXR0YWNobWVudCBpbnN0YW5jZW9mIFBhdGhBdHRhY2htZW50KSkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgcGF0aEF0dGFjaG1lbnQgPSBhdHRhY2htZW50O1xuXHRcdFx0bGV0IG5uID0gcGF0aEF0dGFjaG1lbnQud29ybGRWZXJ0aWNlc0xlbmd0aDtcblx0XHRcdGNvbnN0IHdvcmxkID0gbmV3IEZsb2F0MzJBcnJheShubik7XG5cblx0XHRcdHBhdGhBdHRhY2htZW50LmNvbXB1dGVXb3JsZFZlcnRpY2VzKHNrZWxldG9uLCBzbG90LCAwLCBubiwgd29ybGQsIDAsIDIpO1xuXHRcdFx0bGV0IHgxID0gd29ybGRbMl07XG5cdFx0XHRsZXQgeTEgPSB3b3JsZFszXTtcblx0XHRcdGxldCB4MiA9IDA7XG5cdFx0XHRsZXQgeTIgPSAwO1xuXG5cdFx0XHRpZiAocGF0aEF0dGFjaG1lbnQuY2xvc2VkKSB7XG5cdFx0XHRcdGNvbnN0IGN4MSA9IHdvcmxkWzBdO1xuXHRcdFx0XHRjb25zdCBjeTEgPSB3b3JsZFsxXTtcblx0XHRcdFx0Y29uc3QgY3gyID0gd29ybGRbbm4gLSAyXTtcblx0XHRcdFx0Y29uc3QgY3kyID0gd29ybGRbbm4gLSAxXTtcblxuXHRcdFx0XHR4MiA9IHdvcmxkW25uIC0gNF07XG5cdFx0XHRcdHkyID0gd29ybGRbbm4gLSAzXTtcblxuXHRcdFx0XHQvLyBjdXJ2ZVxuXHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzQ3VydmUubW92ZVRvKHgxLCB5MSk7XG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGF0aHNDdXJ2ZS5iZXppZXJDdXJ2ZVRvKGN4MSwgY3kxLCBjeDIsIGN5MiwgeDIsIHkyKTtcblxuXHRcdFx0XHQvLyBoYW5kbGVcblx0XHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXRoc0xpbmUubW92ZVRvKHgxLCB5MSk7XG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGF0aHNMaW5lLmxpbmVUbyhjeDEsIGN5MSk7XG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGF0aHNMaW5lLm1vdmVUbyh4MiwgeTIpO1xuXHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzTGluZS5saW5lVG8oY3gyLCBjeTIpO1xuXHRcdFx0fVxuXHRcdFx0bm4gLT0gNDtcblx0XHRcdGZvciAobGV0IGlpID0gNDsgaWkgPCBubjsgaWkgKz0gNikge1xuXHRcdFx0XHRjb25zdCBjeDEgPSB3b3JsZFtpaV07XG5cdFx0XHRcdGNvbnN0IGN5MSA9IHdvcmxkW2lpICsgMV07XG5cdFx0XHRcdGNvbnN0IGN4MiA9IHdvcmxkW2lpICsgMl07XG5cdFx0XHRcdGNvbnN0IGN5MiA9IHdvcmxkW2lpICsgM107XG5cblx0XHRcdFx0eDIgPSB3b3JsZFtpaSArIDRdO1xuXHRcdFx0XHR5MiA9IHdvcmxkW2lpICsgNV07XG5cdFx0XHRcdC8vIGN1cnZlXG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGF0aHNDdXJ2ZS5tb3ZlVG8oeDEsIHkxKTtcblx0XHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXRoc0N1cnZlLmJlemllckN1cnZlVG8oY3gxLCBjeTEsIGN4MiwgY3kyLCB4MiwgeTIpO1xuXG5cdFx0XHRcdC8vIGhhbmRsZVxuXHRcdFx0XHRkZWJ1Z0Rpc3BsYXlPYmplY3RzLnBhdGhzTGluZS5tb3ZlVG8oeDEsIHkxKTtcblx0XHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXRoc0xpbmUubGluZVRvKGN4MSwgY3kxKTtcblx0XHRcdFx0ZGVidWdEaXNwbGF5T2JqZWN0cy5wYXRoc0xpbmUubW92ZVRvKHgyLCB5Mik7XG5cdFx0XHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGF0aHNMaW5lLmxpbmVUbyhjeDIsIGN5Mik7XG5cdFx0XHRcdHgxID0geDI7XG5cdFx0XHRcdHkxID0geTI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cHVibGljIHVucmVnaXN0ZXJTcGluZSAoc3BpbmU6IFNwaW5lKTogdm9pZCB7XG5cdFx0aWYgKCF0aGlzLnJlZ2lzdGVyZWRTcGluZXMuaGFzKHNwaW5lKSkge1xuXHRcdFx0Y29uc29sZS53YXJuKFwiU3BpbmVEZWJ1Z1JlbmRlcmVyLnVucmVnaXN0ZXJTcGluZSgpIC0gc3BpbmUgaXMgbm90IHJlZ2lzdGVyZWQsIGNhbid0IHVucmVnaXN0ZXIhXCIsIHNwaW5lKTtcblx0XHR9XG5cdFx0Y29uc3QgZGVidWdEaXNwbGF5T2JqZWN0cyA9IHRoaXMucmVnaXN0ZXJlZFNwaW5lcy5nZXQoc3BpbmUpO1xuXG5cdFx0aWYgKCFkZWJ1Z0Rpc3BsYXlPYmplY3RzKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0c3BpbmUuc3RhdGUucmVtb3ZlTGlzdGVuZXIoZGVidWdEaXNwbGF5T2JqZWN0cy5ldmVudENhbGxiYWNrKTtcblxuXHRcdGRlYnVnRGlzcGxheU9iamVjdHMucGFyZW50RGVidWdDb250YWluZXIuZGVzdHJveSh7IGJhc2VUZXh0dXJlOiB0cnVlLCBjaGlsZHJlbjogdHJ1ZSwgdGV4dHVyZTogdHJ1ZSB9KTtcblx0XHR0aGlzLnJlZ2lzdGVyZWRTcGluZXMuZGVsZXRlKHNwaW5lKTtcblx0fVxufVxuIl19