Skip to content

Instantly share code, notes, and snippets.

@caesarsol
Created May 31, 2017 13:52
Show Gist options
  • Save caesarsol/fd993b488257f419093782ac741b18b9 to your computer and use it in GitHub Desktop.
Save caesarsol/fd993b488257f419093782ac741b18b9 to your computer and use it in GitHub Desktop.
requirebin sketch
'use strict'
const mobx = require('mobx')
const a = mobx.observable({
b: 1,
c: [],
})
const dom = [
document.createElement('div'),
document.createElement('div'),
document.createElement('div'),
document.createElement('div'),
]
dom.forEach((e, i) => {
e.style.background = ['steelblue', 'tomato'][i % 2]
document.body.appendChild(e)
})
const start = Date.now()
document.body.addEventListener('click', () => {
a.b++
a.c.push(Date.now() - start)
})
// 1
let oldValue = null
requestAnimationFrame(function loop() {
let b = a.b
dom[0].innerHTML = b
if (b !== oldValue) {
console.timeEnd()
}
oldValue = b
dom[2].innerHTML = a.c
requestAnimationFrame(loop)
})
// 2
mobx.autorun(() => {
dom[1].innerHTML += a.b + '<br>'
console.time()
})
mobx.autorun(() => {
dom[3].innerHTML = a.c.join('<br>')
})
setTimeout(function(){
;require=(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})({"mobx":[function(require,module,exports){
(function (global){
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
registerGlobals();
exports.extras = {
allowStateChanges: allowStateChanges,
deepEqual: deepEqual,
getAtom: getAtom,
getDebugName: getDebugName,
getDependencyTree: getDependencyTree,
getAdministration: getAdministration,
getGlobalState: getGlobalState,
getObserverTree: getObserverTree,
isComputingDerivation: isComputingDerivation,
isSpyEnabled: isSpyEnabled,
onReactionError: onReactionError,
resetGlobalState: resetGlobalState,
shareGlobalState: shareGlobalState,
spyReport: spyReport,
spyReportEnd: spyReportEnd,
spyReportStart: spyReportStart,
setReactionScheduler: setReactionScheduler
};
if (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === "object") {
__MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx(module.exports);
}
var actionFieldDecorator = createClassPropertyDecorator(function (target, key, value, args, originalDescriptor) {
var actionName = (args && args.length === 1) ? args[0] : (value.name || key || "<unnamed action>");
var wrappedAction = action(actionName, value);
addHiddenProp(target, key, wrappedAction);
}, function (key) {
return this[key];
}, function () {
invariant(false, getMessage("m001"));
}, false, true);
var boundActionDecorator = createClassPropertyDecorator(function (target, key, value) {
defineBoundAction(target, key, value);
}, function (key) {
return this[key];
}, function () {
invariant(false, getMessage("m001"));
}, false, false);
var action = function action(arg1, arg2, arg3, arg4) {
if (arguments.length === 1 && typeof arg1 === "function")
return createAction(arg1.name || "<unnamed action>", arg1);
if (arguments.length === 2 && typeof arg2 === "function")
return createAction(arg1, arg2);
if (arguments.length === 1 && typeof arg1 === "string")
return namedActionDecorator(arg1);
return namedActionDecorator(arg2).apply(null, arguments);
};
exports.action = action;
action.bound = function boundAction(arg1, arg2, arg3) {
if (typeof arg1 === "function") {
var action_1 = createAction("<not yet bound action>", arg1);
action_1.autoBind = true;
return action_1;
}
return boundActionDecorator.apply(null, arguments);
};
function namedActionDecorator(name) {
return function (target, prop, descriptor) {
if (descriptor && typeof descriptor.value === "function") {
descriptor.value = createAction(name, descriptor.value);
descriptor.enumerable = false;
descriptor.configurable = true;
return descriptor;
}
return actionFieldDecorator(name).apply(this, arguments);
};
}
function runInAction(arg1, arg2, arg3) {
var actionName = typeof arg1 === "string" ? arg1 : arg1.name || "<unnamed action>";
var fn = typeof arg1 === "function" ? arg1 : arg2;
var scope = typeof arg1 === "function" ? arg2 : arg3;
invariant(typeof fn === "function", getMessage("m002"));
invariant(fn.length === 0, getMessage("m003"));
invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'");
return executeAction(actionName, fn, scope, undefined);
}
exports.runInAction = runInAction;
function isAction(thing) {
return typeof thing === "function" && thing.isMobxAction === true;
}
exports.isAction = isAction;
function defineBoundAction(target, propertyName, fn) {
var res = function () {
return executeAction(propertyName, fn, target, arguments);
};
res.isMobxAction = true;
addHiddenProp(target, propertyName, res);
}
function autorun(arg1, arg2, arg3) {
var name, view, scope;
if (typeof arg1 === "string") {
name = arg1;
view = arg2;
scope = arg3;
}
else {
name = arg1.name || ("Autorun@" + getNextId());
view = arg1;
scope = arg2;
}
invariant(typeof view === "function", getMessage("m004"));
invariant(isAction(view) === false, getMessage("m005"));
if (scope)
view = view.bind(scope);
var reaction = new Reaction(name, function () {
this.track(reactionRunner);
});
function reactionRunner() {
view(reaction);
}
reaction.schedule();
return reaction.getDisposer();
}
exports.autorun = autorun;
function when(arg1, arg2, arg3, arg4) {
var name, predicate, effect, scope;
if (typeof arg1 === "string") {
name = arg1;
predicate = arg2;
effect = arg3;
scope = arg4;
}
else {
name = ("When@" + getNextId());
predicate = arg1;
effect = arg2;
scope = arg3;
}
var disposer = autorun(name, function (r) {
if (predicate.call(scope)) {
r.dispose();
var prevUntracked = untrackedStart();
effect.call(scope);
untrackedEnd(prevUntracked);
}
});
return disposer;
}
exports.when = when;
function autorunAsync(arg1, arg2, arg3, arg4) {
var name, func, delay, scope;
if (typeof arg1 === "string") {
name = arg1;
func = arg2;
delay = arg3;
scope = arg4;
}
else {
name = arg1.name || ("AutorunAsync@" + getNextId());
func = arg1;
delay = arg2;
scope = arg3;
}
invariant(isAction(func) === false, getMessage("m006"));
if (delay === void 0)
delay = 1;
if (scope)
func = func.bind(scope);
var isScheduled = false;
var r = new Reaction(name, function () {
if (!isScheduled) {
isScheduled = true;
setTimeout(function () {
isScheduled = false;
if (!r.isDisposed)
r.track(reactionRunner);
}, delay);
}
});
function reactionRunner() { func(r); }
r.schedule();
return r.getDisposer();
}
exports.autorunAsync = autorunAsync;
function reaction(expression, effect, arg3) {
if (arguments.length > 3) {
fail(getMessage("m007"));
}
if (isModifierDescriptor(expression)) {
fail(getMessage("m008"));
}
var opts;
if (typeof arg3 === "object") {
opts = arg3;
}
else {
opts = {};
}
opts.name = opts.name || expression.name || effect.name || ("Reaction@" + getNextId());
opts.fireImmediately = arg3 === true || opts.fireImmediately === true;
opts.delay = opts.delay || 0;
opts.compareStructural = opts.compareStructural || opts.struct || false;
effect = action(opts.name, opts.context ? effect.bind(opts.context) : effect);
if (opts.context) {
expression = expression.bind(opts.context);
}
var firstTime = true;
var isScheduled = false;
var nextValue;
var r = new Reaction(opts.name, function () {
if (opts.delay < 1) {
reactionRunner();
}
else if (!isScheduled) {
isScheduled = true;
setTimeout(function () {
isScheduled = false;
reactionRunner();
}, opts.delay);
}
});
function reactionRunner() {
if (r.isDisposed)
return;
var changed = false;
r.track(function () {
var v = expression(r);
changed = valueDidChange(opts.compareStructural, nextValue, v);
nextValue = v;
});
if (firstTime && opts.fireImmediately)
effect(nextValue, r);
if (!firstTime && changed === true)
effect(nextValue, r);
if (firstTime)
firstTime = false;
}
r.schedule();
return r.getDisposer();
}
exports.reaction = reaction;
function createComputedDecorator(compareStructural) {
return createClassPropertyDecorator(function (target, name, _, __, originalDescriptor) {
invariant(typeof originalDescriptor !== "undefined", getMessage("m009"));
invariant(typeof originalDescriptor.get === "function", getMessage("m010"));
var adm = asObservableObject(target, "");
defineComputedProperty(adm, name, originalDescriptor.get, originalDescriptor.set, compareStructural, false);
}, function (name) {
var observable = this.$mobx.values[name];
if (observable === undefined)
return undefined;
return observable.get();
}, function (name, value) {
this.$mobx.values[name].set(value);
}, false, false);
}
var computedDecorator = createComputedDecorator(false);
var computedStructDecorator = createComputedDecorator(true);
var computed = (function computed(arg1, arg2, arg3) {
if (typeof arg2 === "string") {
return computedDecorator.apply(null, arguments);
}
invariant(typeof arg1 === "function", getMessage("m011"));
invariant(arguments.length < 3, getMessage("m012"));
var opts = typeof arg2 === "object" ? arg2 : {};
opts.setter = typeof arg2 === "function" ? arg2 : opts.setter;
return new ComputedValue(arg1, opts.context, opts.compareStructural || opts.struct || false, opts.name || arg1.name || "", opts.setter);
});
exports.computed = computed;
computed.struct = computedStructDecorator;
function createTransformer(transformer, onCleanup) {
invariant(typeof transformer === "function" && transformer.length < 2, "createTransformer expects a function that accepts one argument");
var objectCache = {};
var resetId = globalState.resetId;
var Transformer = (function (_super) {
__extends(Transformer, _super);
function Transformer(sourceIdentifier, sourceObject) {
var _this = _super.call(this, function () { return transformer(sourceObject); }, undefined, false, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined) || this;
_this.sourceIdentifier = sourceIdentifier;
_this.sourceObject = sourceObject;
return _this;
}
Transformer.prototype.onBecomeUnobserved = function () {
var lastValue = this.value;
_super.prototype.onBecomeUnobserved.call(this);
delete objectCache[this.sourceIdentifier];
if (onCleanup)
onCleanup(lastValue, this.sourceObject);
};
return Transformer;
}(ComputedValue));
return function (object) {
if (resetId !== globalState.resetId) {
objectCache = {};
resetId = globalState.resetId;
}
var identifier = getMemoizationId(object);
var reactiveTransformer = objectCache[identifier];
if (reactiveTransformer)
return reactiveTransformer.get();
reactiveTransformer = objectCache[identifier] = new Transformer(identifier, object);
return reactiveTransformer.get();
};
}
exports.createTransformer = createTransformer;
function getMemoizationId(object) {
if (object === null || typeof object !== "object")
throw new Error("[mobx] transform expected some kind of object, got: " + object);
var tid = object.$transformId;
if (tid === undefined) {
tid = getNextId();
addHiddenProp(object, "$transformId", tid);
}
return tid;
}
function expr(expr, scope) {
if (!isComputingDerivation())
console.warn(getMessage("m013"));
return computed(expr, { context: scope }).get();
}
exports.expr = expr;
function extendObservable(target) {
var properties = [];
for (var _i = 1; _i < arguments.length; _i++) {
properties[_i - 1] = arguments[_i];
}
return extendObservableHelper(target, deepEnhancer, properties);
}
exports.extendObservable = extendObservable;
function extendShallowObservable(target) {
var properties = [];
for (var _i = 1; _i < arguments.length; _i++) {
properties[_i - 1] = arguments[_i];
}
return extendObservableHelper(target, referenceEnhancer, properties);
}
exports.extendShallowObservable = extendShallowObservable;
function extendObservableHelper(target, defaultEnhancer, properties) {
invariant(arguments.length >= 2, getMessage("m014"));
invariant(typeof target === "object", getMessage("m015"));
invariant(!(isObservableMap(target)), getMessage("m016"));
properties.forEach(function (propSet) {
invariant(typeof propSet === "object", getMessage("m017"));
invariant(!isObservable(propSet), getMessage("m018"));
});
var adm = asObservableObject(target);
var definedProps = {};
for (var i = properties.length - 1; i >= 0; i--) {
var propSet = properties[i];
for (var key in propSet)
if (definedProps[key] !== true && hasOwnProperty(propSet, key)) {
definedProps[key] = true;
if (target === propSet && !isPropertyConfigurable(target, key))
continue;
var descriptor = Object.getOwnPropertyDescriptor(propSet, key);
defineObservablePropertyFromDescriptor(adm, key, descriptor, defaultEnhancer);
}
}
return target;
}
function getDependencyTree(thing, property) {
return nodeToDependencyTree(getAtom(thing, property));
}
function nodeToDependencyTree(node) {
var result = {
name: node.name
};
if (node.observing && node.observing.length > 0)
result.dependencies = unique(node.observing).map(nodeToDependencyTree);
return result;
}
function getObserverTree(thing, property) {
return nodeToObserverTree(getAtom(thing, property));
}
function nodeToObserverTree(node) {
var result = {
name: node.name
};
if (hasObservers(node))
result.observers = getObservers(node).map(nodeToObserverTree);
return result;
}
function intercept(thing, propOrHandler, handler) {
if (typeof handler === "function")
return interceptProperty(thing, propOrHandler, handler);
else
return interceptInterceptable(thing, propOrHandler);
}
exports.intercept = intercept;
function interceptInterceptable(thing, handler) {
return getAdministration(thing).intercept(handler);
}
function interceptProperty(thing, property, handler) {
return getAdministration(thing, property).intercept(handler);
}
function isComputed(value, property) {
if (value === null || value === undefined)
return false;
if (property !== undefined) {
if (isObservableObject(value) === false)
return false;
var atom = getAtom(value, property);
return isComputedValue(atom);
}
return isComputedValue(value);
}
exports.isComputed = isComputed;
function isObservable(value, property) {
if (value === null || value === undefined)
return false;
if (property !== undefined) {
if (isObservableArray(value) || isObservableMap(value))
throw new Error(getMessage("m019"));
else if (isObservableObject(value)) {
var o = value.$mobx;
return o.values && !!o.values[property];
}
return false;
}
return isObservableObject(value) || !!value.$mobx || isAtom(value) || isReaction(value) || isComputedValue(value);
}
exports.isObservable = isObservable;
var deepDecorator = createDecoratorForEnhancer(deepEnhancer);
var shallowDecorator = createDecoratorForEnhancer(shallowEnhancer);
var refDecorator = createDecoratorForEnhancer(referenceEnhancer);
var deepStructDecorator = createDecoratorForEnhancer(deepStructEnhancer);
var refStructDecorator = createDecoratorForEnhancer(refStructEnhancer);
function createObservable(v) {
if (v === void 0) { v = undefined; }
if (typeof arguments[1] === "string")
return deepDecorator.apply(null, arguments);
invariant(arguments.length <= 1, getMessage("m021"));
invariant(!isModifierDescriptor(v), getMessage("m020"));
if (isObservable(v))
return v;
var res = deepEnhancer(v, undefined, undefined);
if (res !== v)
return res;
return observable.box(v);
}
var IObservableFactories = (function () {
function IObservableFactories() {
}
IObservableFactories.prototype.box = function (value, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("box");
return new ObservableValue(value, deepEnhancer, name);
};
IObservableFactories.prototype.shallowBox = function (value, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("shallowBox");
return new ObservableValue(value, referenceEnhancer, name);
};
IObservableFactories.prototype.array = function (initialValues, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("array");
return new ObservableArray(initialValues, deepEnhancer, name);
};
IObservableFactories.prototype.shallowArray = function (initialValues, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("shallowArray");
return new ObservableArray(initialValues, referenceEnhancer, name);
};
IObservableFactories.prototype.map = function (initialValues, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("map");
return new ObservableMap(initialValues, deepEnhancer, name);
};
IObservableFactories.prototype.shallowMap = function (initialValues, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("shallowMap");
return new ObservableMap(initialValues, referenceEnhancer, name);
};
IObservableFactories.prototype.object = function (props, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("object");
var res = {};
asObservableObject(res, name);
extendObservable(res, props);
return res;
};
IObservableFactories.prototype.shallowObject = function (props, name) {
if (arguments.length > 2)
incorrectlyUsedAsDecorator("shallowObject");
var res = {};
asObservableObject(res, name);
extendShallowObservable(res, props);
return res;
};
IObservableFactories.prototype.ref = function () {
if (arguments.length < 2) {
return createModifierDescriptor(referenceEnhancer, arguments[0]);
}
else {
return refDecorator.apply(null, arguments);
}
};
IObservableFactories.prototype.shallow = function () {
if (arguments.length < 2) {
return createModifierDescriptor(shallowEnhancer, arguments[0]);
}
else {
return shallowDecorator.apply(null, arguments);
}
};
IObservableFactories.prototype.deep = function () {
if (arguments.length < 2) {
return createModifierDescriptor(deepEnhancer, arguments[0]);
}
else {
return deepDecorator.apply(null, arguments);
}
};
IObservableFactories.prototype.struct = function () {
if (arguments.length < 2) {
return createModifierDescriptor(deepStructEnhancer, arguments[0]);
}
else {
return deepStructDecorator.apply(null, arguments);
}
};
return IObservableFactories;
}());
exports.IObservableFactories = IObservableFactories;
var observable = createObservable;
exports.observable = observable;
Object.keys(IObservableFactories.prototype).forEach(function (key) { return observable[key] = IObservableFactories.prototype[key]; });
observable.deep.struct = observable.struct;
observable.ref.struct = function () {
if (arguments.length < 2) {
return createModifierDescriptor(refStructEnhancer, arguments[0]);
}
else {
return refStructDecorator.apply(null, arguments);
}
};
function incorrectlyUsedAsDecorator(methodName) {
fail("Expected one or two arguments to observable." + methodName + ". Did you accidentally try to use observable." + methodName + " as decorator?");
}
function createDecoratorForEnhancer(enhancer) {
invariant(!!enhancer, ":(");
return createClassPropertyDecorator(function (target, name, baseValue, _, baseDescriptor) {
assertPropertyConfigurable(target, name);
invariant(!baseDescriptor || !baseDescriptor.get, getMessage("m022"));
var adm = asObservableObject(target, undefined);
defineObservableProperty(adm, name, baseValue, enhancer);
}, function (name) {
var observable = this.$mobx.values[name];
if (observable === undefined)
return undefined;
return observable.get();
}, function (name, value) {
setPropertyValue(this, name, value);
}, true, false);
}
function observe(thing, propOrCb, cbOrFire, fireImmediately) {
if (typeof cbOrFire === "function")
return observeObservableProperty(thing, propOrCb, cbOrFire, fireImmediately);
else
return observeObservable(thing, propOrCb, cbOrFire);
}
exports.observe = observe;
function observeObservable(thing, listener, fireImmediately) {
return getAdministration(thing).observe(listener, fireImmediately);
}
function observeObservableProperty(thing, property, listener, fireImmediately) {
return getAdministration(thing, property).observe(listener, fireImmediately);
}
function toJS(source, detectCycles, __alreadySeen) {
if (detectCycles === void 0) { detectCycles = true; }
if (__alreadySeen === void 0) { __alreadySeen = []; }
function cache(value) {
if (detectCycles)
__alreadySeen.push([source, value]);
return value;
}
if (isObservable(source)) {
if (detectCycles && __alreadySeen === null)
__alreadySeen = [];
if (detectCycles && source !== null && typeof source === "object") {
for (var i = 0, l = __alreadySeen.length; i < l; i++)
if (__alreadySeen[i][0] === source)
return __alreadySeen[i][1];
}
if (isObservableArray(source)) {
var res = cache([]);
var toAdd = source.map(function (value) { return toJS(value, detectCycles, __alreadySeen); });
res.length = toAdd.length;
for (var i = 0, l = toAdd.length; i < l; i++)
res[i] = toAdd[i];
return res;
}
if (isObservableObject(source)) {
var res = cache({});
for (var key in source)
res[key] = toJS(source[key], detectCycles, __alreadySeen);
return res;
}
if (isObservableMap(source)) {
var res_1 = cache({});
source.forEach(function (value, key) { return res_1[key] = toJS(value, detectCycles, __alreadySeen); });
return res_1;
}
if (isObservableValue(source))
return toJS(source.get(), detectCycles, __alreadySeen);
}
return source;
}
exports.toJS = toJS;
function transaction(action, thisArg) {
if (thisArg === void 0) { thisArg = undefined; }
deprecated(getMessage("m023"));
return runInTransaction.apply(undefined, arguments);
}
exports.transaction = transaction;
function runInTransaction(action, thisArg) {
if (thisArg === void 0) { thisArg = undefined; }
return executeAction("", action);
}
function log(msg) {
console.log(msg);
return msg;
}
function whyRun(thing, prop) {
switch (arguments.length) {
case 0:
thing = globalState.trackingDerivation;
if (!thing)
return log(getMessage("m024"));
break;
case 2:
thing = getAtom(thing, prop);
break;
}
thing = getAtom(thing);
if (isComputedValue(thing))
return log(thing.whyRun());
else if (isReaction(thing))
return log(thing.whyRun());
return fail(getMessage("m025"));
}
exports.whyRun = whyRun;
function createAction(actionName, fn) {
invariant(typeof fn === "function", getMessage("m026"));
invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'");
var res = function () {
return executeAction(actionName, fn, this, arguments);
};
res.originalFn = fn;
res.isMobxAction = true;
return res;
}
function executeAction(actionName, fn, scope, args) {
var runInfo = startAction(actionName, fn, scope, args);
try {
return fn.apply(scope, args);
}
finally {
endAction(runInfo);
}
}
function startAction(actionName, fn, scope, args) {
var notifySpy = isSpyEnabled() && !!actionName;
var startTime = 0;
if (notifySpy) {
startTime = Date.now();
var l = (args && args.length) || 0;
var flattendArgs = new Array(l);
if (l > 0)
for (var i = 0; i < l; i++)
flattendArgs[i] = args[i];
spyReportStart({
type: "action",
name: actionName,
fn: fn,
object: scope,
arguments: flattendArgs
});
}
var prevDerivation = untrackedStart();
startBatch();
var prevAllowStateChanges = allowStateChangesStart(true);
return {
prevDerivation: prevDerivation,
prevAllowStateChanges: prevAllowStateChanges,
notifySpy: notifySpy,
startTime: startTime
};
}
function endAction(runInfo) {
allowStateChangesEnd(runInfo.prevAllowStateChanges);
endBatch();
untrackedEnd(runInfo.prevDerivation);
if (runInfo.notifySpy)
spyReportEnd({ time: Date.now() - runInfo.startTime });
}
function useStrict(strict) {
invariant(globalState.trackingDerivation === null, getMessage("m028"));
globalState.strictMode = strict;
globalState.allowStateChanges = !strict;
}
exports.useStrict = useStrict;
function isStrictModeEnabled() {
return globalState.strictMode;
}
exports.isStrictModeEnabled = isStrictModeEnabled;
function allowStateChanges(allowStateChanges, func) {
var prev = allowStateChangesStart(allowStateChanges);
var res;
try {
res = func();
}
finally {
allowStateChangesEnd(prev);
}
return res;
}
function allowStateChangesStart(allowStateChanges) {
var prev = globalState.allowStateChanges;
globalState.allowStateChanges = allowStateChanges;
return prev;
}
function allowStateChangesEnd(prev) {
globalState.allowStateChanges = prev;
}
var BaseAtom = (function () {
function BaseAtom(name) {
if (name === void 0) { name = "Atom@" + getNextId(); }
this.name = name;
this.isPendingUnobservation = true;
this.observers = [];
this.observersIndexes = {};
this.diffValue = 0;
this.lastAccessedBy = 0;
this.lowestObserverState = IDerivationState.NOT_TRACKING;
}
BaseAtom.prototype.onBecomeUnobserved = function () {
};
BaseAtom.prototype.reportObserved = function () {
reportObserved(this);
};
BaseAtom.prototype.reportChanged = function () {
startBatch();
propagateChanged(this);
endBatch();
};
BaseAtom.prototype.toString = function () {
return this.name;
};
return BaseAtom;
}());
exports.BaseAtom = BaseAtom;
var Atom = (function (_super) {
__extends(Atom, _super);
function Atom(name, onBecomeObservedHandler, onBecomeUnobservedHandler) {
if (name === void 0) { name = "Atom@" + getNextId(); }
if (onBecomeObservedHandler === void 0) { onBecomeObservedHandler = noop; }
if (onBecomeUnobservedHandler === void 0) { onBecomeUnobservedHandler = noop; }
var _this = _super.call(this, name) || this;
_this.name = name;
_this.onBecomeObservedHandler = onBecomeObservedHandler;
_this.onBecomeUnobservedHandler = onBecomeUnobservedHandler;
_this.isPendingUnobservation = false;
_this.isBeingTracked = false;
return _this;
}
Atom.prototype.reportObserved = function () {
startBatch();
_super.prototype.reportObserved.call(this);
if (!this.isBeingTracked) {
this.isBeingTracked = true;
this.onBecomeObservedHandler();
}
endBatch();
return !!globalState.trackingDerivation;
};
Atom.prototype.onBecomeUnobserved = function () {
this.isBeingTracked = false;
this.onBecomeUnobservedHandler();
};
return Atom;
}(BaseAtom));
exports.Atom = Atom;
var isAtom = createInstanceofPredicate("Atom", BaseAtom);
var ComputedValue = (function () {
function ComputedValue(derivation, scope, compareStructural, name, setter) {
this.derivation = derivation;
this.scope = scope;
this.compareStructural = compareStructural;
this.dependenciesState = IDerivationState.NOT_TRACKING;
this.observing = [];
this.newObserving = null;
this.isPendingUnobservation = false;
this.observers = [];
this.observersIndexes = {};
this.diffValue = 0;
this.runId = 0;
this.lastAccessedBy = 0;
this.lowestObserverState = IDerivationState.UP_TO_DATE;
this.unboundDepsCount = 0;
this.__mapid = "#" + getNextId();
this.value = undefined;
this.isComputing = false;
this.isRunningSetter = false;
this.name = name || "ComputedValue@" + getNextId();
if (setter)
this.setter = createAction(name + "-setter", setter);
}
ComputedValue.prototype.onBecomeStale = function () {
propagateMaybeChanged(this);
};
ComputedValue.prototype.onBecomeUnobserved = function () {
invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, getMessage("m029"));
clearObserving(this);
this.value = undefined;
};
ComputedValue.prototype.get = function () {
invariant(!this.isComputing, "Cycle detected in computation " + this.name, this.derivation);
if (globalState.inBatch === 0) {
startBatch();
if (shouldCompute(this))
this.value = this.computeValue(false);
endBatch();
}
else {
reportObserved(this);
if (shouldCompute(this))
if (this.trackAndCompute())
propagateChangeConfirmed(this);
}
var result = this.value;
if (isCaughtException(result))
throw result.cause;
return result;
};
ComputedValue.prototype.peek = function () {
var res = this.computeValue(false);
if (isCaughtException(res))
throw res.cause;
return res;
};
ComputedValue.prototype.set = function (value) {
if (this.setter) {
invariant(!this.isRunningSetter, "The setter of computed value '" + this.name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?");
this.isRunningSetter = true;
try {
this.setter.call(this.scope, value);
}
finally {
this.isRunningSetter = false;
}
}
else
invariant(false, "[ComputedValue '" + this.name + "'] It is not possible to assign a new value to a computed value.");
};
ComputedValue.prototype.trackAndCompute = function () {
if (isSpyEnabled()) {
spyReport({
object: this.scope,
type: "compute",
fn: this.derivation
});
}
var oldValue = this.value;
var newValue = this.value = this.computeValue(true);
return isCaughtException(newValue) || valueDidChange(this.compareStructural, newValue, oldValue);
};
ComputedValue.prototype.computeValue = function (track) {
this.isComputing = true;
globalState.computationDepth++;
var res;
if (track) {
res = trackDerivedFunction(this, this.derivation, this.scope);
}
else {
try {
res = this.derivation.call(this.scope);
}
catch (e) {
res = new CaughtException(e);
}
}
globalState.computationDepth--;
this.isComputing = false;
return res;
};
;
ComputedValue.prototype.observe = function (listener, fireImmediately) {
var _this = this;
var firstTime = true;
var prevValue = undefined;
return autorun(function () {
var newValue = _this.get();
if (!firstTime || fireImmediately) {
var prevU = untrackedStart();
listener({
type: "update",
object: _this,
newValue: newValue,
oldValue: prevValue
});
untrackedEnd(prevU);
}
firstTime = false;
prevValue = newValue;
});
};
ComputedValue.prototype.toJSON = function () {
return this.get();
};
ComputedValue.prototype.toString = function () {
return this.name + "[" + this.derivation.toString() + "]";
};
ComputedValue.prototype.valueOf = function () {
return toPrimitive(this.get());
};
;
ComputedValue.prototype.whyRun = function () {
var isTracking = Boolean(globalState.trackingDerivation);
var observing = unique(this.isComputing ? this.newObserving : this.observing).map(function (dep) { return dep.name; });
var observers = unique(getObservers(this).map(function (dep) { return dep.name; }));
return ("\nWhyRun? computation '" + this.name + "':\n * Running because: " + (isTracking ? "[active] the value of this computation is needed by a reaction" : this.isComputing ? "[get] The value of this computed was requested outside a reaction" : "[idle] not running at the moment") + "\n" +
(this.dependenciesState === IDerivationState.NOT_TRACKING ? getMessage("m032") :
" * This computation will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + ((this.isComputing && isTracking) ? " (... or any observable accessed during the remainder of the current run)" : "") + "\n\t" + getMessage("m038") + "\n\n * If the outcome of this computation changes, the following observers will be re-run:\n " + joinStrings(observers) + "\n"));
};
return ComputedValue;
}());
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
var IDerivationState;
(function (IDerivationState) {
IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
})(IDerivationState || (IDerivationState = {}));
exports.IDerivationState = IDerivationState;
var CaughtException = (function () {
function CaughtException(cause) {
this.cause = cause;
}
return CaughtException;
}());
function isCaughtException(e) {
return e instanceof CaughtException;
}
function shouldCompute(derivation) {
switch (derivation.dependenciesState) {
case IDerivationState.UP_TO_DATE: return false;
case IDerivationState.NOT_TRACKING:
case IDerivationState.STALE: return true;
case IDerivationState.POSSIBLY_STALE: {
var prevUntracked = untrackedStart();
var obs = derivation.observing, l = obs.length;
for (var i = 0; i < l; i++) {
var obj = obs[i];
if (isComputedValue(obj)) {
try {
obj.get();
}
catch (e) {
untrackedEnd(prevUntracked);
return true;
}
if (derivation.dependenciesState === IDerivationState.STALE) {
untrackedEnd(prevUntracked);
return true;
}
}
}
changeDependenciesStateTo0(derivation);
untrackedEnd(prevUntracked);
return false;
}
}
}
function isComputingDerivation() {
return globalState.trackingDerivation !== null;
}
function checkIfStateModificationsAreAllowed(atom) {
var hasObservers = atom.observers.length > 0;
if (globalState.computationDepth > 0 && hasObservers)
fail(getMessage("m031") + atom.name);
if (!globalState.allowStateChanges && hasObservers)
fail(getMessage(globalState.strictMode ? "m030a" : "m030b") + atom.name);
}
function trackDerivedFunction(derivation, f, context) {
changeDependenciesStateTo0(derivation);
derivation.newObserving = new Array(derivation.observing.length + 100);
derivation.unboundDepsCount = 0;
derivation.runId = ++globalState.runId;
var prevTracking = globalState.trackingDerivation;
globalState.trackingDerivation = derivation;
var result;
try {
result = f.call(context);
}
catch (e) {
result = new CaughtException(e);
}
globalState.trackingDerivation = prevTracking;
bindDependencies(derivation);
return result;
}
function bindDependencies(derivation) {
var prevObserving = derivation.observing;
var observing = derivation.observing = derivation.newObserving;
derivation.newObserving = null;
var i0 = 0, l = derivation.unboundDepsCount;
for (var i = 0; i < l; i++) {
var dep = observing[i];
if (dep.diffValue === 0) {
dep.diffValue = 1;
if (i0 !== i)
observing[i0] = dep;
i0++;
}
}
observing.length = i0;
l = prevObserving.length;
while (l--) {
var dep = prevObserving[l];
if (dep.diffValue === 0) {
removeObserver(dep, derivation);
}
dep.diffValue = 0;
}
while (i0--) {
var dep = observing[i0];
if (dep.diffValue === 1) {
dep.diffValue = 0;
addObserver(dep, derivation);
}
}
}
function clearObserving(derivation) {
var obs = derivation.observing;
var i = obs.length;
while (i--)
removeObserver(obs[i], derivation);
derivation.dependenciesState = IDerivationState.NOT_TRACKING;
obs.length = 0;
}
function untracked(action) {
var prev = untrackedStart();
var res = action();
untrackedEnd(prev);
return res;
}
exports.untracked = untracked;
function untrackedStart() {
var prev = globalState.trackingDerivation;
globalState.trackingDerivation = null;
return prev;
}
function untrackedEnd(prev) {
globalState.trackingDerivation = prev;
}
function changeDependenciesStateTo0(derivation) {
if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
return;
derivation.dependenciesState = IDerivationState.UP_TO_DATE;
var obs = derivation.observing;
var i = obs.length;
while (i--)
obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
}
var persistentKeys = ["mobxGuid", "resetId", "spyListeners", "strictMode", "runId"];
var MobXGlobals = (function () {
function MobXGlobals() {
this.version = 5;
this.trackingDerivation = null;
this.computationDepth = 0;
this.runId = 0;
this.mobxGuid = 0;
this.inBatch = 0;
this.pendingUnobservations = [];
this.pendingReactions = [];
this.isRunningReactions = false;
this.allowStateChanges = true;
this.strictMode = false;
this.resetId = 0;
this.spyListeners = [];
this.globalReactionErrorHandlers = [];
}
return MobXGlobals;
}());
var globalState = new MobXGlobals();
function shareGlobalState() {
var global = getGlobal();
var ownState = globalState;
if (global.__mobservableTrackingStack || global.__mobservableViewStack)
throw new Error("[mobx] An incompatible version of mobservable is already loaded.");
if (global.__mobxGlobal && global.__mobxGlobal.version !== ownState.version)
throw new Error("[mobx] An incompatible version of mobx is already loaded.");
if (global.__mobxGlobal)
globalState = global.__mobxGlobal;
else
global.__mobxGlobal = ownState;
}
function getGlobalState() {
return globalState;
}
function registerGlobals() {
}
function resetGlobalState() {
globalState.resetId++;
var defaultGlobals = new MobXGlobals();
for (var key in defaultGlobals)
if (persistentKeys.indexOf(key) === -1)
globalState[key] = defaultGlobals[key];
globalState.allowStateChanges = !globalState.strictMode;
}
function hasObservers(observable) {
return observable.observers && observable.observers.length > 0;
}
function getObservers(observable) {
return observable.observers;
}
function invariantObservers(observable) {
var list = observable.observers;
var map = observable.observersIndexes;
var l = list.length;
for (var i = 0; i < l; i++) {
var id = list[i].__mapid;
if (i) {
invariant(map[id] === i, "INTERNAL ERROR maps derivation.__mapid to index in list");
}
else {
invariant(!(id in map), "INTERNAL ERROR observer on index 0 shouldnt be held in map.");
}
}
invariant(list.length === 0 || Object.keys(map).length === list.length - 1, "INTERNAL ERROR there is no junk in map");
}
function addObserver(observable, node) {
var l = observable.observers.length;
if (l) {
observable.observersIndexes[node.__mapid] = l;
}
observable.observers[l] = node;
if (observable.lowestObserverState > node.dependenciesState)
observable.lowestObserverState = node.dependenciesState;
}
function removeObserver(observable, node) {
if (observable.observers.length === 1) {
observable.observers.length = 0;
queueForUnobservation(observable);
}
else {
var list = observable.observers;
var map_1 = observable.observersIndexes;
var filler = list.pop();
if (filler !== node) {
var index = map_1[node.__mapid] || 0;
if (index) {
map_1[filler.__mapid] = index;
}
else {
delete map_1[filler.__mapid];
}
list[index] = filler;
}
delete map_1[node.__mapid];
}
}
function queueForUnobservation(observable) {
if (!observable.isPendingUnobservation) {
observable.isPendingUnobservation = true;
globalState.pendingUnobservations.push(observable);
}
}
function startBatch() {
globalState.inBatch++;
}
function endBatch() {
if (--globalState.inBatch === 0) {
runReactions();
var list = globalState.pendingUnobservations;
for (var i = 0; i < list.length; i++) {
var observable_1 = list[i];
observable_1.isPendingUnobservation = false;
if (observable_1.observers.length === 0) {
observable_1.onBecomeUnobserved();
}
}
globalState.pendingUnobservations = [];
}
}
function reportObserved(observable) {
var derivation = globalState.trackingDerivation;
if (derivation !== null) {
if (derivation.runId !== observable.lastAccessedBy) {
observable.lastAccessedBy = derivation.runId;
derivation.newObserving[derivation.unboundDepsCount++] = observable;
}
}
else if (observable.observers.length === 0) {
queueForUnobservation(observable);
}
}
function invariantLOS(observable, msg) {
var min = getObservers(observable).reduce(function (a, b) { return Math.min(a, b.dependenciesState); }, 2);
if (min >= observable.lowestObserverState)
return;
throw new Error("lowestObserverState is wrong for " + msg + " because " + min + " < " + observable.lowestObserverState);
}
function propagateChanged(observable) {
if (observable.lowestObserverState === IDerivationState.STALE)
return;
observable.lowestObserverState = IDerivationState.STALE;
var observers = observable.observers;
var i = observers.length;
while (i--) {
var d = observers[i];
if (d.dependenciesState === IDerivationState.UP_TO_DATE)
d.onBecomeStale();
d.dependenciesState = IDerivationState.STALE;
}
}
function propagateChangeConfirmed(observable) {
if (observable.lowestObserverState === IDerivationState.STALE)
return;
observable.lowestObserverState = IDerivationState.STALE;
var observers = observable.observers;
var i = observers.length;
while (i--) {
var d = observers[i];
if (d.dependenciesState === IDerivationState.POSSIBLY_STALE)
d.dependenciesState = IDerivationState.STALE;
else if (d.dependenciesState === IDerivationState.UP_TO_DATE)
observable.lowestObserverState = IDerivationState.UP_TO_DATE;
}
}
function propagateMaybeChanged(observable) {
if (observable.lowestObserverState !== IDerivationState.UP_TO_DATE)
return;
observable.lowestObserverState = IDerivationState.POSSIBLY_STALE;
var observers = observable.observers;
var i = observers.length;
while (i--) {
var d = observers[i];
if (d.dependenciesState === IDerivationState.UP_TO_DATE) {
d.dependenciesState = IDerivationState.POSSIBLY_STALE;
d.onBecomeStale();
}
}
}
var Reaction = (function () {
function Reaction(name, onInvalidate) {
if (name === void 0) { name = "Reaction@" + getNextId(); }
this.name = name;
this.onInvalidate = onInvalidate;
this.observing = [];
this.newObserving = [];
this.dependenciesState = IDerivationState.NOT_TRACKING;
this.diffValue = 0;
this.runId = 0;
this.unboundDepsCount = 0;
this.__mapid = "#" + getNextId();
this.isDisposed = false;
this._isScheduled = false;
this._isTrackPending = false;
this._isRunning = false;
}
Reaction.prototype.onBecomeStale = function () {
this.schedule();
};
Reaction.prototype.schedule = function () {
if (!this._isScheduled) {
this._isScheduled = true;
globalState.pendingReactions.push(this);
runReactions();
}
};
Reaction.prototype.isScheduled = function () {
return this._isScheduled;
};
Reaction.prototype.runReaction = function () {
if (!this.isDisposed) {
startBatch();
this._isScheduled = false;
if (shouldCompute(this)) {
this._isTrackPending = true;
this.onInvalidate();
if (this._isTrackPending && isSpyEnabled()) {
spyReport({
object: this,
type: "scheduled-reaction"
});
}
}
endBatch();
}
};
Reaction.prototype.track = function (fn) {
startBatch();
var notify = isSpyEnabled();
var startTime;
if (notify) {
startTime = Date.now();
spyReportStart({
object: this,
type: "reaction",
fn: fn
});
}
this._isRunning = true;
var result = trackDerivedFunction(this, fn, undefined);
this._isRunning = false;
this._isTrackPending = false;
if (this.isDisposed) {
clearObserving(this);
}
if (isCaughtException(result))
this.reportExceptionInDerivation(result.cause);
if (notify) {
spyReportEnd({
time: Date.now() - startTime
});
}
endBatch();
};
Reaction.prototype.reportExceptionInDerivation = function (error) {
var _this = this;
if (this.errorHandler) {
this.errorHandler(error, this);
return;
}
var message = "[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '" + this;
var messageToUser = getMessage("m037");
console.error(message || messageToUser, error);
if (isSpyEnabled()) {
spyReport({
type: "error",
message: message,
error: error,
object: this
});
}
globalState.globalReactionErrorHandlers.forEach(function (f) { return f(error, _this); });
};
Reaction.prototype.dispose = function () {
if (!this.isDisposed) {
this.isDisposed = true;
if (!this._isRunning) {
startBatch();
clearObserving(this);
endBatch();
}
}
};
Reaction.prototype.getDisposer = function () {
var r = this.dispose.bind(this);
r.$mobx = this;
r.onError = registerErrorHandler;
return r;
};
Reaction.prototype.toString = function () {
return "Reaction[" + this.name + "]";
};
Reaction.prototype.whyRun = function () {
var observing = unique(this._isRunning ? this.newObserving : this.observing).map(function (dep) { return dep.name; });
return ("\nWhyRun? reaction '" + this.name + "':\n * Status: [" + (this.isDisposed ? "stopped" : this._isRunning ? "running" : this.isScheduled() ? "scheduled" : "idle") + "]\n * This reaction will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + ((this._isRunning) ? " (... or any observable accessed during the remainder of the current run)" : "") + "\n\t" + getMessage("m038") + "\n");
};
return Reaction;
}());
exports.Reaction = Reaction;
function registerErrorHandler(handler) {
invariant(this && this.$mobx && isReaction(this.$mobx), "Invalid `this`");
invariant(!this.$mobx.errorHandler, "Only one onErrorHandler can be registered");
this.$mobx.errorHandler = handler;
}
function onReactionError(handler) {
globalState.globalReactionErrorHandlers.push(handler);
return function () {
var idx = globalState.globalReactionErrorHandlers.indexOf(handler);
if (idx >= 0)
globalState.globalReactionErrorHandlers.splice(idx, 1);
};
}
var MAX_REACTION_ITERATIONS = 100;
var reactionScheduler = function (f) { return f(); };
function runReactions() {
if (globalState.inBatch > 0 || globalState.isRunningReactions)
return;
reactionScheduler(runReactionsHelper);
}
function runReactionsHelper() {
globalState.isRunningReactions = true;
var allReactions = globalState.pendingReactions;
var iterations = 0;
while (allReactions.length > 0) {
if (++iterations === MAX_REACTION_ITERATIONS) {
console.error("Reaction doesn't converge to a stable state after " + MAX_REACTION_ITERATIONS + " iterations."
+ (" Probably there is a cycle in the reactive function: " + allReactions[0]));
allReactions.splice(0);
}
var remainingReactions = allReactions.splice(0);
for (var i = 0, l = remainingReactions.length; i < l; i++)
remainingReactions[i].runReaction();
}
globalState.isRunningReactions = false;
}
var isReaction = createInstanceofPredicate("Reaction", Reaction);
function setReactionScheduler(fn) {
var baseScheduler = reactionScheduler;
reactionScheduler = function (f) { return fn(function () { return baseScheduler(f); }); };
}
function isSpyEnabled() {
return !!globalState.spyListeners.length;
}
function spyReport(event) {
if (!globalState.spyListeners.length)
return;
var listeners = globalState.spyListeners;
for (var i = 0, l = listeners.length; i < l; i++)
listeners[i](event);
}
function spyReportStart(event) {
var change = objectAssign({}, event, { spyReportStart: true });
spyReport(change);
}
var END_EVENT = { spyReportEnd: true };
function spyReportEnd(change) {
if (change)
spyReport(objectAssign({}, change, END_EVENT));
else
spyReport(END_EVENT);
}
function spy(listener) {
globalState.spyListeners.push(listener);
return once(function () {
var idx = globalState.spyListeners.indexOf(listener);
if (idx !== -1)
globalState.spyListeners.splice(idx, 1);
});
}
exports.spy = spy;
function hasInterceptors(interceptable) {
return (interceptable.interceptors && interceptable.interceptors.length > 0);
}
function registerInterceptor(interceptable, handler) {
var interceptors = interceptable.interceptors || (interceptable.interceptors = []);
interceptors.push(handler);
return once(function () {
var idx = interceptors.indexOf(handler);
if (idx !== -1)
interceptors.splice(idx, 1);
});
}
function interceptChange(interceptable, change) {
var prevU = untrackedStart();
try {
var interceptors = interceptable.interceptors;
if (interceptors)
for (var i = 0, l = interceptors.length; i < l; i++) {
change = interceptors[i](change);
invariant(!change || change.type, "Intercept handlers should return nothing or a change object");
if (!change)
break;
}
return change;
}
finally {
untrackedEnd(prevU);
}
}
function hasListeners(listenable) {
return listenable.changeListeners && listenable.changeListeners.length > 0;
}
function registerListener(listenable, handler) {
var listeners = listenable.changeListeners || (listenable.changeListeners = []);
listeners.push(handler);
return once(function () {
var idx = listeners.indexOf(handler);
if (idx !== -1)
listeners.splice(idx, 1);
});
}
function notifyListeners(listenable, change) {
var prevU = untrackedStart();
var listeners = listenable.changeListeners;
if (!listeners)
return;
listeners = listeners.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i](change);
}
untrackedEnd(prevU);
}
function asReference(value) {
deprecated("asReference is deprecated, use observable.ref instead");
return observable.ref(value);
}
exports.asReference = asReference;
function asStructure(value) {
deprecated("asStructure is deprecated. Use observable.struct, computed.struct or reaction options instead.");
return observable.struct(value);
}
exports.asStructure = asStructure;
function asFlat(value) {
deprecated("asFlat is deprecated, use observable.shallow instead");
return observable.shallow(value);
}
exports.asFlat = asFlat;
function asMap(data) {
deprecated("asMap is deprecated, use observable.map or observable.shallowMap instead");
return observable.map(data || {});
}
exports.asMap = asMap;
function isModifierDescriptor(thing) {
return typeof thing === "object" && thing !== null && thing.isMobxModifierDescriptor === true;
}
exports.isModifierDescriptor = isModifierDescriptor;
function createModifierDescriptor(enhancer, initialValue) {
invariant(!isModifierDescriptor(initialValue), "Modifiers cannot be nested");
return {
isMobxModifierDescriptor: true,
initialValue: initialValue,
enhancer: enhancer
};
}
function deepEnhancer(v, _, name) {
if (isModifierDescriptor(v))
fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it");
if (isObservable(v))
return v;
if (Array.isArray(v))
return observable.array(v, name);
if (isPlainObject(v))
return observable.object(v, name);
if (isES6Map(v))
return observable.shallowMap(v, name);
return v;
}
function shallowEnhancer(v, _, name) {
if (isModifierDescriptor(v))
fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it");
if (v === undefined || v === null)
return v;
if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v))
return v;
if (Array.isArray(v))
return observable.shallowArray(v, name);
if (isPlainObject(v))
return observable.shallowObject(v, name);
if (isES6Map(v))
return observable.shallowMap(v, name);
return fail("The shallow modifier / decorator can only used in combination with arrays, objects and maps");
}
function referenceEnhancer(newValue) {
return newValue;
}
function deepStructEnhancer(v, oldValue, name) {
if (deepEqual(v, oldValue))
return oldValue;
if (isObservable(v))
return v;
if (Array.isArray(v))
return new ObservableArray(v, deepStructEnhancer, name);
if (isES6Map(v))
return new ObservableMap(v, deepStructEnhancer, name);
if (isPlainObject(v)) {
var res = {};
asObservableObject(res, name);
extendObservableHelper(res, deepStructEnhancer, [v]);
return res;
}
return v;
}
function refStructEnhancer(v, oldValue, name) {
if (deepEqual(v, oldValue))
return oldValue;
return v;
}
var safariPrototypeSetterInheritanceBug = (function () {
var v = false;
var p = {};
Object.defineProperty(p, "0", { set: function () { v = true; } });
Object.create(p)["0"] = 1;
return v === false;
})();
var OBSERVABLE_ARRAY_BUFFER_SIZE = 0;
var StubArray = (function () {
function StubArray() {
}
return StubArray;
}());
StubArray.prototype = [];
var ObservableArrayAdministration = (function () {
function ObservableArrayAdministration(name, enhancer, array, owned) {
this.array = array;
this.owned = owned;
this.lastKnownLength = 0;
this.interceptors = null;
this.changeListeners = null;
this.atom = new BaseAtom(name || ("ObservableArray@" + getNextId()));
this.enhancer = function (newV, oldV) { return enhancer(newV, oldV, name + "[..]"); };
}
ObservableArrayAdministration.prototype.intercept = function (handler) {
return registerInterceptor(this, handler);
};
ObservableArrayAdministration.prototype.observe = function (listener, fireImmediately) {
if (fireImmediately === void 0) { fireImmediately = false; }
if (fireImmediately) {
listener({
object: this.array,
type: "splice",
index: 0,
added: this.values.slice(),
addedCount: this.values.length,
removed: [],
removedCount: 0
});
}
return registerListener(this, listener);
};
ObservableArrayAdministration.prototype.getArrayLength = function () {
this.atom.reportObserved();
return this.values.length;
};
ObservableArrayAdministration.prototype.setArrayLength = function (newLength) {
if (typeof newLength !== "number" || newLength < 0)
throw new Error("[mobx.array] Out of range: " + newLength);
var currentLength = this.values.length;
if (newLength === currentLength)
return;
else if (newLength > currentLength)
this.spliceWithArray(currentLength, 0, new Array(newLength - currentLength));
else
this.spliceWithArray(newLength, currentLength - newLength);
};
ObservableArrayAdministration.prototype.updateArrayLength = function (oldLength, delta) {
if (oldLength !== this.lastKnownLength)
throw new Error("[mobx] Modification exception: the internal structure of an observable array was changed. Did you use peek() to change it?");
this.lastKnownLength += delta;
if (delta > 0 && oldLength + delta + 1 > OBSERVABLE_ARRAY_BUFFER_SIZE)
reserveArrayBuffer(oldLength + delta + 1);
};
ObservableArrayAdministration.prototype.spliceWithArray = function (index, deleteCount, newItems) {
var _this = this;
checkIfStateModificationsAreAllowed(this.atom);
var length = this.values.length;
if (index === undefined)
index = 0;
else if (index > length)
index = length;
else if (index < 0)
index = Math.max(0, length + index);
if (arguments.length === 1)
deleteCount = length - index;
else if (deleteCount === undefined || deleteCount === null)
deleteCount = 0;
else
deleteCount = Math.max(0, Math.min(deleteCount, length - index));
if (newItems === undefined)
newItems = [];
if (hasInterceptors(this)) {
var change = interceptChange(this, {
object: this.array,
type: "splice",
index: index,
removedCount: deleteCount,
added: newItems
});
if (!change)
return EMPTY_ARRAY;
deleteCount = change.removedCount;
newItems = change.added;
}
newItems = newItems.map(function (v) { return _this.enhancer(v, undefined); });
var lengthDelta = newItems.length - deleteCount;
this.updateArrayLength(length, lengthDelta);
var res = (_a = this.values).splice.apply(_a, [index, deleteCount].concat(newItems));
if (deleteCount !== 0 || newItems.length !== 0)
this.notifyArraySplice(index, newItems, res);
return res;
var _a;
};
ObservableArrayAdministration.prototype.notifyArrayChildUpdate = function (index, newValue, oldValue) {
var notifySpy = !this.owned && isSpyEnabled();
var notify = hasListeners(this);
var change = notify || notifySpy ? {
object: this.array,
type: "update",
index: index, newValue: newValue, oldValue: oldValue
} : null;
if (notifySpy)
spyReportStart(change);
this.atom.reportChanged();
if (notify)
notifyListeners(this, change);
if (notifySpy)
spyReportEnd();
};
ObservableArrayAdministration.prototype.notifyArraySplice = function (index, added, removed) {
var notifySpy = !this.owned && isSpyEnabled();
var notify = hasListeners(this);
var change = notify || notifySpy ? {
object: this.array,
type: "splice",
index: index, removed: removed, added: added,
removedCount: removed.length,
addedCount: added.length
} : null;
if (notifySpy)
spyReportStart(change);
this.atom.reportChanged();
if (notify)
notifyListeners(this, change);
if (notifySpy)
spyReportEnd();
};
return ObservableArrayAdministration;
}());
var ObservableArray = (function (_super) {
__extends(ObservableArray, _super);
function ObservableArray(initialValues, enhancer, name, owned) {
if (name === void 0) { name = "ObservableArray@" + getNextId(); }
if (owned === void 0) { owned = false; }
var _this = _super.call(this) || this;
var adm = new ObservableArrayAdministration(name, enhancer, _this, owned);
addHiddenFinalProp(_this, "$mobx", adm);
if (initialValues && initialValues.length) {
adm.updateArrayLength(0, initialValues.length);
adm.values = initialValues.map(function (v) { return enhancer(v, undefined, name + "[..]"); });
adm.notifyArraySplice(0, adm.values.slice(), EMPTY_ARRAY);
}
else {
adm.values = [];
}
if (safariPrototypeSetterInheritanceBug) {
Object.defineProperty(adm.array, "0", ENTRY_0);
}
return _this;
}
ObservableArray.prototype.intercept = function (handler) {
return this.$mobx.intercept(handler);
};
ObservableArray.prototype.observe = function (listener, fireImmediately) {
if (fireImmediately === void 0) { fireImmediately = false; }
return this.$mobx.observe(listener, fireImmediately);
};
ObservableArray.prototype.clear = function () {
return this.splice(0);
};
ObservableArray.prototype.concat = function () {
var arrays = [];
for (var _i = 0; _i < arguments.length; _i++) {
arrays[_i] = arguments[_i];
}
this.$mobx.atom.reportObserved();
return Array.prototype.concat.apply(this.peek(), arrays.map(function (a) { return isObservableArray(a) ? a.peek() : a; }));
};
ObservableArray.prototype.replace = function (newItems) {
return this.$mobx.spliceWithArray(0, this.$mobx.values.length, newItems);
};
ObservableArray.prototype.toJS = function () {
return this.slice();
};
ObservableArray.prototype.toJSON = function () {
return this.toJS();
};
ObservableArray.prototype.peek = function () {
return this.$mobx.values;
};
ObservableArray.prototype.find = function (predicate, thisArg, fromIndex) {
if (fromIndex === void 0) { fromIndex = 0; }
this.$mobx.atom.reportObserved();
var items = this.$mobx.values, l = items.length;
for (var i = fromIndex; i < l; i++)
if (predicate.call(thisArg, items[i], i, this))
return items[i];
return undefined;
};
ObservableArray.prototype.splice = function (index, deleteCount) {
var newItems = [];
for (var _i = 2; _i < arguments.length; _i++) {
newItems[_i - 2] = arguments[_i];
}
switch (arguments.length) {
case 0:
return [];
case 1:
return this.$mobx.spliceWithArray(index);
case 2:
return this.$mobx.spliceWithArray(index, deleteCount);
}
return this.$mobx.spliceWithArray(index, deleteCount, newItems);
};
ObservableArray.prototype.push = function () {
var items = [];
for (var _i = 0; _i < arguments.length; _i++) {
items[_i] = arguments[_i];
}
var adm = this.$mobx;
adm.spliceWithArray(adm.values.length, 0, items);
return adm.values.length;
};
ObservableArray.prototype.pop = function () {
return this.splice(Math.max(this.$mobx.values.length - 1, 0), 1)[0];
};
ObservableArray.prototype.shift = function () {
return this.splice(0, 1)[0];
};
ObservableArray.prototype.unshift = function () {
var items = [];
for (var _i = 0; _i < arguments.length; _i++) {
items[_i] = arguments[_i];
}
var adm = this.$mobx;
adm.spliceWithArray(0, 0, items);
return adm.values.length;
};
ObservableArray.prototype.reverse = function () {
this.$mobx.atom.reportObserved();
var clone = this.slice();
return clone.reverse.apply(clone, arguments);
};
ObservableArray.prototype.sort = function (compareFn) {
this.$mobx.atom.reportObserved();
var clone = this.slice();
return clone.sort.apply(clone, arguments);
};
ObservableArray.prototype.remove = function (value) {
var idx = this.$mobx.values.indexOf(value);
if (idx > -1) {
this.splice(idx, 1);
return true;
}
return false;
};
ObservableArray.prototype.move = function (fromIndex, toIndex) {
function checkIndex(index) {
if (index < 0) {
throw new Error("[mobx.array] Index out of bounds: " + index + " is negative");
}
var length = this.$mobx.values.length;
if (index >= length) {
throw new Error("[mobx.array] Index out of bounds: " + index + " is not smaller than " + length);
}
}
checkIndex.call(this, fromIndex);
checkIndex.call(this, toIndex);
if (fromIndex === toIndex) {
return;
}
var oldItems = this.$mobx.values;
var newItems;
if (fromIndex < toIndex) {
newItems = oldItems.slice(0, fromIndex).concat(oldItems.slice(fromIndex + 1, toIndex + 1), [oldItems[fromIndex]], oldItems.slice(toIndex + 1));
}
else {
newItems = oldItems.slice(0, toIndex).concat([oldItems[fromIndex]], oldItems.slice(toIndex, fromIndex), oldItems.slice(fromIndex + 1));
}
this.replace(newItems);
};
ObservableArray.prototype.toString = function () {
this.$mobx.atom.reportObserved();
return Array.prototype.toString.apply(this.$mobx.values, arguments);
};
ObservableArray.prototype.toLocaleString = function () {
this.$mobx.atom.reportObserved();
return Array.prototype.toLocaleString.apply(this.$mobx.values, arguments);
};
return ObservableArray;
}(StubArray));
declareIterator(ObservableArray.prototype, function () {
return arrayAsIterator(this.slice());
});
makeNonEnumerable(ObservableArray.prototype, [
"constructor",
"intercept",
"observe",
"clear",
"concat",
"replace",
"toJS",
"toJSON",
"peek",
"find",
"splice",
"push",
"pop",
"shift",
"unshift",
"reverse",
"sort",
"remove",
"move",
"toString",
"toLocaleString"
]);
Object.defineProperty(ObservableArray.prototype, "length", {
enumerable: false,
configurable: true,
get: function () {
return this.$mobx.getArrayLength();
},
set: function (newLength) {
this.$mobx.setArrayLength(newLength);
}
});
[
"every",
"filter",
"forEach",
"indexOf",
"join",
"lastIndexOf",
"map",
"reduce",
"reduceRight",
"slice",
"some"
].forEach(function (funcName) {
var baseFunc = Array.prototype[funcName];
invariant(typeof baseFunc === "function", "Base function not defined on Array prototype: '" + funcName + "'");
addHiddenProp(ObservableArray.prototype, funcName, function () {
this.$mobx.atom.reportObserved();
return baseFunc.apply(this.$mobx.values, arguments);
});
});
var ENTRY_0 = {
configurable: true,
enumerable: false,
set: createArraySetter(0),
get: createArrayGetter(0)
};
function createArrayBufferItem(index) {
var set = createArraySetter(index);
var get = createArrayGetter(index);
Object.defineProperty(ObservableArray.prototype, "" + index, {
enumerable: false,
configurable: true,
set: set, get: get
});
}
function createArraySetter(index) {
return function (newValue) {
var adm = this.$mobx;
var values = adm.values;
if (index < values.length) {
checkIfStateModificationsAreAllowed(adm.atom);
var oldValue = values[index];
if (hasInterceptors(adm)) {
var change = interceptChange(adm, {
type: "update",
object: adm.array,
index: index, newValue: newValue
});
if (!change)
return;
newValue = change.newValue;
}
newValue = adm.enhancer(newValue, oldValue);
var changed = newValue !== oldValue;
if (changed) {
values[index] = newValue;
adm.notifyArrayChildUpdate(index, newValue, oldValue);
}
}
else if (index === values.length) {
adm.spliceWithArray(index, 0, [newValue]);
}
else
throw new Error("[mobx.array] Index out of bounds, " + index + " is larger than " + values.length);
};
}
function createArrayGetter(index) {
return function () {
var impl = this.$mobx;
if (impl) {
if (index < impl.values.length) {
impl.atom.reportObserved();
return impl.values[index];
}
console.warn("[mobx.array] Attempt to read an array index (" + index + ") that is out of bounds (" + impl.values.length + "). Please check length first. Out of bound indices will not be tracked by MobX");
}
return undefined;
};
}
function reserveArrayBuffer(max) {
for (var index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max; index++)
createArrayBufferItem(index);
OBSERVABLE_ARRAY_BUFFER_SIZE = max;
}
reserveArrayBuffer(1000);
var isObservableArrayAdministration = createInstanceofPredicate("ObservableArrayAdministration", ObservableArrayAdministration);
function isObservableArray(thing) {
return isObject(thing) && isObservableArrayAdministration(thing.$mobx);
}
exports.isObservableArray = isObservableArray;
var ObservableMapMarker = {};
var ObservableMap = (function () {
function ObservableMap(initialData, enhancer, name) {
if (enhancer === void 0) { enhancer = deepEnhancer; }
if (name === void 0) { name = "ObservableMap@" + getNextId(); }
this.enhancer = enhancer;
this.name = name;
this.$mobx = ObservableMapMarker;
this._data = {};
this._hasMap = {};
this._keys = new ObservableArray(undefined, referenceEnhancer, this.name + ".keys()", true);
this.interceptors = null;
this.changeListeners = null;
this.merge(initialData);
}
ObservableMap.prototype._has = function (key) {
return typeof this._data[key] !== "undefined";
};
ObservableMap.prototype.has = function (key) {
if (!this.isValidKey(key))
return false;
key = "" + key;
if (this._hasMap[key])
return this._hasMap[key].get();
return this._updateHasMapEntry(key, false).get();
};
ObservableMap.prototype.set = function (key, value) {
this.assertValidKey(key);
key = "" + key;
var hasKey = this._has(key);
if (hasInterceptors(this)) {
var change = interceptChange(this, {
type: hasKey ? "update" : "add",
object: this,
newValue: value,
name: key
});
if (!change)
return this;
value = change.newValue;
}
if (hasKey) {
this._updateValue(key, value);
}
else {
this._addValue(key, value);
}
return this;
};
ObservableMap.prototype.delete = function (key) {
var _this = this;
this.assertValidKey(key);
key = "" + key;
if (hasInterceptors(this)) {
var change = interceptChange(this, {
type: "delete",
object: this,
name: key
});
if (!change)
return false;
}
if (this._has(key)) {
var notifySpy = isSpyEnabled();
var notify = hasListeners(this);
var change = notify || notifySpy ? {
type: "delete",
object: this,
oldValue: this._data[key].value,
name: key
} : null;
if (notifySpy)
spyReportStart(change);
runInTransaction(function () {
_this._keys.remove(key);
_this._updateHasMapEntry(key, false);
var observable = _this._data[key];
observable.setNewValue(undefined);
_this._data[key] = undefined;
});
if (notify)
notifyListeners(this, change);
if (notifySpy)
spyReportEnd();
return true;
}
return false;
};
ObservableMap.prototype._updateHasMapEntry = function (key, value) {
var entry = this._hasMap[key];
if (entry) {
entry.setNewValue(value);
}
else {
entry = this._hasMap[key] = new ObservableValue(value, referenceEnhancer, this.name + "." + key + "?", false);
}
return entry;
};
ObservableMap.prototype._updateValue = function (name, newValue) {
var observable = this._data[name];
newValue = observable.prepareNewValue(newValue);
if (newValue !== UNCHANGED) {
var notifySpy = isSpyEnabled();
var notify = hasListeners(this);
var change = notify || notifySpy ? {
type: "update",
object: this,
oldValue: observable.value,
name: name, newValue: newValue
} : null;
if (notifySpy)
spyReportStart(change);
observable.setNewValue(newValue);
if (notify)
notifyListeners(this, change);
if (notifySpy)
spyReportEnd();
}
};
ObservableMap.prototype._addValue = function (name, newValue) {
var _this = this;
runInTransaction(function () {
var observable = _this._data[name] = new ObservableValue(newValue, _this.enhancer, _this.name + "." + name, false);
newValue = observable.value;
_this._updateHasMapEntry(name, true);
_this._keys.push(name);
});
var notifySpy = isSpyEnabled();
var notify = hasListeners(this);
var change = notify || notifySpy ? {
type: "add",
object: this,
name: name, newValue: newValue
} : null;
if (notifySpy)
spyReportStart(change);
if (notify)
notifyListeners(this, change);
if (notifySpy)
spyReportEnd();
};
ObservableMap.prototype.get = function (key) {
key = "" + key;
if (this.has(key))
return this._data[key].get();
return undefined;
};
ObservableMap.prototype.keys = function () {
return arrayAsIterator(this._keys.slice());
};
ObservableMap.prototype.values = function () {
return arrayAsIterator(this._keys.map(this.get, this));
};
ObservableMap.prototype.entries = function () {
var _this = this;
return arrayAsIterator(this._keys.map(function (key) { return [key, _this.get(key)]; }));
};
ObservableMap.prototype.forEach = function (callback, thisArg) {
var _this = this;
this.keys().forEach(function (key) { return callback.call(thisArg, _this.get(key), key, _this); });
};
ObservableMap.prototype.merge = function (other) {
var _this = this;
if (isObservableMap(other)) {
other = other.toJS();
}
runInTransaction(function () {
if (isPlainObject(other))
Object.keys(other).forEach(function (key) { return _this.set(key, other[key]); });
else if (Array.isArray(other))
other.forEach(function (_a) {
var key = _a[0], value = _a[1];
return _this.set(key, value);
});
else if (isES6Map(other))
other.forEach(function (value, key) { return _this.set(key, value); });
else if (other !== null && other !== undefined)
fail("Cannot initialize map from " + other);
});
return this;
};
ObservableMap.prototype.clear = function () {
var _this = this;
runInTransaction(function () {
untracked(function () {
_this.keys().forEach(_this.delete, _this);
});
});
};
ObservableMap.prototype.replace = function (values) {
var _this = this;
runInTransaction(function () {
_this.clear();
_this.merge(values);
});
return this;
};
Object.defineProperty(ObservableMap.prototype, "size", {
get: function () {
return this._keys.length;
},
enumerable: true,
configurable: true
});
ObservableMap.prototype.toJS = function () {
var _this = this;
var res = {};
this.keys().forEach(function (key) { return res[key] = _this.get(key); });
return res;
};
ObservableMap.prototype.toJSON = function () {
return this.toJS();
};
ObservableMap.prototype.isValidKey = function (key) {
if (key === null || key === undefined)
return false;
if (typeof key === "string" || typeof key === "number" || typeof key === "boolean")
return true;
return false;
};
ObservableMap.prototype.assertValidKey = function (key) {
if (!this.isValidKey(key))
throw new Error("[mobx.map] Invalid key: '" + key + "', only strings, numbers and booleans are accepted as key in observable maps.");
};
ObservableMap.prototype.toString = function () {
var _this = this;
return this.name + "[{ " + this.keys().map(function (key) { return key + ": " + ("" + _this.get(key)); }).join(", ") + " }]";
};
ObservableMap.prototype.observe = function (listener, fireImmediately) {
invariant(fireImmediately !== true, getMessage("m033"));
return registerListener(this, listener);
};
ObservableMap.prototype.intercept = function (handler) {
return registerInterceptor(this, handler);
};
return ObservableMap;
}());
exports.ObservableMap = ObservableMap;
declareIterator(ObservableMap.prototype, function () {
return this.entries();
});
function map(initialValues) {
deprecated("`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead");
return observable.map(initialValues);
}
exports.map = map;
var isObservableMap = createInstanceofPredicate("ObservableMap", ObservableMap);
exports.isObservableMap = isObservableMap;
var ObservableObjectAdministration = (function () {
function ObservableObjectAdministration(target, name) {
this.target = target;
this.name = name;
this.values = {};
this.changeListeners = null;
this.interceptors = null;
}
ObservableObjectAdministration.prototype.observe = function (callback, fireImmediately) {
invariant(fireImmediately !== true, "`observe` doesn't support the fire immediately property for observable objects.");
return registerListener(this, callback);
};
ObservableObjectAdministration.prototype.intercept = function (handler) {
return registerInterceptor(this, handler);
};
return ObservableObjectAdministration;
}());
function asObservableObject(target, name) {
if (isObservableObject(target))
return target.$mobx;
invariant(Object.isExtensible(target), getMessage("m035"));
if (!isPlainObject(target))
name = (target.constructor.name || "ObservableObject") + "@" + getNextId();
if (!name)
name = "ObservableObject@" + getNextId();
var adm = new ObservableObjectAdministration(target, name);
addHiddenFinalProp(target, "$mobx", adm);
return adm;
}
function defineObservablePropertyFromDescriptor(adm, propName, descriptor, defaultEnhancer) {
if (adm.values[propName]) {
invariant("value" in descriptor, "The property " + propName + " in " + adm.name + " is already observable, cannot redefine it as computed property");
adm.target[propName] = descriptor.value;
return;
}
if ("value" in descriptor) {
if (isModifierDescriptor(descriptor.value)) {
var modifierDescriptor = descriptor.value;
defineObservableProperty(adm, propName, modifierDescriptor.initialValue, modifierDescriptor.enhancer);
}
else if (isAction(descriptor.value) && descriptor.value.autoBind === true) {
defineBoundAction(adm.target, propName, descriptor.value.originalFn);
}
else if (isComputedValue(descriptor.value)) {
defineComputedPropertyFromComputedValue(adm, propName, descriptor.value);
}
else {
defineObservableProperty(adm, propName, descriptor.value, defaultEnhancer);
}
}
else {
defineComputedProperty(adm, propName, descriptor.get, descriptor.set, false, true);
}
}
function defineObservableProperty(adm, propName, newValue, enhancer) {
assertPropertyConfigurable(adm.target, propName);
if (hasInterceptors(adm)) {
var change = interceptChange(adm, {
object: adm.target,
name: propName,
type: "add",
newValue: newValue
});
if (!change)
return;
newValue = change.newValue;
}
var observable = adm.values[propName] = new ObservableValue(newValue, enhancer, adm.name + "." + propName, false);
newValue = observable.value;
Object.defineProperty(adm.target, propName, generateObservablePropConfig(propName));
notifyPropertyAddition(adm, adm.target, propName, newValue);
}
function defineComputedProperty(adm, propName, getter, setter, compareStructural, asInstanceProperty) {
if (asInstanceProperty)
assertPropertyConfigurable(adm.target, propName);
adm.values[propName] = new ComputedValue(getter, adm.target, compareStructural, adm.name + "." + propName, setter);
if (asInstanceProperty) {
Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName));
}
}
function defineComputedPropertyFromComputedValue(adm, propName, computedValue) {
var name = adm.name + "." + propName;
computedValue.name = name;
if (!computedValue.scope)
computedValue.scope = adm.target;
adm.values[propName] = computedValue;
Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName));
}
var observablePropertyConfigs = {};
var computedPropertyConfigs = {};
function generateObservablePropConfig(propName) {
var config = observablePropertyConfigs[propName];
if (config)
return config;
return observablePropertyConfigs[propName] = {
configurable: true,
enumerable: true,
get: function () {
return this.$mobx.values[propName].get();
},
set: function (v) {
setPropertyValue(this, propName, v);
}
};
}
function generateComputedPropConfig(propName) {
var config = computedPropertyConfigs[propName];
if (config)
return config;
return computedPropertyConfigs[propName] = {
configurable: true,
enumerable: false,
get: function () {
return this.$mobx.values[propName].get();
},
set: function (v) {
return this.$mobx.values[propName].set(v);
}
};
}
function setPropertyValue(instance, name, newValue) {
var adm = instance.$mobx;
var observable = adm.values[name];
if (hasInterceptors(adm)) {
var change = interceptChange(adm, {
type: "update",
object: instance,
name: name, newValue: newValue
});
if (!change)
return;
newValue = change.newValue;
}
newValue = observable.prepareNewValue(newValue);
if (newValue !== UNCHANGED) {
var notify = hasListeners(adm);
var notifySpy = isSpyEnabled();
var change = notify || notifySpy ? {
type: "update",
object: instance,
oldValue: observable.value,
name: name, newValue: newValue
} : null;
if (notifySpy)
spyReportStart(change);
observable.setNewValue(newValue);
if (notify)
notifyListeners(adm, change);
if (notifySpy)
spyReportEnd();
}
}
function notifyPropertyAddition(adm, object, name, newValue) {
var notify = hasListeners(adm);
var notifySpy = isSpyEnabled();
var change = notify || notifySpy ? {
type: "add",
object: object, name: name, newValue: newValue
} : null;
if (notifySpy)
spyReportStart(change);
if (notify)
notifyListeners(adm, change);
if (notifySpy)
spyReportEnd();
}
var isObservableObjectAdministration = createInstanceofPredicate("ObservableObjectAdministration", ObservableObjectAdministration);
function isObservableObject(thing) {
if (isObject(thing)) {
runLazyInitializers(thing);
return isObservableObjectAdministration(thing.$mobx);
}
return false;
}
exports.isObservableObject = isObservableObject;
var UNCHANGED = {};
var ObservableValue = (function (_super) {
__extends(ObservableValue, _super);
function ObservableValue(value, enhancer, name, notifySpy) {
if (name === void 0) { name = "ObservableValue@" + getNextId(); }
if (notifySpy === void 0) { notifySpy = true; }
var _this = _super.call(this, name) || this;
_this.enhancer = enhancer;
_this.hasUnreportedChange = false;
_this.value = enhancer(value, undefined, name);
if (notifySpy && isSpyEnabled()) {
spyReport({ type: "create", object: _this, newValue: _this.value });
}
return _this;
}
ObservableValue.prototype.set = function (newValue) {
var oldValue = this.value;
newValue = this.prepareNewValue(newValue);
if (newValue !== UNCHANGED) {
var notifySpy = isSpyEnabled();
if (notifySpy) {
spyReportStart({
type: "update",
object: this,
newValue: newValue, oldValue: oldValue
});
}
this.setNewValue(newValue);
if (notifySpy)
spyReportEnd();
}
};
ObservableValue.prototype.prepareNewValue = function (newValue) {
checkIfStateModificationsAreAllowed(this);
if (hasInterceptors(this)) {
var change = interceptChange(this, { object: this, type: "update", newValue: newValue });
if (!change)
return UNCHANGED;
newValue = change.newValue;
}
newValue = this.enhancer(newValue, this.value, this.name);
return this.value !== newValue
? newValue
: UNCHANGED;
};
ObservableValue.prototype.setNewValue = function (newValue) {
var oldValue = this.value;
this.value = newValue;
this.reportChanged();
if (hasListeners(this)) {
notifyListeners(this, {
type: "update",
object: this,
newValue: newValue,
oldValue: oldValue
});
}
};
ObservableValue.prototype.get = function () {
this.reportObserved();
return this.value;
};
ObservableValue.prototype.intercept = function (handler) {
return registerInterceptor(this, handler);
};
ObservableValue.prototype.observe = function (listener, fireImmediately) {
if (fireImmediately)
listener({
object: this,
type: "update",
newValue: this.value,
oldValue: undefined
});
return registerListener(this, listener);
};
ObservableValue.prototype.toJSON = function () {
return this.get();
};
ObservableValue.prototype.toString = function () {
return this.name + "[" + this.value + "]";
};
ObservableValue.prototype.valueOf = function () {
return toPrimitive(this.get());
};
return ObservableValue;
}(BaseAtom));
ObservableValue.prototype[primitiveSymbol()] = ObservableValue.prototype.valueOf;
var isObservableValue = createInstanceofPredicate("ObservableValue", ObservableValue);
function getAtom(thing, property) {
if (typeof thing === "object" && thing !== null) {
if (isObservableArray(thing)) {
invariant(property === undefined, getMessage("m036"));
return thing.$mobx.atom;
}
if (isObservableMap(thing)) {
var anyThing = thing;
if (property === undefined)
return getAtom(anyThing._keys);
var observable_2 = anyThing._data[property] || anyThing._hasMap[property];
invariant(!!observable_2, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'");
return observable_2;
}
runLazyInitializers(thing);
if (isObservableObject(thing)) {
if (!property)
return fail("please specify a property");
var observable_3 = thing.$mobx.values[property];
invariant(!!observable_3, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'");
return observable_3;
}
if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
return thing;
}
}
else if (typeof thing === "function") {
if (isReaction(thing.$mobx)) {
return thing.$mobx;
}
}
return fail("Cannot obtain atom from " + thing);
}
function getAdministration(thing, property) {
invariant(thing, "Expecting some object");
if (property !== undefined)
return getAdministration(getAtom(thing, property));
if (isAtom(thing) || isComputedValue(thing) || isReaction(thing))
return thing;
if (isObservableMap(thing))
return thing;
runLazyInitializers(thing);
if (thing.$mobx)
return thing.$mobx;
invariant(false, "Cannot obtain administration from " + thing);
}
function getDebugName(thing, property) {
var named;
if (property !== undefined)
named = getAtom(thing, property);
else if (isObservableObject(thing) || isObservableMap(thing))
named = getAdministration(thing);
else
named = getAtom(thing);
return named.name;
}
function createClassPropertyDecorator(onInitialize, get, set, enumerable, allowCustomArguments) {
function classPropertyDecorator(target, key, descriptor, customArgs, argLen) {
invariant(allowCustomArguments || quacksLikeADecorator(arguments), "This function is a decorator, but it wasn't invoked like a decorator");
if (!descriptor) {
var newDescriptor = {
enumerable: enumerable,
configurable: true,
get: function () {
if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true)
typescriptInitializeProperty(this, key, undefined, onInitialize, customArgs, descriptor);
return get.call(this, key);
},
set: function (v) {
if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true) {
typescriptInitializeProperty(this, key, v, onInitialize, customArgs, descriptor);
}
else {
set.call(this, key, v);
}
}
};
if (arguments.length < 3 || arguments.length === 5 && argLen < 3) {
Object.defineProperty(target, key, newDescriptor);
}
return newDescriptor;
}
else {
if (!hasOwnProperty(target, "__mobxLazyInitializers")) {
addHiddenProp(target, "__mobxLazyInitializers", (target.__mobxLazyInitializers && target.__mobxLazyInitializers.slice()) || []);
}
var value_1 = descriptor.value, initializer_1 = descriptor.initializer;
target.__mobxLazyInitializers.push(function (instance) {
onInitialize(instance, key, (initializer_1 ? initializer_1.call(instance) : value_1), customArgs, descriptor);
});
return {
enumerable: enumerable, configurable: true,
get: function () {
if (this.__mobxDidRunLazyInitializers !== true)
runLazyInitializers(this);
return get.call(this, key);
},
set: function (v) {
if (this.__mobxDidRunLazyInitializers !== true)
runLazyInitializers(this);
set.call(this, key, v);
}
};
}
}
if (allowCustomArguments) {
return function () {
if (quacksLikeADecorator(arguments))
return classPropertyDecorator.apply(null, arguments);
var outerArgs = arguments;
var argLen = arguments.length;
return function (target, key, descriptor) { return classPropertyDecorator(target, key, descriptor, outerArgs, argLen); };
};
}
return classPropertyDecorator;
}
function typescriptInitializeProperty(instance, key, v, onInitialize, customArgs, baseDescriptor) {
if (!hasOwnProperty(instance, "__mobxInitializedProps"))
addHiddenProp(instance, "__mobxInitializedProps", {});
instance.__mobxInitializedProps[key] = true;
onInitialize(instance, key, v, customArgs, baseDescriptor);
}
function runLazyInitializers(instance) {
if (instance.__mobxDidRunLazyInitializers === true)
return;
if (instance.__mobxLazyInitializers) {
addHiddenProp(instance, "__mobxDidRunLazyInitializers", true);
instance.__mobxDidRunLazyInitializers && instance.__mobxLazyInitializers.forEach(function (initializer) { return initializer(instance); });
}
}
function quacksLikeADecorator(args) {
return (args.length === 2 || args.length === 3) && typeof args[1] === "string";
}
function iteratorSymbol() {
return (typeof Symbol === "function" && Symbol.iterator) || "@@iterator";
}
var IS_ITERATING_MARKER = "__$$iterating";
function arrayAsIterator(array) {
invariant(array[IS_ITERATING_MARKER] !== true, "Illegal state: cannot recycle array as iterator");
addHiddenFinalProp(array, IS_ITERATING_MARKER, true);
var idx = -1;
addHiddenFinalProp(array, "next", function next() {
idx++;
return {
done: idx >= this.length,
value: idx < this.length ? this[idx] : undefined
};
});
return array;
}
function declareIterator(prototType, iteratorFactory) {
addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory);
}
var messages = {
"m001": "It is not allowed to assign new values to @action fields",
"m002": "`runInAction` expects a function",
"m003": "`runInAction` expects a function without arguments",
"m004": "autorun expects a function",
"m005": "Warning: attempted to pass an action to autorun. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.",
"m006": "Warning: attempted to pass an action to autorunAsync. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.",
"m007": "reaction only accepts 2 or 3 arguments. If migrating from MobX 2, please provide an options object",
"m008": "wrapping reaction expression in `asReference` is no longer supported, use options object instead",
"m009": "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property.",
"m010": "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'",
"m011": "First argument to `computed` should be an expression. If using computed as decorator, don't pass it arguments",
"m012": "computed takes one or two arguments if used as function",
"m013": "[mobx.expr] 'expr' should only be used inside other reactive functions.",
"m014": "extendObservable expected 2 or more arguments",
"m015": "extendObservable expects an object as first argument",
"m016": "extendObservable should not be used on maps, use map.merge instead",
"m017": "all arguments of extendObservable should be objects",
"m018": "extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540",
"m019": "[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead.",
"m020": "modifiers can only be used for individual object properties",
"m021": "observable expects zero or one arguments",
"m022": "@observable can not be used on getters, use @computed instead",
"m023": "Using `transaction` is deprecated, use `runInAction` or `(@)action` instead.",
"m024": "whyRun() can only be used if a derivation is active, or by passing an computed value / reaction explicitly. If you invoked whyRun from inside a computation; the computation is currently suspended but re-evaluating because somebody requested its value.",
"m025": "whyRun can only be used on reactions and computed values",
"m026": "`action` can only be invoked on functions",
"m028": "It is not allowed to set `useStrict` when a derivation is running",
"m029": "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row",
"m030a": "Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: ",
"m030b": "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, the render function of a React component? Tried to modify: ",
"m031": "Computed values are not allowed to not cause side effects by changing observables that are already being observed. Tried to modify: ",
"m032": "* This computation is suspended (not in use by any reaction) and won't run automatically.\n Didn't expect this computation to be suspended at this point?\n 1. Make sure this computation is used by a reaction (reaction, autorun, observer).\n 2. Check whether you are using this computation synchronously (in the same stack as they reaction that needs it).",
"m033": "`observe` doesn't support the fire immediately property for observable maps.",
"m034": "`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead",
"m035": "Cannot make the designated object observable; it is not extensible",
"m036": "It is not possible to get index atoms from arrays",
"m037": "Hi there! I'm sorry you have just run into an exception.\nIf your debugger ends up here, know that some reaction (like the render() of an observer component, autorun or reaction)\nthrew an exception and that mobx caught it, to avoid that it brings the rest of your application down.\nThe original cause of the exception (the code that caused this reaction to run (again)), is still in the stack.\n\nHowever, more interesting is the actual stack trace of the error itself.\nHopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\nSee `error.stack` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\nThat stack is more interesting than the stack of this console.error itself.\n\nIf the exception you see is an exception you created yourself, make sure to use `throw new Error(\"Oops\")` instead of `throw \"Oops\"`,\nbecause the javascript environment will only preserve the original stack trace in the first form.\n\nYou can also make sure the debugger pauses the next time this very same exception is thrown by enabling \"Pause on caught exception\".\n(Note that it might pause on many other, unrelated exception as well).\n\nIf that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n",
"m038": "Missing items in this list?\n 1. Check whether all used values are properly marked as observable (use isObservable to verify)\n 2. Make sure you didn't dereference values too early. MobX observes props, not primitives. E.g: use 'person.name' instead of 'name' in your computation.\n"
};
function getMessage(id) {
return messages[id];
}
var EMPTY_ARRAY = [];
Object.freeze(EMPTY_ARRAY);
function getGlobal() {
return global;
}
function getNextId() {
return ++globalState.mobxGuid;
}
function fail(message, thing) {
invariant(false, message, thing);
throw "X";
}
function invariant(check, message, thing) {
if (!check)
throw new Error("[mobx] Invariant failed: " + message + (thing ? " in '" + thing + "'" : ""));
}
var deprecatedMessages = [];
function deprecated(msg) {
if (deprecatedMessages.indexOf(msg) !== -1)
return false;
deprecatedMessages.push(msg);
console.error("[mobx] Deprecated: " + msg);
return true;
}
function once(func) {
var invoked = false;
return function () {
if (invoked)
return;
invoked = true;
return func.apply(this, arguments);
};
}
var noop = function () { };
function unique(list) {
var res = [];
list.forEach(function (item) {
if (res.indexOf(item) === -1)
res.push(item);
});
return res;
}
function joinStrings(things, limit, separator) {
if (limit === void 0) { limit = 100; }
if (separator === void 0) { separator = " - "; }
if (!things)
return "";
var sliced = things.slice(0, limit);
return "" + sliced.join(separator) + (things.length > limit ? " (... and " + (things.length - limit) + "more)" : "");
}
function isObject(value) {
return value !== null && typeof value === "object";
}
function isPlainObject(value) {
if (value === null || typeof value !== "object")
return false;
var proto = Object.getPrototypeOf(value);
return proto === Object.prototype || proto === null;
}
function objectAssign() {
var res = arguments[0];
for (var i = 1, l = arguments.length; i < l; i++) {
var source = arguments[i];
for (var key in source)
if (hasOwnProperty(source, key)) {
res[key] = source[key];
}
}
return res;
}
function valueDidChange(compareStructural, oldValue, newValue) {
if (typeof oldValue === 'number' && isNaN(oldValue)) {
return typeof newValue !== 'number' || !isNaN(newValue);
}
return compareStructural
? !deepEqual(oldValue, newValue)
: oldValue !== newValue;
}
var prototypeHasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwnProperty(object, propName) {
return prototypeHasOwnProperty.call(object, propName);
}
function makeNonEnumerable(object, propNames) {
for (var i = 0; i < propNames.length; i++) {
addHiddenProp(object, propNames[i], object[propNames[i]]);
}
}
function addHiddenProp(object, propName, value) {
Object.defineProperty(object, propName, {
enumerable: false,
writable: true,
configurable: true,
value: value
});
}
function addHiddenFinalProp(object, propName, value) {
Object.defineProperty(object, propName, {
enumerable: false,
writable: false,
configurable: true,
value: value
});
}
function isPropertyConfigurable(object, prop) {
var descriptor = Object.getOwnPropertyDescriptor(object, prop);
return !descriptor || (descriptor.configurable !== false && descriptor.writable !== false);
}
function assertPropertyConfigurable(object, prop) {
invariant(isPropertyConfigurable(object, prop), "Cannot make property '" + prop + "' observable, it is not configurable and writable in the target object");
}
function getEnumerableKeys(obj) {
var res = [];
for (var key in obj)
res.push(key);
return res;
}
function deepEqual(a, b) {
if (a === null && b === null)
return true;
if (a === undefined && b === undefined)
return true;
if (typeof a !== "object")
return a === b;
var aIsArray = isArrayLike(a);
var aIsMap = isMapLike(a);
if (aIsArray !== isArrayLike(b)) {
return false;
}
else if (aIsMap !== isMapLike(b)) {
return false;
}
else if (aIsArray) {
if (a.length !== b.length)
return false;
for (var i = a.length - 1; i >= 0; i--)
if (!deepEqual(a[i], b[i]))
return false;
return true;
}
else if (aIsMap) {
if (a.size !== b.size)
return false;
var equals_1 = true;
a.forEach(function (value, key) {
equals_1 = equals_1 && deepEqual(b.get(key), value);
});
return equals_1;
}
else if (typeof a === "object" && typeof b === "object") {
if (a === null || b === null)
return false;
if (isMapLike(a) && isMapLike(b)) {
if (a.size !== b.size)
return false;
return deepEqual(observable.shallowMap(a).entries(), observable.shallowMap(b).entries());
}
if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length)
return false;
for (var prop in a) {
if (!(prop in b))
return false;
if (!deepEqual(a[prop], b[prop]))
return false;
}
return true;
}
return false;
}
function createInstanceofPredicate(name, clazz) {
var propName = "isMobX" + name;
clazz.prototype[propName] = true;
return function (x) {
return isObject(x) && x[propName] === true;
};
}
function isArrayLike(x) {
return Array.isArray(x) || isObservableArray(x);
}
exports.isArrayLike = isArrayLike;
function isMapLike(x) {
return isES6Map(x) || isObservableMap(x);
}
function isES6Map(thing) {
if (getGlobal().Map !== undefined && thing instanceof getGlobal().Map)
return true;
return false;
}
function primitiveSymbol() {
return (typeof Symbol === "function" && Symbol.toPrimitive) || "@@toPrimitive";
}
function toPrimitive(value) {
return value === null ? null : typeof value === "object" ? ("" + value) : value;
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImxpYi9tb2J4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xufTtcbnJlZ2lzdGVyR2xvYmFscygpO1xuZXhwb3J0cy5leHRyYXMgPSB7XG4gICAgYWxsb3dTdGF0ZUNoYW5nZXM6IGFsbG93U3RhdGVDaGFuZ2VzLFxuICAgIGRlZXBFcXVhbDogZGVlcEVxdWFsLFxuICAgIGdldEF0b206IGdldEF0b20sXG4gICAgZ2V0RGVidWdOYW1lOiBnZXREZWJ1Z05hbWUsXG4gICAgZ2V0RGVwZW5kZW5jeVRyZWU6IGdldERlcGVuZGVuY3lUcmVlLFxuICAgIGdldEFkbWluaXN0cmF0aW9uOiBnZXRBZG1pbmlzdHJhdGlvbixcbiAgICBnZXRHbG9iYWxTdGF0ZTogZ2V0R2xvYmFsU3RhdGUsXG4gICAgZ2V0T2JzZXJ2ZXJUcmVlOiBnZXRPYnNlcnZlclRyZWUsXG4gICAgaXNDb21wdXRpbmdEZXJpdmF0aW9uOiBpc0NvbXB1dGluZ0Rlcml2YXRpb24sXG4gICAgaXNTcHlFbmFibGVkOiBpc1NweUVuYWJsZWQsXG4gICAgb25SZWFjdGlvbkVycm9yOiBvblJlYWN0aW9uRXJyb3IsXG4gICAgcmVzZXRHbG9iYWxTdGF0ZTogcmVzZXRHbG9iYWxTdGF0ZSxcbiAgICBzaGFyZUdsb2JhbFN0YXRlOiBzaGFyZUdsb2JhbFN0YXRlLFxuICAgIHNweVJlcG9ydDogc3B5UmVwb3J0LFxuICAgIHNweVJlcG9ydEVuZDogc3B5UmVwb3J0RW5kLFxuICAgIHNweVJlcG9ydFN0YXJ0OiBzcHlSZXBvcnRTdGFydCxcbiAgICBzZXRSZWFjdGlvblNjaGVkdWxlcjogc2V0UmVhY3Rpb25TY2hlZHVsZXJcbn07XG5pZiAodHlwZW9mIF9fTU9CWF9ERVZUT09MU19HTE9CQUxfSE9PS19fID09PSBcIm9iamVjdFwiKSB7XG4gICAgX19NT0JYX0RFVlRPT0xTX0dMT0JBTF9IT09LX18uaW5qZWN0TW9ieChtb2R1bGUuZXhwb3J0cyk7XG59XG52YXIgYWN0aW9uRmllbGREZWNvcmF0b3IgPSBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKGZ1bmN0aW9uICh0YXJnZXQsIGtleSwgdmFsdWUsIGFyZ3MsIG9yaWdpbmFsRGVzY3JpcHRvcikge1xuICAgIHZhciBhY3Rpb25OYW1lID0gKGFyZ3MgJiYgYXJncy5sZW5ndGggPT09IDEpID8gYXJnc1swXSA6ICh2YWx1ZS5uYW1lIHx8IGtleSB8fCBcIjx1bm5hbWVkIGFjdGlvbj5cIik7XG4gICAgdmFyIHdyYXBwZWRBY3Rpb24gPSBhY3Rpb24oYWN0aW9uTmFtZSwgdmFsdWUpO1xuICAgIGFkZEhpZGRlblByb3AodGFyZ2V0LCBrZXksIHdyYXBwZWRBY3Rpb24pO1xufSwgZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzW2tleV07XG59LCBmdW5jdGlvbiAoKSB7XG4gICAgaW52YXJpYW50KGZhbHNlLCBnZXRNZXNzYWdlKFwibTAwMVwiKSk7XG59LCBmYWxzZSwgdHJ1ZSk7XG52YXIgYm91bmRBY3Rpb25EZWNvcmF0b3IgPSBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKGZ1bmN0aW9uICh0YXJnZXQsIGtleSwgdmFsdWUpIHtcbiAgICBkZWZpbmVCb3VuZEFjdGlvbih0YXJnZXQsIGtleSwgdmFsdWUpO1xufSwgZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzW2tleV07XG59LCBmdW5jdGlvbiAoKSB7XG4gICAgaW52YXJpYW50KGZhbHNlLCBnZXRNZXNzYWdlKFwibTAwMVwiKSk7XG59LCBmYWxzZSwgZmFsc2UpO1xudmFyIGFjdGlvbiA9IGZ1bmN0aW9uIGFjdGlvbihhcmcxLCBhcmcyLCBhcmczLCBhcmc0KSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUFjdGlvbihhcmcxLm5hbWUgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCIsIGFyZzEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiBhcmcyID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHJldHVybiBjcmVhdGVBY3Rpb24oYXJnMSwgYXJnMik7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpXG4gICAgICAgIHJldHVybiBuYW1lZEFjdGlvbkRlY29yYXRvcihhcmcxKTtcbiAgICByZXR1cm4gbmFtZWRBY3Rpb25EZWNvcmF0b3IoYXJnMikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbn07XG5leHBvcnRzLmFjdGlvbiA9IGFjdGlvbjtcbmFjdGlvbi5ib3VuZCA9IGZ1bmN0aW9uIGJvdW5kQWN0aW9uKGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB2YXIgYWN0aW9uXzEgPSBjcmVhdGVBY3Rpb24oXCI8bm90IHlldCBib3VuZCBhY3Rpb24+XCIsIGFyZzEpO1xuICAgICAgICBhY3Rpb25fMS5hdXRvQmluZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBhY3Rpb25fMTtcbiAgICB9XG4gICAgcmV0dXJuIGJvdW5kQWN0aW9uRGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG59O1xuZnVuY3Rpb24gbmFtZWRBY3Rpb25EZWNvcmF0b3IobmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBwcm9wLCBkZXNjcmlwdG9yKSB7XG4gICAgICAgIGlmIChkZXNjcmlwdG9yICYmIHR5cGVvZiBkZXNjcmlwdG9yLnZhbHVlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBjcmVhdGVBY3Rpb24obmFtZSwgZGVzY3JpcHRvci52YWx1ZSk7XG4gICAgICAgICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3Rpb25GaWVsZERlY29yYXRvcihuYW1lKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG59XG5mdW5jdGlvbiBydW5JbkFjdGlvbihhcmcxLCBhcmcyLCBhcmczKSB7XG4gICAgdmFyIGFjdGlvbk5hbWUgPSB0eXBlb2YgYXJnMSA9PT0gXCJzdHJpbmdcIiA/IGFyZzEgOiBhcmcxLm5hbWUgfHwgXCI8dW5uYW1lZCBhY3Rpb24+XCI7XG4gICAgdmFyIGZuID0gdHlwZW9mIGFyZzEgPT09IFwiZnVuY3Rpb25cIiA/IGFyZzEgOiBhcmcyO1xuICAgIHZhciBzY29wZSA9IHR5cGVvZiBhcmcxID09PSBcImZ1bmN0aW9uXCIgPyBhcmcyIDogYXJnMztcbiAgICBpbnZhcmlhbnQodHlwZW9mIGZuID09PSBcImZ1bmN0aW9uXCIsIGdldE1lc3NhZ2UoXCJtMDAyXCIpKTtcbiAgICBpbnZhcmlhbnQoZm4ubGVuZ3RoID09PSAwLCBnZXRNZXNzYWdlKFwibTAwM1wiKSk7XG4gICAgaW52YXJpYW50KHR5cGVvZiBhY3Rpb25OYW1lID09PSBcInN0cmluZ1wiICYmIGFjdGlvbk5hbWUubGVuZ3RoID4gMCwgXCJhY3Rpb25zIHNob3VsZCBoYXZlIHZhbGlkIG5hbWVzLCBnb3Q6ICdcIiArIGFjdGlvbk5hbWUgKyBcIidcIik7XG4gICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHNjb3BlLCB1bmRlZmluZWQpO1xufVxuZXhwb3J0cy5ydW5JbkFjdGlvbiA9IHJ1bkluQWN0aW9uO1xuZnVuY3Rpb24gaXNBY3Rpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdHlwZW9mIHRoaW5nID09PSBcImZ1bmN0aW9uXCIgJiYgdGhpbmcuaXNNb2J4QWN0aW9uID09PSB0cnVlO1xufVxuZXhwb3J0cy5pc0FjdGlvbiA9IGlzQWN0aW9uO1xuZnVuY3Rpb24gZGVmaW5lQm91bmRBY3Rpb24odGFyZ2V0LCBwcm9wZXJ0eU5hbWUsIGZuKSB7XG4gICAgdmFyIHJlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24ocHJvcGVydHlOYW1lLCBmbiwgdGFyZ2V0LCBhcmd1bWVudHMpO1xuICAgIH07XG4gICAgcmVzLmlzTW9ieEFjdGlvbiA9IHRydWU7XG4gICAgYWRkSGlkZGVuUHJvcCh0YXJnZXQsIHByb3BlcnR5TmFtZSwgcmVzKTtcbn1cbmZ1bmN0aW9uIGF1dG9ydW4oYXJnMSwgYXJnMiwgYXJnMykge1xuICAgIHZhciBuYW1lLCB2aWV3LCBzY29wZTtcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbmFtZSA9IGFyZzE7XG4gICAgICAgIHZpZXcgPSBhcmcyO1xuICAgICAgICBzY29wZSA9IGFyZzM7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYW1lID0gYXJnMS5uYW1lIHx8IChcIkF1dG9ydW5AXCIgKyBnZXROZXh0SWQoKSk7XG4gICAgICAgIHZpZXcgPSBhcmcxO1xuICAgICAgICBzY29wZSA9IGFyZzI7XG4gICAgfVxuICAgIGludmFyaWFudCh0eXBlb2YgdmlldyA9PT0gXCJmdW5jdGlvblwiLCBnZXRNZXNzYWdlKFwibTAwNFwiKSk7XG4gICAgaW52YXJpYW50KGlzQWN0aW9uKHZpZXcpID09PSBmYWxzZSwgZ2V0TWVzc2FnZShcIm0wMDVcIikpO1xuICAgIGlmIChzY29wZSlcbiAgICAgICAgdmlldyA9IHZpZXcuYmluZChzY29wZSk7XG4gICAgdmFyIHJlYWN0aW9uID0gbmV3IFJlYWN0aW9uKG5hbWUsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50cmFjayhyZWFjdGlvblJ1bm5lcik7XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gcmVhY3Rpb25SdW5uZXIoKSB7XG4gICAgICAgIHZpZXcocmVhY3Rpb24pO1xuICAgIH1cbiAgICByZWFjdGlvbi5zY2hlZHVsZSgpO1xuICAgIHJldHVybiByZWFjdGlvbi5nZXREaXNwb3NlcigpO1xufVxuZXhwb3J0cy5hdXRvcnVuID0gYXV0b3J1bjtcbmZ1bmN0aW9uIHdoZW4oYXJnMSwgYXJnMiwgYXJnMywgYXJnNCkge1xuICAgIHZhciBuYW1lLCBwcmVkaWNhdGUsIGVmZmVjdCwgc2NvcGU7XG4gICAgaWYgKHR5cGVvZiBhcmcxID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIG5hbWUgPSBhcmcxO1xuICAgICAgICBwcmVkaWNhdGUgPSBhcmcyO1xuICAgICAgICBlZmZlY3QgPSBhcmczO1xuICAgICAgICBzY29wZSA9IGFyZzQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBuYW1lID0gKFwiV2hlbkBcIiArIGdldE5leHRJZCgpKTtcbiAgICAgICAgcHJlZGljYXRlID0gYXJnMTtcbiAgICAgICAgZWZmZWN0ID0gYXJnMjtcbiAgICAgICAgc2NvcGUgPSBhcmczO1xuICAgIH1cbiAgICB2YXIgZGlzcG9zZXIgPSBhdXRvcnVuKG5hbWUsIGZ1bmN0aW9uIChyKSB7XG4gICAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChzY29wZSkpIHtcbiAgICAgICAgICAgIHIuZGlzcG9zZSgpO1xuICAgICAgICAgICAgdmFyIHByZXZVbnRyYWNrZWQgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgICAgICAgICAgZWZmZWN0LmNhbGwoc2NvcGUpO1xuICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVbnRyYWNrZWQpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGRpc3Bvc2VyO1xufVxuZXhwb3J0cy53aGVuID0gd2hlbjtcbmZ1bmN0aW9uIGF1dG9ydW5Bc3luYyhhcmcxLCBhcmcyLCBhcmczLCBhcmc0KSB7XG4gICAgdmFyIG5hbWUsIGZ1bmMsIGRlbGF5LCBzY29wZTtcbiAgICBpZiAodHlwZW9mIGFyZzEgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgbmFtZSA9IGFyZzE7XG4gICAgICAgIGZ1bmMgPSBhcmcyO1xuICAgICAgICBkZWxheSA9IGFyZzM7XG4gICAgICAgIHNjb3BlID0gYXJnNDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIG5hbWUgPSBhcmcxLm5hbWUgfHwgKFwiQXV0b3J1bkFzeW5jQFwiICsgZ2V0TmV4dElkKCkpO1xuICAgICAgICBmdW5jID0gYXJnMTtcbiAgICAgICAgZGVsYXkgPSBhcmcyO1xuICAgICAgICBzY29wZSA9IGFyZzM7XG4gICAgfVxuICAgIGludmFyaWFudChpc0FjdGlvbihmdW5jKSA9PT0gZmFsc2UsIGdldE1lc3NhZ2UoXCJtMDA2XCIpKTtcbiAgICBpZiAoZGVsYXkgPT09IHZvaWQgMClcbiAgICAgICAgZGVsYXkgPSAxO1xuICAgIGlmIChzY29wZSlcbiAgICAgICAgZnVuYyA9IGZ1bmMuYmluZChzY29wZSk7XG4gICAgdmFyIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgdmFyIHIgPSBuZXcgUmVhY3Rpb24obmFtZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWlzU2NoZWR1bGVkKSB7XG4gICAgICAgICAgICBpc1NjaGVkdWxlZCA9IHRydWU7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpc1NjaGVkdWxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICghci5pc0Rpc3Bvc2VkKVxuICAgICAgICAgICAgICAgICAgICByLnRyYWNrKHJlYWN0aW9uUnVubmVyKTtcbiAgICAgICAgICAgIH0sIGRlbGF5KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIGZ1bmN0aW9uIHJlYWN0aW9uUnVubmVyKCkgeyBmdW5jKHIpOyB9XG4gICAgci5zY2hlZHVsZSgpO1xuICAgIHJldHVybiByLmdldERpc3Bvc2VyKCk7XG59XG5leHBvcnRzLmF1dG9ydW5Bc3luYyA9IGF1dG9ydW5Bc3luYztcbmZ1bmN0aW9uIHJlYWN0aW9uKGV4cHJlc3Npb24sIGVmZmVjdCwgYXJnMykge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMykge1xuICAgICAgICBmYWlsKGdldE1lc3NhZ2UoXCJtMDA3XCIpKTtcbiAgICB9XG4gICAgaWYgKGlzTW9kaWZpZXJEZXNjcmlwdG9yKGV4cHJlc3Npb24pKSB7XG4gICAgICAgIGZhaWwoZ2V0TWVzc2FnZShcIm0wMDhcIikpO1xuICAgIH1cbiAgICB2YXIgb3B0cztcbiAgICBpZiAodHlwZW9mIGFyZzMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgb3B0cyA9IGFyZzM7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBvcHRzID0ge307XG4gICAgfVxuICAgIG9wdHMubmFtZSA9IG9wdHMubmFtZSB8fCBleHByZXNzaW9uLm5hbWUgfHwgZWZmZWN0Lm5hbWUgfHwgKFwiUmVhY3Rpb25AXCIgKyBnZXROZXh0SWQoKSk7XG4gICAgb3B0cy5maXJlSW1tZWRpYXRlbHkgPSBhcmczID09PSB0cnVlIHx8IG9wdHMuZmlyZUltbWVkaWF0ZWx5ID09PSB0cnVlO1xuICAgIG9wdHMuZGVsYXkgPSBvcHRzLmRlbGF5IHx8IDA7XG4gICAgb3B0cy5jb21wYXJlU3RydWN0dXJhbCA9IG9wdHMuY29tcGFyZVN0cnVjdHVyYWwgfHwgb3B0cy5zdHJ1Y3QgfHwgZmFsc2U7XG4gICAgZWZmZWN0ID0gYWN0aW9uKG9wdHMubmFtZSwgb3B0cy5jb250ZXh0ID8gZWZmZWN0LmJpbmQob3B0cy5jb250ZXh0KSA6IGVmZmVjdCk7XG4gICAgaWYgKG9wdHMuY29udGV4dCkge1xuICAgICAgICBleHByZXNzaW9uID0gZXhwcmVzc2lvbi5iaW5kKG9wdHMuY29udGV4dCk7XG4gICAgfVxuICAgIHZhciBmaXJzdFRpbWUgPSB0cnVlO1xuICAgIHZhciBpc1NjaGVkdWxlZCA9IGZhbHNlO1xuICAgIHZhciBuZXh0VmFsdWU7XG4gICAgdmFyIHIgPSBuZXcgUmVhY3Rpb24ob3B0cy5uYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChvcHRzLmRlbGF5IDwgMSkge1xuICAgICAgICAgICAgcmVhY3Rpb25SdW5uZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaXNTY2hlZHVsZWQpIHtcbiAgICAgICAgICAgIGlzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVhY3Rpb25SdW5uZXIoKTtcbiAgICAgICAgICAgIH0sIG9wdHMuZGVsYXkpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgZnVuY3Rpb24gcmVhY3Rpb25SdW5uZXIoKSB7XG4gICAgICAgIGlmIChyLmlzRGlzcG9zZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHZhciBjaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIHIudHJhY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHYgPSBleHByZXNzaW9uKHIpO1xuICAgICAgICAgICAgY2hhbmdlZCA9IHZhbHVlRGlkQ2hhbmdlKG9wdHMuY29tcGFyZVN0cnVjdHVyYWwsIG5leHRWYWx1ZSwgdik7XG4gICAgICAgICAgICBuZXh0VmFsdWUgPSB2O1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGZpcnN0VGltZSAmJiBvcHRzLmZpcmVJbW1lZGlhdGVseSlcbiAgICAgICAgICAgIGVmZmVjdChuZXh0VmFsdWUsIHIpO1xuICAgICAgICBpZiAoIWZpcnN0VGltZSAmJiBjaGFuZ2VkID09PSB0cnVlKVxuICAgICAgICAgICAgZWZmZWN0KG5leHRWYWx1ZSwgcik7XG4gICAgICAgIGlmIChmaXJzdFRpbWUpXG4gICAgICAgICAgICBmaXJzdFRpbWUgPSBmYWxzZTtcbiAgICB9XG4gICAgci5zY2hlZHVsZSgpO1xuICAgIHJldHVybiByLmdldERpc3Bvc2VyKCk7XG59XG5leHBvcnRzLnJlYWN0aW9uID0gcmVhY3Rpb247XG5mdW5jdGlvbiBjcmVhdGVDb21wdXRlZERlY29yYXRvcihjb21wYXJlU3RydWN0dXJhbCkge1xuICAgIHJldHVybiBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKGZ1bmN0aW9uICh0YXJnZXQsIG5hbWUsIF8sIF9fLCBvcmlnaW5hbERlc2NyaXB0b3IpIHtcbiAgICAgICAgaW52YXJpYW50KHR5cGVvZiBvcmlnaW5hbERlc2NyaXB0b3IgIT09IFwidW5kZWZpbmVkXCIsIGdldE1lc3NhZ2UoXCJtMDA5XCIpKTtcbiAgICAgICAgaW52YXJpYW50KHR5cGVvZiBvcmlnaW5hbERlc2NyaXB0b3IuZ2V0ID09PSBcImZ1bmN0aW9uXCIsIGdldE1lc3NhZ2UoXCJtMDEwXCIpKTtcbiAgICAgICAgdmFyIGFkbSA9IGFzT2JzZXJ2YWJsZU9iamVjdCh0YXJnZXQsIFwiXCIpO1xuICAgICAgICBkZWZpbmVDb21wdXRlZFByb3BlcnR5KGFkbSwgbmFtZSwgb3JpZ2luYWxEZXNjcmlwdG9yLmdldCwgb3JpZ2luYWxEZXNjcmlwdG9yLnNldCwgY29tcGFyZVN0cnVjdHVyYWwsIGZhbHNlKTtcbiAgICB9LCBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICB2YXIgb2JzZXJ2YWJsZSA9IHRoaXMuJG1vYngudmFsdWVzW25hbWVdO1xuICAgICAgICBpZiAob2JzZXJ2YWJsZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUuZ2V0KCk7XG4gICAgfSwgZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuJG1vYngudmFsdWVzW25hbWVdLnNldCh2YWx1ZSk7XG4gICAgfSwgZmFsc2UsIGZhbHNlKTtcbn1cbnZhciBjb21wdXRlZERlY29yYXRvciA9IGNyZWF0ZUNvbXB1dGVkRGVjb3JhdG9yKGZhbHNlKTtcbnZhciBjb21wdXRlZFN0cnVjdERlY29yYXRvciA9IGNyZWF0ZUNvbXB1dGVkRGVjb3JhdG9yKHRydWUpO1xudmFyIGNvbXB1dGVkID0gKGZ1bmN0aW9uIGNvbXB1dGVkKGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgICBpZiAodHlwZW9mIGFyZzIgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgcmV0dXJuIGNvbXB1dGVkRGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfVxuICAgIGludmFyaWFudCh0eXBlb2YgYXJnMSA9PT0gXCJmdW5jdGlvblwiLCBnZXRNZXNzYWdlKFwibTAxMVwiKSk7XG4gICAgaW52YXJpYW50KGFyZ3VtZW50cy5sZW5ndGggPCAzLCBnZXRNZXNzYWdlKFwibTAxMlwiKSk7XG4gICAgdmFyIG9wdHMgPSB0eXBlb2YgYXJnMiA9PT0gXCJvYmplY3RcIiA/IGFyZzIgOiB7fTtcbiAgICBvcHRzLnNldHRlciA9IHR5cGVvZiBhcmcyID09PSBcImZ1bmN0aW9uXCIgPyBhcmcyIDogb3B0cy5zZXR0ZXI7XG4gICAgcmV0dXJuIG5ldyBDb21wdXRlZFZhbHVlKGFyZzEsIG9wdHMuY29udGV4dCwgb3B0cy5jb21wYXJlU3RydWN0dXJhbCB8fCBvcHRzLnN0cnVjdCB8fCBmYWxzZSwgb3B0cy5uYW1lIHx8IGFyZzEubmFtZSB8fCBcIlwiLCBvcHRzLnNldHRlcik7XG59KTtcbmV4cG9ydHMuY29tcHV0ZWQgPSBjb21wdXRlZDtcbmNvbXB1dGVkLnN0cnVjdCA9IGNvbXB1dGVkU3RydWN0RGVjb3JhdG9yO1xuZnVuY3Rpb24gY3JlYXRlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXIsIG9uQ2xlYW51cCkge1xuICAgIGludmFyaWFudCh0eXBlb2YgdHJhbnNmb3JtZXIgPT09IFwiZnVuY3Rpb25cIiAmJiB0cmFuc2Zvcm1lci5sZW5ndGggPCAyLCBcImNyZWF0ZVRyYW5zZm9ybWVyIGV4cGVjdHMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgb25lIGFyZ3VtZW50XCIpO1xuICAgIHZhciBvYmplY3RDYWNoZSA9IHt9O1xuICAgIHZhciByZXNldElkID0gZ2xvYmFsU3RhdGUucmVzZXRJZDtcbiAgICB2YXIgVHJhbnNmb3JtZXIgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMoVHJhbnNmb3JtZXIsIF9zdXBlcik7XG4gICAgICAgIGZ1bmN0aW9uIFRyYW5zZm9ybWVyKHNvdXJjZUlkZW50aWZpZXIsIHNvdXJjZU9iamVjdCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgZnVuY3Rpb24gKCkgeyByZXR1cm4gdHJhbnNmb3JtZXIoc291cmNlT2JqZWN0KTsgfSwgdW5kZWZpbmVkLCBmYWxzZSwgXCJUcmFuc2Zvcm1lci1cIiArIHRyYW5zZm9ybWVyLm5hbWUgKyBcIi1cIiArIHNvdXJjZUlkZW50aWZpZXIsIHVuZGVmaW5lZCkgfHwgdGhpcztcbiAgICAgICAgICAgIF90aGlzLnNvdXJjZUlkZW50aWZpZXIgPSBzb3VyY2VJZGVudGlmaWVyO1xuICAgICAgICAgICAgX3RoaXMuc291cmNlT2JqZWN0ID0gc291cmNlT2JqZWN0O1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzO1xuICAgICAgICB9XG4gICAgICAgIFRyYW5zZm9ybWVyLnByb3RvdHlwZS5vbkJlY29tZVVub2JzZXJ2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGFzdFZhbHVlID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIF9zdXBlci5wcm90b3R5cGUub25CZWNvbWVVbm9ic2VydmVkLmNhbGwodGhpcyk7XG4gICAgICAgICAgICBkZWxldGUgb2JqZWN0Q2FjaGVbdGhpcy5zb3VyY2VJZGVudGlmaWVyXTtcbiAgICAgICAgICAgIGlmIChvbkNsZWFudXApXG4gICAgICAgICAgICAgICAgb25DbGVhbnVwKGxhc3RWYWx1ZSwgdGhpcy5zb3VyY2VPYmplY3QpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gVHJhbnNmb3JtZXI7XG4gICAgfShDb21wdXRlZFZhbHVlKSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChvYmplY3QpIHtcbiAgICAgICAgaWYgKHJlc2V0SWQgIT09IGdsb2JhbFN0YXRlLnJlc2V0SWQpIHtcbiAgICAgICAgICAgIG9iamVjdENhY2hlID0ge307XG4gICAgICAgICAgICByZXNldElkID0gZ2xvYmFsU3RhdGUucmVzZXRJZDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaWRlbnRpZmllciA9IGdldE1lbW9pemF0aW9uSWQob2JqZWN0KTtcbiAgICAgICAgdmFyIHJlYWN0aXZlVHJhbnNmb3JtZXIgPSBvYmplY3RDYWNoZVtpZGVudGlmaWVyXTtcbiAgICAgICAgaWYgKHJlYWN0aXZlVHJhbnNmb3JtZXIpXG4gICAgICAgICAgICByZXR1cm4gcmVhY3RpdmVUcmFuc2Zvcm1lci5nZXQoKTtcbiAgICAgICAgcmVhY3RpdmVUcmFuc2Zvcm1lciA9IG9iamVjdENhY2hlW2lkZW50aWZpZXJdID0gbmV3IFRyYW5zZm9ybWVyKGlkZW50aWZpZXIsIG9iamVjdCk7XG4gICAgICAgIHJldHVybiByZWFjdGl2ZVRyYW5zZm9ybWVyLmdldCgpO1xuICAgIH07XG59XG5leHBvcnRzLmNyZWF0ZVRyYW5zZm9ybWVyID0gY3JlYXRlVHJhbnNmb3JtZXI7XG5mdW5jdGlvbiBnZXRNZW1vaXphdGlvbklkKG9iamVjdCkge1xuICAgIGlmIChvYmplY3QgPT09IG51bGwgfHwgdHlwZW9mIG9iamVjdCAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYnhdIHRyYW5zZm9ybSBleHBlY3RlZCBzb21lIGtpbmQgb2Ygb2JqZWN0LCBnb3Q6IFwiICsgb2JqZWN0KTtcbiAgICB2YXIgdGlkID0gb2JqZWN0LiR0cmFuc2Zvcm1JZDtcbiAgICBpZiAodGlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGlkID0gZ2V0TmV4dElkKCk7XG4gICAgICAgIGFkZEhpZGRlblByb3Aob2JqZWN0LCBcIiR0cmFuc2Zvcm1JZFwiLCB0aWQpO1xuICAgIH1cbiAgICByZXR1cm4gdGlkO1xufVxuZnVuY3Rpb24gZXhwcihleHByLCBzY29wZSkge1xuICAgIGlmICghaXNDb21wdXRpbmdEZXJpdmF0aW9uKCkpXG4gICAgICAgIGNvbnNvbGUud2FybihnZXRNZXNzYWdlKFwibTAxM1wiKSk7XG4gICAgcmV0dXJuIGNvbXB1dGVkKGV4cHIsIHsgY29udGV4dDogc2NvcGUgfSkuZ2V0KCk7XG59XG5leHBvcnRzLmV4cHIgPSBleHByO1xuZnVuY3Rpb24gZXh0ZW5kT2JzZXJ2YWJsZSh0YXJnZXQpIHtcbiAgICB2YXIgcHJvcGVydGllcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHByb3BlcnRpZXNbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIHJldHVybiBleHRlbmRPYnNlcnZhYmxlSGVscGVyKHRhcmdldCwgZGVlcEVuaGFuY2VyLCBwcm9wZXJ0aWVzKTtcbn1cbmV4cG9ydHMuZXh0ZW5kT2JzZXJ2YWJsZSA9IGV4dGVuZE9ic2VydmFibGU7XG5mdW5jdGlvbiBleHRlbmRTaGFsbG93T2JzZXJ2YWJsZSh0YXJnZXQpIHtcbiAgICB2YXIgcHJvcGVydGllcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMTsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHByb3BlcnRpZXNbX2kgLSAxXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgfVxuICAgIHJldHVybiBleHRlbmRPYnNlcnZhYmxlSGVscGVyKHRhcmdldCwgcmVmZXJlbmNlRW5oYW5jZXIsIHByb3BlcnRpZXMpO1xufVxuZXhwb3J0cy5leHRlbmRTaGFsbG93T2JzZXJ2YWJsZSA9IGV4dGVuZFNoYWxsb3dPYnNlcnZhYmxlO1xuZnVuY3Rpb24gZXh0ZW5kT2JzZXJ2YWJsZUhlbHBlcih0YXJnZXQsIGRlZmF1bHRFbmhhbmNlciwgcHJvcGVydGllcykge1xuICAgIGludmFyaWFudChhcmd1bWVudHMubGVuZ3RoID49IDIsIGdldE1lc3NhZ2UoXCJtMDE0XCIpKTtcbiAgICBpbnZhcmlhbnQodHlwZW9mIHRhcmdldCA9PT0gXCJvYmplY3RcIiwgZ2V0TWVzc2FnZShcIm0wMTVcIikpO1xuICAgIGludmFyaWFudCghKGlzT2JzZXJ2YWJsZU1hcCh0YXJnZXQpKSwgZ2V0TWVzc2FnZShcIm0wMTZcIikpO1xuICAgIHByb3BlcnRpZXMuZm9yRWFjaChmdW5jdGlvbiAocHJvcFNldCkge1xuICAgICAgICBpbnZhcmlhbnQodHlwZW9mIHByb3BTZXQgPT09IFwib2JqZWN0XCIsIGdldE1lc3NhZ2UoXCJtMDE3XCIpKTtcbiAgICAgICAgaW52YXJpYW50KCFpc09ic2VydmFibGUocHJvcFNldCksIGdldE1lc3NhZ2UoXCJtMDE4XCIpKTtcbiAgICB9KTtcbiAgICB2YXIgYWRtID0gYXNPYnNlcnZhYmxlT2JqZWN0KHRhcmdldCk7XG4gICAgdmFyIGRlZmluZWRQcm9wcyA9IHt9O1xuICAgIGZvciAodmFyIGkgPSBwcm9wZXJ0aWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHZhciBwcm9wU2V0ID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHByb3BTZXQpXG4gICAgICAgICAgICBpZiAoZGVmaW5lZFByb3BzW2tleV0gIT09IHRydWUgJiYgaGFzT3duUHJvcGVydHkocHJvcFNldCwga2V5KSkge1xuICAgICAgICAgICAgICAgIGRlZmluZWRQcm9wc1trZXldID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAodGFyZ2V0ID09PSBwcm9wU2V0ICYmICFpc1Byb3BlcnR5Q29uZmlndXJhYmxlKHRhcmdldCwga2V5KSlcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHByb3BTZXQsIGtleSk7XG4gICAgICAgICAgICAgICAgZGVmaW5lT2JzZXJ2YWJsZVByb3BlcnR5RnJvbURlc2NyaXB0b3IoYWRtLCBrZXksIGRlc2NyaXB0b3IsIGRlZmF1bHRFbmhhbmNlcik7XG4gICAgICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0YXJnZXQ7XG59XG5mdW5jdGlvbiBnZXREZXBlbmRlbmN5VHJlZSh0aGluZywgcHJvcGVydHkpIHtcbiAgICByZXR1cm4gbm9kZVRvRGVwZW5kZW5jeVRyZWUoZ2V0QXRvbSh0aGluZywgcHJvcGVydHkpKTtcbn1cbmZ1bmN0aW9uIG5vZGVUb0RlcGVuZGVuY3lUcmVlKG5vZGUpIHtcbiAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiBub2RlLm5hbWVcbiAgICB9O1xuICAgIGlmIChub2RlLm9ic2VydmluZyAmJiBub2RlLm9ic2VydmluZy5sZW5ndGggPiAwKVxuICAgICAgICByZXN1bHQuZGVwZW5kZW5jaWVzID0gdW5pcXVlKG5vZGUub2JzZXJ2aW5nKS5tYXAobm9kZVRvRGVwZW5kZW5jeVRyZWUpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiBnZXRPYnNlcnZlclRyZWUodGhpbmcsIHByb3BlcnR5KSB7XG4gICAgcmV0dXJuIG5vZGVUb09ic2VydmVyVHJlZShnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSkpO1xufVxuZnVuY3Rpb24gbm9kZVRvT2JzZXJ2ZXJUcmVlKG5vZGUpIHtcbiAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgICBuYW1lOiBub2RlLm5hbWVcbiAgICB9O1xuICAgIGlmIChoYXNPYnNlcnZlcnMobm9kZSkpXG4gICAgICAgIHJlc3VsdC5vYnNlcnZlcnMgPSBnZXRPYnNlcnZlcnMobm9kZSkubWFwKG5vZGVUb09ic2VydmVyVHJlZSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGludGVyY2VwdCh0aGluZywgcHJvcE9ySGFuZGxlciwgaGFuZGxlcikge1xuICAgIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICByZXR1cm4gaW50ZXJjZXB0UHJvcGVydHkodGhpbmcsIHByb3BPckhhbmRsZXIsIGhhbmRsZXIpO1xuICAgIGVsc2VcbiAgICAgICAgcmV0dXJuIGludGVyY2VwdEludGVyY2VwdGFibGUodGhpbmcsIHByb3BPckhhbmRsZXIpO1xufVxuZXhwb3J0cy5pbnRlcmNlcHQgPSBpbnRlcmNlcHQ7XG5mdW5jdGlvbiBpbnRlcmNlcHRJbnRlcmNlcHRhYmxlKHRoaW5nLCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIGdldEFkbWluaXN0cmF0aW9uKHRoaW5nKS5pbnRlcmNlcHQoaGFuZGxlcik7XG59XG5mdW5jdGlvbiBpbnRlcmNlcHRQcm9wZXJ0eSh0aGluZywgcHJvcGVydHksIGhhbmRsZXIpIHtcbiAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24odGhpbmcsIHByb3BlcnR5KS5pbnRlcmNlcHQoaGFuZGxlcik7XG59XG5mdW5jdGlvbiBpc0NvbXB1dGVkKHZhbHVlLCBwcm9wZXJ0eSkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZU9iamVjdCh2YWx1ZSkgPT09IGZhbHNlKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgYXRvbSA9IGdldEF0b20odmFsdWUsIHByb3BlcnR5KTtcbiAgICAgICAgcmV0dXJuIGlzQ29tcHV0ZWRWYWx1ZShhdG9tKTtcbiAgICB9XG4gICAgcmV0dXJuIGlzQ29tcHV0ZWRWYWx1ZSh2YWx1ZSk7XG59XG5leHBvcnRzLmlzQ29tcHV0ZWQgPSBpc0NvbXB1dGVkO1xuZnVuY3Rpb24gaXNPYnNlcnZhYmxlKHZhbHVlLCBwcm9wZXJ0eSkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZUFycmF5KHZhbHVlKSB8fCBpc09ic2VydmFibGVNYXAodmFsdWUpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGdldE1lc3NhZ2UoXCJtMDE5XCIpKTtcbiAgICAgICAgZWxzZSBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICAgICAgdmFyIG8gPSB2YWx1ZS4kbW9ieDtcbiAgICAgICAgICAgIHJldHVybiBvLnZhbHVlcyAmJiAhIW8udmFsdWVzW3Byb3BlcnR5XTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBpc09ic2VydmFibGVPYmplY3QodmFsdWUpIHx8ICEhdmFsdWUuJG1vYnggfHwgaXNBdG9tKHZhbHVlKSB8fCBpc1JlYWN0aW9uKHZhbHVlKSB8fCBpc0NvbXB1dGVkVmFsdWUodmFsdWUpO1xufVxuZXhwb3J0cy5pc09ic2VydmFibGUgPSBpc09ic2VydmFibGU7XG52YXIgZGVlcERlY29yYXRvciA9IGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKGRlZXBFbmhhbmNlcik7XG52YXIgc2hhbGxvd0RlY29yYXRvciA9IGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKHNoYWxsb3dFbmhhbmNlcik7XG52YXIgcmVmRGVjb3JhdG9yID0gY3JlYXRlRGVjb3JhdG9yRm9yRW5oYW5jZXIocmVmZXJlbmNlRW5oYW5jZXIpO1xudmFyIGRlZXBTdHJ1Y3REZWNvcmF0b3IgPSBjcmVhdGVEZWNvcmF0b3JGb3JFbmhhbmNlcihkZWVwU3RydWN0RW5oYW5jZXIpO1xudmFyIHJlZlN0cnVjdERlY29yYXRvciA9IGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKHJlZlN0cnVjdEVuaGFuY2VyKTtcbmZ1bmN0aW9uIGNyZWF0ZU9ic2VydmFibGUodikge1xuICAgIGlmICh2ID09PSB2b2lkIDApIHsgdiA9IHVuZGVmaW5lZDsgfVxuICAgIGlmICh0eXBlb2YgYXJndW1lbnRzWzFdID09PSBcInN0cmluZ1wiKVxuICAgICAgICByZXR1cm4gZGVlcERlY29yYXRvci5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgIGludmFyaWFudChhcmd1bWVudHMubGVuZ3RoIDw9IDEsIGdldE1lc3NhZ2UoXCJtMDIxXCIpKTtcbiAgICBpbnZhcmlhbnQoIWlzTW9kaWZpZXJEZXNjcmlwdG9yKHYpLCBnZXRNZXNzYWdlKFwibTAyMFwiKSk7XG4gICAgaWYgKGlzT2JzZXJ2YWJsZSh2KSlcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgdmFyIHJlcyA9IGRlZXBFbmhhbmNlcih2LCB1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gICAgaWYgKHJlcyAhPT0gdilcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5ib3godik7XG59XG52YXIgSU9ic2VydmFibGVGYWN0b3JpZXMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIElPYnNlcnZhYmxlRmFjdG9yaWVzKCkge1xuICAgIH1cbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuYm94ID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwiYm94XCIpO1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGVWYWx1ZSh2YWx1ZSwgZGVlcEVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5zaGFsbG93Qm94ID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwic2hhbGxvd0JveFwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlVmFsdWUodmFsdWUsIHJlZmVyZW5jZUVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5hcnJheSA9IGZ1bmN0aW9uIChpbml0aWFsVmFsdWVzLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwiYXJyYXlcIik7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZUFycmF5KGluaXRpYWxWYWx1ZXMsIGRlZXBFbmhhbmNlciwgbmFtZSk7XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvd0FycmF5ID0gZnVuY3Rpb24gKGluaXRpYWxWYWx1ZXMsIG5hbWUpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKVxuICAgICAgICAgICAgaW5jb3JyZWN0bHlVc2VkQXNEZWNvcmF0b3IoXCJzaGFsbG93QXJyYXlcIik7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZUFycmF5KGluaXRpYWxWYWx1ZXMsIHJlZmVyZW5jZUVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5tYXAgPSBmdW5jdGlvbiAoaW5pdGlhbFZhbHVlcywgbmFtZSkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDIpXG4gICAgICAgICAgICBpbmNvcnJlY3RseVVzZWRBc0RlY29yYXRvcihcIm1hcFwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlTWFwKGluaXRpYWxWYWx1ZXMsIGRlZXBFbmhhbmNlciwgbmFtZSk7XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvd01hcCA9IGZ1bmN0aW9uIChpbml0aWFsVmFsdWVzLCBuYW1lKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMilcbiAgICAgICAgICAgIGluY29ycmVjdGx5VXNlZEFzRGVjb3JhdG9yKFwic2hhbGxvd01hcFwiKTtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlTWFwKGluaXRpYWxWYWx1ZXMsIHJlZmVyZW5jZUVuaGFuY2VyLCBuYW1lKTtcbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5vYmplY3QgPSBmdW5jdGlvbiAocHJvcHMsIG5hbWUpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKVxuICAgICAgICAgICAgaW5jb3JyZWN0bHlVc2VkQXNEZWNvcmF0b3IoXCJvYmplY3RcIik7XG4gICAgICAgIHZhciByZXMgPSB7fTtcbiAgICAgICAgYXNPYnNlcnZhYmxlT2JqZWN0KHJlcywgbmFtZSk7XG4gICAgICAgIGV4dGVuZE9ic2VydmFibGUocmVzLCBwcm9wcyk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvd09iamVjdCA9IGZ1bmN0aW9uIChwcm9wcywgbmFtZSkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDIpXG4gICAgICAgICAgICBpbmNvcnJlY3RseVVzZWRBc0RlY29yYXRvcihcInNoYWxsb3dPYmplY3RcIik7XG4gICAgICAgIHZhciByZXMgPSB7fTtcbiAgICAgICAgYXNPYnNlcnZhYmxlT2JqZWN0KHJlcywgbmFtZSk7XG4gICAgICAgIGV4dGVuZFNoYWxsb3dPYnNlcnZhYmxlKHJlcywgcHJvcHMpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgSU9ic2VydmFibGVGYWN0b3JpZXMucHJvdG90eXBlLnJlZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTW9kaWZpZXJEZXNjcmlwdG9yKHJlZmVyZW5jZUVuaGFuY2VyLCBhcmd1bWVudHNbMF0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJlZkRlY29yYXRvci5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBJT2JzZXJ2YWJsZUZhY3Rvcmllcy5wcm90b3R5cGUuc2hhbGxvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTW9kaWZpZXJEZXNjcmlwdG9yKHNoYWxsb3dFbmhhbmNlciwgYXJndW1lbnRzWzBdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBzaGFsbG93RGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZS5kZWVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVNb2RpZmllckRlc2NyaXB0b3IoZGVlcEVuaGFuY2VyLCBhcmd1bWVudHNbMF0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGRlZXBEZWNvcmF0b3IuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSU9ic2VydmFibGVGYWN0b3JpZXMucHJvdG90eXBlLnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlTW9kaWZpZXJEZXNjcmlwdG9yKGRlZXBTdHJ1Y3RFbmhhbmNlciwgYXJndW1lbnRzWzBdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBkZWVwU3RydWN0RGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBJT2JzZXJ2YWJsZUZhY3Rvcmllcztcbn0oKSk7XG5leHBvcnRzLklPYnNlcnZhYmxlRmFjdG9yaWVzID0gSU9ic2VydmFibGVGYWN0b3JpZXM7XG52YXIgb2JzZXJ2YWJsZSA9IGNyZWF0ZU9ic2VydmFibGU7XG5leHBvcnRzLm9ic2VydmFibGUgPSBvYnNlcnZhYmxlO1xuT2JqZWN0LmtleXMoSU9ic2VydmFibGVGYWN0b3JpZXMucHJvdG90eXBlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIG9ic2VydmFibGVba2V5XSA9IElPYnNlcnZhYmxlRmFjdG9yaWVzLnByb3RvdHlwZVtrZXldOyB9KTtcbm9ic2VydmFibGUuZGVlcC5zdHJ1Y3QgPSBvYnNlcnZhYmxlLnN0cnVjdDtcbm9ic2VydmFibGUucmVmLnN0cnVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZU1vZGlmaWVyRGVzY3JpcHRvcihyZWZTdHJ1Y3RFbmhhbmNlciwgYXJndW1lbnRzWzBdKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiByZWZTdHJ1Y3REZWNvcmF0b3IuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICB9XG59O1xuZnVuY3Rpb24gaW5jb3JyZWN0bHlVc2VkQXNEZWNvcmF0b3IobWV0aG9kTmFtZSkge1xuICAgIGZhaWwoXCJFeHBlY3RlZCBvbmUgb3IgdHdvIGFyZ3VtZW50cyB0byBvYnNlcnZhYmxlLlwiICsgbWV0aG9kTmFtZSArIFwiLiBEaWQgeW91IGFjY2lkZW50YWxseSB0cnkgdG8gdXNlIG9ic2VydmFibGUuXCIgKyBtZXRob2ROYW1lICsgXCIgYXMgZGVjb3JhdG9yP1wiKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZURlY29yYXRvckZvckVuaGFuY2VyKGVuaGFuY2VyKSB7XG4gICAgaW52YXJpYW50KCEhZW5oYW5jZXIsIFwiOihcIik7XG4gICAgcmV0dXJuIGNyZWF0ZUNsYXNzUHJvcGVydHlEZWNvcmF0b3IoZnVuY3Rpb24gKHRhcmdldCwgbmFtZSwgYmFzZVZhbHVlLCBfLCBiYXNlRGVzY3JpcHRvcikge1xuICAgICAgICBhc3NlcnRQcm9wZXJ0eUNvbmZpZ3VyYWJsZSh0YXJnZXQsIG5hbWUpO1xuICAgICAgICBpbnZhcmlhbnQoIWJhc2VEZXNjcmlwdG9yIHx8ICFiYXNlRGVzY3JpcHRvci5nZXQsIGdldE1lc3NhZ2UoXCJtMDIyXCIpKTtcbiAgICAgICAgdmFyIGFkbSA9IGFzT2JzZXJ2YWJsZU9iamVjdCh0YXJnZXQsIHVuZGVmaW5lZCk7XG4gICAgICAgIGRlZmluZU9ic2VydmFibGVQcm9wZXJ0eShhZG0sIG5hbWUsIGJhc2VWYWx1ZSwgZW5oYW5jZXIpO1xuICAgIH0sIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHZhciBvYnNlcnZhYmxlID0gdGhpcy4kbW9ieC52YWx1ZXNbbmFtZV07XG4gICAgICAgIGlmIChvYnNlcnZhYmxlID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZS5nZXQoKTtcbiAgICB9LCBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcbiAgICAgICAgc2V0UHJvcGVydHlWYWx1ZSh0aGlzLCBuYW1lLCB2YWx1ZSk7XG4gICAgfSwgdHJ1ZSwgZmFsc2UpO1xufVxuZnVuY3Rpb24gb2JzZXJ2ZSh0aGluZywgcHJvcE9yQ2IsIGNiT3JGaXJlLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICBpZiAodHlwZW9mIGNiT3JGaXJlID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHJldHVybiBvYnNlcnZlT2JzZXJ2YWJsZVByb3BlcnR5KHRoaW5nLCBwcm9wT3JDYiwgY2JPckZpcmUsIGZpcmVJbW1lZGlhdGVseSk7XG4gICAgZWxzZVxuICAgICAgICByZXR1cm4gb2JzZXJ2ZU9ic2VydmFibGUodGhpbmcsIHByb3BPckNiLCBjYk9yRmlyZSk7XG59XG5leHBvcnRzLm9ic2VydmUgPSBvYnNlcnZlO1xuZnVuY3Rpb24gb2JzZXJ2ZU9ic2VydmFibGUodGhpbmcsIGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24odGhpbmcpLm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG59XG5mdW5jdGlvbiBvYnNlcnZlT2JzZXJ2YWJsZVByb3BlcnR5KHRoaW5nLCBwcm9wZXJ0eSwgbGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSkge1xuICAgIHJldHVybiBnZXRBZG1pbmlzdHJhdGlvbih0aGluZywgcHJvcGVydHkpLm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG59XG5mdW5jdGlvbiB0b0pTKHNvdXJjZSwgZGV0ZWN0Q3ljbGVzLCBfX2FscmVhZHlTZWVuKSB7XG4gICAgaWYgKGRldGVjdEN5Y2xlcyA9PT0gdm9pZCAwKSB7IGRldGVjdEN5Y2xlcyA9IHRydWU7IH1cbiAgICBpZiAoX19hbHJlYWR5U2VlbiA9PT0gdm9pZCAwKSB7IF9fYWxyZWFkeVNlZW4gPSBbXTsgfVxuICAgIGZ1bmN0aW9uIGNhY2hlKHZhbHVlKSB7XG4gICAgICAgIGlmIChkZXRlY3RDeWNsZXMpXG4gICAgICAgICAgICBfX2FscmVhZHlTZWVuLnB1c2goW3NvdXJjZSwgdmFsdWVdKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAoaXNPYnNlcnZhYmxlKHNvdXJjZSkpIHtcbiAgICAgICAgaWYgKGRldGVjdEN5Y2xlcyAmJiBfX2FscmVhZHlTZWVuID09PSBudWxsKVxuICAgICAgICAgICAgX19hbHJlYWR5U2VlbiA9IFtdO1xuICAgICAgICBpZiAoZGV0ZWN0Q3ljbGVzICYmIHNvdXJjZSAhPT0gbnVsbCAmJiB0eXBlb2Ygc291cmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IF9fYWxyZWFkeVNlZW4ubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgICAgIGlmIChfX2FscmVhZHlTZWVuW2ldWzBdID09PSBzb3VyY2UpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfX2FscmVhZHlTZWVuW2ldWzFdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc09ic2VydmFibGVBcnJheShzb3VyY2UpKSB7XG4gICAgICAgICAgICB2YXIgcmVzID0gY2FjaGUoW10pO1xuICAgICAgICAgICAgdmFyIHRvQWRkID0gc291cmNlLm1hcChmdW5jdGlvbiAodmFsdWUpIHsgcmV0dXJuIHRvSlModmFsdWUsIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7IH0pO1xuICAgICAgICAgICAgcmVzLmxlbmd0aCA9IHRvQWRkLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdG9BZGQubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgICAgIHJlc1tpXSA9IHRvQWRkW2ldO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHNvdXJjZSkpIHtcbiAgICAgICAgICAgIHZhciByZXMgPSBjYWNoZSh7fSk7XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKVxuICAgICAgICAgICAgICAgIHJlc1trZXldID0gdG9KUyhzb3VyY2Vba2V5XSwgZGV0ZWN0Q3ljbGVzLCBfX2FscmVhZHlTZWVuKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZU1hcChzb3VyY2UpKSB7XG4gICAgICAgICAgICB2YXIgcmVzXzEgPSBjYWNoZSh7fSk7XG4gICAgICAgICAgICBzb3VyY2UuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkgeyByZXR1cm4gcmVzXzFba2V5XSA9IHRvSlModmFsdWUsIGRldGVjdEN5Y2xlcywgX19hbHJlYWR5U2Vlbik7IH0pO1xuICAgICAgICAgICAgcmV0dXJuIHJlc18xO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc09ic2VydmFibGVWYWx1ZShzb3VyY2UpKVxuICAgICAgICAgICAgcmV0dXJuIHRvSlMoc291cmNlLmdldCgpLCBkZXRlY3RDeWNsZXMsIF9fYWxyZWFkeVNlZW4pO1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlO1xufVxuZXhwb3J0cy50b0pTID0gdG9KUztcbmZ1bmN0aW9uIHRyYW5zYWN0aW9uKGFjdGlvbiwgdGhpc0FyZykge1xuICAgIGlmICh0aGlzQXJnID09PSB2b2lkIDApIHsgdGhpc0FyZyA9IHVuZGVmaW5lZDsgfVxuICAgIGRlcHJlY2F0ZWQoZ2V0TWVzc2FnZShcIm0wMjNcIikpO1xuICAgIHJldHVybiBydW5JblRyYW5zYWN0aW9uLmFwcGx5KHVuZGVmaW5lZCwgYXJndW1lbnRzKTtcbn1cbmV4cG9ydHMudHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbjtcbmZ1bmN0aW9uIHJ1bkluVHJhbnNhY3Rpb24oYWN0aW9uLCB0aGlzQXJnKSB7XG4gICAgaWYgKHRoaXNBcmcgPT09IHZvaWQgMCkgeyB0aGlzQXJnID0gdW5kZWZpbmVkOyB9XG4gICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oXCJcIiwgYWN0aW9uKTtcbn1cbmZ1bmN0aW9uIGxvZyhtc2cpIHtcbiAgICBjb25zb2xlLmxvZyhtc2cpO1xuICAgIHJldHVybiBtc2c7XG59XG5mdW5jdGlvbiB3aHlSdW4odGhpbmcsIHByb3ApIHtcbiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgdGhpbmcgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgICAgICAgICBpZiAoIXRoaW5nKVxuICAgICAgICAgICAgICAgIHJldHVybiBsb2coZ2V0TWVzc2FnZShcIm0wMjRcIikpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHRoaW5nID0gZ2V0QXRvbSh0aGluZywgcHJvcCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgdGhpbmcgPSBnZXRBdG9tKHRoaW5nKTtcbiAgICBpZiAoaXNDb21wdXRlZFZhbHVlKHRoaW5nKSlcbiAgICAgICAgcmV0dXJuIGxvZyh0aGluZy53aHlSdW4oKSk7XG4gICAgZWxzZSBpZiAoaXNSZWFjdGlvbih0aGluZykpXG4gICAgICAgIHJldHVybiBsb2codGhpbmcud2h5UnVuKCkpO1xuICAgIHJldHVybiBmYWlsKGdldE1lc3NhZ2UoXCJtMDI1XCIpKTtcbn1cbmV4cG9ydHMud2h5UnVuID0gd2h5UnVuO1xuZnVuY3Rpb24gY3JlYXRlQWN0aW9uKGFjdGlvbk5hbWUsIGZuKSB7XG4gICAgaW52YXJpYW50KHR5cGVvZiBmbiA9PT0gXCJmdW5jdGlvblwiLCBnZXRNZXNzYWdlKFwibTAyNlwiKSk7XG4gICAgaW52YXJpYW50KHR5cGVvZiBhY3Rpb25OYW1lID09PSBcInN0cmluZ1wiICYmIGFjdGlvbk5hbWUubGVuZ3RoID4gMCwgXCJhY3Rpb25zIHNob3VsZCBoYXZlIHZhbGlkIG5hbWVzLCBnb3Q6ICdcIiArIGFjdGlvbk5hbWUgKyBcIidcIik7XG4gICAgdmFyIHJlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dGVBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgICByZXMub3JpZ2luYWxGbiA9IGZuO1xuICAgIHJlcy5pc01vYnhBY3Rpb24gPSB0cnVlO1xuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiBleGVjdXRlQWN0aW9uKGFjdGlvbk5hbWUsIGZuLCBzY29wZSwgYXJncykge1xuICAgIHZhciBydW5JbmZvID0gc3RhcnRBY3Rpb24oYWN0aW9uTmFtZSwgZm4sIHNjb3BlLCBhcmdzKTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gZm4uYXBwbHkoc2NvcGUsIGFyZ3MpO1xuICAgIH1cbiAgICBmaW5hbGx5IHtcbiAgICAgICAgZW5kQWN0aW9uKHJ1bkluZm8pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHN0YXJ0QWN0aW9uKGFjdGlvbk5hbWUsIGZuLCBzY29wZSwgYXJncykge1xuICAgIHZhciBub3RpZnlTcHkgPSBpc1NweUVuYWJsZWQoKSAmJiAhIWFjdGlvbk5hbWU7XG4gICAgdmFyIHN0YXJ0VGltZSA9IDA7XG4gICAgaWYgKG5vdGlmeVNweSkge1xuICAgICAgICBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB2YXIgbCA9IChhcmdzICYmIGFyZ3MubGVuZ3RoKSB8fCAwO1xuICAgICAgICB2YXIgZmxhdHRlbmRBcmdzID0gbmV3IEFycmF5KGwpO1xuICAgICAgICBpZiAobCA+IDApXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKylcbiAgICAgICAgICAgICAgICBmbGF0dGVuZEFyZ3NbaV0gPSBhcmdzW2ldO1xuICAgICAgICBzcHlSZXBvcnRTdGFydCh7XG4gICAgICAgICAgICB0eXBlOiBcImFjdGlvblwiLFxuICAgICAgICAgICAgbmFtZTogYWN0aW9uTmFtZSxcbiAgICAgICAgICAgIGZuOiBmbixcbiAgICAgICAgICAgIG9iamVjdDogc2NvcGUsXG4gICAgICAgICAgICBhcmd1bWVudHM6IGZsYXR0ZW5kQXJnc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgdmFyIHByZXZEZXJpdmF0aW9uID0gdW50cmFja2VkU3RhcnQoKTtcbiAgICBzdGFydEJhdGNoKCk7XG4gICAgdmFyIHByZXZBbGxvd1N0YXRlQ2hhbmdlcyA9IGFsbG93U3RhdGVDaGFuZ2VzU3RhcnQodHJ1ZSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcHJldkRlcml2YXRpb246IHByZXZEZXJpdmF0aW9uLFxuICAgICAgICBwcmV2QWxsb3dTdGF0ZUNoYW5nZXM6IHByZXZBbGxvd1N0YXRlQ2hhbmdlcyxcbiAgICAgICAgbm90aWZ5U3B5OiBub3RpZnlTcHksXG4gICAgICAgIHN0YXJ0VGltZTogc3RhcnRUaW1lXG4gICAgfTtcbn1cbmZ1bmN0aW9uIGVuZEFjdGlvbihydW5JbmZvKSB7XG4gICAgYWxsb3dTdGF0ZUNoYW5nZXNFbmQocnVuSW5mby5wcmV2QWxsb3dTdGF0ZUNoYW5nZXMpO1xuICAgIGVuZEJhdGNoKCk7XG4gICAgdW50cmFja2VkRW5kKHJ1bkluZm8ucHJldkRlcml2YXRpb24pO1xuICAgIGlmIChydW5JbmZvLm5vdGlmeVNweSlcbiAgICAgICAgc3B5UmVwb3J0RW5kKHsgdGltZTogRGF0ZS5ub3coKSAtIHJ1bkluZm8uc3RhcnRUaW1lIH0pO1xufVxuZnVuY3Rpb24gdXNlU3RyaWN0KHN0cmljdCkge1xuICAgIGludmFyaWFudChnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb24gPT09IG51bGwsIGdldE1lc3NhZ2UoXCJtMDI4XCIpKTtcbiAgICBnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlID0gc3RyaWN0O1xuICAgIGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzID0gIXN0cmljdDtcbn1cbmV4cG9ydHMudXNlU3RyaWN0ID0gdXNlU3RyaWN0O1xuZnVuY3Rpb24gaXNTdHJpY3RNb2RlRW5hYmxlZCgpIHtcbiAgICByZXR1cm4gZ2xvYmFsU3RhdGUuc3RyaWN0TW9kZTtcbn1cbmV4cG9ydHMuaXNTdHJpY3RNb2RlRW5hYmxlZCA9IGlzU3RyaWN0TW9kZUVuYWJsZWQ7XG5mdW5jdGlvbiBhbGxvd1N0YXRlQ2hhbmdlcyhhbGxvd1N0YXRlQ2hhbmdlcywgZnVuYykge1xuICAgIHZhciBwcmV2ID0gYWxsb3dTdGF0ZUNoYW5nZXNTdGFydChhbGxvd1N0YXRlQ2hhbmdlcyk7XG4gICAgdmFyIHJlcztcbiAgICB0cnkge1xuICAgICAgICByZXMgPSBmdW5jKCk7XG4gICAgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICBhbGxvd1N0YXRlQ2hhbmdlc0VuZChwcmV2KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGFsbG93U3RhdGVDaGFuZ2VzU3RhcnQoYWxsb3dTdGF0ZUNoYW5nZXMpIHtcbiAgICB2YXIgcHJldiA9IGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzO1xuICAgIGdsb2JhbFN0YXRlLmFsbG93U3RhdGVDaGFuZ2VzID0gYWxsb3dTdGF0ZUNoYW5nZXM7XG4gICAgcmV0dXJuIHByZXY7XG59XG5mdW5jdGlvbiBhbGxvd1N0YXRlQ2hhbmdlc0VuZChwcmV2KSB7XG4gICAgZ2xvYmFsU3RhdGUuYWxsb3dTdGF0ZUNoYW5nZXMgPSBwcmV2O1xufVxudmFyIEJhc2VBdG9tID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlQXRvbShuYW1lKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiQXRvbUBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgIHRoaXMuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbiA9IHRydWU7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXJzID0gW107XG4gICAgICAgIHRoaXMub2JzZXJ2ZXJzSW5kZXhlcyA9IHt9O1xuICAgICAgICB0aGlzLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgIHRoaXMubGFzdEFjY2Vzc2VkQnkgPSAwO1xuICAgICAgICB0aGlzLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORztcbiAgICB9XG4gICAgQmFzZUF0b20ucHJvdG90eXBlLm9uQmVjb21lVW5vYnNlcnZlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB9O1xuICAgIEJhc2VBdG9tLnByb3RvdHlwZS5yZXBvcnRPYnNlcnZlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVwb3J0T2JzZXJ2ZWQodGhpcyk7XG4gICAgfTtcbiAgICBCYXNlQXRvbS5wcm90b3R5cGUucmVwb3J0Q2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc3RhcnRCYXRjaCgpO1xuICAgICAgICBwcm9wYWdhdGVDaGFuZ2VkKHRoaXMpO1xuICAgICAgICBlbmRCYXRjaCgpO1xuICAgIH07XG4gICAgQmFzZUF0b20ucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lO1xuICAgIH07XG4gICAgcmV0dXJuIEJhc2VBdG9tO1xufSgpKTtcbmV4cG9ydHMuQmFzZUF0b20gPSBCYXNlQXRvbTtcbnZhciBBdG9tID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQXRvbSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBBdG9tKG5hbWUsIG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyLCBvbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiQXRvbUBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIGlmIChvbkJlY29tZU9ic2VydmVkSGFuZGxlciA9PT0gdm9pZCAwKSB7IG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyID0gbm9vcDsgfVxuICAgICAgICBpZiAob25CZWNvbWVVbm9ic2VydmVkSGFuZGxlciA9PT0gdm9pZCAwKSB7IG9uQmVjb21lVW5vYnNlcnZlZEhhbmRsZXIgPSBub29wOyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIG5hbWUpIHx8IHRoaXM7XG4gICAgICAgIF90aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICBfdGhpcy5vbkJlY29tZU9ic2VydmVkSGFuZGxlciA9IG9uQmVjb21lT2JzZXJ2ZWRIYW5kbGVyO1xuICAgICAgICBfdGhpcy5vbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyID0gb25CZWNvbWVVbm9ic2VydmVkSGFuZGxlcjtcbiAgICAgICAgX3RoaXMuaXNQZW5kaW5nVW5vYnNlcnZhdGlvbiA9IGZhbHNlO1xuICAgICAgICBfdGhpcy5pc0JlaW5nVHJhY2tlZCA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIEF0b20ucHJvdG90eXBlLnJlcG9ydE9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBzdGFydEJhdGNoKCk7XG4gICAgICAgIF9zdXBlci5wcm90b3R5cGUucmVwb3J0T2JzZXJ2ZWQuY2FsbCh0aGlzKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzQmVpbmdUcmFja2VkKSB7XG4gICAgICAgICAgICB0aGlzLmlzQmVpbmdUcmFja2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMub25CZWNvbWVPYnNlcnZlZEhhbmRsZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICByZXR1cm4gISFnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgfTtcbiAgICBBdG9tLnByb3RvdHlwZS5vbkJlY29tZVVub2JzZXJ2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuaXNCZWluZ1RyYWNrZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vbkJlY29tZVVub2JzZXJ2ZWRIYW5kbGVyKCk7XG4gICAgfTtcbiAgICByZXR1cm4gQXRvbTtcbn0oQmFzZUF0b20pKTtcbmV4cG9ydHMuQXRvbSA9IEF0b207XG52YXIgaXNBdG9tID0gY3JlYXRlSW5zdGFuY2VvZlByZWRpY2F0ZShcIkF0b21cIiwgQmFzZUF0b20pO1xudmFyIENvbXB1dGVkVmFsdWUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbXB1dGVkVmFsdWUoZGVyaXZhdGlvbiwgc2NvcGUsIGNvbXBhcmVTdHJ1Y3R1cmFsLCBuYW1lLCBzZXR0ZXIpIHtcbiAgICAgICAgdGhpcy5kZXJpdmF0aW9uID0gZGVyaXZhdGlvbjtcbiAgICAgICAgdGhpcy5zY29wZSA9IHNjb3BlO1xuICAgICAgICB0aGlzLmNvbXBhcmVTdHJ1Y3R1cmFsID0gY29tcGFyZVN0cnVjdHVyYWw7XG4gICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORztcbiAgICAgICAgdGhpcy5vYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5uZXdPYnNlcnZpbmcgPSBudWxsO1xuICAgICAgICB0aGlzLmlzUGVuZGluZ1Vub2JzZXJ2YXRpb24gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnNJbmRleGVzID0ge307XG4gICAgICAgIHRoaXMuZGlmZlZhbHVlID0gMDtcbiAgICAgICAgdGhpcy5ydW5JZCA9IDA7XG4gICAgICAgIHRoaXMubGFzdEFjY2Vzc2VkQnkgPSAwO1xuICAgICAgICB0aGlzLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEU7XG4gICAgICAgIHRoaXMudW5ib3VuZERlcHNDb3VudCA9IDA7XG4gICAgICAgIHRoaXMuX19tYXBpZCA9IFwiI1wiICsgZ2V0TmV4dElkKCk7XG4gICAgICAgIHRoaXMudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuaXNDb21wdXRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc1J1bm5pbmdTZXR0ZXIgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZSB8fCBcIkNvbXB1dGVkVmFsdWVAXCIgKyBnZXROZXh0SWQoKTtcbiAgICAgICAgaWYgKHNldHRlcilcbiAgICAgICAgICAgIHRoaXMuc2V0dGVyID0gY3JlYXRlQWN0aW9uKG5hbWUgKyBcIi1zZXR0ZXJcIiwgc2V0dGVyKTtcbiAgICB9XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUub25CZWNvbWVTdGFsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcHJvcGFnYXRlTWF5YmVDaGFuZ2VkKHRoaXMpO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUub25CZWNvbWVVbm9ic2VydmVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpbnZhcmlhbnQodGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSAhPT0gSURlcml2YXRpb25TdGF0ZS5OT1RfVFJBQ0tJTkcsIGdldE1lc3NhZ2UoXCJtMDI5XCIpKTtcbiAgICAgICAgY2xlYXJPYnNlcnZpbmcodGhpcyk7XG4gICAgICAgIHRoaXMudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgfTtcbiAgICBDb21wdXRlZFZhbHVlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGludmFyaWFudCghdGhpcy5pc0NvbXB1dGluZywgXCJDeWNsZSBkZXRlY3RlZCBpbiBjb21wdXRhdGlvbiBcIiArIHRoaXMubmFtZSwgdGhpcy5kZXJpdmF0aW9uKTtcbiAgICAgICAgaWYgKGdsb2JhbFN0YXRlLmluQmF0Y2ggPT09IDApIHtcbiAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgIGlmIChzaG91bGRDb21wdXRlKHRoaXMpKVxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLmNvbXB1dGVWYWx1ZShmYWxzZSk7XG4gICAgICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVwb3J0T2JzZXJ2ZWQodGhpcyk7XG4gICAgICAgICAgICBpZiAoc2hvdWxkQ29tcHV0ZSh0aGlzKSlcbiAgICAgICAgICAgICAgICBpZiAodGhpcy50cmFja0FuZENvbXB1dGUoKSlcbiAgICAgICAgICAgICAgICAgICAgcHJvcGFnYXRlQ2hhbmdlQ29uZmlybWVkKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLnZhbHVlO1xuICAgICAgICBpZiAoaXNDYXVnaHRFeGNlcHRpb24ocmVzdWx0KSlcbiAgICAgICAgICAgIHRocm93IHJlc3VsdC5jYXVzZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnBlZWsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXMgPSB0aGlzLmNvbXB1dGVWYWx1ZShmYWxzZSk7XG4gICAgICAgIGlmIChpc0NhdWdodEV4Y2VwdGlvbihyZXMpKVxuICAgICAgICAgICAgdGhyb3cgcmVzLmNhdXNlO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRlcikge1xuICAgICAgICAgICAgaW52YXJpYW50KCF0aGlzLmlzUnVubmluZ1NldHRlciwgXCJUaGUgc2V0dGVyIG9mIGNvbXB1dGVkIHZhbHVlICdcIiArIHRoaXMubmFtZSArIFwiJyBpcyB0cnlpbmcgdG8gdXBkYXRlIGl0c2VsZi4gRGlkIHlvdSBpbnRlbmQgdG8gdXBkYXRlIGFuIF9vYnNlcnZhYmxlXyB2YWx1ZSwgaW5zdGVhZCBvZiB0aGUgY29tcHV0ZWQgcHJvcGVydHk/XCIpO1xuICAgICAgICAgICAgdGhpcy5pc1J1bm5pbmdTZXR0ZXIgPSB0cnVlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRlci5jYWxsKHRoaXMuc2NvcGUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNSdW5uaW5nU2V0dGVyID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgaW52YXJpYW50KGZhbHNlLCBcIltDb21wdXRlZFZhbHVlICdcIiArIHRoaXMubmFtZSArIFwiJ10gSXQgaXMgbm90IHBvc3NpYmxlIHRvIGFzc2lnbiBhIG5ldyB2YWx1ZSB0byBhIGNvbXB1dGVkIHZhbHVlLlwiKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnRyYWNrQW5kQ29tcHV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKGlzU3B5RW5hYmxlZCgpKSB7XG4gICAgICAgICAgICBzcHlSZXBvcnQoe1xuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcy5zY29wZSxcbiAgICAgICAgICAgICAgICB0eXBlOiBcImNvbXB1dGVcIixcbiAgICAgICAgICAgICAgICBmbjogdGhpcy5kZXJpdmF0aW9uXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb2xkVmFsdWUgPSB0aGlzLnZhbHVlO1xuICAgICAgICB2YXIgbmV3VmFsdWUgPSB0aGlzLnZhbHVlID0gdGhpcy5jb21wdXRlVmFsdWUodHJ1ZSk7XG4gICAgICAgIHJldHVybiBpc0NhdWdodEV4Y2VwdGlvbihuZXdWYWx1ZSkgfHwgdmFsdWVEaWRDaGFuZ2UodGhpcy5jb21wYXJlU3RydWN0dXJhbCwgbmV3VmFsdWUsIG9sZFZhbHVlKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLmNvbXB1dGVWYWx1ZSA9IGZ1bmN0aW9uICh0cmFjaykge1xuICAgICAgICB0aGlzLmlzQ29tcHV0aW5nID0gdHJ1ZTtcbiAgICAgICAgZ2xvYmFsU3RhdGUuY29tcHV0YXRpb25EZXB0aCsrO1xuICAgICAgICB2YXIgcmVzO1xuICAgICAgICBpZiAodHJhY2spIHtcbiAgICAgICAgICAgIHJlcyA9IHRyYWNrRGVyaXZlZEZ1bmN0aW9uKHRoaXMsIHRoaXMuZGVyaXZhdGlvbiwgdGhpcy5zY29wZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlcyA9IHRoaXMuZGVyaXZhdGlvbi5jYWxsKHRoaXMuc2NvcGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXMgPSBuZXcgQ2F1Z2h0RXhjZXB0aW9uKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGdsb2JhbFN0YXRlLmNvbXB1dGF0aW9uRGVwdGgtLTtcbiAgICAgICAgdGhpcy5pc0NvbXB1dGluZyA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgO1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLm9ic2VydmUgPSBmdW5jdGlvbiAobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgZmlyc3RUaW1lID0gdHJ1ZTtcbiAgICAgICAgdmFyIHByZXZWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIGF1dG9ydW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG5ld1ZhbHVlID0gX3RoaXMuZ2V0KCk7XG4gICAgICAgICAgICBpZiAoIWZpcnN0VGltZSB8fCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldlUgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyKHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiBfdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWU6IG5ld1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZTogcHJldlZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpcnN0VGltZSA9IGZhbHNlO1xuICAgICAgICAgICAgcHJldlZhbHVlID0gbmV3VmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoKTtcbiAgICB9O1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lICsgXCJbXCIgKyB0aGlzLmRlcml2YXRpb24udG9TdHJpbmcoKSArIFwiXVwiO1xuICAgIH07XG4gICAgQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudmFsdWVPZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRvUHJpbWl0aXZlKHRoaXMuZ2V0KCkpO1xuICAgIH07XG4gICAgO1xuICAgIENvbXB1dGVkVmFsdWUucHJvdG90eXBlLndoeVJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlzVHJhY2tpbmcgPSBCb29sZWFuKGdsb2JhbFN0YXRlLnRyYWNraW5nRGVyaXZhdGlvbik7XG4gICAgICAgIHZhciBvYnNlcnZpbmcgPSB1bmlxdWUodGhpcy5pc0NvbXB1dGluZyA/IHRoaXMubmV3T2JzZXJ2aW5nIDogdGhpcy5vYnNlcnZpbmcpLm1hcChmdW5jdGlvbiAoZGVwKSB7IHJldHVybiBkZXAubmFtZTsgfSk7XG4gICAgICAgIHZhciBvYnNlcnZlcnMgPSB1bmlxdWUoZ2V0T2JzZXJ2ZXJzKHRoaXMpLm1hcChmdW5jdGlvbiAoZGVwKSB7IHJldHVybiBkZXAubmFtZTsgfSkpO1xuICAgICAgICByZXR1cm4gKFwiXFxuV2h5UnVuPyBjb21wdXRhdGlvbiAnXCIgKyB0aGlzLm5hbWUgKyBcIic6XFxuICogUnVubmluZyBiZWNhdXNlOiBcIiArIChpc1RyYWNraW5nID8gXCJbYWN0aXZlXSB0aGUgdmFsdWUgb2YgdGhpcyBjb21wdXRhdGlvbiBpcyBuZWVkZWQgYnkgYSByZWFjdGlvblwiIDogdGhpcy5pc0NvbXB1dGluZyA/IFwiW2dldF0gVGhlIHZhbHVlIG9mIHRoaXMgY29tcHV0ZWQgd2FzIHJlcXVlc3RlZCBvdXRzaWRlIGEgcmVhY3Rpb25cIiA6IFwiW2lkbGVdIG5vdCBydW5uaW5nIGF0IHRoZSBtb21lbnRcIikgKyBcIlxcblwiICtcbiAgICAgICAgICAgICh0aGlzLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLk5PVF9UUkFDS0lORyA/IGdldE1lc3NhZ2UoXCJtMDMyXCIpIDpcbiAgICAgICAgICAgICAgICBcIiAqIFRoaXMgY29tcHV0YXRpb24gd2lsbCByZS1ydW4gaWYgYW55IG9mIHRoZSBmb2xsb3dpbmcgb2JzZXJ2YWJsZXMgY2hhbmdlczpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZpbmcpICsgXCJcXG4gICAgXCIgKyAoKHRoaXMuaXNDb21wdXRpbmcgJiYgaXNUcmFja2luZykgPyBcIiAoLi4uIG9yIGFueSBvYnNlcnZhYmxlIGFjY2Vzc2VkIGR1cmluZyB0aGUgcmVtYWluZGVyIG9mIHRoZSBjdXJyZW50IHJ1bilcIiA6IFwiXCIpICsgXCJcXG5cXHRcIiArIGdldE1lc3NhZ2UoXCJtMDM4XCIpICsgXCJcXG5cXG4gICogSWYgdGhlIG91dGNvbWUgb2YgdGhpcyBjb21wdXRhdGlvbiBjaGFuZ2VzLCB0aGUgZm9sbG93aW5nIG9ic2VydmVycyB3aWxsIGJlIHJlLXJ1bjpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZlcnMpICsgXCJcXG5cIikpO1xuICAgIH07XG4gICAgcmV0dXJuIENvbXB1dGVkVmFsdWU7XG59KCkpO1xuQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGVbcHJpbWl0aXZlU3ltYm9sKCldID0gQ29tcHV0ZWRWYWx1ZS5wcm90b3R5cGUudmFsdWVPZjtcbnZhciBpc0NvbXB1dGVkVmFsdWUgPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiQ29tcHV0ZWRWYWx1ZVwiLCBDb21wdXRlZFZhbHVlKTtcbnZhciBJRGVyaXZhdGlvblN0YXRlO1xuKGZ1bmN0aW9uIChJRGVyaXZhdGlvblN0YXRlKSB7XG4gICAgSURlcml2YXRpb25TdGF0ZVtJRGVyaXZhdGlvblN0YXRlW1wiTk9UX1RSQUNLSU5HXCJdID0gLTFdID0gXCJOT1RfVFJBQ0tJTkdcIjtcbiAgICBJRGVyaXZhdGlvblN0YXRlW0lEZXJpdmF0aW9uU3RhdGVbXCJVUF9UT19EQVRFXCJdID0gMF0gPSBcIlVQX1RPX0RBVEVcIjtcbiAgICBJRGVyaXZhdGlvblN0YXRlW0lEZXJpdmF0aW9uU3RhdGVbXCJQT1NTSUJMWV9TVEFMRVwiXSA9IDFdID0gXCJQT1NTSUJMWV9TVEFMRVwiO1xuICAgIElEZXJpdmF0aW9uU3RhdGVbSURlcml2YXRpb25TdGF0ZVtcIlNUQUxFXCJdID0gMl0gPSBcIlNUQUxFXCI7XG59KShJRGVyaXZhdGlvblN0YXRlIHx8IChJRGVyaXZhdGlvblN0YXRlID0ge30pKTtcbmV4cG9ydHMuSURlcml2YXRpb25TdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGU7XG52YXIgQ2F1Z2h0RXhjZXB0aW9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDYXVnaHRFeGNlcHRpb24oY2F1c2UpIHtcbiAgICAgICAgdGhpcy5jYXVzZSA9IGNhdXNlO1xuICAgIH1cbiAgICByZXR1cm4gQ2F1Z2h0RXhjZXB0aW9uO1xufSgpKTtcbmZ1bmN0aW9uIGlzQ2F1Z2h0RXhjZXB0aW9uKGUpIHtcbiAgICByZXR1cm4gZSBpbnN0YW5jZW9mIENhdWdodEV4Y2VwdGlvbjtcbn1cbmZ1bmN0aW9uIHNob3VsZENvbXB1dGUoZGVyaXZhdGlvbikge1xuICAgIHN3aXRjaCAoZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSkge1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTogcmV0dXJuIGZhbHNlO1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HOlxuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuU1RBTEU6IHJldHVybiB0cnVlO1xuICAgICAgICBjYXNlIElEZXJpdmF0aW9uU3RhdGUuUE9TU0lCTFlfU1RBTEU6IHtcbiAgICAgICAgICAgIHZhciBwcmV2VW50cmFja2VkID0gdW50cmFja2VkU3RhcnQoKTtcbiAgICAgICAgICAgIHZhciBvYnMgPSBkZXJpdmF0aW9uLm9ic2VydmluZywgbCA9IG9icy5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBvYmogPSBvYnNbaV07XG4gICAgICAgICAgICAgICAgaWYgKGlzQ29tcHV0ZWRWYWx1ZShvYmopKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmouZ2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVudHJhY2tlZEVuZChwcmV2VW50cmFja2VkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkZXJpdmF0aW9uLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1bnRyYWNrZWRFbmQocHJldlVudHJhY2tlZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoYW5nZURlcGVuZGVuY2llc1N0YXRlVG8wKGRlcml2YXRpb24pO1xuICAgICAgICAgICAgdW50cmFja2VkRW5kKHByZXZVbnRyYWNrZWQpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gaXNDb21wdXRpbmdEZXJpdmF0aW9uKCkge1xuICAgIHJldHVybiBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb24gIT09IG51bGw7XG59XG5mdW5jdGlvbiBjaGVja0lmU3RhdGVNb2RpZmljYXRpb25zQXJlQWxsb3dlZChhdG9tKSB7XG4gICAgdmFyIGhhc09ic2VydmVycyA9IGF0b20ub2JzZXJ2ZXJzLmxlbmd0aCA+IDA7XG4gICAgaWYgKGdsb2JhbFN0YXRlLmNvbXB1dGF0aW9uRGVwdGggPiAwICYmIGhhc09ic2VydmVycylcbiAgICAgICAgZmFpbChnZXRNZXNzYWdlKFwibTAzMVwiKSArIGF0b20ubmFtZSk7XG4gICAgaWYgKCFnbG9iYWxTdGF0ZS5hbGxvd1N0YXRlQ2hhbmdlcyAmJiBoYXNPYnNlcnZlcnMpXG4gICAgICAgIGZhaWwoZ2V0TWVzc2FnZShnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlID8gXCJtMDMwYVwiIDogXCJtMDMwYlwiKSArIGF0b20ubmFtZSk7XG59XG5mdW5jdGlvbiB0cmFja0Rlcml2ZWRGdW5jdGlvbihkZXJpdmF0aW9uLCBmLCBjb250ZXh0KSB7XG4gICAgY2hhbmdlRGVwZW5kZW5jaWVzU3RhdGVUbzAoZGVyaXZhdGlvbik7XG4gICAgZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmcgPSBuZXcgQXJyYXkoZGVyaXZhdGlvbi5vYnNlcnZpbmcubGVuZ3RoICsgMTAwKTtcbiAgICBkZXJpdmF0aW9uLnVuYm91bmREZXBzQ291bnQgPSAwO1xuICAgIGRlcml2YXRpb24ucnVuSWQgPSArK2dsb2JhbFN0YXRlLnJ1bklkO1xuICAgIHZhciBwcmV2VHJhY2tpbmcgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gZGVyaXZhdGlvbjtcbiAgICB2YXIgcmVzdWx0O1xuICAgIHRyeSB7XG4gICAgICAgIHJlc3VsdCA9IGYuY2FsbChjb250ZXh0KTtcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVzdWx0ID0gbmV3IENhdWdodEV4Y2VwdGlvbihlKTtcbiAgICB9XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gcHJldlRyYWNraW5nO1xuICAgIGJpbmREZXBlbmRlbmNpZXMoZGVyaXZhdGlvbik7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGJpbmREZXBlbmRlbmNpZXMoZGVyaXZhdGlvbikge1xuICAgIHZhciBwcmV2T2JzZXJ2aW5nID0gZGVyaXZhdGlvbi5vYnNlcnZpbmc7XG4gICAgdmFyIG9ic2VydmluZyA9IGRlcml2YXRpb24ub2JzZXJ2aW5nID0gZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmc7XG4gICAgZGVyaXZhdGlvbi5uZXdPYnNlcnZpbmcgPSBudWxsO1xuICAgIHZhciBpMCA9IDAsIGwgPSBkZXJpdmF0aW9uLnVuYm91bmREZXBzQ291bnQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgdmFyIGRlcCA9IG9ic2VydmluZ1tpXTtcbiAgICAgICAgaWYgKGRlcC5kaWZmVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIGRlcC5kaWZmVmFsdWUgPSAxO1xuICAgICAgICAgICAgaWYgKGkwICE9PSBpKVxuICAgICAgICAgICAgICAgIG9ic2VydmluZ1tpMF0gPSBkZXA7XG4gICAgICAgICAgICBpMCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIG9ic2VydmluZy5sZW5ndGggPSBpMDtcbiAgICBsID0gcHJldk9ic2VydmluZy5sZW5ndGg7XG4gICAgd2hpbGUgKGwtLSkge1xuICAgICAgICB2YXIgZGVwID0gcHJldk9ic2VydmluZ1tsXTtcbiAgICAgICAgaWYgKGRlcC5kaWZmVmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgIHJlbW92ZU9ic2VydmVyKGRlcCwgZGVyaXZhdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgZGVwLmRpZmZWYWx1ZSA9IDA7XG4gICAgfVxuICAgIHdoaWxlIChpMC0tKSB7XG4gICAgICAgIHZhciBkZXAgPSBvYnNlcnZpbmdbaTBdO1xuICAgICAgICBpZiAoZGVwLmRpZmZWYWx1ZSA9PT0gMSkge1xuICAgICAgICAgICAgZGVwLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgICAgICBhZGRPYnNlcnZlcihkZXAsIGRlcml2YXRpb24pO1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gY2xlYXJPYnNlcnZpbmcoZGVyaXZhdGlvbikge1xuICAgIHZhciBvYnMgPSBkZXJpdmF0aW9uLm9ic2VydmluZztcbiAgICB2YXIgaSA9IG9icy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSlcbiAgICAgICAgcmVtb3ZlT2JzZXJ2ZXIob2JzW2ldLCBkZXJpdmF0aW9uKTtcbiAgICBkZXJpdmF0aW9uLmRlcGVuZGVuY2llc1N0YXRlID0gSURlcml2YXRpb25TdGF0ZS5OT1RfVFJBQ0tJTkc7XG4gICAgb2JzLmxlbmd0aCA9IDA7XG59XG5mdW5jdGlvbiB1bnRyYWNrZWQoYWN0aW9uKSB7XG4gICAgdmFyIHByZXYgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgIHZhciByZXMgPSBhY3Rpb24oKTtcbiAgICB1bnRyYWNrZWRFbmQocHJldik7XG4gICAgcmV0dXJuIHJlcztcbn1cbmV4cG9ydHMudW50cmFja2VkID0gdW50cmFja2VkO1xuZnVuY3Rpb24gdW50cmFja2VkU3RhcnQoKSB7XG4gICAgdmFyIHByZXYgPSBnbG9iYWxTdGF0ZS50cmFja2luZ0Rlcml2YXRpb247XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gbnVsbDtcbiAgICByZXR1cm4gcHJldjtcbn1cbmZ1bmN0aW9uIHVudHJhY2tlZEVuZChwcmV2KSB7XG4gICAgZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uID0gcHJldjtcbn1cbmZ1bmN0aW9uIGNoYW5nZURlcGVuZGVuY2llc1N0YXRlVG8wKGRlcml2YXRpb24pIHtcbiAgICBpZiAoZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFKVxuICAgICAgICByZXR1cm47XG4gICAgZGVyaXZhdGlvbi5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURTtcbiAgICB2YXIgb2JzID0gZGVyaXZhdGlvbi5vYnNlcnZpbmc7XG4gICAgdmFyIGkgPSBvYnMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0pXG4gICAgICAgIG9ic1tpXS5sb3dlc3RPYnNlcnZlclN0YXRlID0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFO1xufVxudmFyIHBlcnNpc3RlbnRLZXlzID0gW1wibW9ieEd1aWRcIiwgXCJyZXNldElkXCIsIFwic3B5TGlzdGVuZXJzXCIsIFwic3RyaWN0TW9kZVwiLCBcInJ1bklkXCJdO1xudmFyIE1vYlhHbG9iYWxzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBNb2JYR2xvYmFscygpIHtcbiAgICAgICAgdGhpcy52ZXJzaW9uID0gNTtcbiAgICAgICAgdGhpcy50cmFja2luZ0Rlcml2YXRpb24gPSBudWxsO1xuICAgICAgICB0aGlzLmNvbXB1dGF0aW9uRGVwdGggPSAwO1xuICAgICAgICB0aGlzLnJ1bklkID0gMDtcbiAgICAgICAgdGhpcy5tb2J4R3VpZCA9IDA7XG4gICAgICAgIHRoaXMuaW5CYXRjaCA9IDA7XG4gICAgICAgIHRoaXMucGVuZGluZ1Vub2JzZXJ2YXRpb25zID0gW107XG4gICAgICAgIHRoaXMucGVuZGluZ1JlYWN0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmlzUnVubmluZ1JlYWN0aW9ucyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFsbG93U3RhdGVDaGFuZ2VzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdHJpY3RNb2RlID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVzZXRJZCA9IDA7XG4gICAgICAgIHRoaXMuc3B5TGlzdGVuZXJzID0gW107XG4gICAgICAgIHRoaXMuZ2xvYmFsUmVhY3Rpb25FcnJvckhhbmRsZXJzID0gW107XG4gICAgfVxuICAgIHJldHVybiBNb2JYR2xvYmFscztcbn0oKSk7XG52YXIgZ2xvYmFsU3RhdGUgPSBuZXcgTW9iWEdsb2JhbHMoKTtcbmZ1bmN0aW9uIHNoYXJlR2xvYmFsU3RhdGUoKSB7XG4gICAgdmFyIGdsb2JhbCA9IGdldEdsb2JhbCgpO1xuICAgIHZhciBvd25TdGF0ZSA9IGdsb2JhbFN0YXRlO1xuICAgIGlmIChnbG9iYWwuX19tb2JzZXJ2YWJsZVRyYWNraW5nU3RhY2sgfHwgZ2xvYmFsLl9fbW9ic2VydmFibGVWaWV3U3RhY2spXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4XSBBbiBpbmNvbXBhdGlibGUgdmVyc2lvbiBvZiBtb2JzZXJ2YWJsZSBpcyBhbHJlYWR5IGxvYWRlZC5cIik7XG4gICAgaWYgKGdsb2JhbC5fX21vYnhHbG9iYWwgJiYgZ2xvYmFsLl9fbW9ieEdsb2JhbC52ZXJzaW9uICE9PSBvd25TdGF0ZS52ZXJzaW9uKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieF0gQW4gaW5jb21wYXRpYmxlIHZlcnNpb24gb2YgbW9ieCBpcyBhbHJlYWR5IGxvYWRlZC5cIik7XG4gICAgaWYgKGdsb2JhbC5fX21vYnhHbG9iYWwpXG4gICAgICAgIGdsb2JhbFN0YXRlID0gZ2xvYmFsLl9fbW9ieEdsb2JhbDtcbiAgICBlbHNlXG4gICAgICAgIGdsb2JhbC5fX21vYnhHbG9iYWwgPSBvd25TdGF0ZTtcbn1cbmZ1bmN0aW9uIGdldEdsb2JhbFN0YXRlKCkge1xuICAgIHJldHVybiBnbG9iYWxTdGF0ZTtcbn1cbmZ1bmN0aW9uIHJlZ2lzdGVyR2xvYmFscygpIHtcbn1cbmZ1bmN0aW9uIHJlc2V0R2xvYmFsU3RhdGUoKSB7XG4gICAgZ2xvYmFsU3RhdGUucmVzZXRJZCsrO1xuICAgIHZhciBkZWZhdWx0R2xvYmFscyA9IG5ldyBNb2JYR2xvYmFscygpO1xuICAgIGZvciAodmFyIGtleSBpbiBkZWZhdWx0R2xvYmFscylcbiAgICAgICAgaWYgKHBlcnNpc3RlbnRLZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpXG4gICAgICAgICAgICBnbG9iYWxTdGF0ZVtrZXldID0gZGVmYXVsdEdsb2JhbHNba2V5XTtcbiAgICBnbG9iYWxTdGF0ZS5hbGxvd1N0YXRlQ2hhbmdlcyA9ICFnbG9iYWxTdGF0ZS5zdHJpY3RNb2RlO1xufVxuZnVuY3Rpb24gaGFzT2JzZXJ2ZXJzKG9ic2VydmFibGUpIHtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5vYnNlcnZlcnMgJiYgb2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID4gMDtcbn1cbmZ1bmN0aW9uIGdldE9ic2VydmVycyhvYnNlcnZhYmxlKSB7XG4gICAgcmV0dXJuIG9ic2VydmFibGUub2JzZXJ2ZXJzO1xufVxuZnVuY3Rpb24gaW52YXJpYW50T2JzZXJ2ZXJzKG9ic2VydmFibGUpIHtcbiAgICB2YXIgbGlzdCA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBtYXAgPSBvYnNlcnZhYmxlLm9ic2VydmVyc0luZGV4ZXM7XG4gICAgdmFyIGwgPSBsaXN0Lmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBsaXN0W2ldLl9fbWFwaWQ7XG4gICAgICAgIGlmIChpKSB7XG4gICAgICAgICAgICBpbnZhcmlhbnQobWFwW2lkXSA9PT0gaSwgXCJJTlRFUk5BTCBFUlJPUiBtYXBzIGRlcml2YXRpb24uX19tYXBpZCB0byBpbmRleCBpbiBsaXN0XCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaW52YXJpYW50KCEoaWQgaW4gbWFwKSwgXCJJTlRFUk5BTCBFUlJPUiBvYnNlcnZlciBvbiBpbmRleCAwIHNob3VsZG50IGJlIGhlbGQgaW4gbWFwLlwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpbnZhcmlhbnQobGlzdC5sZW5ndGggPT09IDAgfHwgT2JqZWN0LmtleXMobWFwKS5sZW5ndGggPT09IGxpc3QubGVuZ3RoIC0gMSwgXCJJTlRFUk5BTCBFUlJPUiB0aGVyZSBpcyBubyBqdW5rIGluIG1hcFwiKTtcbn1cbmZ1bmN0aW9uIGFkZE9ic2VydmVyKG9ic2VydmFibGUsIG5vZGUpIHtcbiAgICB2YXIgbCA9IG9ic2VydmFibGUub2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICBpZiAobCkge1xuICAgICAgICBvYnNlcnZhYmxlLm9ic2VydmVyc0luZGV4ZXNbbm9kZS5fX21hcGlkXSA9IGw7XG4gICAgfVxuICAgIG9ic2VydmFibGUub2JzZXJ2ZXJzW2xdID0gbm9kZTtcbiAgICBpZiAob2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlID4gbm9kZS5kZXBlbmRlbmNpZXNTdGF0ZSlcbiAgICAgICAgb2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlID0gbm9kZS5kZXBlbmRlbmNpZXNTdGF0ZTtcbn1cbmZ1bmN0aW9uIHJlbW92ZU9ic2VydmVyKG9ic2VydmFibGUsIG5vZGUpIHtcbiAgICBpZiAob2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIG9ic2VydmFibGUub2JzZXJ2ZXJzLmxlbmd0aCA9IDA7XG4gICAgICAgIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBsaXN0ID0gb2JzZXJ2YWJsZS5vYnNlcnZlcnM7XG4gICAgICAgIHZhciBtYXBfMSA9IG9ic2VydmFibGUub2JzZXJ2ZXJzSW5kZXhlcztcbiAgICAgICAgdmFyIGZpbGxlciA9IGxpc3QucG9wKCk7XG4gICAgICAgIGlmIChmaWxsZXIgIT09IG5vZGUpIHtcbiAgICAgICAgICAgIHZhciBpbmRleCA9IG1hcF8xW25vZGUuX19tYXBpZF0gfHwgMDtcbiAgICAgICAgICAgIGlmIChpbmRleCkge1xuICAgICAgICAgICAgICAgIG1hcF8xW2ZpbGxlci5fX21hcGlkXSA9IGluZGV4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIG1hcF8xW2ZpbGxlci5fX21hcGlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpc3RbaW5kZXhdID0gZmlsbGVyO1xuICAgICAgICB9XG4gICAgICAgIGRlbGV0ZSBtYXBfMVtub2RlLl9fbWFwaWRdO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKSB7XG4gICAgaWYgKCFvYnNlcnZhYmxlLmlzUGVuZGluZ1Vub2JzZXJ2YXRpb24pIHtcbiAgICAgICAgb2JzZXJ2YWJsZS5pc1BlbmRpbmdVbm9ic2VydmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgZ2xvYmFsU3RhdGUucGVuZGluZ1Vub2JzZXJ2YXRpb25zLnB1c2gob2JzZXJ2YWJsZSk7XG4gICAgfVxufVxuZnVuY3Rpb24gc3RhcnRCYXRjaCgpIHtcbiAgICBnbG9iYWxTdGF0ZS5pbkJhdGNoKys7XG59XG5mdW5jdGlvbiBlbmRCYXRjaCgpIHtcbiAgICBpZiAoLS1nbG9iYWxTdGF0ZS5pbkJhdGNoID09PSAwKSB7XG4gICAgICAgIHJ1blJlYWN0aW9ucygpO1xuICAgICAgICB2YXIgbGlzdCA9IGdsb2JhbFN0YXRlLnBlbmRpbmdVbm9ic2VydmF0aW9ucztcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb2JzZXJ2YWJsZV8xID0gbGlzdFtpXTtcbiAgICAgICAgICAgIG9ic2VydmFibGVfMS5pc1BlbmRpbmdVbm9ic2VydmF0aW9uID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAob2JzZXJ2YWJsZV8xLm9ic2VydmVycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBvYnNlcnZhYmxlXzEub25CZWNvbWVVbm9ic2VydmVkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2xvYmFsU3RhdGUucGVuZGluZ1Vub2JzZXJ2YXRpb25zID0gW107XG4gICAgfVxufVxuZnVuY3Rpb24gcmVwb3J0T2JzZXJ2ZWQob2JzZXJ2YWJsZSkge1xuICAgIHZhciBkZXJpdmF0aW9uID0gZ2xvYmFsU3RhdGUudHJhY2tpbmdEZXJpdmF0aW9uO1xuICAgIGlmIChkZXJpdmF0aW9uICE9PSBudWxsKSB7XG4gICAgICAgIGlmIChkZXJpdmF0aW9uLnJ1bklkICE9PSBvYnNlcnZhYmxlLmxhc3RBY2Nlc3NlZEJ5KSB7XG4gICAgICAgICAgICBvYnNlcnZhYmxlLmxhc3RBY2Nlc3NlZEJ5ID0gZGVyaXZhdGlvbi5ydW5JZDtcbiAgICAgICAgICAgIGRlcml2YXRpb24ubmV3T2JzZXJ2aW5nW2Rlcml2YXRpb24udW5ib3VuZERlcHNDb3VudCsrXSA9IG9ic2VydmFibGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAob2JzZXJ2YWJsZS5vYnNlcnZlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHF1ZXVlRm9yVW5vYnNlcnZhdGlvbihvYnNlcnZhYmxlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBpbnZhcmlhbnRMT1Mob2JzZXJ2YWJsZSwgbXNnKSB7XG4gICAgdmFyIG1pbiA9IGdldE9ic2VydmVycyhvYnNlcnZhYmxlKS5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIE1hdGgubWluKGEsIGIuZGVwZW5kZW5jaWVzU3RhdGUpOyB9LCAyKTtcbiAgICBpZiAobWluID49IG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSlcbiAgICAgICAgcmV0dXJuO1xuICAgIHRocm93IG5ldyBFcnJvcihcImxvd2VzdE9ic2VydmVyU3RhdGUgaXMgd3JvbmcgZm9yIFwiICsgbXNnICsgXCIgYmVjYXVzZSBcIiArIG1pbiArIFwiIDwgXCIgKyBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUpO1xufVxuZnVuY3Rpb24gcHJvcGFnYXRlQ2hhbmdlZChvYnNlcnZhYmxlKSB7XG4gICAgaWYgKG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5TVEFMRSlcbiAgICAgICAgcmV0dXJuO1xuICAgIG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuU1RBTEU7XG4gICAgdmFyIG9ic2VydmVycyA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBpID0gb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIHZhciBkID0gb2JzZXJ2ZXJzW2ldO1xuICAgICAgICBpZiAoZC5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5VUF9UT19EQVRFKVxuICAgICAgICAgICAgZC5vbkJlY29tZVN0YWxlKCk7XG4gICAgICAgIGQuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHByb3BhZ2F0ZUNoYW5nZUNvbmZpcm1lZChvYnNlcnZhYmxlKSB7XG4gICAgaWYgKG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5TVEFMRSlcbiAgICAgICAgcmV0dXJuO1xuICAgIG9ic2VydmFibGUubG93ZXN0T2JzZXJ2ZXJTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuU1RBTEU7XG4gICAgdmFyIG9ic2VydmVycyA9IG9ic2VydmFibGUub2JzZXJ2ZXJzO1xuICAgIHZhciBpID0gb2JzZXJ2ZXJzLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIHZhciBkID0gb2JzZXJ2ZXJzW2ldO1xuICAgICAgICBpZiAoZC5kZXBlbmRlbmNpZXNTdGF0ZSA9PT0gSURlcml2YXRpb25TdGF0ZS5QT1NTSUJMWV9TVEFMRSlcbiAgICAgICAgICAgIGQuZGVwZW5kZW5jaWVzU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlNUQUxFO1xuICAgICAgICBlbHNlIGlmIChkLmRlcGVuZGVuY2llc1N0YXRlID09PSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEUpXG4gICAgICAgICAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEU7XG4gICAgfVxufVxuZnVuY3Rpb24gcHJvcGFnYXRlTWF5YmVDaGFuZ2VkKG9ic2VydmFibGUpIHtcbiAgICBpZiAob2JzZXJ2YWJsZS5sb3dlc3RPYnNlcnZlclN0YXRlICE9PSBJRGVyaXZhdGlvblN0YXRlLlVQX1RPX0RBVEUpXG4gICAgICAgIHJldHVybjtcbiAgICBvYnNlcnZhYmxlLmxvd2VzdE9ic2VydmVyU3RhdGUgPSBJRGVyaXZhdGlvblN0YXRlLlBPU1NJQkxZX1NUQUxFO1xuICAgIHZhciBvYnNlcnZlcnMgPSBvYnNlcnZhYmxlLm9ic2VydmVycztcbiAgICB2YXIgaSA9IG9ic2VydmVycy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgICB2YXIgZCA9IG9ic2VydmVyc1tpXTtcbiAgICAgICAgaWYgKGQuZGVwZW5kZW5jaWVzU3RhdGUgPT09IElEZXJpdmF0aW9uU3RhdGUuVVBfVE9fREFURSkge1xuICAgICAgICAgICAgZC5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuUE9TU0lCTFlfU1RBTEU7XG4gICAgICAgICAgICBkLm9uQmVjb21lU3RhbGUoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbnZhciBSZWFjdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUmVhY3Rpb24obmFtZSwgb25JbnZhbGlkYXRlKSB7XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiUmVhY3Rpb25AXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLm9uSW52YWxpZGF0ZSA9IG9uSW52YWxpZGF0ZTtcbiAgICAgICAgdGhpcy5vYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5uZXdPYnNlcnZpbmcgPSBbXTtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXNTdGF0ZSA9IElEZXJpdmF0aW9uU3RhdGUuTk9UX1RSQUNLSU5HO1xuICAgICAgICB0aGlzLmRpZmZWYWx1ZSA9IDA7XG4gICAgICAgIHRoaXMucnVuSWQgPSAwO1xuICAgICAgICB0aGlzLnVuYm91bmREZXBzQ291bnQgPSAwO1xuICAgICAgICB0aGlzLl9fbWFwaWQgPSBcIiNcIiArIGdldE5leHRJZCgpO1xuICAgICAgICB0aGlzLmlzRGlzcG9zZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNTY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNUcmFja1BlbmRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgfVxuICAgIFJlYWN0aW9uLnByb3RvdHlwZS5vbkJlY29tZVN0YWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNjaGVkdWxlKCk7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuc2NoZWR1bGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5faXNTY2hlZHVsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2lzU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlLnBlbmRpbmdSZWFjdGlvbnMucHVzaCh0aGlzKTtcbiAgICAgICAgICAgIHJ1blJlYWN0aW9ucygpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuaXNTY2hlZHVsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc1NjaGVkdWxlZDtcbiAgICB9O1xuICAgIFJlYWN0aW9uLnByb3RvdHlwZS5ydW5SZWFjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgIHRoaXMuX2lzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoc2hvdWxkQ29tcHV0ZSh0aGlzKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2lzVHJhY2tQZW5kaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uSW52YWxpZGF0ZSgpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1RyYWNrUGVuZGluZyAmJiBpc1NweUVuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICBzcHlSZXBvcnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzY2hlZHVsZWQtcmVhY3Rpb25cIlxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUudHJhY2sgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgc3RhcnRCYXRjaCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBzdGFydFRpbWU7XG4gICAgICAgIGlmIChub3RpZnkpIHtcbiAgICAgICAgICAgIHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydCh7XG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIHR5cGU6IFwicmVhY3Rpb25cIixcbiAgICAgICAgICAgICAgICBmbjogZm5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2lzUnVubmluZyA9IHRydWU7XG4gICAgICAgIHZhciByZXN1bHQgPSB0cmFja0Rlcml2ZWRGdW5jdGlvbih0aGlzLCBmbiwgdW5kZWZpbmVkKTtcbiAgICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2lzVHJhY2tQZW5kaW5nID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIGNsZWFyT2JzZXJ2aW5nKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0NhdWdodEV4Y2VwdGlvbihyZXN1bHQpKVxuICAgICAgICAgICAgdGhpcy5yZXBvcnRFeGNlcHRpb25JbkRlcml2YXRpb24ocmVzdWx0LmNhdXNlKTtcbiAgICAgICAgaWYgKG5vdGlmeSkge1xuICAgICAgICAgICAgc3B5UmVwb3J0RW5kKHtcbiAgICAgICAgICAgICAgICB0aW1lOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbmRCYXRjaCgpO1xuICAgIH07XG4gICAgUmVhY3Rpb24ucHJvdG90eXBlLnJlcG9ydEV4Y2VwdGlvbkluRGVyaXZhdGlvbiA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAodGhpcy5lcnJvckhhbmRsZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyKGVycm9yLCB0aGlzKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWVzc2FnZSA9IFwiW21vYnhdIEVuY291bnRlcmVkIGFuIHVuY2F1Z2h0IGV4Y2VwdGlvbiB0aGF0IHdhcyB0aHJvd24gYnkgYSByZWFjdGlvbiBvciBvYnNlcnZlciBjb21wb25lbnQsIGluOiAnXCIgKyB0aGlzO1xuICAgICAgICB2YXIgbWVzc2FnZVRvVXNlciA9IGdldE1lc3NhZ2UoXCJtMDM3XCIpO1xuICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UgfHwgbWVzc2FnZVRvVXNlciwgZXJyb3IpO1xuICAgICAgICBpZiAoaXNTcHlFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHNweVJlcG9ydCh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZ2xvYmFsU3RhdGUuZ2xvYmFsUmVhY3Rpb25FcnJvckhhbmRsZXJzLmZvckVhY2goZnVuY3Rpb24gKGYpIHsgcmV0dXJuIGYoZXJyb3IsIF90aGlzKTsgfSk7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuZGlzcG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaXNEaXNwb3NlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2lzUnVubmluZykge1xuICAgICAgICAgICAgICAgIHN0YXJ0QmF0Y2goKTtcbiAgICAgICAgICAgICAgICBjbGVhck9ic2VydmluZyh0aGlzKTtcbiAgICAgICAgICAgICAgICBlbmRCYXRjaCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUuZ2V0RGlzcG9zZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByID0gdGhpcy5kaXNwb3NlLmJpbmQodGhpcyk7XG4gICAgICAgIHIuJG1vYnggPSB0aGlzO1xuICAgICAgICByLm9uRXJyb3IgPSByZWdpc3RlckVycm9ySGFuZGxlcjtcbiAgICAgICAgcmV0dXJuIHI7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlJlYWN0aW9uW1wiICsgdGhpcy5uYW1lICsgXCJdXCI7XG4gICAgfTtcbiAgICBSZWFjdGlvbi5wcm90b3R5cGUud2h5UnVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb2JzZXJ2aW5nID0gdW5pcXVlKHRoaXMuX2lzUnVubmluZyA/IHRoaXMubmV3T2JzZXJ2aW5nIDogdGhpcy5vYnNlcnZpbmcpLm1hcChmdW5jdGlvbiAoZGVwKSB7IHJldHVybiBkZXAubmFtZTsgfSk7XG4gICAgICAgIHJldHVybiAoXCJcXG5XaHlSdW4/IHJlYWN0aW9uICdcIiArIHRoaXMubmFtZSArIFwiJzpcXG4gKiBTdGF0dXM6IFtcIiArICh0aGlzLmlzRGlzcG9zZWQgPyBcInN0b3BwZWRcIiA6IHRoaXMuX2lzUnVubmluZyA/IFwicnVubmluZ1wiIDogdGhpcy5pc1NjaGVkdWxlZCgpID8gXCJzY2hlZHVsZWRcIiA6IFwiaWRsZVwiKSArIFwiXVxcbiAqIFRoaXMgcmVhY3Rpb24gd2lsbCByZS1ydW4gaWYgYW55IG9mIHRoZSBmb2xsb3dpbmcgb2JzZXJ2YWJsZXMgY2hhbmdlczpcXG4gICAgXCIgKyBqb2luU3RyaW5ncyhvYnNlcnZpbmcpICsgXCJcXG4gICAgXCIgKyAoKHRoaXMuX2lzUnVubmluZykgPyBcIiAoLi4uIG9yIGFueSBvYnNlcnZhYmxlIGFjY2Vzc2VkIGR1cmluZyB0aGUgcmVtYWluZGVyIG9mIHRoZSBjdXJyZW50IHJ1bilcIiA6IFwiXCIpICsgXCJcXG5cXHRcIiArIGdldE1lc3NhZ2UoXCJtMDM4XCIpICsgXCJcXG5cIik7XG4gICAgfTtcbiAgICByZXR1cm4gUmVhY3Rpb247XG59KCkpO1xuZXhwb3J0cy5SZWFjdGlvbiA9IFJlYWN0aW9uO1xuZnVuY3Rpb24gcmVnaXN0ZXJFcnJvckhhbmRsZXIoaGFuZGxlcikge1xuICAgIGludmFyaWFudCh0aGlzICYmIHRoaXMuJG1vYnggJiYgaXNSZWFjdGlvbih0aGlzLiRtb2J4KSwgXCJJbnZhbGlkIGB0aGlzYFwiKTtcbiAgICBpbnZhcmlhbnQoIXRoaXMuJG1vYnguZXJyb3JIYW5kbGVyLCBcIk9ubHkgb25lIG9uRXJyb3JIYW5kbGVyIGNhbiBiZSByZWdpc3RlcmVkXCIpO1xuICAgIHRoaXMuJG1vYnguZXJyb3JIYW5kbGVyID0gaGFuZGxlcjtcbn1cbmZ1bmN0aW9uIG9uUmVhY3Rpb25FcnJvcihoYW5kbGVyKSB7XG4gICAgZ2xvYmFsU3RhdGUuZ2xvYmFsUmVhY3Rpb25FcnJvckhhbmRsZXJzLnB1c2goaGFuZGxlcik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlkeCA9IGdsb2JhbFN0YXRlLmdsb2JhbFJlYWN0aW9uRXJyb3JIYW5kbGVycy5pbmRleE9mKGhhbmRsZXIpO1xuICAgICAgICBpZiAoaWR4ID49IDApXG4gICAgICAgICAgICBnbG9iYWxTdGF0ZS5nbG9iYWxSZWFjdGlvbkVycm9ySGFuZGxlcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgfTtcbn1cbnZhciBNQVhfUkVBQ1RJT05fSVRFUkFUSU9OUyA9IDEwMDtcbnZhciByZWFjdGlvblNjaGVkdWxlciA9IGZ1bmN0aW9uIChmKSB7IHJldHVybiBmKCk7IH07XG5mdW5jdGlvbiBydW5SZWFjdGlvbnMoKSB7XG4gICAgaWYgKGdsb2JhbFN0YXRlLmluQmF0Y2ggPiAwIHx8IGdsb2JhbFN0YXRlLmlzUnVubmluZ1JlYWN0aW9ucylcbiAgICAgICAgcmV0dXJuO1xuICAgIHJlYWN0aW9uU2NoZWR1bGVyKHJ1blJlYWN0aW9uc0hlbHBlcik7XG59XG5mdW5jdGlvbiBydW5SZWFjdGlvbnNIZWxwZXIoKSB7XG4gICAgZ2xvYmFsU3RhdGUuaXNSdW5uaW5nUmVhY3Rpb25zID0gdHJ1ZTtcbiAgICB2YXIgYWxsUmVhY3Rpb25zID0gZ2xvYmFsU3RhdGUucGVuZGluZ1JlYWN0aW9ucztcbiAgICB2YXIgaXRlcmF0aW9ucyA9IDA7XG4gICAgd2hpbGUgKGFsbFJlYWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGlmICgrK2l0ZXJhdGlvbnMgPT09IE1BWF9SRUFDVElPTl9JVEVSQVRJT05TKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiUmVhY3Rpb24gZG9lc24ndCBjb252ZXJnZSB0byBhIHN0YWJsZSBzdGF0ZSBhZnRlciBcIiArIE1BWF9SRUFDVElPTl9JVEVSQVRJT05TICsgXCIgaXRlcmF0aW9ucy5cIlxuICAgICAgICAgICAgICAgICsgKFwiIFByb2JhYmx5IHRoZXJlIGlzIGEgY3ljbGUgaW4gdGhlIHJlYWN0aXZlIGZ1bmN0aW9uOiBcIiArIGFsbFJlYWN0aW9uc1swXSkpO1xuICAgICAgICAgICAgYWxsUmVhY3Rpb25zLnNwbGljZSgwKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVtYWluaW5nUmVhY3Rpb25zID0gYWxsUmVhY3Rpb25zLnNwbGljZSgwKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSByZW1haW5pbmdSZWFjdGlvbnMubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgICAgICAgcmVtYWluaW5nUmVhY3Rpb25zW2ldLnJ1blJlYWN0aW9uKCk7XG4gICAgfVxuICAgIGdsb2JhbFN0YXRlLmlzUnVubmluZ1JlYWN0aW9ucyA9IGZhbHNlO1xufVxudmFyIGlzUmVhY3Rpb24gPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiUmVhY3Rpb25cIiwgUmVhY3Rpb24pO1xuZnVuY3Rpb24gc2V0UmVhY3Rpb25TY2hlZHVsZXIoZm4pIHtcbiAgICB2YXIgYmFzZVNjaGVkdWxlciA9IHJlYWN0aW9uU2NoZWR1bGVyO1xuICAgIHJlYWN0aW9uU2NoZWR1bGVyID0gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIGZuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGJhc2VTY2hlZHVsZXIoZik7IH0pOyB9O1xufVxuZnVuY3Rpb24gaXNTcHlFbmFibGVkKCkge1xuICAgIHJldHVybiAhIWdsb2JhbFN0YXRlLnNweUxpc3RlbmVycy5sZW5ndGg7XG59XG5mdW5jdGlvbiBzcHlSZXBvcnQoZXZlbnQpIHtcbiAgICBpZiAoIWdsb2JhbFN0YXRlLnNweUxpc3RlbmVycy5sZW5ndGgpXG4gICAgICAgIHJldHVybjtcbiAgICB2YXIgbGlzdGVuZXJzID0gZ2xvYmFsU3RhdGUuc3B5TGlzdGVuZXJzO1xuICAgIGZvciAodmFyIGkgPSAwLCBsID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGw7IGkrKylcbiAgICAgICAgbGlzdGVuZXJzW2ldKGV2ZW50KTtcbn1cbmZ1bmN0aW9uIHNweVJlcG9ydFN0YXJ0KGV2ZW50KSB7XG4gICAgdmFyIGNoYW5nZSA9IG9iamVjdEFzc2lnbih7fSwgZXZlbnQsIHsgc3B5UmVwb3J0U3RhcnQ6IHRydWUgfSk7XG4gICAgc3B5UmVwb3J0KGNoYW5nZSk7XG59XG52YXIgRU5EX0VWRU5UID0geyBzcHlSZXBvcnRFbmQ6IHRydWUgfTtcbmZ1bmN0aW9uIHNweVJlcG9ydEVuZChjaGFuZ2UpIHtcbiAgICBpZiAoY2hhbmdlKVxuICAgICAgICBzcHlSZXBvcnQob2JqZWN0QXNzaWduKHt9LCBjaGFuZ2UsIEVORF9FVkVOVCkpO1xuICAgIGVsc2VcbiAgICAgICAgc3B5UmVwb3J0KEVORF9FVkVOVCk7XG59XG5mdW5jdGlvbiBzcHkobGlzdGVuZXIpIHtcbiAgICBnbG9iYWxTdGF0ZS5zcHlMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7XG4gICAgcmV0dXJuIG9uY2UoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaWR4ID0gZ2xvYmFsU3RhdGUuc3B5TGlzdGVuZXJzLmluZGV4T2YobGlzdGVuZXIpO1xuICAgICAgICBpZiAoaWR4ICE9PSAtMSlcbiAgICAgICAgICAgIGdsb2JhbFN0YXRlLnNweUxpc3RlbmVycy5zcGxpY2UoaWR4LCAxKTtcbiAgICB9KTtcbn1cbmV4cG9ydHMuc3B5ID0gc3B5O1xuZnVuY3Rpb24gaGFzSW50ZXJjZXB0b3JzKGludGVyY2VwdGFibGUpIHtcbiAgICByZXR1cm4gKGludGVyY2VwdGFibGUuaW50ZXJjZXB0b3JzICYmIGludGVyY2VwdGFibGUuaW50ZXJjZXB0b3JzLmxlbmd0aCA+IDApO1xufVxuZnVuY3Rpb24gcmVnaXN0ZXJJbnRlcmNlcHRvcihpbnRlcmNlcHRhYmxlLCBoYW5kbGVyKSB7XG4gICAgdmFyIGludGVyY2VwdG9ycyA9IGludGVyY2VwdGFibGUuaW50ZXJjZXB0b3JzIHx8IChpbnRlcmNlcHRhYmxlLmludGVyY2VwdG9ycyA9IFtdKTtcbiAgICBpbnRlcmNlcHRvcnMucHVzaChoYW5kbGVyKTtcbiAgICByZXR1cm4gb25jZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpZHggPSBpbnRlcmNlcHRvcnMuaW5kZXhPZihoYW5kbGVyKTtcbiAgICAgICAgaWYgKGlkeCAhPT0gLTEpXG4gICAgICAgICAgICBpbnRlcmNlcHRvcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgfSk7XG59XG5mdW5jdGlvbiBpbnRlcmNlcHRDaGFuZ2UoaW50ZXJjZXB0YWJsZSwgY2hhbmdlKSB7XG4gICAgdmFyIHByZXZVID0gdW50cmFja2VkU3RhcnQoKTtcbiAgICB0cnkge1xuICAgICAgICB2YXIgaW50ZXJjZXB0b3JzID0gaW50ZXJjZXB0YWJsZS5pbnRlcmNlcHRvcnM7XG4gICAgICAgIGlmIChpbnRlcmNlcHRvcnMpXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGludGVyY2VwdG9ycy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjaGFuZ2UgPSBpbnRlcmNlcHRvcnNbaV0oY2hhbmdlKTtcbiAgICAgICAgICAgICAgICBpbnZhcmlhbnQoIWNoYW5nZSB8fCBjaGFuZ2UudHlwZSwgXCJJbnRlcmNlcHQgaGFuZGxlcnMgc2hvdWxkIHJldHVybiBub3RoaW5nIG9yIGEgY2hhbmdlIG9iamVjdFwiKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIHJldHVybiBjaGFuZ2U7XG4gICAgfVxuICAgIGZpbmFsbHkge1xuICAgICAgICB1bnRyYWNrZWRFbmQocHJldlUpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGhhc0xpc3RlbmVycyhsaXN0ZW5hYmxlKSB7XG4gICAgcmV0dXJuIGxpc3RlbmFibGUuY2hhbmdlTGlzdGVuZXJzICYmIGxpc3RlbmFibGUuY2hhbmdlTGlzdGVuZXJzLmxlbmd0aCA+IDA7XG59XG5mdW5jdGlvbiByZWdpc3Rlckxpc3RlbmVyKGxpc3RlbmFibGUsIGhhbmRsZXIpIHtcbiAgICB2YXIgbGlzdGVuZXJzID0gbGlzdGVuYWJsZS5jaGFuZ2VMaXN0ZW5lcnMgfHwgKGxpc3RlbmFibGUuY2hhbmdlTGlzdGVuZXJzID0gW10pO1xuICAgIGxpc3RlbmVycy5wdXNoKGhhbmRsZXIpO1xuICAgIHJldHVybiBvbmNlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlkeCA9IGxpc3RlbmVycy5pbmRleE9mKGhhbmRsZXIpO1xuICAgICAgICBpZiAoaWR4ICE9PSAtMSlcbiAgICAgICAgICAgIGxpc3RlbmVycy5zcGxpY2UoaWR4LCAxKTtcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIG5vdGlmeUxpc3RlbmVycyhsaXN0ZW5hYmxlLCBjaGFuZ2UpIHtcbiAgICB2YXIgcHJldlUgPSB1bnRyYWNrZWRTdGFydCgpO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBsaXN0ZW5hYmxlLmNoYW5nZUxpc3RlbmVycztcbiAgICBpZiAoIWxpc3RlbmVycylcbiAgICAgICAgcmV0dXJuO1xuICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5zbGljZSgpO1xuICAgIGZvciAodmFyIGkgPSAwLCBsID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICBsaXN0ZW5lcnNbaV0oY2hhbmdlKTtcbiAgICB9XG4gICAgdW50cmFja2VkRW5kKHByZXZVKTtcbn1cbmZ1bmN0aW9uIGFzUmVmZXJlbmNlKHZhbHVlKSB7XG4gICAgZGVwcmVjYXRlZChcImFzUmVmZXJlbmNlIGlzIGRlcHJlY2F0ZWQsIHVzZSBvYnNlcnZhYmxlLnJlZiBpbnN0ZWFkXCIpO1xuICAgIHJldHVybiBvYnNlcnZhYmxlLnJlZih2YWx1ZSk7XG59XG5leHBvcnRzLmFzUmVmZXJlbmNlID0gYXNSZWZlcmVuY2U7XG5mdW5jdGlvbiBhc1N0cnVjdHVyZSh2YWx1ZSkge1xuICAgIGRlcHJlY2F0ZWQoXCJhc1N0cnVjdHVyZSBpcyBkZXByZWNhdGVkLiBVc2Ugb2JzZXJ2YWJsZS5zdHJ1Y3QsIGNvbXB1dGVkLnN0cnVjdCBvciByZWFjdGlvbiBvcHRpb25zIGluc3RlYWQuXCIpO1xuICAgIHJldHVybiBvYnNlcnZhYmxlLnN0cnVjdCh2YWx1ZSk7XG59XG5leHBvcnRzLmFzU3RydWN0dXJlID0gYXNTdHJ1Y3R1cmU7XG5mdW5jdGlvbiBhc0ZsYXQodmFsdWUpIHtcbiAgICBkZXByZWNhdGVkKFwiYXNGbGF0IGlzIGRlcHJlY2F0ZWQsIHVzZSBvYnNlcnZhYmxlLnNoYWxsb3cgaW5zdGVhZFwiKTtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5zaGFsbG93KHZhbHVlKTtcbn1cbmV4cG9ydHMuYXNGbGF0ID0gYXNGbGF0O1xuZnVuY3Rpb24gYXNNYXAoZGF0YSkge1xuICAgIGRlcHJlY2F0ZWQoXCJhc01hcCBpcyBkZXByZWNhdGVkLCB1c2Ugb2JzZXJ2YWJsZS5tYXAgb3Igb2JzZXJ2YWJsZS5zaGFsbG93TWFwIGluc3RlYWRcIik7XG4gICAgcmV0dXJuIG9ic2VydmFibGUubWFwKGRhdGEgfHwge30pO1xufVxuZXhwb3J0cy5hc01hcCA9IGFzTWFwO1xuZnVuY3Rpb24gaXNNb2RpZmllckRlc2NyaXB0b3IodGhpbmcpIHtcbiAgICByZXR1cm4gdHlwZW9mIHRoaW5nID09PSBcIm9iamVjdFwiICYmIHRoaW5nICE9PSBudWxsICYmIHRoaW5nLmlzTW9ieE1vZGlmaWVyRGVzY3JpcHRvciA9PT0gdHJ1ZTtcbn1cbmV4cG9ydHMuaXNNb2RpZmllckRlc2NyaXB0b3IgPSBpc01vZGlmaWVyRGVzY3JpcHRvcjtcbmZ1bmN0aW9uIGNyZWF0ZU1vZGlmaWVyRGVzY3JpcHRvcihlbmhhbmNlciwgaW5pdGlhbFZhbHVlKSB7XG4gICAgaW52YXJpYW50KCFpc01vZGlmaWVyRGVzY3JpcHRvcihpbml0aWFsVmFsdWUpLCBcIk1vZGlmaWVycyBjYW5ub3QgYmUgbmVzdGVkXCIpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGlzTW9ieE1vZGlmaWVyRGVzY3JpcHRvcjogdHJ1ZSxcbiAgICAgICAgaW5pdGlhbFZhbHVlOiBpbml0aWFsVmFsdWUsXG4gICAgICAgIGVuaGFuY2VyOiBlbmhhbmNlclxuICAgIH07XG59XG5mdW5jdGlvbiBkZWVwRW5oYW5jZXIodiwgXywgbmFtZSkge1xuICAgIGlmIChpc01vZGlmaWVyRGVzY3JpcHRvcih2KSlcbiAgICAgICAgZmFpbChcIllvdSB0cmllZCB0byBhc3NpZ24gYSBtb2RpZmllciB3cmFwcGVkIHZhbHVlIHRvIGEgY29sbGVjdGlvbiwgcGxlYXNlIGRlZmluZSBtb2RpZmllcnMgd2hlbiBjcmVhdGluZyB0aGUgY29sbGVjdGlvbiwgbm90IHdoZW4gbW9kaWZ5aW5nIGl0XCIpO1xuICAgIGlmIChpc09ic2VydmFibGUodikpXG4gICAgICAgIHJldHVybiB2O1xuICAgIGlmIChBcnJheS5pc0FycmF5KHYpKVxuICAgICAgICByZXR1cm4gb2JzZXJ2YWJsZS5hcnJheSh2LCBuYW1lKTtcbiAgICBpZiAoaXNQbGFpbk9iamVjdCh2KSlcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUub2JqZWN0KHYsIG5hbWUpO1xuICAgIGlmIChpc0VTNk1hcCh2KSlcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUuc2hhbGxvd01hcCh2LCBuYW1lKTtcbiAgICByZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIHNoYWxsb3dFbmhhbmNlcih2LCBfLCBuYW1lKSB7XG4gICAgaWYgKGlzTW9kaWZpZXJEZXNjcmlwdG9yKHYpKVxuICAgICAgICBmYWlsKFwiWW91IHRyaWVkIHRvIGFzc2lnbiBhIG1vZGlmaWVyIHdyYXBwZWQgdmFsdWUgdG8gYSBjb2xsZWN0aW9uLCBwbGVhc2UgZGVmaW5lIG1vZGlmaWVycyB3aGVuIGNyZWF0aW5nIHRoZSBjb2xsZWN0aW9uLCBub3Qgd2hlbiBtb2RpZnlpbmcgaXRcIik7XG4gICAgaWYgKHYgPT09IHVuZGVmaW5lZCB8fCB2ID09PSBudWxsKVxuICAgICAgICByZXR1cm4gdjtcbiAgICBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHYpIHx8IGlzT2JzZXJ2YWJsZUFycmF5KHYpIHx8IGlzT2JzZXJ2YWJsZU1hcCh2KSlcbiAgICAgICAgcmV0dXJuIHY7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodikpXG4gICAgICAgIHJldHVybiBvYnNlcnZhYmxlLnNoYWxsb3dBcnJheSh2LCBuYW1lKTtcbiAgICBpZiAoaXNQbGFpbk9iamVjdCh2KSlcbiAgICAgICAgcmV0dXJuIG9ic2VydmFibGUuc2hhbGxvd09iamVjdCh2LCBuYW1lKTtcbiAgICBpZiAoaXNFUzZNYXAodikpXG4gICAgICAgIHJldHVybiBvYnNlcnZhYmxlLnNoYWxsb3dNYXAodiwgbmFtZSk7XG4gICAgcmV0dXJuIGZhaWwoXCJUaGUgc2hhbGxvdyBtb2RpZmllciAvIGRlY29yYXRvciBjYW4gb25seSB1c2VkIGluIGNvbWJpbmF0aW9uIHdpdGggYXJyYXlzLCBvYmplY3RzIGFuZCBtYXBzXCIpO1xufVxuZnVuY3Rpb24gcmVmZXJlbmNlRW5oYW5jZXIobmV3VmFsdWUpIHtcbiAgICByZXR1cm4gbmV3VmFsdWU7XG59XG5mdW5jdGlvbiBkZWVwU3RydWN0RW5oYW5jZXIodiwgb2xkVmFsdWUsIG5hbWUpIHtcbiAgICBpZiAoZGVlcEVxdWFsKHYsIG9sZFZhbHVlKSlcbiAgICAgICAgcmV0dXJuIG9sZFZhbHVlO1xuICAgIGlmIChpc09ic2VydmFibGUodikpXG4gICAgICAgIHJldHVybiB2O1xuICAgIGlmIChBcnJheS5pc0FycmF5KHYpKVxuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGVBcnJheSh2LCBkZWVwU3RydWN0RW5oYW5jZXIsIG5hbWUpO1xuICAgIGlmIChpc0VTNk1hcCh2KSlcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlTWFwKHYsIGRlZXBTdHJ1Y3RFbmhhbmNlciwgbmFtZSk7XG4gICAgaWYgKGlzUGxhaW5PYmplY3QodikpIHtcbiAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICBhc09ic2VydmFibGVPYmplY3QocmVzLCBuYW1lKTtcbiAgICAgICAgZXh0ZW5kT2JzZXJ2YWJsZUhlbHBlcihyZXMsIGRlZXBTdHJ1Y3RFbmhhbmNlciwgW3ZdKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG4gICAgcmV0dXJuIHY7XG59XG5mdW5jdGlvbiByZWZTdHJ1Y3RFbmhhbmNlcih2LCBvbGRWYWx1ZSwgbmFtZSkge1xuICAgIGlmIChkZWVwRXF1YWwodiwgb2xkVmFsdWUpKVxuICAgICAgICByZXR1cm4gb2xkVmFsdWU7XG4gICAgcmV0dXJuIHY7XG59XG52YXIgc2FmYXJpUHJvdG90eXBlU2V0dGVySW5oZXJpdGFuY2VCdWcgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciB2ID0gZmFsc2U7XG4gICAgdmFyIHAgPSB7fTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocCwgXCIwXCIsIHsgc2V0OiBmdW5jdGlvbiAoKSB7IHYgPSB0cnVlOyB9IH0pO1xuICAgIE9iamVjdC5jcmVhdGUocClbXCIwXCJdID0gMTtcbiAgICByZXR1cm4gdiA9PT0gZmFsc2U7XG59KSgpO1xudmFyIE9CU0VSVkFCTEVfQVJSQVlfQlVGRkVSX1NJWkUgPSAwO1xudmFyIFN0dWJBcnJheSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gU3R1YkFycmF5KCkge1xuICAgIH1cbiAgICByZXR1cm4gU3R1YkFycmF5O1xufSgpKTtcblN0dWJBcnJheS5wcm90b3R5cGUgPSBbXTtcbnZhciBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24obmFtZSwgZW5oYW5jZXIsIGFycmF5LCBvd25lZCkge1xuICAgICAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG4gICAgICAgIHRoaXMub3duZWQgPSBvd25lZDtcbiAgICAgICAgdGhpcy5sYXN0S25vd25MZW5ndGggPSAwO1xuICAgICAgICB0aGlzLmludGVyY2VwdG9ycyA9IG51bGw7XG4gICAgICAgIHRoaXMuY2hhbmdlTGlzdGVuZXJzID0gbnVsbDtcbiAgICAgICAgdGhpcy5hdG9tID0gbmV3IEJhc2VBdG9tKG5hbWUgfHwgKFwiT2JzZXJ2YWJsZUFycmF5QFwiICsgZ2V0TmV4dElkKCkpKTtcbiAgICAgICAgdGhpcy5lbmhhbmNlciA9IGZ1bmN0aW9uIChuZXdWLCBvbGRWKSB7IHJldHVybiBlbmhhbmNlcihuZXdWLCBvbGRWLCBuYW1lICsgXCJbLi5dXCIpOyB9O1xuICAgIH1cbiAgICBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbi5wcm90b3R5cGUuaW50ZXJjZXB0ID0gZnVuY3Rpb24gKGhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVySW50ZXJjZXB0b3IodGhpcywgaGFuZGxlcik7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbi5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uIChsaXN0ZW5lciwgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgIGlmIChmaXJlSW1tZWRpYXRlbHkgPT09IHZvaWQgMCkgeyBmaXJlSW1tZWRpYXRlbHkgPSBmYWxzZTsgfVxuICAgICAgICBpZiAoZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgICAgICBsaXN0ZW5lcih7XG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLmFycmF5LFxuICAgICAgICAgICAgICAgIHR5cGU6IFwic3BsaWNlXCIsXG4gICAgICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICAgICAgYWRkZWQ6IHRoaXMudmFsdWVzLnNsaWNlKCksXG4gICAgICAgICAgICAgICAgYWRkZWRDb3VudDogdGhpcy52YWx1ZXMubGVuZ3RoLFxuICAgICAgICAgICAgICAgIHJlbW92ZWQ6IFtdLFxuICAgICAgICAgICAgICAgIHJlbW92ZWRDb3VudDogMFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVyTGlzdGVuZXIodGhpcywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLmdldEFycmF5TGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheUFkbWluaXN0cmF0aW9uLnByb3RvdHlwZS5zZXRBcnJheUxlbmd0aCA9IGZ1bmN0aW9uIChuZXdMZW5ndGgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuZXdMZW5ndGggIT09IFwibnVtYmVyXCIgfHwgbmV3TGVuZ3RoIDwgMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4LmFycmF5XSBPdXQgb2YgcmFuZ2U6IFwiICsgbmV3TGVuZ3RoKTtcbiAgICAgICAgdmFyIGN1cnJlbnRMZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIGlmIChuZXdMZW5ndGggPT09IGN1cnJlbnRMZW5ndGgpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGVsc2UgaWYgKG5ld0xlbmd0aCA+IGN1cnJlbnRMZW5ndGgpXG4gICAgICAgICAgICB0aGlzLnNwbGljZVdpdGhBcnJheShjdXJyZW50TGVuZ3RoLCAwLCBuZXcgQXJyYXkobmV3TGVuZ3RoIC0gY3VycmVudExlbmd0aCkpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLnNwbGljZVdpdGhBcnJheShuZXdMZW5ndGgsIGN1cnJlbnRMZW5ndGggLSBuZXdMZW5ndGgpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLnVwZGF0ZUFycmF5TGVuZ3RoID0gZnVuY3Rpb24gKG9sZExlbmd0aCwgZGVsdGEpIHtcbiAgICAgICAgaWYgKG9sZExlbmd0aCAhPT0gdGhpcy5sYXN0S25vd25MZW5ndGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieF0gTW9kaWZpY2F0aW9uIGV4Y2VwdGlvbjogdGhlIGludGVybmFsIHN0cnVjdHVyZSBvZiBhbiBvYnNlcnZhYmxlIGFycmF5IHdhcyBjaGFuZ2VkLiBEaWQgeW91IHVzZSBwZWVrKCkgdG8gY2hhbmdlIGl0P1wiKTtcbiAgICAgICAgdGhpcy5sYXN0S25vd25MZW5ndGggKz0gZGVsdGE7XG4gICAgICAgIGlmIChkZWx0YSA+IDAgJiYgb2xkTGVuZ3RoICsgZGVsdGEgKyAxID4gT0JTRVJWQUJMRV9BUlJBWV9CVUZGRVJfU0laRSlcbiAgICAgICAgICAgIHJlc2VydmVBcnJheUJ1ZmZlcihvbGRMZW5ndGggKyBkZWx0YSArIDEpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLnNwbGljZVdpdGhBcnJheSA9IGZ1bmN0aW9uIChpbmRleCwgZGVsZXRlQ291bnQsIG5ld0l0ZW1zKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGNoZWNrSWZTdGF0ZU1vZGlmaWNhdGlvbnNBcmVBbGxvd2VkKHRoaXMuYXRvbSk7XG4gICAgICAgIHZhciBsZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gICAgICAgIGlmIChpbmRleCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgaW5kZXggPSAwO1xuICAgICAgICBlbHNlIGlmIChpbmRleCA+IGxlbmd0aClcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoO1xuICAgICAgICBlbHNlIGlmIChpbmRleCA8IDApXG4gICAgICAgICAgICBpbmRleCA9IE1hdGgubWF4KDAsIGxlbmd0aCArIGluZGV4KTtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpXG4gICAgICAgICAgICBkZWxldGVDb3VudCA9IGxlbmd0aCAtIGluZGV4O1xuICAgICAgICBlbHNlIGlmIChkZWxldGVDb3VudCA9PT0gdW5kZWZpbmVkIHx8IGRlbGV0ZUNvdW50ID09PSBudWxsKVxuICAgICAgICAgICAgZGVsZXRlQ291bnQgPSAwO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGVDb3VudCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGRlbGV0ZUNvdW50LCBsZW5ndGggLSBpbmRleCkpO1xuICAgICAgICBpZiAobmV3SXRlbXMgPT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIG5ld0l0ZW1zID0gW107XG4gICAgICAgIGlmIChoYXNJbnRlcmNlcHRvcnModGhpcykpIHtcbiAgICAgICAgICAgIHZhciBjaGFuZ2UgPSBpbnRlcmNlcHRDaGFuZ2UodGhpcywge1xuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcy5hcnJheSxcbiAgICAgICAgICAgICAgICB0eXBlOiBcInNwbGljZVwiLFxuICAgICAgICAgICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgICAgICAgICByZW1vdmVkQ291bnQ6IGRlbGV0ZUNvdW50LFxuICAgICAgICAgICAgICAgIGFkZGVkOiBuZXdJdGVtc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gRU1QVFlfQVJSQVk7XG4gICAgICAgICAgICBkZWxldGVDb3VudCA9IGNoYW5nZS5yZW1vdmVkQ291bnQ7XG4gICAgICAgICAgICBuZXdJdGVtcyA9IGNoYW5nZS5hZGRlZDtcbiAgICAgICAgfVxuICAgICAgICBuZXdJdGVtcyA9IG5ld0l0ZW1zLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gX3RoaXMuZW5oYW5jZXIodiwgdW5kZWZpbmVkKTsgfSk7XG4gICAgICAgIHZhciBsZW5ndGhEZWx0YSA9IG5ld0l0ZW1zLmxlbmd0aCAtIGRlbGV0ZUNvdW50O1xuICAgICAgICB0aGlzLnVwZGF0ZUFycmF5TGVuZ3RoKGxlbmd0aCwgbGVuZ3RoRGVsdGEpO1xuICAgICAgICB2YXIgcmVzID0gKF9hID0gdGhpcy52YWx1ZXMpLnNwbGljZS5hcHBseShfYSwgW2luZGV4LCBkZWxldGVDb3VudF0uY29uY2F0KG5ld0l0ZW1zKSk7XG4gICAgICAgIGlmIChkZWxldGVDb3VudCAhPT0gMCB8fCBuZXdJdGVtcy5sZW5ndGggIT09IDApXG4gICAgICAgICAgICB0aGlzLm5vdGlmeUFycmF5U3BsaWNlKGluZGV4LCBuZXdJdGVtcywgcmVzKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgdmFyIF9hO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24ucHJvdG90eXBlLm5vdGlmeUFycmF5Q2hpbGRVcGRhdGUgPSBmdW5jdGlvbiAoaW5kZXgsIG5ld1ZhbHVlLCBvbGRWYWx1ZSkge1xuICAgICAgICB2YXIgbm90aWZ5U3B5ID0gIXRoaXMub3duZWQgJiYgaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBub3RpZnkgPSBoYXNMaXN0ZW5lcnModGhpcyk7XG4gICAgICAgIHZhciBjaGFuZ2UgPSBub3RpZnkgfHwgbm90aWZ5U3B5ID8ge1xuICAgICAgICAgICAgb2JqZWN0OiB0aGlzLmFycmF5LFxuICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgIGluZGV4OiBpbmRleCwgbmV3VmFsdWU6IG5ld1ZhbHVlLCBvbGRWYWx1ZTogb2xkVmFsdWVcbiAgICAgICAgfSA6IG51bGw7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICB0aGlzLmF0b20ucmVwb3J0Q2hhbmdlZCgpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIGNoYW5nZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheUFkbWluaXN0cmF0aW9uLnByb3RvdHlwZS5ub3RpZnlBcnJheVNwbGljZSA9IGZ1bmN0aW9uIChpbmRleCwgYWRkZWQsIHJlbW92ZWQpIHtcbiAgICAgICAgdmFyIG5vdGlmeVNweSA9ICF0aGlzLm93bmVkICYmIGlzU3B5RW5hYmxlZCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaGFzTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgICAgIG9iamVjdDogdGhpcy5hcnJheSxcbiAgICAgICAgICAgIHR5cGU6IFwic3BsaWNlXCIsXG4gICAgICAgICAgICBpbmRleDogaW5kZXgsIHJlbW92ZWQ6IHJlbW92ZWQsIGFkZGVkOiBhZGRlZCxcbiAgICAgICAgICAgIHJlbW92ZWRDb3VudDogcmVtb3ZlZC5sZW5ndGgsXG4gICAgICAgICAgICBhZGRlZENvdW50OiBhZGRlZC5sZW5ndGhcbiAgICAgICAgfSA6IG51bGw7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICB0aGlzLmF0b20ucmVwb3J0Q2hhbmdlZCgpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIGNoYW5nZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICB9O1xuICAgIHJldHVybiBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbjtcbn0oKSk7XG52YXIgT2JzZXJ2YWJsZUFycmF5ID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoT2JzZXJ2YWJsZUFycmF5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIE9ic2VydmFibGVBcnJheShpbml0aWFsVmFsdWVzLCBlbmhhbmNlciwgbmFtZSwgb3duZWQpIHtcbiAgICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgeyBuYW1lID0gXCJPYnNlcnZhYmxlQXJyYXlAXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICBpZiAob3duZWQgPT09IHZvaWQgMCkgeyBvd25lZCA9IGZhbHNlOyB9XG4gICAgICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgICAgIHZhciBhZG0gPSBuZXcgT2JzZXJ2YWJsZUFycmF5QWRtaW5pc3RyYXRpb24obmFtZSwgZW5oYW5jZXIsIF90aGlzLCBvd25lZCk7XG4gICAgICAgIGFkZEhpZGRlbkZpbmFsUHJvcChfdGhpcywgXCIkbW9ieFwiLCBhZG0pO1xuICAgICAgICBpZiAoaW5pdGlhbFZhbHVlcyAmJiBpbml0aWFsVmFsdWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgYWRtLnVwZGF0ZUFycmF5TGVuZ3RoKDAsIGluaXRpYWxWYWx1ZXMubGVuZ3RoKTtcbiAgICAgICAgICAgIGFkbS52YWx1ZXMgPSBpbml0aWFsVmFsdWVzLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gZW5oYW5jZXIodiwgdW5kZWZpbmVkLCBuYW1lICsgXCJbLi5dXCIpOyB9KTtcbiAgICAgICAgICAgIGFkbS5ub3RpZnlBcnJheVNwbGljZSgwLCBhZG0udmFsdWVzLnNsaWNlKCksIEVNUFRZX0FSUkFZKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGFkbS52YWx1ZXMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2FmYXJpUHJvdG90eXBlU2V0dGVySW5oZXJpdGFuY2VCdWcpIHtcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhZG0uYXJyYXksIFwiMFwiLCBFTlRSWV8wKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUuaW50ZXJjZXB0ID0gZnVuY3Rpb24gKGhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuJG1vYnguaW50ZXJjZXB0KGhhbmRsZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5vYnNlcnZlID0gZnVuY3Rpb24gKGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICAgICAgaWYgKGZpcmVJbW1lZGlhdGVseSA9PT0gdm9pZCAwKSB7IGZpcmVJbW1lZGlhdGVseSA9IGZhbHNlOyB9XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4Lm9ic2VydmUobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcGxpY2UoMCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLmNvbmNhdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFycmF5cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgYXJyYXlzW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy4kbW9ieC5hdG9tLnJlcG9ydE9ic2VydmVkKCk7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KHRoaXMucGVlaygpLCBhcnJheXMubWFwKGZ1bmN0aW9uIChhKSB7IHJldHVybiBpc09ic2VydmFibGVBcnJheShhKSA/IGEucGVlaygpIDogYTsgfSkpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5yZXBsYWNlID0gZnVuY3Rpb24gKG5ld0l0ZW1zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnNwbGljZVdpdGhBcnJheSgwLCB0aGlzLiRtb2J4LnZhbHVlcy5sZW5ndGgsIG5ld0l0ZW1zKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUudG9KUyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2xpY2UoKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b0pTKCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLnBlZWsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnZhbHVlcztcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uIChwcmVkaWNhdGUsIHRoaXNBcmcsIGZyb21JbmRleCkge1xuICAgICAgICBpZiAoZnJvbUluZGV4ID09PSB2b2lkIDApIHsgZnJvbUluZGV4ID0gMDsgfVxuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgdmFyIGl0ZW1zID0gdGhpcy4kbW9ieC52YWx1ZXMsIGwgPSBpdGVtcy5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSBmcm9tSW5kZXg7IGkgPCBsOyBpKyspXG4gICAgICAgICAgICBpZiAocHJlZGljYXRlLmNhbGwodGhpc0FyZywgaXRlbXNbaV0sIGksIHRoaXMpKVxuICAgICAgICAgICAgICAgIHJldHVybiBpdGVtc1tpXTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUuc3BsaWNlID0gZnVuY3Rpb24gKGluZGV4LCBkZWxldGVDb3VudCkge1xuICAgICAgICB2YXIgbmV3SXRlbXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAyOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIG5ld0l0ZW1zW19pIC0gMl0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4kbW9ieC5zcGxpY2VXaXRoQXJyYXkoaW5kZXgpO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnNwbGljZVdpdGhBcnJheShpbmRleCwgZGVsZXRlQ291bnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnNwbGljZVdpdGhBcnJheShpbmRleCwgZGVsZXRlQ291bnQsIG5ld0l0ZW1zKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGl0ZW1zID0gW107XG4gICAgICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICBpdGVtc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhZG0gPSB0aGlzLiRtb2J4O1xuICAgICAgICBhZG0uc3BsaWNlV2l0aEFycmF5KGFkbS52YWx1ZXMubGVuZ3RoLCAwLCBpdGVtcyk7XG4gICAgICAgIHJldHVybiBhZG0udmFsdWVzLmxlbmd0aDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUucG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zcGxpY2UoTWF0aC5tYXgodGhpcy4kbW9ieC52YWx1ZXMubGVuZ3RoIC0gMSwgMCksIDEpWzBdO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5zaGlmdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3BsaWNlKDAsIDEpWzBdO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS51bnNoaWZ0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXRlbXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIGl0ZW1zW19pXSA9IGFyZ3VtZW50c1tfaV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGFkbSA9IHRoaXMuJG1vYng7XG4gICAgICAgIGFkbS5zcGxpY2VXaXRoQXJyYXkoMCwgMCwgaXRlbXMpO1xuICAgICAgICByZXR1cm4gYWRtLnZhbHVlcy5sZW5ndGg7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLnJldmVyc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuJG1vYnguYXRvbS5yZXBvcnRPYnNlcnZlZCgpO1xuICAgICAgICB2YXIgY2xvbmUgPSB0aGlzLnNsaWNlKCk7XG4gICAgICAgIHJldHVybiBjbG9uZS5yZXZlcnNlLmFwcGx5KGNsb25lLCBhcmd1bWVudHMpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5zb3J0ID0gZnVuY3Rpb24gKGNvbXBhcmVGbikge1xuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgdmFyIGNsb25lID0gdGhpcy5zbGljZSgpO1xuICAgICAgICByZXR1cm4gY2xvbmUuc29ydC5hcHBseShjbG9uZSwgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBpZHggPSB0aGlzLiRtb2J4LnZhbHVlcy5pbmRleE9mKHZhbHVlKTtcbiAgICAgICAgaWYgKGlkeCA+IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS5tb3ZlID0gZnVuY3Rpb24gKGZyb21JbmRleCwgdG9JbmRleCkge1xuICAgICAgICBmdW5jdGlvbiBjaGVja0luZGV4KGluZGV4KSB7XG4gICAgICAgICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYnguYXJyYXldIEluZGV4IG91dCBvZiBib3VuZHM6IFwiICsgaW5kZXggKyBcIiBpcyBuZWdhdGl2ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBsZW5ndGggPSB0aGlzLiRtb2J4LnZhbHVlcy5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYnguYXJyYXldIEluZGV4IG91dCBvZiBib3VuZHM6IFwiICsgaW5kZXggKyBcIiBpcyBub3Qgc21hbGxlciB0aGFuIFwiICsgbGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjaGVja0luZGV4LmNhbGwodGhpcywgZnJvbUluZGV4KTtcbiAgICAgICAgY2hlY2tJbmRleC5jYWxsKHRoaXMsIHRvSW5kZXgpO1xuICAgICAgICBpZiAoZnJvbUluZGV4ID09PSB0b0luZGV4KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9sZEl0ZW1zID0gdGhpcy4kbW9ieC52YWx1ZXM7XG4gICAgICAgIHZhciBuZXdJdGVtcztcbiAgICAgICAgaWYgKGZyb21JbmRleCA8IHRvSW5kZXgpIHtcbiAgICAgICAgICAgIG5ld0l0ZW1zID0gb2xkSXRlbXMuc2xpY2UoMCwgZnJvbUluZGV4KS5jb25jYXQob2xkSXRlbXMuc2xpY2UoZnJvbUluZGV4ICsgMSwgdG9JbmRleCArIDEpLCBbb2xkSXRlbXNbZnJvbUluZGV4XV0sIG9sZEl0ZW1zLnNsaWNlKHRvSW5kZXggKyAxKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBuZXdJdGVtcyA9IG9sZEl0ZW1zLnNsaWNlKDAsIHRvSW5kZXgpLmNvbmNhdChbb2xkSXRlbXNbZnJvbUluZGV4XV0sIG9sZEl0ZW1zLnNsaWNlKHRvSW5kZXgsIGZyb21JbmRleCksIG9sZEl0ZW1zLnNsaWNlKGZyb21JbmRleCArIDEpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlcGxhY2UobmV3SXRlbXMpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZUFycmF5LnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kbW9ieC5hdG9tLnJlcG9ydE9ic2VydmVkKCk7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUudG9TdHJpbmcuYXBwbHkodGhpcy4kbW9ieC52YWx1ZXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLnRvTG9jYWxlU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS50b0xvY2FsZVN0cmluZy5hcHBseSh0aGlzLiRtb2J4LnZhbHVlcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHJldHVybiBPYnNlcnZhYmxlQXJyYXk7XG59KFN0dWJBcnJheSkpO1xuZGVjbGFyZUl0ZXJhdG9yKE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYXJyYXlBc0l0ZXJhdG9yKHRoaXMuc2xpY2UoKSk7XG59KTtcbm1ha2VOb25FbnVtZXJhYmxlKE9ic2VydmFibGVBcnJheS5wcm90b3R5cGUsIFtcbiAgICBcImNvbnN0cnVjdG9yXCIsXG4gICAgXCJpbnRlcmNlcHRcIixcbiAgICBcIm9ic2VydmVcIixcbiAgICBcImNsZWFyXCIsXG4gICAgXCJjb25jYXRcIixcbiAgICBcInJlcGxhY2VcIixcbiAgICBcInRvSlNcIixcbiAgICBcInRvSlNPTlwiLFxuICAgIFwicGVla1wiLFxuICAgIFwiZmluZFwiLFxuICAgIFwic3BsaWNlXCIsXG4gICAgXCJwdXNoXCIsXG4gICAgXCJwb3BcIixcbiAgICBcInNoaWZ0XCIsXG4gICAgXCJ1bnNoaWZ0XCIsXG4gICAgXCJyZXZlcnNlXCIsXG4gICAgXCJzb3J0XCIsXG4gICAgXCJyZW1vdmVcIixcbiAgICBcIm1vdmVcIixcbiAgICBcInRvU3RyaW5nXCIsXG4gICAgXCJ0b0xvY2FsZVN0cmluZ1wiXG5dKTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLCBcImxlbmd0aFwiLCB7XG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy4kbW9ieC5nZXRBcnJheUxlbmd0aCgpO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAobmV3TGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuJG1vYnguc2V0QXJyYXlMZW5ndGgobmV3TGVuZ3RoKTtcbiAgICB9XG59KTtcbltcbiAgICBcImV2ZXJ5XCIsXG4gICAgXCJmaWx0ZXJcIixcbiAgICBcImZvckVhY2hcIixcbiAgICBcImluZGV4T2ZcIixcbiAgICBcImpvaW5cIixcbiAgICBcImxhc3RJbmRleE9mXCIsXG4gICAgXCJtYXBcIixcbiAgICBcInJlZHVjZVwiLFxuICAgIFwicmVkdWNlUmlnaHRcIixcbiAgICBcInNsaWNlXCIsXG4gICAgXCJzb21lXCJcbl0uZm9yRWFjaChmdW5jdGlvbiAoZnVuY05hbWUpIHtcbiAgICB2YXIgYmFzZUZ1bmMgPSBBcnJheS5wcm90b3R5cGVbZnVuY05hbWVdO1xuICAgIGludmFyaWFudCh0eXBlb2YgYmFzZUZ1bmMgPT09IFwiZnVuY3Rpb25cIiwgXCJCYXNlIGZ1bmN0aW9uIG5vdCBkZWZpbmVkIG9uIEFycmF5IHByb3RvdHlwZTogJ1wiICsgZnVuY05hbWUgKyBcIidcIik7XG4gICAgYWRkSGlkZGVuUHJvcChPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLCBmdW5jTmFtZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLiRtb2J4LmF0b20ucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIGJhc2VGdW5jLmFwcGx5KHRoaXMuJG1vYngudmFsdWVzLCBhcmd1bWVudHMpO1xuICAgIH0pO1xufSk7XG52YXIgRU5UUllfMCA9IHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgc2V0OiBjcmVhdGVBcnJheVNldHRlcigwKSxcbiAgICBnZXQ6IGNyZWF0ZUFycmF5R2V0dGVyKDApXG59O1xuZnVuY3Rpb24gY3JlYXRlQXJyYXlCdWZmZXJJdGVtKGluZGV4KSB7XG4gICAgdmFyIHNldCA9IGNyZWF0ZUFycmF5U2V0dGVyKGluZGV4KTtcbiAgICB2YXIgZ2V0ID0gY3JlYXRlQXJyYXlHZXR0ZXIoaW5kZXgpO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYnNlcnZhYmxlQXJyYXkucHJvdG90eXBlLCBcIlwiICsgaW5kZXgsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgc2V0OiBzZXQsIGdldDogZ2V0XG4gICAgfSk7XG59XG5mdW5jdGlvbiBjcmVhdGVBcnJheVNldHRlcihpbmRleCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIGFkbSA9IHRoaXMuJG1vYng7XG4gICAgICAgIHZhciB2YWx1ZXMgPSBhZG0udmFsdWVzO1xuICAgICAgICBpZiAoaW5kZXggPCB2YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjaGVja0lmU3RhdGVNb2RpZmljYXRpb25zQXJlQWxsb3dlZChhZG0uYXRvbSk7XG4gICAgICAgICAgICB2YXIgb2xkVmFsdWUgPSB2YWx1ZXNbaW5kZXhdO1xuICAgICAgICAgICAgaWYgKGhhc0ludGVyY2VwdG9ycyhhZG0pKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGludGVyY2VwdENoYW5nZShhZG0sIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiBhZG0uYXJyYXksXG4gICAgICAgICAgICAgICAgICAgIGluZGV4OiBpbmRleCwgbmV3VmFsdWU6IG5ld1ZhbHVlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKCFjaGFuZ2UpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZSA9IGNoYW5nZS5uZXdWYWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld1ZhbHVlID0gYWRtLmVuaGFuY2VyKG5ld1ZhbHVlLCBvbGRWYWx1ZSk7XG4gICAgICAgICAgICB2YXIgY2hhbmdlZCA9IG5ld1ZhbHVlICE9PSBvbGRWYWx1ZTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzW2luZGV4XSA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgIGFkbS5ub3RpZnlBcnJheUNoaWxkVXBkYXRlKGluZGV4LCBuZXdWYWx1ZSwgb2xkVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGluZGV4ID09PSB2YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBhZG0uc3BsaWNlV2l0aEFycmF5KGluZGV4LCAwLCBbbmV3VmFsdWVdKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJbbW9ieC5hcnJheV0gSW5kZXggb3V0IG9mIGJvdW5kcywgXCIgKyBpbmRleCArIFwiIGlzIGxhcmdlciB0aGFuIFwiICsgdmFsdWVzLmxlbmd0aCk7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUFycmF5R2V0dGVyKGluZGV4KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGltcGwgPSB0aGlzLiRtb2J4O1xuICAgICAgICBpZiAoaW1wbCkge1xuICAgICAgICAgICAgaWYgKGluZGV4IDwgaW1wbC52YWx1ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaW1wbC5hdG9tLnJlcG9ydE9ic2VydmVkKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGltcGwudmFsdWVzW2luZGV4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlttb2J4LmFycmF5XSBBdHRlbXB0IHRvIHJlYWQgYW4gYXJyYXkgaW5kZXggKFwiICsgaW5kZXggKyBcIikgdGhhdCBpcyBvdXQgb2YgYm91bmRzIChcIiArIGltcGwudmFsdWVzLmxlbmd0aCArIFwiKS4gUGxlYXNlIGNoZWNrIGxlbmd0aCBmaXJzdC4gT3V0IG9mIGJvdW5kIGluZGljZXMgd2lsbCBub3QgYmUgdHJhY2tlZCBieSBNb2JYXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfTtcbn1cbmZ1bmN0aW9uIHJlc2VydmVBcnJheUJ1ZmZlcihtYXgpIHtcbiAgICBmb3IgKHZhciBpbmRleCA9IE9CU0VSVkFCTEVfQVJSQVlfQlVGRkVSX1NJWkU7IGluZGV4IDwgbWF4OyBpbmRleCsrKVxuICAgICAgICBjcmVhdGVBcnJheUJ1ZmZlckl0ZW0oaW5kZXgpO1xuICAgIE9CU0VSVkFCTEVfQVJSQVlfQlVGRkVSX1NJWkUgPSBtYXg7XG59XG5yZXNlcnZlQXJyYXlCdWZmZXIoMTAwMCk7XG52YXIgaXNPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbiA9IGNyZWF0ZUluc3RhbmNlb2ZQcmVkaWNhdGUoXCJPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvblwiLCBPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbik7XG5mdW5jdGlvbiBpc09ic2VydmFibGVBcnJheSh0aGluZykge1xuICAgIHJldHVybiBpc09iamVjdCh0aGluZykgJiYgaXNPYnNlcnZhYmxlQXJyYXlBZG1pbmlzdHJhdGlvbih0aGluZy4kbW9ieCk7XG59XG5leHBvcnRzLmlzT2JzZXJ2YWJsZUFycmF5ID0gaXNPYnNlcnZhYmxlQXJyYXk7XG52YXIgT2JzZXJ2YWJsZU1hcE1hcmtlciA9IHt9O1xudmFyIE9ic2VydmFibGVNYXAgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIE9ic2VydmFibGVNYXAoaW5pdGlhbERhdGEsIGVuaGFuY2VyLCBuYW1lKSB7XG4gICAgICAgIGlmIChlbmhhbmNlciA9PT0gdm9pZCAwKSB7IGVuaGFuY2VyID0gZGVlcEVuaGFuY2VyOyB9XG4gICAgICAgIGlmIChuYW1lID09PSB2b2lkIDApIHsgbmFtZSA9IFwiT2JzZXJ2YWJsZU1hcEBcIiArIGdldE5leHRJZCgpOyB9XG4gICAgICAgIHRoaXMuZW5oYW5jZXIgPSBlbmhhbmNlcjtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy4kbW9ieCA9IE9ic2VydmFibGVNYXBNYXJrZXI7XG4gICAgICAgIHRoaXMuX2RhdGEgPSB7fTtcbiAgICAgICAgdGhpcy5faGFzTWFwID0ge307XG4gICAgICAgIHRoaXMuX2tleXMgPSBuZXcgT2JzZXJ2YWJsZUFycmF5KHVuZGVmaW5lZCwgcmVmZXJlbmNlRW5oYW5jZXIsIHRoaXMubmFtZSArIFwiLmtleXMoKVwiLCB0cnVlKTtcbiAgICAgICAgdGhpcy5pbnRlcmNlcHRvcnMgPSBudWxsO1xuICAgICAgICB0aGlzLmNoYW5nZUxpc3RlbmVycyA9IG51bGw7XG4gICAgICAgIHRoaXMubWVyZ2UoaW5pdGlhbERhdGEpO1xuICAgIH1cbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5faGFzID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHRoaXMuX2RhdGFba2V5XSAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWRLZXkoa2V5KSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAga2V5ID0gXCJcIiArIGtleTtcbiAgICAgICAgaWYgKHRoaXMuX2hhc01hcFtrZXldKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2hhc01hcFtrZXldLmdldCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5fdXBkYXRlSGFzTWFwRW50cnkoa2V5LCBmYWxzZSkuZ2V0KCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICB0aGlzLmFzc2VydFZhbGlkS2V5KGtleSk7XG4gICAgICAgIGtleSA9IFwiXCIgKyBrZXk7XG4gICAgICAgIHZhciBoYXNLZXkgPSB0aGlzLl9oYXMoa2V5KTtcbiAgICAgICAgaWYgKGhhc0ludGVyY2VwdG9ycyh0aGlzKSkge1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGludGVyY2VwdENoYW5nZSh0aGlzLCB7XG4gICAgICAgICAgICAgICAgdHlwZTogaGFzS2V5ID8gXCJ1cGRhdGVcIiA6IFwiYWRkXCIsXG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIG5ld1ZhbHVlOiB2YWx1ZSxcbiAgICAgICAgICAgICAgICBuYW1lOiBrZXlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCFjaGFuZ2UpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB2YWx1ZSA9IGNoYW5nZS5uZXdWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzS2V5KSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVWYWx1ZShrZXksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2FkZFZhbHVlKGtleSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmFzc2VydFZhbGlkS2V5KGtleSk7XG4gICAgICAgIGtleSA9IFwiXCIgKyBrZXk7XG4gICAgICAgIGlmIChoYXNJbnRlcmNlcHRvcnModGhpcykpIHtcbiAgICAgICAgICAgIHZhciBjaGFuZ2UgPSBpbnRlcmNlcHRDaGFuZ2UodGhpcywge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiZGVsZXRlXCIsXG4gICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgIG5hbWU6IGtleVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuX2hhcyhrZXkpKSB7XG4gICAgICAgICAgICB2YXIgbm90aWZ5U3B5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgICAgICB2YXIgbm90aWZ5ID0gaGFzTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IG5vdGlmeSB8fCBub3RpZnlTcHkgPyB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJkZWxldGVcIixcbiAgICAgICAgICAgICAgICBvYmplY3Q6IHRoaXMsXG4gICAgICAgICAgICAgICAgb2xkVmFsdWU6IHRoaXMuX2RhdGFba2V5XS52YWx1ZSxcbiAgICAgICAgICAgICAgICBuYW1lOiBrZXlcbiAgICAgICAgICAgIH0gOiBudWxsO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICAgICAgcnVuSW5UcmFuc2FjdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuX2tleXMucmVtb3ZlKGtleSk7XG4gICAgICAgICAgICAgICAgX3RoaXMuX3VwZGF0ZUhhc01hcEVudHJ5KGtleSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgIHZhciBvYnNlcnZhYmxlID0gX3RoaXMuX2RhdGFba2V5XTtcbiAgICAgICAgICAgICAgICBvYnNlcnZhYmxlLnNldE5ld1ZhbHVlKHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuX2RhdGFba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKG5vdGlmeSlcbiAgICAgICAgICAgICAgICBub3RpZnlMaXN0ZW5lcnModGhpcywgY2hhbmdlKTtcbiAgICAgICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICAgICAgc3B5UmVwb3J0RW5kKCk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5fdXBkYXRlSGFzTWFwRW50cnkgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICB2YXIgZW50cnkgPSB0aGlzLl9oYXNNYXBba2V5XTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgICBlbnRyeS5zZXROZXdWYWx1ZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlbnRyeSA9IHRoaXMuX2hhc01hcFtrZXldID0gbmV3IE9ic2VydmFibGVWYWx1ZSh2YWx1ZSwgcmVmZXJlbmNlRW5oYW5jZXIsIHRoaXMubmFtZSArIFwiLlwiICsga2V5ICsgXCI/XCIsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW50cnk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5fdXBkYXRlVmFsdWUgPSBmdW5jdGlvbiAobmFtZSwgbmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIG9ic2VydmFibGUgPSB0aGlzLl9kYXRhW25hbWVdO1xuICAgICAgICBuZXdWYWx1ZSA9IG9ic2VydmFibGUucHJlcGFyZU5ld1ZhbHVlKG5ld1ZhbHVlKTtcbiAgICAgICAgaWYgKG5ld1ZhbHVlICE9PSBVTkNIQU5HRUQpIHtcbiAgICAgICAgICAgIHZhciBub3RpZnlTcHkgPSBpc1NweUVuYWJsZWQoKTtcbiAgICAgICAgICAgIHZhciBub3RpZnkgPSBoYXNMaXN0ZW5lcnModGhpcyk7XG4gICAgICAgICAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInVwZGF0ZVwiLFxuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcyxcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZTogb2JzZXJ2YWJsZS52YWx1ZSxcbiAgICAgICAgICAgICAgICBuYW1lOiBuYW1lLCBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgICAgIH0gOiBudWxsO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICAgICAgb2JzZXJ2YWJsZS5zZXROZXdWYWx1ZShuZXdWYWx1ZSk7XG4gICAgICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgICAgIG5vdGlmeUxpc3RlbmVycyh0aGlzLCBjaGFuZ2UpO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUuX2FkZFZhbHVlID0gZnVuY3Rpb24gKG5hbWUsIG5ld1ZhbHVlKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHJ1bkluVHJhbnNhY3Rpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG9ic2VydmFibGUgPSBfdGhpcy5fZGF0YVtuYW1lXSA9IG5ldyBPYnNlcnZhYmxlVmFsdWUobmV3VmFsdWUsIF90aGlzLmVuaGFuY2VyLCBfdGhpcy5uYW1lICsgXCIuXCIgKyBuYW1lLCBmYWxzZSk7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IG9ic2VydmFibGUudmFsdWU7XG4gICAgICAgICAgICBfdGhpcy5fdXBkYXRlSGFzTWFwRW50cnkobmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgICBfdGhpcy5fa2V5cy5wdXNoKG5hbWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIG5vdGlmeVNweSA9IGlzU3B5RW5hYmxlZCgpO1xuICAgICAgICB2YXIgbm90aWZ5ID0gaGFzTGlzdGVuZXJzKHRoaXMpO1xuICAgICAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgICAgIHR5cGU6IFwiYWRkXCIsXG4gICAgICAgICAgICBvYmplY3Q6IHRoaXMsXG4gICAgICAgICAgICBuYW1lOiBuYW1lLCBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgfSA6IG51bGw7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRTdGFydChjaGFuZ2UpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIGNoYW5nZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAga2V5ID0gXCJcIiArIGtleTtcbiAgICAgICAgaWYgKHRoaXMuaGFzKGtleSkpXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0YVtrZXldLmdldCgpO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5QXNJdGVyYXRvcih0aGlzLl9rZXlzLnNsaWNlKCkpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUudmFsdWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gYXJyYXlBc0l0ZXJhdG9yKHRoaXMuX2tleXMubWFwKHRoaXMuZ2V0LCB0aGlzKSk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5lbnRyaWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gYXJyYXlBc0l0ZXJhdG9yKHRoaXMuX2tleXMubWFwKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIFtrZXksIF90aGlzLmdldChrZXkpXTsgfSkpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUuZm9yRWFjaCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmtleXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgX3RoaXMuZ2V0KGtleSksIGtleSwgX3RoaXMpOyB9KTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLm1lcmdlID0gZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmIChpc09ic2VydmFibGVNYXAob3RoZXIpKSB7XG4gICAgICAgICAgICBvdGhlciA9IG90aGVyLnRvSlMoKTtcbiAgICAgICAgfVxuICAgICAgICBydW5JblRyYW5zYWN0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChpc1BsYWluT2JqZWN0KG90aGVyKSlcbiAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhvdGhlcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBfdGhpcy5zZXQoa2V5LCBvdGhlcltrZXldKTsgfSk7XG4gICAgICAgICAgICBlbHNlIGlmIChBcnJheS5pc0FycmF5KG90aGVyKSlcbiAgICAgICAgICAgICAgICBvdGhlci5mb3JFYWNoKGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0gX2FbMF0sIHZhbHVlID0gX2FbMV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBlbHNlIGlmIChpc0VTNk1hcChvdGhlcikpXG4gICAgICAgICAgICAgICAgb3RoZXIuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkgeyByZXR1cm4gX3RoaXMuc2V0KGtleSwgdmFsdWUpOyB9KTtcbiAgICAgICAgICAgIGVsc2UgaWYgKG90aGVyICE9PSBudWxsICYmIG90aGVyICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICAgICAgZmFpbChcIkNhbm5vdCBpbml0aWFsaXplIG1hcCBmcm9tIFwiICsgb3RoZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcnVuSW5UcmFuc2FjdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB1bnRyYWNrZWQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIF90aGlzLmtleXMoKS5mb3JFYWNoKF90aGlzLmRlbGV0ZSwgX3RoaXMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUucmVwbGFjZSA9IGZ1bmN0aW9uICh2YWx1ZXMpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgcnVuSW5UcmFuc2FjdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5jbGVhcigpO1xuICAgICAgICAgICAgX3RoaXMubWVyZ2UodmFsdWVzKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9ic2VydmFibGVNYXAucHJvdG90eXBlLCBcInNpemVcIiwge1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9rZXlzLmxlbmd0aDtcbiAgICAgICAgfSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUudG9KUyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyIHJlcyA9IHt9O1xuICAgICAgICB0aGlzLmtleXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIHJlc1trZXldID0gX3RoaXMuZ2V0KGtleSk7IH0pO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU1hcC5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50b0pTKCk7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlTWFwLnByb3RvdHlwZS5pc1ZhbGlkS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoa2V5ID09PSBudWxsIHx8IGtleSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAodHlwZW9mIGtleSA9PT0gXCJzdHJpbmdcIiB8fCB0eXBlb2Yga2V5ID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBrZXkgPT09IFwiYm9vbGVhblwiKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmFzc2VydFZhbGlkS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZEtleShrZXkpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiW21vYngubWFwXSBJbnZhbGlkIGtleTogJ1wiICsga2V5ICsgXCInLCBvbmx5IHN0cmluZ3MsIG51bWJlcnMgYW5kIGJvb2xlYW5zIGFyZSBhY2NlcHRlZCBhcyBrZXkgaW4gb2JzZXJ2YWJsZSBtYXBzLlwiKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lICsgXCJbeyBcIiArIHRoaXMua2V5cygpLm1hcChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBrZXkgKyBcIjogXCIgKyAoXCJcIiArIF90aGlzLmdldChrZXkpKTsgfSkuam9pbihcIiwgXCIpICsgXCIgfV1cIjtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLm9ic2VydmUgPSBmdW5jdGlvbiAobGlzdGVuZXIsIGZpcmVJbW1lZGlhdGVseSkge1xuICAgICAgICBpbnZhcmlhbnQoZmlyZUltbWVkaWF0ZWx5ICE9PSB0cnVlLCBnZXRNZXNzYWdlKFwibTAzM1wiKSk7XG4gICAgICAgIHJldHVybiByZWdpc3Rlckxpc3RlbmVyKHRoaXMsIGxpc3RlbmVyKTtcbiAgICB9O1xuICAgIE9ic2VydmFibGVNYXAucHJvdG90eXBlLmludGVyY2VwdCA9IGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgIHJldHVybiByZWdpc3RlckludGVyY2VwdG9yKHRoaXMsIGhhbmRsZXIpO1xuICAgIH07XG4gICAgcmV0dXJuIE9ic2VydmFibGVNYXA7XG59KCkpO1xuZXhwb3J0cy5PYnNlcnZhYmxlTWFwID0gT2JzZXJ2YWJsZU1hcDtcbmRlY2xhcmVJdGVyYXRvcihPYnNlcnZhYmxlTWFwLnByb3RvdHlwZSwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXMoKTtcbn0pO1xuZnVuY3Rpb24gbWFwKGluaXRpYWxWYWx1ZXMpIHtcbiAgICBkZXByZWNhdGVkKFwiYG1vYngubWFwYCBpcyBkZXByZWNhdGVkLCB1c2UgYG5ldyBPYnNlcnZhYmxlTWFwYCBvciBgbW9ieC5vYnNlcnZhYmxlLm1hcGAgaW5zdGVhZFwiKTtcbiAgICByZXR1cm4gb2JzZXJ2YWJsZS5tYXAoaW5pdGlhbFZhbHVlcyk7XG59XG5leHBvcnRzLm1hcCA9IG1hcDtcbnZhciBpc09ic2VydmFibGVNYXAgPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiT2JzZXJ2YWJsZU1hcFwiLCBPYnNlcnZhYmxlTWFwKTtcbmV4cG9ydHMuaXNPYnNlcnZhYmxlTWFwID0gaXNPYnNlcnZhYmxlTWFwO1xudmFyIE9ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2JzZXJ2YWJsZU9iamVjdEFkbWluaXN0cmF0aW9uKHRhcmdldCwgbmFtZSkge1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy52YWx1ZXMgPSB7fTtcbiAgICAgICAgdGhpcy5jaGFuZ2VMaXN0ZW5lcnMgPSBudWxsO1xuICAgICAgICB0aGlzLmludGVyY2VwdG9ycyA9IG51bGw7XG4gICAgfVxuICAgIE9ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbi5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uIChjYWxsYmFjaywgZmlyZUltbWVkaWF0ZWx5KSB7XG4gICAgICAgIGludmFyaWFudChmaXJlSW1tZWRpYXRlbHkgIT09IHRydWUsIFwiYG9ic2VydmVgIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgZmlyZSBpbW1lZGlhdGVseSBwcm9wZXJ0eSBmb3Igb2JzZXJ2YWJsZSBvYmplY3RzLlwiKTtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVyTGlzdGVuZXIodGhpcywgY2FsbGJhY2spO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZU9iamVjdEFkbWluaXN0cmF0aW9uLnByb3RvdHlwZS5pbnRlcmNlcHQgPSBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICByZXR1cm4gcmVnaXN0ZXJJbnRlcmNlcHRvcih0aGlzLCBoYW5kbGVyKTtcbiAgICB9O1xuICAgIHJldHVybiBPYnNlcnZhYmxlT2JqZWN0QWRtaW5pc3RyYXRpb247XG59KCkpO1xuZnVuY3Rpb24gYXNPYnNlcnZhYmxlT2JqZWN0KHRhcmdldCwgbmFtZSkge1xuICAgIGlmIChpc09ic2VydmFibGVPYmplY3QodGFyZ2V0KSlcbiAgICAgICAgcmV0dXJuIHRhcmdldC4kbW9ieDtcbiAgICBpbnZhcmlhbnQoT2JqZWN0LmlzRXh0ZW5zaWJsZSh0YXJnZXQpLCBnZXRNZXNzYWdlKFwibTAzNVwiKSk7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHRhcmdldCkpXG4gICAgICAgIG5hbWUgPSAodGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWUgfHwgXCJPYnNlcnZhYmxlT2JqZWN0XCIpICsgXCJAXCIgKyBnZXROZXh0SWQoKTtcbiAgICBpZiAoIW5hbWUpXG4gICAgICAgIG5hbWUgPSBcIk9ic2VydmFibGVPYmplY3RAXCIgKyBnZXROZXh0SWQoKTtcbiAgICB2YXIgYWRtID0gbmV3IE9ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbih0YXJnZXQsIG5hbWUpO1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcCh0YXJnZXQsIFwiJG1vYnhcIiwgYWRtKTtcbiAgICByZXR1cm4gYWRtO1xufVxuZnVuY3Rpb24gZGVmaW5lT2JzZXJ2YWJsZVByb3BlcnR5RnJvbURlc2NyaXB0b3IoYWRtLCBwcm9wTmFtZSwgZGVzY3JpcHRvciwgZGVmYXVsdEVuaGFuY2VyKSB7XG4gICAgaWYgKGFkbS52YWx1ZXNbcHJvcE5hbWVdKSB7XG4gICAgICAgIGludmFyaWFudChcInZhbHVlXCIgaW4gZGVzY3JpcHRvciwgXCJUaGUgcHJvcGVydHkgXCIgKyBwcm9wTmFtZSArIFwiIGluIFwiICsgYWRtLm5hbWUgKyBcIiBpcyBhbHJlYWR5IG9ic2VydmFibGUsIGNhbm5vdCByZWRlZmluZSBpdCBhcyBjb21wdXRlZCBwcm9wZXJ0eVwiKTtcbiAgICAgICAgYWRtLnRhcmdldFtwcm9wTmFtZV0gPSBkZXNjcmlwdG9yLnZhbHVlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikge1xuICAgICAgICBpZiAoaXNNb2RpZmllckRlc2NyaXB0b3IoZGVzY3JpcHRvci52YWx1ZSkpIHtcbiAgICAgICAgICAgIHZhciBtb2RpZmllckRlc2NyaXB0b3IgPSBkZXNjcmlwdG9yLnZhbHVlO1xuICAgICAgICAgICAgZGVmaW5lT2JzZXJ2YWJsZVByb3BlcnR5KGFkbSwgcHJvcE5hbWUsIG1vZGlmaWVyRGVzY3JpcHRvci5pbml0aWFsVmFsdWUsIG1vZGlmaWVyRGVzY3JpcHRvci5lbmhhbmNlcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNBY3Rpb24oZGVzY3JpcHRvci52YWx1ZSkgJiYgZGVzY3JpcHRvci52YWx1ZS5hdXRvQmluZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgZGVmaW5lQm91bmRBY3Rpb24oYWRtLnRhcmdldCwgcHJvcE5hbWUsIGRlc2NyaXB0b3IudmFsdWUub3JpZ2luYWxGbik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNDb21wdXRlZFZhbHVlKGRlc2NyaXB0b3IudmFsdWUpKSB7XG4gICAgICAgICAgICBkZWZpbmVDb21wdXRlZFByb3BlcnR5RnJvbUNvbXB1dGVkVmFsdWUoYWRtLCBwcm9wTmFtZSwgZGVzY3JpcHRvci52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkZWZpbmVPYnNlcnZhYmxlUHJvcGVydHkoYWRtLCBwcm9wTmFtZSwgZGVzY3JpcHRvci52YWx1ZSwgZGVmYXVsdEVuaGFuY2VyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZGVmaW5lQ29tcHV0ZWRQcm9wZXJ0eShhZG0sIHByb3BOYW1lLCBkZXNjcmlwdG9yLmdldCwgZGVzY3JpcHRvci5zZXQsIGZhbHNlLCB0cnVlKTtcbiAgICB9XG59XG5mdW5jdGlvbiBkZWZpbmVPYnNlcnZhYmxlUHJvcGVydHkoYWRtLCBwcm9wTmFtZSwgbmV3VmFsdWUsIGVuaGFuY2VyKSB7XG4gICAgYXNzZXJ0UHJvcGVydHlDb25maWd1cmFibGUoYWRtLnRhcmdldCwgcHJvcE5hbWUpO1xuICAgIGlmIChoYXNJbnRlcmNlcHRvcnMoYWRtKSkge1xuICAgICAgICB2YXIgY2hhbmdlID0gaW50ZXJjZXB0Q2hhbmdlKGFkbSwge1xuICAgICAgICAgICAgb2JqZWN0OiBhZG0udGFyZ2V0LFxuICAgICAgICAgICAgbmFtZTogcHJvcE5hbWUsXG4gICAgICAgICAgICB0eXBlOiBcImFkZFwiLFxuICAgICAgICAgICAgbmV3VmFsdWU6IG5ld1ZhbHVlXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIWNoYW5nZSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgbmV3VmFsdWUgPSBjaGFuZ2UubmV3VmFsdWU7XG4gICAgfVxuICAgIHZhciBvYnNlcnZhYmxlID0gYWRtLnZhbHVlc1twcm9wTmFtZV0gPSBuZXcgT2JzZXJ2YWJsZVZhbHVlKG5ld1ZhbHVlLCBlbmhhbmNlciwgYWRtLm5hbWUgKyBcIi5cIiArIHByb3BOYW1lLCBmYWxzZSk7XG4gICAgbmV3VmFsdWUgPSBvYnNlcnZhYmxlLnZhbHVlO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhZG0udGFyZ2V0LCBwcm9wTmFtZSwgZ2VuZXJhdGVPYnNlcnZhYmxlUHJvcENvbmZpZyhwcm9wTmFtZSkpO1xuICAgIG5vdGlmeVByb3BlcnR5QWRkaXRpb24oYWRtLCBhZG0udGFyZ2V0LCBwcm9wTmFtZSwgbmV3VmFsdWUpO1xufVxuZnVuY3Rpb24gZGVmaW5lQ29tcHV0ZWRQcm9wZXJ0eShhZG0sIHByb3BOYW1lLCBnZXR0ZXIsIHNldHRlciwgY29tcGFyZVN0cnVjdHVyYWwsIGFzSW5zdGFuY2VQcm9wZXJ0eSkge1xuICAgIGlmIChhc0luc3RhbmNlUHJvcGVydHkpXG4gICAgICAgIGFzc2VydFByb3BlcnR5Q29uZmlndXJhYmxlKGFkbS50YXJnZXQsIHByb3BOYW1lKTtcbiAgICBhZG0udmFsdWVzW3Byb3BOYW1lXSA9IG5ldyBDb21wdXRlZFZhbHVlKGdldHRlciwgYWRtLnRhcmdldCwgY29tcGFyZVN0cnVjdHVyYWwsIGFkbS5uYW1lICsgXCIuXCIgKyBwcm9wTmFtZSwgc2V0dGVyKTtcbiAgICBpZiAoYXNJbnN0YW5jZVByb3BlcnR5KSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhZG0udGFyZ2V0LCBwcm9wTmFtZSwgZ2VuZXJhdGVDb21wdXRlZFByb3BDb25maWcocHJvcE5hbWUpKTtcbiAgICB9XG59XG5mdW5jdGlvbiBkZWZpbmVDb21wdXRlZFByb3BlcnR5RnJvbUNvbXB1dGVkVmFsdWUoYWRtLCBwcm9wTmFtZSwgY29tcHV0ZWRWYWx1ZSkge1xuICAgIHZhciBuYW1lID0gYWRtLm5hbWUgKyBcIi5cIiArIHByb3BOYW1lO1xuICAgIGNvbXB1dGVkVmFsdWUubmFtZSA9IG5hbWU7XG4gICAgaWYgKCFjb21wdXRlZFZhbHVlLnNjb3BlKVxuICAgICAgICBjb21wdXRlZFZhbHVlLnNjb3BlID0gYWRtLnRhcmdldDtcbiAgICBhZG0udmFsdWVzW3Byb3BOYW1lXSA9IGNvbXB1dGVkVmFsdWU7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFkbS50YXJnZXQsIHByb3BOYW1lLCBnZW5lcmF0ZUNvbXB1dGVkUHJvcENvbmZpZyhwcm9wTmFtZSkpO1xufVxudmFyIG9ic2VydmFibGVQcm9wZXJ0eUNvbmZpZ3MgPSB7fTtcbnZhciBjb21wdXRlZFByb3BlcnR5Q29uZmlncyA9IHt9O1xuZnVuY3Rpb24gZ2VuZXJhdGVPYnNlcnZhYmxlUHJvcENvbmZpZyhwcm9wTmFtZSkge1xuICAgIHZhciBjb25maWcgPSBvYnNlcnZhYmxlUHJvcGVydHlDb25maWdzW3Byb3BOYW1lXTtcbiAgICBpZiAoY29uZmlnKVxuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgIHJldHVybiBvYnNlcnZhYmxlUHJvcGVydHlDb25maWdzW3Byb3BOYW1lXSA9IHtcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLiRtb2J4LnZhbHVlc1twcm9wTmFtZV0uZ2V0KCk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgIHNldFByb3BlcnR5VmFsdWUodGhpcywgcHJvcE5hbWUsIHYpO1xuICAgICAgICB9XG4gICAgfTtcbn1cbmZ1bmN0aW9uIGdlbmVyYXRlQ29tcHV0ZWRQcm9wQ29uZmlnKHByb3BOYW1lKSB7XG4gICAgdmFyIGNvbmZpZyA9IGNvbXB1dGVkUHJvcGVydHlDb25maWdzW3Byb3BOYW1lXTtcbiAgICBpZiAoY29uZmlnKVxuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgIHJldHVybiBjb21wdXRlZFByb3BlcnR5Q29uZmlnc1twcm9wTmFtZV0gPSB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJG1vYngudmFsdWVzW3Byb3BOYW1lXS5nZXQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuJG1vYngudmFsdWVzW3Byb3BOYW1lXS5zZXQodik7XG4gICAgICAgIH1cbiAgICB9O1xufVxuZnVuY3Rpb24gc2V0UHJvcGVydHlWYWx1ZShpbnN0YW5jZSwgbmFtZSwgbmV3VmFsdWUpIHtcbiAgICB2YXIgYWRtID0gaW5zdGFuY2UuJG1vYng7XG4gICAgdmFyIG9ic2VydmFibGUgPSBhZG0udmFsdWVzW25hbWVdO1xuICAgIGlmIChoYXNJbnRlcmNlcHRvcnMoYWRtKSkge1xuICAgICAgICB2YXIgY2hhbmdlID0gaW50ZXJjZXB0Q2hhbmdlKGFkbSwge1xuICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgIG9iamVjdDogaW5zdGFuY2UsXG4gICAgICAgICAgICBuYW1lOiBuYW1lLCBuZXdWYWx1ZTogbmV3VmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghY2hhbmdlKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBuZXdWYWx1ZSA9IGNoYW5nZS5uZXdWYWx1ZTtcbiAgICB9XG4gICAgbmV3VmFsdWUgPSBvYnNlcnZhYmxlLnByZXBhcmVOZXdWYWx1ZShuZXdWYWx1ZSk7XG4gICAgaWYgKG5ld1ZhbHVlICE9PSBVTkNIQU5HRUQpIHtcbiAgICAgICAgdmFyIG5vdGlmeSA9IGhhc0xpc3RlbmVycyhhZG0pO1xuICAgICAgICB2YXIgbm90aWZ5U3B5ID0gaXNTcHlFbmFibGVkKCk7XG4gICAgICAgIHZhciBjaGFuZ2UgPSBub3RpZnkgfHwgbm90aWZ5U3B5ID8ge1xuICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgIG9iamVjdDogaW5zdGFuY2UsXG4gICAgICAgICAgICBvbGRWYWx1ZTogb2JzZXJ2YWJsZS52YWx1ZSxcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsIG5ld1ZhbHVlOiBuZXdWYWx1ZVxuICAgICAgICB9IDogbnVsbDtcbiAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgIHNweVJlcG9ydFN0YXJ0KGNoYW5nZSk7XG4gICAgICAgIG9ic2VydmFibGUuc2V0TmV3VmFsdWUobmV3VmFsdWUpO1xuICAgICAgICBpZiAobm90aWZ5KVxuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKGFkbSwgY2hhbmdlKTtcbiAgICAgICAgaWYgKG5vdGlmeVNweSlcbiAgICAgICAgICAgIHNweVJlcG9ydEVuZCgpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIG5vdGlmeVByb3BlcnR5QWRkaXRpb24oYWRtLCBvYmplY3QsIG5hbWUsIG5ld1ZhbHVlKSB7XG4gICAgdmFyIG5vdGlmeSA9IGhhc0xpc3RlbmVycyhhZG0pO1xuICAgIHZhciBub3RpZnlTcHkgPSBpc1NweUVuYWJsZWQoKTtcbiAgICB2YXIgY2hhbmdlID0gbm90aWZ5IHx8IG5vdGlmeVNweSA/IHtcbiAgICAgICAgdHlwZTogXCJhZGRcIixcbiAgICAgICAgb2JqZWN0OiBvYmplY3QsIG5hbWU6IG5hbWUsIG5ld1ZhbHVlOiBuZXdWYWx1ZVxuICAgIH0gOiBudWxsO1xuICAgIGlmIChub3RpZnlTcHkpXG4gICAgICAgIHNweVJlcG9ydFN0YXJ0KGNoYW5nZSk7XG4gICAgaWYgKG5vdGlmeSlcbiAgICAgICAgbm90aWZ5TGlzdGVuZXJzKGFkbSwgY2hhbmdlKTtcbiAgICBpZiAobm90aWZ5U3B5KVxuICAgICAgICBzcHlSZXBvcnRFbmQoKTtcbn1cbnZhciBpc09ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbiA9IGNyZWF0ZUluc3RhbmNlb2ZQcmVkaWNhdGUoXCJPYnNlcnZhYmxlT2JqZWN0QWRtaW5pc3RyYXRpb25cIiwgT2JzZXJ2YWJsZU9iamVjdEFkbWluaXN0cmF0aW9uKTtcbmZ1bmN0aW9uIGlzT2JzZXJ2YWJsZU9iamVjdCh0aGluZykge1xuICAgIGlmIChpc09iamVjdCh0aGluZykpIHtcbiAgICAgICAgcnVuTGF6eUluaXRpYWxpemVycyh0aGluZyk7XG4gICAgICAgIHJldHVybiBpc09ic2VydmFibGVPYmplY3RBZG1pbmlzdHJhdGlvbih0aGluZy4kbW9ieCk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmV4cG9ydHMuaXNPYnNlcnZhYmxlT2JqZWN0ID0gaXNPYnNlcnZhYmxlT2JqZWN0O1xudmFyIFVOQ0hBTkdFRCA9IHt9O1xudmFyIE9ic2VydmFibGVWYWx1ZSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKE9ic2VydmFibGVWYWx1ZSwgX3N1cGVyKTtcbiAgICBmdW5jdGlvbiBPYnNlcnZhYmxlVmFsdWUodmFsdWUsIGVuaGFuY2VyLCBuYW1lLCBub3RpZnlTcHkpIHtcbiAgICAgICAgaWYgKG5hbWUgPT09IHZvaWQgMCkgeyBuYW1lID0gXCJPYnNlcnZhYmxlVmFsdWVAXCIgKyBnZXROZXh0SWQoKTsgfVxuICAgICAgICBpZiAobm90aWZ5U3B5ID09PSB2b2lkIDApIHsgbm90aWZ5U3B5ID0gdHJ1ZTsgfVxuICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBuYW1lKSB8fCB0aGlzO1xuICAgICAgICBfdGhpcy5lbmhhbmNlciA9IGVuaGFuY2VyO1xuICAgICAgICBfdGhpcy5oYXNVbnJlcG9ydGVkQ2hhbmdlID0gZmFsc2U7XG4gICAgICAgIF90aGlzLnZhbHVlID0gZW5oYW5jZXIodmFsdWUsIHVuZGVmaW5lZCwgbmFtZSk7XG4gICAgICAgIGlmIChub3RpZnlTcHkgJiYgaXNTcHlFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIHNweVJlcG9ydCh7IHR5cGU6IFwiY3JlYXRlXCIsIG9iamVjdDogX3RoaXMsIG5ld1ZhbHVlOiBfdGhpcy52YWx1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuICAgIE9ic2VydmFibGVWYWx1ZS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKG5ld1ZhbHVlKSB7XG4gICAgICAgIHZhciBvbGRWYWx1ZSA9IHRoaXMudmFsdWU7XG4gICAgICAgIG5ld1ZhbHVlID0gdGhpcy5wcmVwYXJlTmV3VmFsdWUobmV3VmFsdWUpO1xuICAgICAgICBpZiAobmV3VmFsdWUgIT09IFVOQ0hBTkdFRCkge1xuICAgICAgICAgICAgdmFyIG5vdGlmeVNweSA9IGlzU3B5RW5hYmxlZCgpO1xuICAgICAgICAgICAgaWYgKG5vdGlmeVNweSkge1xuICAgICAgICAgICAgICAgIHNweVJlcG9ydFN0YXJ0KHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0OiB0aGlzLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsIG9sZFZhbHVlOiBvbGRWYWx1ZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXROZXdWYWx1ZShuZXdWYWx1ZSk7XG4gICAgICAgICAgICBpZiAobm90aWZ5U3B5KVxuICAgICAgICAgICAgICAgIHNweVJlcG9ydEVuZCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlVmFsdWUucHJvdG90eXBlLnByZXBhcmVOZXdWYWx1ZSA9IGZ1bmN0aW9uIChuZXdWYWx1ZSkge1xuICAgICAgICBjaGVja0lmU3RhdGVNb2RpZmljYXRpb25zQXJlQWxsb3dlZCh0aGlzKTtcbiAgICAgICAgaWYgKGhhc0ludGVyY2VwdG9ycyh0aGlzKSkge1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IGludGVyY2VwdENoYW5nZSh0aGlzLCB7IG9iamVjdDogdGhpcywgdHlwZTogXCJ1cGRhdGVcIiwgbmV3VmFsdWU6IG5ld1ZhbHVlIH0pO1xuICAgICAgICAgICAgaWYgKCFjaGFuZ2UpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFVOQ0hBTkdFRDtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gY2hhbmdlLm5ld1ZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIG5ld1ZhbHVlID0gdGhpcy5lbmhhbmNlcihuZXdWYWx1ZSwgdGhpcy52YWx1ZSwgdGhpcy5uYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgIT09IG5ld1ZhbHVlXG4gICAgICAgICAgICA/IG5ld1ZhbHVlXG4gICAgICAgICAgICA6IFVOQ0hBTkdFRDtcbiAgICB9O1xuICAgIE9ic2VydmFibGVWYWx1ZS5wcm90b3R5cGUuc2V0TmV3VmFsdWUgPSBmdW5jdGlvbiAobmV3VmFsdWUpIHtcbiAgICAgICAgdmFyIG9sZFZhbHVlID0gdGhpcy52YWx1ZTtcbiAgICAgICAgdGhpcy52YWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB0aGlzLnJlcG9ydENoYW5nZWQoKTtcbiAgICAgICAgaWYgKGhhc0xpc3RlbmVycyh0aGlzKSkge1xuICAgICAgICAgICAgbm90aWZ5TGlzdGVuZXJzKHRoaXMsIHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcInVwZGF0ZVwiLFxuICAgICAgICAgICAgICAgIG9iamVjdDogdGhpcyxcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICAgICAgb2xkVmFsdWU6IG9sZFZhbHVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVwb3J0T2JzZXJ2ZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfTtcbiAgICBPYnNlcnZhYmxlVmFsdWUucHJvdG90eXBlLmludGVyY2VwdCA9IGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgIHJldHVybiByZWdpc3RlckludGVyY2VwdG9yKHRoaXMsIGhhbmRsZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS5vYnNlcnZlID0gZnVuY3Rpb24gKGxpc3RlbmVyLCBmaXJlSW1tZWRpYXRlbHkpIHtcbiAgICAgICAgaWYgKGZpcmVJbW1lZGlhdGVseSlcbiAgICAgICAgICAgIGxpc3RlbmVyKHtcbiAgICAgICAgICAgICAgICBvYmplY3Q6IHRoaXMsXG4gICAgICAgICAgICAgICAgdHlwZTogXCJ1cGRhdGVcIixcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZTogdGhpcy52YWx1ZSxcbiAgICAgICAgICAgICAgICBvbGRWYWx1ZTogdW5kZWZpbmVkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlZ2lzdGVyTGlzdGVuZXIodGhpcywgbGlzdGVuZXIpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldCgpO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSArIFwiW1wiICsgdGhpcy52YWx1ZSArIFwiXVwiO1xuICAgIH07XG4gICAgT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZS52YWx1ZU9mID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdG9QcmltaXRpdmUodGhpcy5nZXQoKSk7XG4gICAgfTtcbiAgICByZXR1cm4gT2JzZXJ2YWJsZVZhbHVlO1xufShCYXNlQXRvbSkpO1xuT2JzZXJ2YWJsZVZhbHVlLnByb3RvdHlwZVtwcmltaXRpdmVTeW1ib2woKV0gPSBPYnNlcnZhYmxlVmFsdWUucHJvdG90eXBlLnZhbHVlT2Y7XG52YXIgaXNPYnNlcnZhYmxlVmFsdWUgPSBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKFwiT2JzZXJ2YWJsZVZhbHVlXCIsIE9ic2VydmFibGVWYWx1ZSk7XG5mdW5jdGlvbiBnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSkge1xuICAgIGlmICh0eXBlb2YgdGhpbmcgPT09IFwib2JqZWN0XCIgJiYgdGhpbmcgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZUFycmF5KHRoaW5nKSkge1xuICAgICAgICAgICAgaW52YXJpYW50KHByb3BlcnR5ID09PSB1bmRlZmluZWQsIGdldE1lc3NhZ2UoXCJtMDM2XCIpKTtcbiAgICAgICAgICAgIHJldHVybiB0aGluZy4kbW9ieC5hdG9tO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc09ic2VydmFibGVNYXAodGhpbmcpKSB7XG4gICAgICAgICAgICB2YXIgYW55VGhpbmcgPSB0aGluZztcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0eSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgIHJldHVybiBnZXRBdG9tKGFueVRoaW5nLl9rZXlzKTtcbiAgICAgICAgICAgIHZhciBvYnNlcnZhYmxlXzIgPSBhbnlUaGluZy5fZGF0YVtwcm9wZXJ0eV0gfHwgYW55VGhpbmcuX2hhc01hcFtwcm9wZXJ0eV07XG4gICAgICAgICAgICBpbnZhcmlhbnQoISFvYnNlcnZhYmxlXzIsIFwidGhlIGVudHJ5ICdcIiArIHByb3BlcnR5ICsgXCInIGRvZXMgbm90IGV4aXN0IGluIHRoZSBvYnNlcnZhYmxlIG1hcCAnXCIgKyBnZXREZWJ1Z05hbWUodGhpbmcpICsgXCInXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG9ic2VydmFibGVfMjtcbiAgICAgICAgfVxuICAgICAgICBydW5MYXp5SW5pdGlhbGl6ZXJzKHRoaW5nKTtcbiAgICAgICAgaWYgKGlzT2JzZXJ2YWJsZU9iamVjdCh0aGluZykpIHtcbiAgICAgICAgICAgIGlmICghcHJvcGVydHkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhaWwoXCJwbGVhc2Ugc3BlY2lmeSBhIHByb3BlcnR5XCIpO1xuICAgICAgICAgICAgdmFyIG9ic2VydmFibGVfMyA9IHRoaW5nLiRtb2J4LnZhbHVlc1twcm9wZXJ0eV07XG4gICAgICAgICAgICBpbnZhcmlhbnQoISFvYnNlcnZhYmxlXzMsIFwibm8gb2JzZXJ2YWJsZSBwcm9wZXJ0eSAnXCIgKyBwcm9wZXJ0eSArIFwiJyBmb3VuZCBvbiB0aGUgb2JzZXJ2YWJsZSBvYmplY3QgJ1wiICsgZ2V0RGVidWdOYW1lKHRoaW5nKSArIFwiJ1wiKTtcbiAgICAgICAgICAgIHJldHVybiBvYnNlcnZhYmxlXzM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQXRvbSh0aGluZykgfHwgaXNDb21wdXRlZFZhbHVlKHRoaW5nKSB8fCBpc1JlYWN0aW9uKHRoaW5nKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaW5nO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIGlmIChpc1JlYWN0aW9uKHRoaW5nLiRtb2J4KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaW5nLiRtb2J4O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWlsKFwiQ2Fubm90IG9idGFpbiBhdG9tIGZyb20gXCIgKyB0aGluZyk7XG59XG5mdW5jdGlvbiBnZXRBZG1pbmlzdHJhdGlvbih0aGluZywgcHJvcGVydHkpIHtcbiAgICBpbnZhcmlhbnQodGhpbmcsIFwiRXhwZWN0aW5nIHNvbWUgb2JqZWN0XCIpO1xuICAgIGlmIChwcm9wZXJ0eSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gZ2V0QWRtaW5pc3RyYXRpb24oZ2V0QXRvbSh0aGluZywgcHJvcGVydHkpKTtcbiAgICBpZiAoaXNBdG9tKHRoaW5nKSB8fCBpc0NvbXB1dGVkVmFsdWUodGhpbmcpIHx8IGlzUmVhY3Rpb24odGhpbmcpKVxuICAgICAgICByZXR1cm4gdGhpbmc7XG4gICAgaWYgKGlzT2JzZXJ2YWJsZU1hcCh0aGluZykpXG4gICAgICAgIHJldHVybiB0aGluZztcbiAgICBydW5MYXp5SW5pdGlhbGl6ZXJzKHRoaW5nKTtcbiAgICBpZiAodGhpbmcuJG1vYngpXG4gICAgICAgIHJldHVybiB0aGluZy4kbW9ieDtcbiAgICBpbnZhcmlhbnQoZmFsc2UsIFwiQ2Fubm90IG9idGFpbiBhZG1pbmlzdHJhdGlvbiBmcm9tIFwiICsgdGhpbmcpO1xufVxuZnVuY3Rpb24gZ2V0RGVidWdOYW1lKHRoaW5nLCBwcm9wZXJ0eSkge1xuICAgIHZhciBuYW1lZDtcbiAgICBpZiAocHJvcGVydHkgIT09IHVuZGVmaW5lZClcbiAgICAgICAgbmFtZWQgPSBnZXRBdG9tKHRoaW5nLCBwcm9wZXJ0eSk7XG4gICAgZWxzZSBpZiAoaXNPYnNlcnZhYmxlT2JqZWN0KHRoaW5nKSB8fCBpc09ic2VydmFibGVNYXAodGhpbmcpKVxuICAgICAgICBuYW1lZCA9IGdldEFkbWluaXN0cmF0aW9uKHRoaW5nKTtcbiAgICBlbHNlXG4gICAgICAgIG5hbWVkID0gZ2V0QXRvbSh0aGluZyk7XG4gICAgcmV0dXJuIG5hbWVkLm5hbWU7XG59XG5mdW5jdGlvbiBjcmVhdGVDbGFzc1Byb3BlcnR5RGVjb3JhdG9yKG9uSW5pdGlhbGl6ZSwgZ2V0LCBzZXQsIGVudW1lcmFibGUsIGFsbG93Q3VzdG9tQXJndW1lbnRzKSB7XG4gICAgZnVuY3Rpb24gY2xhc3NQcm9wZXJ0eURlY29yYXRvcih0YXJnZXQsIGtleSwgZGVzY3JpcHRvciwgY3VzdG9tQXJncywgYXJnTGVuKSB7XG4gICAgICAgIGludmFyaWFudChhbGxvd0N1c3RvbUFyZ3VtZW50cyB8fCBxdWFja3NMaWtlQURlY29yYXRvcihhcmd1bWVudHMpLCBcIlRoaXMgZnVuY3Rpb24gaXMgYSBkZWNvcmF0b3IsIGJ1dCBpdCB3YXNuJ3QgaW52b2tlZCBsaWtlIGEgZGVjb3JhdG9yXCIpO1xuICAgICAgICBpZiAoIWRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgIHZhciBuZXdEZXNjcmlwdG9yID0ge1xuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IGVudW1lcmFibGUsXG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX19tb2J4SW5pdGlhbGl6ZWRQcm9wcyB8fCB0aGlzLl9fbW9ieEluaXRpYWxpemVkUHJvcHNba2V5XSAhPT0gdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVzY3JpcHRJbml0aWFsaXplUHJvcGVydHkodGhpcywga2V5LCB1bmRlZmluZWQsIG9uSW5pdGlhbGl6ZSwgY3VzdG9tQXJncywgZGVzY3JpcHRvcik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXQuY2FsbCh0aGlzLCBrZXkpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiAodikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX19tb2J4SW5pdGlhbGl6ZWRQcm9wcyB8fCB0aGlzLl9fbW9ieEluaXRpYWxpemVkUHJvcHNba2V5XSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZXNjcmlwdEluaXRpYWxpemVQcm9wZXJ0eSh0aGlzLCBrZXksIHYsIG9uSW5pdGlhbGl6ZSwgY3VzdG9tQXJncywgZGVzY3JpcHRvcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXQuY2FsbCh0aGlzLCBrZXksIHYpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMyB8fCBhcmd1bWVudHMubGVuZ3RoID09PSA1ICYmIGFyZ0xlbiA8IDMpIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIG5ld0Rlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ld0Rlc2NyaXB0b3I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3BlcnR5KHRhcmdldCwgXCJfX21vYnhMYXp5SW5pdGlhbGl6ZXJzXCIpKSB7XG4gICAgICAgICAgICAgICAgYWRkSGlkZGVuUHJvcCh0YXJnZXQsIFwiX19tb2J4TGF6eUluaXRpYWxpemVyc1wiLCAodGFyZ2V0Ll9fbW9ieExhenlJbml0aWFsaXplcnMgJiYgdGFyZ2V0Ll9fbW9ieExhenlJbml0aWFsaXplcnMuc2xpY2UoKSkgfHwgW10pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHZhbHVlXzEgPSBkZXNjcmlwdG9yLnZhbHVlLCBpbml0aWFsaXplcl8xID0gZGVzY3JpcHRvci5pbml0aWFsaXplcjtcbiAgICAgICAgICAgIHRhcmdldC5fX21vYnhMYXp5SW5pdGlhbGl6ZXJzLnB1c2goZnVuY3Rpb24gKGluc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgb25Jbml0aWFsaXplKGluc3RhbmNlLCBrZXksIChpbml0aWFsaXplcl8xID8gaW5pdGlhbGl6ZXJfMS5jYWxsKGluc3RhbmNlKSA6IHZhbHVlXzEpLCBjdXN0b21BcmdzLCBkZXNjcmlwdG9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBlbnVtZXJhYmxlLCBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9fbW9ieERpZFJ1bkxhenlJbml0aWFsaXplcnMgIT09IHRydWUpXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5MYXp5SW5pdGlhbGl6ZXJzKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0LmNhbGwodGhpcywga2V5KTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVycyAhPT0gdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bkxhenlJbml0aWFsaXplcnModGhpcyk7XG4gICAgICAgICAgICAgICAgICAgIHNldC5jYWxsKHRoaXMsIGtleSwgdik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoYWxsb3dDdXN0b21Bcmd1bWVudHMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChxdWFja3NMaWtlQURlY29yYXRvcihhcmd1bWVudHMpKVxuICAgICAgICAgICAgICAgIHJldHVybiBjbGFzc1Byb3BlcnR5RGVjb3JhdG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB2YXIgb3V0ZXJBcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgdmFyIGFyZ0xlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKSB7IHJldHVybiBjbGFzc1Byb3BlcnR5RGVjb3JhdG9yKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yLCBvdXRlckFyZ3MsIGFyZ0xlbik7IH07XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBjbGFzc1Byb3BlcnR5RGVjb3JhdG9yO1xufVxuZnVuY3Rpb24gdHlwZXNjcmlwdEluaXRpYWxpemVQcm9wZXJ0eShpbnN0YW5jZSwga2V5LCB2LCBvbkluaXRpYWxpemUsIGN1c3RvbUFyZ3MsIGJhc2VEZXNjcmlwdG9yKSB7XG4gICAgaWYgKCFoYXNPd25Qcm9wZXJ0eShpbnN0YW5jZSwgXCJfX21vYnhJbml0aWFsaXplZFByb3BzXCIpKVxuICAgICAgICBhZGRIaWRkZW5Qcm9wKGluc3RhbmNlLCBcIl9fbW9ieEluaXRpYWxpemVkUHJvcHNcIiwge30pO1xuICAgIGluc3RhbmNlLl9fbW9ieEluaXRpYWxpemVkUHJvcHNba2V5XSA9IHRydWU7XG4gICAgb25Jbml0aWFsaXplKGluc3RhbmNlLCBrZXksIHYsIGN1c3RvbUFyZ3MsIGJhc2VEZXNjcmlwdG9yKTtcbn1cbmZ1bmN0aW9uIHJ1bkxhenlJbml0aWFsaXplcnMoaW5zdGFuY2UpIHtcbiAgICBpZiAoaW5zdGFuY2UuX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVycyA9PT0gdHJ1ZSlcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmIChpbnN0YW5jZS5fX21vYnhMYXp5SW5pdGlhbGl6ZXJzKSB7XG4gICAgICAgIGFkZEhpZGRlblByb3AoaW5zdGFuY2UsIFwiX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVyc1wiLCB0cnVlKTtcbiAgICAgICAgaW5zdGFuY2UuX19tb2J4RGlkUnVuTGF6eUluaXRpYWxpemVycyAmJiBpbnN0YW5jZS5fX21vYnhMYXp5SW5pdGlhbGl6ZXJzLmZvckVhY2goZnVuY3Rpb24gKGluaXRpYWxpemVyKSB7IHJldHVybiBpbml0aWFsaXplcihpbnN0YW5jZSk7IH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHF1YWNrc0xpa2VBRGVjb3JhdG9yKGFyZ3MpIHtcbiAgICByZXR1cm4gKGFyZ3MubGVuZ3RoID09PSAyIHx8IGFyZ3MubGVuZ3RoID09PSAzKSAmJiB0eXBlb2YgYXJnc1sxXSA9PT0gXCJzdHJpbmdcIjtcbn1cbmZ1bmN0aW9uIGl0ZXJhdG9yU3ltYm9sKCkge1xuICAgIHJldHVybiAodHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvcikgfHwgXCJAQGl0ZXJhdG9yXCI7XG59XG52YXIgSVNfSVRFUkFUSU5HX01BUktFUiA9IFwiX18kJGl0ZXJhdGluZ1wiO1xuZnVuY3Rpb24gYXJyYXlBc0l0ZXJhdG9yKGFycmF5KSB7XG4gICAgaW52YXJpYW50KGFycmF5W0lTX0lURVJBVElOR19NQVJLRVJdICE9PSB0cnVlLCBcIklsbGVnYWwgc3RhdGU6IGNhbm5vdCByZWN5Y2xlIGFycmF5IGFzIGl0ZXJhdG9yXCIpO1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcChhcnJheSwgSVNfSVRFUkFUSU5HX01BUktFUiwgdHJ1ZSk7XG4gICAgdmFyIGlkeCA9IC0xO1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcChhcnJheSwgXCJuZXh0XCIsIGZ1bmN0aW9uIG5leHQoKSB7XG4gICAgICAgIGlkeCsrO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZG9uZTogaWR4ID49IHRoaXMubGVuZ3RoLFxuICAgICAgICAgICAgdmFsdWU6IGlkeCA8IHRoaXMubGVuZ3RoID8gdGhpc1tpZHhdIDogdW5kZWZpbmVkXG4gICAgICAgIH07XG4gICAgfSk7XG4gICAgcmV0dXJuIGFycmF5O1xufVxuZnVuY3Rpb24gZGVjbGFyZUl0ZXJhdG9yKHByb3RvdFR5cGUsIGl0ZXJhdG9yRmFjdG9yeSkge1xuICAgIGFkZEhpZGRlbkZpbmFsUHJvcChwcm90b3RUeXBlLCBpdGVyYXRvclN5bWJvbCgpLCBpdGVyYXRvckZhY3RvcnkpO1xufVxudmFyIG1lc3NhZ2VzID0ge1xuICAgIFwibTAwMVwiOiBcIkl0IGlzIG5vdCBhbGxvd2VkIHRvIGFzc2lnbiBuZXcgdmFsdWVzIHRvIEBhY3Rpb24gZmllbGRzXCIsXG4gICAgXCJtMDAyXCI6IFwiYHJ1bkluQWN0aW9uYCBleHBlY3RzIGEgZnVuY3Rpb25cIixcbiAgICBcIm0wMDNcIjogXCJgcnVuSW5BY3Rpb25gIGV4cGVjdHMgYSBmdW5jdGlvbiB3aXRob3V0IGFyZ3VtZW50c1wiLFxuICAgIFwibTAwNFwiOiBcImF1dG9ydW4gZXhwZWN0cyBhIGZ1bmN0aW9uXCIsXG4gICAgXCJtMDA1XCI6IFwiV2FybmluZzogYXR0ZW1wdGVkIHRvIHBhc3MgYW4gYWN0aW9uIHRvIGF1dG9ydW4uIEFjdGlvbnMgYXJlIHVudHJhY2tlZCBhbmQgd2lsbCBub3QgdHJpZ2dlciBvbiBzdGF0ZSBjaGFuZ2VzLiBVc2UgYHJlYWN0aW9uYCBvciB3cmFwIG9ubHkgeW91ciBzdGF0ZSBtb2RpZmljYXRpb24gY29kZSBpbiBhbiBhY3Rpb24uXCIsXG4gICAgXCJtMDA2XCI6IFwiV2FybmluZzogYXR0ZW1wdGVkIHRvIHBhc3MgYW4gYWN0aW9uIHRvIGF1dG9ydW5Bc3luYy4gQWN0aW9ucyBhcmUgdW50cmFja2VkIGFuZCB3aWxsIG5vdCB0cmlnZ2VyIG9uIHN0YXRlIGNoYW5nZXMuIFVzZSBgcmVhY3Rpb25gIG9yIHdyYXAgb25seSB5b3VyIHN0YXRlIG1vZGlmaWNhdGlvbiBjb2RlIGluIGFuIGFjdGlvbi5cIixcbiAgICBcIm0wMDdcIjogXCJyZWFjdGlvbiBvbmx5IGFjY2VwdHMgMiBvciAzIGFyZ3VtZW50cy4gSWYgbWlncmF0aW5nIGZyb20gTW9iWCAyLCBwbGVhc2UgcHJvdmlkZSBhbiBvcHRpb25zIG9iamVjdFwiLFxuICAgIFwibTAwOFwiOiBcIndyYXBwaW5nIHJlYWN0aW9uIGV4cHJlc3Npb24gaW4gYGFzUmVmZXJlbmNlYCBpcyBubyBsb25nZXIgc3VwcG9ydGVkLCB1c2Ugb3B0aW9ucyBvYmplY3QgaW5zdGVhZFwiLFxuICAgIFwibTAwOVwiOiBcIkBjb21wdXRlZCBjYW4gb25seSBiZSB1c2VkIG9uIGdldHRlciBmdW5jdGlvbnMsIGxpa2U6ICdAY29tcHV0ZWQgZ2V0IG15UHJvcHMoKSB7IHJldHVybiAuLi47IH0nLiBJdCBsb29rcyBsaWtlIGl0IHdhcyB1c2VkIG9uIGEgcHJvcGVydHkuXCIsXG4gICAgXCJtMDEwXCI6IFwiQGNvbXB1dGVkIGNhbiBvbmx5IGJlIHVzZWQgb24gZ2V0dGVyIGZ1bmN0aW9ucywgbGlrZTogJ0Bjb21wdXRlZCBnZXQgbXlQcm9wcygpIHsgcmV0dXJuIC4uLjsgfSdcIixcbiAgICBcIm0wMTFcIjogXCJGaXJzdCBhcmd1bWVudCB0byBgY29tcHV0ZWRgIHNob3VsZCBiZSBhbiBleHByZXNzaW9uLiBJZiB1c2luZyBjb21wdXRlZCBhcyBkZWNvcmF0b3IsIGRvbid0IHBhc3MgaXQgYXJndW1lbnRzXCIsXG4gICAgXCJtMDEyXCI6IFwiY29tcHV0ZWQgdGFrZXMgb25lIG9yIHR3byBhcmd1bWVudHMgaWYgdXNlZCBhcyBmdW5jdGlvblwiLFxuICAgIFwibTAxM1wiOiBcIlttb2J4LmV4cHJdICdleHByJyBzaG91bGQgb25seSBiZSB1c2VkIGluc2lkZSBvdGhlciByZWFjdGl2ZSBmdW5jdGlvbnMuXCIsXG4gICAgXCJtMDE0XCI6IFwiZXh0ZW5kT2JzZXJ2YWJsZSBleHBlY3RlZCAyIG9yIG1vcmUgYXJndW1lbnRzXCIsXG4gICAgXCJtMDE1XCI6IFwiZXh0ZW5kT2JzZXJ2YWJsZSBleHBlY3RzIGFuIG9iamVjdCBhcyBmaXJzdCBhcmd1bWVudFwiLFxuICAgIFwibTAxNlwiOiBcImV4dGVuZE9ic2VydmFibGUgc2hvdWxkIG5vdCBiZSB1c2VkIG9uIG1hcHMsIHVzZSBtYXAubWVyZ2UgaW5zdGVhZFwiLFxuICAgIFwibTAxN1wiOiBcImFsbCBhcmd1bWVudHMgb2YgZXh0ZW5kT2JzZXJ2YWJsZSBzaG91bGQgYmUgb2JqZWN0c1wiLFxuICAgIFwibTAxOFwiOiBcImV4dGVuZGluZyBhbiBvYmplY3Qgd2l0aCBhbm90aGVyIG9ic2VydmFibGUgKG9iamVjdCkgaXMgbm90IHN1cHBvcnRlZC4gUGxlYXNlIGNvbnN0cnVjdCBhbiBleHBsaWNpdCBwcm9wZXJ0eW1hcCwgdXNpbmcgYHRvSlNgIGlmIG5lZWQuIFNlZSBpc3N1ZSAjNTQwXCIsXG4gICAgXCJtMDE5XCI6IFwiW21vYnguaXNPYnNlcnZhYmxlXSBpc09ic2VydmFibGUob2JqZWN0LCBwcm9wZXJ0eU5hbWUpIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIGFycmF5cyBhbmQgbWFwcy4gVXNlIG1hcC5oYXMgb3IgYXJyYXkubGVuZ3RoIGluc3RlYWQuXCIsXG4gICAgXCJtMDIwXCI6IFwibW9kaWZpZXJzIGNhbiBvbmx5IGJlIHVzZWQgZm9yIGluZGl2aWR1YWwgb2JqZWN0IHByb3BlcnRpZXNcIixcbiAgICBcIm0wMjFcIjogXCJvYnNlcnZhYmxlIGV4cGVjdHMgemVybyBvciBvbmUgYXJndW1lbnRzXCIsXG4gICAgXCJtMDIyXCI6IFwiQG9ic2VydmFibGUgY2FuIG5vdCBiZSB1c2VkIG9uIGdldHRlcnMsIHVzZSBAY29tcHV0ZWQgaW5zdGVhZFwiLFxuICAgIFwibTAyM1wiOiBcIlVzaW5nIGB0cmFuc2FjdGlvbmAgaXMgZGVwcmVjYXRlZCwgdXNlIGBydW5JbkFjdGlvbmAgb3IgYChAKWFjdGlvbmAgaW5zdGVhZC5cIixcbiAgICBcIm0wMjRcIjogXCJ3aHlSdW4oKSBjYW4gb25seSBiZSB1c2VkIGlmIGEgZGVyaXZhdGlvbiBpcyBhY3RpdmUsIG9yIGJ5IHBhc3NpbmcgYW4gY29tcHV0ZWQgdmFsdWUgLyByZWFjdGlvbiBleHBsaWNpdGx5LiBJZiB5b3UgaW52b2tlZCB3aHlSdW4gZnJvbSBpbnNpZGUgYSBjb21wdXRhdGlvbjsgdGhlIGNvbXB1dGF0aW9uIGlzIGN1cnJlbnRseSBzdXNwZW5kZWQgYnV0IHJlLWV2YWx1YXRpbmcgYmVjYXVzZSBzb21lYm9keSByZXF1ZXN0ZWQgaXRzIHZhbHVlLlwiLFxuICAgIFwibTAyNVwiOiBcIndoeVJ1biBjYW4gb25seSBiZSB1c2VkIG9uIHJlYWN0aW9ucyBhbmQgY29tcHV0ZWQgdmFsdWVzXCIsXG4gICAgXCJtMDI2XCI6IFwiYGFjdGlvbmAgY2FuIG9ubHkgYmUgaW52b2tlZCBvbiBmdW5jdGlvbnNcIixcbiAgICBcIm0wMjhcIjogXCJJdCBpcyBub3QgYWxsb3dlZCB0byBzZXQgYHVzZVN0cmljdGAgd2hlbiBhIGRlcml2YXRpb24gaXMgcnVubmluZ1wiLFxuICAgIFwibTAyOVwiOiBcIklOVEVSTkFMIEVSUk9SIG9ubHkgb25CZWNvbWVVbm9ic2VydmVkIHNob3VsZG4ndCBiZSBjYWxsZWQgdHdpY2UgaW4gYSByb3dcIixcbiAgICBcIm0wMzBhXCI6IFwiU2luY2Ugc3RyaWN0LW1vZGUgaXMgZW5hYmxlZCwgY2hhbmdpbmcgb2JzZXJ2ZWQgb2JzZXJ2YWJsZSB2YWx1ZXMgb3V0c2lkZSBhY3Rpb25zIGlzIG5vdCBhbGxvd2VkLiBQbGVhc2Ugd3JhcCB0aGUgY29kZSBpbiBhbiBgYWN0aW9uYCBpZiB0aGlzIGNoYW5nZSBpcyBpbnRlbmRlZC4gVHJpZWQgdG8gbW9kaWZ5OiBcIixcbiAgICBcIm0wMzBiXCI6IFwiU2lkZSBlZmZlY3RzIGxpa2UgY2hhbmdpbmcgc3RhdGUgYXJlIG5vdCBhbGxvd2VkIGF0IHRoaXMgcG9pbnQuIEFyZSB5b3UgdHJ5aW5nIHRvIG1vZGlmeSBzdGF0ZSBmcm9tLCBmb3IgZXhhbXBsZSwgdGhlIHJlbmRlciBmdW5jdGlvbiBvZiBhIFJlYWN0IGNvbXBvbmVudD8gVHJpZWQgdG8gbW9kaWZ5OiBcIixcbiAgICBcIm0wMzFcIjogXCJDb21wdXRlZCB2YWx1ZXMgYXJlIG5vdCBhbGxvd2VkIHRvIG5vdCBjYXVzZSBzaWRlIGVmZmVjdHMgYnkgY2hhbmdpbmcgb2JzZXJ2YWJsZXMgdGhhdCBhcmUgYWxyZWFkeSBiZWluZyBvYnNlcnZlZC4gVHJpZWQgdG8gbW9kaWZ5OiBcIixcbiAgICBcIm0wMzJcIjogXCIqIFRoaXMgY29tcHV0YXRpb24gaXMgc3VzcGVuZGVkIChub3QgaW4gdXNlIGJ5IGFueSByZWFjdGlvbikgYW5kIHdvbid0IHJ1biBhdXRvbWF0aWNhbGx5Llxcblx0RGlkbid0IGV4cGVjdCB0aGlzIGNvbXB1dGF0aW9uIHRvIGJlIHN1c3BlbmRlZCBhdCB0aGlzIHBvaW50P1xcblx0ICAxLiBNYWtlIHN1cmUgdGhpcyBjb21wdXRhdGlvbiBpcyB1c2VkIGJ5IGEgcmVhY3Rpb24gKHJlYWN0aW9uLCBhdXRvcnVuLCBvYnNlcnZlcikuXFxuXHQgIDIuIENoZWNrIHdoZXRoZXIgeW91IGFyZSB1c2luZyB0aGlzIGNvbXB1dGF0aW9uIHN5bmNocm9ub3VzbHkgKGluIHRoZSBzYW1lIHN0YWNrIGFzIHRoZXkgcmVhY3Rpb24gdGhhdCBuZWVkcyBpdCkuXCIsXG4gICAgXCJtMDMzXCI6IFwiYG9ic2VydmVgIGRvZXNuJ3Qgc3VwcG9ydCB0aGUgZmlyZSBpbW1lZGlhdGVseSBwcm9wZXJ0eSBmb3Igb2JzZXJ2YWJsZSBtYXBzLlwiLFxuICAgIFwibTAzNFwiOiBcImBtb2J4Lm1hcGAgaXMgZGVwcmVjYXRlZCwgdXNlIGBuZXcgT2JzZXJ2YWJsZU1hcGAgb3IgYG1vYngub2JzZXJ2YWJsZS5tYXBgIGluc3RlYWRcIixcbiAgICBcIm0wMzVcIjogXCJDYW5ub3QgbWFrZSB0aGUgZGVzaWduYXRlZCBvYmplY3Qgb2JzZXJ2YWJsZTsgaXQgaXMgbm90IGV4dGVuc2libGVcIixcbiAgICBcIm0wMzZcIjogXCJJdCBpcyBub3QgcG9zc2libGUgdG8gZ2V0IGluZGV4IGF0b21zIGZyb20gYXJyYXlzXCIsXG4gICAgXCJtMDM3XCI6IFwiSGkgdGhlcmUhIEknbSBzb3JyeSB5b3UgaGF2ZSBqdXN0IHJ1biBpbnRvIGFuIGV4Y2VwdGlvbi5cXG5JZiB5b3VyIGRlYnVnZ2VyIGVuZHMgdXAgaGVyZSwga25vdyB0aGF0IHNvbWUgcmVhY3Rpb24gKGxpa2UgdGhlIHJlbmRlcigpIG9mIGFuIG9ic2VydmVyIGNvbXBvbmVudCwgYXV0b3J1biBvciByZWFjdGlvbilcXG50aHJldyBhbiBleGNlcHRpb24gYW5kIHRoYXQgbW9ieCBjYXVnaHQgaXQsIHRvIGF2b2lkIHRoYXQgaXQgYnJpbmdzIHRoZSByZXN0IG9mIHlvdXIgYXBwbGljYXRpb24gZG93bi5cXG5UaGUgb3JpZ2luYWwgY2F1c2Ugb2YgdGhlIGV4Y2VwdGlvbiAodGhlIGNvZGUgdGhhdCBjYXVzZWQgdGhpcyByZWFjdGlvbiB0byBydW4gKGFnYWluKSksIGlzIHN0aWxsIGluIHRoZSBzdGFjay5cXG5cXG5Ib3dldmVyLCBtb3JlIGludGVyZXN0aW5nIGlzIHRoZSBhY3R1YWwgc3RhY2sgdHJhY2Ugb2YgdGhlIGVycm9yIGl0c2VsZi5cXG5Ib3BlZnVsbHkgdGhlIGVycm9yIGlzIGFuIGluc3RhbmNlb2YgRXJyb3IsIGJlY2F1c2UgaW4gdGhhdCBjYXNlIHlvdSBjYW4gaW5zcGVjdCB0aGUgb3JpZ2luYWwgc3RhY2sgb2YgdGhlIGVycm9yIGZyb20gd2hlcmUgaXQgd2FzIHRocm93bi5cXG5TZWUgYGVycm9yLnN0YWNrYCBwcm9wZXJ0eSwgb3IgcHJlc3MgdGhlIHZlcnkgc3VidGxlIFxcXCIoLi4uKVxcXCIgbGluayB5b3Ugc2VlIG5lYXIgdGhlIGNvbnNvbGUuZXJyb3IgbWVzc2FnZSB0aGF0IHByb2JhYmx5IGJyb3VnaHQgeW91IGhlcmUuXFxuVGhhdCBzdGFjayBpcyBtb3JlIGludGVyZXN0aW5nIHRoYW4gdGhlIHN0YWNrIG9mIHRoaXMgY29uc29sZS5lcnJvciBpdHNlbGYuXFxuXFxuSWYgdGhlIGV4Y2VwdGlvbiB5b3Ugc2VlIGlzIGFuIGV4Y2VwdGlvbiB5b3UgY3JlYXRlZCB5b3Vyc2VsZiwgbWFrZSBzdXJlIHRvIHVzZSBgdGhyb3cgbmV3IEVycm9yKFxcXCJPb3BzXFxcIilgIGluc3RlYWQgb2YgYHRocm93IFxcXCJPb3BzXFxcImAsXFxuYmVjYXVzZSB0aGUgamF2YXNjcmlwdCBlbnZpcm9ubWVudCB3aWxsIG9ubHkgcHJlc2VydmUgdGhlIG9yaWdpbmFsIHN0YWNrIHRyYWNlIGluIHRoZSBmaXJzdCBmb3JtLlxcblxcbllvdSBjYW4gYWxzbyBtYWtlIHN1cmUgdGhlIGRlYnVnZ2VyIHBhdXNlcyB0aGUgbmV4dCB0aW1lIHRoaXMgdmVyeSBzYW1lIGV4Y2VwdGlvbiBpcyB0aHJvd24gYnkgZW5hYmxpbmcgXFxcIlBhdXNlIG9uIGNhdWdodCBleGNlcHRpb25cXFwiLlxcbihOb3RlIHRoYXQgaXQgbWlnaHQgcGF1c2Ugb24gbWFueSBvdGhlciwgdW5yZWxhdGVkIGV4Y2VwdGlvbiBhcyB3ZWxsKS5cXG5cXG5JZiB0aGF0IGFsbCBkb2Vzbid0IGhlbHAgeW91IG91dCwgZmVlbCBmcmVlIHRvIG9wZW4gYW4gaXNzdWUgaHR0cHM6Ly9naXRodWIuY29tL21vYnhqcy9tb2J4L2lzc3VlcyFcXG5cIixcbiAgICBcIm0wMzhcIjogXCJNaXNzaW5nIGl0ZW1zIGluIHRoaXMgbGlzdD9cXG4gICAgMS4gQ2hlY2sgd2hldGhlciBhbGwgdXNlZCB2YWx1ZXMgYXJlIHByb3Blcmx5IG1hcmtlZCBhcyBvYnNlcnZhYmxlICh1c2UgaXNPYnNlcnZhYmxlIHRvIHZlcmlmeSlcXG4gICAgMi4gTWFrZSBzdXJlIHlvdSBkaWRuJ3QgZGVyZWZlcmVuY2UgdmFsdWVzIHRvbyBlYXJseS4gTW9iWCBvYnNlcnZlcyBwcm9wcywgbm90IHByaW1pdGl2ZXMuIEUuZzogdXNlICdwZXJzb24ubmFtZScgaW5zdGVhZCBvZiAnbmFtZScgaW4geW91ciBjb21wdXRhdGlvbi5cXG5cIlxufTtcbmZ1bmN0aW9uIGdldE1lc3NhZ2UoaWQpIHtcbiAgICByZXR1cm4gbWVzc2FnZXNbaWRdO1xufVxudmFyIEVNUFRZX0FSUkFZID0gW107XG5PYmplY3QuZnJlZXplKEVNUFRZX0FSUkFZKTtcbmZ1bmN0aW9uIGdldEdsb2JhbCgpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xufVxuZnVuY3Rpb24gZ2V0TmV4dElkKCkge1xuICAgIHJldHVybiArK2dsb2JhbFN0YXRlLm1vYnhHdWlkO1xufVxuZnVuY3Rpb24gZmFpbChtZXNzYWdlLCB0aGluZykge1xuICAgIGludmFyaWFudChmYWxzZSwgbWVzc2FnZSwgdGhpbmcpO1xuICAgIHRocm93IFwiWFwiO1xufVxuZnVuY3Rpb24gaW52YXJpYW50KGNoZWNrLCBtZXNzYWdlLCB0aGluZykge1xuICAgIGlmICghY2hlY2spXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlttb2J4XSBJbnZhcmlhbnQgZmFpbGVkOiBcIiArIG1lc3NhZ2UgKyAodGhpbmcgPyBcIiBpbiAnXCIgKyB0aGluZyArIFwiJ1wiIDogXCJcIikpO1xufVxudmFyIGRlcHJlY2F0ZWRNZXNzYWdlcyA9IFtdO1xuZnVuY3Rpb24gZGVwcmVjYXRlZChtc2cpIHtcbiAgICBpZiAoZGVwcmVjYXRlZE1lc3NhZ2VzLmluZGV4T2YobXNnKSAhPT0gLTEpXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICBkZXByZWNhdGVkTWVzc2FnZXMucHVzaChtc2cpO1xuICAgIGNvbnNvbGUuZXJyb3IoXCJbbW9ieF0gRGVwcmVjYXRlZDogXCIgKyBtc2cpO1xuICAgIHJldHVybiB0cnVlO1xufVxuZnVuY3Rpb24gb25jZShmdW5jKSB7XG4gICAgdmFyIGludm9rZWQgPSBmYWxzZTtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoaW52b2tlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgaW52b2tlZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbn1cbnZhciBub29wID0gZnVuY3Rpb24gKCkgeyB9O1xuZnVuY3Rpb24gdW5pcXVlKGxpc3QpIHtcbiAgICB2YXIgcmVzID0gW107XG4gICAgbGlzdC5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgIGlmIChyZXMuaW5kZXhPZihpdGVtKSA9PT0gLTEpXG4gICAgICAgICAgICByZXMucHVzaChpdGVtKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzO1xufVxuZnVuY3Rpb24gam9pblN0cmluZ3ModGhpbmdzLCBsaW1pdCwgc2VwYXJhdG9yKSB7XG4gICAgaWYgKGxpbWl0ID09PSB2b2lkIDApIHsgbGltaXQgPSAxMDA7IH1cbiAgICBpZiAoc2VwYXJhdG9yID09PSB2b2lkIDApIHsgc2VwYXJhdG9yID0gXCIgLSBcIjsgfVxuICAgIGlmICghdGhpbmdzKVxuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICB2YXIgc2xpY2VkID0gdGhpbmdzLnNsaWNlKDAsIGxpbWl0KTtcbiAgICByZXR1cm4gXCJcIiArIHNsaWNlZC5qb2luKHNlcGFyYXRvcikgKyAodGhpbmdzLmxlbmd0aCA+IGxpbWl0ID8gXCIgKC4uLiBhbmQgXCIgKyAodGhpbmdzLmxlbmd0aCAtIGxpbWl0KSArIFwibW9yZSlcIiA6IFwiXCIpO1xufVxuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiO1xufVxuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB2YXIgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgIHJldHVybiBwcm90byA9PT0gT2JqZWN0LnByb3RvdHlwZSB8fCBwcm90byA9PT0gbnVsbDtcbn1cbmZ1bmN0aW9uIG9iamVjdEFzc2lnbigpIHtcbiAgICB2YXIgcmVzID0gYXJndW1lbnRzWzBdO1xuICAgIGZvciAodmFyIGkgPSAxLCBsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKVxuICAgICAgICAgICAgaWYgKGhhc093blByb3BlcnR5KHNvdXJjZSwga2V5KSkge1xuICAgICAgICAgICAgICAgIHJlc1trZXldID0gc291cmNlW2tleV07XG4gICAgICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG5mdW5jdGlvbiB2YWx1ZURpZENoYW5nZShjb21wYXJlU3RydWN0dXJhbCwgb2xkVmFsdWUsIG5ld1ZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiBvbGRWYWx1ZSA9PT0gJ251bWJlcicgJiYgaXNOYU4ob2xkVmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgbmV3VmFsdWUgIT09ICdudW1iZXInIHx8ICFpc05hTihuZXdWYWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiBjb21wYXJlU3RydWN0dXJhbFxuICAgICAgICA/ICFkZWVwRXF1YWwob2xkVmFsdWUsIG5ld1ZhbHVlKVxuICAgICAgICA6IG9sZFZhbHVlICE9PSBuZXdWYWx1ZTtcbn1cbnZhciBwcm90b3R5cGVIYXNPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5mdW5jdGlvbiBoYXNPd25Qcm9wZXJ0eShvYmplY3QsIHByb3BOYW1lKSB7XG4gICAgcmV0dXJuIHByb3RvdHlwZUhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wTmFtZSk7XG59XG5mdW5jdGlvbiBtYWtlTm9uRW51bWVyYWJsZShvYmplY3QsIHByb3BOYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcE5hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFkZEhpZGRlblByb3Aob2JqZWN0LCBwcm9wTmFtZXNbaV0sIG9iamVjdFtwcm9wTmFtZXNbaV1dKTtcbiAgICB9XG59XG5mdW5jdGlvbiBhZGRIaWRkZW5Qcm9wKG9iamVjdCwgcHJvcE5hbWUsIHZhbHVlKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcE5hbWUsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgIH0pO1xufVxuZnVuY3Rpb24gYWRkSGlkZGVuRmluYWxQcm9wKG9iamVjdCwgcHJvcE5hbWUsIHZhbHVlKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcE5hbWUsIHtcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB2YWx1ZTogdmFsdWVcbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGlzUHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wKSB7XG4gICAgdmFyIGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcCk7XG4gICAgcmV0dXJuICFkZXNjcmlwdG9yIHx8IChkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSAhPT0gZmFsc2UgJiYgZGVzY3JpcHRvci53cml0YWJsZSAhPT0gZmFsc2UpO1xufVxuZnVuY3Rpb24gYXNzZXJ0UHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wKSB7XG4gICAgaW52YXJpYW50KGlzUHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wKSwgXCJDYW5ub3QgbWFrZSBwcm9wZXJ0eSAnXCIgKyBwcm9wICsgXCInIG9ic2VydmFibGUsIGl0IGlzIG5vdCBjb25maWd1cmFibGUgYW5kIHdyaXRhYmxlIGluIHRoZSB0YXJnZXQgb2JqZWN0XCIpO1xufVxuZnVuY3Rpb24gZ2V0RW51bWVyYWJsZUtleXMob2JqKSB7XG4gICAgdmFyIHJlcyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopXG4gICAgICAgIHJlcy5wdXNoKGtleSk7XG4gICAgcmV0dXJuIHJlcztcbn1cbmZ1bmN0aW9uIGRlZXBFcXVhbChhLCBiKSB7XG4gICAgaWYgKGEgPT09IG51bGwgJiYgYiA9PT0gbnVsbClcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgaWYgKGEgPT09IHVuZGVmaW5lZCAmJiBiID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIGlmICh0eXBlb2YgYSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgcmV0dXJuIGEgPT09IGI7XG4gICAgdmFyIGFJc0FycmF5ID0gaXNBcnJheUxpa2UoYSk7XG4gICAgdmFyIGFJc01hcCA9IGlzTWFwTGlrZShhKTtcbiAgICBpZiAoYUlzQXJyYXkgIT09IGlzQXJyYXlMaWtlKGIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZWxzZSBpZiAoYUlzTWFwICE9PSBpc01hcExpa2UoYikpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBlbHNlIGlmIChhSXNBcnJheSkge1xuICAgICAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKHZhciBpID0gYS5sZW5ndGggLSAxOyBpID49IDA7IGktLSlcbiAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKGFbaV0sIGJbaV0pKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYgKGFJc01hcCkge1xuICAgICAgICBpZiAoYS5zaXplICE9PSBiLnNpemUpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIHZhciBlcXVhbHNfMSA9IHRydWU7XG4gICAgICAgIGEuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgICAgZXF1YWxzXzEgPSBlcXVhbHNfMSAmJiBkZWVwRXF1YWwoYi5nZXQoa2V5KSwgdmFsdWUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGVxdWFsc18xO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgYSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgYiA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBpZiAoYSA9PT0gbnVsbCB8fCBiID09PSBudWxsKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBpZiAoaXNNYXBMaWtlKGEpICYmIGlzTWFwTGlrZShiKSkge1xuICAgICAgICAgICAgaWYgKGEuc2l6ZSAhPT0gYi5zaXplKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBkZWVwRXF1YWwob2JzZXJ2YWJsZS5zaGFsbG93TWFwKGEpLmVudHJpZXMoKSwgb2JzZXJ2YWJsZS5zaGFsbG93TWFwKGIpLmVudHJpZXMoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGdldEVudW1lcmFibGVLZXlzKGEpLmxlbmd0aCAhPT0gZ2V0RW51bWVyYWJsZUtleXMoYikubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIGEpIHtcbiAgICAgICAgICAgIGlmICghKHByb3AgaW4gYikpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgaWYgKCFkZWVwRXF1YWwoYVtwcm9wXSwgYltwcm9wXSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5mdW5jdGlvbiBjcmVhdGVJbnN0YW5jZW9mUHJlZGljYXRlKG5hbWUsIGNsYXp6KSB7XG4gICAgdmFyIHByb3BOYW1lID0gXCJpc01vYlhcIiArIG5hbWU7XG4gICAgY2xhenoucHJvdG90eXBlW3Byb3BOYW1lXSA9IHRydWU7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIHJldHVybiBpc09iamVjdCh4KSAmJiB4W3Byb3BOYW1lXSA9PT0gdHJ1ZTtcbiAgICB9O1xufVxuZnVuY3Rpb24gaXNBcnJheUxpa2UoeCkge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHgpIHx8IGlzT2JzZXJ2YWJsZUFycmF5KHgpO1xufVxuZXhwb3J0cy5pc0FycmF5TGlrZSA9IGlzQXJyYXlMaWtlO1xuZnVuY3Rpb24gaXNNYXBMaWtlKHgpIHtcbiAgICByZXR1cm4gaXNFUzZNYXAoeCkgfHwgaXNPYnNlcnZhYmxlTWFwKHgpO1xufVxuZnVuY3Rpb24gaXNFUzZNYXAodGhpbmcpIHtcbiAgICBpZiAoZ2V0R2xvYmFsKCkuTWFwICE9PSB1bmRlZmluZWQgJiYgdGhpbmcgaW5zdGFuY2VvZiBnZXRHbG9iYWwoKS5NYXApXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIHByaW1pdGl2ZVN5bWJvbCgpIHtcbiAgICByZXR1cm4gKHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wudG9QcmltaXRpdmUpIHx8IFwiQEB0b1ByaW1pdGl2ZVwiO1xufVxuZnVuY3Rpb24gdG9QcmltaXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgPyBudWxsIDogdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiID8gKFwiXCIgKyB2YWx1ZSkgOiB2YWx1ZTtcbn1cbiJdfQ==
'use strict'
const mobx = require('mobx')
const a = mobx.observable({
b: 1,
c: [],
})
const dom = [
document.createElement('div'),
document.createElement('div'),
document.createElement('div'),
document.createElement('div'),
]
dom.forEach((e, i) => {
e.style.background = ['steelblue', 'tomato'][i % 2]
document.body.appendChild(e)
})
const start = Date.now()
document.body.addEventListener('click', () => {
a.b++
a.c.push(Date.now() - start)
})
// 1
let oldValue = null
requestAnimationFrame(function loop() {
let b = a.b
dom[0].innerHTML = b
if (b !== oldValue) {
console.timeEnd()
}
oldValue = b
dom[2].innerHTML = a.c
requestAnimationFrame(loop)
})
// 2
mobx.autorun(() => {
dom[1].innerHTML += a.b + '<br>'
console.time()
})
mobx.autorun(() => {
dom[3].innerHTML = a.c.join('<br>')
})
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"mobx": "3.1.0"
}
}
<!-- contents of this file will be placed inside the <body> -->
<!-- contents of this file will be placed inside the <head> -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment