Skip to content

Instantly share code, notes, and snippets.

@ds300
Created August 18, 2016 07:36
Show Gist options
  • Save ds300/991784e3485cf1d5618d0bd332b28017 to your computer and use it in GitHub Desktop.
Save ds300/991784e3485cf1d5618d0bd332b28017 to your computer and use it in GitHub Desktop.
requirebin sketch
const d = require("derivable")
const name = d.atom("World"); // the name of the user
const countryCode = d.atom("en"); // for i18n
// static constants don't need to be wrapped
const greetings = {
en: "Hello",
de: "Hallo",
es: "Hola",
cn: "您好",
fr: "Bonjour",
};
// derive a greeting message based on the user's name and country.
const greeting = countryCode.derive(cc => greetings[cc]);
const message = d.derive`${greeting}, ${name}!`; // es6 tagged template strings!
// set up a Reactor to print the message every time it changes
message.react(msg => console.log(msg));
// $> Hello, World!
countryCode.set("de");
// $> Hallo, World!
name.set("Dagmar");
// $> Hallo, Dagmar!
// we can avoid unwanted intermediate reactions by using transactions
d.transact(() => {
countryCode.set("fr");
name.set("Étienne");
});
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})({"derivable":[function(require,module,exports){
// UMD loader
(function (global, factory) {
"use strict";
if (global && typeof global.define === "function" && global.define.amd) {
global.define(["exports"], factory);
} else if (typeof exports !== "undefined") {
factory(exports);
} else {
factory(global.Derivable = {});
}
})(this, function (exports) {
"use strict";
var util_keys = Object.keys;
function util_extend(obj) {
for (var i = 1; i < arguments.length; i++) {
var other = arguments[i];
var keys = util_keys(other);
for (var j = keys.length; j--;) {
var prop = keys[j];
obj[prop] = other[prop];
}
}
return obj;
}
function _is(a, b) {
// SameValue algorithm
if (a === b) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return a !== 0 || 1 / a === 1 / b;
} else {
// Step 6.a: NaN == NaN
return a !== a && b !== b;
}
}
function util_equals (a, b) {
return _is(a, b) || (a && typeof a.equals === 'function' && a.equals(b));
}
function util_addToArray (a, b) {
var i = a.indexOf(b);
if (i < 0) {
a.push(b);
}
}
function util_removeFromArray (a, b) {
var i = a.indexOf(b);
if (i >= 0) {
a.splice(i, 1);
}
}
function util_arrayContains (a, b) {
return a.indexOf(b) >= 0;
}
var nextId = 0;
function util_nextId () {
return nextId++;
}
function util_slice (a, i) {
return Array.prototype.slice.call(a, i);
}
var util_unique = Object.freeze({equals: function () { return false; }});
function util_some (x) {
return (x !== null) && (x !== void 0);
}
var util_DEBUG_MODE = false;
function util_setDebugMode(val) {
util_DEBUG_MODE = !!val;
}
function util_setEquals(derivable, equals) {
derivable._equals = equals;
return derivable;
}
// node modes
var gc_NEW = 0,
gc_CHANGED = 1,
gc_UNCHANGED = 2,
gc_ORPHANED = 3,
gc_UNSTABLE = 4,
gc_STABLE = 5,
gc_DISOWNED = 6;
function gc_mark(node, reactors) {
// make everything unstable
if (node._type === types_REACTION) {
if (node.reacting) {
throw new Error("Cycle detected! Don't do this!");
}
reactors.push(node);
} else {
for (var i = node._children.length; i--;) {
var child = node._children[i];
if (child._state !== gc_UNSTABLE) {
child._state = gc_UNSTABLE;
gc_mark(child, reactors);
}
}
}
}
function gc_sweep(node) {
var i;
switch (node._state) {
case gc_CHANGED:
case gc_UNCHANGED:
// changed or unchanged means the node was visited
// during the react phase, which means we keep it in
// the graph for the next go round
for (i = node._children.length; i--;) {
var child = node._children[i];
gc_sweep(child);
if (child._state !== gc_STABLE) {
node._children.splice(i, 1);
}
}
node._state = gc_STABLE;
break;
case gc_UNSTABLE:
if (node._type === types_REACTION) {
// only happens when reaction created in transaction. see issue #14
node._state = gc_STABLE;
} else {
// unstable means the node was not visited during
// the react phase, which means we kick it out of the
// graph.
// but first we check if all of its parents were unchanged
// if so, we can avoid recalculating it in future by
// caching its parents' current values.
var stashedParentStates = [];
for (i = node._parents.length; i--;) {
var parent = node._parents[i];
if (parent._state !== gc_UNCHANGED) {
// nope, its parents either have changed or weren't visited,
// so we have to orphan this node
node._state = gc_ORPHANED;
break;
}
stashedParentStates.push([parent, parent._value]);
}
if (node._state !== gc_ORPHANED) {
node._state = gc_DISOWNED;
node._parents = stashedParentStates;
}
}
break;
case gc_STABLE:
case gc_ORPHANED:
case gc_DISOWNED:
break;
default:
throw new Error("can't sweep state " + node._state);
}
}
function gc_abort_sweep(node) {
// set everything to unstable, kill all derivation caches and disconnect
// the graph
var doChildren = false;
switch (node._type) {
case types_ATOM:
node._state = gc_STABLE;
doChildren = true;
break;
case types_DERIVATION:
case types_LENS:
node._state = gc_NEW;
node._value = util_unique;
doChildren = true;
break;
case types_REACTION:
node._state = gc_STABLE;
doChildren = false;
break;
}
if (doChildren) {
for (var i = node._children.length; i--;) {
gc_abort_sweep(node._children[i]);
}
node._children = [];
}
}
var parentsStack = [];
function parents_capturingParents(f) {
var i = parentsStack.length;
parentsStack.push([]);
try {
f();
return parentsStack[i];
} finally {
parentsStack.pop();
}
}
function parents_maybeCaptureParent(p) {
if (parentsStack.length > 0) {
util_addToArray(parentsStack[parentsStack.length - 1], p);
}
}
var types_ATOM = "ATOM",
types_DERIVATION = "DERIVATION",
types_LENS = "LENS",
types_REACTION = "REACTION";
var RUNNING = 0,
COMPLETED = 1,
ABORTED = 3;
var TransactionAbortion = {};
function abortTransaction() {
throw TransactionAbortion;
}
function transactions_newContext () {
return {currentTxn: null};
}
function transactions_inTransaction (ctx) {
return ctx.currentTxn !== null;
}
function transactions_currentTransaction (ctx) {
return ctx.currentTxn;
}
function begin (ctx, txn) {
txn._parent = ctx.currentTxn;
txn._state = RUNNING;
ctx.currentTxn = txn;
}
function popTransaction (ctx, cb) {
var txn = ctx.currentTxn;
ctx.currentTxn = txn._parent;
if (txn._state !== RUNNING) {
throw new Error("unexpected state: " + txn._state);
}
cb(txn);
}
function commit (ctx) {
popTransaction(ctx, function (txn) {
txn._state = COMPLETED;
txn.onCommit && txn.onCommit();
});
}
function abort (ctx) {
popTransaction(ctx, function (txn) {
txn._state = ABORTED;
txn.onAbort && txn.onAbort();
});
}
function transactions_transact (ctx, txn, f) {
begin(ctx, txn);
try {
f(abortTransaction);
} catch (e) {
abort(ctx);
if (e !== TransactionAbortion) {
throw e;
} else {
return;
}
}
commit(ctx);
}
function transactions_ticker (ctx, txnConstructor) {
begin(ctx, txnConstructor());
var disposed = false;
return {
tick: function () {
if (disposed) throw new Error("can't tick disposed ticker");
commit(ctx);
begin(ctx, txnConstructor());
},
stop: function () {
if (disposed) throw new Error("ticker already disposed");
commit(ctx);
}
}
}
function reactorBase (parent, control) {
var base = {
control: control, // the actual object the user gets
parent: parent, // the parent derivable
parentReactor: null,
dependentReactors: [],
_state: gc_STABLE,
active: false, // whether or not listening for changes in parent
_type: types_REACTION,
uid: util_nextId(),
reacting: false, // whether or not reaction function being invoked
yielding: false, // whether or not letting parentReactor react first
};
if (util_DEBUG_MODE) {
base.stack = Error().stack;
}
return base;
}
var cycleMsg = "Cyclical Reactor Dependency! Not allowed!";
function stop (base) {
if (base.active) {
util_removeFromArray(base.parent._children, base);
if (base.parentReactor) {
orphan(base);
}
base.active = false;
base.control.onStop && base.control.onStop();
}
}
var parentReactorStack = [];
function start (base) {
if (!base.active) {
util_addToArray(base.parent._children, base);
base.active = true;
base.parent._get();
// capture reactor dependency relationships
var len = parentReactorStack.length;
if (len > 0) {
base.parentReactor = parentReactorStack[len - 1];
}
base.control.onStart && base.control.onStart();
}
}
function orphan (base) {
if (base.parentReactor) {
base.parentReactor = null;
}
}
function adopt (parentBase, childBase) {
childBase.parentReactor = parentBase;
}
function reactors_maybeReact (base) {
if (base.yielding) {
throw Error(cycleMsg);
}
if (base.active && base._state === gc_UNSTABLE) {
if (base.parentReactor !== null) {
try {
base.yielding = true;
reactors_maybeReact(base.parentReactor);
} finally {
base.yielding = false;
}
}
// parent might have deactivated this one
if (base.active) {
var parent = base.parent, parentState = parent._state;
if (parentState === gc_UNSTABLE ||
parentState === gc_ORPHANED ||
parentState === gc_DISOWNED ||
parentState === gc_NEW) {
parent._get();
}
parentState = parent._state;
if (parentState === gc_UNCHANGED) {
base._state = gc_STABLE;
} else if (parentState === gc_CHANGED) {
force(base);
} else {
throw new Error("invalid parent state: " + parentState);
}
}
}
}
function force (base) {
// base.reacting check now in gc_mark; total solution there as opposed to here
if (base.control.react) {
base._state = gc_STABLE;
try {
base.reacting = true;
parentReactorStack.push(base);
if (!util_DEBUG_MODE) {
base.control.react(base.parent._get());
} else {
try {
base.control.react(base.parent._get());
} catch (e) {
console.error(base.stack);
throw e;
}
}
} finally {
parentReactorStack.pop();
base.reacting = false;
}
} else {
throw new Error("No reactor function available.");
}
}
function reactors_Reactor () {
/*jshint validthis:true */
this._type = types_REACTION;
}
function reactors_createBase (control, parent) {
if (control._base) {
throw new Error("This reactor has already been initialized");
}
control._base = reactorBase(parent, control);
return control;
}
util_extend(reactors_Reactor.prototype, {
start: function () {
start(this._base);
return this;
},
stop: function () {
stop(this._base);
return this;
},
force: function () {
force(this._base);
return this;
},
isActive: function () {
return this._base.active;
},
orphan: function () {
orphan(this._base);
return this;
},
adopt: function (child) {
if (child._type !== types_REACTION) {
throw Error("reactors can only adopt reactors");
}
adopt(this._base, child._base);
return this;
}
});
function reactors_StandardReactor (f) {
/*jshint validthis:true */
this._type = types_REACTION;
this.react = f;
}
util_extend(reactors_StandardReactor.prototype, reactors_Reactor.prototype);
function reactors_anonymousReactor (descriptor) {
return util_extend(new reactors_Reactor(), descriptor);
}
function derivable_createPrototype (D, opts) {
var x = {
/**
* Creates a derived value whose state will always be f applied to this
* value
*/
derive: function (f, a, b, c, d) {
var that = this;
switch (arguments.length) {
case 0:
return that;
case 1:
switch (typeof f) {
case 'function':
return D.derivation(function () {
return f(that.get());
});
case 'string':
case 'number':
return D.derivation(function () {
return that.get()[D.unpack(f)];
});
default:
if (f instanceof Array) {
return f.map(function (x) {
return that.derive(x);
});
} else if (f instanceof RegExp) {
return D.derivation(function () {
return that.get().match(f);
});
} else if (D.isDerivable(f)) {
return D.derivation(function () {
var deriver = f.get();
var thing = that.get();
switch (typeof deriver) {
case 'function':
return deriver(thing);
case 'string':
case 'number':
return thing[deriver];
default:
if (deriver instanceof RegExp) {
return thing.match(deriver);
} else {
throw Error('type error');
}
}
return that.get()[D.unpack(f)];
});
} else {
throw Error('type error');
}
}
break;
case 2:
return D.derivation(function () {
return f(that.get(), D.unpack(a));
});
case 3:
return D.derivation(function () {
return f(that.get(), D.unpack(a), D.unpack(b));
});
case 4:
return D.derivation(function () {
return f(that.get(),
D.unpack(a),
D.unpack(b),
D.unpack(c));
});
case 5:
return D.derivation(function () {
return f(that.get(),
D.unpack(a),
D.unpack(b),
D.unpack(c),
D.unpack(d));
});
default:
var args = ([that]).concat(util_slice(arguments, 1));
return D.derivation(function () {
return f.apply(null, args.map(D.unpack));
});
}
},
reactor: function (f) {
if (typeof f === 'function') {
return reactors_createBase(new reactors_StandardReactor(f), this);
} else if (f instanceof reactors_Reactor) {
return reactors_createBase(f, this);
} else if (f && f.react) {
return reactors_createBase(reactors_anonymousReactor(f), this);
} else {
throw new Error("Unrecognized type for reactor " + f);
}
},
react: function (f, opts) {
if (typeof f !== 'function') {
throw Error('the first argument to .react must be a function');
}
opts = Object.assign({
once: false,
from: true,
until: false,
when: true,
skipFirst: false,
}, opts);
// coerce fn or bool to derivable<bool>
function condDerivable(fOrD, name) {
if (!D.isDerivable(fOrD)) {
if (typeof fOrD === 'function') {
fOrD = D.derivation(fOrD);
} else if (typeof fOrD === 'boolean') {
fOrD = D.atom(fOrD);
} else {
throw Error('react ' + name + ' condition must be derivable');
}
}
return fOrD.derive(function (x) { return !!x; });
}
// wrap reactor so f doesn't get a .this context, and to allow
// stopping after one reaction if desired.
var reactor = this.reactor({
react: function (val) {
if (opts.skipFirst) {
opts.skipFirst = false;
} else {
f(val);
if (opts.once) {
this.stop();
controller.stop();
}
}
},
onStart: opts.onStart,
onStop: opts.onStop
});
// listen to when and until conditions, starting and stopping the
// reactor as appropriate, and stopping this controller when until
// condition becomes true
var controller = D.struct({
until: condDerivable(opts.until, 'until'),
when: condDerivable(opts.when, 'when')
}).reactor(function (conds) {
if (conds.until) {
reactor.stop();
this.stop();
} else if (conds.when) {
if (!reactor.isActive()) {
reactor.start().force();
}
} else if (reactor.isActive()) {
reactor.stop();
}
});
// listen to from condition, starting the reactor controller
// when appropriate
condDerivable(opts.from, 'from').reactor(function (from) {
if (from) {
controller.start().force();
this.stop();
}
}).start().force();
},
get: function () {
parents_maybeCaptureParent(this);
return this._get(); // abstract protected method, in Java parlance
},
is: function (other) {
return D.lift(opts.equals)(this, other);
},
and: function (other) {
return this.derive(function (x) {return x && D.unpack(other);});
},
or: function (other) {
return this.derive(function (x) {return x || D.unpack(other);});
},
then: function (thenClause, elseClause) {
return this.derive(function (x) {
return D.unpack(x ? thenClause : elseClause);
});
},
mThen: function (thenClause, elseClause) {
return this.derive(function (x) {
return D.unpack(util_some(x) ? thenClause : elseClause);
});
},
mOr: function (other) {
return this.mThen(this, other);
},
mDerive: function (arg) {
if (arguments.length === 1 && arg instanceof Array) {
var that = this;
return arg.map(function (a) { return that.mDerive(a); });
} else {
return this.mThen(this.derive.apply(this, arguments));
}
},
mAnd: function (other) {
return this.mThen(other, this);
},
not: function () {
return this.derive(function (x) { return !x; });
},
withEquality: function (equals) {
if (equals) {
if (typeof equals !== 'function') {
throw new Error('equals must be function');
}
} else {
equals = null;
}
return util_setEquals(this._clone(), equals);
},
};
x.switch = function () {
var args = arguments;
return this.derive(function (x) {
var i;
for (i = 0; i < args.length-1; i+=2) {
if (opts.equals(x, D.unpack(args[i]))) {
return D.unpack(args[i+1]);
}
}
if (i === args.length - 1) {
return D.unpack(args[i]);
}
});
};
return x;
}
function derivation_createPrototype (D, opts) {
return {
_clone: function () {
return util_setEquals(D.derivation(this._deriver), this._equals);
},
_forceGet: function () {
var that = this,
i;
var newParents = parents_capturingParents(function () {
var newState;
if (!util_DEBUG_MODE) {
newState = that._deriver();
} else {
try {
newState = that._deriver();
} catch (e) {
console.error(that._stack);
throw e;
}
}
var equals = that._equals || opts.equals;
that._state = equals(newState, that._value) ? gc_UNCHANGED : gc_CHANGED;
that._value = newState;
});
// organise parents
for (i = this._parents.length; i--;) {
var possiblyFormerParent = this._parents[i];
if (!util_arrayContains(newParents, possiblyFormerParent)) {
util_removeFromArray(possiblyFormerParent._children, this);
}
}
this._parents = newParents;
// add this as child to new parents
for (i = newParents.length; i--;) {
util_addToArray(newParents[i]._children, this);
}
},
_get: function () {
var i, parent;
outer: switch (this._state) {
case gc_NEW:
case gc_ORPHANED:
this._forceGet();
break;
case gc_UNSTABLE:
for (i = 0; i < this._parents.length; i++) {
parent = this._parents[i];
var parentState = parent._state;
if (parentState === gc_UNSTABLE ||
parentState === gc_ORPHANED ||
parentState === gc_DISOWNED) {
parent._get();
}
parentState = parent._state;
if (parentState === gc_CHANGED) {
this._forceGet();
break outer;
} else if (!(parentState === gc_STABLE ||
parentState === gc_UNCHANGED)) {
throw new Error("invalid parent mode: " + parentState);
}
}
this._state = gc_UNCHANGED;
break;
case gc_DISOWNED:
var parents = [];
for (i = 0; i < this._parents.length; i++) {
var parentStateTuple = this._parents[i],
state = parentStateTuple[1];
parent = parentStateTuple[0];
if (!opts.equals(parent._get(), state)) {
this._parents = [];
this._forceGet();
break outer;
} else {
parents.push(parent);
}
}
for (i = parents.length; i--;) {
util_addToArray(parents[i]._children, this);
}
this._parents = parents;
this._state = gc_UNCHANGED;
break;
default:
// noop
}
return this._value;
}
}
}
function derivation_construct(obj, deriver) {
obj._children = [];
obj._parents = [];
obj._deriver = deriver;
obj._state = gc_NEW;
obj._type = types_DERIVATION;
obj._value = util_unique;
obj._equals = null;
if (util_DEBUG_MODE) {
obj._stack = Error().stack;
}
return obj;
}
function mutable_createPrototype (D, _) {
return {
swap: function (f) {
var args = util_slice(arguments, 0);
args[0] = this.get();
return this.set(f.apply(null, args));
},
lens: function (monoLensDescriptor) {
var that = this;
return D.lens({
get: function () {
return monoLensDescriptor.get(that.get());
},
set: function (val) {
that.set(monoLensDescriptor.set(that.get(), val));
}
});
}
}
}
function lens_createPrototype(D, _) {
return {
_clone: function () {
return util_setEquals(D.lens(this._lensDescriptor), this._equals);
},
set: function (value) {
var that = this;
D.atomically(function () {
that._lensDescriptor.set(value);
});
return this;
}
}
}
function lens_construct(derivation, descriptor) {
derivation._lensDescriptor = descriptor;
derivation._type = types_LENS;
return derivation;
}
function processReactorQueue (rq) {
for (var i = rq.length; i--;) {
reactors_maybeReact(rq[i]);
}
}
var TXN_CTX = transactions_newContext();
function atom_inTxn () {
return transactions_inTransaction(TXN_CTX)
}
var NOOP_ARRAY = {push: function () {}};
function TransactionState () {
this.inTxnValues = {};
this.reactorQueue = [];
}
function getState (txnState, atom) {
var inTxnValue = txnState.inTxnValues[atom._uid];
if (inTxnValue) {
return inTxnValue[1];
} else {
return atom._value;
}
}
function setState (txnState, atom, state) {
txnState.inTxnValues[atom._uid] = [atom, state];
gc_mark(atom, txnState.reactorQueue);
}
util_extend(TransactionState.prototype, {
onCommit: function () {
var i, atomValueTuple;
var keys = util_keys(this.inTxnValues);
if (atom_inTxn()) {
// push in-txn vals up to current txn
for (i = keys.length; i--;) {
atomValueTuple = this.inTxnValues[keys[i]];
atomValueTuple[0].set(atomValueTuple[1]);
}
} else {
// change root state and run reactors.
for (i = keys.length; i--;) {
atomValueTuple = this.inTxnValues[keys[i]];
atomValueTuple[0]._value = atomValueTuple[1];
gc_mark(atomValueTuple[0], NOOP_ARRAY);
}
processReactorQueue(this.reactorQueue);
// then sweep for a clean finish
for (i = keys.length; i--;) {
gc_sweep(this.inTxnValues[keys[i]][0]);
}
}
},
onAbort: function () {
if (!atom_inTxn()) {
var keys = util_keys(this.inTxnValues);
for (var i = keys.length; i--;) {
gc_abort_sweep(this.inTxnValues[keys[i]][0]);
}
}
}
})
function atom_createPrototype (D, opts) {
return {
_clone: function () {
return util_setEquals(D.atom(this._value), this._equals);
},
withValidator: function (f) {
if (f === null) {
return this._clone();
} if (typeof f === 'function') {
var result = this._clone();
var existing = this._validator;
if (existing) {
result._validator = function (x) { return f(x) && existing(x); }
} else {
result._validator = f;
}
return result;
} else {
throw new Error(".withValidator expects function or null");
}
},
validate: function () {
this._validate(this.get());
},
_validate: function (value) {
var validationResult = this._validator && this._validator(value);
if (this._validator && validationResult !== true) {
throw new Error("Failed validation with value: '" + value + "'." +
" Validator returned '" + validationResult + "' ");
}
},
set: function (value) {
this._validate(value);
var equals = this._equals || opts.equals;
if (!equals(value, this._value)) {
this._state = gc_CHANGED;
if (atom_inTxn()) {
setState(transactions_currentTransaction(TXN_CTX), this, value);
} else {
this._value = value;
var reactorQueue = [];
gc_mark(this, reactorQueue);
processReactorQueue(reactorQueue);
gc_sweep(this);
}
}
return this;
},
_get: function () {
if (atom_inTxn()) {
return getState(transactions_currentTransaction(TXN_CTX), this);
}
return this._value;
}
};
}
function atom_construct (atom, value) {
atom._uid = util_nextId();
atom._children = [];
atom._state = gc_STABLE;
atom._value = value;
atom._type = types_ATOM;
atom._equals = null;
return atom;
}
function atom_transact (f) {
transactions_transact(TXN_CTX, new TransactionState(), f);
}
function atom_transaction (f) {
return function () {
var args = util_slice(arguments, 0);
var that = this;
var result;
atom_transact(function () {
result = f.apply(that, args);
});
return result;
}
}
var ticker = null;
function atom_ticker () {
if (ticker) {
ticker.refCount++;
} else {
ticker = transactions_ticker(TXN_CTX, function () {
return new TransactionState();
});
ticker.refCount = 1;
}
var done = false;
return {
tick: function () {
if (done) throw new Error('tyring to use ticker after release');
ticker.tick();
},
release: function () {
if (done) throw new Error('ticker already released');
if (--ticker.refCount === 0) {
ticker.stop();
ticker = null;
}
done = true;
}
};
}
var defaultConfig = { equals: util_equals };
function constructModule (config) {
config = util_extend({}, defaultConfig, config || {});
var D = {
transact: atom_transact,
defaultEquals: util_equals,
setDebugMode: util_setDebugMode,
transaction: atom_transaction,
ticker: atom_ticker,
Reactor: reactors_Reactor,
isAtom: function (x) {
return x && (x._type === types_ATOM || x._type === types_LENS);
},
isDerivable: function (x) {
return x && (x._type === types_ATOM ||
x._type === types_LENS ||
x._type === types_DERIVATION);
},
isDerivation: function (x) {
return x && (x._type === types_DERIVATION || x._type === types_LENS)
},
isLensed: function (x) {
return x && x._type === types_LENS;
},
isReactor: function (x) {
return x && x._type === types_REACTION;
},
};
var Derivable = derivable_createPrototype(D, config);
var Mutable = mutable_createPrototype(D, config);
var Atom = util_extend({}, Mutable, Derivable,
atom_createPrototype(D, config));
var Derivation = util_extend({}, Derivable,
derivation_createPrototype(D, config));
var Lens = util_extend({}, Mutable, Derivation,
lens_createPrototype(D, config));
/**
* Constructs a new atom whose state is the given value
*/
D.atom = function (val) {
return atom_construct(Object.create(Atom), val);
};
/**
* Returns a copy of f which runs atomically
*/
D.atomic = function (f) {
return function () {
var result;
var that = this;
var args = arguments;
D.atomically(function () {
result = f.apply(that, args);
});
return result;
}
};
D.atomically = function (f) {
if (atom_inTxn()) {
f();
} else {
D.transact(f);
}
};
D.derivation = function (f) {
return derivation_construct(Object.create(Derivation), f);
};
/**
* Template string tag for derivable strings
*/
D.derive = function (parts) {
var args = util_slice(arguments, 1);
return D.derivation(function () {
var s = "";
for (var i=0; i<parts.length; i++) {
s += parts[i];
if (i < args.length) {
s += D.unpack(args[i]);
}
}
return s;
});
};
/**
* creates a new lens
*/
D.lens = function (descriptor) {
return lens_construct(
derivation_construct(Object.create(Lens), descriptor.get),
descriptor
);
};
/**
* dereferences a thing if it is dereferencable, otherwise just returns it.
*/
D.unpack = function (thing) {
if (D.isDerivable(thing)) {
return thing.get();
} else {
return thing;
}
};
/**
* lifts a non-monadic function to work on derivables
*/
D.lift = function (f) {
return function () {
var args = arguments;
var that = this;
return D.derivation(function () {
return f.apply(that, Array.prototype.map.call(args, D.unpack));
});
}
};
function deepUnpack (thing) {
if (D.isDerivable(thing)) {
return thing.get();
} else if (thing instanceof Array) {
return thing.map(deepUnpack);
} else if (thing.constructor === Object) {
var result = {};
var keys = util_keys(thing);
for (var i = keys.length; i--;) {
var prop = keys[i];
result[prop] = deepUnpack(thing[prop]);
}
return result;
} else {
return thing;
}
}
D.struct = function (arg) {
if (arg.constructor === Object || arg instanceof Array) {
return D.derivation(function () {
return deepUnpack(arg);
});
} else {
throw new Error("`struct` expects plain Object or Array");
}
};
function andOrFn (breakOn) {
return function () {
var args = arguments;
return D.derivation(function () {
var val;
for (var i = 0; i < args.length; i++) {
val = D.unpack(args[i]);
if (breakOn(val)) {
break;
}
}
return val;
});
}
}
function identity (x) { return x; }
function complement (f) { return function (x) { return !f(x); }}
D.or = andOrFn(identity);
D.mOr = andOrFn(util_some);
D.and = andOrFn(complement(identity));
D.mAnd = andOrFn(complement(util_some));
return D;
}
util_extend(exports, constructModule());
exports.withEquality = function (equals) {
return constructModule({equals: equals});
};
exports['default'] = exports;
});
//# sourceMappingURL=derivable.js.map
},{}]},{},[])
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImRpc3QvZGVyaXZhYmxlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvLyBVTUQgbG9hZGVyXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICBcInVzZSBzdHJpY3RcIjtcbiAgaWYgKGdsb2JhbCAmJiB0eXBlb2YgZ2xvYmFsLmRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGdsb2JhbC5kZWZpbmUuYW1kKSB7XG4gICAgZ2xvYmFsLmRlZmluZShbXCJleHBvcnRzXCJdLCBmYWN0b3J5KTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIGZhY3RvcnkoZXhwb3J0cyk7XG4gIH0gZWxzZSB7XG4gICAgZmFjdG9yeShnbG9iYWwuRGVyaXZhYmxlID0ge30pO1xuICB9XG59KSh0aGlzLCBmdW5jdGlvbiAoZXhwb3J0cykge1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB1dGlsX2tleXMgPSBPYmplY3Qua2V5cztcblxuZnVuY3Rpb24gdXRpbF9leHRlbmQob2JqKSB7XG4gIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIG90aGVyID0gYXJndW1lbnRzW2ldO1xuICAgIHZhciBrZXlzID0gdXRpbF9rZXlzKG90aGVyKTtcbiAgICBmb3IgKHZhciBqID0ga2V5cy5sZW5ndGg7IGotLTspIHtcbiAgICAgIHZhciBwcm9wID0ga2V5c1tqXTtcbiAgICAgIG9ialtwcm9wXSA9IG90aGVyW3Byb3BdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb2JqO1xufVxuXG5mdW5jdGlvbiBfaXMoYSwgYikge1xuICAvLyBTYW1lVmFsdWUgYWxnb3JpdGhtXG4gIGlmIChhID09PSBiKSB7IC8vIFN0ZXBzIDEtNSwgNy0xMFxuICAgIC8vIFN0ZXBzIDYuYi02LmU6ICswICE9IC0wXG4gICAgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT09IDEgLyBiO1xuICB9IGVsc2Uge1xuICAgIC8vIFN0ZXAgNi5hOiBOYU4gPT0gTmFOXG4gICAgcmV0dXJuIGEgIT09IGEgJiYgYiAhPT0gYjtcbiAgfVxufVxuXG5mdW5jdGlvbiB1dGlsX2VxdWFscyAoYSwgYikge1xuICByZXR1cm4gX2lzKGEsIGIpIHx8IChhICYmIHR5cGVvZiBhLmVxdWFscyA9PT0gJ2Z1bmN0aW9uJyAmJiBhLmVxdWFscyhiKSk7XG59XG5cbmZ1bmN0aW9uIHV0aWxfYWRkVG9BcnJheSAoYSwgYikge1xuICB2YXIgaSA9IGEuaW5kZXhPZihiKTtcbiAgaWYgKGkgPCAwKSB7XG4gICAgYS5wdXNoKGIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHV0aWxfcmVtb3ZlRnJvbUFycmF5IChhLCBiKSB7XG4gIHZhciBpID0gYS5pbmRleE9mKGIpO1xuICBpZiAoaSA+PSAwKSB7XG4gICAgYS5zcGxpY2UoaSwgMSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdXRpbF9hcnJheUNvbnRhaW5zIChhLCBiKSB7XG4gIHJldHVybiBhLmluZGV4T2YoYikgPj0gMDtcbn1cblxudmFyIG5leHRJZCA9IDA7XG5mdW5jdGlvbiB1dGlsX25leHRJZCAoKSB7XG4gIHJldHVybiBuZXh0SWQrKztcbn1cblxuZnVuY3Rpb24gdXRpbF9zbGljZSAoYSwgaSkge1xuICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYSwgaSk7XG59XG5cbnZhciB1dGlsX3VuaXF1ZSA9IE9iamVjdC5mcmVlemUoe2VxdWFsczogZnVuY3Rpb24gKCkgeyByZXR1cm4gZmFsc2U7IH19KTtcblxuZnVuY3Rpb24gdXRpbF9zb21lICh4KSB7XG4gIHJldHVybiAoeCAhPT0gbnVsbCkgJiYgKHggIT09IHZvaWQgMCk7XG59XG5cbnZhciB1dGlsX0RFQlVHX01PREUgPSBmYWxzZTtcbmZ1bmN0aW9uIHV0aWxfc2V0RGVidWdNb2RlKHZhbCkge1xuICB1dGlsX0RFQlVHX01PREUgPSAhIXZhbDtcbn1cblxuZnVuY3Rpb24gdXRpbF9zZXRFcXVhbHMoZGVyaXZhYmxlLCBlcXVhbHMpIHtcbiAgZGVyaXZhYmxlLl9lcXVhbHMgPSBlcXVhbHM7XG4gIHJldHVybiBkZXJpdmFibGU7XG59XG5cbi8vIG5vZGUgbW9kZXNcbnZhciBnY19ORVcgPSAwLFxuICAgIGdjX0NIQU5HRUQgPSAxLFxuICAgIGdjX1VOQ0hBTkdFRCA9IDIsXG4gICAgZ2NfT1JQSEFORUQgPSAzLFxuICAgIGdjX1VOU1RBQkxFID0gNCxcbiAgICBnY19TVEFCTEUgPSA1LFxuICAgIGdjX0RJU09XTkVEID0gNjtcblxuZnVuY3Rpb24gZ2NfbWFyayhub2RlLCByZWFjdG9ycykge1xuICAvLyBtYWtlIGV2ZXJ5dGhpbmcgdW5zdGFibGVcbiAgaWYgKG5vZGUuX3R5cGUgPT09IHR5cGVzX1JFQUNUSU9OKSB7XG4gICAgaWYgKG5vZGUucmVhY3RpbmcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkN5Y2xlIGRldGVjdGVkISBEb24ndCBkbyB0aGlzIVwiKTtcbiAgICB9XG4gICAgcmVhY3RvcnMucHVzaChub2RlKTtcbiAgfSBlbHNlIHtcbiAgICBmb3IgKHZhciBpID0gbm9kZS5fY2hpbGRyZW4ubGVuZ3RoOyBpLS07KSB7XG4gICAgICB2YXIgY2hpbGQgPSBub2RlLl9jaGlsZHJlbltpXTtcbiAgICAgIGlmIChjaGlsZC5fc3RhdGUgIT09IGdjX1VOU1RBQkxFKSB7XG4gICAgICAgIGNoaWxkLl9zdGF0ZSA9IGdjX1VOU1RBQkxFO1xuICAgICAgICBnY19tYXJrKGNoaWxkLCByZWFjdG9ycyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdjX3N3ZWVwKG5vZGUpIHtcbiAgdmFyIGk7XG4gIHN3aXRjaCAobm9kZS5fc3RhdGUpIHtcbiAgY2FzZSBnY19DSEFOR0VEOlxuICBjYXNlIGdjX1VOQ0hBTkdFRDpcbiAgICAvLyBjaGFuZ2VkIG9yIHVuY2hhbmdlZCBtZWFucyB0aGUgbm9kZSB3YXMgdmlzaXRlZFxuICAgIC8vIGR1cmluZyB0aGUgcmVhY3QgcGhhc2UsIHdoaWNoIG1lYW5zIHdlIGtlZXAgaXQgaW5cbiAgICAvLyB0aGUgZ3JhcGggZm9yIHRoZSBuZXh0IGdvIHJvdW5kXG4gICAgZm9yIChpID0gbm9kZS5fY2hpbGRyZW4ubGVuZ3RoOyBpLS07KSB7XG4gICAgICB2YXIgY2hpbGQgPSBub2RlLl9jaGlsZHJlbltpXTtcbiAgICAgIGdjX3N3ZWVwKGNoaWxkKTtcbiAgICAgIGlmIChjaGlsZC5fc3RhdGUgIT09IGdjX1NUQUJMRSkge1xuICAgICAgICBub2RlLl9jaGlsZHJlbi5zcGxpY2UoaSwgMSk7XG4gICAgICB9XG4gICAgfVxuICAgIG5vZGUuX3N0YXRlID0gZ2NfU1RBQkxFO1xuICAgIGJyZWFrO1xuICBjYXNlIGdjX1VOU1RBQkxFOlxuICAgIGlmIChub2RlLl90eXBlID09PSB0eXBlc19SRUFDVElPTikge1xuICAgICAgLy8gb25seSBoYXBwZW5zIHdoZW4gcmVhY3Rpb24gY3JlYXRlZCBpbiB0cmFuc2FjdGlvbi4gc2VlIGlzc3VlICMxNFxuICAgICAgbm9kZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHVuc3RhYmxlIG1lYW5zIHRoZSBub2RlIHdhcyBub3QgdmlzaXRlZCBkdXJpbmdcbiAgICAgIC8vIHRoZSByZWFjdCBwaGFzZSwgd2hpY2ggbWVhbnMgd2Uga2ljayBpdCBvdXQgb2YgdGhlXG4gICAgICAvLyBncmFwaC5cblxuICAgICAgLy8gYnV0IGZpcnN0IHdlIGNoZWNrIGlmIGFsbCBvZiBpdHMgcGFyZW50cyB3ZXJlIHVuY2hhbmdlZFxuICAgICAgLy8gaWYgc28sIHdlIGNhbiBhdm9pZCByZWNhbGN1bGF0aW5nIGl0IGluIGZ1dHVyZSBieVxuICAgICAgLy8gY2FjaGluZyBpdHMgcGFyZW50cycgY3VycmVudCB2YWx1ZXMuXG4gICAgICB2YXIgc3Rhc2hlZFBhcmVudFN0YXRlcyA9IFtdO1xuICAgICAgZm9yIChpID0gbm9kZS5fcGFyZW50cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IG5vZGUuX3BhcmVudHNbaV07XG4gICAgICAgIGlmIChwYXJlbnQuX3N0YXRlICE9PSBnY19VTkNIQU5HRUQpIHtcbiAgICAgICAgICAvLyBub3BlLCBpdHMgcGFyZW50cyBlaXRoZXIgaGF2ZSBjaGFuZ2VkIG9yIHdlcmVuJ3QgdmlzaXRlZCxcbiAgICAgICAgICAvLyBzbyB3ZSBoYXZlIHRvIG9ycGhhbiB0aGlzIG5vZGVcbiAgICAgICAgICBub2RlLl9zdGF0ZSA9IGdjX09SUEhBTkVEO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHN0YXNoZWRQYXJlbnRTdGF0ZXMucHVzaChbcGFyZW50LCBwYXJlbnQuX3ZhbHVlXSk7XG4gICAgICB9XG4gICAgICBpZiAobm9kZS5fc3RhdGUgIT09IGdjX09SUEhBTkVEKSB7XG4gICAgICAgIG5vZGUuX3N0YXRlID0gZ2NfRElTT1dORUQ7XG4gICAgICAgIG5vZGUuX3BhcmVudHMgPSBzdGFzaGVkUGFyZW50U3RhdGVzO1xuICAgICAgfVxuICAgIH1cbiAgICBicmVhaztcbiAgY2FzZSBnY19TVEFCTEU6XG4gIGNhc2UgZ2NfT1JQSEFORUQ6XG4gIGNhc2UgZ2NfRElTT1dORUQ6XG4gICAgYnJlYWs7XG4gIGRlZmF1bHQ6XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY2FuJ3Qgc3dlZXAgc3RhdGUgXCIgKyBub2RlLl9zdGF0ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2NfYWJvcnRfc3dlZXAobm9kZSkge1xuICAvLyBzZXQgZXZlcnl0aGluZyB0byB1bnN0YWJsZSwga2lsbCBhbGwgZGVyaXZhdGlvbiBjYWNoZXMgYW5kIGRpc2Nvbm5lY3RcbiAgLy8gdGhlIGdyYXBoXG4gIHZhciBkb0NoaWxkcmVuID0gZmFsc2U7XG4gIHN3aXRjaCAobm9kZS5fdHlwZSkge1xuICBjYXNlIHR5cGVzX0FUT006XG4gICAgbm9kZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgZG9DaGlsZHJlbiA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgdHlwZXNfREVSSVZBVElPTjpcbiAgY2FzZSB0eXBlc19MRU5TOlxuICAgIG5vZGUuX3N0YXRlID0gZ2NfTkVXO1xuICAgIG5vZGUuX3ZhbHVlID0gdXRpbF91bmlxdWU7XG4gICAgZG9DaGlsZHJlbiA9IHRydWU7XG4gICAgYnJlYWs7XG4gIGNhc2UgdHlwZXNfUkVBQ1RJT046XG4gICAgbm9kZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgZG9DaGlsZHJlbiA9IGZhbHNlO1xuICAgIGJyZWFrO1xuICB9XG4gIGlmIChkb0NoaWxkcmVuKSB7XG4gICAgZm9yICh2YXIgaSA9IG5vZGUuX2NoaWxkcmVuLmxlbmd0aDsgaS0tOykge1xuICAgICAgZ2NfYWJvcnRfc3dlZXAobm9kZS5fY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgICBub2RlLl9jaGlsZHJlbiA9IFtdO1xuICB9XG59XG5cbnZhciBwYXJlbnRzU3RhY2sgPSBbXTtcblxuZnVuY3Rpb24gcGFyZW50c19jYXB0dXJpbmdQYXJlbnRzKGYpIHtcbiAgdmFyIGkgPSBwYXJlbnRzU3RhY2subGVuZ3RoO1xuICBwYXJlbnRzU3RhY2sucHVzaChbXSk7XG4gIHRyeSB7XG4gICAgZigpO1xuICAgIHJldHVybiBwYXJlbnRzU3RhY2tbaV07XG4gIH0gZmluYWxseSB7XG4gICAgcGFyZW50c1N0YWNrLnBvcCgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcmVudHNfbWF5YmVDYXB0dXJlUGFyZW50KHApIHtcbiAgaWYgKHBhcmVudHNTdGFjay5sZW5ndGggPiAwKSB7XG4gICAgdXRpbF9hZGRUb0FycmF5KHBhcmVudHNTdGFja1twYXJlbnRzU3RhY2subGVuZ3RoIC0gMV0sIHApO1xuICB9XG59XG5cbnZhciB0eXBlc19BVE9NID0gXCJBVE9NXCIsXG4gICAgdHlwZXNfREVSSVZBVElPTiA9IFwiREVSSVZBVElPTlwiLFxuICAgIHR5cGVzX0xFTlMgPSBcIkxFTlNcIixcbiAgICB0eXBlc19SRUFDVElPTiA9IFwiUkVBQ1RJT05cIjtcblxudmFyIFJVTk5JTkcgPSAwLFxuICAgIENPTVBMRVRFRCA9IDEsXG4gICAgQUJPUlRFRCA9IDM7XG5cbnZhciBUcmFuc2FjdGlvbkFib3J0aW9uID0ge307XG5cbmZ1bmN0aW9uIGFib3J0VHJhbnNhY3Rpb24oKSB7XG4gIHRocm93IFRyYW5zYWN0aW9uQWJvcnRpb247XG59XG5cbmZ1bmN0aW9uIHRyYW5zYWN0aW9uc19uZXdDb250ZXh0ICgpIHtcbiAgcmV0dXJuIHtjdXJyZW50VHhuOiBudWxsfTtcbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25zX2luVHJhbnNhY3Rpb24gKGN0eCkge1xuICByZXR1cm4gY3R4LmN1cnJlbnRUeG4gIT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIHRyYW5zYWN0aW9uc19jdXJyZW50VHJhbnNhY3Rpb24gKGN0eCkge1xuICByZXR1cm4gY3R4LmN1cnJlbnRUeG47XG59XG5cbmZ1bmN0aW9uIGJlZ2luIChjdHgsIHR4bikge1xuICB0eG4uX3BhcmVudCA9IGN0eC5jdXJyZW50VHhuO1xuICB0eG4uX3N0YXRlID0gUlVOTklORztcbiAgY3R4LmN1cnJlbnRUeG4gPSB0eG47XG59XG5cbmZ1bmN0aW9uIHBvcFRyYW5zYWN0aW9uIChjdHgsIGNiKSB7XG4gIHZhciB0eG4gPSBjdHguY3VycmVudFR4bjtcbiAgY3R4LmN1cnJlbnRUeG4gPSB0eG4uX3BhcmVudDtcbiAgaWYgKHR4bi5fc3RhdGUgIT09IFJVTk5JTkcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1bmV4cGVjdGVkIHN0YXRlOiBcIiArIHR4bi5fc3RhdGUpO1xuICB9XG4gIGNiKHR4bik7XG59XG5cbmZ1bmN0aW9uIGNvbW1pdCAoY3R4KSB7XG4gIHBvcFRyYW5zYWN0aW9uKGN0eCwgZnVuY3Rpb24gKHR4bikge1xuICAgIHR4bi5fc3RhdGUgPSBDT01QTEVURUQ7XG4gICAgdHhuLm9uQ29tbWl0ICYmIHR4bi5vbkNvbW1pdCgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gYWJvcnQgKGN0eCkge1xuICBwb3BUcmFuc2FjdGlvbihjdHgsIGZ1bmN0aW9uICh0eG4pIHtcbiAgICB0eG4uX3N0YXRlID0gQUJPUlRFRDtcbiAgICB0eG4ub25BYm9ydCAmJiB0eG4ub25BYm9ydCgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25zX3RyYW5zYWN0IChjdHgsIHR4biwgZikge1xuICBiZWdpbihjdHgsIHR4bik7XG4gIHRyeSB7XG4gICAgZihhYm9ydFRyYW5zYWN0aW9uKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGFib3J0KGN0eCk7XG4gICAgaWYgKGUgIT09IFRyYW5zYWN0aW9uQWJvcnRpb24pIHtcbiAgICAgIHRocm93IGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cbiAgY29tbWl0KGN0eCk7XG59XG5cbmZ1bmN0aW9uIHRyYW5zYWN0aW9uc190aWNrZXIgKGN0eCwgdHhuQ29uc3RydWN0b3IpIHtcbiAgYmVnaW4oY3R4LCB0eG5Db25zdHJ1Y3RvcigpKTtcbiAgdmFyIGRpc3Bvc2VkID0gZmFsc2U7XG4gIHJldHVybiB7XG4gICAgdGljazogZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGRpc3Bvc2VkKSB0aHJvdyBuZXcgRXJyb3IoXCJjYW4ndCB0aWNrIGRpc3Bvc2VkIHRpY2tlclwiKTtcbiAgICAgIGNvbW1pdChjdHgpO1xuICAgICAgYmVnaW4oY3R4LCB0eG5Db25zdHJ1Y3RvcigpKTtcbiAgICB9LFxuICAgIHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChkaXNwb3NlZCkgdGhyb3cgbmV3IEVycm9yKFwidGlja2VyIGFscmVhZHkgZGlzcG9zZWRcIik7XG4gICAgICBjb21taXQoY3R4KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVhY3RvckJhc2UgKHBhcmVudCwgY29udHJvbCkge1xuICB2YXIgYmFzZSA9IHtcbiAgICBjb250cm9sOiBjb250cm9sLCAgICAgIC8vIHRoZSBhY3R1YWwgb2JqZWN0IHRoZSB1c2VyIGdldHNcbiAgICBwYXJlbnQ6IHBhcmVudCwgICAgICAgIC8vIHRoZSBwYXJlbnQgZGVyaXZhYmxlXG4gICAgcGFyZW50UmVhY3RvcjogbnVsbCxcbiAgICBkZXBlbmRlbnRSZWFjdG9yczogW10sXG4gICAgX3N0YXRlOiBnY19TVEFCTEUsXG4gICAgYWN0aXZlOiBmYWxzZSwgICAgICAgICAvLyB3aGV0aGVyIG9yIG5vdCBsaXN0ZW5pbmcgZm9yIGNoYW5nZXMgaW4gcGFyZW50XG4gICAgX3R5cGU6IHR5cGVzX1JFQUNUSU9OLFxuICAgIHVpZDogdXRpbF9uZXh0SWQoKSxcbiAgICByZWFjdGluZzogZmFsc2UsICAgICAgIC8vIHdoZXRoZXIgb3Igbm90IHJlYWN0aW9uIGZ1bmN0aW9uIGJlaW5nIGludm9rZWRcbiAgICB5aWVsZGluZzogZmFsc2UsICAgICAgIC8vIHdoZXRoZXIgb3Igbm90IGxldHRpbmcgcGFyZW50UmVhY3RvciByZWFjdCBmaXJzdFxuICB9O1xuICBpZiAodXRpbF9ERUJVR19NT0RFKSB7XG4gICAgYmFzZS5zdGFjayA9IEVycm9yKCkuc3RhY2s7XG4gIH1cbiAgcmV0dXJuIGJhc2U7XG59XG52YXIgY3ljbGVNc2cgPSBcIkN5Y2xpY2FsIFJlYWN0b3IgRGVwZW5kZW5jeSEgTm90IGFsbG93ZWQhXCI7XG5cbmZ1bmN0aW9uIHN0b3AgKGJhc2UpIHtcbiAgaWYgKGJhc2UuYWN0aXZlKSB7XG4gICAgdXRpbF9yZW1vdmVGcm9tQXJyYXkoYmFzZS5wYXJlbnQuX2NoaWxkcmVuLCBiYXNlKTtcbiAgICBpZiAoYmFzZS5wYXJlbnRSZWFjdG9yKSB7XG4gICAgICBvcnBoYW4oYmFzZSk7XG4gICAgfVxuICAgIGJhc2UuYWN0aXZlID0gZmFsc2U7XG4gICAgYmFzZS5jb250cm9sLm9uU3RvcCAmJiBiYXNlLmNvbnRyb2wub25TdG9wKCk7XG4gIH1cbn1cblxudmFyIHBhcmVudFJlYWN0b3JTdGFjayA9IFtdO1xuXG5mdW5jdGlvbiBzdGFydCAoYmFzZSkge1xuICBpZiAoIWJhc2UuYWN0aXZlKSB7XG4gICAgdXRpbF9hZGRUb0FycmF5KGJhc2UucGFyZW50Ll9jaGlsZHJlbiwgYmFzZSk7XG4gICAgYmFzZS5hY3RpdmUgPSB0cnVlO1xuICAgIGJhc2UucGFyZW50Ll9nZXQoKTtcbiAgICAvLyBjYXB0dXJlIHJlYWN0b3IgZGVwZW5kZW5jeSByZWxhdGlvbnNoaXBzXG4gICAgdmFyIGxlbiA9IHBhcmVudFJlYWN0b3JTdGFjay5sZW5ndGg7XG4gICAgaWYgKGxlbiA+IDApIHtcbiAgICAgIGJhc2UucGFyZW50UmVhY3RvciA9IHBhcmVudFJlYWN0b3JTdGFja1tsZW4gLSAxXTtcbiAgICB9XG5cbiAgICBiYXNlLmNvbnRyb2wub25TdGFydCAmJiBiYXNlLmNvbnRyb2wub25TdGFydCgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG9ycGhhbiAoYmFzZSkge1xuICBpZiAoYmFzZS5wYXJlbnRSZWFjdG9yKSB7XG4gICAgYmFzZS5wYXJlbnRSZWFjdG9yID0gbnVsbDtcbiAgfVxufVxuXG5mdW5jdGlvbiBhZG9wdCAocGFyZW50QmFzZSwgY2hpbGRCYXNlKSB7XG4gIGNoaWxkQmFzZS5wYXJlbnRSZWFjdG9yID0gcGFyZW50QmFzZTtcbn1cblxuZnVuY3Rpb24gcmVhY3RvcnNfbWF5YmVSZWFjdCAoYmFzZSkge1xuICBpZiAoYmFzZS55aWVsZGluZykge1xuICAgIHRocm93IEVycm9yKGN5Y2xlTXNnKTtcbiAgfVxuICBpZiAoYmFzZS5hY3RpdmUgJiYgYmFzZS5fc3RhdGUgPT09IGdjX1VOU1RBQkxFKSB7XG4gICAgaWYgKGJhc2UucGFyZW50UmVhY3RvciAhPT0gbnVsbCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYmFzZS55aWVsZGluZyA9IHRydWU7XG4gICAgICAgIHJlYWN0b3JzX21heWJlUmVhY3QoYmFzZS5wYXJlbnRSZWFjdG9yKTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGJhc2UueWllbGRpbmcgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gcGFyZW50IG1pZ2h0IGhhdmUgZGVhY3RpdmF0ZWQgdGhpcyBvbmVcbiAgICBpZiAoYmFzZS5hY3RpdmUpIHtcbiAgICAgIHZhciBwYXJlbnQgPSBiYXNlLnBhcmVudCwgcGFyZW50U3RhdGUgPSBwYXJlbnQuX3N0YXRlO1xuICAgICAgaWYgKHBhcmVudFN0YXRlID09PSBnY19VTlNUQUJMRSB8fFxuICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19PUlBIQU5FRCB8fFxuICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19ESVNPV05FRCB8fFxuICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19ORVcpIHtcbiAgICAgICAgcGFyZW50Ll9nZXQoKTtcbiAgICAgIH1cbiAgICAgIHBhcmVudFN0YXRlID0gcGFyZW50Ll9zdGF0ZTtcblxuICAgICAgaWYgKHBhcmVudFN0YXRlID09PSBnY19VTkNIQU5HRUQpIHtcbiAgICAgICAgYmFzZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgICB9IGVsc2UgaWYgKHBhcmVudFN0YXRlID09PSBnY19DSEFOR0VEKSB7XG4gICAgICAgIGZvcmNlKGJhc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBhcmVudCBzdGF0ZTogXCIgKyBwYXJlbnRTdGF0ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZvcmNlIChiYXNlKSB7XG4gIC8vIGJhc2UucmVhY3RpbmcgY2hlY2sgbm93IGluIGdjX21hcms7IHRvdGFsIHNvbHV0aW9uIHRoZXJlIGFzIG9wcG9zZWQgdG8gaGVyZVxuICBpZiAoYmFzZS5jb250cm9sLnJlYWN0KSB7XG4gICAgYmFzZS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gICAgdHJ5IHtcbiAgICAgIGJhc2UucmVhY3RpbmcgPSB0cnVlO1xuICAgICAgcGFyZW50UmVhY3RvclN0YWNrLnB1c2goYmFzZSk7XG4gICAgICBpZiAoIXV0aWxfREVCVUdfTU9ERSkge1xuICAgICAgICBiYXNlLmNvbnRyb2wucmVhY3QoYmFzZS5wYXJlbnQuX2dldCgpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYmFzZS5jb250cm9sLnJlYWN0KGJhc2UucGFyZW50Ll9nZXQoKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGJhc2Uuc3RhY2spO1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgcGFyZW50UmVhY3RvclN0YWNrLnBvcCgpO1xuICAgICAgYmFzZS5yZWFjdGluZyA9IGZhbHNlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIHJlYWN0b3IgZnVuY3Rpb24gYXZhaWxhYmxlLlwiKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZWFjdG9yc19SZWFjdG9yICgpIHtcbiAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cbiAgdGhpcy5fdHlwZSA9IHR5cGVzX1JFQUNUSU9OO1xufVxuXG5mdW5jdGlvbiByZWFjdG9yc19jcmVhdGVCYXNlIChjb250cm9sLCBwYXJlbnQpIHtcbiAgaWYgKGNvbnRyb2wuX2Jhc2UpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGlzIHJlYWN0b3IgaGFzIGFscmVhZHkgYmVlbiBpbml0aWFsaXplZFwiKTtcbiAgfVxuICBjb250cm9sLl9iYXNlID0gcmVhY3RvckJhc2UocGFyZW50LCBjb250cm9sKTtcbiAgcmV0dXJuIGNvbnRyb2w7XG59XG5cbnV0aWxfZXh0ZW5kKHJlYWN0b3JzX1JlYWN0b3IucHJvdG90eXBlLCB7XG4gIHN0YXJ0OiBmdW5jdGlvbiAoKSB7XG4gICAgc3RhcnQodGhpcy5fYmFzZSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHN0b3A6IGZ1bmN0aW9uICgpIHtcbiAgICBzdG9wKHRoaXMuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBmb3JjZTogZnVuY3Rpb24gKCkge1xuICAgIGZvcmNlKHRoaXMuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBpc0FjdGl2ZTogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9iYXNlLmFjdGl2ZTtcbiAgfSxcbiAgb3JwaGFuOiBmdW5jdGlvbiAoKSB7XG4gICAgb3JwaGFuKHRoaXMuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBhZG9wdDogZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgaWYgKGNoaWxkLl90eXBlICE9PSB0eXBlc19SRUFDVElPTikge1xuICAgICAgdGhyb3cgRXJyb3IoXCJyZWFjdG9ycyBjYW4gb25seSBhZG9wdCByZWFjdG9yc1wiKTtcbiAgICB9XG4gICAgYWRvcHQodGhpcy5fYmFzZSwgY2hpbGQuX2Jhc2UpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG59KTtcblxuZnVuY3Rpb24gcmVhY3RvcnNfU3RhbmRhcmRSZWFjdG9yIChmKSB7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIHRoaXMuX3R5cGUgPSB0eXBlc19SRUFDVElPTjtcbiAgdGhpcy5yZWFjdCA9IGY7XG59XG5cbnV0aWxfZXh0ZW5kKHJlYWN0b3JzX1N0YW5kYXJkUmVhY3Rvci5wcm90b3R5cGUsIHJlYWN0b3JzX1JlYWN0b3IucHJvdG90eXBlKTtcblxuZnVuY3Rpb24gcmVhY3RvcnNfYW5vbnltb3VzUmVhY3RvciAoZGVzY3JpcHRvcikge1xuICByZXR1cm4gdXRpbF9leHRlbmQobmV3IHJlYWN0b3JzX1JlYWN0b3IoKSwgZGVzY3JpcHRvcik7XG59XG5cbmZ1bmN0aW9uIGRlcml2YWJsZV9jcmVhdGVQcm90b3R5cGUgKEQsIG9wdHMpIHtcbiAgdmFyIHggPSB7XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlcml2ZWQgdmFsdWUgd2hvc2Ugc3RhdGUgd2lsbCBhbHdheXMgYmUgZiBhcHBsaWVkIHRvIHRoaXNcbiAgICAgKiB2YWx1ZVxuICAgICAqL1xuICAgIGRlcml2ZTogZnVuY3Rpb24gKGYsIGEsIGIsIGMsIGQpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhhdDtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgc3dpdGNoICh0eXBlb2YgZikge1xuICAgICAgICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgICAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gdGhhdC5nZXQoKVtELnVucGFjayhmKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgaWYgKGYgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgICByZXR1cm4gZi5tYXAoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5kZXJpdmUoeCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmdldCgpLm1hdGNoKGYpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoRC5pc0Rlcml2YWJsZShmKSkge1xuICAgICAgICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVyaXZlciA9IGYuZ2V0KCk7XG4gICAgICAgICAgICAgICAgdmFyIHRoaW5nID0gdGhhdC5nZXQoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGVvZiBkZXJpdmVyKSB7XG4gICAgICAgICAgICAgICAgICBjYXNlICdmdW5jdGlvbic6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkZXJpdmVyKHRoaW5nKTtcbiAgICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgICAgICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpbmdbZGVyaXZlcl07XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoZGVyaXZlciBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGluZy5tYXRjaChkZXJpdmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcigndHlwZSBlcnJvcicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmdldCgpW0QudW5wYWNrKGYpXTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBFcnJvcigndHlwZSBlcnJvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpLCBELnVucGFjayhhKSk7XG4gICAgICAgIH0pO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpLCBELnVucGFjayhhKSwgRC51bnBhY2soYikpO1xuICAgICAgICB9KTtcbiAgICAgIGNhc2UgNDpcbiAgICAgICAgcmV0dXJuIEQuZGVyaXZhdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIGYodGhhdC5nZXQoKSxcbiAgICAgICAgICAgICAgICAgICBELnVucGFjayhhKSxcbiAgICAgICAgICAgICAgICAgICBELnVucGFjayhiKSxcbiAgICAgICAgICAgICAgICAgICBELnVucGFjayhjKSk7XG4gICAgICAgIH0pO1xuICAgICAgY2FzZSA1OlxuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZih0aGF0LmdldCgpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGEpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGIpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGMpLFxuICAgICAgICAgICAgICAgICAgIEQudW5wYWNrKGQpKTtcbiAgICAgICAgfSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB2YXIgYXJncyA9IChbdGhhdF0pLmNvbmNhdCh1dGlsX3NsaWNlKGFyZ3VtZW50cywgMSkpO1xuICAgICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gZi5hcHBseShudWxsLCBhcmdzLm1hcChELnVucGFjaykpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG5cblxuICAgIHJlYWN0b3I6IGZ1bmN0aW9uIChmKSB7XG4gICAgICBpZiAodHlwZW9mIGYgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHJlYWN0b3JzX2NyZWF0ZUJhc2UobmV3IHJlYWN0b3JzX1N0YW5kYXJkUmVhY3RvcihmKSwgdGhpcyk7XG4gICAgICB9IGVsc2UgaWYgKGYgaW5zdGFuY2VvZiByZWFjdG9yc19SZWFjdG9yKSB7XG4gICAgICAgIHJldHVybiByZWFjdG9yc19jcmVhdGVCYXNlKGYsIHRoaXMpO1xuICAgICAgfSBlbHNlIGlmIChmICYmIGYucmVhY3QpIHtcbiAgICAgICAgcmV0dXJuIHJlYWN0b3JzX2NyZWF0ZUJhc2UocmVhY3RvcnNfYW5vbnltb3VzUmVhY3RvcihmKSwgdGhpcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbnJlY29nbml6ZWQgdHlwZSBmb3IgcmVhY3RvciBcIiArIGYpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICByZWFjdDogZnVuY3Rpb24gKGYsIG9wdHMpIHtcbiAgICAgIGlmICh0eXBlb2YgZiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBFcnJvcigndGhlIGZpcnN0IGFyZ3VtZW50IHRvIC5yZWFjdCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgIH1cblxuICAgICAgb3B0cyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBvbmNlOiBmYWxzZSxcbiAgICAgICAgZnJvbTogdHJ1ZSxcbiAgICAgICAgdW50aWw6IGZhbHNlLFxuICAgICAgICB3aGVuOiB0cnVlLFxuICAgICAgICBza2lwRmlyc3Q6IGZhbHNlLFxuICAgICAgfSwgb3B0cyk7XG5cbiAgICAgIC8vIGNvZXJjZSBmbiBvciBib29sIHRvIGRlcml2YWJsZTxib29sPlxuICAgICAgZnVuY3Rpb24gY29uZERlcml2YWJsZShmT3JELCBuYW1lKSB7XG4gICAgICAgIGlmICghRC5pc0Rlcml2YWJsZShmT3JEKSkge1xuICAgICAgICAgIGlmICh0eXBlb2YgZk9yRCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgZk9yRCA9IEQuZGVyaXZhdGlvbihmT3JEKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmT3JEID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIGZPckQgPSBELmF0b20oZk9yRCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdyZWFjdCAnICsgbmFtZSArICcgY29uZGl0aW9uIG11c3QgYmUgZGVyaXZhYmxlJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmT3JELmRlcml2ZShmdW5jdGlvbiAoeCkgeyByZXR1cm4gISF4OyB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gd3JhcCByZWFjdG9yIHNvIGYgZG9lc24ndCBnZXQgYSAudGhpcyBjb250ZXh0LCBhbmQgdG8gYWxsb3dcbiAgICAgIC8vIHN0b3BwaW5nIGFmdGVyIG9uZSByZWFjdGlvbiBpZiBkZXNpcmVkLlxuICAgICAgdmFyIHJlYWN0b3IgPSB0aGlzLnJlYWN0b3Ioe1xuICAgICAgICByZWFjdDogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICAgIGlmIChvcHRzLnNraXBGaXJzdCkge1xuICAgICAgICAgICAgb3B0cy5za2lwRmlyc3QgPSBmYWxzZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZih2YWwpO1xuICAgICAgICAgICAgaWYgKG9wdHMub25jZSkge1xuICAgICAgICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgICAgICAgY29udHJvbGxlci5zdG9wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBvblN0YXJ0OiBvcHRzLm9uU3RhcnQsXG4gICAgICAgIG9uU3RvcDogb3B0cy5vblN0b3BcbiAgICAgIH0pO1xuXG4gICAgICAvLyBsaXN0ZW4gdG8gd2hlbiBhbmQgdW50aWwgY29uZGl0aW9ucywgc3RhcnRpbmcgYW5kIHN0b3BwaW5nIHRoZVxuICAgICAgLy8gcmVhY3RvciBhcyBhcHByb3ByaWF0ZSwgYW5kIHN0b3BwaW5nIHRoaXMgY29udHJvbGxlciB3aGVuIHVudGlsXG4gICAgICAvLyBjb25kaXRpb24gYmVjb21lcyB0cnVlXG4gICAgICB2YXIgY29udHJvbGxlciA9IEQuc3RydWN0KHtcbiAgICAgICAgdW50aWw6IGNvbmREZXJpdmFibGUob3B0cy51bnRpbCwgJ3VudGlsJyksXG4gICAgICAgIHdoZW46IGNvbmREZXJpdmFibGUob3B0cy53aGVuLCAnd2hlbicpXG4gICAgICB9KS5yZWFjdG9yKGZ1bmN0aW9uIChjb25kcykge1xuICAgICAgICBpZiAoY29uZHMudW50aWwpIHtcbiAgICAgICAgICByZWFjdG9yLnN0b3AoKTtcbiAgICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb25kcy53aGVuKSB7XG4gICAgICAgICAgaWYgKCFyZWFjdG9yLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgICAgIHJlYWN0b3Iuc3RhcnQoKS5mb3JjZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChyZWFjdG9yLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgICByZWFjdG9yLnN0b3AoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIGxpc3RlbiB0byBmcm9tIGNvbmRpdGlvbiwgc3RhcnRpbmcgdGhlIHJlYWN0b3IgY29udHJvbGxlclxuICAgICAgLy8gd2hlbiBhcHByb3ByaWF0ZVxuICAgICAgY29uZERlcml2YWJsZShvcHRzLmZyb20sICdmcm9tJykucmVhY3RvcihmdW5jdGlvbiAoZnJvbSkge1xuICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgIGNvbnRyb2xsZXIuc3RhcnQoKS5mb3JjZSgpO1xuICAgICAgICAgIHRoaXMuc3RvcCgpO1xuICAgICAgICB9XG4gICAgICB9KS5zdGFydCgpLmZvcmNlKCk7XG4gICAgfSxcblxuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcGFyZW50c19tYXliZUNhcHR1cmVQYXJlbnQodGhpcyk7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0KCk7IC8vIGFic3RyYWN0IHByb3RlY3RlZCBtZXRob2QsIGluIEphdmEgcGFybGFuY2VcbiAgICB9LFxuXG4gICAgaXM6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIEQubGlmdChvcHRzLmVxdWFscykodGhpcywgb3RoZXIpO1xuICAgIH0sXG5cbiAgICBhbmQ6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIHRoaXMuZGVyaXZlKGZ1bmN0aW9uICh4KSB7cmV0dXJuIHggJiYgRC51bnBhY2sob3RoZXIpO30pO1xuICAgIH0sXG5cbiAgICBvcjogZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXJpdmUoZnVuY3Rpb24gKHgpIHtyZXR1cm4geCB8fCBELnVucGFjayhvdGhlcik7fSk7XG4gICAgfSxcblxuICAgIHRoZW46IGZ1bmN0aW9uICh0aGVuQ2xhdXNlLCBlbHNlQ2xhdXNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXJpdmUoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgcmV0dXJuIEQudW5wYWNrKHggPyB0aGVuQ2xhdXNlIDogZWxzZUNsYXVzZSk7XG4gICAgICB9KTtcbiAgICB9LFxuXG4gICAgbVRoZW46IGZ1bmN0aW9uICh0aGVuQ2xhdXNlLCBlbHNlQ2xhdXNlKSB7XG4gICAgICByZXR1cm4gdGhpcy5kZXJpdmUoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgcmV0dXJuIEQudW5wYWNrKHV0aWxfc29tZSh4KSA/IHRoZW5DbGF1c2UgOiBlbHNlQ2xhdXNlKTtcbiAgICAgIH0pO1xuICAgIH0sXG5cbiAgICBtT3I6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIHRoaXMubVRoZW4odGhpcywgb3RoZXIpO1xuICAgIH0sXG5cbiAgICBtRGVyaXZlOiBmdW5jdGlvbiAoYXJnKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSAmJiBhcmcgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgIHJldHVybiBhcmcubWFwKGZ1bmN0aW9uIChhKSB7IHJldHVybiB0aGF0Lm1EZXJpdmUoYSk7IH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubVRoZW4odGhpcy5kZXJpdmUuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIG1BbmQ6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgcmV0dXJuIHRoaXMubVRoZW4ob3RoZXIsIHRoaXMpO1xuICAgIH0sXG5cbiAgICBub3Q6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLmRlcml2ZShmdW5jdGlvbiAoeCkgeyByZXR1cm4gIXg7IH0pO1xuICAgIH0sXG5cbiAgICB3aXRoRXF1YWxpdHk6IGZ1bmN0aW9uIChlcXVhbHMpIHtcbiAgICAgIGlmIChlcXVhbHMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlcXVhbHMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2VxdWFscyBtdXN0IGJlIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVxdWFscyA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB1dGlsX3NldEVxdWFscyh0aGlzLl9jbG9uZSgpLCBlcXVhbHMpO1xuICAgIH0sXG4gIH07XG5cbiAgeC5zd2l0Y2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgcmV0dXJuIHRoaXMuZGVyaXZlKGZ1bmN0aW9uICh4KSB7XG4gICAgICB2YXIgaTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBhcmdzLmxlbmd0aC0xOyBpKz0yKSB7XG4gICAgICAgIGlmIChvcHRzLmVxdWFscyh4LCBELnVucGFjayhhcmdzW2ldKSkpIHtcbiAgICAgICAgICByZXR1cm4gRC51bnBhY2soYXJnc1tpKzFdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGkgPT09IGFyZ3MubGVuZ3RoIC0gMSkge1xuICAgICAgICByZXR1cm4gRC51bnBhY2soYXJnc1tpXSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIHg7XG59XG5cbmZ1bmN0aW9uIGRlcml2YXRpb25fY3JlYXRlUHJvdG90eXBlIChELCBvcHRzKSB7XG4gIHJldHVybiB7XG4gICAgX2Nsb25lOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdXRpbF9zZXRFcXVhbHMoRC5kZXJpdmF0aW9uKHRoaXMuX2Rlcml2ZXIpLCB0aGlzLl9lcXVhbHMpO1xuICAgIH0sXG5cbiAgICBfZm9yY2VHZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcyxcbiAgICAgICAgICBpO1xuICAgICAgdmFyIG5ld1BhcmVudHMgPSBwYXJlbnRzX2NhcHR1cmluZ1BhcmVudHMoZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbmV3U3RhdGU7XG4gICAgICAgIGlmICghdXRpbF9ERUJVR19NT0RFKSB7XG4gICAgICAgICAgbmV3U3RhdGUgPSB0aGF0Ll9kZXJpdmVyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG5ld1N0YXRlID0gdGhhdC5fZGVyaXZlcigpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IodGhhdC5fc3RhY2spO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVxdWFscyA9IHRoYXQuX2VxdWFscyB8fCBvcHRzLmVxdWFscztcbiAgICAgICAgdGhhdC5fc3RhdGUgPSBlcXVhbHMobmV3U3RhdGUsIHRoYXQuX3ZhbHVlKSA/IGdjX1VOQ0hBTkdFRCA6IGdjX0NIQU5HRUQ7XG4gICAgICAgIHRoYXQuX3ZhbHVlID0gbmV3U3RhdGU7XG4gICAgICB9KTtcblxuICAgICAgLy8gb3JnYW5pc2UgcGFyZW50c1xuICAgICAgZm9yIChpID0gdGhpcy5fcGFyZW50cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgdmFyIHBvc3NpYmx5Rm9ybWVyUGFyZW50ID0gdGhpcy5fcGFyZW50c1tpXTtcbiAgICAgICAgaWYgKCF1dGlsX2FycmF5Q29udGFpbnMobmV3UGFyZW50cywgcG9zc2libHlGb3JtZXJQYXJlbnQpKSB7XG4gICAgICAgICAgdXRpbF9yZW1vdmVGcm9tQXJyYXkocG9zc2libHlGb3JtZXJQYXJlbnQuX2NoaWxkcmVuLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLl9wYXJlbnRzID0gbmV3UGFyZW50cztcblxuICAgICAgLy8gYWRkIHRoaXMgYXMgY2hpbGQgdG8gbmV3IHBhcmVudHNcbiAgICAgIGZvciAoaSA9IG5ld1BhcmVudHMubGVuZ3RoOyBpLS07KSB7XG4gICAgICAgIHV0aWxfYWRkVG9BcnJheShuZXdQYXJlbnRzW2ldLl9jaGlsZHJlbiwgdGhpcyk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIF9nZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBpLCBwYXJlbnQ7XG4gICAgICBvdXRlcjogc3dpdGNoICh0aGlzLl9zdGF0ZSkge1xuICAgICAgY2FzZSBnY19ORVc6XG4gICAgICBjYXNlIGdjX09SUEhBTkVEOlxuICAgICAgICB0aGlzLl9mb3JjZUdldCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgZ2NfVU5TVEFCTEU6XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLl9wYXJlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgcGFyZW50ID0gdGhpcy5fcGFyZW50c1tpXTtcbiAgICAgICAgICB2YXIgcGFyZW50U3RhdGUgPSBwYXJlbnQuX3N0YXRlO1xuICAgICAgICAgIGlmIChwYXJlbnRTdGF0ZSA9PT0gZ2NfVU5TVEFCTEUgfHxcbiAgICAgICAgICAgICAgcGFyZW50U3RhdGUgPT09IGdjX09SUEhBTkVEIHx8XG4gICAgICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19ESVNPV05FRCkge1xuICAgICAgICAgICAgcGFyZW50Ll9nZXQoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGFyZW50U3RhdGUgPSBwYXJlbnQuX3N0YXRlO1xuICAgICAgICAgIGlmIChwYXJlbnRTdGF0ZSA9PT0gZ2NfQ0hBTkdFRCkge1xuICAgICAgICAgICAgdGhpcy5fZm9yY2VHZXQoKTtcbiAgICAgICAgICAgIGJyZWFrIG91dGVyO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIShwYXJlbnRTdGF0ZSA9PT0gZ2NfU1RBQkxFIHx8XG4gICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFN0YXRlID09PSBnY19VTkNIQU5HRUQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIHBhcmVudCBtb2RlOiBcIiArIHBhcmVudFN0YXRlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3RhdGUgPSBnY19VTkNIQU5HRUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBnY19ESVNPV05FRDpcbiAgICAgICAgdmFyIHBhcmVudHMgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuX3BhcmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YXIgcGFyZW50U3RhdGVUdXBsZSA9IHRoaXMuX3BhcmVudHNbaV0sXG4gICAgICAgICAgICAgIHN0YXRlID0gcGFyZW50U3RhdGVUdXBsZVsxXTtcbiAgICAgICAgICBwYXJlbnQgPSBwYXJlbnRTdGF0ZVR1cGxlWzBdO1xuICAgICAgICAgIGlmICghb3B0cy5lcXVhbHMocGFyZW50Ll9nZXQoKSwgc3RhdGUpKSB7XG4gICAgICAgICAgICB0aGlzLl9wYXJlbnRzID0gW107XG4gICAgICAgICAgICB0aGlzLl9mb3JjZUdldCgpO1xuICAgICAgICAgICAgYnJlYWsgb3V0ZXI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhcmVudHMucHVzaChwYXJlbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSBwYXJlbnRzLmxlbmd0aDsgaS0tOykge1xuICAgICAgICAgIHV0aWxfYWRkVG9BcnJheShwYXJlbnRzW2ldLl9jaGlsZHJlbiwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcGFyZW50cyA9IHBhcmVudHM7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gZ2NfVU5DSEFOR0VEO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBkZXJpdmF0aW9uX2NvbnN0cnVjdChvYmosIGRlcml2ZXIpIHtcbiAgb2JqLl9jaGlsZHJlbiA9IFtdO1xuICBvYmouX3BhcmVudHMgPSBbXTtcbiAgb2JqLl9kZXJpdmVyID0gZGVyaXZlcjtcbiAgb2JqLl9zdGF0ZSA9IGdjX05FVztcbiAgb2JqLl90eXBlID0gdHlwZXNfREVSSVZBVElPTjtcbiAgb2JqLl92YWx1ZSA9IHV0aWxfdW5pcXVlO1xuICBvYmouX2VxdWFscyA9IG51bGw7XG5cbiAgaWYgKHV0aWxfREVCVUdfTU9ERSkge1xuICAgIG9iai5fc3RhY2sgPSBFcnJvcigpLnN0YWNrO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZnVuY3Rpb24gbXV0YWJsZV9jcmVhdGVQcm90b3R5cGUgKEQsIF8pIHtcbiAgcmV0dXJuIHtcbiAgICBzd2FwOiBmdW5jdGlvbiAoZikge1xuICAgICAgdmFyIGFyZ3MgPSB1dGlsX3NsaWNlKGFyZ3VtZW50cywgMCk7XG4gICAgICBhcmdzWzBdID0gdGhpcy5nZXQoKTtcbiAgICAgIHJldHVybiB0aGlzLnNldChmLmFwcGx5KG51bGwsIGFyZ3MpKTtcbiAgICB9LFxuICAgIGxlbnM6IGZ1bmN0aW9uIChtb25vTGVuc0Rlc2NyaXB0b3IpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgIHJldHVybiBELmxlbnMoe1xuICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gbW9ub0xlbnNEZXNjcmlwdG9yLmdldCh0aGF0LmdldCgpKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiBmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgICAgdGhhdC5zZXQobW9ub0xlbnNEZXNjcmlwdG9yLnNldCh0aGF0LmdldCgpLCB2YWwpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGxlbnNfY3JlYXRlUHJvdG90eXBlKEQsIF8pIHtcbiAgcmV0dXJuIHtcbiAgICBfY2xvbmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB1dGlsX3NldEVxdWFscyhELmxlbnModGhpcy5fbGVuc0Rlc2NyaXB0b3IpLCB0aGlzLl9lcXVhbHMpO1xuICAgIH0sXG5cbiAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgRC5hdG9taWNhbGx5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhhdC5fbGVuc0Rlc2NyaXB0b3Iuc2V0KHZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGxlbnNfY29uc3RydWN0KGRlcml2YXRpb24sIGRlc2NyaXB0b3IpIHtcbiAgZGVyaXZhdGlvbi5fbGVuc0Rlc2NyaXB0b3IgPSBkZXNjcmlwdG9yO1xuICBkZXJpdmF0aW9uLl90eXBlID0gdHlwZXNfTEVOUztcblxuICByZXR1cm4gZGVyaXZhdGlvbjtcbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1JlYWN0b3JRdWV1ZSAocnEpIHtcbiAgZm9yICh2YXIgaSA9IHJxLmxlbmd0aDsgaS0tOykge1xuICAgIHJlYWN0b3JzX21heWJlUmVhY3QocnFbaV0pO1xuICB9XG59XG5cbnZhciBUWE5fQ1RYID0gdHJhbnNhY3Rpb25zX25ld0NvbnRleHQoKTtcblxuZnVuY3Rpb24gYXRvbV9pblR4biAoKSB7XG4gIHJldHVybiB0cmFuc2FjdGlvbnNfaW5UcmFuc2FjdGlvbihUWE5fQ1RYKVxufVxuXG52YXIgTk9PUF9BUlJBWSA9IHtwdXNoOiBmdW5jdGlvbiAoKSB7fX07XG5cbmZ1bmN0aW9uIFRyYW5zYWN0aW9uU3RhdGUgKCkge1xuICB0aGlzLmluVHhuVmFsdWVzID0ge307XG4gIHRoaXMucmVhY3RvclF1ZXVlID0gW107XG59XG5cbmZ1bmN0aW9uIGdldFN0YXRlICh0eG5TdGF0ZSwgYXRvbSkge1xuICB2YXIgaW5UeG5WYWx1ZSA9IHR4blN0YXRlLmluVHhuVmFsdWVzW2F0b20uX3VpZF07XG4gIGlmIChpblR4blZhbHVlKSB7XG4gICAgcmV0dXJuIGluVHhuVmFsdWVbMV07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGF0b20uX3ZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHNldFN0YXRlICh0eG5TdGF0ZSwgYXRvbSwgc3RhdGUpIHtcbiAgdHhuU3RhdGUuaW5UeG5WYWx1ZXNbYXRvbS5fdWlkXSA9IFthdG9tLCBzdGF0ZV07XG4gIGdjX21hcmsoYXRvbSwgdHhuU3RhdGUucmVhY3RvclF1ZXVlKTtcbn1cblxudXRpbF9leHRlbmQoVHJhbnNhY3Rpb25TdGF0ZS5wcm90b3R5cGUsIHtcbiAgb25Db21taXQ6IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgaSwgYXRvbVZhbHVlVHVwbGU7XG4gICAgdmFyIGtleXMgPSB1dGlsX2tleXModGhpcy5pblR4blZhbHVlcyk7XG4gICAgaWYgKGF0b21faW5UeG4oKSkge1xuICAgICAgLy8gcHVzaCBpbi10eG4gdmFscyB1cCB0byBjdXJyZW50IHR4blxuICAgICAgZm9yIChpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgYXRvbVZhbHVlVHVwbGUgPSB0aGlzLmluVHhuVmFsdWVzW2tleXNbaV1dO1xuICAgICAgICBhdG9tVmFsdWVUdXBsZVswXS5zZXQoYXRvbVZhbHVlVHVwbGVbMV0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBjaGFuZ2Ugcm9vdCBzdGF0ZSBhbmQgcnVuIHJlYWN0b3JzLlxuICAgICAgZm9yIChpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgYXRvbVZhbHVlVHVwbGUgPSB0aGlzLmluVHhuVmFsdWVzW2tleXNbaV1dO1xuICAgICAgICBhdG9tVmFsdWVUdXBsZVswXS5fdmFsdWUgPSBhdG9tVmFsdWVUdXBsZVsxXTtcbiAgICAgICAgZ2NfbWFyayhhdG9tVmFsdWVUdXBsZVswXSwgTk9PUF9BUlJBWSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NSZWFjdG9yUXVldWUodGhpcy5yZWFjdG9yUXVldWUpO1xuXG4gICAgICAvLyB0aGVuIHN3ZWVwIGZvciBhIGNsZWFuIGZpbmlzaFxuICAgICAgZm9yIChpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgZ2Nfc3dlZXAodGhpcy5pblR4blZhbHVlc1trZXlzW2ldXVswXSk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIG9uQWJvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIWF0b21faW5UeG4oKSkge1xuICAgICAgdmFyIGtleXMgPSB1dGlsX2tleXModGhpcy5pblR4blZhbHVlcyk7XG4gICAgICBmb3IgKHZhciBpID0ga2V5cy5sZW5ndGg7IGktLTspIHtcbiAgICAgICAgZ2NfYWJvcnRfc3dlZXAodGhpcy5pblR4blZhbHVlc1trZXlzW2ldXVswXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59KVxuXG5cbmZ1bmN0aW9uIGF0b21fY3JlYXRlUHJvdG90eXBlIChELCBvcHRzKSB7XG4gIHJldHVybiB7XG4gICAgX2Nsb25lOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdXRpbF9zZXRFcXVhbHMoRC5hdG9tKHRoaXMuX3ZhbHVlKSwgdGhpcy5fZXF1YWxzKTtcbiAgICB9LFxuXG4gICAgd2l0aFZhbGlkYXRvcjogZnVuY3Rpb24gKGYpIHtcbiAgICAgIGlmIChmID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jbG9uZSgpO1xuICAgICAgfSBpZiAodHlwZW9mIGYgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXMuX2Nsb25lKCk7XG4gICAgICAgIHZhciBleGlzdGluZyA9IHRoaXMuX3ZhbGlkYXRvcjtcbiAgICAgICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICAgICAgcmVzdWx0Ll92YWxpZGF0b3IgPSBmdW5jdGlvbiAoeCkgeyByZXR1cm4gZih4KSAmJiBleGlzdGluZyh4KTsgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc3VsdC5fdmFsaWRhdG9yID0gZjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiLndpdGhWYWxpZGF0b3IgZXhwZWN0cyBmdW5jdGlvbiBvciBudWxsXCIpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICB2YWxpZGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgdGhpcy5fdmFsaWRhdGUodGhpcy5nZXQoKSk7XG4gICAgfSxcblxuICAgIF92YWxpZGF0ZTogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICB2YXIgdmFsaWRhdGlvblJlc3VsdCA9IHRoaXMuX3ZhbGlkYXRvciAmJiB0aGlzLl92YWxpZGF0b3IodmFsdWUpO1xuICAgICAgaWYgKHRoaXMuX3ZhbGlkYXRvciAmJiB2YWxpZGF0aW9uUmVzdWx0ICE9PSB0cnVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB2YWxpZGF0aW9uIHdpdGggdmFsdWU6ICdcIiArIHZhbHVlICsgXCInLlwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiIFZhbGlkYXRvciByZXR1cm5lZCAnXCIgKyB2YWxpZGF0aW9uUmVzdWx0ICsgXCInIFwiKTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcblxuICAgICAgdGhpcy5fdmFsaWRhdGUodmFsdWUpO1xuICAgICAgdmFyIGVxdWFscyA9IHRoaXMuX2VxdWFscyB8fCBvcHRzLmVxdWFscztcbiAgICAgIGlmICghZXF1YWxzKHZhbHVlLCB0aGlzLl92YWx1ZSkpIHtcbiAgICAgICAgdGhpcy5fc3RhdGUgPSBnY19DSEFOR0VEO1xuXG4gICAgICAgIGlmIChhdG9tX2luVHhuKCkpIHtcbiAgICAgICAgICBzZXRTdGF0ZSh0cmFuc2FjdGlvbnNfY3VycmVudFRyYW5zYWN0aW9uKFRYTl9DVFgpLCB0aGlzLCB2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICAgIHZhciByZWFjdG9yUXVldWUgPSBbXTtcbiAgICAgICAgICBnY19tYXJrKHRoaXMsIHJlYWN0b3JRdWV1ZSk7XG4gICAgICAgICAgcHJvY2Vzc1JlYWN0b3JRdWV1ZShyZWFjdG9yUXVldWUpO1xuICAgICAgICAgIGdjX3N3ZWVwKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgX2dldDogZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGF0b21faW5UeG4oKSkge1xuICAgICAgICByZXR1cm4gZ2V0U3RhdGUodHJhbnNhY3Rpb25zX2N1cnJlbnRUcmFuc2FjdGlvbihUWE5fQ1RYKSwgdGhpcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBhdG9tX2NvbnN0cnVjdCAoYXRvbSwgdmFsdWUpIHtcbiAgYXRvbS5fdWlkID0gdXRpbF9uZXh0SWQoKTtcbiAgYXRvbS5fY2hpbGRyZW4gPSBbXTtcbiAgYXRvbS5fc3RhdGUgPSBnY19TVEFCTEU7XG4gIGF0b20uX3ZhbHVlID0gdmFsdWU7XG4gIGF0b20uX3R5cGUgPSB0eXBlc19BVE9NO1xuICBhdG9tLl9lcXVhbHMgPSBudWxsO1xuICByZXR1cm4gYXRvbTtcbn1cblxuZnVuY3Rpb24gYXRvbV90cmFuc2FjdCAoZikge1xuICB0cmFuc2FjdGlvbnNfdHJhbnNhY3QoVFhOX0NUWCwgbmV3IFRyYW5zYWN0aW9uU3RhdGUoKSwgZik7XG59XG5cbmZ1bmN0aW9uIGF0b21fdHJhbnNhY3Rpb24gKGYpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYXJncyA9IHV0aWxfc2xpY2UoYXJndW1lbnRzLCAwKTtcbiAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgdmFyIHJlc3VsdDtcbiAgICBhdG9tX3RyYW5zYWN0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHJlc3VsdCA9IGYuYXBwbHkodGhhdCwgYXJncyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgdGlja2VyID0gbnVsbDtcblxuZnVuY3Rpb24gYXRvbV90aWNrZXIgKCkge1xuICBpZiAodGlja2VyKSB7XG4gICAgdGlja2VyLnJlZkNvdW50Kys7XG4gIH0gZWxzZSB7XG4gICAgdGlja2VyID0gdHJhbnNhY3Rpb25zX3RpY2tlcihUWE5fQ1RYLCBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uU3RhdGUoKTtcbiAgICB9KTtcbiAgICB0aWNrZXIucmVmQ291bnQgPSAxO1xuICB9XG4gIHZhciBkb25lID0gZmFsc2U7XG4gIHJldHVybiB7XG4gICAgdGljazogZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGRvbmUpIHRocm93IG5ldyBFcnJvcigndHlyaW5nIHRvIHVzZSB0aWNrZXIgYWZ0ZXIgcmVsZWFzZScpO1xuICAgICAgdGlja2VyLnRpY2soKTtcbiAgICB9LFxuICAgIHJlbGVhc2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChkb25lKSB0aHJvdyBuZXcgRXJyb3IoJ3RpY2tlciBhbHJlYWR5IHJlbGVhc2VkJyk7XG4gICAgICBpZiAoLS10aWNrZXIucmVmQ291bnQgPT09IDApIHtcbiAgICAgICAgdGlja2VyLnN0b3AoKTtcbiAgICAgICAgdGlja2VyID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIGRvbmUgPSB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxudmFyIGRlZmF1bHRDb25maWcgPSB7IGVxdWFsczogdXRpbF9lcXVhbHMgfTtcblxuZnVuY3Rpb24gY29uc3RydWN0TW9kdWxlIChjb25maWcpIHtcbiAgY29uZmlnID0gdXRpbF9leHRlbmQoe30sIGRlZmF1bHRDb25maWcsIGNvbmZpZyB8fCB7fSk7XG5cbiAgdmFyIEQgPSB7XG4gICAgdHJhbnNhY3Q6IGF0b21fdHJhbnNhY3QsXG4gICAgZGVmYXVsdEVxdWFsczogdXRpbF9lcXVhbHMsXG4gICAgc2V0RGVidWdNb2RlOiB1dGlsX3NldERlYnVnTW9kZSxcbiAgICB0cmFuc2FjdGlvbjogYXRvbV90cmFuc2FjdGlvbixcbiAgICB0aWNrZXI6IGF0b21fdGlja2VyLFxuICAgIFJlYWN0b3I6IHJlYWN0b3JzX1JlYWN0b3IsXG4gICAgaXNBdG9tOiBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIHggJiYgKHguX3R5cGUgPT09IHR5cGVzX0FUT00gfHwgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUyk7XG4gICAgfSxcbiAgICBpc0Rlcml2YWJsZTogZnVuY3Rpb24gKHgpIHtcbiAgICAgIHJldHVybiB4ICYmICh4Ll90eXBlID09PSB0eXBlc19BVE9NIHx8XG4gICAgICAgICAgICAgICAgICAgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUyB8fFxuICAgICAgICAgICAgICAgICAgIHguX3R5cGUgPT09IHR5cGVzX0RFUklWQVRJT04pO1xuICAgIH0sXG4gICAgaXNEZXJpdmF0aW9uOiBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIHggJiYgKHguX3R5cGUgPT09IHR5cGVzX0RFUklWQVRJT04gfHwgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUylcbiAgICB9LFxuICAgIGlzTGVuc2VkOiBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIHggJiYgeC5fdHlwZSA9PT0gdHlwZXNfTEVOUztcbiAgICB9LFxuICAgIGlzUmVhY3RvcjogZnVuY3Rpb24gKHgpIHtcbiAgICAgIHJldHVybiB4ICYmIHguX3R5cGUgPT09IHR5cGVzX1JFQUNUSU9OO1xuICAgIH0sXG4gIH07XG5cbiAgdmFyIERlcml2YWJsZSAgPSBkZXJpdmFibGVfY3JlYXRlUHJvdG90eXBlKEQsIGNvbmZpZyk7XG4gIHZhciBNdXRhYmxlICAgID0gbXV0YWJsZV9jcmVhdGVQcm90b3R5cGUoRCwgY29uZmlnKTtcblxuICB2YXIgQXRvbSAgICAgICA9IHV0aWxfZXh0ZW5kKHt9LCBNdXRhYmxlLCBEZXJpdmFibGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXRvbV9jcmVhdGVQcm90b3R5cGUoRCwgY29uZmlnKSk7XG5cbiAgdmFyIERlcml2YXRpb24gPSB1dGlsX2V4dGVuZCh7fSwgRGVyaXZhYmxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcml2YXRpb25fY3JlYXRlUHJvdG90eXBlKEQsIGNvbmZpZykpO1xuXG4gIHZhciBMZW5zICAgICAgID0gdXRpbF9leHRlbmQoe30sIE11dGFibGUsIERlcml2YXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5zX2NyZWF0ZVByb3RvdHlwZShELCBjb25maWcpKTtcblxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgbmV3IGF0b20gd2hvc2Ugc3RhdGUgaXMgdGhlIGdpdmVuIHZhbHVlXG4gICAqL1xuICBELmF0b20gPSBmdW5jdGlvbiAodmFsKSB7XG4gICAgcmV0dXJuIGF0b21fY29uc3RydWN0KE9iamVjdC5jcmVhdGUoQXRvbSksIHZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb3B5IG9mIGYgd2hpY2ggcnVucyBhdG9taWNhbGx5XG4gICAqL1xuICBELmF0b21pYyA9IGZ1bmN0aW9uIChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIEQuYXRvbWljYWxseShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc3VsdCA9IGYuYXBwbHkodGhhdCwgYXJncyk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9O1xuXG4gIEQuYXRvbWljYWxseSA9IGZ1bmN0aW9uIChmKSB7XG4gICAgaWYgKGF0b21faW5UeG4oKSkge1xuICAgICAgZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBELnRyYW5zYWN0KGYpO1xuICAgIH1cbiAgfTtcblxuICBELmRlcml2YXRpb24gPSBmdW5jdGlvbiAoZikge1xuICAgIHJldHVybiBkZXJpdmF0aW9uX2NvbnN0cnVjdChPYmplY3QuY3JlYXRlKERlcml2YXRpb24pLCBmKTtcbiAgfTtcblxuICAvKipcbiAgICogVGVtcGxhdGUgc3RyaW5nIHRhZyBmb3IgZGVyaXZhYmxlIHN0cmluZ3NcbiAgICovXG4gIEQuZGVyaXZlID0gZnVuY3Rpb24gKHBhcnRzKSB7XG4gICAgdmFyIGFyZ3MgPSB1dGlsX3NsaWNlKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIEQuZGVyaXZhdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgcyA9IFwiXCI7XG4gICAgICBmb3IgKHZhciBpPTA7IGk8cGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcyArPSBwYXJ0c1tpXTtcbiAgICAgICAgaWYgKGkgPCBhcmdzLmxlbmd0aCkge1xuICAgICAgICAgIHMgKz0gRC51bnBhY2soYXJnc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzO1xuICAgIH0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgbmV3IGxlbnNcbiAgICovXG4gIEQubGVucyA9IGZ1bmN0aW9uIChkZXNjcmlwdG9yKSB7XG4gICAgcmV0dXJuIGxlbnNfY29uc3RydWN0KFxuICAgICAgZGVyaXZhdGlvbl9jb25zdHJ1Y3QoT2JqZWN0LmNyZWF0ZShMZW5zKSwgZGVzY3JpcHRvci5nZXQpLFxuICAgICAgZGVzY3JpcHRvclxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIGRlcmVmZXJlbmNlcyBhIHRoaW5nIGlmIGl0IGlzIGRlcmVmZXJlbmNhYmxlLCBvdGhlcndpc2UganVzdCByZXR1cm5zIGl0LlxuICAgKi9cbiAgRC51bnBhY2sgPSBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoRC5pc0Rlcml2YWJsZSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZy5nZXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogbGlmdHMgYSBub24tbW9uYWRpYyBmdW5jdGlvbiB0byB3b3JrIG9uIGRlcml2YWJsZXNcbiAgICovXG4gIEQubGlmdCA9IGZ1bmN0aW9uIChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgcmV0dXJuIEQuZGVyaXZhdGlvbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmLmFwcGx5KHRoYXQsIEFycmF5LnByb3RvdHlwZS5tYXAuY2FsbChhcmdzLCBELnVucGFjaykpO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIGRlZXBVbnBhY2sgKHRoaW5nKSB7XG4gICAgaWYgKEQuaXNEZXJpdmFibGUodGhpbmcpKSB7XG4gICAgICByZXR1cm4gdGhpbmcuZ2V0KCk7XG4gICAgfSBlbHNlIGlmICh0aGluZyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICByZXR1cm4gdGhpbmcubWFwKGRlZXBVbnBhY2spO1xuICAgIH0gZWxzZSBpZiAodGhpbmcuY29uc3RydWN0b3IgPT09IE9iamVjdCkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgdmFyIGtleXMgPSB1dGlsX2tleXModGhpbmcpO1xuICAgICAgZm9yICh2YXIgaSA9IGtleXMubGVuZ3RoOyBpLS07KSB7XG4gICAgICAgIHZhciBwcm9wID0ga2V5c1tpXTtcbiAgICAgICAgcmVzdWx0W3Byb3BdID0gZGVlcFVucGFjayh0aGluZ1twcm9wXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpbmc7XG4gICAgfVxuICB9XG5cbiAgRC5zdHJ1Y3QgPSBmdW5jdGlvbiAoYXJnKSB7XG4gICAgaWYgKGFyZy5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0IHx8IGFyZyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICByZXR1cm4gRC5kZXJpdmF0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGRlZXBVbnBhY2soYXJnKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJgc3RydWN0YCBleHBlY3RzIHBsYWluIE9iamVjdCBvciBBcnJheVwiKTtcbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gYW5kT3JGbiAoYnJlYWtPbikge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIHJldHVybiBELmRlcml2YXRpb24oZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmFsO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB2YWwgPSBELnVucGFjayhhcmdzW2ldKTtcbiAgICAgICAgICBpZiAoYnJlYWtPbih2YWwpKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBpZGVudGl0eSAoeCkgeyByZXR1cm4geDsgfVxuICBmdW5jdGlvbiBjb21wbGVtZW50IChmKSB7IHJldHVybiBmdW5jdGlvbiAoeCkgeyByZXR1cm4gIWYoeCk7IH19XG4gIEQub3IgPSBhbmRPckZuKGlkZW50aXR5KTtcbiAgRC5tT3IgPSBhbmRPckZuKHV0aWxfc29tZSk7XG4gIEQuYW5kID0gYW5kT3JGbihjb21wbGVtZW50KGlkZW50aXR5KSk7XG4gIEQubUFuZCA9IGFuZE9yRm4oY29tcGxlbWVudCh1dGlsX3NvbWUpKTtcblxuICByZXR1cm4gRDtcbn1cblxudXRpbF9leHRlbmQoZXhwb3J0cywgY29uc3RydWN0TW9kdWxlKCkpO1xuZXhwb3J0cy53aXRoRXF1YWxpdHkgPSBmdW5jdGlvbiAoZXF1YWxzKSB7XG4gIHJldHVybiBjb25zdHJ1Y3RNb2R1bGUoe2VxdWFsczogZXF1YWxzfSk7XG59O1xuZXhwb3J0c1snZGVmYXVsdCddID0gZXhwb3J0cztcblxufSk7XG5cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRlcml2YWJsZS5qcy5tYXAiXX0=
const d = require("derivable")
const name = d.atom("World"); // the name of the user
const countryCode = d.atom("en"); // for i18n
// static constants don't need to be wrapped
const greetings = {
en: "Hello",
de: "Hallo",
es: "Hola",
cn: "您好",
fr: "Bonjour",
};
// derive a greeting message based on the user's name and country.
const greeting = countryCode.derive(cc => greetings[cc]);
const message = d.derive`${greeting}, ${name}!`; // es6 tagged template strings!
// set up a Reactor to print the message every time it changes
message.react(msg => console.log(msg));
// $> Hello, World!
countryCode.set("de");
// $> Hallo, World!
name.set("Dagmar");
// $> Hallo, Dagmar!
// we can avoid unwanted intermediate reactions by using transactions
d.transact(() => {
countryCode.set("fr");
name.set("Étienne");
});
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"derivable": "0.12.1"
}
}
<!-- contents of this file will be placed inside the <body> -->
<div></div>
<!-- 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