papercss/tests/vendor/quixote.js
2017-12-02 17:30:44 +00:00

4196 lines
333 KiB
JavaScript

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.quixote = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],2:[function(require,module,exports){
// Copyright (c) 2015 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var oop = require("./util/oop.js");
var shim = require("./util/shim.js");
var Me = module.exports = function Assertable() {
ensure.unreachable("Assertable is abstract and should not be constructed directly.");
};
Me.extend = oop.extendFn(Me);
oop.makeAbstract(Me, []);
Me.prototype.assert = function assert(expected, message) {
ensure.signature(arguments, [ Object, [undefined, String] ]);
if (message === undefined) message = "Differences found";
var diff = this.diff(expected);
if (diff !== "") throw new Error(message + ":\n" + diff + "\n");
};
Me.prototype.diff = function diff(expected) {
ensure.signature(arguments, [ Object ]);
var result = [];
var keys = shim.Object.keys(expected);
var key, oneDiff, descriptor;
for (var i = 0; i < keys.length; i++) {
key = keys[i];
descriptor = this[key];
ensure.that(
descriptor !== undefined,
this + " doesn't have a property named '" + key + "'. Did you misspell it?"
);
oneDiff = descriptor.diff(expected[key]);
if (oneDiff !== "") result.push(oneDiff);
}
return result.join("\n");
};
},{"./util/ensure.js":23,"./util/oop.js":24,"./util/shim.js":25}],3:[function(require,module,exports){
// Copyright (c) 2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var PositionDescriptor = require("./position_descriptor.js");
var Position = require("../values/position.js");
var X_DIMENSION = "x";
var Y_DIMENSION = "y";
var Me = module.exports = function AbsolutePosition(dimension, value) {
ensure.signature(arguments, [ String, Number ]);
switch(dimension) {
case X_DIMENSION:
PositionDescriptor.x(this);
this._value = Position.x(value);
break;
case Y_DIMENSION:
PositionDescriptor.y(this);
this._value = Position.y(value);
break;
default: ensure.unreachable("Unknown dimension: " + dimension);
}
this._dimension = dimension;
};
PositionDescriptor.extend(Me);
Me.x = function(value) {
ensure.signature(arguments, [ Number ]);
return new Me(X_DIMENSION, value);
};
Me.y = function(value) {
ensure.signature(arguments, [ Number ]);
return new Me(Y_DIMENSION, value);
};
Me.prototype.value = function() {
return this._value;
};
Me.prototype.toString = function() {
return this._value + " " + this._dimension + "-coordinate";
};
},{"../util/ensure.js":23,"../values/position.js":27,"./position_descriptor.js":11}],4:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var PositionDescriptor = require("./position_descriptor.js");
var Position = require("../values/position.js");
var RelativePosition = require("./relative_position.js");
var X_DIMENSION = "x";
var Y_DIMENSION = "y";
var Me = module.exports = function Center(dimension, position1, position2, description) {
ensure.signature(arguments, [ String, PositionDescriptor, PositionDescriptor, String ]);
if (dimension === X_DIMENSION) PositionDescriptor.x(this);
else if (dimension === Y_DIMENSION) PositionDescriptor.y(this);
else ensure.unreachable("Unknown dimension: " + dimension);
this._dimension = dimension;
this._position1 = position1;
this._position2 = position2;
this._description = description;
};
PositionDescriptor.extend(Me);
Me.x = factoryFn(X_DIMENSION);
Me.y = factoryFn(Y_DIMENSION);
Me.prototype.value = function value() {
ensure.signature(arguments, []);
return this._position1.value().midpoint(this._position2.value());
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
return this._description;
};
function factoryFn(dimension) {
return function(position1, position2, description) {
return new Me(dimension, position1, position2, description);
};
}
},{"../util/ensure.js":23,"../values/position.js":27,"./position_descriptor.js":11,"./relative_position.js":12}],5:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var oop = require("../util/oop.js");
var Value = require("../values/value.js");
var Me = module.exports = function Descriptor() {
ensure.unreachable("Descriptor is abstract and should not be constructed directly.");
};
Me.extend = oop.extendFn(Me);
oop.makeAbstract(Me, [
"value",
"toString"
]);
Me.prototype.diff = function diff(expected) {
expected = normalizeType(this, expected);
try {
var actualValue = this.value();
var expectedValue = expected.value();
if (actualValue.equals(expectedValue)) return "";
var difference = actualValue.diff(expectedValue);
var expectedDesc = expectedValue.toString();
if (expected instanceof Me) expectedDesc += " (" + expected + ")";
return this + " was " + difference + ".\n" +
" Expected: " + expectedDesc + "\n" +
" But was: " + actualValue;
}
catch (err) {
throw new Error("Can't compare " + this + " to " + expected + ": " + err.message);
}
};
Me.prototype.convert = function convert(arg, type) {
// This method is meant to be overridden by subclasses. It should return 'undefined' when an argument
// can't be converted. In this default implementation, no arguments can be converted, so we always
// return 'undefined'.
return undefined;
};
Me.prototype.equals = function equals(that) {
// Descriptors aren't value objects. They're never equal to anything. But sometimes
// they're used in the same places value objects are used, and this method gets called.
return false;
};
function normalizeType(self, expected) {
var expectedType = typeof expected;
if (expected === null) expectedType = "null";
if (expectedType === "object" && (expected instanceof Me || expected instanceof Value)) return expected;
if (expected === undefined) {
throw new Error("Can't compare " + self + " to " + expected + ". Did you misspell a property name?");
}
else if (expectedType === "object") {
throw new Error("Can't compare " + self + " to " + oop.instanceName(expected) + " instances.");
}
else {
var converted = self.convert(expected, expectedType);
if (converted !== undefined) return converted;
var explanation = expected;
if (expectedType === "string") explanation = "'" + explanation + "'";
if (expectedType === "function") explanation = "a function";
throw new Error("Can't compare " + self + " to " + explanation + ".");
}
}
},{"../util/ensure.js":23,"../util/oop.js":24,"../values/value.js":30}],6:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Position = require("../values/position.js");
var PositionDescriptor = require("./position_descriptor.js");
var TOP = "top";
var RIGHT = "right";
var BOTTOM = "bottom";
var LEFT = "left";
var Me = module.exports = function ElementEdge(element, position) {
var QElement = require("../q_element.js"); // break circular dependency
ensure.signature(arguments, [QElement, String]);
if (position === LEFT || position === RIGHT) PositionDescriptor.x(this);
else if (position === TOP || position === BOTTOM) PositionDescriptor.y(this);
else ensure.unreachable("Unknown position: " + position);
this._element = element;
this._position = position;
};
PositionDescriptor.extend(Me);
Me.top = factoryFn(TOP);
Me.right = factoryFn(RIGHT);
Me.bottom = factoryFn(BOTTOM);
Me.left = factoryFn(LEFT);
Me.prototype.value = function value() {
ensure.signature(arguments, []);
var rawPosition = this._element.getRawPosition();
var edge = rawPosition[this._position];
var scroll = this._element.frame.getRawScrollPosition();
if (this._position === RIGHT || this._position === LEFT) {
if (!elementRendered(this, rawPosition)) return Position.noX();
return Position.x(edge + scroll.x);
}
else {
if (!elementRendered(this, rawPosition)) return Position.noY();
return Position.y(edge + scroll.y);
}
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
return this._position + " edge of " + this._element;
};
function factoryFn(position) {
return function factory(element) {
return new Me(element, position);
};
}
function elementRendered(self, rawPosition) {
var element = self._element;
var inDom = element.frame.body().toDomElement().contains(element.toDomElement());
var displayNone = element.getRawStyle("display") === "none";
return inDom && !displayNone;
}
},{"../q_element.js":17,"../util/ensure.js":23,"../values/position.js":27,"./position_descriptor.js":11}],7:[function(require,module,exports){
// Copyright (c) 2016-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var RenderState = require("../values/render_state.js");
var Position = require("../values/position.js");
var Descriptor = require("./descriptor.js");
var ElementRenderedEdge = require("./element_rendered_edge.js");
var GenericSize = require("./generic_size.js");
var Center = require("./center.js");
var Me = module.exports = function ElementRendered(element) {
var QElement = require("../q_element.js"); // break circular dependency
ensure.signature(arguments, [ QElement ]);
this._element = element;
// properties
this.top = ElementRenderedEdge.top(element);
this.right = ElementRenderedEdge.right(element);
this.bottom = ElementRenderedEdge.bottom(element);
this.left = ElementRenderedEdge.left(element);
this.width = GenericSize.create(this.left, this.right, "rendered width of " + element);
this.height = GenericSize.create(this.top, this.bottom, "rendered height of " + element);
this.center = Center.x(this.left, this.right, "rendered center of " + element);
this.middle = Center.y(this.top, this.bottom, "rendered middle of " + element);
};
Descriptor.extend(Me);
Me.create = function create(element) {
return new Me(element);
};
Me.prototype.value = function value() {
if (this.top.value().equals(Position.noY())) return RenderState.notRendered();
else return RenderState.rendered();
};
Me.prototype.toString = function toString() {
return "render status of " + this._element.toString();
};
Me.prototype.convert = function convert(arg, type) {
if (type === "boolean") {
return arg ? RenderState.rendered() : RenderState.notRendered();
}
};
},{"../q_element.js":17,"../util/ensure.js":23,"../values/position.js":27,"../values/render_state.js":28,"./center.js":4,"./descriptor.js":5,"./element_rendered_edge.js":8,"./generic_size.js":9}],8:[function(require,module,exports){
// Copyright (c) 2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var quixote = require("../quixote.js");
var PositionDescriptor = require("./position_descriptor.js");
var Position = require("../values/position.js");
var Size = require("../values/size.js");
var RenderState = require("../values/render_state.js");
var TOP = "top";
var RIGHT = "right";
var BOTTOM = "bottom";
var LEFT = "left";
var Me = module.exports = function ElementVisibleEdge(element, position) {
var QElement = require("../q_element.js"); // break circular dependency
ensure.signature(arguments, [ QElement, String ]);
if (position === LEFT || position === RIGHT) PositionDescriptor.x(this);
else if (position === TOP || position === BOTTOM) PositionDescriptor.y(this);
else unknownPosition(position);
this._element = element;
this._position = position;
};
PositionDescriptor.extend(Me);
Me.top = factoryFn(TOP);
Me.right = factoryFn(RIGHT);
Me.bottom = factoryFn(BOTTOM);
Me.left = factoryFn(LEFT);
function factoryFn(position) {
return function factory(element) {
return new Me(element, position);
};
}
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
return this._position + " rendered edge of " + this._element;
};
Me.prototype.value = function() {
var position = this._position;
var element = this._element;
var page = element.frame.page();
if (element.top.value().equals(Position.noY())) return notRendered(position);
if (element.width.value().equals(Size.create(0))) return notRendered(position);
if (element.height.value().equals(Size.create(0))) return notRendered(position);
ensure.that(
!hasClipPathProperty(element),
"Can't detect element clipping boundaries when 'clip-path' property is used."
);
var bounds = {
top: page.top.value(),
right: null,
bottom: null,
left: page.left.value()
};
bounds = intersectionWithOverflow(element, bounds);
bounds = intersectionWithClip(element, bounds);
var edges = intersection(
bounds,
element.top.value(),
element.right.value(),
element.bottom.value(),
element.left.value()
);
if (isClippedOutOfExistence(bounds, edges)) return notRendered(position);
else return edge(edges, position);
};
function hasClipPathProperty(element) {
var clipPath = element.getRawStyle("clip-path");
return clipPath !== "none" && clipPath !== "";
}
function intersectionWithOverflow(element, bounds) {
for (var container = element.parent(); container !== null; container = container.parent()) {
if (isClippedByAncestorOverflow(element, container)) {
bounds = intersection(
bounds,
container.top.value(),
container.right.value(),
container.bottom.value(),
container.left.value()
);
}
}
return bounds;
}
function intersectionWithClip(element, bounds) {
// WORKAROUND IE 8: Doesn't have any way to detect 'clip: auto' value.
ensure.that(!quixote.browser.misreportsClipAutoProperty(),
"Can't determine element clipping values on this browser because it misreports the value of the" +
" `clip: auto` property. You can use `quixote.browser.misreportsClipAutoProperty()` to skip this browser."
);
for ( ; element !== null; element = element.parent()) {
var clip = element.getRawStyle("clip");
if (clip === "auto" || !canBeClippedByClipProperty(element)) continue;
var clipEdges = normalizeClipProperty(element, clip);
bounds = intersection(
bounds,
clipEdges.top,
clipEdges.right,
clipEdges.bottom,
clipEdges.left
);
}
return bounds;
}
function normalizeClipProperty(element, clip) {
var clipValues = parseClipProperty(element, clip);
return {
top: clipValues[0] === "auto" ?
element.top.value() :
element.top.value().plus(Position.y(Number(clipValues[0]))),
right: clipValues[1] === "auto" ?
element.right.value() :
element.left.value().plus(Position.x(Number(clipValues[1]))),
bottom: clipValues[2] === "auto" ?
element.bottom.value() :
element.top.value().plus(Position.y(Number(clipValues[2]))),
left: clipValues[3] === "auto" ?
element.left.value() :
element.left.value().plus(Position.x(Number(clipValues[3])))
};
function parseClipProperty(element, clip) {
// WORKAROUND IE 11, Chrome Mobile 44: Reports 0px instead of 'auto' when computing rect() in clip property.
ensure.that(!quixote.browser.misreportsAutoValuesInClipProperty(),
"Can't determine element clipping values on this browser because it misreports the value of the `clip`" +
" property. You can use `quixote.browser.misreportsAutoValuesInClipProperty()` to skip this browser."
);
var clipRegex = /rect\((.*?),? (.*?),? (.*?),? (.*?)\)/;
var matches = clipRegex.exec(clip);
ensure.that(matches !== null, "Unable to parse clip property: " + clip);
return [
parseLength(matches[1], clip),
parseLength(matches[2], clip),
parseLength(matches[3], clip),
parseLength(matches[4], clip)
];
}
function parseLength(pxString, clip) {
if (pxString === "auto") return pxString;
var pxRegex = /^(.*?)px$/;
var matches = pxRegex.exec(pxString);
ensure.that(matches !== null, "Unable to parse '" + pxString + "' in clip property: " + clip);
return matches[1];
}
}
function isClippedByAncestorOverflow(element, ancestor) {
return canBeClippedByOverflowProperty(element) && hasClippingOverflow(ancestor);
}
function canBeClippedByOverflowProperty(element) {
var position = element.getRawStyle("position");
switch (position) {
case "static":
case "relative":
case "absolute":
case "sticky":
return true;
case "fixed":
return false;
default:
ensure.unreachable("Unknown position property: " + position);
}
}
function hasClippingOverflow(element) {
var overflow = element.getRawStyle("overflow");
switch (overflow) {
case "hidden":
case "scroll":
case "auto":
return true;
case "visible":
return false;
default:
ensure.unreachable("Unknown overflow property: " + overflow);
}
}
function canBeClippedByClipProperty(element) {
var position = element.getRawStyle("position");
switch (position) {
case "absolute":
case "fixed":
return true;
case "static":
case "relative":
case "sticky":
return false;
default:
ensure.unreachable("Unknown position property: " + position);
}
}
function intersection(bounds, top, right, bottom, left) {
bounds.top = bounds.top.max(top);
bounds.right = (bounds.right === null) ? right : bounds.right.min(right);
bounds.bottom = (bounds.bottom === null) ? bottom : bounds.bottom.min(bottom);
bounds.left = bounds.left.max(left);
return bounds;
}
function isClippedOutOfExistence(bounds, edges) {
return (bounds.top.compare(edges.bottom) >= 0) ||
(bounds.right !== null && bounds.right.compare(edges.left) <= 0) ||
(bounds.bottom !== null && bounds.bottom.compare(edges.top) <= 0) ||
(bounds.left.compare(edges.right) >= 0);
}
function notRendered(position) {
switch(position) {
case TOP:
case BOTTOM:
return Position.noY();
case LEFT:
case RIGHT:
return Position.noX();
default: unknownPosition(position);
}
}
function edge(edges, position) {
switch(position) {
case TOP: return edges.top;
case RIGHT: return edges.right;
case BOTTOM: return edges.bottom;
case LEFT: return edges.left;
default: unknownPosition(position);
}
}
function unknownPosition(position) {
ensure.unreachable("Unknown position: " + position);
}
},{"../q_element.js":17,"../quixote.js":22,"../util/ensure.js":23,"../values/position.js":27,"../values/render_state.js":28,"../values/size.js":29,"./position_descriptor.js":11}],9:[function(require,module,exports){
// Copyright (c) 2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var PositionDescriptor = require("./position_descriptor.js");
var SizeDescriptor = require("./size_descriptor.js");
var Me = module.exports = function GenericSize(from, to, description) {
ensure.signature(arguments, [ PositionDescriptor, PositionDescriptor, String ]);
this._from = from;
this._to = to;
this._description = description;
};
SizeDescriptor.extend(Me);
Me.create = function(from, to, description) {
return new Me(from, to, description);
};
Me.prototype.value = function() {
ensure.signature(arguments, []);
return this._from.value().distanceTo(this._to.value());
};
Me.prototype.toString = function() {
return this._description;
};
},{"../util/ensure.js":23,"./position_descriptor.js":11,"./size_descriptor.js":14}],10:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var PositionDescriptor = require("./position_descriptor.js");
var Position = require("../values/position.js");
var TOP = "top";
var RIGHT = "right";
var BOTTOM = "bottom";
var LEFT = "left";
var Me = module.exports = function PageEdge(edge, frame) {
var QFrame = require("../q_frame.js"); // break circular dependency
ensure.signature(arguments, [ String, QFrame ]);
if (edge === LEFT || edge === RIGHT) PositionDescriptor.x(this);
else if (edge === TOP || edge === BOTTOM) PositionDescriptor.y(this);
else ensure.unreachable("Unknown edge: " + edge);
this._edge = edge;
this._frame = frame;
};
PositionDescriptor.extend(Me);
Me.top = factoryFn(TOP);
Me.right = factoryFn(RIGHT);
Me.bottom = factoryFn(BOTTOM);
Me.left = factoryFn(LEFT);
Me.prototype.value = function value() {
ensure.signature(arguments, []);
var size = pageSize(this._frame.toDomElement().contentDocument);
switch(this._edge) {
case TOP: return Position.y(0);
case RIGHT: return Position.x(size.width);
case BOTTOM: return Position.y(size.height);
case LEFT: return Position.x(0);
default: ensure.unreachable();
}
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
switch(this._edge) {
case TOP: return "top of page";
case RIGHT: return "right side of page";
case BOTTOM: return "bottom of page";
case LEFT: return "left side of page";
default: ensure.unreachable();
}
};
function factoryFn(edge) {
return function factory(frame) {
return new Me(edge, frame);
};
}
// USEFUL READING: http://www.quirksmode.org/mobile/viewports.html
// and http://www.quirksmode.org/mobile/viewports2.html
// API SEMANTICS.
// Ref https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
// getBoundingClientRect().width: sum of bounding boxes of element (the displayed width of the element,
// including padding and border). Fractional. Applies transformations.
// clientWidth: visible width of element including padding (but not border). EXCEPT on root element (html), where
// it is the width of the viewport. Rounds to an integer. Doesn't apply transformations.
// offsetWidth: visible width of element including padding, border, and scrollbars (if any). Rounds to an integer.
// Doesn't apply transformations.
// scrollWidth: entire width of element, including any part that's not visible due to scrollbars. Rounds to
// an integer. Doesn't apply transformations. Not clear if it includes scrollbars, but I think not. Also
// not clear if it includes borders or padding. (But from tests, apparently not borders. Except on root
// element and body element, which have special results that vary by browser.)
// TEST RESULTS: WIDTH
// ✔ = correct answer
// ✘ = incorrect answer and diverges from spec
// ~ = incorrect answer, but matches spec
// BROWSERS TESTED: Safari 6.2.0 (Mac OS X 10.8.5); Mobile Safari 7.0.0 (iOS 7.1); Firefox 32.0.0 (Mac OS X 10.8);
// Firefox 33.0.0 (Windows 7); Chrome 38.0.2125 (Mac OS X 10.8.5); Chrome 38.0.2125 (Windows 7); IE 8, 9, 10, 11
// html width style smaller than viewport width; body width style smaller than html width style
// NOTE: These tests were conducted when correct result was width of border. That has been changed
// to "width of viewport."
// html.getBoundingClientRect().width
// ✘ IE 8, 9, 10: width of viewport
// ✔ Safari, Mobile Safari, Chrome, Firefox, IE 11: width of html, including border
// html.clientWidth
// ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of viewport
// html.offsetWidth
// ✘ IE 8, 9, 10: width of viewport
// ✔ Safari, Mobile Safari, Chrome, Firefox, IE 11: width of html, including border
// html.scrollWidth
// ✘ IE 8, 9, 10, 11, Firefox: width of viewport
// ~ Safari, Mobile Safari, Chrome: width of html, excluding border
// body.getBoundingClientRect().width
// ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of body, including border
// body.clientWidth
// ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of body, excluding border
// body.offsetWidth
// ~ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: width of body, including border
// body.scrollWidth
// ✘ Safari, Mobile Safari, Chrome: width of viewport
// ~ Firefox, IE 8, 9, 10, 11: width of body, excluding border
// element width style wider than viewport; body and html width styles at default
// BROWSER BEHAVIOR: html and body border extend to width of viewport and not beyond (except on Mobile Safari)
// Correct result is element width + body border-left + html border-left (except on Mobile Safari)
// Mobile Safari uses a layout viewport, so it's expected to include body border-right and html border-right.
// html.getBoundingClientRect().width
// ✔ Mobile Safari: element width + body border + html border
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width
// html.clientWidth
// ✔ Mobile Safari: element width + body border + html border
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width
// html.offsetWidth
// ✔ Mobile Safari: element width + body border + html border
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width
// html.scrollWidth
// ✔ Mobile Safari: element width + body border + html border
// ✘ Safari, Chrome: element width + body border-left (BUT NOT html border-left)
// ✔ Firefox, IE 8, 9, 10, 11: element width + body border-left + html border-left
// body.getBoundingClientRect().width
// ~ Mobile Safari: element width + body border
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width - html border
// body.clientWidth
// ~ Mobile Safari: element width
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width - html border - body border
// body.offsetWidth
// ~ Mobile Safari: element width + body border
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: viewport width - html border
// body.scrollWidth
// ✔ Mobile Safari: element width + body border + html border
// ✔ Safari, Chrome: element width + body border-left + html border-left (matches actual browser)
// ~ Firefox, IE 8, 9, 10, 11: element width
// TEST RESULTS: HEIGHT
// ✔ = correct answer
// ✘ = incorrect answer and diverges from spec
// ~ = incorrect answer, but matches spec
// html height style smaller than viewport height; body height style smaller than html height style
// NOTE: These tests were conducted when correct result was height of viewport.
// html.clientHeight
// ✔ Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11: height of viewport
// element height style taller than viewport; body and html width styles at default
// BROWSER BEHAVIOR: html and body border enclose entire element
// Correct result is element width + body border-top + html border-top + body border-bottom + html border-bottom
// html.clientHeight
// ✔ Mobile Safari: element height + all borders
// ~ Safari, Chrome, Firefox, IE 8, 9, 10, 11: height of viewport
// html.scrollHeight
// ✔ Firefox, IE 8, 9, 10, 11: element height + all borders
// ✘ Safari, Mobile Safari, Chrome: element height + html border-bottom
// body.scrollHeight
// ✔ Safari, Mobile Safari, Chrome: element height + all borders
// ~ Firefox, IE 8, 9, 10, 11: element height (body height - body border)
function pageSize(document) {
var html = document.documentElement;
var body = document.body;
// BEST WIDTH ANSWER SO FAR (ASSUMING VIEWPORT IS MINIMUM ANSWER):
var width = Math.max(body.scrollWidth, html.scrollWidth);
// BEST HEIGHT ANSWER SO FAR (ASSUMING VIEWPORT IS MINIMUM ANSWER):
var height = Math.max(body.scrollHeight, html.scrollHeight);
return {
width: width,
height: height
};
}
},{"../q_frame.js":19,"../util/ensure.js":23,"../values/position.js":27,"./position_descriptor.js":11}],11:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
/*eslint new-cap: "off" */
"use strict";
var ensure = require("../util/ensure.js");
var oop = require("../util/oop.js");
var Descriptor = require("./descriptor.js");
var Position = require("../values/position.js");
// break circular dependencies
function RelativePosition() {
return require("./relative_position.js");
}
function AbsolutePosition() {
return require("./absolute_position.js");
}
function GenericSize() {
return require("./generic_size.js");
}
var X_DIMENSION = "x";
var Y_DIMENSION = "y";
var Me = module.exports = function PositionDescriptor(dimension) {
ensure.signature(arguments, [ String ]);
ensure.unreachable("PositionDescriptor is abstract and should not be constructed directly.");
};
Descriptor.extend(Me);
Me.extend = oop.extendFn(Me);
Me.x = factoryFn(X_DIMENSION);
Me.y = factoryFn(Y_DIMENSION);
Me.prototype.plus = function plus(amount) {
if (this._pdbc.dimension === X_DIMENSION) return RelativePosition().right(this, amount);
else return RelativePosition().down(this, amount);
};
Me.prototype.minus = function minus(amount) {
if (this._pdbc.dimension === X_DIMENSION) return RelativePosition().left(this, amount);
else return RelativePosition().up(this, amount);
};
Me.prototype.to = function to(position) {
ensure.signature(arguments, [[ Me, Number ]]);
if (typeof position === "number") {
if (this._pdbc.dimension === X_DIMENSION) position = AbsolutePosition().x(position);
else position = AbsolutePosition().y(position);
}
if (this._pdbc.dimension !== position._pdbc.dimension) {
throw new Error("Can only calculate distance between two X coordinates or two Y coordinates");
}
return GenericSize().create(this, position, "distance from " + this + " to " + position);
};
Me.prototype.convert = function convert(arg, type) {
switch (type) {
case "number": return this._pdbc.dimension === X_DIMENSION ? Position.x(arg) : Position.y(arg);
case "string":
if (arg === "none") return this._pdbc.dimension === X_DIMENSION ? Position.noX() : Position.noY();
else return undefined;
break;
default: return undefined;
}
};
function factoryFn(dimension) {
return function factory(self) {
// _pdbc: "PositionDescriptor base class." An attempt to prevent name conflicts.
self._pdbc = { dimension: dimension };
};
}
},{"../util/ensure.js":23,"../util/oop.js":24,"../values/position.js":27,"./absolute_position.js":3,"./descriptor.js":5,"./generic_size.js":9,"./relative_position.js":12}],12:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Descriptor = require("./descriptor.js");
var PositionDescriptor = require("./position_descriptor.js");
var Value = require("../values/value.js");
var Size = require("../values/size.js");
var X_DIMENSION = "x";
var Y_DIMENSION = "y";
var PLUS = 1;
var MINUS = -1;
var Me = module.exports = function RelativePosition(dimension, direction, relativeTo, relativeAmount) {
ensure.signature(arguments, [ String, Number, Descriptor, [Number, Descriptor, Value] ]);
if (dimension === X_DIMENSION) PositionDescriptor.x(this);
else if (dimension === Y_DIMENSION) PositionDescriptor.y(this);
else ensure.unreachable("Unknown dimension: " + dimension);
this._dimension = dimension;
this._direction = direction;
this._relativeTo = relativeTo;
if (typeof relativeAmount === "number") {
if (relativeAmount < 0) this._direction *= -1;
this._amount = Size.create(Math.abs(relativeAmount));
}
else {
this._amount = relativeAmount;
}
};
PositionDescriptor.extend(Me);
Me.right = createFn(X_DIMENSION, PLUS);
Me.down = createFn(Y_DIMENSION, PLUS);
Me.left = createFn(X_DIMENSION, MINUS);
Me.up = createFn(Y_DIMENSION, MINUS);
function createFn(dimension, direction) {
return function create(relativeTo, relativeAmount) {
return new Me(dimension, direction, relativeTo, relativeAmount);
};
}
Me.prototype.value = function value() {
ensure.signature(arguments, []);
var baseValue = this._relativeTo.value();
var relativeValue = this._amount.value();
if (this._direction === PLUS) return baseValue.plus(relativeValue);
else return baseValue.minus(relativeValue);
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
var base = this._relativeTo.toString();
if (this._amount.equals(Size.create(0))) return base;
var relation = this._amount.toString();
if (this._dimension === X_DIMENSION) relation += (this._direction === PLUS) ? " to right of " : " to left of ";
else relation += (this._direction === PLUS) ? " below " : " above ";
return relation + base;
};
},{"../util/ensure.js":23,"../values/size.js":29,"../values/value.js":30,"./descriptor.js":5,"./position_descriptor.js":11}],13:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Size = require("../values/size.js");
var Descriptor = require("./descriptor.js");
var SizeDescriptor = require("./size_descriptor.js");
var Value = require("../values/value.js");
var SizeMultiple = require("./size_multiple.js");
var PLUS = 1;
var MINUS = -1;
var Me = module.exports = function RelativeSize(direction, relativeTo, amount) {
ensure.signature(arguments, [ Number, Descriptor, [Number, Descriptor, Value] ]);
this._direction = direction;
this._relativeTo = relativeTo;
if (typeof amount === "number") {
this._amount = Size.create(Math.abs(amount));
if (amount < 0) this._direction *= -1;
}
else {
this._amount = amount;
}
};
SizeDescriptor.extend(Me);
Me.larger = factoryFn(PLUS);
Me.smaller = factoryFn(MINUS);
Me.prototype.value = function value() {
ensure.signature(arguments, []);
var baseValue = this._relativeTo.value();
var relativeValue = this._amount.value();
if (this._direction === PLUS) return baseValue.plus(relativeValue);
else return baseValue.minus(relativeValue);
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
var base = this._relativeTo.toString();
if (this._amount.equals(Size.create(0))) return base;
var relation = this._amount.toString();
if (this._direction === PLUS) relation += " larger than ";
else relation += " smaller than ";
return relation + base;
};
function factoryFn(direction) {
return function factory(relativeTo, amount) {
return new Me(direction, relativeTo, amount);
};
}
},{"../util/ensure.js":23,"../values/size.js":29,"../values/value.js":30,"./descriptor.js":5,"./size_descriptor.js":14,"./size_multiple.js":15}],14:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
/*eslint new-cap: "off" */
"use strict";
var ensure = require("../util/ensure.js");
var oop = require("../util/oop.js");
var Descriptor = require("./descriptor.js");
var Size = require("../values/size.js");
function RelativeSize() {
return require("./relative_size.js"); // break circular dependency
}
function SizeMultiple() {
return require("./size_multiple.js"); // break circular dependency
}
var Me = module.exports = function SizeDescriptor() {
ensure.unreachable("SizeDescriptor is abstract and should not be constructed directly.");
};
Descriptor.extend(Me);
Me.extend = oop.extendFn(Me);
Me.prototype.plus = function plus(amount) {
return RelativeSize().larger(this, amount);
};
Me.prototype.minus = function minus(amount) {
return RelativeSize().smaller(this, amount);
};
Me.prototype.times = function times(amount) {
return SizeMultiple().create(this, amount);
};
Me.prototype.convert = function convert(arg, type) {
switch(type) {
case "number": return Size.create(arg);
case "string": return arg === "none" ? Size.createNone() : undefined;
default: return undefined;
}
};
},{"../util/ensure.js":23,"../util/oop.js":24,"../values/size.js":29,"./descriptor.js":5,"./relative_size.js":13,"./size_multiple.js":15}],15:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Descriptor = require("./descriptor.js");
var SizeDescriptor = require("./size_descriptor.js");
var Size = require("../values/size.js");
var Me = module.exports = function SizeMultiple(relativeTo, multiple) {
ensure.signature(arguments, [ Descriptor, Number ]);
this._relativeTo = relativeTo;
this._multiple = multiple;
};
SizeDescriptor.extend(Me);
Me.create = function create(relativeTo, multiple) {
return new Me(relativeTo, multiple);
};
Me.prototype.value = function value() {
ensure.signature(arguments, []);
return this._relativeTo.value().times(this._multiple);
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
var multiple = this._multiple;
var base = this._relativeTo.toString();
if (multiple === 1) return base;
var desc;
switch(multiple) {
case 1/2: desc = "half of "; break;
case 1/3: desc = "one-third of "; break;
case 2/3: desc = "two-thirds of "; break;
case 1/4: desc = "one-quarter of "; break;
case 3/4: desc = "three-quarters of "; break;
case 1/5: desc = "one-fifth of "; break;
case 2/5: desc = "two-fifths of "; break;
case 3/5: desc = "three-fifths of "; break;
case 4/5: desc = "four-fifths of "; break;
case 1/6: desc = "one-sixth of "; break;
case 5/6: desc = "five-sixths of "; break;
case 1/8: desc = "one-eighth of "; break;
case 3/8: desc = "three-eighths of "; break;
case 5/8: desc = "five-eighths of "; break;
case 7/8: desc = "seven-eighths of "; break;
default:
if (multiple > 1) desc = multiple + " times ";
else desc = (multiple * 100) + "% of ";
}
return desc + base;
};
},{"../util/ensure.js":23,"../values/size.js":29,"./descriptor.js":5,"./size_descriptor.js":14}],16:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var PositionDescriptor = require("./position_descriptor.js");
var Position = require("../values/position.js");
var TOP = "top";
var RIGHT = "right";
var BOTTOM = "bottom";
var LEFT = "left";
var Me = module.exports = function ViewportEdge(position, frame) {
var QFrame = require("../q_frame.js"); // break circular dependency
ensure.signature(arguments, [ String, QFrame ]);
if (position === LEFT || position === RIGHT) PositionDescriptor.x(this);
else if (position === TOP || position === BOTTOM) PositionDescriptor.y(this);
else ensure.unreachable("Unknown position: " + position);
this._position = position;
this._frame = frame;
};
PositionDescriptor.extend(Me);
Me.top = factoryFn(TOP);
Me.right = factoryFn(RIGHT);
Me.bottom = factoryFn(BOTTOM);
Me.left = factoryFn(LEFT);
Me.prototype.value = function() {
ensure.signature(arguments, []);
var scroll = this._frame.getRawScrollPosition();
var x = Position.x(scroll.x);
var y = Position.y(scroll.y);
var size = viewportSize(this._frame.get("html").toDomElement());
switch(this._position) {
case TOP: return y;
case RIGHT: return x.plus(Position.x(size.width));
case BOTTOM: return y.plus(Position.y(size.height));
case LEFT: return x;
default: ensure.unreachable();
}
};
Me.prototype.toString = function() {
ensure.signature(arguments, []);
return this._position + " edge of viewport";
};
function factoryFn(position) {
return function factory(frame) {
return new Me(position, frame);
};
}
// USEFUL READING: http://www.quirksmode.org/mobile/viewports.html
// and http://www.quirksmode.org/mobile/viewports2.html
// BROWSERS TESTED: Safari 6.2.0 (Mac OS X 10.8.5); Mobile Safari 7.0.0 (iOS 7.1); Firefox 32.0.0 (Mac OS X 10.8);
// Firefox 33.0.0 (Windows 7); Chrome 38.0.2125 (Mac OS X 10.8.5); Chrome 38.0.2125 (Windows 7); IE 8, 9, 10, 11
// Width techniques I've tried: (Note: results are different in quirks mode)
// body.clientWidth
// body.offsetWidth
// body.getBoundingClientRect().width
// fails on all browsers: doesn't include margin
// body.scrollWidth
// works on Safari, Mobile Safari, Chrome
// fails on Firefox, IE 8, 9, 10, 11: doesn't include margin
// html.getBoundingClientRect().width
// html.offsetWidth
// works on Safari, Mobile Safari, Chrome, Firefox
// fails on IE 8, 9, 10: includes scrollbar
// html.scrollWidth
// html.clientWidth
// WORKS! Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11
// Height techniques I've tried: (Note that results are different in quirks mode)
// body.clientHeight
// body.offsetHeight
// body.getBoundingClientRect().height
// fails on all browsers: only includes height of content
// body getComputedStyle("height")
// fails on all browsers: IE8 returns "auto"; others only include height of content
// body.scrollHeight
// works on Safari, Mobile Safari, Chrome;
// fails on Firefox, IE 8, 9, 10, 11: only includes height of content
// html.getBoundingClientRect().height
// html.offsetHeight
// works on IE 8, 9, 10
// fails on IE 11, Safari, Mobile Safari, Chrome: only includes height of content
// html.scrollHeight
// works on Firefox, IE 8, 9, 10, 11
// fails on Safari, Mobile Safari, Chrome: only includes height of content
// html.clientHeight
// WORKS! Safari, Mobile Safari, Chrome, Firefox, IE 8, 9, 10, 11
function viewportSize(htmlElement) {
return {
width: htmlElement.clientWidth,
height: htmlElement.clientHeight
};
}
},{"../q_frame.js":19,"../util/ensure.js":23,"../values/position.js":27,"./position_descriptor.js":11}],17:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var shim = require("./util/shim.js");
var camelcase = require("../vendor/camelcase-1.0.1-modified.js");
var ElementRendered = require("./descriptors/element_rendered.js");
var ElementEdge = require("./descriptors/element_edge.js");
var Center = require("./descriptors/center.js");
var GenericSize = require("./descriptors/generic_size.js");
var Assertable = require("./assertable.js");
var Me = module.exports = function QElement(domElement, frame, nickname) {
var QFrame = require("./q_frame.js"); // break circular dependency
ensure.signature(arguments, [Object, QFrame, String]);
this._domElement = domElement;
this._nickname = nickname;
this.frame = frame;
// properties
this.rendered = ElementRendered.create(this);
this.top = ElementEdge.top(this);
this.right = ElementEdge.right(this);
this.bottom = ElementEdge.bottom(this);
this.left = ElementEdge.left(this);
this.center = Center.x(this.left, this.right, "center of " + this);
this.middle = Center.y(this.top, this.bottom, "middle of " + this);
this.width = GenericSize.create(this.left, this.right, "width of " + this);
this.height = GenericSize.create(this.top, this.bottom, "height of " + this);
};
Assertable.extend(Me);
Me.prototype.getRawStyle = function(styleName) {
ensure.signature(arguments, [String]);
var styles;
var result;
// WORKAROUND IE 8: no getComputedStyle()
if (window.getComputedStyle) {
// WORKAROUND Firefox 40.0.3: must use frame's contentWindow (ref https://bugzilla.mozilla.org/show_bug.cgi?id=1204062)
styles = this.frame.toDomElement().contentWindow.getComputedStyle(this._domElement);
result = styles.getPropertyValue(styleName);
}
else {
styles = this._domElement.currentStyle;
result = styles[camelcase(styleName)];
}
if (result === null || result === undefined) result = "";
return result;
};
Me.prototype.getRawPosition = function() {
ensure.signature(arguments, []);
// WORKAROUND IE 8: No TextRectangle.height or .width
var rect = this._domElement.getBoundingClientRect();
return {
left: rect.left,
right: rect.right,
width: rect.width !== undefined ? rect.width : rect.right - rect.left,
top: rect.top,
bottom: rect.bottom,
height: rect.height !== undefined ? rect.height : rect.bottom - rect.top
};
};
Me.prototype.calculatePixelValue = function(sizeString) {
var dom = this._domElement;
if (dom.runtimeStyle !== undefined) return ie8Workaround();
var result;
var style = dom.style;
var oldPosition = style.position;
var oldLeft = style.left;
style.position = "absolute";
style.left = sizeString;
result = parseFloat(this.getRawStyle("left")); // parseInt strips of 'px' value
style.position = oldPosition;
style.left = oldLeft;
return result;
// WORKAROUND IE 8: getRawStyle() doesn't normalize values to px
// Based on code by Dean Edwards: http://disq.us/p/myl99x
function ie8Workaround() {
var runtimeStyleLeft = dom.runtimeStyle.left;
var styleLeft = dom.style.left;
dom.runtimeStyle.left = dom.currentStyle.left;
dom.style.left = sizeString;
result = dom.style.pixelLeft;
dom.runtimeStyle.left = runtimeStyleLeft;
dom.style.left = styleLeft;
return result;
}
};
Me.prototype.parent = function(nickname) {
ensure.signature(arguments, [[ undefined, String ]]);
if (nickname === undefined) nickname = "parent of " + this._nickname;
if (this.equals(this.frame.body())) return null;
var parent = this._domElement.parentElement;
if (parent === null) return null;
return new Me(parent, this.frame, nickname);
};
Me.prototype.add = function(html, nickname) {
ensure.signature(arguments, [String, [undefined, String]]);
if (nickname === undefined) nickname = html + " in " + this._nickname;
var tempElement = document.createElement("div");
tempElement.innerHTML = shim.String.trim(html);
ensure.that(
tempElement.childNodes.length === 1,
"Expected one element, but got " + tempElement.childNodes.length + " (" + html + ")"
);
var insertedElement = tempElement.childNodes[0];
this._domElement.appendChild(insertedElement);
return new Me(insertedElement, this.frame, nickname);
};
Me.prototype.remove = function() {
ensure.signature(arguments, []);
shim.Element.remove(this._domElement);
};
Me.prototype.toDomElement = function() {
ensure.signature(arguments, []);
return this._domElement;
};
Me.prototype.toString = function() {
ensure.signature(arguments, []);
return "'" + this._nickname + "'";
};
Me.prototype.equals = function(that) {
ensure.signature(arguments, [Me]);
return this._domElement === that._domElement;
};
},{"../vendor/camelcase-1.0.1-modified.js":32,"./assertable.js":2,"./descriptors/center.js":4,"./descriptors/element_edge.js":6,"./descriptors/element_rendered.js":7,"./descriptors/generic_size.js":9,"./q_frame.js":19,"./util/ensure.js":23,"./util/shim.js":25}],18:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var QElement = require("./q_element.js");
var Me = module.exports = function QElementList(nodeList, frame, nickname) {
var QFrame = require("./q_frame.js"); // break circular dependency
ensure.signature(arguments, [ Object, QFrame, String ]);
this._nodeList = nodeList;
this._frame = frame;
this._nickname = nickname;
};
Me.prototype.length = function length() {
ensure.signature(arguments, []);
return this._nodeList.length;
};
Me.prototype.at = function at(requestedIndex, nickname) {
ensure.signature(arguments, [ Number, [undefined, String] ]);
var index = requestedIndex;
var length = this.length();
if (index < 0) index = length + index;
ensure.that(
index >= 0 && index < length,
"'" + this._nickname + "'[" + requestedIndex + "] is out of bounds; list length is " + length
);
var element = this._nodeList[index];
if (nickname === undefined) nickname = this._nickname + "[" + index + "]";
return new QElement(element, this._frame, nickname);
};
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
return "'" + this._nickname + "' list";
};
},{"./q_element.js":17,"./q_frame.js":19,"./util/ensure.js":23}],19:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var shim = require("./util/shim.js");
var quixote = require("./quixote.js");
var QElement = require("./q_element.js");
var QElementList = require("./q_element_list.js");
var QViewport = require("./q_viewport.js");
var QPage = require("./q_page.js");
var async = require("../vendor/async-1.4.2.js");
var Me = module.exports = function QFrame() {
ensure.signature(arguments, []);
this._domElement = null;
this._loaded = false;
this._removed = false;
};
function loaded(self, width, height, src, stylesheets) {
self._loaded = true;
self._document = self._domElement.contentDocument;
self._originalBody = self._document.body.innerHTML;
self._originalWidth = width;
self._originalHeight = height;
self._originalSrc = src;
self._originalStylesheets = stylesheets;
}
Me.create = function create(parentElement, options, callback) {
ensure.signature(arguments, [Object, [Object, Function], [undefined, Function]]);
if (callback === undefined) {
callback = options;
options = {};
}
var width = options.width || 2000;
var height = options.height || 2000;
var src = options.src;
var stylesheets = options.stylesheet || [];
var css = options.css;
if (!shim.Array.isArray(stylesheets)) stylesheets = [ stylesheets ];
var frame = new Me();
checkUrls(src, stylesheets, function(err) {
if (err) return callback(err);
var iframe = insertIframe(parentElement, width, height);
shim.EventTarget.addEventListener(iframe, "load", onFrameLoad);
setIframeContent(iframe, src);
frame._domElement = iframe;
setFrameLoadCallback(frame, callback);
});
return frame;
function onFrameLoad() {
// WORKAROUND Mobile Safari 7.0.0, Safari 6.2.0, Chrome 38.0.2125: frame is loaded synchronously
// We force it to be asynchronous here
setTimeout(function() {
loaded(frame, width, height, src, stylesheets);
loadStylesheets(frame, stylesheets, function() {
if (css) loadRawCSS(frame, options.css);
frame._frameLoadCallback(null, frame);
});
}, 0);
}
};
function setFrameLoadCallback(frame, callback) {
frame._frameLoadCallback = callback;
}
function checkUrls(src, stylesheets, callback) {
urlExists(src, function(err, srcExists) {
if (err) return callback(err);
if (!srcExists) return callback(error("src", src));
async.each(stylesheets, checkStylesheet, callback);
});
function checkStylesheet(url, callback2) {
urlExists(url, function(err, stylesheetExists) {
if (err) return callback2(err);
if (!stylesheetExists) return callback2(error("stylesheet", url));
else return callback2(null);
});
}
function error(name, url) {
return new Error("404 error while loading " + name + " (" + url + ")");
}
}
function urlExists(url, callback) {
var STATUS_AVAILABLE = 2; // WORKAROUND IE 8: non-standard XMLHttpRequest constant names
if (url === undefined) {
return callback(null, true);
}
var http = new XMLHttpRequest();
http.open("HEAD", url);
http.onreadystatechange = function() { // WORKAROUND IE 8: doesn't support .addEventListener() or .onload
if (http.readyState === STATUS_AVAILABLE) {
return callback(null, http.status !== 404);
}
};
http.onerror = function() { // onerror handler is not tested
return callback("XMLHttpRequest error while using HTTP HEAD on URL '" + url + "': " + http.statusText);
};
http.send();
}
function insertIframe(parentElement, width, height) {
var iframe = document.createElement("iframe");
iframe.setAttribute("width", width);
iframe.setAttribute("height", height);
iframe.setAttribute("frameborder", "0"); // WORKAROUND IE 8: don't include frame border in position calcs
parentElement.appendChild(iframe);
return iframe;
}
function setIframeContent(iframe, src) {
if (src === undefined) {
writeStandardsModeHtml(iframe);
} else {
setIframeSrc(iframe, src);
}
}
function setIframeSrc(iframe, src) {
iframe.setAttribute("src", src);
}
function writeStandardsModeHtml(iframe) {
var standardsMode = "<!DOCTYPE html>\n<html><head></head><body></body></html>";
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(standardsMode);
iframe.contentWindow.document.close();
}
function loadStylesheets(self, urls, callback) {
async.each(urls, addLinkTag, callback);
function addLinkTag(url, onLinkLoad) {
var link = document.createElement("link");
shim.EventTarget.addEventListener(link, "load", function(event) { onLinkLoad(null); });
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", url);
shim.Document.head(self._document).appendChild(link);
}
}
function loadRawCSS(self, css) {
var style = document.createElement("style");
style.setAttribute("type", "text/css");
if (style.styleSheet) {
// WORKAROUND IE 8: Throws 'unknown runtime error' if you set innerHTML on a <style> tag
style.styleSheet.cssText = css;
}
else {
style.innerHTML = css;
}
shim.Document.head(self._document).appendChild(style);
}
Me.prototype.reset = function() {
ensure.signature(arguments, []);
ensureUsable(this);
this._document.body.innerHTML = this._originalBody;
this.scroll(0, 0);
this.resize(this._originalWidth, this._originalHeight);
};
Me.prototype.reload = function(callback) {
ensure.signature(arguments, [Function]);
ensureUsable(this);
var frame = this;
var iframe = this._domElement;
var src = this._originalSrc;
this.resize(this._originalWidth, this._originalHeight);
setFrameLoadCallback(frame, callback);
setIframeContent(iframe, src);
};
Me.prototype.toDomElement = function() {
ensure.signature(arguments, []);
ensureUsable(this);
return this._domElement;
};
Me.prototype.remove = function() {
ensure.signature(arguments, []);
ensureLoaded(this);
if (this._removed) return;
this._domElement.parentNode.removeChild(this._domElement);
this._removed = true;
};
Me.prototype.viewport = function() {
ensure.signature(arguments, []);
ensureUsable(this);
return new QViewport(this);
};
Me.prototype.page = function() {
ensure.signature(arguments, []);
ensureUsable(this);
return new QPage(this);
};
Me.prototype.body = function() {
ensure.signature(arguments, []);
return this.get("body");
};
Me.prototype.add = function(html, nickname) {
ensure.signature(arguments, [String, [undefined, String]]);
if (nickname === undefined) nickname = html;
return this.body().add(html, nickname);
};
Me.prototype.get = function(selector, nickname) {
ensure.signature(arguments, [String, [undefined, String]]);
if (nickname === undefined) nickname = selector;
ensureUsable(this);
var nodes = this._document.querySelectorAll(selector);
ensure.that(nodes.length === 1, "Expected one element to match '" + selector + "', but found " + nodes.length);
return new QElement(nodes[0], this, nickname);
};
Me.prototype.getAll = function(selector, nickname) {
ensure.signature(arguments, [String, [undefined, String]]);
if (nickname === undefined) nickname = selector;
ensureUsable(this);
return new QElementList(this._document.querySelectorAll(selector), this, nickname);
};
Me.prototype.scroll = function scroll(x, y) {
ensure.signature(arguments, [Number, Number]);
ensureUsable(this);
this._domElement.contentWindow.scroll(x, y);
};
Me.prototype.getRawScrollPosition = function getRawScrollPosition() {
ensure.signature(arguments, []);
ensureUsable(this);
return {
x: shim.Window.pageXOffset(this._domElement.contentWindow, this._document),
y: shim.Window.pageYOffset(this._domElement.contentWindow, this._document)
};
};
Me.prototype.resize = function resize(width, height) {
ensure.signature(arguments, [Number, Number]);
ensureUsable(this);
this._domElement.setAttribute("width", "" + width);
this._domElement.setAttribute("height", "" + height);
};
function ensureUsable(self) {
ensureLoaded(self);
ensureNotRemoved(self);
}
function ensureLoaded(self) {
ensure.that(self._loaded, "QFrame not loaded: Wait for frame creation callback to execute before using frame");
}
function ensureNotRemoved(self) {
ensure.that(!self._removed, "Attempted to use frame after it was removed");
}
},{"../vendor/async-1.4.2.js":31,"./q_element.js":17,"./q_element_list.js":18,"./q_page.js":20,"./q_viewport.js":21,"./quixote.js":22,"./util/ensure.js":23,"./util/shim.js":25}],20:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var PageEdge = require("./descriptors/page_edge.js");
var Center = require("./descriptors/center.js");
var Assertable = require("./assertable.js");
var GenericSize = require("./descriptors/generic_size.js");
var Me = module.exports = function QPage(frame) {
var QFrame = require("./q_frame.js"); // break circular dependency
ensure.signature(arguments, [ QFrame ]);
// properties
this.top = PageEdge.top(frame);
this.right = PageEdge.right(frame);
this.bottom = PageEdge.bottom(frame);
this.left = PageEdge.left(frame);
this.width = GenericSize.create(this.left, this.right, "width of page");
this.height = GenericSize.create(this.top, this.bottom, "height of page");
this.center = Center.x(this.left, this.right, "center of page");
this.middle = Center.y(this.top, this.bottom, "middle of page");
};
Assertable.extend(Me);
},{"./assertable.js":2,"./descriptors/center.js":4,"./descriptors/generic_size.js":9,"./descriptors/page_edge.js":10,"./q_frame.js":19,"./util/ensure.js":23}],21:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var ViewportEdge = require("./descriptors/viewport_edge.js");
var Center = require("./descriptors/center.js");
var Assertable = require("./assertable.js");
var GenericSize = require("./descriptors/generic_size.js");
var Me = module.exports = function QViewport(frame) {
var QFrame = require("./q_frame.js"); // break circular dependency
ensure.signature(arguments, [ QFrame ]);
// properties
this.top = ViewportEdge.top(frame);
this.right = ViewportEdge.right(frame);
this.bottom = ViewportEdge.bottom(frame);
this.left = ViewportEdge.left(frame);
this.width = GenericSize.create(this.left, this.right, "width of viewport");
this.height = GenericSize.create(this.top, this.bottom, "height of viewport");
this.center = Center.x(this.left, this.right, "center of viewport");
this.middle = Center.y(this.top, this.bottom, "middle of viewport");
};
Assertable.extend(Me);
},{"./assertable.js":2,"./descriptors/center.js":4,"./descriptors/generic_size.js":9,"./descriptors/viewport_edge.js":16,"./q_frame.js":19,"./util/ensure.js":23}],22:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("./util/ensure.js");
var QFrame = require("./q_frame.js");
var Size = require("./values/size.js");
var features = null;
exports.createFrame = function(options, callback) {
return QFrame.create(document.body, options, function(err, callbackFrame) {
if (features === null) {
detectBrowserFeatures(function() {
callback(err, callbackFrame);
});
}
else {
callback(err, callbackFrame);
}
});
};
exports.browser = {};
exports.browser.enlargesFrameToPageSize = createDetectionMethod("enlargesFrame");
exports.browser.enlargesFonts = createDetectionMethod("enlargesFonts");
exports.browser.misreportsClipAutoProperty = createDetectionMethod("misreportsClipAuto");
exports.browser.misreportsAutoValuesInClipProperty = createDetectionMethod("misreportsClipValues");
exports.browser.roundsOffPixelCalculations = createDetectionMethod("roundsOffPixelCalculations");
function createDetectionMethod(propertyName) {
return function() {
ensure.signature(arguments, []);
ensure.that(features !== null, "Must create a frame before using Quixote browser feature detection.");
return features[propertyName];
};
}
function detectBrowserFeatures(callback) {
var FRAME_WIDTH = 1500;
var FRAME_HEIGHT = 200;
features = {};
var frame = QFrame.create(document.body, { width: FRAME_WIDTH, height: FRAME_HEIGHT }, function(err) {
if (err) {
console.log("Error while creating Quixote browser feature detection frame: " + err);
return callback();
}
try {
features.enlargesFrame = detectFrameEnlargement(frame, FRAME_WIDTH);
features.misreportsClipAuto = detectReportedClipAuto(frame);
features.misreportsClipValues = detectReportedClipPropertyValues(frame);
features.roundsOffPixelCalculations = detectRoundsOffPixelCalculations(frame);
frame.reset();
detectFontEnlargement(frame, FRAME_WIDTH, function(result) {
features.enlargesFonts = result;
frame.remove();
return callback();
});
}
catch(err2) {
console.log("Error during Quixote browser feature detection: " + err2);
}
});
}
function detectFrameEnlargement(frame, frameWidth) {
frame.add("<div style='width: " + (frameWidth + 200) + "px'>force scrolling</div>");
return !frame.viewport().width.value().equals(Size.create(frameWidth));
}
function detectFontEnlargement(frame, frameWidth, callback) {
ensure.that(frameWidth >= 1500, "Detector frame width must be larger than screen to detect font enlargement");
// WORKAROUND IE 8: we use a <div> because the <style> tag can't be added by frame.add(). At the time of this
// writing, I'm not sure if the issue is with frame.add() or if IE just can't programmatically add <style> tags.
frame.add("<div><style>p { font-size: 15px; }</style></div>");
var text = frame.add("<p>arbitrary text</p>");
frame.add("<p>must have two p tags to work</p>");
// WORKAROUND IE 8: need to force reflow or getting font-size may fail below
// This seems to occur when IE is running in a slow VirtualBox VM. There is no test for this line.
var forceReflow = text.offsetHeight;
// WORKAROUND Safari 8.0.0: timeout required because font is enlarged asynchronously
setTimeout(function() {
var fontSize = text.getRawStyle("font-size");
ensure.that(fontSize !== "", "Expected font-size to be a value");
// WORKAROUND IE 8: ignores <style> tag we added above
if (fontSize === "12pt") return callback(false);
return callback(fontSize !== "15px");
}, 0);
}
function detectReportedClipAuto(frame) {
var element = frame.add("<div style='clip: auto;'></div>");
var clip = element.getRawStyle("clip");
return clip !== "auto";
}
function detectReportedClipPropertyValues(frame) {
var element = frame.add("<div style='clip: rect(auto, auto, auto, auto);'></div>");
var clip = element.getRawStyle("clip");
// WORKAROUND IE 8: Provides 'clipTop' etc. instead of 'clip' property
if (clip === "" && element.getRawStyle("clip-top") === "auto") return false;
return clip !== "rect(auto, auto, auto, auto)" && clip !== "rect(auto auto auto auto)";
}
function detectRoundsOffPixelCalculations(frame) {
var element = frame.add("<div style='font-size: 15px;'></div>");
var size = element.calculatePixelValue("0.5em");
if (size === 7.5) return false;
if (size === 8) return true;
ensure.unreachable("Failure in roundsOffPixelValues() detection: expected 7.5 or 8, but got " + size);
}
},{"./q_frame.js":19,"./util/ensure.js":23,"./values/size.js":29}],23:[function(require,module,exports){
// Copyright (c) 2013-2014 Titanium I.T. LLC. All rights reserved. See LICENSE.TXT for details.
"use strict";
// Runtime assertions for production code. (Contrast to assert.js, which is for test code.)
var shim = require("./shim.js");
var oop = require("./oop.js");
exports.that = function(variable, message) {
if (message === undefined) message = "Expected condition to be true";
if (variable === false) throw new EnsureException(exports.that, message);
if (variable !== true) throw new EnsureException(exports.that, "Expected condition to be true or false");
};
exports.unreachable = function(message) {
if (!message) message = "Unreachable code executed";
throw new EnsureException(exports.unreachable, message);
};
exports.signature = function(args, signature) {
signature = signature || [];
var expectedArgCount = signature.length;
var actualArgCount = args.length;
if (actualArgCount > expectedArgCount) {
throw new EnsureException(
exports.signature,
"Function called with too many arguments: expected " + expectedArgCount + " but got " + actualArgCount
);
}
var arg, types, name;
for (var i = 0; i < signature.length; i++) {
arg = args[i];
types = signature[i];
name = "Argument #" + (i + 1);
if (!shim.Array.isArray(types)) types = [ types ];
if (!argMatchesAnyPossibleType(arg, types)) {
var message = name + " expected " + explainPossibleTypes(types) + ", but was " + explainArg(arg);
throw new EnsureException(exports.signature, message);
}
}
};
function argMatchesAnyPossibleType(arg, type) {
for (var i = 0; i < type.length; i++) {
if (argMatchesType(arg, type[i])) return true;
}
return false;
function argMatchesType(arg, type) {
switch (getArgType(arg)) {
case "boolean": return type === Boolean;
case "string": return type === String;
case "number": return type === Number;
case "array": return type === Array;
case "function": return type === Function;
case "object": return type === Object || arg instanceof type;
case "undefined": return type === undefined;
case "null": return type === null;
case "NaN": return typeof(type) === "number" && isNaN(type);
default: exports.unreachable();
}
}
}
function explainPossibleTypes(type) {
var joiner = "";
var result = "";
for (var i = 0; i < type.length; i++) {
result += joiner + explainOneType(type[i]);
joiner = (i === type.length - 2) ? ", or " : ", ";
}
return result;
function explainOneType(type) {
switch (type) {
case Boolean: return "boolean";
case String: return "string";
case Number: return "number";
case Array: return "array";
case Function: return "function";
case null: return "null";
case undefined: return "undefined";
default:
if (typeof type === "number" && isNaN(type)) return "NaN";
else {
return oop.className(type) + " instance";
}
}
}
}
function explainArg(arg) {
var type = getArgType(arg);
if (type !== "object") return type;
return oop.instanceName(arg) + " instance";
}
function getArgType(variable) {
var type = typeof variable;
if (variable === null) type = "null";
if (shim.Array.isArray(variable)) type = "array";
if (type === "number" && isNaN(variable)) type = "NaN";
return type;
}
/*****/
var EnsureException = exports.EnsureException = function EnsureException(fnToRemoveFromStackTrace, message) {
if (Error.captureStackTrace) Error.captureStackTrace(this, fnToRemoveFromStackTrace);
else this.stack = (new Error()).stack;
this.message = message;
};
EnsureException.prototype = shim.Object.create(Error.prototype);
EnsureException.prototype.constructor = EnsureException;
EnsureException.prototype.name = "EnsureException";
},{"./oop.js":24,"./shim.js":25}],24:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
// can't use ensure.js due to circular dependency
var shim = require("./shim.js");
exports.className = function(constructor) {
if (typeof constructor !== "function") throw new Error("Not a constructor");
return shim.Function.name(constructor);
};
exports.instanceName = function(obj) {
var prototype = shim.Object.getPrototypeOf(obj);
if (prototype === null) return "<no prototype>";
var constructor = prototype.constructor;
if (constructor === undefined || constructor === null) return "<anon>";
return shim.Function.name(constructor);
};
exports.extendFn = function extendFn(parentConstructor) {
return function(childConstructor) {
childConstructor.prototype = shim.Object.create(parentConstructor.prototype);
childConstructor.prototype.constructor = childConstructor;
};
};
exports.makeAbstract = function makeAbstract(constructor, methods) {
var name = shim.Function.name(constructor);
shim.Array.forEach(methods, function(method) {
constructor.prototype[method] = function() {
throw new Error(name + " subclasses must implement " + method + "() method");
};
});
constructor.prototype.checkAbstractMethods = function checkAbstractMethods() {
var unimplemented = [];
var self = this;
shim.Array.forEach(methods, function(name) {
if (self[name] === constructor.prototype[name]) unimplemented.push(name + "()");
});
return unimplemented;
};
};
},{"./shim.js":25}],25:[function(require,module,exports){
// Copyright (c) 2014-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
/*eslint eqeqeq: "off", no-eq-null: "off", no-bitwise: "off" */
"use strict";
exports.Array = {
// WORKAROUND IE 8: no Array.isArray
isArray: function isArray(thing) {
if (Array.isArray) return Array.isArray(thing);
return Object.prototype.toString.call(thing) === '[object Array]';
},
// WORKAROUND IE 8: no Array.every
every: function every(obj, callbackfn, thisArg) {
/*jshint bitwise:false, eqeqeq:false, -W041:false */
if (Array.prototype.every) return obj.every(callbackfn, thisArg);
// This workaround based on polyfill code from MDN:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
var T, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the this
// value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method
// of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (typeof callbackfn !== 'function') {
throw new TypeError();
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0.
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method
// of O with argument Pk.
kValue = O[k];
// ii. Let testResult be the result of calling the Call internal method
// of callbackfn with T as the this value and argument list
// containing kValue, k, and O.
var testResult = callbackfn.call(T, kValue, k, O);
// iii. If ToBoolean(testResult) is false, return false.
if (!testResult) {
return false;
}
}
k++;
}
return true;
},
// WORKAROUND IE 8: no Array.forEach
forEach: function forEach(obj, callback, thisArg) {
/*jshint bitwise:false, eqeqeq:false, -W041:false */
if (Array.prototype.forEach) return obj.forEach(callback, thisArg);
// This workaround based on polyfill code from MDN:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
var T, k;
if (obj == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(obj);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
}
};
exports.Document = {
// WORKAROUND IE 8: no document.head
head: function head(doc) {
if (doc.head) return doc.head;
return doc.querySelector("head");
}
};
exports.Element = {
// WORKAROUND IE 8, IE 9, IE 10, IE 11: no Element.remove()
remove: function remove(element) {
element.parentNode.removeChild(element);
}
};
exports.EventTarget = {
// WORKAROUND IE 8: no EventTarget.addEventListener()
addEventListener: function addEventListener(element, event, callback) {
if (element.addEventListener) return element.addEventListener(event, callback);
element.attachEvent("on" + event, callback);
}
};
exports.Function = {
// WORKAROUND IE 8, IE 9, IE 10, IE 11: no function.name
name: function name(fn) {
if (fn.name) return fn.name;
// Based on code by Jason Bunting et al, http://stackoverflow.com/a/332429
var funcNameRegex = /function\s+(.{1,})\s*\(/;
var results = (funcNameRegex).exec((fn).toString());
return (results && results.length > 1) ? results[1] : "<anon>";
},
};
exports.Object = {
// WORKAROUND IE 8: no Object.create()
create: function create(prototype) {
if (Object.create) return Object.create(prototype);
var Temp = function Temp() {};
Temp.prototype = prototype;
return new Temp();
},
// WORKAROUND IE 8: no Object.getPrototypeOf
// Caution: Doesn't work on IE 8 if constructor has been changed, as is the case with a subclass.
getPrototypeOf: function getPrototypeOf(obj) {
if (Object.getPrototypeOf) return Object.getPrototypeOf(obj);
var result = obj.constructor ? obj.constructor.prototype : null;
return result || null;
},
// WORKAROUND IE 8: No Object.keys
keys: function keys(obj) {
if (Object.keys) return Object.keys(obj);
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
}
};
exports.String = {
// WORKAROUND IE 8: No String.trim()
trim: function(str) {
if (str.trim !== undefined) return str.trim();
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
}
};
exports.Window = {
// WORKAROUND IE 8: No Window.pageXOffset
pageXOffset: function(window, document) {
if (window.pageXOffset !== undefined) return window.pageXOffset;
// Based on https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
return isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
},
// WORKAROUND IE 8: No Window.pageYOffset
pageYOffset: function(window, document) {
if (window.pageYOffset !== undefined) return window.pageYOffset;
// Based on https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
return isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
}
};
},{}],26:[function(require,module,exports){
// Copyright (c) 2014-2016 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Value = require("./value.js");
var Me = module.exports = function Pixels(amount) {
ensure.signature(arguments, [ [ Number, null ] ]);
this._none = (amount === null);
this._amount = amount;
};
Value.extend(Me);
Me.create = function create(amount) {
return new Me(amount);
};
Me.createNone = function createNone() {
return new Me(null);
};
Me.ZERO = Me.create(0);
Me.NONE = Me.createNone();
Me.prototype.compatibility = function compatibility() {
return [ Me ];
};
Me.prototype.plus = Value.safe(function plus(operand) {
if (this._none || operand._none) return Me.createNone();
return new Me(this._amount + operand._amount);
});
Me.prototype.minus = Value.safe(function minus(operand) {
if (this._none || operand._none) return Me.createNone();
return new Me(this._amount - operand._amount);
});
Me.prototype.difference = Value.safe(function difference(operand) {
if (this._none || operand._none) return Me.createNone();
return new Me(Math.abs(this._amount - operand._amount));
});
Me.prototype.times = function times(operand) {
ensure.signature(arguments, [ Number ]);
if (this._none) return Me.createNone();
return new Me(this._amount * operand);
};
Me.prototype.average = Value.safe(function average(operand) {
if (this._none || operand._none) return Me.createNone();
return new Me((this._amount + operand._amount) / 2);
});
Me.prototype.compare = Value.safe(function compare(operand) {
var bothHavePixels = !this._none && !operand._none;
var neitherHavePixels = this._none && operand._none;
var onlyLeftHasPixels = !this._none && operand._none;
if (bothHavePixels) {
var difference = this._amount - operand._amount;
if (Math.abs(difference) <= 0.5) return 0;
else return difference;
}
else if (neitherHavePixels) {
return 0;
}
else if (onlyLeftHasPixels) {
return 1;
}
else {
return -1;
}
});
Me.min = function(l, r) {
ensure.signature(arguments, [ Me, Me ]);
if (l._none || r._none) return Me.createNone();
return l.compare(r) <= 0 ? l : r;
};
Me.max = function(l, r) {
ensure.signature(arguments, [ Me, Me ]);
if (l._none || r._none) return Me.createNone();
return l.compare(r) >= 0 ? l : r;
};
Me.prototype.diff = Value.safe(function diff(expected) {
if (this.compare(expected) === 0) return "";
if (this._none || expected._none) return "non-measurable";
var difference = Math.abs(this._amount - expected._amount);
var desc = difference;
if (difference * 100 !== Math.floor(difference * 100)) desc = "about " + difference.toFixed(2);
return desc + "px";
});
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
return this._none ? "no pixels" : this._amount + "px";
};
},{"../util/ensure.js":23,"./value.js":30}],27:[function(require,module,exports){
// Copyright (c) 2014-2016 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Value = require("./value.js");
var Pixels = require("./pixels.js");
var Size = require("./size.js");
var X_DIMENSION = "x";
var Y_DIMENSION = "y";
var Me = module.exports = function Position(dimension, value) {
ensure.signature(arguments, [ String, [ Number, Pixels ] ]);
this._dimension = dimension;
this._value = (typeof value === "number") ? Pixels.create(value) : value;
};
Value.extend(Me);
Me.x = function x(value) {
ensure.signature(arguments, [ [ Number, Pixels ] ]);
return new Me(X_DIMENSION, value);
};
Me.y = function y(value) {
ensure.signature(arguments, [ [ Number, Pixels ] ]);
return new Me(Y_DIMENSION, value);
};
Me.noX = function noX() {
ensure.signature(arguments, []);
return new Me(X_DIMENSION, Pixels.NONE);
};
Me.noY = function noY() {
ensure.signature(arguments, []);
return new Me(Y_DIMENSION, Pixels.NONE);
};
Me.prototype.compatibility = function compatibility() {
return [ Me, Size ];
};
Me.prototype.distanceTo = function(operand) {
ensure.signature(arguments, [ Me ]);
checkAxis(this, operand);
return Size.create(this._value.difference(operand.toPixels()));
};
Me.prototype.plus = Value.safe(function plus(operand) {
checkAxis(this, operand);
return new Me(this._dimension, this._value.plus(operand.toPixels()));
});
Me.prototype.minus = Value.safe(function minus(operand) {
checkAxis(this, operand);
return new Me(this._dimension, this._value.minus(operand.toPixels()));
});
Me.prototype.midpoint = Value.safe(function midpoint(operand) {
checkAxis(this, operand);
return new Me(this._dimension, this._value.average(operand.toPixels()));
});
Me.prototype.compare = Value.safe(function compare(operand) {
checkAxis(this, operand);
return this._value.compare(operand.toPixels());
});
Me.prototype.min = Value.safe(function min(operand) {
checkAxis(this, operand);
return new Me(this._dimension, Pixels.min(this._value, operand.toPixels()));
});
Me.prototype.max = Value.safe(function max(operand) {
checkAxis(this, operand);
return new Me(this._dimension, Pixels.max(this._value, operand.toPixels()));
});
Me.prototype.diff = Value.safe(function diff(expected) {
ensure.signature(arguments, [ Me ]);
checkAxis(this, expected);
var actualValue = this._value;
var expectedValue = expected._value;
if (actualValue.equals(expectedValue)) return "";
else if (isNone(expected) && !isNone(this)) return "rendered when not expected";
else if (!isNone(expected) && isNone(this)) return "not rendered";
var direction;
var comparison = actualValue.compare(expectedValue);
if (this._dimension === X_DIMENSION) direction = comparison < 0 ? "further left than expected" : "further right than expected";
else direction = comparison < 0 ? "higher than expected" : "lower than expected";
return actualValue.diff(expectedValue) + " " + direction;
});
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
if (isNone(this)) return "not rendered";
else return this._value.toString();
};
Me.prototype.toPixels = function toPixels() {
ensure.signature(arguments, []);
return this._value;
};
function checkAxis(self, other) {
if (other instanceof Me) {
ensure.that(self._dimension === other._dimension, "Can't compare X coordinate to Y coordinate");
}
}
function isNone(position) {
return position._value.equals(Pixels.NONE);
}
},{"../util/ensure.js":23,"./pixels.js":26,"./size.js":29,"./value.js":30}],28:[function(require,module,exports){
// Copyright (c) 2016-2017 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Value = require("./value.js");
var RENDERED = "rendered";
var NOT_RENDERED = "not rendered";
var Me = module.exports = function RenderState(state) {
ensure.signature(arguments, [ String ]);
this._state = state;
};
Value.extend(Me);
Me.rendered = function rendered() {
return new Me(RENDERED);
};
Me.notRendered = function notRendered() {
return new Me(NOT_RENDERED);
};
Me.prototype.compatibility = function compatibility() {
return [ Me ];
};
Me.prototype.diff = Value.safe(function diff(expected) {
var thisState = this._state;
var expectedState = expected._state;
if (thisState === expectedState) return "";
else return "different than expected";
});
Me.prototype.toString = function toString() {
return this._state;
};
},{"../util/ensure.js":23,"./value.js":30}],29:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var Value = require("./value.js");
var Pixels = require("./pixels.js");
var Me = module.exports = function Size(value) {
ensure.signature(arguments, [ [Number, Pixels] ]);
this._value = (typeof value === "number") ? Pixels.create(value) : value;
};
Value.extend(Me);
Me.create = function create(value) {
return new Me(value);
};
Me.createNone = function createNone() {
ensure.signature(arguments, []);
return new Me(Pixels.NONE);
};
Me.prototype.compatibility = function compatibility() {
return [ Me ];
};
Me.prototype.plus = Value.safe(function plus(operand) {
return new Me(this._value.plus(operand._value));
});
Me.prototype.minus = Value.safe(function minus(operand) {
return new Me(this._value.minus(operand._value));
});
Me.prototype.times = function times(operand) {
return new Me(this._value.times(operand));
};
Me.prototype.compare = Value.safe(function compare(that) {
return this._value.compare(that._value);
});
Me.prototype.diff = Value.safe(function diff(expected) {
var actualValue = this._value;
var expectedValue = expected._value;
if (actualValue.equals(expectedValue)) return "";
if (isNone(expected) && !isNone(this)) return "rendered when not expected";
if (!isNone(expected) && isNone(this)) return "not rendered";
var desc = actualValue.compare(expectedValue) > 0 ? " larger than expected" : " smaller than expected";
return actualValue.diff(expectedValue) + desc;
});
Me.prototype.toString = function toString() {
ensure.signature(arguments, []);
if (isNone(this)) return "not rendered";
else return this._value.toString();
};
Me.prototype.toPixels = function toPixels() {
ensure.signature(arguments, []);
return this._value;
};
function isNone(size) {
return size._value.equals(Pixels.NONE);
}
},{"../util/ensure.js":23,"./pixels.js":26,"./value.js":30}],30:[function(require,module,exports){
// Copyright (c) 2014 Titanium I.T. LLC. All rights reserved. For license, see "README" or "LICENSE" file.
"use strict";
var ensure = require("../util/ensure.js");
var oop = require("../util/oop.js");
var shim = require("../util/shim.js");
var Me = module.exports = function Value() {};
Me.extend = oop.extendFn(Me);
oop.makeAbstract(Me, [
"compatibility",
"diff",
"toString"
]);
Me.safe = function safe(fn) {
return function() {
ensureCompatibility(this, this.compatibility(), arguments);
return fn.apply(this, arguments);
};
};
Me.prototype.value = function value() {
ensure.signature(arguments, []);
return this;
};
Me.prototype.equals = function equals(that) {
return this.diff(that) === "";
};
function ensureCompatibility(self, compatible, args) {
var arg;
for (var i = 0; i < args.length; i++) { // args is not an Array, can't use forEach
arg = args[i];
checkOneArg(self, compatible, arg);
}
}
function checkOneArg(self, compatible, arg) {
var type = typeof arg;
if (arg === null) type = "null";
if (type !== "object") throwError(type);
for (var i = 0; i < compatible.length; i++) {
if (arg instanceof compatible[i]) return;
}
throwError(oop.instanceName(arg));
function throwError(type) {
throw new Error(oop.instanceName(self) + " isn't compatible with " + type);
}
}
},{"../util/ensure.js":23,"../util/oop.js":24,"../util/shim.js":25}],31:[function(require,module,exports){
(function (process,global){
/*!
* async
* https://github.com/caolan/async
*
* Copyright 2010-2014 Caolan McMahon
* Released under the MIT license
*/
(function () {
var async = {};
function noop() {}
function identity(v) {
return v;
}
function toBool(v) {
return !!v;
}
function notId(v) {
return !v;
}
// global on the server, window in the browser
var previous_async;
// Establish the root object, `window` (`self`) in the browser, `global`
// on the server, or `this` in some virtual machines. We use `self`
// instead of `window` for `WebWorker` support.
var root = typeof self === 'object' && self.self === self && self ||
typeof global === 'object' && global.global === global && global ||
this;
if (root != null) {
previous_async = root.async;
}
async.noConflict = function () {
root.async = previous_async;
return async;
};
function only_once(fn) {
return function() {
if (fn === null) throw new Error("Callback was already called.");
fn.apply(this, arguments);
fn = null;
};
}
function _once(fn) {
return function() {
if (fn === null) return;
fn.apply(this, arguments);
fn = null;
};
}
//// cross-browser compatiblity functions ////
var _toString = Object.prototype.toString;
var _isArray = Array.isArray || function (obj) {
return _toString.call(obj) === '[object Array]';
};
// Ported from underscore.js isObject
var _isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
function _isArrayLike(arr) {
return _isArray(arr) || (
// has a positive integer length property
typeof arr.length === "number" &&
arr.length >= 0 &&
arr.length % 1 === 0
);
}
function _each(coll, iterator) {
return _isArrayLike(coll) ?
_arrayEach(coll, iterator) :
_forEachOf(coll, iterator);
}
function _arrayEach(arr, iterator) {
var index = -1,
length = arr.length;
while (++index < length) {
iterator(arr[index], index, arr);
}
}
function _map(arr, iterator) {
var index = -1,
length = arr.length,
result = Array(length);
while (++index < length) {
result[index] = iterator(arr[index], index, arr);
}
return result;
}
function _range(count) {
return _map(Array(count), function (v, i) { return i; });
}
function _reduce(arr, iterator, memo) {
_arrayEach(arr, function (x, i, a) {
memo = iterator(memo, x, i, a);
});
return memo;
}
function _forEachOf(object, iterator) {
_arrayEach(_keys(object), function (key) {
iterator(object[key], key);
});
}
function _indexOf(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === item) return i;
}
return -1;
}
var _keys = Object.keys || function (obj) {
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
}
return keys;
};
function _keyIterator(coll) {
var i = -1;
var len;
var keys;
if (_isArrayLike(coll)) {
len = coll.length;
return function next() {
i++;
return i < len ? i : null;
};
} else {
keys = _keys(coll);
len = keys.length;
return function next() {
i++;
return i < len ? keys[i] : null;
};
}
}
// Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)
// This accumulates the arguments passed into an array, after a given index.
// From underscore.js (https://github.com/jashkenas/underscore/pull/2140).
function _restParam(func, startIndex) {
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
var length = Math.max(arguments.length - startIndex, 0);
var rest = Array(length);
for (var index = 0; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
switch (startIndex) {
case 0: return func.call(this, rest);
case 1: return func.call(this, arguments[0], rest);
}
// Currently unused but handle cases outside of the switch statement:
// var args = Array(startIndex + 1);
// for (index = 0; index < startIndex; index++) {
// args[index] = arguments[index];
// }
// args[startIndex] = rest;
// return func.apply(this, args);
};
}
function _withoutIndex(iterator) {
return function (value, index, callback) {
return iterator(value, callback);
};
}
//// exported async module functions ////
//// nextTick implementation with browser-compatible fallback ////
// capture the global reference to guard against fakeTimer mocks
var _setImmediate = typeof setImmediate === 'function' && setImmediate;
var _delay = _setImmediate ? function(fn) {
// not a direct alias for IE10 compatibility
_setImmediate(fn);
} : function(fn) {
setTimeout(fn, 0);
};
if (typeof process === 'object' && typeof process.nextTick === 'function') {
async.nextTick = process.nextTick;
} else {
async.nextTick = _delay;
}
async.setImmediate = _setImmediate ? _delay : async.nextTick;
async.forEach =
async.each = function (arr, iterator, callback) {
return async.eachOf(arr, _withoutIndex(iterator), callback);
};
async.forEachSeries =
async.eachSeries = function (arr, iterator, callback) {
return async.eachOfSeries(arr, _withoutIndex(iterator), callback);
};
async.forEachLimit =
async.eachLimit = function (arr, limit, iterator, callback) {
return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);
};
async.forEachOf =
async.eachOf = function (object, iterator, callback) {
callback = _once(callback || noop);
object = object || [];
var size = _isArrayLike(object) ? object.length : _keys(object).length;
var completed = 0;
if (!size) {
return callback(null);
}
_each(object, function (value, key) {
iterator(object[key], key, only_once(done));
});
function done(err) {
if (err) {
callback(err);
}
else {
completed += 1;
if (completed >= size) {
callback(null);
}
}
}
};
async.forEachOfSeries =
async.eachOfSeries = function (obj, iterator, callback) {
callback = _once(callback || noop);
obj = obj || [];
var nextKey = _keyIterator(obj);
var key = nextKey();
function iterate() {
var sync = true;
if (key === null) {
return callback(null);
}
iterator(obj[key], key, only_once(function (err) {
if (err) {
callback(err);
}
else {
key = nextKey();
if (key === null) {
return callback(null);
} else {
if (sync) {
async.setImmediate(iterate);
} else {
iterate();
}
}
}
}));
sync = false;
}
iterate();
};
async.forEachOfLimit =
async.eachOfLimit = function (obj, limit, iterator, callback) {
_eachOfLimit(limit)(obj, iterator, callback);
};
function _eachOfLimit(limit) {
return function (obj, iterator, callback) {
callback = _once(callback || noop);
obj = obj || [];
var nextKey = _keyIterator(obj);
if (limit <= 0) {
return callback(null);
}
var done = false;
var running = 0;
var errored = false;
(function replenish () {
if (done && running <= 0) {
return callback(null);
}
while (running < limit && !errored) {
var key = nextKey();
if (key === null) {
done = true;
if (running <= 0) {
callback(null);
}
return;
}
running += 1;
iterator(obj[key], key, only_once(function (err) {
running -= 1;
if (err) {
callback(err);
errored = true;
}
else {
replenish();
}
}));
}
})();
};
}
function doParallel(fn) {
return function (obj, iterator, callback) {
return fn(async.eachOf, obj, iterator, callback);
};
}
function doParallelLimit(fn) {
return function (obj, limit, iterator, callback) {
return fn(_eachOfLimit(limit), obj, iterator, callback);
};
}
function doSeries(fn) {
return function (obj, iterator, callback) {
return fn(async.eachOfSeries, obj, iterator, callback);
};
}
function _asyncMap(eachfn, arr, iterator, callback) {
callback = _once(callback || noop);
var results = [];
eachfn(arr, function (value, index, callback) {
iterator(value, function (err, v) {
results[index] = v;
callback(err);
});
}, function (err) {
callback(err, results);
});
}
async.map = doParallel(_asyncMap);
async.mapSeries = doSeries(_asyncMap);
async.mapLimit = doParallelLimit(_asyncMap);
// reduce only has a series version, as doing reduce in parallel won't
// work in many situations.
async.inject =
async.foldl =
async.reduce = function (arr, memo, iterator, callback) {
async.eachOfSeries(arr, function (x, i, callback) {
iterator(memo, x, function (err, v) {
memo = v;
callback(err);
});
}, function (err) {
callback(err || null, memo);
});
};
async.foldr =
async.reduceRight = function (arr, memo, iterator, callback) {
var reversed = _map(arr, identity).reverse();
async.reduce(reversed, memo, iterator, callback);
};
function _filter(eachfn, arr, iterator, callback) {
var results = [];
eachfn(arr, function (x, index, callback) {
iterator(x, function (v) {
if (v) {
results.push({index: index, value: x});
}
callback();
});
}, function () {
callback(_map(results.sort(function (a, b) {
return a.index - b.index;
}), function (x) {
return x.value;
}));
});
}
async.select =
async.filter = doParallel(_filter);
async.selectLimit =
async.filterLimit = doParallelLimit(_filter);
async.selectSeries =
async.filterSeries = doSeries(_filter);
function _reject(eachfn, arr, iterator, callback) {
_filter(eachfn, arr, function(value, cb) {
iterator(value, function(v) {
cb(!v);
});
}, callback);
}
async.reject = doParallel(_reject);
async.rejectLimit = doParallelLimit(_reject);
async.rejectSeries = doSeries(_reject);
function _createTester(eachfn, check, getResult) {
return function(arr, limit, iterator, cb) {
function done() {
if (cb) cb(getResult(false, void 0));
}
function iteratee(x, _, callback) {
if (!cb) return callback();
iterator(x, function (v) {
if (cb && check(v)) {
cb(getResult(true, x));
cb = iterator = false;
}
callback();
});
}
if (arguments.length > 3) {
eachfn(arr, limit, iteratee, done);
} else {
cb = iterator;
iterator = limit;
eachfn(arr, iteratee, done);
}
};
}
async.any =
async.some = _createTester(async.eachOf, toBool, identity);
async.someLimit = _createTester(async.eachOfLimit, toBool, identity);
async.all =
async.every = _createTester(async.eachOf, notId, notId);
async.everyLimit = _createTester(async.eachOfLimit, notId, notId);
function _findGetResult(v, x) {
return x;
}
async.detect = _createTester(async.eachOf, identity, _findGetResult);
async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);
async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);
async.sortBy = function (arr, iterator, callback) {
async.map(arr, function (x, callback) {
iterator(x, function (err, criteria) {
if (err) {
callback(err);
}
else {
callback(null, {value: x, criteria: criteria});
}
});
}, function (err, results) {
if (err) {
return callback(err);
}
else {
callback(null, _map(results.sort(comparator), function (x) {
return x.value;
}));
}
});
function comparator(left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}
};
async.auto = function (tasks, callback) {
callback = _once(callback || noop);
var keys = _keys(tasks);
var remainingTasks = keys.length;
if (!remainingTasks) {
return callback(null);
}
var results = {};
var listeners = [];
function addListener(fn) {
listeners.unshift(fn);
}
function removeListener(fn) {
var idx = _indexOf(listeners, fn);
if (idx >= 0) listeners.splice(idx, 1);
}
function taskComplete() {
remainingTasks--;
_arrayEach(listeners.slice(0), function (fn) {
fn();
});
}
addListener(function () {
if (!remainingTasks) {
callback(null, results);
}
});
_arrayEach(keys, function (k) {
var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
var taskCallback = _restParam(function(err, args) {
if (args.length <= 1) {
args = args[0];
}
if (err) {
var safeResults = {};
_forEachOf(results, function(val, rkey) {
safeResults[rkey] = val;
});
safeResults[k] = args;
callback(err, safeResults);
}
else {
results[k] = args;
async.setImmediate(taskComplete);
}
});
var requires = task.slice(0, task.length - 1);
// prevent dead-locks
var len = requires.length;
var dep;
while (len--) {
if (!(dep = tasks[requires[len]])) {
throw new Error('Has inexistant dependency');
}
if (_isArray(dep) && _indexOf(dep, k) >= 0) {
throw new Error('Has cyclic dependencies');
}
}
function ready() {
return _reduce(requires, function (a, x) {
return (a && results.hasOwnProperty(x));
}, true) && !results.hasOwnProperty(k);
}
if (ready()) {
task[task.length - 1](taskCallback, results);
}
else {
addListener(listener);
}
function listener() {
if (ready()) {
removeListener(listener);
task[task.length - 1](taskCallback, results);
}
}
});
};
async.retry = function(times, task, callback) {
var DEFAULT_TIMES = 5;
var DEFAULT_INTERVAL = 0;
var attempts = [];
var opts = {
times: DEFAULT_TIMES,
interval: DEFAULT_INTERVAL
};
function parseTimes(acc, t){
if(typeof t === 'number'){
acc.times = parseInt(t, 10) || DEFAULT_TIMES;
} else if(typeof t === 'object'){
acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;
acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;
} else {
throw new Error('Unsupported argument type for \'times\': ' + typeof t);
}
}
var length = arguments.length;
if (length < 1 || length > 3) {
throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');
} else if (length <= 2 && typeof times === 'function') {
callback = task;
task = times;
}
if (typeof times !== 'function') {
parseTimes(opts, times);
}
opts.callback = callback;
opts.task = task;
function wrappedTask(wrappedCallback, wrappedResults) {
function retryAttempt(task, finalAttempt) {
return function(seriesCallback) {
task(function(err, result){
seriesCallback(!err || finalAttempt, {err: err, result: result});
}, wrappedResults);
};
}
function retryInterval(interval){
return function(seriesCallback){
setTimeout(function(){
seriesCallback(null);
}, interval);
};
}
while (opts.times) {
var finalAttempt = !(opts.times-=1);
attempts.push(retryAttempt(opts.task, finalAttempt));
if(!finalAttempt && opts.interval > 0){
attempts.push(retryInterval(opts.interval));
}
}
async.series(attempts, function(done, data){
data = data[data.length - 1];
(wrappedCallback || opts.callback)(data.err, data.result);
});
}
// If a callback is passed, run this as a controll flow
return opts.callback ? wrappedTask() : wrappedTask;
};
async.waterfall = function (tasks, callback) {
callback = _once(callback || noop);
if (!_isArray(tasks)) {
var err = new Error('First argument to waterfall must be an array of functions');
return callback(err);
}
if (!tasks.length) {
return callback();
}
function wrapIterator(iterator) {
return _restParam(function (err, args) {
if (err) {
callback.apply(null, [err].concat(args));
}
else {
var next = iterator.next();
if (next) {
args.push(wrapIterator(next));
}
else {
args.push(callback);
}
ensureAsync(iterator).apply(null, args);
}
});
}
wrapIterator(async.iterator(tasks))();
};
function _parallel(eachfn, tasks, callback) {
callback = callback || noop;
var results = _isArrayLike(tasks) ? [] : {};
eachfn(tasks, function (task, key, callback) {
task(_restParam(function (err, args) {
if (args.length <= 1) {
args = args[0];
}
results[key] = args;
callback(err);
}));
}, function (err) {
callback(err, results);
});
}
async.parallel = function (tasks, callback) {
_parallel(async.eachOf, tasks, callback);
};
async.parallelLimit = function(tasks, limit, callback) {
_parallel(_eachOfLimit(limit), tasks, callback);
};
async.series = function(tasks, callback) {
_parallel(async.eachOfSeries, tasks, callback);
};
async.iterator = function (tasks) {
function makeCallback(index) {
function fn() {
if (tasks.length) {
tasks[index].apply(null, arguments);
}
return fn.next();
}
fn.next = function () {
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
};
return fn;
}
return makeCallback(0);
};
async.apply = _restParam(function (fn, args) {
return _restParam(function (callArgs) {
return fn.apply(
null, args.concat(callArgs)
);
});
});
function _concat(eachfn, arr, fn, callback) {
var result = [];
eachfn(arr, function (x, index, cb) {
fn(x, function (err, y) {
result = result.concat(y || []);
cb(err);
});
}, function (err) {
callback(err, result);
});
}
async.concat = doParallel(_concat);
async.concatSeries = doSeries(_concat);
async.whilst = function (test, iterator, callback) {
callback = callback || noop;
if (test()) {
var next = _restParam(function(err, args) {
if (err) {
callback(err);
} else if (test.apply(this, args)) {
iterator(next);
} else {
callback(null);
}
});
iterator(next);
} else {
callback(null);
}
};
async.doWhilst = function (iterator, test, callback) {
var calls = 0;
return async.whilst(function() {
return ++calls <= 1 || test.apply(this, arguments);
}, iterator, callback);
};
async.until = function (test, iterator, callback) {
return async.whilst(function() {
return !test.apply(this, arguments);
}, iterator, callback);
};
async.doUntil = function (iterator, test, callback) {
return async.doWhilst(iterator, function() {
return !test.apply(this, arguments);
}, callback);
};
async.during = function (test, iterator, callback) {
callback = callback || noop;
var next = _restParam(function(err, args) {
if (err) {
callback(err);
} else {
args.push(check);
test.apply(this, args);
}
});
var check = function(err, truth) {
if (err) {
callback(err);
} else if (truth) {
iterator(next);
} else {
callback(null);
}
};
test(check);
};
async.doDuring = function (iterator, test, callback) {
var calls = 0;
async.during(function(next) {
if (calls++ < 1) {
next(null, true);
} else {
test.apply(this, arguments);
}
}, iterator, callback);
};
function _queue(worker, concurrency, payload) {
if (concurrency == null) {
concurrency = 1;
}
else if(concurrency === 0) {
throw new Error('Concurrency must not be zero');
}
function _insert(q, data, pos, callback) {
if (callback != null && typeof callback !== "function") {
throw new Error("task callback must be a function");
}
q.started = true;
if (!_isArray(data)) {
data = [data];
}
if(data.length === 0 && q.idle()) {
// call drain immediately if there are no tasks
return async.setImmediate(function() {
q.drain();
});
}
_arrayEach(data, function(task) {
var item = {
data: task,
callback: callback || noop
};
if (pos) {
q.tasks.unshift(item);
} else {
q.tasks.push(item);
}
if (q.tasks.length === q.concurrency) {
q.saturated();
}
});
async.setImmediate(q.process);
}
function _next(q, tasks) {
return function(){
workers -= 1;
var args = arguments;
_arrayEach(tasks, function (task) {
task.callback.apply(task, args);
});
if (q.tasks.length + workers === 0) {
q.drain();
}
q.process();
};
}
var workers = 0;
var q = {
tasks: [],
concurrency: concurrency,
payload: payload,
saturated: noop,
empty: noop,
drain: noop,
started: false,
paused: false,
push: function (data, callback) {
_insert(q, data, false, callback);
},
kill: function () {
q.drain = noop;
q.tasks = [];
},
unshift: function (data, callback) {
_insert(q, data, true, callback);
},
process: function () {
if (!q.paused && workers < q.concurrency && q.tasks.length) {
while(workers < q.concurrency && q.tasks.length){
var tasks = q.payload ?
q.tasks.splice(0, q.payload) :
q.tasks.splice(0, q.tasks.length);
var data = _map(tasks, function (task) {
return task.data;
});
if (q.tasks.length === 0) {
q.empty();
}
workers += 1;
var cb = only_once(_next(q, tasks));
worker(data, cb);
}
}
},
length: function () {
return q.tasks.length;
},
running: function () {
return workers;
},
idle: function() {
return q.tasks.length + workers === 0;
},
pause: function () {
q.paused = true;
},
resume: function () {
if (q.paused === false) { return; }
q.paused = false;
var resumeCount = Math.min(q.concurrency, q.tasks.length);
// Need to call q.process once per concurrent
// worker to preserve full concurrency after pause
for (var w = 1; w <= resumeCount; w++) {
async.setImmediate(q.process);
}
}
};
return q;
}
async.queue = function (worker, concurrency) {
var q = _queue(function (items, cb) {
worker(items[0], cb);
}, concurrency, 1);
return q;
};
async.priorityQueue = function (worker, concurrency) {
function _compareTasks(a, b){
return a.priority - b.priority;
}
function _binarySearch(sequence, item, compare) {
var beg = -1,
end = sequence.length - 1;
while (beg < end) {
var mid = beg + ((end - beg + 1) >>> 1);
if (compare(item, sequence[mid]) >= 0) {
beg = mid;
} else {
end = mid - 1;
}
}
return beg;
}
function _insert(q, data, priority, callback) {
if (callback != null && typeof callback !== "function") {
throw new Error("task callback must be a function");
}
q.started = true;
if (!_isArray(data)) {
data = [data];
}
if(data.length === 0) {
// call drain immediately if there are no tasks
return async.setImmediate(function() {
q.drain();
});
}
_arrayEach(data, function(task) {
var item = {
data: task,
priority: priority,
callback: typeof callback === 'function' ? callback : noop
};
q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
if (q.tasks.length === q.concurrency) {
q.saturated();
}
async.setImmediate(q.process);
});
}
// Start with a normal queue
var q = async.queue(worker, concurrency);
// Override push to accept second parameter representing priority
q.push = function (data, priority, callback) {
_insert(q, data, priority, callback);
};
// Remove unshift function
delete q.unshift;
return q;
};
async.cargo = function (worker, payload) {
return _queue(worker, 1, payload);
};
function _console_fn(name) {
return _restParam(function (fn, args) {
fn.apply(null, args.concat([_restParam(function (err, args) {
if (typeof console === 'object') {
if (err) {
if (console.error) {
console.error(err);
}
}
else if (console[name]) {
_arrayEach(args, function (x) {
console[name](x);
});
}
}
})]));
});
}
async.log = _console_fn('log');
async.dir = _console_fn('dir');
/*async.info = _console_fn('info');
async.warn = _console_fn('warn');
async.error = _console_fn('error');*/
async.memoize = function (fn, hasher) {
var memo = {};
var queues = {};
hasher = hasher || identity;
var memoized = _restParam(function memoized(args) {
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
async.setImmediate(function () {
callback.apply(null, memo[key]);
});
}
else if (key in queues) {
queues[key].push(callback);
}
else {
queues[key] = [callback];
fn.apply(null, args.concat([_restParam(function (args) {
memo[key] = args;
var q = queues[key];
delete queues[key];
for (var i = 0, l = q.length; i < l; i++) {
q[i].apply(null, args);
}
})]));
}
});
memoized.memo = memo;
memoized.unmemoized = fn;
return memoized;
};
async.unmemoize = function (fn) {
return function () {
return (fn.unmemoized || fn).apply(null, arguments);
};
};
function _times(mapper) {
return function (count, iterator, callback) {
mapper(_range(count), iterator, callback);
};
}
async.times = _times(async.map);
async.timesSeries = _times(async.mapSeries);
async.timesLimit = function (count, limit, iterator, callback) {
return async.mapLimit(_range(count), limit, iterator, callback);
};
async.seq = function (/* functions... */) {
var fns = arguments;
return _restParam(function (args) {
var that = this;
var callback = args[args.length - 1];
if (typeof callback == 'function') {
args.pop();
} else {
callback = noop;
}
async.reduce(fns, args, function (newargs, fn, cb) {
fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {
cb(err, nextargs);
})]));
},
function (err, results) {
callback.apply(that, [err].concat(results));
});
});
};
async.compose = function (/* functions... */) {
return async.seq.apply(null, Array.prototype.reverse.call(arguments));
};
function _applyEach(eachfn) {
return _restParam(function(fns, args) {
var go = _restParam(function(args) {
var that = this;
var callback = args.pop();
return eachfn(fns, function (fn, _, cb) {
fn.apply(that, args.concat([cb]));
},
callback);
});
if (args.length) {
return go.apply(this, args);
}
else {
return go;
}
});
}
async.applyEach = _applyEach(async.eachOf);
async.applyEachSeries = _applyEach(async.eachOfSeries);
async.forever = function (fn, callback) {
var done = only_once(callback || noop);
var task = ensureAsync(fn);
function next(err) {
if (err) {
return done(err);
}
task(next);
}
next();
};
function ensureAsync(fn) {
return _restParam(function (args) {
var callback = args.pop();
args.push(function () {
var innerArgs = arguments;
if (sync) {
async.setImmediate(function () {
callback.apply(null, innerArgs);
});
} else {
callback.apply(null, innerArgs);
}
});
var sync = true;
fn.apply(this, args);
sync = false;
});
}
async.ensureAsync = ensureAsync;
async.constant = _restParam(function(values) {
var args = [null].concat(values);
return function (callback) {
return callback.apply(this, args);
};
});
async.wrapSync =
async.asyncify = function asyncify(func) {
return _restParam(function (args) {
var callback = args.pop();
var result;
try {
result = func.apply(this, args);
} catch (e) {
return callback(e);
}
// if result is Promise object
if (_isObject(result) && typeof result.then === "function") {
result.then(function(value) {
callback(null, value);
})["catch"](function(err) {
callback(err.message ? err : new Error(err));
});
} else {
callback(null, result);
}
});
};
// Node.js
if (typeof module === 'object' && module.exports) {
module.exports = async;
}
// AMD / RequireJS
else if (typeof define === 'function' && define.amd) {
define([], function () {
return async;
});
}
// included directly via <script> tag
else {
root.async = async;
}
}());
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"_process":1}],32:[function(require,module,exports){
'use strict';
module.exports = function (str) {
if (str.length === 1) {
return str;
}
return str
.replace(/^[_.\- ]+/, '')
.toLowerCase()
.replace(/[_.\- ]+(\w|$)/g, function (m, p1) {
return p1.toUpperCase();
});
};
},{}]},{},[22])(22)
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwic3JjL2Fzc2VydGFibGUuanMiLCJzcmMvZGVzY3JpcHRvcnMvYWJzb2x1dGVfcG9zaXRpb24uanMiLCJzcmMvZGVzY3JpcHRvcnMvY2VudGVyLmpzIiwic3JjL2Rlc2NyaXB0b3JzL2Rlc2NyaXB0b3IuanMiLCJzcmMvZGVzY3JpcHRvcnMvZWxlbWVudF9lZGdlLmpzIiwic3JjL2Rlc2NyaXB0b3JzL2VsZW1lbnRfcmVuZGVyZWQuanMiLCJzcmMvZGVzY3JpcHRvcnMvZWxlbWVudF9yZW5kZXJlZF9lZGdlLmpzIiwic3JjL2Rlc2NyaXB0b3JzL2dlbmVyaWNfc2l6ZS5qcyIsInNyYy9kZXNjcmlwdG9ycy9wYWdlX2VkZ2UuanMiLCJzcmMvZGVzY3JpcHRvcnMvcG9zaXRpb25fZGVzY3JpcHRvci5qcyIsInNyYy9kZXNjcmlwdG9ycy9yZWxhdGl2ZV9wb3NpdGlvbi5qcyIsInNyYy9kZXNjcmlwdG9ycy9yZWxhdGl2ZV9zaXplLmpzIiwic3JjL2Rlc2NyaXB0b3JzL3NpemVfZGVzY3JpcHRvci5qcyIsInNyYy9kZXNjcmlwdG9ycy9zaXplX211bHRpcGxlLmpzIiwic3JjL2Rlc2NyaXB0b3JzL3ZpZXdwb3J0X2VkZ2UuanMiLCJzcmMvcV9lbGVtZW50LmpzIiwic3JjL3FfZWxlbWVudF9saXN0LmpzIiwic3JjL3FfZnJhbWUuanMiLCJzcmMvcV9wYWdlLmpzIiwic3JjL3Ffdmlld3BvcnQuanMiLCJzcmMvcXVpeG90ZS5qcyIsInNyYy91dGlsL2Vuc3VyZS5qcyIsInNyYy91dGlsL29vcC5qcyIsInNyYy91dGlsL3NoaW0uanMiLCJzcmMvdmFsdWVzL3BpeGVscy5qcyIsInNyYy92YWx1ZXMvcG9zaXRpb24uanMiLCJzcmMvdmFsdWVzL3JlbmRlcl9zdGF0ZS5qcyIsInNyYy92YWx1ZXMvc2l6ZS5qcyIsInNyYy92YWx1ZXMvdmFsdWUuanMiLCJ2ZW5kb3IvYXN5bmMtMS40LjIuanMiLCJ2ZW5kb3IvY2FtZWxjYXNlLTEuMC4xLW1vZGlmaWVkLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0UUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDalNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9IQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3RzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE1IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgb29wID0gcmVxdWlyZShcIi4vdXRpbC9vb3AuanNcIik7XG52YXIgc2hpbSA9IHJlcXVpcmUoXCIuL3V0aWwvc2hpbS5qc1wiKTtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBBc3NlcnRhYmxlKCkge1xuXHRlbnN1cmUudW5yZWFjaGFibGUoXCJBc3NlcnRhYmxlIGlzIGFic3RyYWN0IGFuZCBzaG91bGQgbm90IGJlIGNvbnN0cnVjdGVkIGRpcmVjdGx5LlwiKTtcbn07XG5NZS5leHRlbmQgPSBvb3AuZXh0ZW5kRm4oTWUpO1xub29wLm1ha2VBYnN0cmFjdChNZSwgW10pO1xuXG5NZS5wcm90b3R5cGUuYXNzZXJ0ID0gZnVuY3Rpb24gYXNzZXJ0KGV4cGVjdGVkLCBtZXNzYWdlKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIE9iamVjdCwgW3VuZGVmaW5lZCwgU3RyaW5nXSBdKTtcblx0aWYgKG1lc3NhZ2UgPT09IHVuZGVmaW5lZCkgbWVzc2FnZSA9IFwiRGlmZmVyZW5jZXMgZm91bmRcIjtcblxuXHR2YXIgZGlmZiA9IHRoaXMuZGlmZihleHBlY3RlZCk7XG5cdGlmIChkaWZmICE9PSBcIlwiKSB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSArIFwiOlxcblwiICsgZGlmZiArIFwiXFxuXCIpO1xufTtcblxuTWUucHJvdG90eXBlLmRpZmYgPSBmdW5jdGlvbiBkaWZmKGV4cGVjdGVkKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIE9iamVjdCBdKTtcblxuXHR2YXIgcmVzdWx0ID0gW107XG5cdHZhciBrZXlzID0gc2hpbS5PYmplY3Qua2V5cyhleHBlY3RlZCk7XG5cdHZhciBrZXksIG9uZURpZmYsIGRlc2NyaXB0b3I7XG5cdGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuXHRcdGtleSA9IGtleXNbaV07XG5cdFx0ZGVzY3JpcHRvciA9IHRoaXNba2V5XTtcblx0XHRlbnN1cmUudGhhdChcblx0XHRcdFx0ZGVzY3JpcHRvciAhPT0gdW5kZWZpbmVkLFxuXHRcdFx0XHR0aGlzICsgXCIgZG9lc24ndCBoYXZlIGEgcHJvcGVydHkgbmFtZWQgJ1wiICsga2V5ICsgXCInLiBEaWQgeW91IG1pc3NwZWxsIGl0P1wiXG5cdFx0KTtcblx0XHRvbmVEaWZmID0gZGVzY3JpcHRvci5kaWZmKGV4cGVjdGVkW2tleV0pO1xuXHRcdGlmIChvbmVEaWZmICE9PSBcIlwiKSByZXN1bHQucHVzaChvbmVEaWZmKTtcblx0fVxuXG5cdHJldHVybiByZXN1bHQuam9pbihcIlxcblwiKTtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgUG9zaXRpb25EZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vcG9zaXRpb25fZGVzY3JpcHRvci5qc1wiKTtcbnZhciBQb3NpdGlvbiA9IHJlcXVpcmUoXCIuLi92YWx1ZXMvcG9zaXRpb24uanNcIik7XG5cbnZhciBYX0RJTUVOU0lPTiA9IFwieFwiO1xudmFyIFlfRElNRU5TSU9OID0gXCJ5XCI7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gQWJzb2x1dGVQb3NpdGlvbihkaW1lbnNpb24sIHZhbHVlKSB7XG4gIGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIFN0cmluZywgTnVtYmVyIF0pO1xuXG4gIHN3aXRjaChkaW1lbnNpb24pIHtcblx0XHRjYXNlIFhfRElNRU5TSU9OOlxuXHRcdFx0UG9zaXRpb25EZXNjcmlwdG9yLngodGhpcyk7XG5cdFx0XHR0aGlzLl92YWx1ZSA9IFBvc2l0aW9uLngodmFsdWUpO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSBZX0RJTUVOU0lPTjpcblx0XHRcdFBvc2l0aW9uRGVzY3JpcHRvci55KHRoaXMpO1xuXHRcdFx0dGhpcy5fdmFsdWUgPSBQb3NpdGlvbi55KHZhbHVlKTtcblx0XHRcdGJyZWFrO1xuXHRcdGRlZmF1bHQ6IGVuc3VyZS51bnJlYWNoYWJsZShcIlVua25vd24gZGltZW5zaW9uOiBcIiArIGRpbWVuc2lvbik7XG4gIH1cbiAgdGhpcy5fZGltZW5zaW9uID0gZGltZW5zaW9uO1xufTtcblBvc2l0aW9uRGVzY3JpcHRvci5leHRlbmQoTWUpO1xuXG5NZS54ID0gZnVuY3Rpb24odmFsdWUpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgTnVtYmVyIF0pO1xuICByZXR1cm4gbmV3IE1lKFhfRElNRU5TSU9OLCB2YWx1ZSk7XG59O1xuXG5NZS55ID0gZnVuY3Rpb24odmFsdWUpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgTnVtYmVyIF0pO1xuXHRyZXR1cm4gbmV3IE1lKFlfRElNRU5TSU9OLCB2YWx1ZSk7XG59O1xuXG5NZS5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xufTtcblxuTWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLl92YWx1ZSArIFwiIFwiICsgdGhpcy5fZGltZW5zaW9uICsgXCItY29vcmRpbmF0ZVwiO1xufTtcbiIsIi8vIENvcHlyaWdodCAoYykgMjAxNCBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBQb3NpdGlvbkRlc2NyaXB0b3IgPSByZXF1aXJlKFwiLi9wb3NpdGlvbl9kZXNjcmlwdG9yLmpzXCIpO1xudmFyIFBvc2l0aW9uID0gcmVxdWlyZShcIi4uL3ZhbHVlcy9wb3NpdGlvbi5qc1wiKTtcbnZhciBSZWxhdGl2ZVBvc2l0aW9uID0gcmVxdWlyZShcIi4vcmVsYXRpdmVfcG9zaXRpb24uanNcIik7XG5cbnZhciBYX0RJTUVOU0lPTiA9IFwieFwiO1xudmFyIFlfRElNRU5TSU9OID0gXCJ5XCI7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gQ2VudGVyKGRpbWVuc2lvbiwgcG9zaXRpb24xLCBwb3NpdGlvbjIsIGRlc2NyaXB0aW9uKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIFN0cmluZywgUG9zaXRpb25EZXNjcmlwdG9yLCBQb3NpdGlvbkRlc2NyaXB0b3IsIFN0cmluZyBdKTtcblxuXHRpZiAoZGltZW5zaW9uID09PSBYX0RJTUVOU0lPTikgUG9zaXRpb25EZXNjcmlwdG9yLngodGhpcyk7XG5cdGVsc2UgaWYgKGRpbWVuc2lvbiA9PT0gWV9ESU1FTlNJT04pIFBvc2l0aW9uRGVzY3JpcHRvci55KHRoaXMpO1xuXHRlbHNlIGVuc3VyZS51bnJlYWNoYWJsZShcIlVua25vd24gZGltZW5zaW9uOiBcIiArIGRpbWVuc2lvbik7XG5cblx0dGhpcy5fZGltZW5zaW9uID0gZGltZW5zaW9uO1xuXHR0aGlzLl9wb3NpdGlvbjEgPSBwb3NpdGlvbjE7XG5cdHRoaXMuX3Bvc2l0aW9uMiA9IHBvc2l0aW9uMjtcblx0dGhpcy5fZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbjtcbn07XG5Qb3NpdGlvbkRlc2NyaXB0b3IuZXh0ZW5kKE1lKTtcblxuTWUueCA9IGZhY3RvcnlGbihYX0RJTUVOU0lPTik7XG5NZS55ID0gZmFjdG9yeUZuKFlfRElNRU5TSU9OKTtcblxuTWUucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdHJldHVybiB0aGlzLl9wb3NpdGlvbjEudmFsdWUoKS5taWRwb2ludCh0aGlzLl9wb3NpdGlvbjIudmFsdWUoKSk7XG59O1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblx0cmV0dXJuIHRoaXMuX2Rlc2NyaXB0aW9uO1xufTtcblxuZnVuY3Rpb24gZmFjdG9yeUZuKGRpbWVuc2lvbikge1xuXHRyZXR1cm4gZnVuY3Rpb24ocG9zaXRpb24xLCBwb3NpdGlvbjIsIGRlc2NyaXB0aW9uKSB7XG5cdFx0cmV0dXJuIG5ldyBNZShkaW1lbnNpb24sIHBvc2l0aW9uMSwgcG9zaXRpb24yLCBkZXNjcmlwdGlvbik7XG5cdH07XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgb29wID0gcmVxdWlyZShcIi4uL3V0aWwvb29wLmpzXCIpO1xudmFyIFZhbHVlID0gcmVxdWlyZShcIi4uL3ZhbHVlcy92YWx1ZS5qc1wiKTtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBEZXNjcmlwdG9yKCkge1xuXHRlbnN1cmUudW5yZWFjaGFibGUoXCJEZXNjcmlwdG9yIGlzIGFic3RyYWN0IGFuZCBzaG91bGQgbm90IGJlIGNvbnN0cnVjdGVkIGRpcmVjdGx5LlwiKTtcbn07XG5NZS5leHRlbmQgPSBvb3AuZXh0ZW5kRm4oTWUpO1xub29wLm1ha2VBYnN0cmFjdChNZSwgW1xuXHRcInZhbHVlXCIsXG5cdFwidG9TdHJpbmdcIlxuXSk7XG5cbk1lLnByb3RvdHlwZS5kaWZmID0gZnVuY3Rpb24gZGlmZihleHBlY3RlZCkge1xuXHRleHBlY3RlZCA9IG5vcm1hbGl6ZVR5cGUodGhpcywgZXhwZWN0ZWQpO1xuXHR0cnkge1xuXHRcdHZhciBhY3R1YWxWYWx1ZSA9IHRoaXMudmFsdWUoKTtcblx0XHR2YXIgZXhwZWN0ZWRWYWx1ZSA9IGV4cGVjdGVkLnZhbHVlKCk7XG5cblx0XHRpZiAoYWN0dWFsVmFsdWUuZXF1YWxzKGV4cGVjdGVkVmFsdWUpKSByZXR1cm4gXCJcIjtcblxuXHRcdHZhciBkaWZmZXJlbmNlID0gYWN0dWFsVmFsdWUuZGlmZihleHBlY3RlZFZhbHVlKTtcblx0XHR2YXIgZXhwZWN0ZWREZXNjID0gZXhwZWN0ZWRWYWx1ZS50b1N0cmluZygpO1xuXHRcdGlmIChleHBlY3RlZCBpbnN0YW5jZW9mIE1lKSBleHBlY3RlZERlc2MgKz0gXCIgKFwiICsgZXhwZWN0ZWQgKyBcIilcIjtcblxuXHRcdHJldHVybiB0aGlzICsgXCIgd2FzIFwiICsgZGlmZmVyZW5jZSArIFwiLlxcblwiICtcblx0XHRcdFwiICBFeHBlY3RlZDogXCIgKyBleHBlY3RlZERlc2MgKyBcIlxcblwiICtcblx0XHRcdFwiICBCdXQgd2FzOiAgXCIgKyBhY3R1YWxWYWx1ZTtcblx0fVxuXHRjYXRjaCAoZXJyKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgY29tcGFyZSBcIiArIHRoaXMgKyBcIiB0byBcIiArIGV4cGVjdGVkICsgXCI6IFwiICsgZXJyLm1lc3NhZ2UpO1xuXHR9XG59O1xuXG5NZS5wcm90b3R5cGUuY29udmVydCA9IGZ1bmN0aW9uIGNvbnZlcnQoYXJnLCB0eXBlKSB7XG5cdC8vIFRoaXMgbWV0aG9kIGlzIG1lYW50IHRvIGJlIG92ZXJyaWRkZW4gYnkgc3ViY2xhc3Nlcy4gSXQgc2hvdWxkIHJldHVybiAndW5kZWZpbmVkJyB3aGVuIGFuIGFyZ3VtZW50XG5cdC8vIGNhbid0IGJlIGNvbnZlcnRlZC4gSW4gdGhpcyBkZWZhdWx0IGltcGxlbWVudGF0aW9uLCBubyBhcmd1bWVudHMgY2FuIGJlIGNvbnZlcnRlZCwgc28gd2UgYWx3YXlzXG5cdC8vIHJldHVybiAndW5kZWZpbmVkJy5cblx0cmV0dXJuIHVuZGVmaW5lZDtcbn07XG5cbk1lLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHModGhhdCkge1xuXHQvLyBEZXNjcmlwdG9ycyBhcmVuJ3QgdmFsdWUgb2JqZWN0cy4gVGhleSdyZSBuZXZlciBlcXVhbCB0byBhbnl0aGluZy4gQnV0IHNvbWV0aW1lc1xuXHQvLyB0aGV5J3JlIHVzZWQgaW4gdGhlIHNhbWUgcGxhY2VzIHZhbHVlIG9iamVjdHMgYXJlIHVzZWQsIGFuZCB0aGlzIG1ldGhvZCBnZXRzIGNhbGxlZC5cblx0cmV0dXJuIGZhbHNlO1xufTtcblxuZnVuY3Rpb24gbm9ybWFsaXplVHlwZShzZWxmLCBleHBlY3RlZCkge1xuXHR2YXIgZXhwZWN0ZWRUeXBlID0gdHlwZW9mIGV4cGVjdGVkO1xuXHRpZiAoZXhwZWN0ZWQgPT09IG51bGwpIGV4cGVjdGVkVHlwZSA9IFwibnVsbFwiO1xuXG5cdGlmIChleHBlY3RlZFR5cGUgPT09IFwib2JqZWN0XCIgJiYgKGV4cGVjdGVkIGluc3RhbmNlb2YgTWUgfHwgZXhwZWN0ZWQgaW5zdGFuY2VvZiBWYWx1ZSkpIHJldHVybiBleHBlY3RlZDtcblxuXHRpZiAoZXhwZWN0ZWQgPT09IHVuZGVmaW5lZCkge1xuXHRcdHRocm93IG5ldyBFcnJvcihcIkNhbid0IGNvbXBhcmUgXCIgKyBzZWxmICsgXCIgdG8gXCIgKyBleHBlY3RlZCArIFwiLiBEaWQgeW91IG1pc3NwZWxsIGEgcHJvcGVydHkgbmFtZT9cIik7XG5cdH1cblx0ZWxzZSBpZiAoZXhwZWN0ZWRUeXBlID09PSBcIm9iamVjdFwiKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgY29tcGFyZSBcIiArIHNlbGYgKyBcIiB0byBcIiArIG9vcC5pbnN0YW5jZU5hbWUoZXhwZWN0ZWQpICsgXCIgaW5zdGFuY2VzLlwiKTtcblx0fVxuXHRlbHNlIHtcblx0XHR2YXIgY29udmVydGVkID0gc2VsZi5jb252ZXJ0KGV4cGVjdGVkLCBleHBlY3RlZFR5cGUpO1xuXHRcdGlmIChjb252ZXJ0ZWQgIT09IHVuZGVmaW5lZCkgcmV0dXJuIGNvbnZlcnRlZDtcblxuXHRcdHZhciBleHBsYW5hdGlvbiA9IGV4cGVjdGVkO1xuXHRcdGlmIChleHBlY3RlZFR5cGUgPT09IFwic3RyaW5nXCIpIGV4cGxhbmF0aW9uID0gXCInXCIgKyBleHBsYW5hdGlvbiArIFwiJ1wiO1xuXHRcdGlmIChleHBlY3RlZFR5cGUgPT09IFwiZnVuY3Rpb25cIikgZXhwbGFuYXRpb24gPSBcImEgZnVuY3Rpb25cIjtcblxuXHRcdHRocm93IG5ldyBFcnJvcihcIkNhbid0IGNvbXBhcmUgXCIgKyBzZWxmICsgXCIgdG8gXCIgKyBleHBsYW5hdGlvbiArIFwiLlwiKTtcblx0fVxuXG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNyBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBQb3NpdGlvbiA9IHJlcXVpcmUoXCIuLi92YWx1ZXMvcG9zaXRpb24uanNcIik7XG52YXIgUG9zaXRpb25EZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vcG9zaXRpb25fZGVzY3JpcHRvci5qc1wiKTtcblxudmFyIFRPUCA9IFwidG9wXCI7XG52YXIgUklHSFQgPSBcInJpZ2h0XCI7XG52YXIgQk9UVE9NID0gXCJib3R0b21cIjtcbnZhciBMRUZUID0gXCJsZWZ0XCI7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gRWxlbWVudEVkZ2UoZWxlbWVudCwgcG9zaXRpb24pIHtcblx0dmFyIFFFbGVtZW50ID0gcmVxdWlyZShcIi4uL3FfZWxlbWVudC5qc1wiKTsgICAgICAvLyBicmVhayBjaXJjdWxhciBkZXBlbmRlbmN5XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbUUVsZW1lbnQsIFN0cmluZ10pO1xuXG5cdGlmIChwb3NpdGlvbiA9PT0gTEVGVCB8fCBwb3NpdGlvbiA9PT0gUklHSFQpIFBvc2l0aW9uRGVzY3JpcHRvci54KHRoaXMpO1xuXHRlbHNlIGlmIChwb3NpdGlvbiA9PT0gVE9QIHx8IHBvc2l0aW9uID09PSBCT1RUT00pIFBvc2l0aW9uRGVzY3JpcHRvci55KHRoaXMpO1xuXHRlbHNlIGVuc3VyZS51bnJlYWNoYWJsZShcIlVua25vd24gcG9zaXRpb246IFwiICsgcG9zaXRpb24pO1xuXG5cdHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuXHR0aGlzLl9wb3NpdGlvbiA9IHBvc2l0aW9uO1xufTtcblBvc2l0aW9uRGVzY3JpcHRvci5leHRlbmQoTWUpO1xuXG5NZS50b3AgPSBmYWN0b3J5Rm4oVE9QKTtcbk1lLnJpZ2h0ID0gZmFjdG9yeUZuKFJJR0hUKTtcbk1lLmJvdHRvbSA9IGZhY3RvcnlGbihCT1RUT00pO1xuTWUubGVmdCA9IGZhY3RvcnlGbihMRUZUKTtcblxuTWUucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cblx0dmFyIHJhd1Bvc2l0aW9uID0gdGhpcy5fZWxlbWVudC5nZXRSYXdQb3NpdGlvbigpO1xuXG5cdHZhciBlZGdlID0gcmF3UG9zaXRpb25bdGhpcy5fcG9zaXRpb25dO1xuXHR2YXIgc2Nyb2xsID0gdGhpcy5fZWxlbWVudC5mcmFtZS5nZXRSYXdTY3JvbGxQb3NpdGlvbigpO1xuXG5cdGlmICh0aGlzLl9wb3NpdGlvbiA9PT0gUklHSFQgfHwgdGhpcy5fcG9zaXRpb24gPT09IExFRlQpIHtcblx0XHRpZiAoIWVsZW1lbnRSZW5kZXJlZCh0aGlzLCByYXdQb3NpdGlvbikpIHJldHVybiBQb3NpdGlvbi5ub1goKTtcblx0XHRyZXR1cm4gUG9zaXRpb24ueChlZGdlICsgc2Nyb2xsLngpO1xuXHR9XG5cdGVsc2Uge1xuXHRcdGlmICghZWxlbWVudFJlbmRlcmVkKHRoaXMsIHJhd1Bvc2l0aW9uKSkgcmV0dXJuIFBvc2l0aW9uLm5vWSgpO1xuXHRcdHJldHVybiBQb3NpdGlvbi55KGVkZ2UgKyBzY3JvbGwueSk7XG5cdH1cbn07XG5cbk1lLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXHRyZXR1cm4gdGhpcy5fcG9zaXRpb24gKyBcIiBlZGdlIG9mIFwiICsgdGhpcy5fZWxlbWVudDtcbn07XG5cbmZ1bmN0aW9uIGZhY3RvcnlGbihwb3NpdGlvbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gZmFjdG9yeShlbGVtZW50KSB7XG5cdFx0cmV0dXJuIG5ldyBNZShlbGVtZW50LCBwb3NpdGlvbik7XG5cdH07XG59XG5cbmZ1bmN0aW9uIGVsZW1lbnRSZW5kZXJlZChzZWxmLCByYXdQb3NpdGlvbikge1xuXHR2YXIgZWxlbWVudCA9IHNlbGYuX2VsZW1lbnQ7XG5cblx0dmFyIGluRG9tID0gZWxlbWVudC5mcmFtZS5ib2R5KCkudG9Eb21FbGVtZW50KCkuY29udGFpbnMoZWxlbWVudC50b0RvbUVsZW1lbnQoKSk7XG5cdHZhciBkaXNwbGF5Tm9uZSA9IGVsZW1lbnQuZ2V0UmF3U3R5bGUoXCJkaXNwbGF5XCIpID09PSBcIm5vbmVcIjtcblxuXHRyZXR1cm4gaW5Eb20gJiYgIWRpc3BsYXlOb25lO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE2LTIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgUmVuZGVyU3RhdGUgPSByZXF1aXJlKFwiLi4vdmFsdWVzL3JlbmRlcl9zdGF0ZS5qc1wiKTtcbnZhciBQb3NpdGlvbiA9IHJlcXVpcmUoXCIuLi92YWx1ZXMvcG9zaXRpb24uanNcIik7XG52YXIgRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL2Rlc2NyaXB0b3IuanNcIik7XG52YXIgRWxlbWVudFJlbmRlcmVkRWRnZSA9IHJlcXVpcmUoXCIuL2VsZW1lbnRfcmVuZGVyZWRfZWRnZS5qc1wiKTtcbnZhciBHZW5lcmljU2l6ZSA9IHJlcXVpcmUoXCIuL2dlbmVyaWNfc2l6ZS5qc1wiKTtcbnZhciBDZW50ZXIgPSByZXF1aXJlKFwiLi9jZW50ZXIuanNcIik7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gRWxlbWVudFJlbmRlcmVkKGVsZW1lbnQpIHtcblx0dmFyIFFFbGVtZW50ID0gcmVxdWlyZShcIi4uL3FfZWxlbWVudC5qc1wiKTsgICAgICAvLyBicmVhayBjaXJjdWxhciBkZXBlbmRlbmN5XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIFFFbGVtZW50IF0pO1xuXG5cdHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuXG5cdC8vIHByb3BlcnRpZXNcblx0dGhpcy50b3AgPSBFbGVtZW50UmVuZGVyZWRFZGdlLnRvcChlbGVtZW50KTtcblx0dGhpcy5yaWdodCA9IEVsZW1lbnRSZW5kZXJlZEVkZ2UucmlnaHQoZWxlbWVudCk7XG5cdHRoaXMuYm90dG9tID0gRWxlbWVudFJlbmRlcmVkRWRnZS5ib3R0b20oZWxlbWVudCk7XG5cdHRoaXMubGVmdCA9IEVsZW1lbnRSZW5kZXJlZEVkZ2UubGVmdChlbGVtZW50KTtcblxuXHR0aGlzLndpZHRoID0gR2VuZXJpY1NpemUuY3JlYXRlKHRoaXMubGVmdCwgdGhpcy5yaWdodCwgXCJyZW5kZXJlZCB3aWR0aCBvZiBcIiArIGVsZW1lbnQpO1xuXHR0aGlzLmhlaWdodCA9IEdlbmVyaWNTaXplLmNyZWF0ZSh0aGlzLnRvcCwgdGhpcy5ib3R0b20sIFwicmVuZGVyZWQgaGVpZ2h0IG9mIFwiICsgZWxlbWVudCk7XG5cblx0dGhpcy5jZW50ZXIgPSBDZW50ZXIueCh0aGlzLmxlZnQsIHRoaXMucmlnaHQsIFwicmVuZGVyZWQgY2VudGVyIG9mIFwiICsgZWxlbWVudCk7XG5cdHRoaXMubWlkZGxlID0gQ2VudGVyLnkodGhpcy50b3AsIHRoaXMuYm90dG9tLCBcInJlbmRlcmVkIG1pZGRsZSBvZiBcIiArIGVsZW1lbnQpO1xufTtcbkRlc2NyaXB0b3IuZXh0ZW5kKE1lKTtcblxuTWUuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGVsZW1lbnQpIHtcblx0cmV0dXJuIG5ldyBNZShlbGVtZW50KTtcbn07XG5cbk1lLnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkge1xuXHRpZiAodGhpcy50b3AudmFsdWUoKS5lcXVhbHMoUG9zaXRpb24ubm9ZKCkpKSByZXR1cm4gUmVuZGVyU3RhdGUubm90UmVuZGVyZWQoKTtcblx0ZWxzZSByZXR1cm4gUmVuZGVyU3RhdGUucmVuZGVyZWQoKTtcbn07XG5cbk1lLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuXHRyZXR1cm4gXCJyZW5kZXIgc3RhdHVzIG9mIFwiICsgdGhpcy5fZWxlbWVudC50b1N0cmluZygpO1xufTtcblxuTWUucHJvdG90eXBlLmNvbnZlcnQgPSBmdW5jdGlvbiBjb252ZXJ0KGFyZywgdHlwZSkge1xuXHRpZiAodHlwZSA9PT0gXCJib29sZWFuXCIpIHtcblx0XHRyZXR1cm4gYXJnID8gUmVuZGVyU3RhdGUucmVuZGVyZWQoKSA6IFJlbmRlclN0YXRlLm5vdFJlbmRlcmVkKCk7XG5cdH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgcXVpeG90ZSA9IHJlcXVpcmUoXCIuLi9xdWl4b3RlLmpzXCIpO1xudmFyIFBvc2l0aW9uRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3Bvc2l0aW9uX2Rlc2NyaXB0b3IuanNcIik7XG52YXIgUG9zaXRpb24gPSByZXF1aXJlKFwiLi4vdmFsdWVzL3Bvc2l0aW9uLmpzXCIpO1xudmFyIFNpemUgPSByZXF1aXJlKFwiLi4vdmFsdWVzL3NpemUuanNcIik7XG52YXIgUmVuZGVyU3RhdGUgPSByZXF1aXJlKFwiLi4vdmFsdWVzL3JlbmRlcl9zdGF0ZS5qc1wiKTtcblxudmFyIFRPUCA9IFwidG9wXCI7XG52YXIgUklHSFQgPSBcInJpZ2h0XCI7XG52YXIgQk9UVE9NID0gXCJib3R0b21cIjtcbnZhciBMRUZUID0gXCJsZWZ0XCI7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gRWxlbWVudFZpc2libGVFZGdlKGVsZW1lbnQsIHBvc2l0aW9uKSB7XG5cdHZhciBRRWxlbWVudCA9IHJlcXVpcmUoXCIuLi9xX2VsZW1lbnQuanNcIik7ICAgICAgLy8gYnJlYWsgY2lyY3VsYXIgZGVwZW5kZW5jeVxuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgWyBRRWxlbWVudCwgU3RyaW5nIF0pO1xuXG5cdGlmIChwb3NpdGlvbiA9PT0gTEVGVCB8fCBwb3NpdGlvbiA9PT0gUklHSFQpIFBvc2l0aW9uRGVzY3JpcHRvci54KHRoaXMpO1xuXHRlbHNlIGlmIChwb3NpdGlvbiA9PT0gVE9QIHx8IHBvc2l0aW9uID09PSBCT1RUT00pIFBvc2l0aW9uRGVzY3JpcHRvci55KHRoaXMpO1xuXHRlbHNlIHVua25vd25Qb3NpdGlvbihwb3NpdGlvbik7XG5cblx0dGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG5cdHRoaXMuX3Bvc2l0aW9uID0gcG9zaXRpb247XG59O1xuUG9zaXRpb25EZXNjcmlwdG9yLmV4dGVuZChNZSk7XG5cbk1lLnRvcCA9IGZhY3RvcnlGbihUT1ApO1xuTWUucmlnaHQgPSBmYWN0b3J5Rm4oUklHSFQpO1xuTWUuYm90dG9tID0gZmFjdG9yeUZuKEJPVFRPTSk7XG5NZS5sZWZ0ID0gZmFjdG9yeUZuKExFRlQpO1xuXG5mdW5jdGlvbiBmYWN0b3J5Rm4ocG9zaXRpb24pIHtcblx0cmV0dXJuIGZ1bmN0aW9uIGZhY3RvcnkoZWxlbWVudCkge1xuXHRcdHJldHVybiBuZXcgTWUoZWxlbWVudCwgcG9zaXRpb24pO1xuXHR9O1xufVxuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblx0cmV0dXJuIHRoaXMuX3Bvc2l0aW9uICsgXCIgcmVuZGVyZWQgZWRnZSBvZiBcIiArIHRoaXMuX2VsZW1lbnQ7XG59O1xuXG5NZS5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbigpIHtcblx0dmFyIHBvc2l0aW9uID0gdGhpcy5fcG9zaXRpb247XG5cdHZhciBlbGVtZW50ID0gdGhpcy5fZWxlbWVudDtcblx0dmFyIHBhZ2UgPSBlbGVtZW50LmZyYW1lLnBhZ2UoKTtcblxuXHRpZiAoZWxlbWVudC50b3AudmFsdWUoKS5lcXVhbHMoUG9zaXRpb24ubm9ZKCkpKSByZXR1cm4gbm90UmVuZGVyZWQocG9zaXRpb24pO1xuXHRpZiAoZWxlbWVudC53aWR0aC52YWx1ZSgpLmVxdWFscyhTaXplLmNyZWF0ZSgwKSkpIHJldHVybiBub3RSZW5kZXJlZChwb3NpdGlvbik7XG5cdGlmIChlbGVtZW50LmhlaWdodC52YWx1ZSgpLmVxdWFscyhTaXplLmNyZWF0ZSgwKSkpIHJldHVybiBub3RSZW5kZXJlZChwb3NpdGlvbik7XG5cblx0ZW5zdXJlLnRoYXQoXG5cdFx0IWhhc0NsaXBQYXRoUHJvcGVydHkoZWxlbWVudCksXG5cdFx0XCJDYW4ndCBkZXRlY3QgZWxlbWVudCBjbGlwcGluZyBib3VuZGFyaWVzIHdoZW4gJ2NsaXAtcGF0aCcgcHJvcGVydHkgaXMgdXNlZC5cIlxuXHQpO1xuXG5cdHZhciBib3VuZHMgPSB7XG5cdFx0dG9wOiBwYWdlLnRvcC52YWx1ZSgpLFxuXHRcdHJpZ2h0OiBudWxsLFxuXHRcdGJvdHRvbTogbnVsbCxcblx0XHRsZWZ0OiBwYWdlLmxlZnQudmFsdWUoKVxuXHR9O1xuXG5cdGJvdW5kcyA9IGludGVyc2VjdGlvbldpdGhPdmVyZmxvdyhlbGVtZW50LCBib3VuZHMpO1xuXHRib3VuZHMgPSBpbnRlcnNlY3Rpb25XaXRoQ2xpcChlbGVtZW50LCBib3VuZHMpO1xuXG5cdHZhciBlZGdlcyA9IGludGVyc2VjdGlvbihcblx0XHRib3VuZHMsXG5cdFx0ZWxlbWVudC50b3AudmFsdWUoKSxcblx0XHRlbGVtZW50LnJpZ2h0LnZhbHVlKCksXG5cdFx0ZWxlbWVudC5ib3R0b20udmFsdWUoKSxcblx0XHRlbGVtZW50LmxlZnQudmFsdWUoKVxuXHQpO1xuXG5cdGlmIChpc0NsaXBwZWRPdXRPZkV4aXN0ZW5jZShib3VuZHMsIGVkZ2VzKSkgcmV0dXJuIG5vdFJlbmRlcmVkKHBvc2l0aW9uKTtcblx0ZWxzZSByZXR1cm4gZWRnZShlZGdlcywgcG9zaXRpb24pO1xufTtcblxuZnVuY3Rpb24gaGFzQ2xpcFBhdGhQcm9wZXJ0eShlbGVtZW50KSB7XG5cdHZhciBjbGlwUGF0aCA9IGVsZW1lbnQuZ2V0UmF3U3R5bGUoXCJjbGlwLXBhdGhcIik7XG5cdHJldHVybiBjbGlwUGF0aCAhPT0gXCJub25lXCIgJiYgY2xpcFBhdGggIT09IFwiXCI7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbldpdGhPdmVyZmxvdyhlbGVtZW50LCBib3VuZHMpIHtcblx0Zm9yICh2YXIgY29udGFpbmVyID0gZWxlbWVudC5wYXJlbnQoKTsgY29udGFpbmVyICE9PSBudWxsOyBjb250YWluZXIgPSBjb250YWluZXIucGFyZW50KCkpIHtcblx0XHRpZiAoaXNDbGlwcGVkQnlBbmNlc3Rvck92ZXJmbG93KGVsZW1lbnQsIGNvbnRhaW5lcikpIHtcblx0XHRcdGJvdW5kcyA9IGludGVyc2VjdGlvbihcblx0XHRcdFx0Ym91bmRzLFxuXHRcdFx0XHRjb250YWluZXIudG9wLnZhbHVlKCksXG5cdFx0XHRcdGNvbnRhaW5lci5yaWdodC52YWx1ZSgpLFxuXHRcdFx0XHRjb250YWluZXIuYm90dG9tLnZhbHVlKCksXG5cdFx0XHRcdGNvbnRhaW5lci5sZWZ0LnZhbHVlKClcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGJvdW5kcztcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uV2l0aENsaXAoZWxlbWVudCwgYm91bmRzKSB7XG5cdC8vIFdPUktBUk9VTkQgSUUgODogRG9lc24ndCBoYXZlIGFueSB3YXkgdG8gZGV0ZWN0ICdjbGlwOiBhdXRvJyB2YWx1ZS5cblx0ZW5zdXJlLnRoYXQoIXF1aXhvdGUuYnJvd3Nlci5taXNyZXBvcnRzQ2xpcEF1dG9Qcm9wZXJ0eSgpLFxuXHRcdFwiQ2FuJ3QgZGV0ZXJtaW5lIGVsZW1lbnQgY2xpcHBpbmcgdmFsdWVzIG9uIHRoaXMgYnJvd3NlciBiZWNhdXNlIGl0IG1pc3JlcG9ydHMgdGhlIHZhbHVlIG9mIHRoZVwiICtcblx0XHRcIiBgY2xpcDogYXV0b2AgcHJvcGVydHkuIFlvdSBjYW4gdXNlIGBxdWl4b3RlLmJyb3dzZXIubWlzcmVwb3J0c0NsaXBBdXRvUHJvcGVydHkoKWAgdG8gc2tpcCB0aGlzIGJyb3dzZXIuXCJcblx0KTtcblxuXHRmb3IgKCA7IGVsZW1lbnQgIT09IG51bGw7IGVsZW1lbnQgPSBlbGVtZW50LnBhcmVudCgpKSB7XG5cdFx0dmFyIGNsaXAgPSBlbGVtZW50LmdldFJhd1N0eWxlKFwiY2xpcFwiKTtcblx0XHRpZiAoY2xpcCA9PT0gXCJhdXRvXCIgfHwgIWNhbkJlQ2xpcHBlZEJ5Q2xpcFByb3BlcnR5KGVsZW1lbnQpKSBjb250aW51ZTtcblxuXHRcdHZhciBjbGlwRWRnZXMgPSBub3JtYWxpemVDbGlwUHJvcGVydHkoZWxlbWVudCwgY2xpcCk7XG5cdFx0Ym91bmRzID0gaW50ZXJzZWN0aW9uKFxuXHRcdFx0Ym91bmRzLFxuXHRcdFx0Y2xpcEVkZ2VzLnRvcCxcblx0XHRcdGNsaXBFZGdlcy5yaWdodCxcblx0XHRcdGNsaXBFZGdlcy5ib3R0b20sXG5cdFx0XHRjbGlwRWRnZXMubGVmdFxuXHRcdCk7XG5cdH1cblxuXHRyZXR1cm4gYm91bmRzO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemVDbGlwUHJvcGVydHkoZWxlbWVudCwgY2xpcCkge1xuXHR2YXIgY2xpcFZhbHVlcyA9IHBhcnNlQ2xpcFByb3BlcnR5KGVsZW1lbnQsIGNsaXApO1xuXG5cdHJldHVybiB7XG5cdFx0dG9wOiBjbGlwVmFsdWVzWzBdID09PSBcImF1dG9cIiA/XG5cdFx0XHRlbGVtZW50LnRvcC52YWx1ZSgpIDpcblx0XHRcdGVsZW1lbnQudG9wLnZhbHVlKCkucGx1cyhQb3NpdGlvbi55KE51bWJlcihjbGlwVmFsdWVzWzBdKSkpLFxuXHRcdHJpZ2h0OiBjbGlwVmFsdWVzWzFdID09PSBcImF1dG9cIiA/XG5cdFx0XHRlbGVtZW50LnJpZ2h0LnZhbHVlKCkgOlxuXHRcdFx0ZWxlbWVudC5sZWZ0LnZhbHVlKCkucGx1cyhQb3NpdGlvbi54KE51bWJlcihjbGlwVmFsdWVzWzFdKSkpLFxuXHRcdGJvdHRvbTogY2xpcFZhbHVlc1syXSA9PT0gXCJhdXRvXCIgP1xuXHRcdFx0ZWxlbWVudC5ib3R0b20udmFsdWUoKSA6XG5cdFx0XHRlbGVtZW50LnRvcC52YWx1ZSgpLnBsdXMoUG9zaXRpb24ueShOdW1iZXIoY2xpcFZhbHVlc1syXSkpKSxcblx0XHRsZWZ0OiBjbGlwVmFsdWVzWzNdID09PSBcImF1dG9cIiA/XG5cdFx0XHRlbGVtZW50LmxlZnQudmFsdWUoKSA6XG5cdFx0XHRlbGVtZW50LmxlZnQudmFsdWUoKS5wbHVzKFBvc2l0aW9uLngoTnVtYmVyKGNsaXBWYWx1ZXNbM10pKSlcblx0fTtcblxuXHRmdW5jdGlvbiBwYXJzZUNsaXBQcm9wZXJ0eShlbGVtZW50LCBjbGlwKSB7XG5cdFx0Ly8gV09SS0FST1VORCBJRSAxMSwgQ2hyb21lIE1vYmlsZSA0NDogUmVwb3J0cyAwcHggaW5zdGVhZCBvZiAnYXV0bycgd2hlbiBjb21wdXRpbmcgcmVjdCgpIGluIGNsaXAgcHJvcGVydHkuXG5cdFx0ZW5zdXJlLnRoYXQoIXF1aXhvdGUuYnJvd3Nlci5taXNyZXBvcnRzQXV0b1ZhbHVlc0luQ2xpcFByb3BlcnR5KCksXG5cdFx0XHRcIkNhbid0IGRldGVybWluZSBlbGVtZW50IGNsaXBwaW5nIHZhbHVlcyBvbiB0aGlzIGJyb3dzZXIgYmVjYXVzZSBpdCBtaXNyZXBvcnRzIHRoZSB2YWx1ZSBvZiB0aGUgYGNsaXBgXCIgK1xuXHRcdFx0XCIgcHJvcGVydHkuIFlvdSBjYW4gdXNlIGBxdWl4b3RlLmJyb3dzZXIubWlzcmVwb3J0c0F1dG9WYWx1ZXNJbkNsaXBQcm9wZXJ0eSgpYCB0byBza2lwIHRoaXMgYnJvd3Nlci5cIlxuXHRcdCk7XG5cblx0XHR2YXIgY2xpcFJlZ2V4ID0gL3JlY3RcXCgoLio/KSw/ICguKj8pLD8gKC4qPyksPyAoLio/KVxcKS87XG5cdFx0dmFyIG1hdGNoZXMgPSBjbGlwUmVnZXguZXhlYyhjbGlwKTtcblx0XHRlbnN1cmUudGhhdChtYXRjaGVzICE9PSBudWxsLCBcIlVuYWJsZSB0byBwYXJzZSBjbGlwIHByb3BlcnR5OiBcIiArIGNsaXApO1xuXG5cdFx0cmV0dXJuIFtcblx0XHRcdHBhcnNlTGVuZ3RoKG1hdGNoZXNbMV0sIGNsaXApLFxuXHRcdFx0cGFyc2VMZW5ndGgobWF0Y2hlc1syXSwgY2xpcCksXG5cdFx0XHRwYXJzZUxlbmd0aChtYXRjaGVzWzNdLCBjbGlwKSxcblx0XHRcdHBhcnNlTGVuZ3RoKG1hdGNoZXNbNF0sIGNsaXApXG5cdFx0XTtcblx0fVxuXG5cdGZ1bmN0aW9uIHBhcnNlTGVuZ3RoKHB4U3RyaW5nLCBjbGlwKSB7XG5cdFx0aWYgKHB4U3RyaW5nID09PSBcImF1dG9cIikgcmV0dXJuIHB4U3RyaW5nO1xuXG5cdFx0dmFyIHB4UmVnZXggPSAvXiguKj8pcHgkLztcblx0XHR2YXIgbWF0Y2hlcyA9IHB4UmVnZXguZXhlYyhweFN0cmluZyk7XG5cdFx0ZW5zdXJlLnRoYXQobWF0Y2hlcyAhPT0gbnVsbCwgXCJVbmFibGUgdG8gcGFyc2UgJ1wiICsgcHhTdHJpbmcgKyBcIicgaW4gY2xpcCBwcm9wZXJ0eTogXCIgKyBjbGlwKTtcblxuXHRcdHJldHVybiBtYXRjaGVzWzFdO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGlzQ2xpcHBlZEJ5QW5jZXN0b3JPdmVyZmxvdyhlbGVtZW50LCBhbmNlc3Rvcikge1xuXHRyZXR1cm4gY2FuQmVDbGlwcGVkQnlPdmVyZmxvd1Byb3BlcnR5KGVsZW1lbnQpICYmIGhhc0NsaXBwaW5nT3ZlcmZsb3coYW5jZXN0b3IpO1xufVxuXG5mdW5jdGlvbiBjYW5CZUNsaXBwZWRCeU92ZXJmbG93UHJvcGVydHkoZWxlbWVudCkge1xuXHR2YXIgcG9zaXRpb24gPSBlbGVtZW50LmdldFJhd1N0eWxlKFwicG9zaXRpb25cIik7XG5cdHN3aXRjaCAocG9zaXRpb24pIHtcblx0XHRjYXNlIFwic3RhdGljXCI6XG5cdFx0Y2FzZSBcInJlbGF0aXZlXCI6XG5cdFx0Y2FzZSBcImFic29sdXRlXCI6XG5cdFx0Y2FzZSBcInN0aWNreVwiOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0Y2FzZSBcImZpeGVkXCI6XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdGVuc3VyZS51bnJlYWNoYWJsZShcIlVua25vd24gcG9zaXRpb24gcHJvcGVydHk6IFwiICsgcG9zaXRpb24pO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGhhc0NsaXBwaW5nT3ZlcmZsb3coZWxlbWVudCkge1xuXHR2YXIgb3ZlcmZsb3cgPSBlbGVtZW50LmdldFJhd1N0eWxlKFwib3ZlcmZsb3dcIik7XG5cdHN3aXRjaCAob3ZlcmZsb3cpIHtcblx0XHRjYXNlIFwiaGlkZGVuXCI6XG5cdFx0Y2FzZSBcInNjcm9sbFwiOlxuXHRcdGNhc2UgXCJhdXRvXCI6XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRjYXNlIFwidmlzaWJsZVwiOlxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdGRlZmF1bHQ6XG5cdFx0XHRlbnN1cmUudW5yZWFjaGFibGUoXCJVbmtub3duIG92ZXJmbG93IHByb3BlcnR5OiBcIiArIG92ZXJmbG93KTtcblx0fVxufVxuXG5mdW5jdGlvbiBjYW5CZUNsaXBwZWRCeUNsaXBQcm9wZXJ0eShlbGVtZW50KSB7XG5cdHZhciBwb3NpdGlvbiA9IGVsZW1lbnQuZ2V0UmF3U3R5bGUoXCJwb3NpdGlvblwiKTtcblx0c3dpdGNoIChwb3NpdGlvbikge1xuXHRcdGNhc2UgXCJhYnNvbHV0ZVwiOlxuXHRcdGNhc2UgXCJmaXhlZFwiOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0Y2FzZSBcInN0YXRpY1wiOlxuXHRcdGNhc2UgXCJyZWxhdGl2ZVwiOlxuXHRcdGNhc2UgXCJzdGlja3lcIjpcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRkZWZhdWx0OlxuXHRcdFx0ZW5zdXJlLnVucmVhY2hhYmxlKFwiVW5rbm93biBwb3NpdGlvbiBwcm9wZXJ0eTogXCIgKyBwb3NpdGlvbik7XG5cdH1cbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uKGJvdW5kcywgdG9wLCByaWdodCwgYm90dG9tLCBsZWZ0KSB7XG5cdGJvdW5kcy50b3AgPSBib3VuZHMudG9wLm1heCh0b3ApO1xuXHRib3VuZHMucmlnaHQgPSAoYm91bmRzLnJpZ2h0ID09PSBudWxsKSA/IHJpZ2h0IDogYm91bmRzLnJpZ2h0Lm1pbihyaWdodCk7XG5cdGJvdW5kcy5ib3R0b20gPSAoYm91bmRzLmJvdHRvbSA9PT0gbnVsbCkgPyBib3R0b20gOiBib3VuZHMuYm90dG9tLm1pbihib3R0b20pO1xuXHRib3VuZHMubGVmdCA9IGJvdW5kcy5sZWZ0Lm1heChsZWZ0KTtcblxuXHRyZXR1cm4gYm91bmRzO1xufVxuXG5mdW5jdGlvbiBpc0NsaXBwZWRPdXRPZkV4aXN0ZW5jZShib3VuZHMsIGVkZ2VzKSB7XG5cdHJldHVybiAoYm91bmRzLnRvcC5jb21wYXJlKGVkZ2VzLmJvdHRvbSkgPj0gMCkgfHxcblx0XHQoYm91bmRzLnJpZ2h0ICE9PSBudWxsICYmIGJvdW5kcy5yaWdodC5jb21wYXJlKGVkZ2VzLmxlZnQpIDw9IDApIHx8XG5cdFx0KGJvdW5kcy5ib3R0b20gIT09IG51bGwgJiYgYm91bmRzLmJvdHRvbS5jb21wYXJlKGVkZ2VzLnRvcCkgPD0gMCkgfHxcblx0XHQoYm91bmRzLmxlZnQuY29tcGFyZShlZGdlcy5yaWdodCkgPj0gMCk7XG59XG5cbmZ1bmN0aW9uIG5vdFJlbmRlcmVkKHBvc2l0aW9uKSB7XG5cdHN3aXRjaChwb3NpdGlvbikge1xuXHRcdGNhc2UgVE9QOlxuXHRcdGNhc2UgQk9UVE9NOlxuXHRcdFx0cmV0dXJuIFBvc2l0aW9uLm5vWSgpO1xuXHRcdGNhc2UgTEVGVDpcblx0XHRjYXNlIFJJR0hUOlxuXHRcdFx0cmV0dXJuIFBvc2l0aW9uLm5vWCgpO1xuXHRcdGRlZmF1bHQ6IHVua25vd25Qb3NpdGlvbihwb3NpdGlvbik7XG5cdH1cbn1cblxuZnVuY3Rpb24gZWRnZShlZGdlcywgcG9zaXRpb24pIHtcblx0c3dpdGNoKHBvc2l0aW9uKSB7XG5cdFx0Y2FzZSBUT1A6IHJldHVybiBlZGdlcy50b3A7XG5cdFx0Y2FzZSBSSUdIVDogcmV0dXJuIGVkZ2VzLnJpZ2h0O1xuXHRcdGNhc2UgQk9UVE9NOiByZXR1cm4gZWRnZXMuYm90dG9tO1xuXHRcdGNhc2UgTEVGVDogcmV0dXJuIGVkZ2VzLmxlZnQ7XG5cdFx0ZGVmYXVsdDogdW5rbm93blBvc2l0aW9uKHBvc2l0aW9uKTtcblx0fVxufVxuXG5mdW5jdGlvbiB1bmtub3duUG9zaXRpb24ocG9zaXRpb24pIHtcblx0ZW5zdXJlLnVucmVhY2hhYmxlKFwiVW5rbm93biBwb3NpdGlvbjogXCIgKyBwb3NpdGlvbik7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgUG9zaXRpb25EZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vcG9zaXRpb25fZGVzY3JpcHRvci5qc1wiKTtcbnZhciBTaXplRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3NpemVfZGVzY3JpcHRvci5qc1wiKTtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBHZW5lcmljU2l6ZShmcm9tLCB0bywgZGVzY3JpcHRpb24pIHtcbiAgZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgUG9zaXRpb25EZXNjcmlwdG9yLCBQb3NpdGlvbkRlc2NyaXB0b3IsIFN0cmluZyBdKTtcblxuICB0aGlzLl9mcm9tID0gZnJvbTtcbiAgdGhpcy5fdG8gPSB0bztcbiAgdGhpcy5fZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbjtcbn07XG5TaXplRGVzY3JpcHRvci5leHRlbmQoTWUpO1xuXG5NZS5jcmVhdGUgPSBmdW5jdGlvbihmcm9tLCB0bywgZGVzY3JpcHRpb24pIHtcbiAgcmV0dXJuIG5ldyBNZShmcm9tLCB0bywgZGVzY3JpcHRpb24pO1xufTtcblxuTWUucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24oKSB7XG4gIGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG4gIHJldHVybiB0aGlzLl9mcm9tLnZhbHVlKCkuZGlzdGFuY2VUbyh0aGlzLl90by52YWx1ZSgpKTtcbn07XG5cbk1lLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5fZGVzY3JpcHRpb247XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4uL3V0aWwvZW5zdXJlLmpzXCIpO1xudmFyIFBvc2l0aW9uRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3Bvc2l0aW9uX2Rlc2NyaXB0b3IuanNcIik7XG52YXIgUG9zaXRpb24gPSByZXF1aXJlKFwiLi4vdmFsdWVzL3Bvc2l0aW9uLmpzXCIpO1xuXG52YXIgVE9QID0gXCJ0b3BcIjtcbnZhciBSSUdIVCA9IFwicmlnaHRcIjtcbnZhciBCT1RUT00gPSBcImJvdHRvbVwiO1xudmFyIExFRlQgPSBcImxlZnRcIjtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBQYWdlRWRnZShlZGdlLCBmcmFtZSkge1xuXHR2YXIgUUZyYW1lID0gcmVxdWlyZShcIi4uL3FfZnJhbWUuanNcIik7ICAgIC8vIGJyZWFrIGNpcmN1bGFyIGRlcGVuZGVuY3lcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgU3RyaW5nLCBRRnJhbWUgXSk7XG5cblx0aWYgKGVkZ2UgPT09IExFRlQgfHwgZWRnZSA9PT0gUklHSFQpIFBvc2l0aW9uRGVzY3JpcHRvci54KHRoaXMpO1xuXHRlbHNlIGlmIChlZGdlID09PSBUT1AgfHwgZWRnZSA9PT0gQk9UVE9NKSBQb3NpdGlvbkRlc2NyaXB0b3IueSh0aGlzKTtcblx0ZWxzZSBlbnN1cmUudW5yZWFjaGFibGUoXCJVbmtub3duIGVkZ2U6IFwiICsgZWRnZSk7XG5cblx0dGhpcy5fZWRnZSA9IGVkZ2U7XG5cdHRoaXMuX2ZyYW1lID0gZnJhbWU7XG59O1xuUG9zaXRpb25EZXNjcmlwdG9yLmV4dGVuZChNZSk7XG5cbk1lLnRvcCA9IGZhY3RvcnlGbihUT1ApO1xuTWUucmlnaHQgPSBmYWN0b3J5Rm4oUklHSFQpO1xuTWUuYm90dG9tID0gZmFjdG9yeUZuKEJPVFRPTSk7XG5NZS5sZWZ0ID0gZmFjdG9yeUZuKExFRlQpO1xuXG5NZS5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbiB2YWx1ZSgpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHR2YXIgc2l6ZSA9IHBhZ2VTaXplKHRoaXMuX2ZyYW1lLnRvRG9tRWxlbWVudCgpLmNvbnRlbnREb2N1bWVudCk7XG5cdHN3aXRjaCh0aGlzLl9lZGdlKSB7XG5cdFx0Y2FzZSBUT1A6IHJldHVybiBQb3NpdGlvbi55KDApO1xuXHRcdGNhc2UgUklHSFQ6IHJldHVybiBQb3NpdGlvbi54KHNpemUud2lkdGgpO1xuXHRcdGNhc2UgQk9UVE9NOiByZXR1cm4gUG9zaXRpb24ueShzaXplLmhlaWdodCk7XG5cdFx0Y2FzZSBMRUZUOiByZXR1cm4gUG9zaXRpb24ueCgwKTtcblxuXHRcdGRlZmF1bHQ6IGVuc3VyZS51bnJlYWNoYWJsZSgpO1xuXHR9XG59O1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHRzd2l0Y2godGhpcy5fZWRnZSkge1xuXHRcdGNhc2UgVE9QOiByZXR1cm4gXCJ0b3Agb2YgcGFnZVwiO1xuXHRcdGNhc2UgUklHSFQ6IHJldHVybiBcInJpZ2h0IHNpZGUgb2YgcGFnZVwiO1xuXHRcdGNhc2UgQk9UVE9NOiByZXR1cm4gXCJib3R0b20gb2YgcGFnZVwiO1xuXHRcdGNhc2UgTEVGVDogcmV0dXJuIFwibGVmdCBzaWRlIG9mIHBhZ2VcIjtcblxuXHRcdGRlZmF1bHQ6IGVuc3VyZS51bnJlYWNoYWJsZSgpO1xuXHR9XG59O1xuXG5mdW5jdGlvbiBmYWN0b3J5Rm4oZWRnZSkge1xuXHRyZXR1cm4gZnVuY3Rpb24gZmFjdG9yeShmcmFtZSkge1xuXHRcdHJldHVybiBuZXcgTWUoZWRnZSwgZnJhbWUpO1xuXHR9O1xufVxuXG5cblxuLy8gVVNFRlVMIFJFQURJTkc6IGh0dHA6Ly93d3cucXVpcmtzbW9kZS5vcmcvbW9iaWxlL3ZpZXdwb3J0cy5odG1sXG4vLyBhbmQgaHR0cDovL3d3dy5xdWlya3Ntb2RlLm9yZy9tb2JpbGUvdmlld3BvcnRzMi5odG1sXG5cbi8vIEFQSSBTRU1BTlRJQ1MuXG4vLyBSZWYgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0NTU19PYmplY3RfTW9kZWwvRGV0ZXJtaW5pbmdfdGhlX2RpbWVuc2lvbnNfb2ZfZWxlbWVudHNcbi8vICAgIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoOiBzdW0gb2YgYm91bmRpbmcgYm94ZXMgb2YgZWxlbWVudCAodGhlIGRpc3BsYXllZCB3aWR0aCBvZiB0aGUgZWxlbWVudCxcbi8vICAgICAgaW5jbHVkaW5nIHBhZGRpbmcgYW5kIGJvcmRlcikuIEZyYWN0aW9uYWwuIEFwcGxpZXMgdHJhbnNmb3JtYXRpb25zLlxuLy8gICAgY2xpZW50V2lkdGg6IHZpc2libGUgd2lkdGggb2YgZWxlbWVudCBpbmNsdWRpbmcgcGFkZGluZyAoYnV0IG5vdCBib3JkZXIpLiBFWENFUFQgb24gcm9vdCBlbGVtZW50IChodG1sKSwgd2hlcmVcbi8vICAgICAgaXQgaXMgdGhlIHdpZHRoIG9mIHRoZSB2aWV3cG9ydC4gUm91bmRzIHRvIGFuIGludGVnZXIuIERvZXNuJ3QgYXBwbHkgdHJhbnNmb3JtYXRpb25zLlxuLy8gICAgb2Zmc2V0V2lkdGg6IHZpc2libGUgd2lkdGggb2YgZWxlbWVudCBpbmNsdWRpbmcgcGFkZGluZywgYm9yZGVyLCBhbmQgc2Nyb2xsYmFycyAoaWYgYW55KS4gUm91bmRzIHRvIGFuIGludGVnZXIuXG4vLyAgICAgIERvZXNuJ3QgYXBwbHkgdHJhbnNmb3JtYXRpb25zLlxuLy8gICAgc2Nyb2xsV2lkdGg6IGVudGlyZSB3aWR0aCBvZiBlbGVtZW50LCBpbmNsdWRpbmcgYW55IHBhcnQgdGhhdCdzIG5vdCB2aXNpYmxlIGR1ZSB0byBzY3JvbGxiYXJzLiBSb3VuZHMgdG9cbi8vICAgICAgYW4gaW50ZWdlci4gRG9lc24ndCBhcHBseSB0cmFuc2Zvcm1hdGlvbnMuIE5vdCBjbGVhciBpZiBpdCBpbmNsdWRlcyBzY3JvbGxiYXJzLCBidXQgSSB0aGluayBub3QuIEFsc29cbi8vICAgICAgbm90IGNsZWFyIGlmIGl0IGluY2x1ZGVzIGJvcmRlcnMgb3IgcGFkZGluZy4gKEJ1dCBmcm9tIHRlc3RzLCBhcHBhcmVudGx5IG5vdCBib3JkZXJzLiBFeGNlcHQgb24gcm9vdFxuLy8gICAgICBlbGVtZW50IGFuZCBib2R5IGVsZW1lbnQsIHdoaWNoIGhhdmUgc3BlY2lhbCByZXN1bHRzIHRoYXQgdmFyeSBieSBicm93c2VyLilcblxuLy8gVEVTVCBSRVNVTFRTOiBXSURUSFxuLy8gICDinJQgPSBjb3JyZWN0IGFuc3dlclxuLy8gICDinJggPSBpbmNvcnJlY3QgYW5zd2VyIGFuZCBkaXZlcmdlcyBmcm9tIHNwZWNcbi8vICAgfiA9IGluY29ycmVjdCBhbnN3ZXIsIGJ1dCBtYXRjaGVzIHNwZWNcbi8vIEJST1dTRVJTIFRFU1RFRDogU2FmYXJpIDYuMi4wIChNYWMgT1MgWCAxMC44LjUpOyBNb2JpbGUgU2FmYXJpIDcuMC4wIChpT1MgNy4xKTsgRmlyZWZveCAzMi4wLjAgKE1hYyBPUyBYIDEwLjgpO1xuLy8gICAgRmlyZWZveCAzMy4wLjAgKFdpbmRvd3MgNyk7IENocm9tZSAzOC4wLjIxMjUgKE1hYyBPUyBYIDEwLjguNSk7IENocm9tZSAzOC4wLjIxMjUgKFdpbmRvd3MgNyk7IElFIDgsIDksIDEwLCAxMVxuXG4vLyBodG1sIHdpZHRoIHN0eWxlIHNtYWxsZXIgdGhhbiB2aWV3cG9ydCB3aWR0aDsgYm9keSB3aWR0aCBzdHlsZSBzbWFsbGVyIHRoYW4gaHRtbCB3aWR0aCBzdHlsZVxuLy8gIE5PVEU6IFRoZXNlIHRlc3RzIHdlcmUgY29uZHVjdGVkIHdoZW4gY29ycmVjdCByZXN1bHQgd2FzIHdpZHRoIG9mIGJvcmRlci4gVGhhdCBoYXMgYmVlbiBjaGFuZ2VkXG4vLyAgdG8gXCJ3aWR0aCBvZiB2aWV3cG9ydC5cIlxuLy8gICAgaHRtbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aFxuLy8gICAgICDinJggSUUgOCwgOSwgMTA6IHdpZHRoIG9mIHZpZXdwb3J0XG4vLyAgICAgIOKclCBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZSwgRmlyZWZveCwgSUUgMTE6IHdpZHRoIG9mIGh0bWwsIGluY2x1ZGluZyBib3JkZXJcbi8vICAgIGh0bWwuY2xpZW50V2lkdGhcbi8vICAgICAgfiBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZSwgRmlyZWZveCwgSUUgOCwgOSwgMTAsIDExOiB3aWR0aCBvZiB2aWV3cG9ydFxuLy8gICAgaHRtbC5vZmZzZXRXaWR0aFxuLy8gICAgICDinJggSUUgOCwgOSwgMTA6IHdpZHRoIG9mIHZpZXdwb3J0XG4vLyAgICAgIOKclCBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZSwgRmlyZWZveCwgSUUgMTE6IHdpZHRoIG9mIGh0bWwsIGluY2x1ZGluZyBib3JkZXJcbi8vICAgIGh0bWwuc2Nyb2xsV2lkdGhcbi8vICAgICAg4pyYIElFIDgsIDksIDEwLCAxMSwgRmlyZWZveDogd2lkdGggb2Ygdmlld3BvcnRcbi8vICAgICAgfiBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZTogd2lkdGggb2YgaHRtbCwgZXhjbHVkaW5nIGJvcmRlclxuLy8gICAgYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aFxuLy8gICAgICB+IFNhZmFyaSwgTW9iaWxlIFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IHdpZHRoIG9mIGJvZHksIGluY2x1ZGluZyBib3JkZXJcbi8vICAgIGJvZHkuY2xpZW50V2lkdGhcbi8vICAgICAgfiBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZSwgRmlyZWZveCwgSUUgOCwgOSwgMTAsIDExOiB3aWR0aCBvZiBib2R5LCBleGNsdWRpbmcgYm9yZGVyXG4vLyAgICBib2R5Lm9mZnNldFdpZHRoXG4vLyAgICAgIH4gU2FmYXJpLCBNb2JpbGUgU2FmYXJpLCBDaHJvbWUsIEZpcmVmb3gsIElFIDgsIDksIDEwLCAxMTogd2lkdGggb2YgYm9keSwgaW5jbHVkaW5nIGJvcmRlclxuLy8gICAgYm9keS5zY3JvbGxXaWR0aFxuLy8gICAgICDinJggU2FmYXJpLCBNb2JpbGUgU2FmYXJpLCBDaHJvbWU6IHdpZHRoIG9mIHZpZXdwb3J0XG4vLyAgICAgIH4gRmlyZWZveCwgSUUgOCwgOSwgMTAsIDExOiB3aWR0aCBvZiBib2R5LCBleGNsdWRpbmcgYm9yZGVyXG5cbi8vIGVsZW1lbnQgd2lkdGggc3R5bGUgd2lkZXIgdGhhbiB2aWV3cG9ydDsgYm9keSBhbmQgaHRtbCB3aWR0aCBzdHlsZXMgYXQgZGVmYXVsdFxuLy8gQlJPV1NFUiBCRUhBVklPUjogaHRtbCBhbmQgYm9keSBib3JkZXIgZXh0ZW5kIHRvIHdpZHRoIG9mIHZpZXdwb3J0IGFuZCBub3QgYmV5b25kIChleGNlcHQgb24gTW9iaWxlIFNhZmFyaSlcbi8vIENvcnJlY3QgcmVzdWx0IGlzIGVsZW1lbnQgd2lkdGggKyBib2R5IGJvcmRlci1sZWZ0ICsgaHRtbCBib3JkZXItbGVmdCAoZXhjZXB0IG9uIE1vYmlsZSBTYWZhcmkpXG4vLyBNb2JpbGUgU2FmYXJpIHVzZXMgYSBsYXlvdXQgdmlld3BvcnQsIHNvIGl0J3MgZXhwZWN0ZWQgdG8gaW5jbHVkZSBib2R5IGJvcmRlci1yaWdodCBhbmQgaHRtbCBib3JkZXItcmlnaHQuXG4vLyAgICBodG1sLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoXG4vLyAgICAgIOKclCBNb2JpbGUgU2FmYXJpOiBlbGVtZW50IHdpZHRoICsgYm9keSBib3JkZXIgKyBodG1sIGJvcmRlclxuLy8gICAgICB+IFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IHZpZXdwb3J0IHdpZHRoXG4vLyAgICBodG1sLmNsaWVudFdpZHRoXG4vLyAgICAgIOKclCBNb2JpbGUgU2FmYXJpOiBlbGVtZW50IHdpZHRoICsgYm9keSBib3JkZXIgKyBodG1sIGJvcmRlclxuLy8gICAgICB+IFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IHZpZXdwb3J0IHdpZHRoXG4vLyAgICBodG1sLm9mZnNldFdpZHRoXG4vLyAgICAgIOKclCBNb2JpbGUgU2FmYXJpOiBlbGVtZW50IHdpZHRoICsgYm9keSBib3JkZXIgKyBodG1sIGJvcmRlclxuLy8gICAgICB+IFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IHZpZXdwb3J0IHdpZHRoXG4vLyAgICBodG1sLnNjcm9sbFdpZHRoXG4vLyAgICAgIOKclCBNb2JpbGUgU2FmYXJpOiBlbGVtZW50IHdpZHRoICsgYm9keSBib3JkZXIgKyBodG1sIGJvcmRlclxuLy8gICAgICDinJggU2FmYXJpLCBDaHJvbWU6IGVsZW1lbnQgd2lkdGggKyBib2R5IGJvcmRlci1sZWZ0IChCVVQgTk9UIGh0bWwgYm9yZGVyLWxlZnQpXG4vLyAgICAgIOKclCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IGVsZW1lbnQgd2lkdGggKyBib2R5IGJvcmRlci1sZWZ0ICsgaHRtbCBib3JkZXItbGVmdFxuLy8gICAgYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aFxuLy8gICAgICB+IE1vYmlsZSBTYWZhcmk6IGVsZW1lbnQgd2lkdGggKyBib2R5IGJvcmRlclxuLy8gICAgICB+IFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IHZpZXdwb3J0IHdpZHRoIC0gaHRtbCBib3JkZXJcbi8vICAgIGJvZHkuY2xpZW50V2lkdGhcbi8vICAgICAgfiBNb2JpbGUgU2FmYXJpOiBlbGVtZW50IHdpZHRoXG4vLyAgICAgIH4gU2FmYXJpLCBDaHJvbWUsIEZpcmVmb3gsIElFIDgsIDksIDEwLCAxMTogdmlld3BvcnQgd2lkdGggLSBodG1sIGJvcmRlciAtIGJvZHkgYm9yZGVyXG4vLyAgICBib2R5Lm9mZnNldFdpZHRoXG4vLyAgICAgIH4gTW9iaWxlIFNhZmFyaTogZWxlbWVudCB3aWR0aCArIGJvZHkgYm9yZGVyXG4vLyAgICAgIH4gU2FmYXJpLCBDaHJvbWUsIEZpcmVmb3gsIElFIDgsIDksIDEwLCAxMTogdmlld3BvcnQgd2lkdGggLSBodG1sIGJvcmRlclxuLy8gICAgYm9keS5zY3JvbGxXaWR0aFxuLy8gICAgICDinJQgTW9iaWxlIFNhZmFyaTogZWxlbWVudCB3aWR0aCArIGJvZHkgYm9yZGVyICsgaHRtbCBib3JkZXJcbi8vICAgICAg4pyUIFNhZmFyaSwgQ2hyb21lOiBlbGVtZW50IHdpZHRoICsgYm9keSBib3JkZXItbGVmdCArIGh0bWwgYm9yZGVyLWxlZnQgKG1hdGNoZXMgYWN0dWFsIGJyb3dzZXIpXG4vLyAgICAgIH4gRmlyZWZveCwgSUUgOCwgOSwgMTAsIDExOiBlbGVtZW50IHdpZHRoXG5cbi8vIFRFU1QgUkVTVUxUUzogSEVJR0hUXG4vLyAgIOKclCA9IGNvcnJlY3QgYW5zd2VyXG4vLyAgIOKcmCA9IGluY29ycmVjdCBhbnN3ZXIgYW5kIGRpdmVyZ2VzIGZyb20gc3BlY1xuLy8gICB+ID0gaW5jb3JyZWN0IGFuc3dlciwgYnV0IG1hdGNoZXMgc3BlY1xuXG4vLyBodG1sIGhlaWdodCBzdHlsZSBzbWFsbGVyIHRoYW4gdmlld3BvcnQgaGVpZ2h0OyBib2R5IGhlaWdodCBzdHlsZSBzbWFsbGVyIHRoYW4gaHRtbCBoZWlnaHQgc3R5bGVcbi8vICBOT1RFOiBUaGVzZSB0ZXN0cyB3ZXJlIGNvbmR1Y3RlZCB3aGVuIGNvcnJlY3QgcmVzdWx0IHdhcyBoZWlnaHQgb2Ygdmlld3BvcnQuXG4vLyAgICBodG1sLmNsaWVudEhlaWdodFxuLy8gICAgICDinJQgU2FmYXJpLCBNb2JpbGUgU2FmYXJpLCBDaHJvbWUsIEZpcmVmb3gsIElFIDgsIDksIDEwLCAxMTogaGVpZ2h0IG9mIHZpZXdwb3J0XG5cbi8vIGVsZW1lbnQgaGVpZ2h0IHN0eWxlIHRhbGxlciB0aGFuIHZpZXdwb3J0OyBib2R5IGFuZCBodG1sIHdpZHRoIHN0eWxlcyBhdCBkZWZhdWx0XG4vLyBCUk9XU0VSIEJFSEFWSU9SOiBodG1sIGFuZCBib2R5IGJvcmRlciBlbmNsb3NlIGVudGlyZSBlbGVtZW50XG4vLyBDb3JyZWN0IHJlc3VsdCBpcyBlbGVtZW50IHdpZHRoICsgYm9keSBib3JkZXItdG9wICsgaHRtbCBib3JkZXItdG9wICsgYm9keSBib3JkZXItYm90dG9tICsgaHRtbCBib3JkZXItYm90dG9tXG4vLyAgICBodG1sLmNsaWVudEhlaWdodFxuLy8gICAgICDinJQgTW9iaWxlIFNhZmFyaTogZWxlbWVudCBoZWlnaHQgKyBhbGwgYm9yZGVyc1xuLy8gICAgICB+IFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IGhlaWdodCBvZiB2aWV3cG9ydFxuLy8gICAgaHRtbC5zY3JvbGxIZWlnaHRcbi8vICAgICAg4pyUIEZpcmVmb3gsIElFIDgsIDksIDEwLCAxMTogZWxlbWVudCBoZWlnaHQgKyBhbGwgYm9yZGVyc1xuLy8gICAgICDinJggU2FmYXJpLCBNb2JpbGUgU2FmYXJpLCBDaHJvbWU6IGVsZW1lbnQgaGVpZ2h0ICsgaHRtbCBib3JkZXItYm90dG9tXG4vLyAgICBib2R5LnNjcm9sbEhlaWdodFxuLy8gICAgICDinJQgU2FmYXJpLCBNb2JpbGUgU2FmYXJpLCBDaHJvbWU6IGVsZW1lbnQgaGVpZ2h0ICsgYWxsIGJvcmRlcnNcbi8vICAgICAgfiBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTE6IGVsZW1lbnQgaGVpZ2h0IChib2R5IGhlaWdodCAtIGJvZHkgYm9yZGVyKVxuZnVuY3Rpb24gcGFnZVNpemUoZG9jdW1lbnQpIHtcblx0dmFyIGh0bWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdHZhciBib2R5ID0gZG9jdW1lbnQuYm9keTtcblxuLy8gQkVTVCBXSURUSCBBTlNXRVIgU08gRkFSIChBU1NVTUlORyBWSUVXUE9SVCBJUyBNSU5JTVVNIEFOU1dFUik6XG5cdHZhciB3aWR0aCA9IE1hdGgubWF4KGJvZHkuc2Nyb2xsV2lkdGgsIGh0bWwuc2Nyb2xsV2lkdGgpO1xuXG4vLyBCRVNUIEhFSUdIVCBBTlNXRVIgU08gRkFSIChBU1NVTUlORyBWSUVXUE9SVCBJUyBNSU5JTVVNIEFOU1dFUik6XG5cdHZhciBoZWlnaHQgPSBNYXRoLm1heChib2R5LnNjcm9sbEhlaWdodCwgaHRtbC5zY3JvbGxIZWlnaHQpO1xuXG5cdHJldHVybiB7XG5cdFx0d2lkdGg6IHdpZHRoLFxuXHRcdGhlaWdodDogaGVpZ2h0XG5cdH07XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNyBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG4vKmVzbGludCBuZXctY2FwOiBcIm9mZlwiICovXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBvb3AgPSByZXF1aXJlKFwiLi4vdXRpbC9vb3AuanNcIik7XG52YXIgRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL2Rlc2NyaXB0b3IuanNcIik7XG52YXIgUG9zaXRpb24gPSByZXF1aXJlKFwiLi4vdmFsdWVzL3Bvc2l0aW9uLmpzXCIpO1xuXG4vLyBicmVhayBjaXJjdWxhciBkZXBlbmRlbmNpZXNcbmZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oKSB7XG5cdHJldHVybiByZXF1aXJlKFwiLi9yZWxhdGl2ZV9wb3NpdGlvbi5qc1wiKTtcbn1cbmZ1bmN0aW9uIEFic29sdXRlUG9zaXRpb24oKSB7XG5cdHJldHVybiByZXF1aXJlKFwiLi9hYnNvbHV0ZV9wb3NpdGlvbi5qc1wiKTtcbn1cbmZ1bmN0aW9uIEdlbmVyaWNTaXplKCkge1xuXHRyZXR1cm4gcmVxdWlyZShcIi4vZ2VuZXJpY19zaXplLmpzXCIpO1xufVxuXG52YXIgWF9ESU1FTlNJT04gPSBcInhcIjtcbnZhciBZX0RJTUVOU0lPTiA9IFwieVwiO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFBvc2l0aW9uRGVzY3JpcHRvcihkaW1lbnNpb24pIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgU3RyaW5nIF0pO1xuXHRlbnN1cmUudW5yZWFjaGFibGUoXCJQb3NpdGlvbkRlc2NyaXB0b3IgaXMgYWJzdHJhY3QgYW5kIHNob3VsZCBub3QgYmUgY29uc3RydWN0ZWQgZGlyZWN0bHkuXCIpO1xufTtcbkRlc2NyaXB0b3IuZXh0ZW5kKE1lKTtcbk1lLmV4dGVuZCA9IG9vcC5leHRlbmRGbihNZSk7XG5cbk1lLnggPSBmYWN0b3J5Rm4oWF9ESU1FTlNJT04pO1xuTWUueSA9IGZhY3RvcnlGbihZX0RJTUVOU0lPTik7XG5cbk1lLnByb3RvdHlwZS5wbHVzID0gZnVuY3Rpb24gcGx1cyhhbW91bnQpIHtcblx0aWYgKHRoaXMuX3BkYmMuZGltZW5zaW9uID09PSBYX0RJTUVOU0lPTikgcmV0dXJuIFJlbGF0aXZlUG9zaXRpb24oKS5yaWdodCh0aGlzLCBhbW91bnQpO1xuXHRlbHNlIHJldHVybiBSZWxhdGl2ZVBvc2l0aW9uKCkuZG93bih0aGlzLCBhbW91bnQpO1xufTtcblxuTWUucHJvdG90eXBlLm1pbnVzID0gZnVuY3Rpb24gbWludXMoYW1vdW50KSB7XG5cdGlmICh0aGlzLl9wZGJjLmRpbWVuc2lvbiA9PT0gWF9ESU1FTlNJT04pIHJldHVybiBSZWxhdGl2ZVBvc2l0aW9uKCkubGVmdCh0aGlzLCBhbW91bnQpO1xuXHRlbHNlIHJldHVybiBSZWxhdGl2ZVBvc2l0aW9uKCkudXAodGhpcywgYW1vdW50KTtcbn07XG5cbk1lLnByb3RvdHlwZS50byA9IGZ1bmN0aW9uIHRvKHBvc2l0aW9uKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbWyBNZSwgTnVtYmVyIF1dKTtcblx0aWYgKHR5cGVvZiBwb3NpdGlvbiA9PT0gXCJudW1iZXJcIikge1xuXHRcdGlmICh0aGlzLl9wZGJjLmRpbWVuc2lvbiA9PT0gWF9ESU1FTlNJT04pIHBvc2l0aW9uID0gQWJzb2x1dGVQb3NpdGlvbigpLngocG9zaXRpb24pO1xuXHRcdGVsc2UgcG9zaXRpb24gPSBBYnNvbHV0ZVBvc2l0aW9uKCkueShwb3NpdGlvbik7XG5cdH1cblx0aWYgKHRoaXMuX3BkYmMuZGltZW5zaW9uICE9PSBwb3NpdGlvbi5fcGRiYy5kaW1lbnNpb24pIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBjYWxjdWxhdGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gWCBjb29yZGluYXRlcyBvciB0d28gWSBjb29yZGluYXRlc1wiKTtcblx0fVxuXG5cdHJldHVybiBHZW5lcmljU2l6ZSgpLmNyZWF0ZSh0aGlzLCBwb3NpdGlvbiwgXCJkaXN0YW5jZSBmcm9tIFwiICsgdGhpcyArIFwiIHRvIFwiICsgcG9zaXRpb24pO1xufTtcblxuTWUucHJvdG90eXBlLmNvbnZlcnQgPSBmdW5jdGlvbiBjb252ZXJ0KGFyZywgdHlwZSkge1xuXHRzd2l0Y2ggKHR5cGUpIHtcblx0XHRjYXNlIFwibnVtYmVyXCI6IHJldHVybiB0aGlzLl9wZGJjLmRpbWVuc2lvbiA9PT0gWF9ESU1FTlNJT04gPyBQb3NpdGlvbi54KGFyZykgOiBQb3NpdGlvbi55KGFyZyk7XG5cdFx0Y2FzZSBcInN0cmluZ1wiOlxuXHRcdFx0aWYgKGFyZyA9PT0gXCJub25lXCIpIHJldHVybiB0aGlzLl9wZGJjLmRpbWVuc2lvbiA9PT0gWF9ESU1FTlNJT04gPyBQb3NpdGlvbi5ub1goKSA6IFBvc2l0aW9uLm5vWSgpO1xuXHRcdFx0ZWxzZSByZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0YnJlYWs7XG5cdFx0ZGVmYXVsdDogcmV0dXJuIHVuZGVmaW5lZDtcblx0fVxufTtcblxuZnVuY3Rpb24gZmFjdG9yeUZuKGRpbWVuc2lvbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gZmFjdG9yeShzZWxmKSB7XG5cdFx0Ly8gX3BkYmM6IFwiUG9zaXRpb25EZXNjcmlwdG9yIGJhc2UgY2xhc3MuXCIgQW4gYXR0ZW1wdCB0byBwcmV2ZW50IG5hbWUgY29uZmxpY3RzLlxuXHRcdHNlbGYuX3BkYmMgPSB7IGRpbWVuc2lvbjogZGltZW5zaW9uIH07XG5cdH07XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL2Rlc2NyaXB0b3IuanNcIik7XG52YXIgUG9zaXRpb25EZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vcG9zaXRpb25fZGVzY3JpcHRvci5qc1wiKTtcbnZhciBWYWx1ZSA9IHJlcXVpcmUoXCIuLi92YWx1ZXMvdmFsdWUuanNcIik7XG52YXIgU2l6ZSA9IHJlcXVpcmUoXCIuLi92YWx1ZXMvc2l6ZS5qc1wiKTtcblxudmFyIFhfRElNRU5TSU9OID0gXCJ4XCI7XG52YXIgWV9ESU1FTlNJT04gPSBcInlcIjtcbnZhciBQTFVTID0gMTtcbnZhciBNSU5VUyA9IC0xO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oZGltZW5zaW9uLCBkaXJlY3Rpb24sIHJlbGF0aXZlVG8sIHJlbGF0aXZlQW1vdW50KSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIFN0cmluZywgTnVtYmVyLCBEZXNjcmlwdG9yLCBbTnVtYmVyLCBEZXNjcmlwdG9yLCBWYWx1ZV0gXSk7XG5cblx0aWYgKGRpbWVuc2lvbiA9PT0gWF9ESU1FTlNJT04pIFBvc2l0aW9uRGVzY3JpcHRvci54KHRoaXMpO1xuXHRlbHNlIGlmIChkaW1lbnNpb24gPT09IFlfRElNRU5TSU9OKSBQb3NpdGlvbkRlc2NyaXB0b3IueSh0aGlzKTtcblx0ZWxzZSBlbnN1cmUudW5yZWFjaGFibGUoXCJVbmtub3duIGRpbWVuc2lvbjogXCIgKyBkaW1lbnNpb24pO1xuXG5cdHRoaXMuX2RpbWVuc2lvbiA9IGRpbWVuc2lvbjtcblx0dGhpcy5fZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXHR0aGlzLl9yZWxhdGl2ZVRvID0gcmVsYXRpdmVUbztcblxuXHRpZiAodHlwZW9mIHJlbGF0aXZlQW1vdW50ID09PSBcIm51bWJlclwiKSB7XG5cdFx0aWYgKHJlbGF0aXZlQW1vdW50IDwgMCkgdGhpcy5fZGlyZWN0aW9uICo9IC0xO1xuXHRcdHRoaXMuX2Ftb3VudCA9IFNpemUuY3JlYXRlKE1hdGguYWJzKHJlbGF0aXZlQW1vdW50KSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0dGhpcy5fYW1vdW50ID0gcmVsYXRpdmVBbW91bnQ7XG5cdH1cbn07XG5Qb3NpdGlvbkRlc2NyaXB0b3IuZXh0ZW5kKE1lKTtcblxuTWUucmlnaHQgPSBjcmVhdGVGbihYX0RJTUVOU0lPTiwgUExVUyk7XG5NZS5kb3duID0gY3JlYXRlRm4oWV9ESU1FTlNJT04sIFBMVVMpO1xuTWUubGVmdCA9IGNyZWF0ZUZuKFhfRElNRU5TSU9OLCBNSU5VUyk7XG5NZS51cCA9IGNyZWF0ZUZuKFlfRElNRU5TSU9OLCBNSU5VUyk7XG5cbmZ1bmN0aW9uIGNyZWF0ZUZuKGRpbWVuc2lvbiwgZGlyZWN0aW9uKSB7XG5cdHJldHVybiBmdW5jdGlvbiBjcmVhdGUocmVsYXRpdmVUbywgcmVsYXRpdmVBbW91bnQpIHtcblx0XHRyZXR1cm4gbmV3IE1lKGRpbWVuc2lvbiwgZGlyZWN0aW9uLCByZWxhdGl2ZVRvLCByZWxhdGl2ZUFtb3VudCk7XG5cdH07XG59XG5cbk1lLnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXG5cdHZhciBiYXNlVmFsdWUgPSB0aGlzLl9yZWxhdGl2ZVRvLnZhbHVlKCk7XG5cdHZhciByZWxhdGl2ZVZhbHVlID0gdGhpcy5fYW1vdW50LnZhbHVlKCk7XG5cblx0aWYgKHRoaXMuX2RpcmVjdGlvbiA9PT0gUExVUykgcmV0dXJuIGJhc2VWYWx1ZS5wbHVzKHJlbGF0aXZlVmFsdWUpO1xuXHRlbHNlIHJldHVybiBiYXNlVmFsdWUubWludXMocmVsYXRpdmVWYWx1ZSk7XG59O1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHR2YXIgYmFzZSA9IHRoaXMuX3JlbGF0aXZlVG8udG9TdHJpbmcoKTtcblx0aWYgKHRoaXMuX2Ftb3VudC5lcXVhbHMoU2l6ZS5jcmVhdGUoMCkpKSByZXR1cm4gYmFzZTtcblxuXHR2YXIgcmVsYXRpb24gPSB0aGlzLl9hbW91bnQudG9TdHJpbmcoKTtcblx0aWYgKHRoaXMuX2RpbWVuc2lvbiA9PT0gWF9ESU1FTlNJT04pIHJlbGF0aW9uICs9ICh0aGlzLl9kaXJlY3Rpb24gPT09IFBMVVMpID8gXCIgdG8gcmlnaHQgb2YgXCIgOiBcIiB0byBsZWZ0IG9mIFwiO1xuXHRlbHNlIHJlbGF0aW9uICs9ICh0aGlzLl9kaXJlY3Rpb24gPT09IFBMVVMpID8gXCIgYmVsb3cgXCIgOiBcIiBhYm92ZSBcIjtcblxuXHRyZXR1cm4gcmVsYXRpb24gKyBiYXNlO1xufTtcbiIsIi8vIENvcHlyaWdodCAoYykgMjAxNCBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBTaXplID0gcmVxdWlyZShcIi4uL3ZhbHVlcy9zaXplLmpzXCIpO1xudmFyIERlc2NyaXB0b3IgPSByZXF1aXJlKFwiLi9kZXNjcmlwdG9yLmpzXCIpO1xudmFyIFNpemVEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vc2l6ZV9kZXNjcmlwdG9yLmpzXCIpO1xudmFyIFZhbHVlID0gcmVxdWlyZShcIi4uL3ZhbHVlcy92YWx1ZS5qc1wiKTtcbnZhciBTaXplTXVsdGlwbGUgPSByZXF1aXJlKFwiLi9zaXplX211bHRpcGxlLmpzXCIpO1xuXG52YXIgUExVUyA9IDE7XG52YXIgTUlOVVMgPSAtMTtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBSZWxhdGl2ZVNpemUoZGlyZWN0aW9uLCByZWxhdGl2ZVRvLCBhbW91bnQpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgTnVtYmVyLCBEZXNjcmlwdG9yLCBbTnVtYmVyLCBEZXNjcmlwdG9yLCBWYWx1ZV0gXSk7XG5cblx0dGhpcy5fZGlyZWN0aW9uID0gZGlyZWN0aW9uO1xuXHR0aGlzLl9yZWxhdGl2ZVRvID0gcmVsYXRpdmVUbztcblxuXHRpZiAodHlwZW9mIGFtb3VudCA9PT0gXCJudW1iZXJcIikge1xuXHRcdHRoaXMuX2Ftb3VudCA9IFNpemUuY3JlYXRlKE1hdGguYWJzKGFtb3VudCkpO1xuXHRcdGlmIChhbW91bnQgPCAwKSB0aGlzLl9kaXJlY3Rpb24gKj0gLTE7XG5cdH1cblx0ZWxzZSB7XG5cdFx0dGhpcy5fYW1vdW50ID0gYW1vdW50O1xuXHR9XG59O1xuU2l6ZURlc2NyaXB0b3IuZXh0ZW5kKE1lKTtcblxuTWUubGFyZ2VyID0gZmFjdG9yeUZuKFBMVVMpO1xuTWUuc21hbGxlciA9IGZhY3RvcnlGbihNSU5VUyk7XG5cbk1lLnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uIHZhbHVlKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXG5cdHZhciBiYXNlVmFsdWUgPSB0aGlzLl9yZWxhdGl2ZVRvLnZhbHVlKCk7XG5cdHZhciByZWxhdGl2ZVZhbHVlID0gdGhpcy5fYW1vdW50LnZhbHVlKCk7XG5cblx0aWYgKHRoaXMuX2RpcmVjdGlvbiA9PT0gUExVUykgcmV0dXJuIGJhc2VWYWx1ZS5wbHVzKHJlbGF0aXZlVmFsdWUpO1xuXHRlbHNlIHJldHVybiBiYXNlVmFsdWUubWludXMocmVsYXRpdmVWYWx1ZSk7XG59O1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHR2YXIgYmFzZSA9IHRoaXMuX3JlbGF0aXZlVG8udG9TdHJpbmcoKTtcblx0aWYgKHRoaXMuX2Ftb3VudC5lcXVhbHMoU2l6ZS5jcmVhdGUoMCkpKSByZXR1cm4gYmFzZTtcblxuXHR2YXIgcmVsYXRpb24gPSB0aGlzLl9hbW91bnQudG9TdHJpbmcoKTtcblx0aWYgKHRoaXMuX2RpcmVjdGlvbiA9PT0gUExVUykgcmVsYXRpb24gKz0gXCIgbGFyZ2VyIHRoYW4gXCI7XG5cdGVsc2UgcmVsYXRpb24gKz0gXCIgc21hbGxlciB0aGFuIFwiO1xuXG5cdHJldHVybiByZWxhdGlvbiArIGJhc2U7XG59O1xuXG5mdW5jdGlvbiBmYWN0b3J5Rm4oZGlyZWN0aW9uKSB7XG5cdHJldHVybiBmdW5jdGlvbiBmYWN0b3J5KHJlbGF0aXZlVG8sIGFtb3VudCkge1xuXHRcdHJldHVybiBuZXcgTWUoZGlyZWN0aW9uLCByZWxhdGl2ZVRvLCBhbW91bnQpO1xuXHR9O1xufSIsIi8vIENvcHlyaWdodCAoYykgMjAxNC0yMDE3IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cbi8qZXNsaW50IG5ldy1jYXA6IFwib2ZmXCIgKi9cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4uL3V0aWwvZW5zdXJlLmpzXCIpO1xudmFyIG9vcCA9IHJlcXVpcmUoXCIuLi91dGlsL29vcC5qc1wiKTtcbnZhciBEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvci5qc1wiKTtcbnZhciBTaXplID0gcmVxdWlyZShcIi4uL3ZhbHVlcy9zaXplLmpzXCIpO1xuXG5mdW5jdGlvbiBSZWxhdGl2ZVNpemUoKSB7XG5cdHJldHVybiByZXF1aXJlKFwiLi9yZWxhdGl2ZV9zaXplLmpzXCIpOyAgIFx0Ly8gYnJlYWsgY2lyY3VsYXIgZGVwZW5kZW5jeVxufVxuXG5mdW5jdGlvbiBTaXplTXVsdGlwbGUoKSB7XG5cdHJldHVybiByZXF1aXJlKFwiLi9zaXplX211bHRpcGxlLmpzXCIpOyAgIFx0Ly8gYnJlYWsgY2lyY3VsYXIgZGVwZW5kZW5jeVxufVxuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFNpemVEZXNjcmlwdG9yKCkge1xuXHRlbnN1cmUudW5yZWFjaGFibGUoXCJTaXplRGVzY3JpcHRvciBpcyBhYnN0cmFjdCBhbmQgc2hvdWxkIG5vdCBiZSBjb25zdHJ1Y3RlZCBkaXJlY3RseS5cIik7XG59O1xuRGVzY3JpcHRvci5leHRlbmQoTWUpO1xuTWUuZXh0ZW5kID0gb29wLmV4dGVuZEZuKE1lKTtcblxuTWUucHJvdG90eXBlLnBsdXMgPSBmdW5jdGlvbiBwbHVzKGFtb3VudCkge1xuXHRyZXR1cm4gUmVsYXRpdmVTaXplKCkubGFyZ2VyKHRoaXMsIGFtb3VudCk7XG59O1xuXG5NZS5wcm90b3R5cGUubWludXMgPSBmdW5jdGlvbiBtaW51cyhhbW91bnQpIHtcblx0cmV0dXJuIFJlbGF0aXZlU2l6ZSgpLnNtYWxsZXIodGhpcywgYW1vdW50KTtcbn07XG5cbk1lLnByb3RvdHlwZS50aW1lcyA9IGZ1bmN0aW9uIHRpbWVzKGFtb3VudCkge1xuXHRyZXR1cm4gU2l6ZU11bHRpcGxlKCkuY3JlYXRlKHRoaXMsIGFtb3VudCk7XG59O1xuXG5NZS5wcm90b3R5cGUuY29udmVydCA9IGZ1bmN0aW9uIGNvbnZlcnQoYXJnLCB0eXBlKSB7XG5cdHN3aXRjaCh0eXBlKSB7XG5cdFx0Y2FzZSBcIm51bWJlclwiOiByZXR1cm4gU2l6ZS5jcmVhdGUoYXJnKTtcblx0XHRjYXNlIFwic3RyaW5nXCI6IHJldHVybiBhcmcgPT09IFwibm9uZVwiID8gU2l6ZS5jcmVhdGVOb25lKCkgOiB1bmRlZmluZWQ7XG5cdFx0ZGVmYXVsdDogcmV0dXJuIHVuZGVmaW5lZDtcblx0fVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgMjAxNCBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvci5qc1wiKTtcbnZhciBTaXplRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3NpemVfZGVzY3JpcHRvci5qc1wiKTtcbnZhciBTaXplID0gcmVxdWlyZShcIi4uL3ZhbHVlcy9zaXplLmpzXCIpO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFNpemVNdWx0aXBsZShyZWxhdGl2ZVRvLCBtdWx0aXBsZSkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgWyBEZXNjcmlwdG9yLCBOdW1iZXIgXSk7XG5cblx0dGhpcy5fcmVsYXRpdmVUbyA9IHJlbGF0aXZlVG87XG5cdHRoaXMuX211bHRpcGxlID0gbXVsdGlwbGU7XG59O1xuU2l6ZURlc2NyaXB0b3IuZXh0ZW5kKE1lKTtcblxuTWUuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHJlbGF0aXZlVG8sIG11bHRpcGxlKSB7XG5cdHJldHVybiBuZXcgTWUocmVsYXRpdmVUbywgbXVsdGlwbGUpO1xufTtcblxuTWUucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cblx0cmV0dXJuIHRoaXMuX3JlbGF0aXZlVG8udmFsdWUoKS50aW1lcyh0aGlzLl9tdWx0aXBsZSk7XG59O1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHR2YXIgbXVsdGlwbGUgPSB0aGlzLl9tdWx0aXBsZTtcblx0dmFyIGJhc2UgPSB0aGlzLl9yZWxhdGl2ZVRvLnRvU3RyaW5nKCk7XG5cdGlmIChtdWx0aXBsZSA9PT0gMSkgcmV0dXJuIGJhc2U7XG5cblx0dmFyIGRlc2M7XG5cdHN3aXRjaChtdWx0aXBsZSkge1xuXHRcdGNhc2UgMS8yOiBkZXNjID0gXCJoYWxmIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDEvMzogZGVzYyA9IFwib25lLXRoaXJkIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDIvMzogZGVzYyA9IFwidHdvLXRoaXJkcyBvZiBcIjsgYnJlYWs7XG5cdFx0Y2FzZSAxLzQ6IGRlc2MgPSBcIm9uZS1xdWFydGVyIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDMvNDogZGVzYyA9IFwidGhyZWUtcXVhcnRlcnMgb2YgXCI7IGJyZWFrO1xuXHRcdGNhc2UgMS81OiBkZXNjID0gXCJvbmUtZmlmdGggb2YgXCI7IGJyZWFrO1xuXHRcdGNhc2UgMi81OiBkZXNjID0gXCJ0d28tZmlmdGhzIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDMvNTogZGVzYyA9IFwidGhyZWUtZmlmdGhzIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDQvNTogZGVzYyA9IFwiZm91ci1maWZ0aHMgb2YgXCI7IGJyZWFrO1xuXHRcdGNhc2UgMS82OiBkZXNjID0gXCJvbmUtc2l4dGggb2YgXCI7IGJyZWFrO1xuXHRcdGNhc2UgNS82OiBkZXNjID0gXCJmaXZlLXNpeHRocyBvZiBcIjsgYnJlYWs7XG5cdFx0Y2FzZSAxLzg6IGRlc2MgPSBcIm9uZS1laWdodGggb2YgXCI7IGJyZWFrO1xuXHRcdGNhc2UgMy84OiBkZXNjID0gXCJ0aHJlZS1laWdodGhzIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDUvODogZGVzYyA9IFwiZml2ZS1laWdodGhzIG9mIFwiOyBicmVhaztcblx0XHRjYXNlIDcvODogZGVzYyA9IFwic2V2ZW4tZWlnaHRocyBvZiBcIjsgYnJlYWs7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdGlmIChtdWx0aXBsZSA+IDEpIGRlc2MgPSBtdWx0aXBsZSArIFwiIHRpbWVzIFwiO1xuXHRcdFx0ZWxzZSBkZXNjID0gKG11bHRpcGxlICogMTAwKSArIFwiJSBvZiBcIjtcblx0fVxuXG5cdHJldHVybiBkZXNjICsgYmFzZTtcbn07IiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4uL3V0aWwvZW5zdXJlLmpzXCIpO1xudmFyIFBvc2l0aW9uRGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3Bvc2l0aW9uX2Rlc2NyaXB0b3IuanNcIik7XG52YXIgUG9zaXRpb24gPSByZXF1aXJlKFwiLi4vdmFsdWVzL3Bvc2l0aW9uLmpzXCIpO1xuXG52YXIgVE9QID0gXCJ0b3BcIjtcbnZhciBSSUdIVCA9IFwicmlnaHRcIjtcbnZhciBCT1RUT00gPSBcImJvdHRvbVwiO1xudmFyIExFRlQgPSBcImxlZnRcIjtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBWaWV3cG9ydEVkZ2UocG9zaXRpb24sIGZyYW1lKSB7XG5cdHZhciBRRnJhbWUgPSByZXF1aXJlKFwiLi4vcV9mcmFtZS5qc1wiKTsgICAgLy8gYnJlYWsgY2lyY3VsYXIgZGVwZW5kZW5jeVxuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgWyBTdHJpbmcsIFFGcmFtZSBdKTtcblxuXHRpZiAocG9zaXRpb24gPT09IExFRlQgfHwgcG9zaXRpb24gPT09IFJJR0hUKSBQb3NpdGlvbkRlc2NyaXB0b3IueCh0aGlzKTtcblx0ZWxzZSBpZiAocG9zaXRpb24gPT09IFRPUCB8fCBwb3NpdGlvbiA9PT0gQk9UVE9NKSBQb3NpdGlvbkRlc2NyaXB0b3IueSh0aGlzKTtcblx0ZWxzZSBlbnN1cmUudW5yZWFjaGFibGUoXCJVbmtub3duIHBvc2l0aW9uOiBcIiArIHBvc2l0aW9uKTtcblxuXHR0aGlzLl9wb3NpdGlvbiA9IHBvc2l0aW9uO1xuXHR0aGlzLl9mcmFtZSA9IGZyYW1lO1xufTtcblBvc2l0aW9uRGVzY3JpcHRvci5leHRlbmQoTWUpO1xuXG5NZS50b3AgPSBmYWN0b3J5Rm4oVE9QKTtcbk1lLnJpZ2h0ID0gZmFjdG9yeUZuKFJJR0hUKTtcbk1lLmJvdHRvbSA9IGZhY3RvcnlGbihCT1RUT00pO1xuTWUubGVmdCA9IGZhY3RvcnlGbihMRUZUKTtcblxuTWUucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24oKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cblx0dmFyIHNjcm9sbCA9IHRoaXMuX2ZyYW1lLmdldFJhd1Njcm9sbFBvc2l0aW9uKCk7XG5cdHZhciB4ID0gUG9zaXRpb24ueChzY3JvbGwueCk7XG5cdHZhciB5ID0gUG9zaXRpb24ueShzY3JvbGwueSk7XG5cblx0dmFyIHNpemUgPSB2aWV3cG9ydFNpemUodGhpcy5fZnJhbWUuZ2V0KFwiaHRtbFwiKS50b0RvbUVsZW1lbnQoKSk7XG5cblx0c3dpdGNoKHRoaXMuX3Bvc2l0aW9uKSB7XG5cdFx0Y2FzZSBUT1A6IHJldHVybiB5O1xuXHRcdGNhc2UgUklHSFQ6IHJldHVybiB4LnBsdXMoUG9zaXRpb24ueChzaXplLndpZHRoKSk7XG5cdFx0Y2FzZSBCT1RUT006IHJldHVybiB5LnBsdXMoUG9zaXRpb24ueShzaXplLmhlaWdodCkpO1xuXHRcdGNhc2UgTEVGVDogcmV0dXJuIHg7XG5cblx0XHRkZWZhdWx0OiBlbnN1cmUudW5yZWFjaGFibGUoKTtcblx0fVxufTtcblxuTWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdHJldHVybiB0aGlzLl9wb3NpdGlvbiArIFwiIGVkZ2Ugb2Ygdmlld3BvcnRcIjtcbn07XG5cbmZ1bmN0aW9uIGZhY3RvcnlGbihwb3NpdGlvbikge1xuXHRyZXR1cm4gZnVuY3Rpb24gZmFjdG9yeShmcmFtZSkge1xuXHRcdHJldHVybiBuZXcgTWUocG9zaXRpb24sIGZyYW1lKTtcblx0fTtcbn1cblxuXG5cbi8vIFVTRUZVTCBSRUFESU5HOiBodHRwOi8vd3d3LnF1aXJrc21vZGUub3JnL21vYmlsZS92aWV3cG9ydHMuaHRtbFxuLy8gYW5kIGh0dHA6Ly93d3cucXVpcmtzbW9kZS5vcmcvbW9iaWxlL3ZpZXdwb3J0czIuaHRtbFxuXG4vLyBCUk9XU0VSUyBURVNURUQ6IFNhZmFyaSA2LjIuMCAoTWFjIE9TIFggMTAuOC41KTsgTW9iaWxlIFNhZmFyaSA3LjAuMCAoaU9TIDcuMSk7IEZpcmVmb3ggMzIuMC4wIChNYWMgT1MgWCAxMC44KTtcbi8vICAgIEZpcmVmb3ggMzMuMC4wIChXaW5kb3dzIDcpOyBDaHJvbWUgMzguMC4yMTI1IChNYWMgT1MgWCAxMC44LjUpOyBDaHJvbWUgMzguMC4yMTI1IChXaW5kb3dzIDcpOyBJRSA4LCA5LCAxMCwgMTFcblxuLy8gV2lkdGggdGVjaG5pcXVlcyBJJ3ZlIHRyaWVkOiAoTm90ZTogcmVzdWx0cyBhcmUgZGlmZmVyZW50IGluIHF1aXJrcyBtb2RlKVxuLy8gYm9keS5jbGllbnRXaWR0aFxuLy8gYm9keS5vZmZzZXRXaWR0aFxuLy8gYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aFxuLy8gICAgZmFpbHMgb24gYWxsIGJyb3dzZXJzOiBkb2Vzbid0IGluY2x1ZGUgbWFyZ2luXG4vLyBib2R5LnNjcm9sbFdpZHRoXG4vLyAgICB3b3JrcyBvbiBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZVxuLy8gICAgZmFpbHMgb24gRmlyZWZveCwgSUUgOCwgOSwgMTAsIDExOiBkb2Vzbid0IGluY2x1ZGUgbWFyZ2luXG4vLyBodG1sLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoXG4vLyBodG1sLm9mZnNldFdpZHRoXG4vLyAgICB3b3JrcyBvbiBTYWZhcmksIE1vYmlsZSBTYWZhcmksIENocm9tZSwgRmlyZWZveFxuLy8gICAgZmFpbHMgb24gSUUgOCwgOSwgMTA6IGluY2x1ZGVzIHNjcm9sbGJhclxuLy8gaHRtbC5zY3JvbGxXaWR0aFxuLy8gaHRtbC5jbGllbnRXaWR0aFxuLy8gICAgV09SS1MhIFNhZmFyaSwgTW9iaWxlIFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTFcblxuLy8gSGVpZ2h0IHRlY2huaXF1ZXMgSSd2ZSB0cmllZDogKE5vdGUgdGhhdCByZXN1bHRzIGFyZSBkaWZmZXJlbnQgaW4gcXVpcmtzIG1vZGUpXG4vLyBib2R5LmNsaWVudEhlaWdodFxuLy8gYm9keS5vZmZzZXRIZWlnaHRcbi8vIGJvZHkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0XG4vLyAgICBmYWlscyBvbiBhbGwgYnJvd3NlcnM6IG9ubHkgaW5jbHVkZXMgaGVpZ2h0IG9mIGNvbnRlbnRcbi8vIGJvZHkgZ2V0Q29tcHV0ZWRTdHlsZShcImhlaWdodFwiKVxuLy8gICAgZmFpbHMgb24gYWxsIGJyb3dzZXJzOiBJRTggcmV0dXJucyBcImF1dG9cIjsgb3RoZXJzIG9ubHkgaW5jbHVkZSBoZWlnaHQgb2YgY29udGVudFxuLy8gYm9keS5zY3JvbGxIZWlnaHRcbi8vICAgIHdvcmtzIG9uIFNhZmFyaSwgTW9iaWxlIFNhZmFyaSwgQ2hyb21lO1xuLy8gICAgZmFpbHMgb24gRmlyZWZveCwgSUUgOCwgOSwgMTAsIDExOiBvbmx5IGluY2x1ZGVzIGhlaWdodCBvZiBjb250ZW50XG4vLyBodG1sLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodFxuLy8gaHRtbC5vZmZzZXRIZWlnaHRcbi8vICAgIHdvcmtzIG9uIElFIDgsIDksIDEwXG4vLyAgICBmYWlscyBvbiBJRSAxMSwgU2FmYXJpLCBNb2JpbGUgU2FmYXJpLCBDaHJvbWU6IG9ubHkgaW5jbHVkZXMgaGVpZ2h0IG9mIGNvbnRlbnRcbi8vIGh0bWwuc2Nyb2xsSGVpZ2h0XG4vLyAgICB3b3JrcyBvbiBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTFcbi8vICAgIGZhaWxzIG9uIFNhZmFyaSwgTW9iaWxlIFNhZmFyaSwgQ2hyb21lOiBvbmx5IGluY2x1ZGVzIGhlaWdodCBvZiBjb250ZW50XG4vLyBodG1sLmNsaWVudEhlaWdodFxuLy8gICAgV09SS1MhIFNhZmFyaSwgTW9iaWxlIFNhZmFyaSwgQ2hyb21lLCBGaXJlZm94LCBJRSA4LCA5LCAxMCwgMTFcbmZ1bmN0aW9uIHZpZXdwb3J0U2l6ZShodG1sRWxlbWVudCkge1xuXHRyZXR1cm4ge1xuXHRcdHdpZHRoOiBodG1sRWxlbWVudC5jbGllbnRXaWR0aCxcblx0XHRoZWlnaHQ6IGh0bWxFbGVtZW50LmNsaWVudEhlaWdodFxuXHR9O1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0LTIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBzaGltID0gcmVxdWlyZShcIi4vdXRpbC9zaGltLmpzXCIpO1xudmFyIGNhbWVsY2FzZSA9IHJlcXVpcmUoXCIuLi92ZW5kb3IvY2FtZWxjYXNlLTEuMC4xLW1vZGlmaWVkLmpzXCIpO1xudmFyIEVsZW1lbnRSZW5kZXJlZCA9IHJlcXVpcmUoXCIuL2Rlc2NyaXB0b3JzL2VsZW1lbnRfcmVuZGVyZWQuanNcIik7XG52YXIgRWxlbWVudEVkZ2UgPSByZXF1aXJlKFwiLi9kZXNjcmlwdG9ycy9lbGVtZW50X2VkZ2UuanNcIik7XG52YXIgQ2VudGVyID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvcnMvY2VudGVyLmpzXCIpO1xudmFyIEdlbmVyaWNTaXplID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvcnMvZ2VuZXJpY19zaXplLmpzXCIpO1xudmFyIEFzc2VydGFibGUgPSByZXF1aXJlKFwiLi9hc3NlcnRhYmxlLmpzXCIpO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFFFbGVtZW50KGRvbUVsZW1lbnQsIGZyYW1lLCBuaWNrbmFtZSkge1xuXHR2YXIgUUZyYW1lID0gcmVxdWlyZShcIi4vcV9mcmFtZS5qc1wiKTsgICAgLy8gYnJlYWsgY2lyY3VsYXIgZGVwZW5kZW5jeVxuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW09iamVjdCwgUUZyYW1lLCBTdHJpbmddKTtcblxuXHR0aGlzLl9kb21FbGVtZW50ID0gZG9tRWxlbWVudDtcblx0dGhpcy5fbmlja25hbWUgPSBuaWNrbmFtZTtcblxuXHR0aGlzLmZyYW1lID0gZnJhbWU7XG5cblx0Ly8gcHJvcGVydGllc1xuXHR0aGlzLnJlbmRlcmVkID0gRWxlbWVudFJlbmRlcmVkLmNyZWF0ZSh0aGlzKTtcblxuXHR0aGlzLnRvcCA9IEVsZW1lbnRFZGdlLnRvcCh0aGlzKTtcblx0dGhpcy5yaWdodCA9IEVsZW1lbnRFZGdlLnJpZ2h0KHRoaXMpO1xuXHR0aGlzLmJvdHRvbSA9IEVsZW1lbnRFZGdlLmJvdHRvbSh0aGlzKTtcblx0dGhpcy5sZWZ0ID0gRWxlbWVudEVkZ2UubGVmdCh0aGlzKTtcblxuXHR0aGlzLmNlbnRlciA9IENlbnRlci54KHRoaXMubGVmdCwgdGhpcy5yaWdodCwgXCJjZW50ZXIgb2YgXCIgKyB0aGlzKTtcblx0dGhpcy5taWRkbGUgPSBDZW50ZXIueSh0aGlzLnRvcCwgdGhpcy5ib3R0b20sIFwibWlkZGxlIG9mIFwiICsgdGhpcyk7XG5cblx0dGhpcy53aWR0aCA9IEdlbmVyaWNTaXplLmNyZWF0ZSh0aGlzLmxlZnQsIHRoaXMucmlnaHQsIFwid2lkdGggb2YgXCIgKyB0aGlzKTtcblx0dGhpcy5oZWlnaHQgPSBHZW5lcmljU2l6ZS5jcmVhdGUodGhpcy50b3AsIHRoaXMuYm90dG9tLCBcImhlaWdodCBvZiBcIiArIHRoaXMpO1xufTtcbkFzc2VydGFibGUuZXh0ZW5kKE1lKTtcblxuTWUucHJvdG90eXBlLmdldFJhd1N0eWxlID0gZnVuY3Rpb24oc3R5bGVOYW1lKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbU3RyaW5nXSk7XG5cblx0dmFyIHN0eWxlcztcblx0dmFyIHJlc3VsdDtcblxuXHQvLyBXT1JLQVJPVU5EIElFIDg6IG5vIGdldENvbXB1dGVkU3R5bGUoKVxuXHRpZiAod2luZG93LmdldENvbXB1dGVkU3R5bGUpIHtcblx0XHQvLyBXT1JLQVJPVU5EIEZpcmVmb3ggNDAuMC4zOiBtdXN0IHVzZSBmcmFtZSdzIGNvbnRlbnRXaW5kb3cgKHJlZiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMjA0MDYyKVxuXHRcdHN0eWxlcyA9IHRoaXMuZnJhbWUudG9Eb21FbGVtZW50KCkuY29udGVudFdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRoaXMuX2RvbUVsZW1lbnQpO1xuXHRcdHJlc3VsdCA9IHN0eWxlcy5nZXRQcm9wZXJ0eVZhbHVlKHN0eWxlTmFtZSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0c3R5bGVzID0gdGhpcy5fZG9tRWxlbWVudC5jdXJyZW50U3R5bGU7XG5cdFx0cmVzdWx0ID0gc3R5bGVzW2NhbWVsY2FzZShzdHlsZU5hbWUpXTtcblx0fVxuXHRpZiAocmVzdWx0ID09PSBudWxsIHx8IHJlc3VsdCA9PT0gdW5kZWZpbmVkKSByZXN1bHQgPSBcIlwiO1xuXHRyZXR1cm4gcmVzdWx0O1xufTtcblxuTWUucHJvdG90eXBlLmdldFJhd1Bvc2l0aW9uID0gZnVuY3Rpb24oKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBObyBUZXh0UmVjdGFuZ2xlLmhlaWdodCBvciAud2lkdGhcblx0dmFyIHJlY3QgPSB0aGlzLl9kb21FbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXHRyZXR1cm4ge1xuXHRcdGxlZnQ6IHJlY3QubGVmdCxcblx0XHRyaWdodDogcmVjdC5yaWdodCxcblx0XHR3aWR0aDogcmVjdC53aWR0aCAhPT0gdW5kZWZpbmVkID8gcmVjdC53aWR0aCA6IHJlY3QucmlnaHQgLSByZWN0LmxlZnQsXG5cblx0XHR0b3A6IHJlY3QudG9wLFxuXHRcdGJvdHRvbTogcmVjdC5ib3R0b20sXG5cdFx0aGVpZ2h0OiByZWN0LmhlaWdodCAhPT0gdW5kZWZpbmVkID8gcmVjdC5oZWlnaHQgOiByZWN0LmJvdHRvbSAtIHJlY3QudG9wXG5cdH07XG59O1xuXG5NZS5wcm90b3R5cGUuY2FsY3VsYXRlUGl4ZWxWYWx1ZSA9IGZ1bmN0aW9uKHNpemVTdHJpbmcpIHtcblx0dmFyIGRvbSA9IHRoaXMuX2RvbUVsZW1lbnQ7XG5cdGlmIChkb20ucnVudGltZVN0eWxlICE9PSB1bmRlZmluZWQpIHJldHVybiBpZThXb3JrYXJvdW5kKCk7XG5cblx0dmFyIHJlc3VsdDtcblx0dmFyIHN0eWxlID0gZG9tLnN0eWxlO1xuXHR2YXIgb2xkUG9zaXRpb24gPSBzdHlsZS5wb3NpdGlvbjtcblx0dmFyIG9sZExlZnQgPSBzdHlsZS5sZWZ0O1xuXG5cdHN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuXHRzdHlsZS5sZWZ0ID0gc2l6ZVN0cmluZztcblx0cmVzdWx0ID0gcGFyc2VGbG9hdCh0aGlzLmdldFJhd1N0eWxlKFwibGVmdFwiKSk7ICAgIC8vIHBhcnNlSW50IHN0cmlwcyBvZiAncHgnIHZhbHVlXG5cblx0c3R5bGUucG9zaXRpb24gPSBvbGRQb3NpdGlvbjtcblx0c3R5bGUubGVmdCA9IG9sZExlZnQ7XG5cdHJldHVybiByZXN1bHQ7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBnZXRSYXdTdHlsZSgpIGRvZXNuJ3Qgbm9ybWFsaXplIHZhbHVlcyB0byBweFxuXHQvLyBCYXNlZCBvbiBjb2RlIGJ5IERlYW4gRWR3YXJkczogaHR0cDovL2Rpc3EudXMvcC9teWw5OXhcblx0ZnVuY3Rpb24gaWU4V29ya2Fyb3VuZCgpIHtcblx0XHR2YXIgcnVudGltZVN0eWxlTGVmdCA9IGRvbS5ydW50aW1lU3R5bGUubGVmdDtcblx0XHR2YXIgc3R5bGVMZWZ0ID0gZG9tLnN0eWxlLmxlZnQ7XG5cblx0XHRkb20ucnVudGltZVN0eWxlLmxlZnQgPSBkb20uY3VycmVudFN0eWxlLmxlZnQ7XG5cdFx0ZG9tLnN0eWxlLmxlZnQgPSBzaXplU3RyaW5nO1xuXHRcdHJlc3VsdCA9IGRvbS5zdHlsZS5waXhlbExlZnQ7XG5cblx0XHRkb20ucnVudGltZVN0eWxlLmxlZnQgPSBydW50aW1lU3R5bGVMZWZ0O1xuXHRcdGRvbS5zdHlsZS5sZWZ0ID0gc3R5bGVMZWZ0O1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cbn07XG5cbk1lLnByb3RvdHlwZS5wYXJlbnQgPSBmdW5jdGlvbihuaWNrbmFtZSkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW1sgdW5kZWZpbmVkLCBTdHJpbmcgXV0pO1xuXHRpZiAobmlja25hbWUgPT09IHVuZGVmaW5lZCkgbmlja25hbWUgPSBcInBhcmVudCBvZiBcIiArIHRoaXMuX25pY2tuYW1lO1xuXG5cdGlmICh0aGlzLmVxdWFscyh0aGlzLmZyYW1lLmJvZHkoKSkpIHJldHVybiBudWxsO1xuXG5cdHZhciBwYXJlbnQgPSB0aGlzLl9kb21FbGVtZW50LnBhcmVudEVsZW1lbnQ7XG5cdGlmIChwYXJlbnQgPT09IG51bGwpIHJldHVybiBudWxsO1xuXG5cdHJldHVybiBuZXcgTWUocGFyZW50LCB0aGlzLmZyYW1lLCBuaWNrbmFtZSk7XG59O1xuXG5NZS5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24oaHRtbCwgbmlja25hbWUpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtTdHJpbmcsIFt1bmRlZmluZWQsIFN0cmluZ11dKTtcblx0aWYgKG5pY2tuYW1lID09PSB1bmRlZmluZWQpIG5pY2tuYW1lID0gaHRtbCArIFwiIGluIFwiICsgdGhpcy5fbmlja25hbWU7XG5cblx0dmFyIHRlbXBFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblx0dGVtcEVsZW1lbnQuaW5uZXJIVE1MID0gc2hpbS5TdHJpbmcudHJpbShodG1sKTtcblx0ZW5zdXJlLnRoYXQoXG5cdFx0dGVtcEVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGggPT09IDEsXG5cdFx0XCJFeHBlY3RlZCBvbmUgZWxlbWVudCwgYnV0IGdvdCBcIiArIHRlbXBFbGVtZW50LmNoaWxkTm9kZXMubGVuZ3RoICsgXCIgKFwiICsgaHRtbCArIFwiKVwiXG5cdCk7XG5cblx0dmFyIGluc2VydGVkRWxlbWVudCA9IHRlbXBFbGVtZW50LmNoaWxkTm9kZXNbMF07XG5cdHRoaXMuX2RvbUVsZW1lbnQuYXBwZW5kQ2hpbGQoaW5zZXJ0ZWRFbGVtZW50KTtcblx0cmV0dXJuIG5ldyBNZShpbnNlcnRlZEVsZW1lbnQsIHRoaXMuZnJhbWUsIG5pY2tuYW1lKTtcbn07XG5cbk1lLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbigpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblx0c2hpbS5FbGVtZW50LnJlbW92ZSh0aGlzLl9kb21FbGVtZW50KTtcbn07XG5cbk1lLnByb3RvdHlwZS50b0RvbUVsZW1lbnQgPSBmdW5jdGlvbigpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblx0cmV0dXJuIHRoaXMuX2RvbUVsZW1lbnQ7XG59O1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblx0cmV0dXJuIFwiJ1wiICsgdGhpcy5fbmlja25hbWUgKyBcIidcIjtcbn07XG5cbk1lLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbih0aGF0KSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbTWVdKTtcblx0cmV0dXJuIHRoaXMuX2RvbUVsZW1lbnQgPT09IHRoYXQuX2RvbUVsZW1lbnQ7XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgUUVsZW1lbnQgPSByZXF1aXJlKFwiLi9xX2VsZW1lbnQuanNcIik7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gUUVsZW1lbnRMaXN0KG5vZGVMaXN0LCBmcmFtZSwgbmlja25hbWUpIHtcblx0dmFyIFFGcmFtZSA9IHJlcXVpcmUoXCIuL3FfZnJhbWUuanNcIik7ICAgIC8vIGJyZWFrIGNpcmN1bGFyIGRlcGVuZGVuY3lcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgT2JqZWN0LCBRRnJhbWUsIFN0cmluZyBdKTtcblxuXHR0aGlzLl9ub2RlTGlzdCA9IG5vZGVMaXN0O1xuXHR0aGlzLl9mcmFtZSA9IGZyYW1lO1xuXHR0aGlzLl9uaWNrbmFtZSA9IG5pY2tuYW1lO1xufTtcblxuTWUucHJvdG90eXBlLmxlbmd0aCA9IGZ1bmN0aW9uIGxlbmd0aCgpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHRyZXR1cm4gdGhpcy5fbm9kZUxpc3QubGVuZ3RoO1xufTtcblxuTWUucHJvdG90eXBlLmF0ID0gZnVuY3Rpb24gYXQocmVxdWVzdGVkSW5kZXgsIG5pY2tuYW1lKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIE51bWJlciwgW3VuZGVmaW5lZCwgU3RyaW5nXSBdKTtcblxuXHR2YXIgaW5kZXggPSByZXF1ZXN0ZWRJbmRleDtcblx0dmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoKCk7XG5cdGlmIChpbmRleCA8IDApIGluZGV4ID0gbGVuZ3RoICsgaW5kZXg7XG5cblx0ZW5zdXJlLnRoYXQoXG5cdFx0aW5kZXggPj0gMCAmJiBpbmRleCA8IGxlbmd0aCxcblx0XHRcIidcIiArIHRoaXMuX25pY2tuYW1lICsgXCInW1wiICsgcmVxdWVzdGVkSW5kZXggKyBcIl0gaXMgb3V0IG9mIGJvdW5kczsgbGlzdCBsZW5ndGggaXMgXCIgKyBsZW5ndGhcblx0KTtcblx0dmFyIGVsZW1lbnQgPSB0aGlzLl9ub2RlTGlzdFtpbmRleF07XG5cblx0aWYgKG5pY2tuYW1lID09PSB1bmRlZmluZWQpIG5pY2tuYW1lID0gdGhpcy5fbmlja25hbWUgKyBcIltcIiArIGluZGV4ICsgXCJdXCI7XG5cdHJldHVybiBuZXcgUUVsZW1lbnQoZWxlbWVudCwgdGhpcy5fZnJhbWUsIG5pY2tuYW1lKTtcbn07XG5cbk1lLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXG5cdHJldHVybiBcIidcIiArIHRoaXMuX25pY2tuYW1lICsgXCInIGxpc3RcIjtcbn07IiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0LTIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBzaGltID0gcmVxdWlyZShcIi4vdXRpbC9zaGltLmpzXCIpO1xudmFyIHF1aXhvdGUgPSByZXF1aXJlKFwiLi9xdWl4b3RlLmpzXCIpO1xudmFyIFFFbGVtZW50ID0gcmVxdWlyZShcIi4vcV9lbGVtZW50LmpzXCIpO1xudmFyIFFFbGVtZW50TGlzdCA9IHJlcXVpcmUoXCIuL3FfZWxlbWVudF9saXN0LmpzXCIpO1xudmFyIFFWaWV3cG9ydCA9IHJlcXVpcmUoXCIuL3Ffdmlld3BvcnQuanNcIik7XG52YXIgUVBhZ2UgPSByZXF1aXJlKFwiLi9xX3BhZ2UuanNcIik7XG52YXIgYXN5bmMgPSByZXF1aXJlKFwiLi4vdmVuZG9yL2FzeW5jLTEuNC4yLmpzXCIpO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFFGcmFtZSgpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHR0aGlzLl9kb21FbGVtZW50ID0gbnVsbDtcblx0dGhpcy5fbG9hZGVkID0gZmFsc2U7XG5cdHRoaXMuX3JlbW92ZWQgPSBmYWxzZTtcbn07XG5cbmZ1bmN0aW9uIGxvYWRlZChzZWxmLCB3aWR0aCwgaGVpZ2h0LCBzcmMsIHN0eWxlc2hlZXRzKSB7XG5cdHNlbGYuX2xvYWRlZCA9IHRydWU7XG5cdHNlbGYuX2RvY3VtZW50ID0gc2VsZi5fZG9tRWxlbWVudC5jb250ZW50RG9jdW1lbnQ7XG5cdHNlbGYuX29yaWdpbmFsQm9keSA9IHNlbGYuX2RvY3VtZW50LmJvZHkuaW5uZXJIVE1MO1xuXHRzZWxmLl9vcmlnaW5hbFdpZHRoID0gd2lkdGg7XG5cdHNlbGYuX29yaWdpbmFsSGVpZ2h0ID0gaGVpZ2h0O1xuXHRzZWxmLl9vcmlnaW5hbFNyYyA9IHNyYztcblx0c2VsZi5fb3JpZ2luYWxTdHlsZXNoZWV0cyA9IHN0eWxlc2hlZXRzO1xufVxuXG5NZS5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocGFyZW50RWxlbWVudCwgb3B0aW9ucywgY2FsbGJhY2spIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtPYmplY3QsIFtPYmplY3QsIEZ1bmN0aW9uXSwgW3VuZGVmaW5lZCwgRnVuY3Rpb25dXSk7XG5cdGlmIChjYWxsYmFjayA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0Y2FsbGJhY2sgPSBvcHRpb25zO1xuXHRcdG9wdGlvbnMgPSB7fTtcblx0fVxuXHR2YXIgd2lkdGggPSBvcHRpb25zLndpZHRoIHx8IDIwMDA7XG5cdHZhciBoZWlnaHQgPSBvcHRpb25zLmhlaWdodCB8fCAyMDAwO1xuXHR2YXIgc3JjID0gb3B0aW9ucy5zcmM7XG5cdHZhciBzdHlsZXNoZWV0cyA9IG9wdGlvbnMuc3R5bGVzaGVldCB8fCBbXTtcblx0dmFyIGNzcyA9IG9wdGlvbnMuY3NzO1xuXHRpZiAoIXNoaW0uQXJyYXkuaXNBcnJheShzdHlsZXNoZWV0cykpIHN0eWxlc2hlZXRzID0gWyBzdHlsZXNoZWV0cyBdO1xuXG5cdHZhciBmcmFtZSA9IG5ldyBNZSgpO1xuXHRjaGVja1VybHMoc3JjLCBzdHlsZXNoZWV0cywgZnVuY3Rpb24oZXJyKSB7XG5cdFx0aWYgKGVycikgcmV0dXJuIGNhbGxiYWNrKGVycik7XG5cblx0XHR2YXIgaWZyYW1lID0gaW5zZXJ0SWZyYW1lKHBhcmVudEVsZW1lbnQsIHdpZHRoLCBoZWlnaHQpO1xuXHRcdHNoaW0uRXZlbnRUYXJnZXQuYWRkRXZlbnRMaXN0ZW5lcihpZnJhbWUsIFwibG9hZFwiLCBvbkZyYW1lTG9hZCk7XG5cdFx0c2V0SWZyYW1lQ29udGVudChpZnJhbWUsIHNyYyk7XG5cblx0XHRmcmFtZS5fZG9tRWxlbWVudCA9IGlmcmFtZTtcblx0XHRzZXRGcmFtZUxvYWRDYWxsYmFjayhmcmFtZSwgY2FsbGJhY2spO1xuXHR9KTtcblx0cmV0dXJuIGZyYW1lO1xuXG5cdGZ1bmN0aW9uIG9uRnJhbWVMb2FkKCkge1xuXHRcdC8vIFdPUktBUk9VTkQgTW9iaWxlIFNhZmFyaSA3LjAuMCwgU2FmYXJpIDYuMi4wLCBDaHJvbWUgMzguMC4yMTI1OiBmcmFtZSBpcyBsb2FkZWQgc3luY2hyb25vdXNseVxuXHRcdC8vIFdlIGZvcmNlIGl0IHRvIGJlIGFzeW5jaHJvbm91cyBoZXJlXG5cdFx0c2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdGxvYWRlZChmcmFtZSwgd2lkdGgsIGhlaWdodCwgc3JjLCBzdHlsZXNoZWV0cyk7XG5cdFx0XHRsb2FkU3R5bGVzaGVldHMoZnJhbWUsIHN0eWxlc2hlZXRzLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKGNzcykgbG9hZFJhd0NTUyhmcmFtZSwgb3B0aW9ucy5jc3MpO1xuXHRcdFx0XHRmcmFtZS5fZnJhbWVMb2FkQ2FsbGJhY2sobnVsbCwgZnJhbWUpO1xuXHRcdFx0fSk7XG5cdFx0fSwgMCk7XG5cdH1cbn07XG5cbmZ1bmN0aW9uIHNldEZyYW1lTG9hZENhbGxiYWNrKGZyYW1lLCBjYWxsYmFjaykge1xuXHRmcmFtZS5fZnJhbWVMb2FkQ2FsbGJhY2sgPSBjYWxsYmFjaztcbn1cblxuZnVuY3Rpb24gY2hlY2tVcmxzKHNyYywgc3R5bGVzaGVldHMsIGNhbGxiYWNrKSB7XG5cdHVybEV4aXN0cyhzcmMsIGZ1bmN0aW9uKGVyciwgc3JjRXhpc3RzKSB7XG5cdFx0aWYgKGVycikgcmV0dXJuIGNhbGxiYWNrKGVycik7XG5cdFx0aWYgKCFzcmNFeGlzdHMpIHJldHVybiBjYWxsYmFjayhlcnJvcihcInNyY1wiLCBzcmMpKTtcblxuXHRcdGFzeW5jLmVhY2goc3R5bGVzaGVldHMsIGNoZWNrU3R5bGVzaGVldCwgY2FsbGJhY2spO1xuXHR9KTtcblxuXHRmdW5jdGlvbiBjaGVja1N0eWxlc2hlZXQodXJsLCBjYWxsYmFjazIpIHtcblx0XHR1cmxFeGlzdHModXJsLCBmdW5jdGlvbihlcnIsIHN0eWxlc2hlZXRFeGlzdHMpIHtcblx0XHRcdGlmIChlcnIpIHJldHVybiBjYWxsYmFjazIoZXJyKTtcblxuXHRcdFx0aWYgKCFzdHlsZXNoZWV0RXhpc3RzKSByZXR1cm4gY2FsbGJhY2syKGVycm9yKFwic3R5bGVzaGVldFwiLCB1cmwpKTtcblx0XHRcdGVsc2UgcmV0dXJuIGNhbGxiYWNrMihudWxsKTtcblx0XHR9KTtcblx0fVxuXG5cdGZ1bmN0aW9uIGVycm9yKG5hbWUsIHVybCkge1xuXHRcdHJldHVybiBuZXcgRXJyb3IoXCI0MDQgZXJyb3Igd2hpbGUgbG9hZGluZyBcIiArIG5hbWUgKyBcIiAoXCIgKyB1cmwgKyBcIilcIik7XG5cdH1cbn1cblxuZnVuY3Rpb24gdXJsRXhpc3RzKHVybCwgY2FsbGJhY2spIHtcblx0dmFyIFNUQVRVU19BVkFJTEFCTEUgPSAyOyAgIC8vIFdPUktBUk9VTkQgSUUgODogbm9uLXN0YW5kYXJkIFhNTEh0dHBSZXF1ZXN0IGNvbnN0YW50IG5hbWVzXG5cblx0aWYgKHVybCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpO1xuXHR9XG5cblx0dmFyIGh0dHAgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcblx0aHR0cC5vcGVuKFwiSEVBRFwiLCB1cmwpO1xuXHRodHRwLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkgeyAgLy8gV09SS0FST1VORCBJRSA4OiBkb2Vzbid0IHN1cHBvcnQgLmFkZEV2ZW50TGlzdGVuZXIoKSBvciAub25sb2FkXG5cdFx0aWYgKGh0dHAucmVhZHlTdGF0ZSA9PT0gU1RBVFVTX0FWQUlMQUJMRSkge1xuXHRcdFx0cmV0dXJuIGNhbGxiYWNrKG51bGwsIGh0dHAuc3RhdHVzICE9PSA0MDQpO1xuXHRcdH1cblx0fTtcblx0aHR0cC5vbmVycm9yID0gZnVuY3Rpb24oKSB7ICAgICAvLyBvbmVycm9yIGhhbmRsZXIgaXMgbm90IHRlc3RlZFxuXHRcdHJldHVybiBjYWxsYmFjayhcIlhNTEh0dHBSZXF1ZXN0IGVycm9yIHdoaWxlIHVzaW5nIEhUVFAgSEVBRCBvbiBVUkwgJ1wiICsgdXJsICsgXCInOiBcIiArIGh0dHAuc3RhdHVzVGV4dCk7XG5cdH07XG5cdGh0dHAuc2VuZCgpO1xufVxuXG5mdW5jdGlvbiBpbnNlcnRJZnJhbWUocGFyZW50RWxlbWVudCwgd2lkdGgsIGhlaWdodCkge1xuXHR2YXIgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImlmcmFtZVwiKTtcblx0aWZyYW1lLnNldEF0dHJpYnV0ZShcIndpZHRoXCIsIHdpZHRoKTtcblx0aWZyYW1lLnNldEF0dHJpYnV0ZShcImhlaWdodFwiLCBoZWlnaHQpO1xuXHRpZnJhbWUuc2V0QXR0cmlidXRlKFwiZnJhbWVib3JkZXJcIiwgXCIwXCIpOyAgICAvLyBXT1JLQVJPVU5EIElFIDg6IGRvbid0IGluY2x1ZGUgZnJhbWUgYm9yZGVyIGluIHBvc2l0aW9uIGNhbGNzXG5cdHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcblx0cmV0dXJuIGlmcmFtZTtcbn1cblxuZnVuY3Rpb24gc2V0SWZyYW1lQ29udGVudChpZnJhbWUsIHNyYykge1xuXHRpZiAoc3JjID09PSB1bmRlZmluZWQpIHtcblx0XHR3cml0ZVN0YW5kYXJkc01vZGVIdG1sKGlmcmFtZSk7XG5cdH1cdGVsc2Uge1xuXHRcdHNldElmcmFtZVNyYyhpZnJhbWUsIHNyYyk7XG5cdH1cbn1cblxuZnVuY3Rpb24gc2V0SWZyYW1lU3JjKGlmcmFtZSwgc3JjKSB7XG5cdGlmcmFtZS5zZXRBdHRyaWJ1dGUoXCJzcmNcIiwgc3JjKTtcbn1cblxuZnVuY3Rpb24gd3JpdGVTdGFuZGFyZHNNb2RlSHRtbChpZnJhbWUpIHtcblx0dmFyIHN0YW5kYXJkc01vZGUgPSBcIjwhRE9DVFlQRSBodG1sPlxcbjxodG1sPjxoZWFkPjwvaGVhZD48Ym9keT48L2JvZHk+PC9odG1sPlwiO1xuXHRpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudC5vcGVuKCk7XG5cdGlmcmFtZS5jb250ZW50V2luZG93LmRvY3VtZW50LndyaXRlKHN0YW5kYXJkc01vZGUpO1xuXHRpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudC5jbG9zZSgpO1xufVxuXG5mdW5jdGlvbiBsb2FkU3R5bGVzaGVldHMoc2VsZiwgdXJscywgY2FsbGJhY2spIHtcblx0YXN5bmMuZWFjaCh1cmxzLCBhZGRMaW5rVGFnLCBjYWxsYmFjayk7XG5cblx0ZnVuY3Rpb24gYWRkTGlua1RhZyh1cmwsIG9uTGlua0xvYWQpIHtcblx0XHR2YXIgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJsaW5rXCIpO1xuXHRcdHNoaW0uRXZlbnRUYXJnZXQuYWRkRXZlbnRMaXN0ZW5lcihsaW5rLCBcImxvYWRcIiwgZnVuY3Rpb24oZXZlbnQpIHsgb25MaW5rTG9hZChudWxsKTsgfSk7XG5cdFx0bGluay5zZXRBdHRyaWJ1dGUoXCJyZWxcIiwgXCJzdHlsZXNoZWV0XCIpO1xuXHRcdGxpbmsuc2V0QXR0cmlidXRlKFwidHlwZVwiLCBcInRleHQvY3NzXCIpO1xuXHRcdGxpbmsuc2V0QXR0cmlidXRlKFwiaHJlZlwiLCB1cmwpO1xuXHRcdHNoaW0uRG9jdW1lbnQuaGVhZChzZWxmLl9kb2N1bWVudCkuYXBwZW5kQ2hpbGQobGluayk7XG5cdH1cbn1cblxuZnVuY3Rpb24gbG9hZFJhd0NTUyhzZWxmLCBjc3MpIHtcblx0dmFyIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInN0eWxlXCIpO1xuXHRzdHlsZS5zZXRBdHRyaWJ1dGUoXCJ0eXBlXCIsIFwidGV4dC9jc3NcIik7XG5cdGlmIChzdHlsZS5zdHlsZVNoZWV0KSB7XG5cdFx0Ly8gV09SS0FST1VORCBJRSA4OiBUaHJvd3MgJ3Vua25vd24gcnVudGltZSBlcnJvcicgaWYgeW91IHNldCBpbm5lckhUTUwgb24gYSA8c3R5bGU+IHRhZ1xuXHRcdHN0eWxlLnN0eWxlU2hlZXQuY3NzVGV4dCA9IGNzcztcblx0fVxuXHRlbHNlIHtcblx0XHRzdHlsZS5pbm5lckhUTUwgPSBjc3M7XG5cdH1cblx0c2hpbS5Eb2N1bWVudC5oZWFkKHNlbGYuX2RvY3VtZW50KS5hcHBlbmRDaGlsZChzdHlsZSk7XG59XG5cbk1lLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXHRlbnN1cmVVc2FibGUodGhpcyk7XG5cblx0dGhpcy5fZG9jdW1lbnQuYm9keS5pbm5lckhUTUwgPSB0aGlzLl9vcmlnaW5hbEJvZHk7XG5cdHRoaXMuc2Nyb2xsKDAsIDApO1xuXHR0aGlzLnJlc2l6ZSh0aGlzLl9vcmlnaW5hbFdpZHRoLCB0aGlzLl9vcmlnaW5hbEhlaWdodCk7XG59O1xuXG5NZS5wcm90b3R5cGUucmVsb2FkID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtGdW5jdGlvbl0pO1xuXHRlbnN1cmVVc2FibGUodGhpcyk7XG5cblx0dmFyIGZyYW1lID0gdGhpcztcblx0dmFyIGlmcmFtZSA9IHRoaXMuX2RvbUVsZW1lbnQ7XG5cdHZhciBzcmMgPSB0aGlzLl9vcmlnaW5hbFNyYztcblxuXHR0aGlzLnJlc2l6ZSh0aGlzLl9vcmlnaW5hbFdpZHRoLCB0aGlzLl9vcmlnaW5hbEhlaWdodCk7XG5cdHNldEZyYW1lTG9hZENhbGxiYWNrKGZyYW1lLCBjYWxsYmFjayk7XG5cdHNldElmcmFtZUNvbnRlbnQoaWZyYW1lLCBzcmMpO1xufTtcblxuTWUucHJvdG90eXBlLnRvRG9tRWxlbWVudCA9IGZ1bmN0aW9uKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXHRlbnN1cmVVc2FibGUodGhpcyk7XG5cblx0cmV0dXJuIHRoaXMuX2RvbUVsZW1lbnQ7XG59O1xuXG5NZS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24oKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdGVuc3VyZUxvYWRlZCh0aGlzKTtcblx0aWYgKHRoaXMuX3JlbW92ZWQpIHJldHVybjtcblxuXHR0aGlzLl9kb21FbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5fZG9tRWxlbWVudCk7XG5cdHRoaXMuX3JlbW92ZWQgPSB0cnVlO1xufTtcblxuTWUucHJvdG90eXBlLnZpZXdwb3J0ID0gZnVuY3Rpb24oKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdGVuc3VyZVVzYWJsZSh0aGlzKTtcblxuXHRyZXR1cm4gbmV3IFFWaWV3cG9ydCh0aGlzKTtcbn07XG5cbk1lLnByb3RvdHlwZS5wYWdlID0gZnVuY3Rpb24oKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdGVuc3VyZVVzYWJsZSh0aGlzKTtcblxuXHRyZXR1cm4gbmV3IFFQYWdlKHRoaXMpO1xufTtcblxuTWUucHJvdG90eXBlLmJvZHkgPSBmdW5jdGlvbigpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHRyZXR1cm4gdGhpcy5nZXQoXCJib2R5XCIpO1xufTtcblxuTWUucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uKGh0bWwsIG5pY2tuYW1lKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbU3RyaW5nLCBbdW5kZWZpbmVkLCBTdHJpbmddXSk7XG5cdGlmIChuaWNrbmFtZSA9PT0gdW5kZWZpbmVkKSBuaWNrbmFtZSA9IGh0bWw7XG5cblx0cmV0dXJuIHRoaXMuYm9keSgpLmFkZChodG1sLCBuaWNrbmFtZSk7XG59O1xuXG5NZS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24oc2VsZWN0b3IsIG5pY2tuYW1lKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbU3RyaW5nLCBbdW5kZWZpbmVkLCBTdHJpbmddXSk7XG5cdGlmIChuaWNrbmFtZSA9PT0gdW5kZWZpbmVkKSBuaWNrbmFtZSA9IHNlbGVjdG9yO1xuXHRlbnN1cmVVc2FibGUodGhpcyk7XG5cblx0dmFyIG5vZGVzID0gdGhpcy5fZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG5cdGVuc3VyZS50aGF0KG5vZGVzLmxlbmd0aCA9PT0gMSwgXCJFeHBlY3RlZCBvbmUgZWxlbWVudCB0byBtYXRjaCAnXCIgKyBzZWxlY3RvciArIFwiJywgYnV0IGZvdW5kIFwiICsgbm9kZXMubGVuZ3RoKTtcblx0cmV0dXJuIG5ldyBRRWxlbWVudChub2Rlc1swXSwgdGhpcywgbmlja25hbWUpO1xufTtcblxuTWUucHJvdG90eXBlLmdldEFsbCA9IGZ1bmN0aW9uKHNlbGVjdG9yLCBuaWNrbmFtZSkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW1N0cmluZywgW3VuZGVmaW5lZCwgU3RyaW5nXV0pO1xuXHRpZiAobmlja25hbWUgPT09IHVuZGVmaW5lZCkgbmlja25hbWUgPSBzZWxlY3Rvcjtcblx0ZW5zdXJlVXNhYmxlKHRoaXMpO1xuXG5cdHJldHVybiBuZXcgUUVsZW1lbnRMaXN0KHRoaXMuX2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpLCB0aGlzLCBuaWNrbmFtZSk7XG59O1xuXG5NZS5wcm90b3R5cGUuc2Nyb2xsID0gZnVuY3Rpb24gc2Nyb2xsKHgsIHkpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtOdW1iZXIsIE51bWJlcl0pO1xuXHRlbnN1cmVVc2FibGUodGhpcyk7XG5cblx0dGhpcy5fZG9tRWxlbWVudC5jb250ZW50V2luZG93LnNjcm9sbCh4LCB5KTtcbn07XG5cbk1lLnByb3RvdHlwZS5nZXRSYXdTY3JvbGxQb3NpdGlvbiA9IGZ1bmN0aW9uIGdldFJhd1Njcm9sbFBvc2l0aW9uKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXHRlbnN1cmVVc2FibGUodGhpcyk7XG5cblx0cmV0dXJuIHtcblx0XHR4OiBzaGltLldpbmRvdy5wYWdlWE9mZnNldCh0aGlzLl9kb21FbGVtZW50LmNvbnRlbnRXaW5kb3csIHRoaXMuX2RvY3VtZW50KSxcblx0XHR5OiBzaGltLldpbmRvdy5wYWdlWU9mZnNldCh0aGlzLl9kb21FbGVtZW50LmNvbnRlbnRXaW5kb3csIHRoaXMuX2RvY3VtZW50KVxuXHR9O1xufTtcblxuTWUucHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uIHJlc2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbTnVtYmVyLCBOdW1iZXJdKTtcblx0ZW5zdXJlVXNhYmxlKHRoaXMpO1xuXG5cdHRoaXMuX2RvbUVsZW1lbnQuc2V0QXR0cmlidXRlKFwid2lkdGhcIiwgXCJcIiArIHdpZHRoKTtcblx0dGhpcy5fZG9tRWxlbWVudC5zZXRBdHRyaWJ1dGUoXCJoZWlnaHRcIiwgXCJcIiArIGhlaWdodCk7XG59O1xuXG5mdW5jdGlvbiBlbnN1cmVVc2FibGUoc2VsZikge1xuXHRlbnN1cmVMb2FkZWQoc2VsZik7XG5cdGVuc3VyZU5vdFJlbW92ZWQoc2VsZik7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZUxvYWRlZChzZWxmKSB7XG5cdGVuc3VyZS50aGF0KHNlbGYuX2xvYWRlZCwgXCJRRnJhbWUgbm90IGxvYWRlZDogV2FpdCBmb3IgZnJhbWUgY3JlYXRpb24gY2FsbGJhY2sgdG8gZXhlY3V0ZSBiZWZvcmUgdXNpbmcgZnJhbWVcIik7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZU5vdFJlbW92ZWQoc2VsZikge1xuXHRlbnN1cmUudGhhdCghc2VsZi5fcmVtb3ZlZCwgXCJBdHRlbXB0ZWQgdG8gdXNlIGZyYW1lIGFmdGVyIGl0IHdhcyByZW1vdmVkXCIpO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgUGFnZUVkZ2UgPSByZXF1aXJlKFwiLi9kZXNjcmlwdG9ycy9wYWdlX2VkZ2UuanNcIik7XG52YXIgQ2VudGVyID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvcnMvY2VudGVyLmpzXCIpO1xudmFyIEFzc2VydGFibGUgPSByZXF1aXJlKFwiLi9hc3NlcnRhYmxlLmpzXCIpO1xudmFyIEdlbmVyaWNTaXplID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvcnMvZ2VuZXJpY19zaXplLmpzXCIpO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFFQYWdlKGZyYW1lKSB7XG5cdHZhciBRRnJhbWUgPSByZXF1aXJlKFwiLi9xX2ZyYW1lLmpzXCIpOyAgIC8vIGJyZWFrIGNpcmN1bGFyIGRlcGVuZGVuY3lcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgUUZyYW1lIF0pO1xuXG5cdC8vIHByb3BlcnRpZXNcblx0dGhpcy50b3AgPSBQYWdlRWRnZS50b3AoZnJhbWUpO1xuXHR0aGlzLnJpZ2h0ID0gUGFnZUVkZ2UucmlnaHQoZnJhbWUpO1xuXHR0aGlzLmJvdHRvbSA9IFBhZ2VFZGdlLmJvdHRvbShmcmFtZSk7XG5cdHRoaXMubGVmdCA9IFBhZ2VFZGdlLmxlZnQoZnJhbWUpO1xuXG5cdHRoaXMud2lkdGggPSBHZW5lcmljU2l6ZS5jcmVhdGUodGhpcy5sZWZ0LCB0aGlzLnJpZ2h0LCBcIndpZHRoIG9mIHBhZ2VcIik7XG5cdHRoaXMuaGVpZ2h0ID0gR2VuZXJpY1NpemUuY3JlYXRlKHRoaXMudG9wLCB0aGlzLmJvdHRvbSwgXCJoZWlnaHQgb2YgcGFnZVwiKTtcblxuXHR0aGlzLmNlbnRlciA9IENlbnRlci54KHRoaXMubGVmdCwgdGhpcy5yaWdodCwgXCJjZW50ZXIgb2YgcGFnZVwiKTtcblx0dGhpcy5taWRkbGUgPSBDZW50ZXIueSh0aGlzLnRvcCwgdGhpcy5ib3R0b20sIFwibWlkZGxlIG9mIHBhZ2VcIik7XG59O1xuQXNzZXJ0YWJsZS5leHRlbmQoTWUpO1xuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgZW5zdXJlID0gcmVxdWlyZShcIi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgVmlld3BvcnRFZGdlID0gcmVxdWlyZShcIi4vZGVzY3JpcHRvcnMvdmlld3BvcnRfZWRnZS5qc1wiKTtcbnZhciBDZW50ZXIgPSByZXF1aXJlKFwiLi9kZXNjcmlwdG9ycy9jZW50ZXIuanNcIik7XG52YXIgQXNzZXJ0YWJsZSA9IHJlcXVpcmUoXCIuL2Fzc2VydGFibGUuanNcIik7XG52YXIgR2VuZXJpY1NpemUgPSByZXF1aXJlKFwiLi9kZXNjcmlwdG9ycy9nZW5lcmljX3NpemUuanNcIik7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gUVZpZXdwb3J0KGZyYW1lKSB7XG5cdHZhciBRRnJhbWUgPSByZXF1aXJlKFwiLi9xX2ZyYW1lLmpzXCIpOyAgIC8vIGJyZWFrIGNpcmN1bGFyIGRlcGVuZGVuY3lcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgUUZyYW1lIF0pO1xuXG5cdC8vIHByb3BlcnRpZXNcblx0dGhpcy50b3AgPSBWaWV3cG9ydEVkZ2UudG9wKGZyYW1lKTtcblx0dGhpcy5yaWdodCA9IFZpZXdwb3J0RWRnZS5yaWdodChmcmFtZSk7XG5cdHRoaXMuYm90dG9tID0gVmlld3BvcnRFZGdlLmJvdHRvbShmcmFtZSk7XG5cdHRoaXMubGVmdCA9IFZpZXdwb3J0RWRnZS5sZWZ0KGZyYW1lKTtcblxuXHR0aGlzLndpZHRoID0gR2VuZXJpY1NpemUuY3JlYXRlKHRoaXMubGVmdCwgdGhpcy5yaWdodCwgXCJ3aWR0aCBvZiB2aWV3cG9ydFwiKTtcblx0dGhpcy5oZWlnaHQgPSBHZW5lcmljU2l6ZS5jcmVhdGUodGhpcy50b3AsIHRoaXMuYm90dG9tLCBcImhlaWdodCBvZiB2aWV3cG9ydFwiKTtcblxuXHR0aGlzLmNlbnRlciA9IENlbnRlci54KHRoaXMubGVmdCwgdGhpcy5yaWdodCwgXCJjZW50ZXIgb2Ygdmlld3BvcnRcIik7XG5cdHRoaXMubWlkZGxlID0gQ2VudGVyLnkodGhpcy50b3AsIHRoaXMuYm90dG9tLCBcIm1pZGRsZSBvZiB2aWV3cG9ydFwiKTtcbn07XG5Bc3NlcnRhYmxlLmV4dGVuZChNZSk7XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNyBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuL3V0aWwvZW5zdXJlLmpzXCIpO1xudmFyIFFGcmFtZSA9IHJlcXVpcmUoXCIuL3FfZnJhbWUuanNcIik7XG52YXIgU2l6ZSA9IHJlcXVpcmUoXCIuL3ZhbHVlcy9zaXplLmpzXCIpO1xuXG52YXIgZmVhdHVyZXMgPSBudWxsO1xuXG5leHBvcnRzLmNyZWF0ZUZyYW1lID0gZnVuY3Rpb24ob3B0aW9ucywgY2FsbGJhY2spIHtcblx0cmV0dXJuIFFGcmFtZS5jcmVhdGUoZG9jdW1lbnQuYm9keSwgb3B0aW9ucywgZnVuY3Rpb24oZXJyLCBjYWxsYmFja0ZyYW1lKSB7XG5cdFx0aWYgKGZlYXR1cmVzID09PSBudWxsKSB7XG5cdFx0XHRkZXRlY3RCcm93c2VyRmVhdHVyZXMoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGNhbGxiYWNrKGVyciwgY2FsbGJhY2tGcmFtZSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRjYWxsYmFjayhlcnIsIGNhbGxiYWNrRnJhbWUpO1xuXHRcdH1cblx0fSk7XG59O1xuXG5leHBvcnRzLmJyb3dzZXIgPSB7fTtcblxuZXhwb3J0cy5icm93c2VyLmVubGFyZ2VzRnJhbWVUb1BhZ2VTaXplID0gY3JlYXRlRGV0ZWN0aW9uTWV0aG9kKFwiZW5sYXJnZXNGcmFtZVwiKTtcbmV4cG9ydHMuYnJvd3Nlci5lbmxhcmdlc0ZvbnRzID0gY3JlYXRlRGV0ZWN0aW9uTWV0aG9kKFwiZW5sYXJnZXNGb250c1wiKTtcbmV4cG9ydHMuYnJvd3Nlci5taXNyZXBvcnRzQ2xpcEF1dG9Qcm9wZXJ0eSA9IGNyZWF0ZURldGVjdGlvbk1ldGhvZChcIm1pc3JlcG9ydHNDbGlwQXV0b1wiKTtcbmV4cG9ydHMuYnJvd3Nlci5taXNyZXBvcnRzQXV0b1ZhbHVlc0luQ2xpcFByb3BlcnR5ID0gY3JlYXRlRGV0ZWN0aW9uTWV0aG9kKFwibWlzcmVwb3J0c0NsaXBWYWx1ZXNcIik7XG5leHBvcnRzLmJyb3dzZXIucm91bmRzT2ZmUGl4ZWxDYWxjdWxhdGlvbnMgPSBjcmVhdGVEZXRlY3Rpb25NZXRob2QoXCJyb3VuZHNPZmZQaXhlbENhbGN1bGF0aW9uc1wiKTtcblxuZnVuY3Rpb24gY3JlYXRlRGV0ZWN0aW9uTWV0aG9kKHByb3BlcnR5TmFtZSkge1xuXHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cdFx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblx0XHRlbnN1cmUudGhhdChmZWF0dXJlcyAhPT0gbnVsbCwgXCJNdXN0IGNyZWF0ZSBhIGZyYW1lIGJlZm9yZSB1c2luZyBRdWl4b3RlIGJyb3dzZXIgZmVhdHVyZSBkZXRlY3Rpb24uXCIpO1xuXG5cdFx0cmV0dXJuIGZlYXR1cmVzW3Byb3BlcnR5TmFtZV07XG5cdH07XG59XG5cbmZ1bmN0aW9uIGRldGVjdEJyb3dzZXJGZWF0dXJlcyhjYWxsYmFjaykge1xuXHR2YXIgRlJBTUVfV0lEVEggPSAxNTAwO1xuXHR2YXIgRlJBTUVfSEVJR0hUID0gMjAwO1xuXG5cdGZlYXR1cmVzID0ge307XG5cdHZhciBmcmFtZSA9IFFGcmFtZS5jcmVhdGUoZG9jdW1lbnQuYm9keSwgeyB3aWR0aDogRlJBTUVfV0lEVEgsIGhlaWdodDogRlJBTUVfSEVJR0hUIH0sIGZ1bmN0aW9uKGVycikge1xuXHRcdGlmIChlcnIpIHtcblx0XHRcdGNvbnNvbGUubG9nKFwiRXJyb3Igd2hpbGUgY3JlYXRpbmcgUXVpeG90ZSBicm93c2VyIGZlYXR1cmUgZGV0ZWN0aW9uIGZyYW1lOiBcIiArIGVycik7XG5cdFx0XHRyZXR1cm4gY2FsbGJhY2soKTtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0ZmVhdHVyZXMuZW5sYXJnZXNGcmFtZSA9IGRldGVjdEZyYW1lRW5sYXJnZW1lbnQoZnJhbWUsIEZSQU1FX1dJRFRIKTtcblx0XHRcdGZlYXR1cmVzLm1pc3JlcG9ydHNDbGlwQXV0byA9IGRldGVjdFJlcG9ydGVkQ2xpcEF1dG8oZnJhbWUpO1xuXHRcdFx0ZmVhdHVyZXMubWlzcmVwb3J0c0NsaXBWYWx1ZXMgPSBkZXRlY3RSZXBvcnRlZENsaXBQcm9wZXJ0eVZhbHVlcyhmcmFtZSk7XG5cdFx0XHRmZWF0dXJlcy5yb3VuZHNPZmZQaXhlbENhbGN1bGF0aW9ucyA9IGRldGVjdFJvdW5kc09mZlBpeGVsQ2FsY3VsYXRpb25zKGZyYW1lKTtcblxuXHRcdFx0ZnJhbWUucmVzZXQoKTtcblx0XHRcdGRldGVjdEZvbnRFbmxhcmdlbWVudChmcmFtZSwgRlJBTUVfV0lEVEgsIGZ1bmN0aW9uKHJlc3VsdCkge1xuXHRcdFx0XHRmZWF0dXJlcy5lbmxhcmdlc0ZvbnRzID0gcmVzdWx0O1xuXHRcdFx0XHRmcmFtZS5yZW1vdmUoKTtcblx0XHRcdFx0cmV0dXJuIGNhbGxiYWNrKCk7XG5cdFx0XHR9KTtcblxuXHRcdH1cblx0XHRjYXRjaChlcnIyKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIkVycm9yIGR1cmluZyBRdWl4b3RlIGJyb3dzZXIgZmVhdHVyZSBkZXRlY3Rpb246IFwiICsgZXJyMik7XG5cdFx0fVxuXHR9KTtcblxufVxuXG5mdW5jdGlvbiBkZXRlY3RGcmFtZUVubGFyZ2VtZW50KGZyYW1lLCBmcmFtZVdpZHRoKSB7XG5cdGZyYW1lLmFkZChcIjxkaXYgc3R5bGU9J3dpZHRoOiBcIiArIChmcmFtZVdpZHRoICsgMjAwKSArIFwicHgnPmZvcmNlIHNjcm9sbGluZzwvZGl2PlwiKTtcblx0cmV0dXJuICFmcmFtZS52aWV3cG9ydCgpLndpZHRoLnZhbHVlKCkuZXF1YWxzKFNpemUuY3JlYXRlKGZyYW1lV2lkdGgpKTtcbn1cblxuZnVuY3Rpb24gZGV0ZWN0Rm9udEVubGFyZ2VtZW50KGZyYW1lLCBmcmFtZVdpZHRoLCBjYWxsYmFjaykge1xuXHRlbnN1cmUudGhhdChmcmFtZVdpZHRoID49IDE1MDAsIFwiRGV0ZWN0b3IgZnJhbWUgd2lkdGggbXVzdCBiZSBsYXJnZXIgdGhhbiBzY3JlZW4gdG8gZGV0ZWN0IGZvbnQgZW5sYXJnZW1lbnRcIik7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiB3ZSB1c2UgYSA8ZGl2PiBiZWNhdXNlIHRoZSA8c3R5bGU+IHRhZyBjYW4ndCBiZSBhZGRlZCBieSBmcmFtZS5hZGQoKS4gQXQgdGhlIHRpbWUgb2YgdGhpc1xuXHQvLyB3cml0aW5nLCBJJ20gbm90IHN1cmUgaWYgdGhlIGlzc3VlIGlzIHdpdGggZnJhbWUuYWRkKCkgb3IgaWYgSUUganVzdCBjYW4ndCBwcm9ncmFtbWF0aWNhbGx5IGFkZCA8c3R5bGU+IHRhZ3MuXG5cdGZyYW1lLmFkZChcIjxkaXY+PHN0eWxlPnAgeyBmb250LXNpemU6IDE1cHg7IH08L3N0eWxlPjwvZGl2PlwiKTtcblxuXHR2YXIgdGV4dCA9IGZyYW1lLmFkZChcIjxwPmFyYml0cmFyeSB0ZXh0PC9wPlwiKTtcblx0ZnJhbWUuYWRkKFwiPHA+bXVzdCBoYXZlIHR3byBwIHRhZ3MgdG8gd29yazwvcD5cIik7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBuZWVkIHRvIGZvcmNlIHJlZmxvdyBvciBnZXR0aW5nIGZvbnQtc2l6ZSBtYXkgZmFpbCBiZWxvd1xuXHQvLyBUaGlzIHNlZW1zIHRvIG9jY3VyIHdoZW4gSUUgaXMgcnVubmluZyBpbiBhIHNsb3cgVmlydHVhbEJveCBWTS4gVGhlcmUgaXMgbm8gdGVzdCBmb3IgdGhpcyBsaW5lLlxuXHR2YXIgZm9yY2VSZWZsb3cgPSB0ZXh0Lm9mZnNldEhlaWdodDtcblxuXHQvLyBXT1JLQVJPVU5EIFNhZmFyaSA4LjAuMDogdGltZW91dCByZXF1aXJlZCBiZWNhdXNlIGZvbnQgaXMgZW5sYXJnZWQgYXN5bmNocm9ub3VzbHlcblx0c2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHR2YXIgZm9udFNpemUgPSB0ZXh0LmdldFJhd1N0eWxlKFwiZm9udC1zaXplXCIpO1xuXHRcdGVuc3VyZS50aGF0KGZvbnRTaXplICE9PSBcIlwiLCBcIkV4cGVjdGVkIGZvbnQtc2l6ZSB0byBiZSBhIHZhbHVlXCIpO1xuXG5cdFx0Ly8gV09SS0FST1VORCBJRSA4OiBpZ25vcmVzIDxzdHlsZT4gdGFnIHdlIGFkZGVkIGFib3ZlXG5cdFx0aWYgKGZvbnRTaXplID09PSBcIjEycHRcIikgcmV0dXJuIGNhbGxiYWNrKGZhbHNlKTtcblxuXHRcdHJldHVybiBjYWxsYmFjayhmb250U2l6ZSAhPT0gXCIxNXB4XCIpO1xuXHR9LCAwKTtcbn1cblxuZnVuY3Rpb24gZGV0ZWN0UmVwb3J0ZWRDbGlwQXV0byhmcmFtZSkge1xuXHR2YXIgZWxlbWVudCA9IGZyYW1lLmFkZChcIjxkaXYgc3R5bGU9J2NsaXA6IGF1dG87Jz48L2Rpdj5cIik7XG5cdHZhciBjbGlwID0gZWxlbWVudC5nZXRSYXdTdHlsZShcImNsaXBcIik7XG5cblx0cmV0dXJuIGNsaXAgIT09IFwiYXV0b1wiO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RSZXBvcnRlZENsaXBQcm9wZXJ0eVZhbHVlcyhmcmFtZSkge1xuXHR2YXIgZWxlbWVudCA9IGZyYW1lLmFkZChcIjxkaXYgc3R5bGU9J2NsaXA6IHJlY3QoYXV0bywgYXV0bywgYXV0bywgYXV0byk7Jz48L2Rpdj5cIik7XG5cdHZhciBjbGlwID0gZWxlbWVudC5nZXRSYXdTdHlsZShcImNsaXBcIik7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBQcm92aWRlcyAnY2xpcFRvcCcgZXRjLiBpbnN0ZWFkIG9mICdjbGlwJyBwcm9wZXJ0eVxuXHRpZiAoY2xpcCA9PT0gXCJcIiAmJiBlbGVtZW50LmdldFJhd1N0eWxlKFwiY2xpcC10b3BcIikgPT09IFwiYXV0b1wiKSByZXR1cm4gZmFsc2U7XG5cblx0cmV0dXJuIGNsaXAgIT09IFwicmVjdChhdXRvLCBhdXRvLCBhdXRvLCBhdXRvKVwiICYmIGNsaXAgIT09IFwicmVjdChhdXRvIGF1dG8gYXV0byBhdXRvKVwiO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RSb3VuZHNPZmZQaXhlbENhbGN1bGF0aW9ucyhmcmFtZSkge1xuXHR2YXIgZWxlbWVudCA9IGZyYW1lLmFkZChcIjxkaXYgc3R5bGU9J2ZvbnQtc2l6ZTogMTVweDsnPjwvZGl2PlwiKTtcblx0dmFyIHNpemUgPSBlbGVtZW50LmNhbGN1bGF0ZVBpeGVsVmFsdWUoXCIwLjVlbVwiKTtcblxuXHRpZiAoc2l6ZSA9PT0gNy41KSByZXR1cm4gZmFsc2U7XG5cdGlmIChzaXplID09PSA4KSByZXR1cm4gdHJ1ZTtcblx0ZW5zdXJlLnVucmVhY2hhYmxlKFwiRmFpbHVyZSBpbiByb3VuZHNPZmZQaXhlbFZhbHVlcygpIGRldGVjdGlvbjogZXhwZWN0ZWQgNy41IG9yIDgsIGJ1dCBnb3QgXCIgKyBzaXplKTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgMjAxMy0yMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBTZWUgTElDRU5TRS5UWFQgZm9yIGRldGFpbHMuXG5cInVzZSBzdHJpY3RcIjtcblxuLy8gUnVudGltZSBhc3NlcnRpb25zIGZvciBwcm9kdWN0aW9uIGNvZGUuIChDb250cmFzdCB0byBhc3NlcnQuanMsIHdoaWNoIGlzIGZvciB0ZXN0IGNvZGUuKVxuXG52YXIgc2hpbSA9IHJlcXVpcmUoXCIuL3NoaW0uanNcIik7XG52YXIgb29wID0gcmVxdWlyZShcIi4vb29wLmpzXCIpO1xuXG5leHBvcnRzLnRoYXQgPSBmdW5jdGlvbih2YXJpYWJsZSwgbWVzc2FnZSkge1xuXHRpZiAobWVzc2FnZSA9PT0gdW5kZWZpbmVkKSBtZXNzYWdlID0gXCJFeHBlY3RlZCBjb25kaXRpb24gdG8gYmUgdHJ1ZVwiO1xuXG5cdGlmICh2YXJpYWJsZSA9PT0gZmFsc2UpIHRocm93IG5ldyBFbnN1cmVFeGNlcHRpb24oZXhwb3J0cy50aGF0LCBtZXNzYWdlKTtcblx0aWYgKHZhcmlhYmxlICE9PSB0cnVlKSB0aHJvdyBuZXcgRW5zdXJlRXhjZXB0aW9uKGV4cG9ydHMudGhhdCwgXCJFeHBlY3RlZCBjb25kaXRpb24gdG8gYmUgdHJ1ZSBvciBmYWxzZVwiKTtcbn07XG5cbmV4cG9ydHMudW5yZWFjaGFibGUgPSBmdW5jdGlvbihtZXNzYWdlKSB7XG5cdGlmICghbWVzc2FnZSkgbWVzc2FnZSA9IFwiVW5yZWFjaGFibGUgY29kZSBleGVjdXRlZFwiO1xuXG5cdHRocm93IG5ldyBFbnN1cmVFeGNlcHRpb24oZXhwb3J0cy51bnJlYWNoYWJsZSwgbWVzc2FnZSk7XG59O1xuXG5leHBvcnRzLnNpZ25hdHVyZSA9IGZ1bmN0aW9uKGFyZ3MsIHNpZ25hdHVyZSkge1xuXHRzaWduYXR1cmUgPSBzaWduYXR1cmUgfHwgW107XG5cdHZhciBleHBlY3RlZEFyZ0NvdW50ID0gc2lnbmF0dXJlLmxlbmd0aDtcblx0dmFyIGFjdHVhbEFyZ0NvdW50ID0gYXJncy5sZW5ndGg7XG5cblx0aWYgKGFjdHVhbEFyZ0NvdW50ID4gZXhwZWN0ZWRBcmdDb3VudCkge1xuXHRcdHRocm93IG5ldyBFbnN1cmVFeGNlcHRpb24oXG5cdFx0XHRleHBvcnRzLnNpZ25hdHVyZSxcblx0XHRcdFwiRnVuY3Rpb24gY2FsbGVkIHdpdGggdG9vIG1hbnkgYXJndW1lbnRzOiBleHBlY3RlZCBcIiArIGV4cGVjdGVkQXJnQ291bnQgKyBcIiBidXQgZ290IFwiICsgYWN0dWFsQXJnQ291bnRcblx0XHQpO1xuXHR9XG5cblx0dmFyIGFyZywgdHlwZXMsIG5hbWU7XG5cdGZvciAodmFyIGkgPSAwOyBpIDwgc2lnbmF0dXJlLmxlbmd0aDsgaSsrKSB7XG5cdFx0YXJnID0gYXJnc1tpXTtcblx0XHR0eXBlcyA9IHNpZ25hdHVyZVtpXTtcblx0XHRuYW1lID0gXCJBcmd1bWVudCAjXCIgKyAoaSArIDEpO1xuXG5cdFx0aWYgKCFzaGltLkFycmF5LmlzQXJyYXkodHlwZXMpKSB0eXBlcyA9IFsgdHlwZXMgXTtcblx0XHRpZiAoIWFyZ01hdGNoZXNBbnlQb3NzaWJsZVR5cGUoYXJnLCB0eXBlcykpIHtcblx0XHRcdHZhciBtZXNzYWdlID0gbmFtZSArIFwiIGV4cGVjdGVkIFwiICsgZXhwbGFpblBvc3NpYmxlVHlwZXModHlwZXMpICsgXCIsIGJ1dCB3YXMgXCIgKyBleHBsYWluQXJnKGFyZyk7XG5cdFx0XHR0aHJvdyBuZXcgRW5zdXJlRXhjZXB0aW9uKGV4cG9ydHMuc2lnbmF0dXJlLCBtZXNzYWdlKTtcblx0XHR9XG5cdH1cbn07XG5cbmZ1bmN0aW9uIGFyZ01hdGNoZXNBbnlQb3NzaWJsZVR5cGUoYXJnLCB0eXBlKSB7XG5cdGZvciAodmFyIGkgPSAwOyBpIDwgdHlwZS5sZW5ndGg7IGkrKykge1xuXHRcdGlmIChhcmdNYXRjaGVzVHlwZShhcmcsIHR5cGVbaV0pKSByZXR1cm4gdHJ1ZTtcblx0fVxuXHRyZXR1cm4gZmFsc2U7XG5cblx0ZnVuY3Rpb24gYXJnTWF0Y2hlc1R5cGUoYXJnLCB0eXBlKSB7XG5cdFx0c3dpdGNoIChnZXRBcmdUeXBlKGFyZykpIHtcblx0XHRcdGNhc2UgXCJib29sZWFuXCI6IHJldHVybiB0eXBlID09PSBCb29sZWFuO1xuXHRcdFx0Y2FzZSBcInN0cmluZ1wiOiByZXR1cm4gdHlwZSA9PT0gU3RyaW5nO1xuXHRcdFx0Y2FzZSBcIm51bWJlclwiOiByZXR1cm4gdHlwZSA9PT0gTnVtYmVyO1xuXHRcdFx0Y2FzZSBcImFycmF5XCI6IHJldHVybiB0eXBlID09PSBBcnJheTtcblx0XHRcdGNhc2UgXCJmdW5jdGlvblwiOiByZXR1cm4gdHlwZSA9PT0gRnVuY3Rpb247XG5cdFx0XHRjYXNlIFwib2JqZWN0XCI6IHJldHVybiB0eXBlID09PSBPYmplY3QgfHwgYXJnIGluc3RhbmNlb2YgdHlwZTtcblx0XHRcdGNhc2UgXCJ1bmRlZmluZWRcIjogcmV0dXJuIHR5cGUgPT09IHVuZGVmaW5lZDtcblx0XHRcdGNhc2UgXCJudWxsXCI6IHJldHVybiB0eXBlID09PSBudWxsO1xuXHRcdFx0Y2FzZSBcIk5hTlwiOiByZXR1cm4gdHlwZW9mKHR5cGUpID09PSBcIm51bWJlclwiICYmIGlzTmFOKHR5cGUpO1xuXG5cdFx0XHRkZWZhdWx0OiBleHBvcnRzLnVucmVhY2hhYmxlKCk7XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGV4cGxhaW5Qb3NzaWJsZVR5cGVzKHR5cGUpIHtcblx0dmFyIGpvaW5lciA9IFwiXCI7XG5cdHZhciByZXN1bHQgPSBcIlwiO1xuXHRmb3IgKHZhciBpID0gMDsgaSA8IHR5cGUubGVuZ3RoOyBpKyspIHtcblx0XHRyZXN1bHQgKz0gam9pbmVyICsgZXhwbGFpbk9uZVR5cGUodHlwZVtpXSk7XG5cdFx0am9pbmVyID0gKGkgPT09IHR5cGUubGVuZ3RoIC0gMikgPyBcIiwgb3IgXCIgOiBcIiwgXCI7XG5cdH1cblx0cmV0dXJuIHJlc3VsdDtcblxuXHRmdW5jdGlvbiBleHBsYWluT25lVHlwZSh0eXBlKSB7XG5cdFx0c3dpdGNoICh0eXBlKSB7XG5cdFx0XHRjYXNlIEJvb2xlYW46IHJldHVybiBcImJvb2xlYW5cIjtcblx0XHRcdGNhc2UgU3RyaW5nOiByZXR1cm4gXCJzdHJpbmdcIjtcblx0XHRcdGNhc2UgTnVtYmVyOiByZXR1cm4gXCJudW1iZXJcIjtcblx0XHRcdGNhc2UgQXJyYXk6IHJldHVybiBcImFycmF5XCI7XG5cdFx0XHRjYXNlIEZ1bmN0aW9uOiByZXR1cm4gXCJmdW5jdGlvblwiO1xuXHRcdFx0Y2FzZSBudWxsOiByZXR1cm4gXCJudWxsXCI7XG5cdFx0XHRjYXNlIHVuZGVmaW5lZDogcmV0dXJuIFwidW5kZWZpbmVkXCI7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRpZiAodHlwZW9mIHR5cGUgPT09IFwibnVtYmVyXCIgJiYgaXNOYU4odHlwZSkpIHJldHVybiBcIk5hTlwiO1xuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRyZXR1cm4gb29wLmNsYXNzTmFtZSh0eXBlKSArIFwiIGluc3RhbmNlXCI7XG5cdFx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gZXhwbGFpbkFyZyhhcmcpIHtcblx0dmFyIHR5cGUgPSBnZXRBcmdUeXBlKGFyZyk7XG5cdGlmICh0eXBlICE9PSBcIm9iamVjdFwiKSByZXR1cm4gdHlwZTtcblxuXHRyZXR1cm4gb29wLmluc3RhbmNlTmFtZShhcmcpICsgXCIgaW5zdGFuY2VcIjtcbn1cblxuZnVuY3Rpb24gZ2V0QXJnVHlwZSh2YXJpYWJsZSkge1xuXHR2YXIgdHlwZSA9IHR5cGVvZiB2YXJpYWJsZTtcblx0aWYgKHZhcmlhYmxlID09PSBudWxsKSB0eXBlID0gXCJudWxsXCI7XG5cdGlmIChzaGltLkFycmF5LmlzQXJyYXkodmFyaWFibGUpKSB0eXBlID0gXCJhcnJheVwiO1xuXHRpZiAodHlwZSA9PT0gXCJudW1iZXJcIiAmJiBpc05hTih2YXJpYWJsZSkpIHR5cGUgPSBcIk5hTlwiO1xuXHRyZXR1cm4gdHlwZTtcbn1cblxuXG4vKioqKiovXG5cbnZhciBFbnN1cmVFeGNlcHRpb24gPSBleHBvcnRzLkVuc3VyZUV4Y2VwdGlvbiA9IGZ1bmN0aW9uIEVuc3VyZUV4Y2VwdGlvbihmblRvUmVtb3ZlRnJvbVN0YWNrVHJhY2UsIG1lc3NhZ2UpIHtcblx0aWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBmblRvUmVtb3ZlRnJvbVN0YWNrVHJhY2UpO1xuXHRlbHNlIHRoaXMuc3RhY2sgPSAobmV3IEVycm9yKCkpLnN0YWNrO1xuXHR0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xufTtcbkVuc3VyZUV4Y2VwdGlvbi5wcm90b3R5cGUgPSBzaGltLk9iamVjdC5jcmVhdGUoRXJyb3IucHJvdG90eXBlKTtcbkVuc3VyZUV4Y2VwdGlvbi5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBFbnN1cmVFeGNlcHRpb247XG5FbnN1cmVFeGNlcHRpb24ucHJvdG90eXBlLm5hbWUgPSBcIkVuc3VyZUV4Y2VwdGlvblwiO1xuIiwiLy8gQ29weXJpZ2h0IChjKSAyMDE0IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cblwidXNlIHN0cmljdFwiO1xuXG4vLyBjYW4ndCB1c2UgZW5zdXJlLmpzIGR1ZSB0byBjaXJjdWxhciBkZXBlbmRlbmN5XG52YXIgc2hpbSA9IHJlcXVpcmUoXCIuL3NoaW0uanNcIik7XG5cbmV4cG9ydHMuY2xhc3NOYW1lID0gZnVuY3Rpb24oY29uc3RydWN0b3IpIHtcblx0aWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3IoXCJOb3QgYSBjb25zdHJ1Y3RvclwiKTtcblx0cmV0dXJuIHNoaW0uRnVuY3Rpb24ubmFtZShjb25zdHJ1Y3Rvcik7XG59O1xuXG5leHBvcnRzLmluc3RhbmNlTmFtZSA9IGZ1bmN0aW9uKG9iaikge1xuXHR2YXIgcHJvdG90eXBlID0gc2hpbS5PYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqKTtcblx0aWYgKHByb3RvdHlwZSA9PT0gbnVsbCkgcmV0dXJuIFwiPG5vIHByb3RvdHlwZT5cIjtcblxuXHR2YXIgY29uc3RydWN0b3IgPSBwcm90b3R5cGUuY29uc3RydWN0b3I7XG5cdGlmIChjb25zdHJ1Y3RvciA9PT0gdW5kZWZpbmVkIHx8IGNvbnN0cnVjdG9yID09PSBudWxsKSByZXR1cm4gXCI8YW5vbj5cIjtcblxuXHRyZXR1cm4gc2hpbS5GdW5jdGlvbi5uYW1lKGNvbnN0cnVjdG9yKTtcbn07XG5cbmV4cG9ydHMuZXh0ZW5kRm4gPSBmdW5jdGlvbiBleHRlbmRGbihwYXJlbnRDb25zdHJ1Y3Rvcikge1xuXHRyZXR1cm4gZnVuY3Rpb24oY2hpbGRDb25zdHJ1Y3Rvcikge1xuXHRcdGNoaWxkQ29uc3RydWN0b3IucHJvdG90eXBlID0gc2hpbS5PYmplY3QuY3JlYXRlKHBhcmVudENvbnN0cnVjdG9yLnByb3RvdHlwZSk7XG5cdFx0Y2hpbGRDb25zdHJ1Y3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjaGlsZENvbnN0cnVjdG9yO1xuXHR9O1xufTtcblxuZXhwb3J0cy5tYWtlQWJzdHJhY3QgPSBmdW5jdGlvbiBtYWtlQWJzdHJhY3QoY29uc3RydWN0b3IsIG1ldGhvZHMpIHtcblx0dmFyIG5hbWUgPSBzaGltLkZ1bmN0aW9uLm5hbWUoY29uc3RydWN0b3IpO1xuXHRzaGltLkFycmF5LmZvckVhY2gobWV0aG9kcywgZnVuY3Rpb24obWV0aG9kKSB7XG5cdFx0Y29uc3RydWN0b3IucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihuYW1lICsgXCIgc3ViY2xhc3NlcyBtdXN0IGltcGxlbWVudCBcIiArIG1ldGhvZCArIFwiKCkgbWV0aG9kXCIpO1xuXHRcdH07XG5cdH0pO1xuXG5cdGNvbnN0cnVjdG9yLnByb3RvdHlwZS5jaGVja0Fic3RyYWN0TWV0aG9kcyA9IGZ1bmN0aW9uIGNoZWNrQWJzdHJhY3RNZXRob2RzKCkge1xuXHRcdHZhciB1bmltcGxlbWVudGVkID0gW107XG5cdFx0dmFyIHNlbGYgPSB0aGlzO1xuXHRcdHNoaW0uQXJyYXkuZm9yRWFjaChtZXRob2RzLCBmdW5jdGlvbihuYW1lKSB7XG5cdFx0XHRpZiAoc2VsZltuYW1lXSA9PT0gY29uc3RydWN0b3IucHJvdG90eXBlW25hbWVdKSB1bmltcGxlbWVudGVkLnB1c2gobmFtZSArIFwiKClcIik7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHVuaW1wbGVtZW50ZWQ7XG5cdH07XG59OyIsIi8vIENvcHlyaWdodCAoYykgMjAxNC0yMDE3IFRpdGFuaXVtIEkuVC4gTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLiBGb3IgbGljZW5zZSwgc2VlIFwiUkVBRE1FXCIgb3IgXCJMSUNFTlNFXCIgZmlsZS5cbi8qZXNsaW50IGVxZXFlcTogXCJvZmZcIiwgbm8tZXEtbnVsbDogXCJvZmZcIiwgbm8tYml0d2lzZTogXCJvZmZcIiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuQXJyYXkgPSB7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBubyBBcnJheS5pc0FycmF5XG5cdGlzQXJyYXk6IGZ1bmN0aW9uIGlzQXJyYXkodGhpbmcpIHtcblx0XHRpZiAoQXJyYXkuaXNBcnJheSkgcmV0dXJuIEFycmF5LmlzQXJyYXkodGhpbmcpO1xuXG5cdFx0cmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0aGluZykgPT09ICdbb2JqZWN0IEFycmF5XSc7XG5cdH0sXG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBubyBBcnJheS5ldmVyeVxuXHRldmVyeTogZnVuY3Rpb24gZXZlcnkob2JqLCBjYWxsYmFja2ZuLCB0aGlzQXJnKSB7XG5cdFx0Lypqc2hpbnQgYml0d2lzZTpmYWxzZSwgZXFlcWVxOmZhbHNlLCAtVzA0MTpmYWxzZSAqL1xuXHRcdGlmIChBcnJheS5wcm90b3R5cGUuZXZlcnkpIHJldHVybiBvYmouZXZlcnkoY2FsbGJhY2tmbiwgdGhpc0FyZyk7XG5cblx0XHQvLyBUaGlzIHdvcmthcm91bmQgYmFzZWQgb24gcG9seWZpbGwgY29kZSBmcm9tIE1ETjpcblx0XHQvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9ldmVyeVxuXHRcdHZhciBULCBrO1xuXG5cdFx0aWYgKHRoaXMgPT0gbnVsbCkge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcigndGhpcyBpcyBudWxsIG9yIG5vdCBkZWZpbmVkJyk7XG5cdFx0fVxuXG5cdFx0Ly8gMS4gTGV0IE8gYmUgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIFRvT2JqZWN0IHBhc3NpbmcgdGhlIHRoaXNcblx0XHQvLyAgICB2YWx1ZSBhcyB0aGUgYXJndW1lbnQuXG5cdFx0dmFyIE8gPSBPYmplY3QodGhpcyk7XG5cblx0XHQvLyAyLiBMZXQgbGVuVmFsdWUgYmUgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIHRoZSBHZXQgaW50ZXJuYWwgbWV0aG9kXG5cdFx0Ly8gICAgb2YgTyB3aXRoIHRoZSBhcmd1bWVudCBcImxlbmd0aFwiLlxuXHRcdC8vIDMuIExldCBsZW4gYmUgVG9VaW50MzIobGVuVmFsdWUpLlxuXHRcdHZhciBsZW4gPSBPLmxlbmd0aCA+Pj4gMDtcblxuXHRcdC8vIDQuIElmIElzQ2FsbGFibGUoY2FsbGJhY2tmbikgaXMgZmFsc2UsIHRocm93IGEgVHlwZUVycm9yIGV4Y2VwdGlvbi5cblx0XHRpZiAodHlwZW9mIGNhbGxiYWNrZm4gIT09ICdmdW5jdGlvbicpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoKTtcblx0XHR9XG5cblx0XHQvLyA1LiBJZiB0aGlzQXJnIHdhcyBzdXBwbGllZCwgbGV0IFQgYmUgdGhpc0FyZzsgZWxzZSBsZXQgVCBiZSB1bmRlZmluZWQuXG5cdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG5cdFx0XHRUID0gdGhpc0FyZztcblx0XHR9XG5cblx0XHQvLyA2LiBMZXQgayBiZSAwLlxuXHRcdGsgPSAwO1xuXG5cdFx0Ly8gNy4gUmVwZWF0LCB3aGlsZSBrIDwgbGVuXG5cdFx0d2hpbGUgKGsgPCBsZW4pIHtcblxuXHRcdFx0dmFyIGtWYWx1ZTtcblxuXHRcdFx0Ly8gYS4gTGV0IFBrIGJlIFRvU3RyaW5nKGspLlxuXHRcdFx0Ly8gICBUaGlzIGlzIGltcGxpY2l0IGZvciBMSFMgb3BlcmFuZHMgb2YgdGhlIGluIG9wZXJhdG9yXG5cdFx0XHQvLyBiLiBMZXQga1ByZXNlbnQgYmUgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIHRoZSBIYXNQcm9wZXJ0eSBpbnRlcm5hbFxuXHRcdFx0Ly8gICAgbWV0aG9kIG9mIE8gd2l0aCBhcmd1bWVudCBQay5cblx0XHRcdC8vICAgVGhpcyBzdGVwIGNhbiBiZSBjb21iaW5lZCB3aXRoIGNcblx0XHRcdC8vIGMuIElmIGtQcmVzZW50IGlzIHRydWUsIHRoZW5cblx0XHRcdGlmIChrIGluIE8pIHtcblxuXHRcdFx0XHQvLyBpLiBMZXQga1ZhbHVlIGJlIHRoZSByZXN1bHQgb2YgY2FsbGluZyB0aGUgR2V0IGludGVybmFsIG1ldGhvZFxuXHRcdFx0XHQvLyAgICBvZiBPIHdpdGggYXJndW1lbnQgUGsuXG5cdFx0XHRcdGtWYWx1ZSA9IE9ba107XG5cblx0XHRcdFx0Ly8gaWkuIExldCB0ZXN0UmVzdWx0IGJlIHRoZSByZXN1bHQgb2YgY2FsbGluZyB0aGUgQ2FsbCBpbnRlcm5hbCBtZXRob2Rcblx0XHRcdFx0Ly8gICAgIG9mIGNhbGxiYWNrZm4gd2l0aCBUIGFzIHRoZSB0aGlzIHZhbHVlIGFuZCBhcmd1bWVudCBsaXN0XG5cdFx0XHRcdC8vICAgICBjb250YWluaW5nIGtWYWx1ZSwgaywgYW5kIE8uXG5cdFx0XHRcdHZhciB0ZXN0UmVzdWx0ID0gY2FsbGJhY2tmbi5jYWxsKFQsIGtWYWx1ZSwgaywgTyk7XG5cblx0XHRcdFx0Ly8gaWlpLiBJZiBUb0Jvb2xlYW4odGVzdFJlc3VsdCkgaXMgZmFsc2UsIHJldHVybiBmYWxzZS5cblx0XHRcdFx0aWYgKCF0ZXN0UmVzdWx0KSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRrKys7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9LFxuXG5cdC8vIFdPUktBUk9VTkQgSUUgODogbm8gQXJyYXkuZm9yRWFjaFxuXHRmb3JFYWNoOiBmdW5jdGlvbiBmb3JFYWNoKG9iaiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcblx0XHQvKmpzaGludCBiaXR3aXNlOmZhbHNlLCBlcWVxZXE6ZmFsc2UsIC1XMDQxOmZhbHNlICovXG5cblx0XHRpZiAoQXJyYXkucHJvdG90eXBlLmZvckVhY2gpIHJldHVybiBvYmouZm9yRWFjaChjYWxsYmFjaywgdGhpc0FyZyk7XG5cblx0XHQvLyBUaGlzIHdvcmthcm91bmQgYmFzZWQgb24gcG9seWZpbGwgY29kZSBmcm9tIE1ETjpcblx0XHQvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9mb3JFYWNoXG5cblx0XHQvLyBQcm9kdWN0aW9uIHN0ZXBzIG9mIEVDTUEtMjYyLCBFZGl0aW9uIDUsIDE1LjQuNC4xOFxuXHRcdC8vIFJlZmVyZW5jZTogaHR0cDovL2VzNS5naXRodWIuaW8vI3gxNS40LjQuMThcblxuXHRcdHZhciBULCBrO1xuXG5cdFx0aWYgKG9iaiA9PSBudWxsKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCcgdGhpcyBpcyBudWxsIG9yIG5vdCBkZWZpbmVkJyk7XG5cdFx0fVxuXG5cdFx0Ly8gMS4gTGV0IE8gYmUgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIFRvT2JqZWN0IHBhc3NpbmcgdGhlIHx0aGlzfCB2YWx1ZSBhcyB0aGUgYXJndW1lbnQuXG5cdFx0dmFyIE8gPSBPYmplY3Qob2JqKTtcblxuXHRcdC8vIDIuIExldCBsZW5WYWx1ZSBiZSB0aGUgcmVzdWx0IG9mIGNhbGxpbmcgdGhlIEdldCBpbnRlcm5hbCBtZXRob2Qgb2YgTyB3aXRoIHRoZSBhcmd1bWVudCBcImxlbmd0aFwiLlxuXHRcdC8vIDMuIExldCBsZW4gYmUgVG9VaW50MzIobGVuVmFsdWUpLlxuXHRcdHZhciBsZW4gPSBPLmxlbmd0aCA+Pj4gMDtcblxuXHRcdC8vIDQuIElmIElzQ2FsbGFibGUoY2FsbGJhY2spIGlzIGZhbHNlLCB0aHJvdyBhIFR5cGVFcnJvciBleGNlcHRpb24uXG5cdFx0Ly8gU2VlOiBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3g5LjExXG5cdFx0aWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKGNhbGxiYWNrICsgJyBpcyBub3QgYSBmdW5jdGlvbicpO1xuXHRcdH1cblxuXHRcdC8vIDUuIElmIHRoaXNBcmcgd2FzIHN1cHBsaWVkLCBsZXQgVCBiZSB0aGlzQXJnOyBlbHNlIGxldCBUIGJlIHVuZGVmaW5lZC5cblx0XHRpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcblx0XHRcdFQgPSB0aGlzQXJnO1xuXHRcdH1cblxuXHRcdC8vIDYuIExldCBrIGJlIDBcblx0XHRrID0gMDtcblxuXHRcdC8vIDcuIFJlcGVhdCwgd2hpbGUgayA8IGxlblxuXHRcdHdoaWxlIChrIDwgbGVuKSB7XG5cblx0XHRcdHZhciBrVmFsdWU7XG5cblx0XHRcdC8vIGEuIExldCBQayBiZSBUb1N0cmluZyhrKS5cblx0XHRcdC8vICAgVGhpcyBpcyBpbXBsaWNpdCBmb3IgTEhTIG9wZXJhbmRzIG9mIHRoZSBpbiBvcGVyYXRvclxuXHRcdFx0Ly8gYi4gTGV0IGtQcmVzZW50IGJlIHRoZSByZXN1bHQgb2YgY2FsbGluZyB0aGUgSGFzUHJvcGVydHkgaW50ZXJuYWwgbWV0aG9kIG9mIE8gd2l0aCBhcmd1bWVudCBQay5cblx0XHRcdC8vICAgVGhpcyBzdGVwIGNhbiBiZSBjb21iaW5lZCB3aXRoIGNcblx0XHRcdC8vIGMuIElmIGtQcmVzZW50IGlzIHRydWUsIHRoZW5cblx0XHRcdGlmIChrIGluIE8pIHtcblxuXHRcdFx0XHQvLyBpLiBMZXQga1ZhbHVlIGJlIHRoZSByZXN1bHQgb2YgY2FsbGluZyB0aGUgR2V0IGludGVybmFsIG1ldGhvZCBvZiBPIHdpdGggYXJndW1lbnQgUGsuXG5cdFx0XHRcdGtWYWx1ZSA9IE9ba107XG5cblx0XHRcdFx0Ly8gaWkuIENhbGwgdGhlIENhbGwgaW50ZXJuYWwgbWV0aG9kIG9mIGNhbGxiYWNrIHdpdGggVCBhcyB0aGUgdGhpcyB2YWx1ZSBhbmRcblx0XHRcdFx0Ly8gYXJndW1lbnQgbGlzdCBjb250YWluaW5nIGtWYWx1ZSwgaywgYW5kIE8uXG5cdFx0XHRcdGNhbGxiYWNrLmNhbGwoVCwga1ZhbHVlLCBrLCBPKTtcblx0XHRcdH1cblx0XHRcdC8vIGQuIEluY3JlYXNlIGsgYnkgMS5cblx0XHRcdGsrKztcblx0XHR9XG5cdFx0Ly8gOC4gcmV0dXJuIHVuZGVmaW5lZFxuXHR9XG5cbn07XG5cblxuZXhwb3J0cy5Eb2N1bWVudCA9IHtcblxuXHQvLyBXT1JLQVJPVU5EIElFIDg6IG5vIGRvY3VtZW50LmhlYWRcblx0aGVhZDogZnVuY3Rpb24gaGVhZChkb2MpIHtcblx0XHRpZiAoZG9jLmhlYWQpIHJldHVybiBkb2MuaGVhZDtcblxuXHRcdHJldHVybiBkb2MucXVlcnlTZWxlY3RvcihcImhlYWRcIik7XG5cdH1cblxufTtcblxuXG5leHBvcnRzLkVsZW1lbnQgPSB7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4LCBJRSA5LCBJRSAxMCwgSUUgMTE6IG5vIEVsZW1lbnQucmVtb3ZlKClcblx0cmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUoZWxlbWVudCkge1xuXHRcdGVsZW1lbnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlbGVtZW50KTtcblx0fVxuXG59O1xuXG5cbmV4cG9ydHMuRXZlbnRUYXJnZXQgPSB7XG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBubyBFdmVudFRhcmdldC5hZGRFdmVudExpc3RlbmVyKClcblx0YWRkRXZlbnRMaXN0ZW5lcjogZnVuY3Rpb24gYWRkRXZlbnRMaXN0ZW5lcihlbGVtZW50LCBldmVudCwgY2FsbGJhY2spIHtcblx0XHRpZiAoZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKSByZXR1cm4gZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBjYWxsYmFjayk7XG5cblx0XHRlbGVtZW50LmF0dGFjaEV2ZW50KFwib25cIiArIGV2ZW50LCBjYWxsYmFjayk7XG5cdH1cblxufTtcblxuXG5leHBvcnRzLkZ1bmN0aW9uID0ge1xuXG5cdC8vIFdPUktBUk9VTkQgSUUgOCwgSUUgOSwgSUUgMTAsIElFIDExOiBubyBmdW5jdGlvbi5uYW1lXG5cdG5hbWU6IGZ1bmN0aW9uIG5hbWUoZm4pIHtcblx0XHRpZiAoZm4ubmFtZSkgcmV0dXJuIGZuLm5hbWU7XG5cblx0XHQvLyBCYXNlZCBvbiBjb2RlIGJ5IEphc29uIEJ1bnRpbmcgZXQgYWwsIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzMzMjQyOVxuXHRcdHZhciBmdW5jTmFtZVJlZ2V4ID0gL2Z1bmN0aW9uXFxzKyguezEsfSlcXHMqXFwoLztcblx0XHR2YXIgcmVzdWx0cyA9IChmdW5jTmFtZVJlZ2V4KS5leGVjKChmbikudG9TdHJpbmcoKSk7XG5cdFx0cmV0dXJuIChyZXN1bHRzICYmIHJlc3VsdHMubGVuZ3RoID4gMSkgPyByZXN1bHRzWzFdIDogXCI8YW5vbj5cIjtcblx0fSxcblxufTtcblxuXG5leHBvcnRzLk9iamVjdCA9IHtcblxuXHQvLyBXT1JLQVJPVU5EIElFIDg6IG5vIE9iamVjdC5jcmVhdGUoKVxuXHRjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShwcm90b3R5cGUpIHtcblx0XHRpZiAoT2JqZWN0LmNyZWF0ZSkgcmV0dXJuIE9iamVjdC5jcmVhdGUocHJvdG90eXBlKTtcblxuXHRcdHZhciBUZW1wID0gZnVuY3Rpb24gVGVtcCgpIHt9O1xuXHRcdFRlbXAucHJvdG90eXBlID0gcHJvdG90eXBlO1xuXHRcdHJldHVybiBuZXcgVGVtcCgpO1xuXHR9LFxuXG5cdC8vIFdPUktBUk9VTkQgSUUgODogbm8gT2JqZWN0LmdldFByb3RvdHlwZU9mXG5cdC8vIENhdXRpb246IERvZXNuJ3Qgd29yayBvbiBJRSA4IGlmIGNvbnN0cnVjdG9yIGhhcyBiZWVuIGNoYW5nZWQsIGFzIGlzIHRoZSBjYXNlIHdpdGggYSBzdWJjbGFzcy5cblx0Z2V0UHJvdG90eXBlT2Y6IGZ1bmN0aW9uIGdldFByb3RvdHlwZU9mKG9iaikge1xuXHRcdGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqKTtcblxuXHRcdHZhciByZXN1bHQgPSBvYmouY29uc3RydWN0b3IgPyBvYmouY29uc3RydWN0b3IucHJvdG90eXBlIDogbnVsbDtcblx0XHRyZXR1cm4gcmVzdWx0IHx8IG51bGw7XG5cdH0sXG5cblx0Ly8gV09SS0FST1VORCBJRSA4OiBObyBPYmplY3Qua2V5c1xuXHRrZXlzOiBmdW5jdGlvbiBrZXlzKG9iaikge1xuXHRcdGlmIChPYmplY3Qua2V5cykgcmV0dXJuIE9iamVjdC5rZXlzKG9iaik7XG5cblx0XHQvLyBGcm9tIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9rZXlzXG5cdFx0dmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eSxcblx0XHRcdGhhc0RvbnRFbnVtQnVnID0gISh7IHRvU3RyaW5nOiBudWxsIH0pLnByb3BlcnR5SXNFbnVtZXJhYmxlKCd0b1N0cmluZycpLFxuXHRcdFx0ZG9udEVudW1zID0gW1xuXHRcdFx0XHQndG9TdHJpbmcnLFxuXHRcdFx0XHQndG9Mb2NhbGVTdHJpbmcnLFxuXHRcdFx0XHQndmFsdWVPZicsXG5cdFx0XHRcdCdoYXNPd25Qcm9wZXJ0eScsXG5cdFx0XHRcdCdpc1Byb3RvdHlwZU9mJyxcblx0XHRcdFx0J3Byb3BlcnR5SXNFbnVtZXJhYmxlJyxcblx0XHRcdFx0J2NvbnN0cnVjdG9yJ1xuXHRcdFx0XSxcblx0XHRcdGRvbnRFbnVtc0xlbmd0aCA9IGRvbnRFbnVtcy5sZW5ndGg7XG5cblx0XHRpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgJiYgKHR5cGVvZiBvYmogIT09ICdmdW5jdGlvbicgfHwgb2JqID09PSBudWxsKSkge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcignT2JqZWN0LmtleXMgY2FsbGVkIG9uIG5vbi1vYmplY3QnKTtcblx0XHR9XG5cblx0XHR2YXIgcmVzdWx0ID0gW10sIHByb3AsIGk7XG5cblx0XHRmb3IgKHByb3AgaW4gb2JqKSB7XG5cdFx0XHRpZiAoaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSB7XG5cdFx0XHRcdHJlc3VsdC5wdXNoKHByb3ApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChoYXNEb250RW51bUJ1Zykge1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGRvbnRFbnVtc0xlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgZG9udEVudW1zW2ldKSkge1xuXHRcdFx0XHRcdHJlc3VsdC5wdXNoKGRvbnRFbnVtc1tpXSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG59O1xuXG5cbmV4cG9ydHMuU3RyaW5nID0ge1xuXG5cdC8vIFdPUktBUk9VTkQgSUUgODogTm8gU3RyaW5nLnRyaW0oKVxuXHR0cmltOiBmdW5jdGlvbihzdHIpIHtcblx0XHRpZiAoc3RyLnRyaW0gIT09IHVuZGVmaW5lZCkgcmV0dXJuIHN0ci50cmltKCk7XG5cblx0XHQvLyBCYXNlZCBvbiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9TdHJpbmcvVHJpbVxuXHRcdHJldHVybiBzdHIucmVwbGFjZSgvXltcXHNcXHVGRUZGXFx4QTBdK3xbXFxzXFx1RkVGRlxceEEwXSskL2csICcnKTtcblx0fVxuXG59O1xuXG5cbmV4cG9ydHMuV2luZG93ID0ge1xuXG5cdC8vIFdPUktBUk9VTkQgSUUgODogTm8gV2luZG93LnBhZ2VYT2Zmc2V0XG5cdHBhZ2VYT2Zmc2V0OiBmdW5jdGlvbih3aW5kb3csIGRvY3VtZW50KSB7XG5cdFx0aWYgKHdpbmRvdy5wYWdlWE9mZnNldCAhPT0gdW5kZWZpbmVkKSByZXR1cm4gd2luZG93LnBhZ2VYT2Zmc2V0O1xuXG5cdFx0Ly8gQmFzZWQgb24gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvdy5zY3JvbGxZXG5cdFx0dmFyIGlzQ1NTMUNvbXBhdCA9ICgoZG9jdW1lbnQuY29tcGF0TW9kZSB8fCBcIlwiKSA9PT0gXCJDU1MxQ29tcGF0XCIpO1xuXHRcdHJldHVybiBpc0NTUzFDb21wYXQgPyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdCA6IGRvY3VtZW50LmJvZHkuc2Nyb2xsTGVmdDtcblx0fSxcblxuXG5cdC8vIFdPUktBUk9VTkQgSUUgODogTm8gV2luZG93LnBhZ2VZT2Zmc2V0XG5cdHBhZ2VZT2Zmc2V0OiBmdW5jdGlvbih3aW5kb3csIGRvY3VtZW50KSB7XG5cdFx0aWYgKHdpbmRvdy5wYWdlWU9mZnNldCAhPT0gdW5kZWZpbmVkKSByZXR1cm4gd2luZG93LnBhZ2VZT2Zmc2V0O1xuXG5cdFx0Ly8gQmFzZWQgb24gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvdy5zY3JvbGxZXG5cdFx0dmFyIGlzQ1NTMUNvbXBhdCA9ICgoZG9jdW1lbnQuY29tcGF0TW9kZSB8fCBcIlwiKSA9PT0gXCJDU1MxQ29tcGF0XCIpO1xuXHRcdHJldHVybiBpc0NTUzFDb21wYXQgPyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIDogZG9jdW1lbnQuYm9keS5zY3JvbGxUb3A7XG5cdH1cblxufTsiLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNiBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBWYWx1ZSA9IHJlcXVpcmUoXCIuL3ZhbHVlLmpzXCIpO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFBpeGVscyhhbW91bnQpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgWyBOdW1iZXIsIG51bGwgXSBdKTtcblx0dGhpcy5fbm9uZSA9IChhbW91bnQgPT09IG51bGwpO1xuXHR0aGlzLl9hbW91bnQgPSBhbW91bnQ7XG59O1xuVmFsdWUuZXh0ZW5kKE1lKTtcblxuTWUuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGFtb3VudCkge1xuXHRyZXR1cm4gbmV3IE1lKGFtb3VudCk7XG59O1xuXG5NZS5jcmVhdGVOb25lID0gZnVuY3Rpb24gY3JlYXRlTm9uZSgpIHtcblx0cmV0dXJuIG5ldyBNZShudWxsKTtcbn07XG5cbk1lLlpFUk8gPSBNZS5jcmVhdGUoMCk7XG5NZS5OT05FID0gTWUuY3JlYXRlTm9uZSgpO1xuXG5NZS5wcm90b3R5cGUuY29tcGF0aWJpbGl0eSA9IGZ1bmN0aW9uIGNvbXBhdGliaWxpdHkoKSB7XG5cdHJldHVybiBbIE1lIF07XG59O1xuXG5NZS5wcm90b3R5cGUucGx1cyA9IFZhbHVlLnNhZmUoZnVuY3Rpb24gcGx1cyhvcGVyYW5kKSB7XG5cdGlmICh0aGlzLl9ub25lIHx8IG9wZXJhbmQuX25vbmUpIHJldHVybiBNZS5jcmVhdGVOb25lKCk7XG5cdHJldHVybiBuZXcgTWUodGhpcy5fYW1vdW50ICsgb3BlcmFuZC5fYW1vdW50KTtcbn0pO1xuXG5NZS5wcm90b3R5cGUubWludXMgPSBWYWx1ZS5zYWZlKGZ1bmN0aW9uIG1pbnVzKG9wZXJhbmQpIHtcblx0aWYgKHRoaXMuX25vbmUgfHwgb3BlcmFuZC5fbm9uZSkgcmV0dXJuIE1lLmNyZWF0ZU5vbmUoKTtcblx0cmV0dXJuIG5ldyBNZSh0aGlzLl9hbW91bnQgLSBvcGVyYW5kLl9hbW91bnQpO1xufSk7XG5cbk1lLnByb3RvdHlwZS5kaWZmZXJlbmNlID0gVmFsdWUuc2FmZShmdW5jdGlvbiBkaWZmZXJlbmNlKG9wZXJhbmQpIHtcblx0aWYgKHRoaXMuX25vbmUgfHwgb3BlcmFuZC5fbm9uZSkgcmV0dXJuIE1lLmNyZWF0ZU5vbmUoKTtcblx0cmV0dXJuIG5ldyBNZShNYXRoLmFicyh0aGlzLl9hbW91bnQgLSBvcGVyYW5kLl9hbW91bnQpKTtcbn0pO1xuXG5NZS5wcm90b3R5cGUudGltZXMgPSBmdW5jdGlvbiB0aW1lcyhvcGVyYW5kKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIE51bWJlciBdKTtcblxuXHRpZiAodGhpcy5fbm9uZSkgcmV0dXJuIE1lLmNyZWF0ZU5vbmUoKTtcblx0cmV0dXJuIG5ldyBNZSh0aGlzLl9hbW91bnQgKiBvcGVyYW5kKTtcbn07XG5cbk1lLnByb3RvdHlwZS5hdmVyYWdlID0gVmFsdWUuc2FmZShmdW5jdGlvbiBhdmVyYWdlKG9wZXJhbmQpIHtcblx0aWYgKHRoaXMuX25vbmUgfHwgb3BlcmFuZC5fbm9uZSkgcmV0dXJuIE1lLmNyZWF0ZU5vbmUoKTtcblx0cmV0dXJuIG5ldyBNZSgodGhpcy5fYW1vdW50ICsgb3BlcmFuZC5fYW1vdW50KSAvIDIpO1xufSk7XG5cbk1lLnByb3RvdHlwZS5jb21wYXJlID0gVmFsdWUuc2FmZShmdW5jdGlvbiBjb21wYXJlKG9wZXJhbmQpIHtcblx0dmFyIGJvdGhIYXZlUGl4ZWxzID0gIXRoaXMuX25vbmUgJiYgIW9wZXJhbmQuX25vbmU7XG5cdHZhciBuZWl0aGVySGF2ZVBpeGVscyA9IHRoaXMuX25vbmUgJiYgb3BlcmFuZC5fbm9uZTtcblx0dmFyIG9ubHlMZWZ0SGFzUGl4ZWxzID0gIXRoaXMuX25vbmUgJiYgb3BlcmFuZC5fbm9uZTtcblxuXHRpZiAoYm90aEhhdmVQaXhlbHMpIHtcblx0XHR2YXIgZGlmZmVyZW5jZSA9IHRoaXMuX2Ftb3VudCAtIG9wZXJhbmQuX2Ftb3VudDtcblx0XHRpZiAoTWF0aC5hYnMoZGlmZmVyZW5jZSkgPD0gMC41KSByZXR1cm4gMDtcblx0XHRlbHNlIHJldHVybiBkaWZmZXJlbmNlO1xuXHR9XG5cdGVsc2UgaWYgKG5laXRoZXJIYXZlUGl4ZWxzKSB7XG5cdFx0XHRcdHJldHVybiAwO1xuXHR9XG5cdGVsc2UgaWYgKG9ubHlMZWZ0SGFzUGl4ZWxzKSB7XG5cdFx0cmV0dXJuIDE7XG5cdH1cblx0ZWxzZSB7XG5cdFx0cmV0dXJuIC0xO1xuXHR9XG59KTtcblxuTWUubWluID0gZnVuY3Rpb24obCwgcikge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgWyBNZSwgTWUgXSk7XG5cblx0aWYgKGwuX25vbmUgfHwgci5fbm9uZSkgcmV0dXJuIE1lLmNyZWF0ZU5vbmUoKTtcblx0cmV0dXJuIGwuY29tcGFyZShyKSA8PSAwID8gbCA6IHI7XG59O1xuXG5NZS5tYXggPSBmdW5jdGlvbihsLCByKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIE1lLCBNZSBdKTtcblxuXHRpZiAobC5fbm9uZSB8fCByLl9ub25lKSByZXR1cm4gTWUuY3JlYXRlTm9uZSgpO1xuXHRyZXR1cm4gbC5jb21wYXJlKHIpID49IDAgPyBsIDogcjtcbn07XG5cbk1lLnByb3RvdHlwZS5kaWZmID0gVmFsdWUuc2FmZShmdW5jdGlvbiBkaWZmKGV4cGVjdGVkKSB7XG5cdGlmICh0aGlzLmNvbXBhcmUoZXhwZWN0ZWQpID09PSAwKSByZXR1cm4gXCJcIjtcblx0aWYgKHRoaXMuX25vbmUgfHwgZXhwZWN0ZWQuX25vbmUpIHJldHVybiBcIm5vbi1tZWFzdXJhYmxlXCI7XG5cblx0dmFyIGRpZmZlcmVuY2UgPSBNYXRoLmFicyh0aGlzLl9hbW91bnQgLSBleHBlY3RlZC5fYW1vdW50KTtcblxuXHR2YXIgZGVzYyA9IGRpZmZlcmVuY2U7XG5cdGlmIChkaWZmZXJlbmNlICogMTAwICE9PSBNYXRoLmZsb29yKGRpZmZlcmVuY2UgKiAxMDApKSBkZXNjID0gXCJhYm91dCBcIiArIGRpZmZlcmVuY2UudG9GaXhlZCgyKTtcblx0cmV0dXJuIGRlc2MgKyBcInB4XCI7XG59KTtcblxuTWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdHJldHVybiB0aGlzLl9ub25lID8gXCJubyBwaXhlbHNcIiA6IHRoaXMuX2Ftb3VudCArIFwicHhcIjtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNiBUaXRhbml1bSBJLlQuIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4gRm9yIGxpY2Vuc2UsIHNlZSBcIlJFQURNRVwiIG9yIFwiTElDRU5TRVwiIGZpbGUuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGVuc3VyZSA9IHJlcXVpcmUoXCIuLi91dGlsL2Vuc3VyZS5qc1wiKTtcbnZhciBWYWx1ZSA9IHJlcXVpcmUoXCIuL3ZhbHVlLmpzXCIpO1xudmFyIFBpeGVscyA9IHJlcXVpcmUoXCIuL3BpeGVscy5qc1wiKTtcbnZhciBTaXplID0gcmVxdWlyZShcIi4vc2l6ZS5qc1wiKTtcblxudmFyIFhfRElNRU5TSU9OID0gXCJ4XCI7XG52YXIgWV9ESU1FTlNJT04gPSBcInlcIjtcblxudmFyIE1lID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBQb3NpdGlvbihkaW1lbnNpb24sIHZhbHVlKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIFN0cmluZywgWyBOdW1iZXIsIFBpeGVscyBdIF0pO1xuXG5cdHRoaXMuX2RpbWVuc2lvbiA9IGRpbWVuc2lvbjtcblx0dGhpcy5fdmFsdWUgPSAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSA/IFBpeGVscy5jcmVhdGUodmFsdWUpIDogdmFsdWU7XG59O1xuVmFsdWUuZXh0ZW5kKE1lKTtcblxuTWUueCA9IGZ1bmN0aW9uIHgodmFsdWUpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgWyBOdW1iZXIsIFBpeGVscyBdIF0pO1xuXG5cdHJldHVybiBuZXcgTWUoWF9ESU1FTlNJT04sIHZhbHVlKTtcbn07XG5cbk1lLnkgPSBmdW5jdGlvbiB5KHZhbHVlKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbIFsgTnVtYmVyLCBQaXhlbHMgXSBdKTtcblxuXHRyZXR1cm4gbmV3IE1lKFlfRElNRU5TSU9OLCB2YWx1ZSk7XG59O1xuXG5NZS5ub1ggPSBmdW5jdGlvbiBub1goKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cblx0cmV0dXJuIG5ldyBNZShYX0RJTUVOU0lPTiwgUGl4ZWxzLk5PTkUpO1xufTtcblxuTWUubm9ZID0gZnVuY3Rpb24gbm9ZKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXG5cdHJldHVybiBuZXcgTWUoWV9ESU1FTlNJT04sIFBpeGVscy5OT05FKTtcbn07XG5cbk1lLnByb3RvdHlwZS5jb21wYXRpYmlsaXR5ID0gZnVuY3Rpb24gY29tcGF0aWJpbGl0eSgpIHtcblx0cmV0dXJuIFsgTWUsIFNpemUgXTtcbn07XG5cbk1lLnByb3RvdHlwZS5kaXN0YW5jZVRvID0gZnVuY3Rpb24ob3BlcmFuZCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgWyBNZSBdKTtcblx0Y2hlY2tBeGlzKHRoaXMsIG9wZXJhbmQpO1xuXHRyZXR1cm4gU2l6ZS5jcmVhdGUodGhpcy5fdmFsdWUuZGlmZmVyZW5jZShvcGVyYW5kLnRvUGl4ZWxzKCkpKTtcbn07XG5cbk1lLnByb3RvdHlwZS5wbHVzID0gVmFsdWUuc2FmZShmdW5jdGlvbiBwbHVzKG9wZXJhbmQpIHtcblx0Y2hlY2tBeGlzKHRoaXMsIG9wZXJhbmQpO1xuXHRyZXR1cm4gbmV3IE1lKHRoaXMuX2RpbWVuc2lvbiwgdGhpcy5fdmFsdWUucGx1cyhvcGVyYW5kLnRvUGl4ZWxzKCkpKTtcbn0pO1xuXG5NZS5wcm90b3R5cGUubWludXMgPSBWYWx1ZS5zYWZlKGZ1bmN0aW9uIG1pbnVzKG9wZXJhbmQpIHtcblx0Y2hlY2tBeGlzKHRoaXMsIG9wZXJhbmQpO1xuXHRyZXR1cm4gbmV3IE1lKHRoaXMuX2RpbWVuc2lvbiwgdGhpcy5fdmFsdWUubWludXMob3BlcmFuZC50b1BpeGVscygpKSk7XG59KTtcblxuTWUucHJvdG90eXBlLm1pZHBvaW50ID0gVmFsdWUuc2FmZShmdW5jdGlvbiBtaWRwb2ludChvcGVyYW5kKSB7XG5cdGNoZWNrQXhpcyh0aGlzLCBvcGVyYW5kKTtcblx0cmV0dXJuIG5ldyBNZSh0aGlzLl9kaW1lbnNpb24sIHRoaXMuX3ZhbHVlLmF2ZXJhZ2Uob3BlcmFuZC50b1BpeGVscygpKSk7XG59KTtcblxuTWUucHJvdG90eXBlLmNvbXBhcmUgPSBWYWx1ZS5zYWZlKGZ1bmN0aW9uIGNvbXBhcmUob3BlcmFuZCkge1xuXHRjaGVja0F4aXModGhpcywgb3BlcmFuZCk7XG5cdHJldHVybiB0aGlzLl92YWx1ZS5jb21wYXJlKG9wZXJhbmQudG9QaXhlbHMoKSk7XG59KTtcblxuTWUucHJvdG90eXBlLm1pbiA9IFZhbHVlLnNhZmUoZnVuY3Rpb24gbWluKG9wZXJhbmQpIHtcblx0Y2hlY2tBeGlzKHRoaXMsIG9wZXJhbmQpO1xuXHRyZXR1cm4gbmV3IE1lKHRoaXMuX2RpbWVuc2lvbiwgUGl4ZWxzLm1pbih0aGlzLl92YWx1ZSwgb3BlcmFuZC50b1BpeGVscygpKSk7XG59KTtcblxuTWUucHJvdG90eXBlLm1heCA9IFZhbHVlLnNhZmUoZnVuY3Rpb24gbWF4KG9wZXJhbmQpIHtcblx0Y2hlY2tBeGlzKHRoaXMsIG9wZXJhbmQpO1xuXHRyZXR1cm4gbmV3IE1lKHRoaXMuX2RpbWVuc2lvbiwgUGl4ZWxzLm1heCh0aGlzLl92YWx1ZSwgb3BlcmFuZC50b1BpeGVscygpKSk7XG59KTtcblxuTWUucHJvdG90eXBlLmRpZmYgPSBWYWx1ZS5zYWZlKGZ1bmN0aW9uIGRpZmYoZXhwZWN0ZWQpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgTWUgXSk7XG5cdGNoZWNrQXhpcyh0aGlzLCBleHBlY3RlZCk7XG5cblx0dmFyIGFjdHVhbFZhbHVlID0gdGhpcy5fdmFsdWU7XG5cdHZhciBleHBlY3RlZFZhbHVlID0gZXhwZWN0ZWQuX3ZhbHVlO1xuXG5cdGlmIChhY3R1YWxWYWx1ZS5lcXVhbHMoZXhwZWN0ZWRWYWx1ZSkpIHJldHVybiBcIlwiO1xuXHRlbHNlIGlmIChpc05vbmUoZXhwZWN0ZWQpICYmICFpc05vbmUodGhpcykpIHJldHVybiBcInJlbmRlcmVkIHdoZW4gbm90IGV4cGVjdGVkXCI7XG5cdGVsc2UgaWYgKCFpc05vbmUoZXhwZWN0ZWQpICYmIGlzTm9uZSh0aGlzKSkgcmV0dXJuIFwibm90IHJlbmRlcmVkXCI7XG5cblx0dmFyIGRpcmVjdGlvbjtcblx0dmFyIGNvbXBhcmlzb24gPSBhY3R1YWxWYWx1ZS5jb21wYXJlKGV4cGVjdGVkVmFsdWUpO1xuXHRpZiAodGhpcy5fZGltZW5zaW9uID09PSBYX0RJTUVOU0lPTikgZGlyZWN0aW9uID0gY29tcGFyaXNvbiA8IDAgPyBcImZ1cnRoZXIgbGVmdCB0aGFuIGV4cGVjdGVkXCIgOiBcImZ1cnRoZXIgcmlnaHQgdGhhbiBleHBlY3RlZFwiO1xuXHRlbHNlIGRpcmVjdGlvbiA9IGNvbXBhcmlzb24gPCAwID8gXCJoaWdoZXIgdGhhbiBleHBlY3RlZFwiIDogXCJsb3dlciB0aGFuIGV4cGVjdGVkXCI7XG5cblx0cmV0dXJuIGFjdHVhbFZhbHVlLmRpZmYoZXhwZWN0ZWRWYWx1ZSkgKyBcIiBcIiArIGRpcmVjdGlvbjtcbn0pO1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHRpZiAoaXNOb25lKHRoaXMpKSByZXR1cm4gXCJub3QgcmVuZGVyZWRcIjtcblx0ZWxzZSByZXR1cm4gdGhpcy5fdmFsdWUudG9TdHJpbmcoKTtcbn07XG5cbk1lLnByb3RvdHlwZS50b1BpeGVscyA9IGZ1bmN0aW9uIHRvUGl4ZWxzKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXHRyZXR1cm4gdGhpcy5fdmFsdWU7XG59O1xuXG5mdW5jdGlvbiBjaGVja0F4aXMoc2VsZiwgb3RoZXIpIHtcblx0aWYgKG90aGVyIGluc3RhbmNlb2YgTWUpIHtcblx0XHRlbnN1cmUudGhhdChzZWxmLl9kaW1lbnNpb24gPT09IG90aGVyLl9kaW1lbnNpb24sIFwiQ2FuJ3QgY29tcGFyZSBYIGNvb3JkaW5hdGUgdG8gWSBjb29yZGluYXRlXCIpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGlzTm9uZShwb3NpdGlvbikge1xuXHRyZXR1cm4gcG9zaXRpb24uX3ZhbHVlLmVxdWFscyhQaXhlbHMuTk9ORSk7XG59IiwiLy8gQ29weXJpZ2h0IChjKSAyMDE2LTIwMTcgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgVmFsdWUgPSByZXF1aXJlKFwiLi92YWx1ZS5qc1wiKTtcblxudmFyIFJFTkRFUkVEID0gXCJyZW5kZXJlZFwiO1xudmFyIE5PVF9SRU5ERVJFRCA9IFwibm90IHJlbmRlcmVkXCI7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gUmVuZGVyU3RhdGUoc3RhdGUpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFsgU3RyaW5nIF0pO1xuXG5cdHRoaXMuX3N0YXRlID0gc3RhdGU7XG59O1xuVmFsdWUuZXh0ZW5kKE1lKTtcblxuTWUucmVuZGVyZWQgPSBmdW5jdGlvbiByZW5kZXJlZCgpIHtcblx0cmV0dXJuIG5ldyBNZShSRU5ERVJFRCk7XG59O1xuXG5NZS5ub3RSZW5kZXJlZCA9IGZ1bmN0aW9uIG5vdFJlbmRlcmVkKCkge1xuXHRyZXR1cm4gbmV3IE1lKE5PVF9SRU5ERVJFRCk7XG59O1xuXG5NZS5wcm90b3R5cGUuY29tcGF0aWJpbGl0eSA9IGZ1bmN0aW9uIGNvbXBhdGliaWxpdHkoKSB7XG5cdHJldHVybiBbIE1lIF07XG59O1xuXG5NZS5wcm90b3R5cGUuZGlmZiA9IFZhbHVlLnNhZmUoZnVuY3Rpb24gZGlmZihleHBlY3RlZCkge1xuXHR2YXIgdGhpc1N0YXRlID0gdGhpcy5fc3RhdGU7XG5cdHZhciBleHBlY3RlZFN0YXRlID0gZXhwZWN0ZWQuX3N0YXRlO1xuXG5cdGlmICh0aGlzU3RhdGUgPT09IGV4cGVjdGVkU3RhdGUpIHJldHVybiBcIlwiO1xuXHRlbHNlIHJldHVybiBcImRpZmZlcmVudCB0aGFuIGV4cGVjdGVkXCI7XG59KTtcblxuTWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG5cdHJldHVybiB0aGlzLl9zdGF0ZTtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgVmFsdWUgPSByZXF1aXJlKFwiLi92YWx1ZS5qc1wiKTtcbnZhciBQaXhlbHMgPSByZXF1aXJlKFwiLi9waXhlbHMuanNcIik7XG5cbnZhciBNZSA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gU2l6ZSh2YWx1ZSkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgWyBbTnVtYmVyLCBQaXhlbHNdIF0pO1xuXG5cdHRoaXMuX3ZhbHVlID0gKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikgPyBQaXhlbHMuY3JlYXRlKHZhbHVlKSA6IHZhbHVlO1xufTtcblZhbHVlLmV4dGVuZChNZSk7XG5cbk1lLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSh2YWx1ZSkge1xuXHRyZXR1cm4gbmV3IE1lKHZhbHVlKTtcbn07XG5cbk1lLmNyZWF0ZU5vbmUgPSBmdW5jdGlvbiBjcmVhdGVOb25lKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXG5cdHJldHVybiBuZXcgTWUoUGl4ZWxzLk5PTkUpO1xufTtcblxuTWUucHJvdG90eXBlLmNvbXBhdGliaWxpdHkgPSBmdW5jdGlvbiBjb21wYXRpYmlsaXR5KCkge1xuXHRyZXR1cm4gWyBNZSBdO1xufTtcblxuTWUucHJvdG90eXBlLnBsdXMgPSBWYWx1ZS5zYWZlKGZ1bmN0aW9uIHBsdXMob3BlcmFuZCkge1xuXHRyZXR1cm4gbmV3IE1lKHRoaXMuX3ZhbHVlLnBsdXMob3BlcmFuZC5fdmFsdWUpKTtcbn0pO1xuXG5NZS5wcm90b3R5cGUubWludXMgPSBWYWx1ZS5zYWZlKGZ1bmN0aW9uIG1pbnVzKG9wZXJhbmQpIHtcblx0cmV0dXJuIG5ldyBNZSh0aGlzLl92YWx1ZS5taW51cyhvcGVyYW5kLl92YWx1ZSkpO1xufSk7XG5cbk1lLnByb3RvdHlwZS50aW1lcyA9IGZ1bmN0aW9uIHRpbWVzKG9wZXJhbmQpIHtcblx0cmV0dXJuIG5ldyBNZSh0aGlzLl92YWx1ZS50aW1lcyhvcGVyYW5kKSk7XG59O1xuXG5NZS5wcm90b3R5cGUuY29tcGFyZSA9IFZhbHVlLnNhZmUoZnVuY3Rpb24gY29tcGFyZSh0aGF0KSB7XG5cdHJldHVybiB0aGlzLl92YWx1ZS5jb21wYXJlKHRoYXQuX3ZhbHVlKTtcbn0pO1xuXG5NZS5wcm90b3R5cGUuZGlmZiA9IFZhbHVlLnNhZmUoZnVuY3Rpb24gZGlmZihleHBlY3RlZCkge1xuXHR2YXIgYWN0dWFsVmFsdWUgPSB0aGlzLl92YWx1ZTtcblx0dmFyIGV4cGVjdGVkVmFsdWUgPSBleHBlY3RlZC5fdmFsdWU7XG5cblx0aWYgKGFjdHVhbFZhbHVlLmVxdWFscyhleHBlY3RlZFZhbHVlKSkgcmV0dXJuIFwiXCI7XG5cdGlmIChpc05vbmUoZXhwZWN0ZWQpICYmICFpc05vbmUodGhpcykpIHJldHVybiBcInJlbmRlcmVkIHdoZW4gbm90IGV4cGVjdGVkXCI7XG5cdGlmICghaXNOb25lKGV4cGVjdGVkKSAmJiBpc05vbmUodGhpcykpIHJldHVybiBcIm5vdCByZW5kZXJlZFwiO1xuXG5cdHZhciBkZXNjID0gYWN0dWFsVmFsdWUuY29tcGFyZShleHBlY3RlZFZhbHVlKSA+IDAgPyBcIiBsYXJnZXIgdGhhbiBleHBlY3RlZFwiIDogXCIgc21hbGxlciB0aGFuIGV4cGVjdGVkXCI7XG5cdHJldHVybiBhY3R1YWxWYWx1ZS5kaWZmKGV4cGVjdGVkVmFsdWUpICsgZGVzYztcbn0pO1xuXG5NZS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcblx0ZW5zdXJlLnNpZ25hdHVyZShhcmd1bWVudHMsIFtdKTtcblxuXHRpZiAoaXNOb25lKHRoaXMpKSByZXR1cm4gXCJub3QgcmVuZGVyZWRcIjtcblx0ZWxzZSByZXR1cm4gdGhpcy5fdmFsdWUudG9TdHJpbmcoKTtcbn07XG5cbk1lLnByb3RvdHlwZS50b1BpeGVscyA9IGZ1bmN0aW9uIHRvUGl4ZWxzKCkge1xuXHRlbnN1cmUuc2lnbmF0dXJlKGFyZ3VtZW50cywgW10pO1xuXHRyZXR1cm4gdGhpcy5fdmFsdWU7XG59O1xuXG5mdW5jdGlvbiBpc05vbmUoc2l6ZSkge1xuXHRyZXR1cm4gc2l6ZS5fdmFsdWUuZXF1YWxzKFBpeGVscy5OT05FKTtcbn0iLCIvLyBDb3B5cmlnaHQgKGMpIDIwMTQgVGl0YW5pdW0gSS5ULiBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIEZvciBsaWNlbnNlLCBzZWUgXCJSRUFETUVcIiBvciBcIkxJQ0VOU0VcIiBmaWxlLlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBlbnN1cmUgPSByZXF1aXJlKFwiLi4vdXRpbC9lbnN1cmUuanNcIik7XG52YXIgb29wID0gcmVxdWlyZShcIi4uL3V0aWwvb29wLmpzXCIpO1xudmFyIHNoaW0gPSByZXF1aXJlKFwiLi4vdXRpbC9zaGltLmpzXCIpO1xuXG52YXIgTWUgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFZhbHVlKCkge307XG5NZS5leHRlbmQgPSBvb3AuZXh0ZW5kRm4oTWUpO1xub29wLm1ha2VBYnN0cmFjdChNZSwgW1xuXHRcImNvbXBhdGliaWxpdHlcIixcblx0XCJkaWZmXCIsXG5cdFwidG9TdHJpbmdcIlxuXSk7XG5cbk1lLnNhZmUgPSBmdW5jdGlvbiBzYWZlKGZuKSB7XG5cdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRlbnN1cmVDb21wYXRpYmlsaXR5KHRoaXMsIHRoaXMuY29tcGF0aWJpbGl0eSgpLCBhcmd1bWVudHMpO1xuXHRcdHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXHR9O1xufTtcblxuTWUucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24gdmFsdWUoKSB7XG5cdGVuc3VyZS5zaWduYXR1cmUoYXJndW1lbnRzLCBbXSk7XG5cdHJldHVybiB0aGlzO1xufTtcblxuTWUucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIGVxdWFscyh0aGF0KSB7XG5cdHJldHVybiB0aGlzLmRpZmYodGhhdCkgPT09IFwiXCI7XG59O1xuXG5mdW5jdGlvbiBlbnN1cmVDb21wYXRpYmlsaXR5KHNlbGYsIGNvbXBhdGlibGUsIGFyZ3MpIHtcblx0dmFyIGFyZztcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7ICAgLy8gYXJncyBpcyBub3QgYW4gQXJyYXksIGNhbid0IHVzZSBmb3JFYWNoXG5cdFx0YXJnID0gYXJnc1tpXTtcblx0XHRjaGVja09uZUFyZyhzZWxmLCBjb21wYXRpYmxlLCBhcmcpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGNoZWNrT25lQXJnKHNlbGYsIGNvbXBhdGlibGUsIGFyZykge1xuXHR2YXIgdHlwZSA9IHR5cGVvZiBhcmc7XG5cdGlmIChhcmcgPT09IG51bGwpIHR5cGUgPSBcIm51bGxcIjtcblx0aWYgKHR5cGUgIT09IFwib2JqZWN0XCIpIHRocm93RXJyb3IodHlwZSk7XG5cblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBjb21wYXRpYmxlLmxlbmd0aDsgaSsrKSB7XG5cdFx0aWYgKGFyZyBpbnN0YW5jZW9mIGNvbXBhdGlibGVbaV0pIHJldHVybjtcblx0fVxuXHR0aHJvd0Vycm9yKG9vcC5pbnN0YW5jZU5hbWUoYXJnKSk7XG5cblx0ZnVuY3Rpb24gdGhyb3dFcnJvcih0eXBlKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKG9vcC5pbnN0YW5jZU5hbWUoc2VsZikgKyBcIiBpc24ndCBjb21wYXRpYmxlIHdpdGggXCIgKyB0eXBlKTtcblx0fVxufSIsIi8qIVxuICogYXN5bmNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9jYW9sYW4vYXN5bmNcbiAqXG4gKiBDb3B5cmlnaHQgMjAxMC0yMDE0IENhb2xhbiBNY01haG9uXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqL1xuKGZ1bmN0aW9uICgpIHtcblxuICAgIHZhciBhc3luYyA9IHt9O1xuICAgIGZ1bmN0aW9uIG5vb3AoKSB7fVxuICAgIGZ1bmN0aW9uIGlkZW50aXR5KHYpIHtcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRvQm9vbCh2KSB7XG4gICAgICAgIHJldHVybiAhIXY7XG4gICAgfVxuICAgIGZ1bmN0aW9uIG5vdElkKHYpIHtcbiAgICAgICAgcmV0dXJuICF2O1xuICAgIH1cblxuICAgIC8vIGdsb2JhbCBvbiB0aGUgc2VydmVyLCB3aW5kb3cgaW4gdGhlIGJyb3dzZXJcbiAgICB2YXIgcHJldmlvdXNfYXN5bmM7XG5cbiAgICAvLyBFc3RhYmxpc2ggdGhlIHJvb3Qgb2JqZWN0LCBgd2luZG93YCAoYHNlbGZgKSBpbiB0aGUgYnJvd3NlciwgYGdsb2JhbGBcbiAgICAvLyBvbiB0aGUgc2VydmVyLCBvciBgdGhpc2AgaW4gc29tZSB2aXJ0dWFsIG1hY2hpbmVzLiBXZSB1c2UgYHNlbGZgXG4gICAgLy8gaW5zdGVhZCBvZiBgd2luZG93YCBmb3IgYFdlYldvcmtlcmAgc3VwcG9ydC5cbiAgICB2YXIgcm9vdCA9IHR5cGVvZiBzZWxmID09PSAnb2JqZWN0JyAmJiBzZWxmLnNlbGYgPT09IHNlbGYgJiYgc2VsZiB8fFxuICAgICAgICAgICAgdHlwZW9mIGdsb2JhbCA9PT0gJ29iamVjdCcgJiYgZ2xvYmFsLmdsb2JhbCA9PT0gZ2xvYmFsICYmIGdsb2JhbCB8fFxuICAgICAgICAgICAgdGhpcztcblxuICAgIGlmIChyb290ICE9IG51bGwpIHtcbiAgICAgICAgcHJldmlvdXNfYXN5bmMgPSByb290LmFzeW5jO1xuICAgIH1cblxuICAgIGFzeW5jLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJvb3QuYXN5bmMgPSBwcmV2aW91c19hc3luYztcbiAgICAgICAgcmV0dXJuIGFzeW5jO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBvbmx5X29uY2UoZm4pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKGZuID09PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsYmFjayB3YXMgYWxyZWFkeSBjYWxsZWQuXCIpO1xuICAgICAgICAgICAgZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGZuID0gbnVsbDtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfb25jZShmbikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAoZm4gPT09IG51bGwpIHJldHVybjtcbiAgICAgICAgICAgIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICBmbiA9IG51bGw7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8vLyBjcm9zcy1icm93c2VyIGNvbXBhdGlibGl0eSBmdW5jdGlvbnMgLy8vL1xuXG4gICAgdmFyIF90b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICB2YXIgX2lzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgcmV0dXJuIF90b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEFycmF5XSc7XG4gICAgfTtcblxuICAgIC8vIFBvcnRlZCBmcm9tIHVuZGVyc2NvcmUuanMgaXNPYmplY3RcbiAgICB2YXIgX2lzT2JqZWN0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIG9iajtcbiAgICAgICAgcmV0dXJuIHR5cGUgPT09ICdmdW5jdGlvbicgfHwgdHlwZSA9PT0gJ29iamVjdCcgJiYgISFvYmo7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIF9pc0FycmF5TGlrZShhcnIpIHtcbiAgICAgICAgcmV0dXJuIF9pc0FycmF5KGFycikgfHwgKFxuICAgICAgICAgICAgLy8gaGFzIGEgcG9zaXRpdmUgaW50ZWdlciBsZW5ndGggcHJvcGVydHlcbiAgICAgICAgICAgIHR5cGVvZiBhcnIubGVuZ3RoID09PSBcIm51bWJlclwiICYmXG4gICAgICAgICAgICBhcnIubGVuZ3RoID49IDAgJiZcbiAgICAgICAgICAgIGFyci5sZW5ndGggJSAxID09PSAwXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gX2VhY2goY29sbCwgaXRlcmF0b3IpIHtcbiAgICAgICAgcmV0dXJuIF9pc0FycmF5TGlrZShjb2xsKSA/XG4gICAgICAgICAgICBfYXJyYXlFYWNoKGNvbGwsIGl0ZXJhdG9yKSA6XG4gICAgICAgICAgICBfZm9yRWFjaE9mKGNvbGwsIGl0ZXJhdG9yKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfYXJyYXlFYWNoKGFyciwgaXRlcmF0b3IpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZW5ndGggPSBhcnIubGVuZ3RoO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpdGVyYXRvcihhcnJbaW5kZXhdLCBpbmRleCwgYXJyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIF9tYXAoYXJyLCBpdGVyYXRvcikge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IGFyci5sZW5ndGgsXG4gICAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0b3IoYXJyW2luZGV4XSwgaW5kZXgsIGFycik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfcmFuZ2UoY291bnQpIHtcbiAgICAgICAgcmV0dXJuIF9tYXAoQXJyYXkoY291bnQpLCBmdW5jdGlvbiAodiwgaSkgeyByZXR1cm4gaTsgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gX3JlZHVjZShhcnIsIGl0ZXJhdG9yLCBtZW1vKSB7XG4gICAgICAgIF9hcnJheUVhY2goYXJyLCBmdW5jdGlvbiAoeCwgaSwgYSkge1xuICAgICAgICAgICAgbWVtbyA9IGl0ZXJhdG9yKG1lbW8sIHgsIGksIGEpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG1lbW87XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gX2ZvckVhY2hPZihvYmplY3QsIGl0ZXJhdG9yKSB7XG4gICAgICAgIF9hcnJheUVhY2goX2tleXMob2JqZWN0KSwgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgaXRlcmF0b3Iob2JqZWN0W2tleV0sIGtleSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIF9pbmRleE9mKGFyciwgaXRlbSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGFycltpXSA9PT0gaXRlbSkgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIHZhciBfa2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgdmFyIGtleXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgayBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoaykpIHtcbiAgICAgICAgICAgICAgICBrZXlzLnB1c2goayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtleXM7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIF9rZXlJdGVyYXRvcihjb2xsKSB7XG4gICAgICAgIHZhciBpID0gLTE7XG4gICAgICAgIHZhciBsZW47XG4gICAgICAgIHZhciBrZXlzO1xuICAgICAgICBpZiAoX2lzQXJyYXlMaWtlKGNvbGwpKSB7XG4gICAgICAgICAgICBsZW4gPSBjb2xsLmxlbmd0aDtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgICAgICByZXR1cm4gaSA8IGxlbiA/IGkgOiBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGtleXMgPSBfa2V5cyhjb2xsKTtcbiAgICAgICAgICAgIGxlbiA9IGtleXMubGVuZ3RoO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5leHQoKSB7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgICAgIHJldHVybiBpIDwgbGVuID8ga2V5c1tpXSA6IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2ltaWxhciB0byBFUzYncyByZXN0IHBhcmFtIChodHRwOi8vYXJpeWEub2ZpbGFicy5jb20vMjAxMy8wMy9lczYtYW5kLXJlc3QtcGFyYW1ldGVyLmh0bWwpXG4gICAgLy8gVGhpcyBhY2N1bXVsYXRlcyB0aGUgYXJndW1lbnRzIHBhc3NlZCBpbnRvIGFuIGFycmF5LCBhZnRlciBhIGdpdmVuIGluZGV4LlxuICAgIC8vIEZyb20gdW5kZXJzY29yZS5qcyAoaHR0cHM6Ly9naXRodWIuY29tL2phc2hrZW5hcy91bmRlcnNjb3JlL3B1bGwvMjE0MCkuXG4gICAgZnVuY3Rpb24gX3Jlc3RQYXJhbShmdW5jLCBzdGFydEluZGV4KSB7XG4gICAgICAgIHN0YXJ0SW5kZXggPSBzdGFydEluZGV4ID09IG51bGwgPyBmdW5jLmxlbmd0aCAtIDEgOiArc3RhcnRJbmRleDtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGxlbmd0aCA9IE1hdGgubWF4KGFyZ3VtZW50cy5sZW5ndGggLSBzdGFydEluZGV4LCAwKTtcbiAgICAgICAgICAgIHZhciByZXN0ID0gQXJyYXkobGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgICAgICByZXN0W2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleCArIHN0YXJ0SW5kZXhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3dpdGNoIChzdGFydEluZGV4KSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gZnVuYy5jYWxsKHRoaXMsIHJlc3QpO1xuICAgICAgICAgICAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmMuY2FsbCh0aGlzLCBhcmd1bWVudHNbMF0sIHJlc3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ3VycmVudGx5IHVudXNlZCBidXQgaGFuZGxlIGNhc2VzIG91dHNpZGUgb2YgdGhlIHN3aXRjaCBzdGF0ZW1lbnQ6XG4gICAgICAgICAgICAvLyB2YXIgYXJncyA9IEFycmF5KHN0YXJ0SW5kZXggKyAxKTtcbiAgICAgICAgICAgIC8vIGZvciAoaW5kZXggPSAwOyBpbmRleCA8IHN0YXJ0SW5kZXg7IGluZGV4KyspIHtcbiAgICAgICAgICAgIC8vICAgICBhcmdzW2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAvLyBhcmdzW3N0YXJ0SW5kZXhdID0gcmVzdDtcbiAgICAgICAgICAgIC8vIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIF93aXRob3V0SW5kZXgoaXRlcmF0b3IpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgaW5kZXgsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlcmF0b3IodmFsdWUsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLy8vIGV4cG9ydGVkIGFzeW5jIG1vZHVsZSBmdW5jdGlvbnMgLy8vL1xuXG4gICAgLy8vLyBuZXh0VGljayBpbXBsZW1lbnRhdGlvbiB3aXRoIGJyb3dzZXItY29tcGF0aWJsZSBmYWxsYmFjayAvLy8vXG5cbiAgICAvLyBjYXB0dXJlIHRoZSBnbG9iYWwgcmVmZXJlbmNlIHRvIGd1YXJkIGFnYWluc3QgZmFrZVRpbWVyIG1vY2tzXG4gICAgdmFyIF9zZXRJbW1lZGlhdGUgPSB0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSAnZnVuY3Rpb24nICYmIHNldEltbWVkaWF0ZTtcblxuICAgIHZhciBfZGVsYXkgPSBfc2V0SW1tZWRpYXRlID8gZnVuY3Rpb24oZm4pIHtcbiAgICAgICAgLy8gbm90IGEgZGlyZWN0IGFsaWFzIGZvciBJRTEwIGNvbXBhdGliaWxpdHlcbiAgICAgICAgX3NldEltbWVkaWF0ZShmbik7XG4gICAgfSA6IGZ1bmN0aW9uKGZuKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgIH07XG5cbiAgICBpZiAodHlwZW9mIHByb2Nlc3MgPT09ICdvYmplY3QnICYmIHR5cGVvZiBwcm9jZXNzLm5leHRUaWNrID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGFzeW5jLm5leHRUaWNrID0gcHJvY2Vzcy5uZXh0VGljaztcbiAgICB9IGVsc2Uge1xuICAgICAgICBhc3luYy5uZXh0VGljayA9IF9kZWxheTtcbiAgICB9XG4gICAgYXN5bmMuc2V0SW1tZWRpYXRlID0gX3NldEltbWVkaWF0ZSA/IF9kZWxheSA6IGFzeW5jLm5leHRUaWNrO1xuXG5cbiAgICBhc3luYy5mb3JFYWNoID1cbiAgICBhc3luYy5lYWNoID0gZnVuY3Rpb24gKGFyciwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBhc3luYy5lYWNoT2YoYXJyLCBfd2l0aG91dEluZGV4KGl0ZXJhdG9yKSwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBhc3luYy5mb3JFYWNoU2VyaWVzID1cbiAgICBhc3luYy5lYWNoU2VyaWVzID0gZnVuY3Rpb24gKGFyciwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBhc3luYy5lYWNoT2ZTZXJpZXMoYXJyLCBfd2l0aG91dEluZGV4KGl0ZXJhdG9yKSwgY2FsbGJhY2spO1xuICAgIH07XG5cblxuICAgIGFzeW5jLmZvckVhY2hMaW1pdCA9XG4gICAgYXN5bmMuZWFjaExpbWl0ID0gZnVuY3Rpb24gKGFyciwgbGltaXQsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gX2VhY2hPZkxpbWl0KGxpbWl0KShhcnIsIF93aXRob3V0SW5kZXgoaXRlcmF0b3IpLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIGFzeW5jLmZvckVhY2hPZiA9XG4gICAgYXN5bmMuZWFjaE9mID0gZnVuY3Rpb24gKG9iamVjdCwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gX29uY2UoY2FsbGJhY2sgfHwgbm9vcCk7XG4gICAgICAgIG9iamVjdCA9IG9iamVjdCB8fCBbXTtcbiAgICAgICAgdmFyIHNpemUgPSBfaXNBcnJheUxpa2Uob2JqZWN0KSA/IG9iamVjdC5sZW5ndGggOiBfa2V5cyhvYmplY3QpLmxlbmd0aDtcbiAgICAgICAgdmFyIGNvbXBsZXRlZCA9IDA7XG4gICAgICAgIGlmICghc2l6ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIF9lYWNoKG9iamVjdCwgZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKG9iamVjdFtrZXldLCBrZXksIG9ubHlfb25jZShkb25lKSk7XG4gICAgICAgIH0pO1xuICAgICAgICBmdW5jdGlvbiBkb25lKGVycikge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb21wbGV0ZWQgKz0gMTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGxldGVkID49IHNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGFzeW5jLmZvckVhY2hPZlNlcmllcyA9XG4gICAgYXN5bmMuZWFjaE9mU2VyaWVzID0gZnVuY3Rpb24gKG9iaiwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gX29uY2UoY2FsbGJhY2sgfHwgbm9vcCk7XG4gICAgICAgIG9iaiA9IG9iaiB8fCBbXTtcbiAgICAgICAgdmFyIG5leHRLZXkgPSBfa2V5SXRlcmF0b3Iob2JqKTtcbiAgICAgICAgdmFyIGtleSA9IG5leHRLZXkoKTtcbiAgICAgICAgZnVuY3Rpb24gaXRlcmF0ZSgpIHtcbiAgICAgICAgICAgIHZhciBzeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChrZXkgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpdGVyYXRvcihvYmpba2V5XSwga2V5LCBvbmx5X29uY2UoZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IG5leHRLZXkoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3luYy5zZXRJbW1lZGlhdGUoaXRlcmF0ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIHN5bmMgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpdGVyYXRlKCk7XG4gICAgfTtcblxuXG5cbiAgICBhc3luYy5mb3JFYWNoT2ZMaW1pdCA9XG4gICAgYXN5bmMuZWFjaE9mTGltaXQgPSBmdW5jdGlvbiAob2JqLCBsaW1pdCwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIF9lYWNoT2ZMaW1pdChsaW1pdCkob2JqLCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBfZWFjaE9mTGltaXQobGltaXQpIHtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG9iaiwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayA9IF9vbmNlKGNhbGxiYWNrIHx8IG5vb3ApO1xuICAgICAgICAgICAgb2JqID0gb2JqIHx8IFtdO1xuICAgICAgICAgICAgdmFyIG5leHRLZXkgPSBfa2V5SXRlcmF0b3Iob2JqKTtcbiAgICAgICAgICAgIGlmIChsaW1pdCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHZhciBydW5uaW5nID0gMDtcbiAgICAgICAgICAgIHZhciBlcnJvcmVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIChmdW5jdGlvbiByZXBsZW5pc2ggKCkge1xuICAgICAgICAgICAgICAgIGlmIChkb25lICYmIHJ1bm5pbmcgPD0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgd2hpbGUgKHJ1bm5pbmcgPCBsaW1pdCAmJiAhZXJyb3JlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0gbmV4dEtleSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChydW5uaW5nIDw9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBydW5uaW5nICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIGl0ZXJhdG9yKG9ialtrZXldLCBrZXksIG9ubHlfb25jZShmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBydW5uaW5nIC09IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxlbmlzaCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfTtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIGRvUGFyYWxsZWwoZm4pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChvYmosIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIGZuKGFzeW5jLmVhY2hPZiwgb2JqLCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBkb1BhcmFsbGVsTGltaXQoZm4pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChvYmosIGxpbWl0LCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJldHVybiBmbihfZWFjaE9mTGltaXQobGltaXQpLCBvYmosIGl0ZXJhdG9yLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRvU2VyaWVzKGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAob2JqLCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJldHVybiBmbihhc3luYy5lYWNoT2ZTZXJpZXMsIG9iaiwgaXRlcmF0b3IsIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfYXN5bmNNYXAoZWFjaGZuLCBhcnIsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayA9IF9vbmNlKGNhbGxiYWNrIHx8IG5vb3ApO1xuICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICBlYWNoZm4oYXJyLCBmdW5jdGlvbiAodmFsdWUsIGluZGV4LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaXRlcmF0b3IodmFsdWUsIGZ1bmN0aW9uIChlcnIsIHYpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRzW2luZGV4XSA9IHY7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYy5tYXAgPSBkb1BhcmFsbGVsKF9hc3luY01hcCk7XG4gICAgYXN5bmMubWFwU2VyaWVzID0gZG9TZXJpZXMoX2FzeW5jTWFwKTtcbiAgICBhc3luYy5tYXBMaW1pdCA9IGRvUGFyYWxsZWxMaW1pdChfYXN5bmNNYXApO1xuXG4gICAgLy8gcmVkdWNlIG9ubHkgaGFzIGEgc2VyaWVzIHZlcnNpb24sIGFzIGRvaW5nIHJlZHVjZSBpbiBwYXJhbGxlbCB3b24ndFxuICAgIC8vIHdvcmsgaW4gbWFueSBzaXR1YXRpb25zLlxuICAgIGFzeW5jLmluamVjdCA9XG4gICAgYXN5bmMuZm9sZGwgPVxuICAgIGFzeW5jLnJlZHVjZSA9IGZ1bmN0aW9uIChhcnIsIG1lbW8sIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICBhc3luYy5lYWNoT2ZTZXJpZXMoYXJyLCBmdW5jdGlvbiAoeCwgaSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKG1lbW8sIHgsIGZ1bmN0aW9uIChlcnIsIHYpIHtcbiAgICAgICAgICAgICAgICBtZW1vID0gdjtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGVyciB8fCBudWxsLCBtZW1vKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGFzeW5jLmZvbGRyID1cbiAgICBhc3luYy5yZWR1Y2VSaWdodCA9IGZ1bmN0aW9uIChhcnIsIG1lbW8sIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgcmV2ZXJzZWQgPSBfbWFwKGFyciwgaWRlbnRpdHkpLnJldmVyc2UoKTtcbiAgICAgICAgYXN5bmMucmVkdWNlKHJldmVyc2VkLCBtZW1vLCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBfZmlsdGVyKGVhY2hmbiwgYXJyLCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgZWFjaGZuKGFyciwgZnVuY3Rpb24gKHgsIGluZGV4LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaXRlcmF0b3IoeCwgZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICBpZiAodikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goe2luZGV4OiBpbmRleCwgdmFsdWU6IHh9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhfbWFwKHJlc3VsdHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhLmluZGV4IC0gYi5pbmRleDtcbiAgICAgICAgICAgIH0pLCBmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4LnZhbHVlO1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYy5zZWxlY3QgPVxuICAgIGFzeW5jLmZpbHRlciA9IGRvUGFyYWxsZWwoX2ZpbHRlcik7XG5cbiAgICBhc3luYy5zZWxlY3RMaW1pdCA9XG4gICAgYXN5bmMuZmlsdGVyTGltaXQgPSBkb1BhcmFsbGVsTGltaXQoX2ZpbHRlcik7XG5cbiAgICBhc3luYy5zZWxlY3RTZXJpZXMgPVxuICAgIGFzeW5jLmZpbHRlclNlcmllcyA9IGRvU2VyaWVzKF9maWx0ZXIpO1xuXG4gICAgZnVuY3Rpb24gX3JlamVjdChlYWNoZm4sIGFyciwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIF9maWx0ZXIoZWFjaGZuLCBhcnIsIGZ1bmN0aW9uKHZhbHVlLCBjYikge1xuICAgICAgICAgICAgaXRlcmF0b3IodmFsdWUsIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICBjYighdik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgY2FsbGJhY2spO1xuICAgIH1cbiAgICBhc3luYy5yZWplY3QgPSBkb1BhcmFsbGVsKF9yZWplY3QpO1xuICAgIGFzeW5jLnJlamVjdExpbWl0ID0gZG9QYXJhbGxlbExpbWl0KF9yZWplY3QpO1xuICAgIGFzeW5jLnJlamVjdFNlcmllcyA9IGRvU2VyaWVzKF9yZWplY3QpO1xuXG4gICAgZnVuY3Rpb24gX2NyZWF0ZVRlc3RlcihlYWNoZm4sIGNoZWNrLCBnZXRSZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFyciwgbGltaXQsIGl0ZXJhdG9yLCBjYikge1xuICAgICAgICAgICAgZnVuY3Rpb24gZG9uZSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoY2IpIGNiKGdldFJlc3VsdChmYWxzZSwgdm9pZCAwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdW5jdGlvbiBpdGVyYXRlZSh4LCBfLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmICghY2IpIHJldHVybiBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIGl0ZXJhdG9yKHgsIGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYiAmJiBjaGVjayh2KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2IoZ2V0UmVzdWx0KHRydWUsIHgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNiID0gaXRlcmF0b3IgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAzKSB7XG4gICAgICAgICAgICAgICAgZWFjaGZuKGFyciwgbGltaXQsIGl0ZXJhdGVlLCBkb25lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2IgPSBpdGVyYXRvcjtcbiAgICAgICAgICAgICAgICBpdGVyYXRvciA9IGxpbWl0O1xuICAgICAgICAgICAgICAgIGVhY2hmbihhcnIsIGl0ZXJhdGVlLCBkb25lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBhc3luYy5hbnkgPVxuICAgIGFzeW5jLnNvbWUgPSBfY3JlYXRlVGVzdGVyKGFzeW5jLmVhY2hPZiwgdG9Cb29sLCBpZGVudGl0eSk7XG5cbiAgICBhc3luYy5zb21lTGltaXQgPSBfY3JlYXRlVGVzdGVyKGFzeW5jLmVhY2hPZkxpbWl0LCB0b0Jvb2wsIGlkZW50aXR5KTtcblxuICAgIGFzeW5jLmFsbCA9XG4gICAgYXN5bmMuZXZlcnkgPSBfY3JlYXRlVGVzdGVyKGFzeW5jLmVhY2hPZiwgbm90SWQsIG5vdElkKTtcblxuICAgIGFzeW5jLmV2ZXJ5TGltaXQgPSBfY3JlYXRlVGVzdGVyKGFzeW5jLmVhY2hPZkxpbWl0LCBub3RJZCwgbm90SWQpO1xuXG4gICAgZnVuY3Rpb24gX2ZpbmRHZXRSZXN1bHQodiwgeCkge1xuICAgICAgICByZXR1cm4geDtcbiAgICB9XG4gICAgYXN5bmMuZGV0ZWN0ID0gX2NyZWF0ZVRlc3Rlcihhc3luYy5lYWNoT2YsIGlkZW50aXR5LCBfZmluZEdldFJlc3VsdCk7XG4gICAgYXN5bmMuZGV0ZWN0U2VyaWVzID0gX2NyZWF0ZVRlc3Rlcihhc3luYy5lYWNoT2ZTZXJpZXMsIGlkZW50aXR5LCBfZmluZEdldFJlc3VsdCk7XG4gICAgYXN5bmMuZGV0ZWN0TGltaXQgPSBfY3JlYXRlVGVzdGVyKGFzeW5jLmVhY2hPZkxpbWl0LCBpZGVudGl0eSwgX2ZpbmRHZXRSZXN1bHQpO1xuXG4gICAgYXN5bmMuc29ydEJ5ID0gZnVuY3Rpb24gKGFyciwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGFzeW5jLm1hcChhcnIsIGZ1bmN0aW9uICh4LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaXRlcmF0b3IoeCwgZnVuY3Rpb24gKGVyciwgY3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCB7dmFsdWU6IHgsIGNyaXRlcmlhOiBjcml0ZXJpYX0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCBfbWFwKHJlc3VsdHMuc29ydChjb21wYXJhdG9yKSwgZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHgudmFsdWU7XG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZ1bmN0aW9uIGNvbXBhcmF0b3IobGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgIHZhciBhID0gbGVmdC5jcml0ZXJpYSwgYiA9IHJpZ2h0LmNyaXRlcmlhO1xuICAgICAgICAgICAgcmV0dXJuIGEgPCBiID8gLTEgOiBhID4gYiA/IDEgOiAwO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGFzeW5jLmF1dG8gPSBmdW5jdGlvbiAodGFza3MsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gX29uY2UoY2FsbGJhY2sgfHwgbm9vcCk7XG4gICAgICAgIHZhciBrZXlzID0gX2tleXModGFza3MpO1xuICAgICAgICB2YXIgcmVtYWluaW5nVGFza3MgPSBrZXlzLmxlbmd0aDtcbiAgICAgICAgaWYgKCFyZW1haW5pbmdUYXNrcykge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlc3VsdHMgPSB7fTtcblxuICAgICAgICB2YXIgbGlzdGVuZXJzID0gW107XG4gICAgICAgIGZ1bmN0aW9uIGFkZExpc3RlbmVyKGZuKSB7XG4gICAgICAgICAgICBsaXN0ZW5lcnMudW5zaGlmdChmbik7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZm4pIHtcbiAgICAgICAgICAgIHZhciBpZHggPSBfaW5kZXhPZihsaXN0ZW5lcnMsIGZuKTtcbiAgICAgICAgICAgIGlmIChpZHggPj0gMCkgbGlzdGVuZXJzLnNwbGljZShpZHgsIDEpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHRhc2tDb21wbGV0ZSgpIHtcbiAgICAgICAgICAgIHJlbWFpbmluZ1Rhc2tzLS07XG4gICAgICAgICAgICBfYXJyYXlFYWNoKGxpc3RlbmVycy5zbGljZSgwKSwgZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYWRkTGlzdGVuZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCFyZW1haW5pbmdUYXNrcykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3VsdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBfYXJyYXlFYWNoKGtleXMsIGZ1bmN0aW9uIChrKSB7XG4gICAgICAgICAgICB2YXIgdGFzayA9IF9pc0FycmF5KHRhc2tzW2tdKSA/IHRhc2tzW2tdOiBbdGFza3Nba11dO1xuICAgICAgICAgICAgdmFyIHRhc2tDYWxsYmFjayA9IF9yZXN0UGFyYW0oZnVuY3Rpb24oZXJyLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoIDw9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgYXJncyA9IGFyZ3NbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNhZmVSZXN1bHRzID0ge307XG4gICAgICAgICAgICAgICAgICAgIF9mb3JFYWNoT2YocmVzdWx0cywgZnVuY3Rpb24odmFsLCBya2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzYWZlUmVzdWx0c1tya2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHNhZmVSZXN1bHRzW2tdID0gYXJncztcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyLCBzYWZlUmVzdWx0cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRzW2tdID0gYXJncztcbiAgICAgICAgICAgICAgICAgICAgYXN5bmMuc2V0SW1tZWRpYXRlKHRhc2tDb21wbGV0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgcmVxdWlyZXMgPSB0YXNrLnNsaWNlKDAsIHRhc2subGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAvLyBwcmV2ZW50IGRlYWQtbG9ja3NcbiAgICAgICAgICAgIHZhciBsZW4gPSByZXF1aXJlcy5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgZGVwO1xuICAgICAgICAgICAgd2hpbGUgKGxlbi0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEoZGVwID0gdGFza3NbcmVxdWlyZXNbbGVuXV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSGFzIGluZXhpc3RhbnQgZGVwZW5kZW5jeScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX2lzQXJyYXkoZGVwKSAmJiBfaW5kZXhPZihkZXAsIGspID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIYXMgY3ljbGljIGRlcGVuZGVuY2llcycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlYWR5KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfcmVkdWNlKHJlcXVpcmVzLCBmdW5jdGlvbiAoYSwgeCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGEgJiYgcmVzdWx0cy5oYXNPd25Qcm9wZXJ0eSh4KSk7XG4gICAgICAgICAgICAgICAgfSwgdHJ1ZSkgJiYgIXJlc3VsdHMuaGFzT3duUHJvcGVydHkoayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVhZHkoKSkge1xuICAgICAgICAgICAgICAgIHRhc2tbdGFzay5sZW5ndGggLSAxXSh0YXNrQ2FsbGJhY2ssIHJlc3VsdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYWRkTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gbGlzdGVuZXIoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlYWR5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICB0YXNrW3Rhc2subGVuZ3RoIC0gMV0odGFza0NhbGxiYWNrLCByZXN1bHRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG5cblxuXG4gICAgYXN5bmMucmV0cnkgPSBmdW5jdGlvbih0aW1lcywgdGFzaywgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIERFRkFVTFRfVElNRVMgPSA1O1xuICAgICAgICB2YXIgREVGQVVMVF9JTlRFUlZBTCA9IDA7XG5cbiAgICAgICAgdmFyIGF0dGVtcHRzID0gW107XG5cbiAgICAgICAgdmFyIG9wdHMgPSB7XG4gICAgICAgICAgICB0aW1lczogREVGQVVMVF9USU1FUyxcbiAgICAgICAgICAgIGludGVydmFsOiBERUZBVUxUX0lOVEVSVkFMXG4gICAgICAgIH07XG5cbiAgICAgICAgZnVuY3Rpb24gcGFyc2VUaW1lcyhhY2MsIHQpe1xuICAgICAgICAgICAgaWYodHlwZW9mIHQgPT09ICdudW1iZXInKXtcbiAgICAgICAgICAgICAgICBhY2MudGltZXMgPSBwYXJzZUludCh0LCAxMCkgfHwgREVGQVVMVF9USU1FUztcbiAgICAgICAgICAgIH0gZWxzZSBpZih0eXBlb2YgdCA9PT0gJ29iamVjdCcpe1xuICAgICAgICAgICAgICAgIGFjYy50aW1lcyA9IHBhcnNlSW50KHQudGltZXMsIDEwKSB8fCBERUZBVUxUX1RJTUVTO1xuICAgICAgICAgICAgICAgIGFjYy5pbnRlcnZhbCA9IHBhcnNlSW50KHQuaW50ZXJ2YWwsIDEwKSB8fCBERUZBVUxUX0lOVEVSVkFMO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIGFyZ3VtZW50IHR5cGUgZm9yIFxcJ3RpbWVzXFwnOiAnICsgdHlwZW9mIHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgIGlmIChsZW5ndGggPCAxIHx8IGxlbmd0aCA+IDMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhcmd1bWVudHMgLSBtdXN0IGJlIGVpdGhlciAodGFzayksICh0YXNrLCBjYWxsYmFjayksICh0aW1lcywgdGFzaykgb3IgKHRpbWVzLCB0YXNrLCBjYWxsYmFjayknKTtcbiAgICAgICAgfSBlbHNlIGlmIChsZW5ndGggPD0gMiAmJiB0eXBlb2YgdGltZXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrID0gdGFzaztcbiAgICAgICAgICAgIHRhc2sgPSB0aW1lcztcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHRpbWVzICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBwYXJzZVRpbWVzKG9wdHMsIHRpbWVzKTtcbiAgICAgICAgfVxuICAgICAgICBvcHRzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICAgIG9wdHMudGFzayA9IHRhc2s7XG5cbiAgICAgICAgZnVuY3Rpb24gd3JhcHBlZFRhc2sod3JhcHBlZENhbGxiYWNrLCB3cmFwcGVkUmVzdWx0cykge1xuICAgICAgICAgICAgZnVuY3Rpb24gcmV0cnlBdHRlbXB0KHRhc2ssIGZpbmFsQXR0ZW1wdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihzZXJpZXNDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICB0YXNrKGZ1bmN0aW9uKGVyciwgcmVzdWx0KXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcmllc0NhbGxiYWNrKCFlcnIgfHwgZmluYWxBdHRlbXB0LCB7ZXJyOiBlcnIsIHJlc3VsdDogcmVzdWx0fSk7XG4gICAgICAgICAgICAgICAgICAgIH0sIHdyYXBwZWRSZXN1bHRzKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXRyeUludGVydmFsKGludGVydmFsKXtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oc2VyaWVzQ2FsbGJhY2spe1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJpZXNDYWxsYmFjayhudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgaW50ZXJ2YWwpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHdoaWxlIChvcHRzLnRpbWVzKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgZmluYWxBdHRlbXB0ID0gIShvcHRzLnRpbWVzLT0xKTtcbiAgICAgICAgICAgICAgICBhdHRlbXB0cy5wdXNoKHJldHJ5QXR0ZW1wdChvcHRzLnRhc2ssIGZpbmFsQXR0ZW1wdCkpO1xuICAgICAgICAgICAgICAgIGlmKCFmaW5hbEF0dGVtcHQgJiYgb3B0cy5pbnRlcnZhbCA+IDApe1xuICAgICAgICAgICAgICAgICAgICBhdHRlbXB0cy5wdXNoKHJldHJ5SW50ZXJ2YWwob3B0cy5pbnRlcnZhbCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXN5bmMuc2VyaWVzKGF0dGVtcHRzLCBmdW5jdGlvbihkb25lLCBkYXRhKXtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGF0YVtkYXRhLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgICh3cmFwcGVkQ2FsbGJhY2sgfHwgb3B0cy5jYWxsYmFjaykoZGF0YS5lcnIsIGRhdGEucmVzdWx0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHJ1biB0aGlzIGFzIGEgY29udHJvbGwgZmxvd1xuICAgICAgICByZXR1cm4gb3B0cy5jYWxsYmFjayA/IHdyYXBwZWRUYXNrKCkgOiB3cmFwcGVkVGFzaztcbiAgICB9O1xuXG4gICAgYXN5bmMud2F0ZXJmYWxsID0gZnVuY3Rpb24gKHRhc2tzLCBjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayA9IF9vbmNlKGNhbGxiYWNrIHx8IG5vb3ApO1xuICAgICAgICBpZiAoIV9pc0FycmF5KHRhc2tzKSkge1xuICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcignRmlyc3QgYXJndW1lbnQgdG8gd2F0ZXJmYWxsIG11c3QgYmUgYW4gYXJyYXkgb2YgZnVuY3Rpb25zJyk7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRhc2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gd3JhcEl0ZXJhdG9yKGl0ZXJhdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gX3Jlc3RQYXJhbShmdW5jdGlvbiAoZXJyLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBbZXJyXS5jb25jYXQoYXJncykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHQgPSBpdGVyYXRvci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmdzLnB1c2god3JhcEl0ZXJhdG9yKG5leHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChjYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZW5zdXJlQXN5bmMoaXRlcmF0b3IpLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHdyYXBJdGVyYXRvcihhc3luYy5pdGVyYXRvcih0YXNrcykpKCk7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIF9wYXJhbGxlbChlYWNoZm4sIHRhc2tzLCBjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayA9IGNhbGxiYWNrIHx8IG5vb3A7XG4gICAgICAgIHZhciByZXN1bHRzID0gX2lzQXJyYXlMaWtlKHRhc2tzKSA/IFtdIDoge307XG5cbiAgICAgICAgZWFjaGZuKHRhc2tzLCBmdW5jdGlvbiAodGFzaywga2V5LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgdGFzayhfcmVzdFBhcmFtKGZ1bmN0aW9uIChlcnIsIGFyZ3MpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPD0gMSkge1xuICAgICAgICAgICAgICAgICAgICBhcmdzID0gYXJnc1swXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzdWx0c1trZXldID0gYXJncztcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYy5wYXJhbGxlbCA9IGZ1bmN0aW9uICh0YXNrcywgY2FsbGJhY2spIHtcbiAgICAgICAgX3BhcmFsbGVsKGFzeW5jLmVhY2hPZiwgdGFza3MsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgYXN5bmMucGFyYWxsZWxMaW1pdCA9IGZ1bmN0aW9uKHRhc2tzLCBsaW1pdCwgY2FsbGJhY2spIHtcbiAgICAgICAgX3BhcmFsbGVsKF9lYWNoT2ZMaW1pdChsaW1pdCksIHRhc2tzLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIGFzeW5jLnNlcmllcyA9IGZ1bmN0aW9uKHRhc2tzLCBjYWxsYmFjaykge1xuICAgICAgICBfcGFyYWxsZWwoYXN5bmMuZWFjaE9mU2VyaWVzLCB0YXNrcywgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBhc3luYy5pdGVyYXRvciA9IGZ1bmN0aW9uICh0YXNrcykge1xuICAgICAgICBmdW5jdGlvbiBtYWtlQ2FsbGJhY2soaW5kZXgpIHtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGZuKCkge1xuICAgICAgICAgICAgICAgIGlmICh0YXNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFza3NbaW5kZXhdLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBmbi5uZXh0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmbi5uZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoaW5kZXggPCB0YXNrcy5sZW5ndGggLSAxKSA/IG1ha2VDYWxsYmFjayhpbmRleCArIDEpOiBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiBmbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWFrZUNhbGxiYWNrKDApO1xuICAgIH07XG5cbiAgICBhc3luYy5hcHBseSA9IF9yZXN0UGFyYW0oZnVuY3Rpb24gKGZuLCBhcmdzKSB7XG4gICAgICAgIHJldHVybiBfcmVzdFBhcmFtKGZ1bmN0aW9uIChjYWxsQXJncykge1xuICAgICAgICAgICAgcmV0dXJuIGZuLmFwcGx5KFxuICAgICAgICAgICAgICAgIG51bGwsIGFyZ3MuY29uY2F0KGNhbGxBcmdzKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBfY29uY2F0KGVhY2hmbiwgYXJyLCBmbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICBlYWNoZm4oYXJyLCBmdW5jdGlvbiAoeCwgaW5kZXgsIGNiKSB7XG4gICAgICAgICAgICBmbih4LCBmdW5jdGlvbiAoZXJyLCB5KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmNvbmNhdCh5IHx8IFtdKTtcbiAgICAgICAgICAgICAgICBjYihlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGFzeW5jLmNvbmNhdCA9IGRvUGFyYWxsZWwoX2NvbmNhdCk7XG4gICAgYXN5bmMuY29uY2F0U2VyaWVzID0gZG9TZXJpZXMoX2NvbmNhdCk7XG5cbiAgICBhc3luYy53aGlsc3QgPSBmdW5jdGlvbiAodGVzdCwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgbm9vcDtcbiAgICAgICAgaWYgKHRlc3QoKSkge1xuICAgICAgICAgICAgdmFyIG5leHQgPSBfcmVzdFBhcmFtKGZ1bmN0aW9uKGVyciwgYXJncykge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRlc3QuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICAgICAgICAgICAgaXRlcmF0b3IobmV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpdGVyYXRvcihuZXh0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGFzeW5jLmRvV2hpbHN0ID0gZnVuY3Rpb24gKGl0ZXJhdG9yLCB0ZXN0LCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgY2FsbHMgPSAwO1xuICAgICAgICByZXR1cm4gYXN5bmMud2hpbHN0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuICsrY2FsbHMgPD0gMSB8fCB0ZXN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH0sIGl0ZXJhdG9yLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIGFzeW5jLnVudGlsID0gZnVuY3Rpb24gKHRlc3QsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gYXN5bmMud2hpbHN0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuICF0ZXN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH0sIGl0ZXJhdG9yLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIGFzeW5jLmRvVW50aWwgPSBmdW5jdGlvbiAoaXRlcmF0b3IsIHRlc3QsIGNhbGxiYWNrKSB7XG4gICAgICAgIHJldHVybiBhc3luYy5kb1doaWxzdChpdGVyYXRvciwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gIXRlc3QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBhc3luYy5kdXJpbmcgPSBmdW5jdGlvbiAodGVzdCwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgbm9vcDtcblxuICAgICAgICB2YXIgbmV4dCA9IF9yZXN0UGFyYW0oZnVuY3Rpb24oZXJyLCBhcmdzKSB7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXJncy5wdXNoKGNoZWNrKTtcbiAgICAgICAgICAgICAgICB0ZXN0LmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgY2hlY2sgPSBmdW5jdGlvbihlcnIsIHRydXRoKSB7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHJ1dGgpIHtcbiAgICAgICAgICAgICAgICBpdGVyYXRvcihuZXh0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdGVzdChjaGVjayk7XG4gICAgfTtcblxuICAgIGFzeW5jLmRvRHVyaW5nID0gZnVuY3Rpb24gKGl0ZXJhdG9yLCB0ZXN0LCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgY2FsbHMgPSAwO1xuICAgICAgICBhc3luYy5kdXJpbmcoZnVuY3Rpb24obmV4dCkge1xuICAgICAgICAgICAgaWYgKGNhbGxzKysgPCAxKSB7XG4gICAgICAgICAgICAgICAgbmV4dChudWxsLCB0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGVzdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBfcXVldWUod29ya2VyLCBjb25jdXJyZW5jeSwgcGF5bG9hZCkge1xuICAgICAgICBpZiAoY29uY3VycmVuY3kgPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uY3VycmVuY3kgPSAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29uY3VycmVuY3kgPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ29uY3VycmVuY3kgbXVzdCBub3QgYmUgemVybycpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIF9pbnNlcnQocSwgZGF0YSwgcG9zLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrICE9IG51bGwgJiYgdHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0YXNrIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvblwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHEuc3RhcnRlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIV9pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IFtkYXRhXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGRhdGEubGVuZ3RoID09PSAwICYmIHEuaWRsZSgpKSB7XG4gICAgICAgICAgICAgICAgLy8gY2FsbCBkcmFpbiBpbW1lZGlhdGVseSBpZiB0aGVyZSBhcmUgbm8gdGFza3NcbiAgICAgICAgICAgICAgICByZXR1cm4gYXN5bmMuc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBxLmRyYWluKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfYXJyYXlFYWNoKGRhdGEsIGZ1bmN0aW9uKHRhc2spIHtcbiAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogdGFzayxcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrIHx8IG5vb3BcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHBvcykge1xuICAgICAgICAgICAgICAgICAgICBxLnRhc2tzLnVuc2hpZnQoaXRlbSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcS50YXNrcy5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChxLnRhc2tzLmxlbmd0aCA9PT0gcS5jb25jdXJyZW5jeSkge1xuICAgICAgICAgICAgICAgICAgICBxLnNhdHVyYXRlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYXN5bmMuc2V0SW1tZWRpYXRlKHEucHJvY2Vzcyk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX25leHQocSwgdGFza3MpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgIHdvcmtlcnMgLT0gMTtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICBfYXJyYXlFYWNoKHRhc2tzLCBmdW5jdGlvbiAodGFzaykge1xuICAgICAgICAgICAgICAgICAgICB0YXNrLmNhbGxiYWNrLmFwcGx5KHRhc2ssIGFyZ3MpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChxLnRhc2tzLmxlbmd0aCArIHdvcmtlcnMgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcS5kcmFpbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBxLnByb2Nlc3MoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgd29ya2VycyA9IDA7XG4gICAgICAgIHZhciBxID0ge1xuICAgICAgICAgICAgdGFza3M6IFtdLFxuICAgICAgICAgICAgY29uY3VycmVuY3k6IGNvbmN1cnJlbmN5LFxuICAgICAgICAgICAgcGF5bG9hZDogcGF5bG9hZCxcbiAgICAgICAgICAgIHNhdHVyYXRlZDogbm9vcCxcbiAgICAgICAgICAgIGVtcHR5OiBub29wLFxuICAgICAgICAgICAgZHJhaW46IG5vb3AsXG4gICAgICAgICAgICBzdGFydGVkOiBmYWxzZSxcbiAgICAgICAgICAgIHBhdXNlZDogZmFsc2UsXG4gICAgICAgICAgICBwdXNoOiBmdW5jdGlvbiAoZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBfaW5zZXJ0KHEsIGRhdGEsIGZhbHNlLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAga2lsbDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHEuZHJhaW4gPSBub29wO1xuICAgICAgICAgICAgICAgIHEudGFza3MgPSBbXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1bnNoaWZ0OiBmdW5jdGlvbiAoZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBfaW5zZXJ0KHEsIGRhdGEsIHRydWUsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwcm9jZXNzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFxLnBhdXNlZCAmJiB3b3JrZXJzIDwgcS5jb25jdXJyZW5jeSAmJiBxLnRhc2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSh3b3JrZXJzIDwgcS5jb25jdXJyZW5jeSAmJiBxLnRhc2tzLmxlbmd0aCl7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGFza3MgPSBxLnBheWxvYWQgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHEudGFza3Muc3BsaWNlKDAsIHEucGF5bG9hZCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHEudGFza3Muc3BsaWNlKDAsIHEudGFza3MubGVuZ3RoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBfbWFwKHRhc2tzLCBmdW5jdGlvbiAodGFzaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXNrLmRhdGE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEudGFza3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcS5lbXB0eSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VycyArPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNiID0gb25seV9vbmNlKF9uZXh0KHEsIHRhc2tzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIoZGF0YSwgY2IpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlbmd0aDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBxLnRhc2tzLmxlbmd0aDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5uaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdvcmtlcnM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaWRsZTogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHEudGFza3MubGVuZ3RoICsgd29ya2VycyA9PT0gMDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXVzZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHEucGF1c2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXN1bWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAocS5wYXVzZWQgPT09IGZhbHNlKSB7IHJldHVybjsgfVxuICAgICAgICAgICAgICAgIHEucGF1c2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VtZUNvdW50ID0gTWF0aC5taW4ocS5jb25jdXJyZW5jeSwgcS50YXNrcy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIC8vIE5lZWQgdG8gY2FsbCBxLnByb2Nlc3Mgb25jZSBwZXIgY29uY3VycmVudFxuICAgICAgICAgICAgICAgIC8vIHdvcmtlciB0byBwcmVzZXJ2ZSBmdWxsIGNvbmN1cnJlbmN5IGFmdGVyIHBhdXNlXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgdyA9IDE7IHcgPD0gcmVzdW1lQ291bnQ7IHcrKykge1xuICAgICAgICAgICAgICAgICAgICBhc3luYy5zZXRJbW1lZGlhdGUocS5wcm9jZXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBxO1xuICAgIH1cblxuICAgIGFzeW5jLnF1ZXVlID0gZnVuY3Rpb24gKHdvcmtlciwgY29uY3VycmVuY3kpIHtcbiAgICAgICAgdmFyIHEgPSBfcXVldWUoZnVuY3Rpb24gKGl0ZW1zLCBjYikge1xuICAgICAgICAgICAgd29ya2VyKGl0ZW1zWzBdLCBjYik7XG4gICAgICAgIH0sIGNvbmN1cnJlbmN5LCAxKTtcblxuICAgICAgICByZXR1cm4gcTtcbiAgICB9O1xuXG4gICAgYXN5bmMucHJpb3JpdHlRdWV1ZSA9IGZ1bmN0aW9uICh3b3JrZXIsIGNvbmN1cnJlbmN5KSB7XG5cbiAgICAgICAgZnVuY3Rpb24gX2NvbXBhcmVUYXNrcyhhLCBiKXtcbiAgICAgICAgICAgIHJldHVybiBhLnByaW9yaXR5IC0gYi5wcmlvcml0eTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIF9iaW5hcnlTZWFyY2goc2VxdWVuY2UsIGl0ZW0sIGNvbXBhcmUpIHtcbiAgICAgICAgICAgIHZhciBiZWcgPSAtMSxcbiAgICAgICAgICAgICAgICBlbmQgPSBzZXF1ZW5jZS5sZW5ndGggLSAxO1xuICAgICAgICAgICAgd2hpbGUgKGJlZyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciBtaWQgPSBiZWcgKyAoKGVuZCAtIGJlZyArIDEpID4+PiAxKTtcbiAgICAgICAgICAgICAgICBpZiAoY29tcGFyZShpdGVtLCBzZXF1ZW5jZVttaWRdKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlZyA9IG1pZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbmQgPSBtaWQgLSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBiZWc7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBfaW5zZXJ0KHEsIGRhdGEsIHByaW9yaXR5LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrICE9IG51bGwgJiYgdHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0YXNrIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvblwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHEuc3RhcnRlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIV9pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IFtkYXRhXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gY2FsbCBkcmFpbiBpbW1lZGlhdGVseSBpZiB0aGVyZSBhcmUgbm8gdGFza3NcbiAgICAgICAgICAgICAgICByZXR1cm4gYXN5bmMuc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBxLmRyYWluKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfYXJyYXlFYWNoKGRhdGEsIGZ1bmN0aW9uKHRhc2spIHtcbiAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogdGFzayxcbiAgICAgICAgICAgICAgICAgICAgcHJpb3JpdHk6IHByaW9yaXR5LFxuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjazogdHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nID8gY2FsbGJhY2sgOiBub29wXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHEudGFza3Muc3BsaWNlKF9iaW5hcnlTZWFyY2gocS50YXNrcywgaXRlbSwgX2NvbXBhcmVUYXNrcykgKyAxLCAwLCBpdGVtKTtcblxuICAgICAgICAgICAgICAgIGlmIChxLnRhc2tzLmxlbmd0aCA9PT0gcS5jb25jdXJyZW5jeSkge1xuICAgICAgICAgICAgICAgICAgICBxLnNhdHVyYXRlZCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhc3luYy5zZXRJbW1lZGlhdGUocS5wcm9jZXNzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RhcnQgd2l0aCBhIG5vcm1hbCBxdWV1ZVxuICAgICAgICB2YXIgcSA9IGFzeW5jLnF1ZXVlKHdvcmtlciwgY29uY3VycmVuY3kpO1xuXG4gICAgICAgIC8vIE92ZXJyaWRlIHB1c2ggdG8gYWNjZXB0IHNlY29uZCBwYXJhbWV0ZXIgcmVwcmVzZW50aW5nIHByaW9yaXR5XG4gICAgICAgIHEucHVzaCA9IGZ1bmN0aW9uIChkYXRhLCBwcmlvcml0eSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIF9pbnNlcnQocSwgZGF0YSwgcHJpb3JpdHksIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZW1vdmUgdW5zaGlmdCBmdW5jdGlvblxuICAgICAgICBkZWxldGUgcS51bnNoaWZ0O1xuXG4gICAgICAgIHJldHVybiBxO1xuICAgIH07XG5cbiAgICBhc3luYy5jYXJnbyA9IGZ1bmN0aW9uICh3b3JrZXIsIHBheWxvYWQpIHtcbiAgICAgICAgcmV0dXJuIF9xdWV1ZSh3b3JrZXIsIDEsIHBheWxvYWQpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBfY29uc29sZV9mbihuYW1lKSB7XG4gICAgICAgIHJldHVybiBfcmVzdFBhcmFtKGZ1bmN0aW9uIChmbiwgYXJncykge1xuICAgICAgICAgICAgZm4uYXBwbHkobnVsbCwgYXJncy5jb25jYXQoW19yZXN0UGFyYW0oZnVuY3Rpb24gKGVyciwgYXJncykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29uc29sZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnNvbGUuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29uc29sZVtuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2FycmF5RWFjaChhcmdzLCBmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGVbbmFtZV0oeCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXSkpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgYXN5bmMubG9nID0gX2NvbnNvbGVfZm4oJ2xvZycpO1xuICAgIGFzeW5jLmRpciA9IF9jb25zb2xlX2ZuKCdkaXInKTtcbiAgICAvKmFzeW5jLmluZm8gPSBfY29uc29sZV9mbignaW5mbycpO1xuICAgIGFzeW5jLndhcm4gPSBfY29uc29sZV9mbignd2FybicpO1xuICAgIGFzeW5jLmVycm9yID0gX2NvbnNvbGVfZm4oJ2Vycm9yJyk7Ki9cblxuICAgIGFzeW5jLm1lbW9pemUgPSBmdW5jdGlvbiAoZm4sIGhhc2hlcikge1xuICAgICAgICB2YXIgbWVtbyA9IHt9O1xuICAgICAgICB2YXIgcXVldWVzID0ge307XG4gICAgICAgIGhhc2hlciA9IGhhc2hlciB8fCBpZGVudGl0eTtcbiAgICAgICAgdmFyIG1lbW9pemVkID0gX3Jlc3RQYXJhbShmdW5jdGlvbiBtZW1vaXplZChhcmdzKSB7XG4gICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSBhcmdzLnBvcCgpO1xuICAgICAgICAgICAgdmFyIGtleSA9IGhhc2hlci5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgICAgICAgIGlmIChrZXkgaW4gbWVtbykge1xuICAgICAgICAgICAgICAgIGFzeW5jLnNldEltbWVkaWF0ZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrLmFwcGx5KG51bGwsIG1lbW9ba2V5XSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChrZXkgaW4gcXVldWVzKSB7XG4gICAgICAgICAgICAgICAgcXVldWVzW2tleV0ucHVzaChjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBxdWV1ZXNba2V5XSA9IFtjYWxsYmFja107XG4gICAgICAgICAgICAgICAgZm4uYXBwbHkobnVsbCwgYXJncy5jb25jYXQoW19yZXN0UGFyYW0oZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVtb1trZXldID0gYXJncztcbiAgICAgICAgICAgICAgICAgICAgdmFyIHEgPSBxdWV1ZXNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHF1ZXVlc1trZXldO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHEubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBxW2ldLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSldKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBtZW1vaXplZC5tZW1vID0gbWVtbztcbiAgICAgICAgbWVtb2l6ZWQudW5tZW1vaXplZCA9IGZuO1xuICAgICAgICByZXR1cm4gbWVtb2l6ZWQ7XG4gICAgfTtcblxuICAgIGFzeW5jLnVubWVtb2l6ZSA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIChmbi51bm1lbW9pemVkIHx8IGZuKS5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBfdGltZXMobWFwcGVyKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoY291bnQsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgbWFwcGVyKF9yYW5nZShjb3VudCksIGl0ZXJhdG9yLCBjYWxsYmFjayk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgYXN5bmMudGltZXMgPSBfdGltZXMoYXN5bmMubWFwKTtcbiAgICBhc3luYy50aW1lc1NlcmllcyA9IF90aW1lcyhhc3luYy5tYXBTZXJpZXMpO1xuICAgIGFzeW5jLnRpbWVzTGltaXQgPSBmdW5jdGlvbiAoY291bnQsIGxpbWl0LCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgcmV0dXJuIGFzeW5jLm1hcExpbWl0KF9yYW5nZShjb3VudCksIGxpbWl0LCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBhc3luYy5zZXEgPSBmdW5jdGlvbiAoLyogZnVuY3Rpb25zLi4uICovKSB7XG4gICAgICAgIHZhciBmbnMgPSBhcmd1bWVudHM7XG4gICAgICAgIHJldHVybiBfcmVzdFBhcmFtKGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3NbYXJncy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGFyZ3MucG9wKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrID0gbm9vcDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXN5bmMucmVkdWNlKGZucywgYXJncywgZnVuY3Rpb24gKG5ld2FyZ3MsIGZuLCBjYikge1xuICAgICAgICAgICAgICAgIGZuLmFwcGx5KHRoYXQsIG5ld2FyZ3MuY29uY2F0KFtfcmVzdFBhcmFtKGZ1bmN0aW9uIChlcnIsIG5leHRhcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNiKGVyciwgbmV4dGFyZ3MpO1xuICAgICAgICAgICAgICAgIH0pXSkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlcnIsIHJlc3VsdHMpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjay5hcHBseSh0aGF0LCBbZXJyXS5jb25jYXQocmVzdWx0cykpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBhc3luYy5jb21wb3NlID0gZnVuY3Rpb24gKC8qIGZ1bmN0aW9ucy4uLiAqLykge1xuICAgICAgICByZXR1cm4gYXN5bmMuc2VxLmFwcGx5KG51bGwsIEFycmF5LnByb3RvdHlwZS5yZXZlcnNlLmNhbGwoYXJndW1lbnRzKSk7XG4gICAgfTtcblxuXG4gICAgZnVuY3Rpb24gX2FwcGx5RWFjaChlYWNoZm4pIHtcbiAgICAgICAgcmV0dXJuIF9yZXN0UGFyYW0oZnVuY3Rpb24oZm5zLCBhcmdzKSB7XG4gICAgICAgICAgICB2YXIgZ28gPSBfcmVzdFBhcmFtKGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gYXJncy5wb3AoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZWFjaGZuKGZucywgZnVuY3Rpb24gKGZuLCBfLCBjYikge1xuICAgICAgICAgICAgICAgICAgICBmbi5hcHBseSh0aGF0LCBhcmdzLmNvbmNhdChbY2JdKSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjYWxsYmFjayk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBnby5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBnbztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMuYXBwbHlFYWNoID0gX2FwcGx5RWFjaChhc3luYy5lYWNoT2YpO1xuICAgIGFzeW5jLmFwcGx5RWFjaFNlcmllcyA9IF9hcHBseUVhY2goYXN5bmMuZWFjaE9mU2VyaWVzKTtcblxuXG4gICAgYXN5bmMuZm9yZXZlciA9IGZ1bmN0aW9uIChmbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGRvbmUgPSBvbmx5X29uY2UoY2FsbGJhY2sgfHwgbm9vcCk7XG4gICAgICAgIHZhciB0YXNrID0gZW5zdXJlQXN5bmMoZm4pO1xuICAgICAgICBmdW5jdGlvbiBuZXh0KGVycikge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHJldHVybiBkb25lKGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0YXNrKG5leHQpO1xuICAgICAgICB9XG4gICAgICAgIG5leHQoKTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZW5zdXJlQXN5bmMoZm4pIHtcbiAgICAgICAgcmV0dXJuIF9yZXN0UGFyYW0oZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4gICAgICAgICAgICBhcmdzLnB1c2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBpbm5lckFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgICAgaWYgKHN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgYXN5bmMuc2V0SW1tZWRpYXRlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrLmFwcGx5KG51bGwsIGlubmVyQXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrLmFwcGx5KG51bGwsIGlubmVyQXJncyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgc3luYyA9IHRydWU7XG4gICAgICAgICAgICBmbi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICAgIHN5bmMgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMuZW5zdXJlQXN5bmMgPSBlbnN1cmVBc3luYztcblxuICAgIGFzeW5jLmNvbnN0YW50ID0gX3Jlc3RQYXJhbShmdW5jdGlvbih2YWx1ZXMpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbbnVsbF0uY29uY2F0KHZhbHVlcyk7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjay5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgfTtcbiAgICB9KTtcblxuICAgIGFzeW5jLndyYXBTeW5jID1cbiAgICBhc3luYy5hc3luY2lmeSA9IGZ1bmN0aW9uIGFzeW5jaWZ5KGZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIF9yZXN0UGFyYW0oZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0O1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGlmIHJlc3VsdCBpcyBQcm9taXNlIG9iamVjdFxuICAgICAgICAgICAgaWYgKF9pc09iamVjdChyZXN1bHQpICYmIHR5cGVvZiByZXN1bHQudGhlbiA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnRoZW4oZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgIH0pW1wiY2F0Y2hcIl0oZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVyci5tZXNzYWdlID8gZXJyIDogbmV3IEVycm9yKGVycikpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCByZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLy8gTm9kZS5qc1xuICAgIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFzeW5jO1xuICAgIH1cbiAgICAvLyBBTUQgLyBSZXF1aXJlSlNcbiAgICBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gYXN5bmM7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBpbmNsdWRlZCBkaXJlY3RseSB2aWEgPHNjcmlwdD4gdGFnXG4gICAgZWxzZSB7XG4gICAgICAgIHJvb3QuYXN5bmMgPSBhc3luYztcbiAgICB9XG5cbn0oKSk7XG4iLCIndXNlIHN0cmljdCc7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzdHIpIHtcblx0aWYgKHN0ci5sZW5ndGggPT09IDEpIHtcblx0XHRyZXR1cm4gc3RyO1xuXHR9XG5cblx0cmV0dXJuIHN0clxuXHQucmVwbGFjZSgvXltfLlxcLSBdKy8sICcnKVxuXHQudG9Mb3dlckNhc2UoKVxuXHQucmVwbGFjZSgvW18uXFwtIF0rKFxcd3wkKS9nLCBmdW5jdGlvbiAobSwgcDEpIHtcblx0XHRyZXR1cm4gcDEudG9VcHBlckNhc2UoKTtcblx0fSk7XG59O1xuIl19